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