Hello, inlined patch adds support for hostap mode for 8188eu chip.

One known issue is documented in urtwn(4), I would like to know if
people with other hw will see it too, or if it's my local issue.

If you want to help, please test the patch and in case of problems
provide as much as you can from this list:

 - commands with which you started the AP
 - dmesg | grep urtwn
 - ifconfig 
 - tcpdump -i urtwn0 -y IEEE802_11 -w test.pcap (command must be run on
   the AP before problem occurs; I assume mailing the file to maillist
   isn't appropriate, so mail it to me directly)
 - if you can - sniff from the client (or, ideally, from third PC) too,
   since previous command won't give radiotap headers and won't show
   beacons.

Patch has been tested with tl-wn725n, and mac mini as a client, running
802.11g and wpa2, speed is about 3-4 mbits in presence of ~20 ssids.
Also, usual client mode with 8188eu chip is confirmed to work as before.

Since the patch touches some bits in STA mode initialization, it would
be helpful, if people with non-8188eu chip test it too in usual client
mode.

Any feedback and advice are appreciated.

diff --git share/man/man4/urtwn.4 share/man/man4/urtwn.4
index d2007a7..00928d4 100644
--- share/man/man4/urtwn.4
+++ share/man/man4/urtwn.4
@@ -58,6 +58,8 @@ capture packets from networks which it wouldn't normally have 
access to,
 or to scan for access points.
 .El
 .Pp
+The RTL8188EUS chip can also operate in Host AP mode.
+.Pp
 The
 .Nm
 driver can be configured to use
@@ -180,3 +182,8 @@ adapters.
 Additional work is required in
 .Xr ieee80211 9
 before those features can be supported.
+.Pp
+Beacon transmission, when operating in Host AP mode, is not started
+immidiatelly, but with timeout of around 40 seconds, it means that if you
+associate within this time frame, your client card will eventually disconnect
+you, assuming that you've left range of AP.
diff --git sys/dev/usb/if_urtwn.c sys/dev/usb/if_urtwn.c
index db47398..18a4200 100644
--- sys/dev/usb/if_urtwn.c
+++ sys/dev/usb/if_urtwn.c
@@ -216,6 +216,7 @@ void                urtwn_rxeof(struct usbd_xfer *, void *,
                    usbd_status);
 void           urtwn_txeof(struct usbd_xfer *, void *,
                    usbd_status);
+int            urtwn_txbcn(struct urtwn_softc *, struct ieee80211_node *);
 int            urtwn_tx(struct urtwn_softc *, struct mbuf *,
                    struct ieee80211_node *);
 void           urtwn_start(struct ifnet *);
@@ -347,6 +348,11 @@ urtwn_attach(struct device *parent, struct device *self, 
void *aux)
            IEEE80211_C_WEP |           /* WEP. */
            IEEE80211_C_RSN;            /* WPA/RSN. */
 
+#ifndef IEEE80211_STA_ONLY
+       if (sc->chip & URTWN_CHIP_88E)
+               ic->ic_caps |= IEEE80211_C_HOSTAP; /* HostAp mode supported */
+#endif
+
 #ifndef IEEE80211_NO_HT
        /* Set HT capabilities. */
        ic->ic_htcaps =
@@ -1319,7 +1325,7 @@ urtwn_newstate_cb(struct urtwn_softc *sc, void *arg)
        struct ieee80211_node *ni;
        enum ieee80211_state ostate;
        uint32_t reg;
-       int s;
+       int s, error;
 
        s = splnet();
        ostate = ic->ic_state;
@@ -1422,22 +1428,62 @@ urtwn_newstate_cb(struct urtwn_softc *sc, void *arg)
                }
                ni = ic->ic_bss;
 
