blob: 16a0abc970c001d5a3f26ce1f2bf81e86df90f85 [file] [log] [blame]
/*!
* @file coreconfigurator.c
* @brief
* @author
* @sa coreconfigurator.h
* @date 1 Mar 2012
* @version 1.0
*/
/*****************************************************************************/
/* File Includes */
/*****************************************************************************/
#include "coreconfigurator.h"
/*****************************************************************************/
/* Constants */
/*****************************************************************************/
#define INLINE static __inline
#define PHY_802_11n
#define MAX_CFG_PKTLEN 1450
#define MSG_HEADER_LEN 4
#define QUERY_MSG_TYPE 'Q'
#define WRITE_MSG_TYPE 'W'
#define RESP_MSG_TYPE 'R'
#define WRITE_RESP_SUCCESS 1
#define INVALID 255
#define MAC_ADDR_LEN 6
#define TAG_PARAM_OFFSET (MAC_HDR_LEN + TIME_STAMP_LEN + \
BEACON_INTERVAL_LEN + CAP_INFO_LEN)
/*****************************************************************************/
/* Function Macros */
/*****************************************************************************/
/*****************************************************************************/
/* Type Definitions */
/*****************************************************************************/
/* Basic Frame Type Codes (2-bit) */
typedef enum {
FRAME_TYPE_CONTROL = 0x04,
FRAME_TYPE_DATA = 0x08,
FRAME_TYPE_MANAGEMENT = 0x00,
FRAME_TYPE_RESERVED = 0x0C,
FRAME_TYPE_FORCE_32BIT = 0xFFFFFFFF
} tenuBasicFrmType;
/* Frame Type and Subtype Codes (6-bit) */
typedef enum {
ASSOC_REQ = 0x00,
ASSOC_RSP = 0x10,
REASSOC_REQ = 0x20,
REASSOC_RSP = 0x30,
PROBE_REQ = 0x40,
PROBE_RSP = 0x50,
BEACON = 0x80,
ATIM = 0x90,
DISASOC = 0xA0,
AUTH = 0xB0,
DEAUTH = 0xC0,
ACTION = 0xD0,
PS_POLL = 0xA4,
RTS = 0xB4,
CTS = 0xC4,
ACK = 0xD4,
CFEND = 0xE4,
CFEND_ACK = 0xF4,
DATA = 0x08,
DATA_ACK = 0x18,
DATA_POLL = 0x28,
DATA_POLL_ACK = 0x38,
NULL_FRAME = 0x48,
CFACK = 0x58,
CFPOLL = 0x68,
CFPOLL_ACK = 0x78,
QOS_DATA = 0x88,
QOS_DATA_ACK = 0x98,
QOS_DATA_POLL = 0xA8,
QOS_DATA_POLL_ACK = 0xB8,
QOS_NULL_FRAME = 0xC8,
QOS_CFPOLL = 0xE8,
QOS_CFPOLL_ACK = 0xF8,
BLOCKACK_REQ = 0x84,
BLOCKACK = 0x94,
FRAME_SUBTYPE_FORCE_32BIT = 0xFFFFFFFF
} tenuFrmSubtype;
/* Basic Frame Classes */
typedef enum {
CLASS1_FRAME_TYPE = 0x00,
CLASS2_FRAME_TYPE = 0x01,
CLASS3_FRAME_TYPE = 0x02,
FRAME_CLASS_FORCE_32BIT = 0xFFFFFFFF
} tenuFrameClass;
/* Element ID of various Information Elements */
typedef enum {
ISSID = 0, /* Service Set Identifier */
ISUPRATES = 1, /* Supported Rates */
IFHPARMS = 2, /* FH parameter set */
IDSPARMS = 3, /* DS parameter set */
ICFPARMS = 4, /* CF parameter set */
ITIM = 5, /* Traffic Information Map */
IIBPARMS = 6, /* IBSS parameter set */
ICOUNTRY = 7, /* Country element */
IEDCAPARAMS = 12, /* EDCA parameter set */
ITSPEC = 13, /* Traffic Specification */
ITCLAS = 14, /* Traffic Classification */
ISCHED = 15, /* Schedule */
ICTEXT = 16, /* Challenge Text */
IPOWERCONSTRAINT = 32, /* Power Constraint */
IPOWERCAPABILITY = 33, /* Power Capability */
ITPCREQUEST = 34, /* TPC Request */
ITPCREPORT = 35, /* TPC Report */
ISUPCHANNEL = 36, /* Supported channel list */
ICHSWANNOUNC = 37, /* Channel Switch Announcement */
IMEASUREMENTREQUEST = 38, /* Measurement request */
IMEASUREMENTREPORT = 39, /* Measurement report */
IQUIET = 40, /* Quiet element Info */
IIBSSDFS = 41, /* IBSS DFS */
IERPINFO = 42, /* ERP Information */
ITSDELAY = 43, /* TS Delay */
ITCLASPROCESS = 44, /* TCLAS Processing */
IHTCAP = 45, /* HT Capabilities */
IQOSCAP = 46, /* QoS Capability */
IRSNELEMENT = 48, /* RSN Information Element */
IEXSUPRATES = 50, /* Extended Supported Rates */
IEXCHSWANNOUNC = 60, /* Extended Ch Switch Announcement*/
IHTOPERATION = 61, /* HT Information */
ISECCHOFF = 62, /* Secondary Channel Offeset */
I2040COEX = 72, /* 20/40 Coexistence IE */
I2040INTOLCHREPORT = 73, /* 20/40 Intolerant channel report*/
IOBSSSCAN = 74, /* OBSS Scan parameters */
IEXTCAP = 127, /* Extended capability */
IWMM = 221, /* WMM parameters */
IWPAELEMENT = 221, /* WPA Information Element */
INFOELEM_ID_FORCE_32BIT = 0xFFFFFFFF
} tenuInfoElemID;
typedef struct {
char *pcRespBuffer;
s32 s32MaxRespBuffLen;
s32 s32BytesRead;
bool bRespRequired;
} tstrConfigPktInfo;
/*****************************************************************************/
/* Extern Variable Declarations */
/*****************************************************************************/
/*****************************************************************************/
/* Extern Function Declarations */
/*****************************************************************************/
extern s32 SendRawPacket(s8 *ps8Packet, s32 s32PacketLen);
extern void NetworkInfoReceived(u8 *pu8Buffer, u32 u32Length);
extern void GnrlAsyncInfoReceived(u8 *pu8Buffer, u32 u32Length);
extern void host_int_ScanCompleteReceived(u8 *pu8Buffer, u32 u32Length);
/*****************************************************************************/
/* Global Variables */
/*****************************************************************************/
static struct semaphore SemHandleSendPkt;
static struct semaphore SemHandlePktResp;
static tstrConfigPktInfo gstrConfigPktInfo;
static u8 g_seqno;
static s16 g_wid_num = -1;
static u16 Res_Len;
static u8 g_oper_mode = SET_CFG;
/* WID Switches */
static tstrWID gastrWIDs[] = {
{WID_FIRMWARE_VERSION, WID_STR},
{WID_PHY_VERSION, WID_STR},
{WID_HARDWARE_VERSION, WID_STR},
{WID_BSS_TYPE, WID_CHAR},
{WID_QOS_ENABLE, WID_CHAR},
{WID_11I_MODE, WID_CHAR},
{WID_CURRENT_TX_RATE, WID_CHAR},
{WID_LINKSPEED, WID_CHAR},
{WID_RTS_THRESHOLD, WID_SHORT},
{WID_FRAG_THRESHOLD, WID_SHORT},
{WID_SSID, WID_STR},
{WID_BSSID, WID_ADR},
{WID_BEACON_INTERVAL, WID_SHORT},
{WID_POWER_MANAGEMENT, WID_CHAR},
{WID_LISTEN_INTERVAL, WID_CHAR},
{WID_DTIM_PERIOD, WID_CHAR},
{WID_CURRENT_CHANNEL, WID_CHAR},
{WID_TX_POWER_LEVEL_11A, WID_CHAR},
{WID_TX_POWER_LEVEL_11B, WID_CHAR},
{WID_PREAMBLE, WID_CHAR},
{WID_11G_OPERATING_MODE, WID_CHAR},
{WID_MAC_ADDR, WID_ADR},
{WID_IP_ADDRESS, WID_ADR},
{WID_ACK_POLICY, WID_CHAR},
{WID_PHY_ACTIVE_REG, WID_CHAR},
{WID_AUTH_TYPE, WID_CHAR},
{WID_REKEY_POLICY, WID_CHAR},
{WID_REKEY_PERIOD, WID_INT},
{WID_REKEY_PACKET_COUNT, WID_INT},
{WID_11I_PSK, WID_STR},
{WID_1X_KEY, WID_STR},
{WID_1X_SERV_ADDR, WID_IP},
{WID_SUPP_USERNAME, WID_STR},
{WID_SUPP_PASSWORD, WID_STR},
{WID_USER_CONTROL_ON_TX_POWER, WID_CHAR},
{WID_MEMORY_ADDRESS, WID_INT},
{WID_MEMORY_ACCESS_32BIT, WID_INT},
{WID_MEMORY_ACCESS_16BIT, WID_SHORT},
{WID_MEMORY_ACCESS_8BIT, WID_CHAR},
{WID_SITE_SURVEY_RESULTS, WID_STR},
{WID_PMKID_INFO, WID_STR},
{WID_ASSOC_RES_INFO, WID_STR},
{WID_MANUFACTURER, WID_STR}, /* 4 Wids added for the CAPI tool*/
{WID_MODEL_NAME, WID_STR},
{WID_MODEL_NUM, WID_STR},
{WID_DEVICE_NAME, WID_STR},
{WID_SSID_PROBE_REQ, WID_STR},
#ifdef MAC_802_11N
{WID_11N_ENABLE, WID_CHAR},
{WID_11N_CURRENT_TX_MCS, WID_CHAR},
{WID_TX_POWER_LEVEL_11N, WID_CHAR},
{WID_11N_OPERATING_MODE, WID_CHAR},
{WID_11N_SMPS_MODE, WID_CHAR},
{WID_11N_PROT_MECH, WID_CHAR},
{WID_11N_ERP_PROT_TYPE, WID_CHAR},
{WID_11N_HT_PROT_TYPE, WID_CHAR},
{WID_11N_PHY_ACTIVE_REG_VAL, WID_INT},
{WID_11N_PRINT_STATS, WID_CHAR},
{WID_11N_AUTORATE_TABLE, WID_BIN_DATA},
{WID_HOST_CONFIG_IF_TYPE, WID_CHAR},
{WID_HOST_DATA_IF_TYPE, WID_CHAR},
{WID_11N_SIG_QUAL_VAL, WID_SHORT},
{WID_11N_IMMEDIATE_BA_ENABLED, WID_CHAR},
{WID_11N_TXOP_PROT_DISABLE, WID_CHAR},
{WID_11N_SHORT_GI_20MHZ_ENABLE, WID_CHAR},
{WID_SHORT_SLOT_ALLOWED, WID_CHAR},
{WID_11W_ENABLE, WID_CHAR},
{WID_11W_MGMT_PROT_REQ, WID_CHAR},
{WID_2040_ENABLE, WID_CHAR},
{WID_2040_COEXISTENCE, WID_CHAR},
{WID_USER_SEC_CHANNEL_OFFSET, WID_CHAR},
{WID_2040_CURR_CHANNEL_OFFSET, WID_CHAR},
{WID_2040_40MHZ_INTOLERANT, WID_CHAR},
{WID_HUT_RESTART, WID_CHAR},
{WID_HUT_NUM_TX_PKTS, WID_INT},
{WID_HUT_FRAME_LEN, WID_SHORT},
{WID_HUT_TX_FORMAT, WID_CHAR},
{WID_HUT_BANDWIDTH, WID_CHAR},
{WID_HUT_OP_BAND, WID_CHAR},
{WID_HUT_STBC, WID_CHAR},
{WID_HUT_ESS, WID_CHAR},
{WID_HUT_ANTSET, WID_CHAR},
{WID_HUT_HT_OP_MODE, WID_CHAR},
{WID_HUT_RIFS_MODE, WID_CHAR},
{WID_HUT_SMOOTHING_REC, WID_CHAR},
{WID_HUT_SOUNDING_PKT, WID_CHAR},
{WID_HUT_HT_CODING, WID_CHAR},
{WID_HUT_TEST_DIR, WID_CHAR},
{WID_HUT_TXOP_LIMIT, WID_SHORT},
{WID_HUT_DEST_ADDR, WID_ADR},
{WID_HUT_TX_PATTERN, WID_BIN_DATA},
{WID_HUT_TX_TIME_TAKEN, WID_INT},
{WID_HUT_PHY_TEST_MODE, WID_CHAR},
{WID_HUT_PHY_TEST_RATE_HI, WID_CHAR},
{WID_HUT_PHY_TEST_RATE_LO, WID_CHAR},
{WID_HUT_TX_TEST_TIME, WID_INT},
{WID_HUT_LOG_INTERVAL, WID_INT},
{WID_HUT_DISABLE_RXQ_REPLENISH, WID_CHAR},
{WID_HUT_TEST_ID, WID_STR},
{WID_HUT_KEY_ORIGIN, WID_CHAR},
{WID_HUT_BCST_PERCENT, WID_CHAR},
{WID_HUT_GROUP_CIPHER_TYPE, WID_CHAR},
{WID_HUT_STATS, WID_BIN_DATA},
{WID_HUT_TSF_TEST_MODE, WID_CHAR},
{WID_HUT_SIG_QUAL_AVG, WID_SHORT},
{WID_HUT_SIG_QUAL_AVG_CNT, WID_SHORT},
{WID_HUT_TSSI_VALUE, WID_CHAR},
{WID_HUT_MGMT_PERCENT, WID_CHAR},
{WID_HUT_MGMT_BCST_PERCENT, WID_CHAR},
{WID_HUT_MGMT_ALLOW_HT, WID_CHAR},
{WID_HUT_UC_MGMT_TYPE, WID_CHAR},
{WID_HUT_BC_MGMT_TYPE, WID_CHAR},
{WID_HUT_UC_MGMT_FRAME_LEN, WID_SHORT},
{WID_HUT_BC_MGMT_FRAME_LEN, WID_SHORT},
{WID_HUT_11W_MFP_REQUIRED_TX, WID_CHAR},
{WID_HUT_11W_MFP_PEER_CAPABLE, WID_CHAR},
{WID_HUT_11W_TX_IGTK_ID, WID_CHAR},
{WID_HUT_FC_TXOP_MOD, WID_CHAR},
{WID_HUT_FC_PROT_TYPE, WID_CHAR},
{WID_HUT_SEC_CCA_ASSERT, WID_CHAR},
#endif /* MAC_802_11N */
};
u16 g_num_total_switches = (sizeof(gastrWIDs) / sizeof(tstrWID));
/*****************************************************************************/
/* Static Function Declarations */
/*****************************************************************************/
/*****************************************************************************/
/* Functions */
/*****************************************************************************/
INLINE u8 ascii_hex_to_dec(u8 num)
{
if ((num >= '0') && (num <= '9'))
return (num - '0');
else if ((num >= 'A') && (num <= 'F'))
return (10 + (num - 'A'));
else if ((num >= 'a') && (num <= 'f'))
return (10 + (num - 'a'));
return INVALID;
}
INLINE u8 get_hex_char(u8 inp)
{
u8 *d2htab = "0123456789ABCDEF";
return d2htab[inp & 0xF];
}
/* This function extracts the MAC address held in a string in standard format */
/* into another buffer as integers. */
INLINE u16 extract_mac_addr(char *str, u8 *buff)
{
*buff = 0;
while (*str != '\0') {
if ((*str == ':') || (*str == '-'))
*(++buff) = 0;
else
*buff = (*buff << 4) + ascii_hex_to_dec(*str);
str++;
}
return MAC_ADDR_LEN;
}
/* This function creates MAC address in standard format from a buffer of */
/* integers. */
INLINE void create_mac_addr(u8 *str, u8 *buff)
{
u32 i = 0;
u32 j = 0;
for (i = 0; i < MAC_ADDR_LEN; i++) {
str[j++] = get_hex_char((u8)((buff[i] >> 4) & 0x0F));
str[j++] = get_hex_char((u8)(buff[i] & 0x0F));
str[j++] = ':';
}
str[--j] = '\0';
}
/* This function converts the IP address string in dotted decimal format to */
/* unsigned integer. This functionality is similar to the library function */
/* inet_addr() but is reimplemented here since I could not confirm that */
/* inet_addr is platform independent. */
/* ips=>IP Address String in dotted decimal format */
/* ipn=>Pointer to IP Address in integer format */
INLINE u8 conv_ip_to_int(u8 *ips, u32 *ipn)
{
u8 i = 0;
u8 ipb = 0;
*ipn = 0;
/* Integer to string for each component */
while (ips[i] != '\0') {
if (ips[i] == '.') {
*ipn = ((*ipn) << 8) | ipb;
ipb = 0;
} else {
ipb = ipb * 10 + ascii_hex_to_dec(ips[i]);
}
i++;
}
/* The last byte of the IP address is read in here */
*ipn = ((*ipn) << 8) | ipb;
return 0;
}
/* This function converts the IP address from integer format to dotted */
/* decimal string format. Alternative to std library fn inet_ntoa(). */
/* ips=>Buffer to hold IP Address String dotted decimal format (Min 17B) */
/* ipn=>IP Address in integer format */
INLINE u8 conv_int_to_ip(u8 *ips, u32 ipn)
{
u8 i = 0;
u8 ipb = 0;
u8 cnt = 0;
u8 ipbsize = 0;
for (cnt = 4; cnt > 0; cnt--) {
ipb = (ipn >> (8 * (cnt - 1))) & 0xFF;
if (ipb >= 100)
ipbsize = 2;
else if (ipb >= 10)
ipbsize = 1;
else
ipbsize = 0;
switch (ipbsize) {
case 2:
ips[i++] = get_hex_char(ipb / 100);
ipb %= 100;
case 1:
ips[i++] = get_hex_char(ipb / 10);
ipb %= 10;
default:
ips[i++] = get_hex_char(ipb);
}
if (cnt > 1)
ips[i++] = '.';
}
ips[i] = '\0';
return i;
}
INLINE tenuWIDtype get_wid_type(u32 wid_num)
{
/* Check for iconfig specific WID types first */
if ((wid_num == WID_BSSID) ||
(wid_num == WID_MAC_ADDR) ||
(wid_num == WID_IP_ADDRESS) ||
(wid_num == WID_HUT_DEST_ADDR)) {
return WID_ADR;
}
if ((WID_1X_SERV_ADDR == wid_num) ||
(WID_STACK_IP_ADDR == wid_num) ||
(WID_STACK_NETMASK_ADDR == wid_num)) {
return WID_IP;
}
/* Next check for standard WID types */
if (wid_num < 0x1000)
return WID_CHAR;
else if (wid_num < 0x2000)
return WID_SHORT;
else if (wid_num < 0x3000)
return WID_INT;
else if (wid_num < 0x4000)
return WID_STR;
else if (wid_num < 0x5000)
return WID_BIN_DATA;
return WID_UNDEF;
}
/* This function extracts the beacon period field from the beacon or probe */
/* response frame. */
INLINE u16 get_beacon_period(u8 *data)
{
u16 bcn_per = 0;
bcn_per = data[0];
bcn_per |= (data[1] << 8);
return bcn_per;
}
INLINE u32 get_beacon_timestamp_lo(u8 *data)
{
u32 time_stamp = 0;
u32 index = MAC_HDR_LEN;
time_stamp |= data[index++];
time_stamp |= (data[index++] << 8);
time_stamp |= (data[index++] << 16);
time_stamp |= (data[index] << 24);
return time_stamp;
}
INLINE u32 get_beacon_timestamp_hi(u8 *data)
{
u32 time_stamp = 0;
u32 index = (MAC_HDR_LEN + 4);
time_stamp |= data[index++];
time_stamp |= (data[index++] << 8);
time_stamp |= (data[index++] << 16);
time_stamp |= (data[index] << 24);
return time_stamp;
}
/* This function extracts the 'frame type' bits from the MAC header of the */
/* input frame. */
/* Returns the value in the LSB of the returned value. */
INLINE tenuBasicFrmType get_type(u8 *header)
{
return ((tenuBasicFrmType)(header[0] & 0x0C));
}
/* This function extracts the 'frame type and sub type' bits from the MAC */
/* header of the input frame. */
/* Returns the value in the LSB of the returned value. */
INLINE tenuFrmSubtype get_sub_type(u8 *header)
{
return ((tenuFrmSubtype)(header[0] & 0xFC));
}
/* This function extracts the 'to ds' bit from the MAC header of the input */
/* frame. */
/* Returns the value in the LSB of the returned value. */
INLINE u8 get_to_ds(u8 *header)
{
return (header[1] & 0x01);
}
/* This function extracts the 'from ds' bit from the MAC header of the input */
/* frame. */
/* Returns the value in the LSB of the returned value. */
INLINE u8 get_from_ds(u8 *header)
{
return ((header[1] & 0x02) >> 1);
}
/* This function extracts the MAC Address in 'address1' field of the MAC */
/* header and updates the MAC Address in the allocated 'addr' variable. */
INLINE void get_address1(u8 *pu8msa, u8 *addr)
{
memcpy(addr, pu8msa + 4, 6);
}
/* This function extracts the MAC Address in 'address2' field of the MAC */
/* header and updates the MAC Address in the allocated 'addr' variable. */
INLINE void get_address2(u8 *pu8msa, u8 *addr)
{
memcpy(addr, pu8msa + 10, 6);
}
/* This function extracts the MAC Address in 'address3' field of the MAC */
/* header and updates the MAC Address in the allocated 'addr' variable. */
INLINE void get_address3(u8 *pu8msa, u8 *addr)
{
memcpy(addr, pu8msa + 16, 6);
}
/* This function extracts the BSSID from the incoming WLAN packet based on */
/* the 'from ds' bit, and updates the MAC Address in the allocated 'addr' */
/* variable. */
INLINE void get_BSSID(u8 *data, u8 *bssid)
{
if (get_from_ds(data) == 1)
get_address2(data, bssid);
else if (get_to_ds(data) == 1)
get_address1(data, bssid);
else
get_address3(data, bssid);
}
/* This function extracts the SSID from a beacon/probe response frame */
INLINE void get_ssid(u8 *data, u8 *ssid, u8 *p_ssid_len)
{
u8 len = 0;
u8 i = 0;
u8 j = 0;
len = data[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN +
CAP_INFO_LEN + 1];
j = MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN +
CAP_INFO_LEN + 2;
/* If the SSID length field is set wrongly to a value greater than the */
/* allowed maximum SSID length limit, reset the length to 0 */
if (len >= MAX_SSID_LEN)
len = 0;
for (i = 0; i < len; i++, j++)
ssid[i] = data[j];
ssid[len] = '\0';
*p_ssid_len = len;
}
/* This function extracts the capability info field from the beacon or probe */
/* response frame. */
INLINE u16 get_cap_info(u8 *data)
{
u16 cap_info = 0;
u16 index = MAC_HDR_LEN;
tenuFrmSubtype st;
st = get_sub_type(data);
/* Location of the Capability field is different for Beacon and */
/* Association frames. */
if ((st == BEACON) || (st == PROBE_RSP))
index += TIME_STAMP_LEN + BEACON_INTERVAL_LEN;
cap_info = data[index];
cap_info |= (data[index + 1] << 8);
return cap_info;
}
/* This function extracts the capability info field from the Association */
/* response frame. */
INLINE u16 get_assoc_resp_cap_info(u8 *data)
{
u16 cap_info = 0;
cap_info = data[0];
cap_info |= (data[1] << 8);
return cap_info;
}
/* This funcion extracts the association status code from the incoming */
/* association response frame and returns association status code */
INLINE u16 get_asoc_status(u8 *data)
{
u16 asoc_status = 0;
asoc_status = data[3];
asoc_status = (asoc_status << 8) | data[2];
return asoc_status;
}
/* This function extracts association ID from the incoming association */
/* response frame */
INLINE u16 get_asoc_id(u8 *data)
{
u16 asoc_id = 0;
asoc_id = data[4];
asoc_id |= (data[5] << 8);
return asoc_id;
}
/**
* @brief initializes the Core Configurator
* @details
* @return Error code indicating success/failure
* @note
* @author mabubakr
* @date 1 Mar 2012
* @version 1.0
*/
s32 CoreConfiguratorInit(void)
{
s32 s32Error = WILC_SUCCESS;
PRINT_D(CORECONFIG_DBG, "CoreConfiguratorInit()\n");
sema_init(&SemHandleSendPkt, 1);
sema_init(&SemHandlePktResp, 0);
memset((void *)(&gstrConfigPktInfo), 0, sizeof(tstrConfigPktInfo));
return s32Error;
}
u8 *get_tim_elm(u8 *pu8msa, u16 u16RxLen, u16 u16TagParamOffset)
{
u16 u16index = 0;
/*************************************************************************/
/* Beacon Frame - Frame Body */
/* --------------------------------------------------------------------- */
/* |Timestamp |BeaconInt |CapInfo |SSID |SupRates |DSParSet |TIM elm | */
/* --------------------------------------------------------------------- */
/* |8 |2 |2 |2-34 |3-10 |3 |4-256 | */
/* --------------------------------------------------------------------- */
/* */
/*************************************************************************/
u16index = u16TagParamOffset;
/* Search for the TIM Element Field and return if the element is found */
while (u16index < (u16RxLen - FCS_LEN)) {
if (pu8msa[u16index] == ITIM)
return &pu8msa[u16index];
else
u16index += (IE_HDR_LEN + pu8msa[u16index + 1]);
}
return 0;
}
/* This function gets the current channel information from
* the 802.11n beacon/probe response frame */
u8 get_current_channel_802_11n(u8 *pu8msa, u16 u16RxLen)
{
u16 index;
index = TAG_PARAM_OFFSET;
while (index < (u16RxLen - FCS_LEN)) {
if (pu8msa[index] == IDSPARMS)
return pu8msa[index + 2];
else
/* Increment index by length information and header */
index += pu8msa[index + 1] + IE_HDR_LEN;
}
/* Return current channel information from the MIB, if beacon/probe */
/* response frame does not contain the DS parameter set IE */
/* return (mget_CurrentChannel() + 1); */
return 0; /* no MIB here */
}
u8 get_current_channel(u8 *pu8msa, u16 u16RxLen)
{
#ifdef PHY_802_11n
#ifdef FIVE_GHZ_BAND
/* Get the current channel as its not set in */
/* 802.11a beacons/probe response */
return (get_rf_channel() + 1);
#else /* FIVE_GHZ_BAND */
/* Extract current channel information from */
/* the beacon/probe response frame */
return get_current_channel_802_11n(pu8msa, u16RxLen);
#endif /* FIVE_GHZ_BAND */
#else
return 0;
#endif /* PHY_802_11n */
}
/**
* @brief parses the received 'N' message
* @details
* @param[in] pu8MsgBuffer The message to be parsed
* @param[out] ppstrNetworkInfo pointer to pointer to the structure containing the parsed Network Info
* @return Error code indicating success/failure
* @note
* @author mabubakr
* @date 1 Mar 2012
* @version 1.0
*/
s32 ParseNetworkInfo(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo)
{
s32 s32Error = WILC_SUCCESS;
tstrNetworkInfo *pstrNetworkInfo = NULL;
u8 u8MsgType = 0;
u8 u8MsgID = 0;
u16 u16MsgLen = 0;
u16 u16WidID = (u16)WID_NIL;
u16 u16WidLen = 0;
u8 *pu8WidVal = 0;
u8MsgType = pu8MsgBuffer[0];
/* Check whether the received message type is 'N' */
if ('N' != u8MsgType) {
PRINT_ER("Received Message format incorrect.\n");
WILC_ERRORREPORT(s32Error, WILC_FAIL);
}
/* Extract message ID */
u8MsgID = pu8MsgBuffer[1];
/* Extract message Length */
u16MsgLen = MAKE_WORD16(pu8MsgBuffer[2], pu8MsgBuffer[3]);
/* Extract WID ID */
u16WidID = MAKE_WORD16(pu8MsgBuffer[4], pu8MsgBuffer[5]);
/* Extract WID Length */
u16WidLen = MAKE_WORD16(pu8MsgBuffer[6], pu8MsgBuffer[7]);
/* Assign a pointer to the WID value */
pu8WidVal = &pu8MsgBuffer[8];
/* parse the WID value of the WID "WID_NEWORK_INFO" */
{
u8 *pu8msa = 0;
u16 u16RxLen = 0;
u8 *pu8TimElm = 0;
u8 *pu8IEs = 0;
u16 u16IEsLen = 0;
u8 u8index = 0;
u32 u32Tsf_Lo;
u32 u32Tsf_Hi;
pstrNetworkInfo = kmalloc(sizeof(tstrNetworkInfo), GFP_KERNEL);
if (!pstrNetworkInfo)
return -ENOMEM;
memset((void *)(pstrNetworkInfo), 0, sizeof(tstrNetworkInfo));
pstrNetworkInfo->s8rssi = pu8WidVal[0];
/* Assign a pointer to msa "Mac Header Start Address" */
pu8msa = &pu8WidVal[1];
u16RxLen = u16WidLen - 1;
/* parse msa*/
/* Get the cap_info */
pstrNetworkInfo->u16CapInfo = get_cap_info(pu8msa);
#ifdef WILC_P2P
/* Get time-stamp [Low only 32 bit] */
pstrNetworkInfo->u32Tsf = get_beacon_timestamp_lo(pu8msa);
PRINT_D(CORECONFIG_DBG, "TSF :%x\n", pstrNetworkInfo->u32Tsf);
#endif
/* Get full time-stamp [Low and High 64 bit] */
u32Tsf_Lo = get_beacon_timestamp_lo(pu8msa);
u32Tsf_Hi = get_beacon_timestamp_hi(pu8msa);
pstrNetworkInfo->u64Tsf = u32Tsf_Lo | ((u64)u32Tsf_Hi << 32);
/* Get SSID */
get_ssid(pu8msa, pstrNetworkInfo->au8ssid, &(pstrNetworkInfo->u8SsidLen));
/* Get BSSID */
get_BSSID(pu8msa, pstrNetworkInfo->au8bssid);
/* Get the current channel */
pstrNetworkInfo->u8channel = get_current_channel(pu8msa, (u16RxLen + FCS_LEN));
/* Get beacon period */
u8index = (MAC_HDR_LEN + TIME_STAMP_LEN);
pstrNetworkInfo->u16BeaconPeriod = get_beacon_period(pu8msa + u8index);
u8index += BEACON_INTERVAL_LEN + CAP_INFO_LEN;
/* Get DTIM Period */
pu8TimElm = get_tim_elm(pu8msa, (u16RxLen + FCS_LEN), u8index);
if (pu8TimElm != 0)
pstrNetworkInfo->u8DtimPeriod = pu8TimElm[3];
pu8IEs = &pu8msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN];
u16IEsLen = u16RxLen - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN);
if (u16IEsLen > 0) {
pstrNetworkInfo->pu8IEs = kmalloc(u16IEsLen, GFP_KERNEL);
if (!pstrNetworkInfo->pu8IEs)
return -ENOMEM;
memset((void *)(pstrNetworkInfo->pu8IEs), 0, u16IEsLen);
memcpy(pstrNetworkInfo->pu8IEs, pu8IEs, u16IEsLen);
}
pstrNetworkInfo->u16IEsLen = u16IEsLen;
}
*ppstrNetworkInfo = pstrNetworkInfo;
ERRORHANDLER:
return s32Error;
}
/**
* @brief Deallocates the parsed Network Info
* @details
* @param[in] pstrNetworkInfo Network Info to be deallocated
* @return Error code indicating success/failure
* @note
* @author mabubakr
* @date 1 Mar 2012
* @version 1.0
*/
s32 DeallocateNetworkInfo(tstrNetworkInfo *pstrNetworkInfo)
{
s32 s32Error = WILC_SUCCESS;
if (pstrNetworkInfo != NULL) {
if (pstrNetworkInfo->pu8IEs != NULL) {
kfree(pstrNetworkInfo->pu8IEs);
pstrNetworkInfo->pu8IEs = NULL;
} else {
s32Error = WILC_FAIL;
}
kfree(pstrNetworkInfo);
pstrNetworkInfo = NULL;
} else {
s32Error = WILC_FAIL;
}
return s32Error;
}
/**
* @brief parses the received Association Response frame
* @details
* @param[in] pu8Buffer The Association Response frame to be parsed
* @param[out] ppstrConnectRespInfo pointer to pointer to the structure containing the parsed Association Response Info
* @return Error code indicating success/failure
* @note
* @author mabubakr
* @date 2 Apr 2012
* @version 1.0
*/
s32 ParseAssocRespInfo(u8 *pu8Buffer, u32 u32BufferLen,
tstrConnectRespInfo **ppstrConnectRespInfo)
{
s32 s32Error = WILC_SUCCESS;
tstrConnectRespInfo *pstrConnectRespInfo = NULL;
u16 u16AssocRespLen = 0;
u8 *pu8IEs = 0;
u16 u16IEsLen = 0;
pstrConnectRespInfo = kmalloc(sizeof(tstrConnectRespInfo), GFP_KERNEL);
if (!pstrConnectRespInfo)
return -ENOMEM;
memset((void *)(pstrConnectRespInfo), 0, sizeof(tstrConnectRespInfo));
/* u16AssocRespLen = pu8Buffer[0]; */
u16AssocRespLen = (u16)u32BufferLen;
/* get the status code */
pstrConnectRespInfo->u16ConnectStatus = get_asoc_status(pu8Buffer);
if (pstrConnectRespInfo->u16ConnectStatus == SUCCESSFUL_STATUSCODE) {
/* get the capability */
pstrConnectRespInfo->u16capability = get_assoc_resp_cap_info(pu8Buffer);
/* get the Association ID */
pstrConnectRespInfo->u16AssocID = get_asoc_id(pu8Buffer);
/* get the Information Elements */
pu8IEs = &pu8Buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN];
u16IEsLen = u16AssocRespLen - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN);
pstrConnectRespInfo->pu8RespIEs = kmalloc(u16IEsLen, GFP_KERNEL);
if (!pstrConnectRespInfo->pu8RespIEs)
return -ENOMEM;
memset((void *)(pstrConnectRespInfo->pu8RespIEs), 0, u16IEsLen);
memcpy(pstrConnectRespInfo->pu8RespIEs, pu8IEs, u16IEsLen);
pstrConnectRespInfo->u16RespIEsLen = u16IEsLen;
}
*ppstrConnectRespInfo = pstrConnectRespInfo;
return s32Error;
}
/**
* @brief Deallocates the parsed Association Response Info
* @details
* @param[in] pstrNetworkInfo Network Info to be deallocated
* @return Error code indicating success/failure
* @note
* @author mabubakr
* @date 2 Apr 2012
* @version 1.0
*/
s32 DeallocateAssocRespInfo(tstrConnectRespInfo *pstrConnectRespInfo)
{
s32 s32Error = WILC_SUCCESS;
if (pstrConnectRespInfo != NULL) {
if (pstrConnectRespInfo->pu8RespIEs != NULL) {
kfree(pstrConnectRespInfo->pu8RespIEs);
pstrConnectRespInfo->pu8RespIEs = NULL;
} else {
s32Error = WILC_FAIL;
}
kfree(pstrConnectRespInfo);
pstrConnectRespInfo = NULL;
} else {
s32Error = WILC_FAIL;
}
return s32Error;
}
#ifndef CONNECT_DIRECT
s32 ParseSurveyResults(u8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZE],
wid_site_survey_reslts_s **ppstrSurveyResults,
u32 *pu32SurveyResultsCount)
{
s32 s32Error = WILC_SUCCESS;
wid_site_survey_reslts_s *pstrSurveyResults = NULL;
u32 u32SurveyResultsCount = 0;
u32 u32SurveyBytesLength = 0;
u8 *pu8BufferPtr;
u32 u32RcvdSurveyResultsNum = 2;
u8 u8ReadSurveyResFragNum;
u32 i;
u32 j;
for (i = 0; i < u32RcvdSurveyResultsNum; i++) {
u32SurveyBytesLength = ppu8RcvdSiteSurveyResults[i][0];
for (j = 0; j < u32SurveyBytesLength; j += SURVEY_RESULT_LENGTH) {
u32SurveyResultsCount++;
}
}
pstrSurveyResults = kmalloc_array(u32SurveyResultsCount,
sizeof(wid_site_survey_reslts_s), GFP_KERNEL);
if (!pstrSurveyResults)
return -ENOMEM;
memset((void *)(pstrSurveyResults), 0, u32SurveyResultsCount * sizeof(wid_site_survey_reslts_s));
u32SurveyResultsCount = 0;
for (i = 0; i < u32RcvdSurveyResultsNum; i++) {
pu8BufferPtr = ppu8RcvdSiteSurveyResults[i];
u32SurveyBytesLength = pu8BufferPtr[0];
/* TODO: mostafa: pu8BufferPtr[1] contains the fragment num */
u8ReadSurveyResFragNum = pu8BufferPtr[1];
pu8BufferPtr += 2;
for (j = 0; j < u32SurveyBytesLength; j += SURVEY_RESULT_LENGTH) {
memcpy(&pstrSurveyResults[u32SurveyResultsCount], pu8BufferPtr, SURVEY_RESULT_LENGTH);
pu8BufferPtr += SURVEY_RESULT_LENGTH;
u32SurveyResultsCount++;
}
}
ERRORHANDLER:
*ppstrSurveyResults = pstrSurveyResults;
*pu32SurveyResultsCount = u32SurveyResultsCount;
return s32Error;
}
s32 DeallocateSurveyResults(wid_site_survey_reslts_s *pstrSurveyResults)
{
s32 s32Error = WILC_SUCCESS;
if (pstrSurveyResults != NULL) {
kfree(pstrSurveyResults);
}
return s32Error;
}
#endif
/*****************************************************************************/
/* */
/* Function Name : ProcessCharWid */
/* */
/* Description : This function processes a WID of type WID_CHAR and */
/* updates the cfg packet with the supplied value. */
/* */
/* Inputs : 1) Pointer to WID cfg structure */
/* 2) Value to set */
/* */
/* Globals : */
/* */
/* Processing : */
/* */
/* Outputs : None */
/* */
/* Returns : None */
/* */
/* Issues : None */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 08 01 2008 Ittiam Draft */
/* */
/*****************************************************************************/
void ProcessCharWid(char *pcPacket, s32 *ps32PktLen,
tstrWID *pstrWID, s8 *ps8WidVal)
{
u8 *pu8val = (u8 *)ps8WidVal;
u8 u8val = 0;
s32 s32PktLen = *ps32PktLen;
if (pstrWID == NULL) {
PRINT_WRN(CORECONFIG_DBG, "Can't set CHAR val 0x%x ,NULL structure\n", u8val);
return;
}
/* WID */
pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF);
pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid >> 8) & 0xFF;
if (g_oper_mode == SET_CFG) {
u8val = *pu8val;
/* Length */
pcPacket[s32PktLen++] = sizeof(u8);
/* Value */
pcPacket[s32PktLen++] = u8val;
}
*ps32PktLen = s32PktLen;
}
/*****************************************************************************/
/* */
/* Function Name : ProcessShortWid */
/* */
/* Description : This function processes a WID of type WID_SHORT and */
/* updates the cfg packet with the supplied value. */
/* */
/* Inputs : 1) Pointer to WID cfg structure */
/* 2) Value to set */
/* */
/* Globals : */
/* */
/* Processing : */
/* */
/* Outputs : None */
/* */
/* Returns : None */
/* */
/* Issues : None */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 08 01 2008 Ittiam Draft */
/* */
/*****************************************************************************/
void ProcessShortWid(char *pcPacket, s32 *ps32PktLen,
tstrWID *pstrWID, s8 *ps8WidVal)
{
u16 *pu16val = (u16 *)ps8WidVal;
u16 u16val = 0;
s32 s32PktLen = *ps32PktLen;
if (pstrWID == NULL) {
PRINT_WRN(CORECONFIG_DBG, "Can't set SHORT val 0x%x ,NULL structure\n", u16val);
return;
}
/* WID */
pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF);
pcPacket[s32PktLen++] = (u8)((pstrWID->u16WIDid >> 8) & 0xFF);
if (g_oper_mode == SET_CFG) {
u16val = *pu16val;
/* Length */
pcPacket[s32PktLen++] = sizeof(u16);
/* Value */
pcPacket[s32PktLen++] = (u8)(u16val & 0xFF);
pcPacket[s32PktLen++] = (u8)((u16val >> 8) & 0xFF);
}
*ps32PktLen = s32PktLen;
}
/*****************************************************************************/
/* */
/* Function Name : ProcessIntWid */
/* */
/* Description : This function processes a WID of type WID_INT and */
/* updates the cfg packet with the supplied value. */
/* */
/* Inputs : 1) Pointer to WID cfg structure */
/* 2) Value to set */
/* */
/* Globals : */
/* */
/* Processing : */
/* */
/* Outputs : None */
/* */
/* Returns : None */
/* */
/* Issues : None */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 08 01 2008 Ittiam Draft */
/* */
/*****************************************************************************/
void ProcessIntWid(char *pcPacket, s32 *ps32PktLen,
tstrWID *pstrWID, s8 *ps8WidVal)
{
u32 *pu32val = (u32 *)ps8WidVal;
u32 u32val = 0;
s32 s32PktLen = *ps32PktLen;
if (pstrWID == NULL) {
PRINT_WRN(CORECONFIG_DBG, "Can't set INT val 0x%x , NULL structure\n", u32val);
return;
}
/* WID */
pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF);
pcPacket[s32PktLen++] = (u8)((pstrWID->u16WIDid >> 8) & 0xFF);
if (g_oper_mode == SET_CFG) {
u32val = *pu32val;
/* Length */
pcPacket[s32PktLen++] = sizeof(u32);
/* Value */
pcPacket[s32PktLen++] = (u8)(u32val & 0xFF);
pcPacket[s32PktLen++] = (u8)((u32val >> 8) & 0xFF);
pcPacket[s32PktLen++] = (u8)((u32val >> 16) & 0xFF);
pcPacket[s32PktLen++] = (u8)((u32val >> 24) & 0xFF);
}
*ps32PktLen = s32PktLen;
}
/*****************************************************************************/
/* */
/* Function Name : ProcessIPwid */
/* */
/* Description : This function processes a WID of type WID_IP and */
/* updates the cfg packet with the supplied value. */
/* */
/* Inputs : 1) Pointer to WID cfg structure */
/* 2) Value to set */
/* */
/* Globals : */
/* */
/* */
/* Processing : */
/* */
/* Outputs : None */
/* */
/* Returns : None */
/* */
/* Issues : None */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 08 01 2008 Ittiam Draft */
/* */
/*****************************************************************************/
void ProcessIPwid(char *pcPacket, s32 *ps32PktLen,
tstrWID *pstrWID, u8 *pu8ip)
{
u32 u32val = 0;
s32 s32PktLen = *ps32PktLen;
if (pstrWID == NULL) {
PRINT_WRN(CORECONFIG_DBG, "Can't set IP Addr , NULL structure\n");
return;
}
/* WID */
pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF);
pcPacket[s32PktLen++] = (u8)((pstrWID->u16WIDid >> 8) & 0xFF);
if (g_oper_mode == SET_CFG) {
/* Length */
pcPacket[s32PktLen++] = sizeof(u32);
/* Convert the IP Address String to Integer */
conv_ip_to_int(pu8ip, &u32val);
/* Value */
pcPacket[s32PktLen++] = (u8)(u32val & 0xFF);
pcPacket[s32PktLen++] = (u8)((u32val >> 8) & 0xFF);
pcPacket[s32PktLen++] = (u8)((u32val >> 16) & 0xFF);
pcPacket[s32PktLen++] = (u8)((u32val >> 24) & 0xFF);
}
*ps32PktLen = s32PktLen;
}
/*****************************************************************************/
/* */
/* Function Name : ProcessStrWid */
/* */
/* Description : This function processes a WID of type WID_STR and */
/* updates the cfg packet with the supplied value. */
/* */
/* Inputs : 1) Pointer to WID cfg structure */
/* 2) Value to set */
/* */
/* Globals : */
/* */
/* Processing : */
/* */
/* Outputs : None */
/* */
/* Returns : None */
/* */
/* Issues : None */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 08 01 2008 Ittiam Draft */
/* */
/*****************************************************************************/
void ProcessStrWid(char *pcPacket, s32 *ps32PktLen,
tstrWID *pstrWID, u8 *pu8val, s32 s32ValueSize)
{
u16 u16MsgLen = 0;
u16 idx = 0;
s32 s32PktLen = *ps32PktLen;
if (pstrWID == NULL) {
PRINT_WRN(CORECONFIG_DBG, "Can't set STR val, NULL structure\n");
return;
}
/* WID */
pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF);
pcPacket[s32PktLen++] = (u8)((pstrWID->u16WIDid >> 8) & 0xFF);
if (g_oper_mode == SET_CFG) {
/* Message Length */
u16MsgLen = (u16)s32ValueSize;
/* Length */
pcPacket[s32PktLen++] = (u8)u16MsgLen;
/* Value */
for (idx = 0; idx < u16MsgLen; idx++)
pcPacket[s32PktLen++] = pu8val[idx];
}
*ps32PktLen = s32PktLen;
}
/*****************************************************************************/
/* */
/* Function Name : ProcessAdrWid */
/* */
/* Description : This function processes a WID of type WID_ADR and */
/* updates the cfg packet with the supplied value. */
/* */
/* Inputs : 1) Pointer to WID cfg structure */
/* 2) Value to set */
/* */
/* Globals : */
/* */
/* Processing : */
/* */
/* Outputs : None */
/* */
/* Returns : None */
/* */
/* Issues : None */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 08 01 2008 Ittiam Draft */
/* */
/*****************************************************************************/
void ProcessAdrWid(char *pcPacket, s32 *ps32PktLen,
tstrWID *pstrWID, u8 *pu8val)
{
u16 u16MsgLen = 0;
s32 s32PktLen = *ps32PktLen;
if (pstrWID == NULL) {
PRINT_WRN(CORECONFIG_DBG, "Can't set Addr WID, NULL structure\n");
return;
}
/* WID */
pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF);
pcPacket[s32PktLen++] = (u8)((pstrWID->u16WIDid >> 8) & 0xFF);
if (g_oper_mode == SET_CFG) {
/* Message Length */
u16MsgLen = MAC_ADDR_LEN;
/* Length */
pcPacket[s32PktLen++] = (u8)u16MsgLen;
/* Value */
extract_mac_addr(pu8val, pcPacket + s32PktLen);
s32PktLen += u16MsgLen;
}
*ps32PktLen = s32PktLen;
}
/*****************************************************************************/
/* */
/* Function Name : ProcessBinWid */
/* */
/* Description : This function processes a WID of type WID_BIN_DATA and */
/* updates the cfg packet with the supplied value. */
/* */
/* Inputs : 1) Pointer to WID cfg structure */
/* 2) Name of file containing the binary data in text mode */
/* */
/* Globals : */
/* */
/* Processing : The binary data is expected to be supplied through a */
/* file in text mode. This file is expected to be in the */
/* finject format. It is parsed, converted to binary format */
/* and copied into g_cfg_pkt for further processing. This */
/* is obviously a round-about way of processing involving */
/* multiple (re)conversions between bin & ascii formats. */
/* But it is done nevertheless to retain uniformity and for */
/* ease of debugging. */
/* */
/* Outputs : None */
/* */
/* Returns : None */
/* */
/* Issues : None */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 08 01 2008 Ittiam Draft */
/* */
/*****************************************************************************/
void ProcessBinWid(char *pcPacket, s32 *ps32PktLen,
tstrWID *pstrWID, u8 *pu8val, s32 s32ValueSize)
{
u16 u16MsgLen = 0;
u16 idx = 0;
s32 s32PktLen = *ps32PktLen;
u8 u8checksum = 0;
if (pstrWID == NULL) {
PRINT_WRN(CORECONFIG_DBG, "Can't set BIN val, NULL structure\n");
return;
}
/* WID */
pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF);
pcPacket[s32PktLen++] = (u8)((pstrWID->u16WIDid >> 8) & 0xFF);
if (g_oper_mode == SET_CFG) {
/* Message Length */
u16MsgLen = (u16)s32ValueSize;
/* Length */
/* pcPacket[s32PktLen++] = (u8)u16MsgLen; */
pcPacket[s32PktLen++] = (u8)(u16MsgLen & 0xFF);
pcPacket[s32PktLen++] = (u8)((u16MsgLen >> 8) & 0xFF);
/* Value */
for (idx = 0; idx < u16MsgLen; idx++)
pcPacket[s32PktLen++] = pu8val[idx];
/* checksum */
for (idx = 0; idx < u16MsgLen; idx++)
u8checksum += pcPacket[MSG_HEADER_LEN + idx + 4];
pcPacket[s32PktLen++] = u8checksum;
}
*ps32PktLen = s32PktLen;
}
/*****************************************************************************/
/* */
/* Function Name : further_process_response */
/* */
/* Description : This function parses the response frame got from the */
/* device. */
/* */
/* Inputs : 1) The received response frame */
/* 2) WID */
/* 3) WID Length */
/* 4) Output file handle */
/* 5) Process Wid Number(i.e wid from --widn switch) */
/* 6) Index the array in the Global Wid Structure. */
/* */
/* Globals : g_wid_num, gastrWIDs */
/* */
/* Processing : This function parses the response of the device depending*/
/* WID type and writes it to the output file in Hex or */
/* decimal notation depending on the --getx or --get switch.*/
/* */
/* Outputs : None */
/* */
/* Returns : 0 on Success & -2 on Failure */
/* */
/* Issues : None */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 08 01 2009 Ittiam Draft */
/* */
/*****************************************************************************/
s32 further_process_response(u8 *resp,
u16 u16WIDid,
u16 cfg_len,
bool process_wid_num,
u32 cnt,
tstrWID *pstrWIDresult)
{
u32 retval = 0;
u32 idx = 0;
u8 cfg_chr = 0;
u16 cfg_sht = 0;
u32 cfg_int = 0;
u8 cfg_str[256] = {0};
tenuWIDtype enuWIDtype = WID_UNDEF;
if (process_wid_num)
enuWIDtype = get_wid_type(g_wid_num);
else
enuWIDtype = gastrWIDs[cnt].enuWIDtype;
switch (enuWIDtype) {
case WID_CHAR:
cfg_chr = resp[idx];
/*Set local copy of WID*/
*(pstrWIDresult->ps8WidVal) = cfg_chr;
break;
case WID_SHORT:
{
u16 *pu16val = (u16 *)(pstrWIDresult->ps8WidVal);
cfg_sht = MAKE_WORD16(resp[idx], resp[idx + 1]);
/*Set local copy of WID*/
/* pstrWIDresult->ps8WidVal = (s8*)(s32)cfg_sht; */
*pu16val = cfg_sht;
break;
}
case WID_INT:
{
u32 *pu32val = (u32 *)(pstrWIDresult->ps8WidVal);
cfg_int = MAKE_WORD32(
MAKE_WORD16(resp[idx], resp[idx + 1]),
MAKE_WORD16(resp[idx + 2], resp[idx + 3])
);
/*Set local copy of WID*/
/* pstrWIDresult->ps8WidVal = (s8*)cfg_int; */
*pu32val = cfg_int;
break;
}
case WID_STR:
memcpy(cfg_str, resp + idx, cfg_len);
/* cfg_str[cfg_len] = '\0'; //mostafa: no need currently for NULL termination */
if (pstrWIDresult->s32ValueSize >= cfg_len) {
memcpy(pstrWIDresult->ps8WidVal, cfg_str, cfg_len); /* mostafa: no need currently for the extra NULL byte */
pstrWIDresult->s32ValueSize = cfg_len;
} else {
PRINT_ER("allocated WID buffer length is smaller than the received WID Length\n");
retval = -2;
}
break;
case WID_ADR:
create_mac_addr(cfg_str, resp + idx);
strncpy(pstrWIDresult->ps8WidVal, cfg_str, strlen(cfg_str));
pstrWIDresult->ps8WidVal[strlen(cfg_str)] = '\0';
break;
case WID_IP:
cfg_int = MAKE_WORD32(
MAKE_WORD16(resp[idx], resp[idx + 1]),
MAKE_WORD16(resp[idx + 2], resp[idx + 3])
);
conv_int_to_ip(cfg_str, cfg_int);
break;
case WID_BIN_DATA:
if (pstrWIDresult->s32ValueSize >= cfg_len) {
memcpy(pstrWIDresult->ps8WidVal, resp + idx, cfg_len);
pstrWIDresult->s32ValueSize = cfg_len;
} else {
PRINT_ER("Allocated WID buffer length is smaller than the received WID Length Err(%d)\n", retval);
retval = -2;
}
break;
default:
PRINT_ER("ERROR: Check config database: Error(%d)\n", retval);
retval = -2;
break;
}
return retval;
}
/*****************************************************************************/
/* */
/* Function Name : ParseResponse */
/* */
/* Description : This function parses the command-line options and */
/* creates the config packets which can be sent to the WLAN */
/* station. */
/* */
/* Inputs : 1) The received response frame */
/* */
/* Globals : g_opt_list, gastrWIDs */
/* */
/* Processing : This function parses the options and creates different */
/* types of packets depending upon the WID-type */
/* corresponding to the option. */
/* */
/* Outputs : None */
/* */
/* Returns : 0 on Success & -1 on Failure */
/* */
/* Issues : None */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 08 01 2008 Ittiam Draft */
/* */
/*****************************************************************************/
s32 ParseResponse(u8 *resp, tstrWID *pstrWIDcfgResult)
{
u16 u16RespLen = 0;
u16 u16WIDid = 0;
u16 cfg_len = 0;
tenuWIDtype enuWIDtype = WID_UNDEF;
bool num_wid_processed = false;
u32 cnt = 0;
u32 idx = 0;
u32 ResCnt = 0;
/* Check whether the received frame is a valid response */
if (RESP_MSG_TYPE != resp[0]) {
PRINT_INFO(CORECONFIG_DBG, "Received Message format incorrect.\n");
return -1;
}
/* Extract Response Length */
u16RespLen = MAKE_WORD16(resp[2], resp[3]);
Res_Len = u16RespLen;
for (idx = MSG_HEADER_LEN; idx < u16RespLen; ) {
u16WIDid = MAKE_WORD16(resp[idx], resp[idx + 1]);
cfg_len = resp[idx + 2];
/* Incase of Bin Type Wid, the length is given by two byte field */
enuWIDtype = get_wid_type(u16WIDid);
if (WID_BIN_DATA == enuWIDtype) {
cfg_len |= ((u16)resp[idx + 3] << 8) & 0xFF00;
idx++;
}
idx += 3;
if ((u16WIDid == g_wid_num) && (!num_wid_processed)) {
num_wid_processed = true;
if (-2 == further_process_response(&resp[idx], u16WIDid, cfg_len, true, 0, &pstrWIDcfgResult[ResCnt])) {
return -2;
}
ResCnt++;
} else {
for (cnt = 0; cnt < g_num_total_switches; cnt++) {
if (gastrWIDs[cnt].u16WIDid == u16WIDid) {
if (-2 == further_process_response(&resp[idx], u16WIDid, cfg_len, false, cnt,
&pstrWIDcfgResult[ResCnt])) {
return -2;
}
ResCnt++;
}
}
}
idx += cfg_len;
/* In case if BIN type Wid, The last byte of the Cfg packet is the */
/* Checksum. The WID Length field does not accounts for the checksum. */
/* The Checksum is discarded. */
if (WID_BIN_DATA == enuWIDtype) {
idx++;
}
}
return 0;
}
/**
* @brief parses the write response [just detects its status: success or failure]
* @details
* @param[in] pu8RespBuffer The Response to be parsed
* @return Error code indicating Write Operation status:
* WRITE_RESP_SUCCESS (1) => Write Success.
* WILC_FAIL (-100) => Write Failure.
* @note
* @author Ittiam
* @date 11 Aug 2009
* @version 1.0
*/
s32 ParseWriteResponse(u8 *pu8RespBuffer)
{
s32 s32Error = WILC_FAIL;
u16 u16WIDtype = (u16)WID_NIL;
/* Check whether the received frame is a valid response */
if (RESP_MSG_TYPE != pu8RespBuffer[0]) {
PRINT_ER("Received Message format incorrect.\n");
return WILC_FAIL;
}
u16WIDtype = MAKE_WORD16(pu8RespBuffer[4], pu8RespBuffer[5]);
/* Check for WID_STATUS ID and then check the length and status value */
if ((u16WIDtype == WID_STATUS) &&
(pu8RespBuffer[6] == 1) &&
(pu8RespBuffer[7] == WRITE_RESP_SUCCESS)) {
s32Error = WRITE_RESP_SUCCESS;
return s32Error;
}
/* If the length or status are not as expected return failure */
s32Error = WILC_FAIL;
return s32Error;
}
/**
* @brief creates the header of the Configuration Packet
* @details
* @param[in,out] pcpacket The Configuration Packet
* @param[in,out] ps32PacketLength Length of the Configuration Packet
* @return Error code indicating success/failure
* @note
* @author aismail
* @date 18 Feb 2012
* @version 1.0
*/
s32 CreatePacketHeader(char *pcpacket, s32 *ps32PacketLength)
{
s32 s32Error = WILC_SUCCESS;
u16 u16MsgLen = (u16)(*ps32PacketLength);
u16 u16MsgInd = 0;
/* The format of the message is: */
/* +-------------------------------------------------------------------+ */
/* | Message Type | Message ID | Message Length |Message body | */
/* +-------------------------------------------------------------------+ */
/* | 1 Byte | 1 Byte | 2 Bytes | Message Length - 4 | */
/* +-------------------------------------------------------------------+ */
/* The format of a message body of a message type 'W' is: */
/* +-------------------------------------------------------------------+ */
/* | WID0 | WID0 Length | WID0 Value | ......................... | */
/* +-------------------------------------------------------------------+ */
/* | 2 Bytes | 1 Byte | WID0 Length | ......................... | */
/* +-------------------------------------------------------------------+ */
/* Message Type */
if (g_oper_mode == SET_CFG)
pcpacket[u16MsgInd++] = WRITE_MSG_TYPE;
else
pcpacket[u16MsgInd++] = QUERY_MSG_TYPE;
/* Sequence Number */
pcpacket[u16MsgInd++] = g_seqno++;
/* Message Length */
pcpacket[u16MsgInd++] = (u8)(u16MsgLen & 0xFF);
pcpacket[u16MsgInd++] = (u8)((u16MsgLen >> 8) & 0xFF);
*ps32PacketLength = u16MsgLen;
return s32Error;
}
/**
* @brief creates Configuration packet based on the Input WIDs
* @details
* @param[in] pstrWIDs WIDs to be sent in the configuration packet
* @param[in] u32WIDsCount number of WIDs to be sent in the configuration packet
* @param[out] ps8packet The created Configuration Packet
* @param[out] ps32PacketLength Length of the created Configuration Packet
* @return Error code indicating success/failure
* @note
* @author
* @date 1 Mar 2012
* @version 1.0
*/
s32 CreateConfigPacket(s8 *ps8packet, s32 *ps32PacketLength,
tstrWID *pstrWIDs, u32 u32WIDsCount)
{
s32 s32Error = WILC_SUCCESS;
u32 u32idx = 0;
*ps32PacketLength = MSG_HEADER_LEN;
for (u32idx = 0; u32idx < u32WIDsCount; u32idx++) {
switch (pstrWIDs[u32idx].enuWIDtype) {
case WID_CHAR:
ProcessCharWid(ps8packet, ps32PacketLength, &pstrWIDs[u32idx],
pstrWIDs[u32idx].ps8WidVal);
break;
case WID_SHORT:
ProcessShortWid(ps8packet, ps32PacketLength, &pstrWIDs[u32idx],
pstrWIDs[u32idx].ps8WidVal);
break;
case WID_INT:
ProcessIntWid(ps8packet, ps32PacketLength, &pstrWIDs[u32idx],
pstrWIDs[u32idx].ps8WidVal);
break;
case WID_STR:
ProcessStrWid(ps8packet, ps32PacketLength, &pstrWIDs[u32idx],
pstrWIDs[u32idx].ps8WidVal, pstrWIDs[u32idx].s32ValueSize);
break;
case WID_IP:
ProcessIPwid(ps8packet, ps32PacketLength, &pstrWIDs[u32idx],
pstrWIDs[u32idx].ps8WidVal);
break;
case WID_BIN_DATA:
ProcessBinWid(ps8packet, ps32PacketLength, &pstrWIDs[u32idx],
pstrWIDs[u32idx].ps8WidVal, pstrWIDs[u32idx].s32ValueSize);
break;
default:
PRINT_ER("ERROR: Check Config database\n");
}
}
CreatePacketHeader(ps8packet, ps32PacketLength);
return s32Error;
}
s32 ConfigWaitResponse(char *pcRespBuffer, s32 s32MaxRespBuffLen, s32 *ps32BytesRead,
bool bRespRequired)
{
s32 s32Error = WILC_SUCCESS;
/*bug 3878*/
/*removed to caller function*/
/*gstrConfigPktInfo.pcRespBuffer = pcRespBuffer;
* gstrConfigPktInfo.s32MaxRespBuffLen = s32MaxRespBuffLen;
* gstrConfigPktInfo.bRespRequired = bRespRequired;*/
if (gstrConfigPktInfo.bRespRequired) {
down(&SemHandlePktResp);
*ps32BytesRead = gstrConfigPktInfo.s32BytesRead;
}
memset((void *)(&gstrConfigPktInfo), 0, sizeof(tstrConfigPktInfo));
return s32Error;
}
s32 ConfigProvideResponse(char *pcRespBuffer, s32 s32RespLen)
{
s32 s32Error = WILC_SUCCESS;
if (gstrConfigPktInfo.bRespRequired) {
if (s32RespLen <= gstrConfigPktInfo.s32MaxRespBuffLen) {
memcpy(gstrConfigPktInfo.pcRespBuffer, pcRespBuffer, s32RespLen);
gstrConfigPktInfo.s32BytesRead = s32RespLen;
} else {
memcpy(gstrConfigPktInfo.pcRespBuffer, pcRespBuffer, gstrConfigPktInfo.s32MaxRespBuffLen);
gstrConfigPktInfo.s32BytesRead = gstrConfigPktInfo.s32MaxRespBuffLen;
PRINT_ER("BusProvideResponse() Response greater than the prepared Buffer Size\n");
}
up(&SemHandlePktResp);
}
return s32Error;
}
/**
* @brief writes the received packet pu8RxPacket in the global Rx FIFO buffer
* @details
* @param[in] pu8RxPacket The received packet
* @param[in] s32RxPacketLen Length of the received packet
* @return Error code indicating success/failure
* @note
*
* @author mabubakr
* @date 1 Mar 2012
* @version 1.0
*/
s32 ConfigPktReceived(u8 *pu8RxPacket, s32 s32RxPacketLen)
{
s32 s32Error = WILC_SUCCESS;
u8 u8MsgType = 0;
u8MsgType = pu8RxPacket[0];
switch (u8MsgType) {
case 'R':
ConfigProvideResponse(pu8RxPacket, s32RxPacketLen);
break;
case 'N':
PRINT_INFO(CORECONFIG_DBG, "NetworkInfo packet received\n");
NetworkInfoReceived(pu8RxPacket, s32RxPacketLen);
break;
case 'I':
GnrlAsyncInfoReceived(pu8RxPacket, s32RxPacketLen);
break;
case 'S':
host_int_ScanCompleteReceived(pu8RxPacket, s32RxPacketLen);
break;
default:
PRINT_ER("ConfigPktReceived(): invalid received msg type at the Core Configurator\n");
break;
}
return s32Error;
}
/**
* @brief Deinitializes the Core Configurator
* @details
* @return Error code indicating success/failure
* @note
* @author mabubakr
* @date 1 Mar 2012
* @version 1.0
*/
s32 CoreConfiguratorDeInit(void)
{
s32 s32Error = WILC_SUCCESS;
PRINT_D(CORECONFIG_DBG, "CoreConfiguratorDeInit()\n");
return s32Error;
}
/*Using the global handle of the driver*/
extern wilc_wlan_oup_t *gpstrWlanOps;
/**
* @brief sends certain Configuration Packet based on the input WIDs pstrWIDs
* using driver config layer
*
* @details
* @param[in] pstrWIDs WIDs to be sent in the configuration packet
* @param[in] u32WIDsCount number of WIDs to be sent in the configuration packet
* @param[out] pu8RxResp The received Packet Response
* @param[out] ps32RxRespLen Length of the received Packet Response
* @return Error code indicating success/failure
* @note
* @author mabubakr
* @date 1 Mar 2012
* @version 1.0
*/
s32 SendConfigPkt(u8 u8Mode, tstrWID *pstrWIDs,
u32 u32WIDsCount, bool bRespRequired, u32 drvHandler)
{
s32 counter = 0, ret = 0;
if (gpstrWlanOps == NULL) {
PRINT_D(CORECONFIG_DBG, "Net Dev is still not initialized\n");
return 1;
} else {
PRINT_D(CORECONFIG_DBG, "Net Dev is initialized\n");
}
if (gpstrWlanOps->wlan_cfg_set == NULL ||
gpstrWlanOps->wlan_cfg_get == NULL) {
PRINT_D(CORECONFIG_DBG, "Set and Get is still not initialized\n");
return 1;
} else {
PRINT_D(CORECONFIG_DBG, "SET is initialized\n");
}
if (u8Mode == GET_CFG) {
for (counter = 0; counter < u32WIDsCount; counter++) {
PRINT_INFO(CORECONFIG_DBG, "Sending CFG packet [%d][%d]\n", !counter,
(counter == u32WIDsCount - 1));
if (!gpstrWlanOps->wlan_cfg_get(!counter,
pstrWIDs[counter].u16WIDid,
(counter == u32WIDsCount - 1), drvHandler)) {
ret = -1;
printk("[Sendconfigpkt]Get Timed out\n");
break;
}
}
/**
* get the value
**/
counter = 0;
for (counter = 0; counter < u32WIDsCount; counter++) {
pstrWIDs[counter].s32ValueSize = gpstrWlanOps->wlan_cfg_get_value(
pstrWIDs[counter].u16WIDid,
pstrWIDs[counter].ps8WidVal, pstrWIDs[counter].s32ValueSize);
}
} else if (u8Mode == SET_CFG) {
for (counter = 0; counter < u32WIDsCount; counter++) {
PRINT_D(CORECONFIG_DBG, "Sending config SET PACKET WID:%x\n", pstrWIDs[counter].u16WIDid);
if (!gpstrWlanOps->wlan_cfg_set(!counter,
pstrWIDs[counter].u16WIDid, pstrWIDs[counter].ps8WidVal,
pstrWIDs[counter].s32ValueSize,
(counter == u32WIDsCount - 1), drvHandler)) {
ret = -1;
printk("[Sendconfigpkt]Set Timed out\n");
break;
}
}
}
return ret;
}