Hey wireless folks,

I wanted to setup a Raspberry Pi as a FreeBSD AP and purchased a picked up a few Edimax 802.11 adapters to play with. Unfortunately these aren't supported in hostap mode. As it turns out these Edimax adapters use the RTL8188CUS chipset so I poked around the net and noticed that Linux does support the host AP feature with it's RTL8188CUS driver. I was also able to find a patch for OpenBSD that added support for the RTL8188EU chipset to the urtwn driver ...


http://marc.info/?l=openbsd-tech&m=143577648117514&w=2

So I ordered one of these which arrived from China a few weeks later ...

http://www.amazon.com/gp/product/B00L28AN88?psc=1&redirect=true&ref_=oh_aui_detailpage_o05_s00

Next I took a stab at porting the patch to FreeBSD. With the attached patch applied, I was able to setup a wlan0 device with the hostap feature. After bridging it with the LAN I could associate with my android phone, obtain an IP address via DHCP, browse a few web pages and watch all the packets pass through the bridge. Sadly, when I attempted to destroy the wlan0 device I got a kernel panic. The screenshot for that is also attached and I'm not sure if I'm going to be able to figure this one out without some help. I'm pretty out of my element here. I assume it's happening in ieee80211_free_node() when IEEE80211_NODE_LOCK() is called. To be clear, the crash only occurs when the adapter is configured in hostap mode with the patch applied. Anyone have any suggestions as to what I should be looking at to prevent this crash?

If I can get this working for the RTL8188EU, I'll also take a stab at getting the RTL8188CUS chipset working in hostap mode. That is, assuming I can glean enough info from drivers that support this feature on other open source platforms. It appears to be extremely popular with the Raspberry PI crowd ...

http://www.amazon.com/Edimax-EW-7811Un-150Mbps-Raspberry-Supports/dp/B003MTTJOY

Thanks in advance,

-Matthew
Index: dev/usb/wlan/if_urtwn.c
===================================================================
--- dev/usb/wlan/if_urtwn.c     (revision 287342)
+++ dev/usb/wlan/if_urtwn.c     (working copy)
@@ -181,6 +181,8 @@
 static struct mbuf *   urtwn_rxeof(struct usb_xfer *, struct urtwn_data *,
                            int *, int8_t *);
 static void            urtwn_txeof(struct usb_xfer *, struct urtwn_data *);
+int                    urtwn_txbcn(struct ieee80211vap *vap,
+                           struct ieee80211_node *);
 static int             urtwn_alloc_list(struct urtwn_softc *,
                            struct urtwn_data[], int, int);
 static int             urtwn_alloc_rx_list(struct urtwn_softc *);
@@ -436,6 +438,10 @@
                | IEEE80211_C_WPA               /* 802.11i */
                ;
 
+       if (sc->chip & URTWN_CHIP_88E)
+               ic->ic_caps |=
+                   IEEE80211_C_HOSTAP;         /* HostAp mode supported */
+
        bands = 0;
        setbit(&bands, IEEE80211_MODE_11B);
        setbit(&bands, IEEE80211_MODE_11G);
@@ -857,6 +863,36 @@
        sc->sc_txtimer = 0;
 }
 
+/*
+ * 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 ieee80211vap *vap, struct ieee80211_node *ni)
+{
+       struct ieee80211com *ic = ni->ni_ic;
+       struct urtwn_softc *sc = ic->ic_softc;
+       struct urtwn_data *bf;
+       struct mbuf *m;
+
+       m = ieee80211_beacon_alloc(ni, &URTWN_VAP(vap)->bo);
+
+       bf = urtwn_getbuf(sc);
+       if (bf == NULL) {
+               m_freem(m);
+               return (ENOBUFS);
+       }
+
+       if (urtwn_tx_start(sc, ni, m, bf) != 0) {
+               STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
+               return (EIO);
+       }
+
+       sc->sc_txtimer = 5;
+
+       return (0);
+}
+
 static void
 urtwn_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
 {
@@ -1466,6 +1502,7 @@
        struct ieee80211_node *ni;
        enum ieee80211_state ostate;
        uint32_t reg;
+       int error;
 
        ostate = vap->iv_state;
        DPRINTF("%s -> %s\n", ieee80211_state_name[ostate],
@@ -1553,23 +1590,68 @@
                }
 
                ni = ieee80211_ref_node(vap->iv_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);
 
-               /* 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_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]));
 
-               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);
+               }
+
+               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_curchan, NULL);
+
+                       /* Push beacon frame into the chip */
+                       error = urtwn_txbcn(vap, ni);
+                       if (error != 0)
+                               printf("%s: unable to push beacon into the"
+                                   " chip\n", device_get_nameunit(sc->sc_dev));
+               }
+
                /* Flush all AC queues. */
                urtwn_write_1(sc, R92C_TXPAUSE, 0);
 
@@ -1576,11 +1658,6 @@
                /* 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);
 
@@ -1754,7 +1831,7 @@
        struct ieee80211vap *vap = ni->ni_vap;
        struct usb_xfer *xfer;
        struct r92c_tx_desc *txd;
-       uint8_t raid, type;
+       uint8_t raid, type, subtype;
        uint16_t sum;
        int i, hasqos, xferlen;
        struct usb_xfer *urtwn_pipes[4] = {
@@ -1771,6 +1848,7 @@
         */
        wh = mtod(m0, 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_crypto_encap(ni, m0);
@@ -1819,7 +1897,7 @@
                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 {
@@ -1843,9 +1921,20 @@
                /* Send data at OFDM54. */
                txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, 11));
        } else {
+               /*
+                * If beacon frame is pushed into wrong queue, the 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(R92C_TXDW1_RAID, R92C_RAID_11B));
 
                /* Force CCK1. */
Index: dev/usb/wlan/if_urtwnreg.h
===================================================================
--- dev/usb/wlan/if_urtwnreg.h  (revision 287342)
+++ dev/usb/wlan/if_urtwnreg.h  (working copy)
@@ -1019,7 +1019,9 @@
 #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
_______________________________________________
freebsd-wireless@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-wireless
To unsubscribe, send any mail to "freebsd-wireless-unsubscr...@freebsd.org"

Reply via email to