/** @file mlanscanagent.c * * @brief This files contains mlanutl scanagent command handling. * * Copyright (C) 2008-2019, 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 */ strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); /* buffer = MRVL_CMD */ 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 */ strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); /* buffer = MRVL_CMD */ 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 */ strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); /* buffer = MRVL_CMD */ 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: \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 */ strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); /* buffer = MRVL_CMD */ 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 */ strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); /* buffer = MRVL_CMD */ 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); }