aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/libertas/ioctl.c')
-rw-r--r--drivers/net/wireless/libertas/ioctl.c2500
1 files changed, 2500 insertions, 0 deletions
diff --git a/drivers/net/wireless/libertas/ioctl.c b/drivers/net/wireless/libertas/ioctl.c
new file mode 100644
index 000000000000..82b39642423a
--- /dev/null
+++ b/drivers/net/wireless/libertas/ioctl.c
@@ -0,0 +1,2500 @@
1/**
2 * This file contains ioctl functions
3 */
4
5#include <linux/ctype.h>
6#include <linux/delay.h>
7#include <linux/if.h>
8#include <linux/if_arp.h>
9#include <linux/wireless.h>
10
11#include <net/iw_handler.h>
12#include <net/ieee80211.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 "wext.h"
21
22#define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN + \
23 IW_ESSID_MAX_SIZE + \
24 IW_EV_UINT_LEN + IW_EV_FREQ_LEN + \
25 IW_EV_QUAL_LEN + IW_ESSID_MAX_SIZE + \
26 IW_EV_PARAM_LEN + 40) /* 40 for WPAIE */
27
28#define WAIT_FOR_SCAN_RRESULT_MAX_TIME (10 * HZ)
29
30static int setrxantenna(wlan_private * priv, int mode)
31{
32 int ret = 0;
33 wlan_adapter *adapter = priv->adapter;
34
35 if (mode != RF_ANTENNA_1 && mode != RF_ANTENNA_2
36 && mode != RF_ANTENNA_AUTO) {
37 return -EINVAL;
38 }
39
40 adapter->rxantennamode = mode;
41
42 lbs_pr_debug(1, "SET RX Antenna mode to 0x%04x\n", adapter->rxantennamode);
43
44 ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_antenna,
45 cmd_act_set_rx,
46 cmd_option_waitforrsp, 0,
47 &adapter->rxantennamode);
48 return ret;
49}
50
51static int settxantenna(wlan_private * priv, int mode)
52{
53 int ret = 0;
54 wlan_adapter *adapter = priv->adapter;
55
56 if ((mode != RF_ANTENNA_1) && (mode != RF_ANTENNA_2)
57 && (mode != RF_ANTENNA_AUTO)) {
58 return -EINVAL;
59 }
60
61 adapter->txantennamode = mode;
62
63 lbs_pr_debug(1, "SET TX Antenna mode to 0x%04x\n", adapter->txantennamode);
64
65 ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_antenna,
66 cmd_act_set_tx,
67 cmd_option_waitforrsp, 0,
68 &adapter->txantennamode);
69
70 return ret;
71}
72
73static int getrxantenna(wlan_private * priv, char *buf)
74{
75 int ret = 0;
76 wlan_adapter *adapter = priv->adapter;
77
78 // clear it, so we will know if the value
79 // returned below is correct or not.
80 adapter->rxantennamode = 0;
81
82 ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_antenna,
83 cmd_act_get_rx,
84 cmd_option_waitforrsp, 0, NULL);
85
86 if (ret) {
87 LEAVE();
88 return ret;
89 }
90
91 lbs_pr_debug(1, "Get Rx Antenna mode:0x%04x\n", adapter->rxantennamode);
92
93 return sprintf(buf, "0x%04x", adapter->rxantennamode) + 1;
94}
95
96static int gettxantenna(wlan_private * priv, char *buf)
97{
98 int ret = 0;
99 wlan_adapter *adapter = priv->adapter;
100
101 // clear it, so we will know if the value
102 // returned below is correct or not.
103 adapter->txantennamode = 0;
104
105 ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_antenna,
106 cmd_act_get_tx,
107 cmd_option_waitforrsp, 0, NULL);
108
109 if (ret) {
110 LEAVE();
111 return ret;
112 }
113
114 lbs_pr_debug(1, "Get Tx Antenna mode:0x%04x\n", adapter->txantennamode);
115
116 return sprintf(buf, "0x%04x", adapter->txantennamode) + 1;
117}
118
119static int wlan_set_region(wlan_private * priv, u16 region_code)
120{
121 int i;
122
123 for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
124 // use the region code to search for the index
125 if (region_code == libertas_region_code_to_index[i]) {
126 priv->adapter->regiontableindex = (u16) i;
127 priv->adapter->regioncode = region_code;
128 break;
129 }
130 }
131
132 // if it's unidentified region code
133 if (i >= MRVDRV_MAX_REGION_CODE) {
134 lbs_pr_debug(1, "region Code not identified\n");
135 LEAVE();
136 return -1;
137 }
138
139 if (libertas_set_regiontable(priv, priv->adapter->regioncode, 0)) {
140 LEAVE();
141 return -EINVAL;
142 }
143
144 return 0;
145}
146
147/**
148 * @brief Get/Set Firmware wakeup method
149 *
150 * @param priv A pointer to wlan_private structure
151 * @param wrq A pointer to user data
152 * @return 0--success, otherwise fail
153 */
154static int wlan_txcontrol(wlan_private * priv, struct iwreq *wrq)
155{
156 wlan_adapter *adapter = priv->adapter;
157 int data;
158 ENTER();
159
160 if ((int)wrq->u.data.length == 0) {
161 if (copy_to_user
162 (wrq->u.data.pointer, &adapter->pkttxctrl, sizeof(u32))) {
163 lbs_pr_alert("copy_to_user failed!\n");
164 return -EFAULT;
165 }
166 } else {
167 if ((int)wrq->u.data.length > 1) {
168 lbs_pr_alert("ioctl too many args!\n");
169 return -EFAULT;
170 }
171 if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
172 lbs_pr_alert("Copy from user failed\n");
173 return -EFAULT;
174 }
175
176 adapter->pkttxctrl = (u32) data;
177 }
178
179 wrq->u.data.length = 1;
180
181 LEAVE();
182 return 0;
183}
184
185/**
186 * @brief Get/Set NULL Package generation interval
187 *
188 * @param priv A pointer to wlan_private structure
189 * @param wrq A pointer to user data
190 * @return 0--success, otherwise fail
191 */
192static int wlan_null_pkt_interval(wlan_private * priv, struct iwreq *wrq)
193{
194 wlan_adapter *adapter = priv->adapter;
195 int data;
196 ENTER();
197
198 if ((int)wrq->u.data.length == 0) {
199 data = adapter->nullpktinterval;
200
201 if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
202 lbs_pr_alert( "copy_to_user failed!\n");
203 return -EFAULT;
204 }
205 } else {
206 if ((int)wrq->u.data.length > 1) {
207 lbs_pr_alert( "ioctl too many args!\n");
208 return -EFAULT;
209 }
210 if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
211 lbs_pr_debug(1, "Copy from user failed\n");
212 return -EFAULT;
213 }
214
215 adapter->nullpktinterval = data;
216 }
217
218 wrq->u.data.length = 1;
219
220 LEAVE();
221 return 0;
222}
223
224static int wlan_get_rxinfo(wlan_private * priv, struct iwreq *wrq)
225{
226 wlan_adapter *adapter = priv->adapter;
227 int data[2];
228 ENTER();
229 data[0] = adapter->SNR[TYPE_RXPD][TYPE_NOAVG];
230 data[1] = adapter->rxpd_rate;
231 if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * 2)) {
232 lbs_pr_debug(1, "Copy to user failed\n");
233 return -EFAULT;
234 }
235 wrq->u.data.length = 2;
236 LEAVE();
237 return 0;
238}
239
240static int wlan_get_snr(wlan_private * priv, struct iwreq *wrq)
241{
242 int ret = 0;
243 wlan_adapter *adapter = priv->adapter;
244 int data[4];
245
246 ENTER();
247 memset(data, 0, sizeof(data));
248 if (wrq->u.data.length) {
249 if (copy_from_user(data, wrq->u.data.pointer,
250 min_t(size_t, wrq->u.data.length, 4) * sizeof(int)))
251 return -EFAULT;
252 }
253 if ((wrq->u.data.length == 0) || (data[0] == 0) || (data[0] == 1)) {
254 if (adapter->connect_status == libertas_connected) {
255 ret = libertas_prepare_and_send_command(priv,
256 cmd_802_11_rssi,
257 0,
258 cmd_option_waitforrsp,
259 0, NULL);
260
261 if (ret) {
262 LEAVE();
263 return ret;
264 }
265 }
266 }
267
268 if (wrq->u.data.length == 0) {
269 data[0] = adapter->SNR[TYPE_BEACON][TYPE_NOAVG];
270 data[1] = adapter->SNR[TYPE_BEACON][TYPE_AVG];
271 data[2] = adapter->SNR[TYPE_RXPD][TYPE_NOAVG];
272 data[3] = adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
273 if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * 4))
274 return -EFAULT;
275 wrq->u.data.length = 4;
276 } else if (data[0] == 0) {
277 data[0] = adapter->SNR[TYPE_BEACON][TYPE_NOAVG];
278 if (copy_to_user(wrq->u.data.pointer, data, sizeof(int)))
279 return -EFAULT;
280 wrq->u.data.length = 1;
281 } else if (data[0] == 1) {
282 data[0] = adapter->SNR[TYPE_BEACON][TYPE_AVG];
283 if (copy_to_user(wrq->u.data.pointer, data, sizeof(int)))
284 return -EFAULT;
285 wrq->u.data.length = 1;
286 } else if (data[0] == 2) {
287 data[0] = adapter->SNR[TYPE_RXPD][TYPE_NOAVG];
288 if (copy_to_user(wrq->u.data.pointer, data, sizeof(int)))
289 return -EFAULT;
290 wrq->u.data.length = 1;
291 } else if (data[0] == 3) {
292 data[0] = adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
293 if (copy_to_user(wrq->u.data.pointer, data, sizeof(int)))
294 return -EFAULT;
295 wrq->u.data.length = 1;
296 } else
297 return -ENOTSUPP;
298
299 LEAVE();
300 return 0;
301}
302
303static int wlan_beacon_interval(wlan_private * priv, struct iwreq *wrq)
304{
305 int data;
306 wlan_adapter *adapter = priv->adapter;
307
308 if (wrq->u.data.length > 0) {
309 if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int)))
310 return -EFAULT;
311
312 lbs_pr_debug(1, "WLAN SET BEACON INTERVAL: %d\n", data);
313 if ((data > MRVDRV_MAX_BEACON_INTERVAL)
314 || (data < MRVDRV_MIN_BEACON_INTERVAL))
315 return -ENOTSUPP;
316 adapter->beaconperiod = data;
317 }
318 data = adapter->beaconperiod;
319 if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int)))
320 return -EFAULT;
321
322 wrq->u.data.length = 1;
323
324 return 0;
325}
326
327static int wlan_get_rssi(wlan_private * priv, struct iwreq *wrq)
328{
329 int ret = 0;
330 wlan_adapter *adapter = priv->adapter;
331 int temp;
332 int data = 0;
333 int *val;
334
335 ENTER();
336 data = SUBCMD_DATA(wrq);
337 if ((data == 0) || (data == 1)) {
338 ret = libertas_prepare_and_send_command(priv,
339 cmd_802_11_rssi,
340 0, cmd_option_waitforrsp,
341 0, NULL);
342 if (ret) {
343 LEAVE();
344 return ret;
345 }
346 }
347
348 switch (data) {
349 case 0:
350
351 temp = CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_NOAVG],
352 adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
353 break;
354 case 1:
355 temp = CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_AVG],
356 adapter->NF[TYPE_BEACON][TYPE_AVG]);
357 break;
358 case 2:
359 temp = CAL_RSSI(adapter->SNR[TYPE_RXPD][TYPE_NOAVG],
360 adapter->NF[TYPE_RXPD][TYPE_NOAVG]);
361 break;
362 case 3:
363 temp = CAL_RSSI(adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
364 adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
365 break;
366 default:
367 return -ENOTSUPP;
368 }
369 val = (int *)wrq->u.name;
370 *val = temp;
371
372 LEAVE();
373 return 0;
374}
375
376static int wlan_get_nf(wlan_private * priv, struct iwreq *wrq)
377{
378 int ret = 0;
379 wlan_adapter *adapter = priv->adapter;
380 int temp;
381 int data = 0;
382 int *val;
383
384 data = SUBCMD_DATA(wrq);
385 if ((data == 0) || (data == 1)) {
386 ret = libertas_prepare_and_send_command(priv,
387 cmd_802_11_rssi,
388 0, cmd_option_waitforrsp,
389 0, NULL);
390
391 if (ret) {
392 LEAVE();
393 return ret;
394 }
395 }
396
397 switch (data) {
398 case 0:
399 temp = adapter->NF[TYPE_BEACON][TYPE_NOAVG];
400 break;
401 case 1:
402 temp = adapter->NF[TYPE_BEACON][TYPE_AVG];
403 break;
404 case 2:
405 temp = adapter->NF[TYPE_RXPD][TYPE_NOAVG];
406 break;
407 case 3:
408 temp = adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
409 break;
410 default:
411 return -ENOTSUPP;
412 }
413
414 temp = CAL_NF(temp);
415
416 lbs_pr_debug(1, "%s: temp = %d\n", __FUNCTION__, temp);
417 val = (int *)wrq->u.name;
418 *val = temp;
419 return 0;
420}
421
422static int wlan_get_txrate_ioctl(wlan_private * priv, struct ifreq *req)
423{
424 wlan_adapter *adapter = priv->adapter;
425 int *pdata;
426 struct iwreq *wrq = (struct iwreq *)req;
427 int ret = 0;
428 adapter->txrate = 0;
429 lbs_pr_debug(1, "wlan_get_txrate_ioctl\n");
430 ret = libertas_prepare_and_send_command(priv, cmd_802_11_tx_rate_query,
431 cmd_act_get, cmd_option_waitforrsp,
432 0, NULL);
433 if (ret)
434 return ret;
435
436 pdata = (int *)wrq->u.name;
437 *pdata = (int)adapter->txrate;
438 return 0;
439}
440
441static int wlan_get_adhoc_status_ioctl(wlan_private * priv, struct iwreq *wrq)
442{
443 char status[64];
444 wlan_adapter *adapter = priv->adapter;
445
446 memset(status, 0, sizeof(status));
447
448 switch (adapter->inframode) {
449 case wlan802_11ibss:
450 if (adapter->connect_status == libertas_connected) {
451 if (adapter->adhoccreate)
452 memcpy(&status, "AdhocStarted", sizeof(status));
453 else
454 memcpy(&status, "AdhocJoined", sizeof(status));
455 } else {
456 memcpy(&status, "AdhocIdle", sizeof(status));
457 }
458 break;
459 case wlan802_11infrastructure:
460 memcpy(&status, "Inframode", sizeof(status));
461 break;
462 default:
463 memcpy(&status, "AutoUnknownmode", sizeof(status));
464 break;
465 }
466
467 lbs_pr_debug(1, "status = %s\n", status);
468 wrq->u.data.length = strlen(status) + 1;
469
470 if (wrq->u.data.pointer) {
471 if (copy_to_user(wrq->u.data.pointer,
472 &status, wrq->u.data.length))
473 return -EFAULT;
474 }
475
476 LEAVE();
477 return 0;
478}
479
480/**
481 * @brief Set/Get WPA IE
482 * @param priv A pointer to wlan_private structure
483 * @param req A pointer to ifreq structure
484 * @return 0 --success, otherwise fail
485 */
486static int wlan_setwpaie_ioctl(wlan_private * priv, struct ifreq *req)
487{
488 struct iwreq *wrq = (struct iwreq *)req;
489 wlan_adapter *adapter = priv->adapter;
490 int ret = 0;
491
492 ENTER();
493
494 if (wrq->u.data.length) {
495 if (wrq->u.data.length > sizeof(adapter->wpa_ie)) {
496 lbs_pr_debug(1, "failed to copy WPA IE, too big \n");
497 return -EFAULT;
498 }
499 if (copy_from_user(adapter->wpa_ie, wrq->u.data.pointer,
500 wrq->u.data.length)) {
501 lbs_pr_debug(1, "failed to copy WPA IE \n");
502 return -EFAULT;
503 }
504 adapter->wpa_ie_len = wrq->u.data.length;
505 lbs_pr_debug(1, "Set wpa_ie_len=%d IE=%#x\n", adapter->wpa_ie_len,
506 adapter->wpa_ie[0]);
507 lbs_dbg_hex("wpa_ie", adapter->wpa_ie, adapter->wpa_ie_len);
508 if (adapter->wpa_ie[0] == WPA_IE)
509 adapter->secinfo.WPAenabled = 1;
510 else if (adapter->wpa_ie[0] == WPA2_IE)
511 adapter->secinfo.WPA2enabled = 1;
512 else {
513 adapter->secinfo.WPAenabled = 0;
514 adapter->secinfo.WPA2enabled = 0;
515 }
516 } else {
517 memset(adapter->wpa_ie, 0, sizeof(adapter->wpa_ie));
518 adapter->wpa_ie_len = wrq->u.data.length;
519 lbs_pr_debug(1, "Reset wpa_ie_len=%d IE=%#x\n",
520 adapter->wpa_ie_len, adapter->wpa_ie[0]);
521 adapter->secinfo.WPAenabled = 0;
522 adapter->secinfo.WPA2enabled = 0;
523 }
524
525 // enable/disable RSN in firmware if WPA is enabled/disabled
526 // depending on variable adapter->secinfo.WPAenabled is set or not
527 ret = libertas_prepare_and_send_command(priv, cmd_802_11_enable_rsn,
528 cmd_act_set, cmd_option_waitforrsp,
529 0, NULL);
530
531 LEAVE();
532 return ret;
533}
534
535/**
536 * @brief Set Auto prescan
537 * @param priv A pointer to wlan_private structure
538 * @param wrq A pointer to iwreq structure
539 * @return 0 --success, otherwise fail
540 */
541static int wlan_subcmd_setprescan_ioctl(wlan_private * priv, struct iwreq *wrq)
542{
543 int data;
544 wlan_adapter *adapter = priv->adapter;
545 int *val;
546
547 data = SUBCMD_DATA(wrq);
548 lbs_pr_debug(1, "WLAN_SUBCMD_SET_PRESCAN %d\n", data);
549 adapter->prescan = data;
550
551 val = (int *)wrq->u.name;
552 *val = data;
553 return 0;
554}
555
556static int wlan_set_multiple_dtim_ioctl(wlan_private * priv, struct ifreq *req)
557{
558 struct iwreq *wrq = (struct iwreq *)req;
559 u32 mdtim;
560 int idata;
561 int ret = -EINVAL;
562
563 ENTER();
564
565 idata = SUBCMD_DATA(wrq);
566 mdtim = (u32) idata;
567 if (((mdtim >= MRVDRV_MIN_MULTIPLE_DTIM)
568 && (mdtim <= MRVDRV_MAX_MULTIPLE_DTIM))
569 || (mdtim == MRVDRV_IGNORE_MULTIPLE_DTIM)) {
570 priv->adapter->multipledtim = mdtim;
571 ret = 0;
572 }
573 if (ret)
574 lbs_pr_debug(1, "Invalid parameter, multipledtim not changed.\n");
575
576 LEAVE();
577 return ret;
578}
579
580/**
581 * @brief Set authentication mode
582 * @param priv A pointer to wlan_private structure
583 * @param req A pointer to ifreq structure
584 * @return 0 --success, otherwise fail
585 */
586static int wlan_setauthalg_ioctl(wlan_private * priv, struct ifreq *req)
587{
588 int alg;
589 struct iwreq *wrq = (struct iwreq *)req;
590 wlan_adapter *adapter = priv->adapter;
591
592 if (wrq->u.data.flags == 0) {
593 //from iwpriv subcmd
594 alg = SUBCMD_DATA(wrq);
595 } else {
596 //from wpa_supplicant subcmd
597 if (copy_from_user(&alg, wrq->u.data.pointer, sizeof(alg))) {
598 lbs_pr_debug(1, "Copy from user failed\n");
599 return -EFAULT;
600 }
601 }
602
603 lbs_pr_debug(1, "auth alg is %#x\n", alg);
604
605 switch (alg) {
606 case AUTH_ALG_SHARED_KEY:
607 adapter->secinfo.authmode = wlan802_11authmodeshared;
608 break;
609 case AUTH_ALG_NETWORK_EAP:
610 adapter->secinfo.authmode =
611 wlan802_11authmodenetworkEAP;
612 break;
613 case AUTH_ALG_OPEN_SYSTEM:
614 default:
615 adapter->secinfo.authmode = wlan802_11authmodeopen;
616 break;
617 }
618 return 0;
619}
620
621/**
622 * @brief Set 802.1x authentication mode
623 * @param priv A pointer to wlan_private structure
624 * @param req A pointer to ifreq structure
625 * @return 0 --success, otherwise fail
626 */
627static int wlan_set8021xauthalg_ioctl(wlan_private * priv, struct ifreq *req)
628{
629 int alg;
630 struct iwreq *wrq = (struct iwreq *)req;
631
632 if (wrq->u.data.flags == 0) {
633 //from iwpriv subcmd
634 alg = SUBCMD_DATA(wrq);
635 } else {
636 //from wpa_supplicant subcmd
637 if (copy_from_user(&alg, wrq->u.data.pointer, sizeof(int))) {
638 lbs_pr_debug(1, "Copy from user failed\n");
639 return -EFAULT;
640 }
641 }
642 lbs_pr_debug(1, "802.1x auth alg is %#x\n", alg);
643 priv->adapter->secinfo.auth1xalg = alg;
644 return 0;
645}
646
647static int wlan_setencryptionmode_ioctl(wlan_private * priv, struct ifreq *req)
648{
649 int mode;
650 struct iwreq *wrq = (struct iwreq *)req;
651
652 ENTER();
653
654 if (wrq->u.data.flags == 0) {
655 //from iwpriv subcmd
656 mode = SUBCMD_DATA(wrq);
657 } else {
658 //from wpa_supplicant subcmd
659 if (copy_from_user(&mode, wrq->u.data.pointer, sizeof(int))) {
660 lbs_pr_debug(1, "Copy from user failed\n");
661 return -EFAULT;
662 }
663 }
664 lbs_pr_debug(1, "encryption mode is %#x\n", mode);
665 priv->adapter->secinfo.Encryptionmode = mode;
666
667 LEAVE();
668 return 0;
669}
670
671static void adjust_mtu(wlan_private * priv)
672{
673 int mtu_increment = 0;
674
675 if (priv->adapter->linkmode == WLAN_LINKMODE_802_11)
676 mtu_increment += sizeof(struct ieee80211_hdr_4addr);
677
678 if (priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP)
679 mtu_increment += max(sizeof(struct tx_radiotap_hdr),
680 sizeof(struct rx_radiotap_hdr));
681 priv->wlan_dev.netdev->mtu = ETH_FRAME_LEN
682 - sizeof(struct ethhdr)
683 + mtu_increment;
684}
685
686/**
687 * @brief Set Link-Layer Layer mode
688 * @param priv A pointer to wlan_private structure
689 * @param req A pointer to ifreq structure
690 * @return 0 --success, otherwise fail
691 */
692static int wlan_set_linkmode_ioctl(wlan_private * priv, struct ifreq *req)
693{
694 int mode;
695
696 mode = (int)((struct ifreq *)((u8 *) req + 4))->ifr_data;
697
698 switch (mode) {
699 case WLAN_LINKMODE_802_3:
700 priv->adapter->linkmode = mode;
701 break;
702 case WLAN_LINKMODE_802_11:
703 priv->adapter->linkmode = mode;
704 break;
705 default:
706 lbs_pr_info("usb8388-5: invalid link-layer mode (%#x)\n",
707 mode);
708 return -EINVAL;
709 break;
710 }
711 lbs_pr_debug(1, "usb8388-5: link-layer mode is %#x\n", mode);
712
713 adjust_mtu(priv);
714
715 return 0;
716}
717
718/**
719 * @brief Set Radio header mode
720 * @param priv A pointer to wlan_private structure
721 * @param req A pointer to ifreq structure
722 * @return 0 --success, otherwise fail
723 */
724static int wlan_set_radiomode_ioctl(wlan_private * priv, struct ifreq *req)
725{
726 int mode;
727
728 mode = (int)((struct ifreq *)((u8 *) req + 4))->ifr_data;
729
730 switch (mode) {
731 case WLAN_RADIOMODE_NONE:
732 priv->adapter->radiomode = mode;
733 break;
734 case WLAN_RADIOMODE_RADIOTAP:
735 priv->adapter->radiomode = mode;
736 break;
737 default:
738 lbs_pr_debug(1, "usb8388-5: invalid radio header mode (%#x)\n",
739 mode);
740 return -EINVAL;
741 }
742 lbs_pr_debug(1, "usb8388-5: radio-header mode is %#x\n", mode);
743
744 adjust_mtu(priv);
745 return 0;
746}
747
748/**
749 * @brief Set Debug header mode
750 * @param priv A pointer to wlan_private structure
751 * @param req A pointer to ifreq structure
752 * @return 0 --success, otherwise fail
753 */
754static int wlan_set_debugmode_ioctl(wlan_private * priv, struct ifreq *req)
755{
756 priv->adapter->debugmode = (int)((struct ifreq *)
757 ((u8 *) req + 4))->ifr_data;
758 return 0;
759}
760
761static int wlan_subcmd_getrxantenna_ioctl(wlan_private * priv,
762 struct ifreq *req)
763{
764 int len;
765 char buf[8];
766 struct iwreq *wrq = (struct iwreq *)req;
767
768 lbs_pr_debug(1, "WLAN_SUBCMD_GETRXANTENNA\n");
769 len = getrxantenna(priv, buf);
770
771 wrq->u.data.length = len;
772 if (wrq->u.data.pointer) {
773 if (copy_to_user(wrq->u.data.pointer, &buf, len)) {
774 lbs_pr_debug(1, "CopyToUser failed\n");
775 return -EFAULT;
776 }
777 }
778
779 return 0;
780}
781
782static int wlan_subcmd_gettxantenna_ioctl(wlan_private * priv,
783 struct ifreq *req)
784{
785 int len;
786 char buf[8];
787 struct iwreq *wrq = (struct iwreq *)req;
788
789 lbs_pr_debug(1, "WLAN_SUBCMD_GETTXANTENNA\n");
790 len = gettxantenna(priv, buf);
791
792 wrq->u.data.length = len;
793 if (wrq->u.data.pointer) {
794 if (copy_to_user(wrq->u.data.pointer, &buf, len)) {
795 lbs_pr_debug(1, "CopyToUser failed\n");
796 return -EFAULT;
797 }
798 }
799 return 0;
800}
801
802/**
803 * @brief Get the MAC TSF value from the firmware
804 *
805 * @param priv A pointer to wlan_private structure
806 * @param wrq A pointer to iwreq structure containing buffer
807 * space to store a TSF value retrieved from the firmware
808 *
809 * @return 0 if successful; IOCTL error code otherwise
810 */
811static int wlan_get_tsf_ioctl(wlan_private * priv, struct iwreq *wrq)
812{
813 u64 tsfval;
814 int ret;
815
816 ret = libertas_prepare_and_send_command(priv,
817 cmd_get_tsf,
818 0, cmd_option_waitforrsp, 0, &tsfval);
819
820 lbs_pr_debug(1, "IOCTL: Get TSF = 0x%016llx\n", tsfval);
821
822 if (ret != 0) {
823 lbs_pr_debug(1, "IOCTL: Get TSF; command exec failed\n");
824 ret = -EFAULT;
825 } else {
826 if (copy_to_user(wrq->u.data.pointer,
827 &tsfval,
828 min_t(size_t, wrq->u.data.length,
829 sizeof(tsfval))) != 0) {
830
831 lbs_pr_debug(1, "IOCTL: Get TSF; Copy to user failed\n");
832 ret = -EFAULT;
833 } else {
834 ret = 0;
835 }
836 }
837 return ret;
838}
839
840/**
841 * @brief Get/Set adapt rate
842 * @param priv A pointer to wlan_private structure
843 * @param wrq A pointer to iwreq structure
844 * @return 0 --success, otherwise fail
845 */
846static int wlan_adapt_rateset(wlan_private * priv, struct iwreq *wrq)
847{
848 int ret;
849 wlan_adapter *adapter = priv->adapter;
850 int data[2];
851
852 memset(data, 0, sizeof(data));
853 if (!wrq->u.data.length) {
854 lbs_pr_debug(1, "Get ADAPT RATE SET\n");
855 ret = libertas_prepare_and_send_command(priv,
856 cmd_802_11_rate_adapt_rateset,
857 cmd_act_get,
858 cmd_option_waitforrsp, 0, NULL);
859 data[0] = adapter->enablehwauto;
860 data[1] = adapter->ratebitmap;
861 if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * 2)) {
862 lbs_pr_debug(1, "Copy to user failed\n");
863 return -EFAULT;
864 }
865#define GET_TWO_INT 2
866 wrq->u.data.length = GET_TWO_INT;
867 } else {
868 lbs_pr_debug(1, "Set ADAPT RATE SET\n");
869 if (wrq->u.data.length > 2)
870 return -EINVAL;
871 if (copy_from_user
872 (data, wrq->u.data.pointer,
873 sizeof(int) * wrq->u.data.length)) {
874 lbs_pr_debug(1, "Copy from user failed\n");
875 return -EFAULT;
876 }
877
878 adapter->enablehwauto = data[0];
879 adapter->ratebitmap = data[1];
880 ret = libertas_prepare_and_send_command(priv,
881 cmd_802_11_rate_adapt_rateset,
882 cmd_act_set,
883 cmd_option_waitforrsp, 0, NULL);
884 }
885 return ret;
886}
887
888/**
889 * @brief Get/Set inactivity timeout
890 * @param priv A pointer to wlan_private structure
891 * @param wrq A pointer to iwreq structure
892 * @return 0 --success, otherwise fail
893 */
894static int wlan_inactivity_timeout(wlan_private * priv, struct iwreq *wrq)
895{
896 int ret;
897 int data = 0;
898 u16 timeout = 0;
899
900 ENTER();
901 if (wrq->u.data.length > 1)
902 return -ENOTSUPP;
903
904 if (wrq->u.data.length == 0) {
905 /* Get */
906 ret = libertas_prepare_and_send_command(priv,
907 cmd_802_11_inactivity_timeout,
908 cmd_act_get,
909 cmd_option_waitforrsp, 0,
910 &timeout);
911 data = timeout;
912 if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
913 lbs_pr_debug(1, "Copy to user failed\n");
914 return -EFAULT;
915 }
916 } else {
917 /* Set */
918 if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
919 lbs_pr_debug(1, "Copy from user failed\n");
920 return -EFAULT;
921 }
922
923 timeout = data;
924 ret = libertas_prepare_and_send_command(priv,
925 cmd_802_11_inactivity_timeout,
926 cmd_act_set,
927 cmd_option_waitforrsp, 0,
928 &timeout);
929 }
930
931 wrq->u.data.length = 1;
932
933 LEAVE();
934 return ret;
935}
936
937static int wlan_do_getlog_ioctl(wlan_private * priv, struct iwreq *wrq)
938{
939 int ret;
940 char buf[GETLOG_BUFSIZE - 1];
941 wlan_adapter *adapter = priv->adapter;
942
943 lbs_pr_debug(1, " GET STATS\n");
944
945 ret = libertas_prepare_and_send_command(priv, cmd_802_11_get_log,
946 0, cmd_option_waitforrsp, 0, NULL);
947
948 if (ret) {
949 return ret;
950 }
951
952 if (wrq->u.data.pointer) {
953 sprintf(buf, "\n mcasttxframe %u failed %u retry %u "
954 "multiretry %u framedup %u "
955 "rtssuccess %u rtsfailure %u ackfailure %u\n"
956 "rxfrag %u mcastrxframe %u fcserror %u "
957 "txframe %u wepundecryptable %u ",
958 adapter->logmsg.mcasttxframe,
959 adapter->logmsg.failed,
960 adapter->logmsg.retry,
961 adapter->logmsg.multiretry,
962 adapter->logmsg.framedup,
963 adapter->logmsg.rtssuccess,
964 adapter->logmsg.rtsfailure,
965 adapter->logmsg.ackfailure,
966 adapter->logmsg.rxfrag,
967 adapter->logmsg.mcastrxframe,
968 adapter->logmsg.fcserror,
969 adapter->logmsg.txframe,
970 adapter->logmsg.wepundecryptable);
971 wrq->u.data.length = strlen(buf) + 1;
972 if (copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length)) {
973 lbs_pr_debug(1, "Copy to user failed\n");
974 return -EFAULT;
975 }
976 }
977
978 return 0;
979}
980
981static int wlan_scan_type_ioctl(wlan_private * priv, struct iwreq *wrq)
982{
983 u8 buf[12];
984 u8 *option[] = { "active", "passive", "get", };
985 int i, max_options = (sizeof(option) / sizeof(option[0]));
986 int ret = 0;
987 wlan_adapter *adapter = priv->adapter;
988
989 if (priv->adapter->enable11d) {
990 lbs_pr_debug(1, "11D: Cannot set scantype when 11D enabled\n");
991 return -EFAULT;
992 }
993
994 memset(buf, 0, sizeof(buf));
995
996 if (copy_from_user(buf, wrq->u.data.pointer, min_t(size_t, sizeof(buf),
997 wrq->u.data.length)))
998 return -EFAULT;
999
1000 lbs_pr_debug(1, "Scan type Option = %s\n", buf);
1001
1002 buf[sizeof(buf) - 1] = '\0';
1003
1004 for (i = 0; i < max_options; i++) {
1005 if (!strcmp(buf, option[i]))
1006 break;
1007 }
1008
1009 switch (i) {
1010 case 0:
1011 adapter->scantype = cmd_scan_type_active;
1012 break;
1013 case 1:
1014 adapter->scantype = cmd_scan_type_passive;
1015 break;
1016 case 2:
1017 wrq->u.data.length = strlen(option[adapter->scantype]) + 1;
1018
1019 if (copy_to_user(wrq->u.data.pointer,
1020 option[adapter->scantype],
1021 wrq->u.data.length)) {
1022 lbs_pr_debug(1, "Copy to user failed\n");
1023 ret = -EFAULT;
1024 }
1025
1026 break;
1027 default:
1028 lbs_pr_debug(1, "Invalid Scan type Ioctl Option\n");
1029 ret = -EINVAL;
1030 break;
1031 }
1032
1033 return ret;
1034}
1035
1036static int wlan_scan_mode_ioctl(wlan_private * priv, struct iwreq *wrq)
1037{
1038 wlan_adapter *adapter = priv->adapter;
1039 u8 buf[12];
1040 u8 *option[] = { "bss", "ibss", "any", "get" };
1041 int i, max_options = (sizeof(option) / sizeof(option[0]));
1042 int ret = 0;
1043
1044 ENTER();
1045
1046 memset(buf, 0, sizeof(buf));
1047
1048 if (copy_from_user(buf, wrq->u.data.pointer, min_t(size_t, sizeof(buf),
1049 wrq->u.data.length))) {
1050 lbs_pr_debug(1, "Copy from user failed\n");
1051 return -EFAULT;
1052 }
1053
1054 lbs_pr_debug(1, "Scan mode Option = %s\n", buf);
1055
1056 buf[sizeof(buf) - 1] = '\0';
1057
1058 for (i = 0; i < max_options; i++) {
1059 if (!strcmp(buf, option[i]))
1060 break;
1061 }
1062
1063 switch (i) {
1064
1065 case 0:
1066 adapter->scanmode = cmd_bss_type_bss;
1067 break;
1068 case 1:
1069 adapter->scanmode = cmd_bss_type_ibss;
1070 break;
1071 case 2:
1072 adapter->scanmode = cmd_bss_type_any;
1073 break;
1074 case 3:
1075
1076 wrq->u.data.length = strlen(option[adapter->scanmode - 1]) + 1;
1077
1078 lbs_pr_debug(1, "Get Scan mode Option = %s\n",
1079 option[adapter->scanmode - 1]);
1080
1081 lbs_pr_debug(1, "Scan mode length %d\n", wrq->u.data.length);
1082
1083 if (copy_to_user(wrq->u.data.pointer,
1084 option[adapter->scanmode - 1],
1085 wrq->u.data.length)) {
1086 lbs_pr_debug(1, "Copy to user failed\n");
1087 ret = -EFAULT;
1088 }
1089 lbs_pr_debug(1, "GET Scan type Option after copy = %s\n",
1090 (char *)wrq->u.data.pointer);
1091
1092 break;
1093
1094 default:
1095 lbs_pr_debug(1, "Invalid Scan mode Ioctl Option\n");
1096 ret = -EINVAL;
1097 break;
1098 }
1099
1100 LEAVE();
1101 return ret;
1102}
1103
1104/**
1105 * @brief Get/Set Adhoc G Rate
1106 *
1107 * @param priv A pointer to wlan_private structure
1108 * @param wrq A pointer to user data
1109 * @return 0--success, otherwise fail
1110 */
1111static int wlan_do_set_grate_ioctl(wlan_private * priv, struct iwreq *wrq)
1112{
1113 wlan_adapter *adapter = priv->adapter;
1114 int data, data1;
1115 int *val;
1116
1117 ENTER();
1118
1119 data1 = SUBCMD_DATA(wrq);
1120 switch (data1) {
1121 case 0:
1122 adapter->adhoc_grate_enabled = 0;
1123 break;
1124 case 1:
1125 adapter->adhoc_grate_enabled = 1;
1126 break;
1127 case 2:
1128 break;
1129 default:
1130 return -EINVAL;
1131 }
1132 data = adapter->adhoc_grate_enabled;
1133 val = (int *)wrq->u.name;
1134 *val = data;
1135 LEAVE();
1136 return 0;
1137}
1138
1139static inline int hex2int(char c)
1140{
1141 if (c >= '0' && c <= '9')
1142 return (c - '0');
1143 if (c >= 'a' && c <= 'f')
1144 return (c - 'a' + 10);
1145 if (c >= 'A' && c <= 'F')
1146 return (c - 'A' + 10);
1147 return -1;
1148}
1149
1150/* Convert a string representation of a MAC address ("xx:xx:xx:xx:xx:xx")
1151 into binary format (6 bytes).
1152
1153 This function expects that each byte is represented with 2 characters
1154 (e.g., 11:2:11:11:11:11 is invalid)
1155
1156 */
1157static char *eth_str2addr(char *ethstr, u8 * addr)
1158{
1159 int i, val, val2;
1160 char *pos = ethstr;
1161
1162 /* get rid of initial blanks */
1163 while (*pos == ' ' || *pos == '\t')
1164 ++pos;
1165
1166 for (i = 0; i < 6; i++) {
1167 val = hex2int(*pos++);
1168 if (val < 0)
1169 return NULL;
1170 val2 = hex2int(*pos++);
1171 if (val2 < 0)
1172 return NULL;
1173 addr[i] = (val * 16 + val2) & 0xff;
1174
1175 if (i < 5 && *pos++ != ':')
1176 return NULL;
1177 }
1178 return pos;
1179}
1180
1181/* this writes xx:xx:xx:xx:xx:xx into ethstr
1182 (ethstr must have space for 18 chars) */
1183static int eth_addr2str(u8 * addr, char *ethstr)
1184{
1185 int i;
1186 char *pos = ethstr;
1187
1188 for (i = 0; i < 6; i++) {
1189 sprintf(pos, "%02x", addr[i] & 0xff);
1190 pos += 2;
1191 if (i < 5)
1192 *pos++ = ':';
1193 }
1194 return 17;
1195}
1196
1197/**
1198 * @brief Add an entry to the BT table
1199 * @param priv A pointer to wlan_private structure
1200 * @param req A pointer to ifreq structure
1201 * @return 0 --success, otherwise fail
1202 */
1203static int wlan_bt_add_ioctl(wlan_private * priv, struct ifreq *req)
1204{
1205 struct iwreq *wrq = (struct iwreq *)req;
1206 char ethaddrs_str[18];
1207 char *pos;
1208 u8 ethaddr[ETH_ALEN];
1209
1210 ENTER();
1211 if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
1212 sizeof(ethaddrs_str)))
1213 return -EFAULT;
1214
1215 if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
1216 lbs_pr_info("BT_ADD: Invalid MAC address\n");
1217 return -EINVAL;
1218 }
1219
1220 lbs_pr_debug(1, "BT: adding %s\n", ethaddrs_str);
1221 LEAVE();
1222 return (libertas_prepare_and_send_command(priv, cmd_bt_access,
1223 cmd_act_bt_access_add,
1224 cmd_option_waitforrsp, 0, ethaddr));
1225}
1226
1227/**
1228 * @brief Delete an entry from the BT table
1229 * @param priv A pointer to wlan_private structure
1230 * @param req A pointer to ifreq structure
1231 * @return 0 --success, otherwise fail
1232 */
1233static int wlan_bt_del_ioctl(wlan_private * priv, struct ifreq *req)
1234{
1235 struct iwreq *wrq = (struct iwreq *)req;
1236 char ethaddrs_str[18];
1237 u8 ethaddr[ETH_ALEN];
1238 char *pos;
1239
1240 ENTER();
1241 if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
1242 sizeof(ethaddrs_str)))
1243 return -EFAULT;
1244
1245 if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
1246 lbs_pr_info("Invalid MAC address\n");
1247 return -EINVAL;
1248 }
1249
1250 lbs_pr_debug(1, "BT: deleting %s\n", ethaddrs_str);
1251
1252 return (libertas_prepare_and_send_command(priv,
1253 cmd_bt_access,
1254 cmd_act_bt_access_del,
1255 cmd_option_waitforrsp, 0, ethaddr));
1256 LEAVE();
1257 return 0;
1258}
1259
1260/**
1261 * @brief Reset all entries from the BT table
1262 * @param priv A pointer to wlan_private structure
1263 * @return 0 --success, otherwise fail
1264 */
1265static int wlan_bt_reset_ioctl(wlan_private * priv)
1266{
1267 ENTER();
1268
1269 lbs_pr_alert( "BT: resetting\n");
1270
1271 return (libertas_prepare_and_send_command(priv,
1272 cmd_bt_access,
1273 cmd_act_bt_access_reset,
1274 cmd_option_waitforrsp, 0, NULL));
1275
1276 LEAVE();
1277 return 0;
1278}
1279
1280/**
1281 * @brief List an entry from the BT table
1282 * @param priv A pointer to wlan_private structure
1283 * @param req A pointer to ifreq structure
1284 * @return 0 --success, otherwise fail
1285 */
1286static int wlan_bt_list_ioctl(wlan_private * priv, struct ifreq *req)
1287{
1288 int pos;
1289 char *addr1;
1290 struct iwreq *wrq = (struct iwreq *)req;
1291 /* used to pass id and store the bt entry returned by the FW */
1292 union {
1293 int id;
1294 char addr1addr2[2 * ETH_ALEN];
1295 } param;
1296 static char outstr[64];
1297 char *pbuf = outstr;
1298 int ret;
1299
1300 ENTER();
1301
1302 if (copy_from_user(outstr, wrq->u.data.pointer, sizeof(outstr))) {
1303 lbs_pr_debug(1, "Copy from user failed\n");
1304 return -1;
1305 }
1306 param.id = simple_strtoul(outstr, NULL, 10);
1307 pos = sprintf(pbuf, "%d: ", param.id);
1308 pbuf += pos;
1309
1310 ret = libertas_prepare_and_send_command(priv, cmd_bt_access,
1311 cmd_act_bt_access_list,
1312 cmd_option_waitforrsp, 0,
1313 (char *)&param);
1314
1315 if (ret == 0) {
1316 addr1 = param.addr1addr2;
1317
1318 pos = sprintf(pbuf, "ignoring traffic from ");
1319 pbuf += pos;
1320 pos = eth_addr2str(addr1, pbuf);
1321 pbuf += pos;
1322 } else {
1323 sprintf(pbuf, "(null)");
1324 pbuf += pos;
1325 }
1326
1327 wrq->u.data.length = strlen(outstr);
1328 if (copy_to_user(wrq->u.data.pointer, (char *)outstr,
1329 wrq->u.data.length)) {
1330 lbs_pr_debug(1, "BT_LIST: Copy to user failed!\n");
1331 return -EFAULT;
1332 }
1333
1334 LEAVE();
1335 return 0;
1336}
1337
1338/**
1339 * @brief Find the next parameter in an input string
1340 * @param ptr A pointer to the input parameter string
1341 * @return A pointer to the next parameter, or 0 if no parameters left.
1342 */
1343static char * next_param(char * ptr)
1344{
1345 if (!ptr) return NULL;
1346 while (*ptr == ' ' || *ptr == '\t') ++ptr;
1347 return (*ptr == '\0') ? NULL : ptr;
1348}
1349
1350/**
1351 * @brief Add an entry to the FWT table
1352 * @param priv A pointer to wlan_private structure
1353 * @param req A pointer to ifreq structure
1354 * @return 0 --success, otherwise fail
1355 */
1356static int wlan_fwt_add_ioctl(wlan_private * priv, struct ifreq *req)
1357{
1358 struct iwreq *wrq = (struct iwreq *)req;
1359 char in_str[128];
1360 static struct cmd_ds_fwt_access fwt_access;
1361 char *ptr;
1362
1363 ENTER();
1364 if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
1365 return -EFAULT;
1366
1367 if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
1368 lbs_pr_alert( "FWT_ADD: Invalid MAC address 1\n");
1369 return -EINVAL;
1370 }
1371
1372 if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) {
1373 lbs_pr_alert( "FWT_ADD: Invalid MAC address 2\n");
1374 return -EINVAL;
1375 }
1376
1377 if ((ptr = next_param(ptr)))
1378 fwt_access.metric =
1379 cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
1380 else
1381 fwt_access.metric = FWT_DEFAULT_METRIC;
1382
1383 if ((ptr = next_param(ptr)))
1384 fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10);
1385 else
1386 fwt_access.dir = FWT_DEFAULT_DIR;
1387
1388 if ((ptr = next_param(ptr)))
1389 fwt_access.ssn =
1390 cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
1391 else
1392 fwt_access.ssn = FWT_DEFAULT_SSN;
1393
1394 if ((ptr = next_param(ptr)))
1395 fwt_access.dsn =
1396 cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
1397 else
1398 fwt_access.dsn = FWT_DEFAULT_DSN;
1399
1400 if ((ptr = next_param(ptr)))
1401 fwt_access.hopcount = simple_strtoul(ptr, &ptr, 10);
1402 else
1403 fwt_access.hopcount = FWT_DEFAULT_HOPCOUNT;
1404
1405 if ((ptr = next_param(ptr)))
1406 fwt_access.ttl = simple_strtoul(ptr, &ptr, 10);
1407 else
1408 fwt_access.ttl = FWT_DEFAULT_TTL;
1409
1410 if ((ptr = next_param(ptr)))
1411 fwt_access.expiration =
1412 cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
1413 else
1414 fwt_access.expiration = FWT_DEFAULT_EXPIRATION;
1415
1416 if ((ptr = next_param(ptr)))
1417 fwt_access.sleepmode = (u8)simple_strtoul(ptr, &ptr, 10);
1418 else
1419 fwt_access.sleepmode = FWT_DEFAULT_SLEEPMODE;
1420
1421 if ((ptr = next_param(ptr)))
1422 fwt_access.snr =
1423 cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
1424 else
1425 fwt_access.snr = FWT_DEFAULT_SNR;
1426
1427#ifdef DEBUG
1428 {
1429 char ethaddr1_str[18], ethaddr2_str[18];
1430 eth_addr2str(fwt_access.da, ethaddr1_str);
1431 eth_addr2str(fwt_access.ra, ethaddr2_str);
1432 lbs_pr_debug(1, "FWT_ADD: adding (da:%s,%i,ra:%s)\n", ethaddr1_str,
1433 fwt_access.dir, ethaddr2_str);
1434 lbs_pr_debug(1, "FWT_ADD: ssn:%u dsn:%u met:%u hop:%u ttl:%u exp:%u slp:%u snr:%u\n",
1435 fwt_access.ssn, fwt_access.dsn, fwt_access.metric,
1436 fwt_access.hopcount, fwt_access.ttl, fwt_access.expiration,
1437 fwt_access.sleepmode, fwt_access.snr);
1438 }
1439#endif
1440
1441 LEAVE();
1442 return (libertas_prepare_and_send_command(priv, cmd_fwt_access,
1443 cmd_act_fwt_access_add,
1444 cmd_option_waitforrsp, 0,
1445 (void *)&fwt_access));
1446}
1447
1448/**
1449 * @brief Delete an entry from the FWT table
1450 * @param priv A pointer to wlan_private structure
1451 * @param req A pointer to ifreq structure
1452 * @return 0 --success, otherwise fail
1453 */
1454static int wlan_fwt_del_ioctl(wlan_private * priv, struct ifreq *req)
1455{
1456 struct iwreq *wrq = (struct iwreq *)req;
1457 char in_str[64];
1458 static struct cmd_ds_fwt_access fwt_access;
1459 char *ptr;
1460
1461 ENTER();
1462 if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
1463 return -EFAULT;
1464
1465 if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
1466 lbs_pr_alert( "FWT_DEL: Invalid MAC address 1\n");
1467 return -EINVAL;
1468 }
1469
1470 if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) {
1471 lbs_pr_alert( "FWT_DEL: Invalid MAC address 2\n");
1472 return -EINVAL;
1473 }
1474
1475 if ((ptr = next_param(ptr)))
1476 fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10);
1477 else
1478 fwt_access.dir = FWT_DEFAULT_DIR;
1479
1480#ifdef DEBUG
1481 {
1482 char ethaddr1_str[18], ethaddr2_str[18];
1483 lbs_pr_debug(1, "FWT_DEL: line is %s\n", in_str);
1484 eth_addr2str(fwt_access.da, ethaddr1_str);
1485 eth_addr2str(fwt_access.ra, ethaddr2_str);
1486 lbs_pr_debug(1, "FWT_DEL: removing (da:%s,ra:%s,dir:%d)\n", ethaddr1_str,
1487 ethaddr2_str, fwt_access.dir);
1488 }
1489#endif
1490
1491 LEAVE();
1492 return (libertas_prepare_and_send_command(priv,
1493 cmd_fwt_access,
1494 cmd_act_fwt_access_del,
1495 cmd_option_waitforrsp, 0,
1496 (void *)&fwt_access));
1497}
1498
1499
1500/**
1501 * @brief Print route parameters
1502 * @param fwt_access struct cmd_ds_fwt_access with route info
1503 * @param buf destination buffer for route info
1504 */
1505static void print_route(struct cmd_ds_fwt_access fwt_access, char *buf)
1506{
1507 buf += sprintf(buf, " ");
1508 buf += eth_addr2str(fwt_access.da, buf);
1509 buf += sprintf(buf, " ");
1510 buf += eth_addr2str(fwt_access.ra, buf);
1511 buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.metric));
1512 buf += sprintf(buf, " %u", fwt_access.dir);
1513 buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.ssn));
1514 buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.dsn));
1515 buf += sprintf(buf, " %u", fwt_access.hopcount);
1516 buf += sprintf(buf, " %u", fwt_access.ttl);
1517 buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.expiration));
1518 buf += sprintf(buf, " %u", fwt_access.sleepmode);
1519 buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.snr));
1520}
1521
1522/**
1523 * @brief Lookup an entry in the FWT table
1524 * @param priv A pointer to wlan_private structure
1525 * @param req A pointer to ifreq structure
1526 * @return 0 --success, otherwise fail
1527 */
1528static int wlan_fwt_lookup_ioctl(wlan_private * priv, struct ifreq *req)
1529{
1530 struct iwreq *wrq = (struct iwreq *)req;
1531 char in_str[64];
1532 char *ptr;
1533 static struct cmd_ds_fwt_access fwt_access;
1534 static char out_str[128];
1535 int ret;
1536
1537 ENTER();
1538 if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
1539 return -EFAULT;
1540
1541 if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
1542 lbs_pr_alert( "FWT_LOOKUP: Invalid MAC address\n");
1543 return -EINVAL;
1544 }
1545
1546#ifdef DEBUG
1547 {
1548 char ethaddr1_str[18];
1549 lbs_pr_debug(1, "FWT_LOOKUP: line is %s\n", in_str);
1550 eth_addr2str(fwt_access.da, ethaddr1_str);
1551 lbs_pr_debug(1, "FWT_LOOKUP: looking for (da:%s)\n", ethaddr1_str);
1552 }
1553#endif
1554
1555 ret = libertas_prepare_and_send_command(priv,
1556 cmd_fwt_access,
1557 cmd_act_fwt_access_lookup,
1558 cmd_option_waitforrsp, 0,
1559 (void *)&fwt_access);
1560
1561 if (ret == 0)
1562 print_route(fwt_access, out_str);
1563 else
1564 sprintf(out_str, "(null)");
1565
1566 wrq->u.data.length = strlen(out_str);
1567 if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
1568 wrq->u.data.length)) {
1569 lbs_pr_debug(1, "FWT_LOOKUP: Copy to user failed!\n");
1570 return -EFAULT;
1571 }
1572
1573 LEAVE();
1574 return 0;
1575}
1576
1577/**
1578 * @brief Reset all entries from the FWT table
1579 * @param priv A pointer to wlan_private structure
1580 * @return 0 --success, otherwise fail
1581 */
1582static int wlan_fwt_reset_ioctl(wlan_private * priv)
1583{
1584 lbs_pr_debug(1, "FWT: resetting\n");
1585
1586 return (libertas_prepare_and_send_command(priv,
1587 cmd_fwt_access,
1588 cmd_act_fwt_access_reset,
1589 cmd_option_waitforrsp, 0, NULL));
1590}
1591
1592/**
1593 * @brief List an entry from the FWT table
1594 * @param priv A pointer to wlan_private structure
1595 * @param req A pointer to ifreq structure
1596 * @return 0 --success, otherwise fail
1597 */
1598static int wlan_fwt_list_ioctl(wlan_private * priv, struct ifreq *req)
1599{
1600 struct iwreq *wrq = (struct iwreq *)req;
1601 char in_str[8];
1602 static struct cmd_ds_fwt_access fwt_access;
1603 char *ptr = in_str;
1604 static char out_str[128];
1605 char *pbuf = out_str;
1606 int ret;
1607
1608 ENTER();
1609 if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
1610 return -EFAULT;
1611
1612 fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
1613
1614#ifdef DEBUG
1615 {
1616 lbs_pr_debug(1, "FWT_LIST: line is %s\n", in_str);
1617 lbs_pr_debug(1, "FWT_LIST: listing id:%i\n", le32_to_cpu(fwt_access.id));
1618 }
1619#endif
1620
1621 ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
1622 cmd_act_fwt_access_list,
1623 cmd_option_waitforrsp, 0, (void *)&fwt_access);
1624
1625 if (ret == 0)
1626 print_route(fwt_access, pbuf);
1627 else
1628 pbuf += sprintf(pbuf, " (null)");
1629
1630 wrq->u.data.length = strlen(out_str);
1631 if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
1632 wrq->u.data.length)) {
1633 lbs_pr_debug(1, "FWT_LIST: Copy to user failed!\n");
1634 return -EFAULT;
1635 }
1636
1637 LEAVE();
1638 return 0;
1639}
1640
1641/**
1642 * @brief List an entry from the FRT table
1643 * @param priv A pointer to wlan_private structure
1644 * @param req A pointer to ifreq structure
1645 * @return 0 --success, otherwise fail
1646 */
1647static int wlan_fwt_list_route_ioctl(wlan_private * priv, struct ifreq *req)
1648{
1649 struct iwreq *wrq = (struct iwreq *)req;
1650 char in_str[64];
1651 static struct cmd_ds_fwt_access fwt_access;
1652 char *ptr = in_str;
1653 static char out_str[128];
1654 char *pbuf = out_str;
1655 int ret;
1656
1657 ENTER();
1658 if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
1659 return -EFAULT;
1660
1661 fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
1662
1663#ifdef DEBUG
1664 {
1665 lbs_pr_debug(1, "FWT_LIST_ROUTE: line is %s\n", in_str);
1666 lbs_pr_debug(1, "FWT_LIST_ROUTE: listing id:%i\n", le32_to_cpu(fwt_access.id));
1667 }
1668#endif
1669
1670 ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
1671 cmd_act_fwt_access_list_route,
1672 cmd_option_waitforrsp, 0, (void *)&fwt_access);
1673
1674 if (ret == 0) {
1675 pbuf += sprintf(pbuf, " ");
1676 pbuf += eth_addr2str(fwt_access.da, pbuf);
1677 pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.metric));
1678 pbuf += sprintf(pbuf, " %u", fwt_access.dir);
1679 /* note that the firmware returns the nid in the id field */
1680 pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.id));
1681 pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.ssn));
1682 pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.dsn));
1683 pbuf += sprintf(pbuf, " hop %u", fwt_access.hopcount);
1684 pbuf += sprintf(pbuf, " ttl %u", fwt_access.ttl);
1685 pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.expiration));
1686 } else
1687 pbuf += sprintf(pbuf, " (null)");
1688
1689 wrq->u.data.length = strlen(out_str);
1690 if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
1691 wrq->u.data.length)) {
1692 lbs_pr_debug(1, "FWT_LIST_ROUTE: Copy to user failed!\n");
1693 return -EFAULT;
1694 }
1695
1696 LEAVE();
1697 return 0;
1698}
1699
1700/**
1701 * @brief List an entry from the FNT table
1702 * @param priv A pointer to wlan_private structure
1703 * @param req A pointer to ifreq structure
1704 * @return 0 --success, otherwise fail
1705 */
1706static int wlan_fwt_list_neighbor_ioctl(wlan_private * priv, struct ifreq *req)
1707{
1708 struct iwreq *wrq = (struct iwreq *)req;
1709 char in_str[8];
1710 static struct cmd_ds_fwt_access fwt_access;
1711 char *ptr = in_str;
1712 static char out_str[128];
1713 char *pbuf = out_str;
1714 int ret;
1715
1716 ENTER();
1717 if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
1718 return -EFAULT;
1719
1720 memset(&fwt_access, 0, sizeof(fwt_access));
1721 fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
1722
1723#ifdef DEBUG
1724 {
1725 lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: line is %s\n", in_str);
1726 lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: listing id:%i\n", le32_to_cpu(fwt_access.id));
1727 }
1728#endif
1729
1730 ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
1731 cmd_act_fwt_access_list_neighbor,
1732 cmd_option_waitforrsp, 0,
1733 (void *)&fwt_access);
1734
1735 if (ret == 0) {
1736 pbuf += sprintf(pbuf, " ra ");
1737 pbuf += eth_addr2str(fwt_access.ra, pbuf);
1738 pbuf += sprintf(pbuf, " slp %u", fwt_access.sleepmode);
1739 pbuf += sprintf(pbuf, " snr %u", le32_to_cpu(fwt_access.snr));
1740 pbuf += sprintf(pbuf, " ref %u", le32_to_cpu(fwt_access.references));
1741 } else
1742 pbuf += sprintf(pbuf, " (null)");
1743
1744 wrq->u.data.length = strlen(out_str);
1745 if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
1746 wrq->u.data.length)) {
1747 lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: Copy to user failed!\n");
1748 return -EFAULT;
1749 }
1750
1751 LEAVE();
1752 return 0;
1753}
1754
1755/**
1756 * @brief Cleans up the route (FRT) and neighbor (FNT) tables
1757 * (Garbage Collection)
1758 * @param priv A pointer to wlan_private structure
1759 * @param req A pointer to ifreq structure
1760 * @return 0 --success, otherwise fail
1761 */
1762static int wlan_fwt_cleanup_ioctl(wlan_private * priv, struct ifreq *req)
1763{
1764 static struct cmd_ds_fwt_access fwt_access;
1765 int ret;
1766
1767 ENTER();
1768
1769 lbs_pr_debug(1, "FWT: cleaning up\n");
1770
1771 memset(&fwt_access, 0, sizeof(fwt_access));
1772
1773 ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
1774 cmd_act_fwt_access_cleanup,
1775 cmd_option_waitforrsp, 0,
1776 (void *)&fwt_access);
1777
1778 if (ret == 0)
1779 req->ifr_data = (char *)(le32_to_cpu(fwt_access.references));
1780 else
1781 return -EFAULT;
1782
1783 LEAVE();
1784 return 0;
1785}
1786
1787/**
1788 * @brief Gets firmware internal time (debug purposes)
1789 * @param priv A pointer to wlan_private structure
1790 * @param req A pointer to ifreq structure
1791 * @return 0 --success, otherwise fail
1792 */
1793static int wlan_fwt_time_ioctl(wlan_private * priv, struct ifreq *req)
1794{
1795 static struct cmd_ds_fwt_access fwt_access;
1796 int ret;
1797
1798 ENTER();
1799
1800 lbs_pr_debug(1, "FWT: getting time\n");
1801
1802 memset(&fwt_access, 0, sizeof(fwt_access));
1803
1804 ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
1805 cmd_act_fwt_access_time,
1806 cmd_option_waitforrsp, 0,
1807 (void *)&fwt_access);
1808
1809 if (ret == 0)
1810 req->ifr_data = (char *)(le32_to_cpu(fwt_access.references));
1811 else
1812 return -EFAULT;
1813
1814 LEAVE();
1815 return 0;
1816}
1817
1818/**
1819 * @brief Gets mesh ttl from firmware
1820 * @param priv A pointer to wlan_private structure
1821 * @param req A pointer to ifreq structure
1822 * @return 0 --success, otherwise fail
1823 */
1824static int wlan_mesh_get_ttl_ioctl(wlan_private * priv, struct ifreq *req)
1825{
1826 struct cmd_ds_mesh_access mesh_access;
1827 int ret;
1828
1829 ENTER();
1830
1831 memset(&mesh_access, 0, sizeof(mesh_access));
1832
1833 ret = libertas_prepare_and_send_command(priv, cmd_mesh_access,
1834 cmd_act_mesh_get_ttl,
1835 cmd_option_waitforrsp, 0,
1836 (void *)&mesh_access);
1837
1838 if (ret == 0) {
1839 req->ifr_data = (char *)(le32_to_cpu(mesh_access.data[0]));
1840 }
1841 else
1842 return -EFAULT;
1843
1844 LEAVE();
1845 return 0;
1846}
1847
1848/**
1849 * @brief Gets mesh ttl from firmware
1850 * @param priv A pointer to wlan_private structure
1851 * @param ttl New ttl value
1852 * @return 0 --success, otherwise fail
1853 */
1854static int wlan_mesh_set_ttl_ioctl(wlan_private * priv, int ttl)
1855{
1856 struct cmd_ds_mesh_access mesh_access;
1857 int ret;
1858
1859 ENTER();
1860
1861 if( (ttl > 0xff) || (ttl < 0) )
1862 return -EINVAL;
1863
1864 memset(&mesh_access, 0, sizeof(mesh_access));
1865 mesh_access.data[0] = ttl;
1866
1867 ret = libertas_prepare_and_send_command(priv, cmd_mesh_access,
1868 cmd_act_mesh_set_ttl,
1869 cmd_option_waitforrsp, 0,
1870 (void *)&mesh_access);
1871
1872 if (ret != 0)
1873 ret = -EFAULT;
1874
1875 LEAVE();
1876 return ret;
1877}
1878
1879/**
1880 * @brief ioctl function - entry point
1881 *
1882 * @param dev A pointer to net_device structure
1883 * @param req A pointer to ifreq structure
1884 * @param cmd command
1885 * @return 0--success, otherwise fail
1886 */
1887int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
1888{
1889 int subcmd = 0;
1890 int idata = 0;
1891 int *pdata;
1892 int ret = 0;
1893 wlan_private *priv = dev->priv;
1894 wlan_adapter *adapter = priv->adapter;
1895 struct iwreq *wrq = (struct iwreq *)req;
1896
1897 ENTER();
1898
1899 lbs_pr_debug(1, "libertas_do_ioctl: ioctl cmd = 0x%x\n", cmd);
1900 switch (cmd) {
1901 case WLANSCAN_TYPE:
1902 lbs_pr_debug(1, "Scan type Ioctl\n");
1903 ret = wlan_scan_type_ioctl(priv, wrq);
1904 break;
1905
1906 case WLAN_SETNONE_GETNONE: /* set WPA mode on/off ioctl #20 */
1907 switch (wrq->u.data.flags) {
1908 case WLANDEAUTH:
1909 lbs_pr_debug(1, "Deauth\n");
1910 libertas_send_deauth(priv);
1911 break;
1912
1913 case WLANADHOCSTOP:
1914 lbs_pr_debug(1, "Adhoc stop\n");
1915 ret = libertas_do_adhocstop_ioctl(priv);
1916 break;
1917
1918 case WLANRADIOON:
1919 wlan_radio_ioctl(priv, 1);
1920 break;
1921
1922 case WLANRADIOOFF:
1923 wlan_radio_ioctl(priv, 0);
1924 break;
1925 case WLANWLANIDLEON:
1926 libertas_idle_on(priv);
1927 break;
1928 case WLANWLANIDLEOFF:
1929 libertas_idle_off(priv);
1930 break;
1931 case WLAN_SUBCMD_BT_RESET: /* bt_reset */
1932 wlan_bt_reset_ioctl(priv);
1933 break;
1934 case WLAN_SUBCMD_FWT_RESET: /* fwt_reset */
1935 wlan_fwt_reset_ioctl(priv);
1936 break;
1937 } /* End of switch */
1938 break;
1939
1940 case WLANSETWPAIE:
1941 ret = wlan_setwpaie_ioctl(priv, req);
1942 break;
1943 case WLAN_SETINT_GETINT:
1944 /* The first 4 bytes of req->ifr_data is sub-ioctl number
1945 * after 4 bytes sits the payload.
1946 */
1947 subcmd = (int)req->ifr_data; //from iwpriv subcmd
1948 switch (subcmd) {
1949 case WLANNF:
1950 ret = wlan_get_nf(priv, wrq);
1951 break;
1952 case WLANRSSI:
1953 ret = wlan_get_rssi(priv, wrq);
1954 break;
1955 case WLANENABLE11D:
1956 ret = libertas_cmd_enable_11d(priv, wrq);
1957 break;
1958 case WLANADHOCGRATE:
1959 ret = wlan_do_set_grate_ioctl(priv, wrq);
1960 break;
1961 case WLAN_SUBCMD_SET_PRESCAN:
1962 ret = wlan_subcmd_setprescan_ioctl(priv, wrq);
1963 break;
1964 }
1965 break;
1966
1967 case WLAN_SETONEINT_GETONEINT:
1968 switch (wrq->u.data.flags) {
1969 case WLAN_BEACON_INTERVAL:
1970 ret = wlan_beacon_interval(priv, wrq);
1971 break;
1972
1973 case WLAN_LISTENINTRVL:
1974 if (!wrq->u.data.length) {
1975 int data;
1976 lbs_pr_debug(1, "Get locallisteninterval value\n");
1977#define GET_ONE_INT 1
1978 data = adapter->locallisteninterval;
1979 if (copy_to_user(wrq->u.data.pointer,
1980 &data, sizeof(int))) {
1981 lbs_pr_debug(1, "Copy to user failed\n");
1982 return -EFAULT;
1983 }
1984
1985 wrq->u.data.length = GET_ONE_INT;
1986 } else {
1987 int data;
1988 if (copy_from_user
1989 (&data, wrq->u.data.pointer, sizeof(int))) {
1990 lbs_pr_debug(1, "Copy from user failed\n");
1991 return -EFAULT;
1992 }
1993
1994 lbs_pr_debug(1, "Set locallisteninterval = %d\n",
1995 data);
1996#define MAX_U16_VAL 65535
1997 if (data > MAX_U16_VAL) {
1998 lbs_pr_debug(1, "Exceeds U16 value\n");
1999 return -EINVAL;
2000 }
2001 adapter->locallisteninterval = data;
2002 }
2003 break;
2004 case WLAN_TXCONTROL:
2005 ret = wlan_txcontrol(priv, wrq); //adds for txcontrol ioctl
2006 break;
2007
2008 case WLAN_NULLPKTINTERVAL:
2009 ret = wlan_null_pkt_interval(priv, wrq);
2010 break;
2011
2012 default:
2013 ret = -EOPNOTSUPP;
2014 break;
2015 }
2016 break;
2017
2018 case WLAN_SETONEINT_GETNONE:
2019 /* The first 4 bytes of req->ifr_data is sub-ioctl number
2020 * after 4 bytes sits the payload.
2021 */
2022 subcmd = wrq->u.data.flags; //from wpa_supplicant subcmd
2023
2024 if (!subcmd)
2025 subcmd = (int)req->ifr_data; //from iwpriv subcmd
2026
2027 switch (subcmd) {
2028 case WLAN_SUBCMD_SETRXANTENNA: /* SETRXANTENNA */
2029 idata = SUBCMD_DATA(wrq);
2030 ret = setrxantenna(priv, idata);
2031 break;
2032 case WLAN_SUBCMD_SETTXANTENNA: /* SETTXANTENNA */
2033 idata = SUBCMD_DATA(wrq);
2034 ret = settxantenna(priv, idata);
2035 break;
2036 case WLAN_SET_ATIM_WINDOW:
2037 adapter->atimwindow = SUBCMD_DATA(wrq);
2038 adapter->atimwindow = min_t(__u16, adapter->atimwindow, 50);
2039 break;
2040 case WLANSETBCNAVG:
2041 adapter->bcn_avg_factor = SUBCMD_DATA(wrq);
2042 if (adapter->bcn_avg_factor == 0)
2043 adapter->bcn_avg_factor =
2044 DEFAULT_BCN_AVG_FACTOR;
2045 if (adapter->bcn_avg_factor > DEFAULT_BCN_AVG_FACTOR)
2046 adapter->bcn_avg_factor =
2047 DEFAULT_BCN_AVG_FACTOR;
2048 break;
2049 case WLANSETDATAAVG:
2050 adapter->data_avg_factor = SUBCMD_DATA(wrq);
2051 if (adapter->data_avg_factor == 0)
2052 adapter->data_avg_factor =
2053 DEFAULT_DATA_AVG_FACTOR;
2054 if (adapter->data_avg_factor > DEFAULT_DATA_AVG_FACTOR)
2055 adapter->data_avg_factor =
2056 DEFAULT_DATA_AVG_FACTOR;
2057 break;
2058 case WLANSETREGION:
2059 idata = SUBCMD_DATA(wrq);
2060 ret = wlan_set_region(priv, (u16) idata);
2061 break;
2062
2063 case WLAN_SET_LISTEN_INTERVAL:
2064 idata = SUBCMD_DATA(wrq);
2065 adapter->listeninterval = (u16) idata;
2066 break;
2067
2068 case WLAN_SET_MULTIPLE_DTIM:
2069 ret = wlan_set_multiple_dtim_ioctl(priv, req);
2070 break;
2071
2072 case WLANSETAUTHALG:
2073 ret = wlan_setauthalg_ioctl(priv, req);
2074 break;
2075
2076 case WLANSET8021XAUTHALG:
2077 ret = wlan_set8021xauthalg_ioctl(priv, req);
2078 break;
2079
2080 case WLANSETENCRYPTIONMODE:
2081 ret = wlan_setencryptionmode_ioctl(priv, req);
2082 break;
2083
2084 case WLAN_SET_LINKMODE:
2085 ret = wlan_set_linkmode_ioctl(priv, req);
2086 break;
2087
2088 case WLAN_SET_RADIOMODE:
2089 ret = wlan_set_radiomode_ioctl(priv, req);
2090 break;
2091
2092 case WLAN_SET_DEBUGMODE:
2093 ret = wlan_set_debugmode_ioctl(priv, req);
2094 break;
2095
2096 case WLAN_SUBCMD_MESH_SET_TTL:
2097 idata = SUBCMD_DATA(wrq);
2098 ret = wlan_mesh_set_ttl_ioctl(priv, idata);
2099 break;
2100
2101 default:
2102 ret = -EOPNOTSUPP;
2103 break;
2104 }
2105
2106 break;
2107
2108 case WLAN_SETNONE_GETTWELVE_CHAR: /* Get Antenna settings */
2109 /*
2110 * We've not used IW_PRIV_TYPE_FIXED so sub-ioctl number is
2111 * in flags of iwreq structure, otherwise it will be in
2112 * mode member of iwreq structure.
2113 */
2114 switch ((int)wrq->u.data.flags) {
2115 case WLAN_SUBCMD_GETRXANTENNA: /* Get Rx Antenna */
2116 ret = wlan_subcmd_getrxantenna_ioctl(priv, req);
2117 break;
2118
2119 case WLAN_SUBCMD_GETTXANTENNA: /* Get Tx Antenna */
2120 ret = wlan_subcmd_gettxantenna_ioctl(priv, req);
2121 break;
2122
2123 case WLAN_GET_TSF:
2124 ret = wlan_get_tsf_ioctl(priv, wrq);
2125 break;
2126 }
2127 break;
2128
2129 case WLAN_SET128CHAR_GET128CHAR:
2130 switch ((int)wrq->u.data.flags) {
2131
2132 case WLANSCAN_MODE:
2133 lbs_pr_debug(1, "Scan mode Ioctl\n");
2134 ret = wlan_scan_mode_ioctl(priv, wrq);
2135 break;
2136
2137 case WLAN_GET_ADHOC_STATUS:
2138 ret = wlan_get_adhoc_status_ioctl(priv, wrq);
2139 break;
2140 case WLAN_SUBCMD_BT_ADD:
2141 ret = wlan_bt_add_ioctl(priv, req);
2142 break;
2143 case WLAN_SUBCMD_BT_DEL:
2144 ret = wlan_bt_del_ioctl(priv, req);
2145 break;
2146 case WLAN_SUBCMD_BT_LIST:
2147 ret = wlan_bt_list_ioctl(priv, req);
2148 break;
2149 case WLAN_SUBCMD_FWT_ADD:
2150 ret = wlan_fwt_add_ioctl(priv, req);
2151 break;
2152 case WLAN_SUBCMD_FWT_DEL:
2153 ret = wlan_fwt_del_ioctl(priv, req);
2154 break;
2155 case WLAN_SUBCMD_FWT_LOOKUP:
2156 ret = wlan_fwt_lookup_ioctl(priv, req);
2157 break;
2158 case WLAN_SUBCMD_FWT_LIST_NEIGHBOR:
2159 ret = wlan_fwt_list_neighbor_ioctl(priv, req);
2160 break;
2161 case WLAN_SUBCMD_FWT_LIST:
2162 ret = wlan_fwt_list_ioctl(priv, req);
2163 break;
2164 case WLAN_SUBCMD_FWT_LIST_ROUTE:
2165 ret = wlan_fwt_list_route_ioctl(priv, req);
2166 break;
2167 }
2168 break;
2169
2170 case WLAN_SETNONE_GETONEINT:
2171 switch ((int)req->ifr_data) {
2172 case WLANGETBCNAVG:
2173 pdata = (int *)wrq->u.name;
2174 *pdata = (int)adapter->bcn_avg_factor;
2175 break;
2176
2177 case WLANGETREGION:
2178 pdata = (int *)wrq->u.name;
2179 *pdata = (int)adapter->regioncode;
2180 break;
2181
2182 case WLAN_GET_LISTEN_INTERVAL:
2183 pdata = (int *)wrq->u.name;
2184 *pdata = (int)adapter->listeninterval;
2185 break;
2186
2187 case WLAN_GET_LINKMODE:
2188 req->ifr_data = (char *)((u32) adapter->linkmode);
2189 break;
2190
2191 case WLAN_GET_RADIOMODE:
2192 req->ifr_data = (char *)((u32) adapter->radiomode);
2193 break;
2194
2195 case WLAN_GET_DEBUGMODE:
2196 req->ifr_data = (char *)((u32) adapter->debugmode);
2197 break;
2198
2199 case WLAN_GET_MULTIPLE_DTIM:
2200 pdata = (int *)wrq->u.name;
2201 *pdata = (int)adapter->multipledtim;
2202 break;
2203 case WLAN_GET_TX_RATE:
2204 ret = wlan_get_txrate_ioctl(priv, req);
2205 break;
2206 case WLAN_SUBCMD_FWT_CLEANUP: /* fwt_cleanup */
2207 ret = wlan_fwt_cleanup_ioctl(priv, req);
2208 break;
2209
2210 case WLAN_SUBCMD_FWT_TIME: /* fwt_time */
2211 ret = wlan_fwt_time_ioctl(priv, req);
2212 break;
2213
2214 case WLAN_SUBCMD_MESH_GET_TTL:
2215 ret = wlan_mesh_get_ttl_ioctl(priv, req);
2216 break;
2217
2218 default:
2219 ret = -EOPNOTSUPP;
2220
2221 }
2222
2223 break;
2224
2225 case WLANGETLOG:
2226 ret = wlan_do_getlog_ioctl(priv, wrq);
2227 break;
2228
2229 case WLAN_SET_GET_SIXTEEN_INT:
2230 switch ((int)wrq->u.data.flags) {
2231 case WLAN_TPCCFG:
2232 {
2233 int data[5];
2234 struct cmd_ds_802_11_tpc_cfg cfg;
2235 memset(&cfg, 0, sizeof(cfg));
2236 if ((wrq->u.data.length > 1)
2237 && (wrq->u.data.length != 5))
2238 return -1;
2239
2240 if (wrq->u.data.length == 0) {
2241 cfg.action =
2242 cpu_to_le16
2243 (cmd_act_get);
2244 } else {
2245 if (copy_from_user
2246 (data, wrq->u.data.pointer,
2247 sizeof(int) * 5)) {
2248 lbs_pr_debug(1,
2249 "Copy from user failed\n");
2250 return -EFAULT;
2251 }
2252
2253 cfg.action =
2254 cpu_to_le16
2255 (cmd_act_set);
2256 cfg.enable = data[0];
2257 cfg.usesnr = data[1];
2258 cfg.P0 = data[2];
2259 cfg.P1 = data[3];
2260 cfg.P2 = data[4];
2261 }
2262
2263 ret =
2264 libertas_prepare_and_send_command(priv,
2265 cmd_802_11_tpc_cfg,
2266 0,
2267 cmd_option_waitforrsp,
2268 0, (void *)&cfg);
2269
2270 data[0] = cfg.enable;
2271 data[1] = cfg.usesnr;
2272 data[2] = cfg.P0;
2273 data[3] = cfg.P1;
2274 data[4] = cfg.P2;
2275 if (copy_to_user
2276 (wrq->u.data.pointer, data,
2277 sizeof(int) * 5)) {
2278 lbs_pr_debug(1, "Copy to user failed\n");
2279 return -EFAULT;
2280 }
2281
2282 wrq->u.data.length = 5;
2283 }
2284 break;
2285
2286 case WLAN_POWERCFG:
2287 {
2288 int data[4];
2289 struct cmd_ds_802_11_pwr_cfg cfg;
2290 memset(&cfg, 0, sizeof(cfg));
2291 if ((wrq->u.data.length > 1)
2292 && (wrq->u.data.length != 4))
2293 return -1;
2294 if (wrq->u.data.length == 0) {
2295 cfg.action =
2296 cpu_to_le16
2297 (cmd_act_get);
2298 } else {
2299 if (copy_from_user
2300 (data, wrq->u.data.pointer,
2301 sizeof(int) * 4)) {
2302 lbs_pr_debug(1,
2303 "Copy from user failed\n");
2304 return -EFAULT;
2305 }
2306
2307 cfg.action =
2308 cpu_to_le16
2309 (cmd_act_set);
2310 cfg.enable = data[0];
2311 cfg.PA_P0 = data[1];
2312 cfg.PA_P1 = data[2];
2313 cfg.PA_P2 = data[3];
2314 }
2315 ret =
2316 libertas_prepare_and_send_command(priv,
2317 cmd_802_11_pwr_cfg,
2318 0,
2319 cmd_option_waitforrsp,
2320 0, (void *)&cfg);
2321 data[0] = cfg.enable;
2322 data[1] = cfg.PA_P0;
2323 data[2] = cfg.PA_P1;
2324 data[3] = cfg.PA_P2;
2325 if (copy_to_user
2326 (wrq->u.data.pointer, data,
2327 sizeof(int) * 4)) {
2328 lbs_pr_debug(1, "Copy to user failed\n");
2329 return -EFAULT;
2330 }
2331
2332 wrq->u.data.length = 4;
2333 }
2334 break;
2335 case WLAN_AUTO_FREQ_SET:
2336 {
2337 int data[3];
2338 struct cmd_ds_802_11_afc afc;
2339 memset(&afc, 0, sizeof(afc));
2340 if (wrq->u.data.length != 3)
2341 return -1;
2342 if (copy_from_user
2343 (data, wrq->u.data.pointer,
2344 sizeof(int) * 3)) {
2345 lbs_pr_debug(1, "Copy from user failed\n");
2346 return -EFAULT;
2347 }
2348 afc.afc_auto = data[0];
2349
2350 if (afc.afc_auto != 0) {
2351 afc.threshold = data[1];
2352 afc.period = data[2];
2353 } else {
2354 afc.timing_offset = data[1];
2355 afc.carrier_offset = data[2];
2356 }
2357 ret =
2358 libertas_prepare_and_send_command(priv,
2359 cmd_802_11_set_afc,
2360 0,
2361 cmd_option_waitforrsp,
2362 0, (void *)&afc);
2363 }
2364 break;
2365 case WLAN_AUTO_FREQ_GET:
2366 {
2367 int data[3];
2368 struct cmd_ds_802_11_afc afc;
2369 memset(&afc, 0, sizeof(afc));
2370 ret =
2371 libertas_prepare_and_send_command(priv,
2372 cmd_802_11_get_afc,
2373 0,
2374 cmd_option_waitforrsp,
2375 0, (void *)&afc);
2376 data[0] = afc.afc_auto;
2377 data[1] = afc.timing_offset;
2378 data[2] = afc.carrier_offset;
2379 if (copy_to_user
2380 (wrq->u.data.pointer, data,
2381 sizeof(int) * 3)) {
2382 lbs_pr_debug(1, "Copy to user failed\n");
2383 return -EFAULT;
2384 }
2385
2386 wrq->u.data.length = 3;
2387 }
2388 break;
2389 case WLAN_SCANPROBES:
2390 {
2391 int data;
2392 if (wrq->u.data.length > 0) {
2393 if (copy_from_user
2394 (&data, wrq->u.data.pointer,
2395 sizeof(int))) {
2396 lbs_pr_debug(1,
2397 "Copy from user failed\n");
2398 return -EFAULT;
2399 }
2400
2401 adapter->scanprobes = data;
2402 } else {
2403 data = adapter->scanprobes;
2404 if (copy_to_user
2405 (wrq->u.data.pointer, &data,
2406 sizeof(int))) {
2407 lbs_pr_debug(1,
2408 "Copy to user failed\n");
2409 return -EFAULT;
2410 }
2411 }
2412 wrq->u.data.length = 1;
2413 }
2414 break;
2415 case WLAN_LED_GPIO_CTRL:
2416 {
2417 int i;
2418 int data[16];
2419
2420 struct cmd_ds_802_11_led_ctrl ctrl;
2421 struct mrvlietypes_ledgpio *gpio =
2422 (struct mrvlietypes_ledgpio *) ctrl.data;
2423
2424 memset(&ctrl, 0, sizeof(ctrl));
2425 if (wrq->u.data.length > MAX_LEDS * 2)
2426 return -ENOTSUPP;
2427 if ((wrq->u.data.length % 2) != 0)
2428 return -ENOTSUPP;
2429 if (wrq->u.data.length == 0) {
2430 ctrl.action =
2431 cpu_to_le16
2432 (cmd_act_get);
2433 } else {
2434 if (copy_from_user
2435 (data, wrq->u.data.pointer,
2436 sizeof(int) *
2437 wrq->u.data.length)) {
2438 lbs_pr_debug(1,
2439 "Copy from user failed\n");
2440 return -EFAULT;
2441 }
2442
2443 ctrl.action =
2444 cpu_to_le16
2445 (cmd_act_set);
2446 ctrl.numled = cpu_to_le16(0);
2447 gpio->header.type =
2448 cpu_to_le16(TLV_TYPE_LED_GPIO);
2449 gpio->header.len = wrq->u.data.length;
2450 for (i = 0; i < wrq->u.data.length;
2451 i += 2) {
2452 gpio->ledpin[i / 2].led =
2453 data[i];
2454 gpio->ledpin[i / 2].pin =
2455 data[i + 1];
2456 }
2457 }
2458 ret =
2459 libertas_prepare_and_send_command(priv,
2460 cmd_802_11_led_gpio_ctrl,
2461 0,
2462 cmd_option_waitforrsp,
2463 0, (void *)&ctrl);
2464 for (i = 0; i < gpio->header.len; i += 2) {
2465 data[i] = gpio->ledpin[i / 2].led;
2466 data[i + 1] = gpio->ledpin[i / 2].pin;
2467 }
2468 if (copy_to_user(wrq->u.data.pointer, data,
2469 sizeof(int) *
2470 gpio->header.len)) {
2471 lbs_pr_debug(1, "Copy to user failed\n");
2472 return -EFAULT;
2473 }
2474
2475 wrq->u.data.length = gpio->header.len;
2476 }
2477 break;
2478 case WLAN_ADAPT_RATESET:
2479 ret = wlan_adapt_rateset(priv, wrq);
2480 break;
2481 case WLAN_INACTIVITY_TIMEOUT:
2482 ret = wlan_inactivity_timeout(priv, wrq);
2483 break;
2484 case WLANSNR:
2485 ret = wlan_get_snr(priv, wrq);
2486 break;
2487 case WLAN_GET_RXINFO:
2488 ret = wlan_get_rxinfo(priv, wrq);
2489 }
2490 break;
2491
2492 default:
2493 ret = -EINVAL;
2494 break;
2495 }
2496 LEAVE();
2497 return ret;
2498}
2499
2500