/** @file mlanhostcmd.c * * @brief This file contains mlanconfig helper functions * * * Copyright 2014-2020 NXP * * NXP CONFIDENTIAL * The source code contained or described herein and all documents related to * the source code (Materials) are owned by NXP, its * suppliers and/or its licensors. Title to the Materials remains with NXP, * its suppliers and/or its licensors. The Materials contain * trade secrets and proprietary and confidential information of NXP, its * suppliers and/or its licensors. The Materials are protected by worldwide copyright * and trade secret laws and treaty provisions. No part of the Materials may be * used, copied, reproduced, modified, published, uploaded, posted, * transmitted, distributed, or disclosed in any way without NXP's prior * express written permission. * * No license under any patent, copyright, trade secret or other intellectual * property right is granted to or conferred upon you by disclosure or delivery * of the Materials, either expressly, by implication, inducement, estoppel or * otherwise. Any license under such intellectual property rights must be * express and approved by NXP in writing. * */ /************************************************************************ Change log: 11/26/2008: initial version ************************************************************************/ #include "mlanconfig.h" #include "mlanhostcmd.h" #ifndef MIN /** Find minimum value */ #define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif /* MIN */ /******************************************************** Local Variables ********************************************************/ /******************************************************** Global Variables ********************************************************/ /******************************************************** Local Functions ********************************************************/ /** * @brief get hostcmd data * * @param ln A pointer to line number * @param buf A pointer to hostcmd data * @param size A pointer to the return size of hostcmd buffer * @return MLAN_STATUS_SUCCESS */ static int mlan_get_hostcmd_data(FILE * fp, int *ln, t_u8 *buf, t_u16 *size) { t_s32 errors = 0, i; t_s8 line[512], *pos, *pos1, *pos2, *pos3; t_u16 len; while ((pos = mlan_config_get_line(fp, line, sizeof(line), ln))) { (*ln)++; if (strcmp(pos, "}") == 0) { break; } pos1 = strchr(pos, ':'); if (pos1 == NULL) { printf("Line %d: Invalid hostcmd line '%s'\n", *ln, pos); errors++; continue; } *pos1++ = '\0'; pos2 = strchr(pos1, '='); if (pos2 == NULL) { printf("Line %d: Invalid hostcmd line '%s'\n", *ln, pos); errors++; continue; } *pos2++ = '\0'; len = a2hex_or_atoi(pos1); if (len < 1 || len > MRVDRV_SIZE_OF_CMD_BUFFER) { printf("Line %d: Invalid hostcmd line '%s'\n", *ln, pos); errors++; continue; } *size += len; if (*pos2 == '"') { pos2++; if ((pos3 = strchr(pos2, '"')) == NULL) { printf("Line %d: invalid quotation '%s'\n", *ln, pos); errors++; continue; } *pos3 = '\0'; memset(buf, 0, len); memmove(buf, pos2, MIN(strlen(pos2), len)); buf += len; } else if (*pos2 == '\'') { pos2++; if ((pos3 = strchr(pos2, '\'')) == NULL) { printf("Line %d: invalid quotation '%s'\n", *ln, pos); errors++; continue; } *pos3 = ','; for (i = 0; i < len; i++) { if ((pos3 = strchr(pos2, ',')) != NULL) { *pos3 = '\0'; *buf++ = (t_u8)a2hex_or_atoi(pos2); pos2 = pos3 + 1; } else *buf++ = 0; } } else if (*pos2 == '{') { t_u16 tlvlen = 0, tmp_tlvlen; mlan_get_hostcmd_data(fp, ln, buf + len, &tlvlen); tmp_tlvlen = tlvlen; while (len--) { *buf++ = (t_u8)(tmp_tlvlen & 0xff); tmp_tlvlen >>= 8; } *size += tlvlen; buf += tlvlen; } else { t_u32 value = a2hex_or_atoi(pos2); while (len--) { *buf++ = (t_u8)(value & 0xff); value >>= 8; } } } return MLAN_STATUS_SUCCESS; } /******************************************************** Global Functions ********************************************************/ /** * @brief convert char to hex integer * * @param chr char to convert * @return hex integer or 0 */ int hexval(t_s32 chr) { if (chr >= '0' && chr <= '9') return chr - '0'; if (chr >= 'A' && chr <= 'F') return chr - 'A' + 10; if (chr >= 'a' && chr <= 'f') return chr - 'a' + 10; return 0; } /** * @brief Hump 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 hex integer */ t_void hexdump(t_s8 *prompt, t_void *p, t_s32 len, t_s8 delim) { t_s32 i; t_u8 *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"); } /** * @brief convert char to hex integer * * @param chr char * @return hex integer */ t_u8 hexc2bin(t_s8 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 convert string to hex integer * * @param s A pointer string buffer * @return hex integer */ t_u32 a2hex(t_s8 *s) { t_u32 val = 0; if (!strncasecmp("0x", s, 2)) { s += 2; } while (*s && isxdigit(*s)) { val = (val << 4) + hexc2bin(*s++); } return val; } /* * @brief convert String to integer * * @param value A pointer to string * @return integer */ t_u32 a2hex_or_atoi(t_s8 *value) { if (value[0] == '0' && (value[1] == 'X' || value[1] == 'x')) { return a2hex(value + 2); } else if (isdigit(*value)) { return atoi(value); } else { return *value; } } /** * @brief convert string to hex * * @param ptr A pointer to data buffer * @param chr A pointer to return integer * @return A pointer to next data field */ t_s8 * convert2hex(t_s8 *ptr, t_u8 *chr) { t_u8 val; for (val = 0; *ptr && isxdigit(*ptr); ptr++) { val = (val * 16) + hexval(*ptr); } *chr = val; return ptr; } /** * @brief Check the Hex String * @param s A pointer to the string * @return MLAN_STATUS_SUCCESS --HexString, MLAN_STATUS_FAILURE --not HexString */ int ishexstring(t_s8 *s) { int ret = MLAN_STATUS_FAILURE; t_s32 tmp; if (!strncasecmp("0x", s, 2)) { s += 2; } while (*s) { tmp = toupper(*s); if (((tmp >= 'A') && (tmp <= 'F')) || ((tmp >= '0') && (tmp <= '9'))) { ret = MLAN_STATUS_SUCCESS; } else { ret = MLAN_STATUS_FAILURE; break; } s++; } return ret; } /** * @brief Convert String to Integer * @param buf A pointer to the string * @return Integer */ int atoval(t_s8 *buf) { if (!strncasecmp(buf, "0x", 2)) return a2hex(buf + 2); else if (!ishexstring(buf)) return a2hex(buf); else return atoi(buf); } /** * @brief Prepare host-command buffer * @param fp File handler * @param cmd_name Command name * @param buf A pointer to comand buffer * @return MLAN_STATUS_SUCCESS--success, otherwise--fail */ int prepare_host_cmd_buffer(FILE * fp, char *cmd_name, t_u8 *buf) { t_s8 line[256], cmdname[256], *pos, cmdcode[10]; HostCmd_DS_GEN *hostcmd; int ln = 0; int cmdname_found = 0, cmdcode_found = 0; memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER); hostcmd = (HostCmd_DS_GEN *)buf; hostcmd->command = 0xffff; snprintf(cmdname, sizeof(cmdname), "%s={", cmd_name); cmdname_found = 0; while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) { if (strcmp(pos, cmdname) == 0) { t_u16 len = 0; cmdname_found = 1; snprintf(cmdcode, sizeof(cmdcode), "CmdCode="); cmdcode_found = 0; while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) { if (strncmp(pos, cmdcode, strlen(cmdcode)) == 0) { cmdcode_found = 1; hostcmd->command = a2hex_or_atoi(pos + strlen(cmdcode)); hostcmd->size = S_DS_GEN; mlan_get_hostcmd_data(fp, &ln, buf + hostcmd->size, &len); hostcmd->size += len; break; } } if (!cmdcode_found) { fprintf(stderr, "mlanconfig: CmdCode not found in conf file\n"); return MLAN_STATUS_FAILURE; } break; } } if (!cmdname_found) { fprintf(stderr, "mlanconfig: cmdname '%s' is not found in conf file\n", cmd_name); return MLAN_STATUS_FAILURE; } hostcmd->seq_num = 0; hostcmd->result = 0; hostcmd->command = cpu_to_le16(hostcmd->command); hostcmd->size = cpu_to_le16(hostcmd->size); return MLAN_STATUS_SUCCESS; } /** Config data header length */ #define CFG_DATA_HEADER_LEN 6 /** * @brief Prepare cfg-data buffer * @param argc number of arguments * @param argv A pointer to arguments array * @param fp File handler * @param buf A pointer to comand buffer * @return MLAN_STATUS_SUCCESS--success, otherwise--fail */ int prepare_cfg_data_buffer(int argc, char *argv[], FILE * fp, t_u8 *buf) { int ln = 0, type; HostCmd_DS_GEN *hostcmd; HostCmd_DS_802_11_CFG_DATA *pcfg_data; memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER); hostcmd = (HostCmd_DS_GEN *)buf; hostcmd->command = cpu_to_le16(HostCmd_CMD_CFG_DATA); pcfg_data = (HostCmd_DS_802_11_CFG_DATA *)(buf + S_DS_GEN); pcfg_data->action = (argc == 4) ? HostCmd_ACT_GEN_GET : HostCmd_ACT_GEN_SET; type = atoi(argv[3]); if ((type < 1) || (type > 2)) { fprintf(stderr, "mlanconfig: Invalid register type\n"); return MLAN_STATUS_FAILURE; } else { pcfg_data->type = type; } if (argc == 5) { ln = fparse_for_hex(fp, pcfg_data->data); } pcfg_data->data_len = ln; hostcmd->size = cpu_to_le16(pcfg_data->data_len + S_DS_GEN + CFG_DATA_HEADER_LEN); pcfg_data->data_len = cpu_to_le16(pcfg_data->data_len); pcfg_data->type = cpu_to_le16(pcfg_data->type); pcfg_data->action = cpu_to_le16(pcfg_data->action); hostcmd->seq_num = 0; hostcmd->result = 0; return MLAN_STATUS_SUCCESS; } /** * @brief Process host_cmd response * @param buf A pointer to the response buffer * @return MLAN_STATUS_SUCCESS--success, otherwise--fail */ int process_host_cmd_resp(t_u8 *buf) { HostCmd_DS_GEN *hostcmd = (HostCmd_DS_GEN *)buf; int ret = MLAN_STATUS_SUCCESS; hostcmd->command = le16_to_cpu(hostcmd->command); hostcmd->size = le16_to_cpu(hostcmd->size); hostcmd->seq_num = le16_to_cpu(hostcmd->seq_num); hostcmd->result = le16_to_cpu(hostcmd->result); hostcmd->command &= ~HostCmd_RET_BIT; if (!hostcmd->result) { switch (hostcmd->command) { case HostCmd_CMD_CFG_DATA: { HostCmd_DS_802_11_CFG_DATA *pstcfgData = (HostCmd_DS_802_11_CFG_DATA *)(buf + S_DS_GEN); pstcfgData->data_len = le16_to_cpu(pstcfgData->data_len); pstcfgData->action = le16_to_cpu(pstcfgData->action); if (pstcfgData->action == HostCmd_ACT_GEN_GET) { hexdump("cfgdata", pstcfgData->data, pstcfgData->data_len, ' '); } break; } case HostCmd_CMD_802_11_TPC_ADAPT_REQ: { mlan_ioctl_11h_tpc_resp *tpcIoctlResp = (mlan_ioctl_11h_tpc_resp *)(buf + S_DS_GEN); if (tpcIoctlResp->status_code == 0) { printf("tpcrequest: txPower(%d), linkMargin(%d), rssi(%d)\n", tpcIoctlResp->tx_power, tpcIoctlResp->link_margin, tpcIoctlResp->rssi); } else { printf("tpcrequest: failure, status = %d\n", tpcIoctlResp->status_code); } break; } case HostCmd_CMD_802_11_CRYPTO: { t_u16 alg = le16_to_cpu((t_u16) *(buf + S_DS_GEN + sizeof(t_u16))); if (alg == CIPHER_TEST_AES_CCM || alg == CIPHER_TEST_GCMP) { HostCmd_DS_802_11_CRYPTO_AES_CCM *cmd_aes_ccm = (HostCmd_DS_802_11_CRYPTO_AES_CCM *)(buf + S_DS_GEN); cmd_aes_ccm->encdec = le16_to_cpu(cmd_aes_ccm-> encdec); cmd_aes_ccm->algorithm = le16_to_cpu(cmd_aes_ccm-> algorithm); cmd_aes_ccm->key_length = le16_to_cpu(cmd_aes_ccm-> key_length); cmd_aes_ccm->nonce_length = le16_to_cpu(cmd_aes_ccm-> nonce_length); cmd_aes_ccm->AAD_length = le16_to_cpu(cmd_aes_ccm-> AAD_length); cmd_aes_ccm->data.header.type = le16_to_cpu(cmd_aes_ccm->data. header.type); cmd_aes_ccm->data.header.len = le16_to_cpu(cmd_aes_ccm->data. header.len); printf("crypto_result: encdec=%d algorithm=%d, KeyLen=%d," " NonceLen=%d,AADLen=%d,dataLen=%d\n", cmd_aes_ccm->encdec, cmd_aes_ccm->algorithm, cmd_aes_ccm->key_length, cmd_aes_ccm->nonce_length, cmd_aes_ccm->AAD_length, cmd_aes_ccm->data.header.len); hexdump("Key", cmd_aes_ccm->key, cmd_aes_ccm->key_length, ' '); hexdump("Nonce", cmd_aes_ccm->nonce, cmd_aes_ccm->nonce_length, ' '); hexdump("AAD", cmd_aes_ccm->AAD, cmd_aes_ccm->AAD_length, ' '); hexdump("Data", cmd_aes_ccm->data.data, cmd_aes_ccm->data.header.len, ' '); } else if (alg == CIPHER_TEST_WAPI) { HostCmd_DS_802_11_CRYPTO_WAPI *cmd_wapi = (HostCmd_DS_802_11_CRYPTO_WAPI *) (buf + S_DS_GEN); cmd_wapi->encdec = le16_to_cpu(cmd_wapi->encdec); cmd_wapi->algorithm = le16_to_cpu(cmd_wapi-> algorithm); cmd_wapi->key_length = le16_to_cpu(cmd_wapi-> key_length); cmd_wapi->nonce_length = le16_to_cpu(cmd_wapi-> nonce_length); cmd_wapi->AAD_length = le16_to_cpu(cmd_wapi-> AAD_length); printf("crypto_result: encdec=%d algorithm=%d, KeyLen=%d," " NonceLen=%d,AADLen=%d,dataLen=%d\n", cmd_wapi->encdec, cmd_wapi->algorithm, cmd_wapi->key_length, cmd_wapi->nonce_length, cmd_wapi->AAD_length, cmd_wapi->data_length); hexdump("Key", cmd_wapi->key, cmd_wapi->key_length, ' '); hexdump("Nonce", cmd_wapi->nonce, cmd_wapi->nonce_length, ' '); hexdump("AAD", cmd_wapi->AAD, cmd_wapi->AAD_length, ' '); } else { HostCmd_DS_802_11_CRYPTO *cmd = (HostCmd_DS_802_11_CRYPTO *)(buf + S_DS_GEN); cmd->encdec = le16_to_cpu(cmd->encdec); cmd->algorithm = le16_to_cpu(cmd->algorithm); cmd->key_IV_length = le16_to_cpu(cmd->key_IV_length); cmd->key_length = le16_to_cpu(cmd->key_length); cmd->data.header.type = le16_to_cpu(cmd->data.header. type); cmd->data.header.len = le16_to_cpu(cmd->data.header. len); printf("crypto_result: encdec=%d algorithm=%d,KeyIVLen=%d," " KeyLen=%d,dataLen=%d\n", cmd->encdec, cmd->algorithm, cmd->key_IV_length, cmd->key_length, cmd->data.header.len); hexdump("KeyIV", cmd->keyIV, cmd->key_IV_length, ' '); hexdump("Key", cmd->key, cmd->key_length, ' '); hexdump("Data", cmd->data.data, cmd->data.header.len, ' '); } break; } case HostCmd_CMD_802_11_AUTO_TX: { HostCmd_DS_802_11_AUTO_TX *at = (HostCmd_DS_802_11_AUTO_TX *)(buf + S_DS_GEN); if (le16_to_cpu(at->action) == HostCmd_ACT_GEN_GET) { if (S_DS_GEN + sizeof(at->action) == hostcmd->size) { printf("auto_tx not configured\n"); } else { MrvlIEtypesHeader_t *header = &at->auto_tx.header; header->type = le16_to_cpu(header-> type); header->len = le16_to_cpu(header-> len); if ((S_DS_GEN + sizeof(at->action) + sizeof(MrvlIEtypesHeader_t) + header->len == hostcmd->size) && (header->type == TLV_TYPE_AUTO_TX)) { AutoTx_MacFrame_t *atmf = &at->auto_tx. auto_tx_mac_frame; printf("Interval: %d second(s)\n", le16_to_cpu(atmf->interval)); printf("Priority: %#x\n", atmf->priority); printf("Frame Length: %d\n", le16_to_cpu(atmf->frame_len)); printf("Dest Mac Address: " "%02x:%02x:%02x:%02x:%02x:%02x\n", atmf->dest_mac_addr[0], atmf->dest_mac_addr[1], atmf->dest_mac_addr[2], atmf->dest_mac_addr[3], atmf->dest_mac_addr[4], atmf->dest_mac_addr[5]); printf("Src Mac Address: " "%02x:%02x:%02x:%02x:%02x:%02x\n", atmf->src_mac_addr[0], atmf->src_mac_addr[1], atmf->src_mac_addr[2], atmf->src_mac_addr[3], atmf->src_mac_addr[4], atmf->src_mac_addr[5]); hexdump("Frame Payload", atmf->payload, le16_to_cpu (atmf-> frame_len) - MLAN_MAC_ADDR_LENGTH * 2, ' '); } else { printf("incorrect auto_tx command response\n"); } } } break; } case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: { HostCmd_DS_802_11_SUBSCRIBE_EVENT *se = (HostCmd_DS_802_11_SUBSCRIBE_EVENT *)(buf + S_DS_GEN); if (le16_to_cpu(se->action) == HostCmd_ACT_GEN_GET) { int len = S_DS_GEN + sizeof (HostCmd_DS_802_11_SUBSCRIBE_EVENT); printf("\nEvent\t\tValue\tFreq\tsubscribed\n\n"); while (len < hostcmd->size) { MrvlIEtypesHeader_t *header = (MrvlIEtypesHeader_t *)(buf + len); switch (le16_to_cpu (header->type)) { case TLV_TYPE_RSSI_LOW: { MrvlIEtypes_RssiThreshold_t *low_rssi = (MrvlIEtypes_RssiThreshold_t *)(buf + len); printf("Beacon Low RSSI\t%d\t%d\t%s\n", low_rssi->RSSI_value, low_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0001) ? "yes" : "no"); break; } case TLV_TYPE_SNR_LOW: { MrvlIEtypes_SnrThreshold_t *low_snr = (MrvlIEtypes_SnrThreshold_t *)(buf + len); printf("Beacon Low SNR\t%d\t%d\t%s\n", low_snr->SNR_value, low_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0002) ? "yes" : "no"); break; } case TLV_TYPE_FAILCOUNT: { MrvlIEtypes_FailureCount_t *failure_count = (MrvlIEtypes_FailureCount_t *)(buf + len); printf("Failure Count\t%d\t%d\t%s\n", failure_count->fail_value, failure_count->fail_freq, (le16_to_cpu(se->events) & 0x0004) ? "yes" : "no"); break; } case TLV_TYPE_BCNMISS: { MrvlIEtypes_BeaconsMissed_t *bcn_missed = (MrvlIEtypes_BeaconsMissed_t *)(buf + len); printf("Beacon Missed\t%d\tN/A\t%s\n", bcn_missed->beacon_missed, (le16_to_cpu(se->events) & 0x0008) ? "yes" : "no"); break; } case TLV_TYPE_RSSI_HIGH: { MrvlIEtypes_RssiThreshold_t *high_rssi = (MrvlIEtypes_RssiThreshold_t *)(buf + len); printf("Bcn High RSSI\t%d\t%d\t%s\n", high_rssi->RSSI_value, high_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0010) ? "yes" : "no"); break; } case TLV_TYPE_SNR_HIGH: { MrvlIEtypes_SnrThreshold_t *high_snr = (MrvlIEtypes_SnrThreshold_t *)(buf + len); printf("Beacon High SNR\t%d\t%d\t%s\n", high_snr->SNR_value, high_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0020) ? "yes" : "no"); break; } case TLV_TYPE_RSSI_LOW_DATA: { MrvlIEtypes_RssiThreshold_t *low_rssi = (MrvlIEtypes_RssiThreshold_t *)(buf + len); printf("Data Low RSSI\t%d\t%d\t%s\n", low_rssi->RSSI_value, low_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0040) ? "yes" : "no"); break; } case TLV_TYPE_SNR_LOW_DATA: { MrvlIEtypes_SnrThreshold_t *low_snr = (MrvlIEtypes_SnrThreshold_t *)(buf + len); printf("Data Low SNR\t%d\t%d\t%s\n", low_snr->SNR_value, low_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0080) ? "yes" : "no"); break; } case TLV_TYPE_RSSI_HIGH_DATA: { MrvlIEtypes_RssiThreshold_t *high_rssi = (MrvlIEtypes_RssiThreshold_t *)(buf + len); printf("Data High RSSI\t%d\t%d\t%s\n", high_rssi->RSSI_value, high_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0100) ? "yes" : "no"); break; } case TLV_TYPE_SNR_HIGH_DATA: { MrvlIEtypes_SnrThreshold_t *high_snr = (MrvlIEtypes_SnrThreshold_t *)(buf + len); printf("Data High SNR\t%d\t%d\t%s\n", high_snr->SNR_value, high_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0200) ? "yes" : "no"); break; } case TLV_TYPE_LINK_QUALITY: { MrvlIEtypes_LinkQuality_t *link_qual = (MrvlIEtypes_LinkQuality_t *)(buf + len); printf("Link Quality Parameters:\n"); printf("------------------------\n"); printf("Link Quality Event Subscribed\t%s\n", (le16_to_cpu(se->events) & 0x0400) ? "yes" : "no"); printf("Link SNR Threshold = %d\n", le16_to_cpu(link_qual->link_SNR_thrs)); printf("Link SNR Frequency = %d\n", le16_to_cpu(link_qual->link_SNR_freq)); printf("Min Rate Value = %d\n", le16_to_cpu(link_qual->min_rate_val)); printf("Min Rate Frequency = %d\n", le16_to_cpu(link_qual->min_rate_freq)); printf("Tx Latency Value = %d\n", le32_to_cpu(link_qual->tx_latency_val)); printf("Tx Latency Threshold = %d\n", le32_to_cpu(link_qual->tx_latency_thrs)); break; } case TLV_TYPE_PRE_BEACON_LOST: { MrvlIEtypes_PreBeaconLost_t *pre_bcn_lost = (MrvlIEtypes_PreBeaconLost_t *)(buf + len); printf("------------------------\n"); printf("Pre-Beacon Lost Event Subscribed\t%s\n", (le16_to_cpu(se->events) & 0x0800) ? "yes" : "no"); printf("Pre-Beacon Lost: %d\n", pre_bcn_lost->pre_beacon_lost); break; } default: printf("Unknown subscribed event TLV Type=%#x," " Len=%d\n", le16_to_cpu(header->type), le16_to_cpu(header->len)); break; } len += (sizeof (MrvlIEtypesHeader_t) + le16_to_cpu(header-> len)); } } break; } case HostCmd_CMD_MAC_REG_ACCESS: case HostCmd_CMD_BBP_REG_ACCESS: case HostCmd_CMD_RF_REG_ACCESS: case HostCmd_CMD_CAU_REG_ACCESS: { HostCmd_DS_REG *preg = (HostCmd_DS_REG *)(buf + S_DS_GEN); preg->action = le16_to_cpu(preg->action); if (preg->action == HostCmd_ACT_GEN_GET) { preg->value = le32_to_cpu(preg->value); printf("value = 0x%08x\n", preg->value); } break; } case HostCmd_CMD_MEM_ACCESS: { HostCmd_DS_MEM *pmem = (HostCmd_DS_MEM *)(buf + S_DS_GEN); pmem->action = le16_to_cpu(pmem->action); if (pmem->action == HostCmd_ACT_GEN_GET) { pmem->value = le32_to_cpu(pmem->value); printf("value = 0x%08x\n", pmem->value); } break; } default: printf("HOSTCMD_RESP: CmdCode=%#04x, Size=%#04x," " SeqNum=%#04x, Result=%#04x\n", hostcmd->command, hostcmd->size, hostcmd->seq_num, hostcmd->result); hexdump("payload", (t_void *)(buf + S_DS_GEN), hostcmd->size - S_DS_GEN, ' '); break; } } else { printf("HOSTCMD failed: CmdCode=%#04x, Size=%#04x," " SeqNum=%#04x, Result=%#04x\n", hostcmd->command, hostcmd->size, hostcmd->seq_num, hostcmd->result); } return ret; } /** * @brief Prepare the hostcmd for register access * @param type Register type * @param offset Register offset * @param value Pointer to value (NULL for read) * @param buf Pointer to hostcmd buffer * @return MLAN_STATUS_SUCCESS--success, otherwise--fail */ int prepare_hostcmd_regrdwr(t_u32 type, t_u32 offset, t_u32 *value, t_u8 *buf) { HostCmd_DS_GEN *hostcmd; HostCmd_DS_REG *preg; hostcmd = (HostCmd_DS_GEN *)buf; switch (type) { case 1: hostcmd->command = cpu_to_le16(HostCmd_CMD_MAC_REG_ACCESS); break; case 2: hostcmd->command = cpu_to_le16(HostCmd_CMD_BBP_REG_ACCESS); break; case 3: hostcmd->command = cpu_to_le16(HostCmd_CMD_RF_REG_ACCESS); break; case 5: hostcmd->command = cpu_to_le16(HostCmd_CMD_CAU_REG_ACCESS); break; default: printf("Invalid register set specified\n"); return -EINVAL; } preg = (HostCmd_DS_REG *)(buf + S_DS_GEN); preg->action = (value) ? HostCmd_ACT_GEN_SET : HostCmd_ACT_GEN_GET; preg->action = cpu_to_le16(preg->action); preg->offset = cpu_to_le16((t_u16)offset); if (value) preg->value = cpu_to_le32(*value); else preg->value = 0; hostcmd->size = cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_REG)); hostcmd->seq_num = 0; hostcmd->result = 0; return MLAN_STATUS_SUCCESS; }