staging: ath6kl: Convert A_UINT32 to u32
[linux-2.6/libata-dev.git] / drivers / staging / ath6kl / os / linux / wireless_ext.c
blobaca58dd28e23cf797c49118732ccc5a1f1ccd4d2
1 //------------------------------------------------------------------------------
2 // Copyright (c) 2004-2010 Atheros Communications Inc.
3 // All rights reserved.
4 //
5 //
6 //
7 // Permission to use, copy, modify, and/or distribute this software for any
8 // purpose with or without fee is hereby granted, provided that the above
9 // copyright notice and this permission notice appear in all copies.
11 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 // Author(s): ="Atheros"
22 //------------------------------------------------------------------------------
24 #include "ar6000_drv.h"
26 #define IWE_STREAM_ADD_EVENT(p1, p2, p3, p4, p5) \
27 iwe_stream_add_event((p1), (p2), (p3), (p4), (p5))
29 #define IWE_STREAM_ADD_POINT(p1, p2, p3, p4, p5) \
30 iwe_stream_add_point((p1), (p2), (p3), (p4), (p5))
32 #define IWE_STREAM_ADD_VALUE(p1, p2, p3, p4, p5, p6) \
33 iwe_stream_add_value((p1), (p2), (p3), (p4), (p5), (p6))
35 static void ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi);
36 extern unsigned int wmitimeout;
37 extern A_WAITQUEUE_HEAD arEvent;
39 #if WIRELESS_EXT > 14
41 * Encode a WPA or RSN information element as a custom
42 * element using the hostap format.
44 static u_int
45 encode_ie(void *buf, size_t bufsize,
46 const u_int8_t *ie, size_t ielen,
47 const char *leader, size_t leader_len)
49 u_int8_t *p;
50 int i;
52 if (bufsize < leader_len)
53 return 0;
54 p = buf;
55 memcpy(p, leader, leader_len);
56 bufsize -= leader_len;
57 p += leader_len;
58 for (i = 0; i < ielen && bufsize > 2; i++)
60 p += sprintf((char*)p, "%02x", ie[i]);
61 bufsize -= 2;
63 return (i == ielen ? p - (u_int8_t *)buf : 0);
65 #endif /* WIRELESS_EXT > 14 */
67 static u8 get_bss_phy_capability(bss_t *bss)
69 u8 capability = 0;
70 struct ieee80211_common_ie *cie = &bss->ni_cie;
71 #define CHAN_IS_11A(x) (!((x >= 2412) && (x <= 2484)))
72 if (CHAN_IS_11A(cie->ie_chan)) {
73 if (cie->ie_htcap) {
74 capability = WMI_11NA_CAPABILITY;
75 } else {
76 capability = WMI_11A_CAPABILITY;
78 } else if ((cie->ie_erp) || (cie->ie_xrates)) {
79 if (cie->ie_htcap) {
80 capability = WMI_11NG_CAPABILITY;
81 } else {
82 capability = WMI_11G_CAPABILITY;
85 return capability;
88 void
89 ar6000_scan_node(void *arg, bss_t *ni)
91 struct iw_event iwe;
92 #if WIRELESS_EXT > 14
93 char buf[256];
94 #endif
95 struct ar_giwscan_param *param;
96 char *current_ev;
97 char *end_buf;
98 struct ieee80211_common_ie *cie;
99 char *current_val;
100 A_INT32 j;
101 u32 rate_len, data_len = 0;
103 param = (struct ar_giwscan_param *)arg;
105 current_ev = param->current_ev;
106 end_buf = param->end_buf;
108 cie = &ni->ni_cie;
110 if ((end_buf - current_ev) > IW_EV_ADDR_LEN)
112 A_MEMZERO(&iwe, sizeof(iwe));
113 iwe.cmd = SIOCGIWAP;
114 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
115 A_MEMCPY(iwe.u.ap_addr.sa_data, ni->ni_macaddr, 6);
116 current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
117 &iwe, IW_EV_ADDR_LEN);
119 param->bytes_needed += IW_EV_ADDR_LEN;
121 data_len = cie->ie_ssid[1] + IW_EV_POINT_LEN;
122 if ((end_buf - current_ev) > data_len)
124 A_MEMZERO(&iwe, sizeof(iwe));
125 iwe.cmd = SIOCGIWESSID;
126 iwe.u.data.flags = 1;
127 iwe.u.data.length = cie->ie_ssid[1];
128 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
129 &iwe, (char*)&cie->ie_ssid[2]);
131 param->bytes_needed += data_len;
133 if (cie->ie_capInfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) {
134 if ((end_buf - current_ev) > IW_EV_UINT_LEN)
136 A_MEMZERO(&iwe, sizeof(iwe));
137 iwe.cmd = SIOCGIWMODE;
138 iwe.u.mode = cie->ie_capInfo & IEEE80211_CAPINFO_ESS ?
139 IW_MODE_MASTER : IW_MODE_ADHOC;
140 current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
141 &iwe, IW_EV_UINT_LEN);
143 param->bytes_needed += IW_EV_UINT_LEN;
146 if ((end_buf - current_ev) > IW_EV_FREQ_LEN)
148 A_MEMZERO(&iwe, sizeof(iwe));
149 iwe.cmd = SIOCGIWFREQ;
150 iwe.u.freq.m = cie->ie_chan * 100000;
151 iwe.u.freq.e = 1;
152 current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
153 &iwe, IW_EV_FREQ_LEN);
155 param->bytes_needed += IW_EV_FREQ_LEN;
157 if ((end_buf - current_ev) > IW_EV_QUAL_LEN)
159 A_MEMZERO(&iwe, sizeof(iwe));
160 iwe.cmd = IWEVQUAL;
161 ar6000_set_quality(&iwe.u.qual, ni->ni_snr);
162 current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
163 &iwe, IW_EV_QUAL_LEN);
165 param->bytes_needed += IW_EV_QUAL_LEN;
167 if ((end_buf - current_ev) > IW_EV_POINT_LEN)
169 A_MEMZERO(&iwe, sizeof(iwe));
170 iwe.cmd = SIOCGIWENCODE;
171 if (cie->ie_capInfo & IEEE80211_CAPINFO_PRIVACY) {
172 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
173 } else {
174 iwe.u.data.flags = IW_ENCODE_DISABLED;
176 iwe.u.data.length = 0;
177 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
178 &iwe, "");
180 param->bytes_needed += IW_EV_POINT_LEN;
182 /* supported bit rate */
183 A_MEMZERO(&iwe, sizeof(iwe));
184 iwe.cmd = SIOCGIWRATE;
185 iwe.u.bitrate.fixed = 0;
186 iwe.u.bitrate.disabled = 0;
187 iwe.u.bitrate.value = 0;
188 current_val = current_ev + IW_EV_LCP_LEN;
189 param->bytes_needed += IW_EV_LCP_LEN;
191 if (cie->ie_rates != NULL) {
192 rate_len = cie->ie_rates[1];
193 data_len = (rate_len * (IW_EV_PARAM_LEN - IW_EV_LCP_LEN));
194 if ((end_buf - current_ev) > data_len)
196 for (j = 0; j < rate_len; j++) {
197 unsigned char val;
198 val = cie->ie_rates[2 + j];
199 iwe.u.bitrate.value =
200 (val >= 0x80)? ((val - 0x80) * 500000): (val * 500000);
201 current_val = IWE_STREAM_ADD_VALUE(param->info, current_ev,
202 current_val, end_buf,
203 &iwe, IW_EV_PARAM_LEN);
206 param->bytes_needed += data_len;
209 if (cie->ie_xrates != NULL) {
210 rate_len = cie->ie_xrates[1];
211 data_len = (rate_len * (IW_EV_PARAM_LEN - IW_EV_LCP_LEN));
212 if ((end_buf - current_ev) > data_len)
214 for (j = 0; j < rate_len; j++) {
215 unsigned char val;
216 val = cie->ie_xrates[2 + j];
217 iwe.u.bitrate.value =
218 (val >= 0x80)? ((val - 0x80) * 500000): (val * 500000);
219 current_val = IWE_STREAM_ADD_VALUE(param->info, current_ev,
220 current_val, end_buf,
221 &iwe, IW_EV_PARAM_LEN);
224 param->bytes_needed += data_len;
226 /* remove fixed header if no rates were added */
227 if ((current_val - current_ev) > IW_EV_LCP_LEN)
228 current_ev = current_val;
230 #if WIRELESS_EXT >= 18
231 /* IE */
232 if (cie->ie_wpa != NULL) {
233 data_len = cie->ie_wpa[1] + 2 + IW_EV_POINT_LEN;
234 if ((end_buf - current_ev) > data_len)
236 A_MEMZERO(&iwe, sizeof(iwe));
237 iwe.cmd = IWEVGENIE;
238 iwe.u.data.length = cie->ie_wpa[1] + 2;
239 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
240 &iwe, (char*)cie->ie_wpa);
242 param->bytes_needed += data_len;
245 if (cie->ie_rsn != NULL && cie->ie_rsn[0] == IEEE80211_ELEMID_RSN) {
246 data_len = cie->ie_rsn[1] + 2 + IW_EV_POINT_LEN;
247 if ((end_buf - current_ev) > data_len)
249 A_MEMZERO(&iwe, sizeof(iwe));
250 iwe.cmd = IWEVGENIE;
251 iwe.u.data.length = cie->ie_rsn[1] + 2;
252 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
253 &iwe, (char*)cie->ie_rsn);
255 param->bytes_needed += data_len;
258 #endif /* WIRELESS_EXT >= 18 */
260 if ((end_buf - current_ev) > IW_EV_CHAR_LEN)
262 /* protocol */
263 A_MEMZERO(&iwe, sizeof(iwe));
264 iwe.cmd = SIOCGIWNAME;
265 switch (get_bss_phy_capability(ni)) {
266 case WMI_11A_CAPABILITY:
267 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a");
268 break;
269 case WMI_11G_CAPABILITY:
270 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
271 break;
272 case WMI_11NA_CAPABILITY:
273 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11na");
274 break;
275 case WMI_11NG_CAPABILITY:
276 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11ng");
277 break;
278 default:
279 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
280 break;
282 current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
283 &iwe, IW_EV_CHAR_LEN);
285 param->bytes_needed += IW_EV_CHAR_LEN;
287 #if WIRELESS_EXT > 14
288 A_MEMZERO(&iwe, sizeof(iwe));
289 iwe.cmd = IWEVCUSTOM;
290 iwe.u.data.length = snprintf(buf, sizeof(buf), "bcn_int=%d", cie->ie_beaconInt);
291 data_len = iwe.u.data.length + IW_EV_POINT_LEN;
292 if ((end_buf - current_ev) > data_len)
294 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
295 &iwe, buf);
297 param->bytes_needed += data_len;
299 #if WIRELESS_EXT < 18
300 if (cie->ie_wpa != NULL) {
301 static const char wpa_leader[] = "wpa_ie=";
302 data_len = (sizeof(wpa_leader) - 1) + ((cie->ie_wpa[1]+2) * 2) + IW_EV_POINT_LEN;
303 if ((end_buf - current_ev) > data_len)
305 A_MEMZERO(&iwe, sizeof(iwe));
306 iwe.cmd = IWEVCUSTOM;
307 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wpa,
308 cie->ie_wpa[1]+2,
309 wpa_leader, sizeof(wpa_leader)-1);
311 if (iwe.u.data.length != 0) {
312 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev,
313 end_buf, &iwe, buf);
316 param->bytes_needed += data_len;
319 if (cie->ie_rsn != NULL && cie->ie_rsn[0] == IEEE80211_ELEMID_RSN) {
320 static const char rsn_leader[] = "rsn_ie=";
321 data_len = (sizeof(rsn_leader) - 1) + ((cie->ie_rsn[1]+2) * 2) + IW_EV_POINT_LEN;
322 if ((end_buf - current_ev) > data_len)
324 A_MEMZERO(&iwe, sizeof(iwe));
325 iwe.cmd = IWEVCUSTOM;
326 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_rsn,
327 cie->ie_rsn[1]+2,
328 rsn_leader, sizeof(rsn_leader)-1);
330 if (iwe.u.data.length != 0) {
331 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev,
332 end_buf, &iwe, buf);
335 param->bytes_needed += data_len;
337 #endif /* WIRELESS_EXT < 18 */
339 if (cie->ie_wmm != NULL) {
340 static const char wmm_leader[] = "wmm_ie=";
341 data_len = (sizeof(wmm_leader) - 1) + ((cie->ie_wmm[1]+2) * 2) + IW_EV_POINT_LEN;
342 if ((end_buf - current_ev) > data_len)
344 A_MEMZERO(&iwe, sizeof(iwe));
345 iwe.cmd = IWEVCUSTOM;
346 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wmm,
347 cie->ie_wmm[1]+2,
348 wmm_leader, sizeof(wmm_leader)-1);
349 if (iwe.u.data.length != 0) {
350 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev,
351 end_buf, &iwe, buf);
354 param->bytes_needed += data_len;
357 if (cie->ie_ath != NULL) {
358 static const char ath_leader[] = "ath_ie=";
359 data_len = (sizeof(ath_leader) - 1) + ((cie->ie_ath[1]+2) * 2) + IW_EV_POINT_LEN;
360 if ((end_buf - current_ev) > data_len)
362 A_MEMZERO(&iwe, sizeof(iwe));
363 iwe.cmd = IWEVCUSTOM;
364 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_ath,
365 cie->ie_ath[1]+2,
366 ath_leader, sizeof(ath_leader)-1);
367 if (iwe.u.data.length != 0) {
368 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev,
369 end_buf, &iwe, buf);
372 param->bytes_needed += data_len;
375 #ifdef WAPI_ENABLE
376 if (cie->ie_wapi != NULL) {
377 static const char wapi_leader[] = "wapi_ie=";
378 data_len = (sizeof(wapi_leader) - 1) + ((cie->ie_wapi[1] + 2) * 2) + IW_EV_POINT_LEN;
379 if ((end_buf - current_ev) > data_len) {
380 A_MEMZERO(&iwe, sizeof(iwe));
381 iwe.cmd = IWEVCUSTOM;
382 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wapi,
383 cie->ie_wapi[1] + 2,
384 wapi_leader, sizeof(wapi_leader) - 1);
385 if (iwe.u.data.length != 0) {
386 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev,
387 end_buf, &iwe, buf);
390 param->bytes_needed += data_len;
392 #endif /* WAPI_ENABLE */
394 #endif /* WIRELESS_EXT > 14 */
396 #if WIRELESS_EXT >= 18
397 if (cie->ie_wsc != NULL) {
398 data_len = (cie->ie_wsc[1] + 2) + IW_EV_POINT_LEN;
399 if ((end_buf - current_ev) > data_len)
401 A_MEMZERO(&iwe, sizeof(iwe));
402 iwe.cmd = IWEVGENIE;
403 iwe.u.data.length = cie->ie_wsc[1] + 2;
404 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
405 &iwe, (char*)cie->ie_wsc);
407 param->bytes_needed += data_len;
409 #endif /* WIRELESS_EXT >= 18 */
411 param->current_ev = current_ev;
415 ar6000_ioctl_giwscan(struct net_device *dev,
416 struct iw_request_info *info,
417 struct iw_point *data, char *extra)
419 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
420 struct ar_giwscan_param param;
422 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
423 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
424 return -EOPNOTSUPP;
427 if (ar->arWlanState == WLAN_DISABLED) {
428 return -EIO;
431 if (ar->arWmiReady == false) {
432 return -EIO;
435 param.current_ev = extra;
436 param.end_buf = extra + data->length;
437 param.bytes_needed = 0;
438 param.info = info;
440 /* Translate data to WE format */
441 wmi_iterate_nodes(ar->arWmi, ar6000_scan_node, &param);
443 /* check if bytes needed is greater than bytes consumed */
444 if (param.bytes_needed > (param.current_ev - extra))
446 /* Request one byte more than needed, because when "data->length" equals bytes_needed,
447 it is not possible to add the last event data as all iwe_stream_add_xxxxx() functions
448 checks whether (cur_ptr + ev_len) < end_ptr, due to this one more retry would happen*/
449 data->length = param.bytes_needed + 1;
451 return -E2BIG;
454 return 0;
457 extern int reconnect_flag;
458 /* SIOCSIWESSID */
459 static int
460 ar6000_ioctl_siwessid(struct net_device *dev,
461 struct iw_request_info *info,
462 struct iw_point *data, char *ssid)
464 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
465 int status;
466 u8 arNetworkType;
467 u8 prevMode = ar->arNetworkType;
469 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
470 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
471 return -EOPNOTSUPP;
474 if (ar->bIsDestroyProgress) {
475 return -EBUSY;
478 if (ar->arWlanState == WLAN_DISABLED) {
479 return -EIO;
482 if (ar->arWmiReady == false) {
483 return -EIO;
486 #if defined(WIRELESS_EXT)
487 if (WIRELESS_EXT >= 20) {
488 data->length += 1;
490 #endif
493 * iwconfig passes a null terminated string with length including this
494 * so we need to account for this
496 if (data->flags && (!data->length || (data->length == 1) ||
497 ((data->length - 1) > sizeof(ar->arSsid))))
500 * ssid is invalid
502 return -EINVAL;
505 if (ar->arNextMode == AP_NETWORK) {
506 /* SSID change for AP network - Will take effect on commit */
507 if(A_MEMCMP(ar->arSsid,ssid,32) != 0) {
508 ar->arSsidLen = data->length - 1;
509 A_MEMCPY(ar->arSsid, ssid, ar->arSsidLen);
510 ar->ap_profile_flag = 1; /* There is a change in profile */
512 return 0;
513 } else if(ar->arNetworkType == AP_NETWORK) {
514 u8 ctr;
515 struct sk_buff *skb;
517 /* We are switching from AP to STA | IBSS mode, cleanup the AP state */
518 for (ctr=0; ctr < AP_MAX_NUM_STA; ctr++) {
519 remove_sta(ar, ar->sta_list[ctr].mac, 0);
521 A_MUTEX_LOCK(&ar->mcastpsqLock);
522 while (!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) {
523 skb = A_NETBUF_DEQUEUE(&ar->mcastpsq);
524 A_NETBUF_FREE(skb);
526 A_MUTEX_UNLOCK(&ar->mcastpsqLock);
529 /* Added for bug 25178, return an IOCTL error instead of target returning
530 Illegal parameter error when either the BSSID or channel is missing
531 and we cannot scan during connect.
533 if (data->flags) {
534 if (ar->arSkipScan == true &&
535 (ar->arChannelHint == 0 ||
536 (!ar->arReqBssid[0] && !ar->arReqBssid[1] && !ar->arReqBssid[2] &&
537 !ar->arReqBssid[3] && !ar->arReqBssid[4] && !ar->arReqBssid[5])))
539 return -EINVAL;
543 if (down_interruptible(&ar->arSem)) {
544 return -ERESTARTSYS;
547 if (ar->bIsDestroyProgress || ar->arWlanState == WLAN_DISABLED) {
548 up(&ar->arSem);
549 return -EBUSY;
552 if (ar->arTxPending[wmi_get_control_ep(ar->arWmi)]) {
554 * sleep until the command queue drains
556 wait_event_interruptible_timeout(arEvent,
557 ar->arTxPending[wmi_get_control_ep(ar->arWmi)] == 0, wmitimeout * HZ);
558 if (signal_pending(current)) {
559 return -EINTR;
563 if (!data->flags) {
564 arNetworkType = ar->arNetworkType;
565 #ifdef ATH6K_CONFIG_CFG80211
566 if (ar->arConnected) {
567 #endif /* ATH6K_CONFIG_CFG80211 */
568 ar6000_init_profile_info(ar);
569 #ifdef ATH6K_CONFIG_CFG80211
571 #endif /* ATH6K_CONFIG_CFG80211 */
572 ar->arNetworkType = arNetworkType;
575 /* Update the arNetworkType */
576 ar->arNetworkType = ar->arNextMode;
579 if ((prevMode != AP_NETWORK) &&
580 ((ar->arSsidLen) || ((ar->arSsidLen == 0) && ar->arConnected) || (!data->flags)))
582 if ((!data->flags) ||
583 (A_MEMCMP(ar->arSsid, ssid, ar->arSsidLen) != 0) ||
584 (ar->arSsidLen != (data->length - 1)))
587 * SSID set previously or essid off has been issued.
589 * Disconnect Command is issued in two cases after wmi is ready
590 * (1) ssid is different from the previous setting
591 * (2) essid off has been issued
594 if (ar->arWmiReady == true) {
595 reconnect_flag = 0;
596 status = wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, 0);
597 status = wmi_disconnect_cmd(ar->arWmi);
598 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
599 ar->arSsidLen = 0;
600 if (ar->arSkipScan == false) {
601 A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
603 if (!data->flags) {
604 up(&ar->arSem);
605 return 0;
607 } else {
608 up(&ar->arSem);
611 else
614 * SSID is same, so we assume profile hasn't changed.
615 * If the interface is up and wmi is ready, we issue
616 * a reconnect cmd. Issue a reconnect only we are already
617 * connected.
619 if((ar->arConnected == true) && (ar->arWmiReady == true))
621 reconnect_flag = true;
622 status = wmi_reconnect_cmd(ar->arWmi,ar->arReqBssid,
623 ar->arChannelHint);
624 up(&ar->arSem);
625 if (status != A_OK) {
626 return -EIO;
628 return 0;
630 else{
632 * Dont return if connect is pending.
634 if(!(ar->arConnectPending)) {
635 up(&ar->arSem);
636 return 0;
642 ar->arSsidLen = data->length - 1;
643 A_MEMCPY(ar->arSsid, ssid, ar->arSsidLen);
645 if (ar6000_connect_to_ap(ar)!= A_OK) {
646 up(&ar->arSem);
647 return -EIO;
648 }else{
649 up(&ar->arSem);
651 return 0;
654 /* SIOCGIWESSID */
655 static int
656 ar6000_ioctl_giwessid(struct net_device *dev,
657 struct iw_request_info *info,
658 struct iw_point *data, char *essid)
660 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
662 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
663 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
664 return -EOPNOTSUPP;
667 if (ar->arWlanState == WLAN_DISABLED) {
668 return -EIO;
671 if (!ar->arSsidLen) {
672 return -EINVAL;
675 data->flags = 1;
676 data->length = ar->arSsidLen;
677 A_MEMCPY(essid, ar->arSsid, ar->arSsidLen);
679 return 0;
683 void ar6000_install_static_wep_keys(AR_SOFTC_T *ar)
685 u8 index;
686 u8 keyUsage;
688 for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) {
689 if (ar->arWepKeyList[index].arKeyLen) {
690 keyUsage = GROUP_USAGE;
691 if (index == ar->arDefTxKeyIndex) {
692 keyUsage |= TX_USAGE;
694 wmi_addKey_cmd(ar->arWmi,
695 index,
696 WEP_CRYPT,
697 keyUsage,
698 ar->arWepKeyList[index].arKeyLen,
699 NULL,
700 ar->arWepKeyList[index].arKey, KEY_OP_INIT_VAL, NULL,
701 NO_SYNC_WMIFLAG);
707 * SIOCSIWRATE
710 ar6000_ioctl_siwrate(struct net_device *dev,
711 struct iw_request_info *info,
712 struct iw_param *rrq, char *extra)
714 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
715 u32 kbps;
716 A_INT8 rate_idx;
718 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
719 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
720 return -EOPNOTSUPP;
723 if (rrq->fixed) {
724 kbps = rrq->value / 1000; /* rrq->value is in bps */
725 } else {
726 kbps = -1; /* -1 indicates auto rate */
728 if(kbps != -1 && wmi_validate_bitrate(ar->arWmi, kbps, &rate_idx) != A_OK)
730 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BitRate is not Valid %d\n", kbps));
731 return -EINVAL;
733 ar->arBitRate = kbps;
734 if(ar->arWmiReady == true)
736 if (wmi_set_bitrate_cmd(ar->arWmi, kbps, -1, -1) != A_OK) {
737 return -EINVAL;
740 return 0;
744 * SIOCGIWRATE
747 ar6000_ioctl_giwrate(struct net_device *dev,
748 struct iw_request_info *info,
749 struct iw_param *rrq, char *extra)
751 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
752 int ret = 0;
754 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
755 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
756 return -EOPNOTSUPP;
759 if (ar->bIsDestroyProgress) {
760 return -EBUSY;
763 if (ar->arWlanState == WLAN_DISABLED) {
764 return -EIO;
767 if ((ar->arNextMode != AP_NETWORK && !ar->arConnected) || ar->arWmiReady == false) {
768 rrq->value = 1000 * 1000;
769 return 0;
772 if (down_interruptible(&ar->arSem)) {
773 return -ERESTARTSYS;
776 if (ar->bIsDestroyProgress || ar->arWlanState == WLAN_DISABLED) {
777 up(&ar->arSem);
778 return -EBUSY;
781 ar->arBitRate = 0xFFFF;
782 if (wmi_get_bitrate_cmd(ar->arWmi) != A_OK) {
783 up(&ar->arSem);
784 return -EIO;
786 wait_event_interruptible_timeout(arEvent, ar->arBitRate != 0xFFFF, wmitimeout * HZ);
787 if (signal_pending(current)) {
788 ret = -EINTR;
790 /* If the interface is down or wmi is not ready or the target is not
791 connected - return the value stored in the device structure */
792 if (!ret) {
793 if (ar->arBitRate == -1) {
794 rrq->fixed = true;
795 rrq->value = 0;
796 } else {
797 rrq->value = ar->arBitRate * 1000;
801 up(&ar->arSem);
803 return ret;
807 * SIOCSIWTXPOW
809 static int
810 ar6000_ioctl_siwtxpow(struct net_device *dev,
811 struct iw_request_info *info,
812 struct iw_param *rrq, char *extra)
814 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
815 u8 dbM;
817 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
818 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
819 return -EOPNOTSUPP;
822 if (ar->arWlanState == WLAN_DISABLED) {
823 return -EIO;
826 if (rrq->disabled) {
827 return -EOPNOTSUPP;
830 if (rrq->fixed) {
831 if (rrq->flags != IW_TXPOW_DBM) {
832 return -EOPNOTSUPP;
834 ar->arTxPwr= dbM = rrq->value;
835 ar->arTxPwrSet = true;
836 } else {
837 ar->arTxPwr = dbM = 0;
838 ar->arTxPwrSet = false;
840 if(ar->arWmiReady == true)
842 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("Set tx pwr cmd %d dbM\n", dbM));
843 wmi_set_txPwr_cmd(ar->arWmi, dbM);
845 return 0;
849 * SIOCGIWTXPOW
852 ar6000_ioctl_giwtxpow(struct net_device *dev,
853 struct iw_request_info *info,
854 struct iw_param *rrq, char *extra)
856 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
857 int ret = 0;
859 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
860 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
861 return -EOPNOTSUPP;
864 if (ar->bIsDestroyProgress) {
865 return -EBUSY;
868 if (ar->arWlanState == WLAN_DISABLED) {
869 return -EIO;
872 if (down_interruptible(&ar->arSem)) {
873 return -ERESTARTSYS;
876 if (ar->bIsDestroyProgress) {
877 up(&ar->arSem);
878 return -EBUSY;
881 if((ar->arWmiReady == true) && (ar->arConnected == true))
883 ar->arTxPwr = 0;
885 if (wmi_get_txPwr_cmd(ar->arWmi) != A_OK) {
886 up(&ar->arSem);
887 return -EIO;
890 wait_event_interruptible_timeout(arEvent, ar->arTxPwr != 0, wmitimeout * HZ);
892 if (signal_pending(current)) {
893 ret = -EINTR;
896 /* If the interace is down or wmi is not ready or target is not connected
897 then return value stored in the device structure */
899 if (!ret) {
900 if (ar->arTxPwrSet == true) {
901 rrq->fixed = true;
903 rrq->value = ar->arTxPwr;
904 rrq->flags = IW_TXPOW_DBM;
906 // IWLIST need this flag to get TxPower
908 rrq->disabled = 0;
911 up(&ar->arSem);
913 return ret;
917 * SIOCSIWRETRY
918 * since iwconfig only provides us with one max retry value, we use it
919 * to apply to data frames of the BE traffic class.
921 static int
922 ar6000_ioctl_siwretry(struct net_device *dev,
923 struct iw_request_info *info,
924 struct iw_param *rrq, char *extra)
926 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
928 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
929 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
930 return -EOPNOTSUPP;
933 if (ar->arWlanState == WLAN_DISABLED) {
934 return -EIO;
937 if (rrq->disabled) {
938 return -EOPNOTSUPP;
941 if ((rrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) {
942 return -EOPNOTSUPP;
945 if ( !(rrq->value >= WMI_MIN_RETRIES) || !(rrq->value <= WMI_MAX_RETRIES)) {
946 return - EINVAL;
948 if(ar->arWmiReady == true)
950 if (wmi_set_retry_limits_cmd(ar->arWmi, DATA_FRAMETYPE, WMM_AC_BE,
951 rrq->value, 0) != A_OK){
952 return -EINVAL;
955 ar->arMaxRetries = rrq->value;
956 return 0;
960 * SIOCGIWRETRY
962 static int
963 ar6000_ioctl_giwretry(struct net_device *dev,
964 struct iw_request_info *info,
965 struct iw_param *rrq, char *extra)
967 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
969 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
970 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
971 return -EOPNOTSUPP;
974 if (ar->arWlanState == WLAN_DISABLED) {
975 return -EIO;
978 rrq->disabled = 0;
979 switch (rrq->flags & IW_RETRY_TYPE) {
980 case IW_RETRY_LIFETIME:
981 return -EOPNOTSUPP;
982 break;
983 case IW_RETRY_LIMIT:
984 rrq->flags = IW_RETRY_LIMIT;
985 switch (rrq->flags & IW_RETRY_MODIFIER) {
986 case IW_RETRY_MIN:
987 rrq->flags |= IW_RETRY_MIN;
988 rrq->value = WMI_MIN_RETRIES;
989 break;
990 case IW_RETRY_MAX:
991 rrq->flags |= IW_RETRY_MAX;
992 rrq->value = ar->arMaxRetries;
993 break;
995 break;
997 return 0;
1001 * SIOCSIWENCODE
1003 static int
1004 ar6000_ioctl_siwencode(struct net_device *dev,
1005 struct iw_request_info *info,
1006 struct iw_point *erq, char *keybuf)
1008 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1009 int index;
1010 A_INT32 auth = 0;
1012 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
1013 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
1014 return -EOPNOTSUPP;
1017 if(ar->arNextMode != AP_NETWORK) {
1019 * Static WEP Keys should be configured before setting the SSID
1021 if (ar->arSsid[0] && erq->length) {
1022 return -EIO;
1026 if (ar->arWlanState == WLAN_DISABLED) {
1027 return -EIO;
1030 index = erq->flags & IW_ENCODE_INDEX;
1032 if (index && (((index - 1) < WMI_MIN_KEY_INDEX) ||
1033 ((index - 1) > WMI_MAX_KEY_INDEX)))
1035 return -EIO;
1038 if (erq->flags & IW_ENCODE_DISABLED) {
1040 * Encryption disabled
1042 if (index) {
1044 * If key index was specified then clear the specified key
1046 index--;
1047 A_MEMZERO(ar->arWepKeyList[index].arKey,
1048 sizeof(ar->arWepKeyList[index].arKey));
1049 ar->arWepKeyList[index].arKeyLen = 0;
1051 ar->arDot11AuthMode = OPEN_AUTH;
1052 ar->arPairwiseCrypto = NONE_CRYPT;
1053 ar->arGroupCrypto = NONE_CRYPT;
1054 ar->arAuthMode = NONE_AUTH;
1055 } else {
1057 * Enabling WEP encryption
1059 if (index) {
1060 index--; /* keyindex is off base 1 in iwconfig */
1063 if (erq->flags & IW_ENCODE_OPEN) {
1064 auth |= OPEN_AUTH;
1065 ar->arDefTxKeyIndex = index;
1067 if (erq->flags & IW_ENCODE_RESTRICTED) {
1068 auth |= SHARED_AUTH;
1071 if (!auth) {
1072 auth = OPEN_AUTH;
1075 if (erq->length) {
1076 if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(erq->length)) {
1077 return -EIO;
1080 A_MEMZERO(ar->arWepKeyList[index].arKey,
1081 sizeof(ar->arWepKeyList[index].arKey));
1082 A_MEMCPY(ar->arWepKeyList[index].arKey, keybuf, erq->length);
1083 ar->arWepKeyList[index].arKeyLen = erq->length;
1084 ar->arDot11AuthMode = auth;
1085 } else {
1086 if (ar->arWepKeyList[index].arKeyLen == 0) {
1087 return -EIO;
1089 ar->arDefTxKeyIndex = index;
1091 if(ar->arSsidLen && ar->arWepKeyList[index].arKeyLen) {
1092 wmi_addKey_cmd(ar->arWmi,
1093 index,
1094 WEP_CRYPT,
1095 GROUP_USAGE | TX_USAGE,
1096 ar->arWepKeyList[index].arKeyLen,
1097 NULL,
1098 ar->arWepKeyList[index].arKey, KEY_OP_INIT_VAL, NULL,
1099 NO_SYNC_WMIFLAG);
1103 ar->arPairwiseCrypto = WEP_CRYPT;
1104 ar->arGroupCrypto = WEP_CRYPT;
1105 ar->arAuthMode = NONE_AUTH;
1108 if(ar->arNextMode != AP_NETWORK) {
1110 * profile has changed. Erase ssid to signal change
1112 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
1113 ar->arSsidLen = 0;
1115 ar->ap_profile_flag = 1; /* There is a change in profile */
1116 return 0;
1119 static int
1120 ar6000_ioctl_giwencode(struct net_device *dev,
1121 struct iw_request_info *info,
1122 struct iw_point *erq, char *key)
1124 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1125 u8 keyIndex;
1126 struct ar_wep_key *wk;
1128 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
1129 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
1130 return -EOPNOTSUPP;
1133 if (ar->arWlanState == WLAN_DISABLED) {
1134 return -EIO;
1137 if (ar->arPairwiseCrypto == NONE_CRYPT) {
1138 erq->length = 0;
1139 erq->flags = IW_ENCODE_DISABLED;
1140 } else {
1141 if (ar->arPairwiseCrypto == WEP_CRYPT) {
1142 /* get the keyIndex */
1143 keyIndex = erq->flags & IW_ENCODE_INDEX;
1144 if (0 == keyIndex) {
1145 keyIndex = ar->arDefTxKeyIndex;
1146 } else if ((keyIndex - 1 < WMI_MIN_KEY_INDEX) ||
1147 (keyIndex - 1 > WMI_MAX_KEY_INDEX))
1149 keyIndex = WMI_MIN_KEY_INDEX;
1150 } else {
1151 keyIndex--;
1153 erq->flags = keyIndex + 1;
1154 erq->flags &= ~IW_ENCODE_DISABLED;
1155 wk = &ar->arWepKeyList[keyIndex];
1156 if (erq->length > wk->arKeyLen) {
1157 erq->length = wk->arKeyLen;
1159 if (wk->arKeyLen) {
1160 A_MEMCPY(key, wk->arKey, erq->length);
1162 } else {
1163 erq->flags &= ~IW_ENCODE_DISABLED;
1164 if (ar->user_saved_keys.keyOk) {
1165 erq->length = ar->user_saved_keys.ucast_ik.ik_keylen;
1166 if (erq->length) {
1167 A_MEMCPY(key, ar->user_saved_keys.ucast_ik.ik_keydata, erq->length);
1169 } else {
1170 erq->length = 1; // not really printing any key but let iwconfig know enc is on
1174 if (ar->arDot11AuthMode & OPEN_AUTH) {
1175 erq->flags |= IW_ENCODE_OPEN;
1177 if (ar->arDot11AuthMode & SHARED_AUTH) {
1178 erq->flags |= IW_ENCODE_RESTRICTED;
1182 return 0;
1185 #if WIRELESS_EXT >= 18
1187 * SIOCSIWGENIE
1189 static int
1190 ar6000_ioctl_siwgenie(struct net_device *dev,
1191 struct iw_request_info *info,
1192 struct iw_point *erq, char *extra)
1194 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1196 #ifdef WAPI_ENABLE
1197 u8 *ie = erq->pointer;
1198 u8 ie_type = ie[0];
1199 u16 ie_length = erq->length;
1200 u8 wapi_ie[128];
1201 #endif
1203 if (ar->arWmiReady == false) {
1204 return -EIO;
1206 #ifdef WAPI_ENABLE
1207 if (ie_type == IEEE80211_ELEMID_WAPI) {
1208 if (ie_length > 0) {
1209 if (copy_from_user(wapi_ie, ie, ie_length)) {
1210 return -EIO;
1213 wmi_set_appie_cmd(ar->arWmi, WMI_FRAME_ASSOC_REQ, ie_length, wapi_ie);
1214 } else if (ie_length == 0) {
1215 wmi_set_appie_cmd(ar->arWmi, WMI_FRAME_ASSOC_REQ, ie_length, wapi_ie);
1217 #endif
1218 return 0;
1223 * SIOCGIWGENIE
1225 static int
1226 ar6000_ioctl_giwgenie(struct net_device *dev,
1227 struct iw_request_info *info,
1228 struct iw_point *erq, char *extra)
1230 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1232 if (ar->arWmiReady == false) {
1233 return -EIO;
1235 erq->length = 0;
1236 erq->flags = 0;
1238 return 0;
1242 * SIOCSIWAUTH
1244 static int
1245 ar6000_ioctl_siwauth(struct net_device *dev,
1246 struct iw_request_info *info,
1247 struct iw_param *data, char *extra)
1249 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1251 bool profChanged;
1252 u16 param;
1253 A_INT32 ret;
1254 A_INT32 value;
1256 if (ar->arWmiReady == false) {
1257 return -EIO;
1260 if (ar->arWlanState == WLAN_DISABLED) {
1261 return -EIO;
1264 param = data->flags & IW_AUTH_INDEX;
1265 value = data->value;
1266 profChanged = true;
1267 ret = 0;
1269 switch (param) {
1270 case IW_AUTH_WPA_VERSION:
1271 if (value & IW_AUTH_WPA_VERSION_DISABLED) {
1272 ar->arAuthMode = NONE_AUTH;
1273 } else if (value & IW_AUTH_WPA_VERSION_WPA) {
1274 ar->arAuthMode = WPA_AUTH;
1275 } else if (value & IW_AUTH_WPA_VERSION_WPA2) {
1276 ar->arAuthMode = WPA2_AUTH;
1277 } else {
1278 ret = -1;
1279 profChanged = false;
1281 break;
1282 case IW_AUTH_CIPHER_PAIRWISE:
1283 if (value & IW_AUTH_CIPHER_NONE) {
1284 ar->arPairwiseCrypto = NONE_CRYPT;
1285 ar->arPairwiseCryptoLen = 0;
1286 } else if (value & IW_AUTH_CIPHER_WEP40) {
1287 ar->arPairwiseCrypto = WEP_CRYPT;
1288 ar->arPairwiseCryptoLen = 5;
1289 } else if (value & IW_AUTH_CIPHER_TKIP) {
1290 ar->arPairwiseCrypto = TKIP_CRYPT;
1291 ar->arPairwiseCryptoLen = 0;
1292 } else if (value & IW_AUTH_CIPHER_CCMP) {
1293 ar->arPairwiseCrypto = AES_CRYPT;
1294 ar->arPairwiseCryptoLen = 0;
1295 } else if (value & IW_AUTH_CIPHER_WEP104) {
1296 ar->arPairwiseCrypto = WEP_CRYPT;
1297 ar->arPairwiseCryptoLen = 13;
1298 } else {
1299 ret = -1;
1300 profChanged = false;
1302 break;
1303 case IW_AUTH_CIPHER_GROUP:
1304 if (value & IW_AUTH_CIPHER_NONE) {
1305 ar->arGroupCrypto = NONE_CRYPT;
1306 ar->arGroupCryptoLen = 0;
1307 } else if (value & IW_AUTH_CIPHER_WEP40) {
1308 ar->arGroupCrypto = WEP_CRYPT;
1309 ar->arGroupCryptoLen = 5;
1310 } else if (value & IW_AUTH_CIPHER_TKIP) {
1311 ar->arGroupCrypto = TKIP_CRYPT;
1312 ar->arGroupCryptoLen = 0;
1313 } else if (value & IW_AUTH_CIPHER_CCMP) {
1314 ar->arGroupCrypto = AES_CRYPT;
1315 ar->arGroupCryptoLen = 0;
1316 } else if (value & IW_AUTH_CIPHER_WEP104) {
1317 ar->arGroupCrypto = WEP_CRYPT;
1318 ar->arGroupCryptoLen = 13;
1319 } else {
1320 ret = -1;
1321 profChanged = false;
1323 break;
1324 case IW_AUTH_KEY_MGMT:
1325 if (value & IW_AUTH_KEY_MGMT_PSK) {
1326 if (WPA_AUTH == ar->arAuthMode) {
1327 ar->arAuthMode = WPA_PSK_AUTH;
1328 } else if (WPA2_AUTH == ar->arAuthMode) {
1329 ar->arAuthMode = WPA2_PSK_AUTH;
1330 } else {
1331 ret = -1;
1333 } else if (!(value & IW_AUTH_KEY_MGMT_802_1X)) {
1334 ar->arAuthMode = NONE_AUTH;
1336 break;
1337 case IW_AUTH_TKIP_COUNTERMEASURES:
1338 wmi_set_tkip_countermeasures_cmd(ar->arWmi, value);
1339 profChanged = false;
1340 break;
1341 case IW_AUTH_DROP_UNENCRYPTED:
1342 profChanged = false;
1343 break;
1344 case IW_AUTH_80211_AUTH_ALG:
1345 ar->arDot11AuthMode = 0;
1346 if (value & IW_AUTH_ALG_OPEN_SYSTEM) {
1347 ar->arDot11AuthMode |= OPEN_AUTH;
1349 if (value & IW_AUTH_ALG_SHARED_KEY) {
1350 ar->arDot11AuthMode |= SHARED_AUTH;
1352 if (value & IW_AUTH_ALG_LEAP) {
1353 ar->arDot11AuthMode = LEAP_AUTH;
1355 if(ar->arDot11AuthMode == 0) {
1356 ret = -1;
1357 profChanged = false;
1359 break;
1360 case IW_AUTH_WPA_ENABLED:
1361 if (!value) {
1362 ar->arAuthMode = NONE_AUTH;
1363 /* when the supplicant is stopped, it calls this
1364 * handler with value=0. The followings need to be
1365 * reset if the STA were to connect again
1366 * without security
1368 ar->arDot11AuthMode = OPEN_AUTH;
1369 ar->arPairwiseCrypto = NONE_CRYPT;
1370 ar->arPairwiseCryptoLen = 0;
1371 ar->arGroupCrypto = NONE_CRYPT;
1372 ar->arGroupCryptoLen = 0;
1374 break;
1375 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1376 profChanged = false;
1377 break;
1378 case IW_AUTH_ROAMING_CONTROL:
1379 profChanged = false;
1380 break;
1381 case IW_AUTH_PRIVACY_INVOKED:
1382 if (!value) {
1383 ar->arPairwiseCrypto = NONE_CRYPT;
1384 ar->arPairwiseCryptoLen = 0;
1385 ar->arGroupCrypto = NONE_CRYPT;
1386 ar->arGroupCryptoLen = 0;
1388 break;
1389 #ifdef WAPI_ENABLE
1390 case IW_AUTH_WAPI_ENABLED:
1391 ar->arWapiEnable = value;
1392 break;
1393 #endif
1394 default:
1395 ret = -1;
1396 profChanged = false;
1397 break;
1400 if (profChanged == true) {
1402 * profile has changed. Erase ssid to signal change
1404 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
1405 ar->arSsidLen = 0;
1408 return ret;
1413 * SIOCGIWAUTH
1415 static int
1416 ar6000_ioctl_giwauth(struct net_device *dev,
1417 struct iw_request_info *info,
1418 struct iw_param *data, char *extra)
1420 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1421 u16 param;
1422 A_INT32 ret;
1424 if (ar->arWmiReady == false) {
1425 return -EIO;
1428 if (ar->arWlanState == WLAN_DISABLED) {
1429 return -EIO;
1432 param = data->flags & IW_AUTH_INDEX;
1433 ret = 0;
1434 data->value = 0;
1437 switch (param) {
1438 case IW_AUTH_WPA_VERSION:
1439 if (ar->arAuthMode == NONE_AUTH) {
1440 data->value |= IW_AUTH_WPA_VERSION_DISABLED;
1441 } else if (ar->arAuthMode == WPA_AUTH) {
1442 data->value |= IW_AUTH_WPA_VERSION_WPA;
1443 } else if (ar->arAuthMode == WPA2_AUTH) {
1444 data->value |= IW_AUTH_WPA_VERSION_WPA2;
1445 } else {
1446 ret = -1;
1448 break;
1449 case IW_AUTH_CIPHER_PAIRWISE:
1450 if (ar->arPairwiseCrypto == NONE_CRYPT) {
1451 data->value |= IW_AUTH_CIPHER_NONE;
1452 } else if (ar->arPairwiseCrypto == WEP_CRYPT) {
1453 if (ar->arPairwiseCryptoLen == 13) {
1454 data->value |= IW_AUTH_CIPHER_WEP104;
1455 } else {
1456 data->value |= IW_AUTH_CIPHER_WEP40;
1458 } else if (ar->arPairwiseCrypto == TKIP_CRYPT) {
1459 data->value |= IW_AUTH_CIPHER_TKIP;
1460 } else if (ar->arPairwiseCrypto == AES_CRYPT) {
1461 data->value |= IW_AUTH_CIPHER_CCMP;
1462 } else {
1463 ret = -1;
1465 break;
1466 case IW_AUTH_CIPHER_GROUP:
1467 if (ar->arGroupCrypto == NONE_CRYPT) {
1468 data->value |= IW_AUTH_CIPHER_NONE;
1469 } else if (ar->arGroupCrypto == WEP_CRYPT) {
1470 if (ar->arGroupCryptoLen == 13) {
1471 data->value |= IW_AUTH_CIPHER_WEP104;
1472 } else {
1473 data->value |= IW_AUTH_CIPHER_WEP40;
1475 } else if (ar->arGroupCrypto == TKIP_CRYPT) {
1476 data->value |= IW_AUTH_CIPHER_TKIP;
1477 } else if (ar->arGroupCrypto == AES_CRYPT) {
1478 data->value |= IW_AUTH_CIPHER_CCMP;
1479 } else {
1480 ret = -1;
1482 break;
1483 case IW_AUTH_KEY_MGMT:
1484 if ((ar->arAuthMode == WPA_PSK_AUTH) ||
1485 (ar->arAuthMode == WPA2_PSK_AUTH)) {
1486 data->value |= IW_AUTH_KEY_MGMT_PSK;
1487 } else if ((ar->arAuthMode == WPA_AUTH) ||
1488 (ar->arAuthMode == WPA2_AUTH)) {
1489 data->value |= IW_AUTH_KEY_MGMT_802_1X;
1491 break;
1492 case IW_AUTH_TKIP_COUNTERMEASURES:
1493 // TODO. Save countermeassure enable/disable
1494 data->value = 0;
1495 break;
1496 case IW_AUTH_DROP_UNENCRYPTED:
1497 break;
1498 case IW_AUTH_80211_AUTH_ALG:
1499 if (ar->arDot11AuthMode == OPEN_AUTH) {
1500 data->value |= IW_AUTH_ALG_OPEN_SYSTEM;
1501 } else if (ar->arDot11AuthMode == SHARED_AUTH) {
1502 data->value |= IW_AUTH_ALG_SHARED_KEY;
1503 } else if (ar->arDot11AuthMode == LEAP_AUTH) {
1504 data->value |= IW_AUTH_ALG_LEAP;
1505 } else {
1506 ret = -1;
1508 break;
1509 case IW_AUTH_WPA_ENABLED:
1510 if (ar->arAuthMode == NONE_AUTH) {
1511 data->value = 0;
1512 } else {
1513 data->value = 1;
1515 break;
1516 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1517 break;
1518 case IW_AUTH_ROAMING_CONTROL:
1519 break;
1520 case IW_AUTH_PRIVACY_INVOKED:
1521 if (ar->arPairwiseCrypto == NONE_CRYPT) {
1522 data->value = 0;
1523 } else {
1524 data->value = 1;
1526 break;
1527 #ifdef WAPI_ENABLE
1528 case IW_AUTH_WAPI_ENABLED:
1529 data->value = ar->arWapiEnable;
1530 break;
1531 #endif
1532 default:
1533 ret = -1;
1534 break;
1537 return 0;
1541 * SIOCSIWPMKSA
1543 static int
1544 ar6000_ioctl_siwpmksa(struct net_device *dev,
1545 struct iw_request_info *info,
1546 struct iw_point *data, char *extra)
1548 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1549 A_INT32 ret;
1550 int status;
1551 struct iw_pmksa *pmksa;
1553 pmksa = (struct iw_pmksa *)extra;
1555 if (ar->arWmiReady == false) {
1556 return -EIO;
1559 ret = 0;
1560 status = A_OK;
1562 switch (pmksa->cmd) {
1563 case IW_PMKSA_ADD:
1564 status = wmi_setPmkid_cmd(ar->arWmi, (u8 *)pmksa->bssid.sa_data, pmksa->pmkid, true);
1565 break;
1566 case IW_PMKSA_REMOVE:
1567 status = wmi_setPmkid_cmd(ar->arWmi, (u8 *)pmksa->bssid.sa_data, pmksa->pmkid, false);
1568 break;
1569 case IW_PMKSA_FLUSH:
1570 if (ar->arConnected == true) {
1571 status = wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, 0);
1573 break;
1574 default:
1575 ret=-1;
1576 break;
1578 if (status != A_OK) {
1579 ret = -1;
1582 return ret;
1585 #ifdef WAPI_ENABLE
1587 #define PN_INIT 0x5c365c36
1589 static int ar6000_set_wapi_key(struct net_device *dev,
1590 struct iw_request_info *info,
1591 struct iw_point *erq, char *extra)
1593 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1594 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1595 KEY_USAGE keyUsage = 0;
1596 A_INT32 keyLen;
1597 u8 *keyData;
1598 A_INT32 index;
1599 u32 *PN;
1600 A_INT32 i;
1601 int status;
1602 u8 wapiKeyRsc[16];
1603 CRYPTO_TYPE keyType = WAPI_CRYPT;
1604 const u8 broadcastMac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1606 index = erq->flags & IW_ENCODE_INDEX;
1607 if (index && (((index - 1) < WMI_MIN_KEY_INDEX) ||
1608 ((index - 1) > WMI_MAX_KEY_INDEX))) {
1609 return -EIO;
1612 index--;
1613 if (index < 0 || index > 4) {
1614 return -EIO;
1616 keyData = (u8 *)(ext + 1);
1617 keyLen = erq->length - sizeof(struct iw_encode_ext);
1618 A_MEMCPY(wapiKeyRsc, ext->tx_seq, sizeof(wapiKeyRsc));
1620 if (A_MEMCMP(ext->addr.sa_data, broadcastMac, sizeof(broadcastMac)) == 0) {
1621 keyUsage |= GROUP_USAGE;
1622 PN = (u32 *)wapiKeyRsc;
1623 for (i = 0; i < 4; i++) {
1624 PN[i] = PN_INIT;
1626 } else {
1627 keyUsage |= PAIRWISE_USAGE;
1629 status = wmi_addKey_cmd(ar->arWmi,
1630 index,
1631 keyType,
1632 keyUsage,
1633 keyLen,
1634 wapiKeyRsc,
1635 keyData,
1636 KEY_OP_INIT_WAPIPN,
1637 NULL,
1638 SYNC_BEFORE_WMIFLAG);
1639 if (A_OK != status) {
1640 return -EIO;
1642 return 0;
1645 #endif
1648 * SIOCSIWENCODEEXT
1650 static int
1651 ar6000_ioctl_siwencodeext(struct net_device *dev,
1652 struct iw_request_info *info,
1653 struct iw_point *erq, char *extra)
1655 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1656 A_INT32 index;
1657 struct iw_encode_ext *ext;
1658 KEY_USAGE keyUsage;
1659 A_INT32 keyLen;
1660 u8 *keyData;
1661 u8 keyRsc[8];
1662 int status;
1663 CRYPTO_TYPE keyType;
1664 #ifdef USER_KEYS
1665 struct ieee80211req_key ik;
1666 #endif /* USER_KEYS */
1668 if (ar->arWlanState == WLAN_DISABLED) {
1669 return -EIO;
1672 #ifdef USER_KEYS
1673 ar->user_saved_keys.keyOk = false;
1674 #endif /* USER_KEYS */
1676 index = erq->flags & IW_ENCODE_INDEX;
1678 if (index && (((index - 1) < WMI_MIN_KEY_INDEX) ||
1679 ((index - 1) > WMI_MAX_KEY_INDEX)))
1681 return -EIO;
1684 ext = (struct iw_encode_ext *)extra;
1685 if (erq->flags & IW_ENCODE_DISABLED) {
1687 * Encryption disabled
1689 if (index) {
1691 * If key index was specified then clear the specified key
1693 index--;
1694 A_MEMZERO(ar->arWepKeyList[index].arKey,
1695 sizeof(ar->arWepKeyList[index].arKey));
1696 ar->arWepKeyList[index].arKeyLen = 0;
1698 } else {
1700 * Enabling WEP encryption
1702 if (index) {
1703 index--; /* keyindex is off base 1 in iwconfig */
1706 keyUsage = 0;
1707 keyLen = erq->length - sizeof(struct iw_encode_ext);
1709 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
1710 keyUsage = TX_USAGE;
1711 ar->arDefTxKeyIndex = index;
1712 // Just setting the key index
1713 if (keyLen == 0) {
1714 return 0;
1718 if (keyLen <= 0) {
1719 return -EIO;
1722 /* key follows iw_encode_ext */
1723 keyData = (u8 *)(ext + 1);
1725 switch (ext->alg) {
1726 case IW_ENCODE_ALG_WEP:
1727 keyType = WEP_CRYPT;
1728 #ifdef USER_KEYS
1729 ik.ik_type = IEEE80211_CIPHER_WEP;
1730 #endif /* USER_KEYS */
1731 if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(keyLen)) {
1732 return -EIO;
1735 /* Check whether it is static wep. */
1736 if (!ar->arConnected) {
1737 A_MEMZERO(ar->arWepKeyList[index].arKey,
1738 sizeof(ar->arWepKeyList[index].arKey));
1739 A_MEMCPY(ar->arWepKeyList[index].arKey, keyData, keyLen);
1740 ar->arWepKeyList[index].arKeyLen = keyLen;
1742 return 0;
1744 break;
1745 case IW_ENCODE_ALG_TKIP:
1746 keyType = TKIP_CRYPT;
1747 #ifdef USER_KEYS
1748 ik.ik_type = IEEE80211_CIPHER_TKIP;
1749 #endif /* USER_KEYS */
1750 break;
1751 case IW_ENCODE_ALG_CCMP:
1752 keyType = AES_CRYPT;
1753 #ifdef USER_KEYS
1754 ik.ik_type = IEEE80211_CIPHER_AES_CCM;
1755 #endif /* USER_KEYS */
1756 break;
1757 #ifdef WAPI_ENABLE
1758 case IW_ENCODE_ALG_SM4:
1759 if (ar->arWapiEnable) {
1760 return ar6000_set_wapi_key(dev, info, erq, extra);
1761 } else {
1762 return -EIO;
1764 #endif
1765 case IW_ENCODE_ALG_PMK:
1766 ar->arConnectCtrlFlags |= CONNECT_DO_WPA_OFFLOAD;
1767 return wmi_set_pmk_cmd(ar->arWmi, keyData);
1768 default:
1769 return -EIO;
1773 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1774 keyUsage |= GROUP_USAGE;
1775 } else {
1776 keyUsage |= PAIRWISE_USAGE;
1779 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
1780 A_MEMCPY(keyRsc, ext->rx_seq, sizeof(keyRsc));
1781 } else {
1782 A_MEMZERO(keyRsc, sizeof(keyRsc));
1785 if (((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMode)) &&
1786 (GROUP_USAGE & keyUsage))
1788 A_UNTIMEOUT(&ar->disconnect_timer);
1791 status = wmi_addKey_cmd(ar->arWmi, index, keyType, keyUsage,
1792 keyLen, keyRsc,
1793 keyData, KEY_OP_INIT_VAL,
1794 (u8 *)ext->addr.sa_data,
1795 SYNC_BOTH_WMIFLAG);
1796 if (status != A_OK) {
1797 return -EIO;
1800 #ifdef USER_KEYS
1801 ik.ik_keyix = index;
1802 ik.ik_keylen = keyLen;
1803 memcpy(ik.ik_keydata, keyData, keyLen);
1804 memcpy(&ik.ik_keyrsc, keyRsc, sizeof(keyRsc));
1805 memcpy(ik.ik_macaddr, ext->addr.sa_data, ETH_ALEN);
1806 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1807 memcpy(&ar->user_saved_keys.bcast_ik, &ik,
1808 sizeof(struct ieee80211req_key));
1809 } else {
1810 memcpy(&ar->user_saved_keys.ucast_ik, &ik,
1811 sizeof(struct ieee80211req_key));
1813 ar->user_saved_keys.keyOk = true;
1814 #endif /* USER_KEYS */
1818 return 0;
1822 * SIOCGIWENCODEEXT
1824 static int
1825 ar6000_ioctl_giwencodeext(struct net_device *dev,
1826 struct iw_request_info *info,
1827 struct iw_point *erq, char *extra)
1829 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1831 if (ar->arWlanState == WLAN_DISABLED) {
1832 return -EIO;
1835 if (ar->arPairwiseCrypto == NONE_CRYPT) {
1836 erq->length = 0;
1837 erq->flags = IW_ENCODE_DISABLED;
1838 } else {
1839 erq->length = 0;
1842 return 0;
1844 #endif // WIRELESS_EXT >= 18
1846 #if WIRELESS_EXT > 20
1847 static int ar6000_ioctl_siwpower(struct net_device *dev,
1848 struct iw_request_info *info,
1849 union iwreq_data *wrqu, char *extra)
1851 #ifndef ATH6K_CONFIG_OTA_MODE
1852 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1853 WMI_POWER_MODE power_mode;
1855 if (ar->arWmiReady == false) {
1856 return -EIO;
1859 if (ar->arWlanState == WLAN_DISABLED) {
1860 return -EIO;
1863 if (wrqu->power.disabled)
1864 power_mode = MAX_PERF_POWER;
1865 else
1866 power_mode = REC_POWER;
1868 if (wmi_powermode_cmd(ar->arWmi, power_mode) < 0)
1869 return -EIO;
1870 #endif
1871 return 0;
1874 static int ar6000_ioctl_giwpower(struct net_device *dev,
1875 struct iw_request_info *info,
1876 union iwreq_data *wrqu, char *extra)
1878 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1879 WMI_POWER_MODE power_mode;
1881 if (ar->arWmiReady == false) {
1882 return -EIO;
1885 if (ar->arWlanState == WLAN_DISABLED) {
1886 return -EIO;
1889 power_mode = wmi_get_power_mode_cmd(ar->arWmi);
1891 if (power_mode == MAX_PERF_POWER)
1892 wrqu->power.disabled = 1;
1893 else
1894 wrqu->power.disabled = 0;
1896 return 0;
1898 #endif // WIRELESS_EXT > 20
1901 * SIOCGIWNAME
1904 ar6000_ioctl_giwname(struct net_device *dev,
1905 struct iw_request_info *info,
1906 char *name, char *extra)
1908 u8 capability;
1909 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1911 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
1912 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
1913 return -EOPNOTSUPP;
1916 if (ar->arWlanState == WLAN_DISABLED) {
1917 return -EIO;
1920 capability = ar->arPhyCapability;
1921 if(ar->arNetworkType == INFRA_NETWORK && ar->arConnected) {
1922 bss_t *bss = wmi_find_node(ar->arWmi, ar->arBssid);
1923 if (bss) {
1924 capability = get_bss_phy_capability(bss);
1925 wmi_node_return(ar->arWmi, bss);
1928 switch (capability) {
1929 case (WMI_11A_CAPABILITY):
1930 strncpy(name, "AR6000 802.11a", IFNAMSIZ);
1931 break;
1932 case (WMI_11G_CAPABILITY):
1933 strncpy(name, "AR6000 802.11g", IFNAMSIZ);
1934 break;
1935 case (WMI_11AG_CAPABILITY):
1936 strncpy(name, "AR6000 802.11ag", IFNAMSIZ);
1937 break;
1938 case (WMI_11NA_CAPABILITY):
1939 strncpy(name, "AR6000 802.11na", IFNAMSIZ);
1940 break;
1941 case (WMI_11NG_CAPABILITY):
1942 strncpy(name, "AR6000 802.11ng", IFNAMSIZ);
1943 break;
1944 case (WMI_11NAG_CAPABILITY):
1945 strncpy(name, "AR6000 802.11nag", IFNAMSIZ);
1946 break;
1947 default:
1948 strncpy(name, "AR6000 802.11b", IFNAMSIZ);
1949 break;
1952 return 0;
1956 * SIOCSIWFREQ
1959 ar6000_ioctl_siwfreq(struct net_device *dev,
1960 struct iw_request_info *info,
1961 struct iw_freq *freq, char *extra)
1963 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1965 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
1966 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
1967 return -EOPNOTSUPP;
1970 if (ar->arWlanState == WLAN_DISABLED) {
1971 return -EIO;
1975 * We support limiting the channels via wmiconfig.
1977 * We use this command to configure the channel hint for the connect cmd
1978 * so it is possible the target will end up connecting to a different
1979 * channel.
1981 if (freq->e > 1) {
1982 return -EINVAL;
1983 } else if (freq->e == 1) {
1984 ar->arChannelHint = freq->m / 100000;
1985 } else {
1986 if(freq->m) {
1987 ar->arChannelHint = wlan_ieee2freq(freq->m);
1988 } else {
1989 /* Auto Channel Selection */
1990 ar->arChannelHint = 0;
1994 ar->ap_profile_flag = 1; /* There is a change in profile */
1996 A_PRINTF("channel hint set to %d\n", ar->arChannelHint);
1997 return 0;
2001 * SIOCGIWFREQ
2004 ar6000_ioctl_giwfreq(struct net_device *dev,
2005 struct iw_request_info *info,
2006 struct iw_freq *freq, char *extra)
2008 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2010 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2011 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2012 return -EOPNOTSUPP;
2015 if (ar->arWlanState == WLAN_DISABLED) {
2016 return -EIO;
2019 if (ar->arNetworkType == AP_NETWORK) {
2020 if(ar->arChannelHint) {
2021 freq->m = ar->arChannelHint * 100000;
2022 } else if(ar->arACS) {
2023 freq->m = ar->arACS * 100000;
2024 } else {
2025 return -EINVAL;
2027 } else {
2028 if (ar->arConnected != true) {
2029 return -EINVAL;
2030 } else {
2031 freq->m = ar->arBssChannel * 100000;
2035 freq->e = 1;
2037 return 0;
2041 * SIOCSIWMODE
2044 ar6000_ioctl_siwmode(struct net_device *dev,
2045 struct iw_request_info *info,
2046 __u32 *mode, char *extra)
2048 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2050 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2051 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2052 return -EOPNOTSUPP;
2055 if (ar->arWlanState == WLAN_DISABLED) {
2056 return -EIO;
2060 * clear SSID during mode switch in connected state
2062 if(!(ar->arNetworkType == (((*mode) == IW_MODE_INFRA) ? INFRA_NETWORK : ADHOC_NETWORK)) && (ar->arConnected == true) ){
2063 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
2064 ar->arSsidLen = 0;
2067 switch (*mode) {
2068 case IW_MODE_INFRA:
2069 ar->arNextMode = INFRA_NETWORK;
2070 break;
2071 case IW_MODE_ADHOC:
2072 ar->arNextMode = ADHOC_NETWORK;
2073 break;
2074 case IW_MODE_MASTER:
2075 ar->arNextMode = AP_NETWORK;
2076 break;
2077 default:
2078 return -EINVAL;
2081 /* clear all shared parameters between AP and STA|IBSS modes when we
2082 * switch between them. Switch between STA & IBSS modes does'nt clear
2083 * the shared profile. This is as per the original design for switching
2084 * between STA & IBSS.
2086 if (ar->arNetworkType == AP_NETWORK || ar->arNextMode == AP_NETWORK) {
2087 ar->arDot11AuthMode = OPEN_AUTH;
2088 ar->arAuthMode = NONE_AUTH;
2089 ar->arPairwiseCrypto = NONE_CRYPT;
2090 ar->arPairwiseCryptoLen = 0;
2091 ar->arGroupCrypto = NONE_CRYPT;
2092 ar->arGroupCryptoLen = 0;
2093 ar->arChannelHint = 0;
2094 ar->arBssChannel = 0;
2095 A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
2096 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
2097 ar->arSsidLen = 0;
2100 /* SSID has to be cleared to trigger a profile change while switching
2101 * between STA & IBSS modes having the same SSID
2103 if (ar->arNetworkType != ar->arNextMode) {
2104 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
2105 ar->arSsidLen = 0;
2108 return 0;
2112 * SIOCGIWMODE
2115 ar6000_ioctl_giwmode(struct net_device *dev,
2116 struct iw_request_info *info,
2117 __u32 *mode, char *extra)
2119 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2121 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2122 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2123 return -EOPNOTSUPP;
2126 if (ar->arWlanState == WLAN_DISABLED) {
2127 return -EIO;
2130 switch (ar->arNetworkType) {
2131 case INFRA_NETWORK:
2132 *mode = IW_MODE_INFRA;
2133 break;
2134 case ADHOC_NETWORK:
2135 *mode = IW_MODE_ADHOC;
2136 break;
2137 case AP_NETWORK:
2138 *mode = IW_MODE_MASTER;
2139 break;
2140 default:
2141 return -EIO;
2143 return 0;
2147 * SIOCSIWSENS
2150 ar6000_ioctl_siwsens(struct net_device *dev,
2151 struct iw_request_info *info,
2152 struct iw_param *sens, char *extra)
2154 return 0;
2158 * SIOCGIWSENS
2161 ar6000_ioctl_giwsens(struct net_device *dev,
2162 struct iw_request_info *info,
2163 struct iw_param *sens, char *extra)
2165 sens->value = 0;
2166 sens->fixed = 1;
2168 return 0;
2172 * SIOCGIWRANGE
2175 ar6000_ioctl_giwrange(struct net_device *dev,
2176 struct iw_request_info *info,
2177 struct iw_point *data, char *extra)
2179 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2180 struct iw_range *range = (struct iw_range *) extra;
2181 int i, ret = 0;
2183 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2184 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2185 return -EOPNOTSUPP;
2188 if (ar->bIsDestroyProgress) {
2189 return -EBUSY;
2192 if (ar->arWmiReady == false) {
2193 return -EIO;
2196 if (down_interruptible(&ar->arSem)) {
2197 return -ERESTARTSYS;
2200 if (ar->bIsDestroyProgress) {
2201 up(&ar->arSem);
2202 return -EBUSY;
2205 ar->arNumChannels = -1;
2206 A_MEMZERO(ar->arChannelList, sizeof (ar->arChannelList));
2208 if (wmi_get_channelList_cmd(ar->arWmi) != A_OK) {
2209 up(&ar->arSem);
2210 return -EIO;
2213 wait_event_interruptible_timeout(arEvent, ar->arNumChannels != -1, wmitimeout * HZ);
2215 if (signal_pending(current)) {
2216 up(&ar->arSem);
2217 return -EINTR;
2220 data->length = sizeof(struct iw_range);
2221 A_MEMZERO(range, sizeof(struct iw_range));
2223 range->txpower_capa = 0;
2225 range->min_pmp = 1 * 1024;
2226 range->max_pmp = 65535 * 1024;
2227 range->min_pmt = 1 * 1024;
2228 range->max_pmt = 1000 * 1024;
2229 range->pmp_flags = IW_POWER_PERIOD;
2230 range->pmt_flags = IW_POWER_TIMEOUT;
2231 range->pm_capa = 0;
2233 range->we_version_compiled = WIRELESS_EXT;
2234 range->we_version_source = 13;
2236 range->retry_capa = IW_RETRY_LIMIT;
2237 range->retry_flags = IW_RETRY_LIMIT;
2238 range->min_retry = 0;
2239 range->max_retry = 255;
2241 range->num_frequency = range->num_channels = ar->arNumChannels;
2242 for (i = 0; i < ar->arNumChannels; i++) {
2243 range->freq[i].i = wlan_freq2ieee(ar->arChannelList[i]);
2244 range->freq[i].m = ar->arChannelList[i] * 100000;
2245 range->freq[i].e = 1;
2247 * Linux supports max of 32 channels, bail out once you
2248 * reach the max.
2250 if (i == IW_MAX_FREQUENCIES) {
2251 break;
2255 /* Max quality is max field value minus noise floor */
2256 range->max_qual.qual = 0xff - 161;
2259 * In order to use dBm measurements, 'level' must be lower
2260 * than any possible measurement (see iw_print_stats() in
2261 * wireless tools). It's unclear how this is meant to be
2262 * done, but setting zero in these values forces dBm and
2263 * the actual numbers are not used.
2265 range->max_qual.level = 0;
2266 range->max_qual.noise = 0;
2268 range->sensitivity = 3;
2270 range->max_encoding_tokens = 4;
2271 /* XXX query driver to find out supported key sizes */
2272 range->num_encoding_sizes = 3;
2273 range->encoding_size[0] = 5; /* 40-bit */
2274 range->encoding_size[1] = 13; /* 104-bit */
2275 range->encoding_size[2] = 16; /* 128-bit */
2277 range->num_bitrates = 0;
2279 /* estimated maximum TCP throughput values (bps) */
2280 range->throughput = 22000000;
2282 range->min_rts = 0;
2283 range->max_rts = 2347;
2284 range->min_frag = 256;
2285 range->max_frag = 2346;
2287 up(&ar->arSem);
2289 return ret;
2294 * SIOCSIWAP
2295 * This ioctl is used to set the desired bssid for the connect command.
2298 ar6000_ioctl_siwap(struct net_device *dev,
2299 struct iw_request_info *info,
2300 struct sockaddr *ap_addr, char *extra)
2302 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2304 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2305 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2306 return -EOPNOTSUPP;
2309 if (ar->arWlanState == WLAN_DISABLED) {
2310 return -EIO;
2313 if (ap_addr->sa_family != ARPHRD_ETHER) {
2314 return -EIO;
2317 if (A_MEMCMP(&ap_addr->sa_data, bcast_mac, AR6000_ETH_ADDR_LEN) == 0) {
2318 A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
2319 } else {
2320 A_MEMCPY(ar->arReqBssid, &ap_addr->sa_data, sizeof(ar->arReqBssid));
2323 return 0;
2327 * SIOCGIWAP
2330 ar6000_ioctl_giwap(struct net_device *dev,
2331 struct iw_request_info *info,
2332 struct sockaddr *ap_addr, char *extra)
2334 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2336 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2337 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2338 return -EOPNOTSUPP;
2341 if (ar->arWlanState == WLAN_DISABLED) {
2342 return -EIO;
2345 if (ar->arNetworkType == AP_NETWORK) {
2346 A_MEMCPY(&ap_addr->sa_data, dev->dev_addr, ATH_MAC_LEN);
2347 ap_addr->sa_family = ARPHRD_ETHER;
2348 return 0;
2351 if (ar->arConnected != true) {
2352 return -EINVAL;
2355 A_MEMCPY(&ap_addr->sa_data, ar->arBssid, sizeof(ar->arBssid));
2356 ap_addr->sa_family = ARPHRD_ETHER;
2358 return 0;
2361 #if (WIRELESS_EXT >= 18)
2363 * SIOCSIWMLME
2366 ar6000_ioctl_siwmlme(struct net_device *dev,
2367 struct iw_request_info *info,
2368 struct iw_point *data, char *extra)
2370 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2372 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2373 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2374 return -EOPNOTSUPP;
2377 if (ar->bIsDestroyProgress) {
2378 return -EBUSY;
2381 if (ar->arWlanState == WLAN_DISABLED) {
2382 return -EIO;
2385 if (ar->arWmiReady == false) {
2386 return -EIO;
2389 if (down_interruptible(&ar->arSem)) {
2390 return -ERESTARTSYS;
2393 if (data->pointer && data->length == sizeof(struct iw_mlme)) {
2395 u8 arNetworkType;
2396 struct iw_mlme mlme;
2398 if (copy_from_user(&mlme, data->pointer, sizeof(struct iw_mlme)))
2399 return -EIO;
2401 switch (mlme.cmd) {
2403 case IW_MLME_DEAUTH:
2404 /* fall through */
2405 case IW_MLME_DISASSOC:
2406 if ((ar->arConnected != true) ||
2407 (memcmp(ar->arBssid, mlme.addr.sa_data, 6) != 0)) {
2409 up(&ar->arSem);
2410 return -EINVAL;
2412 wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, 0);
2413 arNetworkType = ar->arNetworkType;
2414 ar6000_init_profile_info(ar);
2415 ar->arNetworkType = arNetworkType;
2416 reconnect_flag = 0;
2417 wmi_disconnect_cmd(ar->arWmi);
2418 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
2419 ar->arSsidLen = 0;
2420 if (ar->arSkipScan == false) {
2421 A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
2423 break;
2425 case IW_MLME_AUTH:
2426 /* fall through */
2427 case IW_MLME_ASSOC:
2428 /* fall through */
2429 default:
2430 up(&ar->arSem);
2431 return -EOPNOTSUPP;
2435 up(&ar->arSem);
2436 return 0;
2438 #endif /* WIRELESS_EXT >= 18 */
2441 * SIOCGIWAPLIST
2444 ar6000_ioctl_iwaplist(struct net_device *dev,
2445 struct iw_request_info *info,
2446 struct iw_point *data, char *extra)
2448 return -EIO; /* for now */
2452 * SIOCSIWSCAN
2455 ar6000_ioctl_siwscan(struct net_device *dev,
2456 struct iw_request_info *info,
2457 struct iw_point *data, char *extra)
2459 #define ACT_DWELLTIME_DEFAULT 105
2460 #define HOME_TXDRAIN_TIME 100
2461 #define SCAN_INT HOME_TXDRAIN_TIME + ACT_DWELLTIME_DEFAULT
2462 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2463 int ret = 0;
2465 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2466 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2467 return -EOPNOTSUPP;
2470 if (ar->arWmiReady == false) {
2471 return -EIO;
2474 if (ar->arWlanState == WLAN_DISABLED) {
2475 return -EIO;
2478 /* If scan is issued in the middle of ongoing scan or connect,
2479 dont issue another one */
2480 if ( ar->scan_triggered > 0 ) {
2481 ++ar->scan_triggered;
2482 if (ar->scan_triggered < 5) {
2483 return 0;
2484 } else {
2485 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("Scan request is triggered over 5 times. Not scan complete event\n"));
2489 if (!ar->arUserBssFilter) {
2490 if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != A_OK) {
2491 return -EIO;
2495 if (ar->arConnected) {
2496 if (wmi_get_stats_cmd(ar->arWmi) != A_OK) {
2497 return -EIO;
2501 #ifdef ANDROID_ENV
2502 #if WIRELESS_EXT >= 18
2503 if (data->pointer && (data->length == sizeof(struct iw_scan_req)))
2505 if ((data->flags & IW_SCAN_THIS_ESSID) == IW_SCAN_THIS_ESSID)
2507 struct iw_scan_req req;
2508 if (copy_from_user(&req, data->pointer, sizeof(struct iw_scan_req)))
2509 return -EIO;
2510 if (wmi_probedSsid_cmd(ar->arWmi, 1, SPECIFIC_SSID_FLAG, req.essid_len, req.essid) != A_OK)
2511 return -EIO;
2512 ar->scanSpecificSsid = true;
2514 else
2516 if (ar->scanSpecificSsid) {
2517 if (wmi_probedSsid_cmd(ar->arWmi, 1, DISABLE_SSID_FLAG, 0, NULL) != A_OK)
2518 return -EIO;
2519 ar->scanSpecificSsid = false;
2523 else
2525 if (ar->scanSpecificSsid) {
2526 if (wmi_probedSsid_cmd(ar->arWmi, 1, DISABLE_SSID_FLAG, 0, NULL) != A_OK)
2527 return -EIO;
2528 ar->scanSpecificSsid = false;
2531 #endif
2532 #endif /* ANDROID_ENV */
2534 if (wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, false, false, \
2535 0, 0, 0, NULL) != A_OK) {
2536 ret = -EIO;
2539 if (ret == 0) {
2540 ar->scan_triggered = 1;
2543 return ret;
2544 #undef ACT_DWELLTIME_DEFAULT
2545 #undef HOME_TXDRAIN_TIME
2546 #undef SCAN_INT
2551 * Units are in db above the noise floor. That means the
2552 * rssi values reported in the tx/rx descriptors in the
2553 * driver are the SNR expressed in db.
2555 * If you assume that the noise floor is -95, which is an
2556 * excellent assumption 99.5 % of the time, then you can
2557 * derive the absolute signal level (i.e. -95 + rssi).
2558 * There are some other slight factors to take into account
2559 * depending on whether the rssi measurement is from 11b,
2560 * 11g, or 11a. These differences are at most 2db and
2561 * can be documented.
2563 * NB: various calculations are based on the orinoco/wavelan
2564 * drivers for compatibility
2566 static void
2567 ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi)
2569 if (rssi < 0) {
2570 iq->qual = 0;
2571 } else {
2572 iq->qual = rssi;
2575 /* NB: max is 94 because noise is hardcoded to 161 */
2576 if (iq->qual > 94)
2577 iq->qual = 94;
2579 iq->noise = 161; /* -95dBm */
2580 iq->level = iq->noise + iq->qual;
2581 iq->updated = 7;
2586 ar6000_ioctl_siwcommit(struct net_device *dev,
2587 struct iw_request_info *info,
2588 struct iw_point *data, char *extra)
2590 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2592 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2593 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2594 return -EOPNOTSUPP;
2597 if (ar->arWmiReady == false) {
2598 return -EIO;
2601 if (ar->arWlanState == WLAN_DISABLED) {
2602 return -EIO;
2605 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("AP: SSID %s freq %d authmode %d dot11 auth %d"\
2606 " PW crypto %d GRP crypto %d\n",
2607 ar->arSsid, ar->arChannelHint,
2608 ar->arAuthMode, ar->arDot11AuthMode,
2609 ar->arPairwiseCrypto, ar->arGroupCrypto));
2611 ar6000_ap_mode_profile_commit(ar);
2613 /* if there is a profile switch from STA|IBSS mode to AP mode,
2614 * update the host driver association state for the STA|IBSS mode.
2616 if (ar->arNetworkType != AP_NETWORK && ar->arNextMode == AP_NETWORK) {
2617 ar->arConnectPending = false;
2618 ar->arConnected = false;
2619 /* Stop getting pkts from upper stack */
2620 netif_stop_queue(ar->arNetDev);
2621 A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
2622 ar->arBssChannel = 0;
2623 ar->arBeaconInterval = 0;
2625 /* Flush the Tx queues */
2626 ar6000_TxDataCleanup(ar);
2628 /* Start getting pkts from upper stack */
2629 netif_wake_queue(ar->arNetDev);
2632 return 0;
2635 #define W_PROTO(_x) wait_ ## _x
2636 #define WAIT_HANDLER_IMPL(_x, type) \
2637 int wait_ ## _x (struct net_device *dev, struct iw_request_info *info, type wrqu, char *extra) {\
2638 int ret; \
2639 dev_hold(dev); \
2640 rtnl_unlock(); \
2641 ret = _x(dev, info, wrqu, extra); \
2642 rtnl_lock(); \
2643 dev_put(dev); \
2644 return ret;\
2647 WAIT_HANDLER_IMPL(ar6000_ioctl_siwessid, struct iw_point *)
2648 WAIT_HANDLER_IMPL(ar6000_ioctl_giwrate, struct iw_param *)
2649 WAIT_HANDLER_IMPL(ar6000_ioctl_giwtxpow, struct iw_param *)
2650 WAIT_HANDLER_IMPL(ar6000_ioctl_giwrange, struct iw_point*)
2652 /* Structures to export the Wireless Handlers */
2653 static const iw_handler ath_handlers[] = {
2654 (iw_handler) ar6000_ioctl_siwcommit, /* SIOCSIWCOMMIT */
2655 (iw_handler) ar6000_ioctl_giwname, /* SIOCGIWNAME */
2656 (iw_handler) NULL, /* SIOCSIWNWID */
2657 (iw_handler) NULL, /* SIOCGIWNWID */
2658 (iw_handler) ar6000_ioctl_siwfreq, /* SIOCSIWFREQ */
2659 (iw_handler) ar6000_ioctl_giwfreq, /* SIOCGIWFREQ */
2660 (iw_handler) ar6000_ioctl_siwmode, /* SIOCSIWMODE */
2661 (iw_handler) ar6000_ioctl_giwmode, /* SIOCGIWMODE */
2662 (iw_handler) ar6000_ioctl_siwsens, /* SIOCSIWSENS */
2663 (iw_handler) ar6000_ioctl_giwsens, /* SIOCGIWSENS */
2664 (iw_handler) NULL /* not _used */, /* SIOCSIWRANGE */
2665 (iw_handler) W_PROTO(ar6000_ioctl_giwrange),/* SIOCGIWRANGE */
2666 (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */
2667 (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
2668 (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */
2669 (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
2670 (iw_handler) NULL, /* SIOCSIWSPY */
2671 (iw_handler) NULL, /* SIOCGIWSPY */
2672 (iw_handler) NULL, /* SIOCSIWTHRSPY */
2673 (iw_handler) NULL, /* SIOCGIWTHRSPY */
2674 (iw_handler) ar6000_ioctl_siwap, /* SIOCSIWAP */
2675 (iw_handler) ar6000_ioctl_giwap, /* SIOCGIWAP */
2676 #if (WIRELESS_EXT >= 18)
2677 (iw_handler) ar6000_ioctl_siwmlme, /* SIOCSIWMLME */
2678 #else
2679 (iw_handler) NULL, /* -- hole -- */
2680 #endif /* WIRELESS_EXT >= 18 */
2681 (iw_handler) ar6000_ioctl_iwaplist, /* SIOCGIWAPLIST */
2682 (iw_handler) ar6000_ioctl_siwscan, /* SIOCSIWSCAN */
2683 (iw_handler) ar6000_ioctl_giwscan, /* SIOCGIWSCAN */
2684 (iw_handler) W_PROTO(ar6000_ioctl_siwessid),/* SIOCSIWESSID */
2685 (iw_handler) ar6000_ioctl_giwessid, /* SIOCGIWESSID */
2686 (iw_handler) NULL, /* SIOCSIWNICKN */
2687 (iw_handler) NULL, /* SIOCGIWNICKN */
2688 (iw_handler) NULL, /* -- hole -- */
2689 (iw_handler) NULL, /* -- hole -- */
2690 (iw_handler) ar6000_ioctl_siwrate, /* SIOCSIWRATE */
2691 (iw_handler) W_PROTO(ar6000_ioctl_giwrate), /* SIOCGIWRATE */
2692 (iw_handler) NULL, /* SIOCSIWRTS */
2693 (iw_handler) NULL, /* SIOCGIWRTS */
2694 (iw_handler) NULL, /* SIOCSIWFRAG */
2695 (iw_handler) NULL, /* SIOCGIWFRAG */
2696 (iw_handler) ar6000_ioctl_siwtxpow, /* SIOCSIWTXPOW */
2697 (iw_handler) W_PROTO(ar6000_ioctl_giwtxpow),/* SIOCGIWTXPOW */
2698 (iw_handler) ar6000_ioctl_siwretry, /* SIOCSIWRETRY */
2699 (iw_handler) ar6000_ioctl_giwretry, /* SIOCGIWRETRY */
2700 (iw_handler) ar6000_ioctl_siwencode, /* SIOCSIWENCODE */
2701 (iw_handler) ar6000_ioctl_giwencode, /* SIOCGIWENCODE */
2702 #if WIRELESS_EXT > 20
2703 (iw_handler) ar6000_ioctl_siwpower, /* SIOCSIWPOWER */
2704 (iw_handler) ar6000_ioctl_giwpower, /* SIOCGIWPOWER */
2705 #endif // WIRELESS_EXT > 20
2706 #if WIRELESS_EXT >= 18
2707 (iw_handler) NULL, /* -- hole -- */
2708 (iw_handler) NULL, /* -- hole -- */
2709 (iw_handler) ar6000_ioctl_siwgenie, /* SIOCSIWGENIE */
2710 (iw_handler) ar6000_ioctl_giwgenie, /* SIOCGIWGENIE */
2711 (iw_handler) ar6000_ioctl_siwauth, /* SIOCSIWAUTH */
2712 (iw_handler) ar6000_ioctl_giwauth, /* SIOCGIWAUTH */
2713 (iw_handler) ar6000_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */
2714 (iw_handler) ar6000_ioctl_giwencodeext, /* SIOCGIWENCODEEXT */
2715 (iw_handler) ar6000_ioctl_siwpmksa, /* SIOCSIWPMKSA */
2716 #endif // WIRELESS_EXT >= 18
2719 struct iw_handler_def ath_iw_handler_def = {
2720 .standard = (iw_handler *)ath_handlers,
2721 .num_standard = ARRAY_SIZE(ath_handlers),
2722 .private = NULL,
2723 .num_private = 0,