| /** @file mlanscanagent.c |
| * |
| * @brief This files contains mlanutl scanagent command handling. |
| * |
| * Copyright (C) 2008-2017, Marvell International Ltd. |
| * |
| * This software file (the "File") is distributed by Marvell International |
| * Ltd. under the terms of the GNU General Public License Version 2, June 1991 |
| * (the "License"). You may use, redistribute and/or modify this File in |
| * accordance with the terms and conditions of the License, a copy of which |
| * is available by writing to the Free Software Foundation, Inc., |
| * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the |
| * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. |
| * |
| * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE |
| * ARE EXPRESSLY DISCLAIMED. The License provides additional details about |
| * this warranty disclaimer. |
| * |
| */ |
| /************************************************************************ |
| Change log: |
| 08/11/2009: initial version |
| ************************************************************************/ |
| |
| #include "mlanutl.h" |
| #include "mlanhostcmd.h" |
| #include "mlanoffload.h" |
| #include "mlanscanagent.h" |
| |
| /******************************************************** |
| Local Variables |
| ********************************************************/ |
| |
| /******************************************************** |
| Global Variables |
| ********************************************************/ |
| |
| /******************************************************** |
| Local Functions |
| ********************************************************/ |
| |
| /** |
| * @brief scanagent configure scan table |
| * |
| * @param age_limit age limit |
| * @param hold_limit hold limit |
| * |
| * @return MLAN_STATUS_SUCCESS on success, otherwise error code |
| */ |
| static int |
| scanagent_cfg_scan_table_limits(t_u32 age_limit, t_u32 hold_limit) |
| { |
| int ret = 0; |
| struct ifreq ifr; |
| t_u8 *buffer = NULL, *pos = NULL; |
| t_u32 cmd_len = 0, cmd_header_len; |
| struct eth_priv_cmd *cmd = NULL; |
| HostCmd_DS_GEN *hostcmd = NULL; |
| HostCmd_DS_SCANAGENT_SCAN_TABLE_LIMITS *scan_table_limits = NULL; |
| |
| cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); |
| cmd_len = S_DS_GEN + sizeof(HostCmd_DS_SCANAGENT_SCAN_TABLE_LIMITS); |
| |
| buffer = (t_u8 *)malloc(BUFFER_LENGTH); |
| if (buffer == NULL) { |
| fprintf(stderr, "Cannot alloc memory\n"); |
| return -ENOMEM; |
| } |
| memset(buffer, 0, BUFFER_LENGTH); |
| |
| cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); |
| if (!cmd) { |
| printf("ERR:Cannot allocate buffer for command!\n"); |
| free(buffer); |
| return -ENOMEM; |
| } |
| |
| /* Fill up buffer */ |
| #ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT |
| memset(cmd, 0, sizeof(struct eth_priv_cmd)); |
| memcpy(&cmd->buf, &buffer, sizeof(buffer)); |
| #else |
| cmd->buf = buffer; |
| #endif |
| cmd->used_len = 0; |
| cmd->total_len = BUFFER_LENGTH; |
| |
| /* buffer = MRVL_CMD<cmd> */ |
| strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); |
| strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); |
| |
| /* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */ |
| hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); |
| hostcmd->command = cpu_to_le16(HostCmd_CMD_SCANAGENT_SCAN_TABLE_LIMITS); |
| hostcmd->size = cpu_to_le16(cmd_len); |
| hostcmd->seq_num = 0; |
| hostcmd->result = 0; |
| |
| /* Put buffer length */ |
| memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); |
| |
| /* Point after host command header */ |
| pos = (t_u8 *)hostcmd + S_DS_GEN; |
| |
| scan_table_limits = (HostCmd_DS_SCANAGENT_SCAN_TABLE_LIMITS *)pos; |
| scan_table_limits->table_age_limit = cpu_to_le16(age_limit); |
| scan_table_limits->table_hold_limit = cpu_to_le16(hold_limit); |
| |
| /* 0 set values are ignored by firmware */ |
| scan_table_limits->action = cpu_to_le16(HostCmd_ACT_GEN_SET); |
| |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); |
| ifr.ifr_ifru.ifru_data = (void *)cmd; |
| /* Perform ioctl */ |
| if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { |
| perror("ioctl[scanAgentIoctl]"); |
| printf("ERR:Command sending failed!\n"); |
| ret = -EFAULT; |
| goto done; |
| } |
| |
| printf("\nAge limit = %7d seconds\n", |
| le16_to_cpu(scan_table_limits->table_age_limit)); |
| printf("Hold limit = %7d seconds\n\n", |
| le16_to_cpu(scan_table_limits->table_hold_limit)); |
| |
| done: |
| if (buffer) |
| free(buffer); |
| if (cmd) |
| free(cmd); |
| return ret; |
| } |
| |
| /** |
| * @brief Set scanagent age limit |
| * |
| * @param argc number of arguments |
| * @param argv A pointer to arguments array |
| * |
| * @return MLAN_STATUS_SUCCESS on success, otherwise error code |
| */ |
| static int |
| scanagent_age_limit(int argc, char *argv[]) |
| { |
| t_u32 age_limit = 0; |
| |
| if (argc) { |
| age_limit = atoi(argv[0]); |
| } |
| |
| return scanagent_cfg_scan_table_limits(age_limit, 0); |
| } |
| |
| /** |
| * @brief Set scanagent hold limit |
| * |
| * @param argc number of arguments |
| * @param argv A pointer to arguments array |
| * |
| * @return MLAN_STATUS_SUCCESS on success, otherwise error code |
| */ |
| static int |
| scanagent_hold_limit(int argc, char *argv[]) |
| { |
| t_u32 hold_limit = 0; |
| |
| if (argc) { |
| hold_limit = atoi(argv[0]); |
| } |
| |
| return scanagent_cfg_scan_table_limits(0, hold_limit); |
| } |
| |
| /** |
| * @brief Set scanagent scan timing |
| * |
| * @param argc number of arguments |
| * @param argv A pointer to arguments array |
| * |
| * @return MLAN_STATUS_SUCCESS on success, otherwise error code |
| */ |
| static int |
| scanagent_timing(int argc, char *argv[]) |
| { |
| int ret = 0; |
| struct ifreq ifr; |
| int idx; |
| t_u8 *buffer = NULL, *pos = NULL; |
| t_u32 cmd_len = 0, cmd_header_len = 0, sel = 0; |
| struct eth_priv_cmd *cmd = NULL; |
| HostCmd_DS_GEN *hostcmd = NULL; |
| HostCmd_DS_SCANAGENT_CONFIG_TIMING *cfg_timing_cmd = NULL; |
| MrvlIEtypes_ConfigScanTiming_t *cfg_timing_tlv = NULL; |
| timing_sel_t sel_str[] = { {"disconnected", 1}, |
| {"adhoc", 1}, |
| {"fullpower", 1}, |
| {"ieeeps", 1}, |
| {"periodic", 1} |
| }; |
| |
| cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); |
| cmd_len = S_DS_GEN + sizeof(t_u16); |
| |
| buffer = (t_u8 *)malloc(BUFFER_LENGTH); |
| if (buffer == NULL) { |
| fprintf(stderr, "Cannot alloc memory\n"); |
| return -ENOMEM; |
| } |
| memset(buffer, 0, BUFFER_LENGTH); |
| |
| cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); |
| if (!cmd) { |
| printf("ERR:Cannot allocate buffer for command!\n"); |
| free(buffer); |
| return -ENOMEM; |
| } |
| |
| /* Fill up buffer */ |
| #ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT |
| memset(cmd, 0, sizeof(struct eth_priv_cmd)); |
| memcpy(&cmd->buf, &buffer, sizeof(buffer)); |
| #else |
| cmd->buf = buffer; |
| #endif |
| cmd->used_len = 0; |
| cmd->total_len = BUFFER_LENGTH; |
| |
| /* buffer = MRVL_CMD<cmd> */ |
| strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); |
| strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); |
| |
| /* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */ |
| hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); |
| hostcmd->command = cpu_to_le16(HostCmd_CMD_SCANAGENT_SCAN_TIMING); |
| hostcmd->seq_num = 0; |
| hostcmd->result = 0; |
| |
| /* Point after host command header */ |
| pos = (t_u8 *)hostcmd + S_DS_GEN; |
| |
| cfg_timing_cmd = (HostCmd_DS_SCANAGENT_CONFIG_TIMING *)pos; |
| cfg_timing_cmd->action = cpu_to_le16(HostCmd_ACT_GEN_GET); |
| |
| cfg_timing_tlv |
| = (MrvlIEtypes_ConfigScanTiming_t *)cfg_timing_cmd->tlv_buffer; |
| |
| if (argc == 5) { |
| cfg_timing_cmd->action = cpu_to_le16(HostCmd_ACT_GEN_SET); |
| cfg_timing_tlv->header.type = cpu_to_le16(TLV_TYPE_SCAN_TIMING); |
| cfg_timing_tlv->header.len = |
| cpu_to_le16(sizeof(MrvlIEtypes_ConfigScanTiming_t) |
| - sizeof(cfg_timing_tlv->header)); |
| |
| for (idx = 0; (unsigned int)idx < NELEMENTS(sel_str); idx++) { |
| if (strncmp(argv[0], |
| sel_str[idx].str, |
| sel_str[idx].match_len) == 0) { |
| sel = idx + 1; |
| break; |
| } |
| } |
| |
| if (idx == NELEMENTS(sel_str)) { |
| printf("Wrong argument for mode selected \"%s\"\n", |
| argv[0]); |
| ret = -EINVAL; |
| goto done; |
| } |
| |
| /* |
| * HostCmd_DS_ScanagentTimingMode_e; |
| * TIMING_MODE_INVALID = 0, |
| * TIMING_MODE_DISCONNECTED = 1, |
| * TIMING_MODE_ADHOC = 2, |
| * TIMING_MODE_FULL_POWER = 3, |
| * TIMING_MODE_IEEE_PS = 4, |
| * TIMING_MODE_PERIODIC_PS = 5, |
| */ |
| cfg_timing_tlv->mode = cpu_to_le32(sel); |
| cfg_timing_tlv->dwell = cpu_to_le32(atoi(argv[1])); |
| cfg_timing_tlv->max_off = cpu_to_le32(atoi(argv[2])); |
| cfg_timing_tlv->min_link = cpu_to_le32(atoi(argv[3])); |
| cfg_timing_tlv->rsp_timeout = cpu_to_le32(atoi(argv[4])); |
| |
| cmd_len += sizeof(MrvlIEtypes_ConfigScanTiming_t); |
| } |
| |
| hostcmd->size = cpu_to_le16(cmd_len); |
| |
| /* Put buffer length */ |
| memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); |
| |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); |
| ifr.ifr_ifru.ifru_data = (void *)cmd; |
| /* Perform ioctl */ |
| if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { |
| perror("ioctl[scanAgentIoctl]"); |
| printf("ERR:Command sending failed!\n"); |
| ret = -EFAULT; |
| goto done; |
| } |
| |
| ret = process_host_cmd_resp(HOSTCMD, buffer); |
| |
| done: |
| if (buffer) |
| free(buffer); |
| if (cmd) |
| free(cmd); |
| return ret; |
| } |
| |
| /** |
| * @brief Set scanagent profile scan period |
| * |
| * @param argc number of arguments |
| * @param argv A pointer to arguments array |
| * |
| * @return MLAN_STATUS_SUCCESS on success, otherwise error code |
| */ |
| static int |
| scanagent_profile_period(int argc, char *argv[]) |
| { |
| int ret = 0; |
| struct ifreq ifr; |
| t_u8 *buffer = NULL, *pos = NULL; |
| t_u32 cmd_len = 0, cmd_header_len = 0; |
| struct eth_priv_cmd *cmd = NULL; |
| HostCmd_DS_GEN *hostcmd = NULL; |
| HostCmd_DS_SCANAGENT_CONFIG_PROFILE_SCAN *cfg_profile_scan = NULL; |
| |
| cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); |
| cmd_len = S_DS_GEN + sizeof(HostCmd_DS_SCANAGENT_CONFIG_PROFILE_SCAN); |
| |
| buffer = (t_u8 *)malloc(BUFFER_LENGTH); |
| if (buffer == NULL) { |
| fprintf(stderr, "Cannot alloc memory\n"); |
| return -ENOMEM; |
| } |
| memset(buffer, 0, BUFFER_LENGTH); |
| |
| cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); |
| if (!cmd) { |
| printf("ERR:Cannot allocate buffer for command!\n"); |
| free(buffer); |
| return -ENOMEM; |
| } |
| |
| /* Fill up buffer */ |
| #ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT |
| memset(cmd, 0, sizeof(struct eth_priv_cmd)); |
| memcpy(&cmd->buf, &buffer, sizeof(buffer)); |
| #else |
| cmd->buf = buffer; |
| #endif |
| cmd->used_len = 0; |
| cmd->total_len = BUFFER_LENGTH; |
| |
| /* buffer = MRVL_CMD<cmd> */ |
| strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); |
| strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); |
| |
| /* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */ |
| hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); |
| hostcmd->command = |
| cpu_to_le16(HostCmd_CMD_SCANAGENT_CONFIG_PROFILE_SCAN); |
| hostcmd->size = cpu_to_le16(cmd_len); |
| hostcmd->seq_num = 0; |
| hostcmd->result = 0; |
| |
| /* Point after host command header */ |
| pos = (t_u8 *)hostcmd + S_DS_GEN; |
| |
| cfg_profile_scan = (HostCmd_DS_SCANAGENT_CONFIG_PROFILE_SCAN *)pos; |
| if (argc == 1) { |
| cfg_profile_scan->action = cpu_to_le16(HostCmd_ACT_GEN_SET); |
| cfg_profile_scan->scan_interval = cpu_to_le16(atoi(argv[0])); |
| } else { |
| cfg_profile_scan->action = cpu_to_le16(HostCmd_ACT_GEN_GET); |
| } |
| |
| /* Put buffer length */ |
| memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); |
| |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); |
| ifr.ifr_ifru.ifru_data = (void *)cmd; |
| /* Perform ioctl */ |
| if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { |
| perror("ioctl[scanAgentIoctl]"); |
| printf("ERR:Command sending failed!\n"); |
| ret = -EFAULT; |
| goto done; |
| } |
| |
| cfg_profile_scan->scan_interval = |
| le16_to_cpu(cfg_profile_scan->scan_interval); |
| if ((int)cfg_profile_scan->scan_interval == 0) |
| printf("\nProfile Scan interval: <disabled>\n\n"); |
| else |
| printf("\nProfile Scan interval: %d seconds\n\n", |
| (int)cfg_profile_scan->scan_interval); |
| |
| done: |
| if (buffer) |
| free(buffer); |
| if (cmd) |
| free(cmd); |
| return ret; |
| } |
| |
| /** |
| * @brief scanagent parse entry selection |
| * |
| * @param argc number of arguments |
| * @param argv A pointer to arguments array |
| * @param psel A pointer to scanagent entry selection |
| * |
| * @return None |
| */ |
| static void |
| scanAgentParseEntrySel(int argc, char *argv[], |
| HostCmd_DS_SCANAGENT_TABLE_MAINTENANCE *psel, |
| int *cmd_len) |
| { |
| int arg_idx, tmp_idx; |
| t_u8 *tlv_pos; |
| MrvlIEtypes_SsIdParamSet_t *ssid; |
| MrvlIEtypes_Bssid_List_t *bssid; |
| unsigned int mac[ETH_ALEN]; |
| |
| tlv_pos = (t_u8 *)psel->tlv_buffer; |
| |
| for (arg_idx = 0; arg_idx < argc; arg_idx++) { |
| if (strncmp(argv[arg_idx], "ssid=", strlen("ssid=")) == 0) { |
| ssid = (MrvlIEtypes_SsIdParamSet_t *)tlv_pos; |
| ssid->header.type = cpu_to_le16(TLV_TYPE_SSID); |
| ssid->header.len = |
| strlen(argv[arg_idx]) - strlen("ssid="); |
| strncpy((char *)ssid->ssid, |
| (argv[arg_idx] + strlen("ssid=")), |
| ssid->header.len); |
| tlv_pos += |
| ssid->header.len + sizeof(MrvlIEtypesHeader_t); |
| ssid->header.len = cpu_to_le16(ssid->header.len); |
| |
| } else if (strncmp(argv[arg_idx], "bssid=", strlen("bssid=")) == |
| 0) { |
| bssid = (MrvlIEtypes_Bssid_List_t *)tlv_pos; |
| bssid->header.type = cpu_to_le16(TLV_TYPE_BSSID); |
| bssid->header.len = ETH_ALEN; |
| /* |
| * "bssid" token string handler |
| */ |
| sscanf(argv[arg_idx] + strlen("bssid="), |
| "%2x:%2x:%2x:%2x:%2x:%2x", mac + 0, mac + 1, |
| mac + 2, mac + 3, mac + 4, mac + 5); |
| for (tmp_idx = 0; |
| (unsigned int)tmp_idx < NELEMENTS(mac); |
| tmp_idx++) { |
| bssid->bssid[tmp_idx] = (t_u8)mac[tmp_idx]; |
| } |
| tlv_pos += |
| bssid->header.len + sizeof(MrvlIEtypesHeader_t); |
| bssid->header.len = cpu_to_le16(bssid->header.len); |
| |
| } else if (strncmp(argv[arg_idx], "age=", strlen("age=")) == 0) { |
| psel->age = |
| cpu_to_le32(atoi |
| (argv[arg_idx] + strlen("age="))); |
| |
| } else if (strncmp(argv[arg_idx], "id=", strlen("id=")) == 0) { |
| psel->scan_request_id = |
| cpu_to_le32(atoi |
| (argv[arg_idx] + strlen("id="))); |
| } |
| } |
| |
| *cmd_len += (tlv_pos - psel->tlv_buffer); |
| } |
| |
| /** |
| * @brief scanagent execute scan |
| * |
| * @param argc number of arguments |
| * @param argv A pointer to arguments array |
| * |
| * @return MLAN_STATUS_SUCCESS on success, otherwise error code |
| */ |
| static int |
| scanagent_exec_scan(int argc, char *argv[]) |
| { |
| int ret = 0; |
| struct ifreq ifr; |
| int arg_idx, tmp_idx; |
| t_u32 cmd_len = 0, cmd_header_len = 0; |
| t_u8 *buffer = NULL, *pos = NULL, *tlv_pos = NULL; |
| struct eth_priv_cmd *cmd = NULL; |
| HostCmd_DS_GEN *hostcmd = NULL; |
| HostCmd_DS_SCANAGENT_SCAN_EXEC *scan_exec = NULL; |
| MrvlIEtypes_SsIdParamSet_t *ssid = NULL; |
| MrvlIEtypes_Bssid_List_t *bssid = NULL; |
| MrvlIEtypes_ConfigScanTiming_t *cfg_timing_tlv = NULL; |
| unsigned int mac[ETH_ALEN]; |
| |
| cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); |
| cmd_len = (S_DS_GEN + sizeof(HostCmd_DS_SCANAGENT_SCAN_EXEC) |
| - sizeof(scan_exec->tlv_buffer)); |
| |
| buffer = (t_u8 *)malloc(BUFFER_LENGTH); |
| if (buffer == NULL) { |
| fprintf(stderr, "Cannot alloc memory\n"); |
| return -ENOMEM; |
| } |
| memset(buffer, 0, BUFFER_LENGTH); |
| |
| cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); |
| if (!cmd) { |
| printf("ERR:Cannot allocate buffer for command!\n"); |
| free(buffer); |
| return -ENOMEM; |
| } |
| |
| /* Fill up buffer */ |
| #ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT |
| memset(cmd, 0, sizeof(struct eth_priv_cmd)); |
| memcpy(&cmd->buf, &buffer, sizeof(buffer)); |
| #else |
| cmd->buf = buffer; |
| #endif |
| cmd->used_len = 0; |
| cmd->total_len = BUFFER_LENGTH; |
| |
| /* buffer = MRVL_CMD<cmd> */ |
| strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); |
| strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); |
| |
| /* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */ |
| hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); |
| hostcmd->command = cpu_to_le16(HostCmd_CMD_SCANAGENT_SCAN_EXEC); |
| hostcmd->size = 0; |
| hostcmd->seq_num = 0; |
| hostcmd->result = 0; |
| |
| /* Point after host command header */ |
| pos = (t_u8 *)hostcmd + S_DS_GEN; |
| |
| scan_exec = (HostCmd_DS_SCANAGENT_SCAN_EXEC *)pos; |
| tlv_pos = scan_exec->tlv_buffer; |
| |
| for (arg_idx = 0; arg_idx < argc; arg_idx++) { |
| if (strncmp(argv[arg_idx], "ssid=", strlen("ssid=")) == 0) { |
| /* |
| * "ssid" token string handler |
| */ |
| ssid = (MrvlIEtypes_SsIdParamSet_t *)tlv_pos; |
| ssid->header.type = cpu_to_le16(TLV_TYPE_SSID); |
| ssid->header.len = |
| strlen(argv[arg_idx]) - strlen("ssid="); |
| strncpy((char *)ssid->ssid, |
| argv[arg_idx] + strlen("ssid="), |
| ssid->header.len); |
| tlv_pos += |
| ssid->header.len + sizeof(MrvlIEtypesHeader_t); |
| ssid->header.len = cpu_to_le16(ssid->header.len); |
| } else if (strncmp(argv[arg_idx], "bssid=", strlen("bssid=")) == |
| 0) { |
| bssid = (MrvlIEtypes_Bssid_List_t *)tlv_pos; |
| bssid->header.type = cpu_to_le16(TLV_TYPE_BSSID); |
| bssid->header.len = ETH_ALEN; |
| /* |
| * "bssid" token string handler |
| */ |
| sscanf(argv[arg_idx] + strlen("bssid="), |
| "%2x:%2x:%2x:%2x:%2x:%2x", mac + 0, mac + 1, |
| mac + 2, mac + 3, mac + 4, mac + 5); |
| for (tmp_idx = 0; |
| (unsigned int)tmp_idx < NELEMENTS(mac); |
| tmp_idx++) { |
| bssid->bssid[tmp_idx] = (t_u8)mac[tmp_idx]; |
| } |
| tlv_pos += |
| bssid->header.len + sizeof(MrvlIEtypesHeader_t); |
| bssid->header.len = cpu_to_le16(bssid->header.len); |
| } else if (strncmp(argv[arg_idx], "type=", strlen("type=")) == |
| 0) { |
| /* |
| if (strcmp(argv[arg_idx] + strlen("type="), "prof") == 0) { |
| scan_exec->scan_type = CONFIG_PROFILE; |
| } else { |
| scan_exec->scan_type = CONFIG_SITE_SURVEY; |
| } |
| */ |
| scan_exec->scan_type = CONFIG_SITE_SURVEY; |
| scan_exec->scan_type = |
| cpu_to_le16(scan_exec->scan_type); |
| } else if (strncmp(argv[arg_idx], "group=", strlen("group=")) == |
| 0) { |
| sscanf(argv[arg_idx] + strlen("group="), "0x%x", |
| &tmp_idx); |
| scan_exec->chan_group = cpu_to_le32(tmp_idx); |
| } else if (strncmp(argv[arg_idx], "delay=", strlen("delay=")) == |
| 0) { |
| /* |
| * "delay" token string handler |
| */ |
| sscanf(argv[arg_idx] + strlen("delay="), |
| "%d", (int *)&scan_exec->delay); |
| scan_exec->delay = cpu_to_le32(scan_exec->delay); |
| } else if (strncmp(argv[arg_idx], "timing=", strlen("timing=")) |
| == 0) { |
| cfg_timing_tlv = |
| (MrvlIEtypes_ConfigScanTiming_t *)tlv_pos; |
| cfg_timing_tlv->header.type = |
| cpu_to_le16(TLV_TYPE_SCAN_TIMING); |
| cfg_timing_tlv->header.len = ((sizeof(cfg_timing_tlv) |
| - |
| sizeof(cfg_timing_tlv-> |
| header))); |
| /* |
| * "timing" token string handler |
| */ |
| sscanf(argv[arg_idx] + strlen("timing="), "%d,%d,%d,%d", |
| (int *)&cfg_timing_tlv->dwell, |
| (int *)&cfg_timing_tlv->max_off, |
| (int *)&cfg_timing_tlv->min_link, |
| (int *)&cfg_timing_tlv->rsp_timeout); |
| |
| cfg_timing_tlv->mode = 0; |
| cfg_timing_tlv->dwell = |
| cpu_to_le32(cfg_timing_tlv->dwell); |
| cfg_timing_tlv->max_off = |
| cpu_to_le32(cfg_timing_tlv->max_off); |
| cfg_timing_tlv->min_link = |
| cpu_to_le32(cfg_timing_tlv->min_link); |
| cfg_timing_tlv->rsp_timeout = |
| cpu_to_le32(cfg_timing_tlv->rsp_timeout); |
| |
| tlv_pos += sizeof(MrvlIEtypesHeader_t); |
| tlv_pos += cfg_timing_tlv->header.len; |
| cfg_timing_tlv->header.len = |
| cpu_to_le16(cfg_timing_tlv->header.len); |
| } |
| } |
| |
| cmd_len += (tlv_pos - scan_exec->tlv_buffer); |
| hostcmd->size = cpu_to_le16(cmd_len); |
| |
| /* Put buffer length */ |
| memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); |
| |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); |
| ifr.ifr_ifru.ifru_data = (void *)cmd; |
| /* Perform ioctl */ |
| if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { |
| perror("ioctl[scanAgentIoctl]"); |
| printf("ERR:Command sending failed!\n"); |
| ret = -EFAULT; |
| goto done; |
| } else { |
| printf("\nScan Scheduled, ID = %d\n\n", |
| (int)le32_to_cpu(scan_exec->scan_req_id_out)); |
| } |
| |
| done: |
| if (buffer) |
| free(buffer); |
| if (cmd) |
| free(cmd); |
| return ret; |
| } |
| |
| /** |
| * @brief Issue a scanagent cmd_type subcommand |
| * |
| * @param argc number of arguments |
| * @param argv A pointer to arguments array |
| * @param cmd_type command type |
| * |
| * @return MLAN_STATUS_SUCCESS on success, otherwise error code |
| */ |
| static int |
| scanagent_table_entry_sub_cmd(int argc, char *argv[], |
| HostCmd_DS_ScanagentTableMaintenance_e cmd_type) |
| { |
| int ret = 0; |
| struct ifreq ifr; |
| t_u8 *buffer = NULL, *pos = NULL; |
| t_u32 cmd_len = 0, cmd_header_len = 0; |
| struct eth_priv_cmd *cmd = NULL; |
| HostCmd_DS_GEN *hostcmd = NULL; |
| HostCmd_DS_SCANAGENT_TABLE_MAINTENANCE *table_maintenance = NULL; |
| |
| cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); |
| cmd_len = (S_DS_GEN + sizeof(HostCmd_DS_SCANAGENT_TABLE_MAINTENANCE) |
| - sizeof(table_maintenance->tlv_buffer)); |
| |
| buffer = (t_u8 *)malloc(BUFFER_LENGTH); |
| if (buffer == NULL) { |
| fprintf(stderr, "Cannot alloc memory\n"); |
| return -ENOMEM; |
| } |
| memset(buffer, 0, BUFFER_LENGTH); |
| |
| cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); |
| if (!cmd) { |
| printf("ERR:Cannot allocate buffer for command!\n"); |
| free(buffer); |
| return -ENOMEM; |
| } |
| |
| /* Fill up buffer */ |
| #ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT |
| memset(cmd, 0, sizeof(struct eth_priv_cmd)); |
| memcpy(&cmd->buf, &buffer, sizeof(buffer)); |
| #else |
| cmd->buf = buffer; |
| #endif |
| cmd->used_len = 0; |
| cmd->total_len = BUFFER_LENGTH; |
| |
| /* buffer = MRVL_CMD<cmd> */ |
| strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); |
| strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); |
| |
| /* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */ |
| hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); |
| hostcmd->command = cpu_to_le16(HostCmd_CMD_SCANAGENT_TABLE_MAINTENANCE); |
| hostcmd->size = 0; |
| hostcmd->seq_num = 0; |
| hostcmd->result = 0; |
| |
| /* Point after host command header */ |
| pos = (t_u8 *)hostcmd + S_DS_GEN; |
| |
| table_maintenance = (HostCmd_DS_SCANAGENT_TABLE_MAINTENANCE *)pos; |
| table_maintenance->action = cpu_to_le16((t_u16)cmd_type); |
| |
| scanAgentParseEntrySel(argc, argv, table_maintenance, (int *)&cmd_len); |
| |
| hostcmd->size = cpu_to_le16(cmd_len); |
| |
| /* Put buffer length */ |
| memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); |
| |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); |
| ifr.ifr_ifru.ifru_data = (void *)cmd; |
| /* Perform ioctl */ |
| if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { |
| perror("ioctl[scanAgentIoctl]"); |
| printf("ERR:Command sending failed!\n"); |
| ret = -EFAULT; |
| goto done; |
| } |
| |
| done: |
| if (buffer) |
| free(buffer); |
| if (cmd) |
| free(cmd); |
| return ret; |
| } |
| |
| /** |
| * @brief Issue a scanagent table lock subcommand |
| * |
| * @param argc number of arguments |
| * @param argv A pointer to arguments array |
| * |
| * @return MLAN_STATUS_SUCCESS on success, otherwise error code |
| */ |
| static int |
| scanagent_table_lock(int argc, char *argv[]) |
| { |
| return scanagent_table_entry_sub_cmd(argc, argv, SCAN_TABLE_OP_LOCK); |
| } |
| |
| /** |
| * @brief Issue a scanagent table unlock subcommand |
| * |
| * @param argc number of arguments |
| * @param argv A pointer to arguments array |
| * |
| * @return MLAN_STATUS_SUCCESS on success, otherwise error code |
| */ |
| static int |
| scanagent_table_unlock(int argc, char *argv[]) |
| { |
| return scanagent_table_entry_sub_cmd(argc, argv, SCAN_TABLE_OP_UNLOCK); |
| } |
| |
| /** |
| * @brief Issue a scanagent table purge subcommand |
| * |
| * @param argc number of arguments |
| * @param argv A pointer to arguments array |
| * |
| * @return MLAN_STATUS_SUCCESS on success, otherwise error code |
| */ |
| static int |
| scanagent_table_purge(int argc, char *argv[]) |
| { |
| return scanagent_table_entry_sub_cmd(argc, argv, SCAN_TABLE_OP_PURGE); |
| } |
| |
| /** |
| * @brief Issue a scanagent command |
| * |
| * @param argc number of arguments |
| * @param argv A pointer to arguments array |
| * |
| * @return MLAN_STATUS_SUCCESS--success, otherwise--fail |
| */ |
| int |
| process_scanagent(int argc, char *argv[]) |
| { |
| sub_cmd_exec_t sub_cmd[] = { |
| {"timing", 2, 1, scanagent_timing}, |
| {"scan", 2, 1, scanagent_exec_scan}, |
| {"lock", 2, 1, scanagent_table_lock}, |
| {"unlock", 2, 1, scanagent_table_unlock}, |
| {"purge", 2, 1, scanagent_table_purge}, |
| {"profile", 2, 1, scanagent_profile_period}, |
| {"holdlimit", 2, 1, scanagent_hold_limit}, |
| {"agelimit", 2, 1, scanagent_age_limit} |
| }; |
| |
| return process_sub_cmd(sub_cmd, NELEMENTS(sub_cmd), argc, argv); |
| } |