-               /* Set media status to 'Associated'. */
-               reg = urtwn_read_4(sc, R92C_CR);
-               reg = RW(reg, R92C_CR_NETTYPE, R92C_CR_NETTYPE_INFRA);
-               urtwn_write_4(sc, R92C_CR, reg);
+               if (ic->ic_opmode == IEEE80211_M_STA) {
+                       /* Set BSSID. */
+                       urtwn_write_4(sc, R92C_BSSID + 0, 
LE_READ_4(&ni->ni_bssid[0]));
+                       urtwn_write_4(sc, R92C_BSSID + 4, 
LE_READ_2(&ni->ni_bssid[4]));
 
-               /* Set BSSID. */
-               urtwn_write_4(sc, R92C_BSSID + 0, LE_READ_4(&ni->ni_bssid[0]));
-               urtwn_write_4(sc, R92C_BSSID + 4, LE_READ_2(&ni->ni_bssid[4]));
+                       if (ic->ic_curmode == IEEE80211_MODE_11B)
+                               urtwn_write_1(sc, R92C_INIRTS_RATE_SEL, 0);
+                       else    /* 802.11b/g */
+                               urtwn_write_1(sc, R92C_INIRTS_RATE_SEL, 3);
 
-               if (ic->ic_curmode == IEEE80211_MODE_11B)
-                       urtwn_write_1(sc, R92C_INIRTS_RATE_SEL, 0);
-               else    /* 802.11b/g */
-                       urtwn_write_1(sc, R92C_INIRTS_RATE_SEL, 3);
+                       /* Enable Rx of data frames. */
+                       urtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff);
 
-               /* Enable Rx of data frames. */
-               urtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff);
+                       /* Allow Rx from our BSSID only. */
+                       urtwn_write_4(sc, R92C_RCR, urtwn_read_4(sc, R92C_RCR) |
+                           R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN);
+
+                       /* Set media status to 'Associated'. */
+                       reg = urtwn_read_4(sc, R92C_CR);
+                       reg = RW(reg, R92C_CR_NETTYPE, R92C_CR_NETTYPE_INFRA);
+                       urtwn_write_4(sc, R92C_CR, reg);
+               } else if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
+                       /* Set media status to 'AP'. */
+                       reg = urtwn_read_4(sc, R92C_CR);
+                       reg = RW(reg, R92C_CR_NETTYPE, R92C_CR_NETTYPE_AP);
+                       urtwn_write_4(sc, R92C_CR, reg);
+
+                       /* Set BSSID. */
+                       urtwn_write_4(sc, R92C_BSSID + 0,
+                           LE_READ_4(&ni->ni_bssid[0]));
+                       urtwn_write_4(sc, R92C_BSSID + 4,
+                           LE_READ_2(&ni->ni_bssid[4]));
+
+                       /*
+                        * If 3rd or 4th bits are set to zero chip will stop
+                        * repeating beacon after first transmission for port0
+                        * and port1 respectively. This will cause STAs to
+                        * disconnect after short period of time.
+                        */
+                       reg = urtwn_read_1(sc, R92C_MBID_NUM);
+                       reg |= 0x8;
+                       reg |= 0x10;
+                       urtwn_write_1(sc, R92C_MBID_NUM, reg);
+
+                       /* Invalidate cam entries */
+                       urtwn_cam_init(sc);
+
+                       /* Set chan/bw */
+                       urtwn_set_chan(sc, ic->ic_bss->ni_chan, NULL);
+
+                       /* Push beacon frame into the chip */
+                       error = urtwn_txbcn(sc, ni);
+                       if (error != 0)
+                               printf("%s: unable to push beacon into the"
+                                   " chip\n", sc->sc_dev.dv_xname);
+               }
 
                /* Flush all AC queues. */
                urtwn_write_1(sc, R92C_TXPAUSE, 0);
@@ -1445,11 +1491,6 @@ urtwn_newstate_cb(struct urtwn_softc *sc, void *arg)
                /* Set beacon interval. */
                urtwn_write_2(sc, R92C_BCN_INTERVAL, ni->ni_intval);
 
-               /* Allow Rx from our BSSID only. */
-               urtwn_write_4(sc, R92C_RCR,
-                   urtwn_read_4(sc, R92C_RCR) |
-                   R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN);
-
                /* Enable TSF synchronization. */
                urtwn_tsf_sync_enable(sc);
 
@@ -1953,6 +1994,35 @@ urtwn_txeof(struct usbd_xfer *xfer, void *priv,
        splx(s);
 }
 
+/*
+ * Push a beacon frame into the chip and check if it was accepted.  Beacon will
+ * be repeated by the chip every R92C_BCN_INTERVAL.
+ */
+int
+urtwn_txbcn(struct urtwn_softc *sc, struct ieee80211_node *ni)
+{
+       int i, bcnsent = 0;
+       uint32_t reg;
+       struct ieee80211com *ic = &sc->sc_ic;
+
+       reg = urtwn_read_1(sc, R92C_TDECTRL + 2);
+       reg |= 1;
+       urtwn_write_1(sc, R92C_TDECTRL + 2, reg);
+
+       for (i = 0; i < 100; i++) {
+               struct mbuf *m;
+
+               m = ieee80211_beacon_alloc(ic, ni);
+               urtwn_tx(sc, m, ni);
+               DELAY(100);
+               bcnsent = urtwn_read_1(sc, R92C_TDECTRL + 2) & 1;
+               if (bcnsent == 1)
+                       return (0);
+       }
+
+       return (1);
+}
+
 int
 urtwn_tx(struct urtwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
 {
@@ -1963,11 +2033,12 @@ urtwn_tx(struct urtwn_softc *sc, struct mbuf *m, struct 
ieee80211_node *ni)
        struct r92c_tx_desc *txd;
        struct usbd_pipe *pipe;
        uint16_t qos, sum;
-       uint8_t raid, type, tid, qid;
+       uint8_t raid, type, tid, qid, subtype;
        int i, hasqos, xferlen, error;
 
        wh = mtod(m, struct ieee80211_frame *);
        type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
+       subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
 
        if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
                k = ieee80211_get_txkey(ic, wh, ni);
@@ -2031,7 +2102,7 @@ urtwn_tx(struct urtwn_softc *sc, struct mbuf *m, struct 
ieee80211_node *ni)
                if (sc->chip & URTWN_CHIP_88E) {
                        txd->txdw1 |= htole32(
                            SM(R88E_TXDW1_MACID, URTWN_MACID_BSS) |
-                           SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_BE) |
+                           SM(R92C_TXDW1_QSEL, R88E_TXDW1_QSEL_BE) |
                            SM(R92C_TXDW1_RAID, raid));
                        txd->txdw2 |= htole32(R88E_TXDW2_AGGBK);
                } else {
@@ -2057,9 +2128,20 @@ urtwn_tx(struct urtwn_softc *sc, struct mbuf *m, struct 
ieee80211_node *ni)
                txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, 11));
 
        } else {
+               /*
+                * If beacon frame is pushed into wrong queue, chip won't start
+                * repeating it.
+                */
+               if (subtype == IEEE80211_FC0_SUBTYPE_BEACON &&
+                   sc->chip & URTWN_CHIP_88E)
+                       txd->txdw1 |= htole32(SM(R92C_TXDW1_QSEL,
+                           R88E_TXDW1_QSEL_MGNT));
+               else
+                       txd->txdw1 |= htole32(SM(R92C_TXDW1_QSEL,
+                           R92C_TXDW1_QSEL_MGNT));
+
                txd->txdw1 |= htole32(
-                   SM(R92C_TXDW1_MACID, 0) |
-                   SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_MGNT) |
+                   SM(R88E_TXDW1_MACID, 0) |
                    SM(R92C_TXDW1_RAID, R92C_RAID_11B));
 
                /* Force CCK1. */
diff --git sys/dev/usb/if_urtwnreg.h sys/dev/usb/if_urtwnreg.h
index db023ca..f6abdd2 100644
--- sys/dev/usb/if_urtwnreg.h
+++ sys/dev/usb/if_urtwnreg.h
@@ -161,6 +161,7 @@
 #define R92C_RDG_PIFS                  0x513
 #define R92C_SIFS_CCK                  0x514
 #define R92C_SIFS_OFDM                 0x516
+#define R92C_TSFTR_SYN_OFFSET          0x518
 #define R92C_AGGR_BREAK_TIME           0x51a
 #define R92C_SLOT                      0x51b
 #define R92C_TX_PTCL_CTRL              0x520
@@ -171,6 +172,7 @@
 #define R92C_RD_NAV_NXT                        0x544
 #define R92C_NAV_PROT_LEN              0x546
 #define R92C_BCN_CTRL                  0x550
+#define R92C_BCN_CTRL_1                        0x551
 #define R92C_MBID_NUM                  0x552
 #define R92C_DUAL_TSF_RST              0x553
 #define R92C_BCN_INTERVAL              0x554
@@ -1013,7 +1015,9 @@ struct r92c_tx_desc {
 #define R92C_TXDW1_QSEL_M      0x00001f00
 #define R92C_TXDW1_QSEL_S      8
 #define R92C_TXDW1_QSEL_BE     0x00
+#define R88E_TXDW1_QSEL_BE     0x03
 #define R92C_TXDW1_QSEL_MGNT   0x12
+#define R88E_TXDW1_QSEL_MGNT   0x10
 #define R92C_TXDW1_RAID_M      0x000f0000
 #define R92C_TXDW1_RAID_S      16
 #define R92C_TXDW1_CIPHER_M    0x00c00000

Reply via email to