Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F110718481
D4448.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D4448.diff
View Options
Index: head/sys/dev/usb/wlan/if_urtwn.c
===================================================================
--- head/sys/dev/usb/wlan/if_urtwn.c
+++ head/sys/dev/usb/wlan/if_urtwn.c
@@ -244,6 +244,17 @@
static void urtwn_update_beacon(struct ieee80211vap *, int);
static int urtwn_tx_beacon(struct urtwn_softc *sc,
struct urtwn_vap *);
+static int urtwn_key_alloc(struct ieee80211vap *,
+ struct ieee80211_key *, ieee80211_keyix *,
+ ieee80211_keyix *);
+static void urtwn_key_set_cb(struct urtwn_softc *,
+ union sec_param *);
+static void urtwn_key_del_cb(struct urtwn_softc *,
+ union sec_param *);
+static int urtwn_key_set(struct ieee80211vap *,
+ const struct ieee80211_key *);
+static int urtwn_key_delete(struct ieee80211vap *,
+ const struct ieee80211_key *);
static void urtwn_tsf_task_adhoc(void *, int);
static void urtwn_tsf_sync_enable(struct urtwn_softc *,
struct ieee80211vap *);
@@ -279,6 +290,8 @@
static void urtwn_bb_init(struct urtwn_softc *);
static void urtwn_rf_init(struct urtwn_softc *);
static void urtwn_cam_init(struct urtwn_softc *);
+static int urtwn_cam_write(struct urtwn_softc *, uint32_t,
+ uint32_t);
static void urtwn_pa_bias_init(struct urtwn_softc *);
static void urtwn_rxfilter_init(struct urtwn_softc *);
static void urtwn_edca_init(struct urtwn_softc *);
@@ -500,6 +513,11 @@
| IEEE80211_C_WME /* 802.11e */
;
+ ic->ic_cryptocaps =
+ IEEE80211_CRYPTO_WEP |
+ IEEE80211_CRYPTO_TKIP |
+ IEEE80211_CRYPTO_AES_CCM;
+
bands = 0;
setbit(&bands, IEEE80211_MODE_11B);
setbit(&bands, IEEE80211_MODE_11G);
@@ -659,6 +677,9 @@
uvp->newstate = vap->iv_newstate;
vap->iv_newstate = urtwn_newstate;
vap->iv_update_beacon = urtwn_update_beacon;
+ vap->iv_key_alloc = urtwn_key_alloc;
+ vap->iv_key_set = urtwn_key_set;
+ vap->iv_key_delete = urtwn_key_delete;
if (opmode == IEEE80211_M_IBSS) {
uvp->recv_mgmt = vap->iv_recv_mgmt;
vap->iv_recv_mgmt = urtwn_ibss_recv_mgmt;
@@ -699,7 +720,7 @@
struct mbuf *m;
struct r92c_rx_stat *stat;
uint32_t rxdw0, rxdw3;
- uint8_t rate;
+ uint8_t rate, cipher;
int8_t rssi = 0;
int infosz;
@@ -729,6 +750,7 @@
}
rate = MS(rxdw3, R92C_RXDW3_RATE);
+ cipher = MS(rxdw0, R92C_RXDW0_CIPHER);
infosz = MS(rxdw0, R92C_RXDW0_INFOSZ) * 8;
/* Get RSSI from PHY status descriptor if present. */
@@ -748,9 +770,14 @@
}
/* Finalize mbuf. */
- wh = (struct ieee80211_frame *)((uint8_t *)&stat[1] + infosz);
- memcpy(mtod(m, uint8_t *), wh, pktlen);
- m->m_pkthdr.len = m->m_len = pktlen;
+ memcpy(mtod(m, uint8_t *), (uint8_t *)&stat[1] + infosz, pktlen);
+ m->m_pkthdr.len = m->m_len = pktlen;
+ wh = mtod(m, struct ieee80211_frame *);
+
+ if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) &&
+ cipher != R92C_CAM_ALGO_NONE) {
+ m->m_flags |= M_WEP;
+ }
if (ieee80211_radiotap_active(ic)) {
struct urtwn_rx_radiotap_header *tap = &sc->sc_rxtap;
@@ -1862,6 +1889,153 @@
return (0);
}
+static int
+urtwn_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
+ ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
+{
+ struct urtwn_softc *sc = vap->iv_ic->ic_softc;
+ uint8_t i;
+
+ if (!(&vap->iv_nw_keys[0] <= k &&
+ k < &vap->iv_nw_keys[IEEE80211_WEP_NKID])) {
+ if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT)) {
+ URTWN_LOCK(sc);
+ /*
+ * First 4 slots for group keys,
+ * what is left - for pairwise.
+ * XXX incompatible with IBSS RSN.
+ */
+ for (i = IEEE80211_WEP_NKID;
+ i < R92C_CAM_ENTRY_COUNT; i++) {
+ if ((sc->keys_bmap & (1 << i)) == 0) {
+ sc->keys_bmap |= 1 << i;
+ *keyix = i;
+ break;
+ }
+ }
+ URTWN_UNLOCK(sc);
+ if (i == R92C_CAM_ENTRY_COUNT) {
+ device_printf(sc->sc_dev,
+ "%s: no free space in the key table\n",
+ __func__);
+ return 0;
+ }
+ } else
+ *keyix = 0;
+ } else {
+ *keyix = k - vap->iv_nw_keys;
+ }
+ *rxkeyix = *keyix;
+ return 1;
+}
+
+static void
+urtwn_key_set_cb(struct urtwn_softc *sc, union sec_param *data)
+{
+ struct ieee80211_key *k = &data->key;
+ uint8_t algo, keyid;
+ int i, error;
+
+ if (k->wk_keyix < IEEE80211_WEP_NKID)
+ keyid = k->wk_keyix;
+ else
+ keyid = 0;
+
+ /* Map net80211 cipher to HW crypto algorithm. */
+ switch (k->wk_cipher->ic_cipher) {
+ case IEEE80211_CIPHER_WEP:
+ if (k->wk_keylen < 8)
+ algo = R92C_CAM_ALGO_WEP40;
+ else
+ algo = R92C_CAM_ALGO_WEP104;
+ break;
+ case IEEE80211_CIPHER_TKIP:
+ algo = R92C_CAM_ALGO_TKIP;
+ break;
+ case IEEE80211_CIPHER_AES_CCM:
+ algo = R92C_CAM_ALGO_AES;
+ break;
+ default:
+ device_printf(sc->sc_dev, "%s: undefined cipher %d\n",
+ __func__, k->wk_cipher->ic_cipher);
+ return;
+ }
+
+ DPRINTFN(9, "keyix %d, keyid %d, algo %d/%d, flags %04X, len %d, "
+ "macaddr %s\n", k->wk_keyix, keyid, k->wk_cipher->ic_cipher, algo,
+ k->wk_flags, k->wk_keylen, ether_sprintf(k->wk_macaddr));
+
+ /* Write key. */
+ for (i = 0; i < 4; i++) {
+ error = urtwn_cam_write(sc, R92C_CAM_KEY(k->wk_keyix, i),
+ LE_READ_4(&k->wk_key[i * 4]));
+ if (error != 0)
+ goto fail;
+ }
+
+ /* Write CTL0 last since that will validate the CAM entry. */
+ error = urtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix),
+ LE_READ_4(&k->wk_macaddr[2]));
+ if (error != 0)
+ goto fail;
+ error = urtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix),
+ SM(R92C_CAM_ALGO, algo) |
+ SM(R92C_CAM_KEYID, keyid) |
+ SM(R92C_CAM_MACLO, LE_READ_2(&k->wk_macaddr[0])) |
+ R92C_CAM_VALID);
+ if (error != 0)
+ goto fail;
+
+ return;
+
+fail:
+ device_printf(sc->sc_dev, "%s fails, error %d\n", __func__, error);
+}
+
+static void
+urtwn_key_del_cb(struct urtwn_softc *sc, union sec_param *data)
+{
+ struct ieee80211_key *k = &data->key;
+ int i;
+
+ DPRINTFN(9, "keyix %d, flags %04X, macaddr %s\n",
+ k->wk_keyix, k->wk_flags, ether_sprintf(k->wk_macaddr));
+
+ urtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix), 0);
+ urtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix), 0);
+
+ /* Clear key. */
+ for (i = 0; i < 4; i++)
+ urtwn_cam_write(sc, R92C_CAM_KEY(k->wk_keyix, i), 0);
+ sc->keys_bmap &= ~(1 << k->wk_keyix);
+}
+
+static int
+urtwn_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k)
+{
+ struct urtwn_softc *sc = vap->iv_ic->ic_softc;
+
+ if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
+ /* Not for us. */
+ return (1);
+ }
+
+ return (!urtwn_cmd_sleepable(sc, k, sizeof(*k), urtwn_key_set_cb));
+}
+
+static int
+urtwn_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
+{
+ struct urtwn_softc *sc = vap->iv_ic->ic_softc;
+
+ if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
+ /* Not for us. */
+ return (1);
+ }
+
+ return (!urtwn_cmd_sleepable(sc, k, sizeof(*k), urtwn_key_del_cb));
+}
+
static void
urtwn_tsf_task_adhoc(void *arg, int pending)
{
@@ -2479,6 +2653,26 @@
txd->txdseq = htole16(M_SEQNO_GET(m) % IEEE80211_SEQ_RANGE);
}
+ if (k != NULL && !(k->wk_flags & IEEE80211_KEY_SWCRYPT)) {
+ uint8_t cipher;
+
+ switch (k->wk_cipher->ic_cipher) {
+ case IEEE80211_CIPHER_WEP:
+ case IEEE80211_CIPHER_TKIP:
+ cipher = R92C_TXDW1_CIPHER_RC4;
+ break;
+ case IEEE80211_CIPHER_AES_CCM:
+ cipher = R92C_TXDW1_CIPHER_AES;
+ break;
+ default:
+ device_printf(sc->sc_dev, "%s: unknown cipher %d\n",
+ __func__, k->wk_cipher->ic_cipher);
+ return (EINVAL);
+ }
+
+ txd->txdw1 |= htole32(SM(R92C_TXDW1_CIPHER, cipher));
+ }
+
if (ieee80211_radiotap_active_vap(vap)) {
struct urtwn_tx_radiotap_header *tap = &sc->sc_txtap;
@@ -3383,6 +3577,23 @@
R92C_CAMCMD_POLLING | R92C_CAMCMD_CLR);
}
+static int
+urtwn_cam_write(struct urtwn_softc *sc, uint32_t addr, uint32_t data)
+{
+ usb_error_t error;
+
+ error = urtwn_write_4(sc, R92C_CAMWRITE, data);
+ if (error != USB_ERR_NORMAL_COMPLETION)
+ return (EIO);
+ error = urtwn_write_4(sc, R92C_CAMCMD,
+ R92C_CAMCMD_POLLING | R92C_CAMCMD_WRITE |
+ SM(R92C_CAMCMD_ADDR, addr));
+ if (error != USB_ERR_NORMAL_COMPLETION)
+ return (EIO);
+
+ return (0);
+}
+
static void
urtwn_pa_bias_init(struct urtwn_softc *sc)
{
@@ -4271,6 +4482,18 @@
/* Clear per-station keys table. */
urtwn_cam_init(sc);
+ /* Enable decryption / encryption. */
+ urtwn_write_2(sc, R92C_SECCFG,
+ R92C_SECCFG_TXUCKEY_DEF | R92C_SECCFG_RXUCKEY_DEF |
+ R92C_SECCFG_TXENC_ENA | R92C_SECCFG_RXDEC_ENA |
+ R92C_SECCFG_TXBCKEY_DEF | R92C_SECCFG_RXBCKEY_DEF);
+
+ /*
+ * Install static keys (if any).
+ * Must be called after urtwn_cam_init().
+ */
+ ieee80211_runtask(ic, &sc->cmdq_task);
+
/* Enable hardware sequence numbering. */
urtwn_write_1(sc, R92C_HWSEQ_CTRL, 0xff);
Index: head/sys/dev/usb/wlan/if_urtwnreg.h
===================================================================
--- head/sys/dev/usb/wlan/if_urtwnreg.h
+++ head/sys/dev/usb/wlan/if_urtwnreg.h
@@ -557,6 +557,16 @@
#define R92C_CAMCMD_CLR 0x40000000
#define R92C_CAMCMD_POLLING 0x80000000
+/* Bits for R92C_SECCFG. */
+#define R92C_SECCFG_TXUCKEY_DEF 0x0001
+#define R92C_SECCFG_RXUCKEY_DEF 0x0002
+#define R92C_SECCFG_TXENC_ENA 0x0004
+#define R92C_SECCFG_RXDEC_ENA 0x0008
+#define R92C_SECCFG_CMP_A2 0x0010
+#define R92C_SECCFG_TXBCKEY_DEF 0x0040
+#define R92C_SECCFG_RXBCKEY_DEF 0x0080
+#define R88E_SECCFG_CHK_KEYID 0x0100
+
/* Bits for R92C_RXFLTMAP*. */
#define R92C_RXFLTMAP_SUBTYPE(subtype) \
(1 << ((subtype) >> IEEE80211_FC0_SUBTYPE_SHIFT))
@@ -968,6 +978,8 @@
#define R92C_RXDW0_ICVERR 0x00008000
#define R92C_RXDW0_INFOSZ_M 0x000f0000
#define R92C_RXDW0_INFOSZ_S 16
+#define R92C_RXDW0_CIPHER_M 0x00700000
+#define R92C_RXDW0_CIPHER_S 20
#define R92C_RXDW0_QOS 0x00800000
#define R92C_RXDW0_SHIFT_M 0x03000000
#define R92C_RXDW0_SHIFT_S 24
Index: head/sys/dev/usb/wlan/if_urtwnvar.h
===================================================================
--- head/sys/dev/usb/wlan/if_urtwnvar.h
+++ head/sys/dev/usb/wlan/if_urtwnvar.h
@@ -205,6 +205,7 @@
struct callout sc_watchdog_ch;
struct mtx sc_mtx;
+ uint32_t keys_bmap;
struct urtwn_cmdq cmdq[URTWN_CMDQ_SIZE];
struct mtx cmdq_mtx;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Feb 23, 7:15 AM (8 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16790189
Default Alt Text
D4448.diff (9 KB)
Attached To
Mode
D4448: urtwn: add support for hardware encryption (WEP, TKIP and CCMP)
Attached
Detach File
Event Timeline
Log In to Comment