/** @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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 [REASON_CODE]\n"); return; } /** * @brief Creates a STA deauth request and sends to the driver * * Usage: "sta_deauth " * * @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 \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 \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 " * * @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 [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
[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 [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 parameters]\n"); printf("Options:\n" "\t--help\tDisplay help\n" "\t-v\tDisplay version\n" "\t-i \n" "\t-d \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 --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; }