]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/net/wireless/libertas/ioctl.c
c53c0f9dd9640e0da084dd3dab461bc12c33fcb4
[mirror_ubuntu-bionic-kernel.git] / drivers / net / wireless / libertas / ioctl.c
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
30 static 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
51 static 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
73 static 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
96 static 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
119 static 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 */
154 static 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 */
192 static 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
224 static 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
240 static 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
303 static 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
327 static 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
376 static 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
422 static 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
441 static 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 */
486 static 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 */
541 static 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
556 static 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 */
586 static 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 static int wlan_setencryptionmode_ioctl(wlan_private * priv, struct ifreq *req)
622 {
623 int mode;
624 struct iwreq *wrq = (struct iwreq *)req;
625
626 ENTER();
627
628 if (wrq->u.data.flags == 0) {
629 //from iwpriv subcmd
630 mode = SUBCMD_DATA(wrq);
631 } else {
632 //from wpa_supplicant subcmd
633 if (copy_from_user(&mode, wrq->u.data.pointer, sizeof(int))) {
634 lbs_pr_debug(1, "Copy from user failed\n");
635 return -EFAULT;
636 }
637 }
638 lbs_pr_debug(1, "encryption mode is %#x\n", mode);
639 priv->adapter->secinfo.Encryptionmode = mode;
640
641 LEAVE();
642 return 0;
643 }
644
645 static void adjust_mtu(wlan_private * priv)
646 {
647 int mtu_increment = 0;
648
649 if (priv->adapter->linkmode == WLAN_LINKMODE_802_11)
650 mtu_increment += sizeof(struct ieee80211_hdr_4addr);
651
652 if (priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP)
653 mtu_increment += max(sizeof(struct tx_radiotap_hdr),
654 sizeof(struct rx_radiotap_hdr));
655 priv->wlan_dev.netdev->mtu = ETH_FRAME_LEN
656 - sizeof(struct ethhdr)
657 + mtu_increment;
658 }
659
660 /**
661 * @brief Set Link-Layer Layer mode
662 * @param priv A pointer to wlan_private structure
663 * @param req A pointer to ifreq structure
664 * @return 0 --success, otherwise fail
665 */
666 static int wlan_set_linkmode_ioctl(wlan_private * priv, struct ifreq *req)
667 {
668 int mode;
669
670 mode = (int)((struct ifreq *)((u8 *) req + 4))->ifr_data;
671
672 switch (mode) {
673 case WLAN_LINKMODE_802_3:
674 priv->adapter->linkmode = mode;
675 break;
676 case WLAN_LINKMODE_802_11:
677 priv->adapter->linkmode = mode;
678 break;
679 default:
680 lbs_pr_info("usb8388-5: invalid link-layer mode (%#x)\n",
681 mode);
682 return -EINVAL;
683 break;
684 }
685 lbs_pr_debug(1, "usb8388-5: link-layer mode is %#x\n", mode);
686
687 adjust_mtu(priv);
688
689 return 0;
690 }
691
692 /**
693 * @brief Set Radio header mode
694 * @param priv A pointer to wlan_private structure
695 * @param req A pointer to ifreq structure
696 * @return 0 --success, otherwise fail
697 */
698 static int wlan_set_radiomode_ioctl(wlan_private * priv, struct ifreq *req)
699 {
700 int mode;
701
702 mode = (int)((struct ifreq *)((u8 *) req + 4))->ifr_data;
703
704 switch (mode) {
705 case WLAN_RADIOMODE_NONE:
706 priv->adapter->radiomode = mode;
707 break;
708 case WLAN_RADIOMODE_RADIOTAP:
709 priv->adapter->radiomode = mode;
710 break;
711 default:
712 lbs_pr_debug(1, "usb8388-5: invalid radio header mode (%#x)\n",
713 mode);
714 return -EINVAL;
715 }
716 lbs_pr_debug(1, "usb8388-5: radio-header mode is %#x\n", mode);
717
718 adjust_mtu(priv);
719 return 0;
720 }
721
722 /**
723 * @brief Set Debug header mode
724 * @param priv A pointer to wlan_private structure
725 * @param req A pointer to ifreq structure
726 * @return 0 --success, otherwise fail
727 */
728 static int wlan_set_debugmode_ioctl(wlan_private * priv, struct ifreq *req)
729 {
730 priv->adapter->debugmode = (int)((struct ifreq *)
731 ((u8 *) req + 4))->ifr_data;
732 return 0;
733 }
734
735 static int wlan_subcmd_getrxantenna_ioctl(wlan_private * priv,
736 struct ifreq *req)
737 {
738 int len;
739 char buf[8];
740 struct iwreq *wrq = (struct iwreq *)req;
741
742 lbs_pr_debug(1, "WLAN_SUBCMD_GETRXANTENNA\n");
743 len = getrxantenna(priv, buf);
744
745 wrq->u.data.length = len;
746 if (wrq->u.data.pointer) {
747 if (copy_to_user(wrq->u.data.pointer, &buf, len)) {
748 lbs_pr_debug(1, "CopyToUser failed\n");
749 return -EFAULT;
750 }
751 }
752
753 return 0;
754 }
755
756 static int wlan_subcmd_gettxantenna_ioctl(wlan_private * priv,
757 struct ifreq *req)
758 {
759 int len;
760 char buf[8];
761 struct iwreq *wrq = (struct iwreq *)req;
762
763 lbs_pr_debug(1, "WLAN_SUBCMD_GETTXANTENNA\n");
764 len = gettxantenna(priv, buf);
765
766 wrq->u.data.length = len;
767 if (wrq->u.data.pointer) {
768 if (copy_to_user(wrq->u.data.pointer, &buf, len)) {
769 lbs_pr_debug(1, "CopyToUser failed\n");
770 return -EFAULT;
771 }
772 }
773 return 0;
774 }
775
776 /**
777 * @brief Get the MAC TSF value from the firmware
778 *
779 * @param priv A pointer to wlan_private structure
780 * @param wrq A pointer to iwreq structure containing buffer
781 * space to store a TSF value retrieved from the firmware
782 *
783 * @return 0 if successful; IOCTL error code otherwise
784 */
785 static int wlan_get_tsf_ioctl(wlan_private * priv, struct iwreq *wrq)
786 {
787 u64 tsfval;
788 int ret;
789
790 ret = libertas_prepare_and_send_command(priv,
791 cmd_get_tsf,
792 0, cmd_option_waitforrsp, 0, &tsfval);
793
794 lbs_pr_debug(1, "IOCTL: Get TSF = 0x%016llx\n", tsfval);
795
796 if (ret != 0) {
797 lbs_pr_debug(1, "IOCTL: Get TSF; command exec failed\n");
798 ret = -EFAULT;
799 } else {
800 if (copy_to_user(wrq->u.data.pointer,
801 &tsfval,
802 min_t(size_t, wrq->u.data.length,
803 sizeof(tsfval))) != 0) {
804
805 lbs_pr_debug(1, "IOCTL: Get TSF; Copy to user failed\n");
806 ret = -EFAULT;
807 } else {
808 ret = 0;
809 }
810 }
811 return ret;
812 }
813
814 /**
815 * @brief Get/Set adapt rate
816 * @param priv A pointer to wlan_private structure
817 * @param wrq A pointer to iwreq structure
818 * @return 0 --success, otherwise fail
819 */
820 static int wlan_adapt_rateset(wlan_private * priv, struct iwreq *wrq)
821 {
822 int ret;
823 wlan_adapter *adapter = priv->adapter;
824 int data[2];
825
826 memset(data, 0, sizeof(data));
827 if (!wrq->u.data.length) {
828 lbs_pr_debug(1, "Get ADAPT RATE SET\n");
829 ret = libertas_prepare_and_send_command(priv,
830 cmd_802_11_rate_adapt_rateset,
831 cmd_act_get,
832 cmd_option_waitforrsp, 0, NULL);
833 data[0] = adapter->enablehwauto;
834 data[1] = adapter->ratebitmap;
835 if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * 2)) {
836 lbs_pr_debug(1, "Copy to user failed\n");
837 return -EFAULT;
838 }
839 #define GET_TWO_INT 2
840 wrq->u.data.length = GET_TWO_INT;
841 } else {
842 lbs_pr_debug(1, "Set ADAPT RATE SET\n");
843 if (wrq->u.data.length > 2)
844 return -EINVAL;
845 if (copy_from_user
846 (data, wrq->u.data.pointer,
847 sizeof(int) * wrq->u.data.length)) {
848 lbs_pr_debug(1, "Copy from user failed\n");
849 return -EFAULT;
850 }
851
852 adapter->enablehwauto = data[0];
853 adapter->ratebitmap = data[1];
854 ret = libertas_prepare_and_send_command(priv,
855 cmd_802_11_rate_adapt_rateset,
856 cmd_act_set,
857 cmd_option_waitforrsp, 0, NULL);
858 }
859 return ret;
860 }
861
862 /**
863 * @brief Get/Set inactivity timeout
864 * @param priv A pointer to wlan_private structure
865 * @param wrq A pointer to iwreq structure
866 * @return 0 --success, otherwise fail
867 */
868 static int wlan_inactivity_timeout(wlan_private * priv, struct iwreq *wrq)
869 {
870 int ret;
871 int data = 0;
872 u16 timeout = 0;
873
874 ENTER();
875 if (wrq->u.data.length > 1)
876 return -ENOTSUPP;
877
878 if (wrq->u.data.length == 0) {
879 /* Get */
880 ret = libertas_prepare_and_send_command(priv,
881 cmd_802_11_inactivity_timeout,
882 cmd_act_get,
883 cmd_option_waitforrsp, 0,
884 &timeout);
885 data = timeout;
886 if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
887 lbs_pr_debug(1, "Copy to user failed\n");
888 return -EFAULT;
889 }
890 } else {
891 /* Set */
892 if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
893 lbs_pr_debug(1, "Copy from user failed\n");
894 return -EFAULT;
895 }
896
897 timeout = data;
898 ret = libertas_prepare_and_send_command(priv,
899 cmd_802_11_inactivity_timeout,
900 cmd_act_set,
901 cmd_option_waitforrsp, 0,
902 &timeout);
903 }
904
905 wrq->u.data.length = 1;
906
907 LEAVE();
908 return ret;
909 }
910
911 static int wlan_do_getlog_ioctl(wlan_private * priv, struct iwreq *wrq)
912 {
913 int ret;
914 char buf[GETLOG_BUFSIZE - 1];
915 wlan_adapter *adapter = priv->adapter;
916
917 lbs_pr_debug(1, " GET STATS\n");
918
919 ret = libertas_prepare_and_send_command(priv, cmd_802_11_get_log,
920 0, cmd_option_waitforrsp, 0, NULL);
921
922 if (ret) {
923 return ret;
924 }
925
926 if (wrq->u.data.pointer) {
927 sprintf(buf, "\n mcasttxframe %u failed %u retry %u "
928 "multiretry %u framedup %u "
929 "rtssuccess %u rtsfailure %u ackfailure %u\n"
930 "rxfrag %u mcastrxframe %u fcserror %u "
931 "txframe %u wepundecryptable %u ",
932 adapter->logmsg.mcasttxframe,
933 adapter->logmsg.failed,
934 adapter->logmsg.retry,
935 adapter->logmsg.multiretry,
936 adapter->logmsg.framedup,
937 adapter->logmsg.rtssuccess,
938 adapter->logmsg.rtsfailure,
939 adapter->logmsg.ackfailure,
940 adapter->logmsg.rxfrag,
941 adapter->logmsg.mcastrxframe,
942 adapter->logmsg.fcserror,
943 adapter->logmsg.txframe,
944 adapter->logmsg.wepundecryptable);
945 wrq->u.data.length = strlen(buf) + 1;
946 if (copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length)) {
947 lbs_pr_debug(1, "Copy to user failed\n");
948 return -EFAULT;
949 }
950 }
951
952 return 0;
953 }
954
955 static int wlan_scan_type_ioctl(wlan_private * priv, struct iwreq *wrq)
956 {
957 u8 buf[12];
958 u8 *option[] = { "active", "passive", "get", };
959 int i, max_options = (sizeof(option) / sizeof(option[0]));
960 int ret = 0;
961 wlan_adapter *adapter = priv->adapter;
962
963 if (priv->adapter->enable11d) {
964 lbs_pr_debug(1, "11D: Cannot set scantype when 11D enabled\n");
965 return -EFAULT;
966 }
967
968 memset(buf, 0, sizeof(buf));
969
970 if (copy_from_user(buf, wrq->u.data.pointer, min_t(size_t, sizeof(buf),
971 wrq->u.data.length)))
972 return -EFAULT;
973
974 lbs_pr_debug(1, "Scan type Option = %s\n", buf);
975
976 buf[sizeof(buf) - 1] = '\0';
977
978 for (i = 0; i < max_options; i++) {
979 if (!strcmp(buf, option[i]))
980 break;
981 }
982
983 switch (i) {
984 case 0:
985 adapter->scantype = cmd_scan_type_active;
986 break;
987 case 1:
988 adapter->scantype = cmd_scan_type_passive;
989 break;
990 case 2:
991 wrq->u.data.length = strlen(option[adapter->scantype]) + 1;
992
993 if (copy_to_user(wrq->u.data.pointer,
994 option[adapter->scantype],
995 wrq->u.data.length)) {
996 lbs_pr_debug(1, "Copy to user failed\n");
997 ret = -EFAULT;
998 }
999
1000 break;
1001 default:
1002 lbs_pr_debug(1, "Invalid Scan type Ioctl Option\n");
1003 ret = -EINVAL;
1004 break;
1005 }
1006
1007 return ret;
1008 }
1009
1010 static int wlan_scan_mode_ioctl(wlan_private * priv, struct iwreq *wrq)
1011 {
1012 wlan_adapter *adapter = priv->adapter;
1013 u8 buf[12];
1014 u8 *option[] = { "bss", "ibss", "any", "get" };
1015 int i, max_options = (sizeof(option) / sizeof(option[0]));
1016 int ret = 0;
1017
1018 ENTER();
1019
1020 memset(buf, 0, sizeof(buf));
1021
1022 if (copy_from_user(buf, wrq->u.data.pointer, min_t(size_t, sizeof(buf),
1023 wrq->u.data.length))) {
1024 lbs_pr_debug(1, "Copy from user failed\n");
1025 return -EFAULT;
1026 }
1027
1028 lbs_pr_debug(1, "Scan mode Option = %s\n", buf);
1029
1030 buf[sizeof(buf) - 1] = '\0';
1031
1032 for (i = 0; i < max_options; i++) {
1033 if (!strcmp(buf, option[i]))
1034 break;
1035 }
1036
1037 switch (i) {
1038
1039 case 0:
1040 adapter->scanmode = cmd_bss_type_bss;
1041 break;
1042 case 1:
1043 adapter->scanmode = cmd_bss_type_ibss;
1044 break;
1045 case 2:
1046 adapter->scanmode = cmd_bss_type_any;
1047 break;
1048 case 3:
1049
1050 wrq->u.data.length = strlen(option[adapter->scanmode - 1]) + 1;
1051
1052 lbs_pr_debug(1, "Get Scan mode Option = %s\n",
1053 option[adapter->scanmode - 1]);
1054
1055 lbs_pr_debug(1, "Scan mode length %d\n", wrq->u.data.length);
1056
1057 if (copy_to_user(wrq->u.data.pointer,
1058 option[adapter->scanmode - 1],
1059 wrq->u.data.length)) {
1060 lbs_pr_debug(1, "Copy to user failed\n");
1061 ret = -EFAULT;
1062 }
1063 lbs_pr_debug(1, "GET Scan type Option after copy = %s\n",
1064 (char *)wrq->u.data.pointer);
1065
1066 break;
1067
1068 default:
1069 lbs_pr_debug(1, "Invalid Scan mode Ioctl Option\n");
1070 ret = -EINVAL;
1071 break;
1072 }
1073
1074 LEAVE();
1075 return ret;
1076 }
1077
1078 /**
1079 * @brief Get/Set Adhoc G Rate
1080 *
1081 * @param priv A pointer to wlan_private structure
1082 * @param wrq A pointer to user data
1083 * @return 0--success, otherwise fail
1084 */
1085 static int wlan_do_set_grate_ioctl(wlan_private * priv, struct iwreq *wrq)
1086 {
1087 wlan_adapter *adapter = priv->adapter;
1088 int data, data1;
1089 int *val;
1090
1091 ENTER();
1092
1093 data1 = SUBCMD_DATA(wrq);
1094 switch (data1) {
1095 case 0:
1096 adapter->adhoc_grate_enabled = 0;
1097 break;
1098 case 1:
1099 adapter->adhoc_grate_enabled = 1;
1100 break;
1101 case 2:
1102 break;
1103 default:
1104 return -EINVAL;
1105 }
1106 data = adapter->adhoc_grate_enabled;
1107 val = (int *)wrq->u.name;
1108 *val = data;
1109 LEAVE();
1110 return 0;
1111 }
1112
1113 static inline int hex2int(char c)
1114 {
1115 if (c >= '0' && c <= '9')
1116 return (c - '0');
1117 if (c >= 'a' && c <= 'f')
1118 return (c - 'a' + 10);
1119 if (c >= 'A' && c <= 'F')
1120 return (c - 'A' + 10);
1121 return -1;
1122 }
1123
1124 /* Convert a string representation of a MAC address ("xx:xx:xx:xx:xx:xx")
1125 into binary format (6 bytes).
1126
1127 This function expects that each byte is represented with 2 characters
1128 (e.g., 11:2:11:11:11:11 is invalid)
1129
1130 */
1131 static char *eth_str2addr(char *ethstr, u8 * addr)
1132 {
1133 int i, val, val2;
1134 char *pos = ethstr;
1135
1136 /* get rid of initial blanks */
1137 while (*pos == ' ' || *pos == '\t')
1138 ++pos;
1139
1140 for (i = 0; i < 6; i++) {
1141 val = hex2int(*pos++);
1142 if (val < 0)
1143 return NULL;
1144 val2 = hex2int(*pos++);
1145 if (val2 < 0)
1146 return NULL;
1147 addr[i] = (val * 16 + val2) & 0xff;
1148
1149 if (i < 5 && *pos++ != ':')
1150 return NULL;
1151 }
1152 return pos;
1153 }
1154
1155 /* this writes xx:xx:xx:xx:xx:xx into ethstr
1156 (ethstr must have space for 18 chars) */
1157 static int eth_addr2str(u8 * addr, char *ethstr)
1158 {
1159 int i;
1160 char *pos = ethstr;
1161
1162 for (i = 0; i < 6; i++) {
1163 sprintf(pos, "%02x", addr[i] & 0xff);
1164 pos += 2;
1165 if (i < 5)
1166 *pos++ = ':';
1167 }
1168 return 17;
1169 }
1170
1171 /**
1172 * @brief Add an entry to the BT table
1173 * @param priv A pointer to wlan_private structure
1174 * @param req A pointer to ifreq structure
1175 * @return 0 --success, otherwise fail
1176 */
1177 static int wlan_bt_add_ioctl(wlan_private * priv, struct ifreq *req)
1178 {
1179 struct iwreq *wrq = (struct iwreq *)req;
1180 char ethaddrs_str[18];
1181 char *pos;
1182 u8 ethaddr[ETH_ALEN];
1183
1184 ENTER();
1185 if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
1186 sizeof(ethaddrs_str)))
1187 return -EFAULT;
1188
1189 if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
1190 lbs_pr_info("BT_ADD: Invalid MAC address\n");
1191 return -EINVAL;
1192 }
1193
1194 lbs_pr_debug(1, "BT: adding %s\n", ethaddrs_str);
1195 LEAVE();
1196 return (libertas_prepare_and_send_command(priv, cmd_bt_access,
1197 cmd_act_bt_access_add,
1198 cmd_option_waitforrsp, 0, ethaddr));
1199 }
1200
1201 /**
1202 * @brief Delete an entry from the BT table
1203 * @param priv A pointer to wlan_private structure
1204 * @param req A pointer to ifreq structure
1205 * @return 0 --success, otherwise fail
1206 */
1207 static int wlan_bt_del_ioctl(wlan_private * priv, struct ifreq *req)
1208 {
1209 struct iwreq *wrq = (struct iwreq *)req;
1210 char ethaddrs_str[18];
1211 u8 ethaddr[ETH_ALEN];
1212 char *pos;
1213
1214 ENTER();
1215 if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
1216 sizeof(ethaddrs_str)))
1217 return -EFAULT;
1218
1219 if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
1220 lbs_pr_info("Invalid MAC address\n");
1221 return -EINVAL;
1222 }
1223
1224 lbs_pr_debug(1, "BT: deleting %s\n", ethaddrs_str);
1225
1226 return (libertas_prepare_and_send_command(priv,
1227 cmd_bt_access,
1228 cmd_act_bt_access_del,
1229 cmd_option_waitforrsp, 0, ethaddr));
1230 LEAVE();
1231 return 0;
1232 }
1233
1234 /**
1235 * @brief Reset all entries from the BT table
1236 * @param priv A pointer to wlan_private structure
1237 * @return 0 --success, otherwise fail
1238 */
1239 static int wlan_bt_reset_ioctl(wlan_private * priv)
1240 {
1241 ENTER();
1242
1243 lbs_pr_alert( "BT: resetting\n");
1244
1245 return (libertas_prepare_and_send_command(priv,
1246 cmd_bt_access,
1247 cmd_act_bt_access_reset,
1248 cmd_option_waitforrsp, 0, NULL));
1249
1250 LEAVE();
1251 return 0;
1252 }
1253
1254 /**
1255 * @brief List an entry from the BT table
1256 * @param priv A pointer to wlan_private structure
1257 * @param req A pointer to ifreq structure
1258 * @return 0 --success, otherwise fail
1259 */
1260 static int wlan_bt_list_ioctl(wlan_private * priv, struct ifreq *req)
1261 {
1262 int pos;
1263 char *addr1;
1264 struct iwreq *wrq = (struct iwreq *)req;
1265 /* used to pass id and store the bt entry returned by the FW */
1266 union {
1267 int id;
1268 char addr1addr2[2 * ETH_ALEN];
1269 } param;
1270 static char outstr[64];
1271 char *pbuf = outstr;
1272 int ret;
1273
1274 ENTER();
1275
1276 if (copy_from_user(outstr, wrq->u.data.pointer, sizeof(outstr))) {
1277 lbs_pr_debug(1, "Copy from user failed\n");
1278 return -1;
1279 }
1280 param.id = simple_strtoul(outstr, NULL, 10);
1281 pos = sprintf(pbuf, "%d: ", param.id);
1282 pbuf += pos;
1283
1284 ret = libertas_prepare_and_send_command(priv, cmd_bt_access,
1285 cmd_act_bt_access_list,
1286 cmd_option_waitforrsp, 0,
1287 (char *)&param);
1288
1289 if (ret == 0) {
1290 addr1 = param.addr1addr2;
1291
1292 pos = sprintf(pbuf, "ignoring traffic from ");
1293 pbuf += pos;
1294 pos = eth_addr2str(addr1, pbuf);
1295 pbuf += pos;
1296 } else {
1297 sprintf(pbuf, "(null)");
1298 pbuf += pos;
1299 }
1300
1301 wrq->u.data.length = strlen(outstr);
1302 if (copy_to_user(wrq->u.data.pointer, (char *)outstr,
1303 wrq->u.data.length)) {
1304 lbs_pr_debug(1, "BT_LIST: Copy to user failed!\n");
1305 return -EFAULT;
1306 }
1307
1308 LEAVE();
1309 return 0;
1310 }
1311
1312 /**
1313 * @brief Find the next parameter in an input string
1314 * @param ptr A pointer to the input parameter string
1315 * @return A pointer to the next parameter, or 0 if no parameters left.
1316 */
1317 static char * next_param(char * ptr)
1318 {
1319 if (!ptr) return NULL;
1320 while (*ptr == ' ' || *ptr == '\t') ++ptr;
1321 return (*ptr == '\0') ? NULL : ptr;
1322 }
1323
1324 /**
1325 * @brief Add an entry to the FWT table
1326 * @param priv A pointer to wlan_private structure
1327 * @param req A pointer to ifreq structure
1328 * @return 0 --success, otherwise fail
1329 */
1330 static int wlan_fwt_add_ioctl(wlan_private * priv, struct ifreq *req)
1331 {
1332 struct iwreq *wrq = (struct iwreq *)req;
1333 char in_str[128];
1334 static struct cmd_ds_fwt_access fwt_access;
1335 char *ptr;
1336
1337 ENTER();
1338 if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
1339 return -EFAULT;
1340
1341 if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
1342 lbs_pr_alert( "FWT_ADD: Invalid MAC address 1\n");
1343 return -EINVAL;
1344 }
1345
1346 if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) {
1347 lbs_pr_alert( "FWT_ADD: Invalid MAC address 2\n");
1348 return -EINVAL;
1349 }
1350
1351 if ((ptr = next_param(ptr)))
1352 fwt_access.metric =
1353 cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
1354 else
1355 fwt_access.metric = FWT_DEFAULT_METRIC;
1356
1357 if ((ptr = next_param(ptr)))
1358 fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10);
1359 else
1360 fwt_access.dir = FWT_DEFAULT_DIR;
1361
1362 if ((ptr = next_param(ptr)))
1363 fwt_access.ssn =
1364 cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
1365 else
1366 fwt_access.ssn = FWT_DEFAULT_SSN;
1367
1368 if ((ptr = next_param(ptr)))
1369 fwt_access.dsn =
1370 cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
1371 else
1372 fwt_access.dsn = FWT_DEFAULT_DSN;
1373
1374 if ((ptr = next_param(ptr)))
1375 fwt_access.hopcount = simple_strtoul(ptr, &ptr, 10);
1376 else
1377 fwt_access.hopcount = FWT_DEFAULT_HOPCOUNT;
1378
1379 if ((ptr = next_param(ptr)))
1380 fwt_access.ttl = simple_strtoul(ptr, &ptr, 10);
1381 else
1382 fwt_access.ttl = FWT_DEFAULT_TTL;
1383
1384 if ((ptr = next_param(ptr)))
1385 fwt_access.expiration =
1386 cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
1387 else
1388 fwt_access.expiration = FWT_DEFAULT_EXPIRATION;
1389
1390 if ((ptr = next_param(ptr)))
1391 fwt_access.sleepmode = (u8)simple_strtoul(ptr, &ptr, 10);
1392 else
1393 fwt_access.sleepmode = FWT_DEFAULT_SLEEPMODE;
1394
1395 if ((ptr = next_param(ptr)))
1396 fwt_access.snr =
1397 cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
1398 else
1399 fwt_access.snr = FWT_DEFAULT_SNR;
1400
1401 #ifdef DEBUG
1402 {
1403 char ethaddr1_str[18], ethaddr2_str[18];
1404 eth_addr2str(fwt_access.da, ethaddr1_str);
1405 eth_addr2str(fwt_access.ra, ethaddr2_str);
1406 lbs_pr_debug(1, "FWT_ADD: adding (da:%s,%i,ra:%s)\n", ethaddr1_str,
1407 fwt_access.dir, ethaddr2_str);
1408 lbs_pr_debug(1, "FWT_ADD: ssn:%u dsn:%u met:%u hop:%u ttl:%u exp:%u slp:%u snr:%u\n",
1409 fwt_access.ssn, fwt_access.dsn, fwt_access.metric,
1410 fwt_access.hopcount, fwt_access.ttl, fwt_access.expiration,
1411 fwt_access.sleepmode, fwt_access.snr);
1412 }
1413 #endif
1414
1415 LEAVE();
1416 return (libertas_prepare_and_send_command(priv, cmd_fwt_access,
1417 cmd_act_fwt_access_add,
1418 cmd_option_waitforrsp, 0,
1419 (void *)&fwt_access));
1420 }
1421
1422 /**
1423 * @brief Delete an entry from the FWT table
1424 * @param priv A pointer to wlan_private structure
1425 * @param req A pointer to ifreq structure
1426 * @return 0 --success, otherwise fail
1427 */
1428 static int wlan_fwt_del_ioctl(wlan_private * priv, struct ifreq *req)
1429 {
1430 struct iwreq *wrq = (struct iwreq *)req;
1431 char in_str[64];
1432 static struct cmd_ds_fwt_access fwt_access;
1433 char *ptr;
1434
1435 ENTER();
1436 if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
1437 return -EFAULT;
1438
1439 if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
1440 lbs_pr_alert( "FWT_DEL: Invalid MAC address 1\n");
1441 return -EINVAL;
1442 }
1443
1444 if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) {
1445 lbs_pr_alert( "FWT_DEL: Invalid MAC address 2\n");
1446 return -EINVAL;
1447 }
1448
1449 if ((ptr = next_param(ptr)))
1450 fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10);
1451 else
1452 fwt_access.dir = FWT_DEFAULT_DIR;
1453
1454 #ifdef DEBUG
1455 {
1456 char ethaddr1_str[18], ethaddr2_str[18];
1457 lbs_pr_debug(1, "FWT_DEL: line is %s\n", in_str);
1458 eth_addr2str(fwt_access.da, ethaddr1_str);
1459 eth_addr2str(fwt_access.ra, ethaddr2_str);
1460 lbs_pr_debug(1, "FWT_DEL: removing (da:%s,ra:%s,dir:%d)\n", ethaddr1_str,
1461 ethaddr2_str, fwt_access.dir);
1462 }
1463 #endif
1464
1465 LEAVE();
1466 return (libertas_prepare_and_send_command(priv,
1467 cmd_fwt_access,
1468 cmd_act_fwt_access_del,
1469 cmd_option_waitforrsp, 0,
1470 (void *)&fwt_access));
1471 }
1472
1473
1474 /**
1475 * @brief Print route parameters
1476 * @param fwt_access struct cmd_ds_fwt_access with route info
1477 * @param buf destination buffer for route info
1478 */
1479 static void print_route(struct cmd_ds_fwt_access fwt_access, char *buf)
1480 {
1481 buf += sprintf(buf, " ");
1482 buf += eth_addr2str(fwt_access.da, buf);
1483 buf += sprintf(buf, " ");
1484 buf += eth_addr2str(fwt_access.ra, buf);
1485 buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.metric));
1486 buf += sprintf(buf, " %u", fwt_access.dir);
1487 buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.ssn));
1488 buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.dsn));
1489 buf += sprintf(buf, " %u", fwt_access.hopcount);
1490 buf += sprintf(buf, " %u", fwt_access.ttl);
1491 buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.expiration));
1492 buf += sprintf(buf, " %u", fwt_access.sleepmode);
1493 buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.snr));
1494 }
1495
1496 /**
1497 * @brief Lookup an entry in the FWT table
1498 * @param priv A pointer to wlan_private structure
1499 * @param req A pointer to ifreq structure
1500 * @return 0 --success, otherwise fail
1501 */
1502 static int wlan_fwt_lookup_ioctl(wlan_private * priv, struct ifreq *req)
1503 {
1504 struct iwreq *wrq = (struct iwreq *)req;
1505 char in_str[64];
1506 char *ptr;
1507 static struct cmd_ds_fwt_access fwt_access;
1508 static char out_str[128];
1509 int ret;
1510
1511 ENTER();
1512 if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
1513 return -EFAULT;
1514
1515 if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
1516 lbs_pr_alert( "FWT_LOOKUP: Invalid MAC address\n");
1517 return -EINVAL;
1518 }
1519
1520 #ifdef DEBUG
1521 {
1522 char ethaddr1_str[18];
1523 lbs_pr_debug(1, "FWT_LOOKUP: line is %s\n", in_str);
1524 eth_addr2str(fwt_access.da, ethaddr1_str);
1525 lbs_pr_debug(1, "FWT_LOOKUP: looking for (da:%s)\n", ethaddr1_str);
1526 }
1527 #endif
1528
1529 ret = libertas_prepare_and_send_command(priv,
1530 cmd_fwt_access,
1531 cmd_act_fwt_access_lookup,
1532 cmd_option_waitforrsp, 0,
1533 (void *)&fwt_access);
1534
1535 if (ret == 0)
1536 print_route(fwt_access, out_str);
1537 else
1538 sprintf(out_str, "(null)");
1539
1540 wrq->u.data.length = strlen(out_str);
1541 if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
1542 wrq->u.data.length)) {
1543 lbs_pr_debug(1, "FWT_LOOKUP: Copy to user failed!\n");
1544 return -EFAULT;
1545 }
1546
1547 LEAVE();
1548 return 0;
1549 }
1550
1551 /**
1552 * @brief Reset all entries from the FWT table
1553 * @param priv A pointer to wlan_private structure
1554 * @return 0 --success, otherwise fail
1555 */
1556 static int wlan_fwt_reset_ioctl(wlan_private * priv)
1557 {
1558 lbs_pr_debug(1, "FWT: resetting\n");
1559
1560 return (libertas_prepare_and_send_command(priv,
1561 cmd_fwt_access,
1562 cmd_act_fwt_access_reset,
1563 cmd_option_waitforrsp, 0, NULL));
1564 }
1565
1566 /**
1567 * @brief List an entry from the FWT table
1568 * @param priv A pointer to wlan_private structure
1569 * @param req A pointer to ifreq structure
1570 * @return 0 --success, otherwise fail
1571 */
1572 static int wlan_fwt_list_ioctl(wlan_private * priv, struct ifreq *req)
1573 {
1574 struct iwreq *wrq = (struct iwreq *)req;
1575 char in_str[8];
1576 static struct cmd_ds_fwt_access fwt_access;
1577 char *ptr = in_str;
1578 static char out_str[128];
1579 char *pbuf = out_str;
1580 int ret;
1581
1582 ENTER();
1583 if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
1584 return -EFAULT;
1585
1586 fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
1587
1588 #ifdef DEBUG
1589 {
1590 lbs_pr_debug(1, "FWT_LIST: line is %s\n", in_str);
1591 lbs_pr_debug(1, "FWT_LIST: listing id:%i\n", le32_to_cpu(fwt_access.id));
1592 }
1593 #endif
1594
1595 ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
1596 cmd_act_fwt_access_list,
1597 cmd_option_waitforrsp, 0, (void *)&fwt_access);
1598
1599 if (ret == 0)
1600 print_route(fwt_access, pbuf);
1601 else
1602 pbuf += sprintf(pbuf, " (null)");
1603
1604 wrq->u.data.length = strlen(out_str);
1605 if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
1606 wrq->u.data.length)) {
1607 lbs_pr_debug(1, "FWT_LIST: Copy to user failed!\n");
1608 return -EFAULT;
1609 }
1610
1611 LEAVE();
1612 return 0;
1613 }
1614
1615 /**
1616 * @brief List an entry from the FRT table
1617 * @param priv A pointer to wlan_private structure
1618 * @param req A pointer to ifreq structure
1619 * @return 0 --success, otherwise fail
1620 */
1621 static int wlan_fwt_list_route_ioctl(wlan_private * priv, struct ifreq *req)
1622 {
1623 struct iwreq *wrq = (struct iwreq *)req;
1624 char in_str[64];
1625 static struct cmd_ds_fwt_access fwt_access;
1626 char *ptr = in_str;
1627 static char out_str[128];
1628 char *pbuf = out_str;
1629 int ret;
1630
1631 ENTER();
1632 if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
1633 return -EFAULT;
1634
1635 fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
1636
1637 #ifdef DEBUG
1638 {
1639 lbs_pr_debug(1, "FWT_LIST_ROUTE: line is %s\n", in_str);
1640 lbs_pr_debug(1, "FWT_LIST_ROUTE: listing id:%i\n", le32_to_cpu(fwt_access.id));
1641 }
1642 #endif
1643
1644 ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
1645 cmd_act_fwt_access_list_route,
1646 cmd_option_waitforrsp, 0, (void *)&fwt_access);
1647
1648 if (ret == 0) {
1649 pbuf += sprintf(pbuf, " ");
1650 pbuf += eth_addr2str(fwt_access.da, pbuf);
1651 pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.metric));
1652 pbuf += sprintf(pbuf, " %u", fwt_access.dir);
1653 /* note that the firmware returns the nid in the id field */
1654 pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.id));
1655 pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.ssn));
1656 pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.dsn));
1657 pbuf += sprintf(pbuf, " hop %u", fwt_access.hopcount);
1658 pbuf += sprintf(pbuf, " ttl %u", fwt_access.ttl);
1659 pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.expiration));
1660 } else
1661 pbuf += sprintf(pbuf, " (null)");
1662
1663 wrq->u.data.length = strlen(out_str);
1664 if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
1665 wrq->u.data.length)) {
1666 lbs_pr_debug(1, "FWT_LIST_ROUTE: Copy to user failed!\n");
1667 return -EFAULT;
1668 }
1669
1670 LEAVE();
1671 return 0;
1672 }
1673
1674 /**
1675 * @brief List an entry from the FNT table
1676 * @param priv A pointer to wlan_private structure
1677 * @param req A pointer to ifreq structure
1678 * @return 0 --success, otherwise fail
1679 */
1680 static int wlan_fwt_list_neighbor_ioctl(wlan_private * priv, struct ifreq *req)
1681 {
1682 struct iwreq *wrq = (struct iwreq *)req;
1683 char in_str[8];
1684 static struct cmd_ds_fwt_access fwt_access;
1685 char *ptr = in_str;
1686 static char out_str[128];
1687 char *pbuf = out_str;
1688 int ret;
1689
1690 ENTER();
1691 if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
1692 return -EFAULT;
1693
1694 memset(&fwt_access, 0, sizeof(fwt_access));
1695 fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
1696
1697 #ifdef DEBUG
1698 {
1699 lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: line is %s\n", in_str);
1700 lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: listing id:%i\n", le32_to_cpu(fwt_access.id));
1701 }
1702 #endif
1703
1704 ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
1705 cmd_act_fwt_access_list_neighbor,
1706 cmd_option_waitforrsp, 0,
1707 (void *)&fwt_access);
1708
1709 if (ret == 0) {
1710 pbuf += sprintf(pbuf, " ra ");
1711 pbuf += eth_addr2str(fwt_access.ra, pbuf);
1712 pbuf += sprintf(pbuf, " slp %u", fwt_access.sleepmode);
1713 pbuf += sprintf(pbuf, " snr %u", le32_to_cpu(fwt_access.snr));
1714 pbuf += sprintf(pbuf, " ref %u", le32_to_cpu(fwt_access.references));
1715 } else
1716 pbuf += sprintf(pbuf, " (null)");
1717
1718 wrq->u.data.length = strlen(out_str);
1719 if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
1720 wrq->u.data.length)) {
1721 lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: Copy to user failed!\n");
1722 return -EFAULT;
1723 }
1724
1725 LEAVE();
1726 return 0;
1727 }
1728
1729 /**
1730 * @brief Cleans up the route (FRT) and neighbor (FNT) tables
1731 * (Garbage Collection)
1732 * @param priv A pointer to wlan_private structure
1733 * @param req A pointer to ifreq structure
1734 * @return 0 --success, otherwise fail
1735 */
1736 static int wlan_fwt_cleanup_ioctl(wlan_private * priv, struct ifreq *req)
1737 {
1738 static struct cmd_ds_fwt_access fwt_access;
1739 int ret;
1740
1741 ENTER();
1742
1743 lbs_pr_debug(1, "FWT: cleaning up\n");
1744
1745 memset(&fwt_access, 0, sizeof(fwt_access));
1746
1747 ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
1748 cmd_act_fwt_access_cleanup,
1749 cmd_option_waitforrsp, 0,
1750 (void *)&fwt_access);
1751
1752 if (ret == 0)
1753 req->ifr_data = (char *)(le32_to_cpu(fwt_access.references));
1754 else
1755 return -EFAULT;
1756
1757 LEAVE();
1758 return 0;
1759 }
1760
1761 /**
1762 * @brief Gets firmware internal time (debug purposes)
1763 * @param priv A pointer to wlan_private structure
1764 * @param req A pointer to ifreq structure
1765 * @return 0 --success, otherwise fail
1766 */
1767 static int wlan_fwt_time_ioctl(wlan_private * priv, struct ifreq *req)
1768 {
1769 static struct cmd_ds_fwt_access fwt_access;
1770 int ret;
1771
1772 ENTER();
1773
1774 lbs_pr_debug(1, "FWT: getting time\n");
1775
1776 memset(&fwt_access, 0, sizeof(fwt_access));
1777
1778 ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
1779 cmd_act_fwt_access_time,
1780 cmd_option_waitforrsp, 0,
1781 (void *)&fwt_access);
1782
1783 if (ret == 0)
1784 req->ifr_data = (char *)(le32_to_cpu(fwt_access.references));
1785 else
1786 return -EFAULT;
1787
1788 LEAVE();
1789 return 0;
1790 }
1791
1792 /**
1793 * @brief Gets mesh ttl from firmware
1794 * @param priv A pointer to wlan_private structure
1795 * @param req A pointer to ifreq structure
1796 * @return 0 --success, otherwise fail
1797 */
1798 static int wlan_mesh_get_ttl_ioctl(wlan_private * priv, struct ifreq *req)
1799 {
1800 struct cmd_ds_mesh_access mesh_access;
1801 int ret;
1802
1803 ENTER();
1804
1805 memset(&mesh_access, 0, sizeof(mesh_access));
1806
1807 ret = libertas_prepare_and_send_command(priv, cmd_mesh_access,
1808 cmd_act_mesh_get_ttl,
1809 cmd_option_waitforrsp, 0,
1810 (void *)&mesh_access);
1811
1812 if (ret == 0) {
1813 req->ifr_data = (char *)(le32_to_cpu(mesh_access.data[0]));
1814 }
1815 else
1816 return -EFAULT;
1817
1818 LEAVE();
1819 return 0;
1820 }
1821
1822 /**
1823 * @brief Gets mesh ttl from firmware
1824 * @param priv A pointer to wlan_private structure
1825 * @param ttl New ttl value
1826 * @return 0 --success, otherwise fail
1827 */
1828 static int wlan_mesh_set_ttl_ioctl(wlan_private * priv, int ttl)
1829 {
1830 struct cmd_ds_mesh_access mesh_access;
1831 int ret;
1832
1833 ENTER();
1834
1835 if( (ttl > 0xff) || (ttl < 0) )
1836 return -EINVAL;
1837
1838 memset(&mesh_access, 0, sizeof(mesh_access));
1839 mesh_access.data[0] = ttl;
1840
1841 ret = libertas_prepare_and_send_command(priv, cmd_mesh_access,
1842 cmd_act_mesh_set_ttl,
1843 cmd_option_waitforrsp, 0,
1844 (void *)&mesh_access);
1845
1846 if (ret != 0)
1847 ret = -EFAULT;
1848
1849 LEAVE();
1850 return ret;
1851 }
1852
1853 /**
1854 * @brief ioctl function - entry point
1855 *
1856 * @param dev A pointer to net_device structure
1857 * @param req A pointer to ifreq structure
1858 * @param cmd command
1859 * @return 0--success, otherwise fail
1860 */
1861 int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
1862 {
1863 int subcmd = 0;
1864 int idata = 0;
1865 int *pdata;
1866 int ret = 0;
1867 wlan_private *priv = dev->priv;
1868 wlan_adapter *adapter = priv->adapter;
1869 struct iwreq *wrq = (struct iwreq *)req;
1870
1871 ENTER();
1872
1873 lbs_pr_debug(1, "libertas_do_ioctl: ioctl cmd = 0x%x\n", cmd);
1874 switch (cmd) {
1875 case WLANSCAN_TYPE:
1876 lbs_pr_debug(1, "Scan type Ioctl\n");
1877 ret = wlan_scan_type_ioctl(priv, wrq);
1878 break;
1879
1880 case WLAN_SETNONE_GETNONE: /* set WPA mode on/off ioctl #20 */
1881 switch (wrq->u.data.flags) {
1882 case WLANDEAUTH:
1883 lbs_pr_debug(1, "Deauth\n");
1884 libertas_send_deauth(priv);
1885 break;
1886
1887 case WLANADHOCSTOP:
1888 lbs_pr_debug(1, "Adhoc stop\n");
1889 ret = libertas_do_adhocstop_ioctl(priv);
1890 break;
1891
1892 case WLANRADIOON:
1893 wlan_radio_ioctl(priv, 1);
1894 break;
1895
1896 case WLANRADIOOFF:
1897 wlan_radio_ioctl(priv, 0);
1898 break;
1899 case WLANWLANIDLEON:
1900 libertas_idle_on(priv);
1901 break;
1902 case WLANWLANIDLEOFF:
1903 libertas_idle_off(priv);
1904 break;
1905 case WLAN_SUBCMD_BT_RESET: /* bt_reset */
1906 wlan_bt_reset_ioctl(priv);
1907 break;
1908 case WLAN_SUBCMD_FWT_RESET: /* fwt_reset */
1909 wlan_fwt_reset_ioctl(priv);
1910 break;
1911 } /* End of switch */
1912 break;
1913
1914 case WLANSETWPAIE:
1915 ret = wlan_setwpaie_ioctl(priv, req);
1916 break;
1917 case WLAN_SETINT_GETINT:
1918 /* The first 4 bytes of req->ifr_data is sub-ioctl number
1919 * after 4 bytes sits the payload.
1920 */
1921 subcmd = (int)req->ifr_data; //from iwpriv subcmd
1922 switch (subcmd) {
1923 case WLANNF:
1924 ret = wlan_get_nf(priv, wrq);
1925 break;
1926 case WLANRSSI:
1927 ret = wlan_get_rssi(priv, wrq);
1928 break;
1929 case WLANENABLE11D:
1930 ret = libertas_cmd_enable_11d(priv, wrq);
1931 break;
1932 case WLANADHOCGRATE:
1933 ret = wlan_do_set_grate_ioctl(priv, wrq);
1934 break;
1935 case WLAN_SUBCMD_SET_PRESCAN:
1936 ret = wlan_subcmd_setprescan_ioctl(priv, wrq);
1937 break;
1938 }
1939 break;
1940
1941 case WLAN_SETONEINT_GETONEINT:
1942 switch (wrq->u.data.flags) {
1943 case WLAN_BEACON_INTERVAL:
1944 ret = wlan_beacon_interval(priv, wrq);
1945 break;
1946
1947 case WLAN_LISTENINTRVL:
1948 if (!wrq->u.data.length) {
1949 int data;
1950 lbs_pr_debug(1, "Get locallisteninterval value\n");
1951 #define GET_ONE_INT 1
1952 data = adapter->locallisteninterval;
1953 if (copy_to_user(wrq->u.data.pointer,
1954 &data, sizeof(int))) {
1955 lbs_pr_debug(1, "Copy to user failed\n");
1956 return -EFAULT;
1957 }
1958
1959 wrq->u.data.length = GET_ONE_INT;
1960 } else {
1961 int data;
1962 if (copy_from_user
1963 (&data, wrq->u.data.pointer, sizeof(int))) {
1964 lbs_pr_debug(1, "Copy from user failed\n");
1965 return -EFAULT;
1966 }
1967
1968 lbs_pr_debug(1, "Set locallisteninterval = %d\n",
1969 data);
1970 #define MAX_U16_VAL 65535
1971 if (data > MAX_U16_VAL) {
1972 lbs_pr_debug(1, "Exceeds U16 value\n");
1973 return -EINVAL;
1974 }
1975 adapter->locallisteninterval = data;
1976 }
1977 break;
1978 case WLAN_TXCONTROL:
1979 ret = wlan_txcontrol(priv, wrq); //adds for txcontrol ioctl
1980 break;
1981
1982 case WLAN_NULLPKTINTERVAL:
1983 ret = wlan_null_pkt_interval(priv, wrq);
1984 break;
1985
1986 default:
1987 ret = -EOPNOTSUPP;
1988 break;
1989 }
1990 break;
1991
1992 case WLAN_SETONEINT_GETNONE:
1993 /* The first 4 bytes of req->ifr_data is sub-ioctl number
1994 * after 4 bytes sits the payload.
1995 */
1996 subcmd = wrq->u.data.flags; //from wpa_supplicant subcmd
1997
1998 if (!subcmd)
1999 subcmd = (int)req->ifr_data; //from iwpriv subcmd
2000
2001 switch (subcmd) {
2002 case WLAN_SUBCMD_SETRXANTENNA: /* SETRXANTENNA */
2003 idata = SUBCMD_DATA(wrq);
2004 ret = setrxantenna(priv, idata);
2005 break;
2006 case WLAN_SUBCMD_SETTXANTENNA: /* SETTXANTENNA */
2007 idata = SUBCMD_DATA(wrq);
2008 ret = settxantenna(priv, idata);
2009 break;
2010 case WLAN_SET_ATIM_WINDOW:
2011 adapter->atimwindow = SUBCMD_DATA(wrq);
2012 adapter->atimwindow = min_t(__u16, adapter->atimwindow, 50);
2013 break;
2014 case WLANSETBCNAVG:
2015 adapter->bcn_avg_factor = SUBCMD_DATA(wrq);
2016 if (adapter->bcn_avg_factor == 0)
2017 adapter->bcn_avg_factor =
2018 DEFAULT_BCN_AVG_FACTOR;
2019 if (adapter->bcn_avg_factor > DEFAULT_BCN_AVG_FACTOR)
2020 adapter->bcn_avg_factor =
2021 DEFAULT_BCN_AVG_FACTOR;
2022 break;
2023 case WLANSETDATAAVG:
2024 adapter->data_avg_factor = SUBCMD_DATA(wrq);
2025 if (adapter->data_avg_factor == 0)
2026 adapter->data_avg_factor =
2027 DEFAULT_DATA_AVG_FACTOR;
2028 if (adapter->data_avg_factor > DEFAULT_DATA_AVG_FACTOR)
2029 adapter->data_avg_factor =
2030 DEFAULT_DATA_AVG_FACTOR;
2031 break;
2032 case WLANSETREGION:
2033 idata = SUBCMD_DATA(wrq);
2034 ret = wlan_set_region(priv, (u16) idata);
2035 break;
2036
2037 case WLAN_SET_LISTEN_INTERVAL:
2038 idata = SUBCMD_DATA(wrq);
2039 adapter->listeninterval = (u16) idata;
2040 break;
2041
2042 case WLAN_SET_MULTIPLE_DTIM:
2043 ret = wlan_set_multiple_dtim_ioctl(priv, req);
2044 break;
2045
2046 case WLANSETAUTHALG:
2047 ret = wlan_setauthalg_ioctl(priv, req);
2048 break;
2049
2050 case WLANSETENCRYPTIONMODE:
2051 ret = wlan_setencryptionmode_ioctl(priv, req);
2052 break;
2053
2054 case WLAN_SET_LINKMODE:
2055 ret = wlan_set_linkmode_ioctl(priv, req);
2056 break;
2057
2058 case WLAN_SET_RADIOMODE:
2059 ret = wlan_set_radiomode_ioctl(priv, req);
2060 break;
2061
2062 case WLAN_SET_DEBUGMODE:
2063 ret = wlan_set_debugmode_ioctl(priv, req);
2064 break;
2065
2066 case WLAN_SUBCMD_MESH_SET_TTL:
2067 idata = SUBCMD_DATA(wrq);
2068 ret = wlan_mesh_set_ttl_ioctl(priv, idata);
2069 break;
2070
2071 default:
2072 ret = -EOPNOTSUPP;
2073 break;
2074 }
2075
2076 break;
2077
2078 case WLAN_SETNONE_GETTWELVE_CHAR: /* Get Antenna settings */
2079 /*
2080 * We've not used IW_PRIV_TYPE_FIXED so sub-ioctl number is
2081 * in flags of iwreq structure, otherwise it will be in
2082 * mode member of iwreq structure.
2083 */
2084 switch ((int)wrq->u.data.flags) {
2085 case WLAN_SUBCMD_GETRXANTENNA: /* Get Rx Antenna */
2086 ret = wlan_subcmd_getrxantenna_ioctl(priv, req);
2087 break;
2088
2089 case WLAN_SUBCMD_GETTXANTENNA: /* Get Tx Antenna */
2090 ret = wlan_subcmd_gettxantenna_ioctl(priv, req);
2091 break;
2092
2093 case WLAN_GET_TSF:
2094 ret = wlan_get_tsf_ioctl(priv, wrq);
2095 break;
2096 }
2097 break;
2098
2099 case WLAN_SET128CHAR_GET128CHAR:
2100 switch ((int)wrq->u.data.flags) {
2101
2102 case WLANSCAN_MODE:
2103 lbs_pr_debug(1, "Scan mode Ioctl\n");
2104 ret = wlan_scan_mode_ioctl(priv, wrq);
2105 break;
2106
2107 case WLAN_GET_ADHOC_STATUS:
2108 ret = wlan_get_adhoc_status_ioctl(priv, wrq);
2109 break;
2110 case WLAN_SUBCMD_BT_ADD:
2111 ret = wlan_bt_add_ioctl(priv, req);
2112 break;
2113 case WLAN_SUBCMD_BT_DEL:
2114 ret = wlan_bt_del_ioctl(priv, req);
2115 break;
2116 case WLAN_SUBCMD_BT_LIST:
2117 ret = wlan_bt_list_ioctl(priv, req);
2118 break;
2119 case WLAN_SUBCMD_FWT_ADD:
2120 ret = wlan_fwt_add_ioctl(priv, req);
2121 break;
2122 case WLAN_SUBCMD_FWT_DEL:
2123 ret = wlan_fwt_del_ioctl(priv, req);
2124 break;
2125 case WLAN_SUBCMD_FWT_LOOKUP:
2126 ret = wlan_fwt_lookup_ioctl(priv, req);
2127 break;
2128 case WLAN_SUBCMD_FWT_LIST_NEIGHBOR:
2129 ret = wlan_fwt_list_neighbor_ioctl(priv, req);
2130 break;
2131 case WLAN_SUBCMD_FWT_LIST:
2132 ret = wlan_fwt_list_ioctl(priv, req);
2133 break;
2134 case WLAN_SUBCMD_FWT_LIST_ROUTE:
2135 ret = wlan_fwt_list_route_ioctl(priv, req);
2136 break;
2137 }
2138 break;
2139
2140 case WLAN_SETNONE_GETONEINT:
2141 switch ((int)req->ifr_data) {
2142 case WLANGETBCNAVG:
2143 pdata = (int *)wrq->u.name;
2144 *pdata = (int)adapter->bcn_avg_factor;
2145 break;
2146
2147 case WLANGETREGION:
2148 pdata = (int *)wrq->u.name;
2149 *pdata = (int)adapter->regioncode;
2150 break;
2151
2152 case WLAN_GET_LISTEN_INTERVAL:
2153 pdata = (int *)wrq->u.name;
2154 *pdata = (int)adapter->listeninterval;
2155 break;
2156
2157 case WLAN_GET_LINKMODE:
2158 req->ifr_data = (char *)((u32) adapter->linkmode);
2159 break;
2160
2161 case WLAN_GET_RADIOMODE:
2162 req->ifr_data = (char *)((u32) adapter->radiomode);
2163 break;
2164
2165 case WLAN_GET_DEBUGMODE:
2166 req->ifr_data = (char *)((u32) adapter->debugmode);
2167 break;
2168
2169 case WLAN_GET_MULTIPLE_DTIM:
2170 pdata = (int *)wrq->u.name;
2171 *pdata = (int)adapter->multipledtim;
2172 break;
2173 case WLAN_GET_TX_RATE:
2174 ret = wlan_get_txrate_ioctl(priv, req);
2175 break;
2176 case WLAN_SUBCMD_FWT_CLEANUP: /* fwt_cleanup */
2177 ret = wlan_fwt_cleanup_ioctl(priv, req);
2178 break;
2179
2180 case WLAN_SUBCMD_FWT_TIME: /* fwt_time */
2181 ret = wlan_fwt_time_ioctl(priv, req);
2182 break;
2183
2184 case WLAN_SUBCMD_MESH_GET_TTL:
2185 ret = wlan_mesh_get_ttl_ioctl(priv, req);
2186 break;
2187
2188 default:
2189 ret = -EOPNOTSUPP;
2190
2191 }
2192
2193 break;
2194
2195 case WLANGETLOG:
2196 ret = wlan_do_getlog_ioctl(priv, wrq);
2197 break;
2198
2199 case WLAN_SET_GET_SIXTEEN_INT:
2200 switch ((int)wrq->u.data.flags) {
2201 case WLAN_TPCCFG:
2202 {
2203 int data[5];
2204 struct cmd_ds_802_11_tpc_cfg cfg;
2205 memset(&cfg, 0, sizeof(cfg));
2206 if ((wrq->u.data.length > 1)
2207 && (wrq->u.data.length != 5))
2208 return -1;
2209
2210 if (wrq->u.data.length == 0) {
2211 cfg.action =
2212 cpu_to_le16
2213 (cmd_act_get);
2214 } else {
2215 if (copy_from_user
2216 (data, wrq->u.data.pointer,
2217 sizeof(int) * 5)) {
2218 lbs_pr_debug(1,
2219 "Copy from user failed\n");
2220 return -EFAULT;
2221 }
2222
2223 cfg.action =
2224 cpu_to_le16
2225 (cmd_act_set);
2226 cfg.enable = data[0];
2227 cfg.usesnr = data[1];
2228 cfg.P0 = data[2];
2229 cfg.P1 = data[3];
2230 cfg.P2 = data[4];
2231 }
2232
2233 ret =
2234 libertas_prepare_and_send_command(priv,
2235 cmd_802_11_tpc_cfg,
2236 0,
2237 cmd_option_waitforrsp,
2238 0, (void *)&cfg);
2239
2240 data[0] = cfg.enable;
2241 data[1] = cfg.usesnr;
2242 data[2] = cfg.P0;
2243 data[3] = cfg.P1;
2244 data[4] = cfg.P2;
2245 if (copy_to_user
2246 (wrq->u.data.pointer, data,
2247 sizeof(int) * 5)) {
2248 lbs_pr_debug(1, "Copy to user failed\n");
2249 return -EFAULT;
2250 }
2251
2252 wrq->u.data.length = 5;
2253 }
2254 break;
2255
2256 case WLAN_POWERCFG:
2257 {
2258 int data[4];
2259 struct cmd_ds_802_11_pwr_cfg cfg;
2260 memset(&cfg, 0, sizeof(cfg));
2261 if ((wrq->u.data.length > 1)
2262 && (wrq->u.data.length != 4))
2263 return -1;
2264 if (wrq->u.data.length == 0) {
2265 cfg.action =
2266 cpu_to_le16
2267 (cmd_act_get);
2268 } else {
2269 if (copy_from_user
2270 (data, wrq->u.data.pointer,
2271 sizeof(int) * 4)) {
2272 lbs_pr_debug(1,
2273 "Copy from user failed\n");
2274 return -EFAULT;
2275 }
2276
2277 cfg.action =
2278 cpu_to_le16
2279 (cmd_act_set);
2280 cfg.enable = data[0];
2281 cfg.PA_P0 = data[1];
2282 cfg.PA_P1 = data[2];
2283 cfg.PA_P2 = data[3];
2284 }
2285 ret =
2286 libertas_prepare_and_send_command(priv,
2287 cmd_802_11_pwr_cfg,
2288 0,
2289 cmd_option_waitforrsp,
2290 0, (void *)&cfg);
2291 data[0] = cfg.enable;
2292 data[1] = cfg.PA_P0;
2293 data[2] = cfg.PA_P1;
2294 data[3] = cfg.PA_P2;
2295 if (copy_to_user
2296 (wrq->u.data.pointer, data,
2297 sizeof(int) * 4)) {
2298 lbs_pr_debug(1, "Copy to user failed\n");
2299 return -EFAULT;
2300 }
2301
2302 wrq->u.data.length = 4;
2303 }
2304 break;
2305 case WLAN_AUTO_FREQ_SET:
2306 {
2307 int data[3];
2308 struct cmd_ds_802_11_afc afc;
2309 memset(&afc, 0, sizeof(afc));
2310 if (wrq->u.data.length != 3)
2311 return -1;
2312 if (copy_from_user
2313 (data, wrq->u.data.pointer,
2314 sizeof(int) * 3)) {
2315 lbs_pr_debug(1, "Copy from user failed\n");
2316 return -EFAULT;
2317 }
2318 afc.afc_auto = data[0];
2319
2320 if (afc.afc_auto != 0) {
2321 afc.threshold = data[1];
2322 afc.period = data[2];
2323 } else {
2324 afc.timing_offset = data[1];
2325 afc.carrier_offset = data[2];
2326 }
2327 ret =
2328 libertas_prepare_and_send_command(priv,
2329 cmd_802_11_set_afc,
2330 0,
2331 cmd_option_waitforrsp,
2332 0, (void *)&afc);
2333 }
2334 break;
2335 case WLAN_AUTO_FREQ_GET:
2336 {
2337 int data[3];
2338 struct cmd_ds_802_11_afc afc;
2339 memset(&afc, 0, sizeof(afc));
2340 ret =
2341 libertas_prepare_and_send_command(priv,
2342 cmd_802_11_get_afc,
2343 0,
2344 cmd_option_waitforrsp,
2345 0, (void *)&afc);
2346 data[0] = afc.afc_auto;
2347 data[1] = afc.timing_offset;
2348 data[2] = afc.carrier_offset;
2349 if (copy_to_user
2350 (wrq->u.data.pointer, data,
2351 sizeof(int) * 3)) {
2352 lbs_pr_debug(1, "Copy to user failed\n");
2353 return -EFAULT;
2354 }
2355
2356 wrq->u.data.length = 3;
2357 }
2358 break;
2359 case WLAN_SCANPROBES:
2360 {
2361 int data;
2362 if (wrq->u.data.length > 0) {
2363 if (copy_from_user
2364 (&data, wrq->u.data.pointer,
2365 sizeof(int))) {
2366 lbs_pr_debug(1,
2367 "Copy from user failed\n");
2368 return -EFAULT;
2369 }
2370
2371 adapter->scanprobes = data;
2372 } else {
2373 data = adapter->scanprobes;
2374 if (copy_to_user
2375 (wrq->u.data.pointer, &data,
2376 sizeof(int))) {
2377 lbs_pr_debug(1,
2378 "Copy to user failed\n");
2379 return -EFAULT;
2380 }
2381 }
2382 wrq->u.data.length = 1;
2383 }
2384 break;
2385 case WLAN_LED_GPIO_CTRL:
2386 {
2387 int i;
2388 int data[16];
2389
2390 struct cmd_ds_802_11_led_ctrl ctrl;
2391 struct mrvlietypes_ledgpio *gpio =
2392 (struct mrvlietypes_ledgpio *) ctrl.data;
2393
2394 memset(&ctrl, 0, sizeof(ctrl));
2395 if (wrq->u.data.length > MAX_LEDS * 2)
2396 return -ENOTSUPP;
2397 if ((wrq->u.data.length % 2) != 0)
2398 return -ENOTSUPP;
2399 if (wrq->u.data.length == 0) {
2400 ctrl.action =
2401 cpu_to_le16
2402 (cmd_act_get);
2403 } else {
2404 if (copy_from_user
2405 (data, wrq->u.data.pointer,
2406 sizeof(int) *
2407 wrq->u.data.length)) {
2408 lbs_pr_debug(1,
2409 "Copy from user failed\n");
2410 return -EFAULT;
2411 }
2412
2413 ctrl.action =
2414 cpu_to_le16
2415 (cmd_act_set);
2416 ctrl.numled = cpu_to_le16(0);
2417 gpio->header.type =
2418 cpu_to_le16(TLV_TYPE_LED_GPIO);
2419 gpio->header.len = wrq->u.data.length;
2420 for (i = 0; i < wrq->u.data.length;
2421 i += 2) {
2422 gpio->ledpin[i / 2].led =
2423 data[i];
2424 gpio->ledpin[i / 2].pin =
2425 data[i + 1];
2426 }
2427 }
2428 ret =
2429 libertas_prepare_and_send_command(priv,
2430 cmd_802_11_led_gpio_ctrl,
2431 0,
2432 cmd_option_waitforrsp,
2433 0, (void *)&ctrl);
2434 for (i = 0; i < gpio->header.len; i += 2) {
2435 data[i] = gpio->ledpin[i / 2].led;
2436 data[i + 1] = gpio->ledpin[i / 2].pin;
2437 }
2438 if (copy_to_user(wrq->u.data.pointer, data,
2439 sizeof(int) *
2440 gpio->header.len)) {
2441 lbs_pr_debug(1, "Copy to user failed\n");
2442 return -EFAULT;
2443 }
2444
2445 wrq->u.data.length = gpio->header.len;
2446 }
2447 break;
2448 case WLAN_ADAPT_RATESET:
2449 ret = wlan_adapt_rateset(priv, wrq);
2450 break;
2451 case WLAN_INACTIVITY_TIMEOUT:
2452 ret = wlan_inactivity_timeout(priv, wrq);
2453 break;
2454 case WLANSNR:
2455 ret = wlan_get_snr(priv, wrq);
2456 break;
2457 case WLAN_GET_RXINFO:
2458 ret = wlan_get_rxinfo(priv, wrq);
2459 }
2460 break;
2461
2462 default:
2463 ret = -EINVAL;
2464 break;
2465 }
2466 LEAVE();
2467 return ret;
2468 }
2469
2470