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