| /** @file uaputl.c |
| * |
| * @brief Program to send AP commands to the driver/firmware of the uAP |
| * driver. |
| * |
| * Copyright (C) 2008-2017, Marvell International Ltd. |
| * |
| * This software file (the "File") is distributed by Marvell International |
| * Ltd. under the terms of the GNU General Public License Version 2, June 1991 |
| * (the "License"). You may use, redistribute and/or modify this File in |
| * accordance with the terms and conditions of the License, a copy of which |
| * is available along with the File in the gpl.txt file or by writing to |
| * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. |
| * |
| * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE |
| * ARE EXPRESSLY DISCLAIMED. The License provides additional details about |
| * this warranty disclaimer. |
| * |
| */ |
| /**************************************************************************** |
| Change log: |
| 03/01/08: Initial creation |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| Header files |
| ****************************************************************************/ |
| #include <stdarg.h> |
| #include <sys/types.h> |
| #include <unistd.h> |
| #include <sys/socket.h> |
| #include <sys/select.h> |
| #include <stdio.h> |
| #include <getopt.h> |
| #include <netinet/in.h> |
| #include <errno.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <ctype.h> |
| #include <linux/if.h> |
| #include <sys/ioctl.h> |
| #include <errno.h> |
| #include "uaputl.h" |
| #include "uapcmd.h" |
| |
| /**************************************************************************** |
| Definitions |
| ****************************************************************************/ |
| /** Default debug level */ |
| int debug_level = MSG_NONE; |
| |
| /** Enable or disable debug outputs */ |
| #define DEBUG 1 |
| |
| /** Convert character to integer */ |
| #define CHAR2INT(x) (((x) >= 'A') ? ((x) - 'A' + 10) : ((x) - '0')) |
| |
| /** Supported stream modes */ |
| #define HT_STREAM_MODE_1X1 0x11 |
| #define HT_STREAM_MODE_2X2 0x22 |
| |
| static int get_bss_config(t_u8 *buf); |
| |
| /**************************************************************************** |
| 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} |
| }; |
| |
| /** Flag to check if custom IE is present in sys_config response from FW */ |
| int custom_ie_present = 0; |
| |
| /** Flag to check if max mgmt IE is printed in sys_config response from FW */ |
| int max_mgmt_ie_print = 0; |
| |
| /** Flag to bypass re-route path */ |
| int uap_ioctl_no_reroute = 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 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 |
| * |
| */ |
| static int |
| check_mandatory_rates(int argc, char **argv) |
| { |
| int i; |
| int tmp; |
| t_u32 rate_bitmap = 0; |
| int cck_enable = 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: |
| cck_enable = 1; |
| rate_bitmap |= BITMAP_RATE_1M; |
| break; |
| case 4: |
| cck_enable = 1; |
| rate_bitmap |= BITMAP_RATE_2M; |
| break; |
| case 11: |
| cck_enable = 1; |
| rate_bitmap |= BITMAP_RATE_5_5M; |
| break; |
| case 22: |
| cck_enable = 1; |
| 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; |
| } |
| } |
| #ifdef WIFI_DIRECT_SUPPORT |
| if (strncmp(dev_name, "wfd", 3)) |
| #endif |
| if ((rate_bitmap & B_RATE_MANDATORY) != B_RATE_MANDATORY) { |
| if (cck_enable) { |
| 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 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 Get Max sta num from firmware |
| * |
| * @return max number of stations |
| */ |
| int |
| get_max_sta_num_supported(t_u16 *max_sta_num_supported) |
| { |
| apcmdbuf_sys_configure *cmd_buf = NULL; |
| tlvbuf_max_sta_num *tlv = NULL; |
| t_u8 *buffer = NULL; |
| t_u16 cmd_len = 0; |
| t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| int ret = UAP_SUCCESS; |
| |
| /* Initialize the command length */ |
| cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_max_sta_num); |
| |
| /* Initialize the command buffer */ |
| buffer = (t_u8 *)malloc(buf_len); |
| if (!buffer) { |
| printf("ERR:Cannot allocate buffer for command!\n"); |
| return UAP_FAILURE; |
| } |
| memset(buffer, 0, buf_len); |
| |
| /* Locate headers */ |
| cmd_buf = (apcmdbuf_sys_configure *)buffer; |
| tlv = (tlvbuf_max_sta_num *)(buffer + sizeof(apcmdbuf_sys_configure)); |
| |
| /* Fill the command buffer */ |
| cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; |
| cmd_buf->size = cmd_len; |
| cmd_buf->seq_num = 0; |
| cmd_buf->result = 0; |
| tlv->tag = MRVL_MAX_STA_CNT_TLV_ID; |
| tlv->length = 4; |
| cmd_buf->action = ACTION_GET; |
| |
| endian_convert_tlv_header_out(tlv); |
| tlv->max_sta_num_configured = |
| uap_cpu_to_le16(tlv->max_sta_num_configured); |
| tlv->max_sta_num_supported = |
| uap_cpu_to_le16(tlv->max_sta_num_supported); |
| |
| /* Send the command */ |
| ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); |
| endian_convert_tlv_header_in(tlv); |
| tlv->max_sta_num_configured = |
| uap_le16_to_cpu(tlv->max_sta_num_configured); |
| tlv->max_sta_num_supported = |
| uap_le16_to_cpu(tlv->max_sta_num_supported); |
| /* Process response */ |
| if (ret == UAP_SUCCESS) { |
| /* Verify response */ |
| if ((cmd_buf->cmd_code != |
| (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || |
| (tlv->tag != MRVL_MAX_STA_CNT_TLV_ID)) { |
| printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); |
| free(buffer); |
| return UAP_FAILURE; |
| } |
| /* Print response */ |
| if (cmd_buf->result != CMD_SUCCESS) { |
| printf("ERR:Could not get max station number!\n"); |
| ret = UAP_FAILURE; |
| } else { |
| if (tlv->length == 4) { |
| *max_sta_num_supported = |
| tlv->max_sta_num_supported; |
| } else { |
| *max_sta_num_supported = MAX_STA_COUNT; |
| } |
| } |
| } else { |
| printf("ERR:Command sending failed!\n"); |
| } |
| if (buffer) |
| free(buffer); |
| return ret; |
| } |
| |
| /** |
| * @brief Parse domain name for domain_code |
| * |
| * @param dom_name Domain name |
| * @return domain_code / UAP_FAILURE |
| */ |
| static t_u8 |
| parse_domain_name(char *domain_name) |
| { |
| t_u8 domain_code = UAP_FAILURE; |
| |
| if (strstr(domain_name, "DOMAIN_CODE_")) { |
| domain_name += sizeof("DOMAIN_CODE_") - 1; |
| |
| if (!(strncmp(domain_name, "FCC", sizeof("FCC") - 1))) |
| domain_code = DOMAIN_CODE_FCC; |
| else if (!(strcmp(domain_name, "ETSI"))) |
| domain_code = DOMAIN_CODE_ETSI; |
| else if (!(strcmp(domain_name, "MKK"))) |
| domain_code = DOMAIN_CODE_MKK; |
| else if (!(strcmp(domain_name, "IN"))) |
| domain_code = DOMAIN_CODE_IN; |
| else if (!(strcmp(domain_name, "MY"))) |
| domain_code = DOMAIN_CODE_MY; |
| } |
| return domain_code; |
| } |
| |
| /** |
| * @brief Parse domain file for country information |
| * |
| * @param country Country name |
| * @param band Band Info. 0x01 : B band, 0x02 : G band, 0x04 : A band. |
| * @param sub_bands Band information |
| * @param pdomain_code Pointer to receive domain_code |
| * @return number of band/ UAP_FAILURE |
| */ |
| t_u8 |
| parse_domain_file(char *country, int band, ieeetypes_subband_set_t *sub_bands, |
| t_u8 *pdomain_code) |
| { |
| FILE *fp; |
| char str[64]; |
| char domain_name[64]; |
| int cflag = 0; |
| int dflag = 0; |
| int found = 0; |
| int skip = 0; |
| int j = -1, reset_j = 0; |
| t_u8 no_of_sub_band = 0; |
| char *strp = NULL; |
| |
| fp = fopen("config/80211d_domain.conf", "r"); |
| if (fp == NULL) { |
| printf("File opening Error\n"); |
| return UAP_FAILURE; |
| } |
| |
| /** |
| * Search specific domain name |
| */ |
| memset(str, 0, 64); |
| while (!feof(fp)) { |
| fscanf(fp, "%63s", str); |
| if (cflag) { |
| strncpy(domain_name, str, sizeof(domain_name) - 1); |
| cflag = 0; |
| } |
| if (!strcmp(str, "COUNTRY:")) { |
| /** Store next string to domain_name */ |
| cflag = 1; |
| } |
| |
| if (!strcmp(str, country)) { |
| /** Country is matched ;)*/ |
| 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, "%63s", str); |
| |
| if (feof(fp) |
| ) { |
| break; |
| } |
| |
| if (dflag && !strcmp(str, "DOMAIN:")) { |
| |
| if ((band & BAND_A) == 0) |
| break; |
| |
| /* parse next domain */ |
| cflag = 0; |
| dflag = 0; |
| j = -1; |
| reset_j = 0; |
| } |
| if (dflag) { |
| j++; |
| if (strchr(str, ',')) |
| reset_j = 1; |
| |
| strp = strtok(str, ", "); |
| |
| if (strp == NULL) { |
| if (reset_j) { |
| j = -1; |
| reset_j = 0; |
| } |
| continue; |
| } else { |
| strncpy(str, strp, (sizeof(str) - 1)); |
| } |
| |
| 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].first_chan = |
| (t_u8)A2HEXDECIMAL(str); |
| break; |
| case 1: |
| sub_bands[no_of_sub_band].no_of_chan = |
| (t_u8)A2HEXDECIMAL(str); |
| break; |
| case 2: |
| sub_bands[no_of_sub_band++].max_tx_pwr = |
| (t_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; |
| if (band & (BAND_B | BAND_G) || skip) |
| dflag = 1; |
| else |
| skip = 1; |
| } |
| if (!dflag && !strcmp(str, "DOMAIN:")) { |
| cflag = 1; |
| } |
| } |
| fclose(fp); |
| |
| if (pdomain_code && no_of_sub_band && (band & BAND_A)) { |
| *pdomain_code = parse_domain_name(domain_name); |
| } |
| 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(t_u16 action, t_u16 oid, t_u16 size, t_u8 *oid_buf) |
| { |
| apcmdbuf_snmp_mib *cmd_buf = NULL; |
| tlvbuf_header *tlv = NULL; |
| int ret = UAP_FAILURE; |
| t_u8 *buf = NULL; |
| t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| t_u16 cmd_len; |
| int i; |
| |
| cmd_len = sizeof(apcmdbuf_snmp_mib) + sizeof(tlvbuf_header) + size; |
| buf = (t_u8 *)malloc(buf_len); |
| if (!buf) { |
| printf("ERR:Cannot allocate buffer from command!\n"); |
| return ret; |
| } |
| memset(buf, 0, 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->seq_num = 0; |
| cmd_buf->cmd_code = 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); |
| ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); |
| if (ret == UAP_SUCCESS) { |
| if (cmd_buf->result == CMD_SUCCESS) { |
| if (!action) { |
| /** Relocate the headers */ |
| tlv = (tlvbuf_header *)((t_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 UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_sys_info(int argc, char *argv[]) |
| { |
| apcmdbuf_sys_info_request *cmd_buf = NULL; |
| apcmdbuf_sys_info_response *response_buf = NULL; |
| t_u8 *buf = NULL; |
| t_u16 cmd_len; |
| t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| int ret = UAP_SUCCESS; |
| int opt; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_sys_info_usage(); |
| return UAP_FAILURE; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| /* Check arguments */ |
| if (argc != 0) { |
| printf("ERR:Too many arguments.\n"); |
| print_sys_info_usage(); |
| return UAP_FAILURE; |
| } |
| |
| /* Alloc buf for command */ |
| buf = (t_u8 *)malloc(buf_len); |
| |
| if (!buf) { |
| printf("ERR:Cannot allocate buffer from command!\n"); |
| return UAP_FAILURE; |
| } |
| memset(buf, 0, 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->cmd_code = APCMD_SYS_INFO; |
| cmd_buf->size = cmd_len; |
| cmd_buf->seq_num = 0; |
| cmd_buf->result = 0; |
| |
| /* Send the command */ |
| ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); |
| |
| /* Process response */ |
| if (ret == UAP_SUCCESS) { |
| /* Verify response */ |
| if (response_buf->cmd_code != |
| (APCMD_SYS_INFO | APCMD_RESP_CHECK)) { |
| printf("ERR:Corrupted response!\n"); |
| free(buf); |
| return UAP_FAILURE; |
| } |
| /* Print response */ |
| if (response_buf->result == CMD_SUCCESS) { |
| printf("System information = %s\n", |
| response_buf->sys_info); |
| } else { |
| printf("ERR:Could not retrieve system information!\n"); |
| ret = UAP_FAILURE; |
| } |
| } else { |
| printf("ERR:Command sending failed!\n"); |
| } |
| |
| free(buf); |
| return ret; |
| } |
| |
| /** |
| * @brief Show usage information for deepsleep command |
| * |
| * $return N/A |
| */ |
| void |
| print_deepsleep_usage(void) |
| { |
| printf("\nUsage : deepsleep [MODE][IDLE_TIME]"); |
| printf("\nOptions: MODE : 0 - Disable auto deep sleep mode"); |
| printf("\n 1 - Enable auto deep sleep mode"); |
| printf("\n IDLE_TIME: Idle time in milliseconds, default value is 100 ms"); |
| printf("\n empty - get auto deep sleep mode\n"); |
| return; |
| } |
| |
| /** |
| * @brief Creates deepsleep request and send to driver |
| * |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_deepsleep(int argc, char *argv[]) |
| { |
| int opt; |
| deep_sleep_para param; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_deepsleep_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| memset(¶m, 0, sizeof(param)); |
| /* Check arguments */ |
| if (argc > 2) { |
| printf("ERR:wrong arguments. Only support 2 arguments\n"); |
| print_deepsleep_usage(); |
| return UAP_FAILURE; |
| } |
| param.subcmd = UAP_DEEP_SLEEP; |
| if (argc) { |
| if (argc >= 1) { |
| if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) || |
| ((atoi(argv[0]) < 0) || (atoi(argv[0]) > 1))) { |
| printf("ERR: Only Number values are allowed\n"); |
| print_deepsleep_usage(); |
| return UAP_FAILURE; |
| } |
| } |
| param.action = 1; |
| param.deep_sleep = (t_u16)A2HEXDECIMAL(argv[0]); |
| param.idle_time = 0; |
| if (argc == 2) { |
| if (IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) { |
| printf("ERR: Only Number values are allowed\n"); |
| print_deepsleep_usage(); |
| return UAP_FAILURE; |
| } |
| param.idle_time = (t_u16)A2HEXDECIMAL(argv[1]); |
| } |
| } else { |
| param.action = 0; |
| } |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)¶m; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| if (argc) |
| printf("ERR: deep sleep must be disabled before changing idle time\n"); |
| else { |
| perror(""); |
| printf("ERR:deep sleep failed\n"); |
| } |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| if (!argc) { |
| if (param.deep_sleep == 1) { |
| printf("deep sleep mode: enabled\n"); |
| printf("idle time = %dms\n", param.idle_time); |
| } else { |
| printf("deep sleep mode: disabled\n"); |
| } |
| } |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Show usage information for tx_data_pause command |
| * |
| * $return N/A |
| */ |
| void |
| print_txdatapause_usage(void) |
| { |
| printf("\nUsage : tx_data_pause [ENABLE][TX_BUF_CNT]"); |
| printf("\nOptions: ENABLE : 0 - Disable Tx data pause events"); |
| printf("\n 1 - Enable Tx data pause events"); |
| printf("\n TX_BUF_CNT: Max number of TX buffer for PS clients"); |
| printf("\n empty - get Tx data pause settings\n"); |
| return; |
| } |
| |
| /** |
| * @brief Set/get txpause setting |
| * |
| * @param txpause A pointer to the Tx data pause parameters structure |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| send_txpause_ioctl(tx_data_pause_para *txpause) |
| { |
| struct ifreq ifr; |
| t_s32 sockfd; |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)txpause; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| perror(""); |
| printf("ERR:txpause is not supported by %s\n", dev_name); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Creates tx_data_pause request and sends to driver |
| * |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_txdatapause(int argc, char *argv[]) |
| { |
| int opt; |
| tx_data_pause_para param; |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_txdatapause_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| memset(¶m, 0, sizeof(param)); |
| /* Check arguments */ |
| if (argc > 2) { |
| printf("ERR: Wrong number of arguments\n"); |
| print_txdatapause_usage(); |
| return UAP_FAILURE; |
| } |
| param.subcmd = UAP_TX_DATA_PAUSE; |
| if (argc) { |
| if (argc >= 1) { |
| if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) || |
| ((atoi(argv[0]) < TX_DATA_PAUSE_DISABLE) || |
| (atoi(argv[0]) > TX_DATA_PAUSE_ENABLE))) { |
| printf("ERR: First argument can either be 0 or 1\n"); |
| print_txdatapause_usage(); |
| return UAP_FAILURE; |
| } |
| } |
| if (argc == 1) { |
| param.action = ACTION_GET; |
| if (UAP_FAILURE == send_txpause_ioctl(¶m)) { |
| return UAP_FAILURE; |
| } |
| } |
| param.action = ACTION_SET; |
| param.txpause = (t_u16)A2HEXDECIMAL(argv[0]); |
| if (argc == 2) { |
| if (IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE) { |
| printf("ERR: Max buffer length must be numeric\n"); |
| print_txdatapause_usage(); |
| return UAP_FAILURE; |
| } |
| param.txbufcnt = (t_u16)A2HEXDECIMAL(argv[1]); |
| } |
| } else { |
| param.action = ACTION_GET; |
| } |
| if (UAP_FAILURE == send_txpause_ioctl(¶m)) |
| return UAP_FAILURE; |
| if ((argc == 2) && ((t_u16)A2HEXDECIMAL(argv[1]) != param.txbufcnt)) { |
| printf("Max number of TX buffer allowed for all PS client: %d\n", param.txbufcnt); |
| return UAP_FAILURE; |
| } |
| if (!argc) { |
| printf("Tx data pause: %s\n", |
| (param.txpause == 1) ? "enabled" : "disabled"); |
| printf("Max number of TX buffer allowed for all PS client: %d\n", param.txbufcnt); |
| } |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Process host_cmd |
| * |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return N/A |
| */ |
| int |
| apcmd_hostcmd(int argc, char *argv[]) |
| { |
| apcmdbuf *hdr; |
| t_u8 *buffer = NULL; |
| int ret = UAP_SUCCESS; |
| t_u16 cmd_len = 0; |
| t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| char cmdname[256]; |
| |
| if (argc <= 2) { |
| printf("Error: invalid no of arguments\n"); |
| printf("Syntax: ./uaputl hostcmd <hostcmd.conf> <cmdname>\n"); |
| return UAP_FAILURE; |
| } |
| |
| buffer = (t_u8 *)malloc(buf_len); |
| if (!buffer) { |
| printf("ERR:Cannot allocate buffer for command!\n"); |
| return UAP_FAILURE; |
| } |
| |
| memset(buffer, 0, buf_len); |
| sprintf(cmdname, "%s", argv[2]); |
| ret = prepare_host_cmd_buffer(argv[1], cmdname, buffer); |
| if (ret == UAP_FAILURE) |
| goto _exit_; |
| |
| /* Locate headers */ |
| hdr = (apcmdbuf *)buffer; |
| cmd_len = hdr->size + BUF_HEADER_SIZE; |
| |
| /* Send the command */ |
| ret = uap_ioctl((t_u8 *)buffer, &cmd_len, buf_len); |
| |
| /* Process response */ |
| if (ret == UAP_SUCCESS) { |
| hdr->cmd_code &= HostCmd_CMD_ID_MASK; |
| if (!hdr->result) { |
| printf("UAPHOSTCMD: CmdCode=%#04x, Size=%#04x, SeqNum=%#04x, Result=%#04x\n", hdr->cmd_code, hdr->size, hdr->seq_num, hdr->result); |
| hexdump_data("payload", |
| (void *)(buffer + APCMDHEADERLEN), |
| hdr->size - (APCMDHEADERLEN - |
| BUF_HEADER_SIZE), ' '); |
| } else |
| printf("UAPHOSTCMD failed: CmdCode=%#04x, Size=%#04x, SeqNum=%#04x, Result=%#04x\n", hdr->cmd_code, hdr->size, hdr->seq_num, hdr->result); |
| } else |
| printf("ERR:Command sending failed!\n"); |
| |
| _exit_: |
| if (buffer) |
| free(buffer); |
| return ret; |
| } |
| |
| /** |
| * @brief Show usage information for cmd52rw command |
| * |
| * $return N/A |
| */ |
| void |
| print_cmd52rw_usage(void) |
| { |
| printf("\nUsage : sdcmd52rw <FN no.> <address> [data]"); |
| printf("\nOptions: FN no : SDIO function number."); |
| printf("\n address: SDIO address"); |
| printf("\n data: data for SDIO write operation."); |
| printf("\n Read is performed if data is not provided."); |
| return; |
| } |
| |
| /** |
| * @brief Process cmd52 read/write handler |
| * |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return N/A |
| */ |
| int |
| apcmd_cmd52_readwrite(int argc, char *argv[]) |
| { |
| int opt; |
| sdcmd52_para param; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_cmd52rw_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| memset(¶m, 0, sizeof(sdcmd52_para)); |
| /* Check arguments */ |
| if (argc < 2 || argc > 3) { |
| printf("ERR:wrong arguments.\n"); |
| print_cmd52rw_usage(); |
| return UAP_FAILURE; |
| } |
| if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) || |
| (IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE)) { |
| printf("ERR: Only Number values are allowed\n"); |
| print_cmd52rw_usage(); |
| return UAP_FAILURE; |
| } |
| param.cmd52_params[0] = (t_u8)A2HEXDECIMAL(argv[0]); |
| if (param.cmd52_params[0] > 7) { |
| printf("ERR: Invalid function number!\n"); |
| return UAP_FAILURE; |
| } |
| param.cmd52_params[1] = (t_u8)A2HEXDECIMAL(argv[1]); |
| param.action = 0; |
| if (argc == 3) { |
| if (IS_HEX_OR_DIGIT(argv[2]) == UAP_FAILURE) { |
| printf("ERR: Only Number values are allowed\n"); |
| print_cmd52rw_usage(); |
| return UAP_FAILURE; |
| } |
| param.cmd52_params[2] = (t_u8)A2HEXDECIMAL(argv[2]); |
| param.action = 1; |
| } |
| param.subcmd = UAP_SDCMD52_RW; |
| |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)¶m; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| perror(""); |
| printf("ERR:cmd52rw failed\n"); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| if (argc == 2) |
| printf("Cmd52 read done. "); |
| else |
| printf("Cmd52 write done. "); |
| printf("func=%d, reg=%d, data=0x%02X\n", |
| param.cmd52_params[0], param.cmd52_params[1], |
| param.cmd52_params[2]); |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Show usage information for addbapara command |
| * |
| * $return N/A |
| */ |
| void |
| print_addbapara_usage(void) |
| { |
| printf("\nUsage : addbapara [timeout txwinsize rxwinsize]"); |
| printf("\nOptions: timeout : 0 - Disable"); |
| printf("\n 1 - 65535 : Block Ack Timeout in TU"); |
| printf("\n txwinsize: Buffer size for ADDBA request"); |
| printf("\n rxwinsize: Buffer size for ADDBA response"); |
| printf("\n txamsdu: amsdu for ADDBA request"); |
| printf("\n rxamsdu: amsdu for ADDBA response"); |
| printf("\n empty - get ADDBA parameters\n"); |
| return; |
| } |
| |
| /** |
| * @brief Creates addbaparam request and send to driver |
| * |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_addbapara(int argc, char *argv[]) |
| { |
| int opt; |
| addba_param param; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_addbapara_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| memset(¶m, 0, sizeof(param)); |
| /* Check arguments */ |
| if ((argc != 0) && (argc != 5)) { |
| printf("ERR:wrong arguments. Only support 0 or 5 arguments\n"); |
| print_addbapara_usage(); |
| return UAP_FAILURE; |
| } |
| param.subcmd = UAP_ADDBA_PARA; |
| if (argc) { |
| if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) |
| || (IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE) |
| || (IS_HEX_OR_DIGIT(argv[2]) == UAP_FAILURE) |
| || (IS_HEX_OR_DIGIT(argv[3]) == UAP_FAILURE) |
| || (IS_HEX_OR_DIGIT(argv[4]) == UAP_FAILURE) |
| ) { |
| printf("ERR: Only Number values are allowed\n"); |
| print_addbapara_usage(); |
| return UAP_FAILURE; |
| } |
| param.action = 1; |
| param.timeout = (t_u32)A2HEXDECIMAL(argv[0]); |
| if (param.timeout > DEFAULT_BLOCK_ACK_TIMEOUT) { |
| printf("ERR: Block Ack timeout should be in range [1-65535]\n"); |
| print_addbapara_usage(); |
| return UAP_FAILURE; |
| } |
| param.txwinsize = (t_u32)A2HEXDECIMAL(argv[1]); |
| param.rxwinsize = (t_u32)A2HEXDECIMAL(argv[2]); |
| if (param.txwinsize > MAX_TXRX_WINDOW_SIZE || |
| param.rxwinsize > MAX_TXRX_WINDOW_SIZE) { |
| printf("ERR: Tx/Rx window size should not be greater than 1023\n"); |
| print_addbapara_usage(); |
| return UAP_FAILURE; |
| } |
| param.txamsdu = (t_u8)A2HEXDECIMAL(argv[3]); |
| param.rxamsdu = (t_u8)A2HEXDECIMAL(argv[4]); |
| if (param.txamsdu > 1 || param.rxamsdu > 1) { |
| printf("ERR: Tx/Rx amsdu should not be 0 or 1\n"); |
| print_addbapara_usage(); |
| return UAP_FAILURE; |
| } |
| } else { |
| param.action = 0; |
| } |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)¶m; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| perror(""); |
| printf("ERR:ADDBA PARA failed\n"); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| if (!argc) { |
| printf("ADDBA parameters:\n"); |
| printf("\ttimeout=%d\n", (int)param.timeout); |
| printf("\ttxwinsize=%d\n", (int)param.txwinsize); |
| printf("\trxwinsize=%d\n", (int)param.rxwinsize); |
| printf("\ttxamsdu=%d\n", (int)param.txamsdu); |
| printf("\trxamsdu=%d\n", (int)param.rxamsdu); |
| } |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Show usage information for aggrpriotbl command |
| * |
| * $return N/A |
| */ |
| void |
| print_aggrpriotbl_usage(void) |
| { |
| printf("\nUsage : aggrpriotbl <m0> <n0> <m1> <n1> ... <m7> <n7>"); |
| printf("\nOptions: <mx> : 0 - 7, 0xff to disable AMPDU aggregation."); |
| printf("\n <nx> : 0 - 7, 0xff to disable AMSDU aggregation."); |
| printf("\n empty - get the priority table\n"); |
| return; |
| } |
| |
| /** |
| * @brief Creates aggrpriotbl request and send to driver |
| * |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_aggrpriotbl(int argc, char *argv[]) |
| { |
| int opt; |
| aggr_prio_tbl prio_tbl; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| t_u8 value; |
| int i; |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_aggrpriotbl_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| memset(&prio_tbl, 0, sizeof(prio_tbl)); |
| /* Check arguments */ |
| if ((argc != 0) && (argc != 16)) { |
| printf("ERR:wrong arguments. Only support 0 or 16 arguments\n"); |
| print_aggrpriotbl_usage(); |
| return UAP_FAILURE; |
| } |
| prio_tbl.subcmd = UAP_AGGR_PRIOTBL; |
| if (argc) { |
| for (i = 0; i < argc; i++) { |
| if ((IS_HEX_OR_DIGIT(argv[i]) == UAP_FAILURE)) { |
| printf("ERR: Only Number values are allowed\n"); |
| print_aggrpriotbl_usage(); |
| return UAP_FAILURE; |
| } |
| value = (t_u8)A2HEXDECIMAL(argv[i]); |
| if ((value > 7) && (value != 0xff)) { |
| printf("ERR: Invalid priority, Valid value 0-7, 0xff to disable aggregation.\n"); |
| print_aggrpriotbl_usage(); |
| return UAP_FAILURE; |
| } |
| } |
| prio_tbl.action = 1; |
| for (i = 0; i < MAX_NUM_TID; i++) { |
| prio_tbl.ampdu[i] = (t_u8)A2HEXDECIMAL(argv[i * 2]); |
| prio_tbl.amsdu[i] = (t_u8)A2HEXDECIMAL(argv[i * 2 + 1]); |
| } |
| } else { |
| prio_tbl.action = 0; |
| } |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)&prio_tbl; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| perror(""); |
| printf("ERR: priority table failed\n"); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| if (!argc) { |
| printf("AMPDU/AMSDU priority table:"); |
| for (i = 0; i < MAX_NUM_TID; i++) { |
| printf(" %d %d", prio_tbl.ampdu[i], prio_tbl.amsdu[i]); |
| } |
| printf("\n"); |
| } |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Show usage information for addbareject command |
| * |
| * $return N/A |
| */ |
| void |
| print_addba_reject_usage(void) |
| { |
| printf("\nUsage : addbareject <m0> <m1> ... <m7>"); |
| printf("\nOptions: <mx> : 1 enables rejection of ADDBA request for TidX."); |
| printf("\n 0 would accept any ADDBAs for TidX."); |
| printf("\n empty - get the addbareject table\n"); |
| return; |
| } |
| |
| /** |
| * @brief Creates addbareject request and send to driver |
| * |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_addbareject(int argc, char *argv[]) |
| { |
| int opt; |
| addba_reject_para param; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| int i; |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_addba_reject_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| memset(¶m, 0, sizeof(param)); |
| /* Check arguments */ |
| if ((argc != 0) && (argc != 8)) { |
| printf("ERR:wrong arguments. Only support 0 or 8 arguments\n"); |
| print_addba_reject_usage(); |
| return UAP_FAILURE; |
| } |
| param.subcmd = UAP_ADDBA_REJECT; |
| if (argc) { |
| for (i = 0; i < argc; i++) { |
| if ((ISDIGIT(argv[i]) == UAP_FAILURE) || |
| (atoi(argv[i]) < 0) || (atoi(argv[i]) > 1)) { |
| printf("ERR: Only allow 0 or 1\n"); |
| print_addba_reject_usage(); |
| return UAP_FAILURE; |
| } |
| } |
| param.action = 1; |
| for (i = 0; i < MAX_NUM_TID; i++) { |
| param.addba_reject[i] = (t_u8)atoi(argv[i]); |
| } |
| } else { |
| param.action = 0; |
| } |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)¶m; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| perror(""); |
| printf("ERR: addba reject table failed\n"); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| if (!argc) { |
| printf("addba reject table: "); |
| for (i = 0; i < MAX_NUM_TID; i++) { |
| printf("%d ", param.addba_reject[i]); |
| } |
| printf("\n"); |
| } |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Creates get_fw_info request and send to driver |
| * |
| * |
| * @param pfw_info Pointer to FW information structure |
| * @return 0--success, otherwise fail |
| */ |
| int |
| get_fw_info(fw_info *pfw_info) |
| { |
| struct ifreq ifr; |
| t_s32 sockfd; |
| |
| memset(pfw_info, 0, sizeof(fw_info)); |
| pfw_info->subcmd = UAP_FW_INFO; |
| pfw_info->action = 0; |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return -1; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)pfw_info; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| perror(""); |
| printf("ERR: get fw info failed\n"); |
| close(sockfd); |
| return -1; |
| } |
| /* Close socket */ |
| close(sockfd); |
| return 0; |
| } |
| |
| /** |
| * @brief Show usage information for HT Tx command |
| * |
| * $return N/A |
| */ |
| void |
| print_ht_tx_usage(void) |
| { |
| printf("\nUsage : httxcfg [<txcfg>] [<band>]"); |
| printf("\nOptions: txcfg : This is a bitmap and should be used as following"); |
| printf("\n Bit 15-7: Reserved set to 0"); |
| printf("\n Bit 6: Short GI in 40 Mhz enable/disable"); |
| printf("\n Bit 5: Short GI in 20 Mhz enable/disable"); |
| printf("\n Bit 4: Green field enable/disable"); |
| printf("\n Bit 3-2: Reserved set to 0"); |
| printf("\n Bit 1: 20/40 Mhz enable disable."); |
| printf("\n Bit 0: Reserved set to 0"); |
| printf("\n band : This is the band info for <txcfg> settings."); |
| printf("\n 0: Settings for both 2.4G and 5G bands"); |
| printf("\n 1: Settings for 2.4G band"); |
| printf("\n 2: Settings for 5G band\n"); |
| return; |
| } |
| |
| /** |
| * @brief Process HT Tx configuration |
| * @param argc Number of arguments |
| * @param argv A pointer to arguments array |
| * @return MLAN_STATUS_SUCCESS--success, otherwise--fail |
| */ |
| int |
| apcmd_sys_cfg_ht_tx(int argc, char *argv[]) |
| { |
| int opt; |
| ht_tx_cfg_para param; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_ht_tx_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| memset(¶m, 0, sizeof(param)); |
| /* Check arguments */ |
| if (argc == 0) { |
| param.action = ACTION_GET; |
| } else if (argc <= 2) { |
| param.action = ACTION_SET; |
| param.tx_cfg.httxcap = (t_u16)A2HEXDECIMAL(argv[0]); |
| if (argc == 2) { |
| if (atoi(argv[1]) != BAND_SELECT_BG && |
| atoi(argv[1]) != BAND_SELECT_A && |
| atoi(argv[1]) != BAND_SELECT_BOTH) { |
| printf("ERR:Invalid band selection\n"); |
| return UAP_FAILURE; |
| } |
| param.tx_cfg.misc_cfg = (t_u32)A2HEXDECIMAL(argv[1]); |
| } |
| } else { |
| print_ht_tx_usage(); |
| return UAP_FAILURE; |
| } |
| param.subcmd = UAP_HT_TX_CFG; |
| |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)¶m; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| perror(""); |
| printf("ERR: HT Tx configuration failed\n"); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| |
| /* Handle response */ |
| if (param.action == ACTION_GET) { |
| printf("HT Tx cfg: \n"); |
| printf(" BG band: 0x%08x\n", param.tx_cfg.httxcap); |
| printf(" A band : 0x%08x\n", param.tx_cfg.misc_cfg); |
| } |
| |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Show usage information for vhtcfg command |
| * |
| * $return N/A |
| */ |
| void |
| print_vht_usage(void) |
| { |
| printf("\nUsage : vhtcfg <band> <txrx> <bwcfg> <vhtcap> <tx_mcs_map>" |
| "<rx_mcs_map>"); |
| printf("\nOption: band : This is the band info for vhtcfg settings."); |
| printf("\n 0: Settings for both 2.4G and 5G bands"); |
| printf("\n 1: Settings for 2.4G band"); |
| printf("\n 2: Settings for 5G band"); |
| printf("\n txrx : This parameter specifies the configuration of VHT" "operation for TX or/and VHT capabilities."); |
| printf("\n 1: configuration of VHT capabilities tx"); |
| printf("\n 2: configuration of VHT capabilities rx"); |
| printf("\n bwcfg : This parameter specifies the bandwidth (BW)" |
| "configuration applied to the vhtcfg."); |
| printf("\n If <txrx> is 1/3 (Tx operations)"); |
| printf("\n 0: Tx BW follows the BW (20/40 MHz) from" "11N CFG"); |
| printf("\n 1: Tx BW follows the BW (80/160/80+80 MHz)" "from VHT Capabilities."); |
| printf("\n vhtcap : This parameter specifies the VHT capabilities info."); |
| printf("\n tx_mcs_map : This parameter specifies the TX MCS map."); |
| printf("\n rx_mcs_map : This parameter specifies the RX MCS map.\n"); |
| return; |
| } |
| |
| /** |
| * @brief Handle response of the vhtcfg command |
| * |
| * @param vhtcfg Pointer to structure eth_priv_vhtcfg |
| * |
| * $return N/A |
| */ |
| void |
| print_vht_response(struct eth_priv_vhtcfg *vhtcfg) |
| { |
| /* GET operation */ |
| /* Band */ |
| if (vhtcfg->band == BAND_SELECT_BG) |
| printf("Band: 2.4G\n"); |
| else |
| printf("Band: 5G\n"); |
| /* BW confi9 */ |
| if (vhtcfg->txrx & 0x3) { |
| if (vhtcfg->bwcfg == 0) |
| printf(" BW config: the 11N config\n"); |
| else |
| printf(" BW config: the VHT Capabilities\n"); |
| } |
| /* Tx/Rx */ |
| if (vhtcfg->txrx & 0x1) |
| printf(" VHT operation for Tx: 0x%08x\n", |
| vhtcfg->vht_cap_info); |
| if (vhtcfg->txrx & 0x2) |
| /* VHT capabilities */ |
| printf(" VHT Capabilities Info: 0x%08x\n", |
| vhtcfg->vht_cap_info); |
| /* MCS */ |
| printf(" Tx MCS set: 0x%04x\n", vhtcfg->vht_tx_mcs); |
| printf(" Rx MCS set: 0x%04x\n", vhtcfg->vht_rx_mcs); |
| } |
| |
| /** |
| * @brief Set/Get 11AC configurations |
| * @param argc Number of arguments |
| * @param argv A pointer to arguments array |
| * @return MLAN_STATUS_SUCCESS--success, otherwise--fail |
| */ |
| int |
| apcmd_sys_cfg_vht(int argc, char *argv[]) |
| { |
| int opt, i = 0; |
| vht_cfg_para param; |
| struct eth_priv_vhtcfg vhtcfg; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| t_u8 *respbuf = NULL, num = 0; |
| fw_info fw; |
| |
| if (0 == get_fw_info(&fw)) { |
| /*check whether support 802.11AC through BAND_AAC bit */ |
| if (!(fw.fw_bands & BAND_AAC)) { |
| printf("ERR: No support 802 11AC.\n"); |
| return UAP_FAILURE; |
| } |
| } else { |
| printf("ERR: get_fw_info fail\n"); |
| return UAP_FAILURE; |
| } |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_vht_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| respbuf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER); |
| if (!respbuf) { |
| printf("ERR:Cannot allocate buffer for command!\n"); |
| return UAP_FAILURE; |
| } |
| memset(respbuf, 0, MRVDRV_SIZE_OF_CMD_BUFFER); |
| |
| /* Check arguments */ |
| if ((argc > 6) || (argc < 2)) { |
| printf("ERR: Invalid number of arguments.\n"); |
| print_vht_usage(); |
| free(respbuf); |
| return UAP_FAILURE; |
| } |
| if ((atoi(argv[0]) < 0) || (atoi(argv[0]) > 2)) { |
| printf("ERR: Invalid band selection.\n"); |
| print_vht_usage(); |
| free(respbuf); |
| return UAP_FAILURE; |
| } else { |
| param.vht_cfg.band = (t_u32)A2HEXDECIMAL(argv[0]); |
| } |
| if ((atoi(argv[1]) <= 0) || (atoi(argv[1]) > 3)) { |
| printf("ERR: Invalid Tx/Rx selection.\n"); |
| print_vht_usage(); |
| free(respbuf); |
| return UAP_FAILURE; |
| } else { |
| param.vht_cfg.txrx = (t_u32)A2HEXDECIMAL(argv[1]); |
| } |
| if (argc == 2) { |
| param.action = ACTION_GET; |
| } else if (argc > 2) { |
| param.vht_cfg.band = (t_u32)A2HEXDECIMAL(argv[0]); |
| param.vht_cfg.txrx = (t_u32)A2HEXDECIMAL(argv[1]); |
| if (argc == 3) { |
| printf("ERR: Invalid number of arguments.\n"); |
| print_vht_usage(); |
| free(respbuf); |
| return UAP_FAILURE; |
| } |
| if (argc >= 4) { |
| if ((atoi(argv[2]) < 0) || (atoi(argv[2]) > 1) || |
| ((atoi(argv[2]) == 1) && |
| (atoi(argv[0]) & BAND_SELECT_BG))) { |
| printf("ERR: Invalid BW cfg selection.\n"); |
| print_vht_usage(); |
| free(respbuf); |
| return UAP_FAILURE; |
| } else { |
| param.vht_cfg.bwcfg = |
| (t_u32)A2HEXDECIMAL(argv[2]); |
| } |
| param.vht_cfg.vht_cap_info = |
| (t_u32)A2HEXDECIMAL(argv[3]); |
| if (argc == 4) { |
| param.vht_cfg.vht_tx_mcs = 0xffffffff; |
| param.vht_cfg.vht_rx_mcs = 0xffffffff; |
| } else { |
| if (argc == 5) { |
| printf("ERR: Invalid number of arguments.\n"); |
| print_vht_usage(); |
| free(respbuf); |
| return UAP_FAILURE; |
| } |
| param.vht_cfg.vht_tx_mcs = |
| (t_u32)A2HEXDECIMAL(argv[4]); |
| param.vht_cfg.vht_rx_mcs = |
| (t_u32)A2HEXDECIMAL(argv[5]); |
| } |
| } |
| param.action = ACTION_SET; |
| } else { |
| print_vht_usage(); |
| free(respbuf); |
| return UAP_FAILURE; |
| } |
| param.subcmd = UAP_VHT_CFG; |
| memcpy(respbuf, ¶m, sizeof(vht_cfg_para)); |
| |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| free(respbuf); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)respbuf; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| perror(""); |
| printf("ERR: 11ac VHT configuration failed\n"); |
| close(sockfd); |
| free(respbuf); |
| return UAP_FAILURE; |
| } |
| |
| /* Handle response */ |
| if (param.action == ACTION_GET) { |
| /* Process result */ |
| /* the first attribute is the number of vhtcfg entries */ |
| num = *respbuf; |
| printf("11AC VHT Configuration: \n"); |
| for (i = 0; i < num; i++) { |
| memcpy(&vhtcfg, respbuf + 1 + i * sizeof(vhtcfg), |
| sizeof(vhtcfg)); |
| print_vht_response(&vhtcfg); |
| } |
| } else |
| printf("11AC VHT Configuration success!\n"); |
| |
| /* Close socket */ |
| close(sockfd); |
| if (respbuf) |
| free(respbuf); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Show usage information for TX BF command |
| * |
| * $return N/A |
| */ |
| void |
| print_tx_bf_usage(void) |
| { |
| printf("\nUsage : httxbfcfg <ACTION> [ACT_DATA]"); |
| printf("\nOptions: ACTION : 1 - Performs NDP Sounding for PEER"); |
| printf("\n 2 - TX BF interval in milliseconds"); |
| printf("\n 3 - Not to perform any sounding"); |
| printf("\n 4 - TX BF SNR Threshold for peer"); |
| printf("\n ACT_DATA : Specific data for the above actions"); |
| printf("\n For 1: PEER MAC and status"); |
| printf("\n For 2: TX BF interval"); |
| printf("\n For 3: PEER MAC"); |
| printf("\n For 4: PEER MAC and SNR"); |
| printf("\n empty - get action specific settings\n"); |
| return; |
| } |
| |
| /** |
| * @brief Handle response of the TX BF command |
| * |
| * @param param Pointer to structure tx_bf_cfg_para |
| * |
| * $return N/A |
| */ |
| void |
| print_tx_bf_response(tx_bf_cfg_para *param) |
| { |
| int i; |
| trigger_sound_args *bf_sound = param->body.bf_sound; |
| tx_bf_peer_args *tx_bf_peer = param->body.tx_bf_peer; |
| snr_thr_args *bf_snr = param->body.bf_snr; |
| bf_periodicity_args *bf_periodicity = param->body.bf_periodicity; |
| bf_global_cfg_args *bf_global = ¶m->body.bf_global_cfg; |
| |
| switch (param->bf_action) { |
| case BF_GLOBAL_CONFIGURATION: |
| printf("Global BF Status :%s\n", |
| bf_global->bf_enbl ? "ENABLED" : "DISABLED"); |
| printf("Global Sounding Status :%s\n", |
| bf_global->sounding_enbl ? "ENABLED" : "DISABLED"); |
| printf("Default FB Type :%d\n", bf_global->fb_type); |
| printf("Default SNR Threshold :%d\n", bf_global->snr_threshold); |
| printf("Default Sounding Interval :%d\n", |
| bf_global->sounding_interval); |
| printf("Beamforming Mode :%d\n", bf_global->bf_mode); |
| break; |
| case TRIGGER_SOUNDING_FOR_PEER: |
| printf("PEER MAC = %02X:%02X:%02X:%02X:%02X:%02X, STATUS = %s\n", bf_sound->peer_mac[0], bf_sound->peer_mac[1], bf_sound->peer_mac[2], bf_sound->peer_mac[3], bf_sound->peer_mac[4], bf_sound->peer_mac[5], bf_sound->status ? "Failure" : "Success"); |
| break; |
| case SET_GET_BF_PERIODICITY: |
| printf("PEER MAC = %02x:%02x:%02x:%02x:%02x:%02x, Interval (ms) = %d\n", bf_periodicity->peer_mac[0], bf_periodicity->peer_mac[1], bf_periodicity->peer_mac[2], bf_periodicity->peer_mac[3], bf_periodicity->peer_mac[4], bf_periodicity->peer_mac[5], bf_periodicity->interval); |
| break; |
| case TX_BF_FOR_PEER_ENBL: |
| for (i = 0; i < param->no_of_peers; i++) { |
| printf("PEER MAC = %02x:%02x:%02x:%02x:%02x:%02x\n", |
| tx_bf_peer->peer_mac[0], tx_bf_peer->peer_mac[1], |
| tx_bf_peer->peer_mac[2], tx_bf_peer->peer_mac[3], |
| tx_bf_peer->peer_mac[4], |
| tx_bf_peer->peer_mac[5]); |
| printf("BF Status : %s\n", |
| tx_bf_peer->bf_enbl ? "ENABLED" : "DISABLED"); |
| printf("Sounding Status : %s\n", |
| tx_bf_peer-> |
| sounding_enbl ? "ENABLED" : "DISABLED"); |
| printf("FB Type : %d\n", tx_bf_peer->fb_type); |
| tx_bf_peer++; |
| } |
| break; |
| case SET_SNR_THR_PEER: |
| for (i = 0; i < param->no_of_peers; i++) { |
| printf("PEER MAC = %02x:%02x:%02x:%02x:%02x:%02x, SNR = %d\n", bf_snr->peer_mac[0], bf_snr->peer_mac[1], bf_snr->peer_mac[2], bf_snr->peer_mac[3], bf_snr->peer_mac[4], bf_snr->peer_mac[5], bf_snr->snr); |
| bf_snr++; |
| } |
| break; |
| } |
| } |
| |
| /** Tx BF Global conf argument index */ |
| #define BF_ENABLE_PARAM 1 |
| #define SOUND_ENABLE_PARAM 2 |
| #define FB_TYPE_PARAM 3 |
| #define SNR_THRESHOLD_PARAM 4 |
| #define SOUND_INTVL_PARAM 5 |
| #define BF_MODE_PARAM 6 |
| #define BF_CFG_ACT_GET 0 |
| #define BF_CFG_ACT_SET 1 |
| |
| /** |
| * @brief Creates TX BF request and send to driver |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_sys_cfg_tx_bf(int argc, char *argv[]) |
| { |
| int opt, ret = UAP_FAILURE; |
| tx_bf_cfg_para param; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| t_u32 bf_action = 0; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_tx_bf_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| memset(¶m, 0, sizeof(param)); |
| /* Check arguments */ |
| if (argc < 1) { |
| printf("ERR: wrong arguments.\n"); |
| print_tx_bf_usage(); |
| return UAP_FAILURE; |
| } |
| if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) || |
| ((atoi(argv[0]) < BF_GLOBAL_CONFIGURATION) || |
| (atoi(argv[0]) > SET_SNR_THR_PEER))) { |
| printf("ERR: Only Number values are allowed\n"); |
| print_tx_bf_usage(); |
| return UAP_FAILURE; |
| } |
| bf_action = (t_u32)A2HEXDECIMAL(argv[0]); |
| param.subcmd = UAP_TX_BF_CFG; |
| param.bf_action = bf_action; |
| switch (bf_action) { |
| case BF_GLOBAL_CONFIGURATION: |
| if (argc != 1 && argc != 7) { |
| printf("Invalid argument for Global BF Configuration\n"); |
| return UAP_FAILURE; |
| } |
| if (argc == 1) { |
| param.bf_cmd_action = BF_CFG_ACT_GET; |
| param.action = ACTION_GET; |
| } else { |
| param.bf_cmd_action = BF_CFG_ACT_SET; |
| param.action = ACTION_SET; |
| param.body.bf_global_cfg.bf_enbl = |
| atoi(argv[BF_ENABLE_PARAM]); |
| param.body.bf_global_cfg.sounding_enbl = |
| atoi(argv[SOUND_ENABLE_PARAM]); |
| param.body.bf_global_cfg.fb_type = |
| atoi(argv[FB_TYPE_PARAM]); |
| param.body.bf_global_cfg.snr_threshold = |
| atoi(argv[SNR_THRESHOLD_PARAM]); |
| param.body.bf_global_cfg.sounding_interval = |
| atoi(argv[SOUND_INTVL_PARAM]); |
| param.body.bf_global_cfg.bf_mode = |
| atoi(argv[BF_MODE_PARAM]); |
| } |
| break; |
| case TRIGGER_SOUNDING_FOR_PEER: |
| if (argc != 2) { |
| printf("ERR: wrong arguments.\n"); |
| print_tx_bf_usage(); |
| return UAP_FAILURE; |
| } |
| if ((ret = |
| mac2raw(argv[1], |
| param.body.bf_sound[0].peer_mac)) != UAP_SUCCESS) { |
| printf("ERR: %s Address\n", |
| ret == UAP_FAILURE ? "Invalid MAC" : ret == |
| UAP_RET_MAC_BROADCAST ? "Broadcast" : |
| "Multicast"); |
| return UAP_FAILURE; |
| } |
| param.bf_cmd_action = BF_CFG_ACT_SET; |
| param.action = ACTION_SET; |
| break; |
| case SET_GET_BF_PERIODICITY: |
| if (argc != 2 && argc != 3) { |
| printf("ERR: wrong arguments.\n"); |
| print_tx_bf_usage(); |
| return UAP_FAILURE; |
| } |
| if ((ret = |
| mac2raw(argv[1], |
| param.body.bf_periodicity[0].peer_mac)) != |
| UAP_SUCCESS) { |
| printf("ERR: %s Address\n", |
| ret == UAP_FAILURE ? "Invalid MAC" : ret == |
| UAP_RET_MAC_BROADCAST ? "Broadcast" : |
| "Multicast"); |
| return UAP_FAILURE; |
| } |
| |
| if (argc == 3) { |
| if (IS_HEX_OR_DIGIT(argv[2]) == UAP_FAILURE) |
| return UAP_FAILURE; |
| param.body.bf_periodicity[0].interval = |
| (t_u32)A2HEXDECIMAL(argv[2]); |
| param.bf_cmd_action = BF_CFG_ACT_SET; |
| param.action = ACTION_SET; |
| } else { |
| param.bf_cmd_action = BF_CFG_ACT_GET; |
| param.action = ACTION_GET; |
| } |
| break; |
| case TX_BF_FOR_PEER_ENBL: |
| if (argc != 1 && argc != 5) { |
| printf("ERR: wrong arguments.\n"); |
| print_tx_bf_usage(); |
| return UAP_FAILURE; |
| } |
| if (argc == 1) { |
| param.bf_cmd_action = BF_CFG_ACT_GET; |
| param.action = ACTION_GET; |
| } else { |
| if ((ret = |
| mac2raw(argv[1], |
| param.body.tx_bf_peer[0].peer_mac)) != |
| UAP_SUCCESS) { |
| printf("ERR: %s Address\n", |
| ret == |
| UAP_FAILURE ? "Invalid MAC" : ret == |
| UAP_RET_MAC_BROADCAST ? "Broadcast" : |
| "Multicast"); |
| return UAP_FAILURE; |
| } |
| param.body.tx_bf_peer->bf_enbl = atoi(argv[2]); |
| param.body.tx_bf_peer->sounding_enbl = atoi(argv[3]); |
| param.body.tx_bf_peer->fb_type = atoi(argv[4]); |
| param.bf_cmd_action = BF_CFG_ACT_SET; |
| param.action = ACTION_SET; |
| } |
| break; |
| case SET_SNR_THR_PEER: |
| if (argc != 1 && argc != 3) { |
| printf("ERR: wrong arguments.\n"); |
| print_tx_bf_usage(); |
| return UAP_FAILURE; |
| } |
| if (argc == 1) { |
| param.bf_cmd_action = BF_CFG_ACT_GET; |
| param.action = ACTION_GET; |
| } else { |
| if ((ret = |
| mac2raw(argv[1], |
| param.body.bf_snr[0].peer_mac)) != |
| UAP_SUCCESS) { |
| printf("ERR: %s Address\n", |
| ret == |
| UAP_FAILURE ? "Invalid MAC" : ret == |
| UAP_RET_MAC_BROADCAST ? "Broadcast" : |
| "Multicast"); |
| return UAP_FAILURE; |
| } |
| if (IS_HEX_OR_DIGIT(argv[2]) == UAP_FAILURE) |
| return UAP_FAILURE; |
| param.body.bf_snr[0].snr = (t_u8)A2HEXDECIMAL(argv[2]); |
| param.bf_cmd_action = BF_CFG_ACT_SET; |
| param.action = ACTION_SET; |
| } |
| break; |
| default: |
| return UAP_FAILURE; |
| } |
| |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)¶m; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| perror(""); |
| printf("ERR: TX BF configuration failed\n"); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| |
| printf("TX BF configuration successful\n"); |
| /* Handle response */ |
| if (param.action == ACTION_GET) |
| print_tx_bf_response(¶m); |
| |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Show usage information for hscfg command |
| * |
| * $return N/A |
| */ |
| void |
| print_hscfg_usage(void) |
| { |
| printf("\nUsage : hscfg [condition [[GPIO# [gap]]]]"); |
| printf("\nOptions: condition : bit 0 = 1 -- broadcast data"); |
| printf("\n bit 1 = 1 -- unicast data"); |
| printf("\n bit 2 = 1 -- mac event"); |
| printf("\n bit 3 = 1 -- multicast packet"); |
| printf("\n bit 6 = 1 -- mgmt frame received"); |
| printf("\n GPIO: the pin number (e.g. 0-7) of GPIO used to wakeup the host"); |
| printf("\n or 0xff interface (e.g. SDIO) used to wakeup the host"); |
| printf("\n gap: time between wakeup signal and wakeup event (in milliseconds)"); |
| printf("\n or 0xff for special setting when GPIO is used to wakeup host"); |
| printf("\n empty - get current host sleep parameters\n"); |
| return; |
| } |
| |
| /** |
| * @brief Creates host sleep parameter request and send to driver |
| * |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_hscfg(int argc, char *argv[]) |
| { |
| int opt; |
| int i = 0; |
| ds_hs_cfg hscfg; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| |
| if ((argc == 2) && strstr(argv[1], "-1")) |
| strcpy(argv[1], "0xffff"); |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_hscfg_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| memset(&hscfg, 0, sizeof(hscfg)); |
| hscfg.subcmd = UAP_HS_CFG; |
| /* Check arguments */ |
| if (argc > 3) { |
| printf("ERR:wrong arguments.\n"); |
| print_hscfg_usage(); |
| return UAP_FAILURE; |
| } |
| if (argc) { |
| for (i = 0; i < argc; i++) { |
| if (IS_HEX_OR_DIGIT(argv[i]) == UAP_FAILURE) { |
| printf("ERR: Invalid argument %s\n", argv[i]); |
| print_hscfg_usage(); |
| return UAP_FAILURE; |
| } |
| } |
| } |
| |
| if (argc) { |
| hscfg.flags |= HS_CFG_FLAG_SET | HS_CFG_FLAG_CONDITION; |
| hscfg.conditions = (t_u32)A2HEXDECIMAL(argv[0]); |
| if (hscfg.conditions >= 0xffff) |
| hscfg.conditions = HS_CFG_CANCEL; |
| if ((hscfg.conditions != HS_CFG_CANCEL) && |
| (hscfg.conditions & ~HS_CFG_CONDITION_MASK)) { |
| printf("ERR:Illegal conditions 0x%x\n", |
| hscfg.conditions); |
| print_hscfg_usage(); |
| return UAP_FAILURE; |
| } |
| if (argc > 1) { |
| hscfg.flags |= HS_CFG_FLAG_GPIO; |
| hscfg.gpio = (t_u32)A2HEXDECIMAL(argv[1]); |
| if (hscfg.gpio > 255) { |
| printf("ERR:Illegal gpio 0x%x\n", hscfg.gpio); |
| print_hscfg_usage(); |
| return UAP_FAILURE; |
| } |
| } |
| if (argc > 2) { |
| hscfg.flags |= HS_CFG_FLAG_GAP; |
| hscfg.gap = (t_u32)A2HEXDECIMAL(argv[2]); |
| } |
| } else { |
| hscfg.flags = HS_CFG_FLAG_GET; |
| } |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)&hscfg; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| perror(""); |
| printf("ERR:UAP_HS_CFG failed\n"); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| if (!argc) { |
| printf("Host sleep parameters:\n"); |
| printf("\tconditions=%d\n", (int)hscfg.conditions); |
| printf("\tGPIO=%d\n", (int)hscfg.gpio); |
| printf("\tgap=%d\n", (int)hscfg.gap); |
| } |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Show usage information for hssetpara command |
| * |
| * $return N/A |
| */ |
| void |
| print_hssetpara_usage(void) |
| { |
| printf("\nUsage : hssetpara condition [[GPIO# [gap]]]"); |
| printf("\nOptions: condition : bit 0 = 1 -- broadcast data"); |
| printf("\n bit 1 = 1 -- unicast data"); |
| printf("\n bit 2 = 1 -- mac event"); |
| printf("\n bit 3 = 1 -- multicast packet"); |
| printf("\n bit 6 = 1 -- mgmt frame received"); |
| printf("\n GPIO: the pin number (e.g. 0-7) of GPIO used to wakeup the host"); |
| printf("\n or 0xff interface (e.g. SDIO) used to wakeup the host"); |
| printf("\n gap: time between wakeup signal and wakeup event (in milliseconds)"); |
| printf("\n or 0xff for special setting when GPIO is used to wakeup host\n"); |
| return; |
| } |
| |
| /** |
| * @brief Creates host sleep parameter request and send to driver |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_hssetpara(int argc, char *argv[]) |
| { |
| int opt; |
| int i = 0; |
| ds_hs_cfg hscfg; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| |
| if ((argc == 2) && strstr(argv[1], "-1")) |
| strcpy(argv[1], "0xffff"); |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_hssetpara_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| memset(&hscfg, 0, sizeof(hscfg)); |
| hscfg.subcmd = UAP_HS_SET_PARA; |
| /* Check arguments */ |
| if ((argc < 1) || (argc > 3)) { |
| printf("ERR:wrong arguments.\n"); |
| print_hssetpara_usage(); |
| return UAP_FAILURE; |
| } |
| for (i = 0; i < argc; i++) { |
| if (IS_HEX_OR_DIGIT(argv[i]) == UAP_FAILURE) { |
| printf("ERR: Invalid argument %s\n", argv[i]); |
| print_hssetpara_usage(); |
| return UAP_FAILURE; |
| } |
| } |
| |
| hscfg.flags |= HS_CFG_FLAG_SET | HS_CFG_FLAG_CONDITION; |
| hscfg.conditions = (t_u32)A2HEXDECIMAL(argv[0]); |
| if (hscfg.conditions >= 0xffff) |
| hscfg.conditions = HS_CFG_CANCEL; |
| if ((hscfg.conditions != HS_CFG_CANCEL) && |
| (hscfg.conditions & ~HS_CFG_CONDITION_MASK)) { |
| printf("ERR:Illegal conditions 0x%x\n", hscfg.conditions); |
| print_hssetpara_usage(); |
| return UAP_FAILURE; |
| } |
| if (argc > 1) { |
| hscfg.flags |= HS_CFG_FLAG_GPIO; |
| hscfg.gpio = (t_u32)A2HEXDECIMAL(argv[1]); |
| if (hscfg.gpio > 255) { |
| printf("ERR:Illegal gpio 0x%x\n", hscfg.gpio); |
| print_hssetpara_usage(); |
| return UAP_FAILURE; |
| } |
| } |
| if (argc > 2) { |
| hscfg.flags |= HS_CFG_FLAG_GAP; |
| hscfg.gap = (t_u32)A2HEXDECIMAL(argv[2]); |
| } |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* 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 *)&hscfg; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| perror(""); |
| printf("ERR:UAP_HS_SET_PARA failed\n"); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| printf("Host sleep parameters setting successful!\n"); |
| printf("\tconditions=%d\n", (int)hscfg.conditions); |
| printf("\tGPIO=%d\n", (int)hscfg.gpio); |
| printf("\tgap=%d\n", (int)hscfg.gap); |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief get dfs repeater mode |
| * |
| * @param mode status of DFS repeater mode is returned here |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| uap_ioctl_dfs_repeater_mode(int *mode) |
| { |
| struct ifreq ifr; |
| dfs_repeater_mode param; |
| t_s32 sockfd; |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)¶m; |
| param.action = ACTION_GET; |
| param.subcmd = UAP_DFS_REPEATER_MODE; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| printf("ERR:UAP_DFS_REPEATER_MODE is not" |
| "supported by %s\n", dev_name); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| *mode = (int)param.mode; |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Get CAC timer status |
| * |
| * @param mode status of CAC timer is returned here |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| uap_ioctl_cac_timer_status(unsigned int *mode) |
| { |
| struct ifreq ifr; |
| cac_timer_status param; |
| t_s32 sockfd; |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)¶m; |
| param.action = ACTION_GET; |
| param.subcmd = UAP_CAC_TIMER_STATUS; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| printf("ERR:UAP_CAC_TIMER_STATUS is not" |
| "supported by %s\n", dev_name); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| *mode = (int)param.mode; |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Set/get power mode |
| * |
| * @param pm A pointer to ps_mgmt structure |
| * @param flag flag for query |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| send_power_mode_ioctl(ps_mgmt * pm, int flag) |
| { |
| struct ifreq ifr; |
| t_s32 sockfd; |
| t_u32 result = 0; |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)pm; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_POWER_MODE, &ifr)) { |
| memcpy((void *)&result, (void *)pm, sizeof(result)); |
| if (result == 1) { |
| printf("ERR:Power mode needs to be disabled before modifying it\n"); |
| } else { |
| perror(""); |
| printf("ERR:UAP_POWER_MODE is not supported by %s\n", |
| dev_name); |
| } |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| if (flag) { |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| 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 UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Show usage information for the pscfg command |
| * |
| * $return N/A |
| */ |
| void |
| print_pscfg_usage(void) |
| { |
| printf("\nUsage : pscfg [MODE] [CTRL INACTTO MIN_SLEEP MAX_SLEEP 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 PS PARAMS:"); |
| printf("\n CTRL: 0 - disable protection frame Tx before PS"); |
| printf("\n 1 - enable protection frame Tx before PS"); |
| printf("\n INACTTO: Inactivity timeout in miroseconds"); |
| printf("\n MIN_SLEEP: Minimum sleep duration in microseconds"); |
| printf("\n MAX_SLEEP: Maximum sleep duration in miroseconds"); |
| printf("\n MIN_AWAKE: Minimum awake duration in microseconds"); |
| printf("\n MAX_AWAKE: Maximum awake duration in microseconds"); |
| printf("\n MIN_AWAKE,MAX_AWAKE only valid for inactivity based power save mode"); |
| printf("\n empty - get current power mode\n"); |
| return; |
| } |
| |
| /** |
| * @brief Creates power mode request and send to driver |
| * and sends to the driver |
| * |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_pscfg(int argc, char *argv[]) |
| { |
| int opt; |
| ps_mgmt pm; |
| int ret = UAP_SUCCESS; |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_pscfg_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| memset(&pm, 0, sizeof(ps_mgmt)); |
| /* Check arguments */ |
| if ((argc > 7) || |
| ((argc != 0) && (argc != 1) && (argc != 5) && (argc != 7))) { |
| printf("ERR:wrong arguments.\n"); |
| print_pscfg_usage(); |
| return UAP_FAILURE; |
| } |
| |
| if (argc) { |
| if (send_power_mode_ioctl(&pm, 1) == UAP_FAILURE) |
| return UAP_FAILURE; |
| 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_pscfg_usage(); |
| return UAP_FAILURE; |
| } |
| 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_pscfg_usage(); |
| return UAP_FAILURE; |
| } |
| if ((pm.ps_mode != PS_MODE_INACTIVITY) && (argc > 5)) { |
| printf("ERR:Min awake period and Max awake period are valid only for inactivity based power save mode\n"); |
| print_pscfg_usage(); |
| return UAP_FAILURE; |
| } |
| if (argc >= 5) { |
| if ((ISDIGIT(argv[1]) == 0) || (atoi(argv[1]) < 0) || |
| (atoi(argv[1]) > 1)) { |
| printf("ERR:Illegal ctrl bitmap = %s. Must be either '0' or '1'.\n", argv[1]); |
| print_pscfg_usage(); |
| return UAP_FAILURE; |
| } |
| pm.flags |= |
| PS_FLAG_SLEEP_PARAM | PS_FLAG_INACT_SLEEP_PARAM; |
| pm.sleep_param.ctrl_bitmap = atoi(argv[1]); |
| if ((ISDIGIT(argv[2]) == 0) || (ISDIGIT(argv[3]) == 0) |
| || (ISDIGIT(argv[4]) == 0)) { |
| printf("ERR:Illegal parameter\n"); |
| print_pscfg_usage(); |
| return UAP_FAILURE; |
| } |
| pm.inact_param.inactivity_to = atoi(argv[2]); |
| 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 UAP_FAILURE; |
| } |
| 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 UAP_FAILURE; |
| } |
| if (argc == 7) { |
| if ((ISDIGIT(argv[5]) == 0) || |
| (ISDIGIT(argv[6]) == 0)) { |
| printf("ERR:Illegal parameter\n"); |
| print_pscfg_usage(); |
| return UAP_FAILURE; |
| } |
| pm.inact_param.min_awake = atoi(argv[5]); |
| pm.inact_param.max_awake = atoi(argv[6]); |
| 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 UAP_FAILURE; |
| } |
| if (pm.inact_param.min_awake < |
| PS_AWAKE_PERIOD_MIN) { |
| printf("ERR: Incorrect value of MIN_AWAKE period.\n"); |
| return UAP_FAILURE; |
| } |
| } |
| } |
| } |
| ret = send_power_mode_ioctl(&pm, 0); |
| return ret; |
| } |
| |
| /** |
| * @brief Get bss status started/stopped |
| * |
| * @param current bss status |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| static int |
| get_bss_status(int *status) |
| { |
| apcmdbuf_sys_configure *cmd_buf = NULL; |
| tlvbuf_bss_status *tlv = NULL; |
| t_u8 *buffer = NULL; |
| t_u16 cmd_len = 0; |
| t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| int ret = UAP_FAILURE; |
| |
| /* Initialize the command length */ |
| cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_bss_status); |
| |
| /* Initialize the command buffer */ |
| buffer = (t_u8 *)malloc(buf_len); |
| |
| if (!buffer) { |
| printf("ERR:Cannot allocate buffer for command!\n"); |
| return UAP_FAILURE; |
| } |
| memset(buffer, 0, buf_len); |
| /* Locate headers */ |
| cmd_buf = (apcmdbuf_sys_configure *)buffer; |
| tlv = (tlvbuf_bss_status *)(buffer + sizeof(apcmdbuf_sys_configure)); |
| |
| /* Fill the command buffer */ |
| cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; |
| cmd_buf->size = cmd_len; |
| cmd_buf->seq_num = 0; |
| cmd_buf->result = 0; |
| tlv->tag = MRVL_BSS_STATUS_TLV_ID; |
| tlv->length = 2; |
| cmd_buf->action = ACTION_GET; |
| |
| endian_convert_tlv_header_out(tlv); |
| /* Send the command */ |
| ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); |
| endian_convert_tlv_header_in(tlv); |
| tlv->bss_status = uap_le16_to_cpu(tlv->bss_status); |
| |
| /* Process response */ |
| if (ret == UAP_SUCCESS) { |
| /* Verify response */ |
| if ((cmd_buf->cmd_code != |
| (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || |
| (tlv->tag != MRVL_BSS_STATUS_TLV_ID)) { |
| printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); |
| free(buffer); |
| return UAP_FAILURE; |
| } |
| /* Print response */ |
| if (cmd_buf->result == CMD_SUCCESS) { |
| if (tlv->bss_status == 0) |
| *status = UAP_BSS_STOP; |
| else |
| *status = UAP_BSS_START; |
| } else { |
| printf("ERR:Could not get BSS status!\n"); |
| } |
| } else { |
| printf("ERR:Command sending failed!\n"); |
| } |
| if (buffer) |
| free(buffer); |
| return ret; |
| } |
| |
| /** |
| * @brief start/stop/reset bss |
| * |
| * @param mode bss control mode |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| send_bss_ctl_ioctl(int mode) |
| { |
| struct ifreq ifr; |
| t_s32 sockfd; |
| t_u32 data = (t_u32)mode; |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)&data; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_BSS_CTRL, &ifr)) { |
| printf("ERR:UAP_BSS_CTRL fail, result=%d\n", (int)data); |
| switch (mode) { |
| case UAP_BSS_START: |
| if (data == BSS_FAILURE_START_INVAL) |
| printf("ERR:Could not start BSS! Invalid BSS parameters.\n"); |
| else |
| printf("ERR:Could not start BSS!\n"); |
| break; |
| case UAP_BSS_STOP: |
| printf("ERR:Could not stop BSS!\n"); |
| break; |
| case UAP_BSS_RESET: |
| printf("ERR:Could not reset system!\n"); |
| break; |
| } |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| |
| switch (mode) { |
| case UAP_BSS_START: |
| printf("BSS start successful!\n"); |
| break; |
| case UAP_BSS_STOP: |
| printf("BSS stop successful!\n"); |
| break; |
| case UAP_BSS_RESET: |
| printf("System reset successful!\n"); |
| break; |
| } |
| |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @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 UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_sys_reset(int argc, char *argv[]) |
| { |
| int opt; |
| int ret = UAP_SUCCESS; |
| ps_mgmt pm; |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_sys_reset_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| /* Check arguments */ |
| if (argc != 0) { |
| printf("ERR:Too many arguments.\n"); |
| print_sys_reset_usage(); |
| return UAP_FAILURE; |
| } |
| memset(&pm, 0, sizeof(ps_mgmt)); |
| pm.flags = PS_FLAG_PS_MODE; |
| pm.ps_mode = PS_MODE_DISABLE; |
| if (send_power_mode_ioctl(&pm, 0) == UAP_FAILURE) |
| return UAP_FAILURE; |
| ret = send_bss_ctl_ioctl(UAP_BSS_RESET); |
| return ret; |
| } |
| |
| /** |
| * @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 UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_bss_start(int argc, char *argv[]) |
| { |
| int opt; |
| t_u8 *buf = NULL; |
| t_u16 buf_len = 0; |
| int status = 0; |
| int ret = UAP_SUCCESS; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_bss_start_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| /* Check arguments */ |
| if (argc != 0) { |
| printf("ERR:Too many arguments.\n"); |
| print_bss_start_usage(); |
| return UAP_FAILURE; |
| } |
| |
| if (get_bss_status(&status) != UAP_SUCCESS) { |
| printf("ERR:Cannot get current bss status!\n"); |
| return UAP_FAILURE; |
| } |
| |
| if (status == UAP_BSS_START) { |
| printf("ERR: Could not start BSS! BSS already started!\n"); |
| return UAP_FAILURE; |
| } |
| |
| /* Query BSS settings */ |
| |
| /* Alloc buf for command */ |
| buf_len = sizeof(apcmdbuf_bss_configure) + sizeof(bss_config_t); |
| buf = (t_u8 *)malloc(buf_len); |
| if (!buf) { |
| printf("ERR:Cannot allocate buffer from command!\n"); |
| return UAP_FAILURE; |
| } |
| memset((char *)buf, 0, buf_len); |
| |
| /* Get all parametes first */ |
| if (get_bss_config(buf) == UAP_FAILURE) { |
| printf("ERR:Reading current bss configuration\n"); |
| free(buf); |
| return UAP_FAILURE; |
| } |
| |
| ret = check_bss_config(buf + sizeof(apcmdbuf_bss_configure)); |
| |
| if (ret == UAP_FAILURE) { |
| printf("ERR: Wrong bss configuration!\n"); |
| goto done; |
| } |
| |
| ret = send_bss_ctl_ioctl(UAP_BSS_START); |
| |
| done: |
| if (buf) |
| free(buf); |
| return ret; |
| } |
| |
| /** |
| * @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 UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_bss_stop(int argc, char *argv[]) |
| { |
| int opt; |
| int status = 0; |
| int ret = UAP_SUCCESS; |
| unsigned int cac_timer = 0; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_bss_stop_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; /* Check arguments */ |
| |
| if (argc != 0) { |
| printf("ERR:Too many arguments.\n"); |
| print_bss_stop_usage(); |
| return UAP_FAILURE; |
| } |
| if (get_bss_status(&status) != UAP_SUCCESS) { |
| printf("ERR:Cannot get current bss status!\n"); |
| return UAP_FAILURE; |
| } |
| |
| if ((status != UAP_BSS_STOP) |
| || ((uap_ioctl_cac_timer_status(&cac_timer) == UAP_SUCCESS) |
| && (cac_timer)) |
| ) |
| ret = send_bss_ctl_ioctl(UAP_BSS_STOP); |
| else { |
| printf("ERR: Could not stop BSS! BSS already stopped!\n"); |
| ret = UAP_FAILURE; |
| } |
| return ret; |
| } |
| |
| void |
| print_skip_cac_usage(void) |
| { |
| printf("\nUsage : skip_cac [MODE]"); |
| printf("\nOptions: MODE : 0 - Disable skip CAC mode"); |
| printf("\n 1 - Enable skip CAC mode"); |
| printf("\n empty - get skip CAC mode\n"); |
| return; |
| } |
| |
| /** |
| * @brief Skip CAC for next immediate BSS_START |
| * |
| * Usage: "skip_cac [1/0]" |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_skip_cac(int argc, char *argv[]) |
| { |
| int opt; |
| skip_cac_para param; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_skip_cac_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| memset(¶m, 0, sizeof(param)); |
| /* Check arguments */ |
| if (argc > 1) { |
| printf("ERR:wrong arguments. Only support 1 argument\n"); |
| print_skip_cac_usage(); |
| return UAP_FAILURE; |
| } |
| param.subcmd = UAP_SKIP_CAC; |
| if (argc) { |
| if (argc == 1) { |
| if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) || |
| ((atoi(argv[0]) < 0) || (atoi(argv[0]) > 1))) { |
| printf("ERR: Only Number values are allowed\n"); |
| print_skip_cac_usage(); |
| return UAP_FAILURE; |
| } |
| } |
| param.action = 1; |
| param.skip_cac = (t_u16)A2HEXDECIMAL(argv[0]); |
| } else { |
| param.action = 0; |
| } |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)¶m; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| if (argc) |
| printf("ERR:skip_cac set failed\n"); |
| else { |
| perror(""); |
| printf("ERR:skip_cac get failed\n"); |
| } |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| if (!argc) { |
| if (param.skip_cac == 1) { |
| printf("skip CAC mode: enabled\n"); |
| } else { |
| printf("skip CAC mode: disabled\n"); |
| } |
| } |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @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 UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_sta_list(int argc, char *argv[]) |
| { |
| struct ifreq ifr; |
| t_s32 sockfd; |
| sta_list list; |
| 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 UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| /* Check arguments */ |
| if (argc != 0) { |
| printf("ERR:Too many arguments.\n"); |
| print_sta_list_usage(); |
| return UAP_FAILURE; |
| } |
| memset(&list, 0, sizeof(sta_list)); |
| |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)&list; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_GET_STA_LIST, &ifr)) { |
| perror(""); |
| printf("ERR:UAP_GET_STA_LIST is not supported by %s\n", |
| dev_name); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| printf("Number of STA = %d\n\n", list.sta_count); |
| |
| for (i = 0; i < list.sta_count; i++) { |
| printf("STA %d information:\n", i + 1); |
| printf("=====================\n"); |
| printf("MAC Address: "); |
| print_mac(list.info[i].mac_address); |
| printf("\nPower mfg status: %s\n", |
| (list.info[i].power_mfg_status == |
| 0) ? "active" : "power save"); |
| printf("Mode: %s\n", |
| (list.info[i].bandmode == |
| BAND_B) ? "11b," : (list.info[i].bandmode == |
| BAND_G) ? "11g," : (list.info[i]. |
| bandmode == |
| BAND_A) ? "11a," |
| : (list.info[i].bandmode == |
| BAND_GN) ? "2.4G_11n," : (list.info[i].bandmode == |
| BAND_AN) ? "5G_11n," |
| : (list.info[i].bandmode == |
| BAND_GAC) ? "2.4G_11ac," : (list.info[i].bandmode == |
| BAND_AAC) ? "5G_11ac," : |
| "unkown"); |
| /** On some platform, s8 is same as unsigned char*/ |
| rssi = (int)list.info[i].rssi; |
| if (rssi > 0x7f) |
| rssi = -(256 - rssi); |
| printf("Rssi : %d dBm\n\n", rssi); |
| } |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Show usage information for the sta_deauth command |
| * |
| * $return N/A |
| */ |
| void |
| print_sta_deauth_usage(void) |
| { |
| printf("\nUsage : sta_deauth <STA_MAC_ADDRESS>\n"); |
| return; |
| } |
| |
| /** |
| * @brief Creates a STA deauth request and sends to the driver |
| * |
| * Usage: "sta_deauth <STA_MAC_ADDRESS>" |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_sta_deauth(int argc, char *argv[]) |
| { |
| APCMDBUF_STA_DEAUTH *cmd_buf = NULL; |
| t_u8 *buffer = NULL; |
| t_u16 cmd_len = 0; |
| t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| int ret = UAP_FAILURE; |
| int opt; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_sta_deauth_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| /* Check arguments */ |
| if (argc != 1) { |
| printf("ERR:wrong arguments! Must provide STA_MAC_ADDRESS.\n"); |
| print_sta_deauth_usage(); |
| return UAP_FAILURE; |
| } |
| |
| /* Initialize the command length */ |
| cmd_len = sizeof(APCMDBUF_STA_DEAUTH); |
| |
| /* Initialize the command buffer */ |
| buffer = (t_u8 *)malloc(buf_len); |
| if (!buffer) { |
| printf("ERR:Cannot allocate buffer for command!\n"); |
| return UAP_FAILURE; |
| } |
| memset(buffer, 0, buf_len); |
| |
| /* Locate headers */ |
| cmd_buf = (APCMDBUF_STA_DEAUTH *)buffer; |
| |
| /* Fill the command buffer */ |
| cmd_buf->cmd_code = APCMD_STA_DEAUTH; |
| cmd_buf->size = cmd_len - BUF_HEADER_SIZE; |
| cmd_buf->seq_num = 0; |
| cmd_buf->result = 0; |
| if ((ret = mac2raw(argv[0], cmd_buf->sta_mac_address)) != UAP_SUCCESS) { |
| printf("ERR: %s Address\n", ret == UAP_FAILURE ? "Invalid MAC" : |
| ret == |
| UAP_RET_MAC_BROADCAST ? "Broadcast" : "Multicast"); |
| free(buffer); |
| return UAP_FAILURE; |
| } |
| |
| /* Send the command */ |
| ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); |
| |
| /* Process response */ |
| if (ret == UAP_SUCCESS) { |
| /* Verify response */ |
| if (cmd_buf->cmd_code != (APCMD_STA_DEAUTH | APCMD_RESP_CHECK)) { |
| printf("ERR:Corrupted response!\n"); |
| free(buffer); |
| return UAP_FAILURE; |
| } |
| |
| /* Print response */ |
| if (cmd_buf->result == CMD_SUCCESS) { |
| printf("Deauthentication successful!\n"); |
| } else { |
| printf("ERR:Deauthentication unsuccessful!\n"); |
| ret = UAP_FAILURE; |
| } |
| } else { |
| printf("ERR:Command sending failed!\n"); |
| } |
| if (buffer) |
| free(buffer); |
| return ret; |
| } |
| |
| /** |
| * @brief Show usage information for the sta_deauth_ext command |
| * |
| * $return N/A |
| */ |
| void |
| print_sta_deauth_ext_usage(void) |
| { |
| printf("\nUsage : sta_deauth <STA_MAC_ADDRESS> <REASCON_CODE>\n"); |
| return; |
| } |
| |
| /** |
| * @brief Creates a STA deauth request and sends to the driver |
| * |
| * Usage: "sta_deauth <STA_MAC_ADDRESS><REASON_CODE>" |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_sta_deauth_ext(int argc, char *argv[]) |
| { |
| int ret = UAP_SUCCESS; |
| int opt; |
| deauth_param param; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| t_u32 result = 0; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_sta_deauth_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| /* Check arguments */ |
| if (argc != 2) { |
| printf("ERR:wrong arguments! Must provide STA_MAC_ADDRESS, REASON_CODE.\n"); |
| print_sta_deauth_ext_usage(); |
| return UAP_FAILURE; |
| } |
| memset(¶m, 0, sizeof(deauth_param)); |
| |
| if ((ret = mac2raw(argv[0], param.mac_addr)) != UAP_SUCCESS) { |
| printf("ERR: %s Address\n", ret == UAP_FAILURE ? "Invalid MAC" : |
| ret == |
| UAP_RET_MAC_BROADCAST ? "Broadcast" : "Multicast"); |
| return UAP_FAILURE; |
| } |
| |
| if ((IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE) || |
| (atoi(argv[1]) > MAX_DEAUTH_REASON_CODE)) { |
| printf("ERR: Invalid input for reason code\n"); |
| return UAP_FAILURE; |
| } |
| param.reason_code = (t_u16)A2HEXDECIMAL(argv[1]); |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)¶m; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_STA_DEAUTH, &ifr)) { |
| memcpy((void *)&result, (void *)¶m, sizeof(result)); |
| if (result == 1) |
| printf("ERR:UAP_STA_DEAUTH fail\n"); |
| else |
| perror(""); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| printf("Station deauth successful\n"); |
| /* Close socket */ |
| close(sockfd); |
| return ret; |
| } |
| |
| /** |
| * @brief Show usage information for the radioctrl command |
| * |
| * $return N/A |
| */ |
| void |
| print_radio_ctl_usage(void) |
| { |
| printf("\nUsage : radioctrl [ 0 | 1 ]\n"); |
| return; |
| } |
| |
| /** |
| * @brief Creates a Radio control request and sends to the driver |
| * |
| * Usage: "radioctrl [0 | 1]" |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_radio_ctl(int argc, char *argv[]) |
| { |
| int opt; |
| int param[2] = { 0, 0 }; /* action (Set/Get), Control (ON/OFF) */ |
| struct ifreq ifr; |
| t_s32 sockfd; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_radio_ctl_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| /* Check arguments */ |
| if (argc > 1) { |
| printf("ERR:wrong arguments! Only 1 or 0 arguments are supported.\n"); |
| print_radio_ctl_usage(); |
| return UAP_FAILURE; |
| } |
| if (argc && (is_input_valid(RADIOCONTROL, argc, argv) != UAP_SUCCESS)) { |
| print_radio_ctl_usage(); |
| return UAP_FAILURE; |
| } |
| if (argc) { |
| param[0] = ACTION_SET; |
| param[1] = atoi(argv[0]); |
| } |
| |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)param; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_RADIO_CTL, &ifr)) { |
| printf("ERR:UAP_RADIO_CTL fail\n"); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| if (argc) |
| printf("Radio setting successful\n"); |
| else |
| printf("Radio is %s.\n", (param[1]) ? "on" : "off"); |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Show usage information for the txratecfg command |
| * |
| * $return N/A |
| */ |
| void |
| print_txratecfg_usage(void) |
| { |
| printf("\nUsage : txratecfg <datarate index> Index should be one of the following.\n"); |
| printf("\n [l] is <format>"); |
| printf("\n <format> - This parameter specifies the data rate format used in this command"); |
| printf("\n 0: LG"); |
| printf("\n 1: HT"); |
| printf("\n 2: VHT"); |
| printf("\n 0xff: Auto"); |
| printf("\n"); |
| printf("\n [m] is <index>"); |
| printf("\n <index> - This parameter specifies the rate or MCS index"); |
| printf("\n If <format> is 0 (LG),"); |
| printf("\n 0 1 Mbps"); |
| printf("\n 1 2 Mbps"); |
| printf("\n 2 5.5 Mbps"); |
| printf("\n 3 11 Mbps"); |
| printf("\n 4 6 Mbps"); |
| printf("\n 5 9 Mbps"); |
| printf("\n 6 12 Mbps"); |
| printf("\n 7 18 Mbps"); |
| printf("\n 8 24 Mbps"); |
| printf("\n 9 36 Mbps"); |
| printf("\n 10 48 Mbps"); |
| printf("\n 11 54 Mbps"); |
| printf("\n If <format> is 1 (HT), "); |
| printf("\n 0 MCS0"); |
| printf("\n 1 MCS1"); |
| printf("\n 2 MCS2"); |
| printf("\n 3 MCS3"); |
| printf("\n 4 MCS4"); |
| printf("\n 5 MCS5"); |
| printf("\n 6 MCS6"); |
| printf("\n 7 MCS7"); |
| printf("\n 8 MCS8"); |
| printf("\n 9 MCS9"); |
| printf("\n 10 MCS10"); |
| printf("\n 11 MCS11"); |
| printf("\n 12 MCS12"); |
| printf("\n 13 MCS13"); |
| printf("\n 14 MCS14"); |
| printf("\n 15 MCS15"); |
| printf("\n 32 MCS32"); |
| printf("\n If <format> is 2 (VHT), "); |
| printf("\n 0 MCS0"); |
| printf("\n 1 MCS1"); |
| printf("\n 2 MCS2"); |
| printf("\n 3 MCS3"); |
| printf("\n 4 MCS4"); |
| printf("\n 5 MCS5"); |
| printf("\n 6 MCS6"); |
| printf("\n 7 MCS7"); |
| printf("\n 8 MCS8"); |
| printf("\n 9 MCS9"); |
| printf("\n [n] is <nss>"); |
| printf("\n <nss> - This parameter specifies the NSS. It is valid only for VHT"); |
| printf("\n If <format> is 2 (VHT), "); |
| printf("\n 1 NSS1"); |
| printf("\n 2 NSS2"); |
| printf("\n"); |
| return; |
| } |
| |
| /** |
| * @brief Creates a Tx Rate Config get request and sends to the driver |
| * @param rate_config Tx rate config struct |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| static int |
| get_tx_rate_cfg(tx_rate_cfg_t *rate_config) |
| { |
| struct ifreq ifr; |
| t_s32 sockfd; |
| int ret = UAP_SUCCESS; |
| |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(rate_config, 0, sizeof(tx_rate_cfg_t)); |
| rate_config->subcmd = UAP_TX_RATE_CFG; |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); |
| ifr.ifr_ifru.ifru_data = (void *)rate_config; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| printf("ERR:UAP_IOCTL_CMD fail\n"); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| /* Close socket */ |
| close(sockfd); |
| return ret; |
| } |
| |
| static char *rate_format[3] = { "LG", "HT", "VHT" }; |
| |
| static char *lg_rate[] = { "1 Mbps", "2 Mbps", "5.5 Mbps", "11 Mbps", |
| "6 Mbps", "9 Mbps", "12 Mbps", "18 Mbps", |
| "24 Mbps", "36 Mbps", "48 Mbps", "54 Mbps" |
| }; |
| |
| /** |
| * @brief Creates a Tx Rate Config request and sends to the driver |
| * |
| * Usage: "txratecfg <datarate>" |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_tx_rate_cfg(int argc, char *argv[]) |
| { |
| int opt; |
| int status = 0; |
| tx_rate_cfg_t tx_rate_config; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| HTCap_t htcap; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_txratecfg_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| /* Check arguments */ |
| if (argc > 3) { |
| printf("ERR:wrong arguments! Only 0~3 arguments are supported.\n"); |
| print_txratecfg_usage(); |
| return UAP_FAILURE; |
| } |
| if (argc && (is_input_valid(TXRATECFG, argc, argv) != UAP_SUCCESS)) { |
| print_txratecfg_usage(); |
| return UAP_FAILURE; |
| } |
| memset(&tx_rate_config, 0, sizeof(tx_rate_cfg_t)); |
| tx_rate_config.subcmd = UAP_TX_RATE_CFG; |
| if (argc) { |
| tx_rate_config.action = ACTION_SET; |
| tx_rate_config.rate_format = A2HEXDECIMAL(argv[0]); |
| if (argc >= 2) |
| tx_rate_config.rate = A2HEXDECIMAL(argv[1]); |
| if (argc == 3) |
| tx_rate_config.nss = A2HEXDECIMAL(argv[2]); |
| tx_rate_config.user_data_cnt = argc; |
| /* If bss is already started and uAP is in (short GI in 20 MHz + GF) mode, block MCS0-MCS7 rates */ |
| if (get_bss_status(&status) != UAP_SUCCESS) { |
| printf("ERR:Cannot get current bss status!\n"); |
| return UAP_FAILURE; |
| } |
| if (UAP_SUCCESS == get_sys_cfg_11n(&htcap)) { |
| if (htcap.supported_mcs_set[0] && |
| (status == UAP_BSS_START)) { |
| if (((tx_rate_config.rate >= 0) && |
| (tx_rate_config.rate <= 7)) |
| && |
| (IS_11N_20MHZ_SHORTGI_ENABLED |
| (htcap.ht_cap_info) && |
| IS_11N_GF_ENABLED(htcap.ht_cap_info))) { |
| printf("ERR: Invalid rate for bss in (20MHz Short GI + Green Field) mode\n"); |
| return UAP_FAILURE; |
| } |
| if ((tx_rate_config.rate == 32) && |
| (!(IS_11N_40MHZ_ENABLED |
| (htcap.ht_cap_info)))) { |
| printf("ERR:uAP must be configured to operate in 40MHz if tx_rate is MCS32\n"); |
| return UAP_FAILURE; |
| } |
| } |
| } |
| } |
| |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* 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 *)&tx_rate_config; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| printf("ERR:UAP_IOCTL_CMD fail\n"); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| if (argc) { |
| printf("Transmit Rate setting successful\n"); |
| } else { |
| /* GET operation */ |
| printf("Tx Rate Configuration: \n"); |
| /* format */ |
| if (tx_rate_config.rate_format == 0xFF) { |
| printf(" Type: 0xFF (Auto)\n"); |
| } else if (tx_rate_config.rate_format <= 2) { |
| printf(" Type: %d (%s)\n", |
| tx_rate_config.rate_format, |
| rate_format[tx_rate_config.rate_format]); |
| if (tx_rate_config.rate_format == 0) |
| printf(" Rate Index: %d (%s)\n", |
| tx_rate_config.rate, |
| lg_rate[tx_rate_config.rate]); |
| else if (tx_rate_config.rate_format >= 1) |
| printf(" MCS Index: %d\n", |
| (int)tx_rate_config.rate); |
| if (tx_rate_config.rate_format == 2) |
| printf(" NSS: %d\n", |
| (int)tx_rate_config.nss); |
| } else { |
| printf(" Unknown rate format.\n"); |
| } |
| } |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Show usage information for the antcfg |
| * command |
| * |
| * $return N/A |
| */ |
| void |
| print_antcfg_usage(void) |
| { |
| printf("\nUsage : antcfg [<TX_MODE> <RX_MODE>]\n"); |
| printf("\n MODE : 1 - Antenna A"); |
| printf("\n 2 - Antenna B"); |
| printf("\n 3 - Antenna A+B"); |
| printf("\n empty - Get current antenna settings\n"); |
| return; |
| } |
| |
| /** |
| * @brief Creates a RF Antenna Mode Config request and sends to the driver |
| * |
| * Usage: "antcfg [MODE]" |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_antcfg(int argc, char *argv[]) |
| { |
| int opt; |
| ant_cfg_t antenna_config; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_antcfg_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| /* Check arguments */ |
| if (argc > 2) { |
| printf("ERR:wrong arguments!\n"); |
| print_antcfg_usage(); |
| return UAP_FAILURE; |
| } |
| if (argc) { |
| if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 1) || |
| (atoi(argv[0]) > 3)) { |
| printf("ERR:Illegal ANTENNA parameter %s. Must be either '1', '2' or '3'.\n", argv[0]); |
| print_antcfg_usage(); |
| return UAP_FAILURE; |
| } |
| if (argc == 2) { |
| if ((ISDIGIT(argv[1]) == 0) || (atoi(argv[1]) < 1) || |
| (atoi(argv[1]) > 3)) { |
| printf("ERR:Illegal RX ANTENNA parameter %s. Must be either '1', '2' or '3'.\n", argv[1]); |
| print_antcfg_usage(); |
| return UAP_FAILURE; |
| } |
| } |
| } |
| memset(&antenna_config, 0, sizeof(ant_cfg_t)); |
| antenna_config.subcmd = UAP_ANTENNA_CFG; |
| if (argc) { |
| antenna_config.action = ACTION_SET; |
| if (argc == 1) { |
| antenna_config.tx_mode = atoi(argv[0]); |
| antenna_config.rx_mode = atoi(argv[0]); |
| } else { |
| antenna_config.tx_mode = atoi(argv[0]); |
| antenna_config.rx_mode = atoi(argv[1]); |
| } |
| } |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* 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 *)&antenna_config; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| printf("ERR:UAP_IOCTL_CMD fail\n"); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| if (argc) { |
| printf("Antenna mode setting successful\n"); |
| } else { |
| printf("TX Antenna mode is %d.\n", antenna_config.tx_mode); |
| printf("RX Antenna mode is %d.\n", antenna_config.rx_mode); |
| } |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Show usage information for the htstreamcfg |
| * command |
| * |
| * $return N/A |
| */ |
| void |
| print_htstreamcfg_usage(void) |
| { |
| printf("\nUsage : htstreamcfg [<n>]\n"); |
| printf("\n Where <n> "); |
| printf("\n 0x11: HT stream 1x1 mode"); |
| printf("\n 0x22: HT stream 2x2 mode\n"); |
| return; |
| } |
| |
| /** |
| * @brief Set/get HT stream configurations |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_htstreamcfg(int argc, char *argv[]) |
| { |
| int opt; |
| htstream_cfg_t htstream_cfg; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_htstreamcfg_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| /* Check arguments */ |
| |
| memset(&htstream_cfg, 0, sizeof(htstream_cfg)); |
| if (argc == 0) { |
| htstream_cfg.action = ACTION_GET; |
| } else if (argc == 1) { |
| if ((t_u32)A2HEXDECIMAL(argv[0]) != HT_STREAM_MODE_1X1 |
| && (t_u32)A2HEXDECIMAL(argv[0]) != HT_STREAM_MODE_2X2) { |
| printf("ERR:Invalid argument\n"); |
| return UAP_FAILURE; |
| } |
| htstream_cfg.action = ACTION_SET; |
| htstream_cfg.stream_cfg = (t_u32)A2HEXDECIMAL(argv[0]); |
| } else { |
| print_htstreamcfg_usage(); |
| return UAP_FAILURE; |
| } |
| htstream_cfg.subcmd = UAP_HT_STREAM_CFG; |
| |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)&htstream_cfg; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| perror(""); |
| printf("ERR: HT STREAM configuration failed\n"); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| |
| /* Handle response */ |
| if (htstream_cfg.action == ACTION_GET) { |
| if (htstream_cfg.stream_cfg == HT_STREAM_MODE_1X1) |
| printf("HT stream is in 1x1 mode\n"); |
| else if (htstream_cfg.stream_cfg == HT_STREAM_MODE_2X2) |
| printf("HT stream is in 2x2 mode\n"); |
| else |
| printf("HT stream is unknown mode\n"); |
| } |
| |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| static int |
| get_802_11ac_cfg(struct eth_priv_vhtcfg *vhtcfg) |
| { |
| t_u8 *buf = NULL; |
| t_u8 *pos = NULL; |
| mrvl_priv_cmd *cmd = NULL; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| |
| buf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER); |
| if (!buf) { |
| printf("ERR: cannot allocate buffer for command payload \n"); |
| return UAP_FAILURE; |
| } |
| memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER); |
| |
| cmd = (mrvl_priv_cmd *)malloc(sizeof(mrvl_priv_cmd)); |
| if (!cmd) { |
| printf("ERR: cannot allocate buffer for cmd \n"); |
| free(buf); |
| return UAP_FAILURE; |
| } |
| |
| /*prepare command: mlanutl uap0 vhtcfg 2 3 , GET operation */ |
| pos = buf; |
| strncpy((char *)pos, CMD_MARVELL, strlen(CMD_MARVELL)); |
| pos += strlen(CMD_MARVELL); |
| strncpy((char *)pos, "vhtcfg2 3", strlen("vhtcfg2 3")); |
| |
| /* fill up buffer */ |
| cmd->buf = buf; |
| cmd->used_len = 0; |
| cmd->total_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| |
| /* Perform IOCTL */ |
| memset(&ifr, 0, sizeof(struct ifreq)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); |
| ifr.ifr_ifru.ifru_data = (void *)cmd; |
| |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| if (cmd) |
| free(cmd); |
| if (buf) |
| free(buf); |
| return UAP_FAILURE; |
| } |
| |
| if (ioctl(sockfd, MRVLPRIVCMD, &ifr)) { |
| if (cmd) |
| free(cmd); |
| if (buf) |
| free(buf); |
| return UAP_FAILURE; |
| } |
| |
| /* Process result */ |
| memcpy(vhtcfg, buf + 1, sizeof(struct eth_priv_vhtcfg)); |
| |
| close(sockfd); |
| free(cmd); |
| free(buf); |
| |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Show usage information for the sys_config command |
| * |
| * $return N/A |
| */ |
| void |
| print_sys_config_usage(void) |
| { |
| printf("\nUsage : sys_config [CONFIG_FILE]\n"); |
| printf("\nIf CONFIG_FILE is provided, a 'set' is performed, else a 'get' is performed.\n"); |
| printf("CONFIG_FILE is file contain all the Micro AP settings.\n"); |
| return; |
| } |
| |
| /** |
| * @brief Show usage information for the rdeeprom command |
| * |
| * $return N/A |
| */ |
| void |
| print_apcmd_read_eeprom_usage(void) |
| { |
| printf("\nUsage: rdeeprom <offset> <bytecount>\n"); |
| printf(" offset : 0,4,8,..., multiple of 4\n"); |
| printf(" bytecount : 4-20, multiple of 4\n"); |
| return; |
| } |
| |
| /** |
| * @brief Show protocol tlv |
| * |
| * @param protocol Protocol number |
| * |
| * $return N/A |
| */ |
| void |
| print_protocol(t_u16 protocol) |
| { |
| switch (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", protocol); |
| break; |
| } |
| } |
| |
| /** |
| * @brief Show wep tlv |
| * |
| * @param tlv Pointer to wep tlv |
| * |
| * $return N/A |
| */ |
| void |
| print_wep_key(tlvbuf_wep_key *tlv) |
| { |
| int i; |
| t_u16 tlv_len; |
| |
| tlv_len = *(t_u8 *)&tlv->length; |
| tlv_len |= (*((t_u8 *)&tlv->length + 1) << 8); |
| |
| if (tlv_len <= 2) { |
| printf("wrong wep_key tlv: length=%d\n", tlv_len); |
| return; |
| } |
| printf("WEP KEY_%d = ", tlv->key_index); |
| for (i = 0; i < tlv_len - 2; i++) |
| printf("%02x ", tlv->key[i]); |
| if (tlv->is_default) |
| printf("\nDefault WEP Key = %d\n", tlv->key_index); |
| 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 is_escape = 0; |
| int length = 0; |
| int i = 0; |
| int j = 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) { |
| if ((line[i] == '\\') && (i < (length - 1))) { |
| if (line[i + 1] == '"') { |
| is_escape = 1; |
| for (j = i; j < length - 1; j++) { |
| line[j] = line[j + 1]; |
| } |
| line[length - 1] = '\0'; |
| continue; |
| } |
| } |
| /* Ignore comments */ |
| if (line[i] == '#') { |
| if (is_quote == 0) { |
| line[i] = '\0'; |
| arg_num--; |
| } |
| break; |
| } |
| /* Separate by '=' */ |
| if (line[i] == '=') { |
| if (is_quote == 0) { |
| line[i] = '\0'; |
| is_start = 0; |
| continue; |
| } |
| } |
| /* Separate by ',' */ |
| if (line[i] == ',') { |
| if (is_quote == 0) { |
| 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] == '"') { |
| if (is_escape) { |
| is_escape = 0; |
| /* no change in is_quote */ |
| } else { |
| 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) |
| { |
| *_pos = mlan_config_get_line(stream, s, size, line); |
| return *_pos; |
| } |
| |
| /** |
| * @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 |
| */ |
| int |
| 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_ap_mac_filter = 0; |
| apcmdbuf_sys_configure *cmd_buf = NULL; |
| HTCap_t htcap; |
| int enable_11n = -1; |
| t_u16 tlv_offset_11n = 0; |
| t_u32 supported_mcs_set = 0; |
| t_u8 *buffer = NULL; |
| t_u8 *tmp_buffer = NULL; |
| t_u16 cmd_len = 0; |
| t_u16 tlv_len = 0; |
| int keyindex = -1; |
| int protocol = -1; |
| int pwkcipher_wpa = -1; |
| int pwkcipher_wpa2 = -1; |
| int gwkcipher = -1; |
| tlvbuf_sta_mac_addr_filter *filter_tlv = NULL; |
| tlvbuf_channel_config *channel_band_tlv = NULL; |
| int filter_mac_count = -1; |
| int tx_data_rate = -1; |
| int tx_beacon_rate = -1; |
| int mcbc_data_rate = -1; |
| t_u8 rate[MAX_RATES]; |
| int found = 0; |
| char country_80211d[4]; |
| t_u8 state_80211d = 0; |
| int chan_mode = 0; |
| int band = 0; |
| int band_flag = 0; |
| int chan_number = 0; |
| t_u16 max_sta_num_supported = 0; |
| fw_info fw; |
| struct eth_priv_vhtcfg vhtcfg = { 0 }; |
| int ret = UAP_SUCCESS; |
| 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 UAP_FAILURE; |
| } |
| line = (char *)malloc(MAX_CONFIG_LINE); |
| if (!line) { |
| printf("ERR:Cannot allocate memory for line\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| memset(line, 0, 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 |
| ((t_u8)tx_data_rate) != |
| UAP_SUCCESS)) { |
| printf("ERR: Invalid Tx Data Rate \n"); |
| ret = UAP_FAILURE; |
| 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"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } |
| } |
| if (tx_beacon_rate != -1) { |
| if ((!rate[0]) && (tx_beacon_rate) && |
| (is_tx_rate_valid |
| ((t_u8)tx_beacon_rate) != |
| UAP_SUCCESS)) { |
| printf("ERR: Invalid Tx Beacon Rate \n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| if (rate[0] && tx_beacon_rate) { |
| for (i = 0; rate[i] != 0; i++) { |
| if ((rate[i] & |
| ~BASIC_RATE_SET_BIT) |
| == tx_beacon_rate) { |
| found = 1; |
| break; |
| } |
| } |
| if (!found) { |
| printf("ERR: Invalid Tx Beacon Rate \n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } |
| /* Append a new TLV */ |
| tlvbuf_tx_data_rate *tlv = NULL; |
| tlv_len = sizeof(tlvbuf_tx_data_rate); |
| tmp_buffer = |
| realloc(buffer, |
| cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append tx beacon rate TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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_BEACON_RATE_TLV_ID; |
| tlv->length = 2; |
| tlv->tx_data_rate = tx_beacon_rate; |
| endian_convert_tlv_header_out(tlv); |
| tlv->tx_data_rate = |
| uap_cpu_to_le16(tlv-> |
| tx_data_rate); |
| } |
| if (mcbc_data_rate != -1) { |
| if ((!rate[0]) && (mcbc_data_rate) && |
| (is_mcbc_rate_valid |
| ((t_u8)mcbc_data_rate) != |
| UAP_SUCCESS)) { |
| printf("ERR: Invalid Tx Data Rate \n"); |
| ret = UAP_FAILURE; |
| 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"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } |
| |
| /* Append a new TLV */ |
| tlvbuf_mcbc_data_rate *tlv = NULL; |
| tlv_len = sizeof(tlvbuf_mcbc_data_rate); |
| tmp_buffer = |
| realloc(buffer, |
| cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append tx data rate TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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->mcbc_datarate = mcbc_data_rate; |
| endian_convert_tlv_header_out(tlv); |
| tlv->mcbc_datarate = |
| uap_cpu_to_le16(tlv-> |
| mcbc_datarate); |
| } |
| if ((protocol == PROTOCOL_STATIC_WEP) && |
| (enable_11n == 1)) { |
| printf("ERR:WEP cannot be used when AP operates in 802.11n mode.\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| if ((protocol == PROTOCOL_WPA2_MIXED) && |
| ((pwkcipher_wpa < 0) || |
| (pwkcipher_wpa2 < 0))) { |
| printf("ERR:Both PwkCipherWPA and PwkCipherWPA2 should be defined for Mixed mode.\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| |
| if (((pwkcipher_wpa >= 0) || |
| (pwkcipher_wpa2 >= 0)) && |
| (gwkcipher >= 0)) { |
| if ((protocol == PROTOCOL_WPA) || |
| (protocol == PROTOCOL_WPA2_MIXED)) { |
| if (enable_11n != -1) { |
| if (is_cipher_valid_with_11n(pwkcipher_wpa, gwkcipher, protocol, enable_11n) != UAP_SUCCESS) { |
| printf("ERR:Wrong group cipher and WPA pairwise cipher combination!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } else if |
| (is_cipher_valid_with_proto |
| (pwkcipher_wpa, |
| gwkcipher, |
| protocol) != |
| UAP_SUCCESS) { |
| printf("ERR:Wrong group cipher and WPA pairwise cipher combination!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } |
| if ((protocol == PROTOCOL_WPA2) || |
| (protocol == PROTOCOL_WPA2_MIXED)) { |
| if (enable_11n != -1) { |
| if (is_cipher_valid_with_11n(pwkcipher_wpa2, gwkcipher, protocol, enable_11n) != UAP_SUCCESS) { |
| printf("ERR:Wrong group cipher and WPA2 pairwise cipher combination!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } else if |
| (is_cipher_valid_with_proto |
| (pwkcipher_wpa2, |
| gwkcipher, |
| protocol) != |
| UAP_SUCCESS) { |
| printf("ERR:Wrong group cipher and WPA2 pairwise cipher combination!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } |
| } |
| |
| if (0 == get_fw_info(&fw)) { |
| /*check whether support 802.11AC through BAND_AAC bit */ |
| if (fw.fw_bands & BAND_AAC) { |
| ret = get_802_11ac_cfg(&vhtcfg); |
| if (ret != UAP_SUCCESS) |
| goto done; |
| if (enable_11n != -1) { |
| /* Note: When 11AC is disabled, FW sets vht_rx_mcs to 0xffff */ |
| if ((vhtcfg. |
| vht_rx_mcs != |
| 0xffff) && |
| (!enable_11n)) { |
| printf("ERR: 11n must be enabled when AP operates in 11ac mode. \n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } |
| } else |
| printf("No support 802 11AC.\n"); |
| } else { |
| printf("ERR: get_fw_info fail\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| |
| if (protocol != -1) { |
| tlvbuf_protocol *tlv = NULL; |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_protocol); |
| tmp_buffer = |
| realloc(buffer, |
| cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append protocol TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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 = protocol; |
| endian_convert_tlv_header_out(tlv); |
| tlv->protocol = |
| uap_cpu_to_le16(tlv->protocol); |
| if (protocol & |
| (PROTOCOL_WPA | PROTOCOL_WPA2)) { |
| tlvbuf_akmp *tlv = NULL; |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_akmp); |
| tmp_buffer = |
| realloc(buffer, |
| cmd_len + |
| tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append AKMP TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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 = 4; /* sizeof(tlvbuf_akmp) - TLVHEADER */ |
| tlv->key_mgmt = KEY_MGMT_PSK; |
| endian_convert_tlv_header_out |
| (tlv); |
| tlv->key_mgmt = |
| uap_cpu_to_le16(tlv-> |
| key_mgmt); |
| tlv->key_mgmt_operation = 0; |
| } |
| } |
| if (pwkcipher_wpa >= 0) { |
| tlvbuf_pwk_cipher *tlv = NULL; |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_pwk_cipher); |
| tmp_buffer = |
| realloc(buffer, |
| cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append cipher TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| cmd_buf = |
| (apcmdbuf_sys_configure *) |
| buffer; |
| tlv = (tlvbuf_pwk_cipher *)(buffer + |
| cmd_len); |
| memset(tlv, 0, tlv_len); |
| cmd_len += tlv_len; |
| /* Set TLV fields */ |
| tlv->tag = MRVL_CIPHER_PWK_TLV_ID; |
| tlv->length = |
| sizeof(tlvbuf_pwk_cipher) - |
| TLVHEADER_LEN; |
| tlv->pairwise_cipher = pwkcipher_wpa; |
| tlv->protocol = PROTOCOL_WPA; |
| endian_convert_tlv_header_out(tlv); |
| tlv->protocol = |
| uap_cpu_to_le16(tlv->protocol); |
| } |
| |
| if (pwkcipher_wpa2 >= 0) { |
| tlvbuf_pwk_cipher *tlv = NULL; |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_pwk_cipher); |
| tmp_buffer = |
| realloc(buffer, |
| cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append cipher TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| cmd_buf = |
| (apcmdbuf_sys_configure *) |
| buffer; |
| tlv = (tlvbuf_pwk_cipher *)(buffer + |
| cmd_len); |
| memset(tlv, 0, tlv_len); |
| cmd_len += tlv_len; |
| /* Set TLV fields */ |
| tlv->tag = MRVL_CIPHER_PWK_TLV_ID; |
| tlv->length = |
| sizeof(tlvbuf_pwk_cipher) - |
| TLVHEADER_LEN; |
| tlv->pairwise_cipher = pwkcipher_wpa2; |
| tlv->protocol = PROTOCOL_WPA2; |
| endian_convert_tlv_header_out(tlv); |
| tlv->protocol = |
| uap_cpu_to_le16(tlv->protocol); |
| } |
| |
| if (gwkcipher >= 0) { |
| tlvbuf_gwk_cipher *tlv = NULL; |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_gwk_cipher); |
| tmp_buffer = |
| realloc(buffer, |
| cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append cipher TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| cmd_buf = |
| (apcmdbuf_sys_configure *) |
| buffer; |
| tlv = (tlvbuf_gwk_cipher *)(buffer + |
| cmd_len); |
| memset(tlv, 0, tlv_len); |
| cmd_len += tlv_len; |
| /* Set TLV fields */ |
| tlv->tag = MRVL_CIPHER_GWK_TLV_ID; |
| tlv->length = |
| sizeof(tlvbuf_gwk_cipher) - |
| TLVHEADER_LEN; |
| tlv->group_cipher = gwkcipher; |
| endian_convert_tlv_header_out(tlv); |
| } |
| |
| cmd_buf->size = cmd_len; |
| /* Send collective command */ |
| if (uap_ioctl |
| ((t_u8 *)cmd_buf, &cmd_len, |
| cmd_len) == UAP_SUCCESS) { |
| if (cmd_buf->result != CMD_SUCCESS) { |
| printf("ERR: Failed to set the configuration!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } else { |
| printf("ERR: Command sending failed!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| 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 = (t_u8 *)malloc(cmd_len); |
| if (!buffer) { |
| printf("ERR:Cannot allocate memory!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| cmd_buf = (apcmdbuf_sys_configure *)buffer; |
| cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; |
| cmd_buf->size = cmd_len; |
| cmd_buf->seq_num = 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"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| if (filter_tlv->count) { |
| filter_tlv->length = |
| (filter_tlv->count * ETH_ALEN) + |
| 2; |
| cmd_len -= |
| (MAX_MAC_ONESHOT_FILTER - |
| filter_mac_count) * ETH_ALEN; |
| } else { |
| filter_tlv->length = |
| (MAX_MAC_ONESHOT_FILTER * |
| ETH_ALEN) + 2; |
| memset(filter_tlv->mac_address, 0, |
| MAX_MAC_ONESHOT_FILTER * |
| ETH_ALEN); |
| } |
| cmd_buf->size = cmd_len; |
| endian_convert_tlv_header_out(filter_tlv); |
| if (uap_ioctl |
| ((t_u8 *)cmd_buf, &cmd_len, |
| cmd_len) == UAP_SUCCESS) { |
| if (cmd_buf->result != CMD_SUCCESS) { |
| printf("ERR: Failed to set the configuration!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } else { |
| printf("ERR: Command sending failed!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| |
| cmd_len = 0; |
| if (buffer) { |
| free(buffer); |
| buffer = NULL; |
| } |
| continue; |
| } |
| } |
| |
| if (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"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| state_80211d = (t_u8)A2HEXDECIMAL(args[1]); |
| |
| if ((state_80211d != 0) && (state_80211d != 1)) { |
| printf("ERR: valid input for state are 0 or 1 \n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| if (sg_snmp_mib |
| (ACTION_SET, OID_80211D_ENABLE, |
| sizeof(state_80211d), &state_80211d) |
| == UAP_FAILURE) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } |
| |
| if (strcmp(args[0], "country") == 0) { |
| apcmdbuf_cfg_80211d *cmd_buf = NULL; |
| ieeetypes_subband_set_t sub_bands[MAX_SUB_BANDS]; |
| t_u8 no_of_sub_band = 0; |
| t_u16 buf_len; |
| t_u16 cmdlen; |
| t_u8 *buf = NULL; |
| |
| if ((strlen(args[1]) > 3) || (strlen(args[1]) == 0)) { |
| printf("In-correct country input\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| strncpy(country_80211d, args[1], |
| sizeof(country_80211d) - 1); |
| for (i = 0; (unsigned int)i < strlen(country_80211d); |
| i++) { |
| if ((country_80211d[i] < 'A') || |
| (country_80211d[i] > 'z')) { |
| printf("Invalid Country Code\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| if (country_80211d[i] > 'Z') |
| country_80211d[i] = |
| country_80211d[i] - 'a' + 'A'; |
| } |
| no_of_sub_band = |
| parse_domain_file(country_80211d, band, |
| sub_bands, NULL); |
| if (no_of_sub_band == UAP_FAILURE) { |
| printf("Parsing Failed\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| buf_len = sizeof(apcmdbuf_cfg_80211d); |
| buf_len += |
| no_of_sub_band * |
| sizeof(ieeetypes_subband_set_t); |
| buf = (t_u8 *)malloc(buf_len); |
| if (!buf) { |
| printf("ERR:Cannot allocate buffer from command!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| memset(buf, 0, buf_len); |
| cmd_buf = (apcmdbuf_cfg_80211d *)buf; |
| cmdlen = buf_len; |
| cmd_buf->size = cmdlen - BUF_HEADER_SIZE; |
| cmd_buf->result = 0; |
| cmd_buf->seq_num = 0; |
| cmd_buf->action = uap_cpu_to_le16(ACTION_SET); |
| cmd_buf->cmd_code = 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_subband_set_t))); |
| |
| memset(cmd_buf->domain.country_code, ' ', |
| sizeof(cmd_buf->domain.country_code)); |
| memcpy(cmd_buf->domain.country_code, country_80211d, |
| strlen(country_80211d)); |
| memcpy(cmd_buf->domain.subband, sub_bands, |
| no_of_sub_band * |
| sizeof(ieeetypes_subband_set_t)); |
| |
| /* Send the command */ |
| if (uap_ioctl((t_u8 *)cmd_buf, &cmdlen, cmdlen) == |
| UAP_SUCCESS) { |
| if (cmd_buf->result != CMD_SUCCESS) { |
| printf("ERR: Failed to set the configuration!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } else { |
| printf("ERR: Command sending failed!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| |
| 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 = (t_u8 *)malloc(cmd_len); |
| if (!buffer) { |
| printf("ERR:Cannot allocate memory!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| cmd_buf = (apcmdbuf_sys_configure *)buffer; |
| cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; |
| cmd_buf->size = cmd_len; |
| cmd_buf->seq_num = 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; |
| } |
| 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])); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| filter_tlv->filter_mode = 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"); |
| ret = UAP_FAILURE; |
| 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->mac_address[filter_mac_count * |
| ETH_ALEN]) != |
| UAP_SUCCESS) { |
| printf("ERR: Invalid MAC address %s \n", |
| args[1]); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| filter_mac_count++; |
| } else { |
| printf("ERR: Filter table can not have more than %d MAC addresses\n", MAX_MAC_ONESHOT_FILTER); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } |
| |
| if (strcmp(args[0], "SSID") == 0) { |
| if (arg_num == 1) { |
| printf("ERR:SSID field is blank!\n"); |
| ret = UAP_FAILURE; |
| 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); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_ssid) + strlen(args[1]); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot realloc SSID TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_beacon_period *tlv = NULL; |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_beacon_period); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot realloc beacon period TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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->beacon_period_ms = (t_u16)atoi(args[1]); |
| endian_convert_tlv_header_out(tlv); |
| tlv->beacon_period_ms = |
| uap_cpu_to_le16(tlv->beacon_period_ms); |
| } |
| if (strcmp(args[0], "ChanList") == 0) { |
| if (is_input_valid(SCANCHANNELS, arg_num - 1, args + 1) |
| != UAP_SUCCESS) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| |
| tlvbuf_channel_list *tlv = NULL; |
| channel_list *pchan_list = NULL; |
| /* Append a new TLV */ |
| tlv_len = |
| sizeof(tlvbuf_channel_list) + |
| ((arg_num - 1) * sizeof(channel_list)); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append channel list TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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); |
| pchan_list = (channel_list *) tlv->chan_list; |
| for (i = 0; i < (arg_num - 1); i++) { |
| band_flag = -1; |
| sscanf(args[i + 1], "%d.%d", &chan_number, |
| &band_flag); |
| pchan_list->chan_number = chan_number; |
| pchan_list->bandcfg.chanBand = BAND_2GHZ; |
| if (((band_flag != -1) && (band_flag)) || |
| (chan_number > MAX_CHANNELS_BG)) { |
| pchan_list->bandcfg.chanBand = |
| BAND_5GHZ; |
| } |
| pchan_list++; |
| } |
| endian_convert_tlv_header_out(tlv); |
| } |
| if (strcmp(args[0], "Channel") == 0) { |
| if (is_input_valid(CHANNEL, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_channel_config *tlv = NULL; |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_channel_config); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append channel TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| cmd_buf = (apcmdbuf_sys_configure *)buffer; |
| tlv = (tlvbuf_channel_config *)(buffer + cmd_len); |
| channel_band_tlv = tlv; |
| cmd_len += tlv_len; |
| /* Set TLV fields */ |
| tlv->tag = MRVL_CHANNELCONFIG_TLV_ID; |
| tlv->length = |
| sizeof(tlvbuf_channel_config) - TLVHEADER_LEN; |
| tlv->chan_number = (t_u8)atoi(args[1]); |
| if (tlv->chan_number > MAX_CHANNELS_BG) |
| band = BAND_A; |
| else |
| band = BAND_B | BAND_G; |
| if ((arg_num - 1) == 2) { |
| chan_mode = atoi(args[2]); |
| memset(&(tlv->bandcfg), 0, |
| sizeof(tlv->bandcfg)); |
| if (chan_mode & BITMAP_ACS_MODE) { |
| int mode; |
| |
| if (uap_ioctl_dfs_repeater_mode(&mode) |
| == UAP_SUCCESS) { |
| if (mode) { |
| printf("ERR: ACS in DFS Repeater mode" " is not allowed\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } |
| tlv->bandcfg.scanMode = SCAN_MODE_ACS; |
| } |
| if (chan_mode & BITMAP_CHANNEL_ABOVE) |
| tlv->bandcfg.chan2Offset = |
| SEC_CHAN_ABOVE; |
| if (chan_mode & BITMAP_CHANNEL_BELOW) |
| tlv->bandcfg.chan2Offset = |
| SEC_CHAN_BELOW; |
| } else |
| memset(&(tlv->bandcfg), 0, |
| sizeof(tlv->bandcfg)); |
| if (tlv->chan_number > MAX_CHANNELS_BG) { |
| tlv->bandcfg.chanBand = BAND_5GHZ; |
| } |
| endian_convert_tlv_header_out(tlv); |
| } |
| if (strcmp(args[0], "Band") == 0) { |
| if (is_input_valid(BAND, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| if (channel_band_tlv == NULL) { |
| printf("ERR: Channel parameter should be specified before Band\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| /* If band is provided, clear previous value of band */ |
| channel_band_tlv->bandcfg.chanBand = BAND_2GHZ; |
| if (atoi(args[1]) == 0) { |
| band = BAND_B | BAND_G; |
| } else { |
| channel_band_tlv->bandcfg.chanBand = BAND_5GHZ; |
| band = BAND_A; |
| } |
| } |
| if (strcmp(args[0], "AP_MAC") == 0) { |
| tlvbuf_ap_mac_address *tlv = NULL; |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_ap_mac_address); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append ap_mac TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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->ap_mac_addr)) != UAP_SUCCESS) { |
| printf("ERR: %s Address \n", |
| ret == |
| UAP_FAILURE ? "Invalid MAC" : ret == |
| UAP_RET_MAC_BROADCAST ? "Broadcast" : |
| "Multicast"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| 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"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_rates *tlv = NULL; |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_rates) + arg_num - 1; |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append rates TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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->operational_rates[i] = |
| (t_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"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| tlvbuf_tx_power *tlv = NULL; |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_tx_power); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append tx power level TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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->tx_power_dbm = (t_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) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_bcast_ssid_ctl *tlv = NULL; |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_bcast_ssid_ctl); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append SSID broadcast control TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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->bcast_ssid_ctl = (t_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) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_rts_threshold *tlv = NULL; |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_rts_threshold); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append RTS threshold TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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->rts_threshold = (t_u16)atoi(args[1]); |
| endian_convert_tlv_header_out(tlv); |
| tlv->rts_threshold = |
| uap_cpu_to_le16(tlv->rts_threshold); |
| } |
| if (strcmp(args[0], "FragThreshold") == 0) { |
| if (is_input_valid(FRAGTHRESH, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_frag_threshold *tlv = NULL; |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_frag_threshold); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append Fragmentation threshold TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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->frag_threshold = (t_u16)atoi(args[1]); |
| endian_convert_tlv_header_out(tlv); |
| tlv->frag_threshold = |
| uap_cpu_to_le16(tlv->frag_threshold); |
| } |
| if (strcmp(args[0], "DTIMPeriod") == 0) { |
| if (is_input_valid(DTIMPERIOD, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_dtim_period *tlv = NULL; |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_dtim_period); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append DTIM period TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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->dtim_period = (t_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) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_rsn_replay_prot *tlv = NULL; |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_rsn_replay_prot); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append RSN replay protection TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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 = (t_u8)atoi(args[1]); |
| endian_convert_tlv_header_out(tlv); |
| } |
| if (strcmp(args[0], "TxBeaconRate") == 0) { |
| if (is_input_valid(TXBEACONRATE, arg_num - 1, args + 1) |
| != UAP_SUCCESS) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tx_beacon_rate = (t_u16)A2HEXDECIMAL(args[1]); |
| } |
| if (strcmp(args[0], "MCBCdataRate") == 0) { |
| if (is_input_valid(MCBCDATARATE, arg_num - 1, args + 1) |
| != UAP_SUCCESS) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| mcbc_data_rate = (t_u16)A2HEXDECIMAL(args[1]); |
| } |
| if (strcmp(args[0], "PktFwdCtl") == 0) { |
| if (is_input_valid(PKTFWD, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_pkt_fwd_ctl *tlv = NULL; |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_pkt_fwd_ctl); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append packet forwarding control TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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->pkt_fwd_ctl = (t_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) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_sta_ageout_timer *tlv = NULL; |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_sta_ageout_timer); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append STA ageout timer TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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->sta_ageout_timer_ms = (t_u32)atoi(args[1]); |
| endian_convert_tlv_header_out(tlv); |
| tlv->sta_ageout_timer_ms = |
| uap_cpu_to_le32(tlv->sta_ageout_timer_ms); |
| } |
| if (strcmp(args[0], "PSStaAgeoutTimer") == 0) { |
| if (is_input_valid |
| (PSSTAAGEOUTTIMER, arg_num - 1, |
| args + 1) != UAP_SUCCESS) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_ps_sta_ageout_timer *tlv = NULL; |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_ps_sta_ageout_timer); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append PS STA ageout timer TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| cmd_buf = (apcmdbuf_sys_configure *)buffer; |
| tlv = (tlvbuf_ps_sta_ageout_timer *)(buffer + cmd_len); |
| cmd_len += tlv_len; |
| /* Set TLV fields */ |
| tlv->tag = MRVL_PS_STA_AGEOUT_TIMER_TLV_ID; |
| tlv->length = 4; |
| tlv->ps_sta_ageout_timer_ms = (t_u32)atoi(args[1]); |
| endian_convert_tlv_header_out(tlv); |
| tlv->ps_sta_ageout_timer_ms = |
| uap_cpu_to_le32(tlv->ps_sta_ageout_timer_ms); |
| } |
| if (strcmp(args[0], "AuthMode") == 0) { |
| if (is_input_valid(AUTHMODE, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_auth_mode *tlv = NULL; |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_auth_mode); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append auth mode TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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->auth_mode = (t_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"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| if (ISDIGIT(args[1]) == 0) { |
| printf("ERR:Illegal KeyIndex parameter. Must be either '0', '1', '2', or '3'.\n"); |
| ret = UAP_FAILURE; |
| 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"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } |
| } |
| if (strncmp(args[0], "Key_", 4) == 0) { |
| if (arg_num == 1) { |
| printf("ERR:%s is blank!\n", args[0]); |
| ret = UAP_FAILURE; |
| 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"); |
| ret = UAP_FAILURE; |
| 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"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| if (UAP_FAILURE == ishexstring(args[1])) { |
| printf("ERR:Only hex digits are allowed when key length is 10 or 26\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| key_len = strlen(args[1]) / 2; |
| } |
| |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_wep_key) + key_len; |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append WEP key configurations TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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->key_index = 0; |
| } else if (strcmp(args[0], "Key_1") == 0) { |
| tlv->key_index = 1; |
| } else if (strcmp(args[0], "Key_2") == 0) { |
| tlv->key_index = 2; |
| } else if (strcmp(args[0], "Key_3") == 0) { |
| tlv->key_index = 3; |
| } |
| if (keyindex == tlv->key_index) { |
| tlv->is_default = 1; |
| } else { |
| tlv->is_default = 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"); |
| ret = UAP_FAILURE; |
| 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"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| if (strlen(args[1]) < MIN_WPA_PASSPHRASE_LENGTH) { |
| printf("ERR:PSK too short.\n"); |
| ret = UAP_FAILURE; |
| 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"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } |
| /* Append a new TLV */ |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append WPA passphrase TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| protocol = (t_u16)atoi(args[1]); |
| } |
| if ((strcmp(args[0], "PairwiseCipher") == 0) || |
| (strcmp(args[0], "GroupCipher") == 0)) { |
| printf("ERR:PairwiseCipher and GroupCipher are not supported.\n" " Please configure pairwise cipher using parameters PwkCipherWPA or PwkCipherWPA2\n" " and group cipher using GwkCipher in the config file.\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| |
| if ((protocol == PROTOCOL_NO_SECURITY) || |
| (protocol == PROTOCOL_STATIC_WEP)) { |
| if ((strcmp(args[0], "PwkCipherWPA") == 0) || |
| (strcmp(args[0], "PwkCipherWPA2") == 0) |
| || (strcmp(args[0], "GwkCipher") == 0)) { |
| printf("ERR:Pairwise cipher and group cipher should not be defined for Open and WEP mode.\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } |
| |
| if (strcmp(args[0], "PwkCipherWPA") == 0) { |
| if (arg_num == 1) { |
| printf("ERR:PwkCipherWPA is blank!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| if (ISDIGIT(args[1]) == 0) { |
| printf("ERR:Illegal PwkCipherWPA parameter. Must be either bit '2' or '3'.\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| if (atoi(args[1]) & ~CIPHER_BITMAP) { |
| printf("ERR:Illegal PwkCipherWPA parameter. Must be either bit '2' or '3'.\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| pwkcipher_wpa = atoi(args[1]); |
| if (enable_11n && |
| protocol != PROTOCOL_WPA2_MIXED) { |
| memset(&htcap, 0, sizeof(htcap)); |
| if (UAP_SUCCESS == |
| get_sys_cfg_11n(&htcap)) { |
| if (htcap.supported_mcs_set[0] |
| && (atoi(args[1]) == |
| CIPHER_TKIP)) { |
| printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } |
| } |
| } |
| } |
| |
| if (strcmp(args[0], "PwkCipherWPA2") == 0) { |
| if (arg_num == 1) { |
| printf("ERR:PwkCipherWPA2 is blank!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| if (ISDIGIT(args[1]) == 0) { |
| printf("ERR:Illegal PwkCipherWPA2 parameter. Must be either bit '2' or '3'.\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| if (atoi(args[1]) & ~CIPHER_BITMAP) { |
| printf("ERR:Illegal PwkCipherWPA2 parameter. Must be either bit '2' or '3'.\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| pwkcipher_wpa2 = atoi(args[1]); |
| if (enable_11n && |
| protocol != PROTOCOL_WPA2_MIXED) { |
| memset(&htcap, 0, sizeof(htcap)); |
| if (UAP_SUCCESS == |
| get_sys_cfg_11n(&htcap)) { |
| if (htcap.supported_mcs_set[0] |
| && (atoi(args[1]) == |
| CIPHER_TKIP)) { |
| printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } |
| } |
| } |
| } |
| if (strcmp(args[0], "GwkCipher") == 0) { |
| if (is_input_valid(GWK_CIPHER, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| gwkcipher = atoi(args[1]); |
| } |
| if (strcmp(args[0], "GroupRekeyTime") == 0) { |
| if (is_input_valid |
| (GROUPREKEYTIMER, arg_num - 1, |
| args + 1) != UAP_SUCCESS) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_group_rekey_timer *tlv = NULL; |
| |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_group_rekey_timer); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append group rekey timer TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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->group_rekey_time_sec = (t_u32)atoi(args[1]); |
| endian_convert_tlv_header_out(tlv); |
| tlv->group_rekey_time_sec = |
| uap_cpu_to_le32(tlv->group_rekey_time_sec); |
| } |
| if (strcmp(args[0], "MaxStaNum") == 0) { |
| if (is_input_valid(MAXSTANUM, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| if (get_max_sta_num_supported(&max_sta_num_supported) == |
| UAP_FAILURE) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| if (atoi(args[1]) > max_sta_num_supported) { |
| printf("ERR: MAX_STA_NUM must be less than %d\n", max_sta_num_supported); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_max_sta_num *tlv = NULL; |
| |
| /* Append a new TLV */ |
| tlv_len = |
| sizeof(tlvbuf_max_sta_num) - |
| sizeof(tlv->max_sta_num_supported); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot realloc max station number TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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_configured = (t_u16)atoi(args[1]); |
| endian_convert_tlv_header_out(tlv); |
| tlv->max_sta_num_configured = |
| uap_cpu_to_le16(tlv->max_sta_num_configured); |
| } |
| if (strcmp(args[0], "Retrylimit") == 0) { |
| if (is_input_valid(RETRYLIMIT, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_retry_limit *tlv = NULL; |
| |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_retry_limit); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot realloc retry limit TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| 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 = (t_u8)atoi(args[1]); |
| endian_convert_tlv_header_out(tlv); |
| } |
| if (strcmp(args[0], "PairwiseUpdateTimeout") == 0) { |
| if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_eapol_pwk_hsk_timeout *tlv = NULL; |
| |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_eapol_pwk_hsk_timeout); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append pairwise update timeout TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| cmd_buf = (apcmdbuf_sys_configure *)buffer; |
| tlv = (tlvbuf_eapol_pwk_hsk_timeout *)(buffer + |
| cmd_len); |
| cmd_len += tlv_len; |
| /* Set TLV fields */ |
| tlv->tag = MRVL_EAPOL_PWK_HSK_TIMEOUT_TLV_ID; |
| tlv->length = 4; |
| tlv->pairwise_update_timeout = (t_u32)atoi(args[1]); |
| endian_convert_tlv_header_out(tlv); |
| tlv->pairwise_update_timeout = |
| uap_cpu_to_le32(tlv->pairwise_update_timeout); |
| } |
| if (strcmp(args[0], "PairwiseHandshakeRetries") == 0) { |
| if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_eapol_pwk_hsk_retries *tlv = NULL; |
| |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_eapol_pwk_hsk_retries); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append pairwise handshake retries TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| cmd_buf = (apcmdbuf_sys_configure *)buffer; |
| tlv = (tlvbuf_eapol_pwk_hsk_retries *)(buffer + |
| cmd_len); |
| cmd_len += tlv_len; |
| /* Set TLV fields */ |
| tlv->tag = MRVL_EAPOL_PWK_HSK_RETRIES_TLV_ID; |
| tlv->length = 4; |
| tlv->pwk_retries = (t_u32)atoi(args[1]); |
| endian_convert_tlv_header_out(tlv); |
| tlv->pwk_retries = uap_cpu_to_le32(tlv->pwk_retries); |
| } |
| if (strcmp(args[0], "GroupwiseUpdateTimeout") == 0) { |
| if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_eapol_gwk_hsk_timeout *tlv = NULL; |
| |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_eapol_gwk_hsk_timeout); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append groupwise update timeout TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| cmd_buf = (apcmdbuf_sys_configure *)buffer; |
| tlv = (tlvbuf_eapol_gwk_hsk_timeout *)(buffer + |
| cmd_len); |
| cmd_len += tlv_len; |
| /* Set TLV fields */ |
| tlv->tag = MRVL_EAPOL_GWK_HSK_TIMEOUT_TLV_ID; |
| tlv->length = 4; |
| tlv->groupwise_update_timeout = (t_u32)atoi(args[1]); |
| endian_convert_tlv_header_out(tlv); |
| tlv->groupwise_update_timeout = |
| uap_cpu_to_le32(tlv->groupwise_update_timeout); |
| } |
| if (strcmp(args[0], "GroupwiseHandshakeRetries") == 0) { |
| if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_eapol_gwk_hsk_retries *tlv = NULL; |
| |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_eapol_gwk_hsk_retries); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append groupwise handshake retries TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| cmd_buf = (apcmdbuf_sys_configure *)buffer; |
| tlv = (tlvbuf_eapol_gwk_hsk_retries *)(buffer + |
| cmd_len); |
| cmd_len += tlv_len; |
| /* Set TLV fields */ |
| tlv->tag = MRVL_EAPOL_GWK_HSK_RETRIES_TLV_ID; |
| tlv->length = 4; |
| tlv->gwk_retries = (t_u32)atoi(args[1]); |
| endian_convert_tlv_header_out(tlv); |
| tlv->gwk_retries = uap_cpu_to_le32(tlv->gwk_retries); |
| } |
| |
| if (strcmp(args[0], "Enable11n") == 0) { |
| if ((ISDIGIT(args[1]) != UAP_SUCCESS) || |
| (atoi(args[1]) < 0) || (atoi(args[1]) > 1)) { |
| printf("ERR: Invalid Enable11n value\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_htcap_t *tlv = NULL; |
| enable_11n = atoi(args[1]); |
| |
| memset(&htcap, 0, sizeof(htcap)); |
| if (UAP_SUCCESS != get_sys_cfg_11n(&htcap)) { |
| printf("ERR: Reading current 11n configuration.\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_htcap_t); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append HT Cap TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| cmd_buf = (apcmdbuf_sys_configure *)buffer; |
| tlv = (tlvbuf_htcap_t *)(buffer + cmd_len); |
| tlv_offset_11n = cmd_len; |
| cmd_len += tlv_len; |
| /* Set TLV fields */ |
| tlv->tag = HT_CAPABILITY_TLV_ID; |
| tlv->length = sizeof(HTCap_t); |
| memcpy(&tlv->ht_cap, &htcap, sizeof(HTCap_t)); |
| if (enable_11n == 1) { |
| /* enable mcs rate */ |
| tlv->ht_cap.supported_mcs_set[0] = |
| DEFAULT_MCS_SET_0; |
| tlv->ht_cap.supported_mcs_set[4] = |
| DEFAULT_MCS_SET_4; |
| if (0 == get_fw_info(&fw)) { |
| if ((fw.hw_dev_mcs_support & 0x0f) >= 2) |
| tlv->ht_cap. |
| supported_mcs_set[1] = |
| DEFAULT_MCS_SET_1; |
| } |
| } else { |
| /* disable mcs rate */ |
| tlv->ht_cap.supported_mcs_set[0] = 0; |
| tlv->ht_cap.supported_mcs_set[4] = 0; |
| tlv->ht_cap.supported_mcs_set[1] = 0; |
| } |
| endian_convert_tlv_header_out(tlv); |
| } |
| if (strcmp(args[0], "HTCapInfo") == 0) { |
| if (enable_11n <= 0) { |
| printf("ERR: Enable11n parameter should be set before HTCapInfo.\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| if ((IS_HEX_OR_DIGIT(args[1]) == UAP_FAILURE) || |
| ((((t_u16)A2HEXDECIMAL(args[1])) & |
| (~HT_CAP_CONFIG_MASK)) != HT_CAP_CHECK_MASK)) { |
| printf("ERR: Invalid HTCapInfo value\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| |
| /* Find HT tlv pointer in buffer and set HTCapInfo */ |
| tlvbuf_htcap_t *tlv = NULL; |
| tlv = (tlvbuf_htcap_t *)(buffer + tlv_offset_11n); |
| tlv->ht_cap.ht_cap_info = |
| DEFAULT_HT_CAP_VALUE & ~HT_CAP_CONFIG_MASK; |
| tlv->ht_cap.ht_cap_info |= |
| (t_u16)A2HEXDECIMAL(args[1]) & |
| HT_CAP_CONFIG_MASK; |
| tlv->ht_cap.ht_cap_info = |
| uap_cpu_to_le16(tlv->ht_cap.ht_cap_info); |
| } |
| if (strcmp(args[0], "AMPDU") == 0) { |
| if (enable_11n <= 0) { |
| printf("ERR: Enable11n parameter should be set before AMPDU.\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| if ((IS_HEX_OR_DIGIT(args[1]) == UAP_FAILURE) || |
| ((A2HEXDECIMAL(args[1])) > AMPDU_CONFIG_MASK)) { |
| printf("ERR: Invalid AMPDU value\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| |
| /* Find HT tlv pointer in buffer and set AMPDU */ |
| tlvbuf_htcap_t *tlv = NULL; |
| tlv = (tlvbuf_htcap_t *)(buffer + tlv_offset_11n); |
| tlv->ht_cap.ampdu_param = |
| (t_u8)A2HEXDECIMAL(args[1]) & AMPDU_CONFIG_MASK; |
| } |
| if (strcmp(args[0], "HT_MCS_MAP") == 0) { |
| if (enable_11n <= 0) { |
| printf("ERR: Enable11n parameter should be set before HT_MCS_MAP.\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| if (0 == get_fw_info(&fw)) { |
| /* Check upper nibble of MCS support value |
| * and block MCS_SET_1 when 2X2 is not supported |
| * by the underlying hardware */ |
| if (((fw.hw_dev_mcs_support & 0xf0) < |
| STREAM_2X2_MASK) && |
| (A2HEXDECIMAL(args[1]) & MCS_SET_1_MASK)) { |
| printf("ERR: Invalid HT_MCS_MAP\n"); |
| goto done; |
| } |
| } |
| |
| /* Find HT tlv pointer in buffer and set supported MCS set */ |
| tlvbuf_htcap_t *tlv = NULL; |
| tlv = (tlvbuf_htcap_t *)(buffer + tlv_offset_11n); |
| supported_mcs_set = (t_u32)A2HEXDECIMAL(args[1]); |
| supported_mcs_set = uap_cpu_to_le32(supported_mcs_set); |
| memcpy(tlv->ht_cap.supported_mcs_set, |
| &supported_mcs_set, sizeof(t_u32)); |
| } |
| if (strcmp(args[0], "Enable2040Coex") == 0) { |
| if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0) || |
| (atoi(args[1]) > 1)) { |
| printf("ERR: Invalid Enable2040Coex value\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| tlvbuf_2040_coex *tlv = NULL; |
| /* Append a new TLV */ |
| tlv_len = sizeof(tlvbuf_2040_coex); |
| tmp_buffer = realloc(buffer, cmd_len + tlv_len); |
| if (!tmp_buffer) { |
| printf("ERR:Cannot append 2040 coex TLV!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } else { |
| buffer = tmp_buffer; |
| tmp_buffer = NULL; |
| } |
| cmd_buf = (apcmdbuf_sys_configure *)buffer; |
| tlv = (tlvbuf_2040_coex *)(buffer + cmd_len); |
| cmd_len += tlv_len; |
| /* Set TLV fields */ |
| tlv->tag = MRVL_2040_BSS_COEX_CONTROL_TLV_ID; |
| tlv->length = 1; |
| tlv->enable = (t_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); |
| return ret; |
| } |
| |
| /** |
| * @brief Get band from current channel |
| * @param band |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| static int |
| get_band(int *band) |
| { |
| apcmdbuf_sys_configure *cmd_buf = NULL; |
| tlvbuf_channel_config *tlv = NULL; |
| t_u8 *buffer = NULL; |
| t_u16 cmd_len; |
| int ret = UAP_SUCCESS; |
| |
| /* Initialize the command length */ |
| cmd_len = |
| sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_channel_config); |
| |
| /* Initialize the command buffer */ |
| buffer = (t_u8 *)malloc(cmd_len); |
| |
| if (!buffer) { |
| printf("ERR:Cannot allocate buffer for command!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| memset(buffer, 0, cmd_len); |
| |
| /* Locate headers */ |
| cmd_buf = (apcmdbuf_sys_configure *)buffer; |
| tlv = (tlvbuf_channel_config *)(buffer + |
| sizeof(apcmdbuf_sys_configure)); |
| |
| /* Fill the command buffer */ |
| cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; |
| cmd_buf->size = cmd_len; |
| cmd_buf->seq_num = 0; |
| cmd_buf->result = 0; |
| tlv->tag = MRVL_CHANNELCONFIG_TLV_ID; |
| tlv->length = sizeof(tlvbuf_channel_config) - TLVHEADER_LEN; |
| cmd_buf->action = ACTION_GET; |
| |
| endian_convert_tlv_header_out(tlv); |
| /* Send the command */ |
| ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, cmd_len); |
| endian_convert_tlv_header_in(tlv); |
| |
| if (ret == UAP_SUCCESS) { |
| /* Verify response */ |
| if ((cmd_buf->cmd_code != |
| (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || |
| (tlv->tag != MRVL_CHANNELCONFIG_TLV_ID)) { |
| printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| if (cmd_buf->result == CMD_SUCCESS) { |
| if (tlv->chan_number > MAX_CHANNELS_BG) |
| *band = BAND_A; |
| else |
| *band = BAND_B | BAND_G; |
| } else { |
| printf("ERR:Could not get band!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } else { |
| printf("ERR:Command sending failed!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| done: |
| if (buffer) |
| free(buffer); |
| return ret; |
| } |
| |
| /** |
| * @brief Show usage information for the cfg_80211d command |
| * |
| * $return N/A |
| */ |
| void |
| print_apcmd_cfg_80211d_usage(void) |
| { |
| printf("\nUsage: cfg_80211d <state 0/1> <country Country_code> \n"); |
| return; |
| } |
| |
| /** |
| * @brief Show usage information for the uap_stats command |
| * |
| * $return N/A |
| */ |
| void |
| print_apcmd_uap_stats(void) |
| { |
| printf("Usage: uap_stats \n"); |
| return; |
| } |
| |
| /** |
| * SNMP MIB OIDs Table |
| */ |
| static oids_table snmp_oids[] = { |
| {0x0b, 4, "dot11LocalTKIPMICFailures"}, |
| {0x0c, 4, "dot11CCMPDecryptErrors"}, |
| {0x0d, 4, "dot11WEPUndecryptableCount"}, |
| {0x0e, 4, "dot11WEPICVErrorCount"}, |
| {0x0f, 4, "dot11DecryptFailureCount"}, |
| {0x12, 4, "dot11FailedCount"}, |
| {0x13, 4, "dot11RetryCount"}, |
| {0x14, 4, "dot11MultipleRetryCount"}, |
| {0x15, 4, "dot11FrameDuplicateCount"}, |
| {0x16, 4, "dot11RTSSuccessCount"}, |
| {0x17, 4, "dot11RTSFailureCount"}, |
| {0x18, 4, "dot11ACKFailureCount"}, |
| {0x19, 4, "dot11ReceivedFragmentCount"}, |
| {0x1a, 4, "dot11MulticastReceivedFrameCount"}, |
| {0x1b, 4, "dot11FCSErrorCount"}, |
| {0x1c, 4, "dot11TransmittedFrameCount"}, |
| {0x1d, 4, "dot11RSNATKIPCounterMeasuresInvoked"}, |
| {0x1e, 4, "dot11RSNA4WayHandshakeFailures"}, |
| {0x1f, 4, "dot11MulticastTransmittedFrameCount"} |
| }; |
| |
| /** |
| * @brief Get uAP stats |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_uap_stats(int argc, char *argv[]) |
| { |
| t_u8 no_of_oids = sizeof(snmp_oids) / sizeof(snmp_oids[0]); |
| t_u16 i, j; |
| int size; |
| apcmdbuf_snmp_mib *cmd_buf = NULL; |
| t_u8 *buf = NULL; |
| tlvbuf_header *tlv = NULL; |
| t_u16 cmd_len = 0; |
| t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| int opt; |
| t_u16 oid_size, byte2 = 0; |
| t_u32 byte4 = 0; |
| int ret = UAP_SUCCESS; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_apcmd_uap_stats(); |
| return UAP_SUCCESS; |
| } |
| } |
| |
| argc -= optind; |
| argv += optind; |
| if (argc) { |
| printf("Error: Invalid Input\n"); |
| print_apcmd_uap_stats(); |
| return UAP_FAILURE; |
| } |
| |
| /** Command Header */ |
| cmd_len += sizeof(apcmdbuf_snmp_mib); |
| |
| for (i = 0; i < no_of_oids; i++) { |
| /** |
| * Size of Oid + Oid_value + Oid_size |
| */ |
| cmd_len += snmp_oids[i].len + sizeof(tlvbuf_header); |
| } |
| buf = (t_u8 *)malloc(buf_len); |
| if (!buf) { |
| printf("ERR:Cannot allocate buffer from command!\n"); |
| return UAP_FAILURE; |
| } |
| memset(buf, 0, buf_len); |
| |
| /* Locate Headers */ |
| cmd_buf = (apcmdbuf_snmp_mib *)buf; |
| cmd_buf->size = cmd_len - BUF_HEADER_SIZE; |
| cmd_buf->result = 0; |
| cmd_buf->seq_num = 0; |
| cmd_buf->cmd_code = HostCmd_SNMP_MIB; |
| cmd_buf->action = uap_cpu_to_le16(ACTION_GET); |
| |
| tlv = (tlvbuf_header *)((t_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]); |
| } |
| ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); |
| if (ret == UAP_SUCCESS) { |
| if (cmd_buf->result == CMD_SUCCESS) { |
| tlv = (tlvbuf_header *)((t_u8 *)cmd_buf + |
| sizeof(apcmdbuf_snmp_mib)); |
| |
| size = cmd_buf->size - (sizeof(apcmdbuf_snmp_mib) - |
| BUF_HEADER_SIZE); |
| |
| while ((unsigned int)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: |
| memcpy(&byte2, &tlv->data[0], |
| sizeof(oid_size)); |
| printf("%d", |
| (unsigned int) |
| uap_le16_to_cpu(byte2)); |
| break; |
| case 4: |
| memcpy(&byte4, &tlv->data[0], |
| sizeof(oid_size)); |
| printf("%d", |
| (unsigned int) |
| uap_le32_to_cpu(byte4)); |
| break; |
| default: |
| for (j = 0; j < oid_size; j++) { |
| printf("%d ", |
| (t_u8)tlv->data[j]); |
| } |
| 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"); |
| ret = UAP_FAILURE; |
| } |
| } else { |
| printf("ERR:Command sending failed!\n"); |
| } |
| free(buf); |
| return ret; |
| } |
| |
| /** |
| * @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 |
| * |
| */ |
| static 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 UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_cfg_80211d(int argc, char *argv[]) |
| { |
| apcmdbuf_cfg_80211d *cmd_buf = NULL; |
| ieeetypes_subband_set_t *subband = NULL; |
| t_u8 *buf = NULL; |
| t_u16 cmd_len = 0; |
| t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| int output[2][2]; |
| int ret = UAP_SUCCESS; |
| int opt; |
| int status = 0; |
| int i, j; |
| t_u8 state = 0; |
| char country[4] = { ' ', ' ', 0, 0 }; |
| t_u8 sflag = 0, cflag = 0; |
| ieeetypes_subband_set_t sub_bands[MAX_SUB_BANDS]; |
| t_u8 no_of_sub_band = 0; |
| int band; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_apcmd_cfg_80211d_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| if (argc) { |
| if (strcmp(argv[0], "state") && strcmp(argv[0], "country")) { |
| printf("ERR: Incorrect input. Either state or country is needed."); |
| print_apcmd_cfg_80211d_usage(); |
| return UAP_FAILURE; |
| } |
| /** 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 UAP_FAILURE; |
| } |
| |
| 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 UAP_FAILURE; |
| } |
| state = (t_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 UAP_FAILURE; |
| } |
| 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 UAP_FAILURE; |
| } |
| if ((strlen(argv[output[1][0] + 1]) > 3) || |
| (strlen(argv[output[1][0] + 1]) == 0)) { |
| print_apcmd_cfg_80211d_usage(); |
| return UAP_FAILURE; |
| } |
| /* Only 2 characters of country code are copied here as indoor/outdoor |
| * conditions are not handled in domain file */ |
| strncpy(country, argv[output[1][0] + 1], 2); |
| |
| for (i = 0; (unsigned int)i < strlen(country); i++) { |
| if ((country[i] < 'A') || (country[i] > 'z')) { |
| printf("Invalid Country Code\n"); |
| print_apcmd_cfg_80211d_usage(); |
| return UAP_FAILURE; |
| } |
| if (country[i] > 'Z') |
| country[i] = country[i] - 'a' + 'A'; |
| } |
| |
| cflag = 1; |
| if (!get_band(&band)) { |
| printf("ERR:couldn't get band from channel!\n"); |
| return UAP_FAILURE; |
| } |
| /** Get domain information from the file */ |
| no_of_sub_band = |
| parse_domain_file(country, band, sub_bands, |
| NULL); |
| if (no_of_sub_band == UAP_FAILURE) { |
| printf("Parsing Failed\n"); |
| return UAP_FAILURE; |
| } |
| } |
| if (get_bss_status(&status) != UAP_SUCCESS) { |
| printf("ERR:Cannot get current bss status!\n"); |
| return UAP_FAILURE; |
| } |
| if (status == UAP_BSS_START) { |
| printf("ERR: 11d status can not be changed after BSS start!\n"); |
| return UAP_FAILURE; |
| } |
| } |
| |
| if (argc && !cflag && !sflag) { |
| printf("ERR: Invalid input\n"); |
| print_apcmd_cfg_80211d_usage(); |
| return UAP_FAILURE; |
| } |
| |
| 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 UAP_SUCCESS; |
| } else { |
| return UAP_FAILURE; |
| } |
| } |
| |
| cmd_len = sizeof(apcmdbuf_cfg_80211d); |
| |
| if (cflag) { |
| cmd_len += no_of_sub_band * sizeof(ieeetypes_subband_set_t); |
| } else { |
| /** Get */ |
| cmd_len += MAX_SUB_BANDS * sizeof(ieeetypes_subband_set_t); |
| } |
| |
| buf = (t_u8 *)malloc(buf_len); |
| if (!buf) { |
| printf("ERR:Cannot allocate buffer from command!\n"); |
| return UAP_FAILURE; |
| } |
| memset(buf, 0, buf_len); |
| /* Locate headers */ |
| cmd_buf = (apcmdbuf_cfg_80211d *)buf; |
| cmd_len = argc ? cmd_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->seq_num = 0; |
| cmd_buf->action = argc ? ACTION_SET : ACTION_GET; |
| cmd_buf->action = uap_cpu_to_le16(cmd_buf->action); |
| cmd_buf->cmd_code = HostCmd_CMD_802_11D_DOMAIN_INFO; |
| |
| if (cflag) { |
| /* third character of country code is copied here as indoor/outdoor |
| * condition is not supported in domain file*/ |
| strncpy(country, argv[output[1][0] + 1], sizeof(country) - 1); |
| for (i = 0; (unsigned int)i < strlen(country); i++) { |
| if ((country[i] < 'A') || (country[i] > 'z')) { |
| printf("Invalid Country Code\n"); |
| print_apcmd_cfg_80211d_usage(); |
| free(buf); |
| return UAP_FAILURE; |
| } |
| if (country[i] > 'Z') |
| country[i] = country[i] - 'a' + 'A'; |
| } |
| 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_subband_set_t))); |
| |
| memset(cmd_buf->domain.country_code, ' ', |
| sizeof(cmd_buf->domain.country_code)); |
| memcpy(cmd_buf->domain.country_code, country, strlen(country)); |
| memcpy(cmd_buf->domain.subband, sub_bands, |
| no_of_sub_band * sizeof(ieeetypes_subband_set_t)); |
| } |
| |
| /* Send the command */ |
| ret = uap_ioctl((t_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.country_code[0] || |
| cmd_buf->domain.country_code[1] || |
| cmd_buf->domain.country_code[2]) { |
| printf("Country string = %c%c%c", |
| cmd_buf->domain.country_code[0], |
| cmd_buf->domain.country_code[1], |
| cmd_buf->domain.country_code[2]); |
| j -= sizeof(cmd_buf->domain. |
| country_code); |
| subband = |
| (ieeetypes_subband_set_t *) |
| cmd_buf->domain.subband; |
| printf("\nSub-band info="); |
| 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->first_chan, subband->no_of_chan, subband->max_tx_pwr); |
| subband++; |
| } |
| } |
| } |
| } else { |
| printf("ERR:Command Response incorrect!\n"); |
| if (argc) |
| printf("11d info is allowed to set only before bss start.\n"); |
| ret = UAP_FAILURE; |
| } |
| } else { |
| printf("ERR:Command sending failed!\n"); |
| } |
| free(buf); |
| return ret; |
| } |
| |
| /** |
| * @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/UAP_FAILURE |
| */ |
| int |
| apcmd_sys_config(int argc, char *argv[]) |
| { |
| apcmdbuf_sys_configure *cmd_buf = NULL; |
| t_u8 *buf = NULL; |
| t_u16 cmd_len; |
| t_u16 buf_len; |
| int ret = UAP_SUCCESS; |
| int opt; |
| char **argv_dummy = NULL; |
| ps_mgmt pm; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_sys_config_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| /* Check arguments */ |
| if (argc > 1) { |
| printf("ERR:Too many arguments.\n"); |
| print_sys_config_usage(); |
| return UAP_FAILURE; |
| } |
| if (argc == 1) { |
| /* Read profile and send command to firmware */ |
| ret = apcmd_sys_config_profile(argc, argv); |
| return ret; |
| } |
| |
| /** Query AP's setting */ |
| buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| |
| /* Alloc buf for command */ |
| buf = (t_u8 *)malloc(buf_len); |
| |
| if (!buf) { |
| printf("ERR:Cannot allocate buffer from command!\n"); |
| return UAP_FAILURE; |
| } |
| memset(buf, 0, buf_len); |
| |
| /* Reset custom_ie_present flag */ |
| custom_ie_present = 0; |
| |
| /* Reset max_mgmt_ie_print flag */ |
| max_mgmt_ie_print = 0; |
| |
| /* Locate headers */ |
| cmd_len = sizeof(apcmdbuf_sys_configure); |
| cmd_buf = (apcmdbuf_sys_configure *)buf; |
| |
| /* Fill the command buffer */ |
| cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; |
| cmd_buf->size = cmd_len - BUF_HEADER_SIZE; |
| cmd_buf->seq_num = 0; |
| cmd_buf->result = 0; |
| |
| /* Send the command */ |
| ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); |
| |
| /* Process response */ |
| if (ret == UAP_SUCCESS) { |
| /* Verify response */ |
| if (cmd_buf->cmd_code != |
| (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) { |
| printf("ERR:Corrupted response!\n"); |
| free(buf); |
| return UAP_FAILURE; |
| } |
| /* 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); |
| if (apcmd_addbapara(1, argv_dummy) == UAP_FAILURE) { |
| printf("Couldn't get ADDBA parameters\n"); |
| return UAP_FAILURE; |
| } |
| if (apcmd_aggrpriotbl(1, argv_dummy) == UAP_FAILURE) { |
| printf("Couldn't get AMSDU/AMPDU priority table\n"); |
| return UAP_FAILURE; |
| } |
| if (apcmd_addbareject(1, argv_dummy) == UAP_FAILURE) { |
| printf("Couldn't get ADDBA reject table\n"); |
| return UAP_FAILURE; |
| } |
| printf("\n802.11D setting:\n"); |
| if (apcmd_cfg_80211d(1, argv_dummy) == UAP_FAILURE) { |
| return UAP_FAILURE; |
| } |
| if (!custom_ie_present) { |
| printf("\nCustom IE settings:\n"); |
| if (apcmd_sys_cfg_custom_ie(1, argv_dummy) == |
| UAP_FAILURE) { |
| return UAP_FAILURE; |
| } |
| } |
| } else { |
| printf("ERR:Could not retrieve system configure\n"); |
| ret = UAP_FAILURE; |
| } |
| } else { |
| printf("ERR:Command sending failed!\n"); |
| } |
| free(buf); |
| memset(&pm, 0, sizeof(ps_mgmt)); |
| ret = send_power_mode_ioctl(&pm, 0); |
| return ret; |
| } |
| |
| /** Update domain info with given country and band |
| * |
| * @param country_80211d country to be set |
| * @param band band of operation |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| static int |
| update_domain_info(char *country_80211d, int band) |
| { |
| apcmdbuf_cfg_80211d *cmd_buf = NULL; |
| t_u8 *buf = NULL; |
| t_u16 cmd_len = 0; |
| t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| ieeetypes_subband_set_t sub_bands[MAX_SUB_BANDS]; |
| t_u8 no_of_sub_band = 0; |
| char country[4] = { ' ', ' ', 0, 0 }; |
| int ret = UAP_SUCCESS; |
| t_u8 domain_code = 0; |
| rgn_dom_code_t *prgn_dom_code = NULL; |
| |
| /* Get currently set country code from FW */ |
| buf = (t_u8 *)malloc(buf_len); |
| if (!buf) { |
| printf("ERR:Cannot allocate buffer from command!\n"); |
| return UAP_FAILURE; |
| } |
| memset(buf, 0, buf_len); |
| /* Locate headers */ |
| cmd_buf = (apcmdbuf_cfg_80211d *)buf; |
| cmd_len = (sizeof(apcmdbuf_cfg_80211d) - sizeof(domain_param_t)); |
| |
| cmd_buf->size = cmd_len - BUF_HEADER_SIZE; |
| cmd_buf->result = 0; |
| cmd_buf->seq_num = 0; |
| cmd_buf->action = ACTION_GET; |
| cmd_buf->action = uap_cpu_to_le16(cmd_buf->action); |
| cmd_buf->cmd_code = HostCmd_CMD_802_11D_DOMAIN_INFO; |
| |
| ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); |
| if ((ret == UAP_SUCCESS) && (cmd_buf->result == CMD_SUCCESS) && |
| (cmd_buf->domain.country_code[0] || |
| cmd_buf->domain.country_code[1] || |
| cmd_buf->domain.country_code[2])) { |
| country[0] = cmd_buf->domain.country_code[0]; |
| country[1] = cmd_buf->domain.country_code[1]; |
| } else { |
| /* country_80211d will only be used if country code is not already set */ |
| country[0] = country_80211d[0]; |
| country[1] = country_80211d[1]; |
| } |
| |
| if (band == BAND_A) |
| printf("Enabling 11d for 11h operation and setting country code to %s\n", country); |
| cmd_len = sizeof(apcmdbuf_cfg_80211d); |
| /** Get domain information from the file */ |
| no_of_sub_band = |
| parse_domain_file(country, band, sub_bands, &domain_code); |
| if (no_of_sub_band == UAP_FAILURE) { |
| printf("Parsing Failed\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| /* Copy third character of country code here */ |
| if (cmd_buf->domain.country_code[2]) { |
| country[2] = cmd_buf->domain.country_code[2]; |
| } else { |
| country[2] = country_80211d[2]; |
| } |
| |
| /* Set domain for this country code */ |
| memset(buf, 0, buf_len); |
| cmd_len += no_of_sub_band * sizeof(ieeetypes_subband_set_t); |
| /* Locate headers */ |
| cmd_buf = (apcmdbuf_cfg_80211d *)buf; |
| cmd_buf->size = cmd_len - BUF_HEADER_SIZE; |
| cmd_buf->result = 0; |
| cmd_buf->seq_num = 0; |
| cmd_buf->action = ACTION_SET; |
| cmd_buf->action = uap_cpu_to_le16(cmd_buf->action); |
| cmd_buf->cmd_code = 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_subband_set_t))); |
| |
| memset(cmd_buf->domain.country_code, ' ', |
| sizeof(cmd_buf->domain.country_code)); |
| memcpy(cmd_buf->domain.country_code, country, strlen(country)); |
| memcpy(cmd_buf->domain.subband, sub_bands, |
| no_of_sub_band * sizeof(ieeetypes_subband_set_t)); |
| |
| /* Send the command */ |
| ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); |
| if (ret == UAP_SUCCESS) { |
| if (cmd_buf->result != CMD_SUCCESS) { |
| printf("ERR:Command Response incorrect!\n"); |
| printf("11d info is allowed to set only before bss start.\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } else { |
| printf("ERR:Command sending failed!\n"); |
| } |
| |
| if ((band == BAND_A) && domain_code) { |
| /* Send 11D_CMD a second time, with reg_dom_code TLV appended. |
| * Use hostcmd instead of re-route. */ |
| cmd_len = cmd_buf->size + BUF_HEADER_SIZE; |
| prgn_dom_code = (rgn_dom_code_t *)((t_u8 *)cmd_buf + cmd_len); |
| cmd_len += sizeof(rgn_dom_code_t); |
| cmd_buf->size += sizeof(rgn_dom_code_t); |
| #if DEBUG |
| uap_printf(MSG_DEBUG, |
| "Adding Region Domain Code TLV. Domain_code=%d\n", |
| domain_code); |
| #endif |
| prgn_dom_code->tag = |
| uap_cpu_to_le16(MRVL_REGION_DOMAIN_CODE_TLV_ID); |
| prgn_dom_code->length = uap_cpu_to_le16(sizeof(rgn_dom_code_t) |
| - BUF_HEADER_SIZE); |
| prgn_dom_code->domain_code = domain_code; |
| |
| /* Send the command */ |
| uap_ioctl_no_reroute = 1; |
| ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); |
| uap_ioctl_no_reroute = 0; |
| |
| if (ret == UAP_SUCCESS) { |
| if (cmd_buf->result != CMD_SUCCESS) { |
| printf("ERR:Command Response incorrect!\n"); |
| printf("11d info is allowed to set only before bss start.\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| } else { |
| printf("ERR:Command sending failed!\n"); |
| } |
| } |
| |
| done: |
| if (buf) |
| free(buf); |
| return ret; |
| } |
| |
| /** |
| * @brief Covert MCS Rate Bitmap to MCS Rate index |
| * |
| * @param rate_bitmap Pointer to rate bitmap |
| * @param size Size of the bitmap array |
| * |
| * @return Rate index |
| */ |
| int |
| get_rate_index_from_bitmap(t_u16 *rate_bitmap, int size) |
| { |
| int i; |
| |
| for (i = 0; i < size * 8; i++) { |
| if (rate_bitmap[i / 16] & (1 << (i % 16))) { |
| return i; |
| } |
| } |
| return 0; |
| } |
| |
| /** |
| * @brief Checks current system configuration |
| * |
| * @param buf pointer to TLV buffer |
| * @param len TLV buffer length |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| check_sys_config(t_u8 *buf, t_u16 len) |
| { |
| tlvbuf_header *pcurrent_tlv = (tlvbuf_header *)buf; |
| int tlv_buf_left = len; |
| t_u16 tlv_type; |
| t_u16 tlv_len; |
| tlvbuf_channel_config *channel_tlv = NULL; |
| tlvbuf_channel_list *chnlist_tlv = NULL; |
| tlvbuf_pwk_cipher *pwk_cipher_tlv = NULL; |
| tlvbuf_gwk_cipher *gwk_cipher_tlv = NULL; |
| tlvbuf_auth_mode *auth_tlv = NULL; |
| tlvbuf_protocol *protocol_tlv = NULL; |
| tlvbuf_wep_key *wep_key_tlv = NULL; |
| tlvbuf_wpa_passphrase *passphrase_tlv = NULL; |
| tlvbuf_rates *rates_tlv = NULL; |
| tlvbuf_mcbc_data_rate *mcbc_data_rate_tlv = NULL; |
| t_u16 protocol = 0; |
| t_u16 mcbc_data_rate = 0; |
| t_u16 op_rates_len = 0; |
| t_u8 acs_mode_enabled = 0; |
| t_u8 *cbuf = NULL; |
| apcmdbuf_cfg_80211d *cmd_buf = NULL; |
| t_u16 buf_len, cmd_len; |
| char country_80211d[4] = { 'U', 'S', ' ', 0 }; |
| t_u8 state_80211h = 0; |
| int channel_tlv_band = BAND_B | BAND_G; |
| t_u8 secondary_ch_set = 0; |
| int scan_channels_band = BAND_B | BAND_G; |
| t_u8 state_80211d = 0; |
| t_u8 rate = 0; |
| t_u32 rate_bitmap = 0; |
| tlvbuf_htcap_t *ht_cap_tlv = NULL; |
| t_u16 enable_40Mhz = 0; |
| t_u16 enable_20Mhz_sgi = 0; |
| t_u16 enable_gf = 0; |
| t_u8 enable_11n = 0; |
| int flag = 0; |
| fw_info fw; |
| channel_list *pchan_list; |
| tlvbuf_tx_power *txpower_tlv = NULL; |
| int i = 0, ret = UAP_SUCCESS; |
| int pairwise_cipher_wpa = -1; |
| int pairwise_cipher_wpa2 = -1; |
| int group_cipher = -1; |
| int chan_list_len = 0; |
| int key_set = 0; |
| t_u8 channel = 0; |
| tx_rate_cfg_t tx_rate_config; |
| t_u32 mcs_rate_index = 0; |
| struct eth_priv_vhtcfg vhtcfg = { 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 |
| |
| if (pcurrent_tlv == NULL) { |
| printf("ERR: No TLV buffer available!\n"); |
| return UAP_FAILURE; |
| } |
| |
| ret = sg_snmp_mib(ACTION_GET, OID_80211D_ENABLE, sizeof(state_80211d), |
| &state_80211d); |
| |
| buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| cbuf = (t_u8 *)malloc(buf_len); |
| if (!cbuf) { |
| printf("ERR:Cannot allocate buffer from command!\n"); |
| return UAP_FAILURE; |
| } |
| memset(cbuf, 0, buf_len); |
| /* Locate headers */ |
| cmd_buf = (apcmdbuf_cfg_80211d *)cbuf; |
| cmd_len = (sizeof(apcmdbuf_cfg_80211d) - sizeof(domain_param_t)); |
| cmd_buf->size = cmd_len - BUF_HEADER_SIZE; |
| cmd_buf->action = uap_cpu_to_le16(ACTION_GET); |
| cmd_buf->cmd_code = HostCmd_CMD_802_11D_DOMAIN_INFO; |
| ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); |
| if (ret == UAP_SUCCESS && cmd_buf->result == CMD_SUCCESS) { |
| if (cmd_buf->domain.country_code[0] || |
| cmd_buf->domain.country_code[1] || |
| cmd_buf->domain.country_code[2]) { |
| strncpy(country_80211d, |
| (char *)cmd_buf->domain.country_code, |
| COUNTRY_CODE_LEN); |
| } |
| } |
| free(cbuf); |
| |
| /* get region code to handle special cases */ |
| memset(&fw, 0, sizeof(fw)); |
| if (get_fw_info(&fw)) { |
| printf("Could not get fw info!\n"); |
| return UAP_FAILURE; |
| } |
| |
| if (get_tx_rate_cfg(&tx_rate_config) == UAP_FAILURE) { |
| printf("Could not get tx_rate_cfg!\n"); |
| return UAP_FAILURE; |
| } |
| while (tlv_buf_left >= (int)sizeof(tlvbuf_header) && |
| (ret != UAP_FAILURE)) { |
| tlv_type = *(t_u8 *)&pcurrent_tlv->type; |
| tlv_type |= (*((t_u8 *)&pcurrent_tlv->type + 1) << 8); |
| tlv_len = *(t_u8 *)&pcurrent_tlv->len; |
| tlv_len |= (*((t_u8 *)&pcurrent_tlv->len + 1) << 8); |
| if ((sizeof(tlvbuf_header) + tlv_len) > |
| (unsigned int)tlv_buf_left) { |
| printf("wrong tlv: tlv_len=%d, tlv_buf_left=%d\n", |
| tlv_len, tlv_buf_left); |
| break; |
| } |
| switch (tlv_type) { |
| case MRVL_CHANNELCONFIG_TLV_ID: |
| channel_tlv = (tlvbuf_channel_config *)pcurrent_tlv; |
| channel = channel_tlv->chan_number; |
| |
| if ((!state_80211d) && |
| (channel_tlv->chan_number == MAX_CHANNELS_BG) |
| && |
| (strncmp(country_80211d, "JP", COUNTRY_CODE_LEN - 1) |
| == 0) |
| ) { |
| printf("ERR: Invalid channel 14, 802.11d disabled, country code JP!\n"); |
| return UAP_FAILURE; |
| } |
| |
| if (channel_tlv->bandcfg.chanBand == BAND_5GHZ) |
| channel_tlv_band = BAND_A; |
| secondary_ch_set = channel_tlv->bandcfg.chan2Offset; |
| if (channel_tlv_band != BAND_A) { |
| /* When country code is not Japan, allow channels 5-11 for US and 5-13 for non-US |
| * only for secondary channel below */ |
| if (secondary_ch_set == SEC_CHAN_BELOW) { |
| if (!strncmp |
| (country_80211d, "US", |
| COUNTRY_CODE_LEN - 1)) { |
| if (channel_tlv->chan_number > |
| DEFAULT_MAX_CHANNEL_BELOW) { |
| printf("ERR: Only channels 5-11 are allowed with secondary channel below for the US\n"); |
| return UAP_FAILURE; |
| } |
| } else if (strncmp |
| (country_80211d, "JP", |
| COUNTRY_CODE_LEN - 1)) { |
| if (channel_tlv->chan_number > |
| DEFAULT_MAX_CHANNEL_BELOW_NON_US) |
| { |
| printf("ERR: Only channels 5-13 are allowed with secondary channel below for" "non-Japan countries!\n"); |
| return UAP_FAILURE; |
| } |
| } |
| } |
| |
| /* When country code is not Japan, allow channels 1-7 for US and 1-9 for non-US |
| * only for secondary channel above */ |
| if (secondary_ch_set == SEC_CHAN_ABOVE) { |
| if (!strncmp |
| (country_80211d, "US", |
| COUNTRY_CODE_LEN - 1)) { |
| if (channel_tlv->chan_number > |
| DEFAULT_MAX_CHANNEL_ABOVE) { |
| printf("ERR: Only channels 1-7 are allowed with secondary channel above for the US\n"); |
| return UAP_FAILURE; |
| } |
| } else if (strncmp |
| (country_80211d, "JP", |
| COUNTRY_CODE_LEN - 1)) { |
| if (channel_tlv->chan_number > |
| DEFAULT_MAX_CHANNEL_ABOVE_NON_US) |
| { |
| printf("ERR: Only channels 1-9 are allowed with secondary channel above for" "non-Japan countries!\n"); |
| return UAP_FAILURE; |
| } |
| } |
| } |
| } |
| if (!(channel_tlv->bandcfg.scanMode == SCAN_MODE_ACS)) { |
| if (check_channel_validity_11d |
| (channel_tlv->chan_number, channel_tlv_band, |
| 1) == UAP_FAILURE) |
| return UAP_FAILURE; |
| if (state_80211d) { |
| /* Set country code to JP if channel is 8 or 12 and band is 5GHZ */ |
| if ((channel_tlv->chan_number < |
| MAX_CHANNELS_BG) && |
| (channel_tlv_band == BAND_A)) |
| strncpy(country_80211d, "JP ", |
| sizeof(country_80211d) - |
| 1); |
| } else { |
| if ((channel_tlv_band == BAND_A) && |
| ((channel_tlv->chan_number == 8) || |
| (channel_tlv->chan_number == |
| 12))) { |
| printf("ERR:Invalid band for given channel\n"); |
| return UAP_FAILURE; |
| } |
| } |
| } else { |
| acs_mode_enabled = 1; |
| } |
| #define JP_REGION_0xFE 0xFE |
| if (fw.region_code == JP_REGION_0xFE && |
| ((channel_tlv->chan_number == 12) || |
| (channel_tlv->chan_number == 13))) { |
| printf("ERR:Channel 12 or 13 is not allowed for region code 0xFE\n"); |
| return UAP_FAILURE; |
| } |
| break; |
| case MRVL_CHANNELLIST_TLV_ID: |
| chnlist_tlv = (tlvbuf_channel_list *)pcurrent_tlv; |
| pchan_list = |
| (channel_list *) & (chnlist_tlv->chan_list); |
| if (tlv_len % sizeof(channel_list)) { |
| printf("ERR:Invalid Scan channel list TLV!\n"); |
| return UAP_FAILURE; |
| } |
| chan_list_len = tlv_len / sizeof(channel_list); |
| |
| for (i = 0; i < chan_list_len; i++) { |
| scan_channels_band = BAND_B | BAND_G; |
| if ((scan_channels_band != BAND_A) && |
| (pchan_list->bandcfg.chanBand == |
| BAND_5GHZ)) { |
| scan_channels_band = BAND_A; |
| } |
| if (check_channel_validity_11d |
| (pchan_list->chan_number, |
| scan_channels_band, 0) == UAP_FAILURE) |
| return UAP_FAILURE; |
| pchan_list++; |
| } |
| break; |
| case MRVL_TX_POWER_TLV_ID: |
| txpower_tlv = (tlvbuf_tx_power *)pcurrent_tlv; |
| if (state_80211d) { |
| if (check_tx_pwr_validity_11d |
| (txpower_tlv->tx_power_dbm) == UAP_FAILURE) |
| return UAP_FAILURE; |
| } |
| break; |
| case MRVL_CIPHER_PWK_TLV_ID: |
| pwk_cipher_tlv = (tlvbuf_pwk_cipher *)pcurrent_tlv; |
| pwk_cipher_tlv->protocol = |
| uap_le16_to_cpu(pwk_cipher_tlv->protocol); |
| if (pwk_cipher_tlv->protocol == PROTOCOL_WPA) |
| pairwise_cipher_wpa = |
| pwk_cipher_tlv->pairwise_cipher; |
| else if (pwk_cipher_tlv->protocol == PROTOCOL_WPA2) |
| pairwise_cipher_wpa2 = |
| pwk_cipher_tlv->pairwise_cipher; |
| break; |
| case MRVL_CIPHER_GWK_TLV_ID: |
| gwk_cipher_tlv = (tlvbuf_gwk_cipher *)pcurrent_tlv; |
| group_cipher = gwk_cipher_tlv->group_cipher; |
| break; |
| case MRVL_AUTH_TLV_ID: |
| auth_tlv = (tlvbuf_auth_mode *)pcurrent_tlv; |
| break; |
| case MRVL_PROTOCOL_TLV_ID: |
| protocol_tlv = (tlvbuf_protocol *)pcurrent_tlv; |
| protocol = uap_le16_to_cpu(protocol_tlv->protocol); |
| break; |
| case MRVL_WPA_PASSPHRASE_TLV_ID: |
| passphrase_tlv = (tlvbuf_wpa_passphrase *)pcurrent_tlv; |
| break; |
| case MRVL_WEP_KEY_TLV_ID: |
| wep_key_tlv = (tlvbuf_wep_key *)pcurrent_tlv; |
| if (wep_key_tlv->is_default) { |
| key_set = 1; |
| } |
| break; |
| case HT_CAPABILITY_TLV_ID: |
| ht_cap_tlv = (tlvbuf_htcap_t *)pcurrent_tlv; |
| ht_cap_tlv->ht_cap.ht_cap_info = |
| uap_le16_to_cpu(ht_cap_tlv->ht_cap.ht_cap_info); |
| if (ht_cap_tlv->ht_cap.supported_mcs_set[0]) { |
| enable_11n = 1; |
| enable_40Mhz = |
| IS_11N_40MHZ_ENABLED(ht_cap_tlv->ht_cap. |
| ht_cap_info); |
| enable_20Mhz_sgi = |
| IS_11N_20MHZ_SHORTGI_ENABLED |
| (ht_cap_tlv->ht_cap.ht_cap_info); |
| enable_gf = |
| IS_11N_GF_ENABLED(ht_cap_tlv->ht_cap. |
| ht_cap_info); |
| } |
| break; |
| case MRVL_RATES_TLV_ID: |
| rates_tlv = (tlvbuf_rates *)pcurrent_tlv; |
| op_rates_len = tlv_len; |
| break; |
| case MRVL_MCBC_DATA_RATE_TLV_ID: |
| mcbc_data_rate_tlv = |
| (tlvbuf_mcbc_data_rate *)pcurrent_tlv; |
| mcbc_data_rate = |
| uap_le16_to_cpu(mcbc_data_rate_tlv-> |
| mcbc_datarate); |
| if (mcbc_data_rate && |
| (is_mcbc_rate_valid((t_u8)mcbc_data_rate) != |
| UAP_SUCCESS)) { |
| printf("ERR: Invalid MCBC Data Rate \n"); |
| return UAP_FAILURE; |
| } |
| break; |
| } |
| tlv_buf_left -= (sizeof(tlvbuf_header) + tlv_len); |
| pcurrent_tlv = (tlvbuf_header *)(pcurrent_tlv->data + tlv_len); |
| } |
| |
| if ((protocol == PROTOCOL_STATIC_WEP) && !key_set) { |
| printf("ERR:WEP keys not set!\n"); |
| return UAP_FAILURE; |
| } |
| if (auth_tlv == NULL) { |
| printf("ERR: No authentication found\n"); |
| return UAP_FAILURE; |
| } |
| if ((auth_tlv->auth_mode == 1) && (protocol != PROTOCOL_STATIC_WEP)) { |
| printf("ERR:Shared key authentication is not allowed for Open/WPA/WPA2/Mixed mode\n"); |
| return UAP_FAILURE; |
| } |
| |
| if (passphrase_tlv == NULL) { |
| printf("ERR: No passphrase found\n"); |
| return UAP_FAILURE; |
| } |
| if (((protocol == PROTOCOL_WPA) || (protocol == PROTOCOL_WPA2) |
| || (protocol == PROTOCOL_WPA2_MIXED)) && !(passphrase_tlv->length)) { |
| printf("ERR:Passphrase must be set for WPA/WPA2/Mixed mode\n"); |
| return UAP_FAILURE; |
| } |
| if ((protocol == PROTOCOL_WPA) || (protocol == PROTOCOL_WPA2_MIXED)) { |
| if (is_cipher_valid(pairwise_cipher_wpa, group_cipher) != |
| UAP_SUCCESS) { |
| printf("ERR:Wrong group cipher and WPA pairwise cipher combination!\n"); |
| return UAP_FAILURE; |
| } |
| } |
| if ((protocol == PROTOCOL_WPA2) || (protocol == PROTOCOL_WPA2_MIXED)) { |
| if (is_cipher_valid(pairwise_cipher_wpa2, group_cipher) != |
| UAP_SUCCESS) { |
| printf("ERR:Wrong group cipher and WPA2 pairwise cipher combination!\n"); |
| return UAP_FAILURE; |
| } |
| } |
| |
| if (chnlist_tlv == NULL) { |
| printf("ERR: No channel list found\n"); |
| return UAP_FAILURE; |
| } |
| if (acs_mode_enabled) { |
| pchan_list = (channel_list *) & (chnlist_tlv->chan_list); |
| for (i = 0; i < chan_list_len; i++) { |
| if ((!state_80211d) && |
| (pchan_list->chan_number == MAX_CHANNELS_BG) |
| && |
| (strncmp(country_80211d, "JP", COUNTRY_CODE_LEN - 1) |
| == 0) |
| ) { |
| printf("ERR: Invalid scan channel 14, 802.11d disabled, country code JP!\n"); |
| return UAP_FAILURE; |
| } |
| |
| if (fw.region_code == JP_REGION_0xFE && |
| ((pchan_list->chan_number == 12) || |
| (pchan_list->chan_number == 13))) { |
| printf("ERR:Scan Channel 12 or 13 is not allowed for region code 0xFE\n"); |
| return UAP_FAILURE; |
| } |
| pchan_list++; |
| } |
| |
| if (!state_80211d) { |
| /* Block scan channels 8 and 12 in 5GHz band if 11d is not enabled and country code not set to JP */ |
| pchan_list = |
| (channel_list *) & (chnlist_tlv->chan_list); |
| for (i = 0; i < chan_list_len; i++) { |
| if ((pchan_list->bandcfg.chanBand == BAND_5GHZ) |
| && ((pchan_list->chan_number == 8) || |
| (pchan_list->chan_number == 12))) { |
| printf("ERR: Invalid band for scan channel %d\n", pchan_list->chan_number); |
| return UAP_FAILURE; |
| } |
| pchan_list++; |
| } |
| } |
| if (state_80211d) { |
| /* Set default country code to US */ |
| strncpy(country_80211d, "US ", |
| sizeof(country_80211d) - 1); |
| pchan_list = |
| (channel_list *) & (chnlist_tlv->chan_list); |
| for (i = 0; i < chan_list_len; i++) { |
| /* Set country code to JP if channel is 8 or 12 and band is 5GHZ */ |
| if ((pchan_list->chan_number < MAX_CHANNELS_BG) |
| && (scan_channels_band == BAND_A)) { |
| strncpy(country_80211d, "JP ", |
| sizeof(country_80211d) - 1); |
| } |
| if (check_channel_validity_11d |
| (pchan_list->chan_number, |
| scan_channels_band, 0) == UAP_FAILURE) |
| return UAP_FAILURE; |
| pchan_list++; |
| } |
| if (update_domain_info |
| (country_80211d, |
| scan_channels_band) == UAP_FAILURE) { |
| return UAP_FAILURE; |
| } |
| } |
| } |
| #ifdef WIFI_DIRECT_SUPPORT |
| if (strncmp(dev_name, "wfd", 3)) |
| #endif |
| if ((!acs_mode_enabled && |
| (channel_tlv_band == (BAND_B | BAND_G))) |
| || (acs_mode_enabled && |
| (scan_channels_band == (BAND_B | BAND_G)))) { |
| if (rates_tlv == NULL) { |
| printf("ERR: No rates found\n"); |
| return UAP_FAILURE; |
| } |
| for (i = 0; i < op_rates_len; i++) { |
| rate = rates_tlv-> |
| operational_rates[i] & |
| ~BASIC_RATE_SET_BIT; |
| switch (rate) { |
| 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; |
| } |
| } |
| if ((rate_bitmap & B_RATE_MANDATORY) != |
| B_RATE_MANDATORY) { |
| if (acs_mode_enabled) |
| printf("ERR: Rates/Scan channels do not match!\n"); |
| else |
| printf("ERR: Rates/Channel do not match!\n"); |
| return UAP_FAILURE; |
| } |
| } |
| if ((!acs_mode_enabled && (channel_tlv_band == BAND_A)) |
| || (acs_mode_enabled && (scan_channels_band == BAND_A))) { |
| if (rates_tlv == NULL) { |
| printf("ERR: No rates found\n"); |
| return UAP_FAILURE; |
| } |
| for (i = 0; i < op_rates_len; i++) { |
| rate = rates_tlv-> |
| operational_rates[i] & ~BASIC_RATE_SET_BIT; |
| switch (rate) { |
| case 2: |
| case 4: |
| case 11: |
| case 22: |
| if (acs_mode_enabled) |
| printf("ERR: Rates/Scan channels do not match!\n"); |
| else |
| printf("ERR: Rates/Channel do not match!\n"); |
| return UAP_FAILURE; |
| } |
| } |
| state_80211h = 1; |
| if (sg_snmp_mib |
| (ACTION_SET, OID_80211H_ENABLE, sizeof(state_80211h), |
| &state_80211h) |
| == UAP_FAILURE) { |
| return UAP_FAILURE; |
| } |
| if (update_domain_info(country_80211d, BAND_A) == UAP_FAILURE) { |
| return UAP_FAILURE; |
| } |
| } |
| #define ISSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap & MBIT(17)) |
| #define ISSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap & MBIT(24)) |
| |
| if (enable_40Mhz) { |
| if (!ISSUPP_CHANWIDTH40(fw.hw_dot_11n_dev_cap)) { |
| printf("ERR: It's not support HT40 from Hardware Cap\n"); |
| return UAP_FAILURE; |
| } |
| } |
| |
| if (enable_11n) { |
| /*For protocol = Mixed, 11n enabled, only allow TKIP cipher for WPA protocol, not for WPA2 */ |
| if ((protocol == PROTOCOL_WPA2_MIXED) && |
| (pairwise_cipher_wpa2 == CIPHER_TKIP)) { |
| printf("ERR: WPA2 pairwise cipher cannot be TKIP when AP operates in 802.11n Mixed mode.\n"); |
| return UAP_FAILURE; |
| } else if (protocol == PROTOCOL_STATIC_WEP) { |
| printf("ERR: WEP cannot be used when AP operates in 802.11n mode.\n"); |
| return UAP_FAILURE; |
| } |
| } |
| if ((tx_rate_config.rate == UAP_RATE_INDEX_MCS32) && !enable_40Mhz) { |
| printf("ERR:uAP must be configured to operate in 40MHz if tx_rate is MCS32\n"); |
| return UAP_FAILURE; |
| } |
| if (enable_20Mhz_sgi && enable_gf) { |
| if ((tx_rate_config.rate >= UAP_RATE_INDEX_MCS0) && |
| (tx_rate_config.rate <= UAP_RATE_INDEX_MCS7)) { |
| printf("ERR: Invalid tx_rate for uAP in (20MHz Short GI + Green Field) mode\n"); |
| return UAP_FAILURE; |
| } |
| } |
| mcs_rate_index = |
| get_rate_index_from_bitmap(tx_rate_config.bitmap_rates, |
| sizeof(tx_rate_config.bitmap_rates)); |
| if ((mcs_rate_index >= UAP_RATE_BITMAP_MCS0) && |
| (mcs_rate_index <= UAP_RATE_BITMAP_MCS127)) { |
| mcs_rate_index -= (UAP_RATE_BITMAP_MCS0 - UAP_RATE_INDEX_MCS0); |
| if ((mcs_rate_index == UAP_RATE_INDEX_MCS32) & !enable_40Mhz) { |
| printf("ERR:uAP must be configured to operate in 40MHz if rate_bitmap contains MCS32\n"); |
| return UAP_FAILURE; |
| } |
| if (enable_20Mhz_sgi && enable_gf) { |
| if ((mcs_rate_index >= UAP_RATE_INDEX_MCS0) && |
| (mcs_rate_index <= UAP_RATE_INDEX_MCS7)) { |
| printf("ERR: Invalid tx_rate for uAP in (20MHz Short GI + Green Field) mode\n"); |
| return UAP_FAILURE; |
| } |
| } |
| } |
| |
| /* if 11d enabled, Channel 14, country code "JP", only B rates are allowed */ |
| if ((channel == 14) && state_80211d && |
| (strncmp(country_80211d, "JP", COUNTRY_CODE_LEN - 1) == 0)) { |
| if (rates_tlv == NULL) { |
| printf("ERR:No rates found\n"); |
| return UAP_FAILURE; |
| } |
| if (enable_11n) { |
| printf("ERR:11n must be disabled and the only B rates are allowed if 11d enabled and country code is JP with channel 14.\n"); |
| return UAP_FAILURE; |
| } |
| for (i = 0; i < op_rates_len; i++) { |
| rate = rates_tlv-> |
| operational_rates[i] & ~BASIC_RATE_SET_BIT; |
| switch (rate) { |
| case 2: |
| case 4: |
| case 11: |
| case 22: |
| break; |
| default: |
| printf("ERR:If 11d enabled, channel 14 and country code is JP, the only B rates are allowed.\n"); |
| return UAP_FAILURE; |
| } |
| } |
| } |
| |
| /* Channels 14, 165 are not allowed to operate in 40MHz mode */ |
| if (!acs_mode_enabled && enable_40Mhz) { |
| if ((channel == 14) |
| || (channel == 165) |
| ) { |
| printf("ERR:Invalid channel %d for 40MHz operation\n", |
| channel); |
| return UAP_FAILURE; |
| } else if (!secondary_ch_set) { |
| printf("ERR:Secondary channel should be set when 40Mhz is enabled!\n"); |
| return UAP_FAILURE; |
| } |
| } |
| /* Channels 14, 140, 165 are not allowed to operate in 40MHz mode */ |
| if (acs_mode_enabled && enable_40Mhz) { |
| if (chnlist_tlv == NULL) { |
| printf("ERR: No channel list found\n"); |
| return UAP_FAILURE; |
| } |
| pchan_list = (channel_list *) & (chnlist_tlv->chan_list); |
| for (i = 0; i < chan_list_len; i++) { |
| if ((pchan_list->chan_number != 14) |
| && (pchan_list->chan_number != 140) && |
| (pchan_list->chan_number != 165) |
| ) { |
| flag = 1; |
| break; |
| } |
| pchan_list++; |
| } |
| if (!flag) { |
| printf("ERR:Invalid channels in scan channel list for 40MHz operation\n"); |
| return UAP_FAILURE; |
| } |
| } |
| |
| if (0 == get_fw_info(&fw)) { |
| /*check whether support 802.11AC through BAND_AAC bit */ |
| if (fw.fw_bands & BAND_AAC) { |
| ret = get_802_11ac_cfg(&vhtcfg); |
| if (UAP_SUCCESS == ret) { |
| /* Note: When 11AC is disabled, FW sets vht_rx_mcs to 0xffff */ |
| if ((vhtcfg.vht_rx_mcs != 0xffff) && |
| (!enable_11n)) { |
| printf("ERR: 11ac enable while 11n disable, it is forbidden! \n"); |
| return UAP_FAILURE; |
| } |
| } else { |
| printf("Don't support 802.11AC \n"); |
| return UAP_SUCCESS; |
| } |
| } else |
| printf("No support 802 11AC.\n"); |
| } else { |
| printf("ERR: get_fw_info fail\n"); |
| return UAP_FAILURE; |
| } |
| |
| return ret; |
| } |
| |
| /** |
| * @brief Checks current bss configuration |
| * |
| * @param buf pointer to bss_config_t |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| check_bss_config(t_u8 *buf) |
| { |
| bss_config_t *bss_config = NULL;; |
| t_u8 acs_mode_enabled = 0; |
| t_u8 *cbuf = NULL; |
| apcmdbuf_cfg_80211d *cmd_buf = NULL; |
| t_u16 buf_len, cmd_len; |
| char country_80211d[4] = { 'U', 'S', ' ', 0 }; |
| t_u8 state_80211h = 0; |
| int channel_tlv_band = BAND_B | BAND_G; |
| t_u8 secondary_ch_set = 0; |
| int scan_channels_band = BAND_B | BAND_G; |
| t_u8 state_80211d = 0; |
| t_u8 rate = 0; |
| t_u32 rate_bitmap = 0; |
| t_u16 enable_40Mhz = 0; |
| t_u16 enable_20Mhz_sgi = 0; |
| t_u16 enable_gf = 0; |
| t_u8 enable_11n = 0; |
| int flag = 0; |
| fw_info fw; |
| int i = 0, ret = UAP_SUCCESS; |
| tx_rate_cfg_t tx_rate_config; |
| t_u32 mcs_rate_index = 0; |
| struct eth_priv_vhtcfg vhtcfg = { 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 |
| |
| if (NULL == buf) { |
| printf("ERR: No buffer for bss_configure!\n"); |
| return UAP_FAILURE; |
| } |
| |
| bss_config = (bss_config_t *)buf; |
| |
| ret = sg_snmp_mib(ACTION_GET, OID_80211D_ENABLE, sizeof(state_80211d), |
| &state_80211d); |
| |
| buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| cbuf = (t_u8 *)malloc(buf_len); |
| if (!cbuf) { |
| printf("ERR:Cannot allocate buffer from command!\n"); |
| return UAP_FAILURE; |
| } |
| memset(cbuf, 0, buf_len); |
| /* Locate headers */ |
| cmd_buf = (apcmdbuf_cfg_80211d *)cbuf; |
| cmd_len = (sizeof(apcmdbuf_cfg_80211d) - sizeof(domain_param_t)); |
| cmd_buf->size = cmd_len - BUF_HEADER_SIZE; |
| cmd_buf->action = uap_cpu_to_le16(ACTION_GET); |
| cmd_buf->cmd_code = HostCmd_CMD_802_11D_DOMAIN_INFO; |
| ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); |
| if (ret == UAP_SUCCESS && cmd_buf->result == CMD_SUCCESS) { |
| if (cmd_buf->domain.country_code[0] || |
| cmd_buf->domain.country_code[1] || |
| cmd_buf->domain.country_code[2]) { |
| strncpy(country_80211d, |
| (char *)cmd_buf->domain.country_code, |
| COUNTRY_CODE_LEN); |
| } |
| } |
| free(cbuf); |
| |
| /* get region code to handle special cases */ |
| memset(&fw, 0, sizeof(fw)); |
| if (get_fw_info(&fw)) { |
| printf("Could not get fw info!\n"); |
| return UAP_FAILURE; |
| } |
| |
| if (get_tx_rate_cfg(&tx_rate_config) == UAP_FAILURE) { |
| printf("Could not get tx_rate_cfg!\n"); |
| return UAP_FAILURE; |
| } |
| |
| if ((fw.fw_bands & (BAND_B | BAND_G | BAND_GN | BAND_GAC)) |
| && !(fw.fw_bands & (BAND_A | BAND_AAC)) |
| ) { |
| if (bss_config->channel > MAX_CHANNELS_BG) { |
| printf("ERR: Invalid channel in 2.4GHz band!\n"); |
| return UAP_FAILURE; |
| } |
| } |
| |
| if (!(fw.fw_bands & (BAND_B | BAND_G |
| | BAND_GN |
| | BAND_GAC)) && (fw.fw_bands & (BAND_A |
| | BAND_AAC))) { |
| if (bss_config->channel < 36 || |
| bss_config->channel > MAX_CHANNELS) { |
| printf("ERR: Invalid channel in 5GHz band!\n"); |
| return UAP_FAILURE; |
| } |
| } |
| |
| if ((!state_80211d) && (bss_config->channel == MAX_CHANNELS_BG) |
| && (strncmp(country_80211d, "JP", COUNTRY_CODE_LEN - 1) == 0) |
| ) { |
| printf("ERR: Invalid channel 14, 802.11d disabled, country code JP!\n"); |
| return UAP_FAILURE; |
| } |
| |
| if (bss_config->bandcfg.chanBand == BAND_5GHZ) |
| channel_tlv_band = BAND_A; |
| |
| secondary_ch_set = bss_config->bandcfg.chan2Offset; |
| if (channel_tlv_band != BAND_A) { |
| /* When country code is not Japan, allow channels 5-11 for US and 5-13 for non-US |
| * only for secondary channel below */ |
| if (secondary_ch_set == SEC_CHAN_BELOW) { |
| if (!strncmp |
| (country_80211d, "US", COUNTRY_CODE_LEN - 1)) { |
| if (bss_config->channel > |
| DEFAULT_MAX_CHANNEL_BELOW) { |
| printf("ERR: Only channels 5-11 are allowed with secondary channel below for the US\n"); |
| return UAP_FAILURE; |
| } |
| } else if (strncmp |
| (country_80211d, "JP", |
| COUNTRY_CODE_LEN - 1)) { |
| if (bss_config->channel > |
| DEFAULT_MAX_CHANNEL_BELOW_NON_US) { |
| printf("ERR: Only channels 5-13 are allowed with secondary channel below for" "non-Japan countries!\n"); |
| return UAP_FAILURE; |
| } |
| } |
| } |
| |
| /* When country code is not Japan, allow channels 1-7 for US and 1-9 for non-US |
| * only for secondary channel above */ |
| if (secondary_ch_set == SEC_CHAN_ABOVE) { |
| if (!strncmp |
| (country_80211d, "US", COUNTRY_CODE_LEN - 1)) { |
| if (bss_config->channel > |
| DEFAULT_MAX_CHANNEL_ABOVE) { |
| printf("ERR: Only channels 1-7 are allowed with secondary channel above for the US\n"); |
| return UAP_FAILURE; |
| } |
| } else if (strncmp |
| (country_80211d, "JP", |
| COUNTRY_CODE_LEN - 1)) { |
| if (bss_config->channel > |
| DEFAULT_MAX_CHANNEL_ABOVE_NON_US) { |
| printf("ERR: Only channels 1-9 are allowed with secondary channel above for" "non-Japan countries!\n"); |
| return UAP_FAILURE; |
| } |
| } |
| } |
| } |
| |
| if (!(bss_config->bandcfg.scanMode == SCAN_MODE_ACS)) { |
| if (check_channel_validity_11d |
| (bss_config->channel, channel_tlv_band, 1) == UAP_FAILURE) |
| return UAP_FAILURE; |
| if (state_80211d) { |
| /* Set country code to JP if channel is 8 or 12 and band is 5GHZ */ |
| if ((bss_config->channel < MAX_CHANNELS_BG) && |
| (channel_tlv_band == BAND_A)) |
| strncpy(country_80211d, "JP ", |
| sizeof(country_80211d) - 1); |
| } else { |
| if ((channel_tlv_band == BAND_A) && |
| ((bss_config->channel == 8) || |
| (bss_config->channel == 12))) { |
| printf("ERR:Invalid band for given channel\n"); |
| return UAP_FAILURE; |
| } |
| } |
| } else { |
| acs_mode_enabled = 1; |
| } |
| |
| #define JP_REGION_0xFE 0xFE |
| if (fw.region_code == JP_REGION_0xFE && |
| ((bss_config->channel == 12) || (bss_config->channel == 13))) { |
| printf("ERR:Channel 12 or 13 is not allowed for region code 0xFE\n"); |
| return UAP_FAILURE; |
| } |
| |
| for (i = 0; i < bss_config->num_of_chan; i++) { |
| scan_channels_band = BAND_B | BAND_G; |
| if ((scan_channels_band != BAND_A) && |
| (bss_config->chan_list[i].bandcfg.chanBand == BAND_5GHZ)) { |
| scan_channels_band = BAND_A; |
| } |
| if (check_channel_validity_11d |
| (bss_config->chan_list[i].chan_number, scan_channels_band, |
| 0) == UAP_FAILURE) |
| return UAP_FAILURE; |
| } |
| |
| if (state_80211d) { |
| if (check_tx_pwr_validity_11d(bss_config->tx_power_level) == |
| UAP_FAILURE) |
| return UAP_FAILURE; |
| } |
| |
| if (bss_config->supported_mcs_set[0]) { |
| enable_11n = 1; |
| enable_40Mhz = IS_11N_40MHZ_ENABLED(bss_config->ht_cap_info); |
| enable_20Mhz_sgi = |
| IS_11N_20MHZ_SHORTGI_ENABLED(bss_config->ht_cap_info); |
| enable_gf = IS_11N_GF_ENABLED(bss_config->ht_cap_info); |
| } |
| |
| if (bss_config->mcbc_data_rate && |
| (is_mcbc_rate_valid(bss_config->mcbc_data_rate) != UAP_SUCCESS)) { |
| printf("ERR: Invalid MCBC Data Rate \n"); |
| return UAP_FAILURE; |
| } |
| |
| if ((bss_config->protocol == PROTOCOL_STATIC_WEP) |
| && (0 == bss_config->wep_cfg.key0.is_default) |
| && (0 == bss_config->wep_cfg.key1.is_default) |
| && (0 == bss_config->wep_cfg.key2.is_default) |
| && (0 == bss_config->wep_cfg.key3.is_default)) { |
| printf("ERR:WEP keys not set!\n"); |
| return UAP_FAILURE; |
| } |
| |
| if ((bss_config->auth_mode == 1) && |
| (bss_config->protocol != PROTOCOL_STATIC_WEP)) { |
| printf("ERR:Shared key authentication is not allowed for Open/WPA/WPA2/Mixed mode\n"); |
| return UAP_FAILURE; |
| } |
| |
| if (((bss_config->protocol == PROTOCOL_WPA) || |
| (bss_config->protocol == PROTOCOL_WPA2) |
| || (bss_config->protocol == PROTOCOL_WPA2_MIXED)) && |
| !(bss_config->wpa_cfg.length)) { |
| printf("ERR:Passphrase must be set for WPA/WPA2/Mixed mode\n"); |
| return UAP_FAILURE; |
| } |
| |
| if ((bss_config->protocol == PROTOCOL_WPA) || |
| (bss_config->protocol == PROTOCOL_WPA2_MIXED)) { |
| if (is_cipher_valid |
| (bss_config->wpa_cfg.pairwise_cipher_wpa, |
| bss_config->wpa_cfg.group_cipher) != UAP_SUCCESS) { |
| printf("ERR:Wrong group cipher and WPA pairwise cipher combination!\n"); |
| return UAP_FAILURE; |
| } |
| } |
| if ((bss_config->protocol == PROTOCOL_WPA2) || |
| (bss_config->protocol == PROTOCOL_WPA2_MIXED)) { |
| if (is_cipher_valid |
| (bss_config->wpa_cfg.pairwise_cipher_wpa2, |
| bss_config->wpa_cfg.group_cipher) != UAP_SUCCESS) { |
| printf("ERR:Wrong group cipher and WPA2 pairwise cipher combination!\n"); |
| return UAP_FAILURE; |
| } |
| } |
| |
| if (0 == bss_config->num_of_chan) { |
| printf("ERR: No channel list found\n"); |
| return UAP_FAILURE; |
| } |
| |
| if (acs_mode_enabled) { |
| for (i = 0; i < bss_config->num_of_chan; i++) { |
| if ((!state_80211d) && |
| (bss_config->chan_list[i].chan_number == |
| MAX_CHANNELS_BG) |
| && |
| (strncmp(country_80211d, "JP", COUNTRY_CODE_LEN - 1) |
| == 0) |
| ) { |
| printf("ERR: Invalid scan channel 14, 802.11d disabled, country code JP!\n"); |
| return UAP_FAILURE; |
| } |
| |
| if (fw.region_code == JP_REGION_0xFE && |
| ((bss_config->chan_list[i].chan_number == 12) || |
| (bss_config->chan_list[i].chan_number == 13))) { |
| printf("ERR:Scan Channel 12 or 13 is not allowed for region code 0xFE\n"); |
| return UAP_FAILURE; |
| } |
| } |
| |
| if (!state_80211d) { |
| /* Block scan channels 8 and 12 in 5GHz band if 11d is not enabled and country code not set to JP */ |
| for (i = 0; i < bss_config->num_of_chan; i++) { |
| if ((bss_config->chan_list[i].bandcfg. |
| chanBand == BAND_5GHZ) |
| && |
| ((bss_config->chan_list[i].chan_number == 8) |
| || (bss_config->chan_list[i].chan_number == |
| 12))) { |
| printf("ERR: Invalid band for scan channel %d\n", bss_config->chan_list[i].chan_number); |
| return UAP_FAILURE; |
| } |
| } |
| } |
| |
| if (state_80211d) { |
| /* Set default country code to US */ |
| strncpy(country_80211d, "US ", |
| sizeof(country_80211d) - 1); |
| for (i = 0; i < bss_config->num_of_chan; i++) { |
| /* Set country code to JP if channel is 8 or 12 and band is 5GHZ */ |
| if ((bss_config->chan_list[i].chan_number < |
| MAX_CHANNELS_BG) && |
| (scan_channels_band == BAND_A)) { |
| strncpy(country_80211d, "JP ", |
| sizeof(country_80211d) - 1); |
| } |
| if (check_channel_validity_11d |
| (bss_config->chan_list[i].chan_number, |
| scan_channels_band, 0) == UAP_FAILURE) |
| return UAP_FAILURE; |
| } |
| if (update_domain_info |
| (country_80211d, |
| scan_channels_band) == UAP_FAILURE) { |
| return UAP_FAILURE; |
| } |
| } |
| } |
| #ifdef WIFI_DIRECT_SUPPORT |
| if (strncmp(dev_name, "wfd", 3)) |
| #endif |
| if ((!acs_mode_enabled && |
| (channel_tlv_band == (BAND_B | BAND_G))) |
| || (acs_mode_enabled && |
| (scan_channels_band == (BAND_B | BAND_G)))) { |
| if (0 == bss_config->rates[0]) { |
| printf("ERR: No rates found\n"); |
| return UAP_FAILURE; |
| } |
| for (i = 0; i < MAX_DATA_RATES && bss_config->rates[i]; |
| i++) { |
| rate = bss_config-> |
| rates[i] & ~BASIC_RATE_SET_BIT; |
| switch (rate) { |
| 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; |
| } |
| } |
| if ((rate_bitmap & B_RATE_MANDATORY) != |
| B_RATE_MANDATORY) { |
| if (acs_mode_enabled) |
| printf("ERR: Rates/Scan channels do not match!\n"); |
| else |
| printf("ERR: Rates/Channel do not match!\n"); |
| return UAP_FAILURE; |
| } |
| } |
| if ((!acs_mode_enabled && (channel_tlv_band == BAND_A)) |
| || (acs_mode_enabled && (scan_channels_band == BAND_A))) { |
| if (0 == bss_config->rates[0]) { |
| printf("ERR: No rates found\n"); |
| return UAP_FAILURE; |
| } |
| for (i = 0; i < MAX_DATA_RATES && bss_config->rates[i]; i++) { |
| rate = bss_config->rates[i] & ~BASIC_RATE_SET_BIT; |
| switch (rate) { |
| case 2: |
| case 4: |
| case 11: |
| case 22: |
| if (acs_mode_enabled) |
| printf("ERR: Rates/Scan channels do not match!\n"); |
| else |
| printf("ERR: Rates/Channel do not match!\n"); |
| return UAP_FAILURE; |
| } |
| } |
| state_80211h = 1; |
| if (sg_snmp_mib |
| (ACTION_SET, OID_80211H_ENABLE, sizeof(state_80211h), |
| &state_80211h) |
| == UAP_FAILURE) { |
| return UAP_FAILURE; |
| } |
| if (update_domain_info(country_80211d, BAND_A) == UAP_FAILURE) { |
| return UAP_FAILURE; |
| } |
| } |
| #define ISSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap & MBIT(17)) |
| #define ISSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap & MBIT(24)) |
| |
| if (enable_40Mhz) { |
| if (!ISSUPP_CHANWIDTH40(fw.hw_dot_11n_dev_cap)) { |
| printf("ERR: It's not support HT40 from Hardware Cap\n"); |
| return UAP_FAILURE; |
| } |
| } |
| |
| if (enable_11n) { |
| /*For protocol = Mixed, 11n enabled, only allow TKIP cipher for WPA protocol, not for WPA2 */ |
| if ((bss_config->protocol == PROTOCOL_WPA2_MIXED) && |
| (bss_config->wpa_cfg.pairwise_cipher_wpa2 == CIPHER_TKIP)) { |
| printf("ERR: WPA2 pairwise cipher cannot be TKIP when AP operates in 802.11n Mixed mode.\n"); |
| return UAP_FAILURE; |
| } else if (bss_config->protocol == PROTOCOL_STATIC_WEP) { |
| printf("ERR: WEP cannot be used when AP operates in 802.11n mode.\n"); |
| return UAP_FAILURE; |
| } |
| } |
| if ((tx_rate_config.rate == UAP_RATE_INDEX_MCS32) && !enable_40Mhz) { |
| printf("ERR:uAP must be configured to operate in 40MHz if tx_rate is MCS32\n"); |
| return UAP_FAILURE; |
| } |
| if (enable_20Mhz_sgi && enable_gf) { |
| if ((tx_rate_config.rate >= UAP_RATE_INDEX_MCS0) && |
| (tx_rate_config.rate <= UAP_RATE_INDEX_MCS7)) { |
| printf("ERR: Invalid tx_rate for uAP in (20MHz Short GI + Green Field) mode\n"); |
| return UAP_FAILURE; |
| } |
| } |
| mcs_rate_index = |
| get_rate_index_from_bitmap(tx_rate_config.bitmap_rates, |
| sizeof(tx_rate_config.bitmap_rates)); |
| if ((mcs_rate_index >= UAP_RATE_BITMAP_MCS0) && |
| (mcs_rate_index <= UAP_RATE_BITMAP_MCS127)) { |
| mcs_rate_index -= (UAP_RATE_BITMAP_MCS0 - UAP_RATE_INDEX_MCS0); |
| if ((mcs_rate_index == UAP_RATE_INDEX_MCS32) & !enable_40Mhz) { |
| printf("ERR:uAP must be configured to operate in 40MHz if rate_bitmap contains MCS32\n"); |
| return UAP_FAILURE; |
| } |
| if (enable_20Mhz_sgi && enable_gf) { |
| if ((mcs_rate_index >= UAP_RATE_INDEX_MCS0) && |
| (mcs_rate_index <= UAP_RATE_INDEX_MCS7)) { |
| printf("ERR: Invalid tx_rate for uAP in (20MHz Short GI + Green Field) mode\n"); |
| return UAP_FAILURE; |
| } |
| } |
| } |
| |
| /* if 11d enabled, Channel 14, country code "JP", only B rates are allowed*/ |
| if ((bss_config->channel == 14) && state_80211d && |
| (strncmp(country_80211d, "JP", COUNTRY_CODE_LEN - 1) == 0)) { |
| if (0 == bss_config->rates[0]) { |
| printf("ERR:No rates found\n"); |
| return UAP_FAILURE; |
| } |
| if (enable_11n) { |
| printf("ERR:11n must be disabled and the only B rates are allowed if 11d enabled and country code is JP with channel 14.\n"); |
| return UAP_FAILURE; |
| } |
| for (i = 0; i < MAX_DATA_RATES && bss_config->rates[i]; i++) { |
| rate = bss_config->rates[i] & ~BASIC_RATE_SET_BIT; |
| switch (rate) { |
| case 2: |
| case 4: |
| case 11: |
| case 22: |
| break; |
| default: |
| printf("ERR:If 11d enabled, channel 14 and country code is JP, the only B rates are allowed.\n"); |
| return UAP_FAILURE; |
| } |
| } |
| } |
| |
| /* Channels 14, 165 are not allowed to operate in 40MHz mode */ |
| if (!acs_mode_enabled && enable_40Mhz) { |
| if ((bss_config->channel == 14) |
| || (bss_config->channel == 165) |
| ) { |
| printf("ERR:Invalid channel %d for 40MHz operation\n", |
| bss_config->channel); |
| return UAP_FAILURE; |
| } else if (!secondary_ch_set) { |
| printf("ERR:Secondary channel should be set when 40Mhz is enabled!\n"); |
| return UAP_FAILURE; |
| } |
| } |
| /* Channels 14, 140, 165 are not allowed to operate in 40MHz mode */ |
| if (acs_mode_enabled && enable_40Mhz) { |
| if (bss_config->num_of_chan == 0) { |
| printf("ERR: No channel list found\n"); |
| return UAP_FAILURE; |
| } |
| for (i = 0; i < bss_config->num_of_chan; i++) { |
| if ((bss_config->chan_list[i].chan_number != 14) |
| && (bss_config->chan_list[i].chan_number != 140) && |
| (bss_config->chan_list[i].chan_number != 165) |
| ) { |
| flag = 1; |
| break; |
| } |
| } |
| if (!flag) { |
| printf("ERR:Invalid channels in scan channel list for 40MHz operation\n"); |
| return UAP_FAILURE; |
| } |
| } |
| |
| if (0 == get_fw_info(&fw)) { |
| /*check whether support 802.11AC through BAND_AAC bit */ |
| if (fw.fw_bands & BAND_AAC) { |
| ret = get_802_11ac_cfg(&vhtcfg); |
| if (UAP_SUCCESS == ret) { |
| /* Note: When 11AC is disabled, FW sets vht_rx_mcs to 0xffff */ |
| if ((vhtcfg.vht_rx_mcs != 0xffff) && |
| (!enable_11n)) { |
| printf("ERR: 11ac enable while 11n disable, it is forbidden! \n"); |
| return UAP_FAILURE; |
| } |
| } else { |
| printf("Don't support 802.11AC \n"); |
| return UAP_SUCCESS; |
| } |
| } else |
| printf("No support 802 11AC.\n"); |
| } else { |
| printf("ERR: get_fw_info fail\n"); |
| return UAP_FAILURE; |
| } |
| |
| return ret; |
| } |
| |
| /** |
| * @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, char *offset, char *strvalue) |
| { |
| apcmdbuf_reg_rdwr *cmd_buf = NULL; |
| t_u8 *buf = NULL; |
| t_u16 cmd_len = 0; |
| t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| int ret = UAP_SUCCESS; |
| char *whichreg; |
| |
| /* Alloc buf for command */ |
| buf = (t_u8 *)malloc(buf_len); |
| if (!buf) { |
| printf("ERR:Cannot allocate buffer for command!\n"); |
| return UAP_FAILURE; |
| } |
| memset(buf, 0, 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->seq_num = 0; |
| cmd_buf->result = 0; |
| |
| switch (reg) { |
| case CMD_MAC: |
| whichreg = "MAC"; |
| cmd_buf->cmd_code = HostCmd_CMD_MAC_REG_ACCESS; |
| break; |
| case CMD_BBP: |
| whichreg = "BBP"; |
| cmd_buf->cmd_code = HostCmd_CMD_BBP_REG_ACCESS; |
| break; |
| case CMD_RF: |
| cmd_buf->cmd_code = 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((t_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%08x\n", |
| whichreg, uap_le16_to_cpu(cmd_buf->offset), |
| uap_le32_to_cpu(cmd_buf->value)); |
| } else { |
| printf("ERR:Command sending failed!\n"); |
| free(buf); |
| return UAP_FAILURE; |
| } |
| } else { |
| printf("ERR:Command sending failed!\n"); |
| free(buf); |
| return UAP_FAILURE; |
| } |
| |
| free(buf); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Send read command for EEPROM |
| * |
| * Usage: "Usage : rdeeprom <offset> <byteCount>" |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_read_eeprom(int argc, char *argv[]) |
| { |
| apcmdbuf_eeprom_access *cmd_buf = NULL; |
| t_u8 *buf = NULL; |
| t_u16 cmd_len = 0; |
| t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| t_u16 byte_count, offset; |
| int ret = UAP_SUCCESS; |
| int opt; |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_apcmd_read_eeprom_usage(); |
| return UAP_FAILURE; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| /* Check arguments */ |
| if (!argc || |
| (argc && is_input_valid(RDEEPROM, argc, argv) != UAP_SUCCESS)) { |
| print_apcmd_read_eeprom_usage(); |
| return UAP_FAILURE; |
| } |
| offset = A2HEXDECIMAL(argv[0]); |
| byte_count = A2HEXDECIMAL(argv[1]); |
| |
| buf = (t_u8 *)malloc(buf_len); |
| if (!buf) { |
| printf("ERR:Cannot allocate buffer from command!\n"); |
| return UAP_FAILURE; |
| } |
| memset(buf, 0, 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->seq_num = 0; |
| cmd_buf->action = 0; |
| |
| cmd_buf->cmd_code = HostCmd_EEPROM_ACCESS; |
| cmd_buf->offset = uap_cpu_to_le16(offset); |
| cmd_buf->byte_count = uap_cpu_to_le16(byte_count); |
| |
| /* Send the command */ |
| ret = uap_ioctl((t_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"); |
| byte_count = uap_le16_to_cpu(cmd_buf->byte_count); |
| offset = uap_le16_to_cpu(cmd_buf->offset); |
| hexdump_data("EEPROM", (void *)cmd_buf->value, |
| byte_count, ' '); |
| } else { |
| printf("ERR:Command Response incorrect!\n"); |
| ret = UAP_FAILURE; |
| } |
| } else { |
| printf("ERR:Command sending failed!\n"); |
| } |
| |
| free(buf); |
| return ret; |
| } |
| |
| /** |
| * @brief Show usage information for the regrdwr command |
| * command |
| * |
| * $return N/A |
| */ |
| void |
| print_regrdwr_usage(void) |
| { |
| printf("\nUsage : uaputl.exe regrdwr <TYPE> <OFFSET> [value]\n"); |
| printf("\nTYPE Options: 1 - read/write MAC register"); |
| printf("\n 2 - read/write BBP register"); |
| printf("\n 3 - 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 UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_regrdwr(int argc, char *argv[]) |
| { |
| int opt; |
| t_s32 reg; |
| int ret = UAP_SUCCESS; |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_regrdwr_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| /* Check arguments */ |
| if ((argc < 2) || (argc > 3)) { |
| printf("ERR:wrong arguments.\n"); |
| print_regrdwr_usage(); |
| return UAP_FAILURE; |
| } |
| if ((atoi(argv[0]) != 1) && (atoi(argv[0]) != 2) && |
| (atoi(argv[0]) != 3)) { |
| printf("ERR:Illegal register type %s. Must be either '1','2' or '3'.\n", argv[0]); |
| print_regrdwr_usage(); |
| return UAP_FAILURE; |
| } |
| reg = atoi(argv[0]); |
| ret = apcmd_regrdwr_process(reg, argv[1], argc > 2 ? argv[2] : NULL); |
| return ret; |
| } |
| |
| /** |
| * @brief Show usage information for the memaccess command |
| * command |
| * |
| * $return N/A |
| */ |
| void |
| print_memaccess_usage(void) |
| { |
| printf("\nUsage : uaputl.exe memaccess <ADDRESS> [value]\n"); |
| printf("\nRead/Write memory location"); |
| printf("\nADDRESS: Address of the memory location to be read/written"); |
| printf("\nValue : Value to be written at that address\n"); |
| return; |
| } |
| |
| /** |
| * @brief Provides interface to perform read/write memory location |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_memaccess(int argc, char *argv[]) |
| { |
| int opt; |
| apcmdbuf_mem_access *cmd_buf = NULL; |
| t_u8 *buf = NULL; |
| t_u16 cmd_len = 0; |
| t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| int ret = UAP_SUCCESS; |
| char *address = NULL; |
| char *value = NULL; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_memaccess_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| /* Check arguments */ |
| if ((argc < 1) || (argc > 2)) { |
| printf("ERR:wrong arguments.\n"); |
| print_memaccess_usage(); |
| return UAP_FAILURE; |
| } |
| |
| address = argv[0]; |
| if (argc == 2) |
| value = argv[1]; |
| |
| /* Alloc buf for command */ |
| buf = (t_u8 *)malloc(buf_len); |
| |
| if (!buf) { |
| printf("ERR:Cannot allocate buffer from command!\n"); |
| return UAP_FAILURE; |
| } |
| memset(buf, 0, 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->seq_num = 0; |
| cmd_buf->result = 0; |
| cmd_buf->cmd_code = 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((t_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%04x] = 0x%08x\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 UAP_FAILURE; |
| } |
| } else { |
| printf("ERR:Command sending failed!\n"); |
| free(buf); |
| return UAP_FAILURE; |
| } |
| free(buf); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Show usage information for the bss_config command |
| * |
| * $return N/A |
| */ |
| void |
| print_bss_config_usage(void) |
| { |
| printf("\nUsage : bss_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 containing all the BSS settings.\n"); |
| return; |
| } |
| |
| /** |
| * @brief Read the BSS profile and populate structure |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @param bss Pointer to BSS configuration buffer |
| * @return UAP_SUCCESS or UAP_FAILURE |
| */ |
| int |
| parse_bss_config(int argc, char *argv[], bss_config_t *bss) |
| { |
| 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_ap_mac_filter = 0; |
| int keyindex = -1; |
| int pwkcipher_wpa = -1; |
| int pwkcipher_wpa2 = -1; |
| int gwkcipher = -1; |
| int protocol = -1; |
| int tx_data_rate = -1; |
| int tx_beacon_rate = -1; |
| int mcbc_data_rate = -1; |
| int num_rates = 0; |
| int found = 0; |
| int filter_mac_count = -1; |
| int retval = UAP_SUCCESS; |
| int chan_mode = 0; |
| int band_flag = 0; |
| int chan_number = 0; |
| t_u16 max_sta_num_supported = 0; |
| fw_info fw; |
| HTCap_t htcap; |
| int enable_11n = -1; |
| t_u32 supported_mcs_set = 0; |
| int ac = 0; |
| int is_wmm_parameters = 0; |
| char oui_type[4] = { 0x00, 0x50, 0xf2, 0x02 }; |
| struct eth_priv_vhtcfg vhtcfg = { 0 }; |
| |
| /* Check if file exists */ |
| config_file = fopen(argv[0], "r"); |
| if (config_file == NULL) { |
| printf("\nERR:Config file can not open.\n"); |
| return UAP_FAILURE; |
| } |
| line = (char *)malloc(MAX_CONFIG_LINE); |
| if (!line) { |
| printf("ERR:Cannot allocate memory for line\n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| memset(line, 0, 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 ((!bss->rates[0]) && (tx_data_rate) |
| && |
| (is_tx_rate_valid |
| ((t_u8)tx_data_rate) != |
| UAP_SUCCESS)) { |
| printf("ERR: Invalid Tx Data Rate \n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| if (bss->rates[0] && tx_data_rate) { |
| for (i = 0; bss->rates[i] != 0; |
| i++) { |
| if ((bss-> |
| rates[i] & |
| ~BASIC_RATE_SET_BIT) |
| == tx_data_rate) { |
| found = 1; |
| break; |
| } |
| } |
| if (!found) { |
| printf("ERR: Invalid Tx Data Rate \n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| } |
| |
| /* Set Tx data rate field */ |
| bss->tx_data_rate = tx_data_rate; |
| } |
| if (tx_beacon_rate != -1) { |
| if ((!bss->rates[0]) && (tx_beacon_rate) |
| && |
| (is_tx_rate_valid |
| ((t_u8)tx_beacon_rate) != |
| UAP_SUCCESS)) { |
| printf("ERR: Invalid Tx Beacon Rate \n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| if (bss->rates[0] && tx_beacon_rate) { |
| for (i = 0; bss->rates[i] != 0; |
| i++) { |
| if ((bss-> |
| rates[i] & |
| ~BASIC_RATE_SET_BIT) |
| == tx_beacon_rate) { |
| found = 1; |
| break; |
| } |
| } |
| if (!found) { |
| printf("ERR: Invalid Tx Beacon Rate \n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| } |
| |
| /* Set Tx beacon rate field */ |
| bss->tx_beacon_rate = tx_beacon_rate; |
| } |
| if (mcbc_data_rate != -1) { |
| if ((!bss->rates[0]) && (mcbc_data_rate) |
| && |
| (is_mcbc_rate_valid |
| ((t_u8)mcbc_data_rate) != |
| UAP_SUCCESS)) { |
| printf("ERR: Invalid Tx Data Rate \n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| if (bss->rates[0] && mcbc_data_rate) { |
| for (i = 0; bss->rates[i] != 0; |
| i++) { |
| if (bss-> |
| rates[i] & |
| BASIC_RATE_SET_BIT) |
| { |
| if ((bss-> |
| rates[i] & |
| ~BASIC_RATE_SET_BIT) |
| == |
| mcbc_data_rate) |
| { |
| found = 1; |
| break; |
| } |
| } |
| } |
| if (!found) { |
| printf("ERR: Invalid MCBC Data Rate \n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| } |
| |
| /* Set MCBC data rate field */ |
| bss->mcbc_data_rate = mcbc_data_rate; |
| } |
| if ((protocol == PROTOCOL_STATIC_WEP) && |
| (enable_11n == 1)) { |
| printf("ERR:WEP cannot be used when AP operates in 802.11n mode.\n"); |
| goto done; |
| } |
| if (0 == get_fw_info(&fw)) { |
| /*check whether support 802.11AC through BAND_AAC bit */ |
| if (fw.fw_bands & BAND_AAC) { |
| retval = get_802_11ac_cfg |
| (&vhtcfg); |
| if (retval != UAP_SUCCESS) |
| goto done; |
| if ((enable_11n == 1) && |
| (vhtcfg.vht_rx_mcs != |
| 0xffff)) { |
| printf("ERR: 11n must be enabled when AP operates in 11ac mode.\n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| } else |
| printf("No support 802 11AC.\n"); |
| } else { |
| printf("ERR: get_fw_info fail\n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| if ((protocol == PROTOCOL_WPA2_MIXED) && |
| ((pwkcipher_wpa < 0) || |
| (pwkcipher_wpa2 < 0))) { |
| printf("ERR:Both PwkCipherWPA and PwkCipherWPA2 should be defined for Mixed mode.\n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| if (protocol != -1) { |
| bss->protocol = protocol; |
| if (protocol & |
| (PROTOCOL_WPA | PROTOCOL_WPA2)) { |
| /* Set key management field */ |
| bss->key_mgmt = KEY_MGMT_PSK; |
| bss->key_mgmt_operation = 0; |
| } |
| } |
| if (((pwkcipher_wpa >= 0) || |
| (pwkcipher_wpa2 >= 0)) && |
| (gwkcipher >= 0)) { |
| if ((protocol == PROTOCOL_WPA) || |
| (protocol == PROTOCOL_WPA2_MIXED)) { |
| if (enable_11n != -1) { |
| if (is_cipher_valid_with_11n(pwkcipher_wpa, gwkcipher, protocol, enable_11n) != UAP_SUCCESS) { |
| printf("ERR:Wrong group cipher and WPA pairwise cipher combination!\n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| } else if |
| (is_cipher_valid_with_proto |
| (pwkcipher_wpa, |
| gwkcipher, |
| protocol) != |
| UAP_SUCCESS) { |
| printf("ERR:Wrong group cipher and WPA pairwise cipher combination!\n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| } |
| if ((protocol == PROTOCOL_WPA2) || |
| (protocol == PROTOCOL_WPA2_MIXED)) { |
| if (enable_11n != -1) { |
| if (is_cipher_valid_with_11n(pwkcipher_wpa2, gwkcipher, protocol, enable_11n) != UAP_SUCCESS) { |
| printf("ERR:Wrong group cipher and WPA2 pairwise cipher combination!\n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| } else if |
| (is_cipher_valid_with_proto |
| (pwkcipher_wpa2, |
| gwkcipher, |
| protocol) != |
| UAP_SUCCESS) { |
| printf("ERR:Wrong group cipher and WPA2 pairwise cipher combination!\n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| } |
| /* Set pairwise and group cipher fields */ |
| bss->wpa_cfg.pairwise_cipher_wpa = |
| pwkcipher_wpa; |
| bss->wpa_cfg.pairwise_cipher_wpa2 = |
| pwkcipher_wpa2; |
| bss->wpa_cfg.group_cipher = gwkcipher; |
| } |
| continue; |
| } |
| } |
| |
| /* Check for beginning of AP configurations */ |
| if (strcmp(args[0], "ap_config") == 0) { |
| is_ap_config = 1; |
| 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 (bss->filter.mac_count != filter_mac_count) { |
| printf("ERR:Number of MAC address provided does not match 'Count'\n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| if (bss->filter.filter_mode && |
| (bss->filter.mac_count == 0)) { |
| printf("ERR:Filter list can not be empty for %s Filter mode\n", (bss->filter.filter_mode == 1) ? "'Allow'" : "'Block'"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| continue; |
| } |
| } |
| |
| /* Check for beginning of AP MAC address filter configurations */ |
| if (strcmp(args[0], "ap_mac_filter") == 0) { |
| is_ap_mac_filter = 1; |
| bss->filter.mac_count = 0; |
| filter_mac_count = 0; |
| 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])); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| bss->filter.filter_mode = atoi(args[1]); |
| continue; |
| } |
| if ((strcmp(args[0], "Count") == 0) && is_ap_mac_filter) { |
| bss->filter.mac_count = atoi(args[1]); |
| if ((ISDIGIT(args[1]) == 0) || |
| (bss->filter.mac_count > MAX_MAC_ONESHOT_FILTER)) { |
| printf("ERR: Illegal Count parameter.\n"); |
| retval = UAP_FAILURE; |
| 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], |
| bss->filter.mac_list[filter_mac_count]) != |
| UAP_SUCCESS) { |
| printf("ERR: Invalid MAC address %s \n", |
| args[1]); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| filter_mac_count++; |
| } else { |
| printf("ERR: Filter table can not have more than %d MAC addresses\n", MAX_MAC_ONESHOT_FILTER); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| } |
| |
| /* Check for end of Wmm Parameters configurations */ |
| if (is_wmm_parameters == 1) { |
| if (strcmp(args[0], "}") == 0) { |
| is_wmm_parameters = 0; |
| continue; |
| } |
| } |
| /* Check for beginning of Sticky Tim Sta MAC address Configurations */ |
| if (strcmp(args[0], "Wmm_parameters") == 0) { |
| is_wmm_parameters = 1; |
| memset(&(bss->wmm_para), 0, sizeof(bss->wmm_para)); |
| memcpy(bss->wmm_para.ouitype, oui_type, |
| sizeof(oui_type)); |
| bss->wmm_para.ouisubtype = 1; |
| bss->wmm_para.version = 1; |
| continue; |
| } |
| if ((strcmp(args[0], "Qos_info") == 0) && is_wmm_parameters) { |
| bss->wmm_para.qos_info = A2HEXDECIMAL(args[1]); |
| printf("wmm_para.qos_info = %2x\n", |
| bss->wmm_para.qos_info); |
| if ((bss->wmm_para.qos_info != ENABLE_WMM_PS) && |
| (bss->wmm_para.qos_info != DISABLE_WMM_PS)) { |
| printf("ERR:qos_info must be either 0x80 or 0x00.\n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| } |
| if ((strcmp(args[0], "AC_BE") == 0) && is_wmm_parameters) { |
| ac = 0; |
| } |
| if ((strcmp(args[0], "AC_BK") == 0) && is_wmm_parameters) { |
| ac = 1; |
| } |
| if ((strcmp(args[0], "AC_VI") == 0) && is_wmm_parameters) { |
| ac = 2; |
| } |
| if ((strcmp(args[0], "AC_VO") == 0) && is_wmm_parameters) { |
| ac = 3; |
| } |
| if ((strcmp(args[0], "Aifsn") == 0) && is_wmm_parameters) { |
| bss->wmm_para.ac_params[ac].aci_aifsn.aifsn = |
| (t_u8)A2HEXDECIMAL(args[1]); |
| printf("wmm_para.ac_params[%d].aci_aifsn.aifsn = %x\n", |
| ac, bss->wmm_para.ac_params[ac].aci_aifsn.aifsn); |
| bss->wmm_para.ac_params[ac].aci_aifsn.aci = (t_u8)ac; |
| printf("wmm_para.ac_params[%d].aci_aifsn.aci = %x\n", |
| ac, bss->wmm_para.ac_params[ac].aci_aifsn.aci); |
| } |
| if ((strcmp(args[0], "Ecw_max") == 0) && is_wmm_parameters) { |
| bss->wmm_para.ac_params[ac].ecw.ecw_max = |
| (t_u8)A2HEXDECIMAL(args[1]); |
| printf("wmm_para.ac_params[%d].ecw.ecw_max = %x\n", ac, |
| bss->wmm_para.ac_params[ac].ecw.ecw_max); |
| } |
| if ((strcmp(args[0], "Ecw_min") == 0) && is_wmm_parameters) { |
| bss->wmm_para.ac_params[ac].ecw.ecw_min = |
| (t_u8)A2HEXDECIMAL(args[1]); |
| printf("wmm_para.ac_params[%d].ecw.ecw_min = %x\n", ac, |
| bss->wmm_para.ac_params[ac].ecw.ecw_min); |
| } |
| if ((strcmp(args[0], "Tx_op") == 0) && is_wmm_parameters) { |
| bss->wmm_para.ac_params[ac].tx_op_limit = |
| (t_u8)A2HEXDECIMAL(args[1]); |
| printf("wmm_para.ac_params[%d].tx_op_limit = %x\n", ac, |
| bss->wmm_para.ac_params[ac].tx_op_limit); |
| } |
| |
| if (strcmp(args[0], "SSID") == 0) { |
| if (arg_num == 1) { |
| printf("ERR:SSID field is blank!\n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } else { |
| 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); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Set SSID field */ |
| bss->ssid.ssid_len = strlen(args[1]); |
| memcpy(bss->ssid.ssid, args[1], |
| bss->ssid.ssid_len); |
| } |
| } |
| if (strcmp(args[0], "BeaconPeriod") == 0) { |
| if (is_input_valid(BEACONPERIOD, arg_num - 1, args + 1) |
| != UAP_SUCCESS) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Set beacon period field */ |
| bss->beacon_period = (t_u16)atoi(args[1]); |
| } |
| if (strcmp(args[0], "ChanList") == 0) { |
| if (is_input_valid(SCANCHANNELS, arg_num - 1, args + 1) |
| != UAP_SUCCESS) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| |
| /* Set channel list field */ |
| if ((arg_num - 1) < MAX_CHANNELS) { |
| bss->num_of_chan = arg_num - 1; |
| } else { |
| bss->num_of_chan = MAX_CHANNELS; |
| } |
| for (i = 0; (unsigned int)i < bss->num_of_chan; i++) { |
| sscanf(args[i + 1], "%d.%d", &chan_number, |
| &band_flag); |
| bss->chan_list[i].chan_number = chan_number; |
| bss->chan_list[i].bandcfg.chanBand = BAND_2GHZ; |
| if (((band_flag != -1) && (band_flag)) || |
| (chan_number > MAX_CHANNELS_BG)) { |
| bss->chan_list[i].bandcfg.chanBand = |
| BAND_5GHZ; |
| } |
| } |
| } |
| if (strcmp(args[0], "Channel") == 0) { |
| if (is_input_valid(CHANNEL, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Set channel field */ |
| bss->channel = (t_u8)atoi(args[1]); |
| if ((arg_num - 1) == 2) { |
| chan_mode = atoi(args[2]); |
| memset(&(bss->bandcfg), 0, |
| sizeof(bss->bandcfg)); |
| if (chan_mode & BITMAP_ACS_MODE) { |
| int mode; |
| |
| if (uap_ioctl_dfs_repeater_mode(&mode) |
| == UAP_SUCCESS) { |
| if (mode) { |
| printf("ERR: ACS in DFS Repeater mode" " is not allowed\n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| } |
| |
| bss->bandcfg.scanMode = SCAN_MODE_ACS; |
| } |
| if (chan_mode & BITMAP_CHANNEL_ABOVE) |
| bss->bandcfg.chan2Offset = |
| SEC_CHAN_ABOVE; |
| if (chan_mode & BITMAP_CHANNEL_BELOW) |
| bss->bandcfg.chan2Offset = |
| SEC_CHAN_BELOW; |
| } else |
| memset(&(bss->bandcfg), 0, |
| sizeof(bss->bandcfg)); |
| if (bss->channel > MAX_CHANNELS_BG) |
| bss->bandcfg.chanBand = BAND_5GHZ; |
| } |
| if (strcmp(args[0], "Band") == 0) { |
| if (is_input_valid(BAND, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Clear previously set band */ |
| bss->bandcfg.chanBand = BAND_2GHZ; |
| if (atoi(args[1]) == 1) |
| bss->bandcfg.chanBand = BAND_5GHZ; |
| } |
| if (strcmp(args[0], "AP_MAC") == 0) { |
| int ret; |
| if ((ret = |
| mac2raw(args[1], bss->mac_addr)) != UAP_SUCCESS) { |
| printf("ERR: %s Address \n", |
| ret == |
| UAP_FAILURE ? "Invalid MAC" : ret == |
| UAP_RET_MAC_BROADCAST ? "Broadcast" : |
| "Multicast"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| } |
| |
| if (strcmp(args[0], "Rate") == 0) { |
| if (is_input_valid(RATE, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| printf("ERR: Invalid Rate input\n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Set rates field */ |
| if ((arg_num - 1) < MAX_DATA_RATES) { |
| num_rates = arg_num - 1; |
| } else { |
| num_rates = MAX_DATA_RATES; |
| } |
| for (i = 0; i < num_rates; i++) { |
| bss->rates[i] = (t_u8)A2HEXDECIMAL(args[i + 1]); |
| } |
| } |
| if (strcmp(args[0], "TxPowerLevel") == 0) { |
| if (is_input_valid(TXPOWER, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| printf("ERR:Invalid TxPowerLevel \n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Set Tx power level field */ |
| bss->tx_power_level = (t_u8)atoi(args[1]); |
| } |
| if (strcmp(args[0], "BroadcastSSID") == 0) { |
| if (is_input_valid(BROADCASTSSID, arg_num - 1, args + 1) |
| != UAP_SUCCESS) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Set broadcast SSID control field */ |
| bss->bcast_ssid_ctl = (t_u8)atoi(args[1]); |
| } |
| if (strcmp(args[0], "RTSThreshold") == 0) { |
| if (is_input_valid(RTSTHRESH, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Set RTS threshold field */ |
| bss->rts_threshold = (t_u16)atoi(args[1]); |
| } |
| if (strcmp(args[0], "FragThreshold") == 0) { |
| if (is_input_valid(FRAGTHRESH, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Set Frag threshold field */ |
| bss->frag_threshold = (t_u16)atoi(args[1]); |
| } |
| if (strcmp(args[0], "DTIMPeriod") == 0) { |
| if (is_input_valid(DTIMPERIOD, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Set DTIM period field */ |
| bss->dtim_period = (t_u8)atoi(args[1]); |
| } |
| if (strcmp(args[0], "RSNReplayProtection") == 0) { |
| if (is_input_valid(RSNREPLAYPROT, arg_num - 1, args + 1) |
| != UAP_SUCCESS) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Set RSN replay protection field */ |
| bss->wpa_cfg.rsn_protection = (t_u8)atoi(args[1]); |
| } |
| if (strcmp(args[0], "PairwiseUpdateTimeout") == 0) { |
| if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Set Pairwise Update Timeout field */ |
| bss->pairwise_update_timeout = (t_u32)atoi(args[1]); |
| } |
| if (strcmp(args[0], "PairwiseHandshakeRetries") == 0) { |
| if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Set Pairwise Hanshake Retries */ |
| bss->pwk_retries = (t_u32)atoi(args[1]); |
| } |
| if (strcmp(args[0], "GroupwiseUpdateTimeout") == 0) { |
| if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Set Groupwise Update Timeout field */ |
| bss->groupwise_update_timeout = (t_u32)atoi(args[1]); |
| } |
| if (strcmp(args[0], "GroupwiseHandshakeRetries") == 0) { |
| if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Set Groupwise Hanshake Retries */ |
| bss->gwk_retries = (t_u32)atoi(args[1]); |
| } |
| if (strcmp(args[0], "TxBeaconRate") == 0) { |
| if (is_input_valid(TXBEACONRATE, arg_num - 1, args + 1) |
| != UAP_SUCCESS) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| tx_beacon_rate = (t_u16)A2HEXDECIMAL(args[1]); |
| } |
| if (strcmp(args[0], "MCBCdataRate") == 0) { |
| if (is_input_valid(MCBCDATARATE, arg_num - 1, args + 1) |
| != UAP_SUCCESS) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| mcbc_data_rate = (t_u16)A2HEXDECIMAL(args[1]); |
| } |
| if (strcmp(args[0], "PktFwdCtl") == 0) { |
| if (is_input_valid(PKTFWD, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Set packet forward control field */ |
| bss->pkt_forward_ctl = (t_u8)atoi(args[1]); |
| } |
| if (strcmp(args[0], "StaAgeoutTimer") == 0) { |
| if (is_input_valid |
| (STAAGEOUTTIMER, arg_num - 1, |
| args + 1) != UAP_SUCCESS) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Set STA ageout timer field */ |
| bss->sta_ageout_timer = (t_u32)atoi(args[1]); |
| } |
| if (strcmp(args[0], "PSStaAgeoutTimer") == 0) { |
| if (is_input_valid |
| (PSSTAAGEOUTTIMER, arg_num - 1, |
| args + 1) != UAP_SUCCESS) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Set PS STA ageout timer field */ |
| bss->ps_sta_ageout_timer = (t_u32)atoi(args[1]); |
| } |
| if (strcmp(args[0], "AuthMode") == 0) { |
| if (is_input_valid(AUTHMODE, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Set auth mode field */ |
| bss->auth_mode = (t_u16)atoi(args[1]); |
| } |
| if (strcmp(args[0], "KeyIndex") == 0) { |
| if (arg_num == 1) { |
| printf("KeyIndex is blank!\n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } else { |
| if (ISDIGIT(args[1]) == 0) { |
| printf("ERR:Illegal KeyIndex parameter. Must be either '0', '1', '2', or '3'.\n"); |
| retval = UAP_FAILURE; |
| 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"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| switch (keyindex) { |
| case 0: |
| bss->wep_cfg.key0.is_default = 1; |
| break; |
| case 1: |
| bss->wep_cfg.key1.is_default = 1; |
| break; |
| case 2: |
| bss->wep_cfg.key2.is_default = 1; |
| break; |
| case 3: |
| bss->wep_cfg.key3.is_default = 1; |
| break; |
| } |
| } |
| } |
| if (strncmp(args[0], "Key_", 4) == 0) { |
| if (arg_num == 1) { |
| printf("ERR:%s is blank!\n", args[0]); |
| retval = UAP_FAILURE; |
| goto done; |
| } else { |
| 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"); |
| retval = UAP_FAILURE; |
| 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"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| if (UAP_FAILURE == ishexstring(args[1])) { |
| printf("ERR:Only hex digits are allowed when key length is 10 or 26\n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| key_len = strlen(args[1]) / 2; |
| } |
| /* Set WEP key fields */ |
| if (strcmp(args[0], "Key_0") == 0) { |
| bss->wep_cfg.key0.key_index = 0; |
| bss->wep_cfg.key0.length = key_len; |
| if (args[1][0] == '"') { |
| memcpy(bss->wep_cfg.key0.key, |
| &args[1][1], |
| strlen(args[1]) - 2); |
| } else { |
| string2raw(args[1], |
| bss->wep_cfg.key0. |
| key); |
| } |
| } else if (strcmp(args[0], "Key_1") == 0) { |
| bss->wep_cfg.key1.key_index = 1; |
| bss->wep_cfg.key1.length = key_len; |
| if (args[1][0] == '"') { |
| memcpy(bss->wep_cfg.key1.key, |
| &args[1][1], |
| strlen(args[1]) - 2); |
| } else { |
| string2raw(args[1], |
| bss->wep_cfg.key1. |
| key); |
| } |
| } else if (strcmp(args[0], "Key_2") == 0) { |
| bss->wep_cfg.key2.key_index = 2; |
| bss->wep_cfg.key2.length = key_len; |
| if (args[1][0] == '"') { |
| memcpy(bss->wep_cfg.key2.key, |
| &args[1][1], |
| strlen(args[1]) - 2); |
| } else { |
| string2raw(args[1], |
| bss->wep_cfg.key2. |
| key); |
| } |
| } else if (strcmp(args[0], "Key_3") == 0) { |
| bss->wep_cfg.key3.key_index = 3; |
| bss->wep_cfg.key3.length = key_len; |
| if (args[1][0] == '"') { |
| memcpy(bss->wep_cfg.key3.key, |
| &args[1][1], |
| strlen(args[1]) - 2); |
| } else { |
| string2raw(args[1], |
| bss->wep_cfg.key3. |
| key); |
| } |
| } |
| } |
| } |
| if (strcmp(args[0], "PSK") == 0) { |
| if (arg_num == 1) { |
| printf("ERR:PSK is blank!\n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } else { |
| 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_WPA_PASSPHRASE_LENGTH) { |
| printf("ERR:PSK too long.\n"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| if (strlen(args[1]) < MIN_WPA_PASSPHRASE_LENGTH) { |
| printf("ERR:PSK too short.\n"); |
| retval = UAP_FAILURE; |
| 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"); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| } |
| /* Set WPA passphrase field */ |
| bss->wpa_cfg.length = strlen(args[1]); |
| memcpy(bss->wpa_cfg.passphrase, args[1], |
| bss->wpa_cfg.length); |
| } |
| } |
| if (strcmp(args[0], "Protocol") == 0) { |
| if (is_input_valid(PROTOCOL, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Set protocol field */ |
| protocol = (t_u16)atoi(args[1]); |
| } |
| if ((strcmp(args[0], "PairwiseCipher") == 0) || |
| (strcmp(args[0], "GroupCipher") == 0)) { |
| printf("ERR:PairwiseCipher and GroupCipher are not supported.\n" " Please configure pairwise cipher using parameters PwkCipherWPA or PwkCipherWPA2\n" " and group cipher using GwkCipher in the config file.\n"); |
| goto done; |
| } |
| |
| if ((protocol == PROTOCOL_NO_SECURITY) || |
| (protocol == PROTOCOL_STATIC_WEP)) { |
| if ((strcmp(args[0], "PwkCipherWPA") == 0) || |
| (strcmp(args[0], "PwkCipherWPA2") == 0) |
| || (strcmp(args[0], "GwkCipher") == 0)) { |
| printf("ERR:Pairwise cipher and group cipher should not be defined for Open and WEP mode.\n"); |
| goto done; |
| } |
| } |
| |
| if (strcmp(args[0], "PwkCipherWPA") == 0) { |
| if (arg_num == 1) { |
| printf("ERR:PwkCipherWPA is blank!\n"); |
| goto done; |
| } else { |
| if (ISDIGIT(args[1]) == 0) { |
| printf("ERR:Illegal PwkCipherWPA parameter. Must be either bit '2' or '3'.\n"); |
| goto done; |
| } |
| if (atoi(args[1]) & ~CIPHER_BITMAP) { |
| printf("ERR:Illegal PwkCipherWPA parameter. Must be either bit '2' or '3'.\n"); |
| goto done; |
| } |
| pwkcipher_wpa = atoi(args[1]); |
| if (enable_11n && |
| protocol != PROTOCOL_WPA2_MIXED) { |
| memset(&htcap, 0, sizeof(htcap)); |
| if (UAP_SUCCESS == |
| get_sys_cfg_11n(&htcap)) { |
| if (htcap.supported_mcs_set[0] |
| && (atoi(args[1]) == |
| CIPHER_TKIP)) { |
| printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n"); |
| return UAP_FAILURE; |
| } |
| } |
| } |
| } |
| } |
| if (strcmp(args[0], "PwkCipherWPA2") == 0) { |
| if (arg_num == 1) { |
| printf("ERR:PwkCipherWPA2 is blank!\n"); |
| goto done; |
| } else { |
| if (ISDIGIT(args[1]) == 0) { |
| printf("ERR:Illegal PwkCipherWPA2 parameter. Must be either bit '2' or '3'.\n"); |
| goto done; |
| } |
| if (atoi(args[1]) & ~CIPHER_BITMAP) { |
| printf("ERR:Illegal PwkCipherWPA2 parameter. Must be either bit '2' or '3'.\n"); |
| goto done; |
| } |
| pwkcipher_wpa2 = atoi(args[1]); |
| if (enable_11n && |
| protocol != PROTOCOL_WPA2_MIXED) { |
| memset(&htcap, 0, sizeof(htcap)); |
| if (UAP_SUCCESS == |
| get_sys_cfg_11n(&htcap)) { |
| if (htcap.supported_mcs_set[0] |
| && (atoi(args[1]) == |
| CIPHER_TKIP)) { |
| printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n"); |
| return UAP_FAILURE; |
| } |
| } |
| } |
| } |
| } |
| if (strcmp(args[0], "GwkCipher") == 0) { |
| if (is_input_valid(GWK_CIPHER, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| goto done; |
| } |
| gwkcipher = atoi(args[1]); |
| } |
| if (strcmp(args[0], "GroupRekeyTime") == 0) { |
| if (is_input_valid |
| (GROUPREKEYTIMER, arg_num - 1, |
| args + 1) != UAP_SUCCESS) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| |
| /* Set group rekey time field */ |
| bss->wpa_cfg.gk_rekey_time = (t_u32)atoi(args[1]); |
| } |
| if (strcmp(args[0], "MaxStaNum") == 0) { |
| if (is_input_valid(MAXSTANUM, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| if (get_max_sta_num_supported(&max_sta_num_supported) == |
| UAP_FAILURE) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| if (atoi(args[1]) > max_sta_num_supported) { |
| printf("ERR: MAX_STA_NUM must be less than %d\n", max_sta_num_supported); |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| /* Set max STA number field */ |
| bss->max_sta_count = (t_u16)atoi(args[1]); |
| } |
| if (strcmp(args[0], "Retrylimit") == 0) { |
| if (is_input_valid(RETRYLIMIT, arg_num - 1, args + 1) != |
| UAP_SUCCESS) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| |
| /* Set retry limit field */ |
| bss->retry_limit = (t_u16)atoi(args[1]); |
| } |
| if (strcmp(args[0], "PreambleType") == 0) { |
| if (is_input_valid(PREAMBLETYPE, arg_num - 1, args + 1) |
| != UAP_SUCCESS) { |
| retval = UAP_FAILURE; |
| goto done; |
| } |
| |
| /* Set preamble type field */ |
| bss->preamble_type = (t_u8)atoi(args[1]); |
| } |
| if (strcmp(args[0], "Enable11n") == 0) { |
| if ((ISDIGIT(args[1]) != UAP_SUCCESS) || |
| (atoi(args[1]) < 0) || (atoi(args[1]) > 1)) { |
| printf("ERR: Invalid Enable11n value\n"); |
| goto done; |
| } |
| enable_11n = atoi(args[1]); |
| |
| memset(&htcap, 0, sizeof(htcap)); |
| if (UAP_SUCCESS != get_sys_cfg_11n(&htcap)) { |
| printf("ERR: Reading current 11n configuration.\n"); |
| goto done; |
| } |
| bss->ht_cap_info = htcap.ht_cap_info; |
| bss->ampdu_param = htcap.ampdu_param; |
| memcpy(bss->supported_mcs_set, htcap.supported_mcs_set, |
| 16); |
| bss->ht_ext_cap = htcap.ht_ext_cap; |
| bss->tx_bf_cap = htcap.tx_bf_cap; |
| bss->asel = htcap.asel; |
| if (enable_11n == 1) { |
| /* enable mcs rate */ |
| bss->supported_mcs_set[0] = DEFAULT_MCS_SET_0; |
| bss->supported_mcs_set[4] = DEFAULT_MCS_SET_4; |
| if (0 == get_fw_info(&fw)) { |
| if ((fw.hw_dev_mcs_support & 0x0f) >= 2) |
| bss->supported_mcs_set[1] = |
| DEFAULT_MCS_SET_1; |
| } |
| } else { |
| /* disable mcs rate */ |
| bss->supported_mcs_set[0] = 0; |
| bss->supported_mcs_set[4] = 0; |
| bss->supported_mcs_set[1] = 0; |
| } |
| } |
| if (strcmp(args[0], "HTCapInfo") == 0) { |
| if (enable_11n <= 0) { |
| printf("ERR: Enable11n parameter should be set before HTCapInfo.\n"); |
| goto done; |
| } |
| if ((IS_HEX_OR_DIGIT(args[1]) == UAP_FAILURE) || |
| ((((t_u16)A2HEXDECIMAL(args[1])) & |
| (~HT_CAP_CONFIG_MASK)) != HT_CAP_CHECK_MASK)) { |
| printf("ERR: Invalid HTCapInfo value\n"); |
| goto done; |
| } |
| bss->ht_cap_info = |
| DEFAULT_HT_CAP_VALUE & ~HT_CAP_CONFIG_MASK; |
| bss->ht_cap_info |= |
| (t_u16)A2HEXDECIMAL(args[1]) & |
| HT_CAP_CONFIG_MASK; |
| bss->ht_cap_info = uap_cpu_to_le16(bss->ht_cap_info); |
| } |
| if (strcmp(args[0], "AMPDU") == 0) { |
| if (enable_11n <= 0) { |
| printf("ERR: Enable11n parameter should be set before AMPDU.\n"); |
| goto done; |
| } |
| if ((IS_HEX_OR_DIGIT(args[1]) == UAP_FAILURE) || |
| ((A2HEXDECIMAL(args[1])) > AMPDU_CONFIG_MASK)) { |
| printf("ERR: Invalid AMPDU value\n"); |
| goto done; |
| } |
| /* Find HT tlv pointer in buffer and set AMPDU */ |
| bss->ampdu_param = |
| (t_u8)A2HEXDECIMAL(args[1]) & AMPDU_CONFIG_MASK; |
| } |
| if (strcmp(args[0], "HT_MCS_MAP") == 0) { |
| if (enable_11n <= 0) { |
| printf("ERR: Enable11n parameter should be set before HT_MCS_MAP.\n"); |
| goto done; |
| } |
| if ((IS_HEX_OR_DIGIT(args[1]) == UAP_FAILURE)) { |
| printf("ERR: Invalid HT_MCS_MAP value\n"); |
| goto done; |
| } |
| if (0 == get_fw_info(&fw)) { |
| /* Check upper nibble of MCS support value |
| * and block MCS_SET_1 when 2X2 is not supported |
| * by the underlying hardware */ |
| if (((fw.hw_dev_mcs_support & 0xf0) < |
| STREAM_2X2_MASK) && |
| (A2HEXDECIMAL(args[1]) & MCS_SET_1_MASK)) { |
| printf("ERR: Invalid HT_MCS_MAP\n"); |
| goto done; |
| } |
| } |
| supported_mcs_set = (t_u32)A2HEXDECIMAL(args[1]); |
| supported_mcs_set = uap_cpu_to_le32(supported_mcs_set); |
| memcpy(bss->supported_mcs_set, &supported_mcs_set, |
| sizeof(t_u32)); |
| } |
| if (strcmp(args[0], "Enable2040Coex") == 0) { |
| if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0) || |
| (atoi(args[1]) > 1)) { |
| printf("ERR:Invalid Enable2040Coex value.\n"); |
| goto done; |
| } |
| bss->enable_2040coex = (t_u8)atoi(args[1]); |
| } |
| } |
| done: |
| fclose(config_file); |
| if (line) |
| free(line); |
| return retval; |
| } |
| |
| /** |
| * @brief Show all the BSS configuration in the buffer |
| * |
| * @param buf Pointer to BSS configuration buffer |
| * |
| * $return N/A |
| */ |
| void |
| print_bss_config(bss_config_t *buf) |
| { |
| int i = 0; |
| int flag = 0; |
| |
| if (!buf) { |
| printf("ERR:Empty BSS config!\n"); |
| return; |
| } |
| |
| /* Print AP MAC address */ |
| printf("AP MAC address = "); |
| print_mac(buf->mac_addr); |
| printf("\n"); |
| |
| /* Print SSID */ |
| if (buf->ssid.ssid_len) { |
| printf("SSID = %s\n", buf->ssid.ssid); |
| } |
| |
| /* Print broadcast SSID control */ |
| printf("SSID broadcast = %s\n", |
| (buf->bcast_ssid_ctl == 1) ? "enabled" : "disabled"); |
| |
| /* Print DTIM period */ |
| printf("DTIM period = %d\n", buf->dtim_period); |
| |
| /* Print beacon period */ |
| printf("Beacon period = %d\n", buf->beacon_period); |
| |
| /* Print rates */ |
| printf("Basic Rates ="); |
| for (i = 0; i < MAX_DATA_RATES; i++) { |
| if (!buf->rates[i]) |
| break; |
| if (buf->rates[i] > (BASIC_RATE_SET_BIT - 1)) { |
| flag = flag ? : 1; |
| printf(" 0x%x", buf->rates[i]); |
| } |
| } |
| printf("%s\nNon-Basic Rates =", flag ? "" : " ( none ) "); |
| for (flag = 0, i = 0; i < MAX_DATA_RATES; i++) { |
| if (!buf->rates[i]) |
| break; |
| if (buf->rates[i] < BASIC_RATE_SET_BIT) { |
| flag = flag ? : 1; |
| printf(" 0x%x", buf->rates[i]); |
| } |
| } |
| printf("%s\n", flag ? "" : " ( none ) "); |
| |
| /* Print Tx data rate */ |
| printf("Tx data rate = "); |
| if (buf->tx_data_rate == 0) |
| printf("auto\n"); |
| else |
| printf("0x%x\n", buf->tx_data_rate); |
| |
| /* Print MCBC data rate */ |
| printf("MCBC data rate = "); |
| if (buf->mcbc_data_rate == 0) |
| printf("auto\n"); |
| else |
| printf("0x%x\n", buf->mcbc_data_rate); |
| |
| /* Print Tx power level */ |
| printf("Tx power = %d dBm\n", buf->tx_power_level); |
| |
| /* Print Tx antenna */ |
| printf("Tx antenna = %s\n", (buf->tx_antenna) ? "B" : "A"); |
| |
| /* Print Rx antenna */ |
| printf("Rx antenna = %s\n", (buf->rx_antenna) ? "B" : "A"); |
| |
| /* Print packet forward control */ |
| printf("%s handles packet forwarding -\n", |
| ((buf->pkt_forward_ctl & PKT_FWD_FW_BIT) == |
| 0) ? "Host" : "Firmware"); |
| printf("\tIntra-BSS broadcast packets are %s\n", |
| ((buf->pkt_forward_ctl & PKT_FWD_INTRA_BCAST) == |
| 0) ? "allowed" : "denied"); |
| printf("\tIntra-BSS unicast packets are %s\n", |
| ((buf->pkt_forward_ctl & PKT_FWD_INTRA_UCAST) == |
| 0) ? "allowed" : "denied"); |
| printf("\tInter-BSS unicast packets are %s\n", |
| ((buf->pkt_forward_ctl & PKT_FWD_INTER_UCAST) == |
| 0) ? "allowed" : "denied"); |
| |
| /* Print maximum STA count */ |
| printf("Max Station Number configured = %d\n", buf->max_sta_count); |
| |
| /* Print mgmt frame FWD control */ |
| printf("MGMT frame Fwd Control = 0x%x\n", buf->mgmt_ie_passthru_mask); |
| |
| /* Print MAC filter */ |
| if (buf->filter.filter_mode == 0) { |
| printf("Filter Mode = Filter table is disabled\n"); |
| } else { |
| if (buf->filter.filter_mode == 1) { |
| printf("Filter Mode = Allow MAC addresses specified in the allowed list\n"); |
| } else if (buf->filter.filter_mode == 2) { |
| printf("Filter Mode = Block MAC addresses specified in the banned list\n"); |
| } else { |
| printf("Filter Mode = Unknown\n"); |
| } |
| for (i = 0; i < buf->filter.mac_count; i++) { |
| printf("MAC_%d = ", i); |
| print_mac(buf->filter.mac_list[i]); |
| printf("\n"); |
| } |
| } |
| |
| /* Print STA ageout timer */ |
| printf("STA ageout timer = %d\n", buf->sta_ageout_timer); |
| |
| /* Print PS STA ageout timer */ |
| printf("PS STA ageout timer = %d\n", buf->ps_sta_ageout_timer); |
| |
| /* Print RTS threshold */ |
| printf("RTS threshold = %d\n", buf->rts_threshold); |
| |
| /* Print Fragmentation threshold */ |
| printf("Fragmentation threshold = %d\n", buf->frag_threshold); |
| |
| /* Print retry limit */ |
| printf("Retry Limit = %d\n", buf->retry_limit); |
| |
| /* Print preamble type */ |
| printf("Preamble type = %s\n", (buf->preamble_type == 0) ? |
| "auto" : ((buf->preamble_type == 1) ? "short" : "long")); |
| |
| /* Print channel */ |
| printf("Channel = %d\n", buf->channel); |
| printf("Band = %s\n", |
| (buf->bandcfg.chanBand == BAND_5GHZ) ? "5GHz" : "2.4GHz"); |
| printf("Channel Select Mode = %s\n", |
| (buf->bandcfg.scanMode == SCAN_MODE_ACS) ? "ACS" : "Manual"); |
| if (buf->bandcfg.chan2Offset == SEC_CHAN_NONE) |
| printf("no secondary channel\n"); |
| else if (buf->bandcfg.chan2Offset == SEC_CHAN_ABOVE) |
| printf("secondary channel is above primary channel\n"); |
| else if (buf->bandcfg.chan2Offset == SEC_CHAN_BELOW) |
| printf("secondary channel is below primary channel\n"); |
| |
| /* Print channel list */ |
| printf("Channels List = "); |
| for (i = 0; (unsigned int)i < buf->num_of_chan; i++) { |
| printf("\n%d\t%sGHz", buf->chan_list[i].chan_number, |
| (buf->chan_list[i].bandcfg.chanBand == |
| BAND_5GHZ) ? "5" : "2.4"); |
| } |
| printf("\n"); |
| |
| /* Print auth mode */ |
| switch (buf->auth_mode) { |
| case 0: |
| printf("AUTHMODE = Open authentication\n"); |
| break; |
| case 1: |
| printf("AUTHMODE = Shared key authentication\n"); |
| break; |
| case 255: |
| printf("AUTHMODE = Auto (open and shared key)\n"); |
| break; |
| default: |
| printf("ERR: Invalid authmode=%d\n", buf->auth_mode); |
| break; |
| } |
| |
| /* Print protocol */ |
| switch (buf->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", buf->protocol); |
| break; |
| } |
| |
| /* Print key management */ |
| if (buf->key_mgmt == KEY_MGMT_PSK) |
| printf("KeyMgmt = PSK\n"); |
| else |
| printf("KeyMgmt = NONE\n"); |
| |
| /* Print WEP configurations */ |
| if (buf->wep_cfg.key0.length) { |
| printf("WEP KEY_0 = "); |
| for (i = 0; i < buf->wep_cfg.key0.length; i++) { |
| printf("%02x ", buf->wep_cfg.key0.key[i]); |
| } |
| (buf->wep_cfg.key0. |
| is_default) ? (printf("<Default>\n")) : (printf("\n")); |
| } else { |
| printf("WEP KEY_0 = NONE\n"); |
| } |
| if (buf->wep_cfg.key1.length) { |
| printf("WEP KEY_1 = "); |
| for (i = 0; i < buf->wep_cfg.key1.length; i++) { |
| printf("%02x ", buf->wep_cfg.key1.key[i]); |
| } |
| (buf->wep_cfg.key1. |
| is_default) ? (printf("<Default>\n")) : (printf("\n")); |
| } else { |
| printf("WEP KEY_1 = NONE\n"); |
| } |
| if (buf->wep_cfg.key2.length) { |
| printf("WEP KEY_2 = "); |
| for (i = 0; i < buf->wep_cfg.key2.length; i++) { |
| printf("%02x ", buf->wep_cfg.key2.key[i]); |
| } |
| (buf->wep_cfg.key2. |
| is_default) ? (printf("<Default>\n")) : (printf("\n")); |
| } else { |
| printf("WEP KEY_2 = NONE\n"); |
| } |
| if (buf->wep_cfg.key3.length) { |
| printf("WEP KEY_3 = "); |
| for (i = 0; i < buf->wep_cfg.key3.length; i++) { |
| printf("%02x ", buf->wep_cfg.key3.key[i]); |
| } |
| (buf->wep_cfg.key3. |
| is_default) ? (printf("<Default>\n")) : (printf("\n")); |
| } else { |
| printf("WEP KEY_3 = NONE\n"); |
| } |
| |
| /* Print WPA configurations */ |
| if (buf->protocol & PROTOCOL_WPA) { |
| switch (buf->wpa_cfg.pairwise_cipher_wpa) { |
| case CIPHER_TKIP: |
| printf("PwkCipherWPA = TKIP\n"); |
| break; |
| case CIPHER_AES_CCMP: |
| printf("PwkCipherWPA = AES CCMP\n"); |
| break; |
| case CIPHER_TKIP | CIPHER_AES_CCMP: |
| printf("PwkCipherWPA = TKIP + AES CCMP\n"); |
| break; |
| case CIPHER_NONE: |
| printf("PwkCipherWPA = None\n"); |
| break; |
| default: |
| printf("Unknown PwkCipherWPA 0x%x\n", |
| buf->wpa_cfg.pairwise_cipher_wpa); |
| break; |
| } |
| } |
| if (buf->protocol & PROTOCOL_WPA2) { |
| switch (buf->wpa_cfg.pairwise_cipher_wpa2) { |
| case CIPHER_TKIP: |
| printf("PwkCipherWPA2 = TKIP\n"); |
| break; |
| case CIPHER_AES_CCMP: |
| printf("PwkCipherWPA2 = AES CCMP\n"); |
| break; |
| case CIPHER_TKIP | CIPHER_AES_CCMP: |
| printf("PwkCipherWPA2 = TKIP + AES CCMP\n"); |
| break; |
| case CIPHER_NONE: |
| printf("PwkCipherWPA2 = None\n"); |
| break; |
| default: |
| printf("Unknown PwkCipherWPA2 0x%x\n", |
| buf->wpa_cfg.pairwise_cipher_wpa2); |
| break; |
| } |
| } |
| switch (buf->wpa_cfg.group_cipher) { |
| 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", |
| buf->wpa_cfg.group_cipher); |
| break; |
| } |
| printf("RSN replay protection = %s\n", |
| (buf->wpa_cfg.rsn_protection) ? "enabled" : "disabled"); |
| printf("Pairwise Handshake timeout = %d\n", |
| buf->pairwise_update_timeout); |
| printf("Pairwise Handshake Retries = %d\n", buf->pwk_retries); |
| printf("Groupwise Handshake timeout = %d\n", |
| buf->groupwise_update_timeout); |
| printf("Groupwise Handshake Retries = %d\n", buf->gwk_retries); |
| if (buf->wpa_cfg.length > 0) { |
| printf("WPA passphrase = "); |
| for (i = 0; (unsigned int)i < buf->wpa_cfg.length; i++) |
| printf("%c", buf->wpa_cfg.passphrase[i]); |
| printf("\n"); |
| } else { |
| printf("WPA passphrase = None\n"); |
| } |
| if (buf->wpa_cfg.gk_rekey_time == 0) |
| printf("Group re-key time = disabled\n"); |
| else |
| printf("Group re-key time = %d second\n", |
| buf->wpa_cfg.gk_rekey_time); |
| printf("20/40 coex = %s\n", |
| (buf->enable_2040coex) ? "enabled" : "disabled"); |
| printf("wmm parameters:\n"); |
| printf("\tqos_info = 0x%x\n", buf->wmm_para.qos_info); |
| printf("\tBE: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", |
| buf->wmm_para.ac_params[AC_BE].aci_aifsn.aifsn, |
| buf->wmm_para.ac_params[AC_BE].ecw.ecw_max, |
| buf->wmm_para.ac_params[AC_BE].ecw.ecw_min, |
| buf->wmm_para.ac_params[AC_BE].tx_op_limit); |
| printf("\tBK: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", |
| buf->wmm_para.ac_params[AC_BK].aci_aifsn.aifsn, |
| buf->wmm_para.ac_params[AC_BK].ecw.ecw_max, |
| buf->wmm_para.ac_params[AC_BK].ecw.ecw_min, |
| buf->wmm_para.ac_params[AC_BK].tx_op_limit); |
| printf("\tVI: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", |
| buf->wmm_para.ac_params[AC_VI].aci_aifsn.aifsn, |
| buf->wmm_para.ac_params[AC_VI].ecw.ecw_max, |
| buf->wmm_para.ac_params[AC_VI].ecw.ecw_min, |
| buf->wmm_para.ac_params[AC_VI].tx_op_limit); |
| printf("\tVO: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", |
| buf->wmm_para.ac_params[AC_VO].aci_aifsn.aifsn, |
| buf->wmm_para.ac_params[AC_VO].ecw.ecw_max, |
| buf->wmm_para.ac_params[AC_VO].ecw.ecw_min, |
| buf->wmm_para.ac_params[AC_VO].tx_op_limit); |
| |
| return; |
| } |
| |
| /** |
| * @brief Send command to Read the BSS profile |
| * |
| * @param buf Pointer to bss command buffer for get |
| * @return UAP_SUCCESS or UAP_FAILURE |
| */ |
| static int |
| get_bss_config(t_u8 *buf) |
| { |
| apcmdbuf_bss_configure *cmd_buf = NULL; |
| t_s32 sockfd; |
| struct ifreq ifr; |
| |
| cmd_buf = (apcmdbuf_bss_configure *)buf; |
| cmd_buf->action = ACTION_GET; |
| |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| #if DEBUG |
| /* Dump request buffer */ |
| hexdump("Get Request buffer", (void *)buf, |
| sizeof(apcmdbuf_bss_configure) |
| + sizeof(bss_config_t), ' '); |
| #endif |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)cmd_buf; |
| if (ioctl(sockfd, UAP_BSS_CONFIG, &ifr)) { |
| printf("ERR:UAP_BSS_CONFIG is not supported by %s\n", dev_name); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| #if DEBUG |
| /* Dump request buffer */ |
| hexdump("Get Response buffer", (void *)buf, |
| sizeof(apcmdbuf_bss_configure) |
| + sizeof(bss_config_t), ' '); |
| #endif |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Creates a bss_config request and sends to the driver |
| * |
| * Usage: "Usage : bss_config [CONFIG_FILE]" |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_bss_config(int argc, char *argv[]) |
| { |
| apcmdbuf_bss_configure *cmd_buf = NULL; |
| bss_config_t *bss = NULL; |
| t_u8 *buf = NULL; |
| t_u16 cmd_len; |
| t_u16 buf_len; |
| int ret = UAP_SUCCESS; |
| int opt; |
| t_s32 sockfd; |
| struct ifreq ifr; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_bss_config_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| /* Check arguments */ |
| if (argc > 1) { |
| printf("ERR:Too many arguments.\n"); |
| print_bss_config_usage(); |
| return UAP_FAILURE; |
| } |
| |
| /* Query BSS settings */ |
| |
| /* Alloc buf for command */ |
| buf_len = sizeof(apcmdbuf_bss_configure) + sizeof(bss_config_t); |
| buf = (t_u8 *)malloc(buf_len); |
| if (!buf) { |
| printf("ERR:Cannot allocate buffer from command!\n"); |
| return UAP_FAILURE; |
| } |
| memset((char *)buf, 0, buf_len); |
| |
| /* Locate headers */ |
| cmd_len = sizeof(apcmdbuf_bss_configure); |
| cmd_buf = (apcmdbuf_bss_configure *)buf; |
| bss = (bss_config_t *)(buf + cmd_len); |
| |
| /* Get all parametes first */ |
| if (get_bss_config(buf) == UAP_FAILURE) { |
| printf("ERR:Reading current parameters\n"); |
| free(buf); |
| return UAP_FAILURE; |
| } |
| |
| if (argc == 1) { |
| /* Parse config file and populate structure */ |
| ret = parse_bss_config(argc, argv, bss); |
| if (ret == UAP_FAILURE) { |
| free(buf); |
| return ret; |
| } |
| cmd_len += sizeof(bss_config_t); |
| cmd_buf->action = ACTION_SET; |
| |
| /* Send the command */ |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| free(buf); |
| return UAP_FAILURE; |
| } |
| |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)cmd_buf; |
| #if DEBUG |
| /* Dump request buffer */ |
| hexdump("Request buffer", (void *)buf, buf_len, ' '); |
| #endif |
| if (ioctl(sockfd, UAP_BSS_CONFIG, &ifr)) { |
| perror(""); |
| printf("ERR:UAP_BSS_CONFIG is not supported by %s\n", |
| dev_name); |
| close(sockfd); |
| free(buf); |
| return UAP_FAILURE; |
| } |
| #if DEBUG |
| /* Dump respond buffer */ |
| hexdump("Respond buffer", (void *)buf, buf_len, ' '); |
| #endif |
| close(sockfd); |
| } else { |
| /* Print response */ |
| printf("BSS settings:\n"); |
| print_bss_config(bss); |
| } |
| |
| free(buf); |
| return ret; |
| } |
| |
| /** |
| * @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 |
| */ |
| int |
| apcmd_coex_config_profile(int argc, char *argv[]) |
| { |
| FILE *config_file = NULL; |
| char *line = NULL; |
| int i, index, li = 0; |
| int ret = UAP_SUCCESS; |
| 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; |
| t_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; |
| t_u16 acl_enabled = 0; |
| t_u32 conf_bitmap = 0; |
| t_u32 ap_coex_enable = 0; |
| t_u16 cmd_len = 0, tlv_len = 0; |
| t_u16 sco_prot_qtime[4] = { 0, 0, 0, 0 }, sco_prot_rate = |
| 0, sco_acl_freq = 0; |
| t_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 UAP_FAILURE; |
| } |
| line = (char *)malloc(MAX_CONFIG_LINE); |
| if (!line) { |
| printf("ERR:Cannot allocate memory for line\n"); |
| ret = UAP_FAILURE; |
| 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 = (t_u8 *)malloc(cmd_len); |
| if (!buf) { |
| printf("ERR:Cannot allocate buffer from command!\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| bzero((char *)buf, cmd_len); |
| |
| cmd_buf = (apcmdbuf_coex_config *)buf; |
| |
| /* Fill the command buffer */ |
| cmd_buf->cmd_code = HostCmd_ROBUST_COEX; |
| cmd_buf->size = cmd_len - BUF_HEADER_SIZE; |
| cmd_buf->seq_num = 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); |
| coex_common_tlv->ap_bt_coex = |
| uap_cpu_to_le32(ap_coex_enable); |
| 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) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| conf_bitmap = (t_u32)A2HEXDECIMAL(args[1]); |
| } else if ((strcmp(args[0], "APBTCoex") == 0) && |
| is_coex_common_config) { |
| if (is_input_valid |
| (COEX_COMM_AP_COEX, arg_num - 1, |
| args + 1) != UAP_SUCCESS) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| ap_coex_enable = (t_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); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| if (is_input_valid(COEX_PROTECTION, arg_num, args) != |
| UAP_SUCCESS) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| sco_prot_qtime[index] = (t_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) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| sco_prot_rate = (t_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) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| sco_acl_freq = (t_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) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| acl_enabled = (t_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) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| acl_bt_time = (t_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) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| acl_wlan_time = (t_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) { |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| acl_prot_rate = (t_u16)atoi(args[1]); |
| } |
| } |
| /* Send the command */ |
| ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, cmd_len); |
| |
| /* Process response */ |
| if (ret == UAP_SUCCESS) { |
| /* Verify response */ |
| if (cmd_buf->cmd_code != |
| (HostCmd_ROBUST_COEX | APCMD_RESP_CHECK)) { |
| printf("ERR:Corrupted response!\n"); |
| ret = UAP_FAILURE; |
| 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); |
| return ret; |
| } |
| |
| /** |
| * @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 |
| */ |
| int |
| 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; |
| t_u8 *buf = NULL; |
| t_u16 cmd_len = 0; |
| t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| int ret = UAP_SUCCESS; |
| int opt; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_coex_config_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| /* Check arguments */ |
| if (argc > 1) { |
| printf("ERR:Too many arguments.\n"); |
| print_coex_config_usage(); |
| return UAP_FAILURE; |
| } |
| if (argc == 1) { |
| /* Read profile and send command to firmware */ |
| ret = apcmd_coex_config_profile(argc, argv); |
| return ret; |
| } |
| |
| /* 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 = (t_u8 *)malloc(buf_len); |
| if (!buf) { |
| printf("ERR:Cannot allocate buffer from command!\n"); |
| return UAP_FAILURE; |
| } |
| bzero((char *)buf, buf_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->cmd_code = HostCmd_ROBUST_COEX; |
| cmd_buf->size = cmd_len - BUF_HEADER_SIZE; |
| cmd_buf->seq_num = 0; |
| cmd_buf->result = 0; |
| cmd_buf->action = uap_cpu_to_le16(ACTION_GET); |
| |
| /* Send the command */ |
| ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); |
| |
| /* Process response */ |
| if (ret == UAP_SUCCESS) { |
| /* Verify response */ |
| if (cmd_buf->cmd_code != |
| (HostCmd_ROBUST_COEX | APCMD_RESP_CHECK)) { |
| printf("ERR:Corrupted response!\n"); |
| free(buf); |
| return UAP_FAILURE; |
| } |
| /* 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"); |
| ret = UAP_FAILURE; |
| } |
| } else { |
| printf("ERR:Command sending failed!\n"); |
| } |
| free(buf); |
| return ret; |
| } |
| |
| /** |
| * @brief Show usage information for the sys_cfg_custom_ie |
| * command |
| * |
| * $return N/A |
| */ |
| void |
| print_sys_cfg_custom_ie_usage(void) |
| { |
| printf("\nUsage : sys_cfg_custom_ie [INDEX] [MASK] [IEBuffer]"); |
| printf("\n empty - Get all IE settings\n"); |
| printf("\n INDEX: 0 - Get/Set IE index 0 setting"); |
| printf("\n 1 - Get/Set IE index 1 setting"); |
| printf("\n 2 - Get/Set IE index 2 setting"); |
| printf("\n 3 - Get/Set IE index 3 setting"); |
| printf("\n . "); |
| printf("\n . "); |
| printf("\n . "); |
| printf("\n -1 - Append/Delete IE automatically"); |
| printf("\n Delete will delete the IE from the matching IE buffer"); |
| printf("\n Append will append the IE to the buffer with the same mask"); |
| printf("\n MASK : Management subtype mask value as per bit defintions"); |
| printf("\n : Bit 0 - Association request."); |
| printf("\n : Bit 1 - Association response."); |
| printf("\n : Bit 2 - Reassociation request."); |
| printf("\n : Bit 3 - Reassociation response."); |
| printf("\n : Bit 4 - Probe request."); |
| printf("\n : Bit 5 - Probe response."); |
| printf("\n : Bit 8 - Beacon."); |
| printf("\n MASK : MASK = 0 to clear the mask and the IE buffer"); |
| printf("\n IEBuffer : IE Buffer in hex (max 256 bytes)\n\n"); |
| return; |
| } |
| |
| /** custom IE, auto mask value */ |
| #define UAP_CUSTOM_IE_AUTO_MASK 0xffff |
| |
| /** |
| * @brief Get max management IE index |
| * @param max_mgmt_ie |
| * @param print flag |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| static int |
| get_max_mgmt_ie(int *max_mgmt_ie, int flag) |
| { |
| apcmdbuf_sys_configure *cmd_buf = NULL; |
| tlvbuf_max_mgmt_ie *tlv = NULL; |
| t_u8 *buffer = NULL; |
| t_u16 cmd_len = 0, i = 0; |
| t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| int ret = UAP_SUCCESS; |
| |
| *max_mgmt_ie = 0; |
| /* Initialize the command length */ |
| cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_max_mgmt_ie); |
| |
| /* Initialize the command buffer */ |
| buffer = (t_u8 *)malloc(buf_len); |
| if (!buffer) { |
| printf("ERR:Cannot allocate buffer for command!\n"); |
| return UAP_FAILURE; |
| } |
| memset(buffer, 0, buf_len); |
| |
| /* Locate headers */ |
| cmd_buf = (apcmdbuf_sys_configure *)buffer; |
| tlv = (tlvbuf_max_mgmt_ie *)(buffer + sizeof(apcmdbuf_sys_configure)); |
| |
| /* Fill the command buffer */ |
| cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; |
| cmd_buf->size = cmd_len; |
| cmd_buf->seq_num = 0; |
| cmd_buf->result = 0; |
| tlv->tag = MRVL_MAX_MGMT_IE_TLV_ID; |
| tlv->length = 0; |
| cmd_buf->action = ACTION_GET; |
| endian_convert_tlv_header_out(tlv); |
| /* Send the command */ |
| ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); |
| endian_convert_tlv_header_in(tlv); |
| |
| /* Process response */ |
| if (ret == UAP_SUCCESS) { |
| /* Verify response */ |
| if ((cmd_buf->cmd_code != |
| (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || |
| (tlv->tag != MRVL_MAX_MGMT_IE_TLV_ID)) { |
| printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); |
| free(buffer); |
| return UAP_FAILURE; |
| } |
| /* Print response */ |
| if (cmd_buf->result == CMD_SUCCESS) { |
| tlv->count = uap_le16_to_cpu(tlv->count); |
| for (i = 0; i < tlv->count; i++) { |
| tlv->info[i].buf_size = |
| uap_le16_to_cpu(tlv->info[i].buf_size); |
| tlv->info[i].buf_count = |
| uap_le16_to_cpu(tlv->info[i].buf_count); |
| *max_mgmt_ie += tlv->info[i].buf_count; |
| if (flag) { |
| printf("buf%d_size = %d\n", i, |
| tlv->info[i].buf_size); |
| printf("number of buffers = %d\n", |
| tlv->info[i].buf_count); |
| printf("\n"); |
| } |
| } |
| } else { |
| printf("ERR:Could not get max_mgmt_ie_index!\n"); |
| ret = UAP_FAILURE; |
| } |
| } else { |
| printf("ERR:Command sending failed!\n"); |
| } |
| if (buffer) |
| free(buffer); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Creates a sys_cfg request for custom IE settings |
| * and sends to the driver |
| * |
| * Usage: "sys_cfg_custom_ie [INDEX] [MASK] [IEBuffer]" |
| * |
| * Options: INDEX : 0 - Get/Set IE index 0 setting |
| * 1 - Get/Set IE index 1 setting |
| * 2 - Get/Set IE index 2 setting |
| * 3 - Get/Set IE index 3 setting |
| * . |
| * . |
| * . |
| * MASK : Management subtype mask value |
| * IEBuffer: IE Buffer in hex |
| * empty - Get all IE settings |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_sys_cfg_custom_ie(int argc, char *argv[]) |
| { |
| tlvbuf_custom_ie *tlv = NULL; |
| tlvbuf_max_mgmt_ie *max_mgmt_ie_tlv = NULL; |
| custom_ie *ie_ptr = NULL; |
| t_u8 *buffer = NULL; |
| t_u16 buf_len = 0; |
| t_u16 mgmt_subtype_mask = 0; |
| int ie_buf_len = 0, ie_len = 0, i = 0, max_mgmt_ie = 0, print_flag = 0; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| |
| if (argc == 1 && max_mgmt_ie_print == 0) { |
| /* Print buffer sizes only if (argc == 1) i.e. get all indices one by one |
| * && (max_mgmt_ie_print == 0) i.e. max mgmt IE is not printed via sys_config cmd */ |
| print_flag = 1; |
| } |
| |
| /* Reset the max_mgmt_ie_print for successive cmds */ |
| max_mgmt_ie_print = 0; |
| |
| if (!get_max_mgmt_ie(&max_mgmt_ie, print_flag)) { |
| printf("ERR:couldn't get max_mgmt_ie!\n"); |
| return UAP_FAILURE; |
| } |
| if (max_mgmt_ie == 0) { |
| max_mgmt_ie = MAX_MGMT_IE_INDEX; |
| #if DEBUG |
| uap_printf(MSG_DEBUG, |
| "WARN: max_mgmt_ie=0, defaulting to MAX_MGMT_IE_INDEX\n"); |
| #endif |
| } |
| |
| /* Check arguments */ |
| if (argc > 4) { |
| printf("ERR:Too many arguments.\n"); |
| print_sys_cfg_custom_ie_usage(); |
| return UAP_FAILURE; |
| } |
| |
| /* Error checks and initialize the command length */ |
| if (argc >= 2) { |
| if (((IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE) && |
| (atoi(argv[1]) != -1)) || (atoi(argv[1]) < -1)) { |
| printf("ERR:Illegal index %s\n", argv[1]); |
| print_sys_cfg_custom_ie_usage(); |
| return UAP_FAILURE; |
| } |
| } |
| switch (argc) { |
| case 1: |
| buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| break; |
| case 2: |
| if ((atoi(argv[1]) < 0) || (atoi(argv[1]) >= max_mgmt_ie)) { |
| printf("ERR:Illegal index %s. Must be either greater than or equal to 0 and less than %d for Get Operation \n", argv[1], max_mgmt_ie); |
| print_sys_cfg_custom_ie_usage(); |
| return UAP_FAILURE; |
| } |
| buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| break; |
| case 3: |
| if (UAP_FAILURE == ishexstring(argv[2]) || |
| A2HEXDECIMAL(argv[2]) != 0) { |
| printf("ERR: Mask value should be 0 to clear IEBuffers.\n"); |
| print_sys_cfg_custom_ie_usage(); |
| return UAP_FAILURE; |
| } |
| if (atoi(argv[1]) == -1) { |
| printf("ERR: Buffer should be provided for automatic deletion.\n"); |
| print_sys_cfg_custom_ie_usage(); |
| return UAP_FAILURE; |
| } |
| buf_len = sizeof(tlvbuf_custom_ie) + sizeof(custom_ie); |
| break; |
| case 4: |
| /* This is to check negative numbers and special symbols */ |
| if (UAP_FAILURE == IS_HEX_OR_DIGIT(argv[2])) { |
| printf("ERR:Mask value must be 0 or hex digits\n"); |
| print_sys_cfg_custom_ie_usage(); |
| return UAP_FAILURE; |
| } |
| /* If above check is passed and mask is not hex, then it must be 0 */ |
| if ((ISDIGIT(argv[2]) == UAP_SUCCESS) && atoi(argv[2])) { |
| printf("ERR:Mask value must be 0 or hex digits\n "); |
| print_sys_cfg_custom_ie_usage(); |
| return UAP_FAILURE; |
| } |
| if (UAP_FAILURE == ishexstring(argv[3])) { |
| printf("ERR:Only hex digits are allowed\n"); |
| print_sys_cfg_custom_ie_usage(); |
| return UAP_FAILURE; |
| } |
| ie_buf_len = strlen(argv[3]); |
| if (!strncasecmp("0x", argv[3], 2)) { |
| ie_len = (ie_buf_len - 2 + 1) / 2; |
| argv[3] += 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); |
| print_sys_cfg_custom_ie_usage(); |
| return UAP_FAILURE; |
| } |
| mgmt_subtype_mask = (t_u16)A2HEXDECIMAL(argv[2]); |
| buf_len = sizeof(tlvbuf_custom_ie) + sizeof(custom_ie) + ie_len; |
| break; |
| } |
| |
| /* Initialize the command buffer */ |
| buffer = (t_u8 *)malloc(buf_len); |
| if (!buffer) { |
| printf("ERR:Cannot allocate buffer for command!\n"); |
| return UAP_FAILURE; |
| } |
| memset(buffer, 0, buf_len); |
| tlv = (tlvbuf_custom_ie *)buffer; |
| tlv->tag = MRVL_MGMT_IE_LIST_TLV_ID; |
| if (argc == 1 || argc == 2) { |
| if (argc == 1) |
| tlv->length = 0; |
| else { |
| tlv->length = sizeof(t_u16); |
| ie_ptr = (custom_ie *)(tlv->ie_data); |
| ie_ptr->ie_index = (t_u16)(atoi(argv[1])); |
| } |
| } else { |
| /* Locate headers */ |
| ie_ptr = (custom_ie *)(tlv->ie_data); |
| /* Set TLV fields */ |
| tlv->length = sizeof(custom_ie) + ie_len; |
| ie_ptr->ie_index = atoi(argv[1]); |
| ie_ptr->mgmt_subtype_mask = mgmt_subtype_mask; |
| ie_ptr->ie_length = ie_len; |
| if (argc == 4) |
| string2raw(argv[3], ie_ptr->ie_buffer); |
| } |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| if (buffer) |
| free(buffer); |
| return UAP_FAILURE; |
| } |
| if (argc != 1) { |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)buffer; |
| /* Perform ioctl */ |
| if (ioctl(sockfd, UAP_CUSTOM_IE, &ifr)) { |
| if (errno < 0) { |
| perror("ioctl[UAP_CUSTOM_IE]"); |
| printf("ERR:Command sending failed!\n"); |
| } else { |
| printf("custom IE configuration failed!\n"); |
| } |
| close(sockfd); |
| if (buffer) |
| free(buffer); |
| return UAP_FAILURE; |
| } |
| /* Print response */ |
| if (argc > 2) { |
| printf("custom IE setting successful\n"); |
| } else { |
| printf("Querying custom IE successful\n"); |
| tlv = (tlvbuf_custom_ie *)buffer; |
| ie_len = tlv->length; |
| ie_ptr = (custom_ie *)(tlv->ie_data); |
| if (tlv->tag == MRVL_MGMT_IE_LIST_TLV_ID) { |
| while ((unsigned int)ie_len >= |
| sizeof(custom_ie)) { |
| printf("Index [%d]\n", |
| ie_ptr->ie_index); |
| if (ie_ptr->ie_length) |
| printf("Management Subtype Mask = 0x%02x\n", ie_ptr->mgmt_subtype_mask == 0 ? UAP_CUSTOM_IE_AUTO_MASK : ie_ptr->mgmt_subtype_mask); |
| else |
| printf("Management Subtype Mask = 0x%02x\n", ie_ptr->mgmt_subtype_mask); |
| hexdump_data("IE Buffer", |
| (void *)ie_ptr->ie_buffer, |
| (ie_ptr->ie_length), ' '); |
| ie_len -= |
| sizeof(custom_ie) + |
| ie_ptr->ie_length; |
| ie_ptr = (custom_ie *)((t_u8 *)ie_ptr + |
| sizeof(custom_ie) |
| + |
| ie_ptr-> |
| ie_length); |
| } |
| } |
| max_mgmt_ie_tlv = |
| (tlvbuf_max_mgmt_ie *)(buffer + |
| sizeof(tlvbuf_custom_ie) |
| + tlv->length); |
| if (max_mgmt_ie_tlv) { |
| if (max_mgmt_ie_tlv->tag == |
| MRVL_MAX_MGMT_IE_TLV_ID) { |
| for (i = 0; i < max_mgmt_ie_tlv->count; |
| i++) { |
| printf("buf%d_size = %d\n", i, |
| max_mgmt_ie_tlv->info[i]. |
| buf_size); |
| printf("number of buffers = %d\n", max_mgmt_ie_tlv->info[i].buf_count); |
| printf("\n"); |
| } |
| } |
| } |
| } |
| } |
| |
| /* Special handling for all indices: Get all IEs one-by-one */ |
| if (argc == 1) { |
| for (i = 0; i < max_mgmt_ie; i++) { |
| |
| tlv->length = sizeof(t_u16); |
| ie_ptr = (custom_ie *)(tlv->ie_data); |
| ie_ptr->ie_index = (t_u16)(i); |
| |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)buffer; |
| /* Perform ioctl */ |
| if (ioctl(sockfd, UAP_CUSTOM_IE, &ifr)) { |
| if (errno < 0) { |
| perror("ioctl[UAP_CUSTOM_IE]"); |
| printf("ERR:Command sending failed!\n"); |
| } else { |
| printf("custom IE configuration failed!\n"); |
| } |
| close(sockfd); |
| if (buffer) |
| free(buffer); |
| return UAP_FAILURE; |
| } |
| /* Print response */ |
| tlv = (tlvbuf_custom_ie *)buffer; |
| ie_len = tlv->length; |
| ie_ptr = (custom_ie *)(tlv->ie_data); |
| if (tlv->tag == MRVL_MGMT_IE_LIST_TLV_ID) { |
| while ((unsigned int)ie_len >= |
| sizeof(custom_ie)) { |
| printf("Index [%d]\n", |
| ie_ptr->ie_index); |
| if (ie_ptr->ie_length) |
| printf("Management Subtype Mask = 0x%02x\n", ie_ptr->mgmt_subtype_mask == 0 ? UAP_CUSTOM_IE_AUTO_MASK : ie_ptr->mgmt_subtype_mask); |
| else |
| printf("Management Subtype Mask = 0x%02x\n", ie_ptr->mgmt_subtype_mask); |
| hexdump_data("IE Buffer", |
| (void *)ie_ptr->ie_buffer, |
| (ie_ptr->ie_length), ' '); |
| ie_len -= |
| sizeof(custom_ie) + |
| ie_ptr->ie_length; |
| ie_ptr = (custom_ie *)((t_u8 *)ie_ptr + |
| sizeof(custom_ie) |
| + |
| ie_ptr-> |
| ie_length); |
| } |
| } |
| } |
| printf("Querying custom IE successful\n"); |
| } |
| |
| if (buffer) |
| free(buffer); |
| |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| #if defined(DFS_TESTING_SUPPORT) |
| /** |
| * @brief Show usage information for the dfstesting command |
| * |
| * $return N/A |
| */ |
| void |
| print_dfstesting_usage(void) |
| { |
| printf("\nUsage : dfstesting [USER_CAC_PD USER_NOP_PD NO_CHAN_CHANGE FIXED_CHAN_NUM]\n"); |
| printf("\n empty - Get all dfstesting settings\n"); |
| printf("\n USER_CAC_PD: user configured Channel Availability Check period"); |
| printf("\n 0 - disable, use default (60000)"); |
| printf("\n 1-65535 - CAC period in msec"); |
| printf("\n USER_NOP_PD: user configured Non-Occupancy Period"); |
| printf("\n 0 - disable, use default (1800)"); |
| printf("\n 1-65535 - NOP period in sec"); |
| printf("\n NO_CHAN_CHANGE: user setting, don't change channel on radar"); |
| printf("\n 0 - disable, default behavior"); |
| printf("\n non-zero - enable, overrides below setting"); |
| printf("\n FIXED_CHAN_NUM: user fixed channel to change to on radar"); |
| printf("\n 0 - disable, use random channel [default]"); |
| printf("\n 1-255 - set fixed channel (not checked for validity)\n"); |
| return; |
| } |
| |
| /** |
| * @brief user configuration of dfs testing settings |
| * |
| * Usage: "dfstesting [USER_CAC_PD USER_NOP_PD NO_CHAN_CHANGE FIXED_CHAN_NUM]" |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_dfstesting(int argc, char *argv[]) |
| { |
| int opt; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| t_u32 val; |
| dfs_testing_para dfs_test; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_dfstesting_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| memset(&dfs_test, 0x00, sizeof(dfs_test)); |
| |
| /* Check arguments */ |
| if (argc == 0) { |
| dfs_test.action = ACTION_GET; |
| } else if (argc == 4) { |
| if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) || |
| (IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE) || |
| (IS_HEX_OR_DIGIT(argv[2]) == UAP_FAILURE) || |
| (IS_HEX_OR_DIGIT(argv[3]) == UAP_FAILURE)) { |
| printf("ERR: Only Number values are allowed\n"); |
| print_dfstesting_usage(); |
| return UAP_FAILURE; |
| } |
| |
| val = A2HEXDECIMAL(argv[0]); |
| if (val > 0xfffff) { |
| printf("ERR: invalid user_cac_pd value!\n"); |
| return UAP_FAILURE; |
| } |
| dfs_test.usr_cac_period = (t_u32)val; |
| |
| val = A2HEXDECIMAL(argv[1]); |
| if (val > 0xffff) { |
| printf("ERR: invalid user_nop_pd value!\n"); |
| return UAP_FAILURE; |
| } |
| dfs_test.usr_nop_period = (t_u16)val; |
| |
| val = A2HEXDECIMAL(argv[2]); |
| dfs_test.no_chan_change = (t_u8)(val ? 1 : 0); |
| |
| val = A2HEXDECIMAL(argv[3]); |
| if (val > 0xff) { |
| printf("ERR: invalid fixed_chan_num value!\n"); |
| return UAP_FAILURE; |
| } |
| dfs_test.fixed_new_chan = (t_u8)val; |
| dfs_test.action = ACTION_SET; |
| } else { |
| printf("ERR: invalid number of arguments! Must be 0 or 4.\n"); |
| print_dfstesting_usage(); |
| return UAP_FAILURE; |
| } |
| dfs_test.subcmd = UAP_DFS_TESTING; |
| |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)&dfs_test; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| perror(""); |
| printf("ERR: UAP_DFS_TESTING is not supported by %s\n", |
| dev_name); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| |
| if (argc) |
| printf("DFS testing setting successful!\n"); |
| else |
| printf("DFS testing settings:\n" |
| " user_cac_period = %d msec\n" |
| " user_nop_period = %d sec\n" |
| " no_channel_change = %d\n" |
| " fixed_channel_num = %d\n", |
| dfs_test.usr_cac_period, dfs_test.usr_nop_period, |
| dfs_test.no_chan_change, dfs_test.fixed_new_chan); |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| #endif /* DFS_SUPPORT && DFS_TESTING_SUPPORT */ |
| |
| /** |
| * @brief Show usage information for the cscount_cfg |
| * command |
| * |
| * $return N/A |
| */ |
| void |
| print_cscount_cfg_usage(void) |
| { |
| printf("\nUsage : cscount [<n>]"); |
| printf("\n Where <n> "); |
| printf("\n 5-20: No of beacons with Channel Switch Count IE\n"); |
| return; |
| } |
| |
| /** |
| * @brief Set/get cs_count configuration |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_cscount_cfg(int argc, char *argv[]) |
| { |
| int opt; |
| cscount_cfg_t cscount_cfg; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_cscount_cfg_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| /* Check arguments */ |
| |
| memset(&cscount_cfg, 0, sizeof(cscount_cfg)); |
| if (argc == 0) { |
| cscount_cfg.action = ACTION_GET; |
| } else if (argc == 1) { |
| if ((t_u32)A2HEXDECIMAL(argv[0]) < 5 |
| && (t_u32)A2HEXDECIMAL(argv[0]) > 20) { |
| printf("ERR:Invalid Channel switch count value\n"); |
| return UAP_FAILURE; |
| } |
| cscount_cfg.action = ACTION_SET; |
| cscount_cfg.cs_count = (t_u32)A2HEXDECIMAL(argv[0]); |
| } else { |
| print_cscount_cfg_usage(); |
| return UAP_FAILURE; |
| } |
| cscount_cfg.subcmd = UAP_CHAN_SWITCH_COUNT_CFG; |
| |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)&cscount_cfg; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| perror(""); |
| printf("ERR: Channel switch count configuration failed\n"); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| |
| /* Handle response */ |
| if (cscount_cfg.action == ACTION_GET) { |
| printf("Channel Switch count = %d\n", cscount_cfg.cs_count); |
| } |
| |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Show usage information for the mgmtframectrl command |
| * |
| * $return N/A |
| */ |
| void |
| print_mgmtframectrl_usage(void) |
| { |
| printf("\nUsage : mgmtframectrl [MASK]\n"); |
| printf(" empty - Get management frame control mask\n"); |
| printf(" MASK - Set management frame control mask\n"); |
| } |
| |
| /** |
| * @brief Creates management frame control request and send to driver |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_mgmt_frame_control(int argc, char *argv[]) |
| { |
| int opt; |
| mgmt_frame_ctrl param; /* Action =0, Mask =0 */ |
| struct ifreq ifr; |
| t_s32 sockfd; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_mgmtframectrl_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| /* Check arguments */ |
| if (argc > 1) { |
| printf("ERR:wrong arguments.\n"); |
| print_mgmtframectrl_usage(); |
| return UAP_FAILURE; |
| } |
| |
| if ((argc) && (IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE)) { |
| printf("ERR: Invalid argument %s\n", argv[0]); |
| print_mgmtframectrl_usage(); |
| return UAP_FAILURE; |
| } |
| |
| memset(¶m, 0, sizeof(mgmt_frame_ctrl)); |
| param.subcmd = UAP_MGMT_FRAME_CONTROL; |
| if (argc) { |
| param.action = ACTION_SET; |
| param.mask = (t_u16)A2HEXDECIMAL(argv[0]); |
| } else { |
| param.action = ACTION_GET; |
| } |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| return UAP_FAILURE; |
| } |
| /* 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 *)¶m; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| perror(""); |
| printf("ERR:UAP_IOCTL_CMD failed\n"); |
| close(sockfd); |
| return UAP_FAILURE; |
| } |
| if (!argc) { |
| printf("Management Frame control mask = 0x%02x\n", |
| (int)param.mask); |
| } |
| /* Close socket */ |
| close(sockfd); |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @brief Show usage information for the sys_cfg_tdls_ext_cap |
| * command |
| * |
| * $return N/A |
| */ |
| void |
| print_sys_cfg_tdls_ext_cap_usage(void) |
| { |
| printf("\nUsage : sys_cfg_tdls_ext_cap [CONFIG_FILE] \n"); |
| printf("\nIf CONFIG_FILE is provided, a 'set' is performed, else a 'get' is performed.\n"); |
| printf("\n"); |
| return; |
| } |
| |
| /** |
| * @brief Get Extended capability info from firmware |
| * |
| * @param ext_cap A pointer to tdls_ext_cap tlv |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| static int |
| get_tdls_ext_cap(tlvbuf_tdls_ext_cap *ext_cap_tlv) |
| { |
| apcmdbuf_sys_configure *cmd_buf = NULL; |
| tlvbuf_tdls_ext_cap *tlv = NULL; |
| t_u8 *buffer = NULL; |
| t_u16 cmd_len = 0; |
| t_u16 buf_len = 0; |
| int ret = UAP_SUCCESS; |
| |
| /* Initialize the buffer length */ |
| buf_len = |
| sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_tdls_ext_cap) + |
| MAX_TDLS_EXT_CAP_LEN; |
| buffer = (t_u8 *)malloc(buf_len); |
| if (!buffer) { |
| printf("ERR:Cannot allocate buffer for command!\n"); |
| return UAP_FAILURE; |
| } |
| /* Initialize the command buffer */ |
| memset(buffer, 0, buf_len); |
| |
| /* Locate headers */ |
| cmd_buf = (apcmdbuf_sys_configure *)buffer; |
| tlv = (tlvbuf_tdls_ext_cap *)(buffer + sizeof(apcmdbuf_sys_configure)); |
| tlv->tag = MRVL_TDLS_EXT_CAP_TLV_ID; |
| /* Set TLV length to zero for GET request */ |
| tlv->length = 0; |
| cmd_len = |
| sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_tdls_ext_cap) + |
| tlv->length; |
| /* Fill the command buffer */ |
| cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; |
| cmd_buf->size = cmd_len; |
| cmd_buf->seq_num = 0; |
| cmd_buf->result = 0; |
| cmd_buf->action = ACTION_GET; |
| |
| endian_convert_tlv_header_out(tlv); |
| /* Send the command */ |
| ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); |
| endian_convert_tlv_header_in(tlv); |
| /* Process response */ |
| if (ret == UAP_SUCCESS) { |
| /* Verify response */ |
| if ((cmd_buf->cmd_code != |
| (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || |
| (tlv->tag != MRVL_TDLS_EXT_CAP_TLV_ID)) { |
| printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); |
| free(buffer); |
| return UAP_FAILURE; |
| } |
| |
| /* Copy response */ |
| if (cmd_buf->result == CMD_SUCCESS) { |
| memcpy(ext_cap_tlv, tlv, |
| sizeof(tlvbuf_tdls_ext_cap) + tlv->length); |
| } else { |
| ret = UAP_FAILURE; |
| printf("ERR:Could not get TDLS extended capability!\n"); |
| } |
| } else { |
| printf("ERR:Command sending failed!\n"); |
| ret = UAP_FAILURE; |
| } |
| if (buffer) |
| free(buffer); |
| return ret; |
| } |
| |
| /** |
| * @brief Read the TDLS parameters and populate structure |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @param bss Pointer to BSS configuration buffer |
| * @return UAP_SUCCESS or UAP_FAILURE |
| */ |
| static int |
| parse_tdls_config(int argc, char *argv[], tlvbuf_tdls_ext_cap *ext_cap_tlv) |
| { |
| FILE *config_file = NULL; |
| char *line = NULL; |
| char *pos = NULL; |
| char *args[30]; |
| t_u8 *buffer = NULL; |
| tlvbuf_tdls_ext_cap *prev_ext_cap_tlv = NULL; |
| int li = 0, arg_num = 0, i = 0, is_tdls_config = 0; |
| int ret = UAP_SUCCESS; |
| |
| /* Check if file exists */ |
| config_file = fopen(argv[0], "r"); |
| if (config_file == NULL) { |
| printf("\nERR:Config file can not open.\n"); |
| return UAP_FAILURE; |
| } |
| |
| buffer = (t_u8 *)malloc(MAX_TDLS_EXT_CAP_LEN); |
| if (!buffer) { |
| printf("ERR:Cannot allocate memory for buffer\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| memset(buffer, 0, MAX_TDLS_EXT_CAP_LEN); |
| prev_ext_cap_tlv = (tlvbuf_tdls_ext_cap *)buffer; |
| /* Get previous setting of extended capability from FW and copy it to ext_cap_tlv */ |
| if (UAP_SUCCESS != get_tdls_ext_cap(prev_ext_cap_tlv)) { |
| printf("ERR: Couldn't get TDLS extended capability setting!\n"); |
| return UAP_FAILURE; |
| } |
| memcpy(ext_cap_tlv, prev_ext_cap_tlv, |
| sizeof(tlvbuf_tdls_ext_cap) + prev_ext_cap_tlv->length); |
| |
| /* Parse file and process */ |
| line = (char *)malloc(MAX_CONFIG_LINE); |
| if (!line) { |
| printf("ERR:Cannot allocate memory for line\n"); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| memset(line, 0, MAX_CONFIG_LINE); |
| |
| 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 TDLS configurations */ |
| if (is_tdls_config == 1) { |
| if (strcmp(args[0], "}") == 0) { |
| is_tdls_config = 0; |
| } |
| } |
| /* Check for beginning of TDLS configurations */ |
| if (strcmp(args[0], "tdls_config") == 0) { |
| is_tdls_config = 1; |
| } |
| if (is_tdls_config) { |
| if (strcmp(args[0], "tdls_prohibit") == 0) { |
| if ((ISDIGIT(args[1]) != UAP_SUCCESS) || |
| (atoi(args[1]) < 0) || |
| (atoi(args[1]) > 1)) { |
| printf("ERR: Invalid %s value!\n", |
| args[0]); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| ext_cap_tlv->ext_cap[4] &= |
| (~TDLS_PROHIBIT_MASK); |
| ext_cap_tlv->ext_cap[4] |= |
| (atoi(args[1]) << TDLS_PROHIBIT); |
| } |
| if (strcmp(args[0], "tdls_channel_switch_prohibit") == |
| 0) { |
| if ((ISDIGIT(args[1]) != UAP_SUCCESS) || |
| (atoi(args[1]) < 0) || |
| (atoi(args[1]) > 1)) { |
| printf("ERR: Invalid %s value!\n", |
| args[0]); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| ext_cap_tlv->ext_cap[4] &= |
| (~TDLS_CHANNEL_SWITCH_PROHIBIT_MASK); |
| ext_cap_tlv->ext_cap[4] |= |
| (atoi(args[1]) << |
| TDLS_CHANNEL_SWITCH_PROHIBIT); |
| } |
| } |
| } |
| done: |
| fclose(config_file); |
| if (buffer) |
| free(buffer); |
| if (line) |
| free(line); |
| return ret; |
| } |
| |
| /** |
| * @brief Creates a sys_cfg request for setting extended capability for TDLS |
| * and sends to the driver |
| * |
| * Usage: "sys_cfg_tdls_ext_cap [CONFIG_FILE]" |
| * If CONFIG_FILE is provided, a 'set' is performed |
| * else a 'get' is performed. |
| * |
| * @param argc Number of arguments |
| * @param argv Pointer to the arguments |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| apcmd_sys_cfg_tdls_ext_cap(int argc, char *argv[]) |
| { |
| apcmdbuf_sys_configure *cmd_buf = NULL; |
| tlvbuf_tdls_ext_cap *tlv = NULL; |
| t_u8 *buffer = NULL; |
| t_u16 cmd_len = 0; |
| t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| int ret = UAP_SUCCESS; |
| int opt; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_sys_cfg_tdls_ext_cap_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| if (argc > 1) { |
| printf("ERR: Invalid arguments!\n"); |
| return UAP_FAILURE; |
| } |
| |
| /* Initialize the command buffer */ |
| buffer = (t_u8 *)malloc(buf_len); |
| if (!buffer) { |
| printf("ERR:Cannot allocate buffer for command!\n"); |
| return UAP_FAILURE; |
| } |
| memset(buffer, 0, buf_len); |
| |
| /* Locate headers */ |
| cmd_buf = (apcmdbuf_sys_configure *)buffer; |
| tlv = (tlvbuf_tdls_ext_cap *)(buffer + sizeof(apcmdbuf_sys_configure)); |
| if (argc == 1) { |
| /* Get current TDLS extended capability setting from FW and |
| parse new setting from config file */ |
| if (UAP_SUCCESS != parse_tdls_config(argc, argv, tlv)) { |
| return UAP_FAILURE; |
| } |
| } |
| /* Fill the command buffer */ |
| cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; |
| cmd_buf->seq_num = 0; |
| cmd_buf->result = 0; |
| tlv->tag = MRVL_TDLS_EXT_CAP_TLV_ID; |
| if (argc == 0) { |
| cmd_buf->action = ACTION_GET; |
| tlv->length = 0; |
| } else { |
| cmd_buf->action = ACTION_SET; |
| } |
| cmd_buf->size = |
| sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_tdls_ext_cap) + |
| tlv->length; |
| cmd_len = |
| sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_tdls_ext_cap) + |
| tlv->length; |
| endian_convert_tlv_header_out(tlv); |
| /* Send the command */ |
| ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); |
| endian_convert_tlv_header_in(tlv); |
| /* Process response */ |
| if (ret == UAP_SUCCESS) { |
| /* Verify response */ |
| if ((cmd_buf->cmd_code != |
| (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || |
| (tlv->tag != MRVL_TDLS_EXT_CAP_TLV_ID)) { |
| printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); |
| free(buffer); |
| return UAP_FAILURE; |
| } |
| /* Print response */ |
| if (cmd_buf->result == CMD_SUCCESS) { |
| if (argc == 0) { |
| printf("TDLS prohibited = %s\n", |
| (tlv-> |
| ext_cap[4] & TDLS_PROHIBIT_MASK) ? "YES" |
| : "NO"); |
| printf("TDLS Channel switch prohibited = %s\n", |
| (tlv-> |
| ext_cap[4] & |
| TDLS_CHANNEL_SWITCH_PROHIBIT_MASK) ? |
| "YES" : "NO"); |
| } else { |
| printf("TDLS setting successful\n"); |
| } |
| } else { |
| if (argc == 0) { |
| printf("ERR:Could not get tdls setting!\n"); |
| } else { |
| printf("ERR:Could not set tdls setting!\n"); |
| } |
| ret = UAP_FAILURE; |
| } |
| } else { |
| printf("ERR:Command sending failed!\n"); |
| } |
| if (buffer) |
| free(buffer); |
| return ret; |
| } |
| |
| /** |
| * @brief Show usage information for the sys_cfg_pmf command |
| * command |
| * |
| * $return N/A |
| */ |
| void |
| print_sys_cfg_pmf(void) |
| { |
| printf("\nUsage : uaputl.exe sys_cfg_pmf [MFPC] [MFPR]\n"); |
| printf("\nSet/Get PMF capabilities"); |
| printf("\n empty - Get PMF capabilites\n"); |
| printf("\n MFPC: Management frames protection capable"); |
| printf("\n 0 - Not capable"); |
| printf("\n 1 - capable"); |
| printf("\n MFPR: Management frames protection required"); |
| printf("\n don't care if MFPC is set to 0"); |
| printf("\n 0 - Not required"); |
| printf("\n 1 - required\n"); |
| return; |
| } |
| |
| int |
| apcmd_sys_cfg_pmf(int argc, char *argv[]) |
| { |
| int opt; |
| apcmdbuf_pmf_params *cmd_buf = NULL; |
| t_u8 *buf = NULL; |
| t_u16 cmd_len = 0; |
| t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; |
| int ret = UAP_SUCCESS; |
| t_u8 mfpc = 0; |
| t_u8 mfpr = 0; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_sys_cfg_pmf(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| /* Check arguments */ |
| if ((argc > 2)) { |
| printf("ERR:wrong arguments.\n"); |
| print_sys_cfg_pmf(); |
| return UAP_FAILURE; |
| } |
| |
| if (argc > 0) |
| mfpc = atoi(argv[0]); |
| |
| if (mfpc && (argc == 1)) { |
| printf("ERR:wrong arguments.\n"); |
| print_sys_cfg_pmf(); |
| return UAP_FAILURE; |
| } |
| |
| if (mfpc && (argc == 2)) |
| mfpr = atoi(argv[1]); |
| |
| /* Alloc buf for command */ |
| buf = (t_u8 *)malloc(buf_len); |
| |
| if (!buf) { |
| printf("ERR:Cannot allocate buffer from command!\n"); |
| return UAP_FAILURE; |
| } |
| memset(buf, 0, buf_len); |
| |
| /* Locate headers */ |
| cmd_len = sizeof(apcmdbuf_pmf_params); |
| cmd_buf = (apcmdbuf_pmf_params *) buf; |
| |
| /* Fill the command buffer */ |
| cmd_buf->size = cmd_len - BUF_HEADER_SIZE; |
| cmd_buf->seq_num = 0; |
| cmd_buf->result = 0; |
| cmd_buf->cmd_code = HostCmd_CMD_PMF_PARAMS; |
| if (argc == 0) |
| cmd_buf->action = ACTION_GET; |
| else |
| cmd_buf->action = ACTION_SET; |
| cmd_buf->action = uap_cpu_to_le16(cmd_buf->action); |
| cmd_buf->params.mfpc = mfpc; |
| cmd_buf->params.mfpr = mfpr; |
| |
| /* Send the command */ |
| ret = uap_ioctl((t_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("mfpc: %d, mfpr: %d\n", |
| cmd_buf->params.mfpc, cmd_buf->params.mfpr); |
| } 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 Show usage information for uap operation control command |
| * |
| * $return N/A |
| */ |
| void |
| print_uap_oper_ctrl_usage(void) |
| { |
| printf("\nUsage : uap_oper_ctrl <control> <chanopt> <bandcfg> <channel> "); |
| printf("\n set/get uap operation when in-STA disconnected from ext-AP if multi channel is disabled"); |
| printf("\n control: 0: default, do nothing"); |
| printf("\n 2: uap stops and restart automatically"); |
| printf("\n chanopt : specify which channel should be used when uap restarts automatically"); |
| printf("\n 1: uap restarts on default 2.4G/channel 6"); |
| printf("\n 2: uap restart on band/channel configured by driver previously"); |
| printf("\n 3: uap restart on band/channel configured by parameter bandcfg/channel"); |
| printf("\n bandcfg : This parameter specifies the bandwidth (BW)"); |
| printf("\n 0: 20Mhz"); |
| printf("\n 2: 40Mhz"); |
| printf("\n 3: 80Mhz"); |
| printf("\n channel : This parameter specifies the channel will be used when chanopt is 3."); |
| return; |
| } |
| |
| /** |
| * @brief Set/Get uap operation when in-STA disconnected from ext-AP |
| * @param argc Number of arguments |
| * @param argv A pointer to arguments array |
| * @return MLAN_STATUS_SUCCESS--success, otherwise--fail |
| */ |
| int |
| apcmd_uap_oper_ctrl(int argc, char *argv[]) |
| { |
| int opt; |
| uap_operation_ctrl param; |
| struct eth_priv_uap_oper_ctrl *uap_oper = NULL; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| t_u8 *respbuf = NULL; |
| |
| while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { |
| switch (opt) { |
| default: |
| print_uap_oper_ctrl_usage(); |
| return UAP_SUCCESS; |
| } |
| } |
| argc -= optind; |
| argv += optind; |
| |
| respbuf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER); |
| if (!respbuf) { |
| printf("ERR:Cannot allocate buffer for command!\n"); |
| return UAP_FAILURE; |
| } |
| memset(respbuf, 0, MRVDRV_SIZE_OF_CMD_BUFFER); |
| |
| /* Check arguments */ |
| if (argc > 4) { |
| printf("ERR: Invalid number of arguments.\n"); |
| print_uap_oper_ctrl_usage(); |
| free(respbuf); |
| return UAP_FAILURE; |
| } |
| |
| if (argc > 0) { |
| param.uap_oper.ctrl = (t_u16)A2HEXDECIMAL(argv[0]); |
| if (param.uap_oper.ctrl == 2) |
| param.uap_oper.chan_opt = (t_u16)A2HEXDECIMAL(argv[1]); |
| |
| if (argc == 4 && param.uap_oper.chan_opt == 3) { |
| param.uap_oper.bandcfg = (t_u8)A2HEXDECIMAL(argv[2]); |
| param.uap_oper.channel = (t_u8)A2HEXDECIMAL(argv[3]); |
| } |
| param.action = ACTION_SET; |
| } else { |
| param.action = ACTION_GET; |
| } |
| param.subcmd = UAP_OPERATION_CTRL; |
| |
| memcpy(respbuf, ¶m, sizeof(uap_operation_ctrl)); |
| |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| free(respbuf); |
| return UAP_FAILURE; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)respbuf; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| perror(""); |
| printf("ERR: uap operation control set/get failed\n"); |
| close(sockfd); |
| free(respbuf); |
| return UAP_FAILURE; |
| } |
| |
| /* Handle response */ |
| if (param.action == ACTION_GET) { |
| /* Process result */ |
| uap_oper = |
| (struct eth_priv_uap_oper_ctrl *)(respbuf + |
| 2 * sizeof(t_u32)); |
| printf(" uap operation control %x\n", uap_oper->ctrl); |
| printf(" uap channel operation %x\n", uap_oper->chan_opt); |
| if (uap_oper->chan_opt == 3) { |
| printf(" uap bandwidth %s\n", |
| uap_oper-> |
| bandcfg ? ((uap_oper->bandcfg == 2) ? "40Mhz" : |
| "80Mhz") : "20Mhz"); |
| printf(" uap channel %d\n", uap_oper->channel); |
| } |
| } else |
| printf("uap operation control set success!\n"); |
| /* Close socket */ |
| close(sockfd); |
| if (respbuf) |
| free(respbuf); |
| return UAP_SUCCESS; |
| } |
| |
| /** Structure of command table*/ |
| typedef struct { |
| /** Command name */ |
| char *cmd; |
| /** Command function pointer */ |
| int (*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"}, |
| {"skip_cac", apcmd_skip_cac, "\tSkip the CAC"}, |
| {"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_bss_status", apcmd_sys_cfg_bss_status, "Get BSS status"}, |
| {"sys_cfg_channel", apcmd_sys_cfg_channel, |
| "\tSet/get uAP radio channel"}, |
| {"sys_cfg_channel_ext", apcmd_sys_cfg_channel_ext, |
| "\tSet/get uAP radio channel, band and mode"}, |
| {"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, "\tSet/get uAP rates"}, |
| {"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"}, |
| {"antcfg", apcmd_antcfg, "Set/get uAP tx/rx antenna"}, |
| {"htstreamcfg", apcmd_htstreamcfg, |
| "Set/get uAP HT stream configurations"}, |
| {"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"}, |
| {"radioctrl", apcmd_radio_ctl, "Set/get uAP radio on/off"}, |
| {"sys_cfg_tx_beacon_rate", apcmd_sys_cfg_tx_beacon_rate, |
| "Set/get uAP tx beacon rate"}, |
| {"txratecfg", apcmd_tx_rate_cfg, "Set/get trasnmit data 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_ps_sta_ageout_timer", apcmd_sys_cfg_ps_sta_ageout_timer, |
| "Set/get PS 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/WPA2 cipher"}, |
| {"sys_cfg_pwk_cipher", apcmd_sys_cfg_pwk_cipher, |
| "\tSet/get uAP WPA/WPA2 pairwise cipher"}, |
| {"sys_cfg_gwk_cipher", apcmd_sys_cfg_gwk_cipher, |
| "\tSet/get uAP WPA/WPA2 group 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_sticky_tim_config", apcmd_sys_cfg_sticky_tim_config, |
| "Set/get uAP sticky TIM configuration"}, |
| {"sys_cfg_sticky_tim_sta_mac_addr", |
| apcmd_sys_cfg_sticky_tim_sta_mac_addr, |
| "Set/get uAP sticky TIM sta MAC address"}, |
| {"sys_cfg_eapol_pwk_hsk", apcmd_sys_cfg_eapol_pwk_hsk, |
| "Set/getuAP pairwise Handshake timeout value and retries"}, |
| {"sys_cfg_eapol_gwk_hsk", apcmd_sys_cfg_eapol_gwk_hsk, |
| "Set/getuAP groupwise Handshake timeout value and retries"}, |
| {"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_cfg_80211d", apcmd_cfg_80211d, "\tSet/Get 802.11D info"}, |
| {"uap_stats", apcmd_uap_stats, "\tGet uAP stats"}, |
| {"pscfg", apcmd_pscfg, "\t\tSet/get uAP power mode"}, |
| {"bss_config", apcmd_bss_config, "\tSet/get BSS configuration"}, |
| {"sta_deauth_ext", apcmd_sta_deauth_ext, "\tDeauth client"}, |
| {"coex_config", apcmd_coex_config, |
| "\tSet/get uAP BT coex configuration"}, |
| {"hscfg", apcmd_hscfg, "\t\tSet/get uAP host sleep parameters."}, |
| {"hssetpara", apcmd_hssetpara, |
| "\t\tSet/get uAP host sleep parameters."}, |
| {"addbapara", apcmd_addbapara, "\tSet/get uAP ADDBA parameters."}, |
| {"aggrpriotbl", apcmd_aggrpriotbl, |
| "\tSet/get uAP priority table for AMPDU/AMSDU."}, |
| {"addbareject", apcmd_addbareject, "\tSet/get uAP addbareject table."}, |
| {"sys_cfg_11n", apcmd_sys_cfg_11n, "\tSet/get uAP 802.11n parameters."}, |
| #ifdef RX_PACKET_COALESCE |
| {"rxpktcoal_cfg", apcmd_rx_pkt_coalesce, |
| "\tSet/get RX Packet coalesing paramterts."}, |
| #endif |
| {"httxbfcfg", apcmd_sys_cfg_tx_bf, "\tSet/get uAP TX BF parameters."}, |
| {"httxcfg", apcmd_sys_cfg_ht_tx, "\t\tSet/get uAP HT Tx parameters."}, |
| {"vhtcfg", apcmd_sys_cfg_vht, "\t\tSet/get uAP VHT parameters."}, |
| {"sys_cfg_wmm", apcmd_sys_cfg_wmm, |
| "\tSet/get uAP beacon wmm parameters."}, |
| {"sys_cfg_ap_wmm", apcmd_sys_cfg_ap_wmm, |
| "\tSet/get uAP hardware wmm parameters."}, |
| {"deepsleep", apcmd_deepsleep, "\tSet/get deepsleep mode."}, |
| {"hostcmd", apcmd_hostcmd, "\t\tSet/get hostcmd"}, |
| {"tx_data_pause", apcmd_txdatapause, |
| "\tSet/get Tx data pause settings."}, |
| {"sdcmd52rw", apcmd_cmd52_readwrite, |
| "\tRead or write using sdio command 52."}, |
| {"sys_cfg_2040_coex", apcmd_sys_cfg_2040_coex, |
| "\tSet/get 20/40 coex settings."}, |
| #if defined(DFS_TESTING_SUPPORT) |
| {"dfstesting", apcmd_dfstesting, "\tConfigure DFS Testing settings."}, |
| #endif |
| {"cscount", apcmd_cscount_cfg, "\tConfigure DFS Channel Switch Count."}, |
| {"mgmtframectrl", apcmd_mgmt_frame_control, |
| "\tSpecifies mask indicating management frames to be sent from host."}, |
| {"sys_cfg_tdls_ext_cap", apcmd_sys_cfg_tdls_ext_cap, |
| "\tSet/get TDLS parameters in extended capabilities through config file."}, |
| {"sys_cfg_restrict_client_mode", apcmd_sys_cfg_restrict_client_mode, |
| "\tSet/get the mode in which client stations can connect to the uAP."}, |
| {"sys_cfg_pmf", apcmd_sys_cfg_pmf, "\tSet/get PMF capabilities."}, |
| {"uap_oper_ctrl", apcmd_uap_oper_ctrl, |
| "\tSet/get uap operation control value."}, |
| {NULL, NULL, 0} |
| }; |
| |
| /** |
| * @brief Prints usage information of uaputl |
| * |
| * @return N/A |
| */ |
| static void |
| print_tool_usage(void) |
| { |
| int i; |
| printf("uaputl.exe - uAP utility ver %s\n", UAP_VERSION); |
| printf("Usage:\n" |
| "\tuaputl.exe [options] <command> [command parameters]\n"); |
| printf("Options:\n" |
| "\t--help\tDisplay help\n" |
| "\t-v\tDisplay version\n" |
| "\t-i <interface>\n" "\t-d <debug_level=0|1|2>\n"); |
| printf("Commands:\n"); |
| for (i = 0; ap_command[i].cmd; i++) |
| printf("\t%-4s\t\t%s\n", ap_command[i].cmd, ap_command[i].help); |
| printf("\n" |
| "For more information on the usage of each command use:\n" |
| "\tuaputl.exe <command> --help\n"); |
| } |
| |
| /**************************************************************************** |
| Global functions |
| ****************************************************************************/ |
| /** Option parameter*/ |
| static struct option ap_options[] = { |
| {"help", 0, NULL, 'h'}, |
| {"interface", 1, NULL, 'i'}, |
| {"debug", 1, NULL, 'd'}, |
| {"version", 0, NULL, 'v'}, |
| {NULL, 0, NULL, '\0'} |
| }; |
| |
| /** |
| * @brief Checks if given channel in 'a' band is valid or not. |
| * |
| * @param channel Channel number |
| * @return UAP_SUCCESS or UAP_FAILURE |
| */ |
| int |
| is_valid_a_band_channel(int channel) |
| { |
| int ret = UAP_SUCCESS; |
| switch (channel) { |
| case 16: |
| case 34: |
| case 36: |
| case 38: |
| case 40: |
| case 42: |
| case 44: |
| case 46: |
| case 48: |
| case 52: |
| case 56: |
| case 60: |
| case 64: |
| case 100: |
| case 104: |
| case 108: |
| case 112: |
| case 116: |
| case 120: |
| case 124: |
| case 128: |
| case 132: |
| case 136: |
| case 140: |
| case 144: |
| case 149: |
| case 153: |
| case 157: |
| case 161: |
| case 165: |
| break; |
| default: |
| ret = UAP_FAILURE; |
| break; |
| } |
| return ret; |
| } |
| |
| /** |
| * @brief Checks if secondary channel can be set above given primary channel in 'a' band or not. |
| * |
| * @param channel Channel number |
| * @return UAP_SUCCESS or UAP_FAILURE |
| */ |
| int |
| is_valid_a_band_channel_above(int channel) |
| { |
| int ret = UAP_SUCCESS; |
| switch (channel) { |
| case 36: |
| case 44: |
| case 52: |
| case 60: |
| case 100: |
| case 108: |
| case 116: |
| case 124: |
| case 132: |
| case 140: |
| case 149: |
| case 157: |
| break; |
| default: |
| ret = UAP_FAILURE; |
| break; |
| } |
| return ret; |
| } |
| |
| /** |
| * @brief Checks if secondary channel can be set below given primary channel in 'a' band or not. |
| * |
| * @param channel Channel number |
| * @return UAP_SUCCESS or UAP_FAILURE |
| */ |
| int |
| is_valid_a_band_channel_below(int channel) |
| { |
| int ret = UAP_SUCCESS; |
| switch (channel) { |
| case 40: |
| case 48: |
| case 56: |
| case 64: |
| case 104: |
| case 112: |
| case 120: |
| case 128: |
| case 136: |
| case 153: |
| case 161: |
| break; |
| default: |
| ret = UAP_FAILURE; |
| break; |
| } |
| return ret; |
| } |
| |
| /** |
| * @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 chan_number = 0; |
| int band = 0; |
| int ch; |
| 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) || |
| ((int)(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++) { |
| chan_number = -1; |
| band = -1; |
| sscanf(argv[i], "%d.%d", &chan_number, &band); |
| if ((chan_number == -1) || (chan_number < 1) || |
| (chan_number > MAX_CHANNELS)) { |
| printf("ERR: Channel must be in the range of 1 to %d\n", MAX_CHANNELS); |
| ret = UAP_FAILURE; |
| break; |
| } |
| if ((chan_number > MAX_CHANNELS_BG) && |
| !(is_valid_a_band_channel(chan_number))) { |
| printf("ERR: Invalid Channel in 'a' band!\n"); |
| ret = UAP_FAILURE; |
| break; |
| } |
| if ((band < -1) || (band > 1)) { |
| printf("ERR:Band must be either 0 or 1\n"); |
| ret = UAP_FAILURE; |
| break; |
| } else { |
| if (((chan_number < MAX_CHANNELS_BG) && |
| (chan_number != 8) && |
| (chan_number != 12) && (band == 1)) |
| || ((chan_number > MAX_CHANNELS_BG) |
| && (band == 0))) { |
| printf("ERR:Invalid band for given channel\n"); |
| 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; |
| } |
| if ((ret != UAP_FAILURE) && |
| (has_diff_band(argc, argv) != UAP_SUCCESS)) { |
| printf("ERR: Scan channel list should contain channels from only one band\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 > 2) || (ISDIGIT(argv[0]) == 0)) { |
| printf("ERR:Invalid Protocol\n"); |
| ret = UAP_FAILURE; |
| } else |
| ret = is_protocol_valid(atoi(argv[0])); |
| break; |
| case AKM_SUITE: |
| if (argc == 2) { |
| if (A2HEXDECIMAL(argv[1]) & |
| ~(KEY_MGMT_PSK | KEY_MGMT_PSK_SHA256 | KEY_MGMT_EAP |
| | KEY_MGMT_NONE)) { |
| printf("ERR: Invalid AKM suite\n"); |
| ret = UAP_FAILURE; |
| } |
| } |
| 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]) & ~CHANNEL_MODE_MASK)) { |
| printf("ERR: Invalid Mode\n"); |
| ret = UAP_FAILURE; |
| } |
| if ((atoi(argv[1]) & BITMAP_ACS_MODE) && |
| (atoi(argv[0]) != 0)) { |
| printf("ERR: Channel must be 0 for ACS; MODE = 1.\n"); |
| ret = UAP_FAILURE; |
| } |
| if ((atoi(argv[1]) & BITMAP_CHANNEL_ABOVE) && |
| (atoi(argv[1]) & BITMAP_CHANNEL_BELOW)) { |
| printf("ERR: secondary channel above and below both are enabled\n"); |
| ret = UAP_FAILURE; |
| } |
| } |
| if ((argc == 1) || (!(atoi(argv[1]) & BITMAP_ACS_MODE))) { |
| 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; |
| } |
| if ((atoi(argv[0]) > MAX_CHANNELS_BG) && |
| !(is_valid_a_band_channel(atoi(argv[0])))) { |
| printf("ERR: Invalid Channel in 'a' band!\n"); |
| ret = UAP_FAILURE; |
| } |
| ch = atoi(argv[0]); |
| if (ch <= MAX_CHANNELS_BG) { |
| if ((argc == 2) && |
| (atoi(argv[1]) & |
| BITMAP_CHANNEL_ABOVE) && |
| (atoi(argv[0]) > |
| MAX_CHANNEL_ABOVE)) { |
| printf("ERR: only allow channel 1-9 for secondary channel above\n"); |
| ret = UAP_FAILURE; |
| } |
| if ((argc == 2) && |
| (atoi(argv[1]) & |
| BITMAP_CHANNEL_BELOW) && |
| ((atoi(argv[0]) < MIN_CHANNEL_BELOW) |
| || (atoi(argv[0]) == 14))) { |
| printf("ERR: only allow channel 5-13 for secondary channel below\n"); |
| ret = UAP_FAILURE; |
| } |
| } else { |
| if (argc == 2) { |
| if ((atoi(argv[1]) & |
| BITMAP_CHANNEL_BELOW) && |
| !is_valid_a_band_channel_below |
| (atoi(argv[0]))) { |
| printf("ERR: For given primary channel secondary channel can not be set below\n"); |
| ret = UAP_FAILURE; |
| } |
| if ((atoi(argv[1]) & |
| BITMAP_CHANNEL_ABOVE) && |
| !is_valid_a_band_channel_above |
| (atoi(argv[0]))) { |
| printf("ERR: For given primary channel secondary channel can not be set above\n"); |
| ret = UAP_FAILURE; |
| } |
| } |
| } |
| } |
| } |
| break; |
| case CHANNEL_EXT: |
| if (argc > 3) { |
| printf("ERR: Incorrect arguments for channel_ext.\n"); |
| ret = UAP_FAILURE; |
| } else { |
| if (argc == 3) { |
| if ((ISDIGIT(argv[2]) == 0) || |
| (atoi(argv[2]) & ~CHANNEL_MODE_MASK)) { |
| printf("ERR: Invalid Mode\n"); |
| ret = UAP_FAILURE; |
| } |
| if ((atoi(argv[2]) & BITMAP_ACS_MODE) && |
| (atoi(argv[0]) != 0)) { |
| printf("ERR: Channel must be 0 for ACS; MODE = 1.\n"); |
| ret = UAP_FAILURE; |
| } |
| if ((atoi(argv[2]) & BITMAP_CHANNEL_ABOVE) && |
| (atoi(argv[2]) & BITMAP_CHANNEL_BELOW)) { |
| printf("ERR: secondary channel above and below both are enabled\n"); |
| ret = UAP_FAILURE; |
| } |
| } |
| if ((argc == 2) && |
| ((ISDIGIT(argv[1]) == 0) || (atoi(argv[1]) < 0) || |
| atoi(argv[1]) > 1)) { |
| printf("ERR:Invalid band\n"); |
| ret = UAP_FAILURE; |
| } |
| if ((argc == 1) || |
| ((argc == 3) && |
| !(atoi(argv[2]) & BITMAP_ACS_MODE))) { |
| 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; |
| } |
| if ((atoi(argv[0]) > MAX_CHANNELS_BG) && |
| !(is_valid_a_band_channel(atoi(argv[0])))) { |
| printf("ERR: Invalid Channel in 'a' band!\n"); |
| ret = UAP_FAILURE; |
| } |
| ch = atoi(argv[0]); |
| if (ch <= MAX_CHANNELS_BG) { |
| if ((argc == 3) && |
| (atoi(argv[2]) & |
| BITMAP_CHANNEL_ABOVE) && |
| (atoi(argv[0]) > |
| MAX_CHANNEL_ABOVE)) { |
| printf("ERR: only allow channel 1-9 for secondary channel above\n"); |
| ret = UAP_FAILURE; |
| } |
| if ((argc == 3) && |
| (atoi(argv[2]) & |
| BITMAP_CHANNEL_BELOW) && |
| ((atoi(argv[0]) < MIN_CHANNEL_BELOW) |
| || (atoi(argv[0]) == 14))) { |
| printf("ERR: only allow channel 5-13 for secondary channel below\n"); |
| ret = UAP_FAILURE; |
| } |
| } else { |
| if (argc == 3) { |
| if ((atoi(argv[2]) & |
| BITMAP_CHANNEL_BELOW) && |
| !is_valid_a_band_channel_below |
| (atoi(argv[0]))) { |
| printf("ERR: For given primary channel secondary channel can not be set below\n"); |
| ret = UAP_FAILURE; |
| } |
| if ((atoi(argv[2]) & |
| BITMAP_CHANNEL_ABOVE) && |
| !is_valid_a_band_channel_above |
| (atoi(argv[0]))) { |
| printf("ERR: For given primary channel secondary channel can not be set above\n"); |
| ret = UAP_FAILURE; |
| } |
| } |
| } |
| } |
| } |
| break; |
| case BAND: |
| if (argc > 1) { |
| printf("ERR: Incorrect number of BAND arguments.\n"); |
| ret = UAP_FAILURE; |
| } else { |
| if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || |
| (atoi(argv[0]) > 1)) { |
| printf("ERR: Invalid band.\n"); |
| 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) && |
| (atoi(argv[0]) != 2))) { |
| printf("ERR:Illegal parameter %s for BROADCASTSSID. Must be either '0', '1' or '2'.\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 RSNREPLAYPROT: |
| if (argc != 1) { |
| printf("ERR:Incorrect number of arguments for RSNREPLAYPROT\n"); |
| ret = UAP_FAILURE; |
| } else { |
| if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || |
| (atoi(argv[0]) > 1)) { |
| printf("ERR:Illegal RSNREPLAYPROT parameter %s. Must be either '0' or '1'.\n", argv[0]); |
| 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 TXRATECFG: |
| if (argc > 3) { |
| printf("ERR:Incorrect number of arguments for DATARATE\n"); |
| ret = UAP_FAILURE; |
| } else { |
| if (((argc >= 1) && |
| (IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE)) || |
| ((argc >= 2) && |
| (IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE)) |
| || ((argc >= 3) && |
| (IS_HEX_OR_DIGIT(argv[2]) == UAP_FAILURE)) |
| ) { |
| printf("ERR: invalid Tx data rate\n"); |
| ret = UAP_FAILURE; |
| } else if (argc >= 1) { |
| if (A2HEXDECIMAL(argv[0]) == 0xFF) { |
| if (argc != 1) { |
| printf("ERR: invalid auto rate input\n"); |
| ret = UAP_FAILURE; |
| } |
| } else { |
| if ((A2HEXDECIMAL(argv[0]) < 0) || |
| (A2HEXDECIMAL(argv[0]) > 2) |
| ) { |
| printf("ERR: invalid format\n"); |
| ret = UAP_FAILURE; |
| } |
| if (argc >= 2) { |
| if ((A2HEXDECIMAL(argv[1]) < 0) |
| || |
| ((A2HEXDECIMAL(argv[0]) == |
| 0) && |
| (A2HEXDECIMAL(argv[1]) > |
| 11)) || |
| ((A2HEXDECIMAL(argv[0]) == |
| 1) && |
| (A2HEXDECIMAL(argv[1]) != |
| 32) && |
| (A2HEXDECIMAL(argv[1]) > |
| 15) |
| )) { |
| printf("ERR:Incorrect TxRate %s.\n", argv[1]); |
| ret = UAP_FAILURE; |
| } |
| } |
| if (argc == 3) { |
| if ((A2HEXDECIMAL(argv[0]) != 2) |
| || |
| ((A2HEXDECIMAL(argv[2]) < 1) |
| || (A2HEXDECIMAL(argv[2]) > |
| 2))) { |
| printf("ERR:Incorrect nss.\n"); |
| ret = UAP_FAILURE; |
| } |
| } |
| } |
| } |
| } |
| break; |
| case MCBCDATARATE: |
| case TXBEACONRATE: |
| 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]) > 15))) { |
| printf("ERR:Illegal PKTFWD parameter %s. Must be within '0' and '15'.\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 PSSTAAGEOUTTIMER: |
| if (argc != 1) { |
| printf("ERR:Incorrect number of arguments for PSSTAAGEOUTTIMER.\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 PSSTAAGEOUTTIMER %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) && |
| (atoi(argv[0]) != |
| 255))) { |
| printf("ERR:Illegal AUTHMODE parameter %s. Must be either '0','1' or 255''.\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]) <= 0)) { |
| printf("ERR:Invalid STA_NUM argument %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 STICKYTIMCONFIG: |
| if ((argc != 1) && (argc != 3)) { |
| printf("ERR:Incorrect number of arguments for STICKY_TIM_CONFIG\n"); |
| ret = UAP_FAILURE; |
| } else { |
| if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || |
| (atoi(argv[0]) > 2)) { |
| printf("ERR:Enable parameter must be 0, 1 or 2\n"); |
| ret = UAP_FAILURE; |
| break; |
| } |
| if (((atoi(argv[0]) != 1) && (argc > 1))) { |
| printf("ERR: Invalid arguments\n"); |
| ret = UAP_FAILURE; |
| break; |
| } |
| if ((atoi(argv[0]) == 1) && (argc != 3)) { |
| printf("ERR: Both duration and sticky bit mask must be provided for ENABLE = 1\n"); |
| ret = UAP_FAILURE; |
| break; |
| } |
| if (argc > 1) { |
| if ((ISDIGIT(argv[1]) == 0)) { |
| printf("ERR: Invalid duration\n"); |
| ret = UAP_FAILURE; |
| break; |
| } |
| if ((ISDIGIT(argv[2]) == 0) || |
| (atoi(argv[2]) < 1) || |
| (atoi(argv[2]) > 3)) { |
| printf("ERR:Invalid sticky bit mask\n"); |
| ret = UAP_FAILURE; |
| break; |
| } |
| } |
| } |
| break; |
| case STICKYTIMSTAMACADDR: |
| if ((argc != 1) && (argc != 2)) { |
| printf("ERR:Incorrect number of STICKY_TIM_STA_MAC_ADDR arguments\n"); |
| ret = UAP_FAILURE; |
| } else { |
| if ((argc == 2) && |
| ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || |
| (atoi(argv[0]) > 1))) { |
| printf("ERR:Invalid control parameter\n"); |
| ret = UAP_FAILURE; |
| break; |
| } |
| } |
| break; |
| case COEX2040CONFIG: |
| if (argc != 1) { |
| printf("ERR: Incorrect number of 2040 COEX CONFIG arguments\n"); |
| ret = UAP_FAILURE; |
| } else { |
| if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || |
| (atoi(argv[0]) > 1)) { |
| printf("ERR:Invalid enable parameter\n"); |
| ret = UAP_FAILURE; |
| break; |
| } |
| } |
| break; |
| case EAPOL_PWK_HSK: |
| if (argc != 2) { |
| printf("ERR:Incorrect number of EAPOL_PWK_HSK arguments.\n"); |
| ret = UAP_FAILURE; |
| } else { |
| if ((ISDIGIT(argv[0]) == 0) || (ISDIGIT(argv[1]) == 0) |
| || (atoi(argv[0]) < 0) || (atoi(argv[1]) < 0)) { |
| printf("ERR:Illegal parameters for EAPOL_PWK_HSK. Must be digits greater than equal to zero.\n"); |
| } |
| } |
| break; |
| case EAPOL_GWK_HSK: |
| if (argc != 2) { |
| printf("ERR:Incorrect number of EAPOL_GWK_HSK arguments.\n"); |
| ret = UAP_FAILURE; |
| } else { |
| if ((ISDIGIT(argv[0]) == 0) || (ISDIGIT(argv[1]) == 0) |
| || (atoi(argv[0]) < 0) || (atoi(argv[1]) < 0)) { |
| printf("ERR:Illegal parameters for EAPOL_GWK_HSK. Must be digits greater than equal to zero.\n"); |
| } |
| } |
| break; |
| case PREAMBLETYPE: |
| if (argc != 1) { |
| printf("ERR:Incorrect number of arguments for PREAMBLE TYPE\n"); |
| ret = UAP_FAILURE; |
| } else { |
| if ((ISDIGIT(argv[0]) == 0) || |
| (atoi(argv[0]) > MAX_PREAMBLE_TYPE) || |
| (atoi(argv[0]) < 0)) { |
| printf("ERR:PREAMBLE TYPE must be in the range of [0:%d]. The input was %s.\n", MAX_PREAMBLE_TYPE, argv[0]); |
| ret = UAP_FAILURE; |
| } |
| } |
| break; |
| |
| case COEX_COMM_BITMAP: |
| if (argc != 1) { |
| printf("ERR:Incorrect number of argument 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_COMM_AP_COEX: |
| if (argc != 1) { |
| printf("ERR:Incorrect number of argument for APBTCoex.\n"); |
| ret = UAP_FAILURE; |
| } else { |
| if ((IS_HEX_OR_DIGIT(argv[0]) == 0) || |
| (atoi(argv[0]) < 0) || (atoi(argv[0]) > 1)) { |
| printf("ERR: APBTCoex 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; |
| case PWK_CIPHER: |
| if ((argc != 1) && (argc != 2)) { |
| printf("ERR:Incorrect number of arguments for pwk_cipher.\n"); |
| ret = UAP_FAILURE; |
| } else { |
| if ((ISDIGIT(argv[0]) == 0) || |
| (atoi(argv[0]) & ~PROTOCOL_BITMAP)) { |
| printf("Invalid Protocol paramter.\n"); |
| ret = UAP_FAILURE; |
| } |
| if (argc == 2) { |
| if ((ISDIGIT(argv[1]) == 0) || |
| (atoi(argv[1]) & ~CIPHER_BITMAP)) { |
| printf("Invalid pairwise cipher.\n"); |
| ret = UAP_FAILURE; |
| } |
| } |
| } |
| break; |
| case GWK_CIPHER: |
| if (argc != 1) { |
| printf("ERR:Incorrect number of arguments for gwk_cipher.\n"); |
| ret = UAP_FAILURE; |
| } else { |
| if ((ISDIGIT(argv[0]) == 0) || |
| (atoi(argv[0]) & ~CIPHER_BITMAP) || |
| (atoi(argv[0]) == AES_CCMP_TKIP)) { |
| printf("Invalid group cipher.\n"); |
| ret = UAP_FAILURE; |
| } |
| } |
| break; |
| case RESTRICT_CLIENT_MODE: |
| if ((argc != 1) && (argc != 2)) { |
| printf("ERR: Incorrect number of arguments.\n"); |
| ret = UAP_FAILURE; |
| } else { |
| if ((ISDIGIT(argv[0]) == 0) || ((argc == 2) && |
| ((IS_HEX_OR_DIGIT |
| (argv[1]) == 0) || |
| ((atoi(argv[0]) < 0) || |
| (atoi(argv[0]) > |
| 1))))) { |
| printf("ERR: Invalid arguments\n"); |
| ret = UAP_FAILURE; |
| } |
| if ((atoi(argv[0]) == 1) && (argc == 1)) { |
| printf("ERR: Mode_config parameter must be provided to enable this feature.\n"); |
| ret = UAP_FAILURE; |
| } |
| if ((argc == 2) && |
| (((A2HEXDECIMAL(argv[1]) << 8) != B_ONLY_MASK) && |
| ((A2HEXDECIMAL(argv[1]) << 8) != G_ONLY_MASK) && |
| ((A2HEXDECIMAL(argv[1]) << 8) != A_ONLY_MASK) && |
| ((A2HEXDECIMAL(argv[1]) << 8) != N_ONLY_MASK) && |
| ((A2HEXDECIMAL(argv[1]) << 8) != AC_ONLY_MASK))) { |
| printf("ERR: Exactly one mode can be enabled at a time.\n"); |
| 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, t_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] = (t_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(t_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 Pointer to auth tlv |
| * |
| * $return N/A |
| */ |
| void |
| print_auth(tlvbuf_auth_mode *tlv) |
| { |
| switch (tlv->auth_mode) { |
| case 0: |
| printf("AUTHMODE = Open authentication\n"); |
| break; |
| case 1: |
| printf("AUTHMODE = Shared key authentication\n"); |
| break; |
| case 255: |
| printf("AUTHMODE = Auto (open and shared key)\n"); |
| break; |
| default: |
| printf("ERR: Invalid authmode=%d\n", tlv->auth_mode); |
| break; |
| } |
| } |
| |
| /** |
| * |
| * @brief Show cipher tlv |
| * |
| * @param tlv Pointer to cipher tlv |
| * |
| * $return N/A |
| */ |
| void |
| print_cipher(tlvbuf_cipher *tlv) |
| { |
| switch (tlv->pairwise_cipher) { |
| 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->pairwise_cipher); |
| break; |
| } |
| switch (tlv->group_cipher) { |
| 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->group_cipher); |
| break; |
| } |
| } |
| |
| /** |
| * @brief Show pairwise cipher tlv |
| * |
| * @param tlv Pointer to pairwise cipher tlv |
| * |
| * $return N/A |
| */ |
| void |
| print_pwk_cipher(tlvbuf_pwk_cipher *tlv) |
| { |
| switch (tlv->protocol) { |
| case PROTOCOL_WPA: |
| printf("Protocol WPA : "); |
| break; |
| case PROTOCOL_WPA2: |
| printf("Protocol WPA2 : "); |
| break; |
| default: |
| printf("Unknown Protocol 0x%x\n", tlv->protocol); |
| break; |
| } |
| |
| switch (tlv->pairwise_cipher) { |
| 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->pairwise_cipher); |
| break; |
| } |
| } |
| |
| /** |
| * @brief Show group cipher tlv |
| * |
| * @param tlv Pointer to group cipher tlv |
| * |
| * $return N/A |
| */ |
| void |
| print_gwk_cipher(tlvbuf_gwk_cipher *tlv) |
| { |
| switch (tlv->group_cipher) { |
| 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->group_cipher); |
| break; |
| } |
| } |
| |
| /** |
| * @brief Show mac filter tlv |
| * |
| * @param tlv Pointer to filter tlv |
| * |
| * $return N/A |
| */ |
| void |
| print_mac_filter(tlvbuf_sta_mac_addr_filter *tlv) |
| { |
| int i; |
| switch (tlv->filter_mode) { |
| case 0: |
| printf("Filter Mode = Filter table is disabled\n"); |
| return; |
| case 1: |
| if (!tlv->count) { |
| printf("No mac address is allowed to connect\n"); |
| } else { |
| printf("Filter Mode = Allow mac address specified in the allowed list\n"); |
| } |
| break; |
| case 2: |
| if (!tlv->count) { |
| printf("No mac address is blocked\n"); |
| } else { |
| 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->mac_address[i * ETH_ALEN]); |
| printf("\n"); |
| } |
| } |
| |
| /** |
| * @brief Show rate tlv |
| * |
| * @param tlv Pointer to rate tlv |
| * |
| * $return N/A |
| */ |
| void |
| print_rate(tlvbuf_rates *tlv) |
| { |
| int flag = 0; |
| int i; |
| t_u16 tlv_len; |
| |
| tlv_len = *(t_u8 *)&tlv->length; |
| tlv_len |= (*((t_u8 *)&tlv->length + 1) << 8); |
| |
| printf("Basic Rates ="); |
| for (i = 0; i < tlv_len; i++) { |
| if (tlv->operational_rates[i] > (BASIC_RATE_SET_BIT - 1)) { |
| flag = flag ? : 1; |
| printf(" 0x%x", tlv->operational_rates[i]); |
| } |
| } |
| printf("%s\nNon-Basic Rates =", flag ? "" : " ( none ) "); |
| for (flag = 0, i = 0; i < tlv_len; i++) { |
| if (tlv->operational_rates[i] < BASIC_RATE_SET_BIT) { |
| flag = flag ? : 1; |
| printf(" 0x%x", tlv->operational_rates[i]); |
| } |
| } |
| printf("%s\n", flag ? "" : " ( none ) "); |
| } |
| |
| /** |
| * @brief Show all the tlv in the buf |
| * |
| * @param buf Pointer to tlv buffer |
| * @param len Tlv buffer len |
| * |
| * $return N/A |
| */ |
| void |
| print_tlv(t_u8 *buf, t_u16 len) |
| { |
| tlvbuf_header *pcurrent_tlv = (tlvbuf_header *)buf; |
| int tlv_buf_left = len; |
| t_u16 tlv_type; |
| t_u16 tlv_len; |
| t_u16 tlv_val_16; |
| t_u32 tlv_val_32; |
| t_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_bss_status *bss_status_tlv; |
| tlvbuf_rts_threshold *rts_tlv; |
| tlvbuf_mcbc_data_rate *mcbcrate_tlv; |
| tlvbuf_pkt_fwd_ctl *pkt_fwd_tlv; |
| tlvbuf_sta_ageout_timer *ageout_tlv; |
| tlvbuf_ps_sta_ageout_timer *ps_ageout_tlv; |
| tlvbuf_auth_mode *auth_tlv; |
| tlvbuf_protocol *proto_tlv; |
| tlvbuf_akmp *akmp_tlv; |
| tlvbuf_cipher *cipher_tlv; |
| tlvbuf_pwk_cipher *pwk_cipher_tlv; |
| tlvbuf_gwk_cipher *gwk_cipher_tlv; |
| tlvbuf_group_rekey_timer *rekey_tlv; |
| tlvbuf_wpa_passphrase *psk_tlv; |
| 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; |
| 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_eapol_pwk_hsk_timeout *pwk_timeout_tlv; |
| tlvbuf_eapol_pwk_hsk_retries *pwk_retries_tlv; |
| tlvbuf_eapol_gwk_hsk_timeout *gwk_timeout_tlv; |
| tlvbuf_eapol_gwk_hsk_retries *gwk_retries_tlv; |
| tlvbuf_channel_config *channel_tlv; |
| tlvbuf_channel_list *chnlist_tlv; |
| channel_list *pchan_list; |
| t_u16 custom_ie_len; |
| tlvbuf_rsn_replay_prot *replay_prot_tlv; |
| tlvbuf_custom_ie *custom_ie_tlv; |
| custom_ie *custom_ie_ptr; |
| tlvbuf_max_mgmt_ie *max_mgmt_ie_tlv; |
| tlvbuf_wmm_para_t *wmm_para_tlv; |
| int flag = 0; |
| tlvbuf_htcap_t *ht_cap_tlv; |
| tlvbuf_htinfo_t *ht_info_tlv; |
| tlvbuf_2040_coex *coex_2040_tlv; |
| |
| #ifdef RX_PACKET_COALESCE |
| tlvbuf_rx_pkt_coal_t *rx_pkt_coal_tlv; |
| #endif |
| |
| #if DEBUG |
| uap_printf(MSG_DEBUG, "tlv total len=%d\n", len); |
| #endif |
| while (tlv_buf_left >= (int)sizeof(tlvbuf_header)) { |
| tlv_type = *(t_u8 *)&pcurrent_tlv->type; |
| tlv_type |= (*((t_u8 *)&pcurrent_tlv->type + 1) << 8); |
| tlv_len = *(t_u8 *)&pcurrent_tlv->len; |
| tlv_len |= (*((t_u8 *)&pcurrent_tlv->len + 1) << 8); |
| if ((sizeof(tlvbuf_header) + tlv_len) > |
| (unsigned int)tlv_buf_left) { |
| printf("wrong tlv: tlv_len=%d, tlv_buf_left=%d\n", |
| tlv_len, tlv_buf_left); |
| break; |
| } |
| switch (tlv_type) { |
| case MRVL_AP_MAC_ADDRESS_TLV_ID: |
| mac_tlv = (tlvbuf_ap_mac_address *)pcurrent_tlv; |
| printf("AP MAC address = "); |
| print_mac(mac_tlv->ap_mac_addr); |
| printf("\n"); |
| break; |
| case MRVL_SSID_TLV_ID: |
| memset(ssid, 0, sizeof(ssid)); |
| ssid_tlv = (tlvbuf_ssid *)pcurrent_tlv; |
| memcpy(ssid, ssid_tlv->ssid, tlv_len); |
| printf("SSID = %s\n", ssid); |
| break; |
| case MRVL_BEACON_PERIOD_TLV_ID: |
| beacon_tlv = (tlvbuf_beacon_period *)pcurrent_tlv; |
| tlv_val_16 = *(t_u8 *)&beacon_tlv->beacon_period_ms; |
| tlv_val_16 |= |
| (*((t_u8 *)&beacon_tlv->beacon_period_ms + 1) << |
| 8); |
| printf("Beacon period = %d\n", tlv_val_16); |
| break; |
| case MRVL_DTIM_PERIOD_TLV_ID: |
| dtim_tlv = (tlvbuf_dtim_period *)pcurrent_tlv; |
| printf("DTIM period = %d\n", dtim_tlv->dtim_period); |
| break; |
| case MRVL_CHANNELCONFIG_TLV_ID: |
| channel_tlv = (tlvbuf_channel_config *)pcurrent_tlv; |
| printf("Channel = %d\n", channel_tlv->chan_number); |
| printf("Band = %s\n", |
| (channel_tlv->bandcfg.chanBand == |
| BAND_5GHZ) ? "5GHz" : "2.4GHz"); |
| printf("Channel Select Mode = %s\n", |
| (channel_tlv->bandcfg.scanMode == |
| SCAN_MODE_ACS) ? "ACS" : "Manual"); |
| if (channel_tlv->bandcfg.chan2Offset == SEC_CHAN_NONE) |
| printf("no secondary channel\n"); |
| else if (channel_tlv->bandcfg.chan2Offset == |
| SEC_CHAN_ABOVE) |
| printf("secondary channel is above primary channel\n"); |
| else if (channel_tlv->bandcfg.chan2Offset == |
| SEC_CHAN_BELOW) |
| printf("secondary channel is below primary channel\n"); |
| break; |
| case MRVL_CHANNELLIST_TLV_ID: |
| chnlist_tlv = (tlvbuf_channel_list *)pcurrent_tlv; |
| printf("Channels List = "); |
| pchan_list = |
| (channel_list *) & (chnlist_tlv->chan_list); |
| if (tlv_len % sizeof(channel_list)) { |
| break; |
| } |
| for (i = 0; |
| (unsigned int)i < (tlv_len / sizeof(channel_list)); |
| i++) { |
| printf("\n%d\t%sGHz", pchan_list->chan_number, |
| (pchan_list->bandcfg.chanBand == |
| BAND_5GHZ) ? "5" : "2.4"); |
| pchan_list++; |
| } |
| printf("\n"); |
| break; |
| case MRVL_RSN_REPLAY_PROT_TLV_ID: |
| replay_prot_tlv = |
| (tlvbuf_rsn_replay_prot *)pcurrent_tlv; |
| printf("RSN replay protection = %s\n", |
| replay_prot_tlv-> |
| rsn_replay_prot ? "enabled" : "disabled"); |
| break; |
| case MRVL_RATES_TLV_ID: |
| rates_tlv = (tlvbuf_rates *)pcurrent_tlv; |
| print_rate(rates_tlv); |
| break; |
| case MRVL_TX_POWER_TLV_ID: |
| txpower_tlv = (tlvbuf_tx_power *)pcurrent_tlv; |
| printf("Tx power = %d dBm\n", |
| txpower_tlv->tx_power_dbm); |
| break; |
| case MRVL_BCAST_SSID_CTL_TLV_ID: |
| bcast_tlv = (tlvbuf_bcast_ssid_ctl *)pcurrent_tlv; |
| printf("SSID broadcast = %s\n", |
| (bcast_tlv->bcast_ssid_ctl == |
| 1) ? "enabled" : "disabled"); |
| break; |
| case MRVL_PREAMBLE_CTL_TLV_ID: |
| preamble_tlv = (tlvbuf_preamble_ctl *)pcurrent_tlv; |
| printf("Preamble type = %s\n", |
| (preamble_tlv->preamble_type == |
| 0) ? "auto" : ((preamble_tlv->preamble_type == |
| 1) ? "short" : "long")); |
| break; |
| case MRVL_BSS_STATUS_TLV_ID: |
| bss_status_tlv = (tlvbuf_bss_status *)pcurrent_tlv; |
| printf("BSS status = %s\n", |
| (bss_status_tlv->bss_status == |
| 0) ? "stopped" : "started"); |
| break; |
| case MRVL_RTS_THRESHOLD_TLV_ID: |
| rts_tlv = (tlvbuf_rts_threshold *)pcurrent_tlv; |
| tlv_val_16 = *(t_u8 *)&rts_tlv->rts_threshold; |
| tlv_val_16 |= |
| (*((t_u8 *)&rts_tlv->rts_threshold + 1) << 8); |
| printf("RTS threshold = %d\n", tlv_val_16); |
| break; |
| case MRVL_FRAG_THRESHOLD_TLV_ID: |
| frag_tlv = (tlvbuf_frag_threshold *)pcurrent_tlv; |
| tlv_val_16 = *(t_u8 *)&frag_tlv->frag_threshold; |
| tlv_val_16 |= |
| (*((t_u8 *)&frag_tlv->frag_threshold + 1) << 8); |
| printf("Fragmentation threshold = %d\n", tlv_val_16); |
| break; |
| case MRVL_MCBC_DATA_RATE_TLV_ID: |
| mcbcrate_tlv = (tlvbuf_mcbc_data_rate *)pcurrent_tlv; |
| tlv_val_16 = *(t_u8 *)&mcbcrate_tlv->mcbc_datarate; |
| tlv_val_16 |= |
| (*((t_u8 *)&mcbcrate_tlv->mcbc_datarate + 1) << |
| 8); |
| if (mcbcrate_tlv->mcbc_datarate == 0) |
| printf("MCBC data rate = auto\n"); |
| else |
| printf("MCBC data rate = 0x%x\n", tlv_val_16); |
| break; |
| case MRVL_PKT_FWD_CTL_TLV_ID: |
| pkt_fwd_tlv = (tlvbuf_pkt_fwd_ctl *)pcurrent_tlv; |
| printf("%s handles packet forwarding -\n", |
| ((pkt_fwd_tlv->pkt_fwd_ctl & PKT_FWD_FW_BIT) == |
| 0) ? "Host" : "Firmware"); |
| printf("\tIntra-BSS broadcast packets are %s\n", |
| ((pkt_fwd_tlv-> |
| pkt_fwd_ctl & PKT_FWD_INTRA_BCAST) == |
| 0) ? "allowed" : "denied"); |
| printf("\tIntra-BSS unicast packets are %s\n", |
| ((pkt_fwd_tlv-> |
| pkt_fwd_ctl & PKT_FWD_INTRA_UCAST) == |
| 0) ? "allowed" : "denied"); |
| printf("\tInter-BSS unicast packets are %s\n", |
| ((pkt_fwd_tlv-> |
| pkt_fwd_ctl & PKT_FWD_INTER_UCAST) == |
| 0) ? "allowed" : "denied"); |
| break; |
| case MRVL_STA_AGEOUT_TIMER_TLV_ID: |
| ageout_tlv = (tlvbuf_sta_ageout_timer *)pcurrent_tlv; |
| tlv_val_32 = *(t_u8 *)&ageout_tlv->sta_ageout_timer_ms; |
| tlv_val_32 |= |
| (*((t_u8 *)&ageout_tlv->sta_ageout_timer_ms + 1) |
| << 8); |
| tlv_val_32 |= |
| (*((t_u8 *)&ageout_tlv->sta_ageout_timer_ms + 2) |
| << 16); |
| tlv_val_32 |= |
| (*((t_u8 *)&ageout_tlv->sta_ageout_timer_ms + 3) |
| << 24); |
| printf("STA ageout timer = %d\n", (int)tlv_val_32); |
| break; |
| case MRVL_PS_STA_AGEOUT_TIMER_TLV_ID: |
| ps_ageout_tlv = |
| (tlvbuf_ps_sta_ageout_timer *)pcurrent_tlv; |
| tlv_val_32 = |
| *(t_u8 *)&ps_ageout_tlv->ps_sta_ageout_timer_ms; |
| tlv_val_32 |= |
| (* |
| ((t_u8 *)&ps_ageout_tlv-> |
| ps_sta_ageout_timer_ms + 1) << 8); |
| tlv_val_32 |= |
| (* |
| ((t_u8 *)&ps_ageout_tlv-> |
| ps_sta_ageout_timer_ms + 2) << 16); |
| tlv_val_32 |= |
| (* |
| ((t_u8 *)&ps_ageout_tlv-> |
| ps_sta_ageout_timer_ms + 3) << 24); |
| printf("PS STA ageout timer = %d\n", (int)tlv_val_32); |
| break; |
| case MRVL_AUTH_TLV_ID: |
| auth_tlv = (tlvbuf_auth_mode *)pcurrent_tlv; |
| print_auth(auth_tlv); |
| break; |
| case MRVL_PROTOCOL_TLV_ID: |
| proto_tlv = (tlvbuf_protocol *)pcurrent_tlv; |
| tlv_val_16 = *(t_u8 *)&proto_tlv->protocol; |
| tlv_val_16 |= |
| (*((t_u8 *)&proto_tlv->protocol + 1) << 8); |
| print_protocol(tlv_val_16); |
| break; |
| case MRVL_AKMP_TLV_ID: |
| akmp_tlv = (tlvbuf_akmp *)pcurrent_tlv; |
| tlv_val_16 = *(t_u8 *)&akmp_tlv->key_mgmt; |
| tlv_val_16 |= (*((t_u8 *)&akmp_tlv->key_mgmt + 1) << 8); |
| if (tlv_val_16 & (KEY_MGMT_PSK | KEY_MGMT_PSK_SHA256)) { |
| if (tlv_val_16 & KEY_MGMT_PSK) |
| printf("KeyMgmt = PSK\n"); |
| if (tlv_val_16 & KEY_MGMT_PSK_SHA256) |
| printf("KeyMgmt = PSK_SHA256\n"); |
| tlv_val_16 = |
| *(t_u8 *)&akmp_tlv->key_mgmt_operation; |
| if (tlv_len > sizeof(t_u16)) { |
| tlv_val_16 |= |
| (* |
| ((t_u8 *)&akmp_tlv-> |
| key_mgmt_operation + 1) << 8); |
| printf("Key Exchange on : %s.\n", |
| (tlv_val_16 & 0x01) ? "Host" : |
| "Device"); |
| printf("1x Authentication on : %s.\n", |
| (tlv_val_16 & 0x10) ? "Host" : |
| "Device"); |
| } |
| } |
| if (tlv_val_16 & KEY_MGMT_EAP) |
| printf("KeyMgmt = EAP"); |
| if (tlv_val_16 & KEY_MGMT_NONE) |
| printf("KeyMgmt = NONE"); |
| break; |
| case MRVL_CIPHER_TLV_ID: |
| cipher_tlv = (tlvbuf_cipher *)pcurrent_tlv; |
| print_cipher(cipher_tlv); |
| break; |
| case MRVL_CIPHER_PWK_TLV_ID: |
| pwk_cipher_tlv = (tlvbuf_pwk_cipher *)pcurrent_tlv; |
| pwk_cipher_tlv->protocol = |
| uap_le16_to_cpu(pwk_cipher_tlv->protocol); |
| print_pwk_cipher(pwk_cipher_tlv); |
| break; |
| case MRVL_CIPHER_GWK_TLV_ID: |
| gwk_cipher_tlv = (tlvbuf_gwk_cipher *)pcurrent_tlv; |
| print_gwk_cipher(gwk_cipher_tlv); |
| break; |
| case MRVL_GRP_REKEY_TIME_TLV_ID: |
| rekey_tlv = (tlvbuf_group_rekey_timer *)pcurrent_tlv; |
| tlv_val_32 = *(t_u8 *)&rekey_tlv->group_rekey_time_sec; |
| tlv_val_32 |= |
| (*((t_u8 *)&rekey_tlv->group_rekey_time_sec + 1) |
| << 8); |
| tlv_val_32 |= |
| (*((t_u8 *)&rekey_tlv->group_rekey_time_sec + 2) |
| << 16); |
| tlv_val_32 |= |
| (*((t_u8 *)&rekey_tlv->group_rekey_time_sec + 3) |
| << 24); |
| if (tlv_val_32 == 0) |
| printf("Group re-key time = disabled\n"); |
| else |
| printf("Group re-key time = %d second\n", |
| tlv_val_32); |
| break; |
| case MRVL_WPA_PASSPHRASE_TLV_ID: |
| psk_tlv = (tlvbuf_wpa_passphrase *)pcurrent_tlv; |
| if (tlv_len > 0) { |
| printf("WPA passphrase = "); |
| for (i = 0; i < tlv_len; 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 *)pcurrent_tlv; |
| print_wep_key(wep_tlv); |
| break; |
| case MRVL_STA_MAC_ADDR_FILTER_TLV_ID: |
| filter_tlv = (tlvbuf_sta_mac_addr_filter *)pcurrent_tlv; |
| print_mac_filter(filter_tlv); |
| break; |
| case MRVL_MAX_STA_CNT_TLV_ID: |
| max_sta_tlv = (tlvbuf_max_sta_num *)pcurrent_tlv; |
| tlv_val_16 = |
| *(t_u8 *)&max_sta_tlv->max_sta_num_configured; |
| tlv_val_16 |= |
| (* |
| ((t_u8 *)&max_sta_tlv->max_sta_num_configured + |
| 1) << 8); |
| printf("Max Station Number configured = %d\n", |
| tlv_val_16); |
| if (max_sta_tlv->length == 4) { |
| tlv_val_16 = |
| *(t_u8 *)&max_sta_tlv-> |
| max_sta_num_supported; |
| tlv_val_16 |= |
| (* |
| ((t_u8 *)&max_sta_tlv-> |
| max_sta_num_supported + 1) << 8); |
| printf("Max Station Number supported = %d\n", |
| tlv_val_16); |
| } |
| break; |
| case MRVL_RETRY_LIMIT_TLV_ID: |
| retry_limit_tlv = (tlvbuf_retry_limit *)pcurrent_tlv; |
| printf("Retry Limit = %d\n", |
| retry_limit_tlv->retry_limit); |
| break; |
| case MRVL_EAPOL_PWK_HSK_TIMEOUT_TLV_ID: |
| pwk_timeout_tlv = |
| (tlvbuf_eapol_pwk_hsk_timeout *)pcurrent_tlv; |
| pwk_timeout_tlv->pairwise_update_timeout = |
| uap_le32_to_cpu(pwk_timeout_tlv-> |
| pairwise_update_timeout); |
| printf("Pairwise handshake timeout = %d\n", |
| pwk_timeout_tlv->pairwise_update_timeout); |
| break; |
| case MRVL_EAPOL_PWK_HSK_RETRIES_TLV_ID: |
| pwk_retries_tlv = |
| (tlvbuf_eapol_pwk_hsk_retries *)pcurrent_tlv; |
| pwk_retries_tlv->pwk_retries = |
| uap_le32_to_cpu(pwk_retries_tlv->pwk_retries); |
| printf("Pairwise handshake retries = %d\n", |
| pwk_retries_tlv->pwk_retries); |
| break; |
| case MRVL_EAPOL_GWK_HSK_TIMEOUT_TLV_ID: |
| gwk_timeout_tlv = |
| (tlvbuf_eapol_gwk_hsk_timeout *)pcurrent_tlv; |
| gwk_timeout_tlv->groupwise_update_timeout = |
| uap_le32_to_cpu(gwk_timeout_tlv-> |
| groupwise_update_timeout); |
| printf("Groupwise handshake timeout = %d\n", |
| gwk_timeout_tlv->groupwise_update_timeout); |
| break; |
| case MRVL_EAPOL_GWK_HSK_RETRIES_TLV_ID: |
| gwk_retries_tlv = |
| (tlvbuf_eapol_gwk_hsk_retries *)pcurrent_tlv; |
| gwk_retries_tlv->gwk_retries = |
| uap_le32_to_cpu(gwk_retries_tlv->gwk_retries); |
| printf("Groupwise handshake retries = %d\n", |
| gwk_retries_tlv->gwk_retries); |
| break; |
| case MRVL_MGMT_IE_LIST_TLV_ID: |
| custom_ie_tlv = (tlvbuf_custom_ie *)pcurrent_tlv; |
| custom_ie_len = tlv_len; |
| custom_ie_ptr = (custom_ie *)(custom_ie_tlv->ie_data); |
| while (custom_ie_len >= sizeof(custom_ie)) { |
| custom_ie_ptr->ie_index = |
| uap_le16_to_cpu(custom_ie_ptr-> |
| ie_index); |
| custom_ie_ptr->ie_length = |
| uap_le16_to_cpu(custom_ie_ptr-> |
| ie_length); |
| custom_ie_ptr->mgmt_subtype_mask = |
| uap_le16_to_cpu(custom_ie_ptr-> |
| mgmt_subtype_mask); |
| printf("Index [%d]\n", custom_ie_ptr->ie_index); |
| if (custom_ie_ptr->ie_length) |
| printf("Management Subtype Mask = 0x%02x\n", custom_ie_ptr->mgmt_subtype_mask == 0 ? UAP_CUSTOM_IE_AUTO_MASK : custom_ie_ptr->mgmt_subtype_mask); |
| else |
| printf("Management Subtype Mask = 0x%02x\n", custom_ie_ptr->mgmt_subtype_mask); |
| hexdump_data("IE Buffer", |
| (void *)custom_ie_ptr->ie_buffer, |
| (custom_ie_ptr->ie_length), ' '); |
| custom_ie_len -= |
| sizeof(custom_ie) + |
| custom_ie_ptr->ie_length; |
| custom_ie_ptr = |
| (custom_ie *)((t_u8 *)custom_ie_ptr + |
| sizeof(custom_ie) + |
| custom_ie_ptr->ie_length); |
| } |
| custom_ie_present = 1; |
| break; |
| case MRVL_MAX_MGMT_IE_TLV_ID: |
| max_mgmt_ie_tlv = (tlvbuf_max_mgmt_ie *)pcurrent_tlv; |
| max_mgmt_ie_tlv->count = |
| uap_le16_to_cpu(max_mgmt_ie_tlv->count); |
| for (i = 0; i < max_mgmt_ie_tlv->count; i++) { |
| max_mgmt_ie_tlv->info[i].buf_size = |
| uap_le16_to_cpu(max_mgmt_ie_tlv-> |
| info[i].buf_size); |
| max_mgmt_ie_tlv->info[i].buf_count = |
| uap_le16_to_cpu(max_mgmt_ie_tlv-> |
| info[i].buf_count); |
| printf("buf%d_size = %d\n", i, |
| max_mgmt_ie_tlv->info[i].buf_size); |
| printf("number of buffers = %d\n", |
| max_mgmt_ie_tlv->info[i].buf_count); |
| printf("\n"); |
| } |
| max_mgmt_ie_print = 1; |
| break; |
| case MRVL_BT_COEX_COMMON_CFG_TLV_ID: |
| printf("Coex common configuration:\n"); |
| coex_common_tlv = |
| (tlvbuf_coex_common_cfg *)pcurrent_tlv; |
| printf("\tConfig Bitmap = 0x%02x\n", |
| uap_le32_to_cpu(coex_common_tlv->config_bitmap)); |
| printf("\tAP Coex Enabled = %d\n", |
| uap_le32_to_cpu(coex_common_tlv->ap_bt_coex)); |
| break; |
| |
| case MRVL_BT_COEX_SCO_CFG_TLV_ID: |
| printf("Coex sco configuration:\n"); |
| coex_sco_tlv = (tlvbuf_coex_sco_cfg *)pcurrent_tlv; |
| 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 *)pcurrent_tlv; |
| 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 *)pcurrent_tlv; |
| printf("\tNull not sent = %d\n", |
| uap_le32_to_cpu(coex_stats_tlv->null_not_sent)); |
| printf("\tNull queued = %d\n", |
| uap_le32_to_cpu(coex_stats_tlv->null_queued)); |
| printf("\tNull not queued = %d\n", |
| uap_le32_to_cpu(coex_stats_tlv-> |
| null_not_queued)); |
| printf("\tCF End queued = %d\n", |
| uap_le32_to_cpu(coex_stats_tlv->cf_end_queued)); |
| printf("\tCF End not queued = %d\n", |
| uap_le32_to_cpu(coex_stats_tlv-> |
| cf_end_not_queued)); |
| printf("\tNull allocation failures = %d\n", |
| uap_le32_to_cpu(coex_stats_tlv-> |
| null_alloc_fail)); |
| printf("\tCF End allocation failures = %d\n", |
| uap_le32_to_cpu(coex_stats_tlv-> |
| cf_end_alloc_fail)); |
| break; |
| case HT_CAPABILITY_TLV_ID: |
| printf("\nHT Capability Info: \n"); |
| ht_cap_tlv = (tlvbuf_htcap_t *)pcurrent_tlv; |
| if (!ht_cap_tlv->ht_cap.supported_mcs_set[0]) { |
| printf("802.11n is disabled\n"); |
| } else { |
| printf("802.11n is enabled\n"); |
| printf("ht_cap_info=0x%x, ampdu_param=0x%x tx_bf_cap=%#x\n", uap_le16_to_cpu(ht_cap_tlv->ht_cap.ht_cap_info), ht_cap_tlv->ht_cap.ampdu_param, uap_le32_to_cpu(ht_cap_tlv->ht_cap.tx_bf_cap)); |
| printf("supported MCS set:\n"); |
| for (i = 0; i < MCS_SET_LEN; i++) { |
| printf("0x%x ", |
| ht_cap_tlv->ht_cap. |
| supported_mcs_set[i]); |
| } |
| printf("\n"); |
| } |
| break; |
| case HT_INFO_TLV_ID: |
| ht_info_tlv = (tlvbuf_htinfo_t *)pcurrent_tlv; |
| if (ht_info_tlv->length) { |
| printf("\nHT Information Element: \n"); |
| printf("Primary channel = %d\n", |
| ht_info_tlv->ht_info.pri_chan); |
| printf("Secondary channel offset = %d\n", |
| (int)GET_SECONDARY_CHAN(ht_info_tlv-> |
| ht_info.field2)); |
| printf("STA channel width = %dMHz\n", |
| IS_CHANNEL_WIDTH_40(ht_info_tlv->ht_info. |
| field2) ? 40 : 20); |
| printf("RIFS %s\n", |
| IS_RIFS_ALLOWED(ht_info_tlv->ht_info. |
| field2) ? "Allowed" : |
| "Prohibited"); |
| ht_info_tlv->ht_info.field3 = |
| uap_le16_to_cpu(ht_info_tlv->ht_info. |
| field3); |
| ht_info_tlv->ht_info.field4 = |
| uap_le16_to_cpu(ht_info_tlv->ht_info. |
| field4); |
| printf("HT Protection = %d\n", |
| (int)GET_HT_PROTECTION(ht_info_tlv-> |
| ht_info.field3)); |
| printf("Non-Greenfield HT STAs present: %s\n", |
| NONGF_STA_PRESENT(ht_info_tlv->ht_info. |
| field3) ? "Yes" : |
| "No"); |
| printf("OBSS Non-HT STAs present: %s\n", |
| OBSS_NONHT_STA_PRESENT(ht_info_tlv-> |
| ht_info. |
| field3) ? "Yes" : |
| "No"); |
| for (i = 0; i < MCS_SET_LEN; i++) { |
| if (ht_info_tlv->ht_info. |
| basic_mcs_set[i]) { |
| printf("Basic_mcs_set: \n"); |
| flag = 1; |
| break; |
| } |
| } |
| if (flag) { |
| for (i = 0; i < MCS_SET_LEN; i++) |
| printf("%x ", |
| ht_info_tlv->ht_info. |
| basic_mcs_set[i]); |
| printf("\n"); |
| } |
| } |
| break; |
| case MRVL_2040_BSS_COEX_CONTROL_TLV_ID: |
| coex_2040_tlv = (tlvbuf_2040_coex *)pcurrent_tlv; |
| printf("20/40 coex = %s\n", |
| (coex_2040_tlv-> |
| enable) ? "enabled" : "disabled"); |
| break; |
| case VENDOR_SPECIFIC_IE_TLV_ID: |
| wmm_para_tlv = (tlvbuf_wmm_para_t *)pcurrent_tlv; |
| printf("wmm parameters:\n"); |
| printf("\tqos_info = 0x%x\n", |
| wmm_para_tlv->wmm_para.qos_info); |
| printf("\tBE: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", |
| wmm_para_tlv->wmm_para.ac_params[AC_BE]. |
| aci_aifsn.aifsn, |
| wmm_para_tlv->wmm_para.ac_params[AC_BE].ecw. |
| ecw_max, |
| wmm_para_tlv->wmm_para.ac_params[AC_BE].ecw. |
| ecw_min, |
| uap_le16_to_cpu(wmm_para_tlv->wmm_para. |
| ac_params[AC_BE].tx_op_limit)); |
| printf("\tBK: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", |
| wmm_para_tlv->wmm_para.ac_params[AC_BK]. |
| aci_aifsn.aifsn, |
| wmm_para_tlv->wmm_para.ac_params[AC_BK].ecw. |
| ecw_max, |
| wmm_para_tlv->wmm_para.ac_params[AC_BK].ecw. |
| ecw_min, |
| uap_le16_to_cpu(wmm_para_tlv->wmm_para. |
| ac_params[AC_BK].tx_op_limit)); |
| printf("\tVI: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", |
| wmm_para_tlv->wmm_para.ac_params[AC_VI]. |
| aci_aifsn.aifsn, |
| wmm_para_tlv->wmm_para.ac_params[AC_VI].ecw. |
| ecw_max, |
| wmm_para_tlv->wmm_para.ac_params[AC_VI].ecw. |
| ecw_min, |
| uap_le16_to_cpu(wmm_para_tlv->wmm_para. |
| ac_params[AC_VI].tx_op_limit)); |
| printf("\tVO: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", |
| wmm_para_tlv->wmm_para.ac_params[AC_VO]. |
| aci_aifsn.aifsn, |
| wmm_para_tlv->wmm_para.ac_params[AC_VO].ecw. |
| ecw_max, |
| wmm_para_tlv->wmm_para.ac_params[AC_VO].ecw. |
| ecw_min, |
| uap_le16_to_cpu(wmm_para_tlv->wmm_para. |
| ac_params[AC_VO].tx_op_limit)); |
| break; |
| #ifdef RX_PACKET_COALESCE |
| case MRVL_RX_PKT_COAL_TLV_ID: |
| rx_pkt_coal_tlv = (tlvbuf_rx_pkt_coal_t *)pcurrent_tlv; |
| printf("RX packet coalesce threshold=%d\n", |
| uap_le32_to_cpu(rx_pkt_coal_tlv->rx_pkt_count)); |
| printf("RX packet coalesce timeout in msec=%d\n", |
| uap_le16_to_cpu(rx_pkt_coal_tlv->delay)); |
| break; |
| #endif |
| default: |
| break; |
| } |
| tlv_buf_left -= (sizeof(tlvbuf_header) + tlv_len); |
| pcurrent_tlv = (tlvbuf_header *)(pcurrent_tlv->data + tlv_len); |
| } |
| return; |
| } |
| |
| /** |
| * @brief Checks if command requires driver handling, and if so, |
| * repackage and send as regular command, instead of hostcmd. |
| * |
| * @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 |
| * @param reroute_ret Pointer to return value of rerouted command |
| * @return UAP_SUCCESS (handled here, further processing not needed) |
| * or UAP_FAILURE (not handled here, proceed as usual) |
| */ |
| static int |
| uap_ioctl_reroute(t_u8 *cmd, t_u16 *size, t_u16 buf_size, int *reroute_ret) |
| { |
| t_u8 reroute = 0; |
| t_u16 cmd_code = 0; |
| t_u16 cmd_action = 0; |
| apcmdbuf_cfg_80211d *hcmd_domain = NULL; |
| apcmdbuf_snmp_mib *hcmd_snmp = NULL; |
| tlvbuf_header *tlv = NULL; |
| struct ifreq ifr; |
| t_s32 sockfd; |
| t_u8 *buf = NULL; |
| t_u16 buf_len = 0; |
| snmp_mib_param *snmp_param = NULL; |
| domain_info_param *domain_param = NULL; |
| |
| /* assume input is a hostcmd */ |
| cmd_code = ((apcmdbuf *)(cmd))->cmd_code; |
| |
| /* just check if we need to re-route right now */ |
| switch (cmd_code) { |
| case HostCmd_SNMP_MIB: |
| hcmd_snmp = (apcmdbuf_snmp_mib *)cmd; |
| tlv = (tlvbuf_header *)(cmd + sizeof(apcmdbuf_snmp_mib)); |
| cmd_action = uap_le16_to_cpu(hcmd_snmp->action); |
| /* reroute CMD_SNMP_MIB: SET */ |
| if (cmd_action == ACTION_SET) { |
| reroute = 1; |
| buf_len = |
| sizeof(snmp_mib_param) + |
| uap_le16_to_cpu(tlv->len); |
| } |
| break; |
| case HostCmd_CMD_802_11D_DOMAIN_INFO: |
| hcmd_domain = (apcmdbuf_cfg_80211d *)cmd; |
| cmd_action = uap_le16_to_cpu(hcmd_domain->action); |
| /* reroute CMD_DOMAIN_INFO: SET */ |
| if (cmd_action == ACTION_SET) { |
| reroute = 1; |
| buf_len = sizeof(domain_info_param) + (*size |
| - |
| sizeof |
| (apcmdbuf_cfg_80211d) |
| + |
| sizeof |
| (domain_param_t)); |
| } |
| break; |
| } |
| |
| /* Exit early if not re-routing */ |
| if (!reroute || uap_ioctl_no_reroute) |
| return UAP_FAILURE; |
| |
| /* Prepare buffer */ |
| #if DEBUG |
| uap_printf(MSG_DEBUG, "DBG: rerouting CMD 0x%04x\n", cmd_code); |
| #endif |
| buf = (t_u8 *)malloc(buf_len); |
| if (!buf) { |
| printf("ERR:Cannot allocate buffer for command!\n"); |
| goto done_no_socket; |
| } |
| memset(buf, 0, buf_len); |
| |
| /* Prepare param */ |
| switch (cmd_code) { |
| case HostCmd_SNMP_MIB: |
| snmp_param = (snmp_mib_param *)buf; |
| snmp_param->subcmd = UAP_SNMP_MIB; |
| snmp_param->action = cmd_action; |
| snmp_param->oid = uap_le16_to_cpu(tlv->type); |
| snmp_param->oid_val_len = uap_le16_to_cpu(tlv->len); |
| memcpy(snmp_param->oid_value, tlv->data, |
| MIN(sizeof(t_u32), snmp_param->oid_val_len)); |
| break; |
| case HostCmd_CMD_802_11D_DOMAIN_INFO: |
| domain_param = (domain_info_param *)buf; |
| domain_param->subcmd = UAP_DOMAIN_INFO; |
| domain_param->action = cmd_action; |
| memcpy(domain_param->tlv, &hcmd_domain->domain, |
| buf_len - sizeof(domain_info_param)); |
| tlv = (tlvbuf_header *)domain_param->tlv; |
| tlv->type = uap_le16_to_cpu(tlv->type); |
| tlv->len = uap_le16_to_cpu(tlv->len); |
| |
| break; |
| } |
| #if DEBUG |
| /* Dump request buffer */ |
| hexdump("Reroute Request buffer", buf, buf_len, ' '); |
| #endif |
| |
| /* Open socket */ |
| if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| printf("ERR:Cannot open socket\n"); |
| goto done_no_socket; |
| } |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)buf; |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) { |
| *reroute_ret = UAP_FAILURE; |
| perror(""); |
| #if DEBUG |
| uap_printf(MSG_DEBUG, "ERR: reroute of CMD 0x%04x failed\n", |
| cmd_code); |
| #endif |
| goto done; |
| } |
| *reroute_ret = UAP_SUCCESS; |
| |
| done: |
| /* Close socket */ |
| close(sockfd); |
| done_no_socket: |
| if (buf) |
| free(buf); |
| |
| return UAP_SUCCESS; |
| } |
| |
| /** |
| * @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(t_u8 *cmd, t_u16 *size, t_u16 buf_size) |
| { |
| struct ifreq ifr; |
| apcmdbuf *header = NULL; |
| t_s32 sockfd; |
| int reroute_ret = 0; |
| mrvl_priv_cmd *mrvl_cmd = NULL; |
| t_u8 *buf = NULL, *temp = NULL; |
| t_u16 mrvl_header_len = 0; |
| int ret = UAP_SUCCESS; |
| |
| #ifdef WIFI_DIRECT_SUPPORT |
| if (strncmp(dev_name, "wfd", 3)) |
| #endif |
| if (uap_ioctl_reroute(cmd, size, buf_size, &reroute_ret) == |
| UAP_SUCCESS) { |
| return reroute_ret; |
| } |
| |
| 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; |
| } |
| *(t_u32 *)cmd = buf_size - BUF_HEADER_SIZE; |
| |
| mrvl_header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_HOSTCMD); |
| buf = (unsigned char *)malloc(buf_size + sizeof(mrvl_priv_cmd) + |
| mrvl_header_len); |
| if (buf == NULL) |
| return UAP_FAILURE; |
| |
| memset(buf, 0, buf_size + sizeof(mrvl_priv_cmd) + mrvl_header_len); |
| /* Fill up buffer */ |
| mrvl_cmd = (mrvl_priv_cmd *)buf; |
| mrvl_cmd->buf = buf + sizeof(mrvl_priv_cmd); |
| mrvl_cmd->used_len = 0; |
| mrvl_cmd->total_len = buf_size + mrvl_header_len; |
| /* Copy Marvell command string */ |
| temp = mrvl_cmd->buf; |
| strncpy((char *)temp, CMD_MARVELL, strlen(CMD_MARVELL)); |
| temp += (strlen(CMD_MARVELL)); |
| /* Insert command string */ |
| strncpy((char *)temp, PRIV_CMD_HOSTCMD, strlen(PRIV_CMD_HOSTCMD)); |
| temp += (strlen(PRIV_CMD_HOSTCMD)); |
| |
| memcpy(temp, (t_u8 *)cmd, *size); |
| |
| /* Initialize the ifr structure */ |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1); |
| ifr.ifr_ifru.ifru_data = (void *)mrvl_cmd; |
| header = (apcmdbuf *)(buf + sizeof(mrvl_priv_cmd) + mrvl_header_len); |
| header->size = *size - BUF_HEADER_SIZE; |
| if (header->cmd_code == APCMD_SYS_CONFIGURE) { |
| apcmdbuf_sys_configure *sys_cfg; |
| sys_cfg = (apcmdbuf_sys_configure *)header; |
| sys_cfg->action = uap_cpu_to_le16(sys_cfg->action); |
| } |
| endian_convert_request_header(header); |
| #if DEBUG |
| /* Dump request buffer */ |
| hexdump("Request buffer", mrvl_cmd, |
| *size + sizeof(mrvl_priv_cmd) + mrvl_header_len, ' '); |
| #endif |
| /* Perform ioctl */ |
| errno = 0; |
| if (ioctl(sockfd, MRVLPRIVCMD, &ifr)) { |
| perror(""); |
| printf("ERR:MRVLPRIVCMD is not supported by %s\n", dev_name); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| endian_convert_response_header(header); |
| header->cmd_code &= HostCmd_CMD_ID_MASK; |
| header->cmd_code |= 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); |
| ret = UAP_FAILURE; |
| goto done; |
| } |
| memcpy(cmd, (t_u8 *)header, *size + BUF_HEADER_SIZE); |
| #if DEBUG |
| /* Dump respond buffer */ |
| hexdump("Respond buffer", mrvl_cmd, |
| *size + BUF_HEADER_SIZE + sizeof(mrvl_priv_cmd) + |
| mrvl_header_len, ' '); |
| #endif |
| |
| done: |
| /* Close socket */ |
| close(sockfd); |
| if (buf) |
| free(buf); |
| return ret; |
| } |
| |
| /** |
| * @brief Get protocol from the firmware |
| * |
| * @param proto A pointer to protocol var |
| * @return UAP_SUCCESS/UAP_FAILURE |
| */ |
| int |
| get_sys_cfg_protocol(t_u16 *proto) |
| { |
| apcmdbuf_sys_configure *cmd_buf = NULL; |
| tlvbuf_protocol *tlv = NULL; |
| t_u8 *buffer = NULL; |
| t_u16 cmd_len; |
| int ret = UAP_FAILURE; |
| |
| cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_protocol); |
| /* Initialize the command buffer */ |
| buffer = (t_u8 *)malloc(cmd_len); |
| if (!buffer) { |
| printf("ERR:Cannot allocate buffer for command!\n"); |
| return ret; |
| } |
| memset(buffer, 0, cmd_len); |
| /* Locate headers */ |
| cmd_buf = (apcmdbuf_sys_configure *)buffer; |
| tlv = (tlvbuf_protocol *)(buffer + sizeof(apcmdbuf_sys_configure)); |
| /* Fill the command buffer */ |
| cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; |
| cmd_buf->size = cmd_len; |
| cmd_buf->seq_num = 0; |
| cmd_buf->result = 0; |
| cmd_buf->action = ACTION_GET; |
| tlv->tag = MRVL_PROTOCOL_TLV_ID; |
| tlv->length = 2; |
| endian_convert_tlv_header_out(tlv); |
| /* Send the command */ |
| ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, cmd_len); |
| endian_convert_tlv_header_in(tlv); |
| |
| /* Process response */ |
| if (ret == UAP_SUCCESS) { |
| /* Verify response */ |
| if (cmd_buf->cmd_code != |
| (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) { |
| printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); |
| free(buffer); |
| return UAP_FAILURE; |
| } |
| |
| if (cmd_buf->result == CMD_SUCCESS) { |
| tlv->protocol = uap_le16_to_cpu(tlv->protocol); |
| memcpy(proto, &tlv->protocol, sizeof(tlv->protocol)); |
| } else { |
| ret = UAP_FAILURE; |
| } |
| } |
| if (buffer) |
| free(buffer); |
| return ret; |
| } |
| |
| /** |
| * @brief Check cipher is valid or not |
| * |
| * @param pairwisecipher Pairwise cipher |
| * @param groupcipher Group cipher |
| * @param protocol Protocol |
| * @param enable_11n 11n enabled or not. |
| * @return UAP_SUCCESS or UAP_FAILURE |
| */ |
| int |
| is_cipher_valid_with_11n(int pairwisecipher, int groupcipher, |
| int protocol, int enable_11n) |
| { |
| if ((pairwisecipher == CIPHER_NONE) && (groupcipher == CIPHER_NONE)) |
| return UAP_SUCCESS; |
| if (pairwisecipher == CIPHER_TKIP) { |
| /* Ok to have TKIP in mixed mode */ |
| if (enable_11n && protocol != PROTOCOL_WPA2_MIXED) { |
| printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n"); |
| return UAP_FAILURE; |
| } |
| } |
| 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_AES_CCMP) && (groupcipher == CIPHER_TKIP)) |
| return UAP_SUCCESS; |
| if ((pairwisecipher == CIPHER_BITMAP) && (groupcipher == CIPHER_TKIP)) |
| return UAP_SUCCESS; |
| return UAP_FAILURE; |
| } |
| |
| /** |
| * @brief Check cipher is valid or not based on proto |
| * |
| * @param pairwisecipher Pairwise cipher |
| * @param groupcipher Group cipher |
| * @param protocol Protocol |
| * @return UAP_SUCCESS or UAP_FAILURE |
| */ |
| int |
| is_cipher_valid_with_proto(int pairwisecipher, int groupcipher, int protocol) |
| { |
| HTCap_t htcap; |
| |
| if ((pairwisecipher == CIPHER_NONE) && (groupcipher == CIPHER_NONE)) |
| return UAP_SUCCESS; |
| if (pairwisecipher == CIPHER_TKIP) { |
| /* Ok to have TKIP in mixed mode */ |
| if (protocol != PROTOCOL_WPA2_MIXED) { |
| memset(&htcap, 0, sizeof(htcap)); |
| if (UAP_SUCCESS == get_sys_cfg_11n(&htcap)) { |
| if (htcap.supported_mcs_set[0]) { |
| printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n"); |
| return UAP_FAILURE; |
| } |
| } |
| } |
| } |
| 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_AES_CCMP) && (groupcipher == CIPHER_TKIP)) |
| return UAP_SUCCESS; |
| if ((pairwisecipher == CIPHER_BITMAP) && (groupcipher == CIPHER_TKIP)) |
| return UAP_SUCCESS; |
| return UAP_FAILURE; |
| } |
| |
| /** |
| * @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) |
| { |
| HTCap_t htcap; |
| t_u16 proto = 0; |
| |
| if ((pairwisecipher == CIPHER_NONE) && (groupcipher == CIPHER_NONE)) |
| return UAP_SUCCESS; |
| if (pairwisecipher == CIPHER_TKIP) { |
| if (UAP_SUCCESS == get_sys_cfg_protocol(&proto)) { |
| /* Ok to have TKIP in mixed mode */ |
| if (proto != PROTOCOL_WPA2_MIXED) { |
| memset(&htcap, 0, sizeof(htcap)); |
| if (UAP_SUCCESS == get_sys_cfg_11n(&htcap)) { |
| if (htcap.supported_mcs_set[0]) { |
| printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n"); |
| return UAP_FAILURE; |
| } |
| } |
| } |
| } |
| } |
| 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_AES_CCMP) && (groupcipher == CIPHER_TKIP)) |
| 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; |
| int ret = 0; |
| 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); |
| #if DEBUG |
| uap_printf(MSG_DEBUG, "debug_level=%x\n", debug_level); |
| #endif |
| 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; |
| ret = ap_command[i].func(argc, argv); |
| break; |
| } |
| if (!ap_command[i].cmd) { |
| printf("ERR: %s is not supported\n", argv[0]); |
| exit(1); |
| } |
| if (ret == UAP_FAILURE) |
| return -1; |
| else |
| return 0; |
| } |