diff options
Diffstat (limited to 'packages/dreamplug-uaputl/uaputl.c')
-rw-r--r-- | packages/dreamplug-uaputl/uaputl.c | 5565 |
1 files changed, 5565 insertions, 0 deletions
diff --git a/packages/dreamplug-uaputl/uaputl.c b/packages/dreamplug-uaputl/uaputl.c new file mode 100644 index 0000000..8337f2b --- /dev/null +++ b/packages/dreamplug-uaputl/uaputl.c @@ -0,0 +1,5565 @@ +/** @file uaputl.c + * + * @brief Program to send AP commands to the driver/firmware of the uAP + * driver. + * + * Copyright (C) 2008-2009, 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 along with the File in the gpl.txt file or by writing to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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: + 03/01/08: Initial creation +****************************************************************************/ + +/**************************************************************************** + Header files +****************************************************************************/ +#include <stdarg.h> +#include <sys/types.h> +#include <unistd.h> +#include <sys/socket.h> +#include <sys/select.h> +#include <stdio.h> +#include <getopt.h> +#include <netinet/in.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <linux/if.h> +#include <sys/ioctl.h> +#include <errno.h> +#include "uaputl.h" +#include "uapcmd.h" + +/**************************************************************************** + Definitions +****************************************************************************/ +/** Default debug level */ +int debug_level = MSG_NONE; + +/** Enable or disable debug outputs */ +#define DEBUG 1 + +/** Convert character to integer */ +#define CHAR2INT(x) (((x) >= 'A') ? ((x) - 'A' + 10) : ((x) - '0')) + +/**************************************************************************** + Global variables +****************************************************************************/ +/** Device name */ +static char dev_name[IFNAMSIZ + 1]; +/** option for cmd */ +struct option cmd_options[] = { + {"help", 0, 0, 'h'}, + {0, 0, 0, 0} +}; + +/**************************************************************************** + Local functions +****************************************************************************/ +/** + * @brief convert char to hex integer + * + * @param chr char + * @return hex integer + */ +unsigned char +hexc2bin(char chr) +{ + if (chr >= '0' && chr <= '9') + chr -= '0'; + else if (chr >= 'A' && chr <= 'F') + chr -= ('A' - 10); + else if (chr >= 'a' && chr <= 'f') + chr -= ('a' - 10); + + return chr; +} + +/** + * @brief check protocol is valid or not + * + * @param protocol protocol + * + * @return UAP_SUCCESS or UAP_FAILURE + */ +int +is_protocol_valid(int protocol) +{ + int ret = UAP_FAILURE; + switch (protocol) { + case PROTOCOL_NO_SECURITY: + case PROTOCOL_STATIC_WEP: + case PROTOCOL_WPA: + case PROTOCOL_WPA2: + case PROTOCOL_WPA2_MIXED: + ret = UAP_SUCCESS; + break; + default: + printf("ERR: Invalid Protocol: %d\n", protocol); + break; + } + return ret; +} + +/** + * @brief Function to check valid rate + * + * + * @param rate rate to verify + * + * return UAP_SUCCESS or UAP_FAILURE + **/ +int +is_rate_valid(int rate) +{ + int ret = UAP_SUCCESS; + switch (rate) { + case 2: + case 4: + case 11: + case 22: + case 12: + case 18: + case 24: + case 48: + case 72: + case 96: + case 108: + case 36: + break; + default: + ret = UAP_FAILURE; + break; + } + return ret; +} + +/** + * @brief detects duplicates rate in array of strings + * Note that 0x82 and 0x2 are same for rate + * + * @param argc number of elements + * @param argv array of strings + * @return UAP_FAILURE or UAP_SUCCESS + */ +inline int +has_dup_rate(int argc, char *argv[]) +{ + int i, j; + /* Check for duplicate */ + for (i = 0; i < (argc - 1); i++) { + for (j = i + 1; j < argc; j++) { + if ((A2HEXDECIMAL(argv[i]) & ~BASIC_RATE_SET_BIT) == + (A2HEXDECIMAL(argv[j]) & ~BASIC_RATE_SET_BIT)) { + return UAP_FAILURE; + } + } + } + return UAP_SUCCESS; +} + +/** + * @brief Check for mandatory rates + * + * + * 2, 4, 11, 22 must be present + * + * 6 12 and 24 must be present for ofdm + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return UAP_FAILURE or UAP_SUCCESS + * + */ +int +check_mandatory_rates(int argc, char **argv) +{ + int i; + int tmp; + u32 rate_bitmap = 0; + int ofdm_enable = 0; +#define BITMAP_RATE_1M 0x01 +#define BITMAP_RATE_2M 0x02 +#define BITMAP_RATE_5_5M 0x04 +#define BITMAP_RATE_11M 0x8 +#define B_RATE_MANDATORY 0x0f +#define BITMAP_RATE_6M 0x10 +#define BITMAP_RATE_12M 0x20 +#define BITMAP_RATE_24M 0x40 +#define G_RATE_MANDATORY 0x70 + for (i = 0; i < argc; i++) { + tmp = (A2HEXDECIMAL(argv[i]) & ~BASIC_RATE_SET_BIT); + switch (tmp) { + case 2: + rate_bitmap |= BITMAP_RATE_1M; + break; + case 4: + rate_bitmap |= BITMAP_RATE_2M; + break; + case 11: + rate_bitmap |= BITMAP_RATE_5_5M; + break; + case 22: + rate_bitmap |= BITMAP_RATE_11M; + break; + case 12: + ofdm_enable = 1; + rate_bitmap |= BITMAP_RATE_6M; + break; + case 24: + ofdm_enable = 1; + rate_bitmap |= BITMAP_RATE_12M; + break; + case 48: + ofdm_enable = 1; + rate_bitmap |= BITMAP_RATE_24M; + break; + case 18: + case 36: + case 72: + case 96: + case 108: + ofdm_enable = 1; + break; + } + } + if ((rate_bitmap & B_RATE_MANDATORY) != B_RATE_MANDATORY) { + printf("Basic Rates 2, 4, 11 and 22 (500K units) \n" + "must be present in basic or non-basic rates\n"); + return UAP_FAILURE; + } + if (ofdm_enable && ((rate_bitmap & G_RATE_MANDATORY) != G_RATE_MANDATORY)) { + printf("OFDM Rates 12, 24 and 48 ( 500Kb units)\n" + "must be present in basic or non-basic rates\n"); + return UAP_FAILURE; + } + return UAP_SUCCESS; +} + +/** + * @brief detects duplicates channel in array of strings + * + * @param argc number of elements + * @param argv array of strings + * @return UAP_FAILURE or UAP_SUCCESS + */ +inline int +has_dup_channel(int argc, char *argv[]) +{ + int i, j; + /* Check for duplicate */ + for (i = 0; i < (argc - 1); i++) { + for (j = i + 1; j < argc; j++) { + if (atoi(argv[i]) == atoi(argv[j])) { + return UAP_FAILURE; + } + } + } + return UAP_SUCCESS; +} + +/** + * @brief convert string to hex integer + * + * @param s A pointer string buffer + * @return hex integer + */ +unsigned int +a2hex(char *s) +{ + unsigned int val = 0; + if (!strncasecmp("0x", s, 2)) { + s += 2; + } + while (*s && isxdigit(*s)) { + val = (val << 4) + hexc2bin(*s++); + } + return val; +} + +/** + * @brief Dump hex data + * + * @param prompt A pointer prompt buffer + * @param p A pointer to data buffer + * @param len the len of data buffer + * @param delim delim char + * @return None + */ +void +hexdump_data(char *prompt, void *p, int len, char delim) +{ + int i; + unsigned char *s = p; + + if (prompt) { + printf("%s: len=%d\n", prompt, (int) len); + } + for (i = 0; i < len; i++) { + if (i != len - 1) + printf("%02x%c", *s++, delim); + else + printf("%02x\n", *s); + if ((i + 1) % 16 == 0) + printf("\n"); + } + printf("\n"); +} + +#if DEBUG +/** + * @brief conditional printf + * + * @param level severity level of the message + * @param fmt printf format string, followed by optional arguments + */ +void +uap_printf(int level, char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + if (level <= debug_level) { + vprintf(fmt, ap); + } + va_end(ap); +} + +/** + * @brief Dump hex data + * + * @param prompt A pointer prompt buffer + * @param p A pointer to data buffer + * @param len the len of data buffer + * @param delim delim char + * @return None + */ +void +hexdump(char *prompt, void *p, int len, char delim) +{ + if (debug_level < MSG_ALL) + return; + hexdump_data(prompt, p, len, delim); +} +#endif + +/** + * @brief Hex to number + * + * @param c Hex value + * @return Integer value or -1 + */ +int +hex2num(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; +} + +/** + * @brief Show usage information for the sys_info command + * + * $return N/A + */ +void +print_sys_info_usage(void) +{ + printf("\nUsage : sys_info\n"); + return; +} + +/** + * @brief Parse domain file for country information + * + * @param country Country name + * @param sub_bands band information + * @return number of band/ UAP_FAILURE + */ +u8 +parse_domain_file(char *country, IEEEtypes_SubbandSet_t * sub_bands) +{ + FILE *fp; + char str[64]; + char domain_name[40]; + int cflag = 0; + int dflag = 0; + int found = 0; + int j = -1, reset_j = 0; + u8 no_of_sub_band = 0; + char third; + char country2[3]; + + fp = fopen("80211d_domain.conf", "r"); + if (fp == NULL) { + printf("File opening Error\n"); + return UAP_FAILURE; + } + + strncpy((char *) country2, country, 2); + country2[2] = '\0'; + third = country[2]; + + /** + * Search specific domain name + */ + while (!feof(fp)) { + fscanf(fp, "%s", str); + if (cflag) { + strcpy(domain_name, str); + cflag = 0; + } + if (!strcmp(str, "COUNTRY:")) { + /** store next string to domain_name */ + cflag = 1; + } + + if (!strcmp(str, country2)) { + /** Country is matched ;)*/ + if (third && !((third == 'I') || (third == 'O') || (third == ' '))) + found = 0; + else + found = 1; + break; + } + } + + if (!found) { + printf("No match found for Country = %s in the 80211d_domain.conf \n", + country); + fclose(fp); + found = 0; + return UAP_FAILURE; + } + + /** + * Search domain specific information + */ + while (!feof(fp)) { + fscanf(fp, "%s", str); + + if (feof(fp) || (dflag && !strcmp(str, "DOMAIN:"))) { + break; + } + + if (dflag) { + j++; + if (strchr(str, ',')) + reset_j = 1; + + strcpy(str, strtok(str, ", ")); + + if (str == NULL) { + if (reset_j) { + j = -1; + reset_j = 0; + } + continue; + } + + if (IS_HEX_OR_DIGIT(str) == UAP_FAILURE) { + printf("ERR: Only Number values are allowed\n"); + fclose(fp); + return UAP_FAILURE; + } + + switch (j) { + case 0: + sub_bands[no_of_sub_band].FirstChan = (u8) A2HEXDECIMAL(str); + break; + case 1: + sub_bands[no_of_sub_band].NoOfChan = (u8) A2HEXDECIMAL(str); + break; + case 2: + sub_bands[no_of_sub_band++].MaxTxPwr = (u8) A2HEXDECIMAL(str); + break; + default: + printf("ERR: Incorrect 80211d_domain.conf file\n"); + fclose(fp); + return UAP_FAILURE; + } + + if (reset_j) { + j = -1; + reset_j = 0; + } + } + + if (cflag && !strcmp(str, domain_name)) { + /* Followed will be the band details */ + cflag = 0; + dflag = 1; + } + if (!dflag && !strcmp(str, "DOMAIN:")) { + cflag = 1; + } + } + fclose(fp); + return (no_of_sub_band); + +} + +/** + * + * @brief Set/Get SNMP MIB + * + * @param action 0-GET 1-SET + * @param oid oid + * @param size size of oid value + * @param oid_buf oid value + * @return UAP_FAILURE or UAP_SUCCESS + * + */ +int +sg_snmp_mib(u16 action, u16 oid, u16 size, u8 * oid_buf) +{ + APCMDBUF_SNMP_MIB *cmd_buf = NULL; + TLVBUF_HEADER *tlv = NULL; + int ret = UAP_FAILURE; + u8 *buf = NULL; + u16 buf_len; + u16 cmd_len; + int i; + + buf_len = sizeof(APCMDBUF_SNMP_MIB) + sizeof(TLVBUF_HEADER) + size; + buf = (u8 *) malloc(buf_len); + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + return ret; + } + bzero((char *) buf, buf_len); + + /* Locate Headers */ + cmd_buf = (APCMDBUF_SNMP_MIB *) buf; + tlv = (TLVBUF_HEADER *) (buf + sizeof(APCMDBUF_SNMP_MIB)); + cmd_buf->Size = buf_len - BUF_HEADER_SIZE; + cmd_buf->Result = 0; + cmd_buf->SeqNum = 0; + cmd_buf->CmdCode = HostCmd_SNMP_MIB; + + tlv->Type = uap_cpu_to_le16(oid); + tlv->Len = uap_cpu_to_le16(size); + for (i = 0; action && (i < size); i++) { + tlv->Data[i] = oid_buf[i]; + } + + cmd_buf->Action = uap_cpu_to_le16(action); + cmd_len = buf_len; + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + if (ret == UAP_SUCCESS) { + if (cmd_buf->Result == CMD_SUCCESS) { + if (!action) { + /** Reloacte the headers */ + tlv = + (TLVBUF_HEADER *) ((u8 *) cmd_buf + + sizeof(APCMDBUF_SNMP_MIB)); + for (i = 0; i < MIN(uap_le16_to_cpu(tlv->Len), size); i++) { + oid_buf[i] = tlv->Data[i]; + } + } + ret = UAP_SUCCESS; + } else { + printf("ERR:Command Response incorrect!\n"); + ret = UAP_FAILURE; + } + } else { + printf("ERR:Command sending failed!\n"); + } + free(buf); + return ret; +} + +/** + * @brief Creates a sys_info request and sends to the driver + * + * Usage: "sys_info" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_info(int argc, char *argv[]) +{ + APCMDBUF_SYS_INFO_REQUEST *cmd_buf = NULL; + APCMDBUF_SYS_INFO_RESPONSE *response_buf = NULL; + u8 *buf = NULL; + u16 cmd_len; + u16 buf_len; + int ret = UAP_FAILURE; + int opt; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_info_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc != 0) { + printf("ERR:Too many arguments.\n"); + print_sys_info_usage(); + return; + } + + buf_len = + (sizeof(APCMDBUF_SYS_INFO_REQUEST) >= + sizeof(APCMDBUF_SYS_INFO_RESPONSE)) ? sizeof(APCMDBUF_SYS_INFO_REQUEST) + : sizeof(APCMDBUF_SYS_INFO_RESPONSE); + + /* alloc buf for command */ + buf = (u8 *) malloc(buf_len); + + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + return; + } + bzero((char *) buf, buf_len); + + /* Locate headers */ + cmd_len = sizeof(APCMDBUF_SYS_INFO_REQUEST); + cmd_buf = (APCMDBUF_SYS_INFO_REQUEST *) buf; + response_buf = (APCMDBUF_SYS_INFO_RESPONSE *) buf; + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_INFO; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (response_buf->CmdCode != (APCMD_SYS_INFO | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response!\n"); + free(buf); + return; + } + /* Print response */ + if (response_buf->Result == CMD_SUCCESS) { + printf("System information = %s\n", response_buf->SysInfo); + } else { + printf("ERR:Could not retrieve system information!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + + free(buf); + return; +} + +/** + * @brief Show usage information for the powermode command + * + * $return N/A + */ +void +print_power_mode_usage(void) +{ + printf + ("\nUsage : powermode [MODE] [SLEEP_PARAM=1 CTRL MIN_SLEEP MAX_SLEEP]"); + printf("\n [INACT_PARAM=2 INACTTO MIN_AWAKE MAX_AWAKE]"); + printf("\nOptions: MODE : 0 - disable power mode"); + printf("\n 1 - periodic DTIM power save mode"); + printf("\n 2 - inactivity based power save mode"); + printf("\n SLEEP_PARAM:"); + printf + ("\n CTRL: 0 - disable CTS2Self protection frame Tx before PS"); + printf + ("\n 1 - enable CTS2Self protection frame Tx before PS"); + printf("\n MIN_SLEEP: Minimum sleep duration in microseconds"); + printf("\n MAX_SLEEP: Maximum sleep duration in miroseconds"); + printf("\n INACT_PARAM: (only for inactivity based power save mode)"); + printf("\n INACTTO: Inactivity timeout in miroseconds"); + printf("\n MIN_AWAKE: Minimum awake duration in microseconds"); + printf("\n MAX_AWAKE: Maximum awake duration in microseconds"); + printf("\n empty - get current power mode\n"); + return; +} + +/** + * @brief Set/get power mode + * + * @param pm A pointer to ps_mgmt structure + * @return N/A + */ +void +send_power_mode_ioctl(ps_mgmt * pm) +{ + struct ifreq ifr; + s32 sockfd; + + /* Open socket */ + if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + printf("ERR:Cannot open socket\n"); + return; + } + /* 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 *) pm; + /* Perform ioctl */ + errno = 0; + if (ioctl(sockfd, UAP_POWER_MODE, &ifr)) { + perror(""); + printf("ERR:UAP_POWER_MODE is not supported by %s\n", dev_name); + return; + } + switch (pm->ps_mode) { + case 0: + printf("power mode = Disabled\n"); + break; + case 1: + printf("power mode = Periodic DTIM PS\n"); + break; + case 2: + printf("power mode = Inactivity based PS \n"); + break; + } + if (pm->flags & PS_FLAG_SLEEP_PARAM) { + printf("Sleep param:\n"); + printf("\tctrl_bitmap=%d\n", (int) pm->sleep_param.ctrl_bitmap); + printf("\tmin_sleep=%d us\n", (int) pm->sleep_param.min_sleep); + printf("\tmax_sleep=%d us\n", (int) pm->sleep_param.max_sleep); + } + if (pm->flags & PS_FLAG_INACT_SLEEP_PARAM) { + printf("Inactivity sleep param:\n"); + printf("\tinactivity_to=%d us\n", (int) pm->inact_param.inactivity_to); + printf("\tmin_awake=%d us\n", (int) pm->inact_param.min_awake); + printf("\tmax_awake=%d us\n", (int) pm->inact_param.max_awake); + } + /* Close socket */ + close(sockfd); + return; +} + +/** + * @brief Creates power mode request and send to driver + * and sends to the driver + * + * Usage: "Usage : powermode [MODE]" + * + * Options: MODE : 0 - disable power mode + * 1 - enable power mode + * 2 - get current power mode + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_power_mode(int argc, char *argv[]) +{ + int opt; + ps_mgmt pm; + int type = 0; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_power_mode_usage(); + return; + } + } + argc -= optind; + argv += optind; + + memset(&pm, 0, sizeof(ps_mgmt)); + /* Check arguments */ + if ((argc > 9) || + ((argc != 0) && (argc != 1) && (argc != 5) && (argc != 9))) { + printf("ERR:wrong arguments.\n"); + print_power_mode_usage(); + return; + } + + if (argc) { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || + (atoi(argv[0]) > 2)) { + printf + ("ERR:Illegal power mode %s. Must be either '0' '1' or '2'.\n", + argv[0]); + print_power_mode_usage(); + return; + } + pm.flags = PS_FLAG_PS_MODE; + pm.ps_mode = atoi(argv[0]); + if ((pm.ps_mode == PS_MODE_DISABLE) && (argc > 1)) { + printf("ERR: Illegal parameter for disable power mode\n"); + print_power_mode_usage(); + return; + } + if ((pm.ps_mode != PS_MODE_INACTIVITY) && (argc > 5)) { + printf("ERR: Illegal parameter\n"); + print_power_mode_usage(); + return; + } + if (argc >= 5) { + if ((ISDIGIT(argv[1]) == 0) || (atoi(argv[1]) < 1) || + (atoi(argv[1]) > 2)) { + printf + ("ERR:Illegal parameter type %s. Must be either '1' or '2'.\n", + argv[1]); + print_power_mode_usage(); + return; + } + type = atoi(argv[1]); + if ((type == INACTIVITY_SLEEP_PARAMETER) && + (pm.ps_mode != PS_MODE_INACTIVITY)) { + printf + ("ERR: inactivity sleep parameter only valid for inactivity power save mode\n"); + print_power_mode_usage(); + return; + } + if (type == SLEEP_PARAMETER) { + if ((ISDIGIT(argv[2]) == 0) || (atoi(argv[2]) < 0) || + (atoi(argv[2]) > 1)) { + printf + ("ERR:Illegal ctrl bitmap = %s. Must be either '0' or '1'.\n", + argv[2]); + print_power_mode_usage(); + return; + } + pm.flags |= PS_FLAG_SLEEP_PARAM; + pm.sleep_param.ctrl_bitmap = atoi(argv[2]); + if ((ISDIGIT(argv[3]) == 0) || (ISDIGIT(argv[4]) == 0)) { + printf("ERR:Illegal parameter\n"); + print_power_mode_usage(); + return; + } + pm.sleep_param.min_sleep = atoi(argv[3]); + pm.sleep_param.max_sleep = atoi(argv[4]); + if (pm.sleep_param.min_sleep > pm.sleep_param.max_sleep) { + printf + ("ERR: MIN_SLEEP value should be less than or equal to MAX_SLEEP\n"); + return; + } + if (pm.sleep_param.min_sleep < PS_SLEEP_PARAM_MIN || + ((pm.sleep_param.max_sleep > PS_SLEEP_PARAM_MAX) && + pm.sleep_param.ctrl_bitmap)) { + printf + ("ERR: Incorrect value of sleep period. Please check README\n"); + return; + } + } else { + if ((ISDIGIT(argv[2]) == 0) || (ISDIGIT(argv[3]) == 0) || + (ISDIGIT(argv[4]) == 0)) { + printf("ERR:Illegal parameter\n"); + print_power_mode_usage(); + return; + } + pm.flags |= PS_FLAG_INACT_SLEEP_PARAM; + pm.inact_param.inactivity_to = atoi(argv[2]); + pm.inact_param.min_awake = atoi(argv[3]); + pm.inact_param.max_awake = atoi(argv[4]); + if (pm.inact_param.min_awake > pm.inact_param.max_awake) { + printf + ("ERR: MIN_AWAKE value should be less than or equal to MAX_AWAKE\n"); + return; + } + if (pm.inact_param.min_awake < PS_AWAKE_PERIOD_MIN) { + printf("ERR: Incorrect value of MIN_AWAKE period.\n"); + return; + } + } + } + if (argc == 9) { + if ((ISDIGIT(argv[5]) == 0) || (atoi(argv[5]) < 1) || + (atoi(argv[5]) > 2)) { + printf + ("ERR:Illegal parameter type %s. Must be either '1' or '2'.\n", + argv[5]); + print_power_mode_usage(); + return; + } + if (type == atoi(argv[5])) { + printf("ERR: Duplicate parameter type %s.\n", argv[5]); + print_power_mode_usage(); + return; + } + type = atoi(argv[5]); + if (type == SLEEP_PARAMETER) { + if ((ISDIGIT(argv[6]) == 0) || (atoi(argv[6]) < 0) || + (atoi(argv[6]) > 1)) { + printf + ("ERR:Illegal ctrl bitmap = %s. Must be either '0' or '1'.\n", + argv[6]); + print_power_mode_usage(); + return; + } + pm.flags |= PS_FLAG_SLEEP_PARAM; + pm.sleep_param.ctrl_bitmap = atoi(argv[6]); + if ((ISDIGIT(argv[7]) == 0) || (ISDIGIT(argv[8]) == 0)) { + printf("ERR:Illegal parameter\n"); + print_power_mode_usage(); + return; + } + pm.sleep_param.min_sleep = atoi(argv[7]); + pm.sleep_param.max_sleep = atoi(argv[8]); + if (pm.sleep_param.min_sleep > pm.sleep_param.max_sleep) { + printf + ("ERR: MIN_SLEEP value should be less than or equal to MAX_SLEEP\n"); + return; + } + if (pm.sleep_param.min_sleep < PS_SLEEP_PARAM_MIN || + ((pm.sleep_param.max_sleep > PS_SLEEP_PARAM_MAX) && + pm.sleep_param.ctrl_bitmap)) { + printf + ("ERR: Incorrect value of sleep period. Please check README\n"); + return; + } + } else { + if ((ISDIGIT(argv[6]) == 0) || (ISDIGIT(argv[7]) == 0) || + (ISDIGIT(argv[8]) == 0)) { + printf("ERR:Illegal parameter\n"); + print_power_mode_usage(); + return; + } + pm.flags |= PS_FLAG_INACT_SLEEP_PARAM; + pm.inact_param.inactivity_to = atoi(argv[6]); + pm.inact_param.min_awake = atoi(argv[7]); + pm.inact_param.max_awake = atoi(argv[8]); + if (pm.inact_param.min_awake > pm.inact_param.max_awake) { + printf + ("ERR: MIN_AWAKE value should be less than or equal to MAX_AWAKE\n"); + return; + } + if (pm.inact_param.min_awake < PS_AWAKE_PERIOD_MIN) { + printf("ERR: Incorrect value of MIN_AWAKE period.\n"); + return; + } + } + } + } + send_power_mode_ioctl(&pm); + return; +} + +/** + * @brief Show usage information for the sys_reset command + * + * $return N/A + */ +void +print_sys_reset_usage(void) +{ + printf("\nUsage : sys_reset\n"); + return; +} + +/** + * @brief Creates a sys_reset request and sends to the driver + * + * Usage: "sys_reset" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_reset(int argc, char *argv[]) +{ + APCMDBUF_SYS_RESET *cmd_buf = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + ps_mgmt pm; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_reset_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc != 0) { + printf("ERR:Too many arguments.\n"); + print_sys_reset_usage(); + return; + } + + memset(&pm, 0, sizeof(ps_mgmt)); + pm.flags = PS_FLAG_PS_MODE; + pm.ps_mode = PS_MODE_DISABLE; + send_power_mode_ioctl(&pm); + + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_RESET); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_RESET *) buffer; + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_RESET; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (cmd_buf->CmdCode != (APCMD_SYS_RESET | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response!\n"); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + printf("System reset successful!\n"); + } else { + printf("ERR:Could not reset system!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Show usage information for the bss_start command + * + * $return N/A + */ +void +print_bss_start_usage(void) +{ + printf("\nUsage : bss_start\n"); + return; +} + +/** + * @brief Creates a BSS start request and sends to the driver + * + * Usage: "bss_start" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_bss_start(int argc, char *argv[]) +{ + APCMDBUF_BSS_START *cmd_buf = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_bss_start_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc != 0) { + printf("ERR:Too many arguments.\n"); + print_bss_start_usage(); + return; + } + + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_BSS_START); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_BSS_START *) buffer; + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_BSS_START; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (cmd_buf->CmdCode != (APCMD_BSS_START | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response!\n"); + free(buffer); + return; + } + + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + printf("BSS started!\n"); + } else if (cmd_buf->Result == BSS_FAILURE_START_INVAL) { + printf("ERR:Could not start BSS! Invalid BSS parameters.\n"); + } else if (cmd_buf->Result == BSS_FAILURE_START_REDUNDANT) { + printf("ERR:Could not start BSS! BSS already started.\n"); + } else { + printf("ERR:Could not start BSS!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Show usage information for the bss_stop command + * + * $return N/A + */ +void +print_bss_stop_usage(void) +{ + printf("\nUsage : bss_stop\n"); + return; +} + +/** + * @brief Creates a BSS stop request and sends to the driver + * + * Usage: "bss_stop" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_bss_stop(int argc, char *argv[]) +{ + APCMDBUF_BSS_STOP *cmd_buf = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_bss_stop_usage(); + return; + } + } + argc -= optind; + argv += optind; /* Check arguments */ + + if (argc != 0) { + printf("ERR:Too many arguments.\n"); + print_bss_stop_usage(); + } + + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_BSS_STOP); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_BSS_STOP *) buffer; + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_BSS_STOP; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (cmd_buf->CmdCode != (APCMD_BSS_STOP | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response!\n"); + free(buffer); + return; + } + + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + printf("BSS stopped!\n"); + } else if (cmd_buf->Result == BSS_FAILURE_STOP_REDUNDANT) { + printf("ERR:Could not stop BSS! BSS already stopped.\n"); + } else if (cmd_buf->Result == BSS_FAILURE_STOP_INVAL) { + printf("ERR:Could not stop BSS! No active BSS.\n"); + } else { + printf("ERR:Could not stop BSS!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Show usage information for the sta_list command + * + * $return N/A + */ +void +print_sta_list_usage(void) +{ + printf("\nUsage : sta_list\n"); + return; +} + +/** + * @brief Creates a STA list request and sends to the driver + * + * Usage: "sta_list" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sta_list(int argc, char *argv[]) +{ + APCMDBUF_STA_LIST_REQUEST *cmd_buf = NULL; + APCMDBUF_STA_LIST_RESPONSE *response_buf = NULL; + u8 *buf = NULL; + u16 buf_len; + TLVBUF_STA_INFO *tlv = NULL; + u16 cmd_len; + u16 response_len; + int ret = UAP_FAILURE; + int i = 0; + int opt; + int rssi = 0; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sta_list_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc != 0) { + printf("ERR:Too many arguments.\n"); + print_sta_list_usage(); + return; + } + response_len = + sizeof(APCMDBUF_STA_LIST_RESPONSE) + + (MAX_NUM_CLIENTS * sizeof(TLVBUF_STA_INFO)); + if (response_len > sizeof(APCMDBUF_STA_LIST_REQUEST)) + buf_len = response_len; + else + buf_len = sizeof(APCMDBUF_STA_LIST_REQUEST); + + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_STA_LIST_REQUEST); + + /* Initialize the command buffer */ + buf = (u8 *) malloc(buf_len); + + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + return; + } + bzero((char *) buf, buf_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_STA_LIST_REQUEST *) buf; + response_buf = (APCMDBUF_STA_LIST_RESPONSE *) buf; + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_STA_LIST; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + response_buf->StaCount = uap_le16_to_cpu(response_buf->StaCount); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (response_buf->CmdCode != (APCMD_STA_LIST | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response!\n"); + free(buf); + return; + } + + /* Print response */ + if (response_buf->Result == CMD_SUCCESS) { + printf("Number of STA = %d\n\n", response_buf->StaCount); + for (i = 0; i < response_buf->StaCount; i++) { + tlv = (TLVBUF_STA_INFO *) (&response_buf->StaList[i]); + endian_convert_tlv_header_in(tlv); + if (tlv) { + if (tlv->Tag != MRVL_STA_INFO_TLV_ID) { + printf("STA %d information corrupted.\n", i + 1); + continue; + } + printf("STA %d information:\n", i + 1); + printf("=====================\n"); + printf("MAC Address: "); + print_mac(tlv->MacAddress); + printf("\nPower mfg status: %s\n", + (tlv->PowerMfgStatus == + 0) ? "active" : "power save"); + /** On some platform, s8 is same as unsigned char*/ + rssi = (int) tlv->Rssi; + if (rssi > 0x7f) + rssi = -(256 - rssi); + printf("Rssi : %d dBm\n\n", rssi); + } else { + printf("ERR:Unable to find information for STA %d\n\n", + i + 1); + } + } + } else { + printf("ERR:Could not get STA list!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + free(buf); + return; +} + +/** + * @brief Show usage information for the sta_deauth command + * + * $return N/A + */ +void +print_sta_deauth_usage(void) +{ + printf("\nUsage : sta_deauth <STA_MAC_ADDRESS> [REASON_CODE]\n"); + return; +} + +/** + * @brief Creates a STA deauth request and sends to the driver + * + * Usage: "sta_deauth <STA_MAC_ADDRESS>" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sta_deauth(int argc, char *argv[]) +{ + APCMDBUF_STA_DEAUTH *cmd_buf = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sta_deauth_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc != 1 && argc != 2) { + printf("ERR:wrong arguments! Must provide STA_MAC_ADDRESS.\n"); + printf("\t\t with optional REASON_CODE.\n"); + print_sta_deauth_usage(); + return; + } + + /* Check Reason Code */ + if (argc == 2) { + if (IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE) { + printf("ERR: Invalid input for reason code\n"); + print_sta_deauth_usage(); + return; + } + } + + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_STA_DEAUTH); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_STA_DEAUTH *) buffer; + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_STA_DEAUTH; + cmd_buf->Size = cmd_len - BUF_HEADER_SIZE; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + if ((ret = mac2raw(argv[0], cmd_buf->StaMacAddress)) != UAP_SUCCESS) { + printf("ERR: %s Address\n", ret == UAP_FAILURE ? "Invalid MAC" : + ret == UAP_RET_MAC_BROADCAST ? "Broadcast" : "Multicast"); + free(buffer); + return; + } + if (argc == 2) { + cmd_buf->ReasonCode = uap_cpu_to_le16((u16) A2HEXDECIMAL(argv[1])); + } + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (cmd_buf->CmdCode != (APCMD_STA_DEAUTH | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response!\n"); + free(buffer); + return; + } + + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + printf("Deauthentication successful!\n"); + } else { + printf("ERR:Deauthentication unsuccessful!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Show usage information for the coex_config command + * + * $return N/A + */ +void +print_coex_config_usage(void) +{ + printf("\nUsage : coex_config [CONFIG_FILE]\n"); + printf + ("\nIf CONFIG_FILE is provided, a 'set' is performed, else a 'get' is performed.\n"); + return; +} + +/** + * @brief Creates a coex_config request and sends to the driver + * + * Usage: "Usage : coex_config [CONFIG_FILE]" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return UAP_SUCCESS or UAP_FAILURE + */ +void +apcmd_coex_config(int argc, char *argv[]) +{ + apcmdbuf_coex_config *cmd_buf = NULL; + tlvbuf_coex_common_cfg *coex_common_tlv; + tlvbuf_coex_sco_cfg *coex_sco_tlv; + tlvbuf_coex_acl_cfg *coex_acl_tlv; + tlvbuf_coex_stats *coex_stats_tlv; + u8 *buf = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_coex_config_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc > 1) { + printf("ERR:Too many arguments.\n"); + print_coex_config_usage(); + return; + } + if (argc == 1) { + /* Read profile and send command to firmware */ + apcmd_coex_config_profile(argc, argv); + return; + } + + /* fixed command length */ + cmd_len = sizeof(apcmdbuf_coex_config) + sizeof(tlvbuf_coex_common_cfg) + + sizeof(tlvbuf_coex_sco_cfg) + sizeof(tlvbuf_coex_acl_cfg) + + sizeof(tlvbuf_coex_stats); + /* alloc buf for command */ + buf = (u8 *) malloc(cmd_len); + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + return; + } + bzero((char *) buf, cmd_len); + + cmd_buf = (apcmdbuf_coex_config *) buf; + + coex_common_tlv = (tlvbuf_coex_common_cfg *) cmd_buf->tlv_buffer; + coex_common_tlv->Tag = MRVL_BT_COEX_COMMON_CFG_TLV_ID; + coex_common_tlv->Length = + sizeof(tlvbuf_coex_common_cfg) - sizeof(TLVBUF_HEADER); + endian_convert_tlv_header_out(coex_common_tlv); + + coex_sco_tlv = (tlvbuf_coex_sco_cfg *) (cmd_buf->tlv_buffer + + sizeof(tlvbuf_coex_common_cfg)); + coex_sco_tlv->Tag = MRVL_BT_COEX_SCO_CFG_TLV_ID; + coex_sco_tlv->Length = sizeof(tlvbuf_coex_sco_cfg) - sizeof(TLVBUF_HEADER); + endian_convert_tlv_header_out(coex_sco_tlv); + + coex_acl_tlv = (tlvbuf_coex_acl_cfg *) (cmd_buf->tlv_buffer + + sizeof(tlvbuf_coex_common_cfg) + + sizeof(tlvbuf_coex_sco_cfg)); + coex_acl_tlv->Tag = MRVL_BT_COEX_ACL_CFG_TLV_ID; + coex_acl_tlv->Length = sizeof(tlvbuf_coex_acl_cfg) - sizeof(TLVBUF_HEADER); + endian_convert_tlv_header_out(coex_acl_tlv); + + coex_stats_tlv = (tlvbuf_coex_stats *) (cmd_buf->tlv_buffer + + sizeof(tlvbuf_coex_common_cfg) + + sizeof(tlvbuf_coex_sco_cfg) + + sizeof(tlvbuf_coex_acl_cfg)); + coex_stats_tlv->Tag = MRVL_BT_COEX_STATS_TLV_ID; + coex_stats_tlv->Length = sizeof(tlvbuf_coex_stats) - sizeof(TLVBUF_HEADER); + endian_convert_tlv_header_out(coex_stats_tlv); + + /* Fill the command buffer */ + cmd_buf->CmdCode = HostCmd_ROBUST_COEX; + cmd_buf->Size = cmd_len - BUF_HEADER_SIZE; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + cmd_buf->action = uap_cpu_to_le16(ACTION_GET); + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (cmd_buf->CmdCode != (HostCmd_ROBUST_COEX | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response!\n"); + free(buf); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + printf("BT Coex settings:\n"); + print_tlv(buf + sizeof(apcmdbuf_coex_config), + cmd_buf->Size - sizeof(apcmdbuf_coex_config) + + BUF_HEADER_SIZE); + } else { + printf("ERR:Could not retrieve coex configuration.\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + free(buf); + return; +} + +/** + * @brief Show usage information for the sys_config command + * + * $return N/A + */ +void +print_sys_config_usage(void) +{ + printf("\nUsage : sys_config [CONFIG_FILE]\n"); + printf + ("\nIf CONFIG_FILE is provided, a 'set' is performed, else a 'get' is performed.\n"); + printf("CONFIG_FILE is file contain all the Micro AP settings.\n"); + return; +} + +/** + * @brief Show usage information for the rdeeprom command + * + * $return N/A + */ +void +print_apcmd_read_eeprom_usage(void) +{ + printf("\nUsage: rdeeprom <offset> <bytecount>\n"); + printf(" offset : 0,4,8,..., multiple of 4\n"); + printf(" bytecount : 4-20, multiple of 4\n"); + return; +} + +/** + * @brief Show protocol tlv + * + * @param tlv Poniter to protocol tlv + * + * $return N/A + */ +void +print_protocol(TLVBUF_PROTOCOL * tlv) +{ + switch (tlv->Protocol) { + case 0: + case PROTOCOL_NO_SECURITY: + printf("PROTOCOL = No security\n"); + break; + case PROTOCOL_STATIC_WEP: + printf("PROTOCOL = Static WEP\n"); + break; + case PROTOCOL_WPA: + printf("PROTOCOL = WPA \n"); + break; + case PROTOCOL_WPA2: + printf("PROTOCOL = WPA2 \n"); + break; + case PROTOCOL_WPA | PROTOCOL_WPA2: + printf("PROTOCOL = WPA/WPA2 \n"); + break; + default: + printf("Unknown PROTOCOL: 0x%x \n", tlv->Protocol); + break; + } +} + +/** + * @brief Show wep tlv + * + * @param tlv Poniter to wep tlv + * + * $return N/A + */ +void +print_wep_key(TLVBUF_WEP_KEY * tlv) +{ + int i; + if (tlv->Length <= 2) { + printf("wrong wep_key tlv: length=%d\n", tlv->Length); + return; + } + printf("WEP KEY_%d = ", tlv->KeyIndex); + for (i = 0; i < tlv->Length - 2; i++) + printf("%02x ", tlv->Key[i]); + if (tlv->IsDefault) + printf("\nDefault WEP Key = %d\n", tlv->KeyIndex); + else + printf("\n"); +} + +/** + * @brief Parses a command line + * + * @param line The line to parse + * @param args Pointer to the argument buffer to be filled in + * @return Number of arguments in the line or EOF + */ +static int +parse_line(char *line, char *args[]) +{ + int arg_num = 0; + int is_start = 0; + int is_quote = 0; + int length = 0; + int i = 0; + + arg_num = 0; + length = strlen(line); + /* Process line */ + + /* Find number of arguments */ + is_start = 0; + is_quote = 0; + for (i = 0; i < length; i++) { + /* Ignore leading spaces */ + if (is_start == 0) { + if (line[i] == ' ') { + continue; + } else if (line[i] == '\t') { + continue; + } else if (line[i] == '\n') { + break; + } else { + is_start = 1; + args[arg_num] = &line[i]; + arg_num++; + } + } + if (is_start == 1) { + /* Ignore comments */ + if (line[i] == '#') { + line[i] = '\0'; + arg_num--; + break; + } + /* Separate by '=' */ + if (line[i] == '=') { + line[i] = '\0'; + is_start = 0; + continue; + } + /* Separate by ',' */ + if (line[i] == ',') { + line[i] = '\0'; + is_start = 0; + continue; + } + /* Change ',' to ' ', but not inside quotes */ + if ((line[i] == ',') && (is_quote == 0)) { + line[i] = ' '; + continue; + } + } + /* Remove newlines */ + if (line[i] == '\n') { + line[i] = '\0'; + } + /* Check for quotes */ + if (line[i] == '"') { + is_quote = (is_quote == 1) ? 0 : 1; + continue; + } + if (((line[i] == ' ') || (line[i] == '\t')) && (is_quote == 0)) { + line[i] = '\0'; + is_start = 0; + continue; + } + } + return arg_num; +} + +/** + * @brief Parse function for a configuration line + * + * @param s Storage buffer for data + * @param size Maximum size of data + * @param stream File stream pointer + * @param line Pointer to current line within the file + * @param _pos Output string or NULL + * @return String or NULL + */ +static char * +config_get_line(char *s, int size, FILE * stream, int *line, char **_pos) +{ + char *pos, *end, *sstart; + while (fgets(s, size, stream)) { + (*line)++; + s[size - 1] = '\0'; + pos = s; + /* Skip white space from the beginning of line. */ + while (*pos == ' ' || *pos == '\t' || *pos == '\r') + pos++; + /* Skip comment lines and empty lines */ + if (*pos == '#' || *pos == '\n' || *pos == '\0') + continue; + /* + * Remove # comments unless they are within a double quoted + * string. + */ + sstart = strchr(pos, '"'); + if (sstart) + sstart = strrchr(sstart + 1, '"'); + if (!sstart) + sstart = pos; + end = strchr(sstart, '#'); + if (end) + *end-- = '\0'; + else + end = pos + strlen(pos) - 1; + /* Remove trailing white space. */ + while (end > pos && + (*end == '\n' || *end == ' ' || *end == '\t' || *end == '\r')) + *end-- = '\0'; + if (*pos == '\0') + continue; + if (_pos) + *_pos = pos; + return pos; + } + + if (_pos) + *_pos = NULL; + return NULL; +} + +/** + * @brief Read the profile and sends to the driver + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return UAP_SUCCESS or UAP_FAILURE + */ +void +apcmd_coex_config_profile(int argc, char *argv[]) +{ + FILE *config_file = NULL; + char *line = NULL; + int i, ret, index, li = 0; + char *pos = NULL; + int arg_num = 0; + char *args[30]; + int is_coex_config = 0; + int is_coex_common_config = 0; + int is_coex_sco_config = 0; + int is_coex_acl_config = 0; + u8 *buf = NULL; + apcmdbuf_coex_config *cmd_buf = NULL; + tlvbuf_coex_common_cfg *coex_common_tlv; + tlvbuf_coex_sco_cfg *coex_sco_tlv; + tlvbuf_coex_acl_cfg *coex_acl_tlv; + u16 acl_enabled = 0; + u32 conf_bitmap = 0; + u16 cmd_len = 0, tlv_len = 0; + u16 sco_prot_qtime[4] = { 0, 0, 0, 0 }, sco_prot_rate = 0, sco_acl_freq = 0; + u16 acl_bt_time = 0, acl_wlan_time = 0, acl_prot_rate = 0; + + /* Check if file exists */ + config_file = fopen(argv[0], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + return; + } + line = (char *) malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + bzero(line, MAX_CONFIG_LINE); + + /* fixed command length */ + cmd_len = sizeof(apcmdbuf_coex_config) + sizeof(tlvbuf_coex_common_cfg) + + sizeof(tlvbuf_coex_sco_cfg) + sizeof(tlvbuf_coex_acl_cfg); + /* alloc buf for command */ + buf = (u8 *) malloc(cmd_len); + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + goto done; + } + bzero((char *) buf, cmd_len); + + cmd_buf = (apcmdbuf_coex_config *) buf; + + /* Fill the command buffer */ + cmd_buf->CmdCode = HostCmd_ROBUST_COEX; + cmd_buf->Size = cmd_len - BUF_HEADER_SIZE; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + cmd_buf->action = uap_cpu_to_le16(ACTION_SET); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { +#if DEBUG + uap_printf(MSG_DEBUG, "DBG:Received config line (%d) = %s\n", li, line); +#endif + arg_num = parse_line(line, args); +#if DEBUG + uap_printf(MSG_DEBUG, "DBG:Number of arguments = %d\n", arg_num); + for (i = 0; i < arg_num; i++) { + uap_printf(MSG_DEBUG, "\tDBG:Argument %d. %s\n", i + 1, args[i]); + } +#endif + /* Check for end of Coex configurations */ + if (is_coex_acl_config == 1) { + if (strcmp(args[0], "}") == 0) { + coex_acl_tlv = + (tlvbuf_coex_acl_cfg *) (cmd_buf->tlv_buffer + tlv_len); + coex_acl_tlv->Tag = MRVL_BT_COEX_ACL_CFG_TLV_ID; + coex_acl_tlv->Length = + sizeof(tlvbuf_coex_acl_cfg) - sizeof(TLVBUF_HEADER); + endian_convert_tlv_header_out(coex_acl_tlv); + coex_acl_tlv->enabled = uap_cpu_to_le16(acl_enabled); + coex_acl_tlv->bt_time = uap_cpu_to_le16(acl_bt_time); + coex_acl_tlv->wlan_time = uap_cpu_to_le16(acl_wlan_time); + coex_acl_tlv->protection_rate = uap_cpu_to_le16(acl_prot_rate); + tlv_len += sizeof(tlvbuf_coex_acl_cfg); + is_coex_acl_config = 0; + } + } else if (is_coex_sco_config == 1) { + if (strcmp(args[0], "}") == 0) { + coex_sco_tlv = + (tlvbuf_coex_sco_cfg *) (cmd_buf->tlv_buffer + tlv_len); + coex_sco_tlv->Tag = MRVL_BT_COEX_SCO_CFG_TLV_ID; + coex_sco_tlv->Length = + sizeof(tlvbuf_coex_sco_cfg) - sizeof(TLVBUF_HEADER); + endian_convert_tlv_header_out(coex_sco_tlv); + for (i = 0; i < 4; i++) + coex_sco_tlv->protection_qtime[i] = + uap_cpu_to_le16(sco_prot_qtime[i]); + coex_sco_tlv->protection_rate = uap_cpu_to_le16(sco_prot_rate); + coex_sco_tlv->acl_frequency = uap_cpu_to_le16(sco_acl_freq); + tlv_len += sizeof(tlvbuf_coex_sco_cfg); + is_coex_sco_config = 0; + } + } else if (is_coex_common_config == 1) { + if (strcmp(args[0], "}") == 0) { + coex_common_tlv = + (tlvbuf_coex_common_cfg *) (cmd_buf->tlv_buffer + tlv_len); + coex_common_tlv->Tag = MRVL_BT_COEX_COMMON_CFG_TLV_ID; + coex_common_tlv->Length = + sizeof(tlvbuf_coex_common_cfg) - sizeof(TLVBUF_HEADER); + endian_convert_tlv_header_out(coex_common_tlv); + coex_common_tlv->config_bitmap = uap_cpu_to_le32(conf_bitmap); + tlv_len += sizeof(tlvbuf_coex_common_cfg); + is_coex_common_config = 0; + } + } else if (is_coex_config == 1) { + if (strcmp(args[0], "}") == 0) + is_coex_config = 0; + } + if (strcmp(args[0], "coex_config") == 0) { + is_coex_config = 1; + } else if (strcmp(args[0], "common_config") == 0) { + is_coex_common_config = 1; + } else if (strcmp(args[0], "sco_config") == 0) { + is_coex_sco_config = 1; + } else if (strcmp(args[0], "acl_config") == 0) { + is_coex_acl_config = 1; + } + if ((strcmp(args[0], "bitmap") == 0) && is_coex_common_config) { + if (is_input_valid(COEX_COMM_BITMAP, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + conf_bitmap = (u32) A2HEXDECIMAL(args[1]); + } else if ((strncmp(args[0], "protectionFromQTime", 19) == 0) && + is_coex_sco_config) { + index = atoi(args[0] + strlen("protectionFromQTime")); + if (index < 0 || index > 3) { + printf("ERR:Incorrect index %d.\n", index); + goto done; + } + if (is_input_valid(COEX_PROTECTION, arg_num, args) != UAP_SUCCESS) { + goto done; + } + sco_prot_qtime[index] = (u16) atoi(args[1]); + } else if ((strcmp(args[0], "scoProtectionFromRate") == 0) && + is_coex_sco_config) { + if (is_input_valid(COEX_PROTECTION, arg_num, args) != UAP_SUCCESS) { + goto done; + } + sco_prot_rate = (u16) atoi(args[1]); + } else if ((strcmp(args[0], "aclFrequency") == 0) && is_coex_sco_config) { + if (is_input_valid(COEX_SCO_ACL_FREQ, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + sco_acl_freq = (u16) atoi(args[1]); + } else if ((strcmp(args[0], "enabled") == 0) && is_coex_acl_config) { + if (is_input_valid(COEX_ACL_ENABLED, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + acl_enabled = (u16) atoi(args[1]); + } else if ((strcmp(args[0], "btTime") == 0) && is_coex_acl_config) { + if (is_input_valid(COEX_ACL_BT_TIME, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + acl_bt_time = (u16) atoi(args[1]); + } else if ((strcmp(args[0], "wlanTime") == 0) && is_coex_acl_config) { + if (is_input_valid(COEX_ACL_WLAN_TIME, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + acl_wlan_time = (u16) atoi(args[1]); + } else if ((strcmp(args[0], "aclProtectionFromRate") == 0) && + is_coex_acl_config) { + if (is_input_valid(COEX_PROTECTION, arg_num, args) != UAP_SUCCESS) { + goto done; + } + acl_prot_rate = (u16) atoi(args[1]); + } + } + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (cmd_buf->CmdCode != (HostCmd_ROBUST_COEX | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response!\n"); + goto done; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + printf("BT Coex settings sucessfully set.\n"); + } else { + printf("ERR:Could not set coex configuration.\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + done: + fclose(config_file); + if (buf) + free(buf); + if (line) + free(line); +} + +/** + * @brief Read the profile and sends to the driver + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return UAP_SUCCESS or UAP_FAILURE + */ +void +apcmd_sys_config_profile(int argc, char *argv[]) +{ + FILE *config_file = NULL; + char *line = NULL; + int li = 0; + char *pos = NULL; + int arg_num = 0; + char *args[30]; + int i; + int is_ap_config = 0; + int is_custom_ie_config = 0; + int is_ap_mac_filter = 0; + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + u8 *buffer = NULL; + u16 cmd_len = 0; + u16 tlv_len = 0; + u16 ie_len = 0; + u16 ie_buf_len = 0; + u16 mask_ie_index = 0; + int keyindex = -1; + int pairwisecipher = -1; + int groupcipher = -1; + TLVBUF_STA_MAC_ADDR_FILTER *filter_tlv = NULL; + tlvbuf_custom_ie *custom_ie_tlv_head = NULL; + tlvbuf_custom_ie *custom_ie_tlv = NULL; + custom_ie *custom_ie_ptr = NULL; + int custom_ie_tlv_len = 0; + int custom_mask_count = 0; + int custom_buf_count = 0; + int filter_mac_count = -1; + int tx_data_rate = -1; + int mcbc_data_rate = -1; + u8 rate[MAX_RATES]; + int found = 0; + char country_80211d[4]; + u8 state_80211d; + int flag_80211d = 0; + + memset(rate, 0, MAX_RATES); + /* Check if file exists */ + config_file = fopen(argv[0], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + return; + } + line = (char *) malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + bzero(line, MAX_CONFIG_LINE); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { +#if DEBUG + uap_printf(MSG_DEBUG, "DBG:Received config line (%d) = %s\n", li, line); +#endif + arg_num = parse_line(line, args); +#if DEBUG + uap_printf(MSG_DEBUG, "DBG:Number of arguments = %d\n", arg_num); + for (i = 0; i < arg_num; i++) { + uap_printf(MSG_DEBUG, "\tDBG:Argument %d. %s\n", i + 1, args[i]); + } +#endif + /* Check for end of AP configurations */ + if (is_ap_config == 1) { + if (strcmp(args[0], "}") == 0) { + is_ap_config = 0; + if (tx_data_rate != -1) { + if ((!rate[0]) && (tx_data_rate) && + (is_tx_rate_valid((u8) tx_data_rate) != UAP_SUCCESS)) { + printf("ERR: Invalid Tx Data Rate \n"); + goto done; + } + if (rate[0] && tx_data_rate) { + for (i = 0; rate[i] != 0; i++) { + if ((rate[i] & ~BASIC_RATE_SET_BIT) == tx_data_rate) { + found = 1; + break; + } + } + if (!found) { + printf("ERR: Invalid Tx Data Rate \n"); + goto done; + } + } + + /* Append a new TLV */ + TLVBUF_TX_DATA_RATE *tlv = NULL; + tlv_len = sizeof(TLVBUF_TX_DATA_RATE); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append tx data rate TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_TX_DATA_RATE *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_TX_DATA_RATE_TLV_ID; + tlv->Length = 2; + tlv->TxDataRate = tx_data_rate; + endian_convert_tlv_header_out(tlv); + tlv->TxDataRate = uap_cpu_to_le16(tlv->TxDataRate); + } + if (mcbc_data_rate != -1) { + if ((!rate[0]) && (mcbc_data_rate) && + (is_mcbc_rate_valid((u8) mcbc_data_rate) != + UAP_SUCCESS)) { + printf("ERR: Invalid Tx Data Rate \n"); + goto done; + } + if (rate[0] && mcbc_data_rate) { + for (i = 0; rate[i] != 0; i++) { + if (rate[i] & BASIC_RATE_SET_BIT) { + if ((rate[i] & ~BASIC_RATE_SET_BIT) == + mcbc_data_rate) { + found = 1; + break; + } + } + } + if (!found) { + printf("ERR: Invalid MCBC Data Rate \n"); + goto done; + } + } + + /* Append a new TLV */ + TLVBUF_MCBC_DATA_RATE *tlv = NULL; + tlv_len = sizeof(TLVBUF_MCBC_DATA_RATE); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append tx data rate TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_MCBC_DATA_RATE *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_MCBC_DATA_RATE_TLV_ID; + tlv->Length = 2; + tlv->MCBCdatarate = mcbc_data_rate; + endian_convert_tlv_header_out(tlv); + tlv->MCBCdatarate = uap_cpu_to_le16(tlv->MCBCdatarate); + } + + if ((pairwisecipher >= 0) && (groupcipher >= 0)) { + if (is_cipher_valid(pairwisecipher, groupcipher) != + UAP_SUCCESS) { + printf + ("ERR:Wrong group and pair cipher combination!\n"); + goto done; + } + TLVBUF_CIPHER *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_CIPHER); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append cipher TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_CIPHER *) (buffer + cmd_len); + bzero((char *) tlv, tlv_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_CIPHER_TLV_ID; + tlv->Length = 2; + tlv->PairwiseCipher = pairwisecipher; + tlv->GroupCipher = groupcipher; + endian_convert_tlv_header_out(tlv); + } + cmd_buf->Size = cmd_len; + /* Send collective command */ + uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + cmd_len = 0; + if (buffer) { + free(buffer); + buffer = NULL; + } + continue; + } + } + + /* Check for beginning of AP configurations */ + if (strcmp(args[0], "ap_config") == 0) { + is_ap_config = 1; + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE); + if (buffer) { + free(buffer); + buffer = NULL; + } + buffer = (u8 *) malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + cmd_buf->Action = ACTION_SET; + continue; + } + + /* Check for end of AP MAC address filter configurations */ + if (is_ap_mac_filter == 1) { + if (strcmp(args[0], "}") == 0) { + is_ap_mac_filter = 0; + if (filter_tlv->Count != filter_mac_count) { + printf + ("ERR:Number of MAC address provided does not match 'Count'\n"); + goto done; + } + if (filter_tlv->FilterMode && (filter_tlv->Count == 0)) { + printf + ("ERR:Filter list can not be empty for %s Filter mode\n", + (filter_tlv->FilterMode == 1) ? "'Allow'" : "'Block'"); + goto done; + } + filter_tlv->Length = (filter_tlv->Count * ETH_ALEN) + 2; + cmd_len -= + (MAX_MAC_ONESHOT_FILTER - filter_mac_count) * ETH_ALEN; + cmd_buf->Size = cmd_len; + endian_convert_tlv_header_out(filter_tlv); + uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + cmd_len = 0; + if (buffer) { + free(buffer); + buffer = NULL; + } + continue; + } + } + + /* Check for end of custom IE configurations */ + if (is_custom_ie_config == 1) { + if (strcmp(args[0], "}") == 0) { + if (custom_mask_count != custom_buf_count) { + printf + ("ERR:custom IE mask count and buffer count does not match\n"); + goto done; + } + is_custom_ie_config = 0; + custom_ie_tlv_head->Length = custom_ie_tlv_len; + cmd_len -= + (MAX_IE_BUFFER_LEN * MAX_CUSTOM_IE_COUNT) - + custom_ie_tlv_len; + cmd_len -= sizeof(custom_ie) * MAX_CUSTOM_IE_COUNT; + cmd_buf->Size = cmd_len; + endian_convert_tlv_header_out(custom_ie_tlv_head); + uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + cmd_len = 0; + if (buffer) { + free(buffer); + buffer = NULL; + } + continue; + } + } + + if (flag_80211d && (strcmp(args[0], "11d_enable") == 0)) { + if (IS_HEX_OR_DIGIT(args[1]) == UAP_FAILURE) { + printf("ERR: valid input for state are 0 or 1\n"); + goto done; + } + state_80211d = (u8) A2HEXDECIMAL(args[1]); + + if ((state_80211d != 0) && (state_80211d != 1)) { + printf("ERR: valid input for state are 0 or 1 \n"); + goto done; + } + if (sg_snmp_mib + (ACTION_SET, OID_80211D_ENABLE, sizeof(state_80211d), + &state_80211d) + == UAP_FAILURE) { + goto done; + } + } + + if (strcmp(args[0], "country") == 0) { + APCMDBUF_CFG_80211D *cmd_buf = NULL; + IEEEtypes_SubbandSet_t sub_bands[MAX_SUB_BANDS]; + u8 no_of_sub_band = 0; + u16 buf_len; + u16 cmdlen; + u8 *buf = NULL; + + if ((strlen(args[1]) > 3) || (strlen(args[1]) < 0)) { + printf("In-correct country input\n"); + goto done; + } + strcpy(country_80211d, args[1]); + for (i = 0; i < strlen(country_80211d); i++) { + if ((country_80211d[i] < 'A') || (country_80211d[i] > 'z')) { + printf("Invalid Country Code\n"); + goto done; + } + if (country_80211d[i] > 'Z') + country_80211d[i] = country_80211d[i] - 'a' + 'A'; + } + no_of_sub_band = parse_domain_file(country_80211d, sub_bands); + if (no_of_sub_band == UAP_FAILURE) { + printf("Parsing Failed\n"); + goto done; + } + buf_len = sizeof(APCMDBUF_CFG_80211D); + buf_len += no_of_sub_band * sizeof(IEEEtypes_SubbandSet_t); + buf = (u8 *) malloc(buf_len); + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + goto done; + } + bzero((char *) buf, buf_len); + cmd_buf = (APCMDBUF_CFG_80211D *) buf; + cmdlen = buf_len; + cmd_buf->Size = cmdlen - BUF_HEADER_SIZE; + cmd_buf->Result = 0; + cmd_buf->SeqNum = 0; + cmd_buf->Action = uap_cpu_to_le16(ACTION_SET); + cmd_buf->CmdCode = HostCmd_CMD_802_11D_DOMAIN_INFO; + cmd_buf->Domain.Tag = uap_cpu_to_le16(TLV_TYPE_DOMAIN); + cmd_buf->Domain.Length = uap_cpu_to_le16(sizeof(domain_param_t) + - BUF_HEADER_SIZE + + + (no_of_sub_band * + sizeof + (IEEEtypes_SubbandSet_t))); + + memset(cmd_buf->Domain.CountryCode, ' ', + sizeof(cmd_buf->Domain.CountryCode)); + memcpy(cmd_buf->Domain.CountryCode, country_80211d, + strlen(country_80211d)); + memcpy(cmd_buf->Domain.Subband, sub_bands, + no_of_sub_band * sizeof(IEEEtypes_SubbandSet_t)); + + /* Send the command */ + uap_ioctl((u8 *) cmd_buf, &cmdlen, buf_len); + if (buf) + free(buf); + } + + /* Check for beginning of AP MAC address filter configurations */ + if (strcmp(args[0], "ap_mac_filter") == 0) { + is_ap_mac_filter = 1; + cmd_len = + sizeof(APCMDBUF_SYS_CONFIGURE) + + sizeof(TLVBUF_STA_MAC_ADDR_FILTER) + + (MAX_MAC_ONESHOT_FILTER * ETH_ALEN); + if (buffer) { + free(buffer); + buffer = NULL; + } + buffer = (u8 *) malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + cmd_buf->Action = ACTION_SET; + filter_tlv = + (TLVBUF_STA_MAC_ADDR_FILTER *) (buffer + + sizeof(APCMDBUF_SYS_CONFIGURE)); + filter_tlv->Tag = MRVL_STA_MAC_ADDR_FILTER_TLV_ID; + filter_tlv->Length = 2; + filter_tlv->Count = 0; + filter_mac_count = 0; + continue; + } + + /* Check for beginning of custom IE configurations */ + if (strcmp(args[0], "custom_ie_config") == 0) { + is_custom_ie_config = 1; + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(tlvbuf_custom_ie) + + + ((MAX_IE_BUFFER_LEN + sizeof(custom_ie)) * MAX_CUSTOM_IE_COUNT); + if (buffer) { + free(buffer); + buffer = NULL; + } + buffer = (u8 *) malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + cmd_buf->Action = ACTION_SET; + custom_ie_tlv = + (tlvbuf_custom_ie *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + custom_ie_ptr = (custom_ie *) (custom_ie_tlv->ie_data); + custom_ie_tlv_head = custom_ie_tlv; + custom_ie_tlv_head->Tag = MRVL_MGMT_IE_LIST_TLV_ID; + continue; + } + + if ((strcmp(args[0], "FilterMode") == 0) && is_ap_mac_filter) { + if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0) || + (atoi(args[1]) > 2)) { + printf + ("ERR:Illegal FilterMode paramter %d. Must be either '0', '1', or '2'.\n", + atoi(args[1])); + goto done; + } + filter_tlv->FilterMode = atoi(args[1]); + continue; + } + if ((strcmp(args[0], "Count") == 0) && is_ap_mac_filter) { + filter_tlv->Count = atoi(args[1]); + if ((ISDIGIT(args[1]) == 0) || + (filter_tlv->Count > MAX_MAC_ONESHOT_FILTER)) { + printf("ERR: Illegal Count parameter.\n"); + goto done; + } + } + if ((strncmp(args[0], "mac_", 4) == 0) && is_ap_mac_filter) { + if (filter_mac_count < MAX_MAC_ONESHOT_FILTER) { + if (mac2raw + (args[1], + &filter_tlv->MacAddress[filter_mac_count * ETH_ALEN]) != + UAP_SUCCESS) { + printf("ERR: Invalid MAC address %s \n", args[1]); + goto done; + } + filter_mac_count++; + } else { + printf + ("ERR: Filter table can not have more than %d MAC addresses\n", + MAX_MAC_ONESHOT_FILTER); + goto done; + } + } + + /* custom ie configuration parameters */ + if ((strncmp(args[0], "MgmtSubtypeMask_", 16) == 0) && + is_custom_ie_config) { + if (UAP_FAILURE == ishexstring(args[1])) { + printf("ERR:Illegal MgmtSubtypeMask %s.\n", args[1]); + goto done; + } + mask_ie_index = (u16) atoi(args[0] + strlen("MgmtSubtypeMask_")); + if (mask_ie_index > 3) { + printf("ERR:Incorrect index %d.\n", mask_ie_index); + goto done; + } + custom_ie_ptr->ie_index = uap_cpu_to_le16(mask_ie_index); + custom_ie_ptr->mgmt_subtype_mask = (u16) A2HEXDECIMAL(args[1]); + custom_ie_ptr->mgmt_subtype_mask = uap_cpu_to_le16 + (custom_ie_ptr->mgmt_subtype_mask); + custom_mask_count++; + continue; + } + if ((strncmp(args[0], "IEBuffer_", 9) == 0) && is_custom_ie_config) { + if (UAP_FAILURE == ishexstring(args[1])) { + printf("ERR:Only hex digits are allowed\n"); + goto done; + } + ie_buf_len = strlen(args[1]); + if (!strncasecmp("0x", args[1], 2)) { + ie_len = (ie_buf_len - 2 + 1) / 2; + args[1] += 2; + } else + ie_len = (ie_buf_len + 1) / 2; + + if (ie_len > MAX_IE_BUFFER_LEN) { + printf("ERR:Incorrect IE length %d\n", ie_buf_len); + goto done; + } + + custom_ie_ptr->ie_index = (u16) atoi(args[0] + strlen("IEBuffer_")); + if (custom_ie_ptr->ie_index != mask_ie_index) { + printf("ERR:IE buffer%d should follow MgmtSubtypeMask%d\n", + mask_ie_index, mask_ie_index); + goto done; + } + custom_ie_ptr->ie_index = uap_cpu_to_le16(custom_ie_ptr->ie_index); + string2raw(args[1], custom_ie_ptr->ie_buffer); + custom_ie_ptr->ie_length = uap_cpu_to_le16(ie_len); + custom_ie_tlv_len += sizeof(custom_ie) + ie_len; + custom_ie_tlv = (tlvbuf_custom_ie *) ((u8 *) custom_ie_tlv + + sizeof(custom_ie) + ie_len); + custom_ie_ptr = (custom_ie *) (custom_ie_tlv->ie_data); + custom_buf_count++; + continue; + } + if (strcmp(args[0], "SSID") == 0) { + if (arg_num == 1) { + printf("ERR:SSID field is blank!\n"); + goto done; + } else { + TLVBUF_SSID *tlv = NULL; + if (args[1][0] == '"') { + args[1]++; + } + if (args[1][strlen(args[1]) - 1] == '"') { + args[1][strlen(args[1]) - 1] = '\0'; + } + if ((strlen(args[1]) > MAX_SSID_LENGTH) || + (strlen(args[1]) == 0)) { + printf("ERR:SSID length out of range (%d to %d).\n", + MIN_SSID_LENGTH, MAX_SSID_LENGTH); + goto done; + } + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_SSID) + strlen(args[1]); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot realloc SSID TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_SSID *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_SSID_TLV_ID; + tlv->Length = strlen(args[1]); + memcpy(tlv->Ssid, args[1], tlv->Length); + endian_convert_tlv_header_out(tlv); + } + } + if (strcmp(args[0], "BeaconPeriod") == 0) { + if (is_input_valid(BEACONPERIOD, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + TLVBUF_BEACON_PERIOD *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_BEACON_PERIOD); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot realloc beacon period TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_BEACON_PERIOD *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_BEACON_PERIOD_TLV_ID; + tlv->Length = 2; + tlv->BeaconPeriod_ms = (u16) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + tlv->BeaconPeriod_ms = uap_cpu_to_le16(tlv->BeaconPeriod_ms); + } + if (strcmp(args[0], "ChanList") == 0) { + if (is_input_valid(SCANCHANNELS, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + + TLVBUF_CHANNEL_LIST *tlv = NULL; + CHANNEL_LIST *pChanList = NULL; + /* Append a new TLV */ + tlv_len = + sizeof(TLVBUF_CHANNEL_LIST) + + ((arg_num - 1) * sizeof(CHANNEL_LIST)); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append channel list TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_CHANNEL_LIST *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_CHANNELLIST_TLV_ID; + tlv->Length = sizeof(CHANNEL_LIST) * (arg_num - 1); + pChanList = (CHANNEL_LIST *) tlv->ChanList; + for (i = 0; i < (arg_num - 1); i++) { + pChanList->ChanNumber = (u8) atoi(args[i + 1]); + pChanList->BandConfigType = 0; + pChanList++; + } + endian_convert_tlv_header_out(tlv); + } + if (strcmp(args[0], "Channel") == 0) { + if (is_input_valid(CHANNEL, arg_num - 1, args + 1) != UAP_SUCCESS) { + goto done; + } + TLVBUF_CHANNEL_CONFIG *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_CHANNEL_CONFIG); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append channel TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_CHANNEL_CONFIG *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_CHANNELCONFIG_TLV_ID; + tlv->Length = 2; + tlv->ChanNumber = (u8) atoi(args[1]); + if ((arg_num - 1) == 2) + tlv->BandConfigType = atoi(args[2]) ? BAND_CONFIG_ACS_MODE : 0; + else + tlv->BandConfigType = 0; + endian_convert_tlv_header_out(tlv); + } + if (strcmp(args[0], "AP_MAC") == 0) { + int ret; + TLVBUF_AP_MAC_ADDRESS *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_AP_MAC_ADDRESS); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append channel TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_AP_MAC_ADDRESS *) (buffer + cmd_len); + cmd_len += tlv_len; + cmd_buf->Action = ACTION_SET; + tlv->Tag = MRVL_AP_MAC_ADDRESS_TLV_ID; + tlv->Length = ETH_ALEN; + if ((ret = mac2raw(args[1], tlv->ApMacAddr)) != UAP_SUCCESS) { + printf("ERR: %s Address \n", + ret == UAP_FAILURE ? "Invalid MAC" : ret == + UAP_RET_MAC_BROADCAST ? "Broadcast" : "Multicast"); + goto done; + } + endian_convert_tlv_header_out(tlv); + } + + if (strcmp(args[0], "RxAntenna") == 0) { + if ((ISDIGIT(args[1]) != UAP_SUCCESS) || (atoi(args[1]) < 0) || + (atoi(args[1]) > 1)) { + printf("ERR: Invalid Antenna value\n"); + goto done; + } + TLVBUF_ANTENNA_CTL *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_ANTENNA_CTL); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append channel TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_ANTENNA_CTL *) (buffer + cmd_len); + cmd_len += tlv_len; + cmd_buf->Action = ACTION_SET; + tlv->Tag = MRVL_ANTENNA_CTL_TLV_ID; + tlv->Length = 2; + tlv->WhichAntenna = 0; + tlv->AntennaMode = atoi(args[1]); + endian_convert_tlv_header_out(tlv); + } + + if (strcmp(args[0], "TxAntenna") == 0) { + if ((ISDIGIT(args[1]) != UAP_SUCCESS) || (atoi(args[1]) < 0) || + (atoi(args[1]) > 1)) { + printf("ERR: Invalid Antenna value\n"); + goto done; + } + TLVBUF_ANTENNA_CTL *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_ANTENNA_CTL); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append channel TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_ANTENNA_CTL *) (buffer + cmd_len); + cmd_len += tlv_len; + cmd_buf->Action = ACTION_SET; + tlv->Tag = MRVL_ANTENNA_CTL_TLV_ID; + tlv->Length = 2; + tlv->WhichAntenna = 1; + tlv->AntennaMode = atoi(args[1]); + endian_convert_tlv_header_out(tlv); + } + if (strcmp(args[0], "Rate") == 0) { + if (is_input_valid(RATE, arg_num - 1, args + 1) != UAP_SUCCESS) { + printf("ERR: Invalid Rate input\n"); + goto done; + } + TLVBUF_RATES *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_RATES) + arg_num - 1; + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append rates TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_RATES *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_RATES_TLV_ID; + tlv->Length = arg_num - 1; + for (i = 0; i < tlv->Length; i++) { + rate[i] = tlv->OperationalRates[i] = + (u8) A2HEXDECIMAL(args[i + 1]); + } + endian_convert_tlv_header_out(tlv); + } + if (strcmp(args[0], "TxPowerLevel") == 0) { + if (is_input_valid(TXPOWER, arg_num - 1, args + 1) != UAP_SUCCESS) { + printf("ERR:Invalid TxPowerLevel \n"); + goto done; + } else { + TLVBUF_TX_POWER *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_TX_POWER); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append tx power level TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_TX_POWER *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_TX_POWER_TLV_ID; + tlv->Length = 1; + tlv->TxPower_dBm = (u8) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + } + } + if (strcmp(args[0], "BroadcastSSID") == 0) { + if (is_input_valid(BROADCASTSSID, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + TLVBUF_BCAST_SSID_CTL *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_BCAST_SSID_CTL); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append SSID broadcast control TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_BCAST_SSID_CTL *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_BCAST_SSID_CTL_TLV_ID; + tlv->Length = 1; + tlv->BcastSsidCtl = (u8) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + } + if (strcmp(args[0], "RTSThreshold") == 0) { + if (is_input_valid(RTSTHRESH, arg_num - 1, args + 1) != UAP_SUCCESS) { + goto done; + } + TLVBUF_RTS_THRESHOLD *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_RTS_THRESHOLD); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append RTS threshold TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_RTS_THRESHOLD *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_RTS_THRESHOLD_TLV_ID; + tlv->Length = 2; + tlv->RtsThreshold = (u16) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + tlv->RtsThreshold = uap_cpu_to_le16(tlv->RtsThreshold); + } + if (strcmp(args[0], "FragThreshold") == 0) { + if (is_input_valid(FRAGTHRESH, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + TLVBUF_FRAG_THRESHOLD *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_FRAG_THRESHOLD); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append Fragmentation threshold TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_FRAG_THRESHOLD *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_FRAG_THRESHOLD_TLV_ID; + tlv->Length = 2; + tlv->FragThreshold = (u16) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + tlv->FragThreshold = uap_cpu_to_le16(tlv->FragThreshold); + } + if (strcmp(args[0], "DTIMPeriod") == 0) { + if (is_input_valid(DTIMPERIOD, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + TLVBUF_DTIM_PERIOD *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_DTIM_PERIOD); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append DTIM period TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_DTIM_PERIOD *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_DTIM_PERIOD_TLV_ID; + tlv->Length = 1; + tlv->DtimPeriod = (u8) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + } + if (strcmp(args[0], "RadioControl") == 0) { + if (is_input_valid(RADIOCONTROL, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + TLVBUF_RADIO_CTL *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_RADIO_CTL); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append radio control TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_RADIO_CTL *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_RADIO_CTL_TLV_ID; + tlv->Length = 1; + tlv->RadioCtl = (u8) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + } + if (strcmp(args[0], "RSNReplayProtection") == 0) { + if (is_input_valid(RSNREPLAYPROT, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + tlvbuf_rsn_replay_prot *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(tlvbuf_rsn_replay_prot); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append RSN replay protection TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (tlvbuf_rsn_replay_prot *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_RSN_REPLAY_PROT_TLV_ID; + tlv->Length = 1; + tlv->rsn_replay_prot = (u8) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + } + if (strcmp(args[0], "TxDataRate") == 0) { + if (is_input_valid(TXDATARATE, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + tx_data_rate = (u16) A2HEXDECIMAL(args[1]); + } + if (strcmp(args[0], "MCBCdataRate") == 0) { + if (is_input_valid(MCBCDATARATE, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + mcbc_data_rate = (u16) A2HEXDECIMAL(args[1]); + } + if (strcmp(args[0], "PktFwdCtl") == 0) { + if (is_input_valid(PKTFWD, arg_num - 1, args + 1) != UAP_SUCCESS) { + goto done; + } + TLVBUF_PKT_FWD_CTL *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_PKT_FWD_CTL); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append packet forwarding control TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_PKT_FWD_CTL *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_PKT_FWD_CTL_TLV_ID; + tlv->Length = 1; + tlv->PktFwdCtl = (u8) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + } + if (strcmp(args[0], "StaAgeoutTimer") == 0) { + if (is_input_valid(STAAGEOUTTIMER, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + TLVBUF_STA_AGEOUT_TIMER *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_STA_AGEOUT_TIMER); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append STA ageout timer TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_STA_AGEOUT_TIMER *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_STA_AGEOUT_TIMER_TLV_ID; + tlv->Length = 4; + tlv->StaAgeoutTimer_ms = (u32) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + tlv->StaAgeoutTimer_ms = uap_cpu_to_le32(tlv->StaAgeoutTimer_ms); + } + if (strcmp(args[0], "AuthMode") == 0) { + if (is_input_valid(AUTHMODE, arg_num - 1, args + 1) != UAP_SUCCESS) { + goto done; + } + TLVBUF_AUTH_MODE *tlv = NULL; + if ((atoi(args[1]) < 0) || (atoi(args[1]) > 1)) { + printf + ("ERR:Illegal AuthMode parameter. Must be either '0' or '1'.\n"); + goto done; + } + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_AUTH_MODE); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append auth mode TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_AUTH_MODE *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_AUTH_TLV_ID; + tlv->Length = 1; + tlv->AuthMode = (u8) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + } + if (strcmp(args[0], "KeyIndex") == 0) { + if (arg_num == 1) { + printf("KeyIndex is blank!\n"); + goto done; + } else { + if (ISDIGIT(args[1]) == 0) { + printf + ("ERR:Illegal KeyIndex parameter. Must be either '0', '1', '2', or '3'.\n"); + goto done; + } + keyindex = atoi(args[1]); + if ((keyindex < 0) || (keyindex > 3)) { + printf + ("ERR:Illegal KeyIndex parameter. Must be either '0', '1', '2', or '3'.\n"); + goto done; + } + } + } + if (strncmp(args[0], "Key_", 4) == 0) { + if (arg_num == 1) { + printf("ERR:%s is blank!\n", args[0]); + goto done; + } else { + TLVBUF_WEP_KEY *tlv = NULL; + int key_len = 0; + if (args[1][0] == '"') { + if ((strlen(args[1]) != 2) && (strlen(args[1]) != 7) && + (strlen(args[1]) != 15)) { + printf("ERR:Wrong key length!\n"); + goto done; + } + key_len = strlen(args[1]) - 2; + } else { + if ((strlen(args[1]) != 0) && (strlen(args[1]) != 10) && + (strlen(args[1]) != 26)) { + printf("ERR:Wrong key length!\n"); + goto done; + } + if (UAP_FAILURE == ishexstring(args[1])) { + printf + ("ERR:Only hex digits are allowed when key length is 10 or 26\n"); + goto done; + } + key_len = strlen(args[1]) / 2; + } + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_WEP_KEY) + key_len; + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append WEP key configurations TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_WEP_KEY *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_WEP_KEY_TLV_ID; + tlv->Length = key_len + 2; + if (strcmp(args[0], "Key_0") == 0) { + tlv->KeyIndex = 0; + } else if (strcmp(args[0], "Key_1") == 0) { + tlv->KeyIndex = 1; + } else if (strcmp(args[0], "Key_2") == 0) { + tlv->KeyIndex = 2; + } else if (strcmp(args[0], "Key_3") == 0) { + tlv->KeyIndex = 3; + } + if (keyindex == tlv->KeyIndex) { + tlv->IsDefault = 1; + } else { + tlv->IsDefault = 0; + } + if (args[1][0] == '"') { + memcpy(tlv->Key, &args[1][1], strlen(args[1]) - 2); + } else { + string2raw(args[1], tlv->Key); + } + endian_convert_tlv_header_out(tlv); + } + } + if (strcmp(args[0], "PSK") == 0) { + if (arg_num == 1) { + printf("ERR:PSK is blank!\n"); + goto done; + } else { + TLVBUF_WPA_PASSPHRASE *tlv = NULL; + if (args[1][0] == '"') { + args[1]++; + } + if (args[1][strlen(args[1]) - 1] == '"') { + args[1][strlen(args[1]) - 1] = '\0'; + } + tlv_len = sizeof(TLVBUF_WPA_PASSPHRASE) + strlen(args[1]); + if (strlen(args[1]) > MAX_WPA_PASSPHRASE_LENGTH) { + printf("ERR:PSK too long.\n"); + goto done; + } + if (strlen(args[1]) < MIN_WPA_PASSPHRASE_LENGTH) { + printf("ERR:PSK too short.\n"); + goto done; + } + if (strlen(args[1]) == MAX_WPA_PASSPHRASE_LENGTH) { + if (UAP_FAILURE == ishexstring(args[1])) { + printf + ("ERR:Only hex digits are allowed when passphrase's length is 64\n"); + goto done; + } + } + /* Append a new TLV */ + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append WPA passphrase TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_WPA_PASSPHRASE *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_WPA_PASSPHRASE_TLV_ID; + tlv->Length = strlen(args[1]); + memcpy(tlv->Passphrase, args[1], tlv->Length); + endian_convert_tlv_header_out(tlv); + } + } + if (strcmp(args[0], "Protocol") == 0) { + if (is_input_valid(PROTOCOL, arg_num - 1, args + 1) != UAP_SUCCESS) { + goto done; + } + TLVBUF_PROTOCOL *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_PROTOCOL); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append protocol TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_PROTOCOL *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_PROTOCOL_TLV_ID; + tlv->Length = 2; + tlv->Protocol = (u16) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + tlv->Protocol = uap_cpu_to_le16(tlv->Protocol); + if (atoi(args[1]) & (PROTOCOL_WPA | PROTOCOL_WPA2)) { + TLVBUF_AKMP *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_AKMP); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append AKMP TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_AKMP *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_AKMP_TLV_ID; + tlv->Length = 2; + tlv->KeyMgmt = KEY_MGMT_PSK; + endian_convert_tlv_header_out(tlv); + tlv->KeyMgmt = uap_cpu_to_le16(tlv->KeyMgmt); + } + } + if (strcmp(args[0], "PairwiseCipher") == 0) { + if (arg_num == 1) { + printf("ERR:PairwiseCipher is blank!\n"); + goto done; + } else { + if (ISDIGIT(args[1]) == 0) { + printf + ("ERR:Illegal PairwiseCipher parameter. Must be either bit '2' or '3'.\n"); + goto done; + } + pairwisecipher = atoi(args[1]); + if (pairwisecipher & ~CIPHER_BITMAP) { + printf + ("ERR:Illegal PairwiseCipher parameter. Must be either bit '2' or '3'.\n"); + goto done; + } + } + } + if (strcmp(args[0], "GroupCipher") == 0) { + if (arg_num == 1) { + printf("ERR:GroupCipher is blank!\n"); + goto done; + } else { + if (ISDIGIT(args[1]) == 0) { + printf + ("ERR:Illegal GroupCipher parameter. Must be either bit '2' or '3'.\n"); + goto done; + } + groupcipher = atoi(args[1]); + if (groupcipher & ~CIPHER_BITMAP) { + printf + ("ERR:Illegal GroupCipher parameter. Must be either bit '2' or '3'.\n"); + goto done; + } + } + } + if (strcmp(args[0], "GroupRekeyTime") == 0) { + if (is_input_valid(GROUPREKEYTIMER, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + TLVBUF_GROUP_REKEY_TIMER *tlv = NULL; + + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_GROUP_REKEY_TIMER); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append protocol TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_GROUP_REKEY_TIMER *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_GRP_REKEY_TIME_TLV_ID; + tlv->Length = 4; + tlv->GroupRekeyTime_sec = (u32) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + tlv->GroupRekeyTime_sec = uap_cpu_to_le32(tlv->GroupRekeyTime_sec); + } + if (strcmp(args[0], "MaxStaNum") == 0) { + if (is_input_valid(MAXSTANUM, arg_num - 1, args + 1) != UAP_SUCCESS) { + goto done; + } + TLVBUF_MAX_STA_NUM *tlv = NULL; + + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_MAX_STA_NUM); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot realloc max station number TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_MAX_STA_NUM *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_MAX_STA_CNT_TLV_ID; + tlv->Length = 2; + tlv->Max_sta_num = (u16) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + tlv->Max_sta_num = uap_cpu_to_le16(tlv->Max_sta_num); + } + if (strcmp(args[0], "Retrylimit") == 0) { + if (is_input_valid(RETRYLIMIT, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + TLVBUF_RETRY_LIMIT *tlv = NULL; + + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_RETRY_LIMIT); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot realloc retry limit TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_RETRY_LIMIT *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_RETRY_LIMIT_TLV_ID; + tlv->Length = 1; + tlv->retry_limit = (u8) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + } +#if DEBUG + if (cmd_len != 0) { + hexdump("Command Buffer", (void *) cmd_buf, cmd_len, ' '); + } +#endif + } + done: + fclose(config_file); + if (buffer) + free(buffer); + if (line) + free(line); +} + +/** + * @brief Show usage information for the cfg_80211d command + * + * $return N/A + */ +void +print_apcmd_cfg_80211d_usage(void) +{ + printf("\nUsage: cfg_80211d <state 0/1> <country Country_code> \n"); + return; +} + +/** + * @brief Show usage information for the uap_stats command + * + * $return N/A + */ +void +print_apcmd_uap_stats(void) +{ + printf("Usage: uap_stats \n"); + return; +} + +/** + * SNMP MIB OIDs Table + */ +static oids_table snmp_oids[] = { + {0x0b, 4, "dot11LocalTKIPMICFailures"}, + {0x0c, 4, "dot11CCMPDecryptErrors"}, + {0x0d, 4, "dot11WEPUndecryptableCount"}, + {0x0e, 4, "dot11WEPICVErrorCount"}, + {0x0f, 4, "dot11DecryptFailureCount"}, + {0x12, 4, "dot11FailedCount"}, + {0x13, 4, "dot11RetryCount"}, + {0x14, 4, "dot11MultipleRetryCount"}, + {0x15, 4, "dot11FrameDuplicateCount"}, + {0x16, 4, "dot11RTSSuccessCount"}, + {0x17, 4, "dot11RTSFailureCount"}, + {0x18, 4, "dot11ACKFailureCount"}, + {0x19, 4, "dot11ReceivedFragmentCount"}, + {0x1a, 4, "dot11MulticastReceivedFrameCount"}, + {0x1b, 4, "dot11FCSErrorCount"}, + {0x1c, 4, "dot11TransmittedFrameCount"}, + {0x1d, 4, "dot11RSNATKIPCounterMeasuresInvoked"}, + {0x1e, 4, "dot11RSNA4WayHandshakeFailures"}, + {0x1f, 4, "dot11MulticastTransmittedFrameCount"} +}; + +/** + * @brief Get uAP stats + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * + * @return NA + */ +void +apcmd_uap_stats(int argc, char *argv[]) +{ + u8 no_of_oids = sizeof(snmp_oids) / sizeof(snmp_oids[0]); + u16 i, j; + int size; + APCMDBUF_SNMP_MIB *cmd_buf = NULL; + u8 *buf = NULL; + TLVBUF_HEADER *tlv = NULL; + u16 cmd_len = 0; + u16 buf_len = 0; + u8 ret; + int opt; + u16 oid_size; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_apcmd_uap_stats(); + return; + } + } + + argc -= optind; + argv += optind; + if (argc) { + printf("Error: Invalid Input\n"); + print_apcmd_uap_stats(); + return; + } + + /** Command Header */ + buf_len += sizeof(APCMDBUF_SNMP_MIB); + + for (i = 0; i < no_of_oids; i++) { + /** + * size of Oid + Oid_value + Oid_size + */ + buf_len += snmp_oids[i].len + sizeof(TLVBUF_HEADER); + } + buf = (u8 *) malloc(buf_len); + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + return; + } + bzero((char *) buf, buf_len); + + /* Locate Headers */ + cmd_buf = (APCMDBUF_SNMP_MIB *) buf; + cmd_buf->Size = buf_len - BUF_HEADER_SIZE; + cmd_buf->Result = 0; + cmd_buf->SeqNum = 0; + cmd_buf->CmdCode = HostCmd_SNMP_MIB; + cmd_buf->Action = uap_cpu_to_le16(ACTION_GET); + + tlv = (TLVBUF_HEADER *) ((u8 *) cmd_buf + sizeof(APCMDBUF_SNMP_MIB)); + /* Add oid, oid_size and oid_value for each OID */ + for (i = 0; i < no_of_oids; i++) { + /** Copy Index as Oid */ + tlv->Type = uap_cpu_to_le16(snmp_oids[i].type); + /** Copy its size */ + tlv->Len = uap_cpu_to_le16(snmp_oids[i].len); + /** Next TLV */ + tlv = (TLVBUF_HEADER *) & (tlv->Data[snmp_oids[i].len]); + } + cmd_len = buf_len; + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + if (ret == UAP_SUCCESS) { + if (cmd_buf->Result == CMD_SUCCESS) { + tlv = + (TLVBUF_HEADER *) ((u8 *) cmd_buf + sizeof(APCMDBUF_SNMP_MIB)); + + size = + cmd_buf->Size - (sizeof(APCMDBUF_SNMP_MIB) - BUF_HEADER_SIZE); + + while (size >= sizeof(TLVBUF_HEADER)) { + tlv->Type = uap_le16_to_cpu(tlv->Type); + for (i = 0; i < no_of_oids; i++) { + if (snmp_oids[i].type == tlv->Type) { + printf("%s: ", snmp_oids[i].name); + break; + } + } + oid_size = uap_le16_to_cpu(tlv->Len); + switch (oid_size) { + case 1: + printf("%d", (unsigned int) tlv->Data[0]); + break; + case 2: + printf("%d", + (unsigned int) uap_le16_to_cpu(*(u16 *) tlv->Data)); + break; + case 4: + printf("%ld", + (unsigned long) uap_le32_to_cpu(*(u32 *) tlv->Data)); + break; + default: + for (j = 0; j < oid_size; j++) { + printf("%d ", (u8) tlv->Data[i]); + } + break; + } + /** Next TLV */ + tlv = (TLVBUF_HEADER *) & (tlv->Data[oid_size]); + size -= (sizeof(TLVBUF_HEADER) + oid_size); + size = (size > 0) ? size : 0; + printf("\n"); + } + + } else { + printf("ERR:Command Response incorrect!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + free(buf); +} + +/** + * @brief parser for sys_cfg_80211d input + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @param output stores indexes for "state, country" + * arguments + * + * @return NA + * + */ +void +parse_input_80211d(int argc, char **argv, int output[2][2]) +{ + int i, j, k = 0; + char *keywords[2] = { "state", "country" }; + + for (i = 0; i < 2; i++) + output[i][0] = -1; + + for (i = 0; i < argc; i++) { + for (j = 0; j < 2; j++) { + if (strcmp(argv[i], keywords[j]) == 0) { + output[j][1] = output[j][0] = i; + k = j; + break; + } + } + output[k][1] += 1; + } +} + +/** + * @brief Set/Get 802.11D country information + * + * Usage: cfg_80211d state country_code + * + * State 0 or 1 + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_cfg_80211d(int argc, char *argv[]) +{ + APCMDBUF_CFG_80211D *cmd_buf = NULL; + IEEEtypes_SubbandSet_t *subband = NULL; + u8 *buf = NULL; + u16 cmd_len; + u16 buf_len; + int output[2][2]; + int ret = UAP_FAILURE; + int opt; + int i, j; + u8 state = 0; + char country[4] = { ' ', ' ', 0, 0 }; + u8 sflag = 0, cflag = 0; + IEEEtypes_SubbandSet_t sub_bands[MAX_SUB_BANDS]; + u8 no_of_sub_band = 0; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_apcmd_cfg_80211d_usage(); + return; + } + } + argc -= optind; + argv += optind; + + if (argc) { + /** SET */ + parse_input_80211d(argc, argv, output); + + /** state */ + if ((output[0][0] != -1) && (output[0][1] > output[0][0])) { + if ((output[0][1] - output[0][0]) != 2) { + printf("ERR: Invalid state inputs\n"); + print_apcmd_cfg_80211d_usage(); + return; + } + + if (IS_HEX_OR_DIGIT(argv[output[0][0] + 1]) == UAP_FAILURE) { + printf("ERR: valid input for state are 0 or 1\n"); + print_apcmd_cfg_80211d_usage(); + return; + } + state = (u8) A2HEXDECIMAL(argv[output[0][0] + 1]); + + if ((state != 0) && (state != 1)) { + printf("ERR: valid input for state are 0 or 1 \n"); + print_apcmd_cfg_80211d_usage(); + return; + } + sflag = 1; + } + + /** country */ + if ((output[1][0] != -1) && (output[1][1] > output[1][0])) { + if ((output[1][1] - output[1][0]) > 2) { + printf("ERR: Invalid country inputs\n"); + print_apcmd_cfg_80211d_usage(); + return; + } + if ((strlen(argv[output[1][0] + 1]) > 3) || + (strlen(argv[output[1][0] + 1]) < 0)) { + print_apcmd_cfg_80211d_usage(); + return; + } + + strcpy(country, argv[output[1][0] + 1]); + + for (i = 0; i < strlen(country); i++) { + if ((country[i] < 'A') || (country[i] > 'z')) { + printf("Invalid Country Code\n"); + print_apcmd_cfg_80211d_usage(); + return; + } + if (country[i] > 'Z') + country[i] = country[i] - 'a' + 'A'; + } + + cflag = 1; + + /** Get domain information from the file */ + no_of_sub_band = parse_domain_file(country, sub_bands); + if (no_of_sub_band == UAP_FAILURE) { + printf("Parsing Failed\n"); + return; + } + } + } + + if (argc && !cflag && !sflag) { + printf("ERR: Invalid input\n"); + print_apcmd_cfg_80211d_usage(); + return; + } + + if (sflag && !cflag) { + /** + * Update MIB only and return + */ + if (sg_snmp_mib(ACTION_SET, OID_80211D_ENABLE, sizeof(state), &state) == + UAP_SUCCESS) { + printf("802.11d %sd \n", state ? "enable" : "disable"); + } + return; + } + + buf_len = sizeof(APCMDBUF_CFG_80211D); + + if (cflag) { + buf_len += no_of_sub_band * sizeof(IEEEtypes_SubbandSet_t); + } else { /** Get */ + buf_len += MAX_SUB_BANDS * sizeof(IEEEtypes_SubbandSet_t); + } + + buf = (u8 *) malloc(buf_len); + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + return; + } + bzero((char *) buf, buf_len); + /* Locate headers */ + cmd_buf = (APCMDBUF_CFG_80211D *) buf; + cmd_len = argc ? buf_len : + /** set */ + (sizeof(APCMDBUF_CFG_80211D) - sizeof(domain_param_t)); /** Get */ + + cmd_buf->Size = cmd_len - BUF_HEADER_SIZE; + cmd_buf->Result = 0; + cmd_buf->SeqNum = 0; + cmd_buf->Action = argc ? ACTION_SET : ACTION_GET; + cmd_buf->Action = uap_cpu_to_le16(cmd_buf->Action); + cmd_buf->CmdCode = HostCmd_CMD_802_11D_DOMAIN_INFO; + + if (cflag) { + cmd_buf->Domain.Tag = uap_cpu_to_le16(TLV_TYPE_DOMAIN); + cmd_buf->Domain.Length = uap_cpu_to_le16(sizeof(domain_param_t) + - BUF_HEADER_SIZE + + + (no_of_sub_band * + sizeof + (IEEEtypes_SubbandSet_t))); + + memset(cmd_buf->Domain.CountryCode, ' ', + sizeof(cmd_buf->Domain.CountryCode)); + memcpy(cmd_buf->Domain.CountryCode, country, strlen(country)); + memcpy(cmd_buf->Domain.Subband, sub_bands, + no_of_sub_band * sizeof(IEEEtypes_SubbandSet_t)); + } + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + if (ret == UAP_SUCCESS) { + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc) { + printf("Set executed successfully\n"); + if (sflag) { + if (sg_snmp_mib + (ACTION_SET, OID_80211D_ENABLE, sizeof(state), + &state) == UAP_SUCCESS) { + printf("802.11d %sd \n", state ? "enable" : "disable"); + } + } + } else { + j = uap_le16_to_cpu(cmd_buf->Domain.Length); + if (sg_snmp_mib + (ACTION_GET, OID_80211D_ENABLE, sizeof(state), &state) + == UAP_SUCCESS) { + printf("State = %sd\n", state ? "enable" : "disable"); + } + + if (!(cmd_buf->Domain.CountryCode[0] | + cmd_buf->Domain.CountryCode[1] | + cmd_buf->Domain.CountryCode[2])) { + printf("Dot11d = country code is not set.\n"); + } else { + printf("Country string = %c%c%c", + cmd_buf->Domain.CountryCode[0], + cmd_buf->Domain.CountryCode[1], + cmd_buf->Domain.CountryCode[2]); + j -= sizeof(cmd_buf->Domain.CountryCode); + subband = + (IEEEtypes_SubbandSet_t *) cmd_buf->Domain.Subband; + printf("\nSub-band info="); + // printf("\n\t\t(First Channel, Number of Channels, + // Maximum TX Power) \n"); + printf("\t(1st, #chan, MAX-power) \n"); + for (i = 0; i < (j / 3); i++) { + printf("\t\t(%d, \t%d, \t%d dbm)\n", subband->FirstChan, + subband->NoOfChan, subband->MaxTxPwr); + subband++; + } + } + } + } else { + printf("ERR:Command Response incorrect!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + free(buf); + return; +} + +/** + * @brief Creates a sys_config request and sends to the driver + * + * Usage: "Usage : sys_config [CONFIG_FILE]" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return UAP_SUCCESS or UAP_FAILURE + */ +void +apcmd_sys_config(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + u8 *buf = NULL; + u16 cmd_len; + u16 buf_len; + int ret = UAP_FAILURE; + int opt; + char **argv_dummy; + ps_mgmt pm; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_config_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc > 1) { + printf("ERR:Too many arguments.\n"); + print_sys_config_usage(); + return; + } + if (argc == 1) { + /* Read profile and send command to firmware */ + apcmd_sys_config_profile(argc, argv); + return; + } + + /** Query AP's setting */ + buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; + + /* alloc buf for command */ + buf = (u8 *) malloc(buf_len); + + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + return; + } + bzero((char *) buf, buf_len); + + /* Locate headers */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE); + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buf; + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len - BUF_HEADER_SIZE; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response!\n"); + free(buf); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + printf("AP settings:\n"); + print_tlv(buf + sizeof(APCMDBUF_SYS_CONFIGURE), + cmd_buf->Size - sizeof(APCMDBUF_SYS_CONFIGURE) + + BUF_HEADER_SIZE); + printf("\n802.11D setting:\n"); + apcmd_cfg_80211d(1, argv_dummy); + } else { + printf("ERR:Could not retrieve system configure\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + free(buf); + memset(&pm, 0, sizeof(ps_mgmt)); + send_power_mode_ioctl(&pm); + return; +} + +/** + * @brief Send read/write command along with register details to the driver + * @param reg reg type + * @param offset pointer to register offset string + * @param strvalue pointer to value string + * @return UAP_SUCCESS or UAP_FAILURE + */ +int +apcmd_regrdwr_process(int reg, s8 * offset, s8 * strvalue) +{ + APCMDBUF_REG_RDWR *cmd_buf = NULL; + u8 *buf = NULL; + u16 cmd_len; + u16 buf_len; + int ret = UAP_FAILURE; + s8 *whichreg; + + buf_len = sizeof(APCMDBUF_REG_RDWR); + + /* alloc buf for command */ + buf = (u8 *) malloc(buf_len); + + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + return UAP_FAILURE; + } + bzero((char *) buf, buf_len); + + /* Locate headers */ + cmd_len = sizeof(APCMDBUF_REG_RDWR); + cmd_buf = (APCMDBUF_REG_RDWR *) buf; + + /* Fill the command buffer */ + cmd_buf->Size = cmd_len - BUF_HEADER_SIZE; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + + switch (reg) { + case CMD_MAC: + whichreg = "MAC"; + cmd_buf->CmdCode = HostCmd_CMD_MAC_REG_ACCESS; + break; + case CMD_BBP: + whichreg = "BBP"; + cmd_buf->CmdCode = HostCmd_CMD_BBP_REG_ACCESS; + break; + case CMD_RF: + cmd_buf->CmdCode = HostCmd_CMD_RF_REG_ACCESS; + whichreg = "RF"; + break; + default: + printf("Invalid register set specified.\n"); + free(buf); + return UAP_FAILURE; + } + if (strvalue) { + cmd_buf->Action = 1; // WRITE + } else { + cmd_buf->Action = 0; // READ + } + cmd_buf->Action = uap_cpu_to_le16(cmd_buf->Action); + cmd_buf->Offset = A2HEXDECIMAL(offset); + cmd_buf->Offset = uap_cpu_to_le16(cmd_buf->Offset); + if (strvalue) { + cmd_buf->Value = A2HEXDECIMAL(strvalue); + cmd_buf->Value = uap_cpu_to_le32(cmd_buf->Value); + } + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + if (cmd_buf->Result == CMD_SUCCESS) { + printf("Successfully executed the command\n"); + printf("%s[0x%04hx] = 0x%08lx\n", + whichreg, uap_le16_to_cpu(cmd_buf->Offset), + uap_le32_to_cpu(cmd_buf->Value)); + } else { + printf("ERR:Command sending failed!\n"); + free(buf); + return UAP_FAILURE; + } + } else { + printf("ERR:Command sending failed!\n"); + free(buf); + return UAP_FAILURE; + } + + free(buf); + return UAP_SUCCESS; +} + +/** + * @brief Send read command for EEPROM + * + * Usage: "Usage : rdeeprom <offset> <byteCount>" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_read_eeprom(int argc, char *argv[]) +{ + APCMDBUF_EEPROM_ACCESS *cmd_buf = NULL; + u8 *buf = NULL; + u16 cmd_len; + u16 buf_len; + u16 byteCount, offset; + int ret = UAP_FAILURE; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_apcmd_read_eeprom_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (!argc || (argc && is_input_valid(RDEEPROM, argc, argv) != UAP_SUCCESS)) { + print_apcmd_read_eeprom_usage(); + return; + } + offset = A2HEXDECIMAL(argv[0]); + byteCount = A2HEXDECIMAL(argv[1]); + + buf_len = sizeof(APCMDBUF_EEPROM_ACCESS) + MAX_EEPROM_LEN; + buf = (u8 *) malloc(buf_len); + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + return; + } + bzero((char *) buf, buf_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_EEPROM_ACCESS *) buf; + cmd_len = sizeof(APCMDBUF_EEPROM_ACCESS); + + cmd_buf->Size = sizeof(APCMDBUF_EEPROM_ACCESS) - BUF_HEADER_SIZE; + cmd_buf->Result = 0; + cmd_buf->SeqNum = 0; + cmd_buf->Action = 0; + + cmd_buf->CmdCode = HostCmd_EEPROM_ACCESS; + cmd_buf->Offset = uap_cpu_to_le16(offset); + cmd_buf->ByteCount = uap_cpu_to_le16(byteCount); + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + if (cmd_buf->Result == CMD_SUCCESS) { + printf("Successfully executed the command\n"); + byteCount = uap_le16_to_cpu(cmd_buf->ByteCount); + offset = uap_le16_to_cpu(cmd_buf->Offset); + hexdump_data("EEPROM", (void *) cmd_buf->Value, byteCount, ' '); + } else { + printf("ERR:Command Response incorrect!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + + free(buf); + return; +} + +/** + * @brief Show usage information for the regrdwr command + * command + * + * $return N/A + */ +void +print_regrdwr_usage(void) +{ + printf("\nUsage : uaputl.exe regrdwr <TYPE> <OFFSET> [value]\n"); + printf("\nTYPE Options: 0 - read/write MAC register"); + printf("\n 1 - read/write BBP register"); + printf("\n 2 - read/write RF register"); + printf("\n"); + return; + +} + +/** + * @brief Provides interface to perform read/write operations on regsiters + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_regrdwr(int argc, char *argv[]) +{ + int opt; + s32 reg; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_regrdwr_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if ((argc < 2) || (argc > 3)) { + printf("ERR:wrong arguments.\n"); + print_regrdwr_usage(); + return; + } + if ((atoi(argv[0]) != 0) && (atoi(argv[0]) != 1) && (atoi(argv[0]) != 2)) { + printf("ERR:Illegal register type %s. Must be either '0','1' or '2'.\n", + argv[0]); + print_regrdwr_usage(); + return; + } + reg = atoi(argv[0]); + apcmd_regrdwr_process(reg, argv[1], argc > 2 ? argv[2] : NULL); + return; +} + +/** + * @brief Show usage information for the memaccess command + * command + * + * $return N/A + */ +void +print_memaccess_usage(void) +{ + printf("\nUsage : uaputl.exe memaccess <ADDRESS> [value]\n"); + printf("\nRead/Write memory location"); + printf("\nADDRESS: Address of the memory location to be read/written"); + printf("\nValue : Value to be written at that address\n"); + return; +} + +/** + * @brief Provides interface to perform read/write memory location + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_memaccess(int argc, char *argv[]) +{ + int opt; + APCMDBUF_MEM_ACCESS *cmd_buf = NULL; + u8 *buf = NULL; + u16 cmd_len; + u16 buf_len; + int ret = UAP_FAILURE; + s8 *address = NULL; + s8 *value = NULL; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_memaccess_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if ((argc < 1) || (argc > 2)) { + printf("ERR:wrong arguments.\n"); + print_memaccess_usage(); + return; + } + + address = argv[0]; + if (argc == 2) + value = argv[1]; + + buf_len = sizeof(APCMDBUF_MEM_ACCESS); + + /* alloc buf for command */ + buf = (u8 *) malloc(buf_len); + + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + return; + } + bzero((char *) buf, buf_len); + /* Locate headers */ + cmd_len = sizeof(APCMDBUF_MEM_ACCESS); + cmd_buf = (APCMDBUF_MEM_ACCESS *) buf; + + /* Fill the command buffer */ + cmd_buf->Size = cmd_len - BUF_HEADER_SIZE; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + cmd_buf->CmdCode = HostCmd_CMD_MEM_ACCESS; + + if (value) + cmd_buf->Action = 1; // WRITE + else + cmd_buf->Action = 0; // READ + + cmd_buf->Action = uap_cpu_to_le16(cmd_buf->Action); + cmd_buf->Address = A2HEXDECIMAL(address); + cmd_buf->Address = uap_cpu_to_le32(cmd_buf->Address); + + if (value) { + cmd_buf->Value = A2HEXDECIMAL(value); + cmd_buf->Value = uap_cpu_to_le32(cmd_buf->Value); + } + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + if (cmd_buf->Result == CMD_SUCCESS) { + printf("Successfully executed the command\n"); + printf("[0x%04lx] = 0x%08lx\n", + uap_le32_to_cpu(cmd_buf->Address), + uap_le32_to_cpu(cmd_buf->Value)); + } else { + printf("ERR:Command sending failed!\n"); + free(buf); + return; + } + } else { + printf("ERR:Command sending failed!\n"); + free(buf); + return; + } + free(buf); + return; +} + +/** + * @brief Show usage information for sys_debug command + * command + * + * $return N/A + */ +void +print_sys_debug_usage(void) +{ + printf("\nUsage : uaputl.exe sys_debug <subcmd> [parameter]\n"); + printf("\nSet/Get debug parameter"); + printf("\nsubcmd: used to set/get debug parameters or set user scan"); + printf("\nparameter : parameters for specific subcmd"); + printf("\n If no [parameter] are given, it return"); + printf("\n debug parameters for selected subcmd"); + printf("\n\n"); + return; +} + +/** + * @brief Creates a sys_debug request and sends to the driver + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_debug(int argc, char *argv[]) +{ + APCMDBUF_SYS_DEBUG *cmd_buf = NULL; + u8 *buffer = NULL; + u16 cmd_len; + u16 buf_len; + u32 subcmd = 0; + int ret = UAP_FAILURE; + int opt; + s8 *value = NULL; + u32 parameter = 0; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_debug_usage(); + return; + } + } + argc -= optind; + argv += optind; + /* Check arguments */ + if ((argc == 0) || (argc > 2)) { + printf("ERR:wrong arguments.\n"); + print_sys_debug_usage(); + return; + } else { + if (argc == 2) { + value = argv[1]; + parameter = A2HEXDECIMAL(value); + } + } + subcmd = atoi(argv[0]); + /* Initialize the command length */ + if (subcmd == DEBUG_SUBCOMMAND_CHANNEL_SCAN) { + buf_len = + sizeof(APCMDBUF_SYS_DEBUG) + + MAX_CHANNELS * sizeof(CHANNEL_SCAN_ENTRY_T); + cmd_len = sizeof(APCMDBUF_SYS_DEBUG) - sizeof(debugConfig_t); + } else { + cmd_len = sizeof(APCMDBUF_SYS_DEBUG); + buf_len = cmd_len; + } + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(buf_len); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, buf_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_DEBUG *) buffer; + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_DEBUG; + cmd_buf->Size = cmd_len - BUF_HEADER_SIZE; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + cmd_buf->subcmd = subcmd; + if (subcmd == DEBUG_SUBCOMMAND_CHANNEL_SCAN) { + cmd_buf->Action = ACTION_SET; + } else { + if (argc == 1) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + if (subcmd == DEBUG_SUBCOMMAND_GMODE) + cmd_buf->debugConfig.globalDebugMode = (u8) parameter; + else if (subcmd == DEBUG_SUBCOMMAND_MAJOREVTMASK) { + cmd_buf->debugConfig.debugMajorIdMask = parameter; + cmd_buf->debugConfig.debugMajorIdMask = + uap_cpu_to_le32(cmd_buf->debugConfig.debugMajorIdMask); + } else { + cmd_buf->debugConfig.value = uap_cpu_to_le32(parameter); + } + } + } + cmd_buf->Action = uap_cpu_to_le16(cmd_buf->Action); + cmd_buf->subcmd = uap_cpu_to_le32(cmd_buf->subcmd); + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (cmd_buf->CmdCode != (APCMD_SYS_DEBUG | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response! CmdCode=%x\n", cmd_buf->CmdCode); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (subcmd == DEBUG_SUBCOMMAND_CHANNEL_SCAN) { + int i = 0; + CHANNEL_SCAN_ENTRY_T *cst = NULL; + if (cmd_buf->Size < + (sizeof(APCMDBUF_SYS_DEBUG) - BUF_HEADER_SIZE)) { + printf + ("ERR: Invalid command response size, cmd_buf->Size = %x\n", + cmd_buf->Size); + free(buffer); + return; + } + for (i = 0; i < cmd_buf->debugConfig.cs_entry.numChannels; i++) { + if (i == 0) { + printf + ("\n------------------------------------------------------"); + printf("\nChan\tNumAPs\tCCA_Count\tDuration\tWeight"); + printf + ("\n------------------------------------------------------"); + cst = cmd_buf->debugConfig.cs_entry.cst; + } + printf("\n%d\t%d\t%ld\t\t%ld\t\t%ld", cst->chan_num, + cst->num_of_aps, + cst->CCA_count, cst->duration, cst->channel_weight); + cst++; + } + printf + ("\n------------------------------------------------------\n"); + } else { + if (argc == 1) { + if (subcmd == DEBUG_SUBCOMMAND_GMODE) { + printf("globalDebugmode=%d\n", + cmd_buf->debugConfig.globalDebugMode); + } else if (subcmd == DEBUG_SUBCOMMAND_MAJOREVTMASK) { + printf("MajorId mask=0x%08lx\n", + uap_le32_to_cpu(cmd_buf->debugConfig. + debugMajorIdMask)); + } else { + printf("Value = %ld\n", + uap_le32_to_cpu(cmd_buf->debugConfig.value)); + } + } else { + printf("set debug parameter successful\n"); + } + } + } else { + if (argc == 1) { + printf("ERR:Could not get debug parameter!\n"); + } else { + printf("ERR:Could not set debug parameter!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** structure of command table*/ +typedef struct +{ + /** command name */ + char *cmd; + /** command function pointer */ + void (*func) (int argc, char *argv[]); + /**command usuage */ + char *help; +} command_table; + +/** ap command table */ +static command_table ap_command[] = { + {"sys_config", apcmd_sys_config, "\tSet/get uAP's profile"}, + {"sys_info", apcmd_sys_info, "\tDisplay system info"}, + {"sys_reset", apcmd_sys_reset, "\tReset uAP"}, + {"bss_start", apcmd_bss_start, "\tStart the BSS"}, + {"bss_stop", apcmd_bss_stop, "\tStop the BSS"}, + {"sta_deauth", apcmd_sta_deauth, "\tDeauth client"}, + {"sta_list", apcmd_sta_list, "\tDisplay list of clients"}, + {"sys_cfg_ap_mac_address", apcmd_sys_cfg_ap_mac_address, + "Set/get uAP mac address"}, + {"sys_cfg_ssid", apcmd_sys_cfg_ssid, "\tSet/get uAP ssid"}, + {"sys_cfg_beacon_period", apcmd_sys_cfg_beacon_period, + "Set/get uAP beacon period"}, + {"sys_cfg_dtim_period", apcmd_sys_cfg_dtim_period, + "Set/get uAP dtim period"}, + {"sys_cfg_channel", apcmd_sys_cfg_channel, "\tSet/get uAP radio channel"}, + {"sys_cfg_scan_channels", apcmd_sys_cfg_scan_channels, + "Set/get uAP radio channel list"}, + {"sys_cfg_rates", apcmd_sys_cfg_rates, "\tSet/get uAP rates"}, + {"sys_cfg_rates_ext", apcmd_sys_cfg_rates_ext, + "Set/get uAP rates (extended)"}, + {"sys_cfg_tx_power", apcmd_sys_cfg_tx_power, "Set/get uAP tx power"}, + {"sys_cfg_bcast_ssid_ctl", apcmd_sys_cfg_bcast_ssid_ctl, + "Set/get uAP broadcast ssid"}, + {"sys_cfg_preamble_ctl", apcmd_sys_cfg_preamble_ctl, "Get uAP preamble"}, + {"sys_cfg_antenna_ctl", apcmd_sys_cfg_antenna_ctl, + "Set/get uAP tx/rx antenna"}, + {"sys_cfg_rts_threshold", apcmd_sys_cfg_rts_threshold, + "Set/get uAP rts threshold"}, + {"sys_cfg_frag_threshold", apcmd_sys_cfg_frag_threshold, + "Set/get uAP frag threshold"}, + {"sys_cfg_radio_ctl", apcmd_sys_cfg_radio_ctl, "Set/get uAP radio on/off"}, + {"sys_cfg_tx_data_rate", apcmd_sys_cfg_tx_data_rate, "Set/get uAP tx rate"}, + {"sys_cfg_mcbc_data_rate", apcmd_sys_cfg_mcbc_data_rate, + "Set/get uAP MCBC rate"}, + {"sys_cfg_rsn_replay_prot", apcmd_sys_cfg_rsn_replay_prot, + "Set/get RSN replay protection"}, + {"sys_cfg_pkt_fwd_ctl", apcmd_sys_cfg_pkt_fwd_ctl, + "Set/get uAP packet forwarding"}, + {"sys_cfg_sta_ageout_timer", apcmd_sys_cfg_sta_ageout_timer, + "Set/get station ageout timer"}, + {"sys_cfg_auth", apcmd_sys_cfg_auth, "\tSet/get uAP authentication mode"}, + {"sys_cfg_protocol", apcmd_sys_cfg_protocol, + "Set/get uAP security protocol"}, + {"sys_cfg_wep_key", apcmd_sys_cfg_wep_key, "\tSet/get uAP wep key"}, + {"sys_cfg_cipher", apcmd_sys_cfg_cipher, "\tSet/get uAP WPA/WPA cipher"}, + {"sys_cfg_wpa_passphrase", apcmd_sys_cfg_wpa_passphrase, + "Set/get uAP WPA or WPA2 passphrase"}, + {"sys_cfg_group_rekey_timer", apcmd_sys_cfg_group_rekey_timer, + "Set/get uAP group re-key time"}, + {"sys_cfg_max_sta_num", apcmd_sys_cfg_max_sta_num, + "Set/get uAP max station number"}, + {"sys_cfg_retry_limit", apcmd_sys_cfg_retry_limit, + "Set/get uAP retry limit number"}, + {"sys_cfg_custom_ie", apcmd_sys_cfg_custom_ie, + "\tSet/get custom IE configuration"}, + {"sta_filter_table", apcmd_sta_filter_table, "Set/get uAP mac filter"}, + {"regrdwr", apcmd_regrdwr, "\t\tRead/Write register command"}, + {"memaccess", apcmd_memaccess, "\tRead/Write to a memory address command"}, + {"rdeeprom", apcmd_read_eeprom, "\tRead EEPROM "}, + {"cfg_data", apcmd_cfg_data, + "\tGet/Set configuration file from/to firmware"}, + {"sys_debug", apcmd_sys_debug, "\tSet/Get debug parameter"}, + {"sys_cfg_80211d", apcmd_cfg_80211d, "\tSet/Get 802.11D info"}, + {"uap_stats", apcmd_uap_stats, "\tGet uAP stats"}, + {"powermode", apcmd_power_mode, "\tSet/get uAP power mode"}, + {"coex_config", apcmd_coex_config, "\tSet/get uAP BT coex configuration"}, + {NULL, NULL, 0} +}; + +/** + * @brief Prints usage information of uaputl + * + * @return N/A + */ +static void +print_tool_usage(void) +{ + int i; + printf("uaputl.exe - uAP utility ver %s\n", UAP_VERSION); + printf("Usage:\n" + "\tuaputl.exe [options] <command> [command parameters]\n"); + printf("Options:\n" + "\t--help\tDisplay help\n" + "\t-v\tDisplay version\n" + "\t-i <interface>\n" "\t-d <debug_level=0|1|2>\n"); + printf("Commands:\n"); + for (i = 0; ap_command[i].cmd; i++) + printf("\t%-4s\t\t%s\n", ap_command[i].cmd, ap_command[i].help); + printf("\n" + "For more information on the usage of each command use:\n" + "\tuaputl.exe <command> --help\n"); +} + +/**************************************************************************** + Global functions +****************************************************************************/ +/** option parameter*/ +static struct option ap_options[] = { + {"help", 0, NULL, 'h'}, + {"interface", 1, NULL, 'i'}, + {"debug", 1, NULL, 'd'}, + {"version", 0, NULL, 'v'}, + {NULL, 0, NULL, '\0'} +}; + +/** + * @brief isdigit for String. + * + * @param x char string + * @return UAP_FAILURE for non-digit. + * UAP_SUCCESS for digit + */ +inline int +ISDIGIT(char *x) +{ + int i; + for (i = 0; i < strlen(x); i++) + if (isdigit(x[i]) == 0) + return UAP_FAILURE; + return UAP_SUCCESS; +} + +/** + * @brief Checkes a particular input for validatation. + * + * @param cmd Type of input + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return UAP_SUCCESS or UAP_FAILURE + */ +int +is_input_valid(valid_inputs cmd, int argc, char *argv[]) +{ + int i; + int ret = UAP_SUCCESS; + if (argc == 0) + return UAP_FAILURE; + switch (cmd) { + case RDEEPROM: + if (argc != 2) { + printf(" ERR: Argument count mismatch\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || (ISDIGIT(argv[1]) == 0) || + (A2HEXDECIMAL(argv[0]) & 0x03) || + (A2HEXDECIMAL(argv[0]) < 0) || + (A2HEXDECIMAL(argv[1]) & 0x03) || + (A2HEXDECIMAL(argv[1]) < 4) || (A2HEXDECIMAL(argv[1]) > 20)) { + printf(" ERR: Invalid inputs for Read EEPROM\n"); + ret = UAP_FAILURE; + } + } + break; + case SCANCHANNELS: + if (argc > MAX_CHANNELS) { + printf("ERR: Invalid List of Channels\n"); + ret = UAP_FAILURE; + } else { + for (i = 0; i < argc; i++) { + if ((ISDIGIT(argv[i]) == 0) || (atoi(argv[i]) < 1) || + (atoi(argv[i]) > MAX_CHANNELS)) { + printf("ERR: Channel must be in the range of 1 to %d\n", + MAX_CHANNELS); + ret = UAP_FAILURE; + break; + } + } + if ((ret != UAP_FAILURE) && + (has_dup_channel(argc, argv) != UAP_SUCCESS)) { + printf("ERR: Duplicate channel values entered\n"); + ret = UAP_FAILURE; + } + } + break; + case TXPOWER: + if ((argc > 1) || (ISDIGIT(argv[0]) == 0)) { + printf("ERR:Invalid Transmit power\n"); + ret = UAP_FAILURE; + } else { + if ((atoi(argv[0]) < MIN_TX_POWER) || + (atoi(argv[0]) > MAX_TX_POWER)) { + printf("ERR: TX Powar must be in the rage of %d to %d. \n", + MIN_TX_POWER, MAX_TX_POWER); + ret = UAP_FAILURE; + } + } + break; + case PROTOCOL: + if ((argc > 1) || (ISDIGIT(argv[0]) == 0)) { + printf("ERR:Invalid Protocol\n"); + ret = UAP_FAILURE; + } else + ret = is_protocol_valid(atoi(argv[0])); + break; + case CHANNEL: + if ((argc != 1) && (argc != 2)) { + printf("ERR: Incorrect arguments for channel.\n"); + ret = UAP_FAILURE; + } else { + if (argc == 2) { + if ((ISDIGIT(argv[1]) == 0) || (atoi(argv[1]) < 0) || + (atoi(argv[1]) > 1)) { + printf("ERR: MODE must be either 0 or 1\n"); + ret = UAP_FAILURE; + } + if ((atoi(argv[1]) == 1) && (atoi(argv[0]) != 0)) { + printf("ERR: Channel must be 0 for ACS; MODE = 1.\n"); + ret = UAP_FAILURE; + } + } + if ((argc == 1) || (atoi(argv[1]) == 0)) { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 1) || + (atoi(argv[0]) > MAX_CHANNELS)) { + printf("ERR: Channel must be in the range of 1 to %d\n", + MAX_CHANNELS); + ret = UAP_FAILURE; + } + } + } + break; + case RATE: + if (argc > MAX_RATES) { + printf("ERR: Incorrect number of RATES arguments.\n"); + ret = UAP_FAILURE; + } else { + for (i = 0; i < argc; i++) { + if ((IS_HEX_OR_DIGIT(argv[i]) == UAP_FAILURE) || + (is_rate_valid(A2HEXDECIMAL(argv[i]) & ~BASIC_RATE_SET_BIT) + != UAP_SUCCESS)) { + printf("ERR:Unsupported rate.\n"); + ret = UAP_FAILURE; + break; + } + } + if ((ret != UAP_FAILURE) && + (has_dup_rate(argc, argv) != UAP_SUCCESS)) { + printf("ERR: Duplicate rate values entered\n"); + ret = UAP_FAILURE; + } + if (check_mandatory_rates(argc, argv) != UAP_SUCCESS) { + ret = UAP_FAILURE; + } + } + break; + case BROADCASTSSID: + if (argc != 1) { + printf("ERR:wrong BROADCASTSSID arguments.\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || + ((atoi(argv[0]) != 0) && (atoi(argv[0]) != 1))) { + printf + ("ERR:Illegal parameter %s for BROADCASTSSID. Must be either '0' or '1'.\n", + argv[0]); + ret = UAP_FAILURE; + } + } + break; + case RTSTHRESH: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for RTSTHRESHOLD\n"); + ret = UAP_FAILURE; + } else if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || + (atoi(argv[0]) > MAX_RTS_THRESHOLD)) { + printf + ("ERR:Illegal RTSTHRESHOLD %s. The value must between 0 and %d\n", + argv[0], MAX_RTS_THRESHOLD); + ret = UAP_FAILURE; + } + break; + case FRAGTHRESH: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for FRAGTHRESH\n"); + ret = UAP_FAILURE; + } else if ((ISDIGIT(argv[0]) == 0) || + (atoi(argv[0]) < MIN_FRAG_THRESHOLD) || + (atoi(argv[0]) > MAX_FRAG_THRESHOLD)) { + printf + ("ERR:Illegal FRAGTHRESH %s. The value must between %d and %d\n", + argv[0], MIN_FRAG_THRESHOLD, MAX_FRAG_THRESHOLD); + ret = UAP_FAILURE; + } + break; + case DTIMPERIOD: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for DTIMPERIOD\n"); + ret = UAP_FAILURE; + } else if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 1) || + (atoi(argv[0]) > MAX_DTIM_PERIOD)) { + printf("ERR: DTIMPERIOD Value must be in range of 1 to %d\n", + MAX_DTIM_PERIOD); + ret = UAP_FAILURE; + } + break; + case RADIOCONTROL: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for RADIOCONTROL\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || + (atoi(argv[0]) > 1)) { + printf + ("ERR:Illegal RADIOCONTROL parameter %s. Must be either '0' or '1'.\n", + argv[0]); + ret = UAP_FAILURE; + } + } + break; + case RSNREPLAYPROT: + if (argc != 1) { + printf("ERR:wrong RSNREPLAYPROT arguments.\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || + ((atoi(argv[0]) != 0) && (atoi(argv[0]) != 1))) { + printf + ("ERR:Illegal parameter %s for RSNREPLAYPROT. Must be either '0' or '1'.\n", + argv[0]); + ret = UAP_FAILURE; + } + } + break; + case MCBCDATARATE: + case TXDATARATE: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for DATARATE\n"); + ret = UAP_FAILURE; + } else { + if (IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) { + printf("ERR: invalid data rate\n"); + ret = UAP_FAILURE; + } else if ((A2HEXDECIMAL(argv[0]) != 0) && + (is_rate_valid + (A2HEXDECIMAL(argv[0]) & ~BASIC_RATE_SET_BIT) != + UAP_SUCCESS)) { + printf("ERR: invalid data rate\n"); + ret = UAP_FAILURE; + } + } + break; + case PKTFWD: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for PKTFWD.\n"); + ret = UAP_FAILURE; + } else if ((ISDIGIT(argv[0]) == 0) || + ((atoi(argv[0]) != 0) && (atoi(argv[0]) != 1))) { + printf + ("ERR:Illegal PKTFWD parameter %s. Must be either '0' or '1'.\n", + argv[0]); + ret = UAP_FAILURE; + } + break; + case STAAGEOUTTIMER: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for STAAGEOUTTIMER.\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || ((atoi(argv[0]) != 0) && + ((atoi(argv[0]) < + MIN_STAGE_OUT_TIME) || + (atoi(argv[0]) > + MAX_STAGE_OUT_TIME)))) { + printf + ("ERR:Illegal STAAGEOUTTIMER %s. Must be between %d and %d.\n", + argv[0], MIN_STAGE_OUT_TIME, MAX_STAGE_OUT_TIME); + ret = UAP_FAILURE; + } + } + break; + case AUTHMODE: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for AUTHMODE\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || + (atoi(argv[0]) > 1)) { + printf + ("ERR:Illegal AUTHMODE parameter %s. Must be either '0', or '1'.\n", + argv[0]); + ret = UAP_FAILURE; + } + } + break; + case GROUPREKEYTIMER: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for GROUPREKEYTIMER.\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || + (atoi(argv[0]) > MAX_GRP_TIMER)) { + printf("ERR: GROUPREKEYTIMER range is [0:%d] (0 for disable)\n", + MAX_GRP_TIMER); + ret = UAP_FAILURE; + } + } + break; + case MAXSTANUM: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for MAXSTANUM\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) > 8) || + (atoi(argv[0]) < 0)) { + printf("ERR:STA_NUM must be in the range of [0:8] %s.\n", + argv[0]); + ret = UAP_FAILURE; + } + } + break; + case BEACONPERIOD: + if (argc != 1) { + printf("ERR:Incorrect number of argument for BEACONPERIOD.\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < MIN_BEACON_PERIOD) + || (atoi(argv[0]) > MAX_BEACON_PERIOD)) { + printf("ERR: BEACONPERIOD must be in range of %d to %d.\n", + MIN_BEACON_PERIOD, MAX_BEACON_PERIOD); + ret = UAP_FAILURE; + } + } + break; + case RETRYLIMIT: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for RETRY LIMIT\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) > MAX_RETRY_LIMIT) || + (atoi(argv[0]) < 0)) { + printf + ("ERR:RETRY_LIMIT must be in the range of [0:%d]. The input was %s.\n", + MAX_RETRY_LIMIT, argv[0]); + ret = UAP_FAILURE; + } + } + break; + case COEX_COMM_BITMAP: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for Bitmap.\n"); + ret = UAP_FAILURE; + } else { + /* Only bit 0 is supported now, hence check for 1 or 0 */ + if ((IS_HEX_OR_DIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || + (atoi(argv[0]) > 1)) { + printf("ERR: Bitmap must have value of 1 or 0.\n"); + ret = UAP_FAILURE; + } + } + break; + case COEX_SCO_ACL_FREQ: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for aclFrequency.\n"); + ret = UAP_FAILURE; + } else { + if (ISDIGIT(argv[0]) == 0) { + printf("ERR: Incorrect value for aclFrequency.\n"); + ret = UAP_FAILURE; + } + } + break; + case COEX_ACL_ENABLED: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for (acl) enabled.\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || + (atoi(argv[0]) > 1)) { + printf("ERR: (acl) enabled must have value of 1 or 0.\n"); + ret = UAP_FAILURE; + } + } + break; + case COEX_ACL_BT_TIME: + case COEX_ACL_WLAN_TIME: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for bt/wlan time.\n"); + ret = UAP_FAILURE; + } else { + if (ISDIGIT(argv[0]) == 0) { + printf("ERR: Incorrect value for bt/wlan time.\n"); + ret = UAP_FAILURE; + } + } + break; + case COEX_PROTECTION: + if (argc != 2) { + printf("ERR:Incorrect number of arguments for %s.\n", argv[0]); + ret = UAP_FAILURE; + } else { + if (ISDIGIT(argv[1]) == 0) { + printf("ERR: Incorrect value for %s.\n", argv[0]); + ret = UAP_FAILURE; + } + } + break; + default: + ret = UAP_FAILURE; + break; + } + return ret; +} + +/** + * @brief Converts colon separated MAC address to hex value + * + * @param mac A pointer to the colon separated MAC string + * @param raw A pointer to the hex data buffer + * @return UAP_SUCCESS or UAP_FAILURE + * UAP_RET_MAC_BROADCAST - if broadcast mac + * UAP_RET_MAC_MULTICAST - if multicast mac + */ +int +mac2raw(char *mac, u8 * raw) +{ + unsigned int temp_raw[ETH_ALEN]; + int num_tokens = 0; + int i; + if (strlen(mac) != ((2 * ETH_ALEN) + (ETH_ALEN - 1))) { + return UAP_FAILURE; + } + num_tokens = sscanf(mac, "%2x:%2x:%2x:%2x:%2x:%2x", + temp_raw + 0, temp_raw + 1, temp_raw + 2, temp_raw + 3, + temp_raw + 4, temp_raw + 5); + if (num_tokens != ETH_ALEN) { + return UAP_FAILURE; + } + for (i = 0; i < num_tokens; i++) + raw[i] = (u8) temp_raw[i]; + + if (memcmp(raw, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) { + return UAP_RET_MAC_BROADCAST; + } else if (raw[0] & 0x01) { + return UAP_RET_MAC_MULTICAST; + } + return UAP_SUCCESS; +} + +/** + * @brief Converts a string to hex value + * + * @param str A pointer to the string + * @param raw A pointer to the raw data buffer + * @return Number of bytes read + */ +int +string2raw(char *str, unsigned char *raw) +{ + int len = (strlen(str) + 1) / 2; + + do { + if (!isxdigit(*str)) { + return -1; + } + *str = toupper(*str); + *raw = CHAR2INT(*str) << 4; + ++str; + *str = toupper(*str); + if (*str == '\0') + break; + *raw |= CHAR2INT(*str); + ++raw; + } while (*++str != '\0'); + return len; +} + +/** + * @brief Prints a MAC address in colon separated form from hex data + * + * @param raw A pointer to the hex data buffer + * @return N/A + */ +void +print_mac(u8 * raw) +{ + printf("%02x:%02x:%02x:%02x:%02x:%02x", (unsigned int) raw[0], + (unsigned int) raw[1], (unsigned int) raw[2], (unsigned int) raw[3], + (unsigned int) raw[4], (unsigned int) raw[5]); + return; +} + +/** + * @brief check hex string + * + * @param hex A pointer to hex string + * @return UAP_SUCCESS or UAP_FAILURE + */ +int +ishexstring(void *hex) +{ + int i, a; + char *p = hex; + int len = strlen(p); + if (!strncasecmp("0x", p, 2)) { + p += 2; + len -= 2; + } + for (i = 0; i < len; i++) { + a = hex2num(*p); + if (a < 0) + return UAP_FAILURE; + p++; + } + return UAP_SUCCESS; +} + +/** + * @brief Show auth tlv + * + * @param tlv Poniter to auth tlv + * + * $return N/A + */ +void +print_auth(TLVBUF_AUTH_MODE * tlv) +{ + switch (tlv->AuthMode) { + case 0: + printf("AUTHMODE = Open authentication\n"); + break; + case 1: + printf("AUTHMODE = Shared key authentication\n"); + break; + case 2: + printf("AUTHMODE = Auto (open and shared key)\n"); + break; + default: + printf("ERR: Invalid authmode=%d\n", tlv->AuthMode); + break; + } +} + +/** + * + * @brief Show cipher tlv + * + * @param tlv Poniter to cipher tlv + * + * $return N/A + */ +void +print_cipher(TLVBUF_CIPHER * tlv) +{ + switch (tlv->PairwiseCipher) { + case CIPHER_TKIP: + printf("PairwiseCipher = TKIP\n"); + break; + case CIPHER_AES_CCMP: + printf("PairwiseCipher = AES CCMP\n"); + break; + case CIPHER_TKIP | CIPHER_AES_CCMP: + printf("PairwiseCipher = TKIP + AES CCMP\n"); + break; + case CIPHER_NONE: + printf("PairwiseCipher = None\n"); + break; + default: + printf("Unknown Pairwise cipher 0x%x\n", tlv->PairwiseCipher); + break; + } + switch (tlv->GroupCipher) { + case CIPHER_TKIP: + printf("GroupCipher = TKIP\n"); + break; + case CIPHER_AES_CCMP: + printf("GroupCipher = AES CCMP\n"); + break; + case CIPHER_NONE: + printf("GroupCipher = None\n"); + break; + default: + printf("Unknown Group cipher 0x%x\n", tlv->GroupCipher); + break; + } +} + +/** + * @brief Show mac filter tlv + * + * @param tlv Poniter to filter tlv + * + * $return N/A + */ +void +print_mac_filter(TLVBUF_STA_MAC_ADDR_FILTER * tlv) +{ + int i; + switch (tlv->FilterMode) { + case 0: + printf("Filter Mode = Filter table is disabled\n"); + return; + case 1: + printf + ("Filter Mode = Allow mac address specified in the allwed list\n"); + break; + case 2: + printf + ("Filter Mode = Block MAC addresses specified in the banned list\n"); + break; + } + for (i = 0; i < tlv->Count; i++) { + printf("MAC_%d = ", i); + print_mac(&tlv->MacAddress[i * ETH_ALEN]); + printf("\n"); + } +} + +/** + * @brief Show rate tlv + * + * @param tlv Poniter to rate tlv + * + * $return N/A + */ +void +print_rate(TLVBUF_RATES * tlv) +{ + int flag = 0; + int i; + printf("Basic Rates ="); + for (i = 0; i < tlv->Length; i++) { + if (tlv->OperationalRates[i] > (BASIC_RATE_SET_BIT - 1)) { + flag = flag ? : 1; + printf(" 0x%x", tlv->OperationalRates[i]); + } + } + printf("%s\nNon-Basic Rates =", flag ? "" : " ( none ) "); + for (flag = 0, i = 0; i < tlv->Length; i++) { + if (tlv->OperationalRates[i] < BASIC_RATE_SET_BIT) { + flag = flag ? : 1; + printf(" 0x%x", tlv->OperationalRates[i]); + } + } + printf("%s\n", flag ? "" : " ( none ) "); +} + +/** + * @brief Show all the tlv in the buf + * + * @param buf Poniter to tlv buffer + * @param len tlv buffer len + * + * $return N/A + */ +void +print_tlv(u8 * buf, u16 len) +{ + TLVBUF_HEADER *pCurrentTlv = (TLVBUF_HEADER *) buf; + int tlvBufLeft = len; + u16 tlvType; + u16 tlvLen; + u16 custom_ie_len; + u8 ssid[33]; + int i = 0; + TLVBUF_AP_MAC_ADDRESS *mac_tlv; + TLVBUF_SSID *ssid_tlv; + TLVBUF_BEACON_PERIOD *beacon_tlv; + TLVBUF_DTIM_PERIOD *dtim_tlv; + TLVBUF_RATES *rates_tlv; + TLVBUF_TX_POWER *txpower_tlv; + TLVBUF_BCAST_SSID_CTL *bcast_tlv; + TLVBUF_PREAMBLE_CTL *preamble_tlv; + TLVBUF_ANTENNA_CTL *antenna_tlv; + TLVBUF_RTS_THRESHOLD *rts_tlv; + TLVBUF_RADIO_CTL *radio_tlv; + TLVBUF_TX_DATA_RATE *txrate_tlv; + TLVBUF_MCBC_DATA_RATE *mcbcrate_tlv; + TLVBUF_PKT_FWD_CTL *pkt_fwd_tlv; + TLVBUF_STA_AGEOUT_TIMER *ageout_tlv; + TLVBUF_AUTH_MODE *auth_tlv; + TLVBUF_PROTOCOL *proto_tlv; + TLVBUF_AKMP *akmp_tlv; + TLVBUF_CIPHER *cipher_tlv; + TLVBUF_GROUP_REKEY_TIMER *rekey_tlv; + TLVBUF_WPA_PASSPHRASE *psk_tlv; + TLVBUF_WEP_KEY *wep_tlv; + TLVBUF_FRAG_THRESHOLD *frag_tlv; + TLVBUF_STA_MAC_ADDR_FILTER *filter_tlv; + TLVBUF_MAX_STA_NUM *max_sta_tlv; + TLVBUF_RETRY_LIMIT *retry_limit_tlv; + TLVBUF_CHANNEL_CONFIG *channel_tlv; + TLVBUF_CHANNEL_LIST *chnlist_tlv; + tlvbuf_custom_ie *custom_ie_tlv; + custom_ie *custom_ie_ptr; + tlvbuf_coex_common_cfg *coex_common_tlv; + tlvbuf_coex_sco_cfg *coex_sco_tlv; + tlvbuf_coex_acl_cfg *coex_acl_tlv; + tlvbuf_coex_stats *coex_stats_tlv; + CHANNEL_LIST *pChanList; +#ifdef DEBUG + uap_printf(MSG_DEBUG, "tlv total len=%d\n", len); +#endif + while (tlvBufLeft >= (int) sizeof(TLVBUF_HEADER)) { + tlvType = uap_le16_to_cpu(pCurrentTlv->Type); + tlvLen = uap_le16_to_cpu(pCurrentTlv->Len); + if ((sizeof(TLVBUF_HEADER) + tlvLen) > tlvBufLeft) { + printf("wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlvLen, tlvBufLeft); + break; + } + switch (tlvType) { + case MRVL_AP_MAC_ADDRESS_TLV_ID: + mac_tlv = (TLVBUF_AP_MAC_ADDRESS *) pCurrentTlv; + printf("AP MAC address = "); + print_mac(mac_tlv->ApMacAddr); + printf("\n"); + break; + case MRVL_SSID_TLV_ID: + memset(ssid, 0, sizeof(ssid)); + ssid_tlv = (TLVBUF_SSID *) pCurrentTlv; + memcpy(ssid, ssid_tlv->Ssid, ssid_tlv->Length); + printf("SSID = %s\n", ssid); + break; + case MRVL_BEACON_PERIOD_TLV_ID: + beacon_tlv = (TLVBUF_BEACON_PERIOD *) pCurrentTlv; + beacon_tlv->BeaconPeriod_ms = + uap_le16_to_cpu(beacon_tlv->BeaconPeriod_ms); + printf("Beacon period = %d\n", beacon_tlv->BeaconPeriod_ms); + break; + case MRVL_DTIM_PERIOD_TLV_ID: + dtim_tlv = (TLVBUF_DTIM_PERIOD *) pCurrentTlv; + printf("DTIM period = %d\n", dtim_tlv->DtimPeriod); + break; + case MRVL_CHANNELCONFIG_TLV_ID: + channel_tlv = (TLVBUF_CHANNEL_CONFIG *) pCurrentTlv; + printf("Channel = %d\n", channel_tlv->ChanNumber); + printf("Channel Select Mode = %s\n", + (channel_tlv->BandConfigType == 0) ? "Manual" : "ACS"); + break; + case MRVL_CHANNELLIST_TLV_ID: + chnlist_tlv = (TLVBUF_CHANNEL_LIST *) pCurrentTlv; + printf("Channels List = "); + pChanList = (CHANNEL_LIST *) & (chnlist_tlv->ChanList); + if (chnlist_tlv->Length % sizeof(CHANNEL_LIST)) { + break; + } + for (i = 0; i < (chnlist_tlv->Length / sizeof(CHANNEL_LIST)); i++) { + printf("%d ", pChanList->ChanNumber); + pChanList++; + } + printf("\n"); + break; + case MRVL_RATES_TLV_ID: + rates_tlv = (TLVBUF_RATES *) pCurrentTlv; + print_rate(rates_tlv); + break; + case MRVL_TX_POWER_TLV_ID: + txpower_tlv = (TLVBUF_TX_POWER *) pCurrentTlv; + printf("Tx power = %d dBm\n", txpower_tlv->TxPower_dBm); + break; + case MRVL_BCAST_SSID_CTL_TLV_ID: + bcast_tlv = (TLVBUF_BCAST_SSID_CTL *) pCurrentTlv; + printf("SSID broadcast = %s\n", + (bcast_tlv->BcastSsidCtl == 1) ? "enabled" : "disabled"); + break; + case MRVL_PREAMBLE_CTL_TLV_ID: + preamble_tlv = (TLVBUF_PREAMBLE_CTL *) pCurrentTlv; + printf("Preamble type = %s\n", (preamble_tlv->PreambleType == 0) ? + "auto" : ((preamble_tlv->PreambleType == 1) ? "short" : + "long")); + break; + case MRVL_ANTENNA_CTL_TLV_ID: + antenna_tlv = (TLVBUF_ANTENNA_CTL *) pCurrentTlv; + printf("%s antenna = %s\n", (antenna_tlv->WhichAntenna == 0) ? + "Rx" : "Tx", (antenna_tlv->AntennaMode == 0) ? "A" : "B"); + break; + case MRVL_RTS_THRESHOLD_TLV_ID: + rts_tlv = (TLVBUF_RTS_THRESHOLD *) pCurrentTlv; + rts_tlv->RtsThreshold = uap_le16_to_cpu(rts_tlv->RtsThreshold); + printf("RTS threshold = %d\n", rts_tlv->RtsThreshold); + break; + case MRVL_FRAG_THRESHOLD_TLV_ID: + frag_tlv = (TLVBUF_FRAG_THRESHOLD *) pCurrentTlv; + frag_tlv->FragThreshold = uap_le16_to_cpu(frag_tlv->FragThreshold); + printf("Fragmentation threshold = %d\n", frag_tlv->FragThreshold); + break; + case MRVL_RADIO_CTL_TLV_ID: + radio_tlv = (TLVBUF_RADIO_CTL *) pCurrentTlv; + printf("Radio = %s\n", (radio_tlv->RadioCtl == 0) ? "on" : "off"); + break; + case MRVL_TX_DATA_RATE_TLV_ID: + txrate_tlv = (TLVBUF_TX_DATA_RATE *) pCurrentTlv; + txrate_tlv->TxDataRate = uap_le16_to_cpu(txrate_tlv->TxDataRate); + if (txrate_tlv->TxDataRate == 0) + printf("Tx data rate = auto\n"); + else + printf("Tx data rate = 0x%x\n", txrate_tlv->TxDataRate); + break; + case MRVL_MCBC_DATA_RATE_TLV_ID: + mcbcrate_tlv = (TLVBUF_MCBC_DATA_RATE *) pCurrentTlv; + mcbcrate_tlv->MCBCdatarate = + uap_le16_to_cpu(mcbcrate_tlv->MCBCdatarate); + if (mcbcrate_tlv->MCBCdatarate == 0) + printf("MCBC data rate = auto\n"); + else + printf("MCBC data rate = 0x%x\n", mcbcrate_tlv->MCBCdatarate); + break; + case MRVL_PKT_FWD_CTL_TLV_ID: + pkt_fwd_tlv = (TLVBUF_PKT_FWD_CTL *) pCurrentTlv; + printf("Firmware = %s\n", (pkt_fwd_tlv->PktFwdCtl == 0) ? + "forwards all packets to the host" : + "handles intra-BSS packets"); + break; + case MRVL_STA_AGEOUT_TIMER_TLV_ID: + ageout_tlv = (TLVBUF_STA_AGEOUT_TIMER *) pCurrentTlv; + ageout_tlv->StaAgeoutTimer_ms = + uap_le32_to_cpu(ageout_tlv->StaAgeoutTimer_ms); + printf("STA ageout timer = %d\n", + (int) ageout_tlv->StaAgeoutTimer_ms); + break; + case MRVL_AUTH_TLV_ID: + auth_tlv = (TLVBUF_AUTH_MODE *) pCurrentTlv; + print_auth(auth_tlv); + break; + case MRVL_PROTOCOL_TLV_ID: + proto_tlv = (TLVBUF_PROTOCOL *) pCurrentTlv; + proto_tlv->Protocol = uap_le16_to_cpu(proto_tlv->Protocol); + print_protocol(proto_tlv); + break; + case MRVL_AKMP_TLV_ID: + akmp_tlv = (TLVBUF_AKMP *) pCurrentTlv; + if (uap_le16_to_cpu(akmp_tlv->KeyMgmt) == KEY_MGMT_PSK) + printf("KeyMgmt = PSK\n"); + else + printf("KeyMgmt = NONE\n"); + break; + case MRVL_CIPHER_TLV_ID: + cipher_tlv = (TLVBUF_CIPHER *) pCurrentTlv; + print_cipher(cipher_tlv); + break; + case MRVL_GRP_REKEY_TIME_TLV_ID: + rekey_tlv = (TLVBUF_GROUP_REKEY_TIMER *) pCurrentTlv; + if (rekey_tlv->GroupRekeyTime_sec == 0) + printf("Group re-key time = disabled\n"); + else + printf("Group re-key time = %ld second\n", + uap_le32_to_cpu(rekey_tlv->GroupRekeyTime_sec)); + break; + case MRVL_WPA_PASSPHRASE_TLV_ID: + psk_tlv = (TLVBUF_WPA_PASSPHRASE *) pCurrentTlv; + if (psk_tlv->Length > 0) { + printf("WPA passphrase = "); + for (i = 0; i < psk_tlv->Length; i++) + printf("%c", psk_tlv->Passphrase[i]); + printf("\n"); + } else + printf("WPA passphrase = None\n"); + break; + case MRVL_WEP_KEY_TLV_ID: + wep_tlv = (TLVBUF_WEP_KEY *) pCurrentTlv; + print_wep_key(wep_tlv); + break; + case MRVL_STA_MAC_ADDR_FILTER_TLV_ID: + filter_tlv = (TLVBUF_STA_MAC_ADDR_FILTER *) pCurrentTlv; + print_mac_filter(filter_tlv); + break; + case MRVL_MAX_STA_CNT_TLV_ID: + max_sta_tlv = (TLVBUF_MAX_STA_NUM *) pCurrentTlv; + printf("Max Station Number = %d\n", max_sta_tlv->Max_sta_num); + break; + case MRVL_RETRY_LIMIT_TLV_ID: + retry_limit_tlv = (TLVBUF_RETRY_LIMIT *) pCurrentTlv; + printf("Retry Limit = %d\n", retry_limit_tlv->retry_limit); + break; + case MRVL_MGMT_IE_LIST_TLV_ID: + custom_ie_tlv = (tlvbuf_custom_ie *) pCurrentTlv; + custom_ie_len = tlvLen; + custom_ie_ptr = (custom_ie *) (custom_ie_tlv->ie_data); + while (custom_ie_len >= sizeof(custom_ie)) { + printf("Index [%d]\n", + uap_le16_to_cpu(custom_ie_ptr->ie_index)); + printf("Management Subtype Mask = 0x%02x\n", + uap_le16_to_cpu(custom_ie_ptr->mgmt_subtype_mask)); + hexdump_data("IE Buffer", (void *) custom_ie_ptr->ie_buffer, + uap_le16_to_cpu(custom_ie_ptr->ie_length), ' '); + custom_ie_len -= + sizeof(custom_ie) + + uap_le16_to_cpu(custom_ie_ptr->ie_length); + custom_ie_ptr = + (custom_ie *) ((u8 *) custom_ie_ptr + sizeof(custom_ie) + + uap_le16_to_cpu(custom_ie_ptr->ie_length)); + } + break; + case MRVL_BT_COEX_COMMON_CFG_TLV_ID: + printf("Coex common configuration:\n"); + coex_common_tlv = (tlvbuf_coex_common_cfg *) pCurrentTlv; + printf("\tConfig Bitmap = 0x%02lx\n", + uap_le32_to_cpu(coex_common_tlv->config_bitmap)); + break; + + case MRVL_BT_COEX_SCO_CFG_TLV_ID: + printf("Coex sco configuration:\n"); + coex_sco_tlv = (tlvbuf_coex_sco_cfg *) pCurrentTlv; + for (i = 0; i < 4; i++) + printf("\tQtime protection [%d] = %d usecs\n", i, + uap_le16_to_cpu(coex_sco_tlv->protection_qtime[i])); + printf("\tProtection frame rate = %d\n", + uap_le16_to_cpu(coex_sco_tlv->protection_rate)); + printf("\tACL frequency = %d\n", + uap_le16_to_cpu(coex_sco_tlv->acl_frequency)); + break; + + case MRVL_BT_COEX_ACL_CFG_TLV_ID: + printf("Coex acl configuration: "); + coex_acl_tlv = (tlvbuf_coex_acl_cfg *) pCurrentTlv; + coex_acl_tlv->enabled = uap_le16_to_cpu(coex_acl_tlv->enabled); + printf("%s\n", (coex_acl_tlv->enabled) ? "enabled" : "disabled"); + if (coex_acl_tlv->enabled) { + printf("\tBT time = %d usecs\n", + uap_le16_to_cpu(coex_acl_tlv->bt_time)); + printf("\tWLan time = %d usecs\n", + uap_le16_to_cpu(coex_acl_tlv->wlan_time)); + printf("\tProtection frame rate = %d\n", + uap_le16_to_cpu(coex_acl_tlv->protection_rate)); + } + break; + + case MRVL_BT_COEX_STATS_TLV_ID: + printf("Coex statistics: \n"); + coex_stats_tlv = (tlvbuf_coex_stats *) pCurrentTlv; + printf("\tNull not sent = %ld\n", + uap_le32_to_cpu(coex_stats_tlv->null_not_sent)); + printf("\tNull queued = %ld\n", + uap_le32_to_cpu(coex_stats_tlv->null_queued)); + printf("\tNull not queued = %ld\n", + uap_le32_to_cpu(coex_stats_tlv->null_not_queued)); + printf("\tCF End queued = %ld\n", + uap_le32_to_cpu(coex_stats_tlv->cf_end_queued)); + printf("\tCF End not queued = %ld\n", + uap_le32_to_cpu(coex_stats_tlv->cf_end_not_queued)); + printf("\tNull allocation failures = %ld\n", + uap_le32_to_cpu(coex_stats_tlv->null_alloc_fail)); + printf("\tCF End allocation failures = %ld\n", + uap_le32_to_cpu(coex_stats_tlv->cf_end_alloc_fail)); + break; + default: + break; + } + tlvBufLeft -= (sizeof(TLVBUF_HEADER) + tlvLen); + pCurrentTlv = (TLVBUF_HEADER *) (pCurrentTlv->Data + tlvLen); + } + return; +} + +/** + * @brief Performs the ioctl operation to send the command to + * the driver. + * + * @param cmd Pointer to the command buffer + * @param size Pointer to the command size. This value is + * overwritten by the function with the size of the + * received response. + * @param buf_size Size of the allocated command buffer + * @return UAP_SUCCESS or UAP_FAILURE + */ +int +uap_ioctl(u8 * cmd, u16 * size, u16 buf_size) +{ + struct ifreq ifr; + APCMDBUF *header = NULL; + s32 sockfd; + + if (buf_size < *size) { + printf("buf_size should not less than cmd buffer size\n"); + return UAP_FAILURE; + } + + /* Open socket */ + if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + printf("ERR:Cannot open socket\n"); + return UAP_FAILURE; + } + *(u32 *) cmd = buf_size - BUF_HEADER_SIZE; + + /* 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; + header = (APCMDBUF *) cmd; + header->Size = *size - BUF_HEADER_SIZE; + if (header->CmdCode == APCMD_SYS_CONFIGURE) { + APCMDBUF_SYS_CONFIGURE *sys_cfg; + sys_cfg = (APCMDBUF_SYS_CONFIGURE *) cmd; + sys_cfg->Action = uap_cpu_to_le16(sys_cfg->Action); + } + endian_convert_request_header(header); +#if DEBUG + /* Dump request buffer */ + hexdump("Request buffer", (void *) cmd, *size, ' '); +#endif + /* Perform ioctl */ + errno = 0; + if (ioctl(sockfd, UAPHOSTCMD, &ifr)) { + perror(""); + printf("ERR:UAPHOSTCMD is not supported by %s\n", dev_name); + close(sockfd); + return UAP_FAILURE; + } + endian_convert_response_header(header); + header->CmdCode &= HostCmd_CMD_ID_MASK; + header->CmdCode |= APCMD_RESP_CHECK; + *size = header->Size; + + /* Validate response size */ + if (*size > (buf_size - BUF_HEADER_SIZE)) { + printf + ("ERR:Response size (%d) greater than buffer size (%d)! Aborting!\n", + *size, buf_size); + close(sockfd); + return UAP_FAILURE; + } +#if DEBUG + /* Dump respond buffer */ + hexdump("Respond buffer", (void *) header, header->Size + BUF_HEADER_SIZE, + ' '); +#endif + + /* Close socket */ + close(sockfd); + return UAP_SUCCESS; +} + +/** + * @brief check cipher is valid or not + * + * @param pairwisecipher pairwise cipher + * @param groupcipher group cipher + * @return UAP_SUCCESS or UAP_FAILURE + */ +int +is_cipher_valid(int pairwisecipher, int groupcipher) +{ + if ((pairwisecipher == CIPHER_NONE) && (groupcipher == CIPHER_NONE)) + return UAP_SUCCESS; + if ((pairwisecipher == CIPHER_TKIP) && (groupcipher == CIPHER_TKIP)) + return UAP_SUCCESS; + if ((pairwisecipher == CIPHER_AES_CCMP) && (groupcipher == CIPHER_AES_CCMP)) + return UAP_SUCCESS; + if ((pairwisecipher == CIPHER_BITMAP) && (groupcipher == CIPHER_TKIP)) + return UAP_SUCCESS; + return UAP_FAILURE; +} + +/** + * @brief The main function + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return 0 or 1 + */ +int +main(int argc, char *argv[]) +{ + int opt, i; + memset(dev_name, 0, sizeof(dev_name)); + strcpy(dev_name, DEFAULT_DEV_NAME); + + /* parse arguments */ + while ((opt = getopt_long(argc, argv, "+hi:d:v", ap_options, NULL)) != -1) { + switch (opt) { + case 'i': + if (strlen(optarg) < IFNAMSIZ) { + memset(dev_name, 0, sizeof(dev_name)); + strncpy(dev_name, optarg, strlen(optarg)); + } + printf("dev_name:%s\n", dev_name); + break; + case 'v': + printf("uaputl.exe - uAP utility ver %s\n", UAP_VERSION); + exit(0); + case 'd': + debug_level = strtoul(optarg, NULL, 10); + uap_printf(MSG_DEBUG, "debug_level=%x\n", debug_level); + break; + case 'h': + default: + print_tool_usage(); + exit(0); + } + } + + argc -= optind; + argv += optind; + optind = 0; + + if (argc < 1) { + print_tool_usage(); + exit(1); + } + + /* process command */ + for (i = 0; ap_command[i].cmd; i++) { + if (strncmp(ap_command[i].cmd, argv[0], strlen(ap_command[i].cmd))) + continue; + if (strlen(ap_command[i].cmd) != strlen(argv[0])) + continue; + ap_command[i].func(argc, argv); + break; + } + if (!ap_command[i].cmd) { + printf("ERR: %s is not supported\n", argv[0]); + exit(1); + } + return 0; +} |