wireless: checkpatch cleanups
[linux-2.6/mini2440.git] / drivers / net / wireless / libertas / wext.c
blob19c2873d2d78fcd418573912f2bb488e4fcb7f7b
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>
11 #include <net/ieee80211.h>
12 #include <net/iw_handler.h>
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 "wext.h"
21 #include "assoc.h"
24 static inline void libertas_postpone_association_work(wlan_private *priv)
26 if (priv->adapter->surpriseremoved)
27 return;
28 cancel_delayed_work(&priv->assoc_work);
29 queue_delayed_work(priv->work_thread, &priv->assoc_work, HZ / 2);
32 static inline void libertas_cancel_association_work(wlan_private *priv)
34 cancel_delayed_work(&priv->assoc_work);
35 kfree(priv->adapter->pending_assoc_req);
36 priv->adapter->pending_assoc_req = NULL;
40 /**
41 * @brief Find the channel frequency power info with specific channel
43 * @param adapter A pointer to wlan_adapter structure
44 * @param band it can be BAND_A, BAND_G or BAND_B
45 * @param channel the channel for looking
46 * @return A pointer to struct chan_freq_power structure or NULL if not find.
48 struct chan_freq_power *libertas_find_cfp_by_band_and_channel(wlan_adapter * adapter,
49 u8 band, u16 channel)
51 struct chan_freq_power *cfp = NULL;
52 struct region_channel *rc;
53 int i, j;
55 for (j = 0; !cfp && (j < ARRAY_SIZE(adapter->region_channel)); j++) {
56 rc = &adapter->region_channel[j];
58 if (adapter->enable11d)
59 rc = &adapter->universal_channel[j];
60 if (!rc->valid || !rc->CFP)
61 continue;
62 if (rc->band != band)
63 continue;
64 for (i = 0; i < rc->nrcfp; i++) {
65 if (rc->CFP[i].channel == channel) {
66 cfp = &rc->CFP[i];
67 break;
72 if (!cfp && channel)
73 lbs_deb_wext("libertas_find_cfp_by_band_and_channel: can't find "
74 "cfp by band %d / channel %d\n", band, channel);
76 return cfp;
79 /**
80 * @brief Find the channel frequency power info with specific frequency
82 * @param adapter A pointer to wlan_adapter structure
83 * @param band it can be BAND_A, BAND_G or BAND_B
84 * @param freq the frequency for looking
85 * @return A pointer to struct chan_freq_power structure or NULL if not find.
87 static struct chan_freq_power *find_cfp_by_band_and_freq(wlan_adapter * adapter,
88 u8 band, u32 freq)
90 struct chan_freq_power *cfp = NULL;
91 struct region_channel *rc;
92 int i, j;
94 for (j = 0; !cfp && (j < ARRAY_SIZE(adapter->region_channel)); j++) {
95 rc = &adapter->region_channel[j];
97 if (adapter->enable11d)
98 rc = &adapter->universal_channel[j];
99 if (!rc->valid || !rc->CFP)
100 continue;
101 if (rc->band != band)
102 continue;
103 for (i = 0; i < rc->nrcfp; i++) {
104 if (rc->CFP[i].freq == freq) {
105 cfp = &rc->CFP[i];
106 break;
111 if (!cfp && freq)
112 lbs_deb_wext("find_cfp_by_band_and_freql: can't find cfp by "
113 "band %d / freq %d\n", band, freq);
115 return cfp;
120 * @brief Set Radio On/OFF
122 * @param priv A pointer to wlan_private structure
123 * @option Radio Option
124 * @return 0 --success, otherwise fail
126 static int wlan_radio_ioctl(wlan_private * priv, u8 option)
128 int ret = 0;
129 wlan_adapter *adapter = priv->adapter;
131 lbs_deb_enter(LBS_DEB_WEXT);
133 if (adapter->radioon != option) {
134 lbs_deb_wext("switching radio %s\n", option ? "on" : "off");
135 adapter->radioon = option;
137 ret = libertas_prepare_and_send_command(priv,
138 CMD_802_11_RADIO_CONTROL,
139 CMD_ACT_SET,
140 CMD_OPTION_WAITFORRSP, 0, NULL);
143 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
144 return ret;
148 * @brief Copy active data rates based on adapter mode and status
150 * @param adapter A pointer to wlan_adapter structure
151 * @param rate The buf to return the active rates
153 static void copy_active_data_rates(wlan_adapter * adapter, u8 * rates)
155 lbs_deb_enter(LBS_DEB_WEXT);
157 if (adapter->connect_status != LIBERTAS_CONNECTED)
158 memcpy(rates, libertas_bg_rates, MAX_RATES);
159 else
160 memcpy(rates, adapter->curbssparams.rates, MAX_RATES);
162 lbs_deb_leave(LBS_DEB_WEXT);
165 static int wlan_get_name(struct net_device *dev, struct iw_request_info *info,
166 char *cwrq, char *extra)
169 lbs_deb_enter(LBS_DEB_WEXT);
171 /* We could add support for 802.11n here as needed. Jean II */
172 snprintf(cwrq, IFNAMSIZ, "IEEE 802.11b/g");
174 lbs_deb_leave(LBS_DEB_WEXT);
175 return 0;
178 static int wlan_get_freq(struct net_device *dev, struct iw_request_info *info,
179 struct iw_freq *fwrq, char *extra)
181 wlan_private *priv = dev->priv;
182 wlan_adapter *adapter = priv->adapter;
183 struct chan_freq_power *cfp;
185 lbs_deb_enter(LBS_DEB_WEXT);
187 cfp = libertas_find_cfp_by_band_and_channel(adapter, 0,
188 adapter->curbssparams.channel);
190 if (!cfp) {
191 if (adapter->curbssparams.channel)
192 lbs_deb_wext("invalid channel %d\n",
193 adapter->curbssparams.channel);
194 return -EINVAL;
197 fwrq->m = (long)cfp->freq * 100000;
198 fwrq->e = 1;
200 lbs_deb_wext("freq %u\n", fwrq->m);
201 lbs_deb_leave(LBS_DEB_WEXT);
202 return 0;
205 static int wlan_get_wap(struct net_device *dev, struct iw_request_info *info,
206 struct sockaddr *awrq, char *extra)
208 wlan_private *priv = dev->priv;
209 wlan_adapter *adapter = priv->adapter;
211 lbs_deb_enter(LBS_DEB_WEXT);
213 if (adapter->connect_status == LIBERTAS_CONNECTED) {
214 memcpy(awrq->sa_data, adapter->curbssparams.bssid, ETH_ALEN);
215 } else {
216 memset(awrq->sa_data, 0, ETH_ALEN);
218 awrq->sa_family = ARPHRD_ETHER;
220 lbs_deb_leave(LBS_DEB_WEXT);
221 return 0;
224 static int wlan_set_nick(struct net_device *dev, struct iw_request_info *info,
225 struct iw_point *dwrq, char *extra)
227 wlan_private *priv = dev->priv;
228 wlan_adapter *adapter = priv->adapter;
230 lbs_deb_enter(LBS_DEB_WEXT);
233 * Check the size of the string
236 if (dwrq->length > 16) {
237 return -E2BIG;
240 mutex_lock(&adapter->lock);
241 memset(adapter->nodename, 0, sizeof(adapter->nodename));
242 memcpy(adapter->nodename, extra, dwrq->length);
243 mutex_unlock(&adapter->lock);
245 lbs_deb_leave(LBS_DEB_WEXT);
246 return 0;
249 static int wlan_get_nick(struct net_device *dev, struct iw_request_info *info,
250 struct iw_point *dwrq, char *extra)
252 wlan_private *priv = dev->priv;
253 wlan_adapter *adapter = priv->adapter;
255 lbs_deb_enter(LBS_DEB_WEXT);
257 dwrq->length = strlen(adapter->nodename);
258 memcpy(extra, adapter->nodename, dwrq->length);
259 extra[dwrq->length] = '\0';
261 dwrq->flags = 1; /* active */
263 lbs_deb_leave(LBS_DEB_WEXT);
264 return 0;
267 static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info,
268 struct iw_point *dwrq, char *extra)
270 wlan_private *priv = dev->priv;
271 wlan_adapter *adapter = priv->adapter;
273 lbs_deb_enter(LBS_DEB_WEXT);
275 /* Use nickname to indicate that mesh is on */
277 if (adapter->connect_status == LIBERTAS_CONNECTED) {
278 strncpy(extra, "Mesh", 12);
279 extra[12] = '\0';
280 dwrq->length = strlen(extra);
283 else {
284 extra[0] = '\0';
285 dwrq->length = 0;
288 lbs_deb_leave(LBS_DEB_WEXT);
289 return 0;
292 static int wlan_set_rts(struct net_device *dev, struct iw_request_info *info,
293 struct iw_param *vwrq, char *extra)
295 int ret = 0;
296 wlan_private *priv = dev->priv;
297 wlan_adapter *adapter = priv->adapter;
298 u32 rthr = vwrq->value;
300 lbs_deb_enter(LBS_DEB_WEXT);
302 if (vwrq->disabled) {
303 adapter->rtsthsd = rthr = MRVDRV_RTS_MAX_VALUE;
304 } else {
305 if (rthr < MRVDRV_RTS_MIN_VALUE || rthr > MRVDRV_RTS_MAX_VALUE)
306 return -EINVAL;
307 adapter->rtsthsd = rthr;
310 ret = libertas_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
311 CMD_ACT_SET, CMD_OPTION_WAITFORRSP,
312 OID_802_11_RTS_THRESHOLD, &rthr);
314 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
315 return ret;
318 static int wlan_get_rts(struct net_device *dev, struct iw_request_info *info,
319 struct iw_param *vwrq, char *extra)
321 int ret = 0;
322 wlan_private *priv = dev->priv;
323 wlan_adapter *adapter = priv->adapter;
325 lbs_deb_enter(LBS_DEB_WEXT);
327 adapter->rtsthsd = 0;
328 ret = libertas_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
329 CMD_ACT_GET, CMD_OPTION_WAITFORRSP,
330 OID_802_11_RTS_THRESHOLD, NULL);
331 if (ret)
332 goto out;
334 vwrq->value = adapter->rtsthsd;
335 vwrq->disabled = ((vwrq->value < MRVDRV_RTS_MIN_VALUE)
336 || (vwrq->value > MRVDRV_RTS_MAX_VALUE));
337 vwrq->fixed = 1;
339 out:
340 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
341 return ret;
344 static int wlan_set_frag(struct net_device *dev, struct iw_request_info *info,
345 struct iw_param *vwrq, char *extra)
347 int ret = 0;
348 u32 fthr = vwrq->value;
349 wlan_private *priv = dev->priv;
350 wlan_adapter *adapter = priv->adapter;
352 lbs_deb_enter(LBS_DEB_WEXT);
354 if (vwrq->disabled) {
355 adapter->fragthsd = fthr = MRVDRV_FRAG_MAX_VALUE;
356 } else {
357 if (fthr < MRVDRV_FRAG_MIN_VALUE
358 || fthr > MRVDRV_FRAG_MAX_VALUE)
359 return -EINVAL;
360 adapter->fragthsd = fthr;
363 ret = libertas_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
364 CMD_ACT_SET, CMD_OPTION_WAITFORRSP,
365 OID_802_11_FRAGMENTATION_THRESHOLD, &fthr);
367 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
368 return ret;
371 static int wlan_get_frag(struct net_device *dev, struct iw_request_info *info,
372 struct iw_param *vwrq, char *extra)
374 int ret = 0;
375 wlan_private *priv = dev->priv;
376 wlan_adapter *adapter = priv->adapter;
378 lbs_deb_enter(LBS_DEB_WEXT);
380 adapter->fragthsd = 0;
381 ret = libertas_prepare_and_send_command(priv,
382 CMD_802_11_SNMP_MIB,
383 CMD_ACT_GET, CMD_OPTION_WAITFORRSP,
384 OID_802_11_FRAGMENTATION_THRESHOLD, NULL);
385 if (ret)
386 goto out;
388 vwrq->value = adapter->fragthsd;
389 vwrq->disabled = ((vwrq->value < MRVDRV_FRAG_MIN_VALUE)
390 || (vwrq->value > MRVDRV_FRAG_MAX_VALUE));
391 vwrq->fixed = 1;
393 out:
394 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
395 return ret;
398 static int wlan_get_mode(struct net_device *dev,
399 struct iw_request_info *info, u32 * uwrq, char *extra)
401 wlan_private *priv = dev->priv;
402 wlan_adapter *adapter = priv->adapter;
404 lbs_deb_enter(LBS_DEB_WEXT);
406 *uwrq = adapter->mode;
408 lbs_deb_leave(LBS_DEB_WEXT);
409 return 0;
412 static int mesh_wlan_get_mode(struct net_device *dev,
413 struct iw_request_info *info, u32 * uwrq,
414 char *extra)
416 lbs_deb_enter(LBS_DEB_WEXT);
418 *uwrq = IW_MODE_REPEAT ;
420 lbs_deb_leave(LBS_DEB_WEXT);
421 return 0;
424 static int wlan_get_txpow(struct net_device *dev,
425 struct iw_request_info *info,
426 struct iw_param *vwrq, char *extra)
428 int ret = 0;
429 wlan_private *priv = dev->priv;
430 wlan_adapter *adapter = priv->adapter;
432 lbs_deb_enter(LBS_DEB_WEXT);
434 ret = libertas_prepare_and_send_command(priv,
435 CMD_802_11_RF_TX_POWER,
436 CMD_ACT_TX_POWER_OPT_GET,
437 CMD_OPTION_WAITFORRSP, 0, NULL);
439 if (ret)
440 goto out;
442 lbs_deb_wext("tx power level %d dbm\n", adapter->txpowerlevel);
443 vwrq->value = adapter->txpowerlevel;
444 vwrq->fixed = 1;
445 if (adapter->radioon) {
446 vwrq->disabled = 0;
447 vwrq->flags = IW_TXPOW_DBM;
448 } else {
449 vwrq->disabled = 1;
452 out:
453 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
454 return ret;
457 static int wlan_set_retry(struct net_device *dev, struct iw_request_info *info,
458 struct iw_param *vwrq, char *extra)
460 int ret = 0;
461 wlan_private *priv = dev->priv;
462 wlan_adapter *adapter = priv->adapter;
464 lbs_deb_enter(LBS_DEB_WEXT);
466 if (vwrq->flags == IW_RETRY_LIMIT) {
467 /* The MAC has a 4-bit Total_Tx_Count register
468 Total_Tx_Count = 1 + Tx_Retry_Count */
469 #define TX_RETRY_MIN 0
470 #define TX_RETRY_MAX 14
471 if (vwrq->value < TX_RETRY_MIN || vwrq->value > TX_RETRY_MAX)
472 return -EINVAL;
474 /* Adding 1 to convert retry count to try count */
475 adapter->txretrycount = vwrq->value + 1;
477 ret = libertas_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
478 CMD_ACT_SET,
479 CMD_OPTION_WAITFORRSP,
480 OID_802_11_TX_RETRYCOUNT, NULL);
482 if (ret)
483 goto out;
484 } else {
485 return -EOPNOTSUPP;
488 out:
489 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
490 return ret;
493 static int wlan_get_retry(struct net_device *dev, struct iw_request_info *info,
494 struct iw_param *vwrq, char *extra)
496 wlan_private *priv = dev->priv;
497 wlan_adapter *adapter = priv->adapter;
498 int ret = 0;
500 lbs_deb_enter(LBS_DEB_WEXT);
502 adapter->txretrycount = 0;
503 ret = libertas_prepare_and_send_command(priv,
504 CMD_802_11_SNMP_MIB,
505 CMD_ACT_GET, CMD_OPTION_WAITFORRSP,
506 OID_802_11_TX_RETRYCOUNT, NULL);
507 if (ret)
508 goto out;
510 vwrq->disabled = 0;
511 if (!vwrq->flags) {
512 vwrq->flags = IW_RETRY_LIMIT;
513 /* Subtract 1 to convert try count to retry count */
514 vwrq->value = adapter->txretrycount - 1;
517 out:
518 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
519 return ret;
522 static inline void sort_channels(struct iw_freq *freq, int num)
524 int i, j;
525 struct iw_freq temp;
527 for (i = 0; i < num; i++)
528 for (j = i + 1; j < num; j++)
529 if (freq[i].i > freq[j].i) {
530 temp.i = freq[i].i;
531 temp.m = freq[i].m;
533 freq[i].i = freq[j].i;
534 freq[i].m = freq[j].m;
536 freq[j].i = temp.i;
537 freq[j].m = temp.m;
541 /* data rate listing
542 MULTI_BANDS:
543 abg a b b/g
544 Infra G(12) A(8) B(4) G(12)
545 Adhoc A+B(12) A(8) B(4) B(4)
547 non-MULTI_BANDS:
548 b b/g
549 Infra B(4) G(12)
550 Adhoc B(4) B(4)
553 * @brief Get Range Info
555 * @param dev A pointer to net_device structure
556 * @param info A pointer to iw_request_info structure
557 * @param vwrq A pointer to iw_param structure
558 * @param extra A pointer to extra data buf
559 * @return 0 --success, otherwise fail
561 static int wlan_get_range(struct net_device *dev, struct iw_request_info *info,
562 struct iw_point *dwrq, char *extra)
564 int i, j;
565 wlan_private *priv = dev->priv;
566 wlan_adapter *adapter = priv->adapter;
567 struct iw_range *range = (struct iw_range *)extra;
568 struct chan_freq_power *cfp;
569 u8 rates[MAX_RATES + 1];
571 u8 flag = 0;
573 lbs_deb_enter(LBS_DEB_WEXT);
575 dwrq->length = sizeof(struct iw_range);
576 memset(range, 0, sizeof(struct iw_range));
578 range->min_nwid = 0;
579 range->max_nwid = 0;
581 memset(rates, 0, sizeof(rates));
582 copy_active_data_rates(adapter, rates);
583 range->num_bitrates = strnlen(rates, IW_MAX_BITRATES);
584 for (i = 0; i < range->num_bitrates; i++)
585 range->bitrate[i] = rates[i] * 500000;
586 range->num_bitrates = i;
587 lbs_deb_wext("IW_MAX_BITRATES %d, num_bitrates %d\n", IW_MAX_BITRATES,
588 range->num_bitrates);
590 range->num_frequency = 0;
591 if (priv->adapter->enable11d &&
592 adapter->connect_status == LIBERTAS_CONNECTED) {
593 u8 chan_no;
594 u8 band;
596 struct parsed_region_chan_11d *parsed_region_chan =
597 &adapter->parsed_region_chan;
599 if (parsed_region_chan == NULL) {
600 lbs_deb_wext("11d: parsed_region_chan is NULL\n");
601 goto out;
603 band = parsed_region_chan->band;
604 lbs_deb_wext("band %d, nr_char %d\n", band,
605 parsed_region_chan->nr_chan);
607 for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
608 && (i < parsed_region_chan->nr_chan); i++) {
609 chan_no = parsed_region_chan->chanpwr[i].chan;
610 lbs_deb_wext("chan_no %d\n", chan_no);
611 range->freq[range->num_frequency].i = (long)chan_no;
612 range->freq[range->num_frequency].m =
613 (long)libertas_chan_2_freq(chan_no, band) * 100000;
614 range->freq[range->num_frequency].e = 1;
615 range->num_frequency++;
617 flag = 1;
619 if (!flag) {
620 for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
621 && (j < ARRAY_SIZE(adapter->region_channel)); j++) {
622 cfp = adapter->region_channel[j].CFP;
623 for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
624 && adapter->region_channel[j].valid
625 && cfp
626 && (i < adapter->region_channel[j].nrcfp); i++) {
627 range->freq[range->num_frequency].i =
628 (long)cfp->channel;
629 range->freq[range->num_frequency].m =
630 (long)cfp->freq * 100000;
631 range->freq[range->num_frequency].e = 1;
632 cfp++;
633 range->num_frequency++;
638 lbs_deb_wext("IW_MAX_FREQUENCIES %d, num_frequency %d\n",
639 IW_MAX_FREQUENCIES, range->num_frequency);
641 range->num_channels = range->num_frequency;
643 sort_channels(&range->freq[0], range->num_frequency);
646 * Set an indication of the max TCP throughput in bit/s that we can
647 * expect using this interface
649 if (i > 2)
650 range->throughput = 5000 * 1000;
651 else
652 range->throughput = 1500 * 1000;
654 range->min_rts = MRVDRV_RTS_MIN_VALUE;
655 range->max_rts = MRVDRV_RTS_MAX_VALUE;
656 range->min_frag = MRVDRV_FRAG_MIN_VALUE;
657 range->max_frag = MRVDRV_FRAG_MAX_VALUE;
659 range->encoding_size[0] = 5;
660 range->encoding_size[1] = 13;
661 range->num_encoding_sizes = 2;
662 range->max_encoding_tokens = 4;
664 range->min_pmp = 1000000;
665 range->max_pmp = 120000000;
666 range->min_pmt = 1000;
667 range->max_pmt = 1000000;
668 range->pmp_flags = IW_POWER_PERIOD;
669 range->pmt_flags = IW_POWER_TIMEOUT;
670 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
673 * Minimum version we recommend
675 range->we_version_source = 15;
678 * Version we are compiled with
680 range->we_version_compiled = WIRELESS_EXT;
682 range->retry_capa = IW_RETRY_LIMIT;
683 range->retry_flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
685 range->min_retry = TX_RETRY_MIN;
686 range->max_retry = TX_RETRY_MAX;
689 * Set the qual, level and noise range values
691 range->max_qual.qual = 100;
692 range->max_qual.level = 0;
693 range->max_qual.noise = 0;
694 range->max_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
696 range->avg_qual.qual = 70;
697 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
698 range->avg_qual.level = 0;
699 range->avg_qual.noise = 0;
700 range->avg_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
702 range->sensitivity = 0;
705 * Setup the supported power level ranges
707 memset(range->txpower, 0, sizeof(range->txpower));
708 range->txpower[0] = 5;
709 range->txpower[1] = 7;
710 range->txpower[2] = 9;
711 range->txpower[3] = 11;
712 range->txpower[4] = 13;
713 range->txpower[5] = 15;
714 range->txpower[6] = 17;
715 range->txpower[7] = 19;
717 range->num_txpower = 8;
718 range->txpower_capa = IW_TXPOW_DBM;
719 range->txpower_capa |= IW_TXPOW_RANGE;
721 range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
722 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
723 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
724 range->event_capa[1] = IW_EVENT_CAPA_K_1;
726 if (adapter->fwcapinfo & FW_CAPINFO_WPA) {
727 range->enc_capa = IW_ENC_CAPA_WPA
728 | IW_ENC_CAPA_WPA2
729 | IW_ENC_CAPA_CIPHER_TKIP
730 | IW_ENC_CAPA_CIPHER_CCMP;
733 out:
734 lbs_deb_leave(LBS_DEB_WEXT);
735 return 0;
738 static int wlan_set_power(struct net_device *dev, struct iw_request_info *info,
739 struct iw_param *vwrq, char *extra)
741 wlan_private *priv = dev->priv;
742 wlan_adapter *adapter = priv->adapter;
744 lbs_deb_enter(LBS_DEB_WEXT);
746 /* PS is currently supported only in Infrastructure mode
747 * Remove this check if it is to be supported in IBSS mode also
750 if (vwrq->disabled) {
751 adapter->psmode = WLAN802_11POWERMODECAM;
752 if (adapter->psstate != PS_STATE_FULL_POWER) {
753 libertas_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
756 return 0;
759 if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
760 lbs_deb_wext(
761 "setting power timeout is not supported\n");
762 return -EINVAL;
763 } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
764 lbs_deb_wext("setting power period not supported\n");
765 return -EINVAL;
768 if (adapter->psmode != WLAN802_11POWERMODECAM) {
769 return 0;
772 adapter->psmode = WLAN802_11POWERMODEMAX_PSP;
774 if (adapter->connect_status == LIBERTAS_CONNECTED) {
775 libertas_ps_sleep(priv, CMD_OPTION_WAITFORRSP);
778 lbs_deb_leave(LBS_DEB_WEXT);
779 return 0;
782 static int wlan_get_power(struct net_device *dev, struct iw_request_info *info,
783 struct iw_param *vwrq, char *extra)
785 wlan_private *priv = dev->priv;
786 wlan_adapter *adapter = priv->adapter;
787 int mode;
789 lbs_deb_enter(LBS_DEB_WEXT);
791 mode = adapter->psmode;
793 if ((vwrq->disabled = (mode == WLAN802_11POWERMODECAM))
794 || adapter->connect_status == LIBERTAS_DISCONNECTED)
796 goto out;
799 vwrq->value = 0;
801 out:
802 lbs_deb_leave(LBS_DEB_WEXT);
803 return 0;
806 static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev)
808 enum {
809 POOR = 30,
810 FAIR = 60,
811 GOOD = 80,
812 VERY_GOOD = 90,
813 EXCELLENT = 95,
814 PERFECT = 100
816 wlan_private *priv = dev->priv;
817 wlan_adapter *adapter = priv->adapter;
818 u32 rssi_qual;
819 u32 tx_qual;
820 u32 quality = 0;
821 int stats_valid = 0;
822 u8 rssi;
823 u32 tx_retries;
825 lbs_deb_enter(LBS_DEB_WEXT);
827 priv->wstats.status = adapter->mode;
829 /* If we're not associated, all quality values are meaningless */
830 if (adapter->connect_status != LIBERTAS_CONNECTED)
831 goto out;
833 /* Quality by RSSI */
834 priv->wstats.qual.level =
835 CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_NOAVG],
836 adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
838 if (adapter->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
839 priv->wstats.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
840 } else {
841 priv->wstats.qual.noise =
842 CAL_NF(adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
845 lbs_deb_wext("signal level %#x\n", priv->wstats.qual.level);
846 lbs_deb_wext("noise %#x\n", priv->wstats.qual.noise);
848 rssi = priv->wstats.qual.level - priv->wstats.qual.noise;
849 if (rssi < 15)
850 rssi_qual = rssi * POOR / 10;
851 else if (rssi < 20)
852 rssi_qual = (rssi - 15) * (FAIR - POOR) / 5 + POOR;
853 else if (rssi < 30)
854 rssi_qual = (rssi - 20) * (GOOD - FAIR) / 5 + FAIR;
855 else if (rssi < 40)
856 rssi_qual = (rssi - 30) * (VERY_GOOD - GOOD) /
857 10 + GOOD;
858 else
859 rssi_qual = (rssi - 40) * (PERFECT - VERY_GOOD) /
860 10 + VERY_GOOD;
861 quality = rssi_qual;
863 /* Quality by TX errors */
864 priv->wstats.discard.retries = priv->stats.tx_errors;
866 tx_retries = le32_to_cpu(adapter->logmsg.retry);
868 if (tx_retries > 75)
869 tx_qual = (90 - tx_retries) * POOR / 15;
870 else if (tx_retries > 70)
871 tx_qual = (75 - tx_retries) * (FAIR - POOR) / 5 + POOR;
872 else if (tx_retries > 65)
873 tx_qual = (70 - tx_retries) * (GOOD - FAIR) / 5 + FAIR;
874 else if (tx_retries > 50)
875 tx_qual = (65 - tx_retries) * (VERY_GOOD - GOOD) /
876 15 + GOOD;
877 else
878 tx_qual = (50 - tx_retries) *
879 (PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
880 quality = min(quality, tx_qual);
882 priv->wstats.discard.code = le32_to_cpu(adapter->logmsg.wepundecryptable);
883 priv->wstats.discard.fragment = le32_to_cpu(adapter->logmsg.rxfrag);
884 priv->wstats.discard.retries = tx_retries;
885 priv->wstats.discard.misc = le32_to_cpu(adapter->logmsg.ackfailure);
887 /* Calculate quality */
888 priv->wstats.qual.qual = min_t(u8, quality, 100);
889 priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
890 stats_valid = 1;
892 /* update stats asynchronously for future calls */
893 libertas_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
894 0, 0, NULL);
895 libertas_prepare_and_send_command(priv, CMD_802_11_GET_LOG, 0,
896 0, 0, NULL);
897 out:
898 if (!stats_valid) {
899 priv->wstats.miss.beacon = 0;
900 priv->wstats.discard.retries = 0;
901 priv->wstats.qual.qual = 0;
902 priv->wstats.qual.level = 0;
903 priv->wstats.qual.noise = 0;
904 priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED;
905 priv->wstats.qual.updated |= IW_QUAL_NOISE_INVALID |
906 IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
909 lbs_deb_leave(LBS_DEB_WEXT);
910 return &priv->wstats;
915 static int wlan_set_freq(struct net_device *dev, struct iw_request_info *info,
916 struct iw_freq *fwrq, char *extra)
918 int ret = -EINVAL;
919 wlan_private *priv = dev->priv;
920 wlan_adapter *adapter = priv->adapter;
921 struct chan_freq_power *cfp;
922 struct assoc_request * assoc_req;
924 lbs_deb_enter(LBS_DEB_WEXT);
926 mutex_lock(&adapter->lock);
927 assoc_req = wlan_get_association_request(adapter);
928 if (!assoc_req) {
929 ret = -ENOMEM;
930 goto out;
933 /* If setting by frequency, convert to a channel */
934 if (fwrq->e == 1) {
935 long f = fwrq->m / 100000;
937 cfp = find_cfp_by_band_and_freq(adapter, 0, f);
938 if (!cfp) {
939 lbs_deb_wext("invalid freq %ld\n", f);
940 goto out;
943 fwrq->e = 0;
944 fwrq->m = (int) cfp->channel;
947 /* Setting by channel number */
948 if (fwrq->m > 1000 || fwrq->e > 0) {
949 goto out;
952 cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, fwrq->m);
953 if (!cfp) {
954 goto out;
957 assoc_req->channel = fwrq->m;
958 ret = 0;
960 out:
961 if (ret == 0) {
962 set_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags);
963 libertas_postpone_association_work(priv);
964 } else {
965 libertas_cancel_association_work(priv);
967 mutex_unlock(&adapter->lock);
969 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
970 return ret;
973 static int wlan_set_rate(struct net_device *dev, struct iw_request_info *info,
974 struct iw_param *vwrq, char *extra)
976 wlan_private *priv = dev->priv;
977 wlan_adapter *adapter = priv->adapter;
978 u32 new_rate;
979 u16 action;
980 int ret = -EINVAL;
981 u8 rates[MAX_RATES + 1];
983 lbs_deb_enter(LBS_DEB_WEXT);
984 lbs_deb_wext("vwrq->value %d\n", vwrq->value);
986 /* Auto rate? */
987 if (vwrq->value == -1) {
988 action = CMD_ACT_SET_TX_AUTO;
989 adapter->auto_rate = 1;
990 adapter->cur_rate = 0;
991 } else {
992 if (vwrq->value % 100000)
993 goto out;
995 memset(rates, 0, sizeof(rates));
996 copy_active_data_rates(adapter, rates);
997 new_rate = vwrq->value / 500000;
998 if (!memchr(rates, new_rate, sizeof(rates))) {
999 lbs_pr_alert("fixed data rate 0x%X out of range\n",
1000 new_rate);
1001 goto out;
1004 adapter->cur_rate = new_rate;
1005 action = CMD_ACT_SET_TX_FIX_RATE;
1006 adapter->auto_rate = 0;
1009 ret = libertas_prepare_and_send_command(priv, CMD_802_11_DATA_RATE,
1010 action, CMD_OPTION_WAITFORRSP, 0, NULL);
1012 out:
1013 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1014 return ret;
1017 static int wlan_get_rate(struct net_device *dev, struct iw_request_info *info,
1018 struct iw_param *vwrq, char *extra)
1020 wlan_private *priv = dev->priv;
1021 wlan_adapter *adapter = priv->adapter;
1023 lbs_deb_enter(LBS_DEB_WEXT);
1025 if (adapter->connect_status == LIBERTAS_CONNECTED) {
1026 vwrq->value = adapter->cur_rate * 500000;
1028 if (adapter->auto_rate)
1029 vwrq->fixed = 0;
1030 else
1031 vwrq->fixed = 1;
1033 } else {
1034 vwrq->fixed = 0;
1035 vwrq->value = 0;
1038 lbs_deb_leave(LBS_DEB_WEXT);
1039 return 0;
1042 static int wlan_set_mode(struct net_device *dev,
1043 struct iw_request_info *info, u32 * uwrq, char *extra)
1045 int ret = 0;
1046 wlan_private *priv = dev->priv;
1047 wlan_adapter *adapter = priv->adapter;
1048 struct assoc_request * assoc_req;
1050 lbs_deb_enter(LBS_DEB_WEXT);
1052 if ( (*uwrq != IW_MODE_ADHOC)
1053 && (*uwrq != IW_MODE_INFRA)
1054 && (*uwrq != IW_MODE_AUTO)) {
1055 lbs_deb_wext("Invalid mode: 0x%x\n", *uwrq);
1056 ret = -EINVAL;
1057 goto out;
1060 mutex_lock(&adapter->lock);
1061 assoc_req = wlan_get_association_request(adapter);
1062 if (!assoc_req) {
1063 ret = -ENOMEM;
1064 libertas_cancel_association_work(priv);
1065 } else {
1066 assoc_req->mode = *uwrq;
1067 set_bit(ASSOC_FLAG_MODE, &assoc_req->flags);
1068 libertas_postpone_association_work(priv);
1069 lbs_deb_wext("Switching to mode: 0x%x\n", *uwrq);
1071 mutex_unlock(&adapter->lock);
1073 out:
1074 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1075 return ret;
1080 * @brief Get Encryption key
1082 * @param dev A pointer to net_device structure
1083 * @param info A pointer to iw_request_info structure
1084 * @param vwrq A pointer to iw_param structure
1085 * @param extra A pointer to extra data buf
1086 * @return 0 --success, otherwise fail
1088 static int wlan_get_encode(struct net_device *dev,
1089 struct iw_request_info *info,
1090 struct iw_point *dwrq, u8 * extra)
1092 wlan_private *priv = dev->priv;
1093 wlan_adapter *adapter = priv->adapter;
1094 int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
1096 lbs_deb_enter(LBS_DEB_WEXT);
1098 lbs_deb_wext("flags 0x%x, index %d, length %d, wep_tx_keyidx %d\n",
1099 dwrq->flags, index, dwrq->length, adapter->wep_tx_keyidx);
1101 dwrq->flags = 0;
1103 /* Authentication method */
1104 switch (adapter->secinfo.auth_mode) {
1105 case IW_AUTH_ALG_OPEN_SYSTEM:
1106 dwrq->flags = IW_ENCODE_OPEN;
1107 break;
1109 case IW_AUTH_ALG_SHARED_KEY:
1110 case IW_AUTH_ALG_LEAP:
1111 dwrq->flags = IW_ENCODE_RESTRICTED;
1112 break;
1113 default:
1114 dwrq->flags = IW_ENCODE_DISABLED | IW_ENCODE_OPEN;
1115 break;
1118 if ( adapter->secinfo.wep_enabled
1119 || adapter->secinfo.WPAenabled
1120 || adapter->secinfo.WPA2enabled) {
1121 dwrq->flags &= ~IW_ENCODE_DISABLED;
1122 } else {
1123 dwrq->flags |= IW_ENCODE_DISABLED;
1126 memset(extra, 0, 16);
1128 mutex_lock(&adapter->lock);
1130 /* Default to returning current transmit key */
1131 if (index < 0)
1132 index = adapter->wep_tx_keyidx;
1134 if ((adapter->wep_keys[index].len) && adapter->secinfo.wep_enabled) {
1135 memcpy(extra, adapter->wep_keys[index].key,
1136 adapter->wep_keys[index].len);
1137 dwrq->length = adapter->wep_keys[index].len;
1139 dwrq->flags |= (index + 1);
1140 /* Return WEP enabled */
1141 dwrq->flags &= ~IW_ENCODE_DISABLED;
1142 } else if ((adapter->secinfo.WPAenabled)
1143 || (adapter->secinfo.WPA2enabled)) {
1144 /* return WPA enabled */
1145 dwrq->flags &= ~IW_ENCODE_DISABLED;
1146 } else {
1147 dwrq->flags |= IW_ENCODE_DISABLED;
1150 mutex_unlock(&adapter->lock);
1152 dwrq->flags |= IW_ENCODE_NOKEY;
1154 lbs_deb_wext("key: %02x:%02x:%02x:%02x:%02x:%02x, keylen %d\n",
1155 extra[0], extra[1], extra[2],
1156 extra[3], extra[4], extra[5], dwrq->length);
1158 lbs_deb_wext("return flags 0x%x\n", dwrq->flags);
1160 lbs_deb_leave(LBS_DEB_WEXT);
1161 return 0;
1165 * @brief Set Encryption key (internal)
1167 * @param priv A pointer to private card structure
1168 * @param key_material A pointer to key material
1169 * @param key_length length of key material
1170 * @param index key index to set
1171 * @param set_tx_key Force set TX key (1 = yes, 0 = no)
1172 * @return 0 --success, otherwise fail
1174 static int wlan_set_wep_key(struct assoc_request *assoc_req,
1175 const char *key_material,
1176 u16 key_length,
1177 u16 index,
1178 int set_tx_key)
1180 int ret = 0;
1181 struct enc_key *pkey;
1183 lbs_deb_enter(LBS_DEB_WEXT);
1185 /* Paranoid validation of key index */
1186 if (index > 3) {
1187 ret = -EINVAL;
1188 goto out;
1191 /* validate max key length */
1192 if (key_length > KEY_LEN_WEP_104) {
1193 ret = -EINVAL;
1194 goto out;
1197 pkey = &assoc_req->wep_keys[index];
1199 if (key_length > 0) {
1200 memset(pkey, 0, sizeof(struct enc_key));
1201 pkey->type = KEY_TYPE_ID_WEP;
1203 /* Standardize the key length */
1204 pkey->len = (key_length > KEY_LEN_WEP_40) ?
1205 KEY_LEN_WEP_104 : KEY_LEN_WEP_40;
1206 memcpy(pkey->key, key_material, key_length);
1209 if (set_tx_key) {
1210 /* Ensure the chosen key is valid */
1211 if (!pkey->len) {
1212 lbs_deb_wext("key not set, so cannot enable it\n");
1213 ret = -EINVAL;
1214 goto out;
1216 assoc_req->wep_tx_keyidx = index;
1219 assoc_req->secinfo.wep_enabled = 1;
1221 out:
1222 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1223 return ret;
1226 static int validate_key_index(u16 def_index, u16 raw_index,
1227 u16 *out_index, u16 *is_default)
1229 if (!out_index || !is_default)
1230 return -EINVAL;
1232 /* Verify index if present, otherwise use default TX key index */
1233 if (raw_index > 0) {
1234 if (raw_index > 4)
1235 return -EINVAL;
1236 *out_index = raw_index - 1;
1237 } else {
1238 *out_index = def_index;
1239 *is_default = 1;
1241 return 0;
1244 static void disable_wep(struct assoc_request *assoc_req)
1246 int i;
1248 lbs_deb_enter(LBS_DEB_WEXT);
1250 /* Set Open System auth mode */
1251 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1253 /* Clear WEP keys and mark WEP as disabled */
1254 assoc_req->secinfo.wep_enabled = 0;
1255 for (i = 0; i < 4; i++)
1256 assoc_req->wep_keys[i].len = 0;
1258 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
1259 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
1261 lbs_deb_leave(LBS_DEB_WEXT);
1264 static void disable_wpa(struct assoc_request *assoc_req)
1266 lbs_deb_enter(LBS_DEB_WEXT);
1268 memset(&assoc_req->wpa_mcast_key, 0, sizeof (struct enc_key));
1269 assoc_req->wpa_mcast_key.flags = KEY_INFO_WPA_MCAST;
1270 set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
1272 memset(&assoc_req->wpa_unicast_key, 0, sizeof (struct enc_key));
1273 assoc_req->wpa_unicast_key.flags = KEY_INFO_WPA_UNICAST;
1274 set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
1276 assoc_req->secinfo.WPAenabled = 0;
1277 assoc_req->secinfo.WPA2enabled = 0;
1278 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
1280 lbs_deb_leave(LBS_DEB_WEXT);
1284 * @brief Set Encryption key
1286 * @param dev A pointer to net_device structure
1287 * @param info A pointer to iw_request_info structure
1288 * @param vwrq A pointer to iw_param structure
1289 * @param extra A pointer to extra data buf
1290 * @return 0 --success, otherwise fail
1292 static int wlan_set_encode(struct net_device *dev,
1293 struct iw_request_info *info,
1294 struct iw_point *dwrq, char *extra)
1296 int ret = 0;
1297 wlan_private *priv = dev->priv;
1298 wlan_adapter *adapter = priv->adapter;
1299 struct assoc_request * assoc_req;
1300 u16 is_default = 0, index = 0, set_tx_key = 0;
1302 lbs_deb_enter(LBS_DEB_WEXT);
1304 mutex_lock(&adapter->lock);
1305 assoc_req = wlan_get_association_request(adapter);
1306 if (!assoc_req) {
1307 ret = -ENOMEM;
1308 goto out;
1311 if (dwrq->flags & IW_ENCODE_DISABLED) {
1312 disable_wep (assoc_req);
1313 disable_wpa (assoc_req);
1314 goto out;
1317 ret = validate_key_index(assoc_req->wep_tx_keyidx,
1318 (dwrq->flags & IW_ENCODE_INDEX),
1319 &index, &is_default);
1320 if (ret) {
1321 ret = -EINVAL;
1322 goto out;
1325 /* If WEP isn't enabled, or if there is no key data but a valid
1326 * index, set the TX key.
1328 if (!assoc_req->secinfo.wep_enabled || (dwrq->length == 0 && !is_default))
1329 set_tx_key = 1;
1331 ret = wlan_set_wep_key(assoc_req, extra, dwrq->length, index, set_tx_key);
1332 if (ret)
1333 goto out;
1335 if (dwrq->length)
1336 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
1337 if (set_tx_key)
1338 set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags);
1340 if (dwrq->flags & IW_ENCODE_RESTRICTED) {
1341 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
1342 } else if (dwrq->flags & IW_ENCODE_OPEN) {
1343 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1346 out:
1347 if (ret == 0) {
1348 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
1349 libertas_postpone_association_work(priv);
1350 } else {
1351 libertas_cancel_association_work(priv);
1353 mutex_unlock(&adapter->lock);
1355 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1356 return ret;
1360 * @brief Get Extended Encryption key (WPA/802.1x and WEP)
1362 * @param dev A pointer to net_device structure
1363 * @param info A pointer to iw_request_info structure
1364 * @param vwrq A pointer to iw_param structure
1365 * @param extra A pointer to extra data buf
1366 * @return 0 on success, otherwise failure
1368 static int wlan_get_encodeext(struct net_device *dev,
1369 struct iw_request_info *info,
1370 struct iw_point *dwrq,
1371 char *extra)
1373 int ret = -EINVAL;
1374 wlan_private *priv = dev->priv;
1375 wlan_adapter *adapter = priv->adapter;
1376 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1377 int index, max_key_len;
1379 lbs_deb_enter(LBS_DEB_WEXT);
1381 max_key_len = dwrq->length - sizeof(*ext);
1382 if (max_key_len < 0)
1383 goto out;
1385 index = dwrq->flags & IW_ENCODE_INDEX;
1386 if (index) {
1387 if (index < 1 || index > 4)
1388 goto out;
1389 index--;
1390 } else {
1391 index = adapter->wep_tx_keyidx;
1394 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
1395 ext->alg != IW_ENCODE_ALG_WEP) {
1396 if (index != 0 || adapter->mode != IW_MODE_INFRA)
1397 goto out;
1400 dwrq->flags = index + 1;
1401 memset(ext, 0, sizeof(*ext));
1403 if ( !adapter->secinfo.wep_enabled
1404 && !adapter->secinfo.WPAenabled
1405 && !adapter->secinfo.WPA2enabled) {
1406 ext->alg = IW_ENCODE_ALG_NONE;
1407 ext->key_len = 0;
1408 dwrq->flags |= IW_ENCODE_DISABLED;
1409 } else {
1410 u8 *key = NULL;
1412 if ( adapter->secinfo.wep_enabled
1413 && !adapter->secinfo.WPAenabled
1414 && !adapter->secinfo.WPA2enabled) {
1415 /* WEP */
1416 ext->alg = IW_ENCODE_ALG_WEP;
1417 ext->key_len = adapter->wep_keys[index].len;
1418 key = &adapter->wep_keys[index].key[0];
1419 } else if ( !adapter->secinfo.wep_enabled
1420 && (adapter->secinfo.WPAenabled ||
1421 adapter->secinfo.WPA2enabled)) {
1422 /* WPA */
1423 struct enc_key * pkey = NULL;
1425 if ( adapter->wpa_mcast_key.len
1426 && (adapter->wpa_mcast_key.flags & KEY_INFO_WPA_ENABLED))
1427 pkey = &adapter->wpa_mcast_key;
1428 else if ( adapter->wpa_unicast_key.len
1429 && (adapter->wpa_unicast_key.flags & KEY_INFO_WPA_ENABLED))
1430 pkey = &adapter->wpa_unicast_key;
1432 if (pkey) {
1433 if (pkey->type == KEY_TYPE_ID_AES) {
1434 ext->alg = IW_ENCODE_ALG_CCMP;
1435 } else {
1436 ext->alg = IW_ENCODE_ALG_TKIP;
1438 ext->key_len = pkey->len;
1439 key = &pkey->key[0];
1440 } else {
1441 ext->alg = IW_ENCODE_ALG_TKIP;
1442 ext->key_len = 0;
1444 } else {
1445 goto out;
1448 if (ext->key_len > max_key_len) {
1449 ret = -E2BIG;
1450 goto out;
1453 if (ext->key_len)
1454 memcpy(ext->key, key, ext->key_len);
1455 else
1456 dwrq->flags |= IW_ENCODE_NOKEY;
1457 dwrq->flags |= IW_ENCODE_ENABLED;
1459 ret = 0;
1461 out:
1462 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1463 return ret;
1467 * @brief Set Encryption key Extended (WPA/802.1x and WEP)
1469 * @param dev A pointer to net_device structure
1470 * @param info A pointer to iw_request_info structure
1471 * @param vwrq A pointer to iw_param structure
1472 * @param extra A pointer to extra data buf
1473 * @return 0 --success, otherwise fail
1475 static int wlan_set_encodeext(struct net_device *dev,
1476 struct iw_request_info *info,
1477 struct iw_point *dwrq,
1478 char *extra)
1480 int ret = 0;
1481 wlan_private *priv = dev->priv;
1482 wlan_adapter *adapter = priv->adapter;
1483 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1484 int alg = ext->alg;
1485 struct assoc_request * assoc_req;
1487 lbs_deb_enter(LBS_DEB_WEXT);
1489 mutex_lock(&adapter->lock);
1490 assoc_req = wlan_get_association_request(adapter);
1491 if (!assoc_req) {
1492 ret = -ENOMEM;
1493 goto out;
1496 if ((alg == IW_ENCODE_ALG_NONE) || (dwrq->flags & IW_ENCODE_DISABLED)) {
1497 disable_wep (assoc_req);
1498 disable_wpa (assoc_req);
1499 } else if (alg == IW_ENCODE_ALG_WEP) {
1500 u16 is_default = 0, index, set_tx_key = 0;
1502 ret = validate_key_index(assoc_req->wep_tx_keyidx,
1503 (dwrq->flags & IW_ENCODE_INDEX),
1504 &index, &is_default);
1505 if (ret)
1506 goto out;
1508 /* If WEP isn't enabled, or if there is no key data but a valid
1509 * index, or if the set-TX-key flag was passed, set the TX key.
1511 if ( !assoc_req->secinfo.wep_enabled
1512 || (dwrq->length == 0 && !is_default)
1513 || (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY))
1514 set_tx_key = 1;
1516 /* Copy key to driver */
1517 ret = wlan_set_wep_key (assoc_req, ext->key, ext->key_len, index,
1518 set_tx_key);
1519 if (ret)
1520 goto out;
1522 if (dwrq->flags & IW_ENCODE_RESTRICTED) {
1523 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
1524 } else if (dwrq->flags & IW_ENCODE_OPEN) {
1525 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1528 /* Mark the various WEP bits as modified */
1529 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
1530 if (dwrq->length)
1531 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
1532 if (set_tx_key)
1533 set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags);
1534 } else if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) {
1535 struct enc_key * pkey;
1537 /* validate key length */
1538 if (((alg == IW_ENCODE_ALG_TKIP)
1539 && (ext->key_len != KEY_LEN_WPA_TKIP))
1540 || ((alg == IW_ENCODE_ALG_CCMP)
1541 && (ext->key_len != KEY_LEN_WPA_AES))) {
1542 lbs_deb_wext("invalid size %d for key of alg "
1543 "type %d\n",
1544 ext->key_len,
1545 alg);
1546 ret = -EINVAL;
1547 goto out;
1550 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1551 pkey = &assoc_req->wpa_mcast_key;
1552 set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
1553 } else {
1554 pkey = &assoc_req->wpa_unicast_key;
1555 set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
1558 memset(pkey, 0, sizeof (struct enc_key));
1559 memcpy(pkey->key, ext->key, ext->key_len);
1560 pkey->len = ext->key_len;
1561 if (pkey->len)
1562 pkey->flags |= KEY_INFO_WPA_ENABLED;
1564 /* Do this after zeroing key structure */
1565 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1566 pkey->flags |= KEY_INFO_WPA_MCAST;
1567 } else {
1568 pkey->flags |= KEY_INFO_WPA_UNICAST;
1571 if (alg == IW_ENCODE_ALG_TKIP) {
1572 pkey->type = KEY_TYPE_ID_TKIP;
1573 } else if (alg == IW_ENCODE_ALG_CCMP) {
1574 pkey->type = KEY_TYPE_ID_AES;
1577 /* If WPA isn't enabled yet, do that now */
1578 if ( assoc_req->secinfo.WPAenabled == 0
1579 && assoc_req->secinfo.WPA2enabled == 0) {
1580 assoc_req->secinfo.WPAenabled = 1;
1581 assoc_req->secinfo.WPA2enabled = 1;
1582 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
1585 disable_wep (assoc_req);
1588 out:
1589 if (ret == 0) {
1590 libertas_postpone_association_work(priv);
1591 } else {
1592 libertas_cancel_association_work(priv);
1594 mutex_unlock(&adapter->lock);
1596 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1597 return ret;
1601 static int wlan_set_genie(struct net_device *dev,
1602 struct iw_request_info *info,
1603 struct iw_point *dwrq,
1604 char *extra)
1606 wlan_private *priv = dev->priv;
1607 wlan_adapter *adapter = priv->adapter;
1608 int ret = 0;
1609 struct assoc_request * assoc_req;
1611 lbs_deb_enter(LBS_DEB_WEXT);
1613 mutex_lock(&adapter->lock);
1614 assoc_req = wlan_get_association_request(adapter);
1615 if (!assoc_req) {
1616 ret = -ENOMEM;
1617 goto out;
1620 if (dwrq->length > MAX_WPA_IE_LEN ||
1621 (dwrq->length && extra == NULL)) {
1622 ret = -EINVAL;
1623 goto out;
1626 if (dwrq->length) {
1627 memcpy(&assoc_req->wpa_ie[0], extra, dwrq->length);
1628 assoc_req->wpa_ie_len = dwrq->length;
1629 } else {
1630 memset(&assoc_req->wpa_ie[0], 0, sizeof(adapter->wpa_ie));
1631 assoc_req->wpa_ie_len = 0;
1634 out:
1635 if (ret == 0) {
1636 set_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags);
1637 libertas_postpone_association_work(priv);
1638 } else {
1639 libertas_cancel_association_work(priv);
1641 mutex_unlock(&adapter->lock);
1643 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1644 return ret;
1647 static int wlan_get_genie(struct net_device *dev,
1648 struct iw_request_info *info,
1649 struct iw_point *dwrq,
1650 char *extra)
1652 int ret = 0;
1653 wlan_private *priv = dev->priv;
1654 wlan_adapter *adapter = priv->adapter;
1656 lbs_deb_enter(LBS_DEB_WEXT);
1658 if (adapter->wpa_ie_len == 0) {
1659 dwrq->length = 0;
1660 goto out;
1663 if (dwrq->length < adapter->wpa_ie_len) {
1664 ret = -E2BIG;
1665 goto out;
1668 dwrq->length = adapter->wpa_ie_len;
1669 memcpy(extra, &adapter->wpa_ie[0], adapter->wpa_ie_len);
1671 out:
1672 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1673 return ret;
1677 static int wlan_set_auth(struct net_device *dev,
1678 struct iw_request_info *info,
1679 struct iw_param *dwrq,
1680 char *extra)
1682 wlan_private *priv = dev->priv;
1683 wlan_adapter *adapter = priv->adapter;
1684 struct assoc_request * assoc_req;
1685 int ret = 0;
1686 int updated = 0;
1688 lbs_deb_enter(LBS_DEB_WEXT);
1690 mutex_lock(&adapter->lock);
1691 assoc_req = wlan_get_association_request(adapter);
1692 if (!assoc_req) {
1693 ret = -ENOMEM;
1694 goto out;
1697 switch (dwrq->flags & IW_AUTH_INDEX) {
1698 case IW_AUTH_TKIP_COUNTERMEASURES:
1699 case IW_AUTH_CIPHER_PAIRWISE:
1700 case IW_AUTH_CIPHER_GROUP:
1701 case IW_AUTH_KEY_MGMT:
1702 case IW_AUTH_DROP_UNENCRYPTED:
1704 * libertas does not use these parameters
1706 break;
1708 case IW_AUTH_WPA_VERSION:
1709 if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) {
1710 assoc_req->secinfo.WPAenabled = 0;
1711 assoc_req->secinfo.WPA2enabled = 0;
1712 disable_wpa (assoc_req);
1714 if (dwrq->value & IW_AUTH_WPA_VERSION_WPA) {
1715 assoc_req->secinfo.WPAenabled = 1;
1716 assoc_req->secinfo.wep_enabled = 0;
1717 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1719 if (dwrq->value & IW_AUTH_WPA_VERSION_WPA2) {
1720 assoc_req->secinfo.WPA2enabled = 1;
1721 assoc_req->secinfo.wep_enabled = 0;
1722 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1724 updated = 1;
1725 break;
1727 case IW_AUTH_80211_AUTH_ALG:
1728 if (dwrq->value & IW_AUTH_ALG_SHARED_KEY) {
1729 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
1730 } else if (dwrq->value & IW_AUTH_ALG_OPEN_SYSTEM) {
1731 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1732 } else if (dwrq->value & IW_AUTH_ALG_LEAP) {
1733 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_LEAP;
1734 } else {
1735 ret = -EINVAL;
1737 updated = 1;
1738 break;
1740 case IW_AUTH_WPA_ENABLED:
1741 if (dwrq->value) {
1742 if (!assoc_req->secinfo.WPAenabled &&
1743 !assoc_req->secinfo.WPA2enabled) {
1744 assoc_req->secinfo.WPAenabled = 1;
1745 assoc_req->secinfo.WPA2enabled = 1;
1746 assoc_req->secinfo.wep_enabled = 0;
1747 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1749 } else {
1750 assoc_req->secinfo.WPAenabled = 0;
1751 assoc_req->secinfo.WPA2enabled = 0;
1752 disable_wpa (assoc_req);
1754 updated = 1;
1755 break;
1757 default:
1758 ret = -EOPNOTSUPP;
1759 break;
1762 out:
1763 if (ret == 0) {
1764 if (updated)
1765 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
1766 libertas_postpone_association_work(priv);
1767 } else if (ret != -EOPNOTSUPP) {
1768 libertas_cancel_association_work(priv);
1770 mutex_unlock(&adapter->lock);
1772 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1773 return ret;
1776 static int wlan_get_auth(struct net_device *dev,
1777 struct iw_request_info *info,
1778 struct iw_param *dwrq,
1779 char *extra)
1781 int ret = 0;
1782 wlan_private *priv = dev->priv;
1783 wlan_adapter *adapter = priv->adapter;
1785 lbs_deb_enter(LBS_DEB_WEXT);
1787 switch (dwrq->flags & IW_AUTH_INDEX) {
1788 case IW_AUTH_WPA_VERSION:
1789 dwrq->value = 0;
1790 if (adapter->secinfo.WPAenabled)
1791 dwrq->value |= IW_AUTH_WPA_VERSION_WPA;
1792 if (adapter->secinfo.WPA2enabled)
1793 dwrq->value |= IW_AUTH_WPA_VERSION_WPA2;
1794 if (!dwrq->value)
1795 dwrq->value |= IW_AUTH_WPA_VERSION_DISABLED;
1796 break;
1798 case IW_AUTH_80211_AUTH_ALG:
1799 dwrq->value = adapter->secinfo.auth_mode;
1800 break;
1802 case IW_AUTH_WPA_ENABLED:
1803 if (adapter->secinfo.WPAenabled && adapter->secinfo.WPA2enabled)
1804 dwrq->value = 1;
1805 break;
1807 default:
1808 ret = -EOPNOTSUPP;
1811 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1812 return ret;
1816 static int wlan_set_txpow(struct net_device *dev, struct iw_request_info *info,
1817 struct iw_param *vwrq, char *extra)
1819 int ret = 0;
1820 wlan_private *priv = dev->priv;
1821 wlan_adapter *adapter = priv->adapter;
1823 u16 dbm;
1825 lbs_deb_enter(LBS_DEB_WEXT);
1827 if (vwrq->disabled) {
1828 wlan_radio_ioctl(priv, RADIO_OFF);
1829 return 0;
1832 adapter->preamble = CMD_TYPE_AUTO_PREAMBLE;
1834 wlan_radio_ioctl(priv, RADIO_ON);
1836 /* Userspace check in iwrange if it should use dBm or mW,
1837 * therefore this should never happen... Jean II */
1838 if ((vwrq->flags & IW_TXPOW_TYPE) == IW_TXPOW_MWATT) {
1839 return -EOPNOTSUPP;
1840 } else
1841 dbm = (u16) vwrq->value;
1843 /* auto tx power control */
1845 if (vwrq->fixed == 0)
1846 dbm = 0xffff;
1848 lbs_deb_wext("txpower set %d dbm\n", dbm);
1850 ret = libertas_prepare_and_send_command(priv,
1851 CMD_802_11_RF_TX_POWER,
1852 CMD_ACT_TX_POWER_OPT_SET_LOW,
1853 CMD_OPTION_WAITFORRSP, 0, (void *)&dbm);
1855 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1856 return ret;
1859 static int wlan_get_essid(struct net_device *dev, struct iw_request_info *info,
1860 struct iw_point *dwrq, char *extra)
1862 wlan_private *priv = dev->priv;
1863 wlan_adapter *adapter = priv->adapter;
1865 lbs_deb_enter(LBS_DEB_WEXT);
1868 * Note : if dwrq->flags != 0, we should get the relevant SSID from
1869 * the SSID list...
1873 * Get the current SSID
1875 if (adapter->connect_status == LIBERTAS_CONNECTED) {
1876 memcpy(extra, adapter->curbssparams.ssid,
1877 adapter->curbssparams.ssid_len);
1878 extra[adapter->curbssparams.ssid_len] = '\0';
1879 } else {
1880 memset(extra, 0, 32);
1881 extra[adapter->curbssparams.ssid_len] = '\0';
1884 * If none, we may want to get the one that was set
1887 dwrq->length = adapter->curbssparams.ssid_len;
1889 dwrq->flags = 1; /* active */
1891 lbs_deb_leave(LBS_DEB_WEXT);
1892 return 0;
1895 static int wlan_set_essid(struct net_device *dev, struct iw_request_info *info,
1896 struct iw_point *dwrq, char *extra)
1898 wlan_private *priv = dev->priv;
1899 wlan_adapter *adapter = priv->adapter;
1900 int ret = 0;
1901 u8 ssid[IW_ESSID_MAX_SIZE];
1902 u8 ssid_len = 0;
1903 struct assoc_request * assoc_req;
1904 int in_ssid_len = dwrq->length;
1906 lbs_deb_enter(LBS_DEB_WEXT);
1908 /* Check the size of the string */
1909 if (in_ssid_len > IW_ESSID_MAX_SIZE) {
1910 ret = -E2BIG;
1911 goto out;
1914 memset(&ssid, 0, sizeof(ssid));
1916 if (!dwrq->flags || !in_ssid_len) {
1917 /* "any" SSID requested; leave SSID blank */
1918 } else {
1919 /* Specific SSID requested */
1920 memcpy(&ssid, extra, in_ssid_len);
1921 ssid_len = in_ssid_len;
1924 if (!ssid_len) {
1925 lbs_deb_wext("requested any SSID\n");
1926 } else {
1927 lbs_deb_wext("requested SSID '%s'\n",
1928 escape_essid(ssid, ssid_len));
1931 out:
1932 mutex_lock(&adapter->lock);
1933 if (ret == 0) {
1934 /* Get or create the current association request */
1935 assoc_req = wlan_get_association_request(adapter);
1936 if (!assoc_req) {
1937 ret = -ENOMEM;
1938 } else {
1939 /* Copy the SSID to the association request */
1940 memcpy(&assoc_req->ssid, &ssid, IW_ESSID_MAX_SIZE);
1941 assoc_req->ssid_len = ssid_len;
1942 set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
1943 libertas_postpone_association_work(priv);
1947 /* Cancel the association request if there was an error */
1948 if (ret != 0) {
1949 libertas_cancel_association_work(priv);
1952 mutex_unlock(&adapter->lock);
1954 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1955 return ret;
1959 * @brief Connect to the AP or Ad-hoc Network with specific bssid
1961 * @param dev A pointer to net_device structure
1962 * @param info A pointer to iw_request_info structure
1963 * @param awrq A pointer to iw_param structure
1964 * @param extra A pointer to extra data buf
1965 * @return 0 --success, otherwise fail
1967 static int wlan_set_wap(struct net_device *dev, struct iw_request_info *info,
1968 struct sockaddr *awrq, char *extra)
1970 wlan_private *priv = dev->priv;
1971 wlan_adapter *adapter = priv->adapter;
1972 struct assoc_request * assoc_req;
1973 int ret = 0;
1974 DECLARE_MAC_BUF(mac);
1976 lbs_deb_enter(LBS_DEB_WEXT);
1978 if (awrq->sa_family != ARPHRD_ETHER)
1979 return -EINVAL;
1981 lbs_deb_wext("ASSOC: WAP: sa_data %s\n", print_mac(mac, awrq->sa_data));
1983 mutex_lock(&adapter->lock);
1985 /* Get or create the current association request */
1986 assoc_req = wlan_get_association_request(adapter);
1987 if (!assoc_req) {
1988 libertas_cancel_association_work(priv);
1989 ret = -ENOMEM;
1990 } else {
1991 /* Copy the BSSID to the association request */
1992 memcpy(&assoc_req->bssid, awrq->sa_data, ETH_ALEN);
1993 set_bit(ASSOC_FLAG_BSSID, &assoc_req->flags);
1994 libertas_postpone_association_work(priv);
1997 mutex_unlock(&adapter->lock);
1999 return ret;
2002 void libertas_get_fwversion(wlan_adapter * adapter, char *fwversion, int maxlen)
2004 char fwver[32];
2006 mutex_lock(&adapter->lock);
2008 if (adapter->fwreleasenumber[3] == 0)
2009 sprintf(fwver, "%u.%u.%u",
2010 adapter->fwreleasenumber[2],
2011 adapter->fwreleasenumber[1],
2012 adapter->fwreleasenumber[0]);
2013 else
2014 sprintf(fwver, "%u.%u.%u.p%u",
2015 adapter->fwreleasenumber[2],
2016 adapter->fwreleasenumber[1],
2017 adapter->fwreleasenumber[0],
2018 adapter->fwreleasenumber[3]);
2020 mutex_unlock(&adapter->lock);
2021 snprintf(fwversion, maxlen, fwver);
2026 * iwconfig settable callbacks
2028 static const iw_handler wlan_handler[] = {
2029 (iw_handler) NULL, /* SIOCSIWCOMMIT */
2030 (iw_handler) wlan_get_name, /* SIOCGIWNAME */
2031 (iw_handler) NULL, /* SIOCSIWNWID */
2032 (iw_handler) NULL, /* SIOCGIWNWID */
2033 (iw_handler) wlan_set_freq, /* SIOCSIWFREQ */
2034 (iw_handler) wlan_get_freq, /* SIOCGIWFREQ */
2035 (iw_handler) wlan_set_mode, /* SIOCSIWMODE */
2036 (iw_handler) wlan_get_mode, /* SIOCGIWMODE */
2037 (iw_handler) NULL, /* SIOCSIWSENS */
2038 (iw_handler) NULL, /* SIOCGIWSENS */
2039 (iw_handler) NULL, /* SIOCSIWRANGE */
2040 (iw_handler) wlan_get_range, /* SIOCGIWRANGE */
2041 (iw_handler) NULL, /* SIOCSIWPRIV */
2042 (iw_handler) NULL, /* SIOCGIWPRIV */
2043 (iw_handler) NULL, /* SIOCSIWSTATS */
2044 (iw_handler) NULL, /* SIOCGIWSTATS */
2045 iw_handler_set_spy, /* SIOCSIWSPY */
2046 iw_handler_get_spy, /* SIOCGIWSPY */
2047 iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
2048 iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
2049 (iw_handler) wlan_set_wap, /* SIOCSIWAP */
2050 (iw_handler) wlan_get_wap, /* SIOCGIWAP */
2051 (iw_handler) NULL, /* SIOCSIWMLME */
2052 (iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */
2053 (iw_handler) libertas_set_scan, /* SIOCSIWSCAN */
2054 (iw_handler) libertas_get_scan, /* SIOCGIWSCAN */
2055 (iw_handler) wlan_set_essid, /* SIOCSIWESSID */
2056 (iw_handler) wlan_get_essid, /* SIOCGIWESSID */
2057 (iw_handler) wlan_set_nick, /* SIOCSIWNICKN */
2058 (iw_handler) wlan_get_nick, /* SIOCGIWNICKN */
2059 (iw_handler) NULL, /* -- hole -- */
2060 (iw_handler) NULL, /* -- hole -- */
2061 (iw_handler) wlan_set_rate, /* SIOCSIWRATE */
2062 (iw_handler) wlan_get_rate, /* SIOCGIWRATE */
2063 (iw_handler) wlan_set_rts, /* SIOCSIWRTS */
2064 (iw_handler) wlan_get_rts, /* SIOCGIWRTS */
2065 (iw_handler) wlan_set_frag, /* SIOCSIWFRAG */
2066 (iw_handler) wlan_get_frag, /* SIOCGIWFRAG */
2067 (iw_handler) wlan_set_txpow, /* SIOCSIWTXPOW */
2068 (iw_handler) wlan_get_txpow, /* SIOCGIWTXPOW */
2069 (iw_handler) wlan_set_retry, /* SIOCSIWRETRY */
2070 (iw_handler) wlan_get_retry, /* SIOCGIWRETRY */
2071 (iw_handler) wlan_set_encode, /* SIOCSIWENCODE */
2072 (iw_handler) wlan_get_encode, /* SIOCGIWENCODE */
2073 (iw_handler) wlan_set_power, /* SIOCSIWPOWER */
2074 (iw_handler) wlan_get_power, /* SIOCGIWPOWER */
2075 (iw_handler) NULL, /* -- hole -- */
2076 (iw_handler) NULL, /* -- hole -- */
2077 (iw_handler) wlan_set_genie, /* SIOCSIWGENIE */
2078 (iw_handler) wlan_get_genie, /* SIOCGIWGENIE */
2079 (iw_handler) wlan_set_auth, /* SIOCSIWAUTH */
2080 (iw_handler) wlan_get_auth, /* SIOCGIWAUTH */
2081 (iw_handler) wlan_set_encodeext,/* SIOCSIWENCODEEXT */
2082 (iw_handler) wlan_get_encodeext,/* SIOCGIWENCODEEXT */
2083 (iw_handler) NULL, /* SIOCSIWPMKSA */
2086 static const iw_handler mesh_wlan_handler[] = {
2087 (iw_handler) NULL, /* SIOCSIWCOMMIT */
2088 (iw_handler) wlan_get_name, /* SIOCGIWNAME */
2089 (iw_handler) NULL, /* SIOCSIWNWID */
2090 (iw_handler) NULL, /* SIOCGIWNWID */
2091 (iw_handler) wlan_set_freq, /* SIOCSIWFREQ */
2092 (iw_handler) wlan_get_freq, /* SIOCGIWFREQ */
2093 (iw_handler) NULL, /* SIOCSIWMODE */
2094 (iw_handler) mesh_wlan_get_mode, /* SIOCGIWMODE */
2095 (iw_handler) NULL, /* SIOCSIWSENS */
2096 (iw_handler) NULL, /* SIOCGIWSENS */
2097 (iw_handler) NULL, /* SIOCSIWRANGE */
2098 (iw_handler) wlan_get_range, /* SIOCGIWRANGE */
2099 (iw_handler) NULL, /* SIOCSIWPRIV */
2100 (iw_handler) NULL, /* SIOCGIWPRIV */
2101 (iw_handler) NULL, /* SIOCSIWSTATS */
2102 (iw_handler) NULL, /* SIOCGIWSTATS */
2103 iw_handler_set_spy, /* SIOCSIWSPY */
2104 iw_handler_get_spy, /* SIOCGIWSPY */
2105 iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
2106 iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
2107 (iw_handler) NULL, /* SIOCSIWAP */
2108 (iw_handler) NULL, /* SIOCGIWAP */
2109 (iw_handler) NULL, /* SIOCSIWMLME */
2110 (iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */
2111 (iw_handler) libertas_set_scan, /* SIOCSIWSCAN */
2112 (iw_handler) libertas_get_scan, /* SIOCGIWSCAN */
2113 (iw_handler) NULL, /* SIOCSIWESSID */
2114 (iw_handler) NULL, /* SIOCGIWESSID */
2115 (iw_handler) NULL, /* SIOCSIWNICKN */
2116 (iw_handler) mesh_get_nick, /* SIOCGIWNICKN */
2117 (iw_handler) NULL, /* -- hole -- */
2118 (iw_handler) NULL, /* -- hole -- */
2119 (iw_handler) wlan_set_rate, /* SIOCSIWRATE */
2120 (iw_handler) wlan_get_rate, /* SIOCGIWRATE */
2121 (iw_handler) wlan_set_rts, /* SIOCSIWRTS */
2122 (iw_handler) wlan_get_rts, /* SIOCGIWRTS */
2123 (iw_handler) wlan_set_frag, /* SIOCSIWFRAG */
2124 (iw_handler) wlan_get_frag, /* SIOCGIWFRAG */
2125 (iw_handler) wlan_set_txpow, /* SIOCSIWTXPOW */
2126 (iw_handler) wlan_get_txpow, /* SIOCGIWTXPOW */
2127 (iw_handler) wlan_set_retry, /* SIOCSIWRETRY */
2128 (iw_handler) wlan_get_retry, /* SIOCGIWRETRY */
2129 (iw_handler) wlan_set_encode, /* SIOCSIWENCODE */
2130 (iw_handler) wlan_get_encode, /* SIOCGIWENCODE */
2131 (iw_handler) wlan_set_power, /* SIOCSIWPOWER */
2132 (iw_handler) wlan_get_power, /* SIOCGIWPOWER */
2133 (iw_handler) NULL, /* -- hole -- */
2134 (iw_handler) NULL, /* -- hole -- */
2135 (iw_handler) wlan_set_genie, /* SIOCSIWGENIE */
2136 (iw_handler) wlan_get_genie, /* SIOCGIWGENIE */
2137 (iw_handler) wlan_set_auth, /* SIOCSIWAUTH */
2138 (iw_handler) wlan_get_auth, /* SIOCGIWAUTH */
2139 (iw_handler) wlan_set_encodeext,/* SIOCSIWENCODEEXT */
2140 (iw_handler) wlan_get_encodeext,/* SIOCGIWENCODEEXT */
2141 (iw_handler) NULL, /* SIOCSIWPMKSA */
2143 struct iw_handler_def libertas_handler_def = {
2144 .num_standard = ARRAY_SIZE(wlan_handler),
2145 .standard = (iw_handler *) wlan_handler,
2146 .get_wireless_stats = wlan_get_wireless_stats,
2149 struct iw_handler_def mesh_handler_def = {
2150 .num_standard = ARRAY_SIZE(mesh_wlan_handler),
2151 .standard = (iw_handler *) mesh_wlan_handler,
2152 .get_wireless_stats = wlan_get_wireless_stats,