sync hh.org
[hh.org.git] / drivers / net / wireless / acx / ioctl.c
blob24d0ea31876c339848be039a8b081427e92454a1
1 /***********************************************************************
2 ** Copyright (C) 2003 ACX100 Open Source Project
3 **
4 ** The contents of this file are subject to the Mozilla Public
5 ** License Version 1.1 (the "License"); you may not use this file
6 ** except in compliance with the License. You may obtain a copy of
7 ** the License at http://www.mozilla.org/MPL/
8 **
9 ** Software distributed under the License is distributed on an "AS
10 ** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11 ** implied. See the License for the specific language governing
12 ** rights and limitations under the License.
14 ** Alternatively, the contents of this file may be used under the
15 ** terms of the GNU Public License version 2 (the "GPL"), in which
16 ** case the provisions of the GPL are applicable instead of the
17 ** above. If you wish to allow the use of your version of this file
18 ** only under the terms of the GPL and not to allow others to use
19 ** your version of this file under the MPL, indicate your decision
20 ** by deleting the provisions above and replace them with the notice
21 ** and other provisions required by the GPL. If you do not delete
22 ** the provisions above, a recipient may use your version of this
23 ** file under either the MPL or the GPL.
24 ** ---------------------------------------------------------------------
25 ** Inquiries regarding the ACX100 Open Source Project can be
26 ** made directly to:
28 ** acx100-users@lists.sf.net
29 ** http://acx100.sf.net
30 ** ---------------------------------------------------------------------
33 #include <linux/version.h>
34 #include <linux/kernel.h>
35 #include <linux/types.h>
36 #include <asm/io.h>
37 //#include <asm/uaccess.h> /* required for 2.4.x kernels; verify_write() */
38 #include <linux/if_arp.h>
39 #include <linux/wireless.h>
40 #include <net/iw_handler.h>
42 #include "acx.h"
45 /***********************************************************************
48 /* channel frequencies
49 * TODO: Currently, every other 802.11 driver keeps its own copy of this. In
50 * the long run this should be integrated into ieee802_11.h or wireless.h or
51 * whatever IEEE802.11x framework evolves */
52 static const u16 acx_channel_freq[] = {
53 2412, 2417, 2422, 2427, 2432, 2437, 2442,
54 2447, 2452, 2457, 2462, 2467, 2472, 2484,
58 /***********************************************************************
59 ** acx_ioctl_commit
61 static int
62 acx_ioctl_commit(struct net_device *ndev,
63 struct iw_request_info *info,
64 union iwreq_data *wrqu,
65 char *extra)
67 acx_device_t *adev = ndev2adev(ndev);
69 FN_ENTER;
71 acx_sem_lock(adev);
72 if (ACX_STATE_IFACE_UP & adev->dev_state_mask)
73 acx_s_update_card_settings(adev);
74 acx_sem_unlock(adev);
76 FN_EXIT0;
77 return OK;
81 /***********************************************************************
83 static int
84 acx_ioctl_get_name(
85 struct net_device *ndev,
86 struct iw_request_info *info,
87 union iwreq_data *wrqu,
88 char *extra)
90 acx_device_t *adev = ndev2adev(ndev);
91 static const char * const names[] = { "IEEE 802.11b+/g+", "IEEE 802.11b+" };
93 strcpy(wrqu->name, names[IS_ACX111(adev) ? 0 : 1]);
95 return OK;
99 /***********************************************************************
100 ** acx_ioctl_set_freq
102 static int
103 acx_ioctl_set_freq(
104 struct net_device *ndev,
105 struct iw_request_info *info,
106 union iwreq_data *wrqu,
107 char *extra)
109 acx_device_t *adev = ndev2adev(ndev);
110 int channel = -1;
111 unsigned int mult = 1;
112 int result;
114 FN_ENTER;
116 if (wrqu->freq.e == 0 && wrqu->freq.m <= 1000) {
117 /* Setting by channel number */
118 channel = wrqu->freq.m;
119 } else {
120 /* If setting by frequency, convert to a channel */
121 int i;
123 for (i = 0; i < (6 - wrqu->freq.e); i++)
124 mult *= 10;
126 for (i = 1; i <= 14; i++)
127 if (wrqu->freq.m == acx_channel_freq[i - 1] * mult)
128 channel = i;
131 if (channel > 14) {
132 result = -EINVAL;
133 goto end;
136 acx_sem_lock(adev);
138 adev->channel = channel;
139 /* hmm, the following code part is strange, but this is how
140 * it was being done before... */
141 log(L_IOCTL, "Changing to channel %d\n", channel);
142 SET_BIT(adev->set_mask, GETSET_CHANNEL);
144 result = -EINPROGRESS; /* need to call commit handler */
146 acx_sem_unlock(adev);
147 end:
148 FN_EXIT1(result);
149 return result;
153 /***********************************************************************
155 static inline int
156 acx_ioctl_get_freq(
157 struct net_device *ndev,
158 struct iw_request_info *info,
159 union iwreq_data *wrqu,
160 char *extra)
162 acx_device_t *adev = ndev2adev(ndev);
163 wrqu->freq.e = 0;
164 wrqu->freq.m = adev->channel;
165 return OK;
169 /***********************************************************************
170 ** acx_ioctl_set_mode
172 static int
173 acx_ioctl_set_mode(
174 struct net_device *ndev,
175 struct iw_request_info *info,
176 union iwreq_data *wrqu,
177 char *extra)
179 acx_device_t *adev = ndev2adev(ndev);
180 int result;
182 FN_ENTER;
184 acx_sem_lock(adev);
186 switch (wrqu->mode) {
187 case IW_MODE_AUTO:
188 adev->mode = ACX_MODE_OFF;
189 break;
190 case IW_MODE_MONITOR:
191 adev->mode = ACX_MODE_MONITOR;
192 break;
193 case IW_MODE_ADHOC:
194 adev->mode = ACX_MODE_0_ADHOC;
195 break;
196 case IW_MODE_INFRA:
197 adev->mode = ACX_MODE_2_STA;
198 break;
199 case IW_MODE_MASTER:
200 printk("acx: master mode (HostAP) is very, very "
201 "experimental! It might work partially, but "
202 "better get prepared for nasty surprises "
203 "at any time\n");
204 adev->mode = ACX_MODE_3_AP;
205 break;
206 case IW_MODE_REPEAT:
207 case IW_MODE_SECOND:
208 default:
209 result = -EOPNOTSUPP;
210 goto end_unlock;
213 log(L_ASSOC, "new adev->mode=%d\n", adev->mode);
214 SET_BIT(adev->set_mask, GETSET_MODE);
215 result = -EINPROGRESS;
217 end_unlock:
218 acx_sem_unlock(adev);
220 FN_EXIT1(result);
221 return result;
225 /***********************************************************************
227 static int
228 acx_ioctl_get_mode(
229 struct net_device *ndev,
230 struct iw_request_info *info,
231 union iwreq_data *wrqu,
232 char *extra)
234 acx_device_t *adev = ndev2adev(ndev);
235 int result = 0;
237 switch (adev->mode) {
238 case ACX_MODE_OFF:
239 wrqu->mode = IW_MODE_AUTO; break;
240 case ACX_MODE_MONITOR:
241 wrqu->mode = IW_MODE_MONITOR; break;
242 case ACX_MODE_0_ADHOC:
243 wrqu->mode = IW_MODE_ADHOC; break;
244 case ACX_MODE_2_STA:
245 wrqu->mode = IW_MODE_INFRA; break;
246 case ACX_MODE_3_AP:
247 wrqu->mode = IW_MODE_MASTER; break;
248 default:
249 result = -EOPNOTSUPP;
251 return result;
255 /***********************************************************************
257 static int
258 acx_ioctl_set_sens(
259 struct net_device *ndev,
260 struct iw_request_info *info,
261 union iwreq_data *wrqu,
262 char *extra)
264 struct iw_param *vwrq = &wrqu->sens;
265 acx_device_t *adev = ndev2adev(ndev);
267 acx_sem_lock(adev);
269 adev->sensitivity = (1 == vwrq->disabled) ? 0 : vwrq->value;
270 SET_BIT(adev->set_mask, GETSET_SENSITIVITY);
272 acx_sem_unlock(adev);
274 return -EINPROGRESS;
278 /***********************************************************************
280 static int
281 acx_ioctl_get_sens(
282 struct net_device *ndev,
283 struct iw_request_info *info,
284 union iwreq_data *wrqu,
285 char *extra)
287 struct iw_param *vwrq = &wrqu->sens;
288 acx_device_t *adev = ndev2adev(ndev);
290 if (IS_USB(adev))
291 /* setting the PHY reg via fw cmd doesn't work yet */
292 return -EOPNOTSUPP;
294 /* acx_sem_lock(adev); */
296 vwrq->value = adev->sensitivity;
297 vwrq->disabled = (vwrq->value == 0);
298 vwrq->fixed = 1;
300 /* acx_sem_unlock(adev); */
302 return OK;
306 /***********************************************************************
307 ** acx_ioctl_set_ap
309 ** Sets the MAC address of the AP to associate with
311 static int
312 acx_ioctl_set_ap(
313 struct net_device *ndev,
314 struct iw_request_info *info,
315 union iwreq_data *wrqu,
316 char *extra)
318 struct sockaddr *awrq = &wrqu->ap_addr;
319 acx_device_t *adev = ndev2adev(ndev);
320 int result = 0;
321 const u8 *ap;
323 FN_ENTER;
324 if (NULL == awrq) {
325 result = -EFAULT;
326 goto end;
328 if (ARPHRD_ETHER != awrq->sa_family) {
329 result = -EINVAL;
330 goto end;
333 ap = awrq->sa_data;
334 acxlog_mac(L_IOCTL, "set AP=", ap, "\n");
336 MAC_COPY(adev->ap, ap);
338 /* We want to start rescan in managed or ad-hoc mode,
339 ** otherwise just set adev->ap.
340 ** "iwconfig <if> ap <mac> mode managed": we must be able
341 ** to set ap _first_ and _then_ set mode */
342 switch (adev->mode) {
343 case ACX_MODE_0_ADHOC:
344 case ACX_MODE_2_STA:
345 /* FIXME: if there is a convention on what zero AP means,
346 ** please add a comment about that. I don't know of any --vda */
347 if (mac_is_zero(ap)) {
348 /* "off" == 00:00:00:00:00:00 */
349 MAC_BCAST(adev->ap);
350 log(L_IOCTL, "Not reassociating\n");
351 } else {
352 log(L_IOCTL, "Forcing reassociation\n");
353 SET_BIT(adev->set_mask, GETSET_RESCAN);
355 break;
357 result = -EINPROGRESS;
358 end:
359 FN_EXIT1(result);
360 return result;
364 /***********************************************************************
366 static int
367 acx_ioctl_get_ap(
368 struct net_device *ndev,
369 struct iw_request_info *info,
370 union iwreq_data *wrqu,
371 char *extra)
373 struct sockaddr *awrq = &wrqu->ap_addr;
374 acx_device_t *adev = ndev2adev(ndev);
376 if (ACX_STATUS_4_ASSOCIATED == adev->status) {
377 /* as seen in Aironet driver, airo.c */
378 MAC_COPY(awrq->sa_data, adev->bssid);
379 } else {
380 MAC_ZERO(awrq->sa_data);
382 awrq->sa_family = ARPHRD_ETHER;
383 return OK;
387 /***********************************************************************
388 ** acx_ioctl_get_aplist
390 ** Deprecated in favor of iwscan.
391 ** We simply return the list of currently available stations in range,
392 ** don't do a new scan.
394 static int
395 acx_ioctl_get_aplist(
396 struct net_device *ndev,
397 struct iw_request_info *info,
398 union iwreq_data *wrqu,
399 char *extra)
401 struct iw_point *dwrq = &wrqu->data;
402 acx_device_t *adev = ndev2adev(ndev);
403 struct sockaddr *address = (struct sockaddr *) extra;
404 struct iw_quality qual[IW_MAX_AP];
405 int i, cur;
406 int result = OK;
408 FN_ENTER;
410 /* we have AP list only in STA mode */
411 if (ACX_MODE_2_STA != adev->mode) {
412 result = -EOPNOTSUPP;
413 goto end;
416 cur = 0;
417 for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
418 struct client *bss = &adev->sta_list[i];
419 if (!bss->used) continue;
420 MAC_COPY(address[cur].sa_data, bss->bssid);
421 address[cur].sa_family = ARPHRD_ETHER;
422 qual[cur].level = bss->sir;
423 qual[cur].noise = bss->snr;
424 #ifndef OLD_QUALITY
425 qual[cur].qual = acx_signal_determine_quality(qual[cur].level,
426 qual[cur].noise);
427 #else
428 qual[cur].qual = (qual[cur].noise <= 100) ?
429 100 - qual[cur].noise : 0;
430 #endif
431 /* no scan: level/noise/qual not updated: */
432 qual[cur].updated = 0;
433 cur++;
435 if (cur) {
436 dwrq->flags = 1;
437 memcpy(extra + sizeof(struct sockaddr)*cur, &qual,
438 sizeof(struct iw_quality)*cur);
440 dwrq->length = cur;
441 end:
442 FN_EXIT1(result);
443 return result;
447 /***********************************************************************
449 static int
450 acx_ioctl_set_scan(
451 struct net_device *ndev,
452 struct iw_request_info *info,
453 union iwreq_data *wrqu,
454 char *extra)
456 acx_device_t *adev = ndev2adev(ndev);
457 int result;
459 FN_ENTER;
461 acx_sem_lock(adev);
463 /* don't start scan if device is not up yet */
464 if (!(adev->dev_state_mask & ACX_STATE_IFACE_UP)) {
465 result = -EAGAIN;
466 goto end_unlock;
469 /* This is NOT a rescan for new AP!
470 ** Do not use SET_BIT(GETSET_RESCAN); */
471 acx_s_cmd_start_scan(adev);
472 result = OK;
474 end_unlock:
475 acx_sem_unlock(adev);
476 /* end: */
477 FN_EXIT1(result);
478 return result;
482 /***********************************************************************
483 ** acx_s_scan_add_station
485 /* helper. not sure whether it's really a _s_leeping fn */
486 static char*
487 acx_s_scan_add_station(
488 acx_device_t *adev,
489 char *ptr,
490 char *end_buf,
491 struct client *bss)
493 struct iw_event iwe;
494 char *ptr_rate;
496 FN_ENTER;
498 /* MAC address has to be added first */
499 iwe.cmd = SIOCGIWAP;
500 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
501 MAC_COPY(iwe.u.ap_addr.sa_data, bss->bssid);
502 acxlog_mac(L_IOCTL, "scan, station address: ", bss->bssid, "\n");
503 ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_ADDR_LEN);
505 /* Add ESSID */
506 iwe.cmd = SIOCGIWESSID;
507 iwe.u.data.length = bss->essid_len;
508 iwe.u.data.flags = 1;
509 log(L_IOCTL, "scan, essid: %s\n", bss->essid);
510 ptr = iwe_stream_add_point(ptr, end_buf, &iwe, bss->essid);
512 /* Add mode */
513 iwe.cmd = SIOCGIWMODE;
514 if (bss->cap_info & (WF_MGMT_CAP_ESS | WF_MGMT_CAP_IBSS)) {
515 if (bss->cap_info & WF_MGMT_CAP_ESS)
516 iwe.u.mode = IW_MODE_MASTER;
517 else
518 iwe.u.mode = IW_MODE_ADHOC;
519 log(L_IOCTL, "scan, mode: %d\n", iwe.u.mode);
520 ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_UINT_LEN);
523 /* Add frequency */
524 iwe.cmd = SIOCGIWFREQ;
525 iwe.u.freq.m = acx_channel_freq[bss->channel - 1] * 100000;
526 iwe.u.freq.e = 1;
527 log(L_IOCTL, "scan, frequency: %d\n", iwe.u.freq.m);
528 ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_FREQ_LEN);
530 /* Add link quality */
531 iwe.cmd = IWEVQUAL;
532 /* FIXME: these values should be expressed in dBm, but we don't know
533 * how to calibrate it yet */
534 iwe.u.qual.level = bss->sir;
535 iwe.u.qual.noise = bss->snr;
536 #ifndef OLD_QUALITY
537 iwe.u.qual.qual = acx_signal_determine_quality(iwe.u.qual.level,
538 iwe.u.qual.noise);
539 #else
540 iwe.u.qual.qual = (iwe.u.qual.noise <= 100) ?
541 100 - iwe.u.qual.noise : 0;
542 #endif
543 iwe.u.qual.updated = 7;
544 log(L_IOCTL, "scan, link quality: %d/%d/%d\n",
545 iwe.u.qual.level, iwe.u.qual.noise, iwe.u.qual.qual);
546 ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_QUAL_LEN);
548 /* Add encryption */
549 iwe.cmd = SIOCGIWENCODE;
550 if (bss->cap_info & WF_MGMT_CAP_PRIVACY)
551 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
552 else
553 iwe.u.data.flags = IW_ENCODE_DISABLED;
554 iwe.u.data.length = 0;
555 log(L_IOCTL, "scan, encryption flags: %X\n", iwe.u.data.flags);
556 ptr = iwe_stream_add_point(ptr, end_buf, &iwe, bss->essid);
558 /* add rates */
559 iwe.cmd = SIOCGIWRATE;
560 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
561 ptr_rate = ptr + IW_EV_LCP_LEN;
564 u16 rate = bss->rate_cap;
565 const u8* p = acx_bitpos2ratebyte;
566 while (rate) {
567 if (rate & 1) {
568 iwe.u.bitrate.value = *p * 500000; /* units of 500kb/s */
569 log(L_IOCTL, "scan, rate: %d\n", iwe.u.bitrate.value);
570 ptr = iwe_stream_add_value(ptr, ptr_rate, end_buf,
571 &iwe, IW_EV_PARAM_LEN);
573 rate >>= 1;
574 p++;
577 if ((ptr_rate - ptr) > (ptrdiff_t)IW_EV_LCP_LEN)
578 ptr = ptr_rate;
580 /* drop remaining station data items for now */
582 FN_EXIT0;
583 return ptr;
587 /***********************************************************************
588 * acx_ioctl_get_scan
590 static int
591 acx_ioctl_get_scan(
592 struct net_device *ndev,
593 struct iw_request_info *info,
594 union iwreq_data *wrqu,
595 char *extra)
597 struct iw_point *dwrq = &wrqu->data;
598 acx_device_t *adev = ndev2adev(ndev);
599 char *ptr = extra;
600 int i;
601 int result = OK;
603 FN_ENTER;
605 acx_sem_lock(adev);
607 /* no scan available if device is not up yet */
608 if (!(adev->dev_state_mask & ACX_STATE_IFACE_UP)) {
609 log(L_IOCTL, "iface not up yet\n");
610 result = -EAGAIN;
611 goto end_unlock;
614 #ifdef ENODATA_TO_BE_USED_AFTER_SCAN_ERROR_ONLY
615 if (adev->bss_table_count == 0) {
616 /* no stations found */
617 result = -ENODATA;
618 goto end_unlock;
620 #endif
622 for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
623 struct client *bss = &adev->sta_list[i];
624 if (!bss->used) continue;
625 ptr = acx_s_scan_add_station(adev, ptr,
626 extra + IW_SCAN_MAX_DATA, bss);
628 dwrq->length = ptr - extra;
629 dwrq->flags = 0;
631 end_unlock:
632 acx_sem_unlock(adev);
633 /* end: */
634 FN_EXIT1(result);
635 return result;
639 /***********************************************************************
640 ** acx_ioctl_set_essid
642 static int
643 acx_ioctl_set_essid(
644 struct net_device *ndev,
645 struct iw_request_info *info,
646 union iwreq_data *wrqu,
647 char *extra)
649 struct iw_point *dwrq = &wrqu->essid;
650 acx_device_t *adev = ndev2adev(ndev);
651 int len = dwrq->length;
652 int result;
654 FN_ENTER;
656 if (len < 0) {
657 result = -EINVAL;
658 goto end;
661 log(L_IOCTL, "set ESSID '%*s', length %d, flags 0x%04X\n",
662 len, extra, len, dwrq->flags);
664 acx_sem_lock(adev);
666 /* ESSID disabled? */
667 if (0 == dwrq->flags) {
668 adev->essid_active = 0;
670 } else {
671 if (dwrq->length > IW_ESSID_MAX_SIZE+1) {
672 result = -E2BIG;
673 goto end_unlock;
676 if (len > sizeof(adev->essid))
677 len = sizeof(adev->essid);
678 memcpy(adev->essid, extra, len-1);
679 adev->essid[len-1] = '\0';
680 /* Paranoia: just in case there is a '\0'... */
681 adev->essid_len = strlen(adev->essid);
682 adev->essid_active = 1;
685 SET_BIT(adev->set_mask, GETSET_RESCAN);
687 result = -EINPROGRESS;
689 end_unlock:
690 acx_sem_unlock(adev);
691 end:
692 FN_EXIT1(result);
693 return result;
697 /***********************************************************************
699 static int
700 acx_ioctl_get_essid(
701 struct net_device *ndev,
702 struct iw_request_info *info,
703 union iwreq_data *wrqu,
704 char *extra)
706 struct iw_point *dwrq = &wrqu->essid;
707 acx_device_t *adev = ndev2adev(ndev);
709 dwrq->flags = adev->essid_active;
710 if (adev->essid_active) {
711 memcpy(extra, adev->essid, adev->essid_len);
712 extra[adev->essid_len] = '\0';
713 dwrq->length = adev->essid_len + 1;
714 dwrq->flags = 1;
716 return OK;
720 /***********************************************************************
721 ** acx_l_update_client_rates
723 static void
724 acx_l_update_client_rates(acx_device_t *adev, u16 rate)
726 int i;
727 for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
728 client_t *clt = &adev->sta_list[i];
729 if (!clt->used) continue;
730 clt->rate_cfg = (clt->rate_cap & rate);
731 if (!clt->rate_cfg) {
732 /* no compatible rates left: kick client */
733 acxlog_mac(L_ASSOC, "client ",clt->address," kicked: "
734 "rates are not compatible anymore\n");
735 acx_l_sta_list_del(adev, clt);
736 continue;
738 clt->rate_cur &= clt->rate_cfg;
739 if (!clt->rate_cur) {
740 /* current rate become invalid, choose a valid one */
741 clt->rate_cur = 1 << lowest_bit(clt->rate_cfg);
743 if (IS_ACX100(adev))
744 clt->rate_100 = acx_bitpos2rate100[highest_bit(clt->rate_cur)];
745 clt->fallback_count = clt->stepup_count = 0;
746 clt->ignore_count = 16;
748 switch (adev->mode) {
749 case ACX_MODE_2_STA:
750 if (adev->ap_client && !adev->ap_client->used) {
751 /* Owwww... we kicked our AP!! :) */
752 SET_BIT(adev->set_mask, GETSET_RESCAN);
758 /***********************************************************************
760 /* maps bits from acx111 rate to rate in Mbits */
761 static const unsigned int
762 acx111_rate_tbl[] = {
763 1000000, /* 0 */
764 2000000, /* 1 */
765 5500000, /* 2 */
766 6000000, /* 3 */
767 9000000, /* 4 */
768 11000000, /* 5 */
769 12000000, /* 6 */
770 18000000, /* 7 */
771 22000000, /* 8 */
772 24000000, /* 9 */
773 36000000, /* 10 */
774 48000000, /* 11 */
775 54000000, /* 12 */
776 500000, /* 13, should not happen */
777 500000, /* 14, should not happen */
778 500000, /* 15, should not happen */
781 /***********************************************************************
782 * acx_ioctl_set_rate
784 static int
785 acx_ioctl_set_rate(
786 struct net_device *ndev,
787 struct iw_request_info *info,
788 union iwreq_data *wrqu,
789 char *extra)
791 struct iw_param *vwrq = &wrqu->param;
792 acx_device_t *adev = ndev2adev(ndev);
793 u16 txrate_cfg = 1;
794 unsigned long flags;
795 int autorate;
796 int result = -EINVAL;
798 FN_ENTER;
799 log(L_IOCTL, "rate %d fixed 0x%X disabled 0x%X flags 0x%X\n",
800 vwrq->value, vwrq->fixed, vwrq->disabled, vwrq->flags);
802 if ((0 == vwrq->fixed) || (1 == vwrq->fixed)) {
803 int i = VEC_SIZE(acx111_rate_tbl)-1;
804 if (vwrq->value == -1)
805 /* "iwconfig rate auto" --> choose highest */
806 vwrq->value = IS_ACX100(adev) ? 22000000 : 54000000;
807 while (i >= 0) {
808 if (vwrq->value == acx111_rate_tbl[i]) {
809 txrate_cfg <<= i;
810 i = 0;
811 break;
813 i--;
815 if (i == -1) { /* no matching rate */
816 result = -EINVAL;
817 goto end;
819 } else { /* rate N, N<1000 (driver specific): we don't use this */
820 result = -EOPNOTSUPP;
821 goto end;
823 /* now: only one bit is set in txrate_cfg, corresponding to
824 ** indicated rate */
826 autorate = (vwrq->fixed == 0) && (RATE111_1 != txrate_cfg);
827 if (autorate) {
828 /* convert 00100000 -> 00111111 */
829 txrate_cfg = (txrate_cfg<<1)-1;
832 if (IS_ACX100(adev)) {
833 txrate_cfg &= RATE111_ACX100_COMPAT;
834 if (!txrate_cfg) {
835 result = -ENOTSUPP; /* rate is not supported by acx100 */
836 goto end;
840 acx_sem_lock(adev);
841 acx_lock(adev, flags);
843 adev->rate_auto = autorate;
844 adev->rate_oper = txrate_cfg;
845 adev->rate_basic = txrate_cfg;
846 /* only do that in auto mode, non-auto will be able to use
847 * one specific Tx rate only anyway */
848 if (autorate) {
849 /* only use 802.11b base rates, for standard 802.11b H/W
850 * compatibility */
851 adev->rate_basic &= RATE111_80211B_COMPAT;
853 adev->rate_bcast = 1 << lowest_bit(txrate_cfg);
854 if (IS_ACX100(adev))
855 adev->rate_bcast100 = acx_rate111to100(adev->rate_bcast);
856 acx_l_update_ratevector(adev);
857 acx_l_update_client_rates(adev, txrate_cfg);
859 /* Do/don't do tx rate fallback; beacon contents and rate */
860 SET_BIT(adev->set_mask, SET_RATE_FALLBACK|SET_TEMPLATES);
861 result = -EINPROGRESS;
863 acx_unlock(adev, flags);
864 acx_sem_unlock(adev);
865 end:
866 FN_EXIT1(result);
867 return result;
871 /***********************************************************************
872 ** acx_ioctl_get_rate
874 static int
875 acx_ioctl_get_rate(
876 struct net_device *ndev,
877 struct iw_request_info *info,
878 union iwreq_data *wrqu,
879 char *extra)
881 struct iw_param *vwrq = &wrqu->param;
882 acx_device_t *adev = ndev2adev(ndev);
883 unsigned long flags;
884 u16 rate;
886 acx_lock(adev, flags);
887 rate = adev->rate_oper;
888 if (adev->ap_client)
889 rate = adev->ap_client->rate_cur;
890 vwrq->value = acx111_rate_tbl[highest_bit(rate)];
891 vwrq->fixed = !adev->rate_auto;
892 vwrq->disabled = 0;
893 acx_unlock(adev, flags);
895 return OK;
898 static int
899 acx_ioctl_set_rts(
900 struct net_device *ndev,
901 struct iw_request_info *info,
902 union iwreq_data *wrqu,
903 char *extra)
905 struct iw_param *vwrq = &wrqu->rts;
906 acx_device_t *adev = ndev2adev(ndev);
907 int val = vwrq->value;
909 if (vwrq->disabled)
910 val = 2312;
911 if ((val < 0) || (val > 2312))
912 return -EINVAL;
914 adev->rts_threshold = val;
915 return OK;
918 static inline int
919 acx_ioctl_get_rts(
920 struct net_device *ndev,
921 struct iw_request_info *info,
922 union iwreq_data *wrqu,
923 char *extra)
925 struct iw_param *vwrq = &wrqu->rts;
926 acx_device_t *adev = ndev2adev(ndev);
928 vwrq->value = adev->rts_threshold;
929 vwrq->disabled = (vwrq->value >= 2312);
930 vwrq->fixed = 1;
931 return OK;
935 #if ACX_FRAGMENTATION
936 static int
937 acx_ioctl_set_frag(
938 struct net_device *ndev,
939 struct iw_request_info *info,
940 struct iw_param *vwrq,
941 char *extra)
943 acx_device_t *adev = ndev2adev(ndev);
944 int val = vwrq->value;
946 if (vwrq->disabled)
947 val = 32767;
948 else
949 if ((val < 256) || (val > 2347))
950 return -EINVAL;
952 adev->frag_threshold = val;
953 return OK;
956 static inline int
957 acx_ioctl_get_frag(
958 struct net_device *ndev,
959 struct iw_request_info *info,
960 union iwreq_data *wrqu,
961 char *extra)
963 struct iw_param *vwrq = &wrqu->frag;
964 acx_device_t *adev = ndev2adev(ndev);
966 vwrq->value = adev->frag_threshold;
967 vwrq->disabled = (vwrq->value >= 2347);
968 vwrq->fixed = 1;
969 return OK;
971 #endif
974 /***********************************************************************
975 ** acx_ioctl_set_encode
977 static int
978 acx_ioctl_set_encode(
979 struct net_device *ndev,
980 struct iw_request_info *info,
981 union iwreq_data *wrqu,
982 char *extra)
984 struct iw_point *dwrq = &wrqu->encoding;
985 acx_device_t *adev = ndev2adev(ndev);
986 int index;
987 int result;
989 FN_ENTER;
991 log(L_IOCTL, "set encoding flags=0x%04X, size=%d, key: %s\n",
992 dwrq->flags, dwrq->length, extra ? "set" : "No key");
994 acx_sem_lock(adev);
996 index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
998 if (dwrq->length > 0) {
999 /* if index is 0 or invalid, use default key */
1000 if ((index < 0) || (index > 3))
1001 index = (int)adev->wep_current_index;
1003 if (0 == (dwrq->flags & IW_ENCODE_NOKEY)) {
1004 if (dwrq->length > 29)
1005 dwrq->length = 29; /* restrict it */
1007 if (dwrq->length > 13) {
1008 /* 29*8 == 232, WEP256 */
1009 adev->wep_keys[index].size = 29;
1010 } else if (dwrq->length > 5) {
1011 /* 13*8 == 104bit, WEP128 */
1012 adev->wep_keys[index].size = 13;
1013 } else if (dwrq->length > 0) {
1014 /* 5*8 == 40bit, WEP64 */
1015 adev->wep_keys[index].size = 5;
1016 } else {
1017 /* disable key */
1018 adev->wep_keys[index].size = 0;
1021 memset(adev->wep_keys[index].key, 0,
1022 sizeof(adev->wep_keys[index].key));
1023 memcpy(adev->wep_keys[index].key, extra, dwrq->length);
1025 } else {
1026 /* set transmit key */
1027 if ((index >= 0) && (index <= 3))
1028 adev->wep_current_index = index;
1029 else if (0 == (dwrq->flags & IW_ENCODE_MODE)) {
1030 /* complain if we were not just setting
1031 * the key mode */
1032 result = -EINVAL;
1033 goto end_unlock;
1037 adev->wep_enabled = !(dwrq->flags & IW_ENCODE_DISABLED);
1039 if (dwrq->flags & IW_ENCODE_OPEN) {
1040 adev->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM;
1041 adev->wep_restricted = 0;
1043 } else if (dwrq->flags & IW_ENCODE_RESTRICTED) {
1044 adev->auth_alg = WLAN_AUTH_ALG_SHAREDKEY;
1045 adev->wep_restricted = 1;
1048 /* set flag to make sure the card WEP settings get updated */
1049 SET_BIT(adev->set_mask, GETSET_WEP);
1051 log(L_IOCTL, "len=%d, key at 0x%p, flags=0x%X\n",
1052 dwrq->length, extra, dwrq->flags);
1054 for (index = 0; index <= 3; index++) {
1055 if (adev->wep_keys[index].size) {
1056 log(L_IOCTL, "index=%d, size=%d, key at 0x%p\n",
1057 adev->wep_keys[index].index,
1058 (int) adev->wep_keys[index].size,
1059 adev->wep_keys[index].key);
1062 result = -EINPROGRESS;
1064 end_unlock:
1065 acx_sem_unlock(adev);
1067 FN_EXIT1(result);
1068 return result;
1072 /***********************************************************************
1073 ** acx_ioctl_get_encode
1075 static int
1076 acx_ioctl_get_encode(
1077 struct net_device *ndev,
1078 struct iw_request_info *info,
1079 union iwreq_data *wrqu,
1080 char *extra)
1082 struct iw_point *dwrq = &wrqu->encoding;
1083 acx_device_t *adev = ndev2adev(ndev);
1084 int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
1086 FN_ENTER;
1088 if (adev->wep_enabled == 0) {
1089 dwrq->flags = IW_ENCODE_DISABLED;
1090 } else {
1091 if ((index < 0) || (index > 3))
1092 index = (int)adev->wep_current_index;
1094 dwrq->flags = (adev->wep_restricted == 1) ?
1095 IW_ENCODE_RESTRICTED : IW_ENCODE_OPEN;
1096 dwrq->length = adev->wep_keys[index].size;
1098 memcpy(extra, adev->wep_keys[index].key,
1099 adev->wep_keys[index].size);
1102 /* set the current index */
1103 SET_BIT(dwrq->flags, index + 1);
1105 log(L_IOCTL, "len=%d, key=%p, flags=0x%X\n",
1106 dwrq->length, dwrq->pointer,
1107 dwrq->flags);
1109 FN_EXIT1(OK);
1110 return OK;
1114 /***********************************************************************
1116 static int
1117 acx_ioctl_set_power(
1118 struct net_device *ndev,
1119 struct iw_request_info *info,
1120 union iwreq_data *wrqu,
1121 char *extra)
1123 struct iw_param *vwrq = &wrqu->power;
1124 acx_device_t *adev = ndev2adev(ndev);
1125 int result = -EINPROGRESS;
1127 FN_ENTER;
1129 log(L_IOCTL, "set 802.11 powersave flags=0x%04X\n", vwrq->flags);
1131 acx_sem_lock(adev);
1133 if (vwrq->disabled) {
1134 CLEAR_BIT(adev->ps_wakeup_cfg, PS_CFG_ENABLE);
1135 SET_BIT(adev->set_mask, GETSET_POWER_80211);
1136 goto end;
1138 if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
1139 u16 ps_timeout = (vwrq->value * 1024) / 1000;
1141 if (ps_timeout > 255)
1142 ps_timeout = 255;
1143 log(L_IOCTL, "setting PS timeout value to %d time units "
1144 "due to %dus\n", ps_timeout, vwrq->value);
1145 adev->ps_hangover_period = ps_timeout;
1146 } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
1147 u16 ps_periods = vwrq->value / 1000000;
1149 if (ps_periods > 255)
1150 ps_periods = 255;
1151 log(L_IOCTL, "setting PS period value to %d periods "
1152 "due to %dus\n", ps_periods, vwrq->value);
1153 adev->ps_listen_interval = ps_periods;
1154 CLEAR_BIT(adev->ps_wakeup_cfg, PS_CFG_WAKEUP_MODE_MASK);
1155 SET_BIT(adev->ps_wakeup_cfg, PS_CFG_WAKEUP_EACH_ITVL);
1158 switch (vwrq->flags & IW_POWER_MODE) {
1159 /* FIXME: are we doing the right thing here? */
1160 case IW_POWER_UNICAST_R:
1161 CLEAR_BIT(adev->ps_options, PS_OPT_STILL_RCV_BCASTS);
1162 break;
1163 case IW_POWER_MULTICAST_R:
1164 SET_BIT(adev->ps_options, PS_OPT_STILL_RCV_BCASTS);
1165 break;
1166 case IW_POWER_ALL_R:
1167 SET_BIT(adev->ps_options, PS_OPT_STILL_RCV_BCASTS);
1168 break;
1169 case IW_POWER_ON:
1170 break;
1171 default:
1172 log(L_IOCTL, "unknown PS mode\n");
1173 result = -EINVAL;
1174 goto end;
1177 SET_BIT(adev->ps_wakeup_cfg, PS_CFG_ENABLE);
1178 SET_BIT(adev->set_mask, GETSET_POWER_80211);
1179 end:
1180 acx_sem_unlock(adev);
1182 FN_EXIT1(result);
1183 return result;
1187 /***********************************************************************
1189 static int
1190 acx_ioctl_get_power(
1191 struct net_device *ndev,
1192 struct iw_request_info *info,
1193 union iwreq_data *wrqu,
1194 char *extra)
1196 struct iw_param *vwrq = &wrqu->power;
1197 acx_device_t *adev = ndev2adev(ndev);
1199 FN_ENTER;
1201 log(L_IOCTL, "Get 802.11 Power Save flags = 0x%04X\n", vwrq->flags);
1202 vwrq->disabled = ((adev->ps_wakeup_cfg & PS_CFG_ENABLE) == 0);
1203 if (vwrq->disabled)
1204 goto end;
1206 if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
1207 vwrq->value = adev->ps_hangover_period * 1000 / 1024;
1208 vwrq->flags = IW_POWER_TIMEOUT;
1209 } else {
1210 vwrq->value = adev->ps_listen_interval * 1000000;
1211 vwrq->flags = IW_POWER_PERIOD|IW_POWER_RELATIVE;
1213 if (adev->ps_options & PS_OPT_STILL_RCV_BCASTS)
1214 SET_BIT(vwrq->flags, IW_POWER_ALL_R);
1215 else
1216 SET_BIT(vwrq->flags, IW_POWER_UNICAST_R);
1217 end:
1218 FN_EXIT1(OK);
1219 return OK;
1223 /***********************************************************************
1224 ** acx_ioctl_get_txpow
1226 static inline int
1227 acx_ioctl_get_txpow(
1228 struct net_device *ndev,
1229 struct iw_request_info *info,
1230 union iwreq_data *wrqu,
1231 char *extra)
1233 struct iw_param *vwrq = &wrqu->power;
1234 acx_device_t *adev = ndev2adev(ndev);
1236 FN_ENTER;
1238 vwrq->flags = IW_TXPOW_DBM;
1239 vwrq->disabled = 0;
1240 vwrq->fixed = 1;
1241 vwrq->value = adev->tx_level_dbm;
1243 log(L_IOCTL, "get txpower:%d dBm\n", adev->tx_level_dbm);
1245 FN_EXIT1(OK);
1246 return OK;
1250 /***********************************************************************
1251 ** acx_ioctl_set_txpow
1253 static int
1254 acx_ioctl_set_txpow(
1255 struct net_device *ndev,
1256 struct iw_request_info *info,
1257 union iwreq_data *wrqu,
1258 char *extra)
1260 struct iw_param *vwrq = &wrqu->power;
1261 acx_device_t *adev = ndev2adev(ndev);
1262 int result;
1264 FN_ENTER;
1266 log(L_IOCTL, "set txpower:%d, disabled:%d, flags:0x%04X\n",
1267 vwrq->value, vwrq->disabled, vwrq->flags);
1269 acx_sem_lock(adev);
1271 if (vwrq->disabled != adev->tx_disabled) {
1272 SET_BIT(adev->set_mask, GETSET_TX);
1275 adev->tx_disabled = vwrq->disabled;
1276 if (vwrq->value == -1) {
1277 if (vwrq->disabled) {
1278 adev->tx_level_dbm = 0;
1279 log(L_IOCTL, "disable radio tx\n");
1280 } else {
1281 /* adev->tx_level_auto = 1; */
1282 log(L_IOCTL, "set tx power auto (NIY)\n");
1284 } else {
1285 adev->tx_level_dbm = vwrq->value <= 20 ? vwrq->value : 20;
1286 /* adev->tx_level_auto = 0; */
1287 log(L_IOCTL, "set txpower=%d dBm\n", adev->tx_level_dbm);
1289 SET_BIT(adev->set_mask, GETSET_TXPOWER);
1291 result = -EINPROGRESS;
1293 acx_sem_unlock(adev);
1295 FN_EXIT1(result);
1296 return result;
1300 /***********************************************************************
1301 ** acx_ioctl_get_range
1303 static int
1304 acx_ioctl_get_range(
1305 struct net_device *ndev,
1306 struct iw_request_info *info,
1307 union iwreq_data *wrqu,
1308 char *extra)
1310 struct iw_point *dwrq = &wrqu->data;
1311 struct iw_range *range = (struct iw_range *)extra;
1312 acx_device_t *adev = ndev2adev(ndev);
1313 int i,n;
1315 FN_ENTER;
1317 if (!dwrq->pointer)
1318 goto end;
1320 dwrq->length = sizeof(struct iw_range);
1321 memset(range, 0, sizeof(struct iw_range));
1322 n = 0;
1323 for (i = 1; i <= 14; i++) {
1324 if (adev->reg_dom_chanmask & (1 << (i - 1))) {
1325 range->freq[n].i = i;
1326 range->freq[n].m = acx_channel_freq[i - 1] * 100000;
1327 range->freq[n].e = 1; /* units are MHz */
1328 n++;
1331 range->num_channels = n;
1332 range->num_frequency = n;
1334 range->min_rts = 0;
1335 range->max_rts = 2312;
1337 #if ACX_FRAGMENTATION
1338 range->min_frag = 256;
1339 range->max_frag = 2312;
1340 #endif
1342 range->encoding_size[0] = 5;
1343 range->encoding_size[1] = 13;
1344 range->encoding_size[2] = 29;
1345 range->num_encoding_sizes = 3;
1346 range->max_encoding_tokens = 4;
1348 range->min_pmp = 0;
1349 range->max_pmp = 5000000;
1350 range->min_pmt = 0;
1351 range->max_pmt = 65535 * 1000;
1352 range->pmp_flags = IW_POWER_PERIOD;
1353 range->pmt_flags = IW_POWER_TIMEOUT;
1354 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
1356 if (IS_ACX100(adev)) { /* ACX100 has direct radio programming - arbitrary levels, so offer a lot */
1357 for (i = 0; i <= IW_MAX_TXPOWER - 1; i++)
1358 range->txpower[i] = 20 * i / (IW_MAX_TXPOWER - 1);
1359 range->num_txpower = IW_MAX_TXPOWER;
1360 range->txpower_capa = IW_TXPOW_DBM;
1362 else {
1363 int count = min(IW_MAX_TXPOWER, (int)adev->cfgopt_power_levels.len);
1364 for (i = 0; i <= count; i++)
1365 range->txpower[i] = adev->cfgopt_power_levels.list[i];
1366 range->num_txpower = count;
1367 /* this list is given in mW */
1368 range->txpower_capa = IW_TXPOW_MWATT;
1371 range->we_version_compiled = WIRELESS_EXT;
1372 range->we_version_source = 0x9;
1374 range->retry_capa = IW_RETRY_LIMIT;
1375 range->retry_flags = IW_RETRY_LIMIT;
1376 range->min_retry = 1;
1377 range->max_retry = 255;
1379 range->r_time_flags = IW_RETRY_LIFETIME;
1380 range->min_r_time = 0;
1381 /* FIXME: lifetime ranges and orders of magnitude are strange?? */
1382 range->max_r_time = 65535;
1384 if (IS_USB(adev))
1385 range->sensitivity = 0;
1386 else if (IS_ACX111(adev))
1387 range->sensitivity = 3;
1388 else
1389 range->sensitivity = 255;
1391 for (i=0; i < adev->rate_supported_len; i++) {
1392 range->bitrate[i] = (adev->rate_supported[i] & ~0x80) * 500000;
1393 /* never happens, but keep it, to be safe: */
1394 if (range->bitrate[i] == 0)
1395 break;
1397 range->num_bitrates = i;
1399 range->max_qual.qual = 100;
1400 range->max_qual.level = 100;
1401 range->max_qual.noise = 100;
1402 /* TODO: better values */
1403 range->avg_qual.qual = 90;
1404 range->avg_qual.level = 80;
1405 range->avg_qual.noise = 2;
1407 end:
1408 FN_EXIT1(OK);
1409 return OK;
1413 /***********************************************************************
1414 ** Private functions
1417 /***********************************************************************
1418 ** acx_ioctl_get_nick
1420 static inline int
1421 acx_ioctl_get_nick(
1422 struct net_device *ndev,
1423 struct iw_request_info *info,
1424 union iwreq_data *wrqu,
1425 char *extra)
1427 struct iw_point *dwrq = &wrqu->data;
1428 acx_device_t *adev = ndev2adev(ndev);
1430 strcpy(extra, adev->nick);
1431 dwrq->length = strlen(extra) + 1;
1433 return OK;
1437 /***********************************************************************
1438 ** acx_ioctl_set_nick
1440 static int
1441 acx_ioctl_set_nick(
1442 struct net_device *ndev,
1443 struct iw_request_info *info,
1444 union iwreq_data *wrqu,
1445 char *extra)
1447 struct iw_point *dwrq = &wrqu->data;
1448 acx_device_t *adev = ndev2adev(ndev);
1449 int result;
1451 FN_ENTER;
1453 acx_sem_lock(adev);
1455 if (dwrq->length > IW_ESSID_MAX_SIZE + 1) {
1456 result = -E2BIG;
1457 goto end_unlock;
1460 /* extra includes trailing \0, so it's ok */
1461 strcpy(adev->nick, extra);
1462 result = OK;
1464 end_unlock:
1465 acx_sem_unlock(adev);
1467 FN_EXIT1(result);
1468 return result;
1472 /***********************************************************************
1473 ** acx_ioctl_get_retry
1475 static int
1476 acx_ioctl_get_retry(
1477 struct net_device *ndev,
1478 struct iw_request_info *info,
1479 union iwreq_data *wrqu,
1480 char *extra)
1482 struct iw_param *vwrq = &wrqu->retry;
1483 acx_device_t *adev = ndev2adev(ndev);
1484 unsigned int type = vwrq->flags & IW_RETRY_TYPE;
1485 unsigned int modifier = vwrq->flags & IW_RETRY_MODIFIER;
1486 int result;
1488 FN_ENTER;
1490 acx_sem_lock(adev);
1492 /* return the short retry number by default */
1493 if (type == IW_RETRY_LIFETIME) {
1494 vwrq->flags = IW_RETRY_LIFETIME;
1495 vwrq->value = adev->msdu_lifetime;
1496 } else if (modifier == IW_RETRY_MAX) {
1497 vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
1498 vwrq->value = adev->long_retry;
1499 } else {
1500 vwrq->flags = IW_RETRY_LIMIT;
1501 if (adev->long_retry != adev->short_retry)
1502 SET_BIT(vwrq->flags, IW_RETRY_MIN);
1503 vwrq->value = adev->short_retry;
1506 /* can't be disabled */
1507 vwrq->disabled = (u8)0;
1508 result = OK;
1510 acx_sem_unlock(adev);
1512 FN_EXIT1(result);
1513 return result;
1517 /***********************************************************************
1518 ** acx_ioctl_set_retry
1520 static int
1521 acx_ioctl_set_retry(
1522 struct net_device *ndev,
1523 struct iw_request_info *info,
1524 union iwreq_data *wrqu,
1525 char *extra)
1527 struct iw_param *vwrq = &wrqu->retry;
1528 acx_device_t *adev = ndev2adev(ndev);
1529 int result;
1531 FN_ENTER;
1533 if (!vwrq) {
1534 result = -EFAULT;
1535 goto end;
1537 if (vwrq->disabled) {
1538 result = -EINVAL;
1539 goto end;
1542 acx_sem_lock(adev);
1544 result = -EINVAL;
1545 if (IW_RETRY_LIMIT == (vwrq->flags & IW_RETRY_TYPE)) {
1546 printk("old retry limits: short %d long %d\n",
1547 adev->short_retry, adev->long_retry);
1548 if (vwrq->flags & IW_RETRY_MAX) {
1549 adev->long_retry = vwrq->value;
1550 } else if (vwrq->flags & IW_RETRY_MIN) {
1551 adev->short_retry = vwrq->value;
1552 } else {
1553 /* no modifier: set both */
1554 adev->long_retry = vwrq->value;
1555 adev->short_retry = vwrq->value;
1557 printk("new retry limits: short %d long %d\n",
1558 adev->short_retry, adev->long_retry);
1559 SET_BIT(adev->set_mask, GETSET_RETRY);
1560 result = -EINPROGRESS;
1562 else if (vwrq->flags & IW_RETRY_LIFETIME) {
1563 adev->msdu_lifetime = vwrq->value;
1564 printk("new MSDU lifetime: %d\n", adev->msdu_lifetime);
1565 SET_BIT(adev->set_mask, SET_MSDU_LIFETIME);
1566 result = -EINPROGRESS;
1569 acx_sem_unlock(adev);
1570 end:
1571 FN_EXIT1(result);
1572 return result;
1576 /************************ private ioctls ******************************/
1579 /***********************************************************************
1580 ** acx_ioctl_set_debug
1582 #if ACX_DEBUG
1583 static int
1584 acx_ioctl_set_debug(
1585 struct net_device *ndev,
1586 struct iw_request_info *info,
1587 union iwreq_data *wrqu,
1588 char *extra)
1590 unsigned int debug_new = *((unsigned int *)extra);
1591 int result = -EINVAL;
1593 log(L_ANY, "setting debug from %04X to %04X\n", acx_debug, debug_new);
1594 acx_debug = debug_new;
1596 result = OK;
1597 return result;
1600 #endif
1603 /***********************************************************************
1604 ** acx_ioctl_list_reg_domain
1606 static int
1607 acx_ioctl_list_reg_domain(
1608 struct net_device *ndev,
1609 struct iw_request_info *info,
1610 union iwreq_data *wrqu,
1611 char *extra)
1613 int i = 1;
1614 const char * const *entry = acx_reg_domain_strings;
1616 printk("dom# chan# domain/country\n");
1617 while (*entry)
1618 printk("%4d %s\n", i++, *entry++);
1619 return OK;
1623 /***********************************************************************
1624 ** acx_ioctl_set_reg_domain
1626 static int
1627 acx_ioctl_set_reg_domain(
1628 struct net_device *ndev,
1629 struct iw_request_info *info,
1630 union iwreq_data *wrqu,
1631 char *extra)
1633 acx_device_t *adev = ndev2adev(ndev);
1634 int result;
1636 FN_ENTER;
1638 if ((*extra < 1) || ((size_t)*extra > acx_reg_domain_ids_len)) {
1639 result = -EINVAL;
1640 goto end;
1643 acx_sem_lock(adev);
1645 adev->reg_dom_id = acx_reg_domain_ids[*extra - 1];
1646 SET_BIT(adev->set_mask, GETSET_REG_DOMAIN);
1648 result = -EINPROGRESS;
1650 acx_sem_unlock(adev);
1651 end:
1652 FN_EXIT1(result);
1653 return result;
1657 /***********************************************************************
1658 ** acx_ioctl_get_reg_domain
1660 static int
1661 acx_ioctl_get_reg_domain(
1662 struct net_device *ndev,
1663 struct iw_request_info *info,
1664 union iwreq_data *wrqu,
1665 char *extra)
1667 acx_device_t *adev = ndev2adev(ndev);
1668 int dom,i;
1670 /* no locking */
1671 dom = adev->reg_dom_id;
1673 for (i = 1; i <= acx_reg_domain_ids_len; i++) {
1674 if (acx_reg_domain_ids[i-1] == dom) {
1675 log(L_IOCTL, "regulatory domain is currently set "
1676 "to %d (0x%X): %s\n", i, dom,
1677 acx_reg_domain_strings[i-1]);
1678 *extra = i;
1679 break;
1683 return OK;
1687 /***********************************************************************
1688 ** acx_ioctl_set_short_preamble
1690 static const char * const
1691 preamble_modes[] = {
1692 "off",
1693 "on",
1694 "auto (peer capability dependent)",
1695 "unknown mode, error"
1698 static int
1699 acx_ioctl_set_short_preamble(
1700 struct net_device *ndev,
1701 struct iw_request_info *info,
1702 union iwreq_data *wrqu,
1703 char *extra)
1705 acx_device_t *adev = ndev2adev(ndev);
1706 int i;
1707 int result;
1709 FN_ENTER;
1711 if ((unsigned char)*extra > 2) {
1712 result = -EINVAL;
1713 goto end;
1716 acx_sem_lock(adev);
1718 adev->preamble_mode = (u8)*extra;
1719 switch (adev->preamble_mode) {
1720 case 0: /* long */
1721 adev->preamble_cur = 0;
1722 break;
1723 case 1:
1724 /* short, kick incapable peers */
1725 adev->preamble_cur = 1;
1726 for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
1727 client_t *clt = &adev->sta_list[i];
1728 if (!clt->used) continue;
1729 if (!(clt->cap_info & WF_MGMT_CAP_SHORT)) {
1730 clt->used = CLIENT_EMPTY_SLOT_0;
1733 switch (adev->mode) {
1734 case ACX_MODE_2_STA:
1735 if (adev->ap_client && !adev->ap_client->used) {
1736 /* We kicked our AP :) */
1737 SET_BIT(adev->set_mask, GETSET_RESCAN);
1740 break;
1741 case 2: /* auto. short only if all peers are short-capable */
1742 adev->preamble_cur = 1;
1743 for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
1744 client_t *clt = &adev->sta_list[i];
1745 if (!clt->used) continue;
1746 if (!(clt->cap_info & WF_MGMT_CAP_SHORT)) {
1747 adev->preamble_cur = 0;
1748 break;
1751 break;
1753 printk("new short preamble setting: configured %s, active %s\n",
1754 preamble_modes[adev->preamble_mode],
1755 preamble_modes[adev->preamble_cur]);
1756 result = OK;
1758 acx_sem_unlock(adev);
1759 end:
1760 FN_EXIT1(result);
1761 return result;
1765 /***********************************************************************
1766 ** acx_ioctl_get_short_preamble
1768 static int
1769 acx_ioctl_get_short_preamble(
1770 struct net_device *ndev,
1771 struct iw_request_info *info,
1772 union iwreq_data *wrqu,
1773 char *extra)
1775 acx_device_t *adev = ndev2adev(ndev);
1777 acx_sem_lock(adev);
1779 printk("current short preamble setting: configured %s, active %s\n",
1780 preamble_modes[adev->preamble_mode],
1781 preamble_modes[adev->preamble_cur]);
1783 *extra = (char)adev->preamble_mode;
1785 acx_sem_unlock(adev);
1787 return OK;
1791 /***********************************************************************
1792 ** acx_ioctl_set_antenna
1794 ** TX and RX antenna can be set separately but this function good
1795 ** for testing 0-4 bits
1797 static int
1798 acx_ioctl_set_antenna(
1799 struct net_device *ndev,
1800 struct iw_request_info *info,
1801 union iwreq_data *wrqu,
1802 char *extra)
1804 acx_device_t *adev = ndev2adev(ndev);
1806 acx_sem_lock(adev);
1808 printk("old antenna value: 0x%02X (COMBINED bit mask)\n"
1809 "Rx antenna selection:\n"
1810 "0x00 ant. 1\n"
1811 "0x40 ant. 2\n"
1812 "0x80 full diversity\n"
1813 "0xc0 partial diversity\n"
1814 "0x0f dwell time mask (in units of us)\n"
1815 "Tx antenna selection:\n"
1816 "0x00 ant. 2\n" /* yep, those ARE reversed! */
1817 "0x20 ant. 1\n"
1818 "new antenna value: 0x%02X\n",
1819 adev->antenna, (u8)*extra);
1821 adev->antenna = (u8)*extra;
1822 SET_BIT(adev->set_mask, GETSET_ANTENNA);
1824 acx_sem_unlock(adev);
1826 return -EINPROGRESS;
1830 /***********************************************************************
1831 ** acx_ioctl_get_antenna
1833 static int
1834 acx_ioctl_get_antenna(
1835 struct net_device *ndev,
1836 struct iw_request_info *info,
1837 union iwreq_data *wrqu,
1838 char *extra)
1840 acx_device_t *adev = ndev2adev(ndev);
1842 /* no locking. it's pointless to lock a single load */
1843 printk("current antenna value: 0x%02X (COMBINED bit mask)\n"
1844 "Rx antenna selection:\n"
1845 "0x00 ant. 1\n"
1846 "0x40 ant. 2\n"
1847 "0x80 full diversity\n"
1848 "0xc0 partial diversity\n"
1849 "Tx antenna selection:\n"
1850 "0x00 ant. 2\n" /* yep, those ARE reversed! */
1851 "0x20 ant. 1\n", adev->antenna);
1853 return 0;
1857 /***********************************************************************
1858 ** acx_ioctl_set_rx_antenna
1860 ** 0 = antenna1; 1 = antenna2; 2 = full diversity; 3 = partial diversity
1861 ** Could anybody test which antenna is the external one?
1863 static int
1864 acx_ioctl_set_rx_antenna(
1865 struct net_device *ndev,
1866 struct iw_request_info *info,
1867 union iwreq_data *wrqu,
1868 char *extra)
1870 acx_device_t *adev = ndev2adev(ndev);
1871 int result;
1873 FN_ENTER;
1875 if (*extra > 3) {
1876 result = -EINVAL;
1877 goto end;
1880 printk("old antenna value: 0x%02X\n", adev->antenna);
1882 acx_sem_lock(adev);
1884 adev->antenna &= 0x3f;
1885 SET_BIT(adev->antenna, (*extra << 6));
1886 SET_BIT(adev->set_mask, GETSET_ANTENNA);
1887 printk("new antenna value: 0x%02X\n", adev->antenna);
1888 result = -EINPROGRESS;
1890 acx_sem_unlock(adev);
1891 end:
1892 FN_EXIT1(result);
1893 return result;
1897 /***********************************************************************
1898 ** acx_ioctl_set_tx_antenna
1900 ** Arguments: 0 == antenna2; 1 == antenna1;
1901 ** Could anybody test which antenna is the external one?
1903 static int
1904 acx_ioctl_set_tx_antenna(
1905 struct net_device *ndev,
1906 struct iw_request_info *info,
1907 union iwreq_data *wrqu,
1908 char *extra)
1910 acx_device_t *adev = ndev2adev(ndev);
1911 int result;
1913 FN_ENTER;
1915 if (*extra > 1) {
1916 result = -EINVAL;
1917 goto end;
1920 printk("old antenna value: 0x%02X\n", adev->antenna);
1922 acx_sem_lock(adev);
1924 adev->antenna &= ~0x30;
1925 SET_BIT(adev->antenna, ((*extra & 0x01) << 5));
1926 SET_BIT(adev->set_mask, GETSET_ANTENNA);
1927 printk("new antenna value: 0x%02X\n", adev->antenna);
1928 result = -EINPROGRESS;
1930 acx_sem_unlock(adev);
1931 end:
1932 FN_EXIT1(result);
1933 return result;
1937 /***********************************************************************
1938 ** acx_ioctl_wlansniff
1940 ** can we just remove this in favor of monitor mode? --vda
1942 static int
1943 acx_ioctl_wlansniff(
1944 struct net_device *ndev,
1945 struct iw_request_info *info,
1946 union iwreq_data *wrqu,
1947 char *extra)
1949 acx_device_t *adev = ndev2adev(ndev);
1950 unsigned int *params = (unsigned int*)extra;
1951 unsigned int enable = (unsigned int)(params[0] > 0);
1952 int result;
1954 FN_ENTER;
1956 acx_sem_lock(adev);
1958 /* not using printk() here, since it distorts kismet display
1959 * when printk messages activated */
1960 log(L_IOCTL, "setting monitor to: 0x%02X\n", params[0]);
1962 switch (params[0]) {
1963 case 0:
1964 /* no monitor mode. hmm, should we simply ignore it
1965 * or go back to enabling adev->netdev->type ARPHRD_ETHER? */
1966 break;
1967 case 1:
1968 adev->monitor_type = ARPHRD_IEEE80211_PRISM;
1969 break;
1970 case 2:
1971 adev->monitor_type = ARPHRD_IEEE80211;
1972 break;
1975 if (params[0]) {
1976 adev->mode = ACX_MODE_MONITOR;
1977 SET_BIT(adev->set_mask, GETSET_MODE);
1980 if (enable) {
1981 adev->channel = params[1];
1982 SET_BIT(adev->set_mask, GETSET_RX);
1984 result = -EINPROGRESS;
1986 acx_sem_unlock(adev);
1988 FN_EXIT1(result);
1989 return result;
1993 /***********************************************************************
1994 ** acx_ioctl_unknown11
1995 ** FIXME: looks like some sort of "iwpriv kick_sta MAC" but it's broken
1997 static int
1998 acx_ioctl_unknown11(
1999 struct net_device *ndev,
2000 struct iw_request_info *info,
2001 union iwreq_data *wrqu,
2002 char *extra)
2004 #ifdef BROKEN
2005 struct iw_param *vwrq = &wrqu->param;
2006 acx_device_t *adev = ndev2adev(ndev);
2007 unsigned long flags;
2008 client_t client;
2009 int result;
2011 acx_sem_lock(adev);
2012 acx_lock(adev, flags);
2014 acx_l_transmit_disassoc(adev, &client);
2015 result = OK;
2017 acx_unlock(adev, flags);
2018 acx_sem_unlock(adev);
2020 return result;
2021 #endif
2022 return -EINVAL;
2026 /***********************************************************************
2027 ** debug helper function to be able to debug various issues relatively easily
2029 static int
2030 acx_ioctl_dbg_set_masks(
2031 struct net_device *ndev,
2032 struct iw_request_info *info,
2033 union iwreq_data *wrqu,
2034 char *extra)
2036 acx_device_t *adev = ndev2adev(ndev);
2037 const unsigned int *params = (unsigned int*)extra;
2038 int result;
2040 acx_sem_lock(adev);
2042 log(L_IOCTL, "setting flags in settings mask: "
2043 "get_mask %08X set_mask %08X\n"
2044 "before: get_mask %08X set_mask %08X\n",
2045 params[0], params[1],
2046 adev->get_mask, adev->set_mask);
2047 SET_BIT(adev->get_mask, params[0]);
2048 SET_BIT(adev->set_mask, params[1]);
2049 log(L_IOCTL, "after: get_mask %08X set_mask %08X\n",
2050 adev->get_mask, adev->set_mask);
2051 result = -EINPROGRESS; /* immediately call commit handler */
2053 acx_sem_unlock(adev);
2055 return result;
2059 /***********************************************************************
2060 * acx_ioctl_set_rates
2062 * This ioctl takes string parameter. Examples:
2063 * iwpriv wlan0 SetRates "1,2"
2064 * use 1 and 2 Mbit rates, both are in basic rate set
2065 * iwpriv wlan0 SetRates "1,2 5,11"
2066 * use 1,2,5.5,11 Mbit rates. 1 and 2 are basic
2067 * iwpriv wlan0 SetRates "1,2 5c,11c"
2068 * same ('c' means 'CCK modulation' and it is a default for 5 and 11)
2069 * iwpriv wlan0 SetRates "1,2 5p,11p"
2070 * use 1,2,5.5,11 Mbit, 1,2 are basic. 5 and 11 are using PBCC
2071 * iwpriv wlan0 SetRates "1,2,5,11 22p"
2072 * use 1,2,5.5,11,22 Mbit. 1,2,5.5 and 11 are basic. 22 is using PBCC
2073 * (this is the maximum acx100 can do (modulo x4 mode))
2074 * iwpriv wlan0 SetRates "1,2,5,11 22"
2075 * same. 802.11 defines only PBCC modulation
2076 * for 22 and 33 Mbit rates, so there is no ambiguity
2077 * iwpriv wlan0 SetRates "1,2,5,11 6o,9o,12o,18o,24o,36o,48o,54o"
2078 * 1,2,5.5 and 11 are basic. 11g OFDM rates are enabled but
2079 * they are not in basic rate set. 22 Mbit is disabled.
2080 * iwpriv wlan0 SetRates "1,2,5,11 6,9,12,18,24,36,48,54"
2081 * same. OFDM is default for 11g rates except 22 and 33 Mbit,
2082 * thus 'o' is optional
2083 * iwpriv wlan0 SetRates "1,2,5,11 6d,9d,12d,18d,24d,36d,48d,54d"
2084 * 1,2,5.5 and 11 are basic. 11g CCK-OFDM rates are enabled
2085 * (acx111 does not support CCK-OFDM, driver will reject this cmd)
2086 * iwpriv wlan0 SetRates "6,9,12 18,24,36,48,54"
2087 * 6,9,12 are basic, rest of 11g rates is enabled. Using OFDM
2089 #include "setrate.c"
2091 /* disallow: 33Mbit (unsupported by hw) */
2092 /* disallow: CCKOFDM (unsupported by hw) */
2093 static int
2094 acx111_supported(int mbit, int modulation, void *opaque)
2096 if (mbit==33) return -ENOTSUPP;
2097 if (modulation==DOT11_MOD_CCKOFDM) return -ENOTSUPP;
2098 return OK;
2101 static const u16
2102 acx111mask[] = {
2103 [DOT11_RATE_1 ] = RATE111_1 ,
2104 [DOT11_RATE_2 ] = RATE111_2 ,
2105 [DOT11_RATE_5 ] = RATE111_5 ,
2106 [DOT11_RATE_11] = RATE111_11,
2107 [DOT11_RATE_22] = RATE111_22,
2108 /* [DOT11_RATE_33] = */
2109 [DOT11_RATE_6 ] = RATE111_6 ,
2110 [DOT11_RATE_9 ] = RATE111_9 ,
2111 [DOT11_RATE_12] = RATE111_12,
2112 [DOT11_RATE_18] = RATE111_18,
2113 [DOT11_RATE_24] = RATE111_24,
2114 [DOT11_RATE_36] = RATE111_36,
2115 [DOT11_RATE_48] = RATE111_48,
2116 [DOT11_RATE_54] = RATE111_54,
2119 static u32
2120 acx111_gen_mask(int mbit, int modulation, void *opaque)
2122 /* lower 16 bits show selected 1, 2, CCK and OFDM rates */
2123 /* upper 16 bits show selected PBCC rates */
2124 u32 m = acx111mask[rate_mbit2enum(mbit)];
2125 if (modulation==DOT11_MOD_PBCC)
2126 return m<<16;
2127 return m;
2130 static int
2131 verify_rate(u32 rate, int chip_type)
2133 /* never happens. be paranoid */
2134 if (!rate) return -EINVAL;
2136 /* disallow: mixing PBCC and CCK at 5 and 11Mbit
2137 ** (can be supported, but needs complicated handling in tx code) */
2138 if (( rate & ((RATE111_11+RATE111_5)<<16) )
2139 && ( rate & (RATE111_11+RATE111_5) )
2141 return -ENOTSUPP;
2143 if (CHIPTYPE_ACX100 == chip_type) {
2144 if ( rate & ~(RATE111_ACX100_COMPAT+(RATE111_ACX100_COMPAT<<16)) )
2145 return -ENOTSUPP;
2147 return 0;
2150 static int
2151 acx_ioctl_set_rates(struct net_device *ndev,
2152 struct iw_request_info *info,
2153 union iwreq_data *wrqu,
2154 char *extra)
2156 acx_device_t *adev = ndev2adev(ndev);
2157 unsigned long flags;
2158 int result;
2159 u32 brate = 0, orate = 0; /* basic, operational rate set */
2161 FN_ENTER;
2163 log(L_IOCTL, "set_rates %s\n", extra);
2164 result = fill_ratemasks(extra, &brate, &orate,
2165 acx111_supported, acx111_gen_mask, 0);
2166 if (result) goto end;
2167 SET_BIT(orate, brate);
2168 log(L_IOCTL, "brate %08X orate %08X\n", brate, orate);
2170 result = verify_rate(brate, adev->chip_type);
2171 if (result) goto end;
2172 result = verify_rate(orate, adev->chip_type);
2173 if (result) goto end;
2175 acx_sem_lock(adev);
2176 acx_lock(adev, flags);
2178 adev->rate_basic = brate;
2179 adev->rate_oper = orate;
2180 /* TODO: ideally, we shall monitor highest basic rate
2181 ** which was successfully sent to every peer
2182 ** (say, last we checked, everybody could hear 5.5 Mbits)
2183 ** and use that for bcasts when we want to reach all peers.
2184 ** For beacons, we probably shall use lowest basic rate
2185 ** because we want to reach all *potential* new peers too */
2186 adev->rate_bcast = 1 << lowest_bit(brate);
2187 if (IS_ACX100(adev))
2188 adev->rate_bcast100 = acx_rate111to100(adev->rate_bcast);
2189 adev->rate_auto = !has_only_one_bit(orate);
2190 acx_l_update_client_rates(adev, orate);
2191 /* TODO: get rid of ratevector, build it only when needed */
2192 acx_l_update_ratevector(adev);
2194 /* Do/don't do tx rate fallback; beacon contents and rate */
2195 SET_BIT(adev->set_mask, SET_RATE_FALLBACK|SET_TEMPLATES);
2196 result = -EINPROGRESS;
2198 acx_unlock(adev, flags);
2199 acx_sem_unlock(adev);
2200 end:
2201 FN_EXIT1(result);
2202 return result;
2206 /***********************************************************************
2207 ** acx_ioctl_get_phy_chan_busy_percentage
2209 static int
2210 acx_ioctl_get_phy_chan_busy_percentage(
2211 struct net_device *ndev,
2212 struct iw_request_info *info,
2213 union iwreq_data *wrqu,
2214 char *extra)
2216 acx_device_t *adev = ndev2adev(ndev);
2217 struct {
2218 u16 type;
2219 u16 len;
2220 u32 busytime;
2221 u32 totaltime;
2222 } ACX_PACKED usage;
2223 int result;
2225 acx_sem_lock(adev);
2227 if (OK != acx_s_interrogate(adev, &usage, ACX1xx_IE_MEDIUM_USAGE)) {
2228 result = NOT_OK;
2229 goto end_unlock;
2232 usage.busytime = le32_to_cpu(usage.busytime);
2233 usage.totaltime = le32_to_cpu(usage.totaltime);
2234 printk("%s: average busy percentage since last invocation: %d%% "
2235 "(%u of %u microseconds)\n",
2236 ndev->name,
2237 usage.busytime / ((usage.totaltime / 100) + 1),
2238 usage.busytime, usage.totaltime);
2240 result = OK;
2242 end_unlock:
2243 acx_sem_unlock(adev);
2245 return result;
2249 /***********************************************************************
2250 ** acx_ioctl_set_ed_threshold
2252 static inline int
2253 acx_ioctl_set_ed_threshold(
2254 struct net_device *ndev,
2255 struct iw_request_info *info,
2256 union iwreq_data *wrqu,
2257 char *extra)
2259 acx_device_t *adev = ndev2adev(ndev);
2261 acx_sem_lock(adev);
2263 printk("old ED threshold value: %d\n", adev->ed_threshold);
2264 adev->ed_threshold = (unsigned char)*extra;
2265 printk("new ED threshold value: %d\n", (unsigned char)*extra);
2266 SET_BIT(adev->set_mask, GETSET_ED_THRESH);
2268 acx_sem_unlock(adev);
2270 return -EINPROGRESS;
2274 /***********************************************************************
2275 ** acx_ioctl_set_cca
2277 static inline int
2278 acx_ioctl_set_cca(
2279 struct net_device *ndev,
2280 struct iw_request_info *info,
2281 union iwreq_data *wrqu,
2282 char *extra)
2284 acx_device_t *adev = ndev2adev(ndev);
2285 int result;
2287 acx_sem_lock(adev);
2289 printk("old CCA value: 0x%02X\n", adev->cca);
2290 adev->cca = (unsigned char)*extra;
2291 printk("new CCA value: 0x%02X\n", (unsigned char)*extra);
2292 SET_BIT(adev->set_mask, GETSET_CCA);
2293 result = -EINPROGRESS;
2295 acx_sem_unlock(adev);
2297 return result;
2301 /***********************************************************************
2303 static const char * const
2304 scan_modes[] = { "active", "passive", "background" };
2306 static void
2307 acx_print_scan_params(acx_device_t *adev, const char* head)
2309 printk("%s: %smode %d (%s), min chan time %dTU, "
2310 "max chan time %dTU, max scan rate byte: %d\n",
2311 adev->ndev->name, head,
2312 adev->scan_mode, scan_modes[adev->scan_mode],
2313 adev->scan_probe_delay, adev->scan_duration, adev->scan_rate);
2316 static int
2317 acx_ioctl_set_scan_params(
2318 struct net_device *ndev,
2319 struct iw_request_info *info,
2320 union iwreq_data *wrqu,
2321 char *extra)
2323 acx_device_t *adev = ndev2adev(ndev);
2324 int result;
2325 const int *params = (int *)extra;
2327 acx_sem_lock(adev);
2329 acx_print_scan_params(adev, "old scan parameters: ");
2330 if ((params[0] != -1) && (params[0] >= 0) && (params[0] <= 2))
2331 adev->scan_mode = params[0];
2332 if (params[1] != -1)
2333 adev->scan_probe_delay = params[1];
2334 if (params[2] != -1)
2335 adev->scan_duration = params[2];
2336 if ((params[3] != -1) && (params[3] <= 255))
2337 adev->scan_rate = params[3];
2338 acx_print_scan_params(adev, "new scan parameters: ");
2339 SET_BIT(adev->set_mask, GETSET_RESCAN);
2340 result = -EINPROGRESS;
2342 acx_sem_unlock(adev);
2344 return result;
2347 static int
2348 acx_ioctl_get_scan_params(
2349 struct net_device *ndev,
2350 struct iw_request_info *info,
2351 union iwreq_data *wrqu,
2352 char *extra)
2354 acx_device_t *adev = ndev2adev(ndev);
2355 int result;
2356 int *params = (int *)extra;
2358 acx_sem_lock(adev);
2360 acx_print_scan_params(adev, "current scan parameters: ");
2361 params[0] = adev->scan_mode;
2362 params[1] = adev->scan_probe_delay;
2363 params[2] = adev->scan_duration;
2364 params[3] = adev->scan_rate;
2365 result = OK;
2367 acx_sem_unlock(adev);
2369 return result;
2373 /***********************************************************************
2375 static int
2376 acx100_ioctl_set_led_power(
2377 struct net_device *ndev,
2378 struct iw_request_info *info,
2379 union iwreq_data *wrqu,
2380 char *extra)
2382 static const char * const led_modes[] = { "off", "on", "LinkQuality" };
2384 acx_device_t *adev = ndev2adev(ndev);
2385 int result;
2387 acx_sem_lock(adev);
2389 printk("%s: power LED status: old %d (%s), ",
2390 ndev->name,
2391 adev->led_power,
2392 led_modes[adev->led_power]);
2393 adev->led_power = extra[0];
2394 if (adev->led_power > 2) adev->led_power = 2;
2395 printk("new %d (%s)\n",
2396 adev->led_power,
2397 led_modes[adev->led_power]);
2399 if (adev->led_power == 2) {
2400 printk("%s: max link quality setting: old %d, ",
2401 ndev->name, adev->brange_max_quality);
2402 if (extra[1])
2403 adev->brange_max_quality = extra[1];
2404 printk("new %d\n", adev->brange_max_quality);
2407 SET_BIT(adev->set_mask, GETSET_LED_POWER);
2409 result = -EINPROGRESS;
2411 acx_sem_unlock(adev);
2413 return result;
2417 /***********************************************************************
2419 static inline int
2420 acx100_ioctl_get_led_power(
2421 struct net_device *ndev,
2422 struct iw_request_info *info,
2423 union iwreq_data *wrqu,
2424 char *extra)
2426 acx_device_t *adev = ndev2adev(ndev);
2428 acx_sem_lock(adev);
2430 extra[0] = adev->led_power;
2431 if (adev->led_power == 2)
2432 extra[1] = adev->brange_max_quality;
2433 else
2434 extra[1] = -1;
2436 acx_sem_unlock(adev);
2438 return OK;
2442 /***********************************************************************
2444 static int
2445 acx111_ioctl_info(
2446 struct net_device *ndev,
2447 struct iw_request_info *info,
2448 union iwreq_data *wrqu,
2449 char *extra)
2451 struct iw_param *vwrq = &wrqu->param;
2452 if (!IS_PCI(ndev2adev(ndev)))
2453 return OK;
2454 return acx111pci_ioctl_info(ndev, info, vwrq, extra);
2458 /***********************************************************************
2460 static int
2461 acx100_ioctl_set_phy_amp_bias(
2462 struct net_device *ndev,
2463 struct iw_request_info *info,
2464 union iwreq_data *wrqu,
2465 char *extra)
2467 struct iw_param *vwrq = &wrqu->param;
2468 if (IS_USB(ndev2adev(ndev))) {
2469 printk("acx: set_phy_amp_bias() is not supported on USB\n");
2470 return OK;
2472 #ifdef CONFIG_ACX_MEM
2473 return acx100mem_ioctl_set_phy_amp_bias(ndev, info, vwrq, extra);
2474 #else
2475 return acx100pci_ioctl_set_phy_amp_bias(ndev, info, vwrq, extra);
2476 #endif
2480 /***********************************************************************
2482 static const iw_handler acx_ioctl_handler[] =
2484 acx_ioctl_commit, /* SIOCSIWCOMMIT */
2485 acx_ioctl_get_name, /* SIOCGIWNAME */
2486 NULL, /* SIOCSIWNWID */
2487 NULL, /* SIOCGIWNWID */
2488 acx_ioctl_set_freq, /* SIOCSIWFREQ */
2489 acx_ioctl_get_freq, /* SIOCGIWFREQ */
2490 acx_ioctl_set_mode, /* SIOCSIWMODE */
2491 acx_ioctl_get_mode, /* SIOCGIWMODE */
2492 acx_ioctl_set_sens, /* SIOCSIWSENS */
2493 acx_ioctl_get_sens, /* SIOCGIWSENS */
2494 NULL, /* SIOCSIWRANGE */
2495 acx_ioctl_get_range, /* SIOCGIWRANGE */
2496 NULL, /* SIOCSIWPRIV */
2497 NULL, /* SIOCGIWPRIV */
2498 NULL, /* SIOCSIWSTATS */
2499 NULL, /* SIOCGIWSTATS */
2500 #if IW_HANDLER_VERSION > 4
2501 iw_handler_set_spy, /* SIOCSIWSPY */
2502 iw_handler_get_spy, /* SIOCGIWSPY */
2503 iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
2504 iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
2505 #else /* IW_HANDLER_VERSION > 4 */
2506 #ifdef WIRELESS_SPY
2507 NULL /* acx_ioctl_set_spy FIXME */, /* SIOCSIWSPY */
2508 NULL /* acx_ioctl_get_spy */, /* SIOCGIWSPY */
2509 #else /* WSPY */
2510 NULL, /* SIOCSIWSPY */
2511 NULL, /* SIOCGIWSPY */
2512 #endif /* WSPY */
2513 NULL, /* [nothing] */
2514 NULL, /* [nothing] */
2515 #endif /* IW_HANDLER_VERSION > 4 */
2516 acx_ioctl_set_ap, /* SIOCSIWAP */
2517 acx_ioctl_get_ap, /* SIOCGIWAP */
2518 NULL, /* [nothing] */
2519 acx_ioctl_get_aplist, /* SIOCGIWAPLIST */
2520 acx_ioctl_set_scan, /* SIOCSIWSCAN */
2521 acx_ioctl_get_scan, /* SIOCGIWSCAN */
2522 acx_ioctl_set_essid, /* SIOCSIWESSID */
2523 acx_ioctl_get_essid, /* SIOCGIWESSID */
2524 acx_ioctl_set_nick, /* SIOCSIWNICKN */
2525 acx_ioctl_get_nick, /* SIOCGIWNICKN */
2526 NULL, /* [nothing] */
2527 NULL, /* [nothing] */
2528 acx_ioctl_set_rate, /* SIOCSIWRATE */
2529 acx_ioctl_get_rate, /* SIOCGIWRATE */
2530 acx_ioctl_set_rts, /* SIOCSIWRTS */
2531 acx_ioctl_get_rts, /* SIOCGIWRTS */
2532 #if ACX_FRAGMENTATION
2533 acx_ioctl_set_frag, /* SIOCSIWFRAG */
2534 acx_ioctl_get_frag, /* SIOCGIWFRAG */
2535 #else
2536 NULL, /* SIOCSIWFRAG */
2537 NULL, /* SIOCGIWFRAG */
2538 #endif
2539 acx_ioctl_set_txpow, /* SIOCSIWTXPOW */
2540 acx_ioctl_get_txpow, /* SIOCGIWTXPOW */
2541 acx_ioctl_set_retry, /* SIOCSIWRETRY */
2542 acx_ioctl_get_retry, /* SIOCGIWRETRY */
2543 acx_ioctl_set_encode, /* SIOCSIWENCODE */
2544 acx_ioctl_get_encode, /* SIOCGIWENCODE */
2545 acx_ioctl_set_power, /* SIOCSIWPOWER */
2546 acx_ioctl_get_power, /* SIOCGIWPOWER */
2550 /***********************************************************************
2553 /* if you plan to reorder something, make sure to reorder all other places
2554 * accordingly! */
2555 /* SET/GET convention: SETs must have even position, GETs odd */
2556 #define ACX100_IOCTL SIOCIWFIRSTPRIV
2557 enum {
2558 ACX100_IOCTL_DEBUG = ACX100_IOCTL,
2559 ACX100_IOCTL_GET__________UNUSED1,
2560 ACX100_IOCTL_SET_PLED,
2561 ACX100_IOCTL_GET_PLED,
2562 ACX100_IOCTL_SET_RATES,
2563 ACX100_IOCTL_LIST_DOM,
2564 ACX100_IOCTL_SET_DOM,
2565 ACX100_IOCTL_GET_DOM,
2566 ACX100_IOCTL_SET_SCAN_PARAMS,
2567 ACX100_IOCTL_GET_SCAN_PARAMS,
2568 ACX100_IOCTL_SET_PREAMB,
2569 ACX100_IOCTL_GET_PREAMB,
2570 ACX100_IOCTL_SET_ANT,
2571 ACX100_IOCTL_GET_ANT,
2572 ACX100_IOCTL_RX_ANT,
2573 ACX100_IOCTL_TX_ANT,
2574 ACX100_IOCTL_SET_PHY_AMP_BIAS,
2575 ACX100_IOCTL_GET_PHY_CHAN_BUSY,
2576 ACX100_IOCTL_SET_ED,
2577 ACX100_IOCTL_GET__________UNUSED3,
2578 ACX100_IOCTL_SET_CCA,
2579 ACX100_IOCTL_GET__________UNUSED4,
2580 ACX100_IOCTL_MONITOR,
2581 ACX100_IOCTL_TEST,
2582 ACX100_IOCTL_DBG_SET_MASKS,
2583 ACX111_IOCTL_INFO,
2584 ACX100_IOCTL_DBG_SET_IO,
2585 ACX100_IOCTL_DBG_GET_IO
2589 static const iw_handler acx_ioctl_private_handler[] =
2591 #if ACX_DEBUG
2592 [ACX100_IOCTL_DEBUG - ACX100_IOCTL] = acx_ioctl_set_debug,
2593 #endif
2594 [ACX100_IOCTL_SET_PLED - ACX100_IOCTL] = acx100_ioctl_set_led_power,
2595 [ACX100_IOCTL_GET_PLED - ACX100_IOCTL] = acx100_ioctl_get_led_power,
2596 [ACX100_IOCTL_SET_RATES - ACX100_IOCTL] = acx_ioctl_set_rates,
2597 [ACX100_IOCTL_LIST_DOM - ACX100_IOCTL] = acx_ioctl_list_reg_domain,
2598 [ACX100_IOCTL_SET_DOM - ACX100_IOCTL] = acx_ioctl_set_reg_domain,
2599 [ACX100_IOCTL_GET_DOM - ACX100_IOCTL] = acx_ioctl_get_reg_domain,
2600 [ACX100_IOCTL_SET_SCAN_PARAMS - ACX100_IOCTL] = acx_ioctl_set_scan_params,
2601 [ACX100_IOCTL_GET_SCAN_PARAMS - ACX100_IOCTL] = acx_ioctl_get_scan_params,
2602 [ACX100_IOCTL_SET_PREAMB - ACX100_IOCTL] = acx_ioctl_set_short_preamble,
2603 [ACX100_IOCTL_GET_PREAMB - ACX100_IOCTL] = acx_ioctl_get_short_preamble,
2604 [ACX100_IOCTL_SET_ANT - ACX100_IOCTL] = acx_ioctl_set_antenna,
2605 [ACX100_IOCTL_GET_ANT - ACX100_IOCTL] = acx_ioctl_get_antenna,
2606 [ACX100_IOCTL_RX_ANT - ACX100_IOCTL] = acx_ioctl_set_rx_antenna,
2607 [ACX100_IOCTL_TX_ANT - ACX100_IOCTL] = acx_ioctl_set_tx_antenna,
2608 [ACX100_IOCTL_SET_PHY_AMP_BIAS - ACX100_IOCTL] = acx100_ioctl_set_phy_amp_bias,
2609 [ACX100_IOCTL_GET_PHY_CHAN_BUSY - ACX100_IOCTL] = acx_ioctl_get_phy_chan_busy_percentage,
2610 [ACX100_IOCTL_SET_ED - ACX100_IOCTL] = acx_ioctl_set_ed_threshold,
2611 [ACX100_IOCTL_SET_CCA - ACX100_IOCTL] = acx_ioctl_set_cca,
2612 [ACX100_IOCTL_MONITOR - ACX100_IOCTL] = acx_ioctl_wlansniff,
2613 [ACX100_IOCTL_TEST - ACX100_IOCTL] = acx_ioctl_unknown11,
2614 [ACX100_IOCTL_DBG_SET_MASKS - ACX100_IOCTL] = acx_ioctl_dbg_set_masks,
2615 [ACX111_IOCTL_INFO - ACX100_IOCTL] = acx111_ioctl_info,
2619 static const struct iw_priv_args acx_ioctl_private_args[] = {
2620 #if ACX_DEBUG
2621 { cmd : ACX100_IOCTL_DEBUG,
2622 set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
2623 get_args : 0,
2624 name : "SetDebug" },
2625 #endif
2626 { cmd : ACX100_IOCTL_SET_PLED,
2627 set_args : IW_PRIV_TYPE_BYTE | 2,
2628 get_args : 0,
2629 name : "SetLEDPower" },
2630 { cmd : ACX100_IOCTL_GET_PLED,
2631 set_args : 0,
2632 get_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 2,
2633 name : "GetLEDPower" },
2634 { cmd : ACX100_IOCTL_SET_RATES,
2635 set_args : IW_PRIV_TYPE_CHAR | 256,
2636 get_args : 0,
2637 name : "SetRates" },
2638 { cmd : ACX100_IOCTL_LIST_DOM,
2639 set_args : 0,
2640 get_args : 0,
2641 name : "ListRegDomain" },
2642 { cmd : ACX100_IOCTL_SET_DOM,
2643 set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
2644 get_args : 0,
2645 name : "SetRegDomain" },
2646 { cmd : ACX100_IOCTL_GET_DOM,
2647 set_args : 0,
2648 get_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
2649 name : "GetRegDomain" },
2650 { cmd : ACX100_IOCTL_SET_SCAN_PARAMS,
2651 set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4,
2652 get_args : 0,
2653 name : "SetScanParams" },
2654 { cmd : ACX100_IOCTL_GET_SCAN_PARAMS,
2655 set_args : 0,
2656 get_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4,
2657 name : "GetScanParams" },
2658 { cmd : ACX100_IOCTL_SET_PREAMB,
2659 set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
2660 get_args : 0,
2661 name : "SetSPreamble" },
2662 { cmd : ACX100_IOCTL_GET_PREAMB,
2663 set_args : 0,
2664 get_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
2665 name : "GetSPreamble" },
2666 { cmd : ACX100_IOCTL_SET_ANT,
2667 set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
2668 get_args : 0,
2669 name : "SetAntenna" },
2670 { cmd : ACX100_IOCTL_GET_ANT,
2671 set_args : 0,
2672 get_args : 0,
2673 name : "GetAntenna" },
2674 { cmd : ACX100_IOCTL_RX_ANT,
2675 set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
2676 get_args : 0,
2677 name : "SetRxAnt" },
2678 { cmd : ACX100_IOCTL_TX_ANT,
2679 set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
2680 get_args : 0,
2681 name : "SetTxAnt" },
2682 { cmd : ACX100_IOCTL_SET_PHY_AMP_BIAS,
2683 set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
2684 get_args : 0,
2685 name : "SetPhyAmpBias"},
2686 { cmd : ACX100_IOCTL_GET_PHY_CHAN_BUSY,
2687 set_args : 0,
2688 get_args : 0,
2689 name : "GetPhyChanBusy" },
2690 { cmd : ACX100_IOCTL_SET_ED,
2691 set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
2692 get_args : 0,
2693 name : "SetED" },
2694 { cmd : ACX100_IOCTL_SET_CCA,
2695 set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
2696 get_args : 0,
2697 name : "SetCCA" },
2698 { cmd : ACX100_IOCTL_MONITOR,
2699 set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2,
2700 get_args : 0,
2701 name : "monitor" },
2702 { cmd : ACX100_IOCTL_TEST,
2703 set_args : 0,
2704 get_args : 0,
2705 name : "Test" },
2706 { cmd : ACX100_IOCTL_DBG_SET_MASKS,
2707 set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2,
2708 get_args : 0,
2709 name : "DbgSetMasks" },
2710 { cmd : ACX111_IOCTL_INFO,
2711 set_args : 0,
2712 get_args : 0,
2713 name : "GetAcx111Info" },
2714 { cmd : ACX100_IOCTL_DBG_SET_IO,
2715 set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4,
2716 get_args : 0,
2717 name : "DbgSetIO" },
2718 { cmd : ACX100_IOCTL_DBG_GET_IO,
2719 set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
2720 get_args : 0,
2721 name : "DbgGetIO" },
2725 const struct iw_handler_def acx_ioctl_handler_def =
2727 .num_standard = VEC_SIZE(acx_ioctl_handler),
2728 .num_private = VEC_SIZE(acx_ioctl_private_handler),
2729 .num_private_args = VEC_SIZE(acx_ioctl_private_args),
2730 .standard = (iw_handler *) acx_ioctl_handler,
2731 .private = (iw_handler *) acx_ioctl_private_handler,
2732 .private_args = (struct iw_priv_args *) acx_ioctl_private_args,
2733 #if IW_HANDLER_VERSION > 5
2734 .get_wireless_stats = acx_e_get_wireless_stats
2735 #endif /* IW > 5 */