[PATCH] libertas: first pass at fixing up endianness issues
[linux-2.6/x86.git] / drivers / net / wireless / libertas / ioctl.c
blobf41081585564eb65ba9dd9e6138c36fc85f92695
1 /**
2 * This file contains ioctl functions
3 */
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>
11 #include <net/iw_handler.h>
12 #include <net/ieee80211.h>
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"
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 */
28 #define WAIT_FOR_SCAN_RRESULT_MAX_TIME (10 * HZ)
30 static int wlan_set_region(wlan_private * priv, u16 region_code)
32 int i;
33 int ret = 0;
35 for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
36 // use the region code to search for the index
37 if (region_code == libertas_region_code_to_index[i]) {
38 priv->adapter->regiontableindex = (u16) i;
39 priv->adapter->regioncode = region_code;
40 break;
44 // if it's unidentified region code
45 if (i >= MRVDRV_MAX_REGION_CODE) {
46 lbs_deb_ioctl("region Code not identified\n");
47 ret = -1;
48 goto done;
51 if (libertas_set_regiontable(priv, priv->adapter->regioncode, 0)) {
52 ret = -EINVAL;
55 done:
56 lbs_deb_leave_args(LBS_DEB_IOCTL, "ret %d", ret);
57 return ret;
60 static inline int hex2int(char c)
62 if (c >= '0' && c <= '9')
63 return (c - '0');
64 if (c >= 'a' && c <= 'f')
65 return (c - 'a' + 10);
66 if (c >= 'A' && c <= 'F')
67 return (c - 'A' + 10);
68 return -1;
71 /* Convert a string representation of a MAC address ("xx:xx:xx:xx:xx:xx")
72 into binary format (6 bytes).
74 This function expects that each byte is represented with 2 characters
75 (e.g., 11:2:11:11:11:11 is invalid)
78 static char *eth_str2addr(char *ethstr, u8 * addr)
80 int i, val, val2;
81 char *pos = ethstr;
83 /* get rid of initial blanks */
84 while (*pos == ' ' || *pos == '\t')
85 ++pos;
87 for (i = 0; i < 6; i++) {
88 val = hex2int(*pos++);
89 if (val < 0)
90 return NULL;
91 val2 = hex2int(*pos++);
92 if (val2 < 0)
93 return NULL;
94 addr[i] = (val * 16 + val2) & 0xff;
96 if (i < 5 && *pos++ != ':')
97 return NULL;
99 return pos;
102 /* this writes xx:xx:xx:xx:xx:xx into ethstr
103 (ethstr must have space for 18 chars) */
104 static int eth_addr2str(u8 * addr, char *ethstr)
106 int i;
107 char *pos = ethstr;
109 for (i = 0; i < 6; i++) {
110 sprintf(pos, "%02x", addr[i] & 0xff);
111 pos += 2;
112 if (i < 5)
113 *pos++ = ':';
115 return 17;
119 * @brief Add an entry to the BT table
120 * @param priv A pointer to wlan_private structure
121 * @param req A pointer to ifreq structure
122 * @return 0 --success, otherwise fail
124 static int wlan_bt_add_ioctl(wlan_private * priv, struct ifreq *req)
126 struct iwreq *wrq = (struct iwreq *)req;
127 char ethaddrs_str[18];
128 char *pos;
129 u8 ethaddr[ETH_ALEN];
130 int ret;
132 lbs_deb_enter(LBS_DEB_IOCTL);
134 if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
135 sizeof(ethaddrs_str)))
136 return -EFAULT;
138 if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
139 lbs_pr_info("BT_ADD: Invalid MAC address\n");
140 return -EINVAL;
143 lbs_deb_ioctl("BT: adding %s\n", ethaddrs_str);
144 ret = libertas_prepare_and_send_command(priv, cmd_bt_access,
145 cmd_act_bt_access_add,
146 cmd_option_waitforrsp, 0, ethaddr);
147 lbs_deb_leave_args(LBS_DEB_IOCTL, "ret %d", ret);
148 return ret;
152 * @brief Delete an entry from the BT table
153 * @param priv A pointer to wlan_private structure
154 * @param req A pointer to ifreq structure
155 * @return 0 --success, otherwise fail
157 static int wlan_bt_del_ioctl(wlan_private * priv, struct ifreq *req)
159 struct iwreq *wrq = (struct iwreq *)req;
160 char ethaddrs_str[18];
161 u8 ethaddr[ETH_ALEN];
162 char *pos;
164 lbs_deb_enter(LBS_DEB_IOCTL);
166 if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
167 sizeof(ethaddrs_str)))
168 return -EFAULT;
170 if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
171 lbs_pr_info("Invalid MAC address\n");
172 return -EINVAL;
175 lbs_deb_ioctl("BT: deleting %s\n", ethaddrs_str);
177 return (libertas_prepare_and_send_command(priv,
178 cmd_bt_access,
179 cmd_act_bt_access_del,
180 cmd_option_waitforrsp, 0, ethaddr));
182 lbs_deb_leave(LBS_DEB_IOCTL);
183 return 0;
187 * @brief Reset all entries from the BT table
188 * @param priv A pointer to wlan_private structure
189 * @return 0 --success, otherwise fail
191 static int wlan_bt_reset_ioctl(wlan_private * priv)
193 lbs_deb_enter(LBS_DEB_IOCTL);
195 lbs_pr_alert( "BT: resetting\n");
197 return (libertas_prepare_and_send_command(priv,
198 cmd_bt_access,
199 cmd_act_bt_access_reset,
200 cmd_option_waitforrsp, 0, NULL));
202 lbs_deb_leave(LBS_DEB_IOCTL);
203 return 0;
207 * @brief List an entry from the BT table
208 * @param priv A pointer to wlan_private structure
209 * @param req A pointer to ifreq structure
210 * @return 0 --success, otherwise fail
212 static int wlan_bt_list_ioctl(wlan_private * priv, struct ifreq *req)
214 int pos;
215 char *addr1;
216 struct iwreq *wrq = (struct iwreq *)req;
217 /* used to pass id and store the bt entry returned by the FW */
218 union {
219 u32 id;
220 char addr1addr2[2 * ETH_ALEN];
221 } param;
222 static char outstr[64];
223 char *pbuf = outstr;
224 int ret;
226 lbs_deb_enter(LBS_DEB_IOCTL);
228 if (copy_from_user(outstr, wrq->u.data.pointer, sizeof(outstr))) {
229 lbs_deb_ioctl("Copy from user failed\n");
230 return -1;
232 param.id = simple_strtoul(outstr, NULL, 10);
233 pos = sprintf(pbuf, "%d: ", param.id);
234 pbuf += pos;
236 ret = libertas_prepare_and_send_command(priv, cmd_bt_access,
237 cmd_act_bt_access_list,
238 cmd_option_waitforrsp, 0,
239 (char *)&param);
241 if (ret == 0) {
242 addr1 = param.addr1addr2;
244 pos = sprintf(pbuf, "BT includes node ");
245 pbuf += pos;
246 pos = eth_addr2str(addr1, pbuf);
247 pbuf += pos;
248 } else {
249 sprintf(pbuf, "(null)");
250 pbuf += pos;
253 wrq->u.data.length = strlen(outstr);
254 if (copy_to_user(wrq->u.data.pointer, (char *)outstr,
255 wrq->u.data.length)) {
256 lbs_deb_ioctl("BT_LIST: Copy to user failed!\n");
257 return -EFAULT;
260 lbs_deb_leave(LBS_DEB_IOCTL);
261 return 0 ;
265 * @brief Sets inverted state of blacklist (non-zero if inverted)
266 * @param priv A pointer to wlan_private structure
267 * @param req A pointer to ifreq structure
268 * @return 0 --success, otherwise fail
270 static int wlan_bt_set_invert_ioctl(wlan_private * priv, struct ifreq *req)
272 int ret;
273 struct iwreq *wrq = (struct iwreq *)req;
274 union {
275 u32 id;
276 char addr1addr2[2 * ETH_ALEN];
277 } param;
279 lbs_deb_enter(LBS_DEB_IOCTL);
281 param.id = SUBCMD_DATA(wrq) ;
282 ret = libertas_prepare_and_send_command(priv, cmd_bt_access,
283 cmd_act_bt_access_set_invert,
284 cmd_option_waitforrsp, 0,
285 (char *)&param);
286 if (ret != 0)
287 return -EFAULT;
288 lbs_deb_leave(LBS_DEB_IOCTL);
289 return 0;
293 * @brief Gets inverted state of blacklist (non-zero if inverted)
294 * @param priv A pointer to wlan_private structure
295 * @param req A pointer to ifreq structure
296 * @return 0 --success, otherwise fail
298 static int wlan_bt_get_invert_ioctl(wlan_private * priv, struct ifreq *req)
300 struct iwreq *wrq = (struct iwreq *)req;
301 int ret;
302 union {
303 u32 id;
304 char addr1addr2[2 * ETH_ALEN];
305 } param;
307 lbs_deb_enter(LBS_DEB_IOCTL);
309 ret = libertas_prepare_and_send_command(priv, cmd_bt_access,
310 cmd_act_bt_access_get_invert,
311 cmd_option_waitforrsp, 0,
312 (char *)&param);
314 if (ret == 0)
315 wrq->u.param.value = le32_to_cpu(param.id);
316 else
317 return -EFAULT;
319 lbs_deb_leave(LBS_DEB_IOCTL);
320 return 0;
324 * @brief Find the next parameter in an input string
325 * @param ptr A pointer to the input parameter string
326 * @return A pointer to the next parameter, or 0 if no parameters left.
328 static char * next_param(char * ptr)
330 if (!ptr) return NULL;
331 while (*ptr == ' ' || *ptr == '\t') ++ptr;
332 return (*ptr == '\0') ? NULL : ptr;
336 * @brief Add an entry to the FWT table
337 * @param priv A pointer to wlan_private structure
338 * @param req A pointer to ifreq structure
339 * @return 0 --success, otherwise fail
341 static int wlan_fwt_add_ioctl(wlan_private * priv, struct ifreq *req)
343 struct iwreq *wrq = (struct iwreq *)req;
344 char in_str[128];
345 static struct cmd_ds_fwt_access fwt_access;
346 char *ptr;
347 int ret;
349 lbs_deb_enter(LBS_DEB_IOCTL);
351 if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
352 return -EFAULT;
354 if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
355 lbs_pr_alert( "FWT_ADD: Invalid MAC address 1\n");
356 return -EINVAL;
359 if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) {
360 lbs_pr_alert( "FWT_ADD: Invalid MAC address 2\n");
361 return -EINVAL;
364 if ((ptr = next_param(ptr)))
365 fwt_access.metric =
366 cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
367 else
368 fwt_access.metric = cpu_to_le32(FWT_DEFAULT_METRIC);
370 if ((ptr = next_param(ptr)))
371 fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10);
372 else
373 fwt_access.dir = FWT_DEFAULT_DIR;
375 if ((ptr = next_param(ptr)))
376 fwt_access.rate = (u8) simple_strtoul(ptr, &ptr, 10);
377 else
378 fwt_access.rate = FWT_DEFAULT_RATE;
380 if ((ptr = next_param(ptr)))
381 fwt_access.ssn =
382 cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
383 else
384 fwt_access.ssn = cpu_to_le32(FWT_DEFAULT_SSN);
386 if ((ptr = next_param(ptr)))
387 fwt_access.dsn =
388 cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
389 else
390 fwt_access.dsn = cpu_to_le32(FWT_DEFAULT_DSN);
392 if ((ptr = next_param(ptr)))
393 fwt_access.hopcount = simple_strtoul(ptr, &ptr, 10);
394 else
395 fwt_access.hopcount = FWT_DEFAULT_HOPCOUNT;
397 if ((ptr = next_param(ptr)))
398 fwt_access.ttl = simple_strtoul(ptr, &ptr, 10);
399 else
400 fwt_access.ttl = FWT_DEFAULT_TTL;
402 if ((ptr = next_param(ptr)))
403 fwt_access.expiration =
404 cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
405 else
406 fwt_access.expiration = cpu_to_le32(FWT_DEFAULT_EXPIRATION);
408 if ((ptr = next_param(ptr)))
409 fwt_access.sleepmode = (u8)simple_strtoul(ptr, &ptr, 10);
410 else
411 fwt_access.sleepmode = FWT_DEFAULT_SLEEPMODE;
413 if ((ptr = next_param(ptr)))
414 fwt_access.snr =
415 cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
416 else
417 fwt_access.snr = cpu_to_le32(FWT_DEFAULT_SNR);
419 #ifdef DEBUG
421 char ethaddr1_str[18], ethaddr2_str[18];
422 eth_addr2str(fwt_access.da, ethaddr1_str);
423 eth_addr2str(fwt_access.ra, ethaddr2_str);
424 lbs_deb_ioctl("FWT_ADD: adding (da:%s,%i,ra:%s)\n", ethaddr1_str,
425 fwt_access.dir, ethaddr2_str);
426 lbs_deb_ioctl("FWT_ADD: ssn:%u dsn:%u met:%u hop:%u ttl:%u exp:%u slp:%u snr:%u\n",
427 fwt_access.ssn, fwt_access.dsn, fwt_access.metric,
428 fwt_access.hopcount, fwt_access.ttl, fwt_access.expiration,
429 fwt_access.sleepmode, fwt_access.snr);
431 #endif
433 ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
434 cmd_act_fwt_access_add,
435 cmd_option_waitforrsp, 0,
436 (void *)&fwt_access);
438 lbs_deb_leave_args(LBS_DEB_IOCTL, "ret %d", ret);
439 return ret;
443 * @brief Delete an entry from the FWT table
444 * @param priv A pointer to wlan_private structure
445 * @param req A pointer to ifreq structure
446 * @return 0 --success, otherwise fail
448 static int wlan_fwt_del_ioctl(wlan_private * priv, struct ifreq *req)
450 struct iwreq *wrq = (struct iwreq *)req;
451 char in_str[64];
452 static struct cmd_ds_fwt_access fwt_access;
453 char *ptr;
454 int ret;
456 lbs_deb_enter(LBS_DEB_IOCTL);
458 if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
459 return -EFAULT;
461 if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
462 lbs_pr_alert( "FWT_DEL: Invalid MAC address 1\n");
463 return -EINVAL;
466 if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) {
467 lbs_pr_alert( "FWT_DEL: Invalid MAC address 2\n");
468 return -EINVAL;
471 if ((ptr = next_param(ptr)))
472 fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10);
473 else
474 fwt_access.dir = FWT_DEFAULT_DIR;
476 #ifdef DEBUG
478 char ethaddr1_str[18], ethaddr2_str[18];
479 lbs_deb_ioctl("FWT_DEL: line is %s\n", in_str);
480 eth_addr2str(fwt_access.da, ethaddr1_str);
481 eth_addr2str(fwt_access.ra, ethaddr2_str);
482 lbs_deb_ioctl("FWT_DEL: removing (da:%s,ra:%s,dir:%d)\n", ethaddr1_str,
483 ethaddr2_str, fwt_access.dir);
485 #endif
487 ret = libertas_prepare_and_send_command(priv,
488 cmd_fwt_access,
489 cmd_act_fwt_access_del,
490 cmd_option_waitforrsp, 0,
491 (void *)&fwt_access);
492 lbs_deb_leave_args(LBS_DEB_IOCTL, "ret %d", ret);
493 return ret;
498 * @brief Print route parameters
499 * @param fwt_access struct cmd_ds_fwt_access with route info
500 * @param buf destination buffer for route info
502 static void print_route(struct cmd_ds_fwt_access fwt_access, char *buf)
504 buf += sprintf(buf, " ");
505 buf += eth_addr2str(fwt_access.da, buf);
506 buf += sprintf(buf, " ");
507 buf += eth_addr2str(fwt_access.ra, buf);
508 buf += sprintf(buf, " %u", fwt_access.valid);
509 buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.metric));
510 buf += sprintf(buf, " %u", fwt_access.dir);
511 buf += sprintf(buf, " %u", fwt_access.rate);
512 buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.ssn));
513 buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.dsn));
514 buf += sprintf(buf, " %u", fwt_access.hopcount);
515 buf += sprintf(buf, " %u", fwt_access.ttl);
516 buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.expiration));
517 buf += sprintf(buf, " %u", fwt_access.sleepmode);
518 buf += sprintf(buf, " %u ", le32_to_cpu(fwt_access.snr));
519 buf += eth_addr2str(fwt_access.prec, buf);
523 * @brief Lookup an entry in the FWT table
524 * @param priv A pointer to wlan_private structure
525 * @param req A pointer to ifreq structure
526 * @return 0 --success, otherwise fail
528 static int wlan_fwt_lookup_ioctl(wlan_private * priv, struct ifreq *req)
530 struct iwreq *wrq = (struct iwreq *)req;
531 char in_str[64];
532 char *ptr;
533 static struct cmd_ds_fwt_access fwt_access;
534 static char out_str[128];
535 int ret;
537 lbs_deb_enter(LBS_DEB_IOCTL);
539 if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
540 return -EFAULT;
542 if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
543 lbs_pr_alert( "FWT_LOOKUP: Invalid MAC address\n");
544 return -EINVAL;
547 #ifdef DEBUG
549 char ethaddr1_str[18];
550 lbs_deb_ioctl("FWT_LOOKUP: line is %s\n", in_str);
551 eth_addr2str(fwt_access.da, ethaddr1_str);
552 lbs_deb_ioctl("FWT_LOOKUP: looking for (da:%s)\n", ethaddr1_str);
554 #endif
556 ret = libertas_prepare_and_send_command(priv,
557 cmd_fwt_access,
558 cmd_act_fwt_access_lookup,
559 cmd_option_waitforrsp, 0,
560 (void *)&fwt_access);
562 if (ret == 0)
563 print_route(fwt_access, out_str);
564 else
565 sprintf(out_str, "(null)");
567 wrq->u.data.length = strlen(out_str);
568 if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
569 wrq->u.data.length)) {
570 lbs_deb_ioctl("FWT_LOOKUP: Copy to user failed!\n");
571 return -EFAULT;
574 lbs_deb_leave(LBS_DEB_IOCTL);
575 return 0;
579 * @brief Reset all entries from the FWT table
580 * @param priv A pointer to wlan_private structure
581 * @return 0 --success, otherwise fail
583 static int wlan_fwt_reset_ioctl(wlan_private * priv)
585 lbs_deb_ioctl("FWT: resetting\n");
587 return (libertas_prepare_and_send_command(priv,
588 cmd_fwt_access,
589 cmd_act_fwt_access_reset,
590 cmd_option_waitforrsp, 0, NULL));
594 * @brief List an entry from the FWT table
595 * @param priv A pointer to wlan_private structure
596 * @param req A pointer to ifreq structure
597 * @return 0 --success, otherwise fail
599 static int wlan_fwt_list_ioctl(wlan_private * priv, struct ifreq *req)
601 struct iwreq *wrq = (struct iwreq *)req;
602 char in_str[8];
603 static struct cmd_ds_fwt_access fwt_access;
604 char *ptr = in_str;
605 static char out_str[128];
606 char *pbuf = out_str;
607 int ret = 0;
609 lbs_deb_enter(LBS_DEB_IOCTL);
611 if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str))) {
612 ret = -EFAULT;
613 goto out;
616 fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
618 #ifdef DEBUG
620 lbs_deb_ioctl("FWT_LIST: line is %s\n", in_str);
621 lbs_deb_ioctl("FWT_LIST: listing id:%i\n", le32_to_cpu(fwt_access.id));
623 #endif
625 ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
626 cmd_act_fwt_access_list,
627 cmd_option_waitforrsp, 0, (void *)&fwt_access);
629 if (ret == 0)
630 print_route(fwt_access, pbuf);
631 else
632 pbuf += sprintf(pbuf, " (null)");
634 wrq->u.data.length = strlen(out_str);
635 if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
636 wrq->u.data.length)) {
637 lbs_deb_ioctl("FWT_LIST: Copy to user failed!\n");
638 ret = -EFAULT;
639 goto out;
642 ret = 0;
644 out:
645 lbs_deb_leave(LBS_DEB_IOCTL);
646 return ret;
650 * @brief List an entry from the FRT table
651 * @param priv A pointer to wlan_private structure
652 * @param req A pointer to ifreq structure
653 * @return 0 --success, otherwise fail
655 static int wlan_fwt_list_route_ioctl(wlan_private * priv, struct ifreq *req)
657 struct iwreq *wrq = (struct iwreq *)req;
658 char in_str[64];
659 static struct cmd_ds_fwt_access fwt_access;
660 char *ptr = in_str;
661 static char out_str[128];
662 char *pbuf = out_str;
663 int ret;
665 lbs_deb_enter(LBS_DEB_IOCTL);
667 if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
668 return -EFAULT;
670 fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
672 #ifdef DEBUG
674 lbs_deb_ioctl("FWT_LIST_ROUTE: line is %s\n", in_str);
675 lbs_deb_ioctl("FWT_LIST_ROUTE: listing id:%i\n", le32_to_cpu(fwt_access.id));
677 #endif
679 ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
680 cmd_act_fwt_access_list_route,
681 cmd_option_waitforrsp, 0, (void *)&fwt_access);
683 if (ret == 0) {
684 print_route(fwt_access, pbuf);
685 } else
686 pbuf += sprintf(pbuf, " (null)");
688 wrq->u.data.length = strlen(out_str);
689 if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
690 wrq->u.data.length)) {
691 lbs_deb_ioctl("FWT_LIST_ROUTE: Copy to user failed!\n");
692 return -EFAULT;
695 lbs_deb_leave(LBS_DEB_IOCTL);
696 return 0;
700 * @brief List an entry from the FNT table
701 * @param priv A pointer to wlan_private structure
702 * @param req A pointer to ifreq structure
703 * @return 0 --success, otherwise fail
705 static int wlan_fwt_list_neighbor_ioctl(wlan_private * priv, struct ifreq *req)
707 struct iwreq *wrq = (struct iwreq *)req;
708 char in_str[8];
709 static struct cmd_ds_fwt_access fwt_access;
710 char *ptr = in_str;
711 static char out_str[128];
712 char *pbuf = out_str;
713 int ret;
715 lbs_deb_enter(LBS_DEB_IOCTL);
717 if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
718 return -EFAULT;
720 memset(&fwt_access, 0, sizeof(fwt_access));
721 fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
723 #ifdef DEBUG
725 lbs_deb_ioctl("FWT_LIST_NEIGHBOR: line is %s\n", in_str);
726 lbs_deb_ioctl("FWT_LIST_NEIGHBOR: listing id:%i\n", le32_to_cpu(fwt_access.id));
728 #endif
730 ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
731 cmd_act_fwt_access_list_neighbor,
732 cmd_option_waitforrsp, 0,
733 (void *)&fwt_access);
735 if (ret == 0) {
736 pbuf += sprintf(pbuf, " ra ");
737 pbuf += eth_addr2str(fwt_access.ra, pbuf);
738 pbuf += sprintf(pbuf, " slp %u", fwt_access.sleepmode);
739 pbuf += sprintf(pbuf, " snr %u", le32_to_cpu(fwt_access.snr));
740 pbuf += sprintf(pbuf, " ref %u", le32_to_cpu(fwt_access.references));
741 } else
742 pbuf += sprintf(pbuf, " (null)");
744 wrq->u.data.length = strlen(out_str);
745 if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
746 wrq->u.data.length)) {
747 lbs_deb_ioctl("FWT_LIST_NEIGHBOR: Copy to user failed!\n");
748 return -EFAULT;
751 lbs_deb_leave(LBS_DEB_IOCTL);
752 return 0;
756 * @brief Cleans up the route (FRT) and neighbor (FNT) tables
757 * (Garbage Collection)
758 * @param priv A pointer to wlan_private structure
759 * @param req A pointer to ifreq structure
760 * @return 0 --success, otherwise fail
762 static int wlan_fwt_cleanup_ioctl(wlan_private * priv, struct ifreq *req)
764 struct iwreq *wrq = (struct iwreq *)req;
765 static struct cmd_ds_fwt_access fwt_access;
766 int ret;
768 lbs_deb_enter(LBS_DEB_IOCTL);
770 lbs_deb_ioctl("FWT: cleaning up\n");
772 memset(&fwt_access, 0, sizeof(fwt_access));
774 ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
775 cmd_act_fwt_access_cleanup,
776 cmd_option_waitforrsp, 0,
777 (void *)&fwt_access);
779 if (ret == 0)
780 wrq->u.param.value = le32_to_cpu(fwt_access.references);
781 else
782 return -EFAULT;
784 lbs_deb_leave(LBS_DEB_IOCTL);
785 return 0;
789 * @brief Gets firmware internal time (debug purposes)
790 * @param priv A pointer to wlan_private structure
791 * @param req A pointer to ifreq structure
792 * @return 0 --success, otherwise fail
794 static int wlan_fwt_time_ioctl(wlan_private * priv, struct ifreq *req)
796 struct iwreq *wrq = (struct iwreq *)req;
797 static struct cmd_ds_fwt_access fwt_access;
798 int ret;
800 lbs_deb_enter(LBS_DEB_IOCTL);
802 lbs_deb_ioctl("FWT: getting time\n");
804 memset(&fwt_access, 0, sizeof(fwt_access));
806 ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
807 cmd_act_fwt_access_time,
808 cmd_option_waitforrsp, 0,
809 (void *)&fwt_access);
811 if (ret == 0)
812 wrq->u.param.value = le32_to_cpu(fwt_access.references);
813 else
814 return -EFAULT;
816 lbs_deb_leave(LBS_DEB_IOCTL);
817 return 0;
821 * @brief Gets mesh ttl from firmware
822 * @param priv A pointer to wlan_private structure
823 * @param req A pointer to ifreq structure
824 * @return 0 --success, otherwise fail
826 static int wlan_mesh_get_ttl_ioctl(wlan_private * priv, struct ifreq *req)
828 struct iwreq *wrq = (struct iwreq *)req;
829 struct cmd_ds_mesh_access mesh_access;
830 int ret;
832 lbs_deb_enter(LBS_DEB_IOCTL);
834 memset(&mesh_access, 0, sizeof(mesh_access));
836 ret = libertas_prepare_and_send_command(priv, cmd_mesh_access,
837 cmd_act_mesh_get_ttl,
838 cmd_option_waitforrsp, 0,
839 (void *)&mesh_access);
841 if (ret == 0)
842 wrq->u.param.value = le32_to_cpu(mesh_access.data[0]);
843 else
844 return -EFAULT;
846 lbs_deb_leave(LBS_DEB_IOCTL);
847 return 0;
851 * @brief Gets mesh ttl from firmware
852 * @param priv A pointer to wlan_private structure
853 * @param ttl New ttl value
854 * @return 0 --success, otherwise fail
856 static int wlan_mesh_set_ttl_ioctl(wlan_private * priv, int ttl)
858 struct cmd_ds_mesh_access mesh_access;
859 int ret;
861 lbs_deb_enter(LBS_DEB_IOCTL);
863 if( (ttl > 0xff) || (ttl < 0) )
864 return -EINVAL;
866 memset(&mesh_access, 0, sizeof(mesh_access));
867 mesh_access.data[0] = cpu_to_le32(ttl);
869 ret = libertas_prepare_and_send_command(priv, cmd_mesh_access,
870 cmd_act_mesh_set_ttl,
871 cmd_option_waitforrsp, 0,
872 (void *)&mesh_access);
874 if (ret != 0)
875 ret = -EFAULT;
877 lbs_deb_leave(LBS_DEB_IOCTL);
878 return ret;
882 * @brief ioctl function - entry point
884 * @param dev A pointer to net_device structure
885 * @param req A pointer to ifreq structure
886 * @param cmd command
887 * @return 0--success, otherwise fail
889 int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
891 int subcmd = 0;
892 int idata = 0;
893 int *pdata;
894 int ret = 0;
895 wlan_private *priv = dev->priv;
896 wlan_adapter *adapter = priv->adapter;
897 struct iwreq *wrq = (struct iwreq *)req;
899 lbs_deb_enter(LBS_DEB_IOCTL);
901 lbs_deb_ioctl("libertas_do_ioctl: ioctl cmd = 0x%x\n", cmd);
902 switch (cmd) {
903 case WLAN_SETNONE_GETNONE: /* set WPA mode on/off ioctl #20 */
904 switch (wrq->u.data.flags) {
905 case WLAN_SUBCMD_BT_RESET: /* bt_reset */
906 wlan_bt_reset_ioctl(priv);
907 break;
908 case WLAN_SUBCMD_FWT_RESET: /* fwt_reset */
909 wlan_fwt_reset_ioctl(priv);
910 break;
911 } /* End of switch */
912 break;
914 case WLAN_SETONEINT_GETNONE:
915 /* The first 4 bytes of req->ifr_data is sub-ioctl number
916 * after 4 bytes sits the payload.
918 subcmd = wrq->u.data.flags;
919 if (!subcmd)
920 subcmd = (int)wrq->u.param.value;
922 switch (subcmd) {
923 case WLANSETREGION:
924 idata = SUBCMD_DATA(wrq);
925 ret = wlan_set_region(priv, (u16) idata);
926 break;
927 case WLAN_SUBCMD_MESH_SET_TTL:
928 idata = SUBCMD_DATA(wrq);
929 ret = wlan_mesh_set_ttl_ioctl(priv, idata);
930 break;
932 case WLAN_SUBCMD_BT_SET_INVERT:
933 ret = wlan_bt_set_invert_ioctl(priv, req);
934 break ;
936 default:
937 ret = -EOPNOTSUPP;
938 break;
941 break;
943 case WLAN_SET128CHAR_GET128CHAR:
944 switch ((int)wrq->u.data.flags) {
945 case WLAN_SUBCMD_BT_ADD:
946 ret = wlan_bt_add_ioctl(priv, req);
947 break;
948 case WLAN_SUBCMD_BT_DEL:
949 ret = wlan_bt_del_ioctl(priv, req);
950 break;
951 case WLAN_SUBCMD_BT_LIST:
952 ret = wlan_bt_list_ioctl(priv, req);
953 break;
954 case WLAN_SUBCMD_FWT_ADD:
955 ret = wlan_fwt_add_ioctl(priv, req);
956 break;
957 case WLAN_SUBCMD_FWT_DEL:
958 ret = wlan_fwt_del_ioctl(priv, req);
959 break;
960 case WLAN_SUBCMD_FWT_LOOKUP:
961 ret = wlan_fwt_lookup_ioctl(priv, req);
962 break;
963 case WLAN_SUBCMD_FWT_LIST_NEIGHBOR:
964 ret = wlan_fwt_list_neighbor_ioctl(priv, req);
965 break;
966 case WLAN_SUBCMD_FWT_LIST:
967 ret = wlan_fwt_list_ioctl(priv, req);
968 break;
969 case WLAN_SUBCMD_FWT_LIST_ROUTE:
970 ret = wlan_fwt_list_route_ioctl(priv, req);
971 break;
973 break;
975 case WLAN_SETNONE_GETONEINT:
976 switch (wrq->u.param.value) {
977 case WLANGETREGION:
978 pdata = (int *)wrq->u.name;
979 *pdata = (int)adapter->regioncode;
980 break;
981 case WLAN_SUBCMD_FWT_CLEANUP: /* fwt_cleanup */
982 ret = wlan_fwt_cleanup_ioctl(priv, req);
983 break;
985 case WLAN_SUBCMD_FWT_TIME: /* fwt_time */
986 ret = wlan_fwt_time_ioctl(priv, req);
987 break;
989 case WLAN_SUBCMD_MESH_GET_TTL:
990 ret = wlan_mesh_get_ttl_ioctl(priv, req);
991 break;
993 case WLAN_SUBCMD_BT_GET_INVERT:
994 ret = wlan_bt_get_invert_ioctl(priv, req);
995 break ;
997 default:
998 ret = -EOPNOTSUPP;
1002 break;
1004 case WLAN_SET_GET_SIXTEEN_INT:
1005 switch ((int)wrq->u.data.flags) {
1006 case WLAN_LED_GPIO_CTRL:
1008 int i;
1009 int data[16];
1011 struct cmd_ds_802_11_led_ctrl ctrl;
1012 struct mrvlietypes_ledgpio *gpio =
1013 (struct mrvlietypes_ledgpio *) ctrl.data;
1015 memset(&ctrl, 0, sizeof(ctrl));
1016 if (wrq->u.data.length > MAX_LEDS * 2)
1017 return -ENOTSUPP;
1018 if ((wrq->u.data.length % 2) != 0)
1019 return -ENOTSUPP;
1020 if (wrq->u.data.length == 0) {
1021 ctrl.action =
1022 cpu_to_le16
1023 (cmd_act_get);
1024 } else {
1025 if (copy_from_user
1026 (data, wrq->u.data.pointer,
1027 sizeof(int) *
1028 wrq->u.data.length)) {
1029 lbs_deb_ioctl(
1030 "Copy from user failed\n");
1031 return -EFAULT;
1034 ctrl.action =
1035 cpu_to_le16
1036 (cmd_act_set);
1037 ctrl.numled = cpu_to_le16(0);
1038 gpio->header.type =
1039 cpu_to_le16(TLV_TYPE_LED_GPIO);
1040 gpio->header.len = wrq->u.data.length;
1041 for (i = 0; i < wrq->u.data.length;
1042 i += 2) {
1043 gpio->ledpin[i / 2].led =
1044 data[i];
1045 gpio->ledpin[i / 2].pin =
1046 data[i + 1];
1049 ret =
1050 libertas_prepare_and_send_command(priv,
1051 cmd_802_11_led_gpio_ctrl,
1053 cmd_option_waitforrsp,
1054 0, (void *)&ctrl);
1055 for (i = 0; i < gpio->header.len; i += 2) {
1056 data[i] = gpio->ledpin[i / 2].led;
1057 data[i + 1] = gpio->ledpin[i / 2].pin;
1059 if (copy_to_user(wrq->u.data.pointer, data,
1060 sizeof(int) *
1061 gpio->header.len)) {
1062 lbs_deb_ioctl("Copy to user failed\n");
1063 return -EFAULT;
1066 wrq->u.data.length = gpio->header.len;
1068 break;
1070 break;
1072 default:
1073 ret = -EINVAL;
1074 break;
1077 lbs_deb_leave_args(LBS_DEB_IOCTL, "ret %d", ret);
1078 return ret;