]> Pileus Git - ~andy/linux/blob - drivers/net/wireless/libertas/ioctl.c
[PATCH] libertas: Purge non-mesh ioctls
[~andy/linux] / 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 wlan_set_region(wlan_private * priv, u16 region_code)
31 {
32         int i;
33
34         for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
35                 // use the region code to search for the index
36                 if (region_code == libertas_region_code_to_index[i]) {
37                         priv->adapter->regiontableindex = (u16) i;
38                         priv->adapter->regioncode = region_code;
39                         break;
40                 }
41         }
42
43         // if it's unidentified region code
44         if (i >= MRVDRV_MAX_REGION_CODE) {
45                 lbs_pr_debug(1, "region Code not identified\n");
46                 LEAVE();
47                 return -1;
48         }
49
50         if (libertas_set_regiontable(priv, priv->adapter->regioncode, 0)) {
51                 LEAVE();
52                 return -EINVAL;
53         }
54
55         return 0;
56 }
57
58 static inline int hex2int(char c)
59 {
60         if (c >= '0' && c <= '9')
61                 return (c - '0');
62         if (c >= 'a' && c <= 'f')
63                 return (c - 'a' + 10);
64         if (c >= 'A' && c <= 'F')
65                 return (c - 'A' + 10);
66         return -1;
67 }
68
69 /* Convert a string representation of a MAC address ("xx:xx:xx:xx:xx:xx")
70    into binary format (6 bytes).
71
72    This function expects that each byte is represented with 2 characters
73    (e.g., 11:2:11:11:11:11 is invalid)
74
75  */
76 static char *eth_str2addr(char *ethstr, u8 * addr)
77 {
78         int i, val, val2;
79         char *pos = ethstr;
80
81         /* get rid of initial blanks */
82         while (*pos == ' ' || *pos == '\t')
83                 ++pos;
84
85         for (i = 0; i < 6; i++) {
86                 val = hex2int(*pos++);
87                 if (val < 0)
88                         return NULL;
89                 val2 = hex2int(*pos++);
90                 if (val2 < 0)
91                         return NULL;
92                 addr[i] = (val * 16 + val2) & 0xff;
93
94                 if (i < 5 && *pos++ != ':')
95                         return NULL;
96         }
97         return pos;
98 }
99
100 /* this writes xx:xx:xx:xx:xx:xx into ethstr
101    (ethstr must have space for 18 chars) */
102 static int eth_addr2str(u8 * addr, char *ethstr)
103 {
104         int i;
105         char *pos = ethstr;
106
107         for (i = 0; i < 6; i++) {
108                 sprintf(pos, "%02x", addr[i] & 0xff);
109                 pos += 2;
110                 if (i < 5)
111                         *pos++ = ':';
112         }
113         return 17;
114 }
115
116 /**
117  *  @brief          Add an entry to the BT table
118  *  @param priv     A pointer to wlan_private structure
119  *  @param req      A pointer to ifreq structure
120  *  @return         0 --success, otherwise fail
121  */
122 static int wlan_bt_add_ioctl(wlan_private * priv, struct ifreq *req)
123 {
124         struct iwreq *wrq = (struct iwreq *)req;
125         char ethaddrs_str[18];
126         char *pos;
127         u8 ethaddr[ETH_ALEN];
128
129         ENTER();
130         if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
131                            sizeof(ethaddrs_str)))
132                 return -EFAULT;
133
134         if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
135                 lbs_pr_info("BT_ADD: Invalid MAC address\n");
136                 return -EINVAL;
137         }
138
139         lbs_pr_debug(1, "BT: adding %s\n", ethaddrs_str);
140         LEAVE();
141         return (libertas_prepare_and_send_command(priv, cmd_bt_access,
142                                       cmd_act_bt_access_add,
143                                       cmd_option_waitforrsp, 0, ethaddr));
144 }
145
146 /**
147  *  @brief          Delete an entry from the BT table
148  *  @param priv     A pointer to wlan_private structure
149  *  @param req      A pointer to ifreq structure
150  *  @return         0 --success, otherwise fail
151  */
152 static int wlan_bt_del_ioctl(wlan_private * priv, struct ifreq *req)
153 {
154         struct iwreq *wrq = (struct iwreq *)req;
155         char ethaddrs_str[18];
156         u8 ethaddr[ETH_ALEN];
157         char *pos;
158
159         ENTER();
160         if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
161                            sizeof(ethaddrs_str)))
162                 return -EFAULT;
163
164         if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
165                 lbs_pr_info("Invalid MAC address\n");
166                 return -EINVAL;
167         }
168
169         lbs_pr_debug(1, "BT: deleting %s\n", ethaddrs_str);
170
171         return (libertas_prepare_and_send_command(priv,
172                                       cmd_bt_access,
173                                       cmd_act_bt_access_del,
174                                       cmd_option_waitforrsp, 0, ethaddr));
175         LEAVE();
176         return 0;
177 }
178
179 /**
180  *  @brief          Reset all entries from the BT table
181  *  @param priv     A pointer to wlan_private structure
182  *  @return         0 --success, otherwise fail
183  */
184 static int wlan_bt_reset_ioctl(wlan_private * priv)
185 {
186         ENTER();
187
188         lbs_pr_alert( "BT: resetting\n");
189
190         return (libertas_prepare_and_send_command(priv,
191                                       cmd_bt_access,
192                                       cmd_act_bt_access_reset,
193                                       cmd_option_waitforrsp, 0, NULL));
194
195         LEAVE();
196         return 0;
197 }
198
199 /**
200  *  @brief          List an entry from the BT table
201  *  @param priv     A pointer to wlan_private structure
202  *  @param req      A pointer to ifreq structure
203  *  @return         0 --success, otherwise fail
204  */
205 static int wlan_bt_list_ioctl(wlan_private * priv, struct ifreq *req)
206 {
207         int pos;
208         char *addr1;
209         struct iwreq *wrq = (struct iwreq *)req;
210         /* used to pass id and store the bt entry returned by the FW */
211         union {
212                 int id;
213                 char addr1addr2[2 * ETH_ALEN];
214         } param;
215         static char outstr[64];
216         char *pbuf = outstr;
217         int ret;
218
219         ENTER();
220
221         if (copy_from_user(outstr, wrq->u.data.pointer, sizeof(outstr))) {
222                 lbs_pr_debug(1, "Copy from user failed\n");
223                 return -1;
224         }
225         param.id = simple_strtoul(outstr, NULL, 10);
226         pos = sprintf(pbuf, "%d: ", param.id);
227         pbuf += pos;
228
229         ret = libertas_prepare_and_send_command(priv, cmd_bt_access,
230                                     cmd_act_bt_access_list,
231                                     cmd_option_waitforrsp, 0,
232                                     (char *)&param);
233
234         if (ret == 0) {
235                 addr1 = param.addr1addr2;
236
237                 pos = sprintf(pbuf, "ignoring traffic from ");
238                 pbuf += pos;
239                 pos = eth_addr2str(addr1, pbuf);
240                 pbuf += pos;
241         } else {
242                 sprintf(pbuf, "(null)");
243                 pbuf += pos;
244         }
245
246         wrq->u.data.length = strlen(outstr);
247         if (copy_to_user(wrq->u.data.pointer, (char *)outstr,
248                          wrq->u.data.length)) {
249                 lbs_pr_debug(1, "BT_LIST: Copy to user failed!\n");
250                 return -EFAULT;
251         }
252
253         LEAVE();
254         return 0;
255 }
256
257 /**
258  *  @brief          Find the next parameter in an input string
259  *  @param ptr      A pointer to the input parameter string
260  *  @return         A pointer to the next parameter, or 0 if no parameters left.
261  */
262 static char * next_param(char * ptr)
263 {
264         if (!ptr) return NULL;
265         while (*ptr == ' ' || *ptr == '\t') ++ptr;
266         return (*ptr == '\0') ? NULL : ptr;
267 }
268
269 /**
270  *  @brief          Add an entry to the FWT table
271  *  @param priv     A pointer to wlan_private structure
272  *  @param req      A pointer to ifreq structure
273  *  @return         0 --success, otherwise fail
274  */
275 static int wlan_fwt_add_ioctl(wlan_private * priv, struct ifreq *req)
276 {
277         struct iwreq *wrq = (struct iwreq *)req;
278         char in_str[128];
279         static struct cmd_ds_fwt_access fwt_access;
280         char *ptr;
281
282         ENTER();
283         if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
284                 return -EFAULT;
285
286         if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
287                 lbs_pr_alert( "FWT_ADD: Invalid MAC address 1\n");
288                 return -EINVAL;
289         }
290
291         if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) {
292                 lbs_pr_alert( "FWT_ADD: Invalid MAC address 2\n");
293                 return -EINVAL;
294         }
295
296         if ((ptr = next_param(ptr)))
297                 fwt_access.metric =
298                         cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
299         else
300                 fwt_access.metric = FWT_DEFAULT_METRIC;
301
302         if ((ptr = next_param(ptr)))
303                 fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10);
304         else
305                 fwt_access.dir = FWT_DEFAULT_DIR;
306
307         if ((ptr = next_param(ptr)))
308                 fwt_access.ssn =
309                         cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
310         else
311                 fwt_access.ssn = FWT_DEFAULT_SSN;
312
313         if ((ptr = next_param(ptr)))
314                 fwt_access.dsn =
315                         cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
316         else
317                 fwt_access.dsn = FWT_DEFAULT_DSN;
318
319         if ((ptr = next_param(ptr)))
320                 fwt_access.hopcount = simple_strtoul(ptr, &ptr, 10);
321         else
322                 fwt_access.hopcount = FWT_DEFAULT_HOPCOUNT;
323
324         if ((ptr = next_param(ptr)))
325                 fwt_access.ttl = simple_strtoul(ptr, &ptr, 10);
326         else
327                 fwt_access.ttl = FWT_DEFAULT_TTL;
328
329         if ((ptr = next_param(ptr)))
330                 fwt_access.expiration =
331                         cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
332         else
333                 fwt_access.expiration = FWT_DEFAULT_EXPIRATION;
334
335         if ((ptr = next_param(ptr)))
336                 fwt_access.sleepmode = (u8)simple_strtoul(ptr, &ptr, 10);
337         else
338                 fwt_access.sleepmode = FWT_DEFAULT_SLEEPMODE;
339
340         if ((ptr = next_param(ptr)))
341                 fwt_access.snr =
342                         cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
343         else
344                 fwt_access.snr = FWT_DEFAULT_SNR;
345
346 #ifdef DEBUG
347         {
348                 char ethaddr1_str[18], ethaddr2_str[18];
349                 eth_addr2str(fwt_access.da, ethaddr1_str);
350                 eth_addr2str(fwt_access.ra, ethaddr2_str);
351                 lbs_pr_debug(1, "FWT_ADD: adding (da:%s,%i,ra:%s)\n", ethaddr1_str,
352                        fwt_access.dir, ethaddr2_str);
353                 lbs_pr_debug(1, "FWT_ADD: ssn:%u dsn:%u met:%u hop:%u ttl:%u exp:%u slp:%u snr:%u\n",
354                        fwt_access.ssn, fwt_access.dsn, fwt_access.metric,
355                        fwt_access.hopcount, fwt_access.ttl, fwt_access.expiration,
356                        fwt_access.sleepmode, fwt_access.snr);
357         }
358 #endif
359
360         LEAVE();
361         return (libertas_prepare_and_send_command(priv, cmd_fwt_access,
362                                                   cmd_act_fwt_access_add,
363                                                   cmd_option_waitforrsp, 0,
364                                                   (void *)&fwt_access));
365 }
366
367 /**
368  *  @brief          Delete an entry from the FWT table
369  *  @param priv     A pointer to wlan_private structure
370  *  @param req      A pointer to ifreq structure
371  *  @return         0 --success, otherwise fail
372  */
373 static int wlan_fwt_del_ioctl(wlan_private * priv, struct ifreq *req)
374 {
375         struct iwreq *wrq = (struct iwreq *)req;
376         char in_str[64];
377         static struct cmd_ds_fwt_access fwt_access;
378         char *ptr;
379
380         ENTER();
381         if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
382                 return -EFAULT;
383
384         if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
385                 lbs_pr_alert( "FWT_DEL: Invalid MAC address 1\n");
386                 return -EINVAL;
387         }
388
389         if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) {
390                 lbs_pr_alert( "FWT_DEL: Invalid MAC address 2\n");
391                 return -EINVAL;
392         }
393
394         if ((ptr = next_param(ptr)))
395                 fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10);
396         else
397                 fwt_access.dir = FWT_DEFAULT_DIR;
398
399 #ifdef DEBUG
400         {
401                 char ethaddr1_str[18], ethaddr2_str[18];
402                 lbs_pr_debug(1, "FWT_DEL: line is %s\n", in_str);
403                 eth_addr2str(fwt_access.da, ethaddr1_str);
404                 eth_addr2str(fwt_access.ra, ethaddr2_str);
405                 lbs_pr_debug(1, "FWT_DEL: removing (da:%s,ra:%s,dir:%d)\n", ethaddr1_str,
406                        ethaddr2_str, fwt_access.dir);
407         }
408 #endif
409
410         LEAVE();
411         return (libertas_prepare_and_send_command(priv,
412                                                   cmd_fwt_access,
413                                                   cmd_act_fwt_access_del,
414                                                   cmd_option_waitforrsp, 0,
415                                                   (void *)&fwt_access));
416 }
417
418
419 /**
420  *  @brief             Print route parameters
421  *  @param fwt_access  struct cmd_ds_fwt_access with route info
422  *  @param buf         destination buffer for route info
423  */
424 static void print_route(struct cmd_ds_fwt_access fwt_access, char *buf)
425 {
426         buf += sprintf(buf, " ");
427         buf += eth_addr2str(fwt_access.da, buf);
428         buf += sprintf(buf, " ");
429         buf += eth_addr2str(fwt_access.ra, buf);
430         buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.metric));
431         buf += sprintf(buf, " %u", fwt_access.dir);
432         buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.ssn));
433         buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.dsn));
434         buf += sprintf(buf, " %u", fwt_access.hopcount);
435         buf += sprintf(buf, " %u", fwt_access.ttl);
436         buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.expiration));
437         buf += sprintf(buf, " %u", fwt_access.sleepmode);
438         buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.snr));
439 }
440
441 /**
442  *  @brief          Lookup an entry in the FWT table
443  *  @param priv     A pointer to wlan_private structure
444  *  @param req      A pointer to ifreq structure
445  *  @return         0 --success, otherwise fail
446  */
447 static int wlan_fwt_lookup_ioctl(wlan_private * priv, struct ifreq *req)
448 {
449         struct iwreq *wrq = (struct iwreq *)req;
450         char in_str[64];
451         char *ptr;
452         static struct cmd_ds_fwt_access fwt_access;
453         static char out_str[128];
454         int ret;
455
456         ENTER();
457         if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
458                 return -EFAULT;
459
460         if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
461                 lbs_pr_alert( "FWT_LOOKUP: Invalid MAC address\n");
462                 return -EINVAL;
463         }
464
465 #ifdef DEBUG
466         {
467                 char ethaddr1_str[18];
468                 lbs_pr_debug(1, "FWT_LOOKUP: line is %s\n", in_str);
469                 eth_addr2str(fwt_access.da, ethaddr1_str);
470                 lbs_pr_debug(1, "FWT_LOOKUP: looking for (da:%s)\n", ethaddr1_str);
471         }
472 #endif
473
474         ret = libertas_prepare_and_send_command(priv,
475                                                 cmd_fwt_access,
476                                                 cmd_act_fwt_access_lookup,
477                                                 cmd_option_waitforrsp, 0,
478                                                 (void *)&fwt_access);
479
480         if (ret == 0)
481                 print_route(fwt_access, out_str);
482         else
483                 sprintf(out_str, "(null)");
484
485         wrq->u.data.length = strlen(out_str);
486         if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
487                          wrq->u.data.length)) {
488                 lbs_pr_debug(1, "FWT_LOOKUP: Copy to user failed!\n");
489                 return -EFAULT;
490         }
491
492         LEAVE();
493         return 0;
494 }
495
496 /**
497  *  @brief          Reset all entries from the FWT table
498  *  @param priv     A pointer to wlan_private structure
499  *  @return         0 --success, otherwise fail
500  */
501 static int wlan_fwt_reset_ioctl(wlan_private * priv)
502 {
503         lbs_pr_debug(1, "FWT: resetting\n");
504
505         return (libertas_prepare_and_send_command(priv,
506                                       cmd_fwt_access,
507                                       cmd_act_fwt_access_reset,
508                                       cmd_option_waitforrsp, 0, NULL));
509 }
510
511 /**
512  *  @brief          List an entry from the FWT table
513  *  @param priv     A pointer to wlan_private structure
514  *  @param req      A pointer to ifreq structure
515  *  @return         0 --success, otherwise fail
516  */
517 static int wlan_fwt_list_ioctl(wlan_private * priv, struct ifreq *req)
518 {
519         struct iwreq *wrq = (struct iwreq *)req;
520         char in_str[8];
521         static struct cmd_ds_fwt_access fwt_access;
522         char *ptr = in_str;
523         static char out_str[128];
524         char *pbuf = out_str;
525         int ret;
526
527         ENTER();
528         if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
529                 return -EFAULT;
530
531         fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
532
533 #ifdef DEBUG
534         {
535                 lbs_pr_debug(1, "FWT_LIST: line is %s\n", in_str);
536                 lbs_pr_debug(1, "FWT_LIST: listing id:%i\n", le32_to_cpu(fwt_access.id));
537         }
538 #endif
539
540         ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
541                                     cmd_act_fwt_access_list,
542                                     cmd_option_waitforrsp, 0, (void *)&fwt_access);
543
544         if (ret == 0)
545                 print_route(fwt_access, pbuf);
546         else
547                 pbuf += sprintf(pbuf, " (null)");
548
549         wrq->u.data.length = strlen(out_str);
550         if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
551                          wrq->u.data.length)) {
552                 lbs_pr_debug(1, "FWT_LIST: Copy to user failed!\n");
553                 return -EFAULT;
554         }
555
556         LEAVE();
557         return 0;
558 }
559
560 /**
561  *  @brief          List an entry from the FRT table
562  *  @param priv     A pointer to wlan_private structure
563  *  @param req      A pointer to ifreq structure
564  *  @return         0 --success, otherwise fail
565  */
566 static int wlan_fwt_list_route_ioctl(wlan_private * priv, struct ifreq *req)
567 {
568         struct iwreq *wrq = (struct iwreq *)req;
569         char in_str[64];
570         static struct cmd_ds_fwt_access fwt_access;
571         char *ptr = in_str;
572         static char out_str[128];
573         char *pbuf = out_str;
574         int ret;
575
576         ENTER();
577         if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
578                 return -EFAULT;
579
580         fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
581
582 #ifdef DEBUG
583         {
584                 lbs_pr_debug(1, "FWT_LIST_ROUTE: line is %s\n", in_str);
585                 lbs_pr_debug(1, "FWT_LIST_ROUTE: listing id:%i\n", le32_to_cpu(fwt_access.id));
586         }
587 #endif
588
589         ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
590                                     cmd_act_fwt_access_list_route,
591                                     cmd_option_waitforrsp, 0, (void *)&fwt_access);
592
593         if (ret == 0) {
594                 pbuf += sprintf(pbuf, " ");
595                 pbuf += eth_addr2str(fwt_access.da, pbuf);
596                 pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.metric));
597                 pbuf += sprintf(pbuf, " %u", fwt_access.dir);
598                 /* note that the firmware returns the nid in the id field */
599                 pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.id));
600                 pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.ssn));
601                 pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.dsn));
602                 pbuf += sprintf(pbuf, "  hop %u", fwt_access.hopcount);
603                 pbuf += sprintf(pbuf, "  ttl %u", fwt_access.ttl);
604                 pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.expiration));
605         } else
606                 pbuf += sprintf(pbuf, " (null)");
607
608         wrq->u.data.length = strlen(out_str);
609         if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
610                          wrq->u.data.length)) {
611                 lbs_pr_debug(1, "FWT_LIST_ROUTE: Copy to user failed!\n");
612                 return -EFAULT;
613         }
614
615         LEAVE();
616         return 0;
617 }
618
619 /**
620  *  @brief          List an entry from the FNT table
621  *  @param priv     A pointer to wlan_private structure
622  *  @param req      A pointer to ifreq structure
623  *  @return         0 --success, otherwise fail
624  */
625 static int wlan_fwt_list_neighbor_ioctl(wlan_private * priv, struct ifreq *req)
626 {
627         struct iwreq *wrq = (struct iwreq *)req;
628         char in_str[8];
629         static struct cmd_ds_fwt_access fwt_access;
630         char *ptr = in_str;
631         static char out_str[128];
632         char *pbuf = out_str;
633         int ret;
634
635         ENTER();
636         if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
637                 return -EFAULT;
638
639         memset(&fwt_access, 0, sizeof(fwt_access));
640         fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
641
642 #ifdef DEBUG
643         {
644                 lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: line is %s\n", in_str);
645                 lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: listing id:%i\n", le32_to_cpu(fwt_access.id));
646         }
647 #endif
648
649         ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
650                                     cmd_act_fwt_access_list_neighbor,
651                                     cmd_option_waitforrsp, 0,
652                                     (void *)&fwt_access);
653
654         if (ret == 0) {
655                 pbuf += sprintf(pbuf, " ra ");
656                 pbuf += eth_addr2str(fwt_access.ra, pbuf);
657                 pbuf += sprintf(pbuf, "  slp %u", fwt_access.sleepmode);
658                 pbuf += sprintf(pbuf, "  snr %u", le32_to_cpu(fwt_access.snr));
659                 pbuf += sprintf(pbuf, "  ref %u", le32_to_cpu(fwt_access.references));
660         } else
661                 pbuf += sprintf(pbuf, " (null)");
662
663         wrq->u.data.length = strlen(out_str);
664         if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
665                          wrq->u.data.length)) {
666                 lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: Copy to user failed!\n");
667                 return -EFAULT;
668         }
669
670         LEAVE();
671         return 0;
672 }
673
674 /**
675  *  @brief          Cleans up the route (FRT) and neighbor (FNT) tables
676  *                  (Garbage Collection)
677  *  @param priv     A pointer to wlan_private structure
678  *  @param req      A pointer to ifreq structure
679  *  @return         0 --success, otherwise fail
680  */
681 static int wlan_fwt_cleanup_ioctl(wlan_private * priv, struct ifreq *req)
682 {
683         static struct cmd_ds_fwt_access fwt_access;
684         int ret;
685
686         ENTER();
687
688         lbs_pr_debug(1, "FWT: cleaning up\n");
689
690         memset(&fwt_access, 0, sizeof(fwt_access));
691
692         ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
693                                     cmd_act_fwt_access_cleanup,
694                                     cmd_option_waitforrsp, 0,
695                                     (void *)&fwt_access);
696
697         if (ret == 0)
698                 req->ifr_data = (char *)(le32_to_cpu(fwt_access.references));
699         else
700                 return -EFAULT;
701
702         LEAVE();
703         return 0;
704 }
705
706 /**
707  *  @brief          Gets firmware internal time (debug purposes)
708  *  @param priv     A pointer to wlan_private structure
709  *  @param req      A pointer to ifreq structure
710  *  @return         0 --success, otherwise fail
711  */
712 static int wlan_fwt_time_ioctl(wlan_private * priv, struct ifreq *req)
713 {
714         static struct cmd_ds_fwt_access fwt_access;
715         int ret;
716
717         ENTER();
718
719         lbs_pr_debug(1, "FWT: getting time\n");
720
721         memset(&fwt_access, 0, sizeof(fwt_access));
722
723         ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
724                                     cmd_act_fwt_access_time,
725                                     cmd_option_waitforrsp, 0,
726                                     (void *)&fwt_access);
727
728         if (ret == 0)
729                 req->ifr_data = (char *)(le32_to_cpu(fwt_access.references));
730         else
731                 return -EFAULT;
732
733         LEAVE();
734         return 0;
735 }
736
737 /**
738  *  @brief          Gets mesh ttl from firmware
739  *  @param priv     A pointer to wlan_private structure
740  *  @param req      A pointer to ifreq structure
741  *  @return         0 --success, otherwise fail
742  */
743 static int wlan_mesh_get_ttl_ioctl(wlan_private * priv, struct ifreq *req)
744 {
745         struct cmd_ds_mesh_access mesh_access;
746         int ret;
747
748         ENTER();
749
750         memset(&mesh_access, 0, sizeof(mesh_access));
751
752         ret = libertas_prepare_and_send_command(priv, cmd_mesh_access,
753                                     cmd_act_mesh_get_ttl,
754                                     cmd_option_waitforrsp, 0,
755                                     (void *)&mesh_access);
756
757         if (ret == 0) {
758                 req->ifr_data = (char *)(le32_to_cpu(mesh_access.data[0]));
759         }
760         else
761                 return -EFAULT;
762
763         LEAVE();
764         return 0;
765 }
766
767 /**
768  *  @brief          Gets mesh ttl from firmware
769  *  @param priv     A pointer to wlan_private structure
770  *  @param ttl      New ttl value
771  *  @return         0 --success, otherwise fail
772  */
773 static int wlan_mesh_set_ttl_ioctl(wlan_private * priv, int ttl)
774 {
775         struct cmd_ds_mesh_access mesh_access;
776         int ret;
777
778         ENTER();
779
780         if( (ttl > 0xff) || (ttl < 0) )
781                 return -EINVAL;
782
783         memset(&mesh_access, 0, sizeof(mesh_access));
784         mesh_access.data[0] = ttl;
785
786         ret = libertas_prepare_and_send_command(priv, cmd_mesh_access,
787                                                 cmd_act_mesh_set_ttl,
788                                                 cmd_option_waitforrsp, 0,
789                                                 (void *)&mesh_access);
790
791         if (ret != 0)
792                 ret = -EFAULT;
793
794         LEAVE();
795         return ret;
796 }
797
798 /**
799  *  @brief ioctl function - entry point
800  *
801  *  @param dev          A pointer to net_device structure
802  *  @param req          A pointer to ifreq structure
803  *  @param cmd          command
804  *  @return             0--success, otherwise fail
805  */
806 int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
807 {
808         int subcmd = 0;
809         int idata = 0;
810         int *pdata;
811         int ret = 0;
812         wlan_private *priv = dev->priv;
813         wlan_adapter *adapter = priv->adapter;
814         struct iwreq *wrq = (struct iwreq *)req;
815
816         ENTER();
817
818         lbs_pr_debug(1, "libertas_do_ioctl: ioctl cmd = 0x%x\n", cmd);
819         switch (cmd) {
820         case WLAN_SETNONE_GETNONE:      /* set WPA mode on/off ioctl #20 */
821                 switch (wrq->u.data.flags) {
822                 case WLAN_SUBCMD_BT_RESET:      /* bt_reset */
823                         wlan_bt_reset_ioctl(priv);
824                         break;
825                 case WLAN_SUBCMD_FWT_RESET:     /* fwt_reset */
826                         wlan_fwt_reset_ioctl(priv);
827                         break;
828                 }               /* End of switch */
829                 break;
830
831         case WLAN_SETONEINT_GETNONE:
832                 /* The first 4 bytes of req->ifr_data is sub-ioctl number
833                  * after 4 bytes sits the payload.
834                  */
835                 subcmd = wrq->u.data.flags;     //from wpa_supplicant subcmd
836
837                 if (!subcmd)
838                         subcmd = (int)req->ifr_data;    //from iwpriv subcmd
839
840                 switch (subcmd) {
841                 case WLANSETREGION:
842                         idata = SUBCMD_DATA(wrq);
843                         ret = wlan_set_region(priv, (u16) idata);
844                         break;
845                 case WLAN_SUBCMD_MESH_SET_TTL:
846                         idata = SUBCMD_DATA(wrq);
847                         ret = wlan_mesh_set_ttl_ioctl(priv, idata);
848                         break;
849
850                 default:
851                         ret = -EOPNOTSUPP;
852                         break;
853                 }
854
855                 break;
856
857         case WLAN_SET128CHAR_GET128CHAR:
858                 switch ((int)wrq->u.data.flags) {
859                 case WLAN_SUBCMD_BT_ADD:
860                         ret = wlan_bt_add_ioctl(priv, req);
861                         break;
862                 case WLAN_SUBCMD_BT_DEL:
863                         ret = wlan_bt_del_ioctl(priv, req);
864                         break;
865                 case WLAN_SUBCMD_BT_LIST:
866                         ret = wlan_bt_list_ioctl(priv, req);
867                         break;
868                 case WLAN_SUBCMD_FWT_ADD:
869                         ret = wlan_fwt_add_ioctl(priv, req);
870                         break;
871                 case WLAN_SUBCMD_FWT_DEL:
872                         ret = wlan_fwt_del_ioctl(priv, req);
873                         break;
874                 case WLAN_SUBCMD_FWT_LOOKUP:
875                         ret = wlan_fwt_lookup_ioctl(priv, req);
876                         break;
877                 case WLAN_SUBCMD_FWT_LIST_NEIGHBOR:
878                         ret = wlan_fwt_list_neighbor_ioctl(priv, req);
879                         break;
880                 case WLAN_SUBCMD_FWT_LIST:
881                         ret = wlan_fwt_list_ioctl(priv, req);
882                         break;
883                 case WLAN_SUBCMD_FWT_LIST_ROUTE:
884                         ret = wlan_fwt_list_route_ioctl(priv, req);
885                         break;
886                 }
887                 break;
888
889         case WLAN_SETNONE_GETONEINT:
890                 switch ((int)req->ifr_data) {
891                 case WLANGETREGION:
892                         pdata = (int *)wrq->u.name;
893                         *pdata = (int)adapter->regioncode;
894                         break;
895                 case WLAN_SUBCMD_FWT_CLEANUP:   /* fwt_cleanup */
896                         ret = wlan_fwt_cleanup_ioctl(priv, req);
897                         break;
898
899                 case WLAN_SUBCMD_FWT_TIME:      /* fwt_time */
900                         ret = wlan_fwt_time_ioctl(priv, req);
901                         break;
902
903                 case WLAN_SUBCMD_MESH_GET_TTL:
904                         ret = wlan_mesh_get_ttl_ioctl(priv, req);
905                         break;
906
907                 default:
908                         ret = -EOPNOTSUPP;
909
910                 }
911
912                 break;
913
914         case WLAN_SET_GET_SIXTEEN_INT:
915                 switch ((int)wrq->u.data.flags) {
916                 case WLAN_LED_GPIO_CTRL:
917                         {
918                                 int i;
919                                 int data[16];
920
921                                 struct cmd_ds_802_11_led_ctrl ctrl;
922                                 struct mrvlietypes_ledgpio *gpio =
923                                     (struct mrvlietypes_ledgpio *) ctrl.data;
924
925                                 memset(&ctrl, 0, sizeof(ctrl));
926                                 if (wrq->u.data.length > MAX_LEDS * 2)
927                                         return -ENOTSUPP;
928                                 if ((wrq->u.data.length % 2) != 0)
929                                         return -ENOTSUPP;
930                                 if (wrq->u.data.length == 0) {
931                                         ctrl.action =
932                                             cpu_to_le16
933                                             (cmd_act_get);
934                                 } else {
935                                         if (copy_from_user
936                                             (data, wrq->u.data.pointer,
937                                              sizeof(int) *
938                                              wrq->u.data.length)) {
939                                                 lbs_pr_debug(1,
940                                                        "Copy from user failed\n");
941                                                 return -EFAULT;
942                                         }
943
944                                         ctrl.action =
945                                             cpu_to_le16
946                                             (cmd_act_set);
947                                         ctrl.numled = cpu_to_le16(0);
948                                         gpio->header.type =
949                                             cpu_to_le16(TLV_TYPE_LED_GPIO);
950                                         gpio->header.len = wrq->u.data.length;
951                                         for (i = 0; i < wrq->u.data.length;
952                                              i += 2) {
953                                                 gpio->ledpin[i / 2].led =
954                                                     data[i];
955                                                 gpio->ledpin[i / 2].pin =
956                                                     data[i + 1];
957                                         }
958                                 }
959                                 ret =
960                                     libertas_prepare_and_send_command(priv,
961                                                           cmd_802_11_led_gpio_ctrl,
962                                                           0,
963                                                           cmd_option_waitforrsp,
964                                                           0, (void *)&ctrl);
965                                 for (i = 0; i < gpio->header.len; i += 2) {
966                                         data[i] = gpio->ledpin[i / 2].led;
967                                         data[i + 1] = gpio->ledpin[i / 2].pin;
968                                 }
969                                 if (copy_to_user(wrq->u.data.pointer, data,
970                                                  sizeof(int) *
971                                                  gpio->header.len)) {
972                                         lbs_pr_debug(1, "Copy to user failed\n");
973                                         return -EFAULT;
974                                 }
975
976                                 wrq->u.data.length = gpio->header.len;
977                         }
978                         break;
979                 }
980                 break;
981
982         default:
983                 ret = -EINVAL;
984                 break;
985         }
986         LEAVE();
987         return ret;
988 }
989
990