af78ae05fcb5d9a1ad73ad63a8b302b95f62f934
[openwrt/svn-archive/archive.git] / target / linux / s3c24xx / files-2.6.31 / drivers / ar6000 / ar6000 / wireless_ext.c
1 /*
2 *
3 * Copyright (c) 2004-2007 Atheros Communications Inc.
4 * All rights reserved.
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation;
10 *
11 * Software distributed under the License is distributed on an "AS
12 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
13 * implied. See the License for the specific language governing
14 * rights and limitations under the License.
15 *
16 *
17 *
18 */
19
20 #include "ar6000_drv.h"
21
22 static A_UINT8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
23 static void ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi);
24 extern unsigned int wmitimeout;
25 extern A_WAITQUEUE_HEAD arEvent;
26 extern wait_queue_head_t ar6000_scan_queue;
27
28 /*
29 * Encode a WPA or RSN information element as a custom
30 * element using the hostap format.
31 */
32 static u_int
33 encode_ie(void *buf, size_t bufsize,
34 const u_int8_t *ie, size_t ielen,
35 const char *leader, size_t leader_len)
36 {
37 u_int8_t *p;
38 int i;
39
40 if (bufsize < leader_len)
41 return 0;
42 p = buf;
43 memcpy(p, leader, leader_len);
44 bufsize -= leader_len;
45 p += leader_len;
46 for (i = 0; i < ielen && bufsize > 2; i++)
47 p += sprintf(p, "%02x", ie[i]);
48 return (i == ielen ? p - (u_int8_t *)buf : 0);
49 }
50
51 void
52 ar6000_scan_node(void *arg, bss_t *ni)
53 {
54 struct iw_event iwe;
55 #if WIRELESS_EXT > 14
56 char buf[64*2 + 30];
57 #endif
58 struct ar_giwscan_param *param;
59 A_CHAR *current_ev;
60 A_CHAR *end_buf;
61 struct ieee80211_common_ie *cie;
62 struct iw_request_info info;
63
64 info.cmd = 0;
65 info.flags = 0;
66
67 param = (struct ar_giwscan_param *)arg;
68
69 if (param->current_ev >= param->end_buf) {
70 return;
71 }
72 if ((param->firstPass == TRUE) &&
73 ((ni->ni_cie.ie_wpa == NULL) && (ni->ni_cie.ie_rsn == NULL))) {
74 /*
75 * Only forward wpa bss's in first pass
76 */
77 return;
78 }
79
80 if ((param->firstPass == FALSE) &&
81 ((ni->ni_cie.ie_wpa != NULL) || (ni->ni_cie.ie_rsn != NULL))) {
82 /*
83 * Only forward non-wpa bss's in 2nd pass
84 */
85 return;
86 }
87
88 current_ev = param->current_ev;
89 end_buf = param->end_buf;
90
91 cie = &ni->ni_cie;
92
93 A_MEMZERO(&iwe, sizeof(iwe));
94 iwe.cmd = SIOCGIWAP;
95 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
96 A_MEMCPY(iwe.u.ap_addr.sa_data, ni->ni_macaddr, 6);
97 current_ev = iwe_stream_add_event(&info, current_ev, end_buf, &iwe,
98 IW_EV_ADDR_LEN);
99
100 A_MEMZERO(&iwe, sizeof(iwe));
101 iwe.cmd = SIOCGIWESSID;
102 iwe.u.data.flags = 1;
103 iwe.u.data.length = cie->ie_ssid[1];
104 current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe,
105 &cie->ie_ssid[2]);
106
107 if (cie->ie_capInfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) {
108 A_MEMZERO(&iwe, sizeof(iwe));
109 iwe.cmd = SIOCGIWMODE;
110 iwe.u.mode = cie->ie_capInfo & IEEE80211_CAPINFO_ESS ?
111 IW_MODE_MASTER : IW_MODE_ADHOC;
112 current_ev = iwe_stream_add_event(&info, current_ev, end_buf, &iwe,
113 IW_EV_UINT_LEN);
114 }
115
116 A_MEMZERO(&iwe, sizeof(iwe));
117 iwe.cmd = SIOCGIWFREQ;
118 iwe.u.freq.m = cie->ie_chan * 100000;
119 iwe.u.freq.e = 1;
120 current_ev = iwe_stream_add_event(&info, current_ev, end_buf, &iwe,
121 IW_EV_FREQ_LEN);
122
123 A_MEMZERO(&iwe, sizeof(iwe));
124 iwe.cmd = IWEVQUAL;
125 ar6000_set_quality(&iwe.u.qual, ni->ni_snr);
126 current_ev = iwe_stream_add_event(&info, current_ev, end_buf, &iwe,
127 IW_EV_QUAL_LEN);
128
129 A_MEMZERO(&iwe, sizeof(iwe));
130 iwe.cmd = SIOCGIWENCODE;
131 if (cie->ie_capInfo & IEEE80211_CAPINFO_PRIVACY) {
132 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
133 } else {
134 iwe.u.data.flags = IW_ENCODE_DISABLED;
135 }
136 iwe.u.data.length = 0;
137 current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, "");
138
139 A_MEMZERO(&iwe, sizeof(iwe));
140 iwe.cmd = IWEVCUSTOM;
141 snprintf(buf, sizeof(buf), "bcn_int=%d", cie->ie_beaconInt);
142 iwe.u.data.length = strlen(buf);
143 current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, buf);
144
145 if (cie->ie_wpa != NULL) {
146 static const char wpa_leader[] = "wpa_ie=";
147
148 A_MEMZERO(&iwe, sizeof(iwe));
149 iwe.cmd = IWEVCUSTOM;
150 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wpa,
151 cie->ie_wpa[1]+2,
152 wpa_leader, sizeof(wpa_leader)-1);
153
154 if (iwe.u.data.length != 0) {
155 current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe,
156 buf);
157 }
158 }
159
160 if (cie->ie_rsn != NULL && cie->ie_rsn[0] == IEEE80211_ELEMID_RSN) {
161 static const char rsn_leader[] = "rsn_ie=";
162
163 A_MEMZERO(&iwe, sizeof(iwe));
164 iwe.cmd = IWEVCUSTOM;
165 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_rsn,
166 cie->ie_rsn[1]+2,
167 rsn_leader, sizeof(rsn_leader)-1);
168
169 if (iwe.u.data.length != 0) {
170 current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe,
171 buf);
172 }
173 }
174
175 if (cie->ie_wmm != NULL) {
176 static const char wmm_leader[] = "wmm_ie=";
177
178 A_MEMZERO(&iwe, sizeof(iwe));
179 iwe.cmd = IWEVCUSTOM;
180 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wmm,
181 cie->ie_wmm[1]+2,
182 wmm_leader, sizeof(wmm_leader)-1);
183 if (iwe.u.data.length != 0) {
184 current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe,
185 buf);
186 }
187 }
188
189 if (cie->ie_ath != NULL) {
190 static const char ath_leader[] = "ath_ie=";
191
192 A_MEMZERO(&iwe, sizeof(iwe));
193 iwe.cmd = IWEVCUSTOM;
194 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_ath,
195 cie->ie_ath[1]+2,
196 ath_leader, sizeof(ath_leader)-1);
197 if (iwe.u.data.length != 0) {
198 current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe,
199 buf);
200 }
201 }
202
203 param->current_ev = current_ev;
204 }
205
206 int
207 ar6000_ioctl_giwscan(struct net_device *dev,
208 struct iw_request_info *info,
209 struct iw_point *data, char *extra)
210 {
211 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
212 struct ar_giwscan_param param;
213 int i;
214
215 if (ar->arWlanState == WLAN_DISABLED) {
216 return -EIO;
217 }
218
219 if (ar->arWmiReady == FALSE) {
220 return -EIO;
221 }
222
223 param.current_ev = extra;
224 param.end_buf = extra + IW_SCAN_MAX_DATA;
225 param.firstPass = TRUE;
226
227 /*
228 * Do two passes to insure WPA scan candidates
229 * are sorted to the front. This is a hack to deal with
230 * the wireless extensions capping scan results at
231 * IW_SCAN_MAX_DATA bytes. In densely populated environments
232 * it's easy to overflow this buffer (especially with WPA/RSN
233 * information elements). Note this sorting hack does not
234 * guarantee we won't overflow anyway.
235 */
236 for (i = 0; i < 2; i++) {
237 /*
238 * Translate data to WE format.
239 */
240 wmi_iterate_nodes(ar->arWmi, ar6000_scan_node, &param);
241 param.firstPass = FALSE;
242 if (param.current_ev >= param.end_buf) {
243 data->length = param.current_ev - extra;
244 return -E2BIG;
245 }
246 }
247
248 data->length = param.current_ev - extra;
249 return 0;
250 }
251
252 extern int reconnect_flag;
253 /* SIOCSIWESSID */
254 static int
255 ar6000_ioctl_siwessid(struct net_device *dev,
256 struct iw_request_info *info,
257 struct iw_point *data, char *ssid)
258 {
259 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
260 A_STATUS status;
261 A_UINT8 arNetworkType;
262
263 if (ar->arWlanState == WLAN_DISABLED) {
264 return -EIO;
265 }
266
267 if (ar->arWmiReady == FALSE) {
268 return -EIO;
269 }
270
271 /*
272 * iwconfig passes a string with length excluding any trailing NUL.
273 * FIXME: we should be able to set an ESSID of 32 bytes, yet things fall
274 * over badly if we do. So we limit the ESSID to 31 bytes.
275 */
276 if (data->flags && (!data->length || data->length >= sizeof(ar->arSsid))) {
277 /*
278 * ssid is invalid
279 */
280 return -EINVAL;
281 }
282 /* Added for bug 25178, return an IOCTL error instead of target returning
283 Illegal parameter error when either the BSSID or channel is missing
284 and we cannot scan during connect.
285 */
286 if (data->flags) {
287 if (ar->arSkipScan == TRUE &&
288 (ar->arChannelHint == 0 ||
289 (!ar->arReqBssid[0] && !ar->arReqBssid[1] && !ar->arReqBssid[2] &&
290 !ar->arReqBssid[3] && !ar->arReqBssid[4] && !ar->arReqBssid[5])))
291 {
292 return -EINVAL;
293 }
294 }
295
296 if (down_interruptible(&ar->arSem)) {
297 return -ERESTARTSYS;
298 }
299
300 if (ar->arTxPending[WMI_CONTROL_PRI]) {
301 /*
302 * sleep until the command queue drains
303 */
304 wait_event_interruptible_timeout(arEvent,
305 ar->arTxPending[WMI_CONTROL_PRI] == 0, wmitimeout * HZ);
306 if (signal_pending(current)) {
307 return -EINTR;
308 }
309 }
310
311 if (!data->flags) {
312 arNetworkType = ar->arNetworkType;
313 ar6000_init_profile_info(ar);
314 ar->arNetworkType = arNetworkType;
315 }
316
317 /*
318 * The original logic here prevented a disconnect if issuing an "essid off"
319 * if no ESSID was set, presumably to prevent sending multiple disconnects
320 * to the WMI.
321 *
322 * Unfortunately, this also meant that no disconnect was sent when we were
323 * already connected, but the profile has been changed since (which also
324 * clears the ESSID as a reminder that the WMI needs updating.)
325 *
326 * The "1 ||" makes sure we always disconnect or reconnect. The WMI doesn't
327 * seem to mind being sent multiple disconnects.
328 */
329 if (1 || (ar->arSsidLen) || (!data->flags))
330 {
331 if ((!data->flags) ||
332 (A_MEMCMP(ar->arSsid, ssid, ar->arSsidLen) != 0) ||
333 (ar->arSsidLen != (data->length)))
334 {
335 /*
336 * SSID set previously or essid off has been issued.
337 *
338 * Disconnect Command is issued in two cases after wmi is ready
339 * (1) ssid is different from the previous setting
340 * (2) essid off has been issued
341 *
342 */
343 if (ar->arWmiReady == TRUE) {
344 reconnect_flag = 0;
345 status = wmi_disconnect_cmd(ar->arWmi);
346 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
347 ar->arSsidLen = 0;
348 if (ar->arSkipScan == FALSE) {
349 A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
350 }
351 if (!data->flags) {
352 up(&ar->arSem);
353 return 0;
354 }
355 } else {
356 up(&ar->arSem);
357 }
358 }
359 else
360 {
361 /*
362 * SSID is same, so we assume profile hasn't changed.
363 * If the interface is up and wmi is ready, we issue
364 * a reconnect cmd. Issue a reconnect only we are already
365 * connected.
366 */
367 if((ar->arConnected == TRUE) && (ar->arWmiReady == TRUE))
368 {
369 reconnect_flag = TRUE;
370 status = wmi_reconnect_cmd(ar->arWmi,ar->arReqBssid,
371 ar->arChannelHint);
372 up(&ar->arSem);
373 if (status != A_OK) {
374 return -EIO;
375 }
376 return 0;
377 }
378 else{
379 /*
380 * Dont return if connect is pending.
381 */
382 if(!(ar->arConnectPending)) {
383 up(&ar->arSem);
384 return 0;
385 }
386 }
387 }
388 }
389
390 ar->arSsidLen = data->length;
391 A_MEMCPY(ar->arSsid, ssid, ar->arSsidLen);
392
393 /* The ssid length check prevents second "essid off" from the user,
394 to be treated as a connect cmd. The second "essid off" is ignored.
395 */
396 if((ar->arWmiReady == TRUE) && (ar->arSsidLen > 0) )
397 {
398 AR6000_SPIN_LOCK(&ar->arLock, 0);
399 if (SHARED_AUTH == ar->arDot11AuthMode) {
400 ar6000_install_static_wep_keys(ar);
401 }
402 AR_DEBUG_PRINTF("Connect called with authmode %d dot11 auth %d"\
403 " PW crypto %d PW crypto Len %d GRP crypto %d"\
404 " GRP crypto Len %d\n",
405 ar->arAuthMode, ar->arDot11AuthMode,
406 ar->arPairwiseCrypto, ar->arPairwiseCryptoLen,
407 ar->arGroupCrypto, ar->arGroupCryptoLen);
408 reconnect_flag = 0;
409 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
410 status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType,
411 ar->arDot11AuthMode, ar->arAuthMode,
412 ar->arPairwiseCrypto, ar->arPairwiseCryptoLen,
413 ar->arGroupCrypto,ar->arGroupCryptoLen,
414 ar->arSsidLen, ar->arSsid,
415 ar->arReqBssid, ar->arChannelHint,
416 ar->arConnectCtrlFlags);
417
418
419 up(&ar->arSem);
420
421 if (status != A_OK) {
422 return -EIO;
423 }
424 ar->arConnectPending = TRUE;
425 }else{
426 up(&ar->arSem);
427 }
428 return 0;
429 }
430
431 /* SIOCGIWESSID */
432 static int
433 ar6000_ioctl_giwessid(struct net_device *dev,
434 struct iw_request_info *info,
435 struct iw_point *data, char *essid)
436 {
437 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
438
439 if (ar->arWlanState == WLAN_DISABLED) {
440 return -EIO;
441 }
442
443 data->flags = 1;
444 data->length = ar->arSsidLen;
445 A_MEMCPY(essid, ar->arSsid, ar->arSsidLen);
446
447 return 0;
448 }
449
450
451 void ar6000_install_static_wep_keys(AR_SOFTC_T *ar)
452 {
453 A_UINT8 index;
454 A_UINT8 keyUsage;
455
456 for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) {
457 if (ar->arWepKeyList[index].arKeyLen) {
458 keyUsage = GROUP_USAGE;
459 if (index == ar->arDefTxKeyIndex) {
460 keyUsage |= TX_USAGE;
461 }
462 wmi_addKey_cmd(ar->arWmi,
463 index,
464 WEP_CRYPT,
465 keyUsage,
466 ar->arWepKeyList[index].arKeyLen,
467 NULL,
468 ar->arWepKeyList[index].arKey, KEY_OP_INIT_VAL,
469 NO_SYNC_WMIFLAG);
470 }
471 }
472 }
473
474 int
475 ar6000_ioctl_delkey(struct net_device *dev, struct iw_request_info *info,
476 void *w, char *extra)
477 {
478 return 0;
479 }
480
481 int
482 ar6000_ioctl_setmlme(struct net_device *dev, struct iw_request_info *info,
483 void *w, char *extra)
484 {
485 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
486 struct ieee80211req_mlme *mlme = (struct ieee80211req_mlme *)extra;
487
488 if ((ar->arWmiReady == FALSE) || (ar->arConnected != TRUE))
489 return -EIO;
490
491 switch (mlme->im_op) {
492 case IEEE80211_MLME_DISASSOC:
493 case IEEE80211_MLME_DEAUTH:
494 /* Not Supported */
495 break;
496 default:
497 break;
498 }
499 return 0;
500 }
501
502
503 int
504 ar6000_ioctl_setwmmparams(struct net_device *dev, struct iw_request_info *info,
505 void *w, char *extra)
506 {
507 return -EIO; /* for now */
508 }
509
510 int
511 ar6000_ioctl_getwmmparams(struct net_device *dev, struct iw_request_info *info,
512 void *w, char *extra)
513 {
514 return -EIO; /* for now */
515 }
516
517 int ar6000_ioctl_setoptie(struct net_device *dev, struct iw_request_info *info,
518 struct iw_point *data, char *extra)
519 {
520 /* The target generates the WPA/RSN IE */
521 return 0;
522 }
523
524 int
525 ar6000_ioctl_setauthalg(struct net_device *dev, struct iw_request_info *info,
526 void *w, char *extra)
527 {
528 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
529 struct ieee80211req_authalg *req = (struct ieee80211req_authalg *)extra;
530 int ret = 0;
531
532
533 AR6000_SPIN_LOCK(&ar->arLock, 0);
534
535 if (req->auth_alg == AUTH_ALG_OPEN_SYSTEM) {
536 ar->arDot11AuthMode = OPEN_AUTH;
537 } else if (req->auth_alg == AUTH_ALG_LEAP) {
538 ar->arDot11AuthMode = LEAP_AUTH;
539 ar->arPairwiseCrypto = WEP_CRYPT;
540 ar->arGroupCrypto = WEP_CRYPT;
541 } else {
542 ret = -EIO;
543 }
544
545 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
546
547 return ret;
548 }
549 static int
550 ar6000_ioctl_addpmkid(struct net_device *dev, struct iw_request_info *info,
551 void *w, char *extra)
552 {
553 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
554 struct ieee80211req_addpmkid *req = (struct ieee80211req_addpmkid *)extra;
555 A_STATUS status;
556
557 if (ar->arWlanState == WLAN_DISABLED) {
558 return -EIO;
559 }
560
561 AR_DEBUG_PRINTF("Add pmkid for %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x en=%d\n",
562 req->pi_bssid[0], req->pi_bssid[1], req->pi_bssid[2],
563 req->pi_bssid[3], req->pi_bssid[4], req->pi_bssid[5],
564 req->pi_enable);
565
566 status = wmi_setPmkid_cmd(ar->arWmi, req->pi_bssid, req->pi_pmkid,
567 req->pi_enable);
568
569 if (status != A_OK) {
570 return -EIO;
571 }
572
573 return 0;
574 }
575
576 /*
577 * SIOCSIWRATE
578 */
579 int
580 ar6000_ioctl_siwrate(struct net_device *dev,
581 struct iw_request_info *info,
582 struct iw_param *rrq, char *extra)
583 {
584 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
585 A_UINT32 kbps;
586
587 if (rrq->fixed) {
588 kbps = rrq->value / 1000; /* rrq->value is in bps */
589 } else {
590 kbps = -1; /* -1 indicates auto rate */
591 }
592 if(kbps != -1 && wmi_validate_bitrate(ar->arWmi, kbps) == A_EINVAL)
593 {
594 AR_DEBUG_PRINTF("BitRate is not Valid %d\n", kbps);
595 return -EINVAL;
596 }
597 ar->arBitRate = kbps;
598 if(ar->arWmiReady == TRUE)
599 {
600 if (wmi_set_bitrate_cmd(ar->arWmi, kbps) != A_OK) {
601 return -EINVAL;
602 }
603 }
604 return 0;
605 }
606
607 /*
608 * SIOCGIWRATE
609 */
610 int
611 ar6000_ioctl_giwrate(struct net_device *dev,
612 struct iw_request_info *info,
613 struct iw_param *rrq, char *extra)
614 {
615 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
616 int ret = 0;
617
618 if (down_interruptible(&ar->arSem)) {
619 return -ERESTARTSYS;
620 }
621 if(ar->arWmiReady == TRUE)
622 {
623 ar->arBitRate = 0xFFFF;
624 if (wmi_get_bitrate_cmd(ar->arWmi) != A_OK) {
625 up(&ar->arSem);
626 return -EIO;
627 }
628 wait_event_interruptible_timeout(arEvent, ar->arBitRate != 0xFFFF, wmitimeout * HZ);
629 if (signal_pending(current)) {
630 ret = -EINTR;
631 }
632 }
633 /* If the interface is down or wmi is not ready or the target is not
634 connected - return the value stored in the device structure */
635 if (!ret) {
636 if (ar->arBitRate == -1) {
637 rrq->fixed = TRUE;
638 rrq->value = 0;
639 } else {
640 rrq->value = ar->arBitRate * 1000;
641 }
642 }
643
644 up(&ar->arSem);
645
646 return ret;
647 }
648
649 /*
650 * SIOCSIWTXPOW
651 */
652 static int
653 ar6000_ioctl_siwtxpow(struct net_device *dev,
654 struct iw_request_info *info,
655 struct iw_param *rrq, char *extra)
656 {
657 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
658 A_UINT8 dbM;
659
660 if (ar->arWlanState == WLAN_DISABLED) {
661 return -EIO;
662 }
663
664 if (ar->arRadioSwitch == WLAN_ENABLED
665 && rrq->disabled) {
666 if (wmi_switch_radio(ar->arWmi, WLAN_DISABLED) < 0)
667 return -EIO;
668 ar->arRadioSwitch = WLAN_DISABLED;
669 } else if (ar->arRadioSwitch == WLAN_DISABLED
670 && !rrq->disabled) {
671 if (wmi_switch_radio(ar->arWmi, WLAN_ENABLED) < 0)
672 return -EIO;
673 ar->arRadioSwitch = WLAN_ENABLED;
674 }
675
676 if (rrq->fixed) {
677 if (rrq->flags != IW_TXPOW_DBM) {
678 return -EOPNOTSUPP;
679 }
680 ar->arTxPwr= dbM = rrq->value;
681 ar->arTxPwrSet = TRUE;
682 } else {
683 ar->arTxPwr = dbM = 0;
684 ar->arTxPwrSet = FALSE;
685 }
686 if(ar->arWmiReady == TRUE)
687 {
688 AR_DEBUG_PRINTF("Set tx pwr cmd %d dbM\n", dbM);
689 wmi_set_txPwr_cmd(ar->arWmi, dbM);
690 }
691 return 0;
692 }
693
694 /*
695 * SIOCGIWTXPOW
696 */
697 int
698 ar6000_ioctl_giwtxpow(struct net_device *dev,
699 struct iw_request_info *info,
700 struct iw_param *rrq, char *extra)
701 {
702 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
703 int ret = 0;
704
705 if (ar->arWlanState == WLAN_DISABLED) {
706 return -EIO;
707 }
708
709 if (ar->arRadioSwitch == WLAN_DISABLED) {
710 rrq->disabled = 1;
711 return 0;
712 }
713
714 if (down_interruptible(&ar->arSem)) {
715 return -ERESTARTSYS;
716 }
717 if((ar->arWmiReady == TRUE) && (ar->arConnected == TRUE))
718 {
719 ar->arTxPwr = 0;
720
721 if (wmi_get_txPwr_cmd(ar->arWmi) != A_OK) {
722 up(&ar->arSem);
723 return -EIO;
724 }
725
726 wait_event_interruptible_timeout(arEvent, ar->arTxPwr != 0, wmitimeout * HZ);
727
728 if (signal_pending(current)) {
729 ret = -EINTR;
730 }
731 }
732 /* If the interace is down or wmi is not ready or target is not connected
733 then return value stored in the device structure */
734
735 if (!ret) {
736 if (ar->arTxPwrSet == TRUE) {
737 rrq->fixed = TRUE;
738 }
739 rrq->value = ar->arTxPwr;
740 rrq->flags = IW_TXPOW_DBM;
741 }
742
743 up(&ar->arSem);
744
745 return ret;
746 }
747
748 /*
749 * SIOCSIWRETRY
750 * since iwconfig only provides us with one max retry value, we use it
751 * to apply to data frames of the BE traffic class.
752 */
753 static int
754 ar6000_ioctl_siwretry(struct net_device *dev,
755 struct iw_request_info *info,
756 struct iw_param *rrq, char *extra)
757 {
758 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
759
760 if (ar->arWlanState == WLAN_DISABLED) {
761 return -EIO;
762 }
763
764 if (rrq->disabled) {
765 return -EOPNOTSUPP;
766 }
767
768 if ((rrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) {
769 return -EOPNOTSUPP;
770 }
771
772 if ( !(rrq->value >= WMI_MIN_RETRIES) || !(rrq->value <= WMI_MAX_RETRIES)) {
773 return - EINVAL;
774 }
775 if(ar->arWmiReady == TRUE)
776 {
777 if (wmi_set_retry_limits_cmd(ar->arWmi, DATA_FRAMETYPE, WMM_AC_BE,
778 rrq->value, 0) != A_OK){
779 return -EINVAL;
780 }
781 }
782 ar->arMaxRetries = rrq->value;
783 return 0;
784 }
785
786 /*
787 * SIOCGIWRETRY
788 */
789 static int
790 ar6000_ioctl_giwretry(struct net_device *dev,
791 struct iw_request_info *info,
792 struct iw_param *rrq, char *extra)
793 {
794 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
795
796 if (ar->arWlanState == WLAN_DISABLED) {
797 return -EIO;
798 }
799
800 rrq->disabled = 0;
801 switch (rrq->flags & IW_RETRY_TYPE) {
802 case IW_RETRY_LIFETIME:
803 return -EOPNOTSUPP;
804 break;
805 case IW_RETRY_LIMIT:
806 rrq->flags = IW_RETRY_LIMIT;
807 switch (rrq->flags & IW_RETRY_MODIFIER) {
808 case IW_RETRY_MIN:
809 rrq->flags |= IW_RETRY_MIN;
810 rrq->value = WMI_MIN_RETRIES;
811 break;
812 case IW_RETRY_MAX:
813 rrq->flags |= IW_RETRY_MAX;
814 rrq->value = ar->arMaxRetries;
815 break;
816 }
817 break;
818 }
819 return 0;
820 }
821
822 /*
823 * SIOCSIWENCODE
824 */
825 static int
826 ar6000_ioctl_siwencode(struct net_device *dev,
827 struct iw_request_info *info,
828 struct iw_point *erq, char *keybuf)
829 {
830 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
831 int index;
832 A_INT32 auth = ar->arDot11AuthMode;
833
834 if (ar->arWlanState == WLAN_DISABLED) {
835 return -EIO;
836 }
837
838 index = erq->flags & IW_ENCODE_INDEX;
839
840 if (index && (((index - 1) < WMI_MIN_KEY_INDEX) ||
841 ((index - 1) > WMI_MAX_KEY_INDEX)))
842 {
843 return -EIO;
844 }
845
846 if (erq->flags & IW_ENCODE_DISABLED) {
847 /*
848 * Encryption disabled
849 */
850 if (index) {
851 /*
852 * If key index was specified then clear the specified key
853 */
854 index--;
855 A_MEMZERO(ar->arWepKeyList[index].arKey,
856 sizeof(ar->arWepKeyList[index].arKey));
857 ar->arWepKeyList[index].arKeyLen = 0;
858 }
859 ar->arDot11AuthMode = OPEN_AUTH;
860 ar->arPairwiseCrypto = NONE_CRYPT;
861 ar->arGroupCrypto = NONE_CRYPT;
862 ar->arAuthMode = NONE_AUTH;
863 } else {
864 /*
865 * Enabling WEP encryption
866 */
867 if (index) {
868 index--; /* keyindex is off base 1 in iwconfig */
869 }
870
871 if (erq->flags & IW_ENCODE_OPEN) {
872 auth = OPEN_AUTH;
873 } else if (erq->flags & IW_ENCODE_RESTRICTED) {
874 auth = SHARED_AUTH;
875 }
876
877 if (erq->length) {
878 if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(erq->length)) {
879 return -EIO;
880 }
881
882 A_MEMZERO(ar->arWepKeyList[index].arKey,
883 sizeof(ar->arWepKeyList[index].arKey));
884 A_MEMCPY(ar->arWepKeyList[index].arKey, keybuf, erq->length);
885 ar->arWepKeyList[index].arKeyLen = erq->length;
886 } else {
887 if (ar->arWepKeyList[index].arKeyLen == 0) {
888 return -EIO;
889 }
890 ar->arDefTxKeyIndex = index;
891 }
892
893 ar->arPairwiseCrypto = WEP_CRYPT;
894 ar->arGroupCrypto = WEP_CRYPT;
895 ar->arDot11AuthMode = auth;
896 ar->arAuthMode = NONE_AUTH;
897 }
898
899 /*
900 * profile has changed. Erase ssid to signal change
901 */
902 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
903 ar->arSsidLen = 0;
904
905 return 0;
906 }
907
908 static int
909 ar6000_ioctl_giwencode(struct net_device *dev,
910 struct iw_request_info *info,
911 struct iw_point *erq, char *key)
912 {
913 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
914 A_UINT8 keyIndex;
915 struct ar_wep_key *wk;
916
917 if (ar->arWlanState == WLAN_DISABLED) {
918 return -EIO;
919 }
920
921 if (ar->arPairwiseCrypto == NONE_CRYPT) {
922 erq->length = 0;
923 erq->flags = IW_ENCODE_DISABLED;
924 } else {
925 /* get the keyIndex */
926 keyIndex = erq->flags & IW_ENCODE_INDEX;
927 if (0 == keyIndex) {
928 keyIndex = ar->arDefTxKeyIndex;
929 } else if ((keyIndex - 1 < WMI_MIN_KEY_INDEX) ||
930 (keyIndex - 1 > WMI_MAX_KEY_INDEX))
931 {
932 keyIndex = WMI_MIN_KEY_INDEX;
933 } else {
934 keyIndex--;
935 }
936 erq->flags = keyIndex + 1;
937 erq->flags |= IW_ENCODE_ENABLED;
938 wk = &ar->arWepKeyList[keyIndex];
939 if (erq->length > wk->arKeyLen) {
940 erq->length = wk->arKeyLen;
941 }
942 if (wk->arKeyLen) {
943 A_MEMCPY(key, wk->arKey, erq->length);
944 }
945 if (ar->arDot11AuthMode == OPEN_AUTH) {
946 erq->flags |= IW_ENCODE_OPEN;
947 } else if (ar->arDot11AuthMode == SHARED_AUTH) {
948 erq->flags |= IW_ENCODE_RESTRICTED;
949 }
950 }
951
952 return 0;
953 }
954
955 static int ar6000_ioctl_siwpower(struct net_device *dev,
956 struct iw_request_info *info,
957 union iwreq_data *wrqu, char *extra)
958 {
959 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
960 WMI_POWER_MODE power_mode;
961
962 if (wrqu->power.disabled)
963 power_mode = MAX_PERF_POWER;
964 else
965 power_mode = REC_POWER;
966
967 if (wmi_powermode_cmd(ar->arWmi, power_mode) < 0)
968 return -EIO;
969
970 return 0;
971 }
972
973 static int ar6000_ioctl_giwpower(struct net_device *dev,
974 struct iw_request_info *info,
975 union iwreq_data *wrqu, char *extra)
976 {
977 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
978
979 /*
980 * FIXME:
981 * https://docs.openmoko.org/trac/ticket/2267
982 * When starting wpa_supplicant the kernel oopses.
983 * The following condition avoids the oops.
984 * Remove this comment to bless this solution.
985 */
986 if (ar->arWlanState == WLAN_DISABLED || ar->arWmiReady == FALSE)
987 return -EIO;
988
989 return wmi_get_power_mode_cmd(ar->arWmi);
990 }
991
992 static int ar6000_ioctl_siwgenie(struct net_device *dev,
993 struct iw_request_info *info,
994 struct iw_point *dwrq,
995 char *extra)
996 {
997 /* The target does that for us */
998 return 0;
999 }
1000
1001 static int ar6000_ioctl_giwgenie(struct net_device *dev,
1002 struct iw_request_info *info,
1003 struct iw_point *dwrq,
1004 char *extra)
1005 {
1006 return 0;
1007 }
1008
1009 static int ar6000_ioctl_siwauth(struct net_device *dev,
1010 struct iw_request_info *info,
1011 struct iw_param *param,
1012 char *extra)
1013 {
1014 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1015 int reset = 0;
1016
1017 switch (param->flags & IW_AUTH_INDEX) {
1018 case IW_AUTH_WPA_VERSION:
1019 if (param->value & IW_AUTH_WPA_VERSION_DISABLED) {
1020 ar->arAuthMode = NONE_AUTH;
1021 }
1022 if (param->value & IW_AUTH_WPA_VERSION_WPA) {
1023 ar->arAuthMode = WPA_AUTH;
1024 }
1025 if (param->value & IW_AUTH_WPA_VERSION_WPA2) {
1026 ar->arAuthMode = WPA2_AUTH;
1027 }
1028
1029 reset = 1;
1030 break;
1031 case IW_AUTH_CIPHER_PAIRWISE:
1032 if (param->value & IW_AUTH_CIPHER_NONE) {
1033 ar->arPairwiseCrypto = NONE_CRYPT;
1034 }
1035 if (param->value & IW_AUTH_CIPHER_WEP40) {
1036 ar->arPairwiseCrypto = WEP_CRYPT;
1037 }
1038 if (param->value & IW_AUTH_CIPHER_TKIP) {
1039 ar->arPairwiseCrypto = TKIP_CRYPT;
1040 }
1041 if (param->value & IW_AUTH_CIPHER_CCMP) {
1042 ar->arPairwiseCrypto = AES_CRYPT;
1043 }
1044
1045 reset = 1;
1046 break;
1047 case IW_AUTH_CIPHER_GROUP:
1048 if (param->value & IW_AUTH_CIPHER_NONE) {
1049 ar->arGroupCrypto = NONE_CRYPT;
1050 }
1051 if (param->value & IW_AUTH_CIPHER_WEP40) {
1052 ar->arGroupCrypto = WEP_CRYPT;
1053 }
1054 if (param->value & IW_AUTH_CIPHER_TKIP) {
1055 ar->arGroupCrypto = TKIP_CRYPT;
1056 }
1057 if (param->value & IW_AUTH_CIPHER_CCMP) {
1058 ar->arGroupCrypto = AES_CRYPT;
1059 }
1060
1061 reset = 1;
1062 break;
1063 case IW_AUTH_KEY_MGMT:
1064 if (param->value & IW_AUTH_KEY_MGMT_PSK) {
1065 if (ar->arAuthMode == WPA_AUTH) {
1066 ar->arAuthMode = WPA_PSK_AUTH;
1067 } else if (ar->arAuthMode == WPA2_AUTH) {
1068 ar->arAuthMode = WPA2_PSK_AUTH;
1069 }
1070
1071 reset = 1;
1072 }
1073 break;
1074
1075 case IW_AUTH_TKIP_COUNTERMEASURES:
1076 if (ar->arWmiReady == FALSE) {
1077 return -EIO;
1078 }
1079 wmi_set_tkip_countermeasures_cmd(ar->arWmi, param->value);
1080 break;
1081
1082 case IW_AUTH_DROP_UNENCRYPTED:
1083 break;
1084
1085 case IW_AUTH_80211_AUTH_ALG:
1086 if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
1087 ar->arDot11AuthMode = OPEN_AUTH;
1088 }
1089 if (param->value & IW_AUTH_ALG_SHARED_KEY) {
1090 ar->arDot11AuthMode = SHARED_AUTH;
1091 }
1092 if (param->value & IW_AUTH_ALG_LEAP) {
1093 ar->arDot11AuthMode = LEAP_AUTH;
1094 ar->arPairwiseCrypto = WEP_CRYPT;
1095 ar->arGroupCrypto = WEP_CRYPT;
1096 }
1097
1098 reset = 1;
1099 break;
1100
1101 case IW_AUTH_WPA_ENABLED:
1102 reset = 1;
1103 break;
1104
1105 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1106 break;
1107
1108 case IW_AUTH_PRIVACY_INVOKED:
1109 break;
1110
1111 default:
1112 printk("%s(): Unknown flag 0x%x\n", __FUNCTION__, param->flags);
1113 return -EOPNOTSUPP;
1114 }
1115
1116 if (reset) {
1117 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
1118 ar->arSsidLen = 0;
1119 }
1120
1121 return 0;
1122 }
1123
1124 static int ar6000_ioctl_giwauth(struct net_device *dev,
1125 struct iw_request_info *info,
1126 struct iw_param *dwrq,
1127 char *extra)
1128 {
1129 return 0;
1130 }
1131
1132 static int ar6000_ioctl_siwencodeext(struct net_device *dev,
1133 struct iw_request_info *info,
1134 union iwreq_data *wrqu,
1135 char *extra)
1136 {
1137 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1138 struct iw_point *encoding = &wrqu->encoding;
1139 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1140 int alg = ext->alg, idx;
1141
1142 if (ar->arWlanState == WLAN_DISABLED) {
1143 return -EIO;
1144 }
1145
1146 /* Determine and validate the key index */
1147 idx = (encoding->flags & IW_ENCODE_INDEX) - 1;
1148 if (idx) {
1149 if (idx < 0 || idx > 3)
1150 return -EINVAL;
1151 }
1152
1153 if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) {
1154 struct ieee80211req_key ik;
1155 KEY_USAGE key_usage;
1156 CRYPTO_TYPE key_type = NONE_CRYPT;
1157 int status;
1158
1159 ar->user_saved_keys.keyOk = FALSE;
1160
1161 if (alg == IW_ENCODE_ALG_TKIP) {
1162 key_type = TKIP_CRYPT;
1163 ik.ik_type = IEEE80211_CIPHER_TKIP;
1164 } else {
1165 key_type = AES_CRYPT;
1166 ik.ik_type = IEEE80211_CIPHER_AES_CCM;
1167 }
1168
1169 ik.ik_keyix = idx;
1170 ik.ik_keylen = ext->key_len;
1171 ik.ik_flags = IEEE80211_KEY_RECV;
1172 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
1173 ik.ik_flags |= IEEE80211_KEY_XMIT
1174 | IEEE80211_KEY_DEFAULT;
1175 }
1176
1177 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
1178 memcpy(&ik.ik_keyrsc, ext->rx_seq, 8);
1179 }
1180
1181 memcpy(ik.ik_keydata, ext->key, ext->key_len);
1182
1183 ar->user_saved_keys.keyType = key_type;
1184 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1185 key_usage = GROUP_USAGE;
1186 memset(ik.ik_macaddr, 0, ETH_ALEN);
1187 memcpy(&ar->user_saved_keys.bcast_ik, &ik,
1188 sizeof(struct ieee80211req_key));
1189 } else {
1190 key_usage = PAIRWISE_USAGE;
1191 memcpy(ik.ik_macaddr, ext->addr.sa_data, ETH_ALEN);
1192 memcpy(&ar->user_saved_keys.ucast_ik, &ik,
1193 sizeof(struct ieee80211req_key));
1194 }
1195
1196 status = wmi_addKey_cmd(ar->arWmi, ik.ik_keyix, key_type,
1197 key_usage, ik.ik_keylen,
1198 (A_UINT8 *)&ik.ik_keyrsc,
1199 ik.ik_keydata,
1200 KEY_OP_INIT_VAL, SYNC_BEFORE_WMIFLAG);
1201
1202 if (status < 0)
1203 return -EIO;
1204
1205 ar->user_saved_keys.keyOk = TRUE;
1206
1207 return 0;
1208
1209 } else {
1210 /* WEP falls back to SIWENCODE */
1211 return -EOPNOTSUPP;
1212 }
1213
1214 return 0;
1215 }
1216
1217
1218 static int ar6000_ioctl_giwencodeext(struct net_device *dev,
1219 struct iw_request_info *info,
1220 struct iw_point *dwrq,
1221 char *extra)
1222 {
1223 return 0;
1224 }
1225
1226
1227 static int
1228 ar6000_ioctl_setparam(struct net_device *dev,
1229 struct iw_request_info *info,
1230 void *erq, char *extra)
1231 {
1232 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1233 int *i = (int *)extra;
1234 int param = i[0];
1235 int value = i[1];
1236 int ret = 0;
1237 A_BOOL profChanged = FALSE;
1238
1239 if (ar->arWlanState == WLAN_DISABLED) {
1240 return -EIO;
1241 }
1242
1243 switch (param) {
1244 case IEEE80211_PARAM_WPA:
1245 switch (value) {
1246 case WPA_MODE_WPA1:
1247 ar->arAuthMode = WPA_AUTH;
1248 profChanged = TRUE;
1249 break;
1250 case WPA_MODE_WPA2:
1251 ar->arAuthMode = WPA2_AUTH;
1252 profChanged = TRUE;
1253 break;
1254 case WPA_MODE_NONE:
1255 ar->arAuthMode = NONE_AUTH;
1256 profChanged = TRUE;
1257 break;
1258 default:
1259 printk("IEEE80211_PARAM_WPA: Unknown value %d\n", value);
1260 }
1261 break;
1262 case IEEE80211_PARAM_AUTHMODE:
1263 switch(value) {
1264 case IEEE80211_AUTH_WPA_PSK:
1265 if (WPA_AUTH == ar->arAuthMode) {
1266 ar->arAuthMode = WPA_PSK_AUTH;
1267 profChanged = TRUE;
1268 } else if (WPA2_AUTH == ar->arAuthMode) {
1269 ar->arAuthMode = WPA2_PSK_AUTH;
1270 profChanged = TRUE;
1271 } else {
1272 AR_DEBUG_PRINTF("Error - Setting PSK mode when WPA "\
1273 "param was set to %d\n",
1274 ar->arAuthMode);
1275 ret = -1;
1276 }
1277 break;
1278 case IEEE80211_AUTH_WPA_CCKM:
1279 if (WPA2_AUTH == ar->arAuthMode) {
1280 ar->arAuthMode = WPA2_AUTH_CCKM;
1281 } else {
1282 ar->arAuthMode = WPA_AUTH_CCKM;
1283 }
1284 break;
1285 default:
1286 break;
1287 }
1288 break;
1289 case IEEE80211_PARAM_UCASTCIPHER:
1290 switch (value) {
1291 case IEEE80211_CIPHER_AES_CCM:
1292 ar->arPairwiseCrypto = AES_CRYPT;
1293 profChanged = TRUE;
1294 break;
1295 case IEEE80211_CIPHER_TKIP:
1296 ar->arPairwiseCrypto = TKIP_CRYPT;
1297 profChanged = TRUE;
1298 break;
1299 case IEEE80211_CIPHER_WEP:
1300 ar->arPairwiseCrypto = WEP_CRYPT;
1301 profChanged = TRUE;
1302 break;
1303 case IEEE80211_CIPHER_NONE:
1304 ar->arPairwiseCrypto = NONE_CRYPT;
1305 profChanged = TRUE;
1306 break;
1307 }
1308 break;
1309 case IEEE80211_PARAM_UCASTKEYLEN:
1310 if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(value)) {
1311 ret = -EIO;
1312 } else {
1313 ar->arPairwiseCryptoLen = value;
1314 }
1315 break;
1316 case IEEE80211_PARAM_MCASTCIPHER:
1317 switch (value) {
1318 case IEEE80211_CIPHER_AES_CCM:
1319 ar->arGroupCrypto = AES_CRYPT;
1320 profChanged = TRUE;
1321 break;
1322 case IEEE80211_CIPHER_TKIP:
1323 ar->arGroupCrypto = TKIP_CRYPT;
1324 profChanged = TRUE;
1325 break;
1326 case IEEE80211_CIPHER_WEP:
1327 ar->arGroupCrypto = WEP_CRYPT;
1328 profChanged = TRUE;
1329 break;
1330 case IEEE80211_CIPHER_NONE:
1331 ar->arGroupCrypto = NONE_CRYPT;
1332 profChanged = TRUE;
1333 break;
1334 }
1335 break;
1336 case IEEE80211_PARAM_MCASTKEYLEN:
1337 if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(value)) {
1338 ret = -EIO;
1339 } else {
1340 ar->arGroupCryptoLen = value;
1341 }
1342 break;
1343 case IEEE80211_PARAM_COUNTERMEASURES:
1344 if (ar->arWmiReady == FALSE) {
1345 return -EIO;
1346 }
1347 wmi_set_tkip_countermeasures_cmd(ar->arWmi, value);
1348 break;
1349 default:
1350 break;
1351 }
1352
1353 if (profChanged == TRUE) {
1354 /*
1355 * profile has changed. Erase ssid to signal change
1356 */
1357 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
1358 ar->arSsidLen = 0;
1359 }
1360
1361 return ret;
1362 }
1363
1364 int
1365 ar6000_ioctl_getparam(struct net_device *dev, struct iw_request_info *info,
1366 void *w, char *extra)
1367 {
1368 return -EIO; /* for now */
1369 }
1370
1371 int
1372 ar6000_ioctl_setkey(struct net_device *dev, struct iw_request_info *info,
1373 void *w, char *extra)
1374 {
1375 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1376 struct ieee80211req_key *ik = (struct ieee80211req_key *)extra;
1377 KEY_USAGE keyUsage;
1378 A_STATUS status;
1379 CRYPTO_TYPE keyType = NONE_CRYPT;
1380
1381 if (ar->arWlanState == WLAN_DISABLED) {
1382 return -EIO;
1383 }
1384
1385 ar->user_saved_keys.keyOk = FALSE;
1386
1387 if ( 0 == memcmp(ik->ik_macaddr, "\x00\x00\x00\x00\x00\x00",
1388 IEEE80211_ADDR_LEN)) {
1389 keyUsage = GROUP_USAGE;
1390 A_MEMCPY(&ar->user_saved_keys.bcast_ik, ik,
1391 sizeof(struct ieee80211req_key));
1392 } else {
1393 keyUsage = PAIRWISE_USAGE;
1394 A_MEMCPY(&ar->user_saved_keys.ucast_ik, ik,
1395 sizeof(struct ieee80211req_key));
1396 }
1397
1398 switch (ik->ik_type) {
1399 case IEEE80211_CIPHER_WEP:
1400 keyType = WEP_CRYPT;
1401 break;
1402 case IEEE80211_CIPHER_TKIP:
1403 keyType = TKIP_CRYPT;
1404 break;
1405 case IEEE80211_CIPHER_AES_CCM:
1406 keyType = AES_CRYPT;
1407 break;
1408 default:
1409 break;
1410 }
1411 ar->user_saved_keys.keyType = keyType;
1412
1413 if (IEEE80211_CIPHER_CCKM_KRK != ik->ik_type) {
1414 if (NONE_CRYPT == keyType) {
1415 return -EIO;
1416 }
1417
1418 status = wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, keyType, keyUsage,
1419 ik->ik_keylen, (A_UINT8 *)&ik->ik_keyrsc,
1420 ik->ik_keydata, KEY_OP_INIT_VAL,
1421 SYNC_BEFORE_WMIFLAG);
1422
1423 if (status != A_OK) {
1424 return -EIO;
1425 }
1426 } else {
1427 status = wmi_add_krk_cmd(ar->arWmi, ik->ik_keydata);
1428 }
1429
1430 ar->user_saved_keys.keyOk = TRUE;
1431
1432 return 0;
1433 }
1434
1435
1436 /*
1437 * SIOCGIWNAME
1438 */
1439 int
1440 ar6000_ioctl_giwname(struct net_device *dev,
1441 struct iw_request_info *info,
1442 char *name, char *extra)
1443 {
1444 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1445
1446 if (ar->arWlanState == WLAN_DISABLED) {
1447 return -EIO;
1448 }
1449
1450 switch (ar->arPhyCapability) {
1451 case (WMI_11A_CAPABILITY):
1452 strncpy(name, "AR6000 802.11a", IFNAMSIZ);
1453 break;
1454 case (WMI_11G_CAPABILITY):
1455 strncpy(name, "AR6000 802.11g", IFNAMSIZ);
1456 break;
1457 case (WMI_11AG_CAPABILITY):
1458 strncpy(name, "AR6000 802.11ag", IFNAMSIZ);
1459 break;
1460 default:
1461 strncpy(name, "AR6000 802.11", IFNAMSIZ);
1462 break;
1463 }
1464
1465 return 0;
1466 }
1467
1468 /*
1469 * SIOCSIWFREQ
1470 */
1471 int
1472 ar6000_ioctl_siwfreq(struct net_device *dev,
1473 struct iw_request_info *info,
1474 struct iw_freq *freq, char *extra)
1475 {
1476 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1477
1478 if (ar->arWlanState == WLAN_DISABLED) {
1479 return -EIO;
1480 }
1481
1482 /*
1483 * We support limiting the channels via wmiconfig.
1484 *
1485 * We use this command to configure the channel hint for the connect cmd
1486 * so it is possible the target will end up connecting to a different
1487 * channel.
1488 */
1489 if (freq->e > 1) {
1490 return -EINVAL;
1491 } else if (freq->e == 1) {
1492 ar->arChannelHint = freq->m / 100000;
1493 } else {
1494 ar->arChannelHint = wlan_ieee2freq(freq->m);
1495 }
1496
1497 A_PRINTF("channel hint set to %d\n", ar->arChannelHint);
1498 return 0;
1499 }
1500
1501 /*
1502 * SIOCGIWFREQ
1503 */
1504 int
1505 ar6000_ioctl_giwfreq(struct net_device *dev,
1506 struct iw_request_info *info,
1507 struct iw_freq *freq, char *extra)
1508 {
1509 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1510
1511 if (ar->arWlanState == WLAN_DISABLED) {
1512 return -EIO;
1513 }
1514
1515 if (ar->arConnected != TRUE) {
1516 return -EINVAL;
1517 }
1518
1519 freq->m = ar->arBssChannel * 100000;
1520 freq->e = 1;
1521
1522 return 0;
1523 }
1524
1525 /*
1526 * SIOCSIWMODE
1527 */
1528 int
1529 ar6000_ioctl_siwmode(struct net_device *dev,
1530 struct iw_request_info *info,
1531 __u32 *mode, char *extra)
1532 {
1533 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1534
1535 if (ar->arWlanState == WLAN_DISABLED) {
1536 return -EIO;
1537 }
1538
1539 switch (*mode) {
1540 case IW_MODE_INFRA:
1541 ar->arNetworkType = INFRA_NETWORK;
1542 break;
1543 case IW_MODE_ADHOC:
1544 ar->arNetworkType = ADHOC_NETWORK;
1545 break;
1546 default:
1547 return -EINVAL;
1548 }
1549
1550 return 0;
1551 }
1552
1553 /*
1554 * SIOCGIWMODE
1555 */
1556 int
1557 ar6000_ioctl_giwmode(struct net_device *dev,
1558 struct iw_request_info *info,
1559 __u32 *mode, char *extra)
1560 {
1561 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1562
1563 if (ar->arWlanState == WLAN_DISABLED) {
1564 return -EIO;
1565 }
1566
1567 switch (ar->arNetworkType) {
1568 case INFRA_NETWORK:
1569 *mode = IW_MODE_INFRA;
1570 break;
1571 case ADHOC_NETWORK:
1572 *mode = IW_MODE_ADHOC;
1573 break;
1574 default:
1575 return -EIO;
1576 }
1577 return 0;
1578 }
1579
1580 /*
1581 * SIOCSIWSENS
1582 */
1583 int
1584 ar6000_ioctl_siwsens(struct net_device *dev,
1585 struct iw_request_info *info,
1586 struct iw_param *sens, char *extra)
1587 {
1588 return 0;
1589 }
1590
1591 /*
1592 * SIOCGIWSENS
1593 */
1594 int
1595 ar6000_ioctl_giwsens(struct net_device *dev,
1596 struct iw_request_info *info,
1597 struct iw_param *sens, char *extra)
1598 {
1599 sens->value = 0;
1600 sens->fixed = 1;
1601
1602 return 0;
1603 }
1604
1605 /*
1606 * SIOCGIWRANGE
1607 */
1608 int
1609 ar6000_ioctl_giwrange(struct net_device *dev,
1610 struct iw_request_info *info,
1611 struct iw_point *data, char *extra)
1612 {
1613 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1614 struct iw_range *range = (struct iw_range *) extra;
1615 int i, ret = 0;
1616
1617 if (ar->arWmiReady == FALSE) {
1618 return -EIO;
1619 }
1620
1621 if (ar->arWlanState == WLAN_DISABLED) {
1622 return -EIO;
1623 }
1624
1625 if (down_interruptible(&ar->arSem)) {
1626 return -ERESTARTSYS;
1627 }
1628 ar->arNumChannels = -1;
1629 A_MEMZERO(ar->arChannelList, sizeof (ar->arChannelList));
1630
1631 if (wmi_get_channelList_cmd(ar->arWmi) != A_OK) {
1632 up(&ar->arSem);
1633 return -EIO;
1634 }
1635
1636 wait_event_interruptible_timeout(arEvent, ar->arNumChannels != -1, wmitimeout * HZ);
1637
1638 if (signal_pending(current)) {
1639 up(&ar->arSem);
1640 return -EINTR;
1641 }
1642
1643 data->length = sizeof(struct iw_range);
1644 A_MEMZERO(range, sizeof(struct iw_range));
1645
1646 range->txpower_capa = IW_TXPOW_DBM;
1647
1648 range->min_pmp = 1 * 1024;
1649 range->max_pmp = 65535 * 1024;
1650 range->min_pmt = 1 * 1024;
1651 range->max_pmt = 1000 * 1024;
1652 range->pmp_flags = IW_POWER_PERIOD;
1653 range->pmt_flags = IW_POWER_TIMEOUT;
1654 range->pm_capa = 0;
1655
1656 range->we_version_compiled = WIRELESS_EXT;
1657 range->we_version_source = 13;
1658
1659 range->retry_capa = IW_RETRY_LIMIT;
1660 range->retry_flags = IW_RETRY_LIMIT;
1661 range->min_retry = 0;
1662 range->max_retry = 255;
1663
1664 range->num_frequency = range->num_channels = ar->arNumChannels;
1665 for (i = 0; i < ar->arNumChannels; i++) {
1666 range->freq[i].i = wlan_freq2ieee(ar->arChannelList[i]);
1667 range->freq[i].m = ar->arChannelList[i] * 100000;
1668 range->freq[i].e = 1;
1669 /*
1670 * Linux supports max of 32 channels, bail out once you
1671 * reach the max.
1672 */
1673 if (i == IW_MAX_FREQUENCIES) {
1674 break;
1675 }
1676 }
1677
1678 /* Max quality is max field value minus noise floor */
1679 range->max_qual.qual = 0xff - 161;
1680
1681 /*
1682 * In order to use dBm measurements, 'level' must be lower
1683 * than any possible measurement (see iw_print_stats() in
1684 * wireless tools). It's unclear how this is meant to be
1685 * done, but setting zero in these values forces dBm and
1686 * the actual numbers are not used.
1687 */
1688 range->max_qual.level = 0;
1689 range->max_qual.noise = 0;
1690
1691 range->sensitivity = 3;
1692
1693 range->max_encoding_tokens = 4;
1694 /* XXX query driver to find out supported key sizes */
1695 range->num_encoding_sizes = 3;
1696 range->encoding_size[0] = 5; /* 40-bit */
1697 range->encoding_size[1] = 13; /* 104-bit */
1698 range->encoding_size[2] = 16; /* 128-bit */
1699
1700 range->num_bitrates = 0;
1701
1702 /* estimated maximum TCP throughput values (bps) */
1703 range->throughput = 22000000;
1704
1705 range->min_rts = 0;
1706 range->max_rts = 2347;
1707 range->min_frag = 256;
1708 range->max_frag = 2346;
1709
1710 up(&ar->arSem);
1711
1712 return ret;
1713 }
1714
1715
1716 /*
1717 * SIOCSIWAP
1718 * This ioctl is used to set the desired bssid for the connect command.
1719 */
1720 int
1721 ar6000_ioctl_siwap(struct net_device *dev,
1722 struct iw_request_info *info,
1723 struct sockaddr *ap_addr, char *extra)
1724 {
1725 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1726
1727 if (ar->arWlanState == WLAN_DISABLED) {
1728 return -EIO;
1729 }
1730
1731 if (ap_addr->sa_family != ARPHRD_ETHER) {
1732 return -EIO;
1733 }
1734
1735 if (A_MEMCMP(&ap_addr->sa_data, bcast_mac, AR6000_ETH_ADDR_LEN) == 0) {
1736 A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
1737 } else {
1738 A_MEMCPY(ar->arReqBssid, &ap_addr->sa_data, sizeof(ar->arReqBssid));
1739 }
1740
1741 return 0;
1742 }
1743
1744 /*
1745 * SIOCGIWAP
1746 */
1747 int
1748 ar6000_ioctl_giwap(struct net_device *dev,
1749 struct iw_request_info *info,
1750 struct sockaddr *ap_addr, char *extra)
1751 {
1752 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1753
1754 if (ar->arWlanState == WLAN_DISABLED) {
1755 return -EIO;
1756 }
1757
1758 if (ar->arConnected != TRUE) {
1759 return -EINVAL;
1760 }
1761
1762 A_MEMCPY(&ap_addr->sa_data, ar->arBssid, sizeof(ar->arBssid));
1763 ap_addr->sa_family = ARPHRD_ETHER;
1764
1765 return 0;
1766 }
1767
1768 /*
1769 * SIOCGIWAPLIST
1770 */
1771 int
1772 ar6000_ioctl_iwaplist(struct net_device *dev,
1773 struct iw_request_info *info,
1774 struct iw_point *data, char *extra)
1775 {
1776 return -EIO; /* for now */
1777 }
1778
1779 /*
1780 * SIOCSIWSCAN
1781 */
1782 int
1783 ar6000_ioctl_siwscan(struct net_device *dev,
1784 struct iw_request_info *info,
1785 struct iw_point *data, char *extra)
1786 {
1787 #define ACT_DWELLTIME_DEFAULT 105
1788 #define HOME_TXDRAIN_TIME 100
1789 #define SCAN_INT HOME_TXDRAIN_TIME + ACT_DWELLTIME_DEFAULT
1790 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1791 int ret = 0;
1792
1793 if (ar->arWmiReady == FALSE) {
1794 return -EIO;
1795 }
1796
1797 if (ar->arWlanState == WLAN_DISABLED) {
1798 return -EIO;
1799 }
1800
1801 /* We ask for everything from the target */
1802 if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != A_OK) {
1803 printk("Couldn't set filtering\n");
1804 ret = -EIO;
1805 }
1806
1807 if (wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, FALSE, FALSE, \
1808 HOME_TXDRAIN_TIME, SCAN_INT) != A_OK) {
1809 ret = -EIO;
1810 }
1811
1812 ar->scan_complete = 0;
1813 wait_event_interruptible_timeout(ar6000_scan_queue, ar->scan_complete,
1814 5 * HZ);
1815
1816 if (wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0) != A_OK) {
1817 printk("Couldn't set filtering\n");
1818 ret = -EIO;
1819 }
1820
1821 return ret;
1822 #undef ACT_DWELLTIME_DEFAULT
1823 #undef HOME_TXDRAIN_TIME
1824 #undef SCAN_INT
1825 }
1826
1827
1828 /*
1829 * Units are in db above the noise floor. That means the
1830 * rssi values reported in the tx/rx descriptors in the
1831 * driver are the SNR expressed in db.
1832 *
1833 * If you assume that the noise floor is -95, which is an
1834 * excellent assumption 99.5 % of the time, then you can
1835 * derive the absolute signal level (i.e. -95 + rssi).
1836 * There are some other slight factors to take into account
1837 * depending on whether the rssi measurement is from 11b,
1838 * 11g, or 11a. These differences are at most 2db and
1839 * can be documented.
1840 *
1841 * NB: various calculations are based on the orinoco/wavelan
1842 * drivers for compatibility
1843 */
1844 static void
1845 ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi)
1846 {
1847 if (rssi < 0) {
1848 iq->qual = 0;
1849 } else {
1850 iq->qual = rssi;
1851 }
1852
1853 /* NB: max is 94 because noise is hardcoded to 161 */
1854 if (iq->qual > 94)
1855 iq->qual = 94;
1856
1857 iq->noise = 161; /* -95dBm */
1858 iq->level = iq->noise + iq->qual;
1859 iq->updated = 7;
1860 }
1861
1862
1863 /* Structures to export the Wireless Handlers */
1864 static const iw_handler ath_handlers[] = {
1865 (iw_handler) NULL, /* SIOCSIWCOMMIT */
1866 (iw_handler) ar6000_ioctl_giwname, /* SIOCGIWNAME */
1867 (iw_handler) NULL, /* SIOCSIWNWID */
1868 (iw_handler) NULL, /* SIOCGIWNWID */
1869 (iw_handler) ar6000_ioctl_siwfreq, /* SIOCSIWFREQ */
1870 (iw_handler) ar6000_ioctl_giwfreq, /* SIOCGIWFREQ */
1871 (iw_handler) ar6000_ioctl_siwmode, /* SIOCSIWMODE */
1872 (iw_handler) ar6000_ioctl_giwmode, /* SIOCGIWMODE */
1873 (iw_handler) ar6000_ioctl_siwsens, /* SIOCSIWSENS */
1874 (iw_handler) ar6000_ioctl_giwsens, /* SIOCGIWSENS */
1875 (iw_handler) NULL /* not _used */, /* SIOCSIWRANGE */
1876 (iw_handler) ar6000_ioctl_giwrange, /* SIOCGIWRANGE */
1877 (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */
1878 (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
1879 (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */
1880 (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
1881 (iw_handler) NULL, /* SIOCSIWSPY */
1882 (iw_handler) NULL, /* SIOCGIWSPY */
1883 (iw_handler) NULL, /* SIOCSIWTHRSPY */
1884 (iw_handler) NULL, /* SIOCGIWTHRSPY */
1885 (iw_handler) ar6000_ioctl_siwap, /* SIOCSIWAP */
1886 (iw_handler) ar6000_ioctl_giwap, /* SIOCGIWAP */
1887 (iw_handler) NULL, /* -- hole -- */
1888 (iw_handler) ar6000_ioctl_iwaplist, /* SIOCGIWAPLIST */
1889 (iw_handler) ar6000_ioctl_siwscan, /* SIOCSIWSCAN */
1890 (iw_handler) ar6000_ioctl_giwscan, /* SIOCGIWSCAN */
1891 (iw_handler) ar6000_ioctl_siwessid, /* SIOCSIWESSID */
1892 (iw_handler) ar6000_ioctl_giwessid, /* SIOCGIWESSID */
1893 (iw_handler) NULL, /* SIOCSIWNICKN */
1894 (iw_handler) NULL, /* SIOCGIWNICKN */
1895 (iw_handler) NULL, /* -- hole -- */
1896 (iw_handler) NULL, /* -- hole -- */
1897 (iw_handler) ar6000_ioctl_siwrate, /* SIOCSIWRATE */
1898 (iw_handler) ar6000_ioctl_giwrate, /* SIOCGIWRATE */
1899 (iw_handler) NULL, /* SIOCSIWRTS */
1900 (iw_handler) NULL, /* SIOCGIWRTS */
1901 (iw_handler) NULL, /* SIOCSIWFRAG */
1902 (iw_handler) NULL, /* SIOCGIWFRAG */
1903 (iw_handler) ar6000_ioctl_siwtxpow, /* SIOCSIWTXPOW */
1904 (iw_handler) ar6000_ioctl_giwtxpow, /* SIOCGIWTXPOW */
1905 (iw_handler) ar6000_ioctl_siwretry, /* SIOCSIWRETRY */
1906 (iw_handler) ar6000_ioctl_giwretry, /* SIOCGIWRETRY */
1907 (iw_handler) ar6000_ioctl_siwencode, /* SIOCSIWENCODE */
1908 (iw_handler) ar6000_ioctl_giwencode, /* SIOCGIWENCODE */
1909 (iw_handler) ar6000_ioctl_siwpower, /* SIOCSIWPOWER */
1910 (iw_handler) ar6000_ioctl_giwpower, /* SIOCGIWPOWER */
1911 (iw_handler) NULL, /* -- hole -- */
1912 (iw_handler) NULL, /* -- hole -- */
1913 (iw_handler) ar6000_ioctl_siwgenie, /* SIOCSIWGENIE */
1914 (iw_handler) ar6000_ioctl_giwgenie, /* SIOCGIWGENIE */
1915 (iw_handler) ar6000_ioctl_siwauth, /* SIOCSIWAUTH */
1916 (iw_handler) ar6000_ioctl_giwauth, /* SIOCGIWAUTH */
1917 (iw_handler) ar6000_ioctl_siwencodeext,/* SIOCSIWENCODEEXT */
1918 (iw_handler) ar6000_ioctl_giwencodeext,/* SIOCGIWENCODEEXT */
1919 (iw_handler) NULL, /* SIOCSIWPMKSA */
1920 };
1921
1922 static const iw_handler ath_priv_handlers[] = {
1923 (iw_handler) ar6000_ioctl_setparam, /* SIOCWFIRSTPRIV+0 */
1924 (iw_handler) ar6000_ioctl_getparam, /* SIOCWFIRSTPRIV+1 */
1925 (iw_handler) ar6000_ioctl_setkey, /* SIOCWFIRSTPRIV+2 */
1926 (iw_handler) ar6000_ioctl_setwmmparams, /* SIOCWFIRSTPRIV+3 */
1927 (iw_handler) ar6000_ioctl_delkey, /* SIOCWFIRSTPRIV+4 */
1928 (iw_handler) ar6000_ioctl_getwmmparams, /* SIOCWFIRSTPRIV+5 */
1929 (iw_handler) ar6000_ioctl_setoptie, /* SIOCWFIRSTPRIV+6 */
1930 (iw_handler) ar6000_ioctl_setmlme, /* SIOCWFIRSTPRIV+7 */
1931 (iw_handler) ar6000_ioctl_addpmkid, /* SIOCWFIRSTPRIV+8 */
1932 };
1933
1934 #define IW_PRIV_TYPE_KEY \
1935 (IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_key))
1936 #define IW_PRIV_TYPE_DELKEY \
1937 (IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_del_key))
1938 #define IW_PRIV_TYPE_MLME \
1939 (IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_mlme))
1940 #define IW_PRIV_TYPE_ADDPMKID \
1941 (IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_addpmkid))
1942
1943 static const struct iw_priv_args ar6000_priv_args[] = {
1944 { IEEE80211_IOCTL_SETKEY,
1945 IW_PRIV_TYPE_KEY | IW_PRIV_SIZE_FIXED, 0, "setkey"},
1946 { IEEE80211_IOCTL_DELKEY,
1947 IW_PRIV_TYPE_DELKEY | IW_PRIV_SIZE_FIXED, 0, "delkey"},
1948 { IEEE80211_IOCTL_SETPARAM,
1949 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setparam"},
1950 { IEEE80211_IOCTL_GETPARAM,
1951 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1952 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getparam"},
1953 { IEEE80211_IOCTL_SETWMMPARAMS,
1954 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4, 0, "setwmmparams"},
1955 { IEEE80211_IOCTL_GETWMMPARAMS,
1956 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
1957 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getwmmparams"},
1958 { IEEE80211_IOCTL_SETOPTIE,
1959 IW_PRIV_TYPE_BYTE, 0, "setie"},
1960 { IEEE80211_IOCTL_SETMLME,
1961 IW_PRIV_TYPE_MLME, 0, "setmlme"},
1962 { IEEE80211_IOCTL_ADDPMKID,
1963 IW_PRIV_TYPE_ADDPMKID | IW_PRIV_SIZE_FIXED, 0, "addpmkid"},
1964 };
1965
1966 void ar6000_ioctl_iwsetup(struct iw_handler_def *def)
1967 {
1968 def->private_args = (struct iw_priv_args *)ar6000_priv_args;
1969 def->num_private_args = ARRAY_SIZE(ar6000_priv_args);
1970 }
1971
1972 struct iw_handler_def ath_iw_handler_def = {
1973 .standard = (iw_handler *)ath_handlers,
1974 .num_standard = ARRAY_SIZE(ath_handlers),
1975 .private = (iw_handler *)ath_priv_handlers,
1976 .num_private = ARRAY_SIZE(ath_priv_handlers),
1977 };
1978
1979