Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(332)

Side by Side Diff: chromeos/drivers/ath6kl/os/linux/wireless_ext.c

Issue 646055: Atheros AR600x driver + build glue (Closed)
Patch Set: Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 *
3 * Copyright (c) 2004-2010 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 void ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi);
23 extern unsigned int wmitimeout;
24 extern A_WAITQUEUE_HEAD arEvent;
25
26 #if WIRELESS_EXT > 14
27 /*
28 * Encode a WPA or RSN information element as a custom
29 * element using the hostap format.
30 */
31 static u_int
32 encode_ie(void *buf, size_t bufsize,
33 const u_int8_t *ie, size_t ielen,
34 const char *leader, size_t leader_len)
35 {
36 u_int8_t *p;
37 int i;
38
39 if (bufsize < leader_len)
40 return 0;
41 p = buf;
42 memcpy(p, leader, leader_len);
43 bufsize -= leader_len;
44 p += leader_len;
45 for (i = 0; i < ielen && bufsize > 2; i++)
46 {
47 p += sprintf(p, "%02x", ie[i]);
48 bufsize -= 2;
49 }
50 return (i == ielen ? p - (u_int8_t *)buf : 0);
51 }
52 #endif /* WIRELESS_EXT > 14 */
53
54 void
55 ar6000_scan_node(void *arg, bss_t *ni)
56 {
57 struct iw_event iwe;
58 #if WIRELESS_EXT > 14
59 char buf[256];
60 #endif
61 struct ar_giwscan_param *param;
62 A_CHAR *current_ev;
63 A_CHAR *end_buf;
64 struct ieee80211_common_ie *cie;
65 A_CHAR *current_val;
66 A_INT32 j;
67 A_UINT32 rate_len, data_len = 0;
68
69 param = (struct ar_giwscan_param *)arg;
70
71 current_ev = param->current_ev;
72 end_buf = param->end_buf;
73
74 cie = &ni->ni_cie;
75
76 if ((end_buf - current_ev) > IW_EV_ADDR_LEN)
77 {
78 A_MEMZERO(&iwe, sizeof(iwe));
79 iwe.cmd = SIOCGIWAP;
80 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
81 A_MEMCPY(iwe.u.ap_addr.sa_data, ni->ni_macaddr, 6);
82 current_ev = iwe_stream_add_event(
83 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
84 param->info,
85 #endif
86 current_ev, end_buf, &iwe,
87 IW_EV_ADDR_LEN);
88 }
89 param->bytes_needed += IW_EV_ADDR_LEN;
90
91 data_len = cie->ie_ssid[1] + IW_EV_POINT_LEN;
92 if ((end_buf - current_ev) > data_len)
93 {
94 A_MEMZERO(&iwe, sizeof(iwe));
95 iwe.cmd = SIOCGIWESSID;
96 iwe.u.data.flags = 1;
97 iwe.u.data.length = cie->ie_ssid[1];
98 current_ev = iwe_stream_add_point(
99 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
100 param->info,
101 #endif
102 current_ev, end_buf, &iwe,
103 &cie->ie_ssid[2]);
104 }
105 param->bytes_needed += data_len;
106
107 if (cie->ie_capInfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) {
108 if ((end_buf - current_ev) > IW_EV_UINT_LEN)
109 {
110 A_MEMZERO(&iwe, sizeof(iwe));
111 iwe.cmd = SIOCGIWMODE;
112 iwe.u.mode = cie->ie_capInfo & IEEE80211_CAPINFO_ESS ?
113 IW_MODE_MASTER : IW_MODE_ADHOC;
114 current_ev = iwe_stream_add_event(
115 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
116 param->info,
117 #endif
118 current_ev, end_buf, &iwe,
119 IW_EV_UINT_LEN);
120 }
121 param->bytes_needed += IW_EV_UINT_LEN;
122 }
123
124 if ((end_buf - current_ev) > IW_EV_FREQ_LEN)
125 {
126 A_MEMZERO(&iwe, sizeof(iwe));
127 iwe.cmd = SIOCGIWFREQ;
128 iwe.u.freq.m = cie->ie_chan * 100000;
129 iwe.u.freq.e = 1;
130 current_ev = iwe_stream_add_event(
131 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
132 param->info,
133 #endif
134 current_ev, end_buf, &iwe,
135 IW_EV_FREQ_LEN);
136 }
137 param->bytes_needed += IW_EV_FREQ_LEN;
138
139 if ((end_buf - current_ev) > IW_EV_QUAL_LEN)
140 {
141 A_MEMZERO(&iwe, sizeof(iwe));
142 iwe.cmd = IWEVQUAL;
143 ar6000_set_quality(&iwe.u.qual, ni->ni_snr);
144 current_ev = iwe_stream_add_event(
145 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
146 param->info,
147 #endif
148 current_ev, end_buf, &iwe,
149 IW_EV_QUAL_LEN);
150 }
151 param->bytes_needed += IW_EV_QUAL_LEN;
152
153 if ((end_buf - current_ev) > IW_EV_POINT_LEN)
154 {
155 A_MEMZERO(&iwe, sizeof(iwe));
156 iwe.cmd = SIOCGIWENCODE;
157 if (cie->ie_capInfo & IEEE80211_CAPINFO_PRIVACY) {
158 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
159 } else {
160 iwe.u.data.flags = IW_ENCODE_DISABLED;
161 }
162 iwe.u.data.length = 0;
163 current_ev = iwe_stream_add_point(
164 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
165 param->info,
166 #endif
167 current_ev, end_buf, &iwe, "");
168 }
169 param->bytes_needed += IW_EV_POINT_LEN;
170
171 /* supported bit rate */
172 A_MEMZERO(&iwe, sizeof(iwe));
173 iwe.cmd = SIOCGIWRATE;
174 iwe.u.bitrate.fixed = 0;
175 iwe.u.bitrate.disabled = 0;
176 iwe.u.bitrate.value = 0;
177 current_val = current_ev + IW_EV_LCP_LEN;
178 param->bytes_needed += IW_EV_LCP_LEN;
179
180 if (cie->ie_rates != NULL) {
181 rate_len = cie->ie_rates[1];
182 data_len = (rate_len * (IW_EV_PARAM_LEN - IW_EV_LCP_LEN));
183 if ((end_buf - current_ev) > data_len)
184 {
185 for (j = 0; j < rate_len; j++) {
186 unsigned char val;
187 val = cie->ie_rates[2 + j];
188 iwe.u.bitrate.value =
189 (val >= 0x80)? ((val - 0x80) * 500000): (val * 500000);
190 current_val = iwe_stream_add_value(
191 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
192 param->info,
193 #endif
194 current_ev,
195 current_val,
196 end_buf,
197 &iwe,
198 IW_EV_PARAM_LEN);
199 }
200 }
201 param->bytes_needed += data_len;
202 }
203
204 if (cie->ie_xrates != NULL) {
205 rate_len = cie->ie_xrates[1];
206 data_len = (rate_len * (IW_EV_PARAM_LEN - IW_EV_LCP_LEN));
207 if ((end_buf - current_ev) > data_len)
208 {
209 for (j = 0; j < rate_len; j++) {
210 unsigned char val;
211 val = cie->ie_xrates[2 + j];
212 iwe.u.bitrate.value =
213 (val >= 0x80)? ((val - 0x80) * 500000): (val * 500000);
214 current_val = iwe_stream_add_value(
215 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
216 param->info,
217 #endif
218 current_ev,
219 current_val,
220 end_buf,
221 &iwe,
222 IW_EV_PARAM_LEN);
223 }
224 }
225 param->bytes_needed += data_len;
226 }
227 /* remove fixed header if no rates were added */
228 if ((current_val - current_ev) > IW_EV_LCP_LEN)
229 current_ev = current_val;
230
231 #if WIRELESS_EXT >= 18
232 /* IE */
233 if (cie->ie_wpa != NULL) {
234 data_len = cie->ie_wpa[1] + 2 + IW_EV_POINT_LEN;
235 if ((end_buf - current_ev) > data_len)
236 {
237 A_MEMZERO(&iwe, sizeof(iwe));
238 iwe.cmd = IWEVGENIE;
239 iwe.u.data.length = cie->ie_wpa[1] + 2;
240 current_ev = iwe_stream_add_point(
241 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
242 param->info,
243 #endif
244 current_ev, end_buf, &iwe, cie->ie_wpa);
245 }
246 param->bytes_needed += data_len;
247 }
248
249 if (cie->ie_rsn != NULL && cie->ie_rsn[0] == IEEE80211_ELEMID_RSN) {
250 data_len = cie->ie_rsn[1] + 2 + IW_EV_POINT_LEN;
251 if ((end_buf - current_ev) > data_len)
252 {
253 A_MEMZERO(&iwe, sizeof(iwe));
254 iwe.cmd = IWEVGENIE;
255 iwe.u.data.length = cie->ie_rsn[1] + 2;
256 current_ev = iwe_stream_add_point(
257 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
258 param->info,
259 #endif
260 current_ev, end_buf, &iwe, cie->ie_rsn);
261 }
262 param->bytes_needed += data_len;
263 }
264
265 #endif /* WIRELESS_EXT >= 18 */
266
267 if ((end_buf - current_ev) > IW_EV_CHAR_LEN)
268 {
269 /* protocol */
270 A_MEMZERO(&iwe, sizeof(iwe));
271 iwe.cmd = SIOCGIWNAME;
272 #define CHAN_IS_11A(x) (!((x >= 2412) && (x <= 2484)))
273 if (CHAN_IS_11A(cie->ie_chan)) {
274 if (cie->ie_htcap) {
275 /* 11na */
276 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11na");
277 }
278 else {
279 /* 11a */
280 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a");
281 }
282 } else if ((cie->ie_erp) || (cie->ie_xrates)) {
283 if (cie->ie_htcap) {
284 /* 11ng */
285 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11ng");
286 }
287 else {
288 /* 11g */
289 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
290 }
291 } else {
292 /* 11b */
293 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
294 }
295 current_ev = iwe_stream_add_event(
296 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
297 param->info,
298 #endif
299 current_ev, end_buf, &iwe, IW_EV_CHAR_LEN);
300 }
301 param->bytes_needed += IW_EV_CHAR_LEN;
302
303 #if WIRELESS_EXT > 14
304 A_MEMZERO(&iwe, sizeof(iwe));
305 iwe.cmd = IWEVCUSTOM;
306 iwe.u.data.length = snprintf(buf, sizeof(buf), "bcn_int=%d", cie->ie_beaconI nt);
307 data_len = iwe.u.data.length + IW_EV_POINT_LEN;
308 if ((end_buf - current_ev) > data_len)
309 {
310 current_ev = iwe_stream_add_point(
311 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
312 param->info,
313 #endif
314 current_ev, end_buf, &iwe, buf);
315 }
316 param->bytes_needed += data_len;
317
318 #if WIRELESS_EXT < 18
319 if (cie->ie_wpa != NULL) {
320 static const char wpa_leader[] = "wpa_ie=";
321 data_len = (sizeof(wpa_leader) - 1) + ((cie->ie_wpa[1]+2) * 2) + IW_EV_P OINT_LEN;
322 if ((end_buf - current_ev) > data_len)
323 {
324 A_MEMZERO(&iwe, sizeof(iwe));
325 iwe.cmd = IWEVCUSTOM;
326 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wpa,
327 cie->ie_wpa[1]+2,
328 wpa_leader, sizeof(wpa_leader)-1);
329
330 if (iwe.u.data.length != 0) {
331 current_ev = iwe_stream_add_point(
332 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
333 param->info,
334 #endif
335 current_ev, end_buf, &iwe, buf);
336 }
337 }
338 param->bytes_needed += data_len;
339 }
340
341 if (cie->ie_rsn != NULL && cie->ie_rsn[0] == IEEE80211_ELEMID_RSN) {
342 static const char rsn_leader[] = "rsn_ie=";
343 data_len = (sizeof(rsn_leader) - 1) + ((cie->ie_rsn[1]+2) * 2) + IW_EV_P OINT_LEN;
344 if ((end_buf - current_ev) > data_len)
345 {
346 A_MEMZERO(&iwe, sizeof(iwe));
347 iwe.cmd = IWEVCUSTOM;
348 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_rsn,
349 cie->ie_rsn[1]+2,
350 rsn_leader, sizeof(rsn_leader)-1);
351
352 if (iwe.u.data.length != 0) {
353 current_ev = iwe_stream_add_point(
354 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
355 param->info,
356 #endif
357 current_ev, end_buf, &iwe, buf);
358 }
359 }
360 param->bytes_needed += data_len;
361 }
362 #endif /* WIRELESS_EXT < 18 */
363
364 if (cie->ie_wmm != NULL) {
365 static const char wmm_leader[] = "wmm_ie=";
366 data_len = (sizeof(wmm_leader) - 1) + ((cie->ie_wmm[1]+2) * 2) + IW_EV_P OINT_LEN;
367 if ((end_buf - current_ev) > data_len)
368 {
369 A_MEMZERO(&iwe, sizeof(iwe));
370 iwe.cmd = IWEVCUSTOM;
371 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wmm,
372 cie->ie_wmm[1]+2,
373 wmm_leader, sizeof(wmm_leader)-1);
374 if (iwe.u.data.length != 0) {
375 current_ev = iwe_stream_add_point(
376 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
377 param->info,
378 #endif
379 current_ev, end_buf, &iwe, buf);
380 }
381 }
382 param->bytes_needed += data_len;
383 }
384
385 if (cie->ie_ath != NULL) {
386 static const char ath_leader[] = "ath_ie=";
387 data_len = (sizeof(ath_leader) - 1) + ((cie->ie_ath[1]+2) * 2) + IW_EV_P OINT_LEN;
388 if ((end_buf - current_ev) > data_len)
389 {
390 A_MEMZERO(&iwe, sizeof(iwe));
391 iwe.cmd = IWEVCUSTOM;
392 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_ath,
393 cie->ie_ath[1]+2,
394 ath_leader, sizeof(ath_leader)-1);
395 if (iwe.u.data.length != 0) {
396 current_ev = iwe_stream_add_point(
397 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
398 param->info,
399 #endif
400 current_ev, end_buf, &iwe, buf);
401 }
402 }
403 param->bytes_needed += data_len;
404 }
405
406 #ifdef WAPI_ENABLE
407 if (cie->ie_wapi != NULL) {
408 static const char wapi_leader[] = "wapi_ie=";
409 data_len = (sizeof(wapi_leader) - 1) + ((cie->ie_wapi[1] + 2) * 2) + IW_ EV_POINT_LEN;
410 if ((end_buf - current_ev) > data_len) {
411 A_MEMZERO(&iwe, sizeof(iwe));
412 iwe.cmd = IWEVCUSTOM;
413 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wapi,
414 cie->ie_wapi[1] + 2,
415 wapi_leader, sizeof(wapi_leader) - 1);
416 if (iwe.u.data.length != 0) {
417 current_ev = iwe_stream_add_point(
418 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
419 param->info,
420 #endif
421 current_ev, end_buf, &iwe, buf);
422 }
423 }
424 param->bytes_needed += data_len;
425 }
426 #endif /* WAPI_ENABLE */
427
428 #endif /* WIRELESS_EXT > 14 */
429
430 #if WIRELESS_EXT >= 18
431 if (cie->ie_wsc != NULL) {
432 data_len = (cie->ie_wsc[1] + 2) + IW_EV_POINT_LEN;
433 if ((end_buf - current_ev) > data_len)
434 {
435 A_MEMZERO(&iwe, sizeof(iwe));
436 iwe.cmd = IWEVGENIE;
437 iwe.u.data.length = cie->ie_wsc[1] + 2;
438 current_ev = iwe_stream_add_point(
439 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
440 param->info,
441 #endif
442 current_ev, end_buf, &iwe, cie->ie_wsc);
443 }
444 param->bytes_needed += data_len;
445 }
446 #endif /* WIRELESS_EXT >= 18 */
447
448 param->current_ev = current_ev;
449 }
450
451 int
452 ar6000_ioctl_giwscan(struct net_device *dev,
453 struct iw_request_info *info,
454 struct iw_point *data, char *extra)
455 {
456 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
457 struct ar_giwscan_param param;
458
459 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
460 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
461 return -EOPNOTSUPP;
462 }
463
464 if (ar->arWlanState == WLAN_DISABLED) {
465 return -EIO;
466 }
467
468 if (ar->arWmiReady == FALSE) {
469 return -EIO;
470 }
471
472 param.current_ev = extra;
473 param.end_buf = extra + data->length;
474 param.bytes_needed = 0;
475 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
476 param.info = info;
477 #endif
478
479 /* Translate data to WE format */
480 wmi_iterate_nodes(ar->arWmi, ar6000_scan_node, &param);
481
482 /* check if bytes needed is greater than bytes consumed */
483 if (param.bytes_needed > (param.current_ev - extra))
484 {
485 /* Request one byte more than needed, because when "data->length" equals bytes_needed,
486 it is not possible to add the last event data as all iwe_stream_add_xxxx x() functions
487 checks whether (cur_ptr + ev_len) < end_ptr, due to this one more retry would happen*/
488 data->length = param.bytes_needed + 1;
489
490 return -E2BIG;
491 }
492
493 return 0;
494 }
495
496 extern int reconnect_flag;
497 /* SIOCSIWESSID */
498 static int
499 ar6000_ioctl_siwessid(struct net_device *dev,
500 struct iw_request_info *info,
501 struct iw_point *data, char *ssid)
502 {
503 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
504 A_STATUS status;
505 A_UINT8 arNetworkType;
506 A_UINT8 prevMode = ar->arNetworkType;
507
508 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
509 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
510 return -EOPNOTSUPP;
511 }
512
513 if (ar->bIsDestroyProgress) {
514 return -EBUSY;
515 }
516
517 if (ar->arWlanState == WLAN_DISABLED) {
518 return -EIO;
519 }
520
521 if (ar->arWmiReady == FALSE) {
522 return -EIO;
523 }
524
525 #if defined(WIRELESS_EXT)
526 if (WIRELESS_EXT >= 20) {
527 data->length += 1;
528 }
529 #endif
530
531 /*
532 * iwconfig passes a null terminated string with length including this
533 * so we need to account for this
534 */
535 if (data->flags && (!data->length || (data->length == 1) ||
536 ((data->length - 1) > sizeof(ar->arSsid))))
537 {
538 /*
539 * ssid is invalid
540 */
541 return -EINVAL;
542 }
543
544 if (ar->arNextMode == AP_NETWORK) {
545 /* SSID change for AP network - Will take effect on commit */
546 if(A_MEMCMP(ar->arSsid,ssid,32) != 0) {
547 ar->arSsidLen = data->length - 1;
548 A_MEMCPY(ar->arSsid, ssid, ar->arSsidLen);
549 ar->ap_profile_flag = 1; /* There is a change in profile */
550 }
551 return 0;
552 } else if(ar->arNetworkType == AP_NETWORK) {
553 A_UINT8 ctr;
554 struct sk_buff *skb;
555
556 /* We are switching from AP to STA | IBSS mode, cleanup the AP state */
557 for (ctr=0; ctr < AP_MAX_NUM_STA; ctr++) {
558 remove_sta(ar, ar->sta_list[ctr].mac, 0);
559 }
560 A_MUTEX_LOCK(&ar->mcastpsqLock);
561 while (!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) {
562 skb = A_NETBUF_DEQUEUE(&ar->mcastpsq);
563 A_NETBUF_FREE(skb);
564 }
565 A_MUTEX_UNLOCK(&ar->mcastpsqLock);
566 }
567
568 /* Added for bug 25178, return an IOCTL error instead of target returning
569 Illegal parameter error when either the BSSID or channel is missing
570 and we cannot scan during connect.
571 */
572 if (data->flags) {
573 if (ar->arSkipScan == TRUE &&
574 (ar->arChannelHint == 0 ||
575 (!ar->arReqBssid[0] && !ar->arReqBssid[1] && !ar->arReqBssid[2] &&
576 !ar->arReqBssid[3] && !ar->arReqBssid[4] && !ar->arReqBssid[5])))
577 {
578 return -EINVAL;
579 }
580 }
581
582 if (down_interruptible(&ar->arSem)) {
583 return -ERESTARTSYS;
584 }
585
586 if (ar->bIsDestroyProgress) {
587 up(&ar->arSem);
588 return -EBUSY;
589 }
590
591 if (ar->arTxPending[wmi_get_control_ep(ar->arWmi)]) {
592 /*
593 * sleep until the command queue drains
594 */
595 wait_event_interruptible_timeout(arEvent,
596 ar->arTxPending[wmi_get_control_ep(ar->arWmi)] == 0, wmitimeout * HZ );
597 if (signal_pending(current)) {
598 return -EINTR;
599 }
600 }
601
602 if (!data->flags) {
603 arNetworkType = ar->arNetworkType;
604 ar6000_init_profile_info(ar);
605 ar->arNetworkType = arNetworkType;
606 }
607
608 /* Update the arNetworkType */
609 ar->arNetworkType = ar->arNextMode;
610
611
612 if ((prevMode != AP_NETWORK) && ((ar->arSsidLen) || (!data->flags)))
613 {
614 if ((!data->flags) ||
615 (A_MEMCMP(ar->arSsid, ssid, ar->arSsidLen) != 0) ||
616 (ar->arSsidLen != (data->length - 1)))
617 {
618 /*
619 * SSID set previously or essid off has been issued.
620 *
621 * Disconnect Command is issued in two cases after wmi is ready
622 * (1) ssid is different from the previous setting
623 * (2) essid off has been issued
624 *
625 */
626 if (ar->arWmiReady == TRUE) {
627 reconnect_flag = 0;
628 status = wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, 0);
629 status = wmi_disconnect_cmd(ar->arWmi);
630 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
631 ar->arSsidLen = 0;
632 if (ar->arSkipScan == FALSE) {
633 A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
634 }
635 if (!data->flags) {
636 up(&ar->arSem);
637 return 0;
638 }
639 } else {
640 up(&ar->arSem);
641 }
642 }
643 else
644 {
645 /*
646 * SSID is same, so we assume profile hasn't changed.
647 * If the interface is up and wmi is ready, we issue
648 * a reconnect cmd. Issue a reconnect only we are already
649 * connected.
650 */
651 if((ar->arConnected == TRUE) && (ar->arWmiReady == TRUE))
652 {
653 reconnect_flag = TRUE;
654 status = wmi_reconnect_cmd(ar->arWmi,ar->arReqBssid,
655 ar->arChannelHint);
656 up(&ar->arSem);
657 if (status != A_OK) {
658 return -EIO;
659 }
660 return 0;
661 }
662 else{
663 /*
664 * Dont return if connect is pending.
665 */
666 if(!(ar->arConnectPending)) {
667 up(&ar->arSem);
668 return 0;
669 }
670 }
671 }
672 }
673
674 ar->arSsidLen = data->length - 1;
675 A_MEMCPY(ar->arSsid, ssid, ar->arSsidLen);
676
677 /* The ssid length check prevents second "essid off" from the user,
678 to be treated as a connect cmd. The second "essid off" is ignored.
679 */
680 if((ar->arWmiReady == TRUE) && (ar->arSsidLen > 0) )
681 {
682 if((ADHOC_NETWORK != ar->arNetworkType) &&
683 (NONE_AUTH==ar->arAuthMode) &&
684 (WEP_CRYPT==ar->arPairwiseCrypto)) {
685 ar6000_install_static_wep_keys(ar);
686 }
687
688 if (!ar->arUserBssFilter) {
689 if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != A_OK) {
690 up(&ar->arSem);
691 return -EIO;
692 }
693 }
694 #ifdef WAPI_ENABLE
695 if (ar->arWapiEnable) {
696 ar->arPairwiseCrypto = WAPI_CRYPT;
697 ar->arPairwiseCryptoLen = 0;
698 ar->arGroupCrypto = WAPI_CRYPT;
699 ar->arGroupCryptoLen = 0;
700 ar->arAuthMode = NONE_AUTH;
701 ar->arConnectCtrlFlags |= CONNECT_IGNORE_WPAx_GROUP_CIPHER;
702 }
703 #endif
704 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("Connect called with authmode %d dot11 auth %d"\
705 " PW crypto %d PW crypto Len %d GRP crypto %d"\
706 " GRP crypto Len %d\n",
707 ar->arAuthMode, ar->arDot11AuthMode,
708 ar->arPairwiseCrypto, ar->arPairwiseCryptoLen,
709 ar->arGroupCrypto, ar->arGroupCryptoLen));
710 reconnect_flag = 0;
711 status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType,
712 ar->arDot11AuthMode, ar->arAuthMode,
713 ar->arPairwiseCrypto, ar->arPairwiseCryptoLen,
714 ar->arGroupCrypto,ar->arGroupCryptoLen,
715 ar->arSsidLen, ar->arSsid,
716 ar->arReqBssid, ar->arChannelHint,
717 ar->arConnectCtrlFlags);
718
719 if ((!(ar->arConnectCtrlFlags & CONNECT_DO_WPA_OFFLOAD)) &&
720 ((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMod e)))
721 {
722 A_TIMEOUT_MS(&ar->disconnect_timer, A_DISCONNECT_TIMER_INTERVAL, 0);
723 }
724
725 ar->arConnectCtrlFlags &= ~CONNECT_DO_WPA_OFFLOAD;
726 up(&ar->arSem);
727
728 if (status != A_OK) {
729 return -EIO;
730 }
731 ar->arConnectPending = TRUE;
732 }else{
733 up(&ar->arSem);
734 }
735 return 0;
736 }
737
738 /* SIOCGIWESSID */
739 static int
740 ar6000_ioctl_giwessid(struct net_device *dev,
741 struct iw_request_info *info,
742 struct iw_point *data, char *essid)
743 {
744 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
745
746 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
747 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
748 return -EOPNOTSUPP;
749 }
750
751 if (ar->arWlanState == WLAN_DISABLED) {
752 return -EIO;
753 }
754
755 if (!ar->arSsidLen) {
756 return -EINVAL;
757 }
758
759 data->flags = 1;
760 data->length = ar->arSsidLen;
761 A_MEMCPY(essid, ar->arSsid, ar->arSsidLen);
762
763 return 0;
764 }
765
766
767 void ar6000_install_static_wep_keys(AR_SOFTC_T *ar)
768 {
769 A_UINT8 index;
770 A_UINT8 keyUsage;
771
772 for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) {
773 if (ar->arWepKeyList[index].arKeyLen) {
774 keyUsage = GROUP_USAGE;
775 if (index == ar->arDefTxKeyIndex) {
776 keyUsage |= TX_USAGE;
777 }
778 wmi_addKey_cmd(ar->arWmi,
779 index,
780 WEP_CRYPT,
781 keyUsage,
782 ar->arWepKeyList[index].arKeyLen,
783 NULL,
784 ar->arWepKeyList[index].arKey, KEY_OP_INIT_VAL, NULL,
785 NO_SYNC_WMIFLAG);
786 }
787 }
788 }
789
790 /*
791 * SIOCSIWRATE
792 */
793 int
794 ar6000_ioctl_siwrate(struct net_device *dev,
795 struct iw_request_info *info,
796 struct iw_param *rrq, char *extra)
797 {
798 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
799 A_UINT32 kbps;
800
801 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
802 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
803 return -EOPNOTSUPP;
804 }
805
806 if (rrq->fixed) {
807 kbps = rrq->value / 1000; /* rrq->value is in bps */
808 } else {
809 kbps = -1; /* -1 indicates auto rate */
810 }
811 if(kbps != -1 && wmi_validate_bitrate(ar->arWmi, kbps) == A_EINVAL)
812 {
813 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BitRate is not Valid %d\n", kbps));
814 return -EINVAL;
815 }
816 ar->arBitRate = kbps;
817 if(ar->arWmiReady == TRUE)
818 {
819 if (wmi_set_bitrate_cmd(ar->arWmi, kbps, -1, -1) != A_OK) {
820 return -EINVAL;
821 }
822 }
823 return 0;
824 }
825
826 /*
827 * SIOCGIWRATE
828 */
829 int
830 ar6000_ioctl_giwrate(struct net_device *dev,
831 struct iw_request_info *info,
832 struct iw_param *rrq, char *extra)
833 {
834 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
835 int ret = 0;
836
837 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
838 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
839 return -EOPNOTSUPP;
840 }
841
842 if (ar->bIsDestroyProgress) {
843 return -EBUSY;
844 }
845
846 if (down_interruptible(&ar->arSem)) {
847 return -ERESTARTSYS;
848 }
849
850 if (ar->bIsDestroyProgress) {
851 up(&ar->arSem);
852 return -EBUSY;
853 }
854
855 if(ar->arWmiReady == TRUE)
856 {
857 ar->arBitRate = 0xFFFF;
858 if (wmi_get_bitrate_cmd(ar->arWmi) != A_OK) {
859 up(&ar->arSem);
860 return -EIO;
861 }
862 wait_event_interruptible_timeout(arEvent, ar->arBitRate != 0xFFFF, wmiti meout * HZ);
863 if (signal_pending(current)) {
864 ret = -EINTR;
865 }
866 }
867 /* If the interface is down or wmi is not ready or the target is not
868 connected - return the value stored in the device structure */
869 if (!ret) {
870 if (ar->arBitRate == -1) {
871 rrq->fixed = TRUE;
872 rrq->value = 0;
873 } else {
874 rrq->value = ar->arBitRate * 1000;
875 }
876 }
877
878 up(&ar->arSem);
879
880 return ret;
881 }
882
883 /*
884 * SIOCSIWTXPOW
885 */
886 static int
887 ar6000_ioctl_siwtxpow(struct net_device *dev,
888 struct iw_request_info *info,
889 struct iw_param *rrq, char *extra)
890 {
891 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
892 A_UINT8 dbM;
893
894 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
895 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
896 return -EOPNOTSUPP;
897 }
898
899 if (ar->arWlanState == WLAN_DISABLED) {
900 return -EIO;
901 }
902
903 if (rrq->disabled) {
904 return -EOPNOTSUPP;
905 }
906
907 if (rrq->fixed) {
908 if (rrq->flags != IW_TXPOW_DBM) {
909 return -EOPNOTSUPP;
910 }
911 ar->arTxPwr= dbM = rrq->value;
912 ar->arTxPwrSet = TRUE;
913 } else {
914 ar->arTxPwr = dbM = 0;
915 ar->arTxPwrSet = FALSE;
916 }
917 if(ar->arWmiReady == TRUE)
918 {
919 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("Set tx pwr cmd %d dbM\n", dbM));
920 wmi_set_txPwr_cmd(ar->arWmi, dbM);
921 }
922 return 0;
923 }
924
925 /*
926 * SIOCGIWTXPOW
927 */
928 int
929 ar6000_ioctl_giwtxpow(struct net_device *dev,
930 struct iw_request_info *info,
931 struct iw_param *rrq, char *extra)
932 {
933 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
934 int ret = 0;
935
936 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
937 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
938 return -EOPNOTSUPP;
939 }
940
941 if (ar->bIsDestroyProgress) {
942 return -EBUSY;
943 }
944
945 if (ar->arWlanState == WLAN_DISABLED) {
946 return -EIO;
947 }
948
949 if (down_interruptible(&ar->arSem)) {
950 return -ERESTARTSYS;
951 }
952
953 if (ar->bIsDestroyProgress) {
954 up(&ar->arSem);
955 return -EBUSY;
956 }
957
958 if((ar->arWmiReady == TRUE) && (ar->arConnected == TRUE))
959 {
960 ar->arTxPwr = 0;
961
962 if (wmi_get_txPwr_cmd(ar->arWmi) != A_OK) {
963 up(&ar->arSem);
964 return -EIO;
965 }
966
967 wait_event_interruptible_timeout(arEvent, ar->arTxPwr != 0, wmitimeout * HZ);
968
969 if (signal_pending(current)) {
970 ret = -EINTR;
971 }
972 }
973 /* If the interace is down or wmi is not ready or target is not connected
974 then return value stored in the device structure */
975
976 if (!ret) {
977 if (ar->arTxPwrSet == TRUE) {
978 rrq->fixed = TRUE;
979 }
980 rrq->value = ar->arTxPwr;
981 rrq->flags = IW_TXPOW_DBM;
982 //
983 // IWLIST need this flag to get TxPower
984 //
985 rrq->disabled = 0;
986 }
987
988 up(&ar->arSem);
989
990 return ret;
991 }
992
993 /*
994 * SIOCSIWRETRY
995 * since iwconfig only provides us with one max retry value, we use it
996 * to apply to data frames of the BE traffic class.
997 */
998 static int
999 ar6000_ioctl_siwretry(struct net_device *dev,
1000 struct iw_request_info *info,
1001 struct iw_param *rrq, char *extra)
1002 {
1003 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1004
1005 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
1006 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
1007 return -EOPNOTSUPP;
1008 }
1009
1010 if (ar->arWlanState == WLAN_DISABLED) {
1011 return -EIO;
1012 }
1013
1014 if (rrq->disabled) {
1015 return -EOPNOTSUPP;
1016 }
1017
1018 if ((rrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) {
1019 return -EOPNOTSUPP;
1020 }
1021
1022 if ( !(rrq->value >= WMI_MIN_RETRIES) || !(rrq->value <= WMI_MAX_RETRIES)) {
1023 return - EINVAL;
1024 }
1025 if(ar->arWmiReady == TRUE)
1026 {
1027 if (wmi_set_retry_limits_cmd(ar->arWmi, DATA_FRAMETYPE, WMM_AC_BE,
1028 rrq->value, 0) != A_OK){
1029 return -EINVAL;
1030 }
1031 }
1032 ar->arMaxRetries = rrq->value;
1033 return 0;
1034 }
1035
1036 /*
1037 * SIOCGIWRETRY
1038 */
1039 static int
1040 ar6000_ioctl_giwretry(struct net_device *dev,
1041 struct iw_request_info *info,
1042 struct iw_param *rrq, char *extra)
1043 {
1044 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1045
1046 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
1047 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
1048 return -EOPNOTSUPP;
1049 }
1050
1051 if (ar->arWlanState == WLAN_DISABLED) {
1052 return -EIO;
1053 }
1054
1055 rrq->disabled = 0;
1056 switch (rrq->flags & IW_RETRY_TYPE) {
1057 case IW_RETRY_LIFETIME:
1058 return -EOPNOTSUPP;
1059 break;
1060 case IW_RETRY_LIMIT:
1061 rrq->flags = IW_RETRY_LIMIT;
1062 switch (rrq->flags & IW_RETRY_MODIFIER) {
1063 case IW_RETRY_MIN:
1064 rrq->flags |= IW_RETRY_MIN;
1065 rrq->value = WMI_MIN_RETRIES;
1066 break;
1067 case IW_RETRY_MAX:
1068 rrq->flags |= IW_RETRY_MAX;
1069 rrq->value = ar->arMaxRetries;
1070 break;
1071 }
1072 break;
1073 }
1074 return 0;
1075 }
1076
1077 /*
1078 * SIOCSIWENCODE
1079 */
1080 static int
1081 ar6000_ioctl_siwencode(struct net_device *dev,
1082 struct iw_request_info *info,
1083 struct iw_point *erq, char *keybuf)
1084 {
1085 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1086 int index;
1087 A_INT32 auth = 0;
1088
1089 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
1090 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
1091 return -EOPNOTSUPP;
1092 }
1093
1094 if(ar->arNextMode != AP_NETWORK) {
1095 /*
1096 * Static WEP Keys should be configured before setting the SSID
1097 */
1098 if (ar->arSsid[0] && erq->length) {
1099 return -EIO;
1100 }
1101 }
1102
1103 if (ar->arWlanState == WLAN_DISABLED) {
1104 return -EIO;
1105 }
1106
1107 index = erq->flags & IW_ENCODE_INDEX;
1108
1109 if (index && (((index - 1) < WMI_MIN_KEY_INDEX) ||
1110 ((index - 1) > WMI_MAX_KEY_INDEX)))
1111 {
1112 return -EIO;
1113 }
1114
1115 if (erq->flags & IW_ENCODE_DISABLED) {
1116 /*
1117 * Encryption disabled
1118 */
1119 if (index) {
1120 /*
1121 * If key index was specified then clear the specified key
1122 */
1123 index--;
1124 A_MEMZERO(ar->arWepKeyList[index].arKey,
1125 sizeof(ar->arWepKeyList[index].arKey));
1126 ar->arWepKeyList[index].arKeyLen = 0;
1127 }
1128 ar->arDot11AuthMode = OPEN_AUTH;
1129 ar->arPairwiseCrypto = NONE_CRYPT;
1130 ar->arGroupCrypto = NONE_CRYPT;
1131 ar->arAuthMode = NONE_AUTH;
1132 } else {
1133 /*
1134 * Enabling WEP encryption
1135 */
1136 if (index) {
1137 index--; /* keyindex is off base 1 in iwconfig */
1138 }
1139
1140 if (erq->flags & IW_ENCODE_OPEN) {
1141 auth |= OPEN_AUTH;
1142 ar->arDefTxKeyIndex = index;
1143 }
1144 if (erq->flags & IW_ENCODE_RESTRICTED) {
1145 auth |= SHARED_AUTH;
1146 }
1147
1148 if (!auth) {
1149 auth = OPEN_AUTH;
1150 }
1151
1152 if (erq->length) {
1153 if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(erq->length)) {
1154 return -EIO;
1155 }
1156
1157 A_MEMZERO(ar->arWepKeyList[index].arKey,
1158 sizeof(ar->arWepKeyList[index].arKey));
1159 A_MEMCPY(ar->arWepKeyList[index].arKey, keybuf, erq->length);
1160 ar->arWepKeyList[index].arKeyLen = erq->length;
1161 ar->arDot11AuthMode = auth;
1162 } else {
1163 if (ar->arWepKeyList[index].arKeyLen == 0) {
1164 return -EIO;
1165 }
1166 ar->arDefTxKeyIndex = index;
1167
1168 if(ar->arSsidLen && ar->arWepKeyList[index].arKeyLen) {
1169 wmi_addKey_cmd(ar->arWmi,
1170 index,
1171 WEP_CRYPT,
1172 GROUP_USAGE | TX_USAGE,
1173 ar->arWepKeyList[index].arKeyLen,
1174 NULL,
1175 ar->arWepKeyList[index].arKey, KEY_OP_INIT_VAL, N ULL,
1176 NO_SYNC_WMIFLAG);
1177 }
1178 }
1179
1180 ar->arPairwiseCrypto = WEP_CRYPT;
1181 ar->arGroupCrypto = WEP_CRYPT;
1182 ar->arAuthMode = NONE_AUTH;
1183 }
1184
1185 if(ar->arNextMode != AP_NETWORK) {
1186 /*
1187 * profile has changed. Erase ssid to signal change
1188 */
1189 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
1190 ar->arSsidLen = 0;
1191 }
1192 ar->ap_profile_flag = 1; /* There is a change in profile */
1193 return 0;
1194 }
1195
1196 static int
1197 ar6000_ioctl_giwencode(struct net_device *dev,
1198 struct iw_request_info *info,
1199 struct iw_point *erq, char *key)
1200 {
1201 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1202 A_UINT8 keyIndex;
1203 struct ar_wep_key *wk;
1204
1205 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
1206 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
1207 return -EOPNOTSUPP;
1208 }
1209
1210 if (ar->arWlanState == WLAN_DISABLED) {
1211 return -EIO;
1212 }
1213
1214 if (ar->arPairwiseCrypto == NONE_CRYPT) {
1215 erq->length = 0;
1216 erq->flags = IW_ENCODE_DISABLED;
1217 } else {
1218 if (ar->arPairwiseCrypto == WEP_CRYPT) {
1219 /* get the keyIndex */
1220 keyIndex = erq->flags & IW_ENCODE_INDEX;
1221 if (0 == keyIndex) {
1222 keyIndex = ar->arDefTxKeyIndex;
1223 } else if ((keyIndex - 1 < WMI_MIN_KEY_INDEX) ||
1224 (keyIndex - 1 > WMI_MAX_KEY_INDEX))
1225 {
1226 keyIndex = WMI_MIN_KEY_INDEX;
1227 } else {
1228 keyIndex--;
1229 }
1230 erq->flags = keyIndex + 1;
1231 erq->flags &= ~IW_ENCODE_DISABLED;
1232 wk = &ar->arWepKeyList[keyIndex];
1233 if (erq->length > wk->arKeyLen) {
1234 erq->length = wk->arKeyLen;
1235 }
1236 if (wk->arKeyLen) {
1237 A_MEMCPY(key, wk->arKey, erq->length);
1238 }
1239 } else {
1240 erq->flags &= ~IW_ENCODE_DISABLED;
1241 if (ar->user_saved_keys.keyOk) {
1242 erq->length = ar->user_saved_keys.ucast_ik.ik_keylen;
1243 if (erq->length) {
1244 A_MEMCPY(key, ar->user_saved_keys.ucast_ik.ik_keydata, erq-> length);
1245 }
1246 } else {
1247 erq->length = 1; // not really printing any key but let iwcon fig know enc is on
1248 }
1249 }
1250
1251 if (ar->arDot11AuthMode & OPEN_AUTH) {
1252 erq->flags |= IW_ENCODE_OPEN;
1253 }
1254 if (ar->arDot11AuthMode & SHARED_AUTH) {
1255 erq->flags |= IW_ENCODE_RESTRICTED;
1256 }
1257 }
1258
1259 return 0;
1260 }
1261
1262 #if WIRELESS_EXT >= 18
1263 /*
1264 * SIOCSIWGENIE
1265 */
1266 static int
1267 ar6000_ioctl_siwgenie(struct net_device *dev,
1268 struct iw_request_info *info,
1269 struct iw_point *erq, char *extra)
1270 {
1271 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1272
1273 #ifdef WAPI_ENABLE
1274 A_UINT8 *ie = erq->pointer;
1275 A_UINT8 ie_type = ie[0];
1276 A_UINT16 ie_length = erq->length;
1277 A_UINT8 wapi_ie[128];
1278 #endif
1279
1280 if (ar->arWmiReady == FALSE) {
1281 return -EIO;
1282 }
1283 #ifdef WAPI_ENABLE
1284 if (ie_type == IEEE80211_ELEMID_WAPI) {
1285 if(copy_from_user(wapi_ie, ie, ie_length))
1286 return -EIO;
1287 wmi_set_appie_cmd(ar->arWmi, WMI_FRAME_ASSOC_REQ, ie_length, wapi_ie);
1288 }
1289 #endif
1290 return 0;
1291 }
1292
1293
1294 /*
1295 * SIOCGIWGENIE
1296 */
1297 static int
1298 ar6000_ioctl_giwgenie(struct net_device *dev,
1299 struct iw_request_info *info,
1300 struct iw_point *erq, char *extra)
1301 {
1302 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1303
1304 if (ar->arWmiReady == FALSE) {
1305 return -EIO;
1306 }
1307 erq->length = 0;
1308 erq->flags = 0;
1309
1310 return 0;
1311 }
1312
1313 /*
1314 * SIOCSIWAUTH
1315 */
1316 static int
1317 ar6000_ioctl_siwauth(struct net_device *dev,
1318 struct iw_request_info *info,
1319 struct iw_param *data, char *extra)
1320 {
1321 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1322
1323 A_BOOL profChanged;
1324 A_UINT16 param;
1325 A_INT32 ret;
1326 A_INT32 value;
1327
1328 if (ar->arWmiReady == FALSE) {
1329 return -EIO;
1330 }
1331
1332 if (ar->arWlanState == WLAN_DISABLED) {
1333 return -EIO;
1334 }
1335
1336 param = data->flags & IW_AUTH_INDEX;
1337 value = data->value;
1338 profChanged = TRUE;
1339 ret = 0;
1340
1341 switch (param) {
1342 case IW_AUTH_WPA_VERSION:
1343 if (value & IW_AUTH_WPA_VERSION_DISABLED) {
1344 ar->arAuthMode = NONE_AUTH;
1345 } else if (value & IW_AUTH_WPA_VERSION_WPA) {
1346 ar->arAuthMode = WPA_AUTH;
1347 } else if (value & IW_AUTH_WPA_VERSION_WPA2) {
1348 ar->arAuthMode = WPA2_AUTH;
1349 } else {
1350 ret = -1;
1351 profChanged = FALSE;
1352 }
1353 break;
1354 case IW_AUTH_CIPHER_PAIRWISE:
1355 if (value & IW_AUTH_CIPHER_NONE) {
1356 ar->arPairwiseCrypto = NONE_CRYPT;
1357 ar->arPairwiseCryptoLen = 0;
1358 } else if (value & IW_AUTH_CIPHER_WEP40) {
1359 ar->arPairwiseCrypto = WEP_CRYPT;
1360 ar->arPairwiseCryptoLen = 5;
1361 } else if (value & IW_AUTH_CIPHER_TKIP) {
1362 ar->arPairwiseCrypto = TKIP_CRYPT;
1363 ar->arPairwiseCryptoLen = 0;
1364 } else if (value & IW_AUTH_CIPHER_CCMP) {
1365 ar->arPairwiseCrypto = AES_CRYPT;
1366 ar->arPairwiseCryptoLen = 0;
1367 } else if (value & IW_AUTH_CIPHER_WEP104) {
1368 ar->arPairwiseCrypto = WEP_CRYPT;
1369 ar->arPairwiseCryptoLen = 13;
1370 } else {
1371 ret = -1;
1372 profChanged = FALSE;
1373 }
1374 break;
1375 case IW_AUTH_CIPHER_GROUP:
1376 if (value & IW_AUTH_CIPHER_NONE) {
1377 ar->arGroupCrypto = NONE_CRYPT;
1378 ar->arGroupCryptoLen = 0;
1379 } else if (value & IW_AUTH_CIPHER_WEP40) {
1380 ar->arGroupCrypto = WEP_CRYPT;
1381 ar->arGroupCryptoLen = 5;
1382 } else if (value & IW_AUTH_CIPHER_TKIP) {
1383 ar->arGroupCrypto = TKIP_CRYPT;
1384 ar->arGroupCryptoLen = 0;
1385 } else if (value & IW_AUTH_CIPHER_CCMP) {
1386 ar->arGroupCrypto = AES_CRYPT;
1387 ar->arGroupCryptoLen = 0;
1388 } else if (value & IW_AUTH_CIPHER_WEP104) {
1389 ar->arGroupCrypto = WEP_CRYPT;
1390 ar->arGroupCryptoLen = 13;
1391 } else {
1392 ret = -1;
1393 profChanged = FALSE;
1394 }
1395 break;
1396 case IW_AUTH_KEY_MGMT:
1397 if (value & IW_AUTH_KEY_MGMT_PSK) {
1398 if (WPA_AUTH == ar->arAuthMode) {
1399 ar->arAuthMode = WPA_PSK_AUTH;
1400 } else if (WPA2_AUTH == ar->arAuthMode) {
1401 ar->arAuthMode = WPA2_PSK_AUTH;
1402 } else {
1403 ret = -1;
1404 }
1405 } else if (!(value & IW_AUTH_KEY_MGMT_802_1X)) {
1406 ar->arAuthMode = NONE_AUTH;
1407 }
1408 break;
1409 case IW_AUTH_TKIP_COUNTERMEASURES:
1410 wmi_set_tkip_countermeasures_cmd(ar->arWmi, value);
1411 profChanged = FALSE;
1412 break;
1413 case IW_AUTH_DROP_UNENCRYPTED:
1414 profChanged = FALSE;
1415 break;
1416 case IW_AUTH_80211_AUTH_ALG:
1417 ar->arDot11AuthMode = 0;
1418 if (value & IW_AUTH_ALG_OPEN_SYSTEM) {
1419 ar->arDot11AuthMode |= OPEN_AUTH;
1420 }
1421 if (value & IW_AUTH_ALG_SHARED_KEY) {
1422 ar->arDot11AuthMode |= SHARED_AUTH;
1423 }
1424 if (value & IW_AUTH_ALG_LEAP) {
1425 ar->arDot11AuthMode = LEAP_AUTH;
1426 }
1427 if(ar->arDot11AuthMode == 0) {
1428 ret = -1;
1429 profChanged = FALSE;
1430 }
1431 break;
1432 case IW_AUTH_WPA_ENABLED:
1433 if (!value) {
1434 ar->arAuthMode = NONE_AUTH;
1435 /* when the supplicant is stopped, it calls this
1436 * handler with value=0. The followings need to be
1437 * reset if the STA were to connect again
1438 * without security
1439 */
1440 ar->arDot11AuthMode = OPEN_AUTH;
1441 ar->arPairwiseCrypto = NONE_CRYPT;
1442 ar->arPairwiseCryptoLen = 0;
1443 ar->arGroupCrypto = NONE_CRYPT;
1444 ar->arGroupCryptoLen = 0;
1445 }
1446 break;
1447 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1448 profChanged = FALSE;
1449 break;
1450 case IW_AUTH_ROAMING_CONTROL:
1451 profChanged = FALSE;
1452 break;
1453 case IW_AUTH_PRIVACY_INVOKED:
1454 if (!value) {
1455 ar->arPairwiseCrypto = NONE_CRYPT;
1456 ar->arPairwiseCryptoLen = 0;
1457 ar->arGroupCrypto = NONE_CRYPT;
1458 ar->arGroupCryptoLen = 0;
1459 }
1460 break;
1461 #ifdef WAPI_ENABLE
1462 case IW_AUTH_WAPI_ENABLED:
1463 ar->arWapiEnable = value;
1464 break;
1465 #endif
1466 default:
1467 ret = -1;
1468 profChanged = FALSE;
1469 break;
1470 }
1471
1472 if (profChanged == TRUE) {
1473 /*
1474 * profile has changed. Erase ssid to signal change
1475 */
1476 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
1477 ar->arSsidLen = 0;
1478 }
1479
1480 return ret;
1481 }
1482
1483
1484 /*
1485 * SIOCGIWAUTH
1486 */
1487 static int
1488 ar6000_ioctl_giwauth(struct net_device *dev,
1489 struct iw_request_info *info,
1490 struct iw_param *data, char *extra)
1491 {
1492 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1493 A_UINT16 param;
1494 A_INT32 ret;
1495
1496 if (ar->arWmiReady == FALSE) {
1497 return -EIO;
1498 }
1499
1500 if (ar->arWlanState == WLAN_DISABLED) {
1501 return -EIO;
1502 }
1503
1504 param = data->flags & IW_AUTH_INDEX;
1505 ret = 0;
1506 data->value = 0;
1507
1508
1509 switch (param) {
1510 case IW_AUTH_WPA_VERSION:
1511 if (ar->arAuthMode == NONE_AUTH) {
1512 data->value |= IW_AUTH_WPA_VERSION_DISABLED;
1513 } else if (ar->arAuthMode == WPA_AUTH) {
1514 data->value |= IW_AUTH_WPA_VERSION_WPA;
1515 } else if (ar->arAuthMode == WPA2_AUTH) {
1516 data->value |= IW_AUTH_WPA_VERSION_WPA2;
1517 } else {
1518 ret = -1;
1519 }
1520 break;
1521 case IW_AUTH_CIPHER_PAIRWISE:
1522 if (ar->arPairwiseCrypto == NONE_CRYPT) {
1523 data->value |= IW_AUTH_CIPHER_NONE;
1524 } else if (ar->arPairwiseCrypto == WEP_CRYPT) {
1525 if (ar->arPairwiseCryptoLen == 13) {
1526 data->value |= IW_AUTH_CIPHER_WEP104;
1527 } else {
1528 data->value |= IW_AUTH_CIPHER_WEP104;
1529 }
1530 } else if (ar->arPairwiseCrypto == TKIP_CRYPT) {
1531 data->value |= IW_AUTH_CIPHER_TKIP;
1532 } else if (ar->arPairwiseCrypto == AES_CRYPT) {
1533 data->value |= IW_AUTH_CIPHER_CCMP;
1534 } else {
1535 ret = -1;
1536 }
1537 break;
1538 case IW_AUTH_CIPHER_GROUP:
1539 if (ar->arGroupCrypto == NONE_CRYPT) {
1540 data->value |= IW_AUTH_CIPHER_NONE;
1541 } else if (ar->arGroupCrypto == WEP_CRYPT) {
1542 if (ar->arGroupCryptoLen == 13) {
1543 data->value |= IW_AUTH_CIPHER_WEP104;
1544 } else {
1545 data->value |= IW_AUTH_CIPHER_WEP104;
1546 }
1547 } else if (ar->arGroupCrypto == TKIP_CRYPT) {
1548 data->value |= IW_AUTH_CIPHER_TKIP;
1549 } else if (ar->arGroupCrypto == AES_CRYPT) {
1550 data->value |= IW_AUTH_CIPHER_CCMP;
1551 } else {
1552 ret = -1;
1553 }
1554 break;
1555 case IW_AUTH_KEY_MGMT:
1556 if ((ar->arAuthMode == WPA_PSK_AUTH) ||
1557 (ar->arAuthMode == WPA2_PSK_AUTH)) {
1558 data->value |= IW_AUTH_KEY_MGMT_PSK;
1559 } else if ((ar->arAuthMode == WPA_AUTH) ||
1560 (ar->arAuthMode == WPA2_AUTH)) {
1561 data->value |= IW_AUTH_KEY_MGMT_802_1X;
1562 }
1563 break;
1564 case IW_AUTH_TKIP_COUNTERMEASURES:
1565 // TODO. Save countermeassure enable/disable
1566 data->value = 0;
1567 break;
1568 case IW_AUTH_DROP_UNENCRYPTED:
1569 break;
1570 case IW_AUTH_80211_AUTH_ALG:
1571 if (ar->arDot11AuthMode == OPEN_AUTH) {
1572 data->value |= IW_AUTH_ALG_OPEN_SYSTEM;
1573 } else if (ar->arDot11AuthMode == SHARED_AUTH) {
1574 data->value |= IW_AUTH_ALG_SHARED_KEY;
1575 } else if (ar->arDot11AuthMode == LEAP_AUTH) {
1576 data->value |= IW_AUTH_ALG_LEAP;
1577 } else {
1578 ret = -1;
1579 }
1580 break;
1581 case IW_AUTH_WPA_ENABLED:
1582 if (ar->arAuthMode == NONE_AUTH) {
1583 data->value = 0;
1584 } else {
1585 data->value = 1;
1586 }
1587 break;
1588 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1589 break;
1590 case IW_AUTH_ROAMING_CONTROL:
1591 break;
1592 case IW_AUTH_PRIVACY_INVOKED:
1593 if (ar->arPairwiseCrypto == NONE_CRYPT) {
1594 data->value = 0;
1595 } else {
1596 data->value = 1;
1597 }
1598 break;
1599 #ifdef WAPI_ENABLE
1600 case IW_AUTH_WAPI_ENABLED:
1601 data->value = ar->arWapiEnable;
1602 break;
1603 #endif
1604 default:
1605 ret = -1;
1606 break;
1607 }
1608
1609 return 0;
1610 }
1611
1612 /*
1613 * SIOCSIWPMKSA
1614 */
1615 static int
1616 ar6000_ioctl_siwpmksa(struct net_device *dev,
1617 struct iw_request_info *info,
1618 struct iw_point *data, char *extra)
1619 {
1620 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1621 A_INT32 ret;
1622 A_STATUS status;
1623 struct iw_pmksa *pmksa;
1624
1625 pmksa = (struct iw_pmksa *)extra;
1626
1627 if (ar->arWmiReady == FALSE) {
1628 return -EIO;
1629 }
1630
1631 ret = 0;
1632 status = A_OK;
1633
1634 switch (pmksa->cmd) {
1635 case IW_PMKSA_ADD:
1636 status = wmi_setPmkid_cmd(ar->arWmi, pmksa->bssid.sa_data, pmksa->pm kid, TRUE);
1637 break;
1638 case IW_PMKSA_REMOVE:
1639 status = wmi_setPmkid_cmd(ar->arWmi, pmksa->bssid.sa_data, pmksa->pm kid, FALSE);
1640 break;
1641 case IW_PMKSA_FLUSH:
1642 break;
1643 default:
1644 ret=-1;
1645 break;
1646 }
1647 if (status != A_OK) {
1648 ret = -1;
1649 }
1650
1651 return ret;
1652 }
1653
1654 #ifdef WAPI_ENABLE
1655
1656 #define PN_INIT 0x5c365c36
1657
1658 static int ar6000_set_wapi_key(struct net_device *dev,
1659 struct iw_request_info *info,
1660 struct iw_point *erq, char *extra)
1661 {
1662 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1663 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1664 KEY_USAGE keyUsage = 0;
1665 A_INT32 keyLen;
1666 A_UINT8 *keyData;
1667 A_INT32 index;
1668 A_UINT32 *PN;
1669 A_INT32 i;
1670 A_STATUS status;
1671 A_UINT8 wapiKeyRsc[16];
1672 CRYPTO_TYPE keyType = WAPI_CRYPT;
1673 const A_UINT8 broadcastMac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1674
1675 index = erq->flags & IW_ENCODE_INDEX;
1676 if (index && (((index - 1) < WMI_MIN_KEY_INDEX) ||
1677 ((index - 1) > WMI_MAX_KEY_INDEX))) {
1678 return -EIO;
1679 }
1680
1681 index--;
1682 if (index < 0 || index > 4) {
1683 return -EIO;
1684 }
1685 keyData = (A_UINT8 *)(ext + 1);
1686 keyLen = erq->length - sizeof(struct iw_encode_ext);
1687 A_MEMCPY(wapiKeyRsc, ext->tx_seq, sizeof(wapiKeyRsc));
1688
1689 if (A_MEMCMP(ext->addr.sa_data, broadcastMac, sizeof(broadcastMac)) == 0) {
1690 keyUsage |= GROUP_USAGE;
1691 PN = (A_UINT32 *)wapiKeyRsc;
1692 for (i = 0; i < 4; i++) {
1693 PN[i] = PN_INIT;
1694 }
1695 } else {
1696 keyUsage |= PAIRWISE_USAGE;
1697 }
1698 status = wmi_addKey_cmd(ar->arWmi,
1699 index,
1700 keyType,
1701 keyUsage,
1702 keyLen,
1703 wapiKeyRsc,
1704 keyData,
1705 KEY_OP_INIT_WAPIPN,
1706 NULL,
1707 SYNC_BEFORE_WMIFLAG);
1708 if (A_OK != status) {
1709 return -EIO;
1710 }
1711 return 0;
1712 }
1713
1714 #endif
1715
1716 /*
1717 * SIOCSIWENCODEEXT
1718 */
1719 static int
1720 ar6000_ioctl_siwencodeext(struct net_device *dev,
1721 struct iw_request_info *info,
1722 struct iw_point *erq, char *extra)
1723 {
1724 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1725 A_INT32 index;
1726 struct iw_encode_ext *ext;
1727 KEY_USAGE keyUsage;
1728 A_INT32 keyLen;
1729 A_UINT8 *keyData;
1730 A_UINT8 keyRsc[8];
1731 A_STATUS status;
1732 CRYPTO_TYPE keyType;
1733 #ifdef USER_KEYS
1734 struct ieee80211req_key ik;
1735 #endif /* USER_KEYS */
1736
1737 if (ar->arWlanState == WLAN_DISABLED) {
1738 return -EIO;
1739 }
1740
1741 #ifdef USER_KEYS
1742 ar->user_saved_keys.keyOk = FALSE;
1743 #endif /* USER_KEYS */
1744
1745 index = erq->flags & IW_ENCODE_INDEX;
1746
1747 if (index && (((index - 1) < WMI_MIN_KEY_INDEX) ||
1748 ((index - 1) > WMI_MAX_KEY_INDEX)))
1749 {
1750 return -EIO;
1751 }
1752
1753 ext = (struct iw_encode_ext *)extra;
1754 if (erq->flags & IW_ENCODE_DISABLED) {
1755 /*
1756 * Encryption disabled
1757 */
1758 if (index) {
1759 /*
1760 * If key index was specified then clear the specified key
1761 */
1762 index--;
1763 A_MEMZERO(ar->arWepKeyList[index].arKey,
1764 sizeof(ar->arWepKeyList[index].arKey));
1765 ar->arWepKeyList[index].arKeyLen = 0;
1766 }
1767 } else {
1768 /*
1769 * Enabling WEP encryption
1770 */
1771 if (index) {
1772 index--; /* keyindex is off base 1 in iwconfig */
1773 }
1774
1775 keyUsage = 0;
1776 keyLen = erq->length - sizeof(struct iw_encode_ext);
1777
1778 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
1779 keyUsage = TX_USAGE;
1780 ar->arDefTxKeyIndex = index;
1781 // Just setting the key index
1782 if (keyLen == 0) {
1783 return 0;
1784 }
1785 }
1786
1787 if (keyLen <= 0) {
1788 return -EIO;
1789 }
1790
1791 /* key follows iw_encode_ext */
1792 keyData = (A_UINT8 *)(ext + 1);
1793
1794 switch (ext->alg) {
1795 case IW_ENCODE_ALG_WEP:
1796 keyType = WEP_CRYPT;
1797 #ifdef USER_KEYS
1798 ik.ik_type = IEEE80211_CIPHER_WEP;
1799 #endif /* USER_KEYS */
1800 if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(keyLen)) {
1801 return -EIO;
1802 }
1803
1804 // Check whether it is static wep
1805 if (!ar->arConnected) {
1806 A_MEMZERO(ar->arWepKeyList[index].arKey,
1807 sizeof(ar->arWepKeyList[index].arKey));
1808 A_MEMCPY(ar->arWepKeyList[index].arKey, keyData, keyLen);
1809 ar->arWepKeyList[index].arKeyLen = keyLen;
1810
1811 return 0;
1812 }
1813 break;
1814 case IW_ENCODE_ALG_TKIP:
1815 keyType = TKIP_CRYPT;
1816 #ifdef USER_KEYS
1817 ik.ik_type = IEEE80211_CIPHER_TKIP;
1818 #endif /* USER_KEYS */
1819 break;
1820 case IW_ENCODE_ALG_CCMP:
1821 keyType = AES_CRYPT;
1822 #ifdef USER_KEYS
1823 ik.ik_type = IEEE80211_CIPHER_AES_CCM;
1824 #endif /* USER_KEYS */
1825 break;
1826 #ifdef WAPI_ENABLE
1827 case IW_ENCODE_ALG_SM4:
1828 if (ar->arWapiEnable) {
1829 return ar6000_set_wapi_key(dev, info, erq, extra);
1830 } else {
1831 return -EIO;
1832 }
1833 #endif
1834 case IW_ENCODE_ALG_PMK:
1835 ar->arConnectCtrlFlags |= CONNECT_DO_WPA_OFFLOAD;
1836 return wmi_set_pmk_cmd(ar->arWmi, keyData);
1837 default:
1838 return -EIO;
1839 }
1840
1841
1842 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1843 keyUsage |= GROUP_USAGE;
1844 } else {
1845 keyUsage |= PAIRWISE_USAGE;
1846 }
1847
1848 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
1849 A_MEMCPY(keyRsc, ext->rx_seq, sizeof(keyRsc));
1850 } else {
1851 A_MEMZERO(keyRsc, sizeof(keyRsc));
1852 }
1853
1854 if (((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMod e)) &&
1855 (GROUP_USAGE & keyUsage))
1856 {
1857 A_UNTIMEOUT(&ar->disconnect_timer);
1858 }
1859
1860 status = wmi_addKey_cmd(ar->arWmi, index, keyType, keyUsage,
1861 keyLen, keyRsc,
1862 keyData, KEY_OP_INIT_VAL,
1863 ext->addr.sa_data,
1864 SYNC_BOTH_WMIFLAG);
1865 if (status != A_OK) {
1866 return -EIO;
1867 }
1868
1869 #ifdef USER_KEYS
1870 ik.ik_keyix = index;
1871 ik.ik_keylen = keyLen;
1872 memcpy(ik.ik_keydata, keyData, keyLen);
1873 memcpy(&ik.ik_keyrsc, keyRsc, sizeof(keyRsc));
1874 memcpy(ik.ik_macaddr, ext->addr.sa_data, ETH_ALEN);
1875 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1876 memcpy(&ar->user_saved_keys.bcast_ik, &ik,
1877 sizeof(struct ieee80211req_key));
1878 } else {
1879 memcpy(&ar->user_saved_keys.ucast_ik, &ik,
1880 sizeof(struct ieee80211req_key));
1881 }
1882 ar->user_saved_keys.keyOk = TRUE;
1883 #endif /* USER_KEYS */
1884 }
1885
1886
1887 return 0;
1888 }
1889
1890 /*
1891 * SIOCGIWENCODEEXT
1892 */
1893 static int
1894 ar6000_ioctl_giwencodeext(struct net_device *dev,
1895 struct iw_request_info *info,
1896 struct iw_point *erq, char *extra)
1897 {
1898 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1899
1900 if (ar->arWlanState == WLAN_DISABLED) {
1901 return -EIO;
1902 }
1903
1904 if (ar->arPairwiseCrypto == NONE_CRYPT) {
1905 erq->length = 0;
1906 erq->flags = IW_ENCODE_DISABLED;
1907 } else {
1908 erq->length = 0;
1909 }
1910
1911 return 0;
1912 }
1913 #endif // WIRELESS_EXT >= 18
1914
1915 #if WIRELESS_EXT > 20
1916 static int ar6000_ioctl_siwpower(struct net_device *dev,
1917 struct iw_request_info *info,
1918 union iwreq_data *wrqu, char *extra)
1919 {
1920 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1921 WMI_POWER_MODE power_mode;
1922
1923 if (ar->arWlanState == WLAN_DISABLED) {
1924 return -EIO;
1925 }
1926
1927 if (wrqu->power.disabled)
1928 power_mode = MAX_PERF_POWER;
1929 else
1930 power_mode = REC_POWER;
1931
1932 if (wmi_powermode_cmd(ar->arWmi, power_mode) < 0)
1933 return -EIO;
1934 return 0;
1935 }
1936
1937 static int ar6000_ioctl_giwpower(struct net_device *dev,
1938 struct iw_request_info *info,
1939 union iwreq_data *wrqu, char *extra)
1940 {
1941 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1942
1943 if (ar->arWlanState == WLAN_DISABLED) {
1944 return -EIO;
1945 }
1946
1947 if(!ar->arWmi){
1948 return -EIO;
1949 }
1950 return wmi_get_power_mode_cmd(ar->arWmi);
1951 }
1952 #endif // WIRELESS_EXT > 20
1953
1954 /*
1955 * SIOCGIWNAME
1956 */
1957 int
1958 ar6000_ioctl_giwname(struct net_device *dev,
1959 struct iw_request_info *info,
1960 char *name, char *extra)
1961 {
1962 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1963
1964 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
1965 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
1966 return -EOPNOTSUPP;
1967 }
1968
1969 if (ar->arWlanState == WLAN_DISABLED) {
1970 return -EIO;
1971 }
1972
1973 switch (ar->arPhyCapability) {
1974 case (WMI_11A_CAPABILITY):
1975 strncpy(name, "AR6000 802.11a", IFNAMSIZ);
1976 break;
1977 case (WMI_11G_CAPABILITY):
1978 strncpy(name, "AR6000 802.11g", IFNAMSIZ);
1979 break;
1980 case (WMI_11AG_CAPABILITY):
1981 strncpy(name, "AR6000 802.11ag", IFNAMSIZ);
1982 break;
1983 case (WMI_11NA_CAPABILITY):
1984 strncpy(name, "AR6000 802.11na", IFNAMSIZ);
1985 break;
1986 case (WMI_11NG_CAPABILITY):
1987 strncpy(name, "AR6000 802.11ng", IFNAMSIZ);
1988 break;
1989 case (WMI_11NAG_CAPABILITY):
1990 strncpy(name, "AR6000 802.11nag", IFNAMSIZ);
1991 break;
1992 default:
1993 strncpy(name, "AR6000 802.11", IFNAMSIZ);
1994 break;
1995 }
1996
1997 return 0;
1998 }
1999
2000 /*
2001 * SIOCSIWFREQ
2002 */
2003 int
2004 ar6000_ioctl_siwfreq(struct net_device *dev,
2005 struct iw_request_info *info,
2006 struct iw_freq *freq, char *extra)
2007 {
2008 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2009
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;
2013 }
2014
2015 if (ar->arWlanState == WLAN_DISABLED) {
2016 return -EIO;
2017 }
2018
2019 /*
2020 * We support limiting the channels via wmiconfig.
2021 *
2022 * We use this command to configure the channel hint for the connect cmd
2023 * so it is possible the target will end up connecting to a different
2024 * channel.
2025 */
2026 if (freq->e > 1) {
2027 return -EINVAL;
2028 } else if (freq->e == 1) {
2029 ar->arChannelHint = freq->m / 100000;
2030 } else {
2031 if(freq->m) {
2032 ar->arChannelHint = wlan_ieee2freq(freq->m);
2033 } else {
2034 /* Auto Channel Selection */
2035 ar->arChannelHint = 0;
2036 }
2037 }
2038
2039 ar->ap_profile_flag = 1; /* There is a change in profile */
2040
2041 A_PRINTF("channel hint set to %d\n", ar->arChannelHint);
2042 return 0;
2043 }
2044
2045 /*
2046 * SIOCGIWFREQ
2047 */
2048 int
2049 ar6000_ioctl_giwfreq(struct net_device *dev,
2050 struct iw_request_info *info,
2051 struct iw_freq *freq, char *extra)
2052 {
2053 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2054
2055 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2056 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2057 return -EOPNOTSUPP;
2058 }
2059
2060 if (ar->arWlanState == WLAN_DISABLED) {
2061 return -EIO;
2062 }
2063
2064 if (ar->arNetworkType == AP_NETWORK) {
2065 if(ar->arChannelHint) {
2066 freq->m = ar->arChannelHint * 100000;
2067 } else if(ar->arACS) {
2068 freq->m = ar->arACS * 100000;
2069 } else {
2070 return -EINVAL;
2071 }
2072 } else {
2073 if (ar->arConnected != TRUE) {
2074 return -EINVAL;
2075 } else {
2076 freq->m = ar->arBssChannel * 100000;
2077 }
2078 }
2079
2080 freq->e = 1;
2081
2082 return 0;
2083 }
2084
2085 /*
2086 * SIOCSIWMODE
2087 */
2088 int
2089 ar6000_ioctl_siwmode(struct net_device *dev,
2090 struct iw_request_info *info,
2091 __u32 *mode, char *extra)
2092 {
2093 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2094
2095 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2096 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2097 return -EOPNOTSUPP;
2098 }
2099
2100 if (ar->arWlanState == WLAN_DISABLED) {
2101 return -EIO;
2102 }
2103
2104 /*
2105 * clear SSID during mode switch in connected state
2106 */
2107 if(!(ar->arNetworkType == (((*mode) == IW_MODE_INFRA) ? INFRA_NETWORK : ADHO C_NETWORK)) && (ar->arConnected == TRUE) ){
2108 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
2109 ar->arSsidLen = 0;
2110 }
2111
2112 switch (*mode) {
2113 case IW_MODE_INFRA:
2114 ar->arNextMode = INFRA_NETWORK;
2115 break;
2116 case IW_MODE_ADHOC:
2117 ar->arNextMode = ADHOC_NETWORK;
2118 break;
2119 case IW_MODE_MASTER:
2120 ar->arNextMode = AP_NETWORK;
2121 break;
2122 default:
2123 return -EINVAL;
2124 }
2125
2126 /* clear all shared parameters between AP and STA|IBSS modes when we
2127 * switch between them. Switch between STA & IBSS modes does'nt clear
2128 * the shared profile. This is as per the original design for switching
2129 * between STA & IBSS.
2130 */
2131 if (ar->arNetworkType == AP_NETWORK || ar->arNextMode == AP_NETWORK) {
2132 ar->arDot11AuthMode = OPEN_AUTH;
2133 ar->arAuthMode = NONE_AUTH;
2134 ar->arPairwiseCrypto = NONE_CRYPT;
2135 ar->arPairwiseCryptoLen = 0;
2136 ar->arGroupCrypto = NONE_CRYPT;
2137 ar->arGroupCryptoLen = 0;
2138 ar->arChannelHint = 0;
2139 ar->arBssChannel = 0;
2140 A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
2141 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
2142 ar->arSsidLen = 0;
2143 }
2144
2145 /* SSID has to be cleared to trigger a profile change while switching
2146 * between STA & IBSS modes having the same SSID
2147 */
2148 if (ar->arNetworkType != ar->arNextMode) {
2149 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
2150 ar->arSsidLen = 0;
2151 }
2152
2153 return 0;
2154 }
2155
2156 /*
2157 * SIOCGIWMODE
2158 */
2159 int
2160 ar6000_ioctl_giwmode(struct net_device *dev,
2161 struct iw_request_info *info,
2162 __u32 *mode, char *extra)
2163 {
2164 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2165
2166 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2167 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2168 return -EOPNOTSUPP;
2169 }
2170
2171 if (ar->arWlanState == WLAN_DISABLED) {
2172 return -EIO;
2173 }
2174
2175 switch (ar->arNetworkType) {
2176 case INFRA_NETWORK:
2177 *mode = IW_MODE_INFRA;
2178 break;
2179 case ADHOC_NETWORK:
2180 *mode = IW_MODE_ADHOC;
2181 break;
2182 case AP_NETWORK:
2183 *mode = IW_MODE_MASTER;
2184 break;
2185 default:
2186 return -EIO;
2187 }
2188 return 0;
2189 }
2190
2191 /*
2192 * SIOCSIWSENS
2193 */
2194 int
2195 ar6000_ioctl_siwsens(struct net_device *dev,
2196 struct iw_request_info *info,
2197 struct iw_param *sens, char *extra)
2198 {
2199 return 0;
2200 }
2201
2202 /*
2203 * SIOCGIWSENS
2204 */
2205 int
2206 ar6000_ioctl_giwsens(struct net_device *dev,
2207 struct iw_request_info *info,
2208 struct iw_param *sens, char *extra)
2209 {
2210 sens->value = 0;
2211 sens->fixed = 1;
2212
2213 return 0;
2214 }
2215
2216 /*
2217 * SIOCGIWRANGE
2218 */
2219 int
2220 ar6000_ioctl_giwrange(struct net_device *dev,
2221 struct iw_request_info *info,
2222 struct iw_point *data, char *extra)
2223 {
2224 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2225 struct iw_range *range = (struct iw_range *) extra;
2226 int i, ret = 0;
2227
2228 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2229 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2230 return -EOPNOTSUPP;
2231 }
2232
2233 if (ar->bIsDestroyProgress) {
2234 return -EBUSY;
2235 }
2236
2237 if (ar->arWmiReady == FALSE) {
2238 return -EIO;
2239 }
2240
2241 if (ar->arWlanState == WLAN_DISABLED) {
2242 return -EIO;
2243 }
2244
2245 if (down_interruptible(&ar->arSem)) {
2246 return -ERESTARTSYS;
2247 }
2248
2249 if (ar->bIsDestroyProgress) {
2250 up(&ar->arSem);
2251 return -EBUSY;
2252 }
2253
2254 ar->arNumChannels = -1;
2255 A_MEMZERO(ar->arChannelList, sizeof (ar->arChannelList));
2256
2257 if (wmi_get_channelList_cmd(ar->arWmi) != A_OK) {
2258 up(&ar->arSem);
2259 return -EIO;
2260 }
2261
2262 wait_event_interruptible_timeout(arEvent, ar->arNumChannels != -1, wmitimeou t * HZ);
2263
2264 if (signal_pending(current)) {
2265 up(&ar->arSem);
2266 return -EINTR;
2267 }
2268
2269 data->length = sizeof(struct iw_range);
2270 A_MEMZERO(range, sizeof(struct iw_range));
2271
2272 range->txpower_capa = 0;
2273
2274 range->min_pmp = 1 * 1024;
2275 range->max_pmp = 65535 * 1024;
2276 range->min_pmt = 1 * 1024;
2277 range->max_pmt = 1000 * 1024;
2278 range->pmp_flags = IW_POWER_PERIOD;
2279 range->pmt_flags = IW_POWER_TIMEOUT;
2280 range->pm_capa = 0;
2281
2282 range->we_version_compiled = WIRELESS_EXT;
2283 range->we_version_source = 13;
2284
2285 range->retry_capa = IW_RETRY_LIMIT;
2286 range->retry_flags = IW_RETRY_LIMIT;
2287 range->min_retry = 0;
2288 range->max_retry = 255;
2289
2290 range->num_frequency = range->num_channels = ar->arNumChannels;
2291 for (i = 0; i < ar->arNumChannels; i++) {
2292 range->freq[i].i = wlan_freq2ieee(ar->arChannelList[i]);
2293 range->freq[i].m = ar->arChannelList[i] * 100000;
2294 range->freq[i].e = 1;
2295 /*
2296 * Linux supports max of 32 channels, bail out once you
2297 * reach the max.
2298 */
2299 if (i == IW_MAX_FREQUENCIES) {
2300 break;
2301 }
2302 }
2303
2304 /* Max quality is max field value minus noise floor */
2305 range->max_qual.qual = 0xff - 161;
2306
2307 /*
2308 * In order to use dBm measurements, 'level' must be lower
2309 * than any possible measurement (see iw_print_stats() in
2310 * wireless tools). It's unclear how this is meant to be
2311 * done, but setting zero in these values forces dBm and
2312 * the actual numbers are not used.
2313 */
2314 range->max_qual.level = 0;
2315 range->max_qual.noise = 0;
2316
2317 range->sensitivity = 3;
2318
2319 range->max_encoding_tokens = 4;
2320 /* XXX query driver to find out supported key sizes */
2321 range->num_encoding_sizes = 3;
2322 range->encoding_size[0] = 5; /* 40-bit */
2323 range->encoding_size[1] = 13; /* 104-bit */
2324 range->encoding_size[2] = 16; /* 128-bit */
2325
2326 range->num_bitrates = 0;
2327
2328 /* estimated maximum TCP throughput values (bps) */
2329 range->throughput = 22000000;
2330
2331 range->min_rts = 0;
2332 range->max_rts = 2347;
2333 range->min_frag = 256;
2334 range->max_frag = 2346;
2335
2336 up(&ar->arSem);
2337
2338 return ret;
2339 }
2340
2341
2342 /*
2343 * SIOCSIWAP
2344 * This ioctl is used to set the desired bssid for the connect command.
2345 */
2346 int
2347 ar6000_ioctl_siwap(struct net_device *dev,
2348 struct iw_request_info *info,
2349 struct sockaddr *ap_addr, char *extra)
2350 {
2351 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2352
2353 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2354 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2355 return -EOPNOTSUPP;
2356 }
2357
2358 if (ar->arWlanState == WLAN_DISABLED) {
2359 return -EIO;
2360 }
2361
2362 if (ap_addr->sa_family != ARPHRD_ETHER) {
2363 return -EIO;
2364 }
2365
2366 if (A_MEMCMP(&ap_addr->sa_data, bcast_mac, AR6000_ETH_ADDR_LEN) == 0) {
2367 A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
2368 } else {
2369 A_MEMCPY(ar->arReqBssid, &ap_addr->sa_data, sizeof(ar->arReqBssid));
2370 }
2371
2372 return 0;
2373 }
2374
2375 /*
2376 * SIOCGIWAP
2377 */
2378 int
2379 ar6000_ioctl_giwap(struct net_device *dev,
2380 struct iw_request_info *info,
2381 struct sockaddr *ap_addr, char *extra)
2382 {
2383 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2384
2385 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2386 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2387 return -EOPNOTSUPP;
2388 }
2389
2390 if (ar->arWlanState == WLAN_DISABLED) {
2391 return -EIO;
2392 }
2393
2394 if (ar->arNetworkType == AP_NETWORK) {
2395 A_MEMCPY(&ap_addr->sa_data, dev->dev_addr, ATH_MAC_LEN);
2396 ap_addr->sa_family = ARPHRD_ETHER;
2397 return 0;
2398 }
2399
2400 if (ar->arConnected != TRUE) {
2401 return -EINVAL;
2402 }
2403
2404 A_MEMCPY(&ap_addr->sa_data, ar->arBssid, sizeof(ar->arBssid));
2405 ap_addr->sa_family = ARPHRD_ETHER;
2406
2407 return 0;
2408 }
2409
2410 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
2411 /*
2412 * SIOCSIWMLME
2413 */
2414 int
2415 ar6000_ioctl_siwmlme(struct net_device *dev,
2416 struct iw_request_info *info,
2417 struct iw_point *data, char *extra)
2418 {
2419 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2420
2421 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2422 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2423 return -EOPNOTSUPP;
2424 }
2425
2426 if (ar->bIsDestroyProgress) {
2427 return -EBUSY;
2428 }
2429
2430 if (ar->arWlanState == WLAN_DISABLED) {
2431 return -EIO;
2432 }
2433
2434 if (ar->arWmiReady == FALSE) {
2435 return -EIO;
2436 }
2437
2438 if (ar->arNetworkType == AP_NETWORK) {
2439 return -EINVAL;
2440 }
2441
2442 if (down_interruptible(&ar->arSem)) {
2443 return -ERESTARTSYS;
2444 }
2445
2446 if (ar->bIsDestroyProgress) {
2447 up(&ar->arSem);
2448 return -EBUSY;
2449 }
2450
2451 if (data->pointer && data->length == sizeof(struct iw_mlme)) {
2452
2453 A_UINT8 arNetworkType;
2454 struct iw_mlme mlme;
2455
2456 if (copy_from_user(&mlme, data->pointer, sizeof(struct iw_mlme)))
2457 return -EIO;
2458
2459 switch (mlme.cmd) {
2460
2461 case IW_MLME_DEAUTH:
2462 /* ignore it */
2463 break;
2464
2465 case IW_MLME_DISASSOC:
2466 if ((ar->arConnected != TRUE) ||
2467 (memcmp(ar->arBssid, mlme.addr.sa_data, 6) != 0)) {
2468
2469 up(&ar->arSem);
2470 return -EINVAL;
2471 }
2472 wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, 0);
2473 arNetworkType = ar->arNetworkType;
2474 ar6000_init_profile_info(ar);
2475 ar->arNetworkType = arNetworkType;
2476 reconnect_flag = 0;
2477 wmi_disconnect_cmd(ar->arWmi);
2478 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
2479 ar->arSsidLen = 0;
2480 if (ar->arSkipScan == FALSE) {
2481 A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
2482 }
2483 break;
2484
2485 case IW_MLME_AUTH:
2486 /* fall through */
2487 case IW_MLME_ASSOC:
2488 /* fall through */
2489 default:
2490 up(&ar->arSem);
2491 return -EOPNOTSUPP;
2492 }
2493 }
2494
2495 up(&ar->arSem);
2496 return 0;
2497 }
2498 #endif /* LINUX_VERSION_CODE */
2499
2500 /*
2501 * SIOCGIWAPLIST
2502 */
2503 int
2504 ar6000_ioctl_iwaplist(struct net_device *dev,
2505 struct iw_request_info *info,
2506 struct iw_point *data, char *extra)
2507 {
2508 return -EIO; /* for now */
2509 }
2510
2511 /*
2512 * SIOCSIWSCAN
2513 */
2514 int
2515 ar6000_ioctl_siwscan(struct net_device *dev,
2516 struct iw_request_info *info,
2517 struct iw_point *data, char *extra)
2518 {
2519 #define ACT_DWELLTIME_DEFAULT 105
2520 #define HOME_TXDRAIN_TIME 100
2521 #define SCAN_INT HOME_TXDRAIN_TIME + ACT_DWELLTIME_DEFAULT
2522 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2523 int ret = 0;
2524
2525 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2526 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2527 return -EOPNOTSUPP;
2528 }
2529
2530 if (ar->arWmiReady == FALSE) {
2531 return -EIO;
2532 }
2533
2534 if (ar->arWlanState == WLAN_DISABLED) {
2535 return -EIO;
2536 }
2537
2538 if (!ar->arUserBssFilter) {
2539 if (wmi_bssfilter_cmd(ar->arWmi, (ar->arConnected ? ALL_BUT_BSS_FILTER : ALL_BSS_FILTER), 0) != A_OK) {
2540 return -EIO;
2541 }
2542 }
2543
2544 if (ar->arConnected) {
2545 if (wmi_get_stats_cmd(ar->arWmi) != A_OK) {
2546 return -EIO;
2547 }
2548 }
2549
2550 #ifdef ANDROID_ENV
2551 #if WIRELESS_EXT >= 18
2552 if (data->pointer && (data->length == sizeof(struct iw_scan_req)))
2553 {
2554 if ((data->flags & IW_SCAN_THIS_ESSID) == IW_SCAN_THIS_ESSID)
2555 {
2556 struct iw_scan_req req;
2557 if (copy_from_user(&req, data->pointer, sizeof(struct iw_scan_req)))
2558 return -EIO;
2559 if (wmi_probedSsid_cmd(ar->arWmi, 1, SPECIFIC_SSID_FLAG, req.essid_l en, req.essid) != A_OK)
2560 return -EIO;
2561 }
2562 else
2563 {
2564 if (wmi_probedSsid_cmd(ar->arWmi, 1, DISABLE_SSID_FLAG, 0, NULL) != A_OK)
2565 return -EIO;
2566 }
2567 }
2568 else
2569 {
2570 if (wmi_probedSsid_cmd(ar->arWmi, 1, DISABLE_SSID_FLAG, 0, NULL) != A_OK )
2571 return -EIO;
2572 }
2573 #endif
2574 #endif
2575
2576 if (wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, FALSE, FALSE, \
2577 0, 0, 0, NULL) != A_OK) {
2578 ret = -EIO;
2579 }
2580
2581 return ret;
2582 #undef ACT_DWELLTIME_DEFAULT
2583 #undef HOME_TXDRAIN_TIME
2584 #undef SCAN_INT
2585 }
2586
2587
2588 /*
2589 * Units are in db above the noise floor. That means the
2590 * rssi values reported in the tx/rx descriptors in the
2591 * driver are the SNR expressed in db.
2592 *
2593 * If you assume that the noise floor is -95, which is an
2594 * excellent assumption 99.5 % of the time, then you can
2595 * derive the absolute signal level (i.e. -95 + rssi).
2596 * There are some other slight factors to take into account
2597 * depending on whether the rssi measurement is from 11b,
2598 * 11g, or 11a. These differences are at most 2db and
2599 * can be documented.
2600 *
2601 * NB: various calculations are based on the orinoco/wavelan
2602 * drivers for compatibility
2603 */
2604 static void
2605 ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi)
2606 {
2607 if (rssi < 0) {
2608 iq->qual = 0;
2609 } else {
2610 iq->qual = rssi;
2611 }
2612
2613 /* NB: max is 94 because noise is hardcoded to 161 */
2614 if (iq->qual > 94)
2615 iq->qual = 94;
2616
2617 iq->noise = 161; /* -95dBm */
2618 iq->level = iq->noise + iq->qual;
2619 iq->updated = 7;
2620 }
2621
2622
2623 int
2624 ar6000_ioctl_siwcommit(struct net_device *dev,
2625 struct iw_request_info *info,
2626 struct iw_point *data, char *extra)
2627 {
2628 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2629
2630 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2631 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2632 return -EOPNOTSUPP;
2633 }
2634
2635 if (ar->arWmiReady == FALSE) {
2636 return -EIO;
2637 }
2638
2639 if (ar->arWlanState == WLAN_DISABLED) {
2640 return -EIO;
2641 }
2642
2643 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("AP: SSID %s freq %d authmode %d dot 11 auth %d"\
2644 " PW crypto %d GRP crypto %d\n",
2645 ar->arSsid, ar->arChannelHint,
2646 ar->arAuthMode, ar->arDot11AuthMode,
2647 ar->arPairwiseCrypto, ar->arGroupCrypto));
2648
2649 ar6000_ap_mode_profile_commit(ar);
2650
2651 /* if there is a profile switch from STA|IBSS mode to AP mode,
2652 * update the host driver association state for the STA|IBSS mode.
2653 */
2654 if (ar->arNetworkType != AP_NETWORK && ar->arNextMode == AP_NETWORK) {
2655 ar->arConnectPending = FALSE;
2656 ar->arConnected = FALSE;
2657 /* Stop getting pkts from upper stack */
2658 netif_stop_queue(ar->arNetDev);
2659 A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
2660 ar->arBssChannel = 0;
2661 ar->arBeaconInterval = 0;
2662
2663 /* Flush the Tx queues */
2664 ar6000_TxDataCleanup(ar);
2665
2666 /* Start getting pkts from upper stack */
2667 netif_wake_queue(ar->arNetDev);
2668 }
2669
2670 return 0;
2671 }
2672
2673 /* Structures to export the Wireless Handlers */
2674 static const iw_handler ath_handlers[] = {
2675 (iw_handler) ar6000_ioctl_siwcommit, /* SIOCSIWCOMMIT */
2676 (iw_handler) ar6000_ioctl_giwname, /* SIOCGIWNAME */
2677 (iw_handler) NULL, /* SIOCSIWNWID */
2678 (iw_handler) NULL, /* SIOCGIWNWID */
2679 (iw_handler) ar6000_ioctl_siwfreq, /* SIOCSIWFREQ */
2680 (iw_handler) ar6000_ioctl_giwfreq, /* SIOCGIWFREQ */
2681 (iw_handler) ar6000_ioctl_siwmode, /* SIOCSIWMODE */
2682 (iw_handler) ar6000_ioctl_giwmode, /* SIOCGIWMODE */
2683 (iw_handler) ar6000_ioctl_siwsens, /* SIOCSIWSENS */
2684 (iw_handler) ar6000_ioctl_giwsens, /* SIOCGIWSENS */
2685 (iw_handler) NULL /* not _used */, /* SIOCSIWRANGE */
2686 (iw_handler) ar6000_ioctl_giwrange, /* SIOCGIWRANGE */
2687 (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */
2688 (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
2689 (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */
2690 (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
2691 (iw_handler) NULL, /* SIOCSIWSPY */
2692 (iw_handler) NULL, /* SIOCGIWSPY */
2693 (iw_handler) NULL, /* SIOCSIWTHRSPY */
2694 (iw_handler) NULL, /* SIOCGIWTHRSPY */
2695 (iw_handler) ar6000_ioctl_siwap, /* SIOCSIWAP */
2696 (iw_handler) ar6000_ioctl_giwap, /* SIOCGIWAP */
2697 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
2698 (iw_handler) ar6000_ioctl_siwmlme, /* SIOCSIWMLME */
2699 #else
2700 (iw_handler) NULL, /* -- hole -- */
2701 #endif /* LINUX_VERSION_CODE */
2702 (iw_handler) ar6000_ioctl_iwaplist, /* SIOCGIWAPLIST */
2703 (iw_handler) ar6000_ioctl_siwscan, /* SIOCSIWSCAN */
2704 (iw_handler) ar6000_ioctl_giwscan, /* SIOCGIWSCAN */
2705 (iw_handler) ar6000_ioctl_siwessid, /* SIOCSIWESSID */
2706 (iw_handler) ar6000_ioctl_giwessid, /* SIOCGIWESSID */
2707 (iw_handler) NULL, /* SIOCSIWNICKN */
2708 (iw_handler) NULL, /* SIOCGIWNICKN */
2709 (iw_handler) NULL, /* -- hole -- */
2710 (iw_handler) NULL, /* -- hole -- */
2711 (iw_handler) ar6000_ioctl_siwrate, /* SIOCSIWRATE */
2712 (iw_handler) ar6000_ioctl_giwrate, /* SIOCGIWRATE */
2713 (iw_handler) NULL, /* SIOCSIWRTS */
2714 (iw_handler) NULL, /* SIOCGIWRTS */
2715 (iw_handler) NULL, /* SIOCSIWFRAG */
2716 (iw_handler) NULL, /* SIOCGIWFRAG */
2717 (iw_handler) ar6000_ioctl_siwtxpow, /* SIOCSIWTXPOW */
2718 (iw_handler) ar6000_ioctl_giwtxpow, /* SIOCGIWTXPOW */
2719 (iw_handler) ar6000_ioctl_siwretry, /* SIOCSIWRETRY */
2720 (iw_handler) ar6000_ioctl_giwretry, /* SIOCGIWRETRY */
2721 (iw_handler) ar6000_ioctl_siwencode, /* SIOCSIWENCODE */
2722 (iw_handler) ar6000_ioctl_giwencode, /* SIOCGIWENCODE */
2723 #if WIRELESS_EXT > 20
2724 (iw_handler) ar6000_ioctl_siwpower, /* SIOCSIWPOWER */
2725 (iw_handler) ar6000_ioctl_giwpower, /* SIOCGIWPOWER */
2726 #endif // WIRELESS_EXT > 20
2727 #if WIRELESS_EXT >= 18
2728 (iw_handler) NULL, /* -- hole -- */
2729 (iw_handler) NULL, /* -- hole -- */
2730 (iw_handler) ar6000_ioctl_siwgenie, /* SIOCSIWGENIE */
2731 (iw_handler) ar6000_ioctl_giwgenie, /* SIOCGIWGENIE */
2732 (iw_handler) ar6000_ioctl_siwauth, /* SIOCSIWAUTH */
2733 (iw_handler) ar6000_ioctl_giwauth, /* SIOCGIWAUTH */
2734 (iw_handler) ar6000_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */
2735 (iw_handler) ar6000_ioctl_giwencodeext, /* SIOCGIWENCODEEXT */
2736 (iw_handler) ar6000_ioctl_siwpmksa, /* SIOCSIWPMKSA */
2737 #endif // WIRELESS_EXT >= 18
2738 };
2739
2740 struct iw_handler_def ath_iw_handler_def = {
2741 .standard = (iw_handler *)ath_handlers,
2742 .num_standard = ARRAY_SIZE(ath_handlers),
2743 .private = NULL,
2744 .num_private = 0,
2745 };
OLDNEW
« no previous file with comments | « chromeos/drivers/ath6kl/os/linux/netbuf.c ('k') | chromeos/drivers/ath6kl/reorder/aggr_rx_internal.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698