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