diff options
Diffstat (limited to 'package/libertas/src/ioctl.c')
-rw-r--r-- | package/libertas/src/ioctl.c | 1243 |
1 files changed, 0 insertions, 1243 deletions
diff --git a/package/libertas/src/ioctl.c b/package/libertas/src/ioctl.c deleted file mode 100644 index 18aebe956..000000000 --- a/package/libertas/src/ioctl.c +++ /dev/null @@ -1,1243 +0,0 @@ -/** - * This file contains ioctl functions - */ - -#include <linux/ctype.h> -#include <linux/delay.h> -#include <linux/if.h> -#include <linux/if_arp.h> -#include <linux/wireless.h> - -#include <net/iw_handler.h> -#include <net/ieee80211.h> - -#include "host.h" -#include "radiotap.h" -#include "decl.h" -#include "defs.h" -#include "dev.h" -#include "wext.h" -#include "cmd.h" -#include "ioctl.h" - -#define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN + \ - IW_ESSID_MAX_SIZE + \ - IW_EV_UINT_LEN + IW_EV_FREQ_LEN + \ - IW_EV_QUAL_LEN + IW_ESSID_MAX_SIZE + \ - IW_EV_PARAM_LEN + 40) /* 40 for WPAIE */ - -#define WAIT_FOR_SCAN_RRESULT_MAX_TIME (10 * HZ) - -static int lbs_set_region(struct lbs_private * priv, u16 region_code) -{ - int i; - int ret = 0; - - for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) { - // use the region code to search for the index - if (region_code == lbs_region_code_to_index[i]) { - priv->regioncode = region_code; - break; - } - } - - // if it's unidentified region code - if (i >= MRVDRV_MAX_REGION_CODE) { - lbs_deb_ioctl("region Code not identified\n"); - ret = -1; - goto done; - } - - if (lbs_set_regiontable(priv, priv->regioncode, 0)) { - ret = -EINVAL; - } - -done: - lbs_deb_leave_args(LBS_DEB_IOCTL, "ret %d", ret); - return ret; -} - -static inline int hex2int(char c) -{ - if (c >= '0' && c <= '9') - return (c - '0'); - if (c >= 'a' && c <= 'f') - return (c - 'a' + 10); - if (c >= 'A' && c <= 'F') - return (c - 'A' + 10); - return -1; -} - -/* Convert a string representation of a MAC address ("xx:xx:xx:xx:xx:xx") - into binary format (6 bytes). - - This function expects that each byte is represented with 2 characters - (e.g., 11:2:11:11:11:11 is invalid) - - */ -static char *eth_str2addr(char *ethstr, u8 * addr) -{ - int i, val, val2; - char *pos = ethstr; - - /* get rid of initial blanks */ - while (*pos == ' ' || *pos == '\t') - ++pos; - - for (i = 0; i < 6; i++) { - val = hex2int(*pos++); - if (val < 0) - return NULL; - val2 = hex2int(*pos++); - if (val2 < 0) - return NULL; - addr[i] = (val * 16 + val2) & 0xff; - - if (i < 5 && *pos++ != ':') - return NULL; - } - return pos; -} - -/* this writes xx:xx:xx:xx:xx:xx into ethstr - (ethstr must have space for 18 chars) */ -static int eth_addr2str(u8 * addr, char *ethstr) -{ - int i; - char *pos = ethstr; - - for (i = 0; i < 6; i++) { - sprintf(pos, "%02x", addr[i] & 0xff); - pos += 2; - if (i < 5) - *pos++ = ':'; - } - return 17; -} - -/** - * @brief Add an entry to the BT table - * @param priv A pointer to struct lbs_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int lbs_bt_add_ioctl(struct lbs_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - char ethaddrs_str[18]; - char *pos; - u8 ethaddr[ETH_ALEN]; - int ret; - - lbs_deb_enter(LBS_DEB_IOCTL); - - if (copy_from_user(ethaddrs_str, wrq->u.data.pointer, - sizeof(ethaddrs_str))) - return -EFAULT; - - if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) { - lbs_pr_info("BT_ADD: Invalid MAC address\n"); - return -EINVAL; - } - - lbs_deb_ioctl("BT: adding %s\n", ethaddrs_str); - ret = lbs_prepare_and_send_command(priv, CMD_BT_ACCESS, - CMD_ACT_BT_ACCESS_ADD, - CMD_OPTION_WAITFORRSP, 0, ethaddr); - lbs_deb_leave_args(LBS_DEB_IOCTL, "ret %d", ret); - return ret; -} - -/** - * @brief Delete an entry from the BT table - * @param priv A pointer to struct lbs_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int lbs_bt_del_ioctl(struct lbs_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - char ethaddrs_str[18]; - u8 ethaddr[ETH_ALEN]; - char *pos; - - lbs_deb_enter(LBS_DEB_IOCTL); - - if (copy_from_user(ethaddrs_str, wrq->u.data.pointer, - sizeof(ethaddrs_str))) - return -EFAULT; - - if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) { - lbs_pr_info("Invalid MAC address\n"); - return -EINVAL; - } - - lbs_deb_ioctl("BT: deleting %s\n", ethaddrs_str); - - return (lbs_prepare_and_send_command(priv, - CMD_BT_ACCESS, - CMD_ACT_BT_ACCESS_DEL, - CMD_OPTION_WAITFORRSP, 0, ethaddr)); - - lbs_deb_leave(LBS_DEB_IOCTL); - return 0; -} - -/** - * @brief Reset all entries from the BT table - * @param priv A pointer to struct lbs_private structure - * @return 0 --success, otherwise fail - */ -static int lbs_bt_reset_ioctl(struct lbs_private * priv) -{ - lbs_deb_enter(LBS_DEB_IOCTL); - - lbs_pr_alert( "BT: resetting\n"); - - return (lbs_prepare_and_send_command(priv, - CMD_BT_ACCESS, - CMD_ACT_BT_ACCESS_RESET, - CMD_OPTION_WAITFORRSP, 0, NULL)); - - lbs_deb_leave(LBS_DEB_IOCTL); - return 0; -} - -/** - * @brief List an entry from the BT table - * @param priv A pointer to struct lbs_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int lbs_bt_list_ioctl(struct lbs_private * priv, struct ifreq *req) -{ - int pos; - char *addr1; - struct iwreq *wrq = (struct iwreq *)req; - /* used to pass id and store the bt entry returned by the FW */ - union { - u32 id; - char addr1addr2[2 * ETH_ALEN]; - } param; - static char outstr[64]; - char *pbuf = outstr; - int ret; - - lbs_deb_enter(LBS_DEB_IOCTL); - - if (copy_from_user(outstr, wrq->u.data.pointer, sizeof(outstr))) { - lbs_deb_ioctl("Copy from user failed\n"); - return -1; - } - param.id = simple_strtoul(outstr, NULL, 10); - pos = sprintf(pbuf, "%d: ", param.id); - pbuf += pos; - - ret = lbs_prepare_and_send_command(priv, CMD_BT_ACCESS, - CMD_ACT_BT_ACCESS_LIST, - CMD_OPTION_WAITFORRSP, 0, - (char *)¶m); - - if (ret == 0) { - addr1 = param.addr1addr2; - - pos = sprintf(pbuf, "BT includes node "); - pbuf += pos; - pos = eth_addr2str(addr1, pbuf); - pbuf += pos; - } else { - sprintf(pbuf, "(null)"); - pbuf += pos; - } - - wrq->u.data.length = strlen(outstr); - if (copy_to_user(wrq->u.data.pointer, (char *)outstr, - wrq->u.data.length)) { - lbs_deb_ioctl("BT_LIST: Copy to user failed!\n"); - return -EFAULT; - } - - lbs_deb_leave(LBS_DEB_IOCTL); - return 0 ; -} - -/** - * @brief Sets inverted state of blacklist (non-zero if inverted) - * @param priv A pointer to struct lbs_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int lbs_bt_set_invert_ioctl(struct lbs_private * priv, struct ifreq *req) -{ - int ret; - struct iwreq *wrq = (struct iwreq *)req; - union { - u32 id; - char addr1addr2[2 * ETH_ALEN]; - } param; - - lbs_deb_enter(LBS_DEB_IOCTL); - - param.id = SUBCMD_DATA(wrq) ; - ret = lbs_prepare_and_send_command(priv, CMD_BT_ACCESS, - CMD_ACT_BT_ACCESS_SET_INVERT, - CMD_OPTION_WAITFORRSP, 0, - (char *)¶m); - if (ret != 0) - return -EFAULT; - lbs_deb_leave(LBS_DEB_IOCTL); - return 0; -} - -/** - * @brief Gets inverted state of blacklist (non-zero if inverted) - * @param priv A pointer to struct lbs_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int lbs_bt_get_invert_ioctl(struct lbs_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - int ret; - union { - __le32 id; - char addr1addr2[2 * ETH_ALEN]; - } param; - - lbs_deb_enter(LBS_DEB_IOCTL); - - ret = lbs_prepare_and_send_command(priv, CMD_BT_ACCESS, - CMD_ACT_BT_ACCESS_GET_INVERT, - CMD_OPTION_WAITFORRSP, 0, - (char *)¶m); - - if (ret == 0) - wrq->u.param.value = le32_to_cpu(param.id); - else - return -EFAULT; - - lbs_deb_leave(LBS_DEB_IOCTL); - return 0; -} - -/** - * @brief Find the next parameter in an input string - * @param ptr A pointer to the input parameter string - * @return A pointer to the next parameter, or 0 if no parameters left. - */ -static char * next_param(char * ptr) -{ - if (!ptr) return NULL; - while (*ptr == ' ' || *ptr == '\t') ++ptr; - return (*ptr == '\0') ? NULL : ptr; -} - -/** - * @brief Add an entry to the FWT table - * @param priv A pointer to struct lbs_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int lbs_fwt_add_ioctl(struct lbs_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - char in_str[128]; - static struct cmd_ds_fwt_access fwt_access; - char *ptr; - int ret; - - lbs_deb_enter(LBS_DEB_IOCTL); - - if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str))) - return -EFAULT; - - if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) { - lbs_pr_alert( "FWT_ADD: Invalid MAC address 1\n"); - return -EINVAL; - } - - if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) { - lbs_pr_alert( "FWT_ADD: Invalid MAC address 2\n"); - return -EINVAL; - } - - if ((ptr = next_param(ptr))) - fwt_access.metric = - cpu_to_le32(simple_strtoul(ptr, &ptr, 10)); - else - fwt_access.metric = cpu_to_le32(FWT_DEFAULT_METRIC); - - if ((ptr = next_param(ptr))) - fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10); - else - fwt_access.dir = FWT_DEFAULT_DIR; - - if ((ptr = next_param(ptr))) - fwt_access.rate = (u8) simple_strtoul(ptr, &ptr, 10); - else - fwt_access.rate = FWT_DEFAULT_RATE; - - if ((ptr = next_param(ptr))) - fwt_access.ssn = - cpu_to_le32(simple_strtoul(ptr, &ptr, 10)); - else - fwt_access.ssn = cpu_to_le32(FWT_DEFAULT_SSN); - - if ((ptr = next_param(ptr))) - fwt_access.dsn = - cpu_to_le32(simple_strtoul(ptr, &ptr, 10)); - else - fwt_access.dsn = cpu_to_le32(FWT_DEFAULT_DSN); - - if ((ptr = next_param(ptr))) - fwt_access.hopcount = simple_strtoul(ptr, &ptr, 10); - else - fwt_access.hopcount = FWT_DEFAULT_HOPCOUNT; - - if ((ptr = next_param(ptr))) - fwt_access.ttl = simple_strtoul(ptr, &ptr, 10); - else - fwt_access.ttl = FWT_DEFAULT_TTL; - - if ((ptr = next_param(ptr))) - fwt_access.expiration = - cpu_to_le32(simple_strtoul(ptr, &ptr, 10)); - else - fwt_access.expiration = cpu_to_le32(FWT_DEFAULT_EXPIRATION); - - if ((ptr = next_param(ptr))) - fwt_access.sleepmode = (u8)simple_strtoul(ptr, &ptr, 10); - else - fwt_access.sleepmode = FWT_DEFAULT_SLEEPMODE; - - if ((ptr = next_param(ptr))) - fwt_access.snr = - cpu_to_le32(simple_strtoul(ptr, &ptr, 10)); - else - fwt_access.snr = cpu_to_le32(FWT_DEFAULT_SNR); - -#ifdef DEBUG - { - char ethaddr1_str[18], ethaddr2_str[18]; - eth_addr2str(fwt_access.da, ethaddr1_str); - eth_addr2str(fwt_access.ra, ethaddr2_str); - lbs_deb_ioctl("FWT_ADD: adding (da:%s,%i,ra:%s)\n", ethaddr1_str, - fwt_access.dir, ethaddr2_str); - lbs_deb_ioctl("FWT_ADD: ssn:%u dsn:%u met:%u hop:%u ttl:%u exp:%u slp:%u snr:%u\n", - fwt_access.ssn, fwt_access.dsn, fwt_access.metric, - fwt_access.hopcount, fwt_access.ttl, fwt_access.expiration, - fwt_access.sleepmode, fwt_access.snr); - } -#endif - - ret = lbs_prepare_and_send_command(priv, CMD_FWT_ACCESS, - CMD_ACT_FWT_ACCESS_ADD, - CMD_OPTION_WAITFORRSP, 0, - (void *)&fwt_access); - - lbs_deb_leave_args(LBS_DEB_IOCTL, "ret %d", ret); - return ret; -} - -/** - * @brief Delete an entry from the FWT table - * @param priv A pointer to struct lbs_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int lbs_fwt_del_ioctl(struct lbs_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - char in_str[64]; - static struct cmd_ds_fwt_access fwt_access; - char *ptr; - int ret; - - lbs_deb_enter(LBS_DEB_IOCTL); - - if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str))) - return -EFAULT; - - if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) { - lbs_pr_alert( "FWT_DEL: Invalid MAC address 1\n"); - return -EINVAL; - } - - if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) { - lbs_pr_alert( "FWT_DEL: Invalid MAC address 2\n"); - return -EINVAL; - } - - if ((ptr = next_param(ptr))) - fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10); - else - fwt_access.dir = FWT_DEFAULT_DIR; - -#ifdef DEBUG - { - char ethaddr1_str[18], ethaddr2_str[18]; - lbs_deb_ioctl("FWT_DEL: line is %s\n", in_str); - eth_addr2str(fwt_access.da, ethaddr1_str); - eth_addr2str(fwt_access.ra, ethaddr2_str); - lbs_deb_ioctl("FWT_DEL: removing (da:%s,ra:%s,dir:%d)\n", ethaddr1_str, - ethaddr2_str, fwt_access.dir); - } -#endif - - ret = lbs_prepare_and_send_command(priv, - CMD_FWT_ACCESS, - CMD_ACT_FWT_ACCESS_DEL, - CMD_OPTION_WAITFORRSP, 0, - (void *)&fwt_access); - lbs_deb_leave_args(LBS_DEB_IOCTL, "ret %d", ret); - return ret; -} - - -/** - * @brief Print route parameters - * @param fwt_access struct cmd_ds_fwt_access with route info - * @param buf destination buffer for route info - */ -static void print_route(struct cmd_ds_fwt_access fwt_access, char *buf) -{ - buf += sprintf(buf, " "); - buf += eth_addr2str(fwt_access.da, buf); - buf += sprintf(buf, " "); - buf += eth_addr2str(fwt_access.ra, buf); - buf += sprintf(buf, " %u", fwt_access.valid); - buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.metric)); - buf += sprintf(buf, " %u", fwt_access.dir); - buf += sprintf(buf, " %u", fwt_access.rate); - buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.ssn)); - buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.dsn)); - buf += sprintf(buf, " %u", fwt_access.hopcount); - buf += sprintf(buf, " %u", fwt_access.ttl); - buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.expiration)); - buf += sprintf(buf, " %u", fwt_access.sleepmode); - buf += sprintf(buf, " %u ", le32_to_cpu(fwt_access.snr)); - buf += eth_addr2str(fwt_access.prec, buf); -} - -/** - * @brief Lookup an entry in the FWT table - * @param priv A pointer to struct lbs_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int lbs_fwt_lookup_ioctl(struct lbs_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - char in_str[64]; - char *ptr; - static struct cmd_ds_fwt_access fwt_access; - static char out_str[128]; - int ret; - - lbs_deb_enter(LBS_DEB_IOCTL); - - if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str))) - return -EFAULT; - - if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) { - lbs_pr_alert( "FWT_LOOKUP: Invalid MAC address\n"); - return -EINVAL; - } - -#ifdef DEBUG - { - char ethaddr1_str[18]; - lbs_deb_ioctl("FWT_LOOKUP: line is %s\n", in_str); - eth_addr2str(fwt_access.da, ethaddr1_str); - lbs_deb_ioctl("FWT_LOOKUP: looking for (da:%s)\n", ethaddr1_str); - } -#endif - - ret = lbs_prepare_and_send_command(priv, - CMD_FWT_ACCESS, - CMD_ACT_FWT_ACCESS_LOOKUP, - CMD_OPTION_WAITFORRSP, 0, - (void *)&fwt_access); - - if (ret == 0) - print_route(fwt_access, out_str); - else - sprintf(out_str, "(null)"); - - wrq->u.data.length = strlen(out_str); - if (copy_to_user(wrq->u.data.pointer, (char *)out_str, - wrq->u.data.length)) { - lbs_deb_ioctl("FWT_LOOKUP: Copy to user failed!\n"); - return -EFAULT; - } - - lbs_deb_leave(LBS_DEB_IOCTL); - return 0; -} - -/** - * @brief Reset all entries from the FWT table - * @param priv A pointer to struct lbs_private structure - * @return 0 --success, otherwise fail - */ -static int lbs_fwt_reset_ioctl(struct lbs_private * priv) -{ - lbs_deb_ioctl("FWT: resetting\n"); - - return (lbs_prepare_and_send_command(priv, - CMD_FWT_ACCESS, - CMD_ACT_FWT_ACCESS_RESET, - CMD_OPTION_WAITFORRSP, 0, NULL)); -} - -/** - * @brief List an entry from the FWT table - * @param priv A pointer to struct lbs_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int lbs_fwt_list_ioctl(struct lbs_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - char in_str[8]; - static struct cmd_ds_fwt_access fwt_access; - char *ptr = in_str; - static char out_str[128]; - char *pbuf = out_str; - int ret = 0; - - lbs_deb_enter(LBS_DEB_IOCTL); - - if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str))) { - ret = -EFAULT; - goto out; - } - - fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10)); - -#ifdef DEBUG - { - lbs_deb_ioctl("FWT_LIST: line is %s\n", in_str); - lbs_deb_ioctl("FWT_LIST: listing id:%i\n", le32_to_cpu(fwt_access.id)); - } -#endif - - ret = lbs_prepare_and_send_command(priv, CMD_FWT_ACCESS, - CMD_ACT_FWT_ACCESS_LIST, - CMD_OPTION_WAITFORRSP, 0, (void *)&fwt_access); - - if (ret == 0) - print_route(fwt_access, pbuf); - else - pbuf += sprintf(pbuf, " (null)"); - - wrq->u.data.length = strlen(out_str); - if (copy_to_user(wrq->u.data.pointer, (char *)out_str, - wrq->u.data.length)) { - lbs_deb_ioctl("FWT_LIST: Copy to user failed!\n"); - ret = -EFAULT; - goto out; - } - - ret = 0; - -out: - lbs_deb_leave(LBS_DEB_IOCTL); - return ret; -} - -/** - * @brief List an entry from the FRT table - * @param priv A pointer to struct lbs_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int lbs_fwt_list_route_ioctl(struct lbs_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - char in_str[64]; - static struct cmd_ds_fwt_access fwt_access; - char *ptr = in_str; - static char out_str[128]; - char *pbuf = out_str; - int ret; - - lbs_deb_enter(LBS_DEB_IOCTL); - - if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str))) - return -EFAULT; - - fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10)); - -#ifdef DEBUG - { - lbs_deb_ioctl("FWT_LIST_ROUTE: line is %s\n", in_str); - lbs_deb_ioctl("FWT_LIST_ROUTE: listing id:%i\n", le32_to_cpu(fwt_access.id)); - } -#endif - - ret = lbs_prepare_and_send_command(priv, CMD_FWT_ACCESS, - CMD_ACT_FWT_ACCESS_LIST_ROUTE, - CMD_OPTION_WAITFORRSP, 0, (void *)&fwt_access); - - if (ret == 0) { - print_route(fwt_access, pbuf); - } else - pbuf += sprintf(pbuf, " (null)"); - - wrq->u.data.length = strlen(out_str); - if (copy_to_user(wrq->u.data.pointer, (char *)out_str, - wrq->u.data.length)) { - lbs_deb_ioctl("FWT_LIST_ROUTE: Copy to user failed!\n"); - return -EFAULT; - } - - lbs_deb_leave(LBS_DEB_IOCTL); - return 0; -} - -/** - * @brief List an entry from the FNT table - * @param priv A pointer to struct lbs_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int lbs_fwt_list_neighbor_ioctl(struct lbs_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - char in_str[8]; - static struct cmd_ds_fwt_access fwt_access; - char *ptr = in_str; - static char out_str[128]; - char *pbuf = out_str; - int ret; - - lbs_deb_enter(LBS_DEB_IOCTL); - - if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str))) - return -EFAULT; - - memset(&fwt_access, 0, sizeof(fwt_access)); - fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10)); - -#ifdef DEBUG - { - lbs_deb_ioctl("FWT_LIST_NEIGHBOR: line is %s\n", in_str); - lbs_deb_ioctl("FWT_LIST_NEIGHBOR: listing id:%i\n", le32_to_cpu(fwt_access.id)); - } -#endif - - ret = lbs_prepare_and_send_command(priv, CMD_FWT_ACCESS, - CMD_ACT_FWT_ACCESS_LIST_NEIGHBOR, - CMD_OPTION_WAITFORRSP, 0, - (void *)&fwt_access); - - if (ret == 0) { - pbuf += sprintf(pbuf, " ra "); - pbuf += eth_addr2str(fwt_access.ra, pbuf); - pbuf += sprintf(pbuf, " slp %u", fwt_access.sleepmode); - pbuf += sprintf(pbuf, " snr %u", le32_to_cpu(fwt_access.snr)); - pbuf += sprintf(pbuf, " ref %u", le32_to_cpu(fwt_access.references)); - } else - pbuf += sprintf(pbuf, " (null)"); - - wrq->u.data.length = strlen(out_str); - if (copy_to_user(wrq->u.data.pointer, (char *)out_str, - wrq->u.data.length)) { - lbs_deb_ioctl("FWT_LIST_NEIGHBOR: Copy to user failed!\n"); - return -EFAULT; - } - - lbs_deb_leave(LBS_DEB_IOCTL); - return 0; -} - -/** - * @brief Cleans up the route (FRT) and neighbor (FNT) tables - * (Garbage Collection) - * @param priv A pointer to struct lbs_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int lbs_fwt_cleanup_ioctl(struct lbs_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - static struct cmd_ds_fwt_access fwt_access; - int ret; - - lbs_deb_enter(LBS_DEB_IOCTL); - - lbs_deb_ioctl("FWT: cleaning up\n"); - - memset(&fwt_access, 0, sizeof(fwt_access)); - - ret = lbs_prepare_and_send_command(priv, CMD_FWT_ACCESS, - CMD_ACT_FWT_ACCESS_CLEANUP, - CMD_OPTION_WAITFORRSP, 0, - (void *)&fwt_access); - - if (ret == 0) - wrq->u.param.value = le32_to_cpu(fwt_access.references); - else - return -EFAULT; - - lbs_deb_leave(LBS_DEB_IOCTL); - return 0; -} - -/** - * @brief Gets firmware internal time (debug purposes) - * @param priv A pointer to struct lbs_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int lbs_fwt_time_ioctl(struct lbs_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - static struct cmd_ds_fwt_access fwt_access; - int ret; - - lbs_deb_enter(LBS_DEB_IOCTL); - - lbs_deb_ioctl("FWT: getting time\n"); - - memset(&fwt_access, 0, sizeof(fwt_access)); - - ret = lbs_prepare_and_send_command(priv, CMD_FWT_ACCESS, - CMD_ACT_FWT_ACCESS_TIME, - CMD_OPTION_WAITFORRSP, 0, - (void *)&fwt_access); - - if (ret == 0) - wrq->u.param.value = le32_to_cpu(fwt_access.references); - else - return -EFAULT; - - lbs_deb_leave(LBS_DEB_IOCTL); - return 0; -} - - -/** - * @brief Manages all mesh related ioctls - * @param priv A pointer to struct lbs_private structure - * @param req A pointer to ifreq structure - * @param cmd The command type - * @param host_subcmd The device code for the subcommand - * 0: sets a value in the firmware - * 1: retrieves an int from the firmware - * @return 0 --success, otherwise fail - */ -static int lbs_mesh_ioctl(struct lbs_private * priv, struct iwreq * wrq, - int cmd, int subcmd) -{ - struct cmd_ds_mesh_access mesh_access; - int parameter; - char str[128]; - char *ptr = str; - int ret, i; - - lbs_deb_enter(LBS_DEB_IOCTL); - - memset(&mesh_access, 0, sizeof(mesh_access)); - - if (cmd == LBS_SETONEINT_GETNONE) { - parameter = SUBCMD_DATA(wrq); - - /* Convert rate from Mbps -> firmware rate index */ - if (subcmd == CMD_ACT_MESH_SET_BCAST_RATE) - parameter = lbs_data_rate_to_fw_index(parameter); - - if (parameter < 0) - return -EINVAL; - mesh_access.data[0] = cpu_to_le32(parameter); - } else if (subcmd == CMD_ACT_MESH_SET_LINK_COSTS) { - if (copy_from_user(str, wrq->u.data.pointer, sizeof(str))) - return -EFAULT; - - for (i = 0; i < COSTS_LIST_SIZE; i++) { - mesh_access.data[i] = cpu_to_le32(simple_strtoul(ptr, &ptr, 10)); - if (!(ptr = next_param(ptr)) && i!= (COSTS_LIST_SIZE - 1)) - return -EINVAL; - } - } - - ret = lbs_mesh_access(priv, subcmd, &mesh_access); - - if (ret != 0) - return ret; - - if (cmd == LBS_SETNONE_GETONEINT) { - u32 data = le32_to_cpu(mesh_access.data[0]); - - if (subcmd == CMD_ACT_MESH_GET_BCAST_RATE) - wrq->u.param.value = lbs_fw_index_to_data_rate(data); - else - wrq->u.param.value = data; - } else if (subcmd == CMD_ACT_MESH_GET_LINK_COSTS) { - for (i = 0; i < COSTS_LIST_SIZE; i++) - ptr += sprintf (ptr, " %u", le32_to_cpu(mesh_access.data[i])); - wrq->u.data.length = strlen(str); - - if (copy_to_user(wrq->u.data.pointer, (char *)str, - wrq->u.data.length)) { - lbs_deb_ioctl("MESH_IOCTL: Copy to user failed!\n"); - ret = -EFAULT; - } - } - - lbs_deb_leave(LBS_DEB_IOCTL); - return ret; -} - -/** - * @brief Control Beacon transmissions - * @param priv A pointer to struct lbs_private structure - * @param wrq A pointer to iwreq structure - * @return 0 --success, otherwise fail - */ -static int lbs_bcn_ioctl(struct lbs_private * priv, struct iwreq *wrq) -{ - int ret; - int data[2]; - - memset(data, 0, sizeof(data)); - if (!wrq->u.data.length) { - lbs_deb_ioctl("Get Beacon control\n"); - ret = lbs_prepare_and_send_command(priv, - CMD_802_11_BEACON_CTRL, - CMD_ACT_GET, - CMD_OPTION_WAITFORRSP, 0, NULL); - data[0] = priv->beacon_enable; - data[1] = priv->beacon_period; - if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * 2)) { - lbs_deb_ioctl("Copy to user failed\n"); - return -EFAULT; - } -#define GET_TWO_INT 2 - wrq->u.data.length = GET_TWO_INT; - } else { - lbs_deb_ioctl("Set beacon control\n"); - if (wrq->u.data.length > 2) - return -EINVAL; - if (copy_from_user (data, wrq->u.data.pointer, - sizeof(int) * wrq->u.data.length)) { - lbs_deb_ioctl("Copy from user failed\n"); - return -EFAULT; - } - priv->beacon_enable = data[0]; - if (wrq->u.data.length > 1) { - if ((data[1] > MRVDRV_MAX_BEACON_INTERVAL) - || (data[1] < MRVDRV_MIN_BEACON_INTERVAL)) - return -ENOTSUPP; - priv->beacon_period= data[1]; - } - ret = lbs_prepare_and_send_command(priv, - CMD_802_11_BEACON_CTRL, - CMD_ACT_SET, - CMD_OPTION_WAITFORRSP, 0, NULL); - } - return ret; -} - -static int lbs_led_gpio_ioctl(struct lbs_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - int i, ret = 0; - int data[16]; - struct cmd_ds_802_11_led_ctrl ctrl; - struct mrvlietypes_ledgpio *gpio = (struct mrvlietypes_ledgpio *) ctrl.data; - int len = wrq->u.data.length; - - if ((len > MAX_LEDS * 2) || (len % 2 != 0)) - return -ENOTSUPP; - - memset(&ctrl, 0, sizeof(ctrl)); - if (len == 0) { - ctrl.action = cpu_to_le16(CMD_ACT_GET); - } else { - if (copy_from_user(data, wrq->u.data.pointer, sizeof(int) * len)) { - lbs_deb_ioctl("Copy from user failed\n"); - ret = -EFAULT; - goto out; - } - - ctrl.action = cpu_to_le16(CMD_ACT_SET); - ctrl.numled = cpu_to_le16(0); - gpio->header.type = cpu_to_le16(TLV_TYPE_LED_GPIO); - gpio->header.len = cpu_to_le16(len); - for (i = 0; i < len; i += 2) { - gpio->ledpin[i / 2].led = data[i]; - gpio->ledpin[i / 2].pin = data[i + 1]; - } - } - - ret = lbs_prepare_and_send_command(priv, CMD_802_11_LED_GPIO_CTRL, - 0, CMD_OPTION_WAITFORRSP, 0, (void *)&ctrl); - if (ret) { - lbs_deb_ioctl("Error doing LED GPIO control: %d\n", ret); - goto out; - } - len = le16_to_cpu(gpio->header.len); - for (i = 0; i < len; i += 2) { - data[i] = gpio->ledpin[i / 2].led; - data[i + 1] = gpio->ledpin[i / 2].pin; - } - - if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * len)) { - lbs_deb_ioctl("Copy to user failed\n"); - ret = -EFAULT; - goto out; - } - - wrq->u.data.length = len; - -out: - return ret; -} - - -static int lbs_led_bhv_ioctl(struct lbs_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - int i, ret = 0; - int data[MAX_LEDS*4]; - int firmwarestate = 0; - struct cmd_ds_802_11_led_ctrl ctrl; - struct mrvlietypes_ledbhv *bhv = (struct mrvlietypes_ledbhv *) ctrl.data; - int len = wrq->u.data.length; - - if ((len > MAX_LEDS * 4) ||(len == 0) ) - return -ENOTSUPP; - - memset(&ctrl, 0, sizeof(ctrl)); - if (copy_from_user(data, wrq->u.data.pointer, sizeof(int) * len)) { - lbs_deb_ioctl("Copy from user failed\n"); - ret = -EFAULT; - goto out; - } - if (len == 1) { - ctrl.action = cpu_to_le16(CMD_ACT_GET); - firmwarestate = data[0]; - } else { - - if (len % 4 != 0 ) - return -ENOTSUPP; - - bhv->header.type = cpu_to_le16(TLV_TYPE_LEDBEHAVIOR); - bhv->header.len = cpu_to_le16(len); - ctrl.action = cpu_to_le16(CMD_ACT_SET); - ctrl.numled = cpu_to_le16(0); - for (i = 0; i < len; i += 4) { - bhv->ledbhv[i / 4].firmwarestate = data[i]; - bhv->ledbhv[i / 4].led = data[i + 1]; - bhv->ledbhv[i / 4].ledstate = data[i + 2]; - bhv->ledbhv[i / 4].ledarg = data[i + 3]; - } - } - - ret = lbs_prepare_and_send_command(priv, CMD_802_11_LED_GPIO_CTRL, - 0, CMD_OPTION_WAITFORRSP, 0, (void *)&ctrl); - if (ret) { - lbs_deb_ioctl("Error doing LED GPIO control: %d\n", ret); - goto out; - } - - /* Get LED behavior IE, we have received gpio control as well when len - is equal to 1. */ - if (len ==1 ) { - bhv = (struct mrvlietypes_ledbhv *) - ((unsigned char *)bhv->ledbhv + le16_to_cpu(bhv->header.len)); - i = 0; - while ( i < (MAX_LEDS*4) && - (bhv->header.type != cpu_to_le16(MRVL_TERMINATE_TLV_ID)) ) { - if (bhv->ledbhv[0].firmwarestate == firmwarestate) { - data[i++] = bhv->ledbhv[0].firmwarestate; - data[i++] = bhv->ledbhv[0].led; - data[i++] = bhv->ledbhv[0].ledstate; - data[i++] = bhv->ledbhv[0].ledarg; - } - bhv++; - } - len = i; - } else { - for (i = 0; i < le16_to_cpu(bhv->header.len); i += 4) { - data[i] = bhv->ledbhv[i / 4].firmwarestate; - data[i + 1] = bhv->ledbhv[i / 4].led; - data[i + 2] = bhv->ledbhv[i / 4].ledstate; - data[i + 3] = bhv->ledbhv[i / 4].ledarg; - } - len = le16_to_cpu(bhv->header.len); - } - - if (copy_to_user(wrq->u.data.pointer, data, - sizeof(int) * len)) { - lbs_deb_ioctl("Copy to user failed\n"); - ret = -EFAULT; - goto out; - } - - wrq->u.data.length = len; - -out: - return ret; -} - -/** - * @brief ioctl function - entry point - * - * @param dev A pointer to net_device structure - * @param req A pointer to ifreq structure - * @param cmd command - * @return 0--success, otherwise fail - */ -int lbs_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) -{ - int *pdata; - int ret = 0; - struct lbs_private *priv = dev->priv; - struct iwreq *wrq = (struct iwreq *)req; - - lbs_deb_enter(LBS_DEB_IOCTL); - - lbs_deb_ioctl("lbs_do_ioctl: ioctl cmd = 0x%x\n", cmd); - switch (cmd) { - case LBS_SETNONE_GETNONE: - switch (wrq->u.data.flags) { - case LBS_SUBCMD_BT_RESET: - lbs_bt_reset_ioctl(priv); - break; - case LBS_SUBCMD_FWT_RESET: - lbs_fwt_reset_ioctl(priv); - break; - } - break; - - case LBS_SETONEINT_GETNONE: - switch (wrq->u.mode) { - case LBS_SUBCMD_SET_REGION: - ret = lbs_set_region(priv, (u16) SUBCMD_DATA(wrq)); - break; - case LBS_SUBCMD_MESH_SET_TTL: - ret = lbs_mesh_ioctl(priv, wrq, cmd, - CMD_ACT_MESH_SET_TTL); - break; - case LBS_SUBCMD_MESH_SET_BCAST_RATE: - ret = lbs_mesh_ioctl(priv, wrq, cmd, - CMD_ACT_MESH_SET_BCAST_RATE); - break; - case LBS_SUBCMD_MESH_SET_RREQ_DELAY: - ret = lbs_mesh_ioctl(priv, wrq, cmd, - CMD_ACT_MESH_SET_RREQ_DELAY); - break; - case LBS_SUBCMD_MESH_SET_ROUTE_EXP: - ret = lbs_mesh_ioctl(priv, wrq, cmd, - CMD_ACT_MESH_SET_ROUTE_EXP); - break; - case LBS_SUBCMD_BT_SET_INVERT: - ret = lbs_bt_set_invert_ioctl(priv, req); - break; - default: - ret = -EOPNOTSUPP; - break; - } - break; - - case LBS_SET128CHAR_GET128CHAR: - switch ((int)wrq->u.data.flags) { - case LBS_SUBCMD_BT_ADD: - ret = lbs_bt_add_ioctl(priv, req); - break; - case LBS_SUBCMD_BT_DEL: - ret = lbs_bt_del_ioctl(priv, req); - break; - case LBS_SUBCMD_BT_LIST: - ret = lbs_bt_list_ioctl(priv, req); - break; - case LBS_SUBCMD_FWT_ADD: - ret = lbs_fwt_add_ioctl(priv, req); - break; - case LBS_SUBCMD_FWT_DEL: - ret = lbs_fwt_del_ioctl(priv, req); - break; - case LBS_SUBCMD_FWT_LOOKUP: - ret = lbs_fwt_lookup_ioctl(priv, req); - break; - case LBS_SUBCMD_FWT_LIST_NEIGHBOR: - ret = lbs_fwt_list_neighbor_ioctl(priv, req); - break; - case LBS_SUBCMD_FWT_LIST: - ret = lbs_fwt_list_ioctl(priv, req); - break; - case LBS_SUBCMD_FWT_LIST_ROUTE: - ret = lbs_fwt_list_route_ioctl(priv, req); - break; - case LBS_SUBCMD_MESH_SET_LINK_COSTS: - ret = lbs_mesh_ioctl(priv, wrq, cmd, - CMD_ACT_MESH_SET_LINK_COSTS); - break ; - case LBS_SUBCMD_MESH_GET_LINK_COSTS: - ret = lbs_mesh_ioctl(priv, wrq, cmd, - CMD_ACT_MESH_GET_LINK_COSTS); - break; - } - break; - - case LBS_SETNONE_GETONEINT: - switch (wrq->u.mode) { - case LBS_SUBCMD_GET_REGION: - pdata = (int *)wrq->u.name; - *pdata = (int)priv->regioncode; - break; - case LBS_SUBCMD_FWT_CLEANUP: - ret = lbs_fwt_cleanup_ioctl(priv, req); - break; - case LBS_SUBCMD_FWT_TIME: - ret = lbs_fwt_time_ioctl(priv, req); - break; - case LBS_SUBCMD_MESH_GET_TTL: - ret = lbs_mesh_ioctl(priv, wrq, cmd, - CMD_ACT_MESH_GET_TTL); - break; - case LBS_SUBCMD_MESH_GET_BCAST_RATE: - ret = lbs_mesh_ioctl(priv, wrq, cmd, - CMD_ACT_MESH_GET_BCAST_RATE); - break; - case LBS_SUBCMD_MESH_GET_RREQ_DELAY: - ret = lbs_mesh_ioctl(priv, wrq, cmd, - CMD_ACT_MESH_GET_RREQ_DELAY); - break; - case LBS_SUBCMD_MESH_GET_ROUTE_EXP: - ret = lbs_mesh_ioctl(priv, wrq, cmd, - CMD_ACT_MESH_GET_ROUTE_EXP); - break; - case LBS_SUBCMD_BT_GET_INVERT: - ret = lbs_bt_get_invert_ioctl(priv, req); - break; - default: - ret = -EOPNOTSUPP; - } - break; - - case LBS_SET_GET_SIXTEEN_INT: - switch ((int)wrq->u.data.flags) { - case LBS_LED_GPIO_CTRL: - ret = lbs_led_gpio_ioctl(priv, req); - break; - case LBS_BCN_CTRL: - ret = lbs_bcn_ioctl(priv,wrq); - break; - case LBS_LED_BEHAVIOR_CTRL: - ret = lbs_led_bhv_ioctl(priv, req); - break; - } - break; - - default: - ret = -EINVAL; - break; - } - - lbs_deb_leave_args(LBS_DEB_IOCTL, "ret %d", ret); - return ret; -} |