[PATCH] Marvell Libertas 8388 802.11b/g USB driver
[linux-2.6.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 /**
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  */
627 static 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
647 static 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
671 static 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  */
692 static 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  */
724 static 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  */
754 static 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
761 static 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
782 static 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  */
811 static 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  */
846 static 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  */
894 static 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
937 static 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
981 static 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
1036 static 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  */
1111 static 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
1139 static 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  */
1157 static 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) */
1183 static 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  */
1203 static 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  */
1233 static 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  */
1265 static 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  */
1286 static 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  */
1343 static 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  */
1356 static 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  */
1454 static 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  */
1505 static 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  */
1528 static 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  */
1582 static 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  */
1598 static 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  */
1647 static 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  */
1706 static 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  */
1762 static 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  */
1793 static 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  */
1824 static 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  */
1854 static 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  */
1887 int 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