aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/wext.c
diff options
context:
space:
mode:
authorMarcelo Tosatti <marcelo@kvack.org>2007-02-10 09:25:27 -0500
committerJeff Garzik <jeff@garzik.org>2007-04-28 11:00:54 -0400
commit876c9d3aeb989cf1961f2c228d309ba5dcfb1172 (patch)
tree239e9db92d13abc799c1ffc5304d8ec1503dbc61 /drivers/net/wireless/libertas/wext.c
parent35c3404efa7407811b706453f83d39b2539dcbd0 (diff)
[PATCH] Marvell Libertas 8388 802.11b/g USB driver
Add the Marvell Libertas 8388 802.11 USB driver. Signed-off-by: Marcelo Tosatti <marcelo@kvack.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas/wext.c')
-rw-r--r--drivers/net/wireless/libertas/wext.c2769
1 files changed, 2769 insertions, 0 deletions
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
new file mode 100644
index 000000000000..4a52336bc0f6
--- /dev/null
+++ b/drivers/net/wireless/libertas/wext.c
@@ -0,0 +1,2769 @@
1/**
2 * This file contains ioctl functions
3 */
4#include <linux/ctype.h>
5#include <linux/delay.h>
6#include <linux/if.h>
7#include <linux/if_arp.h>
8#include <linux/wireless.h>
9#include <linux/bitops.h>
10
11#include <net/ieee80211.h>
12#include <net/iw_handler.h>
13
14#include "host.h"
15#include "radiotap.h"
16#include "decl.h"
17#include "defs.h"
18#include "dev.h"
19#include "join.h"
20#include "version.h"
21#include "wext.h"
22#include "assoc.h"
23
24
25/**
26 * @brief Convert mw value to dbm value
27 *
28 * @param mw the value of mw
29 * @return the value of dbm
30 */
31static int mw_to_dbm(int mw)
32{
33 if (mw < 2)
34 return 0;
35 else if (mw < 3)
36 return 3;
37 else if (mw < 4)
38 return 5;
39 else if (mw < 6)
40 return 7;
41 else if (mw < 7)
42 return 8;
43 else if (mw < 8)
44 return 9;
45 else if (mw < 10)
46 return 10;
47 else if (mw < 13)
48 return 11;
49 else if (mw < 16)
50 return 12;
51 else if (mw < 20)
52 return 13;
53 else if (mw < 25)
54 return 14;
55 else if (mw < 32)
56 return 15;
57 else if (mw < 40)
58 return 16;
59 else if (mw < 50)
60 return 17;
61 else if (mw < 63)
62 return 18;
63 else if (mw < 79)
64 return 19;
65 else if (mw < 100)
66 return 20;
67 else
68 return 21;
69}
70
71/**
72 * @brief Find the channel frequency power info with specific channel
73 *
74 * @param adapter A pointer to wlan_adapter structure
75 * @param band it can be BAND_A, BAND_G or BAND_B
76 * @param channel the channel for looking
77 * @return A pointer to struct chan_freq_power structure or NULL if not find.
78 */
79struct chan_freq_power *libertas_find_cfp_by_band_and_channel(wlan_adapter * adapter,
80 u8 band, u16 channel)
81{
82 struct chan_freq_power *cfp = NULL;
83 struct region_channel *rc;
84 int count = sizeof(adapter->region_channel) /
85 sizeof(adapter->region_channel[0]);
86 int i, j;
87
88 for (j = 0; !cfp && (j < count); j++) {
89 rc = &adapter->region_channel[j];
90
91 if (adapter->enable11d)
92 rc = &adapter->universal_channel[j];
93 if (!rc->valid || !rc->CFP)
94 continue;
95 if (rc->band != band)
96 continue;
97 for (i = 0; i < rc->nrcfp; i++) {
98 if (rc->CFP[i].channel == channel) {
99 cfp = &rc->CFP[i];
100 break;
101 }
102 }
103 }
104
105 if (!cfp && channel)
106 lbs_pr_debug(1, "libertas_find_cfp_by_band_and_channel(): cannot find "
107 "cfp by band %d & channel %d\n", band, channel);
108
109 return cfp;
110}
111
112/**
113 * @brief Find the channel frequency power info with specific frequency
114 *
115 * @param adapter A pointer to wlan_adapter structure
116 * @param band it can be BAND_A, BAND_G or BAND_B
117 * @param freq the frequency for looking
118 * @return A pointer to struct chan_freq_power structure or NULL if not find.
119 */
120static struct chan_freq_power *find_cfp_by_band_and_freq(wlan_adapter * adapter,
121 u8 band, u32 freq)
122{
123 struct chan_freq_power *cfp = NULL;
124 struct region_channel *rc;
125 int count = sizeof(adapter->region_channel) /
126 sizeof(adapter->region_channel[0]);
127 int i, j;
128
129 for (j = 0; !cfp && (j < count); j++) {
130 rc = &adapter->region_channel[j];
131
132 if (adapter->enable11d)
133 rc = &adapter->universal_channel[j];
134 if (!rc->valid || !rc->CFP)
135 continue;
136 if (rc->band != band)
137 continue;
138 for (i = 0; i < rc->nrcfp; i++) {
139 if (rc->CFP[i].freq == freq) {
140 cfp = &rc->CFP[i];
141 break;
142 }
143 }
144 }
145
146 if (!cfp && freq)
147 lbs_pr_debug(1, "find_cfp_by_band_and_freql(): cannot find cfp by "
148 "band %d & freq %d\n", band, freq);
149
150 return cfp;
151}
152
153static int updatecurrentchannel(wlan_private * priv)
154{
155 int ret;
156
157 /*
158 ** the channel in f/w could be out of sync, get the current channel
159 */
160 ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
161 cmd_opt_802_11_rf_channel_get,
162 cmd_option_waitforrsp, 0, NULL);
163
164 lbs_pr_debug(1, "Current channel = %d\n",
165 priv->adapter->curbssparams.channel);
166
167 return ret;
168}
169
170static int setcurrentchannel(wlan_private * priv, int channel)
171{
172 lbs_pr_debug(1, "Set channel = %d\n", channel);
173
174 /*
175 ** Current channel is not set to adhocchannel requested, set channel
176 */
177 return (libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
178 cmd_opt_802_11_rf_channel_set,
179 cmd_option_waitforrsp, 0, &channel));
180}
181
182static int changeadhocchannel(wlan_private * priv, int channel)
183{
184 int ret = 0;
185 wlan_adapter *adapter = priv->adapter;
186
187 adapter->adhocchannel = channel;
188
189 updatecurrentchannel(priv);
190
191 if (adapter->curbssparams.channel == adapter->adhocchannel) {
192 /* adhocchannel is set to the current channel already */
193 LEAVE();
194 return 0;
195 }
196
197 lbs_pr_debug(1, "Updating channel from %d to %d\n",
198 adapter->curbssparams.channel, adapter->adhocchannel);
199
200 setcurrentchannel(priv, adapter->adhocchannel);
201
202 updatecurrentchannel(priv);
203
204 if (adapter->curbssparams.channel != adapter->adhocchannel) {
205 lbs_pr_debug(1, "failed to updated channel to %d, channel = %d\n",
206 adapter->adhocchannel, adapter->curbssparams.channel);
207 LEAVE();
208 return -1;
209 }
210
211 if (adapter->connect_status == libertas_connected) {
212 int i;
213 struct WLAN_802_11_SSID curadhocssid;
214
215 lbs_pr_debug(1, "channel Changed while in an IBSS\n");
216
217 /* Copy the current ssid */
218 memcpy(&curadhocssid, &adapter->curbssparams.ssid,
219 sizeof(struct WLAN_802_11_SSID));
220
221 /* Exit Adhoc mode */
222 lbs_pr_debug(1, "In changeadhocchannel(): Sending Adhoc Stop\n");
223 ret = libertas_stop_adhoc_network(priv);
224
225 if (ret) {
226 LEAVE();
227 return ret;
228 }
229 /* Scan for the network, do not save previous results. Stale
230 * scan data will cause us to join a non-existant adhoc network
231 */
232 libertas_send_specific_SSID_scan(priv, &curadhocssid, 0);
233
234 // find out the BSSID that matches the current SSID
235 i = libertas_find_SSID_in_list(adapter, &curadhocssid, NULL,
236 wlan802_11ibss);
237
238 if (i >= 0) {
239 lbs_pr_debug(1, "SSID found at %d in List,"
240 "so join\n", i);
241 libertas_join_adhoc_network(priv, &adapter->scantable[i]);
242 } else {
243 // else send START command
244 lbs_pr_debug(1, "SSID not found in list, "
245 "so creating adhoc with ssid = %s\n",
246 curadhocssid.ssid);
247 libertas_start_adhoc_network(priv, &curadhocssid);
248 } // end of else (START command)
249 }
250
251 LEAVE();
252 return 0;
253}
254
255/**
256 * @brief Set Radio On/OFF
257 *
258 * @param priv A pointer to wlan_private structure
259 * @option Radio Option
260 * @return 0 --success, otherwise fail
261 */
262int wlan_radio_ioctl(wlan_private * priv, u8 option)
263{
264 int ret = 0;
265 wlan_adapter *adapter = priv->adapter;
266
267 ENTER();
268
269 if (adapter->radioon != option) {
270 lbs_pr_debug(1, "Switching %s the Radio\n", option ? "On" : "Off");
271 adapter->radioon = option;
272
273 ret = libertas_prepare_and_send_command(priv,
274 cmd_802_11_radio_control,
275 cmd_act_set,
276 cmd_option_waitforrsp, 0, NULL);
277 }
278
279 LEAVE();
280 return ret;
281}
282
283/**
284 * @brief Copy rates
285 *
286 * @param dest A pointer to Dest Buf
287 * @param src A pointer to Src Buf
288 * @param len The len of Src Buf
289 * @return Number of rates copyed
290 */
291static inline int copyrates(u8 * dest, int pos, u8 * src, int len)
292{
293 int i;
294
295 for (i = 0; i < len && src[i]; i++, pos++) {
296 if (pos >= sizeof(u8) * WLAN_SUPPORTED_RATES)
297 break;
298 dest[pos] = src[i];
299 }
300
301 return pos;
302}
303
304/**
305 * @brief Get active data rates
306 *
307 * @param adapter A pointer to wlan_adapter structure
308 * @param rate The buf to return the active rates
309 * @return The number of rates
310 */
311static int get_active_data_rates(wlan_adapter * adapter,
312 u8* rates)
313{
314 int k = 0;
315
316 ENTER();
317
318 if (adapter->connect_status != libertas_connected) {
319 if (adapter->inframode == wlan802_11infrastructure) {
320 //Infra. mode
321 lbs_pr_debug(1, "Infra\n");
322 k = copyrates(rates, k, libertas_supported_rates,
323 sizeof(libertas_supported_rates));
324 } else {
325 //ad-hoc mode
326 lbs_pr_debug(1, "Adhoc G\n");
327 k = copyrates(rates, k, libertas_adhoc_rates_g,
328 sizeof(libertas_adhoc_rates_g));
329 }
330 } else {
331 k = copyrates(rates, 0, adapter->curbssparams.datarates,
332 adapter->curbssparams.numofrates);
333 }
334
335 LEAVE();
336
337 return k;
338}
339
340static int wlan_get_name(struct net_device *dev, struct iw_request_info *info,
341 char *cwrq, char *extra)
342{
343 const char *cp;
344 char comm[6] = { "COMM-" };
345 char mrvl[6] = { "MRVL-" };
346 int cnt;
347
348 ENTER();
349
350 strcpy(cwrq, mrvl);
351
352 cp = strstr(libertas_driver_version, comm);
353 if (cp == libertas_driver_version) //skip leading "COMM-"
354 cp = libertas_driver_version + strlen(comm);
355 else
356 cp = libertas_driver_version;
357
358 cnt = strlen(mrvl);
359 cwrq += cnt;
360 while (cnt < 16 && (*cp != '-')) {
361 *cwrq++ = toupper(*cp++);
362 cnt++;
363 }
364 *cwrq = '\0';
365
366 LEAVE();
367
368 return 0;
369}
370
371static int wlan_get_freq(struct net_device *dev, struct iw_request_info *info,
372 struct iw_freq *fwrq, char *extra)
373{
374 wlan_private *priv = dev->priv;
375 wlan_adapter *adapter = priv->adapter;
376 struct chan_freq_power *cfp;
377
378 ENTER();
379
380 cfp = libertas_find_cfp_by_band_and_channel(adapter, 0,
381 adapter->curbssparams.channel);
382
383 if (!cfp) {
384 if (adapter->curbssparams.channel)
385 lbs_pr_debug(1, "Invalid channel=%d\n",
386 adapter->curbssparams.channel);
387 return -EINVAL;
388 }
389
390 fwrq->m = (long)cfp->freq * 100000;
391 fwrq->e = 1;
392
393 lbs_pr_debug(1, "freq=%u\n", fwrq->m);
394
395 LEAVE();
396 return 0;
397}
398
399static int wlan_get_wap(struct net_device *dev, struct iw_request_info *info,
400 struct sockaddr *awrq, char *extra)
401{
402 wlan_private *priv = dev->priv;
403 wlan_adapter *adapter = priv->adapter;
404
405 ENTER();
406
407 if (adapter->connect_status == libertas_connected) {
408 memcpy(awrq->sa_data, adapter->curbssparams.bssid, ETH_ALEN);
409 } else {
410 memset(awrq->sa_data, 0, ETH_ALEN);
411 }
412 awrq->sa_family = ARPHRD_ETHER;
413
414 LEAVE();
415 return 0;
416}
417
418static int wlan_set_nick(struct net_device *dev, struct iw_request_info *info,
419 struct iw_point *dwrq, char *extra)
420{
421 wlan_private *priv = dev->priv;
422 wlan_adapter *adapter = priv->adapter;
423
424 ENTER();
425
426 /*
427 * Check the size of the string
428 */
429
430 if (dwrq->length > 16) {
431 return -E2BIG;
432 }
433
434 mutex_lock(&adapter->lock);
435 memset(adapter->nodename, 0, sizeof(adapter->nodename));
436 memcpy(adapter->nodename, extra, dwrq->length);
437 mutex_unlock(&adapter->lock);
438
439 LEAVE();
440 return 0;
441}
442
443static int wlan_get_nick(struct net_device *dev, struct iw_request_info *info,
444 struct iw_point *dwrq, char *extra)
445{
446 wlan_private *priv = dev->priv;
447 wlan_adapter *adapter = priv->adapter;
448
449 ENTER();
450
451 /*
452 * Get the Nick Name saved
453 */
454
455 mutex_lock(&adapter->lock);
456 strncpy(extra, adapter->nodename, 16);
457 mutex_unlock(&adapter->lock);
458
459 extra[16] = '\0';
460
461 /*
462 * If none, we may want to get the one that was set
463 */
464
465 /*
466 * Push it out !
467 */
468 dwrq->length = strlen(extra) + 1;
469
470 LEAVE();
471 return 0;
472}
473
474static int wlan_set_rts(struct net_device *dev, struct iw_request_info *info,
475 struct iw_param *vwrq, char *extra)
476{
477 int ret = 0;
478 wlan_private *priv = dev->priv;
479 wlan_adapter *adapter = priv->adapter;
480 int rthr = vwrq->value;
481
482 ENTER();
483
484 if (vwrq->disabled) {
485 adapter->rtsthsd = rthr = MRVDRV_RTS_MAX_VALUE;
486 } else {
487 if (rthr < MRVDRV_RTS_MIN_VALUE || rthr > MRVDRV_RTS_MAX_VALUE)
488 return -EINVAL;
489 adapter->rtsthsd = rthr;
490 }
491
492 ret = libertas_prepare_and_send_command(priv, cmd_802_11_snmp_mib,
493 cmd_act_set, cmd_option_waitforrsp,
494 OID_802_11_RTS_THRESHOLD, &rthr);
495
496 LEAVE();
497 return ret;
498}
499
500static int wlan_get_rts(struct net_device *dev, struct iw_request_info *info,
501 struct iw_param *vwrq, char *extra)
502{
503 int ret = 0;
504 wlan_private *priv = dev->priv;
505 wlan_adapter *adapter = priv->adapter;
506
507 ENTER();
508
509 adapter->rtsthsd = 0;
510 ret = libertas_prepare_and_send_command(priv, cmd_802_11_snmp_mib,
511 cmd_act_get, cmd_option_waitforrsp,
512 OID_802_11_RTS_THRESHOLD, NULL);
513 if (ret) {
514 LEAVE();
515 return ret;
516 }
517
518 vwrq->value = adapter->rtsthsd;
519 vwrq->disabled = ((vwrq->value < MRVDRV_RTS_MIN_VALUE)
520 || (vwrq->value > MRVDRV_RTS_MAX_VALUE));
521 vwrq->fixed = 1;
522
523 LEAVE();
524 return 0;
525}
526
527static int wlan_set_frag(struct net_device *dev, struct iw_request_info *info,
528 struct iw_param *vwrq, char *extra)
529{
530 int ret = 0;
531 int fthr = vwrq->value;
532 wlan_private *priv = dev->priv;
533 wlan_adapter *adapter = priv->adapter;
534
535 ENTER();
536
537 if (vwrq->disabled) {
538 adapter->fragthsd = fthr = MRVDRV_FRAG_MAX_VALUE;
539 } else {
540 if (fthr < MRVDRV_FRAG_MIN_VALUE
541 || fthr > MRVDRV_FRAG_MAX_VALUE)
542 return -EINVAL;
543 adapter->fragthsd = fthr;
544 }
545
546 ret = libertas_prepare_and_send_command(priv, cmd_802_11_snmp_mib,
547 cmd_act_set, cmd_option_waitforrsp,
548 OID_802_11_FRAGMENTATION_THRESHOLD, &fthr);
549 LEAVE();
550 return ret;
551}
552
553static int wlan_get_frag(struct net_device *dev, struct iw_request_info *info,
554 struct iw_param *vwrq, char *extra)
555{
556 int ret = 0;
557 wlan_private *priv = dev->priv;
558 wlan_adapter *adapter = priv->adapter;
559
560 ENTER();
561
562 adapter->fragthsd = 0;
563 ret = libertas_prepare_and_send_command(priv,
564 cmd_802_11_snmp_mib,
565 cmd_act_get, cmd_option_waitforrsp,
566 OID_802_11_FRAGMENTATION_THRESHOLD, NULL);
567 if (ret) {
568 LEAVE();
569 return ret;
570 }
571
572 vwrq->value = adapter->fragthsd;
573 vwrq->disabled = ((vwrq->value < MRVDRV_FRAG_MIN_VALUE)
574 || (vwrq->value > MRVDRV_FRAG_MAX_VALUE));
575 vwrq->fixed = 1;
576
577 LEAVE();
578 return ret;
579}
580
581static int wlan_get_mode(struct net_device *dev,
582 struct iw_request_info *info, u32 * uwrq, char *extra)
583{
584 wlan_private *priv = dev->priv;
585 wlan_adapter *adapter = priv->adapter;
586
587 ENTER();
588
589 switch (adapter->inframode) {
590 case wlan802_11ibss:
591 *uwrq = IW_MODE_ADHOC;
592 break;
593
594 case wlan802_11infrastructure:
595 *uwrq = IW_MODE_INFRA;
596 break;
597
598 default:
599 case wlan802_11autounknown:
600 *uwrq = IW_MODE_AUTO;
601 break;
602 }
603
604 LEAVE();
605 return 0;
606}
607
608static int wlan_get_txpow(struct net_device *dev,
609 struct iw_request_info *info,
610 struct iw_param *vwrq, char *extra)
611{
612 int ret = 0;
613 wlan_private *priv = dev->priv;
614 wlan_adapter *adapter = priv->adapter;
615
616 ENTER();
617
618 ret = libertas_prepare_and_send_command(priv,
619 cmd_802_11_rf_tx_power,
620 cmd_act_tx_power_opt_get,
621 cmd_option_waitforrsp, 0, NULL);
622
623 if (ret) {
624 LEAVE();
625 return ret;
626 }
627
628 lbs_pr_debug(1, "TXPOWER GET %d dbm.\n", adapter->txpowerlevel);
629 vwrq->value = adapter->txpowerlevel;
630 vwrq->fixed = 1;
631 if (adapter->radioon) {
632 vwrq->disabled = 0;
633 vwrq->flags = IW_TXPOW_DBM;
634 } else {
635 vwrq->disabled = 1;
636 }
637
638 LEAVE();
639 return 0;
640}
641
642static int wlan_set_retry(struct net_device *dev, struct iw_request_info *info,
643 struct iw_param *vwrq, char *extra)
644{
645 int ret = 0;
646 wlan_private *priv = dev->priv;
647 wlan_adapter *adapter = priv->adapter;
648
649 ENTER();
650
651 if (vwrq->flags == IW_RETRY_LIMIT) {
652 /* The MAC has a 4-bit Total_Tx_Count register
653 Total_Tx_Count = 1 + Tx_Retry_Count */
654#define TX_RETRY_MIN 0
655#define TX_RETRY_MAX 14
656 if (vwrq->value < TX_RETRY_MIN || vwrq->value > TX_RETRY_MAX)
657 return -EINVAL;
658
659 /* Adding 1 to convert retry count to try count */
660 adapter->txretrycount = vwrq->value + 1;
661
662 ret = libertas_prepare_and_send_command(priv, cmd_802_11_snmp_mib,
663 cmd_act_set,
664 cmd_option_waitforrsp,
665 OID_802_11_TX_RETRYCOUNT, NULL);
666
667 if (ret) {
668 LEAVE();
669 return ret;
670 }
671 } else {
672 return -EOPNOTSUPP;
673 }
674
675 LEAVE();
676 return 0;
677}
678
679static int wlan_get_retry(struct net_device *dev, struct iw_request_info *info,
680 struct iw_param *vwrq, char *extra)
681{
682 wlan_private *priv = dev->priv;
683 wlan_adapter *adapter = priv->adapter;
684 int ret = 0;
685
686 ENTER();
687 adapter->txretrycount = 0;
688 ret = libertas_prepare_and_send_command(priv,
689 cmd_802_11_snmp_mib,
690 cmd_act_get, cmd_option_waitforrsp,
691 OID_802_11_TX_RETRYCOUNT, NULL);
692 if (ret) {
693 LEAVE();
694 return ret;
695 }
696 vwrq->disabled = 0;
697 if (!vwrq->flags) {
698 vwrq->flags = IW_RETRY_LIMIT;
699 /* Subtract 1 to convert try count to retry count */
700 vwrq->value = adapter->txretrycount - 1;
701 }
702
703 LEAVE();
704 return 0;
705}
706
707static inline void sort_channels(struct iw_freq *freq, int num)
708{
709 int i, j;
710 struct iw_freq temp;
711
712 for (i = 0; i < num; i++)
713 for (j = i + 1; j < num; j++)
714 if (freq[i].i > freq[j].i) {
715 temp.i = freq[i].i;
716 temp.m = freq[i].m;
717
718 freq[i].i = freq[j].i;
719 freq[i].m = freq[j].m;
720
721 freq[j].i = temp.i;
722 freq[j].m = temp.m;
723 }
724}
725
726/* data rate listing
727 MULTI_BANDS:
728 abg a b b/g
729 Infra G(12) A(8) B(4) G(12)
730 Adhoc A+B(12) A(8) B(4) B(4)
731
732 non-MULTI_BANDS:
733 b b/g
734 Infra B(4) G(12)
735 Adhoc B(4) B(4)
736 */
737/**
738 * @brief Get Range Info
739 *
740 * @param dev A pointer to net_device structure
741 * @param info A pointer to iw_request_info structure
742 * @param vwrq A pointer to iw_param structure
743 * @param extra A pointer to extra data buf
744 * @return 0 --success, otherwise fail
745 */
746static int wlan_get_range(struct net_device *dev, struct iw_request_info *info,
747 struct iw_point *dwrq, char *extra)
748{
749 int i, j;
750 wlan_private *priv = dev->priv;
751 wlan_adapter *adapter = priv->adapter;
752 struct iw_range *range = (struct iw_range *)extra;
753 struct chan_freq_power *cfp;
754 u8 rates[WLAN_SUPPORTED_RATES];
755
756 u8 flag = 0;
757
758 ENTER();
759
760 dwrq->length = sizeof(struct iw_range);
761 memset(range, 0, sizeof(struct iw_range));
762
763 range->min_nwid = 0;
764 range->max_nwid = 0;
765
766 memset(rates, 0, sizeof(rates));
767 range->num_bitrates = get_active_data_rates(adapter, rates);
768
769 for (i = 0; i < min_t(__u8, range->num_bitrates, IW_MAX_BITRATES) && rates[i];
770 i++) {
771 range->bitrate[i] = (rates[i] & 0x7f) * 500000;
772 }
773 range->num_bitrates = i;
774 lbs_pr_debug(1, "IW_MAX_BITRATES=%d num_bitrates=%d\n", IW_MAX_BITRATES,
775 range->num_bitrates);
776
777 range->num_frequency = 0;
778 if (priv->adapter->enable11d &&
779 adapter->connect_status == libertas_connected) {
780 u8 chan_no;
781 u8 band;
782
783 struct parsed_region_chan_11d *parsed_region_chan =
784 &adapter->parsed_region_chan;
785
786 if (parsed_region_chan == NULL) {
787 lbs_pr_debug(1, "11D:parsed_region_chan is NULL\n");
788 LEAVE();
789 return 0;
790 }
791 band = parsed_region_chan->band;
792 lbs_pr_debug(1, "band=%d NoOfChan=%d\n", band,
793 parsed_region_chan->nr_chan);
794
795 for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
796 && (i < parsed_region_chan->nr_chan); i++) {
797 chan_no = parsed_region_chan->chanpwr[i].chan;
798 lbs_pr_debug(1, "chan_no=%d\n", chan_no);
799 range->freq[range->num_frequency].i = (long)chan_no;
800 range->freq[range->num_frequency].m =
801 (long)libertas_chan_2_freq(chan_no, band) * 100000;
802 range->freq[range->num_frequency].e = 1;
803 range->num_frequency++;
804 }
805 flag = 1;
806 }
807 if (!flag) {
808 for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
809 && (j < sizeof(adapter->region_channel)
810 / sizeof(adapter->region_channel[0])); j++) {
811 cfp = adapter->region_channel[j].CFP;
812 for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
813 && adapter->region_channel[j].valid
814 && cfp
815 && (i < adapter->region_channel[j].nrcfp); i++) {
816 range->freq[range->num_frequency].i =
817 (long)cfp->channel;
818 range->freq[range->num_frequency].m =
819 (long)cfp->freq * 100000;
820 range->freq[range->num_frequency].e = 1;
821 cfp++;
822 range->num_frequency++;
823 }
824 }
825 }
826
827 lbs_pr_debug(1, "IW_MAX_FREQUENCIES=%d num_frequency=%d\n",
828 IW_MAX_FREQUENCIES, range->num_frequency);
829
830 range->num_channels = range->num_frequency;
831
832 sort_channels(&range->freq[0], range->num_frequency);
833
834 /*
835 * Set an indication of the max TCP throughput in bit/s that we can
836 * expect using this interface
837 */
838 if (i > 2)
839 range->throughput = 5000 * 1000;
840 else
841 range->throughput = 1500 * 1000;
842
843 range->min_rts = MRVDRV_RTS_MIN_VALUE;
844 range->max_rts = MRVDRV_RTS_MAX_VALUE;
845 range->min_frag = MRVDRV_FRAG_MIN_VALUE;
846 range->max_frag = MRVDRV_FRAG_MAX_VALUE;
847
848 range->encoding_size[0] = 5;
849 range->encoding_size[1] = 13;
850 range->num_encoding_sizes = 2;
851 range->max_encoding_tokens = 4;
852
853 range->min_pmp = 1000000;
854 range->max_pmp = 120000000;
855 range->min_pmt = 1000;
856 range->max_pmt = 1000000;
857 range->pmp_flags = IW_POWER_PERIOD;
858 range->pmt_flags = IW_POWER_TIMEOUT;
859 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
860
861 /*
862 * Minimum version we recommend
863 */
864 range->we_version_source = 15;
865
866 /*
867 * Version we are compiled with
868 */
869 range->we_version_compiled = WIRELESS_EXT;
870
871 range->retry_capa = IW_RETRY_LIMIT;
872 range->retry_flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
873
874 range->min_retry = TX_RETRY_MIN;
875 range->max_retry = TX_RETRY_MAX;
876
877 /*
878 * Set the qual, level and noise range values
879 */
880 range->max_qual.qual = 100;
881 range->max_qual.level = 0;
882 range->max_qual.noise = 0;
883 range->max_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
884
885 range->avg_qual.qual = 70;
886 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
887 range->avg_qual.level = 0;
888 range->avg_qual.noise = 0;
889 range->avg_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
890
891 range->sensitivity = 0;
892
893 /*
894 * Setup the supported power level ranges
895 */
896 memset(range->txpower, 0, sizeof(range->txpower));
897 range->txpower[0] = 5;
898 range->txpower[1] = 7;
899 range->txpower[2] = 9;
900 range->txpower[3] = 11;
901 range->txpower[4] = 13;
902 range->txpower[5] = 15;
903 range->txpower[6] = 17;
904 range->txpower[7] = 19;
905
906 range->num_txpower = 8;
907 range->txpower_capa = IW_TXPOW_DBM;
908 range->txpower_capa |= IW_TXPOW_RANGE;
909
910 range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
911 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
912 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
913 range->event_capa[1] = IW_EVENT_CAPA_K_1;
914
915 if (adapter->fwcapinfo & FW_CAPINFO_WPA) {
916 range->enc_capa = IW_ENC_CAPA_WPA
917 | IW_ENC_CAPA_WPA2
918 | IW_ENC_CAPA_CIPHER_TKIP
919 | IW_ENC_CAPA_CIPHER_CCMP;
920 }
921
922 LEAVE();
923 return 0;
924}
925
926static int wlan_set_power(struct net_device *dev, struct iw_request_info *info,
927 struct iw_param *vwrq, char *extra)
928{
929 wlan_private *priv = dev->priv;
930 wlan_adapter *adapter = priv->adapter;
931
932 ENTER();
933
934 /* PS is currently supported only in Infrastructure mode
935 * Remove this check if it is to be supported in IBSS mode also
936 */
937
938 if (vwrq->disabled) {
939 adapter->psmode = wlan802_11powermodecam;
940 if (adapter->psstate != PS_STATE_FULL_POWER) {
941 libertas_ps_wakeup(priv, cmd_option_waitforrsp);
942 }
943
944 return 0;
945 }
946
947 if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
948 lbs_pr_debug(1,
949 "Setting power timeout command is not supported\n");
950 return -EINVAL;
951 } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
952 lbs_pr_debug(1, "Setting power period command is not supported\n");
953 return -EINVAL;
954 }
955
956 if (adapter->psmode != wlan802_11powermodecam) {
957 return 0;
958 }
959
960 adapter->psmode = wlan802_11powermodemax_psp;
961
962 if (adapter->connect_status == libertas_connected) {
963 libertas_ps_sleep(priv, cmd_option_waitforrsp);
964 }
965
966 LEAVE();
967 return 0;
968}
969
970static int wlan_get_power(struct net_device *dev, struct iw_request_info *info,
971 struct iw_param *vwrq, char *extra)
972{
973 wlan_private *priv = dev->priv;
974 wlan_adapter *adapter = priv->adapter;
975 int mode;
976
977 ENTER();
978
979 mode = adapter->psmode;
980
981 if ((vwrq->disabled = (mode == wlan802_11powermodecam))
982 || adapter->connect_status == libertas_disconnected) {
983 LEAVE();
984 return 0;
985 }
986
987 vwrq->value = 0;
988
989 LEAVE();
990 return 0;
991}
992
993/*
994 * iwpriv settable callbacks
995 */
996
997static const iw_handler wlan_private_handler[] = {
998 NULL, /* SIOCIWFIRSTPRIV */
999};
1000
1001static const struct iw_priv_args wlan_private_args[] = {
1002 /*
1003 * { cmd, set_args, get_args, name }
1004 */
1005 {
1006 WLANSCAN_TYPE,
1007 IW_PRIV_TYPE_CHAR | 8,
1008 IW_PRIV_TYPE_CHAR | 8,
1009 "scantype"},
1010
1011 {
1012 WLAN_SETINT_GETINT,
1013 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1014 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1015 ""},
1016 {
1017 WLANNF,
1018 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1019 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1020 "getNF"},
1021 {
1022 WLANRSSI,
1023 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1024 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1025 "getRSSI"},
1026 {
1027 WLANENABLE11D,
1028 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1029 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1030 "enable11d"},
1031 {
1032 WLANADHOCGRATE,
1033 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1034 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1035 "adhocgrate"},
1036
1037 {
1038 WLAN_SUBCMD_SET_PRESCAN,
1039 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1040 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1041 "prescan"},
1042 {
1043 WLAN_SETONEINT_GETONEINT,
1044 IW_PRIV_TYPE_INT | 1,
1045 IW_PRIV_TYPE_INT | 1,
1046 ""},
1047 {
1048 WLAN_BEACON_INTERVAL,
1049 IW_PRIV_TYPE_INT | 1,
1050 IW_PRIV_TYPE_INT | 1,
1051 "bcninterval"},
1052 {
1053 WLAN_LISTENINTRVL,
1054 IW_PRIV_TYPE_INT | 1,
1055 IW_PRIV_TYPE_INT | 1,
1056 "lolisteninter"},
1057 {
1058 WLAN_TXCONTROL,
1059 IW_PRIV_TYPE_INT | 1,
1060 IW_PRIV_TYPE_INT | 1,
1061 "txcontrol"},
1062 {
1063 WLAN_NULLPKTINTERVAL,
1064 IW_PRIV_TYPE_INT | 1,
1065 IW_PRIV_TYPE_INT | 1,
1066 "psnullinterval"},
1067 /* Using iwpriv sub-command feature */
1068 {
1069 WLAN_SETONEINT_GETNONE, /* IOCTL: 24 */
1070 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1071 IW_PRIV_TYPE_NONE,
1072 ""},
1073
1074 {
1075 WLAN_SUBCMD_SETRXANTENNA,
1076 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1077 IW_PRIV_TYPE_NONE,
1078 "setrxant"},
1079 {
1080 WLAN_SUBCMD_SETTXANTENNA,
1081 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1082 IW_PRIV_TYPE_NONE,
1083 "settxant"},
1084 {
1085 WLANSETAUTHALG,
1086 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1087 IW_PRIV_TYPE_NONE,
1088 "authalgs",
1089 },
1090 {
1091 WLANSET8021XAUTHALG,
1092 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1093 IW_PRIV_TYPE_NONE,
1094 "8021xauthalgs",
1095 },
1096 {
1097 WLANSETENCRYPTIONMODE,
1098 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1099 IW_PRIV_TYPE_NONE,
1100 "encryptionmode",
1101 },
1102 {
1103 WLANSETREGION,
1104 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1105 IW_PRIV_TYPE_NONE,
1106 "setregioncode"},
1107 {
1108 WLAN_SET_LISTEN_INTERVAL,
1109 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1110 IW_PRIV_TYPE_NONE,
1111 "setlisteninter"},
1112 {
1113 WLAN_SET_MULTIPLE_DTIM,
1114 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1115 IW_PRIV_TYPE_NONE,
1116 "setmultipledtim"},
1117 {
1118 WLAN_SET_ATIM_WINDOW,
1119 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1120 IW_PRIV_TYPE_NONE,
1121 "atimwindow"},
1122 {
1123 WLANSETBCNAVG,
1124 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1125 IW_PRIV_TYPE_NONE,
1126 "setbcnavg"},
1127 {
1128 WLANSETDATAAVG,
1129 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1130 IW_PRIV_TYPE_NONE,
1131 "setdataavg"},
1132 {
1133 WLAN_SET_LINKMODE,
1134 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1135 IW_PRIV_TYPE_NONE,
1136 "linkmode"},
1137 {
1138 WLAN_SET_RADIOMODE,
1139 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1140 IW_PRIV_TYPE_NONE,
1141 "radiomode"},
1142 {
1143 WLAN_SET_DEBUGMODE,
1144 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1145 IW_PRIV_TYPE_NONE,
1146 "debugmode"},
1147 {
1148 WLAN_SUBCMD_MESH_SET_TTL,
1149 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1150 IW_PRIV_TYPE_NONE,
1151 "mesh_set_ttl"},
1152 {
1153 WLAN_SETNONE_GETONEINT,
1154 IW_PRIV_TYPE_NONE,
1155 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1156 ""},
1157 {
1158 WLANGETREGION,
1159 IW_PRIV_TYPE_NONE,
1160 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1161 "getregioncode"},
1162 {
1163 WLAN_GET_LISTEN_INTERVAL,
1164 IW_PRIV_TYPE_NONE,
1165 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1166 "getlisteninter"},
1167 {
1168 WLAN_GET_MULTIPLE_DTIM,
1169 IW_PRIV_TYPE_NONE,
1170 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1171 "getmultipledtim"},
1172 {
1173 WLAN_GET_TX_RATE,
1174 IW_PRIV_TYPE_NONE,
1175 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1176 "gettxrate"},
1177 {
1178 WLANGETBCNAVG,
1179 IW_PRIV_TYPE_NONE,
1180 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1181 "getbcnavg"},
1182 {
1183 WLAN_GET_LINKMODE,
1184 IW_PRIV_TYPE_NONE,
1185 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1186 "get_linkmode"},
1187 {
1188 WLAN_GET_RADIOMODE,
1189 IW_PRIV_TYPE_NONE,
1190 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1191 "get_radiomode"},
1192 {
1193 WLAN_GET_DEBUGMODE,
1194 IW_PRIV_TYPE_NONE,
1195 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1196 "get_debugmode"},
1197 {
1198 WLAN_SUBCMD_FWT_CLEANUP,
1199 IW_PRIV_TYPE_NONE,
1200 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1201 "fwt_cleanup"},
1202 {
1203 WLAN_SUBCMD_FWT_TIME,
1204 IW_PRIV_TYPE_NONE,
1205 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1206 "fwt_time"},
1207 {
1208 WLAN_SUBCMD_MESH_GET_TTL,
1209 IW_PRIV_TYPE_NONE,
1210 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1211 "mesh_get_ttl"},
1212 {
1213 WLAN_SETNONE_GETTWELVE_CHAR,
1214 IW_PRIV_TYPE_NONE,
1215 IW_PRIV_TYPE_CHAR | 12,
1216 ""},
1217 {
1218 WLAN_SUBCMD_GETRXANTENNA,
1219 IW_PRIV_TYPE_NONE,
1220 IW_PRIV_TYPE_CHAR | 12,
1221 "getrxant"},
1222 {
1223 WLAN_SUBCMD_GETTXANTENNA,
1224 IW_PRIV_TYPE_NONE,
1225 IW_PRIV_TYPE_CHAR | 12,
1226 "gettxant"},
1227 {
1228 WLAN_GET_TSF,
1229 IW_PRIV_TYPE_NONE,
1230 IW_PRIV_TYPE_CHAR | 12,
1231 "gettsf"},
1232 {
1233 WLAN_SETNONE_GETNONE,
1234 IW_PRIV_TYPE_NONE,
1235 IW_PRIV_TYPE_NONE,
1236 ""},
1237 {
1238 WLANDEAUTH,
1239 IW_PRIV_TYPE_NONE,
1240 IW_PRIV_TYPE_NONE,
1241 "deauth"},
1242 {
1243 WLANADHOCSTOP,
1244 IW_PRIV_TYPE_NONE,
1245 IW_PRIV_TYPE_NONE,
1246 "adhocstop"},
1247 {
1248 WLANRADIOON,
1249 IW_PRIV_TYPE_NONE,
1250 IW_PRIV_TYPE_NONE,
1251 "radioon"},
1252 {
1253 WLANRADIOOFF,
1254 IW_PRIV_TYPE_NONE,
1255 IW_PRIV_TYPE_NONE,
1256 "radiooff"},
1257 {
1258 WLANWLANIDLEON,
1259 IW_PRIV_TYPE_NONE,
1260 IW_PRIV_TYPE_NONE,
1261 "wlanidle-on"},
1262 {
1263 WLANWLANIDLEOFF,
1264 IW_PRIV_TYPE_NONE,
1265 IW_PRIV_TYPE_NONE,
1266 "wlanidle-off"},
1267 {
1268 WLAN_SUBCMD_FWT_RESET,
1269 IW_PRIV_TYPE_NONE,
1270 IW_PRIV_TYPE_NONE,
1271 "fwt_reset"},
1272 {
1273 WLAN_SUBCMD_BT_RESET,
1274 IW_PRIV_TYPE_NONE,
1275 IW_PRIV_TYPE_NONE,
1276 "bt_reset"},
1277 {
1278 WLAN_SET128CHAR_GET128CHAR,
1279 IW_PRIV_TYPE_CHAR | 128,
1280 IW_PRIV_TYPE_CHAR | 128,
1281 ""},
1282 /* BT Management */
1283 {
1284 WLAN_SUBCMD_BT_ADD,
1285 IW_PRIV_TYPE_CHAR | 128,
1286 IW_PRIV_TYPE_CHAR | 128,
1287 "bt_add"},
1288 {
1289 WLAN_SUBCMD_BT_DEL,
1290 IW_PRIV_TYPE_CHAR | 128,
1291 IW_PRIV_TYPE_CHAR | 128,
1292 "bt_del"},
1293 {
1294 WLAN_SUBCMD_BT_LIST,
1295 IW_PRIV_TYPE_CHAR | 128,
1296 IW_PRIV_TYPE_CHAR | 128,
1297 "bt_list"},
1298 /* FWT Management */
1299 {
1300 WLAN_SUBCMD_FWT_ADD,
1301 IW_PRIV_TYPE_CHAR | 128,
1302 IW_PRIV_TYPE_CHAR | 128,
1303 "fwt_add"},
1304 {
1305 WLAN_SUBCMD_FWT_DEL,
1306 IW_PRIV_TYPE_CHAR | 128,
1307 IW_PRIV_TYPE_CHAR | 128,
1308 "fwt_del"},
1309 {
1310 WLAN_SUBCMD_FWT_LOOKUP,
1311 IW_PRIV_TYPE_CHAR | 128,
1312 IW_PRIV_TYPE_CHAR | 128,
1313 "fwt_lookup"},
1314 {
1315 WLAN_SUBCMD_FWT_LIST_NEIGHBOR,
1316 IW_PRIV_TYPE_CHAR | 128,
1317 IW_PRIV_TYPE_CHAR | 128,
1318 "fwt_list_neigh"},
1319 {
1320 WLAN_SUBCMD_FWT_LIST,
1321 IW_PRIV_TYPE_CHAR | 128,
1322 IW_PRIV_TYPE_CHAR | 128,
1323 "fwt_list"},
1324 {
1325 WLAN_SUBCMD_FWT_LIST_ROUTE,
1326 IW_PRIV_TYPE_CHAR | 128,
1327 IW_PRIV_TYPE_CHAR | 128,
1328 "fwt_list_route"},
1329 {
1330 WLANSCAN_MODE,
1331 IW_PRIV_TYPE_CHAR | 128,
1332 IW_PRIV_TYPE_CHAR | 128,
1333 "scanmode"},
1334 {
1335 WLAN_GET_ADHOC_STATUS,
1336 IW_PRIV_TYPE_CHAR | 128,
1337 IW_PRIV_TYPE_CHAR | 128,
1338 "getadhocstatus"},
1339 {
1340 WLAN_SETNONE_GETWORDCHAR,
1341 IW_PRIV_TYPE_NONE,
1342 IW_PRIV_TYPE_CHAR | 128,
1343 ""},
1344 {
1345 WLANSETWPAIE,
1346 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 24,
1347 IW_PRIV_TYPE_NONE,
1348 "setwpaie"},
1349 {
1350 WLANGETLOG,
1351 IW_PRIV_TYPE_NONE,
1352 IW_PRIV_TYPE_CHAR | GETLOG_BUFSIZE,
1353 "getlog"},
1354 {
1355 WLAN_SET_GET_SIXTEEN_INT,
1356 IW_PRIV_TYPE_INT | 16,
1357 IW_PRIV_TYPE_INT | 16,
1358 ""},
1359 {
1360 WLAN_TPCCFG,
1361 IW_PRIV_TYPE_INT | 16,
1362 IW_PRIV_TYPE_INT | 16,
1363 "tpccfg"},
1364 {
1365 WLAN_POWERCFG,
1366 IW_PRIV_TYPE_INT | 16,
1367 IW_PRIV_TYPE_INT | 16,
1368 "powercfg"},
1369 {
1370 WLAN_AUTO_FREQ_SET,
1371 IW_PRIV_TYPE_INT | 16,
1372 IW_PRIV_TYPE_INT | 16,
1373 "setafc"},
1374 {
1375 WLAN_AUTO_FREQ_GET,
1376 IW_PRIV_TYPE_INT | 16,
1377 IW_PRIV_TYPE_INT | 16,
1378 "getafc"},
1379 {
1380 WLAN_SCANPROBES,
1381 IW_PRIV_TYPE_INT | 16,
1382 IW_PRIV_TYPE_INT | 16,
1383 "scanprobes"},
1384 {
1385 WLAN_LED_GPIO_CTRL,
1386 IW_PRIV_TYPE_INT | 16,
1387 IW_PRIV_TYPE_INT | 16,
1388 "ledgpio"},
1389 {
1390 WLAN_ADAPT_RATESET,
1391 IW_PRIV_TYPE_INT | 16,
1392 IW_PRIV_TYPE_INT | 16,
1393 "rateadapt"},
1394 {
1395 WLAN_INACTIVITY_TIMEOUT,
1396 IW_PRIV_TYPE_INT | 16,
1397 IW_PRIV_TYPE_INT | 16,
1398 "inactivityto"},
1399 {
1400 WLANSNR,
1401 IW_PRIV_TYPE_INT | 16,
1402 IW_PRIV_TYPE_INT | 16,
1403 "getSNR"},
1404 {
1405 WLAN_GET_RATE,
1406 IW_PRIV_TYPE_INT | 16,
1407 IW_PRIV_TYPE_INT | 16,
1408 "getrate"},
1409 {
1410 WLAN_GET_RXINFO,
1411 IW_PRIV_TYPE_INT | 16,
1412 IW_PRIV_TYPE_INT | 16,
1413 "getrxinfo"},
1414};
1415
1416static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev)
1417{
1418 enum {
1419 POOR = 30,
1420 FAIR = 60,
1421 GOOD = 80,
1422 VERY_GOOD = 90,
1423 EXCELLENT = 95,
1424 PERFECT = 100
1425 };
1426 wlan_private *priv = dev->priv;
1427 wlan_adapter *adapter = priv->adapter;
1428 u32 rssi_qual;
1429 u32 tx_qual;
1430 u32 quality = 0;
1431 int stats_valid = 0;
1432 u8 rssi;
1433 u32 tx_retries;
1434
1435 ENTER();
1436
1437 priv->wstats.status = adapter->inframode;
1438
1439 /* If we're not associated, all quality values are meaningless */
1440 if (adapter->connect_status != libertas_connected)
1441 goto out;
1442
1443 /* Quality by RSSI */
1444 priv->wstats.qual.level =
1445 CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_NOAVG],
1446 adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
1447
1448 if (adapter->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
1449 priv->wstats.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
1450 } else {
1451 priv->wstats.qual.noise =
1452 CAL_NF(adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
1453 }
1454
1455 lbs_pr_debug(1, "Signal Level = %#x\n", priv->wstats.qual.level);
1456 lbs_pr_debug(1, "Noise = %#x\n", priv->wstats.qual.noise);
1457
1458 rssi = priv->wstats.qual.level - priv->wstats.qual.noise;
1459 if (rssi < 15)
1460 rssi_qual = rssi * POOR / 10;
1461 else if (rssi < 20)
1462 rssi_qual = (rssi - 15) * (FAIR - POOR) / 5 + POOR;
1463 else if (rssi < 30)
1464 rssi_qual = (rssi - 20) * (GOOD - FAIR) / 5 + FAIR;
1465 else if (rssi < 40)
1466 rssi_qual = (rssi - 30) * (VERY_GOOD - GOOD) /
1467 10 + GOOD;
1468 else
1469 rssi_qual = (rssi - 40) * (PERFECT - VERY_GOOD) /
1470 10 + VERY_GOOD;
1471 quality = rssi_qual;
1472
1473 /* Quality by TX errors */
1474 priv->wstats.discard.retries = priv->stats.tx_errors;
1475
1476 tx_retries = adapter->logmsg.retry;
1477
1478 if (tx_retries > 75)
1479 tx_qual = (90 - tx_retries) * POOR / 15;
1480 else if (tx_retries > 70)
1481 tx_qual = (75 - tx_retries) * (FAIR - POOR) / 5 + POOR;
1482 else if (tx_retries > 65)
1483 tx_qual = (70 - tx_retries) * (GOOD - FAIR) / 5 + FAIR;
1484 else if (tx_retries > 50)
1485 tx_qual = (65 - tx_retries) * (VERY_GOOD - GOOD) /
1486 15 + GOOD;
1487 else
1488 tx_qual = (50 - tx_retries) *
1489 (PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
1490 quality = min(quality, tx_qual);
1491
1492 priv->wstats.discard.code = adapter->logmsg.wepundecryptable;
1493 priv->wstats.discard.fragment = adapter->logmsg.fcserror;
1494 priv->wstats.discard.retries = tx_retries;
1495 priv->wstats.discard.misc = adapter->logmsg.ackfailure;
1496
1497 /* Calculate quality */
1498 priv->wstats.qual.qual = max(quality, (u32)100);
1499 priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1500 stats_valid = 1;
1501
1502 /* update stats asynchronously for future calls */
1503 libertas_prepare_and_send_command(priv, cmd_802_11_rssi, 0,
1504 0, 0, NULL);
1505 libertas_prepare_and_send_command(priv, cmd_802_11_get_log, 0,
1506 0, 0, NULL);
1507out:
1508 if (!stats_valid) {
1509 priv->wstats.miss.beacon = 0;
1510 priv->wstats.discard.retries = 0;
1511 priv->wstats.qual.qual = 0;
1512 priv->wstats.qual.level = 0;
1513 priv->wstats.qual.noise = 0;
1514 priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED;
1515 priv->wstats.qual.updated |= IW_QUAL_NOISE_INVALID |
1516 IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
1517 }
1518
1519 LEAVE ();
1520 return &priv->wstats;
1521
1522
1523}
1524
1525static int wlan_set_freq(struct net_device *dev, struct iw_request_info *info,
1526 struct iw_freq *fwrq, char *extra)
1527{
1528 int ret = 0;
1529 wlan_private *priv = dev->priv;
1530 wlan_adapter *adapter = priv->adapter;
1531 int rc = -EINPROGRESS; /* Call commit handler */
1532 struct chan_freq_power *cfp;
1533
1534 ENTER();
1535
1536 /*
1537 * If setting by frequency, convert to a channel
1538 */
1539 if (fwrq->e == 1) {
1540
1541 long f = fwrq->m / 100000;
1542 int c = 0;
1543
1544 cfp = find_cfp_by_band_and_freq(adapter, 0, f);
1545 if (!cfp) {
1546 lbs_pr_debug(1, "Invalid freq=%ld\n", f);
1547 return -EINVAL;
1548 }
1549
1550 c = (int)cfp->channel;
1551
1552 if (c < 0)
1553 return -EINVAL;
1554
1555 fwrq->e = 0;
1556 fwrq->m = c;
1557 }
1558
1559 /*
1560 * Setting by channel number
1561 */
1562 if (fwrq->m > 1000 || fwrq->e > 0) {
1563 rc = -EOPNOTSUPP;
1564 } else {
1565 int channel = fwrq->m;
1566
1567 cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, channel);
1568 if (!cfp) {
1569 rc = -EINVAL;
1570 } else {
1571 if (adapter->inframode == wlan802_11ibss) {
1572 rc = changeadhocchannel(priv, channel);
1573 /* If station is WEP enabled, send the
1574 * command to set WEP in firmware
1575 */
1576 if (adapter->secinfo.WEPstatus ==
1577 wlan802_11WEPenabled) {
1578 lbs_pr_debug(1, "set_freq: WEP enabled\n");
1579 ret = libertas_prepare_and_send_command(priv,
1580 cmd_802_11_set_wep,
1581 cmd_act_add,
1582 cmd_option_waitforrsp,
1583 0,
1584 NULL);
1585
1586 if (ret) {
1587 LEAVE();
1588 return ret;
1589 }
1590
1591 adapter->currentpacketfilter |=
1592 cmd_act_mac_wep_enable;
1593
1594 libertas_set_mac_packet_filter(priv);
1595 }
1596 } else {
1597 rc = -EOPNOTSUPP;
1598 }
1599 }
1600 }
1601
1602 LEAVE();
1603 return rc;
1604}
1605
1606/**
1607 * @brief use index to get the data rate
1608 *
1609 * @param index The index of data rate
1610 * @return data rate or 0
1611 */
1612u32 libertas_index_to_data_rate(u8 index)
1613{
1614 if (index >= sizeof(libertas_wlan_data_rates))
1615 index = 0;
1616
1617 return libertas_wlan_data_rates[index];
1618}
1619
1620/**
1621 * @brief use rate to get the index
1622 *
1623 * @param rate data rate
1624 * @return index or 0
1625 */
1626u8 libertas_data_rate_to_index(u32 rate)
1627{
1628 u8 *ptr;
1629
1630 if (rate)
1631 if ((ptr = memchr(libertas_wlan_data_rates, (u8) rate,
1632 sizeof(libertas_wlan_data_rates))))
1633 return (ptr - libertas_wlan_data_rates);
1634
1635 return 0;
1636}
1637
1638static int wlan_set_rate(struct net_device *dev, struct iw_request_info *info,
1639 struct iw_param *vwrq, char *extra)
1640{
1641 wlan_private *priv = dev->priv;
1642 wlan_adapter *adapter = priv->adapter;
1643 u32 data_rate;
1644 u16 action;
1645 int ret = 0;
1646 u8 rates[WLAN_SUPPORTED_RATES];
1647 u8 *rate;
1648
1649 ENTER();
1650
1651 lbs_pr_debug(1, "Vwrq->value = %d\n", vwrq->value);
1652
1653 if (vwrq->value == -1) {
1654 action = cmd_act_set_tx_auto; // Auto
1655 adapter->is_datarate_auto = 1;
1656 adapter->datarate = 0;
1657 } else {
1658 if (vwrq->value % 100000) {
1659 return -EINVAL;
1660 }
1661
1662 data_rate = vwrq->value / 500000;
1663
1664 memset(rates, 0, sizeof(rates));
1665 get_active_data_rates(adapter, rates);
1666 rate = rates;
1667 while (*rate) {
1668 lbs_pr_debug(1, "Rate=0x%X Wanted=0x%X\n", *rate,
1669 data_rate);
1670 if ((*rate & 0x7f) == (data_rate & 0x7f))
1671 break;
1672 rate++;
1673 }
1674 if (!*rate) {
1675 lbs_pr_alert( "The fixed data rate 0x%X is out "
1676 "of range.\n", data_rate);
1677 return -EINVAL;
1678 }
1679
1680 adapter->datarate = data_rate;
1681 action = cmd_act_set_tx_fix_rate;
1682 adapter->is_datarate_auto = 0;
1683 }
1684
1685 ret = libertas_prepare_and_send_command(priv, cmd_802_11_data_rate,
1686 action, cmd_option_waitforrsp, 0, NULL);
1687
1688 LEAVE();
1689 return ret;
1690}
1691
1692static int wlan_get_rate(struct net_device *dev, struct iw_request_info *info,
1693 struct iw_param *vwrq, char *extra)
1694{
1695 wlan_private *priv = dev->priv;
1696 wlan_adapter *adapter = priv->adapter;
1697
1698 ENTER();
1699
1700 if (adapter->is_datarate_auto) {
1701 vwrq->fixed = 0;
1702 } else {
1703 vwrq->fixed = 1;
1704 }
1705
1706 vwrq->value = adapter->datarate * 500000;
1707
1708 LEAVE();
1709 return 0;
1710}
1711
1712static int wlan_set_mode(struct net_device *dev,
1713 struct iw_request_info *info, u32 * uwrq, char *extra)
1714{
1715 int ret = 0;
1716 wlan_private *priv = dev->priv;
1717 wlan_adapter *adapter = priv->adapter;
1718 struct assoc_request * assoc_req;
1719 enum WLAN_802_11_NETWORK_INFRASTRUCTURE new_mode;
1720
1721 ENTER();
1722
1723 switch (*uwrq) {
1724 case IW_MODE_ADHOC:
1725 lbs_pr_debug(1, "Wanted mode is ad-hoc: current datarate=%#x\n",
1726 adapter->datarate);
1727 new_mode = wlan802_11ibss;
1728 adapter->adhocchannel = DEFAULT_AD_HOC_CHANNEL;
1729 break;
1730
1731 case IW_MODE_INFRA:
1732 lbs_pr_debug(1, "Wanted mode is Infrastructure\n");
1733 new_mode = wlan802_11infrastructure;
1734 break;
1735
1736 case IW_MODE_AUTO:
1737 lbs_pr_debug(1, "Wanted mode is Auto\n");
1738 new_mode = wlan802_11autounknown;
1739 break;
1740
1741 default:
1742 lbs_pr_debug(1, "Wanted mode is Unknown: 0x%x\n", *uwrq);
1743 return -EINVAL;
1744 }
1745
1746 mutex_lock(&adapter->lock);
1747 assoc_req = wlan_get_association_request(adapter);
1748 if (!assoc_req) {
1749 ret = -ENOMEM;
1750 } else {
1751 assoc_req->mode = new_mode;
1752 }
1753
1754 if (ret == 0) {
1755 set_bit(ASSOC_FLAG_MODE, &assoc_req->flags);
1756 wlan_postpone_association_work(priv);
1757 } else {
1758 wlan_cancel_association_work(priv);
1759 }
1760 mutex_unlock(&adapter->lock);
1761
1762 LEAVE();
1763 return ret;
1764}
1765
1766
1767/**
1768 * @brief Get Encryption key
1769 *
1770 * @param dev A pointer to net_device structure
1771 * @param info A pointer to iw_request_info structure
1772 * @param vwrq A pointer to iw_param structure
1773 * @param extra A pointer to extra data buf
1774 * @return 0 --success, otherwise fail
1775 */
1776static int wlan_get_encode(struct net_device *dev,
1777 struct iw_request_info *info,
1778 struct iw_point *dwrq, u8 * extra)
1779{
1780 wlan_private *priv = dev->priv;
1781 wlan_adapter *adapter = priv->adapter;
1782 int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
1783
1784 ENTER();
1785
1786 lbs_pr_debug(1, "flags=0x%x index=%d length=%d wep_tx_keyidx=%d\n",
1787 dwrq->flags, index, dwrq->length, adapter->wep_tx_keyidx);
1788
1789 dwrq->flags = 0;
1790
1791 /* Authentication method */
1792 switch (adapter->secinfo.authmode) {
1793 case wlan802_11authmodeopen:
1794 dwrq->flags = IW_ENCODE_OPEN;
1795 break;
1796
1797 case wlan802_11authmodeshared:
1798 case wlan802_11authmodenetworkEAP:
1799 dwrq->flags = IW_ENCODE_RESTRICTED;
1800 break;
1801 default:
1802 dwrq->flags = IW_ENCODE_DISABLED | IW_ENCODE_OPEN;
1803 break;
1804 }
1805
1806 if ((adapter->secinfo.WEPstatus == wlan802_11WEPenabled)
1807 || adapter->secinfo.WPAenabled || adapter->secinfo.WPA2enabled) {
1808 dwrq->flags &= ~IW_ENCODE_DISABLED;
1809 } else {
1810 dwrq->flags |= IW_ENCODE_DISABLED;
1811 }
1812
1813 memset(extra, 0, 16);
1814
1815 mutex_lock(&adapter->lock);
1816
1817 /* Default to returning current transmit key */
1818 if (index < 0)
1819 index = adapter->wep_tx_keyidx;
1820
1821 if ((adapter->wep_keys[index].len) &&
1822 (adapter->secinfo.WEPstatus == wlan802_11WEPenabled)) {
1823 memcpy(extra, adapter->wep_keys[index].key,
1824 adapter->wep_keys[index].len);
1825 dwrq->length = adapter->wep_keys[index].len;
1826
1827 dwrq->flags |= (index + 1);
1828 /* Return WEP enabled */
1829 dwrq->flags &= ~IW_ENCODE_DISABLED;
1830 } else if ((adapter->secinfo.WPAenabled)
1831 || (adapter->secinfo.WPA2enabled)) {
1832 /* return WPA enabled */
1833 dwrq->flags &= ~IW_ENCODE_DISABLED;
1834 } else {
1835 dwrq->flags |= IW_ENCODE_DISABLED;
1836 }
1837
1838 mutex_unlock(&adapter->lock);
1839
1840 dwrq->flags |= IW_ENCODE_NOKEY;
1841
1842 lbs_pr_debug(1, "key:%02x:%02x:%02x:%02x:%02x:%02x keylen=%d\n",
1843 extra[0], extra[1], extra[2],
1844 extra[3], extra[4], extra[5], dwrq->length);
1845
1846 lbs_pr_debug(1, "Return flags=0x%x\n", dwrq->flags);
1847
1848 LEAVE();
1849 return 0;
1850}
1851
1852/**
1853 * @brief Set Encryption key (internal)
1854 *
1855 * @param priv A pointer to private card structure
1856 * @param key_material A pointer to key material
1857 * @param key_length length of key material
1858 * @param index key index to set
1859 * @param set_tx_key Force set TX key (1 = yes, 0 = no)
1860 * @return 0 --success, otherwise fail
1861 */
1862static int wlan_set_wep_key(struct assoc_request *assoc_req,
1863 const char *key_material,
1864 u16 key_length,
1865 u16 index,
1866 int set_tx_key)
1867{
1868 struct WLAN_802_11_KEY *pkey;
1869
1870 ENTER();
1871
1872 /* Paranoid validation of key index */
1873 if (index > 3) {
1874 LEAVE();
1875 return -EINVAL;
1876 }
1877
1878 /* validate max key length */
1879 if (key_length > KEY_LEN_WEP_104) {
1880 LEAVE();
1881 return -EINVAL;
1882 }
1883
1884 pkey = &assoc_req->wep_keys[index];
1885
1886 if (key_length > 0) {
1887 memset(pkey, 0, sizeof(struct WLAN_802_11_KEY));
1888 pkey->type = KEY_TYPE_ID_WEP;
1889
1890 /* Standardize the key length */
1891 pkey->len = (key_length > KEY_LEN_WEP_40) ?
1892 KEY_LEN_WEP_104 : KEY_LEN_WEP_40;
1893 memcpy(pkey->key, key_material, key_length);
1894 }
1895
1896 if (set_tx_key) {
1897 /* Ensure the chosen key is valid */
1898 if (!pkey->len) {
1899 lbs_pr_debug(1, "key not set, so cannot enable it\n");
1900 LEAVE();
1901 return -EINVAL;
1902 }
1903 assoc_req->wep_tx_keyidx = index;
1904 }
1905
1906 assoc_req->secinfo.WEPstatus = wlan802_11WEPenabled;
1907
1908 LEAVE();
1909 return 0;
1910}
1911
1912static int validate_key_index(u16 def_index, u16 raw_index,
1913 u16 *out_index, u16 *is_default)
1914{
1915 if (!out_index || !is_default)
1916 return -EINVAL;
1917
1918 /* Verify index if present, otherwise use default TX key index */
1919 if (raw_index > 0) {
1920 if (raw_index > 4)
1921 return -EINVAL;
1922 *out_index = raw_index - 1;
1923 } else {
1924 *out_index = def_index;
1925 *is_default = 1;
1926 }
1927 return 0;
1928}
1929
1930static void disable_wep(struct assoc_request *assoc_req)
1931{
1932 int i;
1933
1934 /* Set Open System auth mode */
1935 assoc_req->secinfo.authmode = wlan802_11authmodeopen;
1936
1937 /* Clear WEP keys and mark WEP as disabled */
1938 assoc_req->secinfo.WEPstatus = wlan802_11WEPdisabled;
1939 for (i = 0; i < 4; i++)
1940 assoc_req->wep_keys[i].len = 0;
1941
1942 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
1943 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
1944}
1945
1946/**
1947 * @brief Set Encryption key
1948 *
1949 * @param dev A pointer to net_device structure
1950 * @param info A pointer to iw_request_info structure
1951 * @param vwrq A pointer to iw_param structure
1952 * @param extra A pointer to extra data buf
1953 * @return 0 --success, otherwise fail
1954 */
1955static int wlan_set_encode(struct net_device *dev,
1956 struct iw_request_info *info,
1957 struct iw_point *dwrq, char *extra)
1958{
1959 int ret = 0;
1960 wlan_private *priv = dev->priv;
1961 wlan_adapter *adapter = priv->adapter;
1962 struct assoc_request * assoc_req;
1963 u16 is_default = 0, index = 0, set_tx_key = 0;
1964
1965 ENTER();
1966
1967 mutex_lock(&adapter->lock);
1968 assoc_req = wlan_get_association_request(adapter);
1969 if (!assoc_req) {
1970 ret = -ENOMEM;
1971 goto out;
1972 }
1973
1974 if (dwrq->flags & IW_ENCODE_DISABLED) {
1975 disable_wep (assoc_req);
1976 goto out;
1977 }
1978
1979 ret = validate_key_index(assoc_req->wep_tx_keyidx,
1980 (dwrq->flags & IW_ENCODE_INDEX),
1981 &index, &is_default);
1982 if (ret) {
1983 ret = -EINVAL;
1984 goto out;
1985 }
1986
1987 /* If WEP isn't enabled, or if there is no key data but a valid
1988 * index, set the TX key.
1989 */
1990 if ((assoc_req->secinfo.WEPstatus != wlan802_11WEPenabled)
1991 || (dwrq->length == 0 && !is_default))
1992 set_tx_key = 1;
1993
1994 ret = wlan_set_wep_key(assoc_req, extra, dwrq->length, index, set_tx_key);
1995 if (ret)
1996 goto out;
1997
1998 if (dwrq->length)
1999 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
2000 if (set_tx_key)
2001 set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags);
2002
2003 if (dwrq->flags & IW_ENCODE_RESTRICTED) {
2004 assoc_req->secinfo.authmode = wlan802_11authmodeshared;
2005 } else if (dwrq->flags & IW_ENCODE_OPEN) {
2006 assoc_req->secinfo.authmode = wlan802_11authmodeopen;
2007 }
2008
2009out:
2010 if (ret == 0) {
2011 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
2012 wlan_postpone_association_work(priv);
2013 } else {
2014 wlan_cancel_association_work(priv);
2015 }
2016 mutex_unlock(&adapter->lock);
2017
2018 LEAVE();
2019 return ret;
2020}
2021
2022/**
2023 * @brief Get Extended Encryption key (WPA/802.1x and WEP)
2024 *
2025 * @param dev A pointer to net_device structure
2026 * @param info A pointer to iw_request_info structure
2027 * @param vwrq A pointer to iw_param structure
2028 * @param extra A pointer to extra data buf
2029 * @return 0 on success, otherwise failure
2030 */
2031static int wlan_get_encodeext(struct net_device *dev,
2032 struct iw_request_info *info,
2033 struct iw_point *dwrq,
2034 char *extra)
2035{
2036 int ret = -EINVAL;
2037 wlan_private *priv = dev->priv;
2038 wlan_adapter *adapter = priv->adapter;
2039 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
2040 int index, max_key_len;
2041
2042 ENTER();
2043
2044 max_key_len = dwrq->length - sizeof(*ext);
2045 if (max_key_len < 0)
2046 goto out;
2047
2048 index = dwrq->flags & IW_ENCODE_INDEX;
2049 if (index) {
2050 if (index < 1 || index > 4)
2051 goto out;
2052 index--;
2053 } else {
2054 index = adapter->wep_tx_keyidx;
2055 }
2056
2057 if (!ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY &&
2058 ext->alg != IW_ENCODE_ALG_WEP) {
2059 if (index != 0 || adapter->inframode != wlan802_11infrastructure)
2060 goto out;
2061 }
2062
2063 dwrq->flags = index + 1;
2064 memset(ext, 0, sizeof(*ext));
2065
2066 if ((adapter->secinfo.WEPstatus == wlan802_11WEPdisabled)
2067 && !adapter->secinfo.WPAenabled && !adapter->secinfo.WPA2enabled) {
2068 ext->alg = IW_ENCODE_ALG_NONE;
2069 ext->key_len = 0;
2070 dwrq->flags |= IW_ENCODE_DISABLED;
2071 } else {
2072 u8 *key = NULL;
2073
2074 if ((adapter->secinfo.WEPstatus == wlan802_11WEPenabled)
2075 && !adapter->secinfo.WPAenabled
2076 && !adapter->secinfo.WPA2enabled) {
2077 ext->alg = IW_ENCODE_ALG_WEP;
2078 ext->key_len = adapter->wep_keys[index].len;
2079 key = &adapter->wep_keys[index].key[0];
2080 } else if ((adapter->secinfo.WEPstatus == wlan802_11WEPdisabled) &&
2081 (adapter->secinfo.WPAenabled ||
2082 adapter->secinfo.WPA2enabled)) {
2083 /* WPA */
2084 ext->alg = IW_ENCODE_ALG_TKIP;
2085 ext->key_len = 0;
2086 } else {
2087 goto out;
2088 }
2089
2090 if (ext->key_len > max_key_len) {
2091 ret = -E2BIG;
2092 goto out;
2093 }
2094
2095 if (ext->key_len)
2096 memcpy(ext->key, key, ext->key_len);
2097 else
2098 dwrq->flags |= IW_ENCODE_NOKEY;
2099 dwrq->flags |= IW_ENCODE_ENABLED;
2100 }
2101 ret = 0;
2102
2103out:
2104 LEAVE();
2105 return ret;
2106}
2107
2108/**
2109 * @brief Set Encryption key Extended (WPA/802.1x and WEP)
2110 *
2111 * @param dev A pointer to net_device structure
2112 * @param info A pointer to iw_request_info structure
2113 * @param vwrq A pointer to iw_param structure
2114 * @param extra A pointer to extra data buf
2115 * @return 0 --success, otherwise fail
2116 */
2117static int wlan_set_encodeext(struct net_device *dev,
2118 struct iw_request_info *info,
2119 struct iw_point *dwrq,
2120 char *extra)
2121{
2122 int ret = 0;
2123 wlan_private *priv = dev->priv;
2124 wlan_adapter *adapter = priv->adapter;
2125 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
2126 int alg = ext->alg;
2127 struct assoc_request * assoc_req;
2128
2129 ENTER();
2130
2131 mutex_lock(&adapter->lock);
2132 assoc_req = wlan_get_association_request(adapter);
2133 if (!assoc_req) {
2134 ret = -ENOMEM;
2135 goto out;
2136 }
2137
2138 if ((alg == IW_ENCODE_ALG_NONE) || (dwrq->flags & IW_ENCODE_DISABLED)) {
2139 disable_wep (assoc_req);
2140 } else if (alg == IW_ENCODE_ALG_WEP) {
2141 u16 is_default = 0, index, set_tx_key = 0;
2142
2143 ret = validate_key_index(assoc_req->wep_tx_keyidx,
2144 (dwrq->flags & IW_ENCODE_INDEX),
2145 &index, &is_default);
2146 if (ret)
2147 goto out;
2148
2149 /* If WEP isn't enabled, or if there is no key data but a valid
2150 * index, or if the set-TX-key flag was passed, set the TX key.
2151 */
2152 if ((assoc_req->secinfo.WEPstatus != wlan802_11WEPenabled)
2153 || (dwrq->length == 0 && !is_default)
2154 || (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY))
2155 set_tx_key = 1;
2156
2157 /* Copy key to driver */
2158 ret = wlan_set_wep_key (assoc_req, ext->key, ext->key_len, index,
2159 set_tx_key);
2160 if (ret)
2161 goto out;
2162
2163 if (dwrq->flags & IW_ENCODE_RESTRICTED) {
2164 assoc_req->secinfo.authmode =
2165 wlan802_11authmodeshared;
2166 } else if (dwrq->flags & IW_ENCODE_OPEN) {
2167 assoc_req->secinfo.authmode =
2168 wlan802_11authmodeopen;
2169 }
2170
2171 /* Mark the various WEP bits as modified */
2172 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
2173 if (dwrq->length)
2174 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
2175 if (set_tx_key)
2176 set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags);
2177
2178 } else if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) {
2179 struct WLAN_802_11_KEY * pkey;
2180
2181 /* validate key length */
2182 if (((alg == IW_ENCODE_ALG_TKIP)
2183 && (ext->key_len != KEY_LEN_WPA_TKIP))
2184 || ((alg == IW_ENCODE_ALG_CCMP)
2185 && (ext->key_len != KEY_LEN_WPA_AES))) {
2186 lbs_pr_debug(1, "Invalid size %d for key of alg"
2187 "type %d.\n",
2188 ext->key_len,
2189 alg);
2190 ret = -EINVAL;
2191 goto out;
2192 }
2193
2194 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
2195 pkey = &assoc_req->wpa_mcast_key;
2196 else
2197 pkey = &assoc_req->wpa_unicast_key;
2198
2199 memset(pkey, 0, sizeof (struct WLAN_802_11_KEY));
2200 memcpy(pkey->key, ext->key, ext->key_len);
2201 pkey->len = ext->key_len;
2202 pkey->flags = KEY_INFO_WPA_ENABLED;
2203
2204 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
2205 pkey->flags |= KEY_INFO_WPA_MCAST;
2206 set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
2207 } else {
2208 pkey->flags |= KEY_INFO_WPA_UNICAST;
2209 set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
2210 }
2211
2212 if (alg == IW_ENCODE_ALG_TKIP)
2213 pkey->type = KEY_TYPE_ID_TKIP;
2214 else if (alg == IW_ENCODE_ALG_CCMP)
2215 pkey->type = KEY_TYPE_ID_AES;
2216
2217 /* If WPA isn't enabled yet, do that now */
2218 if ( assoc_req->secinfo.WPAenabled == 0
2219 && assoc_req->secinfo.WPA2enabled == 0) {
2220 assoc_req->secinfo.WPAenabled = 1;
2221 assoc_req->secinfo.WPA2enabled = 1;
2222 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
2223 }
2224
2225 disable_wep (assoc_req);
2226 }
2227
2228out:
2229 if (ret == 0) {
2230 wlan_postpone_association_work(priv);
2231 } else {
2232 wlan_cancel_association_work(priv);
2233 }
2234 mutex_unlock(&adapter->lock);
2235
2236 LEAVE();
2237 return ret;
2238}
2239
2240
2241static int wlan_set_genie(struct net_device *dev,
2242 struct iw_request_info *info,
2243 struct iw_point *dwrq,
2244 char *extra)
2245{
2246 wlan_private *priv = dev->priv;
2247 wlan_adapter *adapter = priv->adapter;
2248 int ret = 0;
2249 struct assoc_request * assoc_req;
2250
2251 ENTER();
2252
2253 mutex_lock(&adapter->lock);
2254 assoc_req = wlan_get_association_request(adapter);
2255 if (!assoc_req) {
2256 ret = -ENOMEM;
2257 goto out;
2258 }
2259
2260 if (dwrq->length > MAX_WPA_IE_LEN ||
2261 (dwrq->length && extra == NULL)) {
2262 ret = -EINVAL;
2263 goto out;
2264 }
2265
2266 if (dwrq->length) {
2267 memcpy(&assoc_req->wpa_ie[0], extra, dwrq->length);
2268 assoc_req->wpa_ie_len = dwrq->length;
2269 } else {
2270 memset(&assoc_req->wpa_ie[0], 0, sizeof(adapter->wpa_ie));
2271 assoc_req->wpa_ie_len = 0;
2272 }
2273
2274out:
2275 if (ret == 0) {
2276 set_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags);
2277 wlan_postpone_association_work(priv);
2278 } else {
2279 wlan_cancel_association_work(priv);
2280 }
2281 mutex_unlock(&adapter->lock);
2282
2283 LEAVE();
2284 return ret;
2285}
2286
2287static int wlan_get_genie(struct net_device *dev,
2288 struct iw_request_info *info,
2289 struct iw_point *dwrq,
2290 char *extra)
2291{
2292 wlan_private *priv = dev->priv;
2293 wlan_adapter *adapter = priv->adapter;
2294
2295 ENTER();
2296
2297 if (adapter->wpa_ie_len == 0) {
2298 dwrq->length = 0;
2299 LEAVE();
2300 return 0;
2301 }
2302
2303 if (dwrq->length < adapter->wpa_ie_len) {
2304 LEAVE();
2305 return -E2BIG;
2306 }
2307
2308 dwrq->length = adapter->wpa_ie_len;
2309 memcpy(extra, &adapter->wpa_ie[0], adapter->wpa_ie_len);
2310
2311 LEAVE();
2312 return 0;
2313}
2314
2315
2316static int wlan_set_auth(struct net_device *dev,
2317 struct iw_request_info *info,
2318 struct iw_param *dwrq,
2319 char *extra)
2320{
2321 wlan_private *priv = dev->priv;
2322 wlan_adapter *adapter = priv->adapter;
2323 struct assoc_request * assoc_req;
2324 int ret = 0;
2325 int updated = 0;
2326
2327 ENTER();
2328
2329 mutex_lock(&adapter->lock);
2330 assoc_req = wlan_get_association_request(adapter);
2331 if (!assoc_req) {
2332 ret = -ENOMEM;
2333 goto out;
2334 }
2335
2336 switch (dwrq->flags & IW_AUTH_INDEX) {
2337 case IW_AUTH_TKIP_COUNTERMEASURES:
2338 case IW_AUTH_CIPHER_PAIRWISE:
2339 case IW_AUTH_CIPHER_GROUP:
2340 case IW_AUTH_KEY_MGMT:
2341 /*
2342 * libertas does not use these parameters
2343 */
2344 break;
2345
2346 case IW_AUTH_WPA_VERSION:
2347 if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) {
2348 assoc_req->secinfo.WPAenabled = 0;
2349 assoc_req->secinfo.WPA2enabled = 0;
2350 }
2351 if (dwrq->value & IW_AUTH_WPA_VERSION_WPA) {
2352 assoc_req->secinfo.WPAenabled = 1;
2353 assoc_req->secinfo.WEPstatus = wlan802_11WEPdisabled;
2354 assoc_req->secinfo.authmode =
2355 wlan802_11authmodeopen;
2356 }
2357 if (dwrq->value & IW_AUTH_WPA_VERSION_WPA2) {
2358 assoc_req->secinfo.WPA2enabled = 1;
2359 assoc_req->secinfo.WEPstatus = wlan802_11WEPdisabled;
2360 assoc_req->secinfo.authmode =
2361 wlan802_11authmodeopen;
2362 }
2363 updated = 1;
2364 break;
2365
2366 case IW_AUTH_DROP_UNENCRYPTED:
2367 if (dwrq->value) {
2368 adapter->currentpacketfilter |=
2369 cmd_act_mac_strict_protection_enable;
2370 } else {
2371 adapter->currentpacketfilter &=
2372 ~cmd_act_mac_strict_protection_enable;
2373 }
2374 updated = 1;
2375 break;
2376
2377 case IW_AUTH_80211_AUTH_ALG:
2378 if (dwrq->value & IW_AUTH_ALG_SHARED_KEY) {
2379 assoc_req->secinfo.authmode =
2380 wlan802_11authmodeshared;
2381 } else if (dwrq->value & IW_AUTH_ALG_OPEN_SYSTEM) {
2382 assoc_req->secinfo.authmode =
2383 wlan802_11authmodeopen;
2384 } else if (dwrq->value & IW_AUTH_ALG_LEAP) {
2385 assoc_req->secinfo.authmode =
2386 wlan802_11authmodenetworkEAP;
2387 } else {
2388 ret = -EINVAL;
2389 }
2390 updated = 1;
2391 break;
2392
2393 case IW_AUTH_WPA_ENABLED:
2394 if (dwrq->value) {
2395 if (!assoc_req->secinfo.WPAenabled &&
2396 !assoc_req->secinfo.WPA2enabled) {
2397 assoc_req->secinfo.WPAenabled = 1;
2398 assoc_req->secinfo.WPA2enabled = 1;
2399 assoc_req->secinfo.WEPstatus = wlan802_11WEPdisabled;
2400 assoc_req->secinfo.authmode =
2401 wlan802_11authmodeopen;
2402 }
2403 } else {
2404 assoc_req->secinfo.WPAenabled = 0;
2405 assoc_req->secinfo.WPA2enabled = 0;
2406 }
2407 updated = 1;
2408 break;
2409
2410 default:
2411 ret = -EOPNOTSUPP;
2412 break;
2413 }
2414
2415out:
2416 if (ret == 0) {
2417 if (updated)
2418 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
2419 wlan_postpone_association_work(priv);
2420 } else if (ret != -EOPNOTSUPP) {
2421 wlan_cancel_association_work(priv);
2422 }
2423 mutex_unlock(&adapter->lock);
2424
2425 LEAVE();
2426 return ret;
2427}
2428
2429static int wlan_get_auth(struct net_device *dev,
2430 struct iw_request_info *info,
2431 struct iw_param *dwrq,
2432 char *extra)
2433{
2434 wlan_private *priv = dev->priv;
2435 wlan_adapter *adapter = priv->adapter;
2436
2437 ENTER();
2438
2439 switch (dwrq->flags & IW_AUTH_INDEX) {
2440 case IW_AUTH_WPA_VERSION:
2441 dwrq->value = 0;
2442 if (adapter->secinfo.WPAenabled)
2443 dwrq->value |= IW_AUTH_WPA_VERSION_WPA;
2444 if (adapter->secinfo.WPA2enabled)
2445 dwrq->value |= IW_AUTH_WPA_VERSION_WPA2;
2446 if (!dwrq->value)
2447 dwrq->value |= IW_AUTH_WPA_VERSION_DISABLED;
2448 break;
2449
2450 case IW_AUTH_DROP_UNENCRYPTED:
2451 dwrq->value = 0;
2452 if (adapter->currentpacketfilter &
2453 cmd_act_mac_strict_protection_enable)
2454 dwrq->value = 1;
2455 break;
2456
2457 case IW_AUTH_80211_AUTH_ALG:
2458 switch (adapter->secinfo.authmode) {
2459 case wlan802_11authmodeshared:
2460 dwrq->value = IW_AUTH_ALG_SHARED_KEY;
2461 break;
2462 case wlan802_11authmodeopen:
2463 dwrq->value = IW_AUTH_ALG_OPEN_SYSTEM;
2464 break;
2465 case wlan802_11authmodenetworkEAP:
2466 dwrq->value = IW_AUTH_ALG_LEAP;
2467 break;
2468 default:
2469 break;
2470 }
2471 break;
2472
2473 case IW_AUTH_WPA_ENABLED:
2474 if (adapter->secinfo.WPAenabled && adapter->secinfo.WPA2enabled)
2475 dwrq->value = 1;
2476 break;
2477
2478 default:
2479 LEAVE();
2480 return -EOPNOTSUPP;
2481 }
2482
2483 LEAVE();
2484 return 0;
2485}
2486
2487
2488static int wlan_set_txpow(struct net_device *dev, struct iw_request_info *info,
2489 struct iw_param *vwrq, char *extra)
2490{
2491 int ret = 0;
2492 wlan_private *priv = dev->priv;
2493 wlan_adapter *adapter = priv->adapter;
2494
2495 u16 dbm;
2496
2497 ENTER();
2498
2499 if (vwrq->disabled) {
2500 wlan_radio_ioctl(priv, RADIO_OFF);
2501 return 0;
2502 }
2503
2504 adapter->preamble = cmd_type_auto_preamble;
2505
2506 wlan_radio_ioctl(priv, RADIO_ON);
2507
2508 if ((vwrq->flags & IW_TXPOW_TYPE) == IW_TXPOW_MWATT) {
2509 dbm = (u16) mw_to_dbm(vwrq->value);
2510 } else
2511 dbm = (u16) vwrq->value;
2512
2513 /* auto tx power control */
2514
2515 if (vwrq->fixed == 0)
2516 dbm = 0xffff;
2517
2518 lbs_pr_debug(1, "<1>TXPOWER SET %d dbm.\n", dbm);
2519
2520 ret = libertas_prepare_and_send_command(priv,
2521 cmd_802_11_rf_tx_power,
2522 cmd_act_tx_power_opt_set_low,
2523 cmd_option_waitforrsp, 0, (void *)&dbm);
2524
2525 LEAVE();
2526 return ret;
2527}
2528
2529static int wlan_get_essid(struct net_device *dev, struct iw_request_info *info,
2530 struct iw_point *dwrq, char *extra)
2531{
2532 wlan_private *priv = dev->priv;
2533 wlan_adapter *adapter = priv->adapter;
2534
2535 ENTER();
2536 /*
2537 * Note : if dwrq->flags != 0, we should get the relevant SSID from
2538 * the SSID list...
2539 */
2540
2541 /*
2542 * Get the current SSID
2543 */
2544 if (adapter->connect_status == libertas_connected) {
2545 memcpy(extra, adapter->curbssparams.ssid.ssid,
2546 adapter->curbssparams.ssid.ssidlength);
2547 extra[adapter->curbssparams.ssid.ssidlength] = '\0';
2548 } else {
2549 memset(extra, 0, 32);
2550 extra[adapter->curbssparams.ssid.ssidlength] = '\0';
2551 }
2552 /*
2553 * If none, we may want to get the one that was set
2554 */
2555
2556 /* To make the driver backward compatible with WPA supplicant v0.2.4 */
2557 if (dwrq->length == 32) /* check with WPA supplicant buffer size */
2558 dwrq->length = min_t(size_t, adapter->curbssparams.ssid.ssidlength,
2559 IW_ESSID_MAX_SIZE);
2560 else
2561 dwrq->length = adapter->curbssparams.ssid.ssidlength + 1;
2562
2563 dwrq->flags = 1; /* active */
2564
2565 LEAVE();
2566 return 0;
2567}
2568
2569static int wlan_set_essid(struct net_device *dev, struct iw_request_info *info,
2570 struct iw_point *dwrq, char *extra)
2571{
2572 wlan_private *priv = dev->priv;
2573 wlan_adapter *adapter = priv->adapter;
2574 int ret = 0;
2575 struct WLAN_802_11_SSID ssid;
2576 struct assoc_request * assoc_req;
2577 int ssid_len = dwrq->length;
2578
2579 ENTER();
2580
2581 /*
2582 * WE-20 and earlier NULL pad the end of the SSID and increment
2583 * SSID length so it can be used like a string. WE-21 and later don't,
2584 * but some userspace tools aren't able to cope with the change.
2585 */
2586 if ((ssid_len > 0) && (extra[ssid_len - 1] == '\0'))
2587 ssid_len--;
2588
2589 /* Check the size of the string */
2590 if (ssid_len > IW_ESSID_MAX_SIZE) {
2591 ret = -E2BIG;
2592 goto out;
2593 }
2594
2595 memset(&ssid, 0, sizeof(struct WLAN_802_11_SSID));
2596
2597 if (!dwrq->flags || !ssid_len) {
2598 /* "any" SSID requested; leave SSID blank */
2599 } else {
2600 /* Specific SSID requested */
2601 memcpy(&ssid.ssid, extra, ssid_len);
2602 ssid.ssidlength = ssid_len;
2603 }
2604
2605 lbs_pr_debug(1, "Requested new SSID = %s\n",
2606 (ssid.ssidlength > 0) ? (char *)ssid.ssid : "any");
2607
2608out:
2609 mutex_lock(&adapter->lock);
2610 if (ret == 0) {
2611 /* Get or create the current association request */
2612 assoc_req = wlan_get_association_request(adapter);
2613 if (!assoc_req) {
2614 ret = -ENOMEM;
2615 } else {
2616 /* Copy the SSID to the association request */
2617 memcpy(&assoc_req->ssid, &ssid, sizeof(struct WLAN_802_11_SSID));
2618 set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
2619 wlan_postpone_association_work(priv);
2620 }
2621 }
2622
2623 /* Cancel the association request if there was an error */
2624 if (ret != 0) {
2625 wlan_cancel_association_work(priv);
2626 }
2627
2628 mutex_unlock(&adapter->lock);
2629
2630 LEAVE();
2631 return ret;
2632}
2633
2634/**
2635 * @brief Connect to the AP or Ad-hoc Network with specific bssid
2636 *
2637 * @param dev A pointer to net_device structure
2638 * @param info A pointer to iw_request_info structure
2639 * @param awrq A pointer to iw_param structure
2640 * @param extra A pointer to extra data buf
2641 * @return 0 --success, otherwise fail
2642 */
2643static int wlan_set_wap(struct net_device *dev, struct iw_request_info *info,
2644 struct sockaddr *awrq, char *extra)
2645{
2646 wlan_private *priv = dev->priv;
2647 wlan_adapter *adapter = priv->adapter;
2648 struct assoc_request * assoc_req;
2649 int ret = 0;
2650
2651 ENTER();
2652
2653 if (awrq->sa_family != ARPHRD_ETHER)
2654 return -EINVAL;
2655
2656 lbs_pr_debug(1, "ASSOC: WAP: sa_data: " MAC_FMT "\n", MAC_ARG(awrq->sa_data));
2657
2658 mutex_lock(&adapter->lock);
2659
2660 /* Get or create the current association request */
2661 assoc_req = wlan_get_association_request(adapter);
2662 if (!assoc_req) {
2663 wlan_cancel_association_work(priv);
2664 ret = -ENOMEM;
2665 } else {
2666 /* Copy the BSSID to the association request */
2667 memcpy(&assoc_req->bssid, awrq->sa_data, ETH_ALEN);
2668 set_bit(ASSOC_FLAG_BSSID, &assoc_req->flags);
2669 wlan_postpone_association_work(priv);
2670 }
2671
2672 mutex_unlock(&adapter->lock);
2673
2674 return ret;
2675}
2676
2677void libertas_get_fwversion(wlan_adapter * adapter, char *fwversion, int maxlen)
2678{
2679 union {
2680 u32 l;
2681 u8 c[4];
2682 } ver;
2683 char fwver[32];
2684
2685 mutex_lock(&adapter->lock);
2686 ver.l = adapter->fwreleasenumber;
2687 mutex_unlock(&adapter->lock);
2688
2689 if (ver.c[3] == 0)
2690 sprintf(fwver, "%u.%u.%u", ver.c[2], ver.c[1], ver.c[0]);
2691 else
2692 sprintf(fwver, "%u.%u.%u.p%u",
2693 ver.c[2], ver.c[1], ver.c[0], ver.c[3]);
2694
2695 snprintf(fwversion, maxlen, fwver);
2696}
2697
2698
2699/*
2700 * iwconfig settable callbacks
2701 */
2702static const iw_handler wlan_handler[] = {
2703 (iw_handler) NULL, /* SIOCSIWCOMMIT */
2704 (iw_handler) wlan_get_name, /* SIOCGIWNAME */
2705 (iw_handler) NULL, /* SIOCSIWNWID */
2706 (iw_handler) NULL, /* SIOCGIWNWID */
2707 (iw_handler) wlan_set_freq, /* SIOCSIWFREQ */
2708 (iw_handler) wlan_get_freq, /* SIOCGIWFREQ */
2709 (iw_handler) wlan_set_mode, /* SIOCSIWMODE */
2710 (iw_handler) wlan_get_mode, /* SIOCGIWMODE */
2711 (iw_handler) NULL, /* SIOCSIWSENS */
2712 (iw_handler) NULL, /* SIOCGIWSENS */
2713 (iw_handler) NULL, /* SIOCSIWRANGE */
2714 (iw_handler) wlan_get_range, /* SIOCGIWRANGE */
2715 (iw_handler) NULL, /* SIOCSIWPRIV */
2716 (iw_handler) NULL, /* SIOCGIWPRIV */
2717 (iw_handler) NULL, /* SIOCSIWSTATS */
2718 (iw_handler) NULL, /* SIOCGIWSTATS */
2719 iw_handler_set_spy, /* SIOCSIWSPY */
2720 iw_handler_get_spy, /* SIOCGIWSPY */
2721 iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
2722 iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
2723 (iw_handler) wlan_set_wap, /* SIOCSIWAP */
2724 (iw_handler) wlan_get_wap, /* SIOCGIWAP */
2725 (iw_handler) NULL, /* SIOCSIWMLME */
2726 (iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */
2727 (iw_handler) libertas_set_scan, /* SIOCSIWSCAN */
2728 (iw_handler) libertas_get_scan, /* SIOCGIWSCAN */
2729 (iw_handler) wlan_set_essid, /* SIOCSIWESSID */
2730 (iw_handler) wlan_get_essid, /* SIOCGIWESSID */
2731 (iw_handler) wlan_set_nick, /* SIOCSIWNICKN */
2732 (iw_handler) wlan_get_nick, /* SIOCGIWNICKN */
2733 (iw_handler) NULL, /* -- hole -- */
2734 (iw_handler) NULL, /* -- hole -- */
2735 (iw_handler) wlan_set_rate, /* SIOCSIWRATE */
2736 (iw_handler) wlan_get_rate, /* SIOCGIWRATE */
2737 (iw_handler) wlan_set_rts, /* SIOCSIWRTS */
2738 (iw_handler) wlan_get_rts, /* SIOCGIWRTS */
2739 (iw_handler) wlan_set_frag, /* SIOCSIWFRAG */
2740 (iw_handler) wlan_get_frag, /* SIOCGIWFRAG */
2741 (iw_handler) wlan_set_txpow, /* SIOCSIWTXPOW */
2742 (iw_handler) wlan_get_txpow, /* SIOCGIWTXPOW */
2743 (iw_handler) wlan_set_retry, /* SIOCSIWRETRY */
2744 (iw_handler) wlan_get_retry, /* SIOCGIWRETRY */
2745 (iw_handler) wlan_set_encode, /* SIOCSIWENCODE */
2746 (iw_handler) wlan_get_encode, /* SIOCGIWENCODE */
2747 (iw_handler) wlan_set_power, /* SIOCSIWPOWER */
2748 (iw_handler) wlan_get_power, /* SIOCGIWPOWER */
2749 (iw_handler) NULL, /* -- hole -- */
2750 (iw_handler) NULL, /* -- hole -- */
2751 (iw_handler) wlan_set_genie, /* SIOCSIWGENIE */
2752 (iw_handler) wlan_get_genie, /* SIOCGIWGENIE */
2753 (iw_handler) wlan_set_auth, /* SIOCSIWAUTH */
2754 (iw_handler) wlan_get_auth, /* SIOCGIWAUTH */
2755 (iw_handler) wlan_set_encodeext,/* SIOCSIWENCODEEXT */
2756 (iw_handler) wlan_get_encodeext,/* SIOCGIWENCODEEXT */
2757 (iw_handler) NULL, /* SIOCSIWPMKSA */
2758};
2759
2760struct iw_handler_def libertas_handler_def = {
2761 .num_standard = sizeof(wlan_handler) / sizeof(iw_handler),
2762 .num_private = sizeof(wlan_private_handler) / sizeof(iw_handler),
2763 .num_private_args = sizeof(wlan_private_args) /
2764 sizeof(struct iw_priv_args),
2765 .standard = (iw_handler *) wlan_handler,
2766 .private = (iw_handler *) wlan_private_handler,
2767 .private_args = (struct iw_priv_args *)wlan_private_args,
2768 .get_wireless_stats = wlan_get_wireless_stats,
2769};