From: Johnny Kim Date: Mon, 11 May 2015 05:30:56 +0000 (+0900) Subject: staging: wilc1000: Add SDIO/SPI 802.11 driver X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=c5c77ba18ea66aa05441c71e38473efb787705a4;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git staging: wilc1000: Add SDIO/SPI 802.11 driver This driver is for the wilc1000 which is a single chip IEEE 802.11 b/g/n device. The driver works together with cfg80211, which is the kernel side of configuration management for wireless devices because the wilc1000 chipset is fullmac where the MLME is managed in hardware. The driver worked from kernel version 2.6.38 and being now ported to several others since then. A TODO file is included as well in this commit. Signed-off-by: Johnny Kim Signed-off-by: Rachel Kim Signed-off-by: Dean Lee Signed-off-by: Chris Park Acked-by: Nicolas Ferre Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index c204ab2693c1..7f6cae5beb90 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -110,4 +110,6 @@ source "drivers/staging/fbtft/Kconfig" source "drivers/staging/fsl-mc/Kconfig" +source "drivers/staging/wilc1000/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 9b9151758bbd..347f6477aa3e 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -47,3 +47,4 @@ obj-$(CONFIG_UNISYSSPAR) += unisys/ obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/ obj-$(CONFIG_FB_TFT) += fbtft/ obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/ +obj-$(CONFIG_WILC1000) += wilc1000/ diff --git a/drivers/staging/wilc1000/Kconfig b/drivers/staging/wilc1000/Kconfig new file mode 100644 index 000000000000..101f908bc9ed --- /dev/null +++ b/drivers/staging/wilc1000/Kconfig @@ -0,0 +1,55 @@ +config WILC1000 + tristate "WILC1000 support (WiFi only)" + ---help--- + This module only support IEEE 802.11n WiFi. + +choice + prompt "Memory Allocation" + depends on WILC1000 + default WILC1000_PREALLOCATE_AT_LOADING_DRIVER + + config WILC1000_PREALLOCATE_AT_LOADING_DRIVER + bool "Preallocate memory at loading driver" + ---help--- + This choice supports static allocation of the memory + for the receive buffer. The driver will allocate the RX buffer + during initial time. The driver will also free the buffer + by calling network device stop. + + config WILC1000_DYNAMICALLY_ALLOCATE_MEMROY + bool "Dynamically allocate memory in real time" + ---help--- + This choice supports dynamic allocation of the memory + for the receive buffer. The driver will allocate the RX buffer + when it is required. +endchoice + + +choice + prompt "Bus Type" + depends on WILC1000 + default WILC1000_SDIO + + config WILC1000_SDIO + bool "SDIO support" + depends on MMC + ---help--- + This module adds support for the SDIO interface of adapters using + WILC chipset. Select this if your platform is using the SDIO bus. + + config WILC1000_SPI + bool "SPI support" + ---help--- + This module adds support for the SPI interface of adapters using + WILC chipset. Select this if your platform is using the SPI bus. +endchoice + + +config WILC1000_HW_OOB_INTR + bool "Use out of band interrupt" + depends on WILC1000 && WILC1000_SDIO + default n + ---help--- + If your platform don't recognize SDIO IRQ, connect chipset external IRQ pin + and check this option. Or, Use this to get all interrupts including SDIO interrupts. + diff --git a/drivers/staging/wilc1000/Makefile b/drivers/staging/wilc1000/Makefile new file mode 100644 index 000000000000..84bd975ff3be --- /dev/null +++ b/drivers/staging/wilc1000/Makefile @@ -0,0 +1,41 @@ +obj-$(CONFIG_WILC1000) += wilc1000.o +obj-$(CONFIG_WILC1000_PREALLOCATE_DURING_SYSTEM_BOOT) += wilc_exported_buf.o + + +ccflags-$(CONFIG_WILC1000_SDIO) += -DWILC_SDIO -DCOMPLEMENT_BOOT +ccflags-$(CONFIG_WILC1000_HW_OOB_INTR) += -DWILC_SDIO_IRQ_GPIO +ccflags-$(CONFIG_WILC1000_SPI) += -DWILC_SPI + +ccflags-y += -DSTA_FIRMWARE=\"atmel/wilc1000_fw.bin\" \ + -DAP_FIRMWARE=\"atmel/wilc1000_ap_fw.bin\" \ + -DP2P_CONCURRENCY_FIRMWARE=\"atmel/wilc1000_p2p_fw.bin\" + +ccflags-y += -I$(src)/ -DEXPORT_SYMTAB -D__CHECK_ENDIAN__ -DWILC_ASIC_A0 \ + -DPLL_WORKAROUND -DCONNECT_DIRECT -DAGING_ALG \ + -DWILC_PARSE_SCAN_IN_HOST -DDISABLE_PWRSAVE_AND_SCAN_DURING_IP \ + -DWILC_PLATFORM=WILC_LINUXKERNEL -Wno-unused-function -DUSE_WIRELESS \ + -DWILC_DEBUGFS +#ccflags-y += -DTCP_ACK_FILTER + +ccflags-$(CONFIG_WILC1000_PREALLOCATE_DURING_SYSTEM_BOOT) += -DMEMORY_STATIC \ + -DWILC_PREALLOC_AT_BOOT + +ccflags-$(CONFIG_WILC1000_PREALLOCATE_AT_LOADING_DRIVER) += -DMEMORY_STATIC \ + -DWILC_PREALLOC_AT_INSMOD + +ccflags-$(CONFIG_WILC1000_DYNAMICALLY_ALLOCATE_MEMROY) += -DWILC_NORMAL_ALLOC + + +wilc1000-objs := wilc_wfi_netdevice.o wilc_wfi_cfgoperations.o linux_wlan.o linux_mon.o \ + wilc_memory.o wilc_msgqueue.o wilc_semaphore.o wilc_sleep.o wilc_strutils.o \ + wilc_thread.o wilc_time.o wilc_timer.o coreconfigurator.o host_interface.o \ + fifo_buffer.o wilc_sdio.o wilc_spi.o wilc_wlan_cfg.o wilc_debugfs.o + +wilc1000-$(CONFIG_WILC1000_SDIO) += linux_wlan_sdio.o +wilc1000-$(CONFIG_WILC1000_SPI) += linux_wlan_spi.o + +WILC1000_SRC_VERSION = 10.0 +PATCHLEVEL = 2 +WILC1000_FW_VERSION = 0 + +ccflags-y += -D__DRIVER_VERSION__=\"$(WILC1000_SRC_VERSION).$(PATCHLEVEL)\" diff --git a/drivers/staging/wilc1000/TODO b/drivers/staging/wilc1000/TODO new file mode 100644 index 000000000000..5dfeb3eda599 --- /dev/null +++ b/drivers/staging/wilc1000/TODO @@ -0,0 +1,8 @@ +TODO: +- remove the defined feature as kernel versions +- remove OS wrapper functions +- remove custom debug and tracing functions +- rework comments and function headers(also coding style) +- remove build warnings +- support soft-ap and p2p mode +- support resume/suspend function diff --git a/drivers/staging/wilc1000/coreconfigsimulator.h b/drivers/staging/wilc1000/coreconfigsimulator.h new file mode 100644 index 000000000000..6c3f431314fa --- /dev/null +++ b/drivers/staging/wilc1000/coreconfigsimulator.h @@ -0,0 +1,20 @@ + +/*! + * @file coreconfigsimulator.h + * @brief + * @author + * @sa coreconfigsimulator.c + * @date 1 Mar 2012 + * @version 1.0 + */ + + +#ifndef CORECONFIGSIMULATOR_H +#define CORECONFIGSIMULATOR_H + + +extern WILC_Sint32 CoreConfigSimulatorInit (void); +extern WILC_Sint32 CoreConfigSimulatorDeInit (void); + + +#endif \ No newline at end of file diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c new file mode 100644 index 000000000000..01625bdda454 --- /dev/null +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -0,0 +1,2201 @@ + +/*! + * @file coreconfigurator.c + * @brief + * @author + * @sa coreconfigurator.h + * @date 1 Mar 2012 + * @version 1.0 + */ + + +/*****************************************************************************/ +/* File Includes */ +/*****************************************************************************/ +#include "itypes.h" +#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 { + WILC_Char *pcRespBuffer; + WILC_Sint32 s32MaxRespBuffLen; + WILC_Sint32 s32BytesRead; + WILC_Bool bRespRequired; +} tstrConfigPktInfo; + + + +/*****************************************************************************/ +/* Extern Variable Declarations */ +/*****************************************************************************/ + + +/*****************************************************************************/ +/* Extern Function Declarations */ +/*****************************************************************************/ +extern WILC_Sint32 SendRawPacket(WILC_Sint8 *ps8Packet, WILC_Sint32 s32PacketLen); +extern void NetworkInfoReceived(WILC_Uint8 *pu8Buffer, WILC_Uint32 u32Length); +extern void GnrlAsyncInfoReceived(WILC_Uint8 *pu8Buffer, WILC_Uint32 u32Length); +extern void host_int_ScanCompleteReceived(WILC_Uint8 *pu8Buffer, WILC_Uint32 u32Length); +/*****************************************************************************/ +/* Global Variables */ +/*****************************************************************************/ +static WILC_SemaphoreHandle SemHandleSendPkt; +static WILC_SemaphoreHandle SemHandlePktResp; + +static WILC_Sint8 *gps8ConfigPacket; + +static tstrConfigPktInfo gstrConfigPktInfo; + +static WILC_Uint8 g_seqno; + +static WILC_Sint16 g_wid_num = -1; + +static WILC_Uint16 Res_Len; + +static WILC_Uint8 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}, +#if 0 + {WID_WEP_KEY_VALUE0, WID_STR}, +#endif + {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 */ +}; + +WILC_Uint16 g_num_total_switches = (sizeof(gastrWIDs) / sizeof(tstrWID)); +/*****************************************************************************/ +/* Static Function Declarations */ +/*****************************************************************************/ + + + +/*****************************************************************************/ +/* Functions */ +/*****************************************************************************/ +INLINE WILC_Uint8 ascii_hex_to_dec(WILC_Uint8 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 WILC_Uint8 get_hex_char(WILC_Uint8 inp) +{ + WILC_Uint8 *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 WILC_Uint16 extract_mac_addr(WILC_Char *str, WILC_Uint8 *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(WILC_Uint8 *str, WILC_Uint8 *buff) +{ + WILC_Uint32 i = 0; + WILC_Uint32 j = 0; + + for (i = 0; i < MAC_ADDR_LEN; i++) { + str[j++] = get_hex_char((WILC_Uint8)((buff[i] >> 4) & 0x0F)); + str[j++] = get_hex_char((WILC_Uint8)(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 WILC_Uint8 conv_ip_to_int(WILC_Uint8 *ips, WILC_Uint32 *ipn) +{ + WILC_Uint8 i = 0; + WILC_Uint8 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 WILC_Uint8 conv_int_to_ip(WILC_Uint8 *ips, WILC_Uint32 ipn) +{ + WILC_Uint8 i = 0; + WILC_Uint8 ipb = 0; + WILC_Uint8 cnt = 0; + WILC_Uint8 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(WILC_Uint32 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 WILC_Uint16 get_beacon_period(WILC_Uint8 *data) +{ + WILC_Uint16 bcn_per = 0; + + bcn_per = data[0]; + bcn_per |= (data[1] << 8); + + return bcn_per; +} + +INLINE WILC_Uint32 get_beacon_timestamp_lo(WILC_Uint8 *data) +{ + WILC_Uint32 time_stamp = 0; + WILC_Uint32 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 UWORD32 get_beacon_timestamp_hi(UWORD8 *data) +{ + UWORD32 time_stamp = 0; + UWORD32 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(WILC_Uint8 *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(WILC_Uint8 *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 WILC_Uint8 get_to_ds(WILC_Uint8 *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 WILC_Uint8 get_from_ds(WILC_Uint8 *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(WILC_Uint8 *pu8msa, WILC_Uint8 *addr) +{ + WILC_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(WILC_Uint8 *pu8msa, WILC_Uint8 *addr) +{ + WILC_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(WILC_Uint8 *pu8msa, WILC_Uint8 *addr) +{ + WILC_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(WILC_Uint8 *data, WILC_Uint8 *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(WILC_Uint8 *data, WILC_Uint8 *ssid, WILC_Uint8 *p_ssid_len) +{ + WILC_Uint8 len = 0; + WILC_Uint8 i = 0; + WILC_Uint8 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 WILC_Uint16 get_cap_info(WILC_Uint8 *data) +{ + WILC_Uint16 cap_info = 0; + WILC_Uint16 index = MAC_HDR_LEN; + tenuFrmSubtype st = BEACON; + + 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 WILC_Uint16 get_assoc_resp_cap_info(WILC_Uint8 *data) +{ + WILC_Uint16 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 WILC_Uint16 get_asoc_status(WILC_Uint8 *data) +{ + WILC_Uint16 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 WILC_Uint16 get_asoc_id(WILC_Uint8 *data) +{ + WILC_Uint16 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 + */ + +WILC_Sint32 CoreConfiguratorInit(void) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_SemaphoreAttrs strSemSendPktAttrs; + tstrWILC_SemaphoreAttrs strSemPktRespAttrs; + + PRINT_D(CORECONFIG_DBG, "CoreConfiguratorInit() \n"); + + WILC_SemaphoreFillDefault(&strSemSendPktAttrs); + strSemSendPktAttrs.u32InitCount = 1; + WILC_SemaphoreCreate(&SemHandleSendPkt, &strSemSendPktAttrs); + + WILC_SemaphoreFillDefault(&strSemPktRespAttrs); + strSemPktRespAttrs.u32InitCount = 0; + WILC_SemaphoreCreate(&SemHandlePktResp, &strSemPktRespAttrs); + + gps8ConfigPacket = (WILC_Sint8 *)WILC_MALLOC(MAX_PACKET_BUFF_SIZE); + if (gps8ConfigPacket == NULL) { + PRINT_ER("failed in gps8ConfigPacket allocation \n"); + s32Error = WILC_NO_MEM; + goto _fail_; + } + + WILC_memset((void *)gps8ConfigPacket, 0, MAX_PACKET_BUFF_SIZE); + + WILC_memset((void *)(&gstrConfigPktInfo), 0, sizeof(tstrConfigPktInfo)); +_fail_: + return s32Error; +} + +WILC_Uint8 *get_tim_elm(WILC_Uint8 *pu8msa, WILC_Uint16 u16RxLen, WILC_Uint16 u16TagParamOffset) +{ + WILC_Uint16 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 */ +WILC_Uint8 get_current_channel_802_11n(WILC_Uint8 *pu8msa, WILC_Uint16 u16RxLen) +{ + WILC_Uint16 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 */ +} + +WILC_Uint8 get_current_channel(WILC_Uint8 *pu8msa, WILC_Uint16 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 + */ +WILC_Sint32 ParseNetworkInfo(WILC_Uint8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrNetworkInfo *pstrNetworkInfo = WILC_NULL; + WILC_Uint8 u8MsgType = 0; + WILC_Uint8 u8MsgID = 0; + WILC_Uint16 u16MsgLen = 0; + + WILC_Uint16 u16WidID = (WILC_Uint16)WID_NIL; + WILC_Uint16 u16WidLen = 0; + WILC_Uint8 *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" */ + { + WILC_Uint8 *pu8msa = 0; + WILC_Uint16 u16RxLen = 0; + WILC_Uint8 *pu8TimElm = 0; + WILC_Uint8 *pu8IEs = 0; + WILC_Uint16 u16IEsLen = 0; + WILC_Uint8 u8index = 0; + WILC_Uint32 u32Tsf_Lo; + WILC_Uint32 u32Tsf_Hi; + + pstrNetworkInfo = (tstrNetworkInfo *)WILC_MALLOC(sizeof(tstrNetworkInfo)); + WILC_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 | ((WILC_Uint64)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 = (WILC_Uint8 *)WILC_MALLOC(u16IEsLen); + WILC_memset((void *)(pstrNetworkInfo->pu8IEs), 0, u16IEsLen); + + WILC_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 + */ +WILC_Sint32 DeallocateNetworkInfo(tstrNetworkInfo *pstrNetworkInfo) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + + if (pstrNetworkInfo != WILC_NULL) { + if (pstrNetworkInfo->pu8IEs != WILC_NULL) { + WILC_FREE(pstrNetworkInfo->pu8IEs); + pstrNetworkInfo->pu8IEs = WILC_NULL; + } else { + s32Error = WILC_FAIL; + } + + WILC_FREE(pstrNetworkInfo); + pstrNetworkInfo = WILC_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 + */ +WILC_Sint32 ParseAssocRespInfo(WILC_Uint8 *pu8Buffer, WILC_Uint32 u32BufferLen, + tstrConnectRespInfo **ppstrConnectRespInfo) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrConnectRespInfo *pstrConnectRespInfo = WILC_NULL; + WILC_Uint16 u16AssocRespLen = 0; + WILC_Uint8 *pu8IEs = 0; + WILC_Uint16 u16IEsLen = 0; + + pstrConnectRespInfo = (tstrConnectRespInfo *)WILC_MALLOC(sizeof(tstrConnectRespInfo)); + WILC_memset((void *)(pstrConnectRespInfo), 0, sizeof(tstrConnectRespInfo)); + + /* u16AssocRespLen = pu8Buffer[0]; */ + u16AssocRespLen = (WILC_Uint16)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 = (WILC_Uint8 *)WILC_MALLOC(u16IEsLen); + WILC_memset((void *)(pstrConnectRespInfo->pu8RespIEs), 0, u16IEsLen); + + WILC_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 + */ +WILC_Sint32 DeallocateAssocRespInfo(tstrConnectRespInfo *pstrConnectRespInfo) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + + if (pstrConnectRespInfo != WILC_NULL) { + if (pstrConnectRespInfo->pu8RespIEs != WILC_NULL) { + WILC_FREE(pstrConnectRespInfo->pu8RespIEs); + pstrConnectRespInfo->pu8RespIEs = WILC_NULL; + } else { + s32Error = WILC_FAIL; + } + + WILC_FREE(pstrConnectRespInfo); + pstrConnectRespInfo = WILC_NULL; + + } else { + s32Error = WILC_FAIL; + } + + return s32Error; +} + +#ifndef CONNECT_DIRECT +WILC_Sint32 ParseSurveyResults(WILC_Uint8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZE], + wid_site_survey_reslts_s **ppstrSurveyResults, + WILC_Uint32 *pu32SurveyResultsCount) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + wid_site_survey_reslts_s *pstrSurveyResults = NULL; + WILC_Uint32 u32SurveyResultsCount = 0; + WILC_Uint32 u32SurveyBytesLength = 0; + WILC_Uint8 *pu8BufferPtr; + WILC_Uint32 u32RcvdSurveyResultsNum = 2; + WILC_Uint8 u8ReadSurveyResFragNum; + WILC_Uint32 i; + WILC_Uint32 j; + + for (i = 0; i < u32RcvdSurveyResultsNum; i++) { + u32SurveyBytesLength = ppu8RcvdSiteSurveyResults[i][0]; + + + for (j = 0; j < u32SurveyBytesLength; j += SURVEY_RESULT_LENGTH) { + u32SurveyResultsCount++; + } + } + + pstrSurveyResults = (wid_site_survey_reslts_s *)WILC_MALLOC(u32SurveyResultsCount * sizeof(wid_site_survey_reslts_s)); + if (pstrSurveyResults == NULL) { + u32SurveyResultsCount = 0; + WILC_ERRORREPORT(s32Error, WILC_NO_MEM); + } + + WILC_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) { + WILC_memcpy(&pstrSurveyResults[u32SurveyResultsCount], pu8BufferPtr, SURVEY_RESULT_LENGTH); + pu8BufferPtr += SURVEY_RESULT_LENGTH; + u32SurveyResultsCount++; + } + } + +ERRORHANDLER: + *ppstrSurveyResults = pstrSurveyResults; + *pu32SurveyResultsCount = u32SurveyResultsCount; + + return s32Error; +} + + +WILC_Sint32 DeallocateSurveyResults(wid_site_survey_reslts_s *pstrSurveyResults) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + + if (pstrSurveyResults != WILC_NULL) { + WILC_FREE(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(WILC_Char *pcPacket, WILC_Sint32 *ps32PktLen, + tstrWID *pstrWID, WILC_Sint8 *ps8WidVal) +{ + WILC_Uint8 *pu8val = (WILC_Uint8 *)ps8WidVal; + WILC_Uint8 u8val = 0; + WILC_Sint32 s32PktLen = *ps32PktLen; + if (pstrWID == NULL) { + PRINT_WRN(CORECONFIG_DBG, "Can't set CHAR val 0x%x ,NULL structure\n", u8val); + return; + } + + /* WID */ + pcPacket[s32PktLen++] = (WILC_Uint8)(pstrWID->u16WIDid & 0xFF); + pcPacket[s32PktLen++] = (WILC_Uint8)(pstrWID->u16WIDid >> 8) & 0xFF; + if (g_oper_mode == SET_CFG) { + u8val = *pu8val; + + /* Length */ + pcPacket[s32PktLen++] = sizeof(WILC_Uint8); + + + /* 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(WILC_Char *pcPacket, WILC_Sint32 *ps32PktLen, + tstrWID *pstrWID, WILC_Sint8 *ps8WidVal) +{ + WILC_Uint16 *pu16val = (WILC_Uint16 *)ps8WidVal; + WILC_Uint16 u16val = 0; + WILC_Sint32 s32PktLen = *ps32PktLen; + if (pstrWID == NULL) { + PRINT_WRN(CORECONFIG_DBG, "Can't set SHORT val 0x%x ,NULL structure\n", u16val); + return; + } + + /* WID */ + pcPacket[s32PktLen++] = (WILC_Uint8)(pstrWID->u16WIDid & 0xFF); + pcPacket[s32PktLen++] = (WILC_Uint8)((pstrWID->u16WIDid >> 8) & 0xFF); + + if (g_oper_mode == SET_CFG) { + u16val = *pu16val; + + /* Length */ + pcPacket[s32PktLen++] = sizeof(WILC_Uint16); + + /* Value */ + pcPacket[s32PktLen++] = (WILC_Uint8)(u16val & 0xFF); + pcPacket[s32PktLen++] = (WILC_Uint8)((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(WILC_Char *pcPacket, WILC_Sint32 *ps32PktLen, + tstrWID *pstrWID, WILC_Sint8 *ps8WidVal) +{ + WILC_Uint32 *pu32val = (WILC_Uint32 *)ps8WidVal; + WILC_Uint32 u32val = 0; + WILC_Sint32 s32PktLen = *ps32PktLen; + if (pstrWID == NULL) { + PRINT_WRN(CORECONFIG_DBG, "Can't set INT val 0x%x , NULL structure\n", u32val); + return; + } + + /* WID */ + pcPacket[s32PktLen++] = (WILC_Uint8)(pstrWID->u16WIDid & 0xFF); + pcPacket[s32PktLen++] = (WILC_Uint8)((pstrWID->u16WIDid >> 8) & 0xFF); + + if (g_oper_mode == SET_CFG) { + u32val = *pu32val; + + /* Length */ + pcPacket[s32PktLen++] = sizeof(WILC_Uint32); + + /* Value */ + pcPacket[s32PktLen++] = (WILC_Uint8)(u32val & 0xFF); + pcPacket[s32PktLen++] = (WILC_Uint8)((u32val >> 8) & 0xFF); + pcPacket[s32PktLen++] = (WILC_Uint8)((u32val >> 16) & 0xFF); + pcPacket[s32PktLen++] = (WILC_Uint8)((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(WILC_Char *pcPacket, WILC_Sint32 *ps32PktLen, + tstrWID *pstrWID, WILC_Uint8 *pu8ip) +{ + WILC_Uint32 u32val = 0; + WILC_Sint32 s32PktLen = *ps32PktLen; + + if (pstrWID == NULL) { + PRINT_WRN(CORECONFIG_DBG, "Can't set IP Addr , NULL structure\n"); + return; + } + + /* WID */ + pcPacket[s32PktLen++] = (WILC_Uint8)(pstrWID->u16WIDid & 0xFF); + pcPacket[s32PktLen++] = (WILC_Uint8)((pstrWID->u16WIDid >> 8) & 0xFF); + + if (g_oper_mode == SET_CFG) { + /* Length */ + pcPacket[s32PktLen++] = sizeof(WILC_Uint32); + + /* Convert the IP Address String to Integer */ + conv_ip_to_int(pu8ip, &u32val); + + /* Value */ + pcPacket[s32PktLen++] = (WILC_Uint8)(u32val & 0xFF); + pcPacket[s32PktLen++] = (WILC_Uint8)((u32val >> 8) & 0xFF); + pcPacket[s32PktLen++] = (WILC_Uint8)((u32val >> 16) & 0xFF); + pcPacket[s32PktLen++] = (WILC_Uint8)((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(WILC_Char *pcPacket, WILC_Sint32 *ps32PktLen, + tstrWID *pstrWID, WILC_Uint8 *pu8val, WILC_Sint32 s32ValueSize) +{ + WILC_Uint16 u16MsgLen = 0; + WILC_Uint16 idx = 0; + WILC_Sint32 s32PktLen = *ps32PktLen; + if (pstrWID == NULL) { + PRINT_WRN(CORECONFIG_DBG, "Can't set STR val, NULL structure\n"); + return; + } + + /* WID */ + pcPacket[s32PktLen++] = (WILC_Uint8)(pstrWID->u16WIDid & 0xFF); + pcPacket[s32PktLen++] = (WILC_Uint8)((pstrWID->u16WIDid >> 8) & 0xFF); + + if (g_oper_mode == SET_CFG) { + /* Message Length */ + /* u16MsgLen = WILC_strlen(pu8val); */ + u16MsgLen = (WILC_Uint16)s32ValueSize; + + /* Length */ + pcPacket[s32PktLen++] = (WILC_Uint8)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(WILC_Char *pcPacket, WILC_Sint32 *ps32PktLen, + tstrWID *pstrWID, WILC_Uint8 *pu8val) +{ + WILC_Uint16 u16MsgLen = 0; + WILC_Sint32 s32PktLen = *ps32PktLen; + + if (pstrWID == NULL) { + PRINT_WRN(CORECONFIG_DBG, "Can't set Addr WID, NULL structure\n"); + return; + } + + /* WID */ + pcPacket[s32PktLen++] = (WILC_Uint8)(pstrWID->u16WIDid & 0xFF); + pcPacket[s32PktLen++] = (WILC_Uint8)((pstrWID->u16WIDid >> 8) & 0xFF); + + if (g_oper_mode == SET_CFG) { + /* Message Length */ + u16MsgLen = MAC_ADDR_LEN; + + /* Length */ + pcPacket[s32PktLen++] = (WILC_Uint8)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(WILC_Char *pcPacket, WILC_Sint32 *ps32PktLen, + tstrWID *pstrWID, WILC_Uint8 *pu8val, WILC_Sint32 s32ValueSize) +{ + /* WILC_ERROR("processing Binary WIDs is not supported \n"); */ + + WILC_Uint16 u16MsgLen = 0; + WILC_Uint16 idx = 0; + WILC_Sint32 s32PktLen = *ps32PktLen; + WILC_Uint8 u8checksum = 0; + + if (pstrWID == NULL) { + PRINT_WRN(CORECONFIG_DBG, "Can't set BIN val, NULL structure\n"); + return; + } + + /* WID */ + pcPacket[s32PktLen++] = (WILC_Uint8)(pstrWID->u16WIDid & 0xFF); + pcPacket[s32PktLen++] = (WILC_Uint8)((pstrWID->u16WIDid >> 8) & 0xFF); + + if (g_oper_mode == SET_CFG) { + /* Message Length */ + u16MsgLen = (WILC_Uint16)s32ValueSize; + + /* Length */ + /* pcPacket[s32PktLen++] = (WILC_Uint8)u16MsgLen; */ + pcPacket[s32PktLen++] = (WILC_Uint8)(u16MsgLen & 0xFF); + pcPacket[s32PktLen++] = (WILC_Uint8)((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 */ +/* */ +/*****************************************************************************/ + +WILC_Sint32 further_process_response(WILC_Uint8 *resp, + WILC_Uint16 u16WIDid, + WILC_Uint16 cfg_len, + WILC_Bool process_wid_num, + WILC_Uint32 cnt, + tstrWID *pstrWIDresult) +{ + WILC_Uint32 retval = 0; + WILC_Uint32 idx = 0; + WILC_Uint8 cfg_chr = 0; + WILC_Uint16 cfg_sht = 0; + WILC_Uint32 cfg_int = 0; + WILC_Uint8 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: + { + WILC_Uint16 *pu16val = (WILC_Uint16 *)(pstrWIDresult->ps8WidVal); + cfg_sht = MAKE_WORD16(resp[idx], resp[idx + 1]); + /*Set local copy of WID*/ + /* pstrWIDresult->ps8WidVal = (WILC_Sint8*)(WILC_Sint32)cfg_sht; */ + *pu16val = cfg_sht; + break; + } + + case WID_INT: + { + WILC_Uint32 *pu32val = (WILC_Uint32 *)(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 = (WILC_Sint8*)cfg_int; */ + *pu32val = cfg_int; + break; + } + + case WID_STR: + WILC_memcpy(cfg_str, resp + idx, cfg_len); + /* cfg_str[cfg_len] = '\0'; //mostafa: no need currently for NULL termination */ + if (process_wid_num) { + /*fprintf(out_file,"0x%4.4x = %s\n",g_wid_num, + * cfg_str);*/ + } else { + /*fprintf(out_file,"%s = %s\n",gastrWIDs[cnt].cfg_switch, + * cfg_str);*/ + } + + if (pstrWIDresult->s32ValueSize >= cfg_len) { + WILC_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); + + WILC_strncpy(pstrWIDresult->ps8WidVal, cfg_str, WILC_strlen(cfg_str)); + pstrWIDresult->ps8WidVal[WILC_strlen(cfg_str)] = '\0'; + if (process_wid_num) { + /*fprintf(out_file,"0x%4.4x = %s\n",g_wid_num, + * cfg_str);*/ + } else { + /*fprintf(out_file,"%s = %s\n",gastrWIDs[cnt].cfg_switch, + * cfg_str);*/ + } + 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); + if (process_wid_num) { + /*fprintf(out_file,"0x%4.4x = %s\n",g_wid_num, + * cfg_str);*/ + } else { + /*fprintf(out_file,"%s = %s\n",gastrWIDs[cnt].cfg_switch, + * cfg_str);*/ + } + break; + + case WID_BIN_DATA: + #if 0 + /* FILE *fp_bin = NULL; */ + WILC_Uint8 first_bin_wid = 1; + if (first_bin_wid) { + /* fp_bin = fopen("wid_response.bin","wb"); */ + first_bin_wid = 0; + } else { + /* fp_bin = fopen("wid_response.bin","ab"); */ + } + + if (/*fp_bin == NULL*/ 0) { + PRINT_ER("Error: Could not open wid_response.bin for write\n"); + return -2; + } + + /* fwrite(resp + idx, cfg_len, 1, fp_bin); */ + + /* fclose(fp_bin); */ + #endif + + if (pstrWIDresult->s32ValueSize >= cfg_len) { + WILC_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 */ +/* */ +/*****************************************************************************/ + +WILC_Sint32 ParseResponse(WILC_Uint8 *resp, tstrWID *pstrWIDcfgResult) +{ + WILC_Uint16 u16RespLen = 0; + WILC_Uint16 u16WIDid = 0; + WILC_Uint16 cfg_len = 0; + tenuWIDtype enuWIDtype = WID_UNDEF; + WILC_Bool num_wid_processed = WILC_FALSE; + WILC_Uint32 cnt = 0; + WILC_Uint32 idx = 0; + WILC_Uint32 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 |= ((WILC_Uint16)resp[idx + 3] << 8) & 0xFF00; + idx++; + } + idx += 3; + if ((u16WIDid == g_wid_num) && (num_wid_processed == WILC_FALSE)) { + num_wid_processed = WILC_TRUE; + + if (-2 == further_process_response(&resp[idx], u16WIDid, cfg_len, WILC_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, WILC_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 + */ + +WILC_Sint32 ParseWriteResponse(WILC_Uint8 *pu8RespBuffer) +{ + WILC_Sint32 s32Error = WILC_FAIL; + WILC_Uint16 u16RespLen = 0; + WILC_Uint16 u16WIDtype = (WILC_Uint16)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; + } + + /* Extract Response Length */ + u16RespLen = MAKE_WORD16(pu8RespBuffer[2], pu8RespBuffer[3]); + + 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 + */ + +WILC_Sint32 CreatePacketHeader(WILC_Char *pcpacket, WILC_Sint32 *ps32PacketLength) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + WILC_Uint16 u16MsgLen = (WILC_Uint16)(*ps32PacketLength); + WILC_Uint16 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++] = (WILC_Uint8)(u16MsgLen & 0xFF); + pcpacket[u16MsgInd++] = (WILC_Uint8)((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 + */ + +WILC_Sint32 CreateConfigPacket(WILC_Sint8 *ps8packet, WILC_Sint32 *ps32PacketLength, + tstrWID *pstrWIDs, WILC_Uint32 u32WIDsCount) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + WILC_Uint32 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; + + #if 0 + case WID_ADR: + ProcessAdrWid(ps8packet, ps32PacketLength, &pstrWIDs[u32idx], + pstrWIDs[u32idx].ps8WidVal); + break; + + #endif + 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; +} + +WILC_Sint32 ConfigWaitResponse(WILC_Char *pcRespBuffer, WILC_Sint32 s32MaxRespBuffLen, WILC_Sint32 *ps32BytesRead, + WILC_Bool bRespRequired) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + /*bug 3878*/ + /*removed to caller function*/ + /*gstrConfigPktInfo.pcRespBuffer = pcRespBuffer; + * gstrConfigPktInfo.s32MaxRespBuffLen = s32MaxRespBuffLen; + * gstrConfigPktInfo.bRespRequired = bRespRequired;*/ + + + if (gstrConfigPktInfo.bRespRequired == WILC_TRUE) { + WILC_SemaphoreAcquire(&SemHandlePktResp, WILC_NULL); + + *ps32BytesRead = gstrConfigPktInfo.s32BytesRead; + } + + WILC_memset((void *)(&gstrConfigPktInfo), 0, sizeof(tstrConfigPktInfo)); + + return s32Error; +} + +/** + * @brief sends certain Configuration Packet based on the input WIDs pstrWIDs + * and retrieves the packet response pu8RxResp + * @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 + */ +#ifdef SIMULATION +WILC_Sint32 SendConfigPkt(WILC_Uint8 u8Mode, tstrWID *pstrWIDs, + WILC_Uint32 u32WIDsCount, WILC_Bool bRespRequired, WILC_Uint32 drvHandler) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + WILC_Sint32 err = WILC_SUCCESS; + WILC_Sint32 s32ConfigPacketLen = 0; + WILC_Sint32 s32RcvdRespLen = 0; + + WILC_SemaphoreAcquire(&SemHandleSendPkt, WILC_NULL); + + /*set the packet mode*/ + g_oper_mode = u8Mode; + + WILC_memset((void *)gps8ConfigPacket, 0, MAX_PACKET_BUFF_SIZE); + + if (CreateConfigPacket(gps8ConfigPacket, &s32ConfigPacketLen, pstrWIDs, u32WIDsCount) != WILC_SUCCESS) { + s32Error = WILC_FAIL; + goto End_ConfigPkt; + } + /*bug 3878*/ + gstrConfigPktInfo.pcRespBuffer = gps8ConfigPacket; + gstrConfigPktInfo.s32MaxRespBuffLen = MAX_PACKET_BUFF_SIZE; + PRINT_INFO(CORECONFIG_DBG, "GLOBAL =bRespRequired =%d\n", bRespRequired); + gstrConfigPktInfo.bRespRequired = bRespRequired; + + s32Error = SendRawPacket(gps8ConfigPacket, s32ConfigPacketLen); + if (s32Error != WILC_SUCCESS) { + goto End_ConfigPkt; + } + + WILC_memset((void *)gps8ConfigPacket, 0, MAX_PACKET_BUFF_SIZE); + + ConfigWaitResponse(gps8ConfigPacket, MAX_PACKET_BUFF_SIZE, &s32RcvdRespLen, bRespRequired); + + + if (bRespRequired == WILC_TRUE) { + /* If the operating Mode is GET, then we expect a response frame from */ + /* the driver. Hence start listening to the port for response */ + if (g_oper_mode == GET_CFG) { + #if 1 + err = ParseResponse(gps8ConfigPacket, pstrWIDs); + if (err != 0) { + s32Error = WILC_FAIL; + goto End_ConfigPkt; + } else { + s32Error = WILC_SUCCESS; + } + #endif + } else { + err = ParseWriteResponse(gps8ConfigPacket); + if (err != WRITE_RESP_SUCCESS) { + s32Error = WILC_FAIL; + goto End_ConfigPkt; + } else { + s32Error = WILC_SUCCESS; + } + } + + + } + + +End_ConfigPkt: + WILC_SemaphoreRelease(&SemHandleSendPkt, WILC_NULL); + + return s32Error; +} +#endif +WILC_Sint32 ConfigProvideResponse(WILC_Char *pcRespBuffer, WILC_Sint32 s32RespLen) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + + if (gstrConfigPktInfo.bRespRequired == WILC_TRUE) { + if (s32RespLen <= gstrConfigPktInfo.s32MaxRespBuffLen) { + WILC_memcpy(gstrConfigPktInfo.pcRespBuffer, pcRespBuffer, s32RespLen); + gstrConfigPktInfo.s32BytesRead = s32RespLen; + } else { + WILC_memcpy(gstrConfigPktInfo.pcRespBuffer, pcRespBuffer, gstrConfigPktInfo.s32MaxRespBuffLen); + gstrConfigPktInfo.s32BytesRead = gstrConfigPktInfo.s32MaxRespBuffLen; + PRINT_ER("BusProvideResponse() Response greater than the prepared Buffer Size \n"); + } + + WILC_SemaphoreRelease(&SemHandlePktResp, WILC_NULL); + } + + 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 + */ + +WILC_Sint32 ConfigPktReceived(WILC_Uint8 *pu8RxPacket, WILC_Sint32 s32RxPacketLen) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + WILC_Uint8 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 + */ + +WILC_Sint32 CoreConfiguratorDeInit(void) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + + PRINT_D(CORECONFIG_DBG, "CoreConfiguratorDeInit() \n"); + + + WILC_SemaphoreDestroy(&SemHandleSendPkt, WILC_NULL); + WILC_SemaphoreDestroy(&SemHandlePktResp, WILC_NULL); + + + if (gps8ConfigPacket != NULL) { + + WILC_FREE(gps8ConfigPacket); + gps8ConfigPacket = NULL; + } + + return s32Error; +} + + +#ifndef SIMULATION +#if WILC_PLATFORM != WILC_WIN32 +/*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 + */ +WILC_Sint32 SendConfigPkt(WILC_Uint8 u8Mode, tstrWID *pstrWIDs, + WILC_Uint32 u32WIDsCount, WILC_Bool bRespRequired, WILC_Uint32 drvHandler) +{ + WILC_Sint32 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 + **/ + /* WILC_Sleep(1000); */ + 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; +} +#endif +#endif diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h new file mode 100644 index 000000000000..9cdfa2ac8fca --- /dev/null +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -0,0 +1,498 @@ + +/*! + * @file coreconfigurator.h + * @brief + * @author + * @sa coreconfigurator.c + * @date 1 Mar 2012 + * @version 1.0 + */ + + +#ifndef CORECONFIGURATOR_H +#define CORECONFIGURATOR_H + +#include "wilc_oswrapper.h" +#include "wilc_wlan_if.h" +/*****************************************************************************/ +/* Constants */ +/*****************************************************************************/ +/* Number of WID Options Supported */ +#define NUM_BASIC_SWITCHES 45 +#define NUM_FHSS_SWITCHES 0 + +#define NUM_RSSI 5 + +#ifdef MAC_802_11N +#define NUM_11N_BASIC_SWITCHES 25 +#define NUM_11N_HUT_SWITCHES 47 +#else /* MAC_802_11N */ +#define NUM_11N_BASIC_SWITCHES 0 +#define NUM_11N_HUT_SWITCHES 0 +#endif /* MAC_802_11N */ + +extern WILC_Uint16 g_num_total_switches; + +#define MAC_HDR_LEN 24 /* No Address4 - non-ESS */ +#define MAX_SSID_LEN 33 +#define FCS_LEN 4 +#define TIME_STAMP_LEN 8 +#define BEACON_INTERVAL_LEN 2 +#define CAP_INFO_LEN 2 +#define STATUS_CODE_LEN 2 +#define AID_LEN 2 +#define IE_HDR_LEN 2 + + +/* Operating Mode: SET */ +#define SET_CFG 0 +/* Operating Mode: GET */ +#define GET_CFG 1 + +#define MAX_PACKET_BUFF_SIZE 1596 + +#define MAX_STRING_LEN 256 +#define MAX_SURVEY_RESULT_FRAG_SIZE MAX_STRING_LEN +#define SURVEY_RESULT_LENGTH 44 +#define MAX_ASSOC_RESP_FRAME_SIZE MAX_STRING_LEN + +#define STATUS_MSG_LEN 12 +#define MAC_CONNECTED 1 +#define MAC_DISCONNECTED 0 + + + +/*****************************************************************************/ +/* Function Macros */ +/*****************************************************************************/ +#define MAKE_WORD16(lsb, msb) ((((WILC_Uint16)(msb) << 8) & 0xFF00) | (lsb)) +#define MAKE_WORD32(lsw, msw) ((((WILC_Uint32)(msw) << 16) & 0xFFFF0000) | (lsw)) + + +/*****************************************************************************/ +/* Type Definitions */ +/*****************************************************************************/ +/* WID Data Types */ +#if 0 +typedef enum { + WID_CHAR = 0, + WID_SHORT = 1, + WID_INT = 2, + WID_STR = 3, + WID_ADR = 4, + WID_BIN = 5, + WID_IP = 6, + WID_UNDEF = 7, + WID_TYPE_FORCE_32BIT = 0xFFFFFFFF +} tenuWIDtype; + +/* WLAN Identifiers */ +typedef enum { + WID_NIL = -1, + /* EMAC Character WID list */ + WID_BSS_TYPE = 0x0000, + WID_CURRENT_TX_RATE = 0x0001, + WID_CURRENT_CHANNEL = 0x0002, + WID_PREAMBLE = 0x0003, + WID_11G_OPERATING_MODE = 0x0004, + WID_STATUS = 0x0005, + WID_11G_PROT_MECH = 0x0006, + WID_SCAN_TYPE = 0x0007, + WID_PRIVACY_INVOKED = 0x0008, + WID_KEY_ID = 0x0009, + WID_QOS_ENABLE = 0x000A, + WID_POWER_MANAGEMENT = 0x000B, + WID_11I_MODE = 0x000C, + WID_AUTH_TYPE = 0x000D, + WID_SITE_SURVEY = 0x000E, + WID_LISTEN_INTERVAL = 0x000F, + WID_DTIM_PERIOD = 0x0010, + WID_ACK_POLICY = 0x0011, + WID_RESET = 0x0012, + WID_PCF_MODE = 0x0013, + WID_CFP_PERIOD = 0x0014, + WID_BCAST_SSID = 0x0015, + WID_PHY_TEST_PATTERN = 0x0016, + WID_DISCONNECT = 0x0016, + WID_READ_ADDR_SDRAM = 0x0017, + WID_TX_POWER_LEVEL_11A = 0x0018, + WID_REKEY_POLICY = 0x0019, + WID_SHORT_SLOT_ALLOWED = 0x001A, + WID_PHY_ACTIVE_REG = 0x001B, + WID_PHY_ACTIVE_REG_VAL = 0x001C, + WID_TX_POWER_LEVEL_11B = 0x001D, + WID_START_SCAN_REQ = 0x001E, + WID_RSSI = 0x001F, + WID_JOIN_REQ = 0x0020, + WID_ANTENNA_SELECTION = 0x0021, + WID_USER_CONTROL_ON_TX_POWER = 0x0027, + WID_MEMORY_ACCESS_8BIT = 0x0029, + WID_UAPSD_SUPPORT_AP = 0x002A, + WID_CURRENT_MAC_STATUS = 0x0031, + WID_AUTO_RX_SENSITIVITY = 0x0032, + WID_DATAFLOW_CONTROL = 0x0033, + WID_SCAN_FILTER = 0x0036, + WID_LINK_LOSS_THRESHOLD = 0x0037, + WID_AUTORATE_TYPE = 0x0038, + WID_CCA_THRESHOLD = 0x0039, + WID_802_11H_DFS_MODE = 0x003B, + WID_802_11H_TPC_MODE = 0x003C, + WID_DEVICE_READY = 0x003D, + WID_PM_NULL_FRAME_INTERVAL = 0x003E, + WID_PM_ACTIVITY_TIMER = 0x003F, + WID_PM_NULL_FRAME_WAIT_ENABLE = 0x0040, + WID_SCAN_WAIT_TIME = 0x0041, + WID_WSC_IE_EN = 0x0042, + WID_WPS_START = 0x0043, + WID_WPS_DEV_MODE = 0x0044, + WID_BT_COEXISTENCE = 0x0050, + WID_TRACKING_ROAMING = 0x0070, + WID_NUM_PKTS_FOR_RSSI_AVG = 0x0071, + WID_FHSS_SCAN_CHAN_INDEX = 0x0072, + WID_FHSS_SCAN_STEP_INDEX = 0x0073, + + /* NMAC Character WID list */ + WID_11N_PROT_MECH = 0x0080, + WID_11N_ERP_PROT_TYPE = 0x0081, + WID_11N_ENABLE = 0x0082, + WID_11N_OPERATING_MODE = 0x0083, + WID_11N_OBSS_NONHT_DETECTION = 0x0084, + WID_11N_HT_PROT_TYPE = 0x0085, + WID_11N_RIFS_PROT_ENABLE = 0x0086, + WID_11N_SMPS_MODE = 0x0087, + WID_11N_CURRENT_TX_MCS = 0x0088, + WID_11N_PRINT_STATS = 0x0089, + WID_HUT_FCS_CORRUPT_MODE = 0x008A, + WID_HUT_RESTART = 0x008B, + WID_HUT_TX_FORMAT = 0x008C, + WID_11N_SHORT_GI_20MHZ_ENABLE = 0x008D, + WID_HUT_BANDWIDTH = 0x008E, + WID_HUT_OP_BAND = 0x008F, + WID_HUT_STBC = 0x0090, + WID_HUT_ESS = 0x0091, + WID_HUT_ANTSET = 0x0092, + WID_HUT_HT_OP_MODE = 0x0093, + WID_HUT_RIFS_MODE = 0x0094, + WID_HUT_SMOOTHING_REC = 0x0095, + WID_HUT_SOUNDING_PKT = 0x0096, + WID_HUT_HT_CODING = 0x0097, + WID_HUT_TEST_DIR = 0x0098, + WID_HUT_CAPTURE_MODE = 0x0099, + WID_HUT_PHY_TEST_MODE = 0x009A, + WID_HUT_PHY_TEST_RATE_HI = 0x009B, + WID_HUT_PHY_TEST_RATE_LO = 0x009C, + WID_HUT_DISABLE_RXQ_REPLENISH = 0x009D, + WID_HUT_KEY_ORIGIN = 0x009E, + WID_HUT_BCST_PERCENT = 0x009F, + WID_HUT_GROUP_CIPHER_TYPE = 0x00A0, + WID_TX_ABORT_CONFIG = 0x00A1, + WID_HOST_DATA_IF_TYPE = 0x00A2, + WID_HOST_CONFIG_IF_TYPE = 0x00A3, + WID_HUT_TSF_TEST_MODE = 0x00A4, + WID_HUT_TSSI_VALUE = 0x00A5, + WID_HUT_PKT_TSSI_VALUE = 0x00A5, + WID_REG_TSSI_11B_VALUE = 0x00A6, + WID_REG_TSSI_11G_VALUE = 0x00A7, + WID_REG_TSSI_11N_VALUE = 0x00A8, + WID_TX_CALIBRATION = 0x00A9, + WID_DSCR_TSSI_11B_VALUE = 0x00AA, + WID_DSCR_TSSI_11G_VALUE = 0x00AB, + WID_DSCR_TSSI_11N_VALUE = 0x00AC, + WID_HUT_RSSI_EX = 0x00AD, + WID_HUT_ADJ_RSSI_EX = 0x00AE, + WID_11N_IMMEDIATE_BA_ENABLED = 0x00AF, + WID_11N_TXOP_PROT_DISABLE = 0x00B0, + WID_TX_POWER_LEVEL_11N = 0x00B1, + WID_HUT_MGMT_PERCENT = 0x00B3, + WID_HUT_MGMT_BCST_PERCENT = 0x00B4, + WID_HUT_MGMT_ALLOW_HT = 0x00B5, + WID_HUT_UC_MGMT_TYPE = 0x00B6, + WID_HUT_BC_MGMT_TYPE = 0x00B7, + WID_HUT_11W_MFP_REQUIRED_TX = 0x00B8, + WID_HUT_11W_MFP_PEER_CAPABLE = 0x00B9, + WID_HUT_11W_TX_IGTK_ID = 0x00BA, + WID_11W_ENABLE = 0x00BB, + WID_11W_MGMT_PROT_REQ = 0x00BC, + WID_USER_SEC_CHANNEL_OFFSET = 0x00C0, + WID_2040_COEXISTENCE = 0x00C1, + WID_HUT_FC_TXOP_MOD = 0x00C2, + WID_HUT_FC_PROT_TYPE = 0x00C3, + WID_HUT_SEC_CCA_ASSERT = 0x00C4, + WID_2040_ENABLE = 0x00C5, + WID_2040_CURR_CHANNEL_OFFSET = 0x00C6, + WID_2040_40MHZ_INTOLERANT = 0x00C7, + + + /* Custom Character WID list */ + WID_POWER_SAVE = 0x0100, + WID_WAKE_STATUS = 0x0101, + WID_WAKE_CONTROL = 0x0102, + WID_CCA_BUSY_START = 0x0103, + + /* EMAC Short WID list */ + WID_RTS_THRESHOLD = 0x1000, + WID_FRAG_THRESHOLD = 0x1001, + WID_SHORT_RETRY_LIMIT = 0x1002, + WID_LONG_RETRY_LIMIT = 0x1003, + WID_CFP_MAX_DUR = 0x1004, + WID_PHY_TEST_FRAME_LEN = 0x1005, + WID_BEACON_INTERVAL = 0x1006, + WID_MEMORY_ACCESS_16BIT = 0x1008, + WID_RX_SENSE = 0x100B, + WID_ACTIVE_SCAN_TIME = 0x100C, + WID_PASSIVE_SCAN_TIME = 0x100D, + WID_SITE_SURVEY_SCAN_TIME = 0x100E, + WID_JOIN_START_TIMEOUT = 0x100F, + WID_AUTH_TIMEOUT = 0x1010, + WID_ASOC_TIMEOUT = 0x1011, + WID_11I_PROTOCOL_TIMEOUT = 0x1012, + WID_EAPOL_RESPONSE_TIMEOUT = 0x1013, + WID_WPS_PASS_ID = 0x1017, + WID_WPS_CONFIG_METHOD = 0x1018, + WID_FHSS_INIT_SCAN_TIME = 0x1070, + WID_FHSS_ROAM_SCAN_TIME = 0x1071, + + /* NMAC Short WID list */ + WID_11N_RF_REG_VAL = 0x1080, + WID_HUT_FRAME_LEN = 0x1081, + WID_HUT_TXOP_LIMIT = 0x1082, + WID_HUT_SIG_QUAL_AVG = 0x1083, + WID_HUT_SIG_QUAL_AVG_CNT = 0x1084, + WID_11N_SIG_QUAL_VAL = 0x1085, + WID_HUT_RSSI_EX_COUNT = 0x1086, + WID_HUT_UC_MGMT_FRAME_LEN = 0x1088, + WID_HUT_BC_MGMT_FRAME_LEN = 0x1089, + + /* Custom Short WID list */ + + WID_CCA_BUSY_STATUS = 0x1100, + + /* EMAC Integer WID list */ + WID_FAILED_COUNT = 0x2000, + WID_RETRY_COUNT = 0x2001, + WID_MULTIPLE_RETRY_COUNT = 0x2002, + WID_FRAME_DUPLICATE_COUNT = 0x2003, + WID_ACK_FAILURE_COUNT = 0x2004, + WID_RECEIVED_FRAGMENT_COUNT = 0x2005, + WID_MCAST_RECEIVED_FRAME_COUNT = 0x2006, + WID_FCS_ERROR_COUNT = 0x2007, + WID_SUCCESS_FRAME_COUNT = 0x2008, + WID_PHY_TEST_PKT_CNT = 0x2009, + WID_HUT_TX_COUNT = 0x200A, + WID_TX_FRAGMENT_COUNT = 0x200B, + WID_TX_MULTICAST_FRAME_COUNT = 0x200C, + WID_RTS_SUCCESS_COUNT = 0x200D, + WID_RTS_FAILURE_COUNT = 0x200E, + WID_WEP_UNDECRYPTABLE_COUNT = 0x200F, + WID_REKEY_PERIOD = 0x2010, + WID_REKEY_PACKET_COUNT = 0x2011, + WID_1X_SERV_ADDR = 0x2012, + WID_STACK_IP_ADDR = 0x2013, + WID_STACK_NETMASK_ADDR = 0x2014, + WID_HW_RX_COUNT = 0x2015, + WID_MEMORY_ADDRESS = 0x201E, + WID_MEMORY_ACCESS_32BIT = 0x201F, + WID_RF_REG_VAL = 0x2021, + WID_FIRMWARE_INFO = 0x2023, + WID_DEV_OS_VERSION = 0x2025, + WID_ROAM_RSSI_THESHOLDS = 0x2070, + WID_TRACK_INTERVAL_SEC = 0x2071, + WID_FHSS_HOPPING_PARAMS = 0x2072, + WID_FHSS_HOP_DWELL_TIME = 0x2073, + + /* NMAC Integer WID list */ + WID_11N_PHY_ACTIVE_REG_VAL = 0x2080, + WID_HUT_NUM_TX_PKTS = 0x2081, + WID_HUT_TX_TIME_TAKEN = 0x2082, + WID_HUT_TX_TEST_TIME = 0x2083, + WID_HUT_LOG_INTERVAL = 0x2084, + + /* EMAC String WID list */ + WID_SSID = 0x3000, + WID_FIRMWARE_VERSION = 0x3001, + WID_OPERATIONAL_RATE_SET = 0x3002, + WID_BSSID = 0x3003, + #if 0 + WID_WEP_KEY_VALUE0 = 0x3004, + #endif + WID_11I_PSK = 0x3008, + WID_11E_P_ACTION_REQ = 0x3009, + WID_1X_KEY = 0x300A, + WID_HARDWARE_VERSION = 0x300B, + WID_MAC_ADDR = 0x300C, + WID_HUT_DEST_ADDR = 0x300D, + /*WID_HUT_STATS = 0x300E,*/ + WID_PHY_VERSION = 0x300F, + WID_SUPP_USERNAME = 0x3010, + WID_SUPP_PASSWORD = 0x3011, + WID_SITE_SURVEY_RESULTS = 0x3012, + WID_RX_POWER_LEVEL = 0x3013, + WID_MANUFACTURER = 0x3026, /*Added for CAPI tool */ + WID_MODEL_NAME = 0x3027, /*Added for CAPI tool */ + WID_MODEL_NUM = 0x3028, /*Added for CAPI tool */ + WID_DEVICE_NAME = 0x3029, /*Added for CAPI tool */ + + WID_ASSOC_RES_INFO = 0x3020, + + /* NMAC String WID list */ + WID_11N_P_ACTION_REQ = 0x3080, + WID_HUT_TEST_ID = 0x3081, + WID_PMKID_INFO = 0x3082, + + /* Custom String WID list */ + WID_FLASH_DATA = 0x3100, + WID_EEPROM_DATA = 0x3101, + WID_SERIAL_NUMBER = 0x3102, + + /* EMAC Binary WID list */ + WID_UAPSD_CONFIG = 0x4001, + WID_UAPSD_STATUS = 0x4002, + WID_AC_PARAMS_AP = 0x4003, + WID_AC_PARAMS_STA = 0x4004, + WID_NEWORK_INFO = 0x4005, + WID_WPS_CRED_LIST = 0x4006, + WID_PRIM_DEV_TYPE = 0x4007, + WID_STA_JOIN_INFO = 0x4008, + WID_CONNECTED_STA_LIST = 0x4009, + + /* NMAC Binary WID list */ + WID_11N_AUTORATE_TABLE = 0x4080, + WID_HUT_TX_PATTERN = 0x4081, + WID_HUT_STATS = 0x4082, + WID_HUT_LOG_STATS = 0x4083, + + /*BugID_3746 WID to add IE to be added in next probe request*/ + WID_INFO_ELEMENT_PROBE = 0x4085, + /*BugID_3746 WID to add IE to be added in next associate request*/ + WID_INFO_ELEMENT_ASSOCIATE = 0x4086, + + /* Miscellaneous WIDs */ + WID_ALL = 0x7FFE, + WID_MAX = 0xFFFF +} tenuWIDid; +#endif + +/* Status Codes for Authentication and Association Frames */ +typedef enum { + SUCCESSFUL_STATUSCODE = 0, + UNSPEC_FAIL = 1, + UNSUP_CAP = 10, + REASOC_NO_ASOC = 11, + FAIL_OTHER = 12, + UNSUPT_ALG = 13, + AUTH_SEQ_FAIL = 14, + CHLNG_FAIL = 15, + AUTH_TIMEOUT = 16, + AP_FULL = 17, + UNSUP_RATE = 18, + SHORT_PREAMBLE_UNSUP = 19, + PBCC_UNSUP = 20, + CHANNEL_AGIL_UNSUP = 21, + SHORT_SLOT_UNSUP = 25, + OFDM_DSSS_UNSUP = 26, + CONNECT_STS_FORCE_16_BIT = 0xFFFF +} tenuConnectSts; + +typedef struct { + WILC_Uint16 u16WIDid; + tenuWIDtype enuWIDtype; + WILC_Sint32 s32ValueSize; + WILC_Sint8 *ps8WidVal; + +} tstrWID; + +typedef struct { + WILC_Uint8 u8Full; + WILC_Uint8 u8Index; + WILC_Sint8 as8RSSI[NUM_RSSI]; +} tstrRSSI; +/* This structure is used to support parsing of the received 'N' message */ +typedef struct { + WILC_Sint8 s8rssi; + WILC_Uint16 u16CapInfo; + WILC_Uint8 au8ssid[MAX_SSID_LEN]; + WILC_Uint8 u8SsidLen; + WILC_Uint8 au8bssid[6]; + WILC_Uint16 u16BeaconPeriod; + WILC_Uint8 u8DtimPeriod; + WILC_Uint8 u8channel; + unsigned long u32TimeRcvdInScanCached; /* of type unsigned long to be accepted by the linux kernel macro time_after() */ + unsigned long u32TimeRcvdInScan; + WILC_Bool bNewNetwork; +#ifdef AGING_ALG + WILC_Uint8 u8Found; +#endif +#ifdef WILC_P2P + WILC_Uint32 u32Tsf; /* time-stamp [Low only 32 bit] */ +#endif + WILC_Uint8 *pu8IEs; + WILC_Uint16 u16IEsLen; + void *pJoinParams; + tstrRSSI strRssi; + WILC_Uint64 u64Tsf; /* time-stamp [Low and High 64 bit] */ +} tstrNetworkInfo; + +/* This structure is used to support parsing of the received Association Response frame */ +typedef struct { + WILC_Uint16 u16capability; + WILC_Uint16 u16ConnectStatus; + WILC_Uint16 u16AssocID; + WILC_Uint8 *pu8RespIEs; + WILC_Uint16 u16RespIEsLen; +} tstrConnectRespInfo; + + +typedef struct { + WILC_Uint8 au8bssid[6]; + WILC_Uint8 *pu8ReqIEs; + size_t ReqIEsLen; + WILC_Uint8 *pu8RespIEs; + WILC_Uint16 u16RespIEsLen; + WILC_Uint16 u16ConnectStatus; +} tstrConnectInfo; + + + +typedef struct { + WILC_Uint16 u16reason; + WILC_Uint8 *ie; + size_t ie_len; +} tstrDisconnectNotifInfo; + +#ifndef CONNECT_DIRECT +typedef struct wid_site_survey_reslts { + WILC_Char SSID[MAX_SSID_LEN]; + WILC_Uint8 BssType; + WILC_Uint8 Channel; + WILC_Uint8 SecurityStatus; + WILC_Uint8 BSSID[6]; + WILC_Char RxPower; + WILC_Uint8 Reserved; + +} wid_site_survey_reslts_s; +#endif + +extern WILC_Sint32 CoreConfiguratorInit(void); +extern WILC_Sint32 CoreConfiguratorDeInit(void); + +extern WILC_Sint32 SendConfigPkt(WILC_Uint8 u8Mode, tstrWID *pstrWIDs, + WILC_Uint32 u32WIDsCount, WILC_Bool bRespRequired, WILC_Uint32 drvHandler); +extern WILC_Sint32 ParseNetworkInfo(WILC_Uint8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo); +extern WILC_Sint32 DeallocateNetworkInfo(tstrNetworkInfo *pstrNetworkInfo); + +extern WILC_Sint32 ParseAssocRespInfo(WILC_Uint8 *pu8Buffer, WILC_Uint32 u32BufferLen, + tstrConnectRespInfo **ppstrConnectRespInfo); +extern WILC_Sint32 DeallocateAssocRespInfo(tstrConnectRespInfo *pstrConnectRespInfo); + +#ifndef CONNECT_DIRECT +extern WILC_Sint32 ParseSurveyResults(WILC_Uint8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZE], + wid_site_survey_reslts_s **ppstrSurveyResults, WILC_Uint32 *pu32SurveyResultsCount); +extern WILC_Sint32 DeallocateSurveyResults(wid_site_survey_reslts_s *pstrSurveyResults); +#endif + +extern WILC_Sint32 SendRawPacket(WILC_Sint8 *pspacket, WILC_Sint32 s32PacketLen); +extern void NetworkInfoReceived(WILC_Uint8 *pu8Buffer, WILC_Uint32 u32Length); +void GnrlAsyncInfoReceived(WILC_Uint8 *pu8Buffer, WILC_Uint32 u32Length); +void host_int_ScanCompleteReceived(WILC_Uint8 *pu8Buffer, WILC_Uint32 u32Length); + +#endif diff --git a/drivers/staging/wilc1000/fifo_buffer.c b/drivers/staging/wilc1000/fifo_buffer.c new file mode 100644 index 000000000000..733d81f2eeca --- /dev/null +++ b/drivers/staging/wilc1000/fifo_buffer.c @@ -0,0 +1,142 @@ + + +#include "wilc_oswrapper.h" +#include "fifo_buffer.h" + + + +WILC_Uint32 FIFO_InitBuffer(tHANDLE *hBuffer, WILC_Uint32 u32BufferLength) +{ + WILC_Uint32 u32Error = 0; + tstrFifoHandler *pstrFifoHandler = WILC_MALLOC (sizeof (tstrFifoHandler)); + if (pstrFifoHandler) { + WILC_memset (pstrFifoHandler, 0, sizeof (tstrFifoHandler)); + pstrFifoHandler->pu8Buffer = WILC_MALLOC (u32BufferLength); + if (pstrFifoHandler->pu8Buffer) { + tstrWILC_SemaphoreAttrs strSemBufferAttrs; + pstrFifoHandler->u32BufferLength = u32BufferLength; + WILC_memset (pstrFifoHandler->pu8Buffer, 0, u32BufferLength); + /* create semaphore */ + WILC_SemaphoreFillDefault (&strSemBufferAttrs); + strSemBufferAttrs.u32InitCount = 1; + WILC_SemaphoreCreate(&pstrFifoHandler->SemBuffer, &strSemBufferAttrs); + *hBuffer = pstrFifoHandler; + } else { + *hBuffer = NULL; + u32Error = 1; + } + } else { + u32Error = 1; + } + return u32Error; +} +WILC_Uint32 FIFO_DeInit(tHANDLE hFifo) +{ + WILC_Uint32 u32Error = 0; + tstrFifoHandler *pstrFifoHandler = (tstrFifoHandler *) hFifo; + if (pstrFifoHandler) { + if (pstrFifoHandler->pu8Buffer) { + WILC_FREE (pstrFifoHandler->pu8Buffer); + } else { + u32Error = 1; + } + + WILC_SemaphoreDestroy (&pstrFifoHandler->SemBuffer, WILC_NULL); + + WILC_FREE (pstrFifoHandler); + } else { + u32Error = 1; + } + return u32Error; +} + +WILC_Uint32 FIFO_ReadBytes(tHANDLE hFifo, WILC_Uint8 *pu8Buffer, WILC_Uint32 u32BytesToRead, WILC_Uint32 *pu32BytesRead) +{ + WILC_Uint32 u32Error = 0; + tstrFifoHandler *pstrFifoHandler = (tstrFifoHandler *) hFifo; + if (pstrFifoHandler && pu32BytesRead) { + if (pstrFifoHandler->u32TotalBytes) { + if (WILC_SemaphoreAcquire(&pstrFifoHandler->SemBuffer, WILC_NULL) == WILC_SUCCESS) { + if (u32BytesToRead > pstrFifoHandler->u32TotalBytes) { + *pu32BytesRead = pstrFifoHandler->u32TotalBytes; + } else { + *pu32BytesRead = u32BytesToRead; + } + if ((pstrFifoHandler->u32ReadOffset + u32BytesToRead) <= pstrFifoHandler->u32BufferLength) { + WILC_memcpy(pu8Buffer, pstrFifoHandler->pu8Buffer + pstrFifoHandler->u32ReadOffset, + *pu32BytesRead); + /* update read offset and total bytes */ + pstrFifoHandler->u32ReadOffset += u32BytesToRead; + pstrFifoHandler->u32TotalBytes -= u32BytesToRead; + + } else { + WILC_Uint32 u32FirstPart = + pstrFifoHandler->u32BufferLength - pstrFifoHandler->u32ReadOffset; + WILC_memcpy(pu8Buffer, pstrFifoHandler->pu8Buffer + pstrFifoHandler->u32ReadOffset, + u32FirstPart); + WILC_memcpy(pu8Buffer + u32FirstPart, pstrFifoHandler->pu8Buffer, + u32BytesToRead - u32FirstPart); + /* update read offset and total bytes */ + pstrFifoHandler->u32ReadOffset = u32BytesToRead - u32FirstPart; + pstrFifoHandler->u32TotalBytes -= u32BytesToRead; + } + WILC_SemaphoreRelease (&pstrFifoHandler->SemBuffer, WILC_NULL); + } else { + u32Error = 1; + } + } else { + u32Error = 1; + } + } else { + u32Error = 1; + } + return u32Error; +} + +WILC_Uint32 FIFO_WriteBytes(tHANDLE hFifo, WILC_Uint8 *pu8Buffer, WILC_Uint32 u32BytesToWrite, WILC_Bool bForceOverWrite) +{ + WILC_Uint32 u32Error = 0; + tstrFifoHandler *pstrFifoHandler = (tstrFifoHandler *) hFifo; + if (pstrFifoHandler) { + if (u32BytesToWrite < pstrFifoHandler->u32BufferLength) { + if ((pstrFifoHandler->u32TotalBytes + u32BytesToWrite) <= pstrFifoHandler->u32BufferLength || + bForceOverWrite) { + if (WILC_SemaphoreAcquire(&pstrFifoHandler->SemBuffer, WILC_NULL) == WILC_SUCCESS) { + if ((pstrFifoHandler->u32WriteOffset + u32BytesToWrite) <= pstrFifoHandler->u32BufferLength) { + WILC_memcpy(pstrFifoHandler->pu8Buffer + pstrFifoHandler->u32WriteOffset, pu8Buffer, + u32BytesToWrite); + /* update read offset and total bytes */ + pstrFifoHandler->u32WriteOffset += u32BytesToWrite; + pstrFifoHandler->u32TotalBytes += u32BytesToWrite; + + } else { + WILC_Uint32 u32FirstPart = + pstrFifoHandler->u32BufferLength - pstrFifoHandler->u32WriteOffset; + WILC_memcpy(pstrFifoHandler->pu8Buffer + pstrFifoHandler->u32WriteOffset, pu8Buffer, + u32FirstPart); + WILC_memcpy(pstrFifoHandler->pu8Buffer, pu8Buffer + u32FirstPart, + u32BytesToWrite - u32FirstPart); + /* update read offset and total bytes */ + pstrFifoHandler->u32WriteOffset = u32BytesToWrite - u32FirstPart; + pstrFifoHandler->u32TotalBytes += u32BytesToWrite; + } + /* if data overwriten */ + if (pstrFifoHandler->u32TotalBytes > pstrFifoHandler->u32BufferLength) { + /* adjust read offset to the oldest data available */ + pstrFifoHandler->u32ReadOffset = pstrFifoHandler->u32WriteOffset; + /* data availabe is the buffer length */ + pstrFifoHandler->u32TotalBytes = pstrFifoHandler->u32BufferLength; + } + WILC_SemaphoreRelease(&pstrFifoHandler->SemBuffer, WILC_NULL); + } + } else { + u32Error = 1; + } + } else { + u32Error = 1; + } + } else { + u32Error = 1; + } + return u32Error; +} \ No newline at end of file diff --git a/drivers/staging/wilc1000/fifo_buffer.h b/drivers/staging/wilc1000/fifo_buffer.h new file mode 100644 index 000000000000..0700e7929c00 --- /dev/null +++ b/drivers/staging/wilc1000/fifo_buffer.h @@ -0,0 +1,23 @@ + +#include "wilc_oswrapper.h" + + +#define tHANDLE void * + +typedef struct { + WILC_Uint8 *pu8Buffer; + WILC_Uint32 u32BufferLength; + WILC_Uint32 u32WriteOffset; + WILC_Uint32 u32ReadOffset; + WILC_Uint32 u32TotalBytes; + WILC_SemaphoreHandle SemBuffer; +} tstrFifoHandler; + + +extern WILC_Uint32 FIFO_InitBuffer(tHANDLE *hBuffer, + WILC_Uint32 u32BufferLength); +extern WILC_Uint32 FIFO_DeInit(tHANDLE hFifo); +extern WILC_Uint32 FIFO_ReadBytes(tHANDLE hFifo, WILC_Uint8 *pu8Buffer, + WILC_Uint32 u32BytesToRead, WILC_Uint32 *pu32BytesRead); +extern WILC_Uint32 FIFO_WriteBytes(tHANDLE hFifo, WILC_Uint8 *pu8Buffer, + WILC_Uint32 u32BytesToWrite, WILC_Bool bForceOverWrite); \ No newline at end of file diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c new file mode 100644 index 000000000000..fcbadd1885de --- /dev/null +++ b/drivers/staging/wilc1000/host_interface.c @@ -0,0 +1,8074 @@ +#include "host_interface.h" +#include "wilc_oswrapper.h" +#include "itypes.h" +#include "coreconfigurator.h" + +extern WILC_Sint32 TransportInit(void); +extern WILC_Sint32 TransportDeInit(void); +extern WILC_Uint8 connecting; + +#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP +extern WILC_TimerHandle hDuringIpTimer; +#endif + +extern WILC_Bool bEnablePS; +/*BugID_5137*/ +extern WILC_Uint8 g_wilc_initialized; +/*****************************************************************************/ +/* Macros */ +/*****************************************************************************/ + +/* Message types of the Host IF Message Queue*/ +#define HOST_IF_MSG_SCAN ((WILC_Uint16)0) +#define HOST_IF_MSG_CONNECT ((WILC_Uint16)1) +#define HOST_IF_MSG_RCVD_GNRL_ASYNC_INFO ((WILC_Uint16)2) +#define HOST_IF_MSG_KEY ((WILC_Uint16)3) +#define HOST_IF_MSG_RCVD_NTWRK_INFO ((WILC_Uint16)4) +#define HOST_IF_MSG_RCVD_SCAN_COMPLETE ((WILC_Uint16)5) +#define HOST_IF_MSG_CFG_PARAMS ((WILC_Uint16)6) +#define HOST_IF_MSG_SET_CHANNEL ((WILC_Uint16)7) +#define HOST_IF_MSG_DISCONNECT ((WILC_Uint16)8) +#define HOST_IF_MSG_GET_RSSI ((WILC_Uint16)9) +#define HOST_IF_MSG_GET_CHNL ((WILC_Uint16)10) +#define HOST_IF_MSG_ADD_BEACON ((WILC_Uint16)11) +#define HOST_IF_MSG_DEL_BEACON ((WILC_Uint16)12) +#define HOST_IF_MSG_ADD_STATION ((WILC_Uint16)13) +#define HOST_IF_MSG_DEL_STATION ((WILC_Uint16)14) +#define HOST_IF_MSG_EDIT_STATION ((WILC_Uint16)15) +#define HOST_IF_MSG_SCAN_TIMER_FIRED ((WILC_Uint16)16) +#define HOST_IF_MSG_CONNECT_TIMER_FIRED ((WILC_Uint16)17) +#define HOST_IF_MSG_POWER_MGMT ((WILC_Uint16)18) +#define HOST_IF_MSG_GET_INACTIVETIME ((WILC_Uint16)19) +#define HOST_IF_MSG_REMAIN_ON_CHAN ((WILC_Uint16)20) +#define HOST_IF_MSG_REGISTER_FRAME ((WILC_Uint16)21) +#define HOST_IF_MSG_LISTEN_TIMER_FIRED ((WILC_Uint16)22) +#define HOST_IF_MSG_GET_LINKSPEED ((WILC_Uint16)23) +#define HOST_IF_MSG_SET_WFIDRV_HANDLER ((WILC_Uint16)24) +#define HOST_IF_MSG_SET_MAC_ADDRESS ((WILC_Uint16)25) +#define HOST_IF_MSG_GET_MAC_ADDRESS ((WILC_Uint16)26) +#define HOST_IF_MSG_SET_OPERATION_MODE ((WILC_Uint16)27) +#define HOST_IF_MSG_SET_IPADDRESS ((WILC_Uint16)28) +#define HOST_IF_MSG_GET_IPADDRESS ((WILC_Uint16)29) +#define HOST_IF_MSG_FLUSH_CONNECT ((WILC_Uint16)30) +#define HOST_IF_MSG_GET_STATISTICS ((WILC_Uint16)31) +#define HOST_IF_MSG_SET_MULTICAST_FILTER ((WILC_Uint16)32) +#define HOST_IF_MSG_ADD_BA_SESSION ((WILC_Uint16)33) +#define HOST_IF_MSG_DEL_BA_SESSION ((WILC_Uint16)34) +#define HOST_IF_MSG_Q_IDLE ((WILC_Uint16)35) +#define HOST_IF_MSG_DEL_ALL_STA ((WILC_Uint16)36) +#define HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS ((WILC_Uint16)34) + +#define HOST_IF_MSG_EXIT ((WILC_Uint16)100) + +#define HOST_IF_SCAN_TIMEOUT 4000 +#define HOST_IF_CONNECT_TIMEOUT 9500 + +#define BA_SESSION_DEFAULT_BUFFER_SIZE 16 +#define BA_SESSION_DEFAULT_TIMEOUT 1000 +#define BLOCK_ACK_REQ_SIZE 0x14 +/*****************************************************************************/ +/* Type Definitions */ +/*****************************************************************************/ + +/*! + * @struct tstrHostIFCfgParamAttr + * @brief Structure to hold Host IF CFG Params Attributes + * @details + * @todo + * @sa + * @author Mai Daftedar + * @date 02 April 2012 + * @version 1.0 + */ +typedef struct _tstrHostIFCfgParamAttr { + tstrCfgParamVal pstrCfgParamVal; + +} tstrHostIFCfgParamAttr; + +/*! + * @struct tstrHostIFwpaAttr + * @brief Structure to hold Host IF Scan Attributes + * @details + * @todo + * @sa + * @author Mai Daftedar + * @date 25 March 2012 + * @version 1.0 + */ +typedef struct _tstrHostIFwpaAttr { + WILC_Uint8 *pu8key; + const WILC_Uint8 *pu8macaddr; + WILC_Uint8 *pu8seq; + WILC_Uint8 u8seqlen; + WILC_Uint8 u8keyidx; + WILC_Uint8 u8Keylen; + WILC_Uint8 u8Ciphermode; +} tstrHostIFwpaAttr; + + +/*! + * @struct tstrHostIFwepAttr + * @brief Structure to hold Host IF Scan Attributes + * @details + * @todo + * @sa + * @author Mai Daftedar + * @date 25 March 2012 + * @version 1.0 + */ +typedef struct _tstrHostIFwepAttr { + WILC_Uint8 *pu8WepKey; + WILC_Uint8 u8WepKeylen; + WILC_Uint8 u8Wepidx; + WILC_Uint8 u8mode; + AUTHTYPE_T tenuAuth_type; + +} tstrHostIFwepAttr; + +/*! + * @struct tuniHostIFkeyAttr + * @brief Structure to hold Host IF Scan Attributes + * @details + * @todo + * @sa + * @author Mai Daftedar + * @date 25 March 2012 + * @version 1.0 + */ +typedef union _tuniHostIFkeyAttr { + tstrHostIFwepAttr strHostIFwepAttr; + tstrHostIFwpaAttr strHostIFwpaAttr; + tstrHostIFpmkidAttr strHostIFpmkidAttr; +} tuniHostIFkeyAttr; + +/*! + * @struct tstrHostIFkeyAttr + * @brief Structure to hold Host IF Scan Attributes + * @details + * @todo + * @sa + * @author Mai Daftedar + * @date 25 March 2012 + * @version 1.0 + */ +typedef struct _tstrHostIFkeyAttr { + tenuKeyType enuKeyType; + WILC_Uint8 u8KeyAction; + tuniHostIFkeyAttr uniHostIFkeyAttr; +} tstrHostIFkeyAttr; + + + + +/*! + * @struct tstrHostIFscanAttr + * @brief Structure to hold Host IF Scan Attributes + * @details + * @todo + * @sa + * @author Mostafa Abu Bakr + * @date 25 March 2012 + * @version 1.0 + */ +typedef struct _tstrHostIFscanAttr { + WILC_Uint8 u8ScanSource; + WILC_Uint8 u8ScanType; + WILC_Uint8 *pu8ChnlFreqList; + WILC_Uint8 u8ChnlListLen; + WILC_Uint8 *pu8IEs; + size_t IEsLen; + tWILCpfScanResult pfScanResult; + void *pvUserArg; + /*BugID_4189*/ + tstrHiddenNetwork strHiddenNetwork; + +} tstrHostIFscanAttr; + +/*! + * @struct tstrHostIFconnectAttr + * @brief Structure to hold Host IF Connect Attributes + * @details + * @todo + * @sa + * @author Mostafa Abu Bakr + * @date 25 March 2012 + * @version 1.0 + */ +typedef struct _tstrHostIFconnectAttr { + WILC_Uint8 *pu8bssid; + WILC_Uint8 *pu8ssid; + size_t ssidLen; + WILC_Uint8 *pu8IEs; + size_t IEsLen; + WILC_Uint8 u8security; + tWILCpfConnectResult pfConnectResult; + void *pvUserArg; + AUTHTYPE_T tenuAuth_type; + WILC_Uint8 u8channel; + void *pJoinParams; +} tstrHostIFconnectAttr; + +/*! + * @struct tstrRcvdGnrlAsyncInfo + * @brief Structure to hold Received General Asynchronous info + * @details + * @todo + * @sa + * @author Mostafa Abu Bakr + * @date 25 March 2012 + * @version 1.0 + */ +typedef struct _tstrRcvdGnrlAsyncInfo { + WILC_Uint8 *pu8Buffer; + WILC_Uint32 u32Length; +} tstrRcvdGnrlAsyncInfo; + +/*! + * @struct tstrHostIFSetChan + * @brief Set Channel message body + * @details + * @todo + * @sa + * @author Mai Daftedar + * @date 25 March 2012 + * @version 1.0 + */ +typedef struct _tstrHostIFSetChan { + WILC_Uint8 u8SetChan; +} tstrHostIFSetChan; + +/*! + * @struct tstrHostIFSetChan + * @brief Get Channel message body + * @details + * @todo + * @sa + * @author Mai Daftedar + * @date 01 Jule 2012 + * @version 1.0 + */ +typedef struct _tstrHostIFGetChan { + WILC_Uint8 u8GetChan; +} tstrHostIFGetChan; + +/*bug3819: Add Scan acomplete notification to host*/ +/*! + * @struct tstrScanComplete + * @brief hold received Async. Scan Complete message body + * @details + * @todo + * @sa + * @author zsalah + * @date 25 March 2012 + * @version 1.0 + */ +/*typedef struct _tstrScanComplete + * { + * WILC_Uint8* pu8Buffer; + * WILC_Uint32 u32Length; + * } tstrScanComplete;*/ + +/*! + * @struct tstrHostIFSetBeacon + * @brief Set Beacon message body + * @details + * @todo + * @sa + * @author Adham Abozaeid + * @date 10 July 2012 + * @version 1.0 + */ +typedef struct _tstrHostIFSetBeacon { + WILC_Uint32 u32Interval; /*!< Beacon Interval. Period between two successive beacons on air */ + WILC_Uint32 u32DTIMPeriod; /*!< DTIM Period. Indicates how many Beacon frames + * (including the current frame) appear before the next DTIM */ + WILC_Uint32 u32HeadLen; /*!< Length of the head buffer in bytes */ + WILC_Uint8 *pu8Head; /*!< Pointer to the beacon's head buffer. Beacon's head is the part + * from the beacon's start till the TIM element, NOT including the TIM */ + WILC_Uint32 u32TailLen; /*!< Length of the tail buffer in bytes */ + WILC_Uint8 *pu8Tail; /*!< Pointer to the beacon's tail buffer. Beacon's tail starts just + * after the TIM inormation element */ +} tstrHostIFSetBeacon; + + + +/*! + * @struct tstrHostIFDelBeacon + * @brief Del Beacon message body + * @details + * @todo + * @sa + * @author Adham Abozaeid + * @date 15 July 2012 + * @version 1.0 + */ +typedef struct _tstrHostIFDelBeacon { + WILC_Uint8 u8dummy; +} tstrHostIFDelBeacon; + +/*! + * @struct tstrHostIFSetMulti + * @brief set Multicast filter Address + * @details + * @todo + * @sa + * @author Abdelrahman Sobhy + * @date 30 August 2013 + * @version 1.0 Description + */ + +typedef struct { + WILC_Bool bIsEnabled; + WILC_Uint32 u32count; +} tstrHostIFSetMulti; + +/*! + * @struct tstrHostIFDelAllSta + * @brief Deauth station message body + * @details + * @todo + * @sa + * @author Mai Daftedar + * @date 09 April 2014 + * @version 1.0 Description + */ + +typedef struct { + WILC_Uint8 au8Sta_DelAllSta[MAX_NUM_STA][ETH_ALEN]; + WILC_Uint8 u8Num_AssocSta; +} tstrHostIFDelAllSta; + +/*! + * @struct tstrHostIFDelSta + * @brief Delete station message body + * @details + * @todo + * @sa + * @author Adham Abozaeid + * @date 15 July 2012 + * @version 1.0 Description + */ + +typedef struct { + WILC_Uint8 au8MacAddr[ETH_ALEN]; +} tstrHostIFDelSta; + +/*! + * @struct tstrTimerCb + * @brief Timer callback message body + * @details + * @todo + * @sa + * @author Mostafa Abu Bakr + * @date 25 March 2012 + * @version 1.0 + */ +typedef struct _tstrTimerCb { + void *pvUsrArg; /*!< Private data passed at timer start */ +} tstrTimerCb; + +/*! + * @struct tstrHostIfPowerMgmtParam + * @brief Power management message body + * @details + * @todo + * @sa + * @author Adham Abozaeid + * @date 24 November 2012 + * @version 1.0 + */ +typedef struct { + + WILC_Bool bIsEnabled; + WILC_Uint32 u32Timeout; +} tstrHostIfPowerMgmtParam; + +/*! + * @struct tstrHostIFSetIPAddr + * @brief set IP Address message body + * @details + * @todo + * @sa + * @author Abdelrahman Sobhy + * @date 30 August 2013 + * @version 1.0 Description + */ + +typedef struct { + WILC_Uint8 *au8IPAddr; + WILC_Uint8 idx; +} tstrHostIFSetIPAddr; + +/*! + * @struct tstrHostIfStaInactiveT + * @brief Get station message body + * @details + * @todo + * @sa + * @author Mai Daftedar + * @date 16 April 2013 + * @version 1.0 + */ +typedef struct { + WILC_Uint8 mac[6]; + +} tstrHostIfStaInactiveT; +/**/ +/*! + * @union tuniHostIFmsgBody + * @brief Message body for the Host Interface message_q + * @details + * @todo + * @sa + * @author Mostafa Abu Bakr + * @date 25 March 2012 + * @version 1.0 + */ +typedef union _tuniHostIFmsgBody { + tstrHostIFscanAttr strHostIFscanAttr; /*!< Host IF Scan Request Attributes message body */ + tstrHostIFconnectAttr strHostIFconnectAttr; /*!< Host IF Connect Request Attributes message body */ + tstrRcvdNetworkInfo strRcvdNetworkInfo; /*!< Received Asynchronous Network Info message body */ + tstrRcvdGnrlAsyncInfo strRcvdGnrlAsyncInfo; /*!< Received General Asynchronous Info message body */ + tstrHostIFkeyAttr strHostIFkeyAttr; /*!<>*/ + tstrHostIFCfgParamAttr strHostIFCfgParamAttr; /*! */ + tstrHostIFSetChan strHostIFSetChan; + tstrHostIFGetChan strHostIFGetChan; + tstrHostIFSetBeacon strHostIFSetBeacon; /*!< Set beacon message body */ + tstrHostIFDelBeacon strHostIFDelBeacon; /*!< Del beacon message body */ + tstrWILC_AddStaParam strAddStaParam; /*!< Add station message body */ + tstrHostIFDelSta strDelStaParam; /*!< Del Station message body */ + tstrWILC_AddStaParam strEditStaParam; /*!< Edit station message body */ + /* tstrScanComplete strScanComplete; / *Received Async. Scan Complete message body* / */ + tstrTimerCb strTimerCb; /*!< Timer callback message body */ + tstrHostIfPowerMgmtParam strPowerMgmtparam; /*!< Power Management message body */ + tstrHostIfStaInactiveT strHostIfStaInactiveT; + tstrHostIFSetIPAddr strHostIfSetIP; + tstrHostIfSetDrvHandler strHostIfSetDrvHandler; + tstrHostIFSetMulti strHostIfSetMulti; + tstrHostIfSetOperationMode strHostIfSetOperationMode; + tstrHostIfSetMacAddress strHostIfSetMacAddress; + tstrHostIfGetMacAddress strHostIfGetMacAddress; + tstrHostIfBASessionInfo strHostIfBASessionInfo; + #ifdef WILC_P2P + tstrHostIfRemainOnChan strHostIfRemainOnChan; + tstrHostIfRegisterFrame strHostIfRegisterFrame; + #endif + WILC_Char *pUserData; + tstrHostIFDelAllSta strHostIFDelAllSta; +} tuniHostIFmsgBody; + +/*! + * @struct tstrHostIFmsg + * @brief Host Interface message + * @details + * @todo + * @sa + * @author Mostafa Abu Bakr + * @date 25 March 2012 + * @version 1.0 + */ +typedef struct _tstrHostIFmsg { + WILC_Uint16 u16MsgId; /*!< Message ID */ + tuniHostIFmsgBody uniHostIFmsgBody; /*!< Message body */ + void *drvHandler; +} tstrHostIFmsg; + +#ifdef CONNECT_DIRECT +typedef struct _tstrWidJoinReqExt { + WILC_Char SSID[MAX_SSID_LEN]; + WILC_Uint8 u8channel; + WILC_Uint8 BSSID[6]; +} tstrWidJoinReqExt; +#endif + +/*Bug4218: Parsing Join Param*/ +#ifdef WILC_PARSE_SCAN_IN_HOST +/*Struct containg joinParam of each AP*/ +typedef struct _tstrJoinBssParam { + BSSTYPE_T bss_type; + WILC_Uint8 dtim_period; + WILC_Uint16 beacon_period; + WILC_Uint16 cap_info; + WILC_Uint8 au8bssid[6]; + WILC_Char ssid[MAX_SSID_LEN]; + WILC_Uint8 ssidLen; + WILC_Uint8 supp_rates[MAX_RATES_SUPPORTED + 1]; + WILC_Uint8 ht_capable; + WILC_Uint8 wmm_cap; + WILC_Uint8 uapsd_cap; + WILC_Bool rsn_found; + WILC_Uint8 rsn_grp_policy; + WILC_Uint8 mode_802_11i; + WILC_Uint8 rsn_pcip_policy[3]; + WILC_Uint8 rsn_auth_policy[3]; + WILC_Uint8 rsn_cap[2]; + struct _tstrJoinParam *nextJoinBss; + #ifdef WILC_P2P + WILC_Uint32 tsf; + WILC_Uint8 u8NoaEnbaled; + WILC_Uint8 u8OppEnable; + WILC_Uint8 u8CtWindow; + WILC_Uint8 u8Count; + WILC_Uint8 u8Index; + WILC_Uint8 au8Duration[4]; + WILC_Uint8 au8Interval[4]; + WILC_Uint8 au8StartTime[4]; + #endif +} tstrJoinBssParam; +/*Bug4218: Parsing Join Param*/ +/*a linked list table containing needed join parameters entries for each AP found in most recent scan*/ +typedef struct _tstrBssTable { + WILC_Uint8 u8noBssEntries; + tstrJoinBssParam *head; + tstrJoinBssParam *tail; +} tstrBssTable; +#endif /*WILC_PARSE_SCAN_IN_HOST*/ + +typedef enum { + SCAN_TIMER = 0, + CONNECT_TIMER = 1, + SCAN_CONNECT_TIMER_FORCE_32BIT = 0xFFFFFFFF +} tenuScanConnTimer; + +/*****************************************************************************/ +/* */ +/* Global Variabls */ +/* */ +/*****************************************************************************/ + + +tstrWILC_WFIDrv *terminated_handle = WILC_NULL; +tstrWILC_WFIDrv *gWFiDrvHandle = WILC_NULL; +#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP +WILC_Bool g_obtainingIP = WILC_FALSE; +#endif +WILC_Uint8 P2P_LISTEN_STATE; +static WILC_ThreadHandle HostIFthreadHandler; +static WILC_MsgQueueHandle gMsgQHostIF; +static WILC_SemaphoreHandle hSemHostIFthrdEnd; + +WILC_SemaphoreHandle hSemDeinitDrvHandle; +static WILC_SemaphoreHandle hWaitResponse; +WILC_SemaphoreHandle hSemHostIntDeinit; +WILC_TimerHandle g_hPeriodicRSSI; + + + +WILC_Uint8 gau8MulticastMacAddrList[WILC_MULTICAST_TABLE_SIZE][ETH_ALEN]; + +#ifndef CONNECT_DIRECT +static WILC_Uint8 gapu8RcvdSurveyResults[2][MAX_SURVEY_RESULT_FRAG_SIZE]; +#endif + +static WILC_Uint8 gapu8RcvdAssocResp[MAX_ASSOC_RESP_FRAME_SIZE]; + +WILC_Bool gbScanWhileConnected = WILC_FALSE; + +static WILC_Sint8 gs8Rssi; +static WILC_Sint8 gs8lnkspd; +static WILC_Uint8 gu8Chnl; +static WILC_Uint8 gs8SetIP[2][4]; +static WILC_Uint8 gs8GetIP[2][4]; +#ifdef WILC_AP_EXTERNAL_MLME +static WILC_Uint32 gu32InactiveTime; +static WILC_Uint8 gu8DelBcn; +#endif +#ifndef SIMULATION +static WILC_Uint32 gu32WidConnRstHack; +#endif + +/*BugID_5137*/ +WILC_Uint8 *gu8FlushedJoinReq; +WILC_Uint8 *gu8FlushedInfoElemAsoc; +WILC_Uint8 gu8Flushed11iMode; +WILC_Uint8 gu8FlushedAuthType; +WILC_Uint32 gu32FlushedJoinReqSize; +WILC_Uint32 gu32FlushedInfoElemAsocSize; +WILC_Uint32 gu8FlushedJoinReqDrvHandler; +#define REAL_JOIN_REQ 0 +#define FLUSHED_JOIN_REQ 1 +#define FLUSHED_BYTE_POS 79 /* Position the byte indicating flushing in the flushed request */ + +/*Bug4218: Parsing Join Param*/ +#ifdef WILC_PARSE_SCAN_IN_HOST +/*Bug4218: Parsing Join Param*/ +static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo); +#endif /*WILC_PARSE_SCAN_IN_HOST*/ + +extern void chip_sleep_manually(WILC_Uint32 u32SleepTime); +extern int linux_wlan_get_num_conn_ifcs(void); + +/** + * @brief Handle_SetChannel + * @details Sending config packet to firmware to set channel + * @param[in] tstrHostIFSetChan* pstrHostIFSetChan + * @return Error code. + * @author + * @date + * @version 1.0 + */ +static WILC_Sint32 Handle_SetChannel(void *drvHandler, tstrHostIFSetChan *pstrHostIFSetChan) +{ + + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + /*prepare configuration packet*/ + strWID.u16WIDid = (WILC_Uint16)WID_CURRENT_CHANNEL; + strWID.enuWIDtype = WID_CHAR; + strWID.ps8WidVal = (WILC_Char *)&(pstrHostIFSetChan->u8SetChan); + strWID.s32ValueSize = sizeof(WILC_Char); + + PRINT_D(HOSTINF_DBG, "Setting channel\n"); + /*Sending Cfg*/ + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + if (s32Error) { + PRINT_ER("Failed to set channel\n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_STATE); + } + WILC_CATCH(s32Error) + { + + } + + return s32Error; +} +/** + * @brief Handle_SetWfiDrvHandler + * @details Sending config packet to firmware to set driver handler + * @param[in] void * drvHandler,tstrHostIfSetDrvHandler* pstrHostIfSetDrvHandler + * @return Error code. + * @author + * @date + * @version 1.0 + */ +static WILC_Sint32 Handle_SetWfiDrvHandler(tstrHostIfSetDrvHandler *pstrHostIfSetDrvHandler) +{ + + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)((pstrHostIfSetDrvHandler->u32Address)); + + + /*prepare configuration packet*/ + strWID.u16WIDid = (WILC_Uint16)WID_SET_DRV_HANDLER; + strWID.enuWIDtype = WID_INT; + strWID.ps8WidVal = (WILC_Sint8 *)&(pstrHostIfSetDrvHandler->u32Address); + strWID.s32ValueSize = sizeof(WILC_Uint32); + + /*Sending Cfg*/ + + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + + + if ((pstrHostIfSetDrvHandler->u32Address) == (WILC_Uint32)NULL) { + WILC_SemaphoreRelease(&hSemDeinitDrvHandle, WILC_NULL); + } + + + if (s32Error) { + PRINT_ER("Failed to set driver handler\n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_STATE); + } + WILC_CATCH(s32Error) + { + + } + + return s32Error; +} + +/** + * @brief Handle_SetWfiAPDrvHandler + * @details Sending config packet to firmware to set driver handler + * @param[in] void * drvHandler,tstrHostIfSetDrvHandler* pstrHostIfSetDrvHandler + * @return Error code. + * @author + * @date + * @version 1.0 + */ +static WILC_Sint32 Handle_SetOperationMode(void *drvHandler, tstrHostIfSetOperationMode *pstrHostIfSetOperationMode) +{ + + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + + /*prepare configuration packet*/ + strWID.u16WIDid = (WILC_Uint16)WID_SET_OPERATION_MODE; + strWID.enuWIDtype = WID_INT; + strWID.ps8WidVal = (WILC_Sint8 *)&(pstrHostIfSetOperationMode->u32Mode); + strWID.s32ValueSize = sizeof(WILC_Uint32); + + /*Sending Cfg*/ + PRINT_INFO(HOSTINF_DBG, "(WILC_Uint32)pstrWFIDrv= %x \n", (WILC_Uint32)pstrWFIDrv); + + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + + + if ((pstrHostIfSetOperationMode->u32Mode) == (WILC_Uint32)NULL) { + WILC_SemaphoreRelease(&hSemDeinitDrvHandle, WILC_NULL); + } + + + if (s32Error) { + PRINT_ER("Failed to set driver handler\n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_STATE); + } + WILC_CATCH(s32Error) + { + + } + + return s32Error; +} + +/** + * @brief host_int_set_IPAddress + * @details Setting IP address params in message queue + * @param[in] WILC_WFIDrvHandle hWFIDrv, WILC_Uint8* pu8IPAddr + * @return Error code. + * @author + * @date + * @version 1.0 + */ +WILC_Sint32 Handle_set_IPAddress(void *drvHandler, WILC_Uint8 *pu8IPAddr, WILC_Uint8 idx) +{ + + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + char firmwareIPAddress[4] = {0}; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + if (pu8IPAddr[0] < 192) + pu8IPAddr[0] = 0; + + PRINT_INFO(HOSTINF_DBG, "Indx = %d, Handling set IP = %d.%d.%d.%d \n", idx, pu8IPAddr[0], pu8IPAddr[1], pu8IPAddr[2], pu8IPAddr[3]); + + WILC_memcpy(gs8SetIP[idx], pu8IPAddr, IP_ALEN); + + /*prepare configuration packet*/ + strWID.u16WIDid = (WILC_Uint16)WID_IP_ADDRESS; + strWID.enuWIDtype = WID_STR; + strWID.ps8WidVal = (WILC_Uint8 *)pu8IPAddr; + strWID.s32ValueSize = IP_ALEN; + + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + + + + host_int_get_ipaddress((WILC_WFIDrvHandle)drvHandler, firmwareIPAddress, idx); + + if (s32Error) { + PRINT_D(HOSTINF_DBG, "Failed to set IP address\n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_STATE); + } else { + PRINT_INFO(HOSTINF_DBG, "IP address set\n"); + } + + WILC_CATCH(s32Error) + { + + } + + return s32Error; +} + + +/** + * @brief Handle_get_IPAddress + * @details Setting IP address params in message queue + * @param[in] WILC_WFIDrvHandle hWFIDrv, WILC_Uint8* pu8IPAddr + * @return Error code. + * @author + * @date + * @version 1.0 + */ +WILC_Sint32 Handle_get_IPAddress(void *drvHandler, WILC_Uint8 *pu8IPAddr, WILC_Uint8 idx) +{ + + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + /*prepare configuration packet*/ + strWID.u16WIDid = (WILC_Uint16)WID_IP_ADDRESS; + strWID.enuWIDtype = WID_STR; + strWID.ps8WidVal = (WILC_Uint8 *)WILC_MALLOC(IP_ALEN); + strWID.s32ValueSize = IP_ALEN; + + s32Error = SendConfigPkt(GET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + + PRINT_INFO(HOSTINF_DBG, "%d.%d.%d.%d\n", (WILC_Uint8)(strWID.ps8WidVal[0]), (WILC_Uint8)(strWID.ps8WidVal[1]), (WILC_Uint8)(strWID.ps8WidVal[2]), (WILC_Uint8)(strWID.ps8WidVal[3])); + + WILC_memcpy(gs8GetIP[idx], strWID.ps8WidVal, IP_ALEN); + + /*get the value by searching the local copy*/ + WILC_FREE(strWID.ps8WidVal); + + if (WILC_memcmp(gs8GetIP[idx], gs8SetIP[idx], IP_ALEN) != 0) + host_int_setup_ipaddress((WILC_WFIDrvHandle)pstrWFIDrv, gs8SetIP[idx], idx); + + if (s32Error != WILC_SUCCESS) { + PRINT_ER("Failed to get IP address\n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_STATE); + } else { + PRINT_INFO(HOSTINF_DBG, "IP address retrieved:: u8IfIdx = %d \n", idx); + PRINT_INFO(HOSTINF_DBG, "%d.%d.%d.%d\n", gs8GetIP[idx][0], gs8GetIP[idx][1], gs8GetIP[idx][2], gs8GetIP[idx][3]); + PRINT_INFO(HOSTINF_DBG, "\n"); + } + + WILC_CATCH(s32Error) + { + + } + + return s32Error; +} + + +/*BugId_5077*/ +/** + * @brief Handle_SetMacAddress + * @details Setting mac address + * @param[in] void * drvHandler,tstrHostIfSetDrvHandler* pstrHostIfSetDrvHandler + * @return Error code. + * @author Amr Abdel-Moghny + * @date November 2013 + * @version 7.0 + */ +static WILC_Sint32 Handle_SetMacAddress(void *drvHandler, tstrHostIfSetMacAddress *pstrHostIfSetMacAddress) +{ + + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + WILC_Uint8 *mac_buf = (WILC_Uint8 *)WILC_MALLOC(ETH_ALEN); + if (mac_buf == NULL) { + PRINT_ER("No buffer to send mac address\n"); + return WILC_FAIL; + } + WILC_memcpy(mac_buf, pstrHostIfSetMacAddress->u8MacAddress, ETH_ALEN); + + /*prepare configuration packet*/ + strWID.u16WIDid = (WILC_Uint16)WID_MAC_ADDR; + strWID.enuWIDtype = WID_STR; + strWID.ps8WidVal = mac_buf; + strWID.s32ValueSize = ETH_ALEN; + PRINT_D(GENERIC_DBG, "mac addr = :%x:%x:%x:%x:%x:%x\n", strWID.ps8WidVal[0], strWID.ps8WidVal[1], strWID.ps8WidVal[2], strWID.ps8WidVal[3], strWID.ps8WidVal[4], strWID.ps8WidVal[5]); + /*Sending Cfg*/ + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + if (s32Error) { + PRINT_ER("Failed to set mac address\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + + WILC_CATCH(s32Error) + { + + } + WILC_FREE(mac_buf); + return s32Error; +} + + +/*BugID_5213*/ +/** + * @brief Handle_GetMacAddress + * @details Getting mac address + * @param[in] void * drvHandler,tstrHostIfSetDrvHandler* pstrHostIfSetDrvHandler + * @return Error code. + * @author Amr Abdel-Moghny + * @date JAN 2013 + * @version 8.0 + */ +static WILC_Sint32 Handle_GetMacAddress(void *drvHandler, tstrHostIfGetMacAddress *pstrHostIfGetMacAddress) +{ + + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + + /*prepare configuration packet*/ + strWID.u16WIDid = (WILC_Uint16)WID_MAC_ADDR; + strWID.enuWIDtype = WID_STR; + strWID.ps8WidVal = pstrHostIfGetMacAddress->u8MacAddress; + strWID.s32ValueSize = ETH_ALEN; + + /*Sending Cfg*/ + s32Error = SendConfigPkt(GET_CFG, &strWID, 1, WILC_FALSE, (WILC_Uint32)drvHandler); + if (s32Error) { + PRINT_ER("Failed to get mac address\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + WILC_CATCH(s32Error) + { + + } + WILC_SemaphoreRelease(&hWaitResponse, NULL); + + return s32Error; +} + + +/** + * @brief Handle_CfgParam + * @details Sending config packet to firmware to set CFG params + * @param[in] tstrHostIFCfgParamAttr* strHostIFCfgParamAttr + * @return Error code. + * @author + * @date + * @version 1.0 + */ +static WILC_Sint32 Handle_CfgParam(void *drvHandler, tstrHostIFCfgParamAttr *strHostIFCfgParamAttr) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWIDList[32]; + WILC_Uint8 u8WidCnt = 0; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + + WILC_SemaphoreAcquire(&(pstrWFIDrv->gtOsCfgValuesSem), NULL); + + + PRINT_D(HOSTINF_DBG, "Setting CFG params\n"); + + if (strHostIFCfgParamAttr->pstrCfgParamVal.u32SetCfgFlag & BSS_TYPE) { + /*----------------------------------------------------------*/ + /*Input Value: INFRASTRUCTURE = 1, */ + /* INDEPENDENT= 2, */ + /* ANY_BSS= 3 */ + /*----------------------------------------------------------*/ + /* validate input then copy>> need to check value 4 and 5 */ + if (strHostIFCfgParamAttr->pstrCfgParamVal.bss_type < 6) { + strWIDList[u8WidCnt].u16WIDid = WID_BSS_TYPE; + strWIDList[u8WidCnt].ps8WidVal = (WILC_Sint8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.bss_type; + strWIDList[u8WidCnt].enuWIDtype = WID_CHAR; + strWIDList[u8WidCnt].s32ValueSize = sizeof(WILC_Char); + pstrWFIDrv->strCfgValues.bss_type = (WILC_Uint8)strHostIFCfgParamAttr->pstrCfgParamVal.bss_type; + } else { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + u8WidCnt++; + } + if (strHostIFCfgParamAttr->pstrCfgParamVal.u32SetCfgFlag & AUTH_TYPE) { + /*------------------------------------------------------*/ + /*Input Values: OPEN_SYSTEM = 0, */ + /* SHARED_KEY = 1, */ + /* ANY = 2 */ + /*------------------------------------------------------*/ + /*validate Possible values*/ + if ((strHostIFCfgParamAttr->pstrCfgParamVal.auth_type) == 1 || (strHostIFCfgParamAttr->pstrCfgParamVal.auth_type) == 2 || (strHostIFCfgParamAttr->pstrCfgParamVal.auth_type) == 5) { + strWIDList[u8WidCnt].u16WIDid = WID_AUTH_TYPE; + strWIDList[u8WidCnt].ps8WidVal = (WILC_Sint8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.auth_type; + strWIDList[u8WidCnt].enuWIDtype = WID_CHAR; + strWIDList[u8WidCnt].s32ValueSize = sizeof(WILC_Char); + pstrWFIDrv->strCfgValues.auth_type = (WILC_Uint8)strHostIFCfgParamAttr->pstrCfgParamVal.auth_type; + } else { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + u8WidCnt++; + } + if (strHostIFCfgParamAttr->pstrCfgParamVal.u32SetCfgFlag & AUTHEN_TIMEOUT) { + /* range is 1 to 65535. */ + if (strHostIFCfgParamAttr->pstrCfgParamVal.auth_timeout > 0 && strHostIFCfgParamAttr->pstrCfgParamVal.auth_timeout < 65536) { + strWIDList[u8WidCnt].u16WIDid = WID_AUTH_TIMEOUT; + strWIDList[u8WidCnt].ps8WidVal = (WILC_Sint8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.auth_timeout; + strWIDList[u8WidCnt].enuWIDtype = WID_SHORT; + strWIDList[u8WidCnt].s32ValueSize = sizeof(WILC_Uint16); + pstrWFIDrv->strCfgValues.auth_timeout = strHostIFCfgParamAttr->pstrCfgParamVal.auth_timeout; + } else { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + u8WidCnt++; + } + if (strHostIFCfgParamAttr->pstrCfgParamVal.u32SetCfgFlag & POWER_MANAGEMENT) { + /*-----------------------------------------------------------*/ + /*Input Values: NO_POWERSAVE = 0, */ + /* MIN_FAST_PS = 1, */ + /* MAX_FAST_PS = 2, */ + /* MIN_PSPOLL_PS = 3, */ + /* MAX_PSPOLL_PS = 4 */ + /*----------------------------------------------------------*/ + if (strHostIFCfgParamAttr->pstrCfgParamVal.power_mgmt_mode < 5) { + strWIDList[u8WidCnt].u16WIDid = WID_POWER_MANAGEMENT; + strWIDList[u8WidCnt].ps8WidVal = (WILC_Sint8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.power_mgmt_mode; + strWIDList[u8WidCnt].enuWIDtype = WID_CHAR; + strWIDList[u8WidCnt].s32ValueSize = sizeof(WILC_Char); + pstrWFIDrv->strCfgValues.power_mgmt_mode = (WILC_Uint8)strHostIFCfgParamAttr->pstrCfgParamVal.power_mgmt_mode; + } else { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + u8WidCnt++; + } + if (strHostIFCfgParamAttr->pstrCfgParamVal.u32SetCfgFlag & RETRY_SHORT) { + /* range from 1 to 256 */ + if ((strHostIFCfgParamAttr->pstrCfgParamVal.short_retry_limit > 0) && (strHostIFCfgParamAttr->pstrCfgParamVal.short_retry_limit < 256)) { + strWIDList[u8WidCnt].u16WIDid = WID_SHORT_RETRY_LIMIT; + strWIDList[u8WidCnt].ps8WidVal = (WILC_Sint8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.short_retry_limit; + strWIDList[u8WidCnt].enuWIDtype = WID_SHORT; + strWIDList[u8WidCnt].s32ValueSize = sizeof(WILC_Uint16); + pstrWFIDrv->strCfgValues.short_retry_limit = strHostIFCfgParamAttr->pstrCfgParamVal.short_retry_limit; + } else { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + u8WidCnt++; + } + if (strHostIFCfgParamAttr->pstrCfgParamVal.u32SetCfgFlag & RETRY_LONG) { + /* range from 1 to 256 */ + if ((strHostIFCfgParamAttr->pstrCfgParamVal.long_retry_limit > 0) && (strHostIFCfgParamAttr->pstrCfgParamVal.long_retry_limit < 256)) { + strWIDList[u8WidCnt].u16WIDid = WID_LONG_RETRY_LIMIT; + strWIDList[u8WidCnt].ps8WidVal = (WILC_Sint8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.long_retry_limit; + + strWIDList[u8WidCnt].enuWIDtype = WID_SHORT; + strWIDList[u8WidCnt].s32ValueSize = sizeof(WILC_Uint16); + pstrWFIDrv->strCfgValues.long_retry_limit = strHostIFCfgParamAttr->pstrCfgParamVal.long_retry_limit; + } else { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + u8WidCnt++; + } + if (strHostIFCfgParamAttr->pstrCfgParamVal.u32SetCfgFlag & FRAG_THRESHOLD) { + + if (strHostIFCfgParamAttr->pstrCfgParamVal.frag_threshold > 255 && strHostIFCfgParamAttr->pstrCfgParamVal.frag_threshold < 7937) { + strWIDList[u8WidCnt].u16WIDid = WID_FRAG_THRESHOLD; + strWIDList[u8WidCnt].ps8WidVal = (WILC_Sint8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.frag_threshold; + strWIDList[u8WidCnt].enuWIDtype = WID_SHORT; + strWIDList[u8WidCnt].s32ValueSize = sizeof(WILC_Uint16); + pstrWFIDrv->strCfgValues.frag_threshold = strHostIFCfgParamAttr->pstrCfgParamVal.frag_threshold; + } else { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + u8WidCnt++; + } + if (strHostIFCfgParamAttr->pstrCfgParamVal.u32SetCfgFlag & RTS_THRESHOLD) { + /* range 256 to 65535 */ + if (strHostIFCfgParamAttr->pstrCfgParamVal.rts_threshold > 255 && strHostIFCfgParamAttr->pstrCfgParamVal.rts_threshold < 65536) { + strWIDList[u8WidCnt].u16WIDid = WID_RTS_THRESHOLD; + strWIDList[u8WidCnt].ps8WidVal = (WILC_Sint8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.rts_threshold; + strWIDList[u8WidCnt].enuWIDtype = WID_SHORT; + strWIDList[u8WidCnt].s32ValueSize = sizeof(WILC_Uint16); + pstrWFIDrv->strCfgValues.rts_threshold = strHostIFCfgParamAttr->pstrCfgParamVal.rts_threshold; + } else { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + u8WidCnt++; + } + if (strHostIFCfgParamAttr->pstrCfgParamVal.u32SetCfgFlag & PREAMBLE) { + /*-----------------------------------------------------*/ + /*Input Values: Short= 0, */ + /* Long= 1, */ + /* Auto= 2 */ + /*------------------------------------------------------*/ + if (strHostIFCfgParamAttr->pstrCfgParamVal.preamble_type < 3) { + strWIDList[u8WidCnt].u16WIDid = WID_PREAMBLE; + strWIDList[u8WidCnt].ps8WidVal = (WILC_Sint8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.preamble_type; + strWIDList[u8WidCnt].enuWIDtype = WID_CHAR; + strWIDList[u8WidCnt].s32ValueSize = sizeof(WILC_Char); + pstrWFIDrv->strCfgValues.preamble_type = strHostIFCfgParamAttr->pstrCfgParamVal.preamble_type; + } else { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + u8WidCnt++; + } + if (strHostIFCfgParamAttr->pstrCfgParamVal.u32SetCfgFlag & SHORT_SLOT_ALLOWED) { + if (strHostIFCfgParamAttr->pstrCfgParamVal.short_slot_allowed < 2) { + strWIDList[u8WidCnt].u16WIDid = WID_SHORT_SLOT_ALLOWED; + strWIDList[u8WidCnt].ps8WidVal = (WILC_Sint8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.short_slot_allowed; + strWIDList[u8WidCnt].enuWIDtype = WID_CHAR; + strWIDList[u8WidCnt].s32ValueSize = sizeof(WILC_Char); + pstrWFIDrv->strCfgValues.short_slot_allowed = (WILC_Uint8)strHostIFCfgParamAttr->pstrCfgParamVal.short_slot_allowed; + } else { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + u8WidCnt++; + } + if (strHostIFCfgParamAttr->pstrCfgParamVal.u32SetCfgFlag & TXOP_PROT_DISABLE) { + /*Description: used to Disable RTS-CTS protection for TXOP burst*/ + /*transmission when the acknowledgement policy is No-Ack or Block-Ack */ + /* this information is useful for external supplicant */ + /*Input Values: 1 for enable and 0 for disable. */ + if (strHostIFCfgParamAttr->pstrCfgParamVal.txop_prot_disabled < 2) { + strWIDList[u8WidCnt].u16WIDid = WID_11N_TXOP_PROT_DISABLE; + strWIDList[u8WidCnt].ps8WidVal = (WILC_Sint8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.txop_prot_disabled; + strWIDList[u8WidCnt].enuWIDtype = WID_CHAR; + strWIDList[u8WidCnt].s32ValueSize = sizeof(WILC_Char); + pstrWFIDrv->strCfgValues.txop_prot_disabled = (WILC_Uint8)strHostIFCfgParamAttr->pstrCfgParamVal.txop_prot_disabled; + } else { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + u8WidCnt++; + } + if (strHostIFCfgParamAttr->pstrCfgParamVal.u32SetCfgFlag & BEACON_INTERVAL) { + /* range is 1 to 65535. */ + if (strHostIFCfgParamAttr->pstrCfgParamVal.beacon_interval > 0 && strHostIFCfgParamAttr->pstrCfgParamVal.beacon_interval < 65536) { + strWIDList[u8WidCnt].u16WIDid = WID_BEACON_INTERVAL; + strWIDList[u8WidCnt].ps8WidVal = (WILC_Sint8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.beacon_interval; + strWIDList[u8WidCnt].enuWIDtype = WID_SHORT; + strWIDList[u8WidCnt].s32ValueSize = sizeof(WILC_Uint16); + pstrWFIDrv->strCfgValues.beacon_interval = strHostIFCfgParamAttr->pstrCfgParamVal.beacon_interval; + } else { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + u8WidCnt++; + } + if (strHostIFCfgParamAttr->pstrCfgParamVal.u32SetCfgFlag & DTIM_PERIOD) { + /* range is 1 to 255. */ + if (strHostIFCfgParamAttr->pstrCfgParamVal.dtim_period > 0 && strHostIFCfgParamAttr->pstrCfgParamVal.dtim_period < 256) { + strWIDList[u8WidCnt].u16WIDid = WID_DTIM_PERIOD; + strWIDList[u8WidCnt].ps8WidVal = (WILC_Sint8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.dtim_period; + strWIDList[u8WidCnt].enuWIDtype = WID_CHAR; + strWIDList[u8WidCnt].s32ValueSize = sizeof(WILC_Char); + pstrWFIDrv->strCfgValues.dtim_period = strHostIFCfgParamAttr->pstrCfgParamVal.dtim_period; + } else { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + u8WidCnt++; + } + if (strHostIFCfgParamAttr->pstrCfgParamVal.u32SetCfgFlag & SITE_SURVEY) { + /*----------------------------------------------------------------------*/ + /*Input Values: SITE_SURVEY_1CH = 0, i.e.: currently set channel */ + /* SITE_SURVEY_ALL_CH = 1, */ + /* SITE_SURVEY_OFF = 2 */ + /*----------------------------------------------------------------------*/ + if (strHostIFCfgParamAttr->pstrCfgParamVal.site_survey_enabled < 3) { + strWIDList[u8WidCnt].u16WIDid = WID_SITE_SURVEY; + strWIDList[u8WidCnt].ps8WidVal = (WILC_Sint8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.site_survey_enabled; + strWIDList[u8WidCnt].enuWIDtype = WID_CHAR; + strWIDList[u8WidCnt].s32ValueSize = sizeof(WILC_Char); + pstrWFIDrv->strCfgValues.site_survey_enabled = (WILC_Uint8)strHostIFCfgParamAttr->pstrCfgParamVal.site_survey_enabled; + } else { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + u8WidCnt++; + } + if (strHostIFCfgParamAttr->pstrCfgParamVal.u32SetCfgFlag & SITE_SURVEY_SCAN_TIME) { + /* range is 1 to 65535. */ + if (strHostIFCfgParamAttr->pstrCfgParamVal.site_survey_scan_time > 0 && strHostIFCfgParamAttr->pstrCfgParamVal.site_survey_scan_time < 65536) { + strWIDList[u8WidCnt].u16WIDid = WID_SITE_SURVEY_SCAN_TIME; + strWIDList[u8WidCnt].ps8WidVal = (WILC_Sint8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.site_survey_scan_time; + strWIDList[u8WidCnt].enuWIDtype = WID_SHORT; + strWIDList[u8WidCnt].s32ValueSize = sizeof(WILC_Uint16); + pstrWFIDrv->strCfgValues.site_survey_scan_time = strHostIFCfgParamAttr->pstrCfgParamVal.site_survey_scan_time; + } else { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + u8WidCnt++; + } + if (strHostIFCfgParamAttr->pstrCfgParamVal.u32SetCfgFlag & ACTIVE_SCANTIME) { + /* range is 1 to 65535. */ + if (strHostIFCfgParamAttr->pstrCfgParamVal.active_scan_time > 0 && strHostIFCfgParamAttr->pstrCfgParamVal.active_scan_time < 65536) { + strWIDList[u8WidCnt].u16WIDid = WID_ACTIVE_SCAN_TIME; + strWIDList[u8WidCnt].ps8WidVal = (WILC_Sint8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.active_scan_time; + strWIDList[u8WidCnt].enuWIDtype = WID_SHORT; + strWIDList[u8WidCnt].s32ValueSize = sizeof(WILC_Uint16); + pstrWFIDrv->strCfgValues.active_scan_time = strHostIFCfgParamAttr->pstrCfgParamVal.active_scan_time; + } else { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + u8WidCnt++; + } + if (strHostIFCfgParamAttr->pstrCfgParamVal.u32SetCfgFlag & PASSIVE_SCANTIME) { + /* range is 1 to 65535. */ + if (strHostIFCfgParamAttr->pstrCfgParamVal.passive_scan_time > 0 && strHostIFCfgParamAttr->pstrCfgParamVal.passive_scan_time < 65536) { + strWIDList[u8WidCnt].u16WIDid = WID_PASSIVE_SCAN_TIME; + strWIDList[u8WidCnt].ps8WidVal = (WILC_Sint8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.passive_scan_time; + strWIDList[u8WidCnt].enuWIDtype = WID_SHORT; + strWIDList[u8WidCnt].s32ValueSize = sizeof(WILC_Uint16); + pstrWFIDrv->strCfgValues.passive_scan_time = strHostIFCfgParamAttr->pstrCfgParamVal.passive_scan_time; + } else { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + u8WidCnt++; + } + if (strHostIFCfgParamAttr->pstrCfgParamVal.u32SetCfgFlag & CURRENT_TX_RATE) { + CURRENT_TX_RATE_T curr_tx_rate = strHostIFCfgParamAttr->pstrCfgParamVal.curr_tx_rate; + /*----------------------------------------------------------------------*/ + /*Rates: 1 2 5.5 11 6 9 12 18 24 36 48 54 Auto */ + /*InputValues: 1 2 3 4 5 6 7 8 9 10 11 12 0 */ + /*----------------------------------------------------------------------*/ + /* validate rate */ + if (curr_tx_rate == AUTORATE || curr_tx_rate == MBPS_1 + || curr_tx_rate == MBPS_2 || curr_tx_rate == MBPS_5_5 + || curr_tx_rate == MBPS_11 || curr_tx_rate == MBPS_6 + || curr_tx_rate == MBPS_9 || curr_tx_rate == MBPS_12 + || curr_tx_rate == MBPS_18 || curr_tx_rate == MBPS_24 + || curr_tx_rate == MBPS_36 || curr_tx_rate == MBPS_48 || curr_tx_rate == MBPS_54) { + strWIDList[u8WidCnt].u16WIDid = WID_CURRENT_TX_RATE; + strWIDList[u8WidCnt].ps8WidVal = (WILC_Sint8 *)&curr_tx_rate; + strWIDList[u8WidCnt].enuWIDtype = WID_SHORT; + strWIDList[u8WidCnt].s32ValueSize = sizeof(WILC_Uint16); + pstrWFIDrv->strCfgValues.curr_tx_rate = (WILC_Uint8)curr_tx_rate; + } else { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + u8WidCnt++; + } + s32Error = SendConfigPkt(SET_CFG, strWIDList, u8WidCnt, WILC_FALSE, (WILC_Uint32)pstrWFIDrv); + + if (s32Error) { + PRINT_ER("Error in setting CFG params\n"); + + } + WILC_CATCH(s32Error) + { + } + WILC_SemaphoreRelease(&(pstrWFIDrv->gtOsCfgValuesSem), NULL); + return s32Error; +} + + +/** + * @brief Handle_wait_msg_q_empty + * @details this should be the last msg and then the msg Q becomes idle + * @param[in] tstrHostIFscanAttr* pstrHostIFscanAttr + * @return Error code. + * @author + * @date + * @version 1.0 + */ +static WILC_Sint32 Handle_wait_msg_q_empty(void) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + g_wilc_initialized = 0; + WILC_SemaphoreRelease(&hWaitResponse, NULL); + return s32Error; +} + +/** + * @brief Handle_Scan + * @details Sending config packet to firmware to set the scan params + * @param[in] tstrHostIFscanAttr* pstrHostIFscanAttr + * @return Error code. + * @author + * @date + * @version 1.0 + */ +static WILC_Sint32 Handle_Scan(void *drvHandler, tstrHostIFscanAttr *pstrHostIFscanAttr) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWIDList[5]; + WILC_Uint32 u32WidsCount = 0; + WILC_Uint32 i; + WILC_Uint8 *pu8Buffer; + WILC_Uint8 valuesize = 0; + WILC_Uint8 *pu8HdnNtwrksWidVal = NULL; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *) drvHandler; + + PRINT_D(HOSTINF_DBG, "Setting SCAN params\n"); + PRINT_D(HOSTINF_DBG, "Scanning: In [%d] state \n", pstrWFIDrv->enuHostIFstate); + + pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult = pstrHostIFscanAttr->pfScanResult; + pstrWFIDrv->strWILC_UsrScanReq.u32UserScanPvoid = pstrHostIFscanAttr->pvUserArg; + + #ifdef WILC_P2P + #if 0 + if (pstrWFIDrv->enuHostIFstate == HOST_IF_P2P_LISTEN || (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTED && pstrWFIDrv->u8P2PConnect)) { + PRINT_INFO(GENERIC_DBG, "Busy: State: %d\n", pstrWFIDrv->enuHostIFstate); + PRINT_INFO(GENERIC_DBG, "Current Jiffies: %lu Timeout:%llu\n", jiffies, pstrWFIDrv->u64P2p_MgmtTimeout); + WILC_ERRORREPORT(s32Error, WILC_BUSY); + } + #endif + #endif + + if ((pstrWFIDrv->enuHostIFstate >= HOST_IF_SCANNING) && (pstrWFIDrv->enuHostIFstate < HOST_IF_CONNECTED)) { + /* here we either in HOST_IF_SCANNING, HOST_IF_WAITING_CONN_REQ or HOST_IF_WAITING_CONN_RESP */ + PRINT_D(GENERIC_DBG, "Don't scan we are already in [%d] state\n", pstrWFIDrv->enuHostIFstate); + WILC_ERRORREPORT(s32Error, WILC_BUSY); + } + + #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP + if (g_obtainingIP || connecting) { + PRINT_D(GENERIC_DBG, "[handle_scan]: Don't do obss scan until IP adresss is obtained\n"); + WILC_ERRORREPORT(s32Error, WILC_BUSY); + } + #endif + + PRINT_D(HOSTINF_DBG, "Setting SCAN params\n"); + + + pstrWFIDrv->strWILC_UsrScanReq.u32RcvdChCount = 0; + + /*BugID_4189*/ + strWIDList[u32WidsCount].u16WIDid = (WILC_Uint16)WID_SSID_PROBE_REQ; + strWIDList[u32WidsCount].enuWIDtype = WID_STR; + + for (i = 0; i < pstrHostIFscanAttr->strHiddenNetwork.u8ssidnum; i++) { + valuesize += ((pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen) + 1); + } + pu8HdnNtwrksWidVal = WILC_MALLOC(valuesize + 1); + strWIDList[u32WidsCount].ps8WidVal = pu8HdnNtwrksWidVal; + if (strWIDList[u32WidsCount].ps8WidVal != WILC_NULL) { + pu8Buffer = strWIDList[u32WidsCount].ps8WidVal; + + *pu8Buffer++ = pstrHostIFscanAttr->strHiddenNetwork.u8ssidnum; + + PRINT_D(HOSTINF_DBG, "In Handle_ProbeRequest number of ssid %d\n", pstrHostIFscanAttr->strHiddenNetwork.u8ssidnum); + + for (i = 0; i < pstrHostIFscanAttr->strHiddenNetwork.u8ssidnum; i++) { + *pu8Buffer++ = pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen; + WILC_memcpy(pu8Buffer, pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid, pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen); + pu8Buffer += pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen; + } + + + + strWIDList[u32WidsCount].s32ValueSize = (WILC_Sint32)(valuesize + 1); + u32WidsCount++; + } + + /*filling cfg param array*/ + + /* if((pstrHostIFscanAttr->pu8IEs != NULL) && (pstrHostIFscanAttr->IEsLen != 0)) */ + { + /* IEs to be inserted in Probe Request */ + strWIDList[u32WidsCount].u16WIDid = WID_INFO_ELEMENT_PROBE; + strWIDList[u32WidsCount].enuWIDtype = WID_BIN_DATA; + strWIDList[u32WidsCount].ps8WidVal = pstrHostIFscanAttr->pu8IEs; + strWIDList[u32WidsCount].s32ValueSize = pstrHostIFscanAttr->IEsLen; + u32WidsCount++; + } + + /*Scan Type*/ + strWIDList[u32WidsCount].u16WIDid = WID_SCAN_TYPE; + strWIDList[u32WidsCount].enuWIDtype = WID_CHAR; + strWIDList[u32WidsCount].s32ValueSize = sizeof(WILC_Char); + strWIDList[u32WidsCount].ps8WidVal = (WILC_Sint8 *)(&(pstrHostIFscanAttr->u8ScanType)); + u32WidsCount++; + + /*list of channels to be scanned*/ + strWIDList[u32WidsCount].u16WIDid = WID_SCAN_CHANNEL_LIST; + strWIDList[u32WidsCount].enuWIDtype = WID_BIN_DATA; + + /* Bug 4648: Convert channel numbers to start from 0 not 1. */ + if (pstrHostIFscanAttr->pu8ChnlFreqList != NULL && pstrHostIFscanAttr->u8ChnlListLen > 0) { + int i; + + for (i = 0; i < pstrHostIFscanAttr->u8ChnlListLen; i++) { + if (pstrHostIFscanAttr->pu8ChnlFreqList[i] > 0) { + pstrHostIFscanAttr->pu8ChnlFreqList[i] = pstrHostIFscanAttr->pu8ChnlFreqList[i] - 1; + } + } + } + + strWIDList[u32WidsCount].ps8WidVal = pstrHostIFscanAttr->pu8ChnlFreqList; + strWIDList[u32WidsCount].s32ValueSize = pstrHostIFscanAttr->u8ChnlListLen; + u32WidsCount++; + + /*Scan Request*/ + strWIDList[u32WidsCount].u16WIDid = WID_START_SCAN_REQ; + strWIDList[u32WidsCount].enuWIDtype = WID_CHAR; + strWIDList[u32WidsCount].s32ValueSize = sizeof(WILC_Char); + strWIDList[u32WidsCount].ps8WidVal = (WILC_Sint8 *)(&(pstrHostIFscanAttr->u8ScanSource)); + u32WidsCount++; + + /*keep the state as is , no need to change it*/ + /* gWFiDrvHandle->enuHostIFstate = HOST_IF_SCANNING; */ + + if (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTED) { + gbScanWhileConnected = WILC_TRUE; + } else if (pstrWFIDrv->enuHostIFstate == HOST_IF_IDLE) { + gbScanWhileConnected = WILC_FALSE; + } + + s32Error = SendConfigPkt(SET_CFG, strWIDList, u32WidsCount, WILC_FALSE, (WILC_Uint32)pstrWFIDrv); + + if (s32Error) { + PRINT_ER("Failed to send scan paramters config packet\n"); + WILC_ERRORREPORT(s32Error, s32Error); + } else { + PRINT_D(HOSTINF_DBG, "Successfully sent SCAN params config packet\n"); + } + + WILC_CATCH(s32Error) + { + WILC_TimerStop(&(pstrWFIDrv->hScanTimer), WILC_NULL); + /*if there is an ongoing scan request*/ + Handle_ScanDone(drvHandler, SCAN_EVENT_ABORTED); + } + + /* Deallocate pstrHostIFscanAttr->u8ChnlListLen which was prevoisuly allocated by the sending thread */ + if (pstrHostIFscanAttr->pu8ChnlFreqList != NULL) { + WILC_FREE(pstrHostIFscanAttr->pu8ChnlFreqList); + pstrHostIFscanAttr->pu8ChnlFreqList = NULL; + } + + /* Deallocate pstrHostIFscanAttr->pu8IEs which was previously allocated by the sending thread */ + if (pstrHostIFscanAttr->pu8IEs != NULL) { + WILC_FREE(pstrHostIFscanAttr->pu8IEs); + pstrHostIFscanAttr->pu8IEs = NULL; + } + if (pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo != NULL) { + WILC_FREE(pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo); + pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo = NULL; + } + + /* Deallocate pstrHostIFscanAttr->u8ChnlListLen which was prevoisuly allocated by the sending thread */ + if (pstrHostIFscanAttr->pu8ChnlFreqList != NULL) { + WILC_FREE(pstrHostIFscanAttr->pu8ChnlFreqList); + pstrHostIFscanAttr->pu8ChnlFreqList = NULL; + } + + if (pu8HdnNtwrksWidVal != NULL) { + WILC_FREE(pu8HdnNtwrksWidVal); + } + + return s32Error; +} + +/** + * @brief Handle_ScanDone + * @details Call scan notification callback function + * @param[in] NONE + * @return Error code. + * @author + * @date + * @version 1.0 + */ +static WILC_Sint32 Handle_ScanDone(void *drvHandler, tenuScanEvent enuEvent) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + + WILC_Uint8 u8abort_running_scan; + tstrWID strWID; + + + PRINT_D(HOSTINF_DBG, "in Handle_ScanDone()\n"); + + /*BugID_4978*/ + /*Ask FW to abort the running scan, if any*/ + if (enuEvent == SCAN_EVENT_ABORTED) { + PRINT_D(GENERIC_DBG, "Abort running scan\n"); + u8abort_running_scan = 1; + strWID.u16WIDid = (WILC_Uint16)WID_ABORT_RUNNING_SCAN; + strWID.enuWIDtype = WID_CHAR; + strWID.ps8WidVal = (WILC_Sint8 *)&u8abort_running_scan; + strWID.s32ValueSize = sizeof(WILC_Char); + + /*Sending Cfg*/ + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + if (s32Error != WILC_SUCCESS) { + PRINT_ER("Failed to set abort running scan\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + WILC_CATCH(s32Error) + { + } + } + + if (pstrWFIDrv == NULL) { + PRINT_ER("Driver handler is NULL\n"); + return s32Error; + } + + /*if there is an ongoing scan request*/ + if (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult) { + pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult(enuEvent, WILC_NULL, + pstrWFIDrv->strWILC_UsrScanReq.u32UserScanPvoid, NULL); + /*delete current scan request*/ + pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult = NULL; + } + + return s32Error; +} + +/** + * @brief Handle_Connect + * @details Sending config packet to firmware to starting connection + * @param[in] tstrHostIFconnectAttr* pstrHostIFconnectAttr + * @return Error code. + * @author + * @date + * @version 1.0 + */ +WILC_Uint8 u8ConnectedSSID[6] = {0}; +static WILC_Sint32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFconnectAttr) +{ + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *) drvHandler; + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWIDList[8]; + WILC_Uint32 u32WidsCount = 0, dummyval = 0; + /* char passphrase[] = "12345678"; */ + #ifndef CONNECT_DIRECT + WILC_Sint32 s32Err = WILC_SUCCESS; + WILC_Uint32 i; + WILC_Uint8 u8bssDscListIndex; + wid_site_survey_reslts_s *pstrSurveyResults = WILC_NULL; + #else + WILC_Uint8 *pu8CurrByte = WILC_NULL; + /*Bug4218: Parsing Join Param*/ + #ifdef WILC_PARSE_SCAN_IN_HOST + tstrJoinBssParam *ptstrJoinBssParam; + #endif /*WILC_PARSE_SCAN_IN_HOST*/ + + #endif + + PRINT_D(GENERIC_DBG, "Handling connect request\n"); + + #ifndef CONNECT_DIRECT + WILC_memset(gapu8RcvdSurveyResults[0], 0, MAX_SURVEY_RESULT_FRAG_SIZE); + WILC_memset(gapu8RcvdSurveyResults[1], 0, MAX_SURVEY_RESULT_FRAG_SIZE); + + + PRINT_D(HOSTINF_DBG, "Getting site survey results\n"); + s32Err = host_int_get_site_survey_results((WILC_WFIDrvHandle)pstrWFIDrv, + gapu8RcvdSurveyResults, + MAX_SURVEY_RESULT_FRAG_SIZE); + if (s32Err) { + PRINT_ER("Failed to get site survey results\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + + } + s32Err = ParseSurveyResults(gapu8RcvdSurveyResults, &pstrSurveyResults, + &pstrWFIDrv->u32SurveyResultsCount); + + + if (s32Err == WILC_SUCCESS) { + /* use the parsed info in pstrSurveyResults, then deallocate it */ + PRINT_D(HOSTINF_DBG, "Copying site survey results in global structure, then deallocate\n"); + for (i = 0; i < pstrWFIDrv->u32SurveyResultsCount; i++) { + WILC_memcpy(&pstrWFIDrv->astrSurveyResults[i], &pstrSurveyResults[i], + sizeof(wid_site_survey_reslts_s)); + } + + DeallocateSurveyResults(pstrSurveyResults); + } else { + WILC_ERRORREPORT(s32Error, WILC_FAIL); + PRINT_ER("ParseSurveyResults() Error(%d) \n", s32Err); + } + + + for (i = 0; i < pstrWFIDrv->u32SurveyResultsCount; i++) { + if (WILC_memcmp(pstrWFIDrv->astrSurveyResults[i].SSID, + pstrHostIFconnectAttr->pu8ssid, + pstrHostIFconnectAttr->ssidLen) == 0) { + PRINT_INFO(HOSTINF_DBG, "Network with required SSID is found %s\n", pstrHostIFconnectAttr->pu8ssid); + if (pstrHostIFconnectAttr->pu8bssid == NULL) { + /* BSSID is not passed from the user, so decision of matching + * is done by SSID only */ + PRINT_INFO(HOSTINF_DBG, "BSSID is not passed from the user\n"); + break; + } else { + /* BSSID is also passed from the user, so decision of matching + * should consider also this passed BSSID */ + + if (WILC_memcmp(pstrWFIDrv->astrSurveyResults[i].BSSID, + pstrHostIFconnectAttr->pu8bssid, + 6) == 0) { + PRINT_INFO(HOSTINF_DBG, "BSSID is passed from the user and matched\n"); + break; + } + } + } + } + + if (i < pstrWFIDrv->u32SurveyResultsCount) { + u8bssDscListIndex = i; + + PRINT_INFO(HOSTINF_DBG, "Connecting to network of Bss Idx %d and SSID %s and channel %d \n", + u8bssDscListIndex, pstrWFIDrv->astrSurveyResults[u8bssDscListIndex].SSID, + pstrWFIDrv->astrSurveyResults[u8bssDscListIndex].Channel); + + PRINT_INFO(HOSTINF_DBG, "Saving connection parameters in global structure\n"); + + if (pstrHostIFconnectAttr->pu8bssid != NULL) { + pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = (WILC_Uint8 *)WILC_MALLOC(6); + WILC_memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, pstrHostIFconnectAttr->pu8bssid, 6); + } + + pstrWFIDrv->strWILC_UsrConnReq.ssidLen = pstrHostIFconnectAttr->ssidLen; + if (pstrHostIFconnectAttr->pu8ssid != NULL) { + pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = (WILC_Uint8 *)WILC_MALLOC(pstrHostIFconnectAttr->ssidLen + 1); + WILC_memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid, pstrHostIFconnectAttr->pu8ssid, + pstrHostIFconnectAttr->ssidLen); + pstrWFIDrv->strWILC_UsrConnReq.pu8ssid[pstrHostIFconnectAttr->ssidLen] = '\0'; + } + + pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen = pstrHostIFconnectAttr->IEsLen; + if (pstrHostIFconnectAttr->pu8IEs != NULL) { + pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = (WILC_Uint8 *)WILC_MALLOC(pstrHostIFconnectAttr->IEsLen); + WILC_memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs, pstrHostIFconnectAttr->pu8IEs, + pstrHostIFconnectAttr->IEsLen); + } + + pstrWFIDrv->strWILC_UsrConnReq.u8security = pstrHostIFconnectAttr->u8security; + pstrWFIDrv->strWILC_UsrConnReq.tenuAuth_type = pstrHostIFconnectAttr->tenuAuth_type; + pstrWFIDrv->strWILC_UsrConnReq.pfUserConnectResult = pstrHostIFconnectAttr->pfConnectResult; + pstrWFIDrv->strWILC_UsrConnReq.u32UserConnectPvoid = pstrHostIFconnectAttr->pvUserArg; + + + /* if((gWFiDrvHandle->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) && */ + /* (gWFiDrvHandle->strWILC_UsrConnReq.ConnReqIEsLen != 0)) */ + { + /* IEs to be inserted in Association Request */ + strWIDList[u32WidsCount].u16WIDid = WID_INFO_ELEMENT_ASSOCIATE; + strWIDList[u32WidsCount].enuWIDtype = WID_BIN_DATA; + strWIDList[u32WidsCount].ps8WidVal = pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs; + strWIDList[u32WidsCount].s32ValueSize = pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen; + u32WidsCount++; + } + strWIDList[u32WidsCount].u16WIDid = (WILC_Uint16)WID_11I_MODE; + strWIDList[u32WidsCount].enuWIDtype = WID_CHAR; + strWIDList[u32WidsCount].s32ValueSize = sizeof(WILC_Char); + strWIDList[u32WidsCount].ps8WidVal = (WILC_Sint8 *)(&(pstrWFIDrv->strWILC_UsrConnReq.u8security)); + u32WidsCount++; + + PRINT_INFO(HOSTINF_DBG, "Encrypt Mode = %x\n", pstrWFIDrv->strWILC_UsrConnReq.u8security); + + strWIDList[u32WidsCount].u16WIDid = (WILC_Uint16)WID_AUTH_TYPE; + strWIDList[u32WidsCount].enuWIDtype = WID_CHAR; + strWIDList[u32WidsCount].s32ValueSize = sizeof(WILC_Char); + strWIDList[u32WidsCount].ps8WidVal = (WILC_Sint8 *)(&pstrWFIDrv->strWILC_UsrConnReq.tenuAuth_type); + u32WidsCount++; + + PRINT_INFO(HOSTINF_DBG, "Authentication Type = %x\n", pstrWFIDrv->strWILC_UsrConnReq.tenuAuth_type); + /* + * strWIDList[u32WidsCount].u16WIDid = (WILC_Uint16)WID_11I_PSK; + * strWIDList[u32WidsCount].enuWIDtype = WID_STR; + * strWIDList[u32WidsCount].s32ValueSize = sizeof(passphrase); + * strWIDList[u32WidsCount].ps8WidVal = (WILC_Sint8*)(passphrase); + * u32WidsCount++; + */ + + strWIDList[u32WidsCount].u16WIDid = (WILC_Uint16)WID_JOIN_REQ; + strWIDList[u32WidsCount].enuWIDtype = WID_CHAR; + strWIDList[u32WidsCount].s32ValueSize = sizeof(WILC_Char); + strWIDList[u32WidsCount].ps8WidVal = (WILC_Sint8 *)&u8bssDscListIndex; + u32WidsCount++; + + #ifndef SIMULATION + /* A temporary workaround to avoid handling the misleading MAC_DISCONNECTED raised from the + * firmware at chip reset when processing the WIDs of the Connect Request. + * (This workaround should be removed in the future when the Chip reset of the Connect WIDs is disabled) */ + /* ////////////////////// */ + gu32WidConnRstHack = 0; + /* ////////////////////// */ + #endif + + s32Error = SendConfigPkt(SET_CFG, strWIDList, u32WidsCount, WILC_FALSE, (WILC_Uint32)pstrWFIDrv); + if (s32Error) { + PRINT_ER("Handle_Connect()] failed to send config packet\n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_STATE); + } else { + pstrWFIDrv->enuHostIFstate = HOST_IF_WAITING_CONN_RESP; + } + + } else { + PRINT_ER("Required BSSID not found\n"); + WILC_ERRORREPORT(s32Error, WILC_NOT_FOUND); + } + + #else + + /* if we try to connect to an already connected AP then discard the request */ + + if (WILC_memcmp(pstrHostIFconnectAttr->pu8bssid, u8ConnectedSSID, ETH_ALEN) == 0) { + + s32Error = WILC_SUCCESS; + PRINT_ER("Trying to connect to an already connected AP, Discard connect request\n"); + return s32Error; + } + + PRINT_INFO(HOSTINF_DBG, "Saving connection parameters in global structure\n"); + + /*Bug4218: Parsing Join Param*/ + #ifdef WILC_PARSE_SCAN_IN_HOST + ptstrJoinBssParam = (tstrJoinBssParam *)pstrHostIFconnectAttr->pJoinParams; + if (ptstrJoinBssParam == NULL) { + PRINT_ER("Required BSSID not found\n"); + WILC_ERRORREPORT(s32Error, WILC_NOT_FOUND); + } + #endif /*WILC_PARSE_SCAN_IN_HOST*/ + +#if 0 + /* if we try to connect to an already connected AP then discard the request */ + PRINT_D(GENERIC_DBG, "Bssid = %x:%x:%x:%x:%x:%x\n", (pstrHostIFconnectAttr->pu8bssid[0]), (pstrHostIFconnectAttr->pu8bssid[1]), (pstrHostIFconnectAttr->pu8bssid[2]), (pstrHostIFconnectAttr->pu8bssid[3]), (pstrHostIFconnectAttr->pu8bssid[4]), (pstrHostIFconnectAttr->pu8bssid[5])); + PRINT_D(GENERIC_DBG, "bssid = %x:%x:%x:%x:%x:%x\n", (u8ConnectedSSID[0]), (u8ConnectedSSID[1]), (u8ConnectedSSID[2]), (u8ConnectedSSID[3]), (u8ConnectedSSID[4]), (u8ConnectedSSID[5])); + if (WILC_memcmp(pstrHostIFconnectAttr->pu8bssid, u8ConnectedSSID, ETH_ALEN) == 0) { + PRINT_ER("Discard connect request\n"); + s32Error = WILC_FAIL; + return s32Error; + } +#endif + + if (pstrHostIFconnectAttr->pu8bssid != NULL) { + pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = (WILC_Uint8 *)WILC_MALLOC(6); + WILC_memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, pstrHostIFconnectAttr->pu8bssid, 6); + } + + pstrWFIDrv->strWILC_UsrConnReq.ssidLen = pstrHostIFconnectAttr->ssidLen; + if (pstrHostIFconnectAttr->pu8ssid != NULL) { + pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = (WILC_Uint8 *)WILC_MALLOC(pstrHostIFconnectAttr->ssidLen + 1); + WILC_memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid, pstrHostIFconnectAttr->pu8ssid, + pstrHostIFconnectAttr->ssidLen); + pstrWFIDrv->strWILC_UsrConnReq.pu8ssid[pstrHostIFconnectAttr->ssidLen] = '\0'; + } + + pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen = pstrHostIFconnectAttr->IEsLen; + if (pstrHostIFconnectAttr->pu8IEs != NULL) { + pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = (WILC_Uint8 *)WILC_MALLOC(pstrHostIFconnectAttr->IEsLen); + WILC_memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs, pstrHostIFconnectAttr->pu8IEs, + pstrHostIFconnectAttr->IEsLen); + } + + pstrWFIDrv->strWILC_UsrConnReq.u8security = pstrHostIFconnectAttr->u8security; + pstrWFIDrv->strWILC_UsrConnReq.tenuAuth_type = pstrHostIFconnectAttr->tenuAuth_type; + pstrWFIDrv->strWILC_UsrConnReq.pfUserConnectResult = pstrHostIFconnectAttr->pfConnectResult; + pstrWFIDrv->strWILC_UsrConnReq.u32UserConnectPvoid = pstrHostIFconnectAttr->pvUserArg; + + strWIDList[u32WidsCount].u16WIDid = WID_SUCCESS_FRAME_COUNT; + strWIDList[u32WidsCount].enuWIDtype = WID_INT; + strWIDList[u32WidsCount].s32ValueSize = sizeof(WILC_Uint32); + strWIDList[u32WidsCount].ps8WidVal = (WILC_Sint8 *)(&(dummyval)); + u32WidsCount++; + + strWIDList[u32WidsCount].u16WIDid = WID_RECEIVED_FRAGMENT_COUNT; + strWIDList[u32WidsCount].enuWIDtype = WID_INT; + strWIDList[u32WidsCount].s32ValueSize = sizeof(WILC_Uint32); + strWIDList[u32WidsCount].ps8WidVal = (WILC_Sint8 *)(&(dummyval)); + u32WidsCount++; + + strWIDList[u32WidsCount].u16WIDid = WID_FAILED_COUNT; + strWIDList[u32WidsCount].enuWIDtype = WID_INT; + strWIDList[u32WidsCount].s32ValueSize = sizeof(WILC_Uint32); + strWIDList[u32WidsCount].ps8WidVal = (WILC_Sint8 *)(&(dummyval)); + u32WidsCount++; + + /* if((gWFiDrvHandle->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) && */ + /* (gWFiDrvHandle->strWILC_UsrConnReq.ConnReqIEsLen != 0)) */ + { + /* IEs to be inserted in Association Request */ + strWIDList[u32WidsCount].u16WIDid = WID_INFO_ELEMENT_ASSOCIATE; + strWIDList[u32WidsCount].enuWIDtype = WID_BIN_DATA; + strWIDList[u32WidsCount].ps8WidVal = pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs; + strWIDList[u32WidsCount].s32ValueSize = pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen; + u32WidsCount++; + + /*BugID_5137*/ + if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) { + + gu32FlushedInfoElemAsocSize = pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen; + gu8FlushedInfoElemAsoc = WILC_MALLOC(gu32FlushedInfoElemAsocSize); + memcpy(gu8FlushedInfoElemAsoc, pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs, + gu32FlushedInfoElemAsocSize); + } + } + strWIDList[u32WidsCount].u16WIDid = (WILC_Uint16)WID_11I_MODE; + strWIDList[u32WidsCount].enuWIDtype = WID_CHAR; + strWIDList[u32WidsCount].s32ValueSize = sizeof(WILC_Char); + strWIDList[u32WidsCount].ps8WidVal = (WILC_Sint8 *)(&(pstrWFIDrv->strWILC_UsrConnReq.u8security)); + u32WidsCount++; + + /*BugID_5137*/ + if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) + gu8Flushed11iMode = pstrWFIDrv->strWILC_UsrConnReq.u8security; + + PRINT_INFO(HOSTINF_DBG, "Encrypt Mode = %x\n", pstrWFIDrv->strWILC_UsrConnReq.u8security); + + + strWIDList[u32WidsCount].u16WIDid = (WILC_Uint16)WID_AUTH_TYPE; + strWIDList[u32WidsCount].enuWIDtype = WID_CHAR; + strWIDList[u32WidsCount].s32ValueSize = sizeof(WILC_Char); + strWIDList[u32WidsCount].ps8WidVal = (WILC_Sint8 *)(&pstrWFIDrv->strWILC_UsrConnReq.tenuAuth_type); + u32WidsCount++; + + /*BugID_5137*/ + if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) + gu8FlushedAuthType = (WILC_Uint8)pstrWFIDrv->strWILC_UsrConnReq.tenuAuth_type; + + PRINT_INFO(HOSTINF_DBG, "Authentication Type = %x\n", pstrWFIDrv->strWILC_UsrConnReq.tenuAuth_type); + /* + * strWIDList[u32WidsCount].u16WIDid = (WILC_Uint16)WID_11I_PSK; + * strWIDList[u32WidsCount].enuWIDtype = WID_STR; + * strWIDList[u32WidsCount].s32ValueSize = sizeof(passphrase); + * strWIDList[u32WidsCount].ps8WidVal = (WILC_Sint8*)(passphrase); + * u32WidsCount++; + */ + + PRINT_D(HOSTINF_DBG, "Connecting to network of SSID %s on channel %d\n", + pstrWFIDrv->strWILC_UsrConnReq.pu8ssid, pstrHostIFconnectAttr->u8channel); + + +#ifndef WILC_PARSE_SCAN_IN_HOST + strWIDList[u32WidsCount].u16WIDid = (WILC_Uint16)WID_JOIN_REQ_EXTENDED; + strWIDList[u32WidsCount].enuWIDtype = WID_STR; + strWIDList[u32WidsCount].s32ValueSize = MAX_SSID_LEN + 7; + strWIDList[u32WidsCount].ps8WidVal = WILC_MALLOC(strWIDList[u32WidsCount].s32ValueSize); + + if (strWIDList[u32WidsCount].ps8WidVal == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_NO_MEM); + } + + pu8CurrByte = strWIDList[u32WidsCount].ps8WidVal; + + if (pstrHostIFconnectAttr->pu8ssid != NULL) { + WILC_memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8ssid, pstrHostIFconnectAttr->ssidLen); + pu8CurrByte[pstrHostIFconnectAttr->ssidLen] = '\0'; + } + pu8CurrByte += MAX_SSID_LEN; + if ((pstrHostIFconnectAttr->u8channel >= 1) && (pstrHostIFconnectAttr->u8channel <= 14)) { + *(pu8CurrByte++) = pstrHostIFconnectAttr->u8channel; + } else { + PRINT_ER("Channel out of range\n"); + *(pu8CurrByte++) = 0xFF; + } + if (pstrHostIFconnectAttr->pu8bssid != NULL) { + WILC_memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8bssid, 6); + } + pu8CurrByte += 6; + + /* keep the buffer at the start of the allocated pointer to use it with the free*/ + pu8CurrByte = strWIDList[u32WidsCount].ps8WidVal; + + #else + + strWIDList[u32WidsCount].u16WIDid = (WILC_Uint16)WID_JOIN_REQ_EXTENDED; + strWIDList[u32WidsCount].enuWIDtype = WID_STR; + + /*Sending NoA attributes during connection*/ + strWIDList[u32WidsCount].s32ValueSize = 112; /* 79; */ + strWIDList[u32WidsCount].ps8WidVal = WILC_MALLOC(strWIDList[u32WidsCount].s32ValueSize); + + /*BugID_5137*/ + if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) { + gu32FlushedJoinReqSize = strWIDList[u32WidsCount].s32ValueSize; + gu8FlushedJoinReq = WILC_MALLOC(gu32FlushedJoinReqSize); + } + if (strWIDList[u32WidsCount].ps8WidVal == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_NO_MEM); + } + + pu8CurrByte = strWIDList[u32WidsCount].ps8WidVal; + + + if (pstrHostIFconnectAttr->pu8ssid != NULL) { + WILC_memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8ssid, pstrHostIFconnectAttr->ssidLen); + pu8CurrByte[pstrHostIFconnectAttr->ssidLen] = '\0'; + } + pu8CurrByte += MAX_SSID_LEN; + + /* BSS type*/ + *(pu8CurrByte++) = INFRASTRUCTURE; + /* Channel*/ + if ((pstrHostIFconnectAttr->u8channel >= 1) && (pstrHostIFconnectAttr->u8channel <= 14)) { + *(pu8CurrByte++) = pstrHostIFconnectAttr->u8channel; + } else { + PRINT_ER("Channel out of range\n"); + *(pu8CurrByte++) = 0xFF; + } + /* Cap Info*/ + *(pu8CurrByte++) = (ptstrJoinBssParam->cap_info) & 0xFF; + *(pu8CurrByte++) = ((ptstrJoinBssParam->cap_info) >> 8) & 0xFF; + PRINT_D(HOSTINF_DBG, "* Cap Info %0x*\n", (*(pu8CurrByte - 2) | ((*(pu8CurrByte - 1)) << 8))); + + /* sa*/ + if (pstrHostIFconnectAttr->pu8bssid != NULL) { + WILC_memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8bssid, 6); + } + pu8CurrByte += 6; + + /* bssid*/ + if (pstrHostIFconnectAttr->pu8bssid != NULL) { + WILC_memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8bssid, 6); + } + pu8CurrByte += 6; + + /* Beacon Period*/ + *(pu8CurrByte++) = (ptstrJoinBssParam->beacon_period) & 0xFF; + *(pu8CurrByte++) = ((ptstrJoinBssParam->beacon_period) >> 8) & 0xFF; + PRINT_D(HOSTINF_DBG, "* Beacon Period %d*\n", (*(pu8CurrByte - 2) | ((*(pu8CurrByte - 1)) << 8))); + /* DTIM Period*/ + *(pu8CurrByte++) = ptstrJoinBssParam->dtim_period; + PRINT_D(HOSTINF_DBG, "* DTIM Period %d*\n", (*(pu8CurrByte - 1))); + /* Supported rates*/ + WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->supp_rates, MAX_RATES_SUPPORTED + 1); + pu8CurrByte += (MAX_RATES_SUPPORTED + 1); + + /* wmm cap*/ + *(pu8CurrByte++) = ptstrJoinBssParam->wmm_cap; + PRINT_D(HOSTINF_DBG, "* wmm cap%d*\n", (*(pu8CurrByte - 1))); + /* uapsd cap*/ + *(pu8CurrByte++) = ptstrJoinBssParam->uapsd_cap; + + /* ht cap*/ + *(pu8CurrByte++) = ptstrJoinBssParam->ht_capable; + /* copy this information to the user request */ + pstrWFIDrv->strWILC_UsrConnReq.IsHTCapable = ptstrJoinBssParam->ht_capable; + + /* rsn found*/ + *(pu8CurrByte++) = ptstrJoinBssParam->rsn_found; + PRINT_D(HOSTINF_DBG, "* rsn found %d*\n", *(pu8CurrByte - 1)); + /* rsn group policy*/ + *(pu8CurrByte++) = ptstrJoinBssParam->rsn_grp_policy; + PRINT_D(HOSTINF_DBG, "* rsn group policy %0x*\n", (*(pu8CurrByte - 1))); + /* mode_802_11i*/ + *(pu8CurrByte++) = ptstrJoinBssParam->mode_802_11i; + PRINT_D(HOSTINF_DBG, "* mode_802_11i %d*\n", (*(pu8CurrByte - 1))); + /* rsn pcip policy*/ + WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_pcip_policy, sizeof(ptstrJoinBssParam->rsn_pcip_policy)); + pu8CurrByte += sizeof(ptstrJoinBssParam->rsn_pcip_policy); + + /* rsn auth policy*/ + WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_auth_policy, sizeof(ptstrJoinBssParam->rsn_auth_policy)); + pu8CurrByte += sizeof(ptstrJoinBssParam->rsn_auth_policy); + + /* rsn auth policy*/ + WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_cap, sizeof(ptstrJoinBssParam->rsn_cap)); + pu8CurrByte += sizeof(ptstrJoinBssParam->rsn_cap); + + /*BugID_5137*/ + *(pu8CurrByte++) = REAL_JOIN_REQ; + + #ifdef WILC_P2P + *(pu8CurrByte++) = ptstrJoinBssParam->u8NoaEnbaled; + if (ptstrJoinBssParam->u8NoaEnbaled) { + PRINT_D(HOSTINF_DBG, "NOA present\n"); + + *(pu8CurrByte++) = (ptstrJoinBssParam->tsf) & 0xFF; + *(pu8CurrByte++) = ((ptstrJoinBssParam->tsf) >> 8) & 0xFF; + *(pu8CurrByte++) = ((ptstrJoinBssParam->tsf) >> 16) & 0xFF; + *(pu8CurrByte++) = ((ptstrJoinBssParam->tsf) >> 24) & 0xFF; + + *(pu8CurrByte++) = ptstrJoinBssParam->u8Index; + + *(pu8CurrByte++) = ptstrJoinBssParam->u8OppEnable; + + if (ptstrJoinBssParam->u8OppEnable) + *(pu8CurrByte++) = ptstrJoinBssParam->u8CtWindow; + + *(pu8CurrByte++) = ptstrJoinBssParam->u8Count; + + WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->au8Duration, sizeof(ptstrJoinBssParam->au8Duration)); + + pu8CurrByte += sizeof(ptstrJoinBssParam->au8Duration); + + WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->au8Interval, sizeof(ptstrJoinBssParam->au8Interval)); + + pu8CurrByte += sizeof(ptstrJoinBssParam->au8Interval); + + WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->au8StartTime, sizeof(ptstrJoinBssParam->au8StartTime)); + + pu8CurrByte += sizeof(ptstrJoinBssParam->au8StartTime); + + } else + PRINT_D(HOSTINF_DBG, "NOA not present\n"); + #endif + + + /* keep the buffer at the start of the allocated pointer to use it with the free*/ + pu8CurrByte = strWIDList[u32WidsCount].ps8WidVal; + + + #endif /* #ifdef WILC_PARSE_SCAN_IN_HOST*/ + u32WidsCount++; + + #ifndef SIMULATION + /* A temporary workaround to avoid handling the misleading MAC_DISCONNECTED raised from the + * firmware at chip reset when processing the WIDs of the Connect Request. + * (This workaround should be removed in the future when the Chip reset of the Connect WIDs is disabled) */ + /* ////////////////////// */ + gu32WidConnRstHack = 0; + /* ////////////////////// */ + #endif + + /*BugID_5137*/ + if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) { + memcpy(gu8FlushedJoinReq, pu8CurrByte, gu32FlushedJoinReqSize); + gu8FlushedJoinReqDrvHandler = (WILC_Uint32)pstrWFIDrv; + } + + PRINT_D(GENERIC_DBG, "send HOST_IF_WAITING_CONN_RESP\n"); + + if (pstrHostIFconnectAttr->pu8bssid != NULL) { + WILC_memcpy(u8ConnectedSSID, pstrHostIFconnectAttr->pu8bssid, ETH_ALEN); + + PRINT_D(GENERIC_DBG, "save Bssid = %x:%x:%x:%x:%x:%x\n", (pstrHostIFconnectAttr->pu8bssid[0]), (pstrHostIFconnectAttr->pu8bssid[1]), (pstrHostIFconnectAttr->pu8bssid[2]), (pstrHostIFconnectAttr->pu8bssid[3]), (pstrHostIFconnectAttr->pu8bssid[4]), (pstrHostIFconnectAttr->pu8bssid[5])); + PRINT_D(GENERIC_DBG, "save bssid = %x:%x:%x:%x:%x:%x\n", (u8ConnectedSSID[0]), (u8ConnectedSSID[1]), (u8ConnectedSSID[2]), (u8ConnectedSSID[3]), (u8ConnectedSSID[4]), (u8ConnectedSSID[5])); + } + + s32Error = SendConfigPkt(SET_CFG, strWIDList, u32WidsCount, WILC_FALSE, (WILC_Uint32)pstrWFIDrv); + if (s32Error) { + PRINT_ER("Handle_Connect()] failed to send config packet\n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_STATE); + } else { + PRINT_D(GENERIC_DBG, "set HOST_IF_WAITING_CONN_RESP\n"); + pstrWFIDrv->enuHostIFstate = HOST_IF_WAITING_CONN_RESP; + } + #endif + + WILC_CATCH(s32Error) + { + tstrConnectInfo strConnectInfo; + + WILC_TimerStop(&(pstrWFIDrv->hConnectTimer), WILC_NULL); + + PRINT_D(HOSTINF_DBG, "could not start connecting to the required network\n"); + + WILC_memset(&strConnectInfo, 0, sizeof(tstrConnectInfo)); + + if (pstrHostIFconnectAttr->pfConnectResult != NULL) { + if (pstrHostIFconnectAttr->pu8bssid != NULL) { + WILC_memcpy(strConnectInfo.au8bssid, pstrHostIFconnectAttr->pu8bssid, 6); + } + + if (pstrHostIFconnectAttr->pu8IEs != NULL) { + strConnectInfo.ReqIEsLen = pstrHostIFconnectAttr->IEsLen; + strConnectInfo.pu8ReqIEs = (WILC_Uint8 *)WILC_MALLOC(pstrHostIFconnectAttr->IEsLen); + WILC_memcpy(strConnectInfo.pu8ReqIEs, + pstrHostIFconnectAttr->pu8IEs, + pstrHostIFconnectAttr->IEsLen); + } + + pstrHostIFconnectAttr->pfConnectResult(CONN_DISCONN_EVENT_CONN_RESP, + &strConnectInfo, + MAC_DISCONNECTED, + NULL, + pstrHostIFconnectAttr->pvUserArg); + /*Change state to idle*/ + pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE; + /* Deallocation */ + if (strConnectInfo.pu8ReqIEs != NULL) { + WILC_FREE(strConnectInfo.pu8ReqIEs); + strConnectInfo.pu8ReqIEs = NULL; + } + + } else { + PRINT_ER("Connect callback function pointer is NULL \n"); + } + } + + PRINT_D(HOSTINF_DBG, "Deallocating connection parameters\n"); + /* Deallocate pstrHostIFconnectAttr->pu8bssid which was prevoisuly allocated by the sending thread */ + if (pstrHostIFconnectAttr->pu8bssid != NULL) { + WILC_FREE(pstrHostIFconnectAttr->pu8bssid); + pstrHostIFconnectAttr->pu8bssid = NULL; + } + + /* Deallocate pstrHostIFconnectAttr->pu8ssid which was prevoisuly allocated by the sending thread */ + if (pstrHostIFconnectAttr->pu8ssid != NULL) { + WILC_FREE(pstrHostIFconnectAttr->pu8ssid); + pstrHostIFconnectAttr->pu8ssid = NULL; + } + + /* Deallocate pstrHostIFconnectAttr->pu8IEs which was prevoisuly allocated by the sending thread */ + if (pstrHostIFconnectAttr->pu8IEs != NULL) { + WILC_FREE(pstrHostIFconnectAttr->pu8IEs); + pstrHostIFconnectAttr->pu8IEs = NULL; + } + + if (pu8CurrByte != WILC_NULL) { + WILC_FREE(pu8CurrByte); + } + return s32Error; +} + +/** + * @brief Handle_FlushConnect + * @details Sending config packet to firmware to flush an old connection + * after switching FW from station one to hybrid one + * @param[in] void * drvHandler + * @return Error code. + * @author Amr Abdel-Moghny + * @date 19 DEC 2013 + * @version 8.0 + */ + +static WILC_Sint32 Handle_FlushConnect(void *drvHandler) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWIDList[5]; + WILC_Uint32 u32WidsCount = 0; + WILC_Uint8 *pu8CurrByte = WILC_NULL; + + + /* IEs to be inserted in Association Request */ + strWIDList[u32WidsCount].u16WIDid = WID_INFO_ELEMENT_ASSOCIATE; + strWIDList[u32WidsCount].enuWIDtype = WID_BIN_DATA; + strWIDList[u32WidsCount].ps8WidVal = gu8FlushedInfoElemAsoc; + strWIDList[u32WidsCount].s32ValueSize = gu32FlushedInfoElemAsocSize; + u32WidsCount++; + + strWIDList[u32WidsCount].u16WIDid = (WILC_Uint16)WID_11I_MODE; + strWIDList[u32WidsCount].enuWIDtype = WID_CHAR; + strWIDList[u32WidsCount].s32ValueSize = sizeof(WILC_Char); + strWIDList[u32WidsCount].ps8WidVal = (WILC_Sint8 *)(&(gu8Flushed11iMode)); + u32WidsCount++; + + + + strWIDList[u32WidsCount].u16WIDid = (WILC_Uint16)WID_AUTH_TYPE; + strWIDList[u32WidsCount].enuWIDtype = WID_CHAR; + strWIDList[u32WidsCount].s32ValueSize = sizeof(WILC_Char); + strWIDList[u32WidsCount].ps8WidVal = (WILC_Sint8 *)(&gu8FlushedAuthType); + u32WidsCount++; + + + #ifdef WILC_PARSE_SCAN_IN_HOST + strWIDList[u32WidsCount].u16WIDid = (WILC_Uint16)WID_JOIN_REQ_EXTENDED; + strWIDList[u32WidsCount].enuWIDtype = WID_STR; + strWIDList[u32WidsCount].s32ValueSize = gu32FlushedJoinReqSize; + strWIDList[u32WidsCount].ps8WidVal = (WILC_Sint8 *)gu8FlushedJoinReq; + pu8CurrByte = strWIDList[u32WidsCount].ps8WidVal; + + pu8CurrByte += FLUSHED_BYTE_POS; + *(pu8CurrByte) = FLUSHED_JOIN_REQ; + + u32WidsCount++; + + #endif + + s32Error = SendConfigPkt(SET_CFG, strWIDList, u32WidsCount, WILC_FALSE, gu8FlushedJoinReqDrvHandler); + if (s32Error) { + PRINT_ER("Handle_Flush_Connect()] failed to send config packet\n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_STATE); + } + + WILC_CATCH(s32Error) + { + + } + + return s32Error; +} + +/** + * @brief Handle_ConnectTimeout + * @details Call connect notification callback function indicating connection failure + * @param[in] NONE + * @return Error code. + * @author + * @date + * @version 1.0 + */ +static WILC_Sint32 Handle_ConnectTimeout(void *drvHandler) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrConnectInfo strConnectInfo; + tstrWID strWID; + WILC_Uint16 u16DummyReasonCode = 0; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *) drvHandler; + + if (pstrWFIDrv == NULL) { + PRINT_ER("Driver handler is NULL\n"); + return s32Error; + } + + pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE; + + gbScanWhileConnected = WILC_FALSE; + + + WILC_memset(&strConnectInfo, 0, sizeof(tstrConnectInfo)); + + + /* First, we will notify the upper layer with the Connection failure {through the Connect Callback function}, + * then we will notify our firmware also with the Connection failure {through sending to it Cfg packet carrying + * WID_DISCONNECT} */ + if (pstrWFIDrv->strWILC_UsrConnReq.pfUserConnectResult != NULL) { + if (pstrWFIDrv->strWILC_UsrConnReq.pu8bssid != NULL) { + WILC_memcpy(strConnectInfo.au8bssid, + pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, 6); + } + + if (pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) { + strConnectInfo.ReqIEsLen = pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen; + strConnectInfo.pu8ReqIEs = (WILC_Uint8 *)WILC_MALLOC(pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen); + WILC_memcpy(strConnectInfo.pu8ReqIEs, + pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs, + pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen); + } + + pstrWFIDrv->strWILC_UsrConnReq.pfUserConnectResult(CONN_DISCONN_EVENT_CONN_RESP, + &strConnectInfo, + MAC_DISCONNECTED, + NULL, + pstrWFIDrv->strWILC_UsrConnReq.u32UserConnectPvoid); + + /* Deallocation of strConnectInfo.pu8ReqIEs */ + if (strConnectInfo.pu8ReqIEs != NULL) { + WILC_FREE(strConnectInfo.pu8ReqIEs); + strConnectInfo.pu8ReqIEs = NULL; + } + } else { + PRINT_ER("Connect callback function pointer is NULL \n"); + } + + /* Here we will notify our firmware also with the Connection failure {through sending to it Cfg packet carrying + * WID_DISCONNECT} */ + strWID.u16WIDid = (WILC_Uint16)WID_DISCONNECT; + strWID.enuWIDtype = WID_CHAR; + strWID.ps8WidVal = (WILC_Sint8 *)&u16DummyReasonCode; + strWID.s32ValueSize = sizeof(WILC_Char); + + PRINT_D(HOSTINF_DBG, "Sending disconnect request\n"); + + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_FALSE, (WILC_Uint32)pstrWFIDrv); + if (s32Error) { + PRINT_ER("Failed to send dissconect config packet\n"); + } + + /* Deallocation of the Saved Connect Request in the global Handle */ + pstrWFIDrv->strWILC_UsrConnReq.ssidLen = 0; + if (pstrWFIDrv->strWILC_UsrConnReq.pu8ssid != NULL) { + WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid); + pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = NULL; + } + + if (pstrWFIDrv->strWILC_UsrConnReq.pu8bssid != NULL) { + WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid); + pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = NULL; + } + + pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen = 0; + if (pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) { + WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs); + pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = NULL; + } + + WILC_memset(u8ConnectedSSID, 0, ETH_ALEN); + /*BugID_5213*/ + /*Freeing flushed join request params on connect timeout*/ + if (gu8FlushedJoinReq != NULL && gu8FlushedJoinReqDrvHandler == (WILC_Uint32)drvHandler) { + WILC_FREE(gu8FlushedJoinReq); + gu8FlushedJoinReq = NULL; + } + if (gu8FlushedInfoElemAsoc != NULL && gu8FlushedJoinReqDrvHandler == (WILC_Uint32)drvHandler) { + WILC_FREE(gu8FlushedInfoElemAsoc); + gu8FlushedInfoElemAsoc = NULL; + } + + return s32Error; +} + +/** + * @brief Handle_RcvdNtwrkInfo + * @details Handling received network information + * @param[in] tstrRcvdNetworkInfo* pstrRcvdNetworkInfo + * @return Error code. + * @author + * @date + * @version 1.0 + */ +static WILC_Sint32 Handle_RcvdNtwrkInfo(void *drvHandler, tstrRcvdNetworkInfo *pstrRcvdNetworkInfo) +{ + WILC_Uint32 i; + WILC_Bool bNewNtwrkFound; + + + + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrNetworkInfo *pstrNetworkInfo = NULL; + void *pJoinParams = NULL; + + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + + + bNewNtwrkFound = WILC_TRUE; + PRINT_INFO(HOSTINF_DBG, "Handling received network info\n"); + + /*if there is a an ongoing scan request*/ + if (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult) { + PRINT_D(HOSTINF_DBG, "State: Scanning, parsing network information received\n"); + ParseNetworkInfo(pstrRcvdNetworkInfo->pu8Buffer, &pstrNetworkInfo); + if ((pstrNetworkInfo == NULL) + || (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult == WILC_NULL)) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + /* check whether this network is discovered before */ + for (i = 0; i < pstrWFIDrv->strWILC_UsrScanReq.u32RcvdChCount; i++) { + + if ((pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[i].au8bssid != NULL) && + (pstrNetworkInfo->au8bssid != NULL)) { + if (WILC_memcmp(pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[i].au8bssid, + pstrNetworkInfo->au8bssid, 6) == 0) { + if (pstrNetworkInfo->s8rssi <= pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[i].s8rssi) { + /*we have already found this network with better rssi, so keep the old cached one and don't + * send anything to the upper layer */ + PRINT_D(HOSTINF_DBG, "Network previously discovered\n"); + goto done; + } else { + /* here the same already found network is found again but with a better rssi, so just update + * the rssi for this cached network and send this updated network to the upper layer but + * don't add a new record for it */ + pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[i].s8rssi = pstrNetworkInfo->s8rssi; + bNewNtwrkFound = WILC_FALSE; + break; + } + } + } + } + + if (bNewNtwrkFound == WILC_TRUE) { + /* here it is confirmed that it is a new discovered network, + * so add its record then call the User CallBack function */ + + PRINT_D(HOSTINF_DBG, "New network found\n"); + + if (pstrWFIDrv->strWILC_UsrScanReq.u32RcvdChCount < MAX_NUM_SCANNED_NETWORKS) { + pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[pstrWFIDrv->strWILC_UsrScanReq.u32RcvdChCount].s8rssi = pstrNetworkInfo->s8rssi; + + if ((pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[pstrWFIDrv->strWILC_UsrScanReq.u32RcvdChCount].au8bssid != NULL) + && (pstrNetworkInfo->au8bssid != NULL)) { + WILC_memcpy(pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[pstrWFIDrv->strWILC_UsrScanReq.u32RcvdChCount].au8bssid, + pstrNetworkInfo->au8bssid, 6); + + pstrWFIDrv->strWILC_UsrScanReq.u32RcvdChCount++; + + pstrNetworkInfo->bNewNetwork = WILC_TRUE; + /*Bug4218: Parsing Join Param*/ + /* add new BSS to JoinBssTable */ + #ifdef WILC_PARSE_SCAN_IN_HOST + pJoinParams = host_int_ParseJoinBssParam(pstrNetworkInfo); + #endif /*WILC_PARSE_SCAN_IN_HOST*/ + + pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult(SCAN_EVENT_NETWORK_FOUND, pstrNetworkInfo, + pstrWFIDrv->strWILC_UsrScanReq.u32UserScanPvoid, + pJoinParams); + + + } + } else { + PRINT_WRN(HOSTINF_DBG, "Discovered networks exceeded max. limit \n"); + } + } else { + pstrNetworkInfo->bNewNetwork = WILC_FALSE; + /* just call the User CallBack function to send the same discovered network with its updated RSSI */ + pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult(SCAN_EVENT_NETWORK_FOUND, pstrNetworkInfo, + pstrWFIDrv->strWILC_UsrScanReq.u32UserScanPvoid, NULL); + } + } + + + WILC_CATCH(s32Error) + { + + } + +done: + /* Deallocate pstrRcvdNetworkInfo->pu8Buffer which was prevoisuly allocated by the sending thread */ + if (pstrRcvdNetworkInfo->pu8Buffer != NULL) { + WILC_FREE(pstrRcvdNetworkInfo->pu8Buffer); + pstrRcvdNetworkInfo->pu8Buffer = NULL; + } + + /*free structure allocated*/ + if (pstrNetworkInfo != WILC_NULL) { + DeallocateNetworkInfo(pstrNetworkInfo); + pstrNetworkInfo = WILC_NULL; + } + + return s32Error; +} + +/** + * @brief Handle_RcvdGnrlAsyncInfo + * @details Handling received asynchrous general network information + * @param[in] tstrRcvdGnrlAsyncInfo* pstrRcvdGnrlAsyncInfo + * @return Error code. + * @author + * @date + * @version 1.0 + */ +static WILC_Sint32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pstrRcvdGnrlAsyncInfo) +{ + /* TODO: mostafa: till now, this function just handles only the received mac status msg, */ + /* which carries only 1 WID which have WID ID = WID_STATUS */ + WILC_Sint32 s32Error = WILC_SUCCESS; + WILC_Uint8 u8MsgType = 0; + WILC_Uint8 u8MsgID = 0; + WILC_Uint16 u16MsgLen = 0; + WILC_Uint16 u16WidID = (WILC_Uint16)WID_NIL; + WILC_Uint8 u8WidLen = 0; + WILC_Uint8 u8MacStatus; + WILC_Uint8 u8MacStatusReasonCode; + WILC_Uint8 u8MacStatusAdditionalInfo; + tstrConnectInfo strConnectInfo; + tstrDisconnectNotifInfo strDisconnectNotifInfo; + WILC_Sint32 s32Err = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *) drvHandler; + if (pstrWFIDrv == NULL) { + PRINT_ER("Driver handler is NULL\n"); + } + PRINT_D(GENERIC_DBG, "Current State = %d,Received state = %d\n", pstrWFIDrv->enuHostIFstate, + pstrRcvdGnrlAsyncInfo->pu8Buffer[7]); + + if ((pstrWFIDrv->enuHostIFstate == HOST_IF_WAITING_CONN_RESP) || + (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTED) || + pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult) { + if ((pstrRcvdGnrlAsyncInfo->pu8Buffer == NULL) || + (pstrWFIDrv->strWILC_UsrConnReq.pfUserConnectResult == WILC_NULL)) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + u8MsgType = pstrRcvdGnrlAsyncInfo->pu8Buffer[0]; + + /* Check whether the received message type is 'I' */ + if ('I' != u8MsgType) { + PRINT_ER("Received Message format incorrect.\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + + /* Extract message ID */ + u8MsgID = pstrRcvdGnrlAsyncInfo->pu8Buffer[1]; + + /* Extract message Length */ + u16MsgLen = MAKE_WORD16(pstrRcvdGnrlAsyncInfo->pu8Buffer[2], pstrRcvdGnrlAsyncInfo->pu8Buffer[3]); + + /* Extract WID ID [expected to be = WID_STATUS] */ + u16WidID = MAKE_WORD16(pstrRcvdGnrlAsyncInfo->pu8Buffer[4], pstrRcvdGnrlAsyncInfo->pu8Buffer[5]); + + /* Extract WID Length [expected to be = 1] */ + u8WidLen = pstrRcvdGnrlAsyncInfo->pu8Buffer[6]; + + /* get the WID value [expected to be one of two values: either MAC_CONNECTED = (1) or MAC_DISCONNECTED = (0)] */ + u8MacStatus = pstrRcvdGnrlAsyncInfo->pu8Buffer[7]; + u8MacStatusReasonCode = pstrRcvdGnrlAsyncInfo->pu8Buffer[8]; + u8MacStatusAdditionalInfo = pstrRcvdGnrlAsyncInfo->pu8Buffer[9]; + PRINT_INFO(HOSTINF_DBG, "Recieved MAC status = %d with Reason = %d , Info = %d\n", u8MacStatus, u8MacStatusReasonCode, u8MacStatusAdditionalInfo); + if (pstrWFIDrv->enuHostIFstate == HOST_IF_WAITING_CONN_RESP) { + /* our station had sent Association Request frame, so here it will get the Association Response frame then parse it */ + WILC_Uint32 u32RcvdAssocRespInfoLen; + tstrConnectRespInfo *pstrConnectRespInfo = NULL; + + PRINT_D(HOSTINF_DBG, "Recieved MAC status = %d with Reason = %d , Code = %d\n", u8MacStatus, u8MacStatusReasonCode, u8MacStatusAdditionalInfo); + + WILC_memset(&strConnectInfo, 0, sizeof(tstrConnectInfo)); + + if (u8MacStatus == MAC_CONNECTED) { + WILC_memset(gapu8RcvdAssocResp, 0, MAX_ASSOC_RESP_FRAME_SIZE); + + host_int_get_assoc_res_info((WILC_WFIDrvHandle)pstrWFIDrv, + gapu8RcvdAssocResp, + MAX_ASSOC_RESP_FRAME_SIZE, + &u32RcvdAssocRespInfoLen); + + PRINT_INFO(HOSTINF_DBG, "Received association response with length = %d\n", u32RcvdAssocRespInfoLen); + + if (u32RcvdAssocRespInfoLen != 0) { + + PRINT_D(HOSTINF_DBG, "Parsing association response\n"); + s32Err = ParseAssocRespInfo(gapu8RcvdAssocResp, u32RcvdAssocRespInfoLen, + &pstrConnectRespInfo); + if (s32Err) { + PRINT_ER("ParseAssocRespInfo() returned error %d \n", s32Err); + } else { + /* use the necessary parsed Info from the Received Association Response */ + strConnectInfo.u16ConnectStatus = pstrConnectRespInfo->u16ConnectStatus; + + if (strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE) { + PRINT_INFO(HOSTINF_DBG, "Association response received : Successful connection status\n"); + if (pstrConnectRespInfo->pu8RespIEs != NULL) { + strConnectInfo.u16RespIEsLen = pstrConnectRespInfo->u16RespIEsLen; + + + strConnectInfo.pu8RespIEs = (WILC_Uint8 *)WILC_MALLOC(pstrConnectRespInfo->u16RespIEsLen); + WILC_memcpy(strConnectInfo.pu8RespIEs, pstrConnectRespInfo->pu8RespIEs, + pstrConnectRespInfo->u16RespIEsLen); + } + } + + /* deallocate the Assoc. Resp. parsed structure as it is not needed anymore */ + if (pstrConnectRespInfo != NULL) { + DeallocateAssocRespInfo(pstrConnectRespInfo); + pstrConnectRespInfo = NULL; + } + } + } + } + + /* The station has just received mac status and it also received assoc. response which + * it was waiting for. + * So check first the matching between the received mac status and the received status code in Asoc Resp */ + if ((u8MacStatus == MAC_CONNECTED) && + (strConnectInfo.u16ConnectStatus != SUCCESSFUL_STATUSCODE)) { + PRINT_ER("Received MAC status is MAC_CONNECTED while the received status code in Asoc Resp is not SUCCESSFUL_STATUSCODE \n"); + WILC_memset(u8ConnectedSSID, 0, ETH_ALEN); + + } else if (u8MacStatus == MAC_DISCONNECTED) { + PRINT_ER("Received MAC status is MAC_DISCONNECTED\n"); + WILC_memset(u8ConnectedSSID, 0, ETH_ALEN); + } + + /* TODO: mostafa: correct BSSID should be retrieved from actual BSSID received from AP */ + /* through a structure of type tstrConnectRespInfo */ + if (pstrWFIDrv->strWILC_UsrConnReq.pu8bssid != NULL) { + PRINT_D(HOSTINF_DBG, "Retrieving actual BSSID from AP\n"); + WILC_memcpy(strConnectInfo.au8bssid, pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, 6); + + if ((u8MacStatus == MAC_CONNECTED) && + (strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE)) { + WILC_memcpy(pstrWFIDrv->au8AssociatedBSSID, + pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, ETH_ALEN); + } + } + + + if (pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) { + strConnectInfo.ReqIEsLen = pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen; + strConnectInfo.pu8ReqIEs = (WILC_Uint8 *)WILC_MALLOC(pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen); + WILC_memcpy(strConnectInfo.pu8ReqIEs, + pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs, + pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen); + } + + + WILC_TimerStop(&(pstrWFIDrv->hConnectTimer), WILC_NULL); + pstrWFIDrv->strWILC_UsrConnReq.pfUserConnectResult(CONN_DISCONN_EVENT_CONN_RESP, + &strConnectInfo, + u8MacStatus, + NULL, + pstrWFIDrv->strWILC_UsrConnReq.u32UserConnectPvoid); + + + /* if received mac status is MAC_CONNECTED and + * received status code in Asoc Resp is SUCCESSFUL_STATUSCODE, change state to CONNECTED + * else change state to IDLE */ + if ((u8MacStatus == MAC_CONNECTED) && + (strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE)) { + #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP + + host_int_set_power_mgmt((WILC_WFIDrvHandle)pstrWFIDrv, 0, 0); + #endif + + PRINT_D(HOSTINF_DBG, "MAC status : CONNECTED and Connect Status : Successful\n"); + pstrWFIDrv->enuHostIFstate = HOST_IF_CONNECTED; + + #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP + PRINT_D(GENERIC_DBG, "Obtaining an IP, Disable Scan\n"); + g_obtainingIP = WILC_TRUE; + WILC_TimerStart(&hDuringIpTimer, 10000, WILC_NULL, WILC_NULL); + #endif + + #ifdef WILC_PARSE_SCAN_IN_HOST + /* open a BA session if possible */ + /* if(pstrWFIDrv->strWILC_UsrConnReq.IsHTCapable) */ + + #endif + + /* host_int_addBASession(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid,0, */ + /* BA_SESSION_DEFAULT_BUFFER_SIZE,BA_SESSION_DEFAULT_TIMEOUT); */ + } else { + PRINT_D(HOSTINF_DBG, "MAC status : %d and Connect Status : %d\n", u8MacStatus, strConnectInfo.u16ConnectStatus); + pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE; + gbScanWhileConnected = WILC_FALSE; + } + + /* Deallocation */ + if (strConnectInfo.pu8RespIEs != NULL) { + WILC_FREE(strConnectInfo.pu8RespIEs); + strConnectInfo.pu8RespIEs = NULL; + } + + if (strConnectInfo.pu8ReqIEs != NULL) { + WILC_FREE(strConnectInfo.pu8ReqIEs); + strConnectInfo.pu8ReqIEs = NULL; + } + + + pstrWFIDrv->strWILC_UsrConnReq.ssidLen = 0; + if (pstrWFIDrv->strWILC_UsrConnReq.pu8ssid != NULL) { + WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid); + pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = NULL; + } + + if (pstrWFIDrv->strWILC_UsrConnReq.pu8bssid != NULL) { + WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid); + pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = NULL; + } + + pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen = 0; + if (pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) { + WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs); + pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = NULL; + } + + } else if ((u8MacStatus == MAC_DISCONNECTED) && + (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTED)) { + /* Disassociation or Deauthentication frame has been received */ + PRINT_D(HOSTINF_DBG, "Received MAC_DISCONNECTED from the FW\n"); + + WILC_memset(&strDisconnectNotifInfo, 0, sizeof(tstrDisconnectNotifInfo)); + + if (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult) { + PRINT_D(HOSTINF_DBG, "\n\n<< Abort the running OBSS Scan >> \n\n"); + WILC_TimerStop(&(pstrWFIDrv->hScanTimer), WILC_NULL); + Handle_ScanDone((void *)pstrWFIDrv, SCAN_EVENT_ABORTED); + } + + strDisconnectNotifInfo.u16reason = 0; + strDisconnectNotifInfo.ie = NULL; + strDisconnectNotifInfo.ie_len = 0; + + if (pstrWFIDrv->strWILC_UsrConnReq.pfUserConnectResult != NULL) { + #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP + + g_obtainingIP = WILC_FALSE; + host_int_set_power_mgmt((WILC_WFIDrvHandle)pstrWFIDrv, 0, 0); + #endif + + pstrWFIDrv->strWILC_UsrConnReq.pfUserConnectResult(CONN_DISCONN_EVENT_DISCONN_NOTIF, + NULL, + 0, + &strDisconnectNotifInfo, + pstrWFIDrv->strWILC_UsrConnReq.u32UserConnectPvoid); + + } else { + PRINT_ER("Connect result callback function is NULL \n"); + } + + WILC_memset(pstrWFIDrv->au8AssociatedBSSID, 0, ETH_ALEN); + + + /* Deallocation */ + + /* if Information Elements were retrieved from the Received deauth/disassoc frame, then they + * should be deallocated here */ + /* + * if(strDisconnectNotifInfo.ie != NULL) + * { + * WILC_FREE(strDisconnectNotifInfo.ie); + * strDisconnectNotifInfo.ie = NULL; + * } + */ + + pstrWFIDrv->strWILC_UsrConnReq.ssidLen = 0; + if (pstrWFIDrv->strWILC_UsrConnReq.pu8ssid != NULL) { + WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid); + pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = NULL; + } + + if (pstrWFIDrv->strWILC_UsrConnReq.pu8bssid != NULL) { + WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid); + pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = NULL; + } + + pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen = 0; + if (pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) { + WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs); + pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = NULL; + } + + /*BugID_5213*/ + /*Freeing flushed join request params on receiving*/ + /*MAC_DISCONNECTED while connected*/ + if (gu8FlushedJoinReq != NULL && gu8FlushedJoinReqDrvHandler == (WILC_Uint32)drvHandler) { + WILC_FREE(gu8FlushedJoinReq); + gu8FlushedJoinReq = NULL; + } + if (gu8FlushedInfoElemAsoc != NULL && gu8FlushedJoinReqDrvHandler == (WILC_Uint32)drvHandler) { + WILC_FREE(gu8FlushedInfoElemAsoc); + gu8FlushedInfoElemAsoc = NULL; + } + + pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE; + gbScanWhileConnected = WILC_FALSE; + + } else if ((u8MacStatus == MAC_DISCONNECTED) && + (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult != NULL)) { + PRINT_D(HOSTINF_DBG, "Received MAC_DISCONNECTED from the FW while scanning\n"); + PRINT_D(HOSTINF_DBG, "\n\n<< Abort the running Scan >> \n\n"); + /*Abort the running scan*/ + WILC_TimerStop(&(pstrWFIDrv->hScanTimer), WILC_NULL); + if (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult) { + Handle_ScanDone((void *)pstrWFIDrv, SCAN_EVENT_ABORTED); + + } + } + + } + + WILC_CATCH(s32Error) + { + + } + + /* Deallocate pstrRcvdGnrlAsyncInfo->pu8Buffer which was prevoisuly allocated by the sending thread */ + if (pstrRcvdGnrlAsyncInfo->pu8Buffer != NULL) { + WILC_FREE(pstrRcvdGnrlAsyncInfo->pu8Buffer); + pstrRcvdGnrlAsyncInfo->pu8Buffer = NULL; + } + + return s32Error; +} + +/** + * @brief Handle_Key + * @details Sending config packet to firmware to set key + * @param[in] tstrHostIFkeyAttr* pstrHostIFkeyAttr + * @return Error code. + * @author + * @date + * @version 1.0 + */ +static int Handle_Key(void *drvHandler, tstrHostIFkeyAttr *pstrHostIFkeyAttr) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + #ifdef WILC_AP_EXTERNAL_MLME + tstrWID strWIDList[5]; + #endif + WILC_Uint8 i; + WILC_Uint8 *pu8keybuf; + WILC_Sint8 s8idxarray[1]; + WILC_Sint8 ret = 0; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + + switch (pstrHostIFkeyAttr->enuKeyType) { + + + case WEP: + +#ifdef WILC_AP_EXTERNAL_MLME + if (pstrHostIFkeyAttr->u8KeyAction & ADDKEY_AP) { + + PRINT_D(HOSTINF_DBG, "Handling WEP key\n"); + PRINT_D(GENERIC_DBG, "ID Hostint is %d\n", (pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8Wepidx)); + strWIDList[0].u16WIDid = (WILC_Uint16)WID_11I_MODE; + strWIDList[0].enuWIDtype = WID_CHAR; + strWIDList[0].s32ValueSize = sizeof(WILC_Char); + strWIDList[0].ps8WidVal = (WILC_Sint8 *)(&(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8mode)); + + strWIDList[1].u16WIDid = WID_AUTH_TYPE; + strWIDList[1].enuWIDtype = WID_CHAR; + strWIDList[1].s32ValueSize = sizeof(WILC_Char); + strWIDList[1].ps8WidVal = (WILC_Sint8 *)(&(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.tenuAuth_type)); + + strWIDList[2].u16WIDid = (WILC_Uint16)WID_KEY_ID; + strWIDList[2].enuWIDtype = WID_CHAR; + + strWIDList[2].ps8WidVal = (WILC_Sint8 *)(&(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8Wepidx)); + strWIDList[2].s32ValueSize = sizeof(WILC_Char); + + + pu8keybuf = (WILC_Uint8 *)WILC_MALLOC(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen); + + + if (pu8keybuf == NULL) { + PRINT_ER("No buffer to send Key\n"); + return -1; + } + + WILC_memcpy(pu8keybuf, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey, + pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen); + + + WILC_FREE(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey); + + strWIDList[3].u16WIDid = (WILC_Uint16)WID_WEP_KEY_VALUE; + strWIDList[3].enuWIDtype = WID_STR; + strWIDList[3].s32ValueSize = pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen; + strWIDList[3].ps8WidVal = (WILC_Sint8 *)pu8keybuf; + + + s32Error = SendConfigPkt(SET_CFG, strWIDList, 4, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + WILC_FREE(pu8keybuf); + + + } +#endif + + if (pstrHostIFkeyAttr->u8KeyAction & ADDKEY) { + PRINT_D(HOSTINF_DBG, "Handling WEP key\n"); + pu8keybuf = (WILC_Uint8 *)WILC_MALLOC(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen + 2); + if (pu8keybuf == NULL) { + PRINT_ER("No buffer to send Key\n"); + return -1; + } + pu8keybuf[0] = pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8Wepidx; + + WILC_memcpy(pu8keybuf + 1, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen, 1); + + WILC_memcpy(pu8keybuf + 2, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey, + pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen); + + WILC_FREE(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey); + + strWID.u16WIDid = (WILC_Uint16)WID_ADD_WEP_KEY; + strWID.enuWIDtype = WID_STR; + strWID.ps8WidVal = (WILC_Sint8 *)pu8keybuf; + strWID.s32ValueSize = pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen + 2; + + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + WILC_FREE(pu8keybuf); + } else if (pstrHostIFkeyAttr->u8KeyAction & REMOVEKEY) { + + PRINT_D(HOSTINF_DBG, "Removing key\n"); + strWID.u16WIDid = (WILC_Uint16)WID_REMOVE_WEP_KEY; + strWID.enuWIDtype = WID_STR; + + s8idxarray[0] = (WILC_Sint8)pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8Wepidx; + strWID.ps8WidVal = s8idxarray; + strWID.s32ValueSize = 1; + + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + } else { + strWID.u16WIDid = (WILC_Uint16)WID_KEY_ID; + strWID.enuWIDtype = WID_CHAR; + strWID.ps8WidVal = (WILC_Sint8 *)(&(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8Wepidx)); + strWID.s32ValueSize = sizeof(WILC_Char); + + PRINT_D(HOSTINF_DBG, "Setting default key index\n"); + + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + } + WILC_SemaphoreRelease(&(pstrWFIDrv->hSemTestKeyBlock), WILC_NULL); + break; + + case WPARxGtk: + #ifdef WILC_AP_EXTERNAL_MLME + if (pstrHostIFkeyAttr->u8KeyAction & ADDKEY_AP) { + pu8keybuf = (WILC_Uint8 *)WILC_MALLOC(RX_MIC_KEY_MSG_LEN); + if (pu8keybuf == NULL) { + PRINT_ER("No buffer to send RxGTK Key\n"); + ret = -1; + goto _WPARxGtk_end_case_; + } + + WILC_memset(pu8keybuf, 0, RX_MIC_KEY_MSG_LEN); + + + /*|----------------------------------------------------------------------------| + * |Sta Address | Key RSC | KeyID | Key Length | Temporal Key | Rx Michael Key | + * |------------|---------|-------|------------|---------------|----------------| + | 6 bytes | 8 byte |1 byte | 1 byte | 16 bytes | 8 bytes |*/ + + + + if (pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq != NULL) + WILC_memcpy(pu8keybuf + 6, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq, 8); + + + WILC_memcpy(pu8keybuf + 14, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8keyidx, 1); + + WILC_memcpy(pu8keybuf + 15, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen, 1); + + WILC_memcpy(pu8keybuf + 16, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key, + pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen); + /* pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Ciphermode = 0X51; */ + strWIDList[0].u16WIDid = (WILC_Uint16)WID_11I_MODE; + strWIDList[0].enuWIDtype = WID_CHAR; + strWIDList[0].s32ValueSize = sizeof(WILC_Char); + strWIDList[0].ps8WidVal = (WILC_Sint8 *)(&(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Ciphermode)); + + strWIDList[1].u16WIDid = (WILC_Uint16)WID_ADD_RX_GTK; + strWIDList[1].enuWIDtype = WID_STR; + strWIDList[1].ps8WidVal = (WILC_Sint8 *)pu8keybuf; + strWIDList[1].s32ValueSize = RX_MIC_KEY_MSG_LEN; + + s32Error = SendConfigPkt(SET_CFG, strWIDList, 2, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + + WILC_FREE(pu8keybuf); + + /* ////////////////////////// */ + WILC_SemaphoreRelease(&(pstrWFIDrv->hSemTestKeyBlock), WILC_NULL); + /* ///////////////////////// */ + } + + #endif + if (pstrHostIFkeyAttr->u8KeyAction & ADDKEY) { + PRINT_D(HOSTINF_DBG, "Handling group key(Rx) function\n"); + + pu8keybuf = (WILC_Uint8 *)WILC_MALLOC(RX_MIC_KEY_MSG_LEN); + if (pu8keybuf == NULL) { + PRINT_ER("No buffer to send RxGTK Key\n"); + ret = -1; + goto _WPARxGtk_end_case_; + } + + WILC_memset(pu8keybuf, 0, RX_MIC_KEY_MSG_LEN); + + + /*|----------------------------------------------------------------------------| + * |Sta Address | Key RSC | KeyID | Key Length | Temporal Key | Rx Michael Key | + * |------------|---------|-------|------------|---------------|----------------| + | 6 bytes | 8 byte |1 byte | 1 byte | 16 bytes | 8 bytes |*/ + + if (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTED) { + WILC_memcpy(pu8keybuf, pstrWFIDrv->au8AssociatedBSSID, ETH_ALEN); + } else { + PRINT_ER("Couldn't handle WPARxGtk while enuHostIFstate is not HOST_IF_CONNECTED \n"); + } + + WILC_memcpy(pu8keybuf + 6, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq, 8); + + WILC_memcpy(pu8keybuf + 14, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8keyidx, 1); + + WILC_memcpy(pu8keybuf + 15, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen, 1); + WILC_memcpy(pu8keybuf + 16, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key, + pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen); + + strWID.u16WIDid = (WILC_Uint16)WID_ADD_RX_GTK; + strWID.enuWIDtype = WID_STR; + strWID.ps8WidVal = (WILC_Sint8 *)pu8keybuf; + strWID.s32ValueSize = RX_MIC_KEY_MSG_LEN; + + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + + WILC_FREE(pu8keybuf); + + /* ////////////////////////// */ + WILC_SemaphoreRelease(&(pstrWFIDrv->hSemTestKeyBlock), WILC_NULL); + /* ///////////////////////// */ + } +_WPARxGtk_end_case_: + WILC_FREE(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key); + WILC_FREE(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq); + if (ret == -1) + return ret; + + break; + + case WPAPtk: + #ifdef WILC_AP_EXTERNAL_MLME + if (pstrHostIFkeyAttr->u8KeyAction & ADDKEY_AP) { + + + pu8keybuf = (WILC_Uint8 *)WILC_MALLOC(PTK_KEY_MSG_LEN + 1); + + + + if (pu8keybuf == NULL) { + PRINT_ER("No buffer to send PTK Key\n"); + ret = -1; + goto _WPAPtk_end_case_; + + } + + /*|-----------------------------------------------------------------------------| + * |Station address | keyidx |Key Length |Temporal Key | Rx Michael Key |Tx Michael Key | + * |----------------|------------ |--------------|----------------|---------------| + | 6 bytes | 1 byte | 1byte | 16 bytes | 8 bytes | 8 bytes | + |-----------------------------------------------------------------------------|*/ + + WILC_memcpy(pu8keybuf, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8macaddr, 6); /*1 bytes Key Length */ + + WILC_memcpy(pu8keybuf + 6, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8keyidx, 1); + WILC_memcpy(pu8keybuf + 7, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen, 1); + /*16 byte TK*/ + WILC_memcpy(pu8keybuf + 8, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key, + pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen); + + + strWIDList[0].u16WIDid = (WILC_Uint16)WID_11I_MODE; + strWIDList[0].enuWIDtype = WID_CHAR; + strWIDList[0].s32ValueSize = sizeof(WILC_Char); + strWIDList[0].ps8WidVal = (WILC_Sint8 *)(&(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Ciphermode)); + + strWIDList[1].u16WIDid = (WILC_Uint16)WID_ADD_PTK; + strWIDList[1].enuWIDtype = WID_STR; + strWIDList[1].ps8WidVal = (WILC_Sint8 *)pu8keybuf; + strWIDList[1].s32ValueSize = PTK_KEY_MSG_LEN + 1; + + s32Error = SendConfigPkt(SET_CFG, strWIDList, 2, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + WILC_FREE(pu8keybuf); + + /* ////////////////////////// */ + WILC_SemaphoreRelease(&(pstrWFIDrv->hSemTestKeyBlock), WILC_NULL); + /* ///////////////////////// */ + } + #endif + if (pstrHostIFkeyAttr->u8KeyAction & ADDKEY) { + + + pu8keybuf = (WILC_Uint8 *)WILC_MALLOC(PTK_KEY_MSG_LEN); + + + + if (pu8keybuf == NULL) { + PRINT_ER("No buffer to send PTK Key\n"); + ret = -1; + goto _WPAPtk_end_case_; + + } + + /*|-----------------------------------------------------------------------------| + * |Station address | Key Length | Temporal Key | Rx Michael Key |Tx Michael Key | + * |----------------|------------|--------------|----------------|---------------| + | 6 bytes | 1byte | 16 bytes | 8 bytes | 8 bytes | + |-----------------------------------------------------------------------------|*/ + + WILC_memcpy(pu8keybuf, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8macaddr, 6); /*1 bytes Key Length */ + + WILC_memcpy(pu8keybuf + 6, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen, 1); + /*16 byte TK*/ + WILC_memcpy(pu8keybuf + 7, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key, + pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen); + + + strWID.u16WIDid = (WILC_Uint16)WID_ADD_PTK; + strWID.enuWIDtype = WID_STR; + strWID.ps8WidVal = (WILC_Sint8 *)pu8keybuf; + strWID.s32ValueSize = PTK_KEY_MSG_LEN; + + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + WILC_FREE(pu8keybuf); + + /* ////////////////////////// */ + WILC_SemaphoreRelease(&(pstrWFIDrv->hSemTestKeyBlock), WILC_NULL); + /* ///////////////////////// */ + } + +_WPAPtk_end_case_: + WILC_FREE(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key); + if (ret == -1) + return ret; + + break; + + + case PMKSA: + + PRINT_D(HOSTINF_DBG, "Handling PMKSA key\n"); + + pu8keybuf = (WILC_Uint8 *)WILC_MALLOC((pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.numpmkid * PMKSA_KEY_LEN) + 1); + if (pu8keybuf == NULL) { + PRINT_ER("No buffer to send PMKSA Key\n"); + return -1; + } + + pu8keybuf[0] = pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.numpmkid; + + for (i = 0; i < pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.numpmkid; i++) { + + WILC_memcpy(pu8keybuf + ((PMKSA_KEY_LEN * i) + 1), pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.pmkidlist[i].bssid, ETH_ALEN); + WILC_memcpy(pu8keybuf + ((PMKSA_KEY_LEN * i) + ETH_ALEN + 1), pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.pmkidlist[i].pmkid, PMKID_LEN); + } + + strWID.u16WIDid = (WILC_Uint16)WID_PMKID_INFO; + strWID.enuWIDtype = WID_STR; + strWID.ps8WidVal = (WILC_Sint8 *)pu8keybuf; + strWID.s32ValueSize = (pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.numpmkid * PMKSA_KEY_LEN) + 1; + + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + + WILC_FREE(pu8keybuf); + break; + } + + if (s32Error) + PRINT_ER("Failed to send key config packet\n"); + + + return s32Error; +} + + +/** + * @brief Handle_Disconnect + * @details Sending config packet to firmware to disconnect + * @param[in] NONE + * @return NONE + * @author + * @date + * @version 1.0 + */ +static void Handle_Disconnect(void *drvHandler) +{ + tstrWID strWID; + + WILC_Sint32 s32Error = WILC_SUCCESS; + WILC_Uint16 u16DummyReasonCode = 0; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + + strWID.u16WIDid = (WILC_Uint16)WID_DISCONNECT; + strWID.enuWIDtype = WID_CHAR; + strWID.ps8WidVal = (WILC_Sint8 *)&u16DummyReasonCode; + strWID.s32ValueSize = sizeof(WILC_Char); + + + + PRINT_D(HOSTINF_DBG, "Sending disconnect request\n"); + + #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP + + g_obtainingIP = WILC_FALSE; + host_int_set_power_mgmt((WILC_WFIDrvHandle)pstrWFIDrv, 0, 0); + #endif + + WILC_memset(u8ConnectedSSID, 0, ETH_ALEN); + + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_FALSE, (WILC_Uint32)pstrWFIDrv); + + if (s32Error) { + PRINT_ER("Failed to send dissconect config packet\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } else { + tstrDisconnectNotifInfo strDisconnectNotifInfo; + + WILC_memset(&strDisconnectNotifInfo, 0, sizeof(tstrDisconnectNotifInfo)); + + strDisconnectNotifInfo.u16reason = 0; + strDisconnectNotifInfo.ie = NULL; + strDisconnectNotifInfo.ie_len = 0; + + if (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult) { + WILC_TimerStop(&(pstrWFIDrv->hScanTimer), WILC_NULL); + pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult(SCAN_EVENT_ABORTED, WILC_NULL, + pstrWFIDrv->strWILC_UsrScanReq.u32UserScanPvoid, NULL); + + pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult = WILC_NULL; + } + + if (pstrWFIDrv->strWILC_UsrConnReq.pfUserConnectResult != NULL) { + + /*BugID_5193*/ + /*Stop connect timer, if connection in progress*/ + if (pstrWFIDrv->enuHostIFstate == HOST_IF_WAITING_CONN_RESP) { + PRINT_D(HOSTINF_DBG, "Upper layer requested termination of connection\n"); + WILC_TimerStop(&(pstrWFIDrv->hConnectTimer), WILC_NULL); + } + + pstrWFIDrv->strWILC_UsrConnReq.pfUserConnectResult(CONN_DISCONN_EVENT_DISCONN_NOTIF, NULL, + 0, &strDisconnectNotifInfo, pstrWFIDrv->strWILC_UsrConnReq.u32UserConnectPvoid); + } else { + PRINT_ER("strWILC_UsrConnReq.pfUserConnectResult = NULL \n"); + } + + gbScanWhileConnected = WILC_FALSE; + + pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE; + + WILC_memset(pstrWFIDrv->au8AssociatedBSSID, 0, ETH_ALEN); + + + /* Deallocation */ + pstrWFIDrv->strWILC_UsrConnReq.ssidLen = 0; + if (pstrWFIDrv->strWILC_UsrConnReq.pu8ssid != NULL) { + WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid); + pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = NULL; + } + + if (pstrWFIDrv->strWILC_UsrConnReq.pu8bssid != NULL) { + WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid); + pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = NULL; + } + + pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen = 0; + if (pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) { + WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs); + pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = NULL; + } + + + /*BugID_5137*/ + if (gu8FlushedJoinReq != NULL && gu8FlushedJoinReqDrvHandler == (WILC_Uint32)drvHandler) { + WILC_FREE(gu8FlushedJoinReq); + gu8FlushedJoinReq = NULL; + } + if (gu8FlushedInfoElemAsoc != NULL && gu8FlushedJoinReqDrvHandler == (WILC_Uint32)drvHandler) { + WILC_FREE(gu8FlushedInfoElemAsoc); + gu8FlushedInfoElemAsoc = NULL; + } + + } + + WILC_CATCH(s32Error) + { + + } + + /* ////////////////////////// */ + WILC_SemaphoreRelease(&(pstrWFIDrv->hSemTestDisconnectBlock), WILC_NULL); + /* ///////////////////////// */ + +} + + +void resolve_disconnect_aberration(void *drvHandler) +{ + tstrWILC_WFIDrv *pstrWFIDrv; + + pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + if (pstrWFIDrv == WILC_NULL) + return; + if ((pstrWFIDrv->enuHostIFstate == HOST_IF_WAITING_CONN_RESP) || (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTING)) { + PRINT_D(HOSTINF_DBG, "\n\n<< correcting Supplicant state machine >>\n\n"); + host_int_disconnect((WILC_WFIDrvHandle)pstrWFIDrv, 1); + } +} +static WILC_Sint32 Switch_Log_Terminal(void *drvHandler) +{ + + + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + static char dummy = 9; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + strWID.u16WIDid = (WILC_Uint16)WID_LOGTerminal_Switch; + strWID.enuWIDtype = WID_CHAR; + strWID.ps8WidVal = &dummy; + strWID.s32ValueSize = sizeof(WILC_Char); + + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + + + if (s32Error) { + PRINT_D(HOSTINF_DBG, "Failed to switch log terminal\n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_STATE); + } else { + PRINT_INFO(HOSTINF_DBG, "MAC address set :: \n"); + + + } + + WILC_CATCH(s32Error) + { + + } + + return s32Error; +} + +/** + * @brief Handle_GetChnl + * @details Sending config packet to get channel + * @param[in] NONE + * @return NONE + * + * @author + * @date + * @version 1.0 + */ +static WILC_Sint32 Handle_GetChnl(void *drvHandler) +{ + + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */ + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + strWID.u16WIDid = (WILC_Uint16)WID_CURRENT_CHANNEL; + strWID.enuWIDtype = WID_CHAR; + strWID.ps8WidVal = (WILC_Sint8 *)&gu8Chnl; + strWID.s32ValueSize = sizeof(WILC_Char); + + PRINT_D(HOSTINF_DBG, "Getting channel value\n"); + + s32Error = SendConfigPkt(GET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + /*get the value by searching the local copy*/ + if (s32Error) { + PRINT_ER("Failed to get channel number\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + + + WILC_CATCH(s32Error) + { + + } + WILC_SemaphoreRelease(&(pstrWFIDrv->hSemGetCHNL), WILC_NULL); + + return s32Error; + + + +} + + +/** + * @brief Handle_GetRssi + * @details Sending config packet to get RSSI + * @param[in] NONE + * @return NONE + * @author + * @date + * @version 1.0 + */ +static void Handle_GetRssi(void *drvHandler) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + strWID.u16WIDid = (WILC_Uint16)WID_RSSI; + strWID.enuWIDtype = WID_CHAR; + strWID.ps8WidVal = &gs8Rssi; + strWID.s32ValueSize = sizeof(WILC_Char); + + /*Sending Cfg*/ + PRINT_D(HOSTINF_DBG, "Getting RSSI value\n"); + + s32Error = SendConfigPkt(GET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + if (s32Error) { + PRINT_ER("Failed to get RSSI value\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + + WILC_CATCH(s32Error) + { + + } + WILC_SemaphoreRelease(&(pstrWFIDrv->hSemGetRSSI), WILC_NULL); + + +} + + +static void Handle_GetLinkspeed(void *drvHandler) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + gs8lnkspd = 0; + + strWID.u16WIDid = (WILC_Uint16)WID_LINKSPEED; + strWID.enuWIDtype = WID_CHAR; + strWID.ps8WidVal = &gs8lnkspd; + strWID.s32ValueSize = sizeof(WILC_Char); + /*Sending Cfg*/ + PRINT_D(HOSTINF_DBG, "Getting LINKSPEED value\n"); + + s32Error = SendConfigPkt(GET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + if (s32Error) { + PRINT_ER("Failed to get LINKSPEED value\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + + WILC_CATCH(s32Error) + { + + } + WILC_SemaphoreRelease(&(pstrWFIDrv->hSemGetLINKSPEED), WILC_NULL); + + +} + +WILC_Sint32 Handle_GetStatistics(void *drvHandler, tstrStatistics *pstrStatistics) +{ + tstrWID strWIDList[5]; + uint32_t u32WidsCount = 0, s32Error = 0; + + strWIDList[u32WidsCount].u16WIDid = WID_LINKSPEED; + strWIDList[u32WidsCount].enuWIDtype = WID_CHAR; + strWIDList[u32WidsCount].s32ValueSize = sizeof(WILC_Char); + strWIDList[u32WidsCount].ps8WidVal = (WILC_Sint8 *)(&(pstrStatistics->u8LinkSpeed)); + u32WidsCount++; + + strWIDList[u32WidsCount].u16WIDid = WID_RSSI; + strWIDList[u32WidsCount].enuWIDtype = WID_CHAR; + strWIDList[u32WidsCount].s32ValueSize = sizeof(WILC_Char); + strWIDList[u32WidsCount].ps8WidVal = (WILC_Sint8 *)(&(pstrStatistics->s8RSSI)); + u32WidsCount++; + + strWIDList[u32WidsCount].u16WIDid = WID_SUCCESS_FRAME_COUNT; + strWIDList[u32WidsCount].enuWIDtype = WID_INT; + strWIDList[u32WidsCount].s32ValueSize = sizeof(WILC_Uint32); + strWIDList[u32WidsCount].ps8WidVal = (WILC_Sint8 *)(&(pstrStatistics->u32TxCount)); + u32WidsCount++; + + strWIDList[u32WidsCount].u16WIDid = WID_RECEIVED_FRAGMENT_COUNT; + strWIDList[u32WidsCount].enuWIDtype = WID_INT; + strWIDList[u32WidsCount].s32ValueSize = sizeof(WILC_Uint32); + strWIDList[u32WidsCount].ps8WidVal = (WILC_Sint8 *)(&(pstrStatistics->u32RxCount)); + u32WidsCount++; + + strWIDList[u32WidsCount].u16WIDid = WID_FAILED_COUNT; + strWIDList[u32WidsCount].enuWIDtype = WID_INT; + strWIDList[u32WidsCount].s32ValueSize = sizeof(WILC_Uint32); + strWIDList[u32WidsCount].ps8WidVal = (WILC_Sint8 *)(&(pstrStatistics->u32TxFailureCount)); + u32WidsCount++; + + s32Error = SendConfigPkt(GET_CFG, strWIDList, u32WidsCount, WILC_FALSE, (WILC_Uint32)drvHandler); + + if (s32Error) { + PRINT_ER("Failed to send scan paramters config packet\n"); + /* WILC_ERRORREPORT(s32Error, s32Error); */ + } + WILC_SemaphoreRelease(&hWaitResponse, NULL); + return 0; + +} + + +#ifdef WILC_AP_EXTERNAL_MLME + + +/** + * @brief Handle_Get_InActiveTime + * @details Sending config packet to set mac adddress for station and + * get inactive time + * @param[in] NONE + * @return NONE + * + * @author + * @date + * @version 1.0 + */ +static WILC_Sint32 Handle_Get_InActiveTime(void *drvHandler, tstrHostIfStaInactiveT *strHostIfStaInactiveT) +{ + + WILC_Sint32 s32Error = WILC_SUCCESS; + WILC_Uint8 *stamac; + tstrWID strWID; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + + strWID.u16WIDid = (WILC_Uint16)WID_SET_STA_MAC_INACTIVE_TIME; + strWID.enuWIDtype = WID_STR; + strWID.s32ValueSize = ETH_ALEN; + strWID.ps8WidVal = (WILC_Uint8 *)WILC_MALLOC(strWID.s32ValueSize); + + + stamac = strWID.ps8WidVal; + WILC_memcpy(stamac, strHostIfStaInactiveT->mac, ETH_ALEN); + + + PRINT_D(CFG80211_DBG, "SETING STA inactive time\n"); + + + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + /*get the value by searching the local copy*/ + if (s32Error) { + PRINT_ER("Failed to SET incative time\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + + + strWID.u16WIDid = (WILC_Uint16)WID_GET_INACTIVE_TIME; + strWID.enuWIDtype = WID_INT; + strWID.ps8WidVal = (WILC_Sint8 *)&gu32InactiveTime; + strWID.s32ValueSize = sizeof(WILC_Uint32); + + + s32Error = SendConfigPkt(GET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + /*get the value by searching the local copy*/ + if (s32Error) { + PRINT_ER("Failed to get incative time\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + + + PRINT_D(CFG80211_DBG, "Getting inactive time : %d\n", gu32InactiveTime); + + WILC_SemaphoreRelease(&(pstrWFIDrv->hSemInactiveTime), WILC_NULL); + WILC_CATCH(s32Error) + { + + } + + + return s32Error; + + + +} + + +/** + * @brief Handle_AddBeacon + * @details Sending config packet to add beacon + * @param[in] tstrHostIFSetBeacon* pstrSetBeaconParam + * @return NONE + * @author + * @date + * @version 1.0 + */ +static void Handle_AddBeacon(void *drvHandler, tstrHostIFSetBeacon *pstrSetBeaconParam) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + WILC_Uint8 *pu8CurrByte; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + PRINT_D(HOSTINF_DBG, "Adding BEACON\n"); + + strWID.u16WIDid = (WILC_Uint16)WID_ADD_BEACON; + strWID.enuWIDtype = WID_BIN; + strWID.s32ValueSize = pstrSetBeaconParam->u32HeadLen + pstrSetBeaconParam->u32TailLen + 16; + strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize); + if (strWID.ps8WidVal == NULL) { + WILC_ERRORREPORT(s32Error, WILC_NO_MEM); + } + + pu8CurrByte = strWID.ps8WidVal; + *pu8CurrByte++ = (pstrSetBeaconParam->u32Interval & 0xFF); + *pu8CurrByte++ = ((pstrSetBeaconParam->u32Interval >> 8) & 0xFF); + *pu8CurrByte++ = ((pstrSetBeaconParam->u32Interval >> 16) & 0xFF); + *pu8CurrByte++ = ((pstrSetBeaconParam->u32Interval >> 24) & 0xFF); + + *pu8CurrByte++ = (pstrSetBeaconParam->u32DTIMPeriod & 0xFF); + *pu8CurrByte++ = ((pstrSetBeaconParam->u32DTIMPeriod >> 8) & 0xFF); + *pu8CurrByte++ = ((pstrSetBeaconParam->u32DTIMPeriod >> 16) & 0xFF); + *pu8CurrByte++ = ((pstrSetBeaconParam->u32DTIMPeriod >> 24) & 0xFF); + + *pu8CurrByte++ = (pstrSetBeaconParam->u32HeadLen & 0xFF); + *pu8CurrByte++ = ((pstrSetBeaconParam->u32HeadLen >> 8) & 0xFF); + *pu8CurrByte++ = ((pstrSetBeaconParam->u32HeadLen >> 16) & 0xFF); + *pu8CurrByte++ = ((pstrSetBeaconParam->u32HeadLen >> 24) & 0xFF); + + memcpy(pu8CurrByte, pstrSetBeaconParam->pu8Head, pstrSetBeaconParam->u32HeadLen); + pu8CurrByte += pstrSetBeaconParam->u32HeadLen; + + *pu8CurrByte++ = (pstrSetBeaconParam->u32TailLen & 0xFF); + *pu8CurrByte++ = ((pstrSetBeaconParam->u32TailLen >> 8) & 0xFF); + *pu8CurrByte++ = ((pstrSetBeaconParam->u32TailLen >> 16) & 0xFF); + *pu8CurrByte++ = ((pstrSetBeaconParam->u32TailLen >> 24) & 0xFF); + + /* Bug 4599 : if tail length = 0 skip copying */ + if (pstrSetBeaconParam->pu8Tail > 0) + memcpy(pu8CurrByte, pstrSetBeaconParam->pu8Tail, pstrSetBeaconParam->u32TailLen); + pu8CurrByte += pstrSetBeaconParam->u32TailLen; + + + + /*Sending Cfg*/ + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_FALSE, (WILC_Uint32)pstrWFIDrv); + if (s32Error) { + PRINT_ER("Failed to send add beacon config packet\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + + WILC_CATCH(s32Error) + { + } + WILC_FREE_IF_TRUE(strWID.ps8WidVal); + WILC_FREE_IF_TRUE(pstrSetBeaconParam->pu8Head); + WILC_FREE_IF_TRUE(pstrSetBeaconParam->pu8Tail); +} + + +/** + * @brief Handle_AddBeacon + * @details Sending config packet to delete beacon + * @param[in] tstrHostIFDelBeacon* pstrDelBeacon + * @return NONE + * @author + * @date + * @version 1.0 + */ +static void Handle_DelBeacon(void *drvHandler, tstrHostIFDelBeacon *pstrDelBeacon) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + WILC_Uint8 *pu8CurrByte; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + strWID.u16WIDid = (WILC_Uint16)WID_DEL_BEACON; + strWID.enuWIDtype = WID_CHAR; + strWID.s32ValueSize = sizeof(WILC_Char); + strWID.ps8WidVal = &gu8DelBcn; + + if (strWID.ps8WidVal == NULL) { + WILC_ERRORREPORT(s32Error, WILC_NO_MEM); + } + + pu8CurrByte = strWID.ps8WidVal; + + PRINT_D(HOSTINF_DBG, "Deleting BEACON\n"); + /* TODO: build del beacon message*/ + + /*Sending Cfg*/ + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_FALSE, (WILC_Uint32)pstrWFIDrv); + if (s32Error) { + + PRINT_ER("Failed to send delete beacon config packet\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + + WILC_CATCH(s32Error) + { + } +} + + +/** + * @brief WILC_HostIf_PackStaParam + * @details Handling packing of the station params in a buffer + * @param[in] WILC_Uint8* pu8Buffer, tstrWILC_AddStaParam* pstrStationParam + * @return NONE + * @author + * @date + * @version 1.0 + */ +static WILC_Uint32 WILC_HostIf_PackStaParam(WILC_Uint8 *pu8Buffer, tstrWILC_AddStaParam *pstrStationParam) +{ + WILC_Uint8 *pu8CurrByte; + + pu8CurrByte = pu8Buffer; + + PRINT_D(HOSTINF_DBG, "Packing STA params\n"); + WILC_memcpy(pu8CurrByte, pstrStationParam->au8BSSID, ETH_ALEN); + pu8CurrByte += ETH_ALEN; + + *pu8CurrByte++ = pstrStationParam->u16AssocID & 0xFF; + *pu8CurrByte++ = (pstrStationParam->u16AssocID >> 8) & 0xFF; + + *pu8CurrByte++ = pstrStationParam->u8NumRates; + if (pstrStationParam->u8NumRates > 0) { + WILC_memcpy(pu8CurrByte, pstrStationParam->pu8Rates, pstrStationParam->u8NumRates); + } + pu8CurrByte += pstrStationParam->u8NumRates; + + *pu8CurrByte++ = pstrStationParam->bIsHTSupported; + *pu8CurrByte++ = pstrStationParam->u16HTCapInfo & 0xFF; + *pu8CurrByte++ = (pstrStationParam->u16HTCapInfo >> 8) & 0xFF; + + *pu8CurrByte++ = pstrStationParam->u8AmpduParams; + WILC_memcpy(pu8CurrByte, pstrStationParam->au8SuppMCsSet, WILC_SUPP_MCS_SET_SIZE); + pu8CurrByte += WILC_SUPP_MCS_SET_SIZE; + + *pu8CurrByte++ = pstrStationParam->u16HTExtParams & 0xFF; + *pu8CurrByte++ = (pstrStationParam->u16HTExtParams >> 8) & 0xFF; + + *pu8CurrByte++ = pstrStationParam->u32TxBeamformingCap & 0xFF; + *pu8CurrByte++ = (pstrStationParam->u32TxBeamformingCap >> 8) & 0xFF; + *pu8CurrByte++ = (pstrStationParam->u32TxBeamformingCap >> 16) & 0xFF; + *pu8CurrByte++ = (pstrStationParam->u32TxBeamformingCap >> 24) & 0xFF; + + *pu8CurrByte++ = pstrStationParam->u8ASELCap; + + *pu8CurrByte++ = pstrStationParam->u16FlagsMask & 0xFF; + *pu8CurrByte++ = (pstrStationParam->u16FlagsMask >> 8) & 0xFF; + + *pu8CurrByte++ = pstrStationParam->u16FlagsSet & 0xFF; + *pu8CurrByte++ = (pstrStationParam->u16FlagsSet >> 8) & 0xFF; + + return pu8CurrByte - pu8Buffer; +} + +/** + * @brief Handle_AddStation + * @details Sending config packet to add station + * @param[in] tstrWILC_AddStaParam* pstrStationParam + * @return NONE + * @author + * @date + * @version 1.0 + */ +static void Handle_AddStation(void *drvHandler, tstrWILC_AddStaParam *pstrStationParam) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + WILC_Uint8 *pu8CurrByte; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + PRINT_D(HOSTINF_DBG, "Handling add station\n"); + strWID.u16WIDid = (WILC_Uint16)WID_ADD_STA; + strWID.enuWIDtype = WID_BIN; + strWID.s32ValueSize = WILC_ADD_STA_LENGTH + pstrStationParam->u8NumRates; + + strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize); + if (strWID.ps8WidVal == NULL) { + WILC_ERRORREPORT(s32Error, WILC_NO_MEM); + } + + pu8CurrByte = strWID.ps8WidVal; + pu8CurrByte += WILC_HostIf_PackStaParam(pu8CurrByte, pstrStationParam); + + /*Sending Cfg*/ + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_FALSE, (WILC_Uint32)pstrWFIDrv); + if (s32Error != WILC_SUCCESS) { + + PRINT_ER("Failed to send add station config packet\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + + WILC_CATCH(s32Error) + { + } + WILC_FREE_IF_TRUE(pstrStationParam->pu8Rates); + WILC_FREE_IF_TRUE(strWID.ps8WidVal); +} + +/** + * @brief Handle_DelAllSta + * @details Sending config packet to delete station + * @param[in] tstrHostIFDelSta* pstrDelStaParam + * @return NONE + * @author + * @date + * @version 1.0 + */ +static void Handle_DelAllSta(void *drvHandler, tstrHostIFDelAllSta *pstrDelAllStaParam) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + WILC_Uint8 *pu8CurrByte; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + WILC_Uint8 i; + UWORD8 au8Zero_Buff[6] = {0}; + strWID.u16WIDid = (WILC_Uint16)WID_DEL_ALL_STA; + strWID.enuWIDtype = WID_STR; + strWID.s32ValueSize = (pstrDelAllStaParam->u8Num_AssocSta * ETH_ALEN) + 1; + + PRINT_D(HOSTINF_DBG, "Handling delete station \n"); + + strWID.ps8WidVal = WILC_MALLOC((pstrDelAllStaParam->u8Num_AssocSta * ETH_ALEN) + 1); + if (strWID.ps8WidVal == NULL) { + WILC_ERRORREPORT(s32Error, WILC_NO_MEM); + } + + pu8CurrByte = strWID.ps8WidVal; + + *(pu8CurrByte++) = pstrDelAllStaParam->u8Num_AssocSta; + + for (i = 0; i < MAX_NUM_STA; i++) { + if (memcmp(pstrDelAllStaParam->au8Sta_DelAllSta[i], au8Zero_Buff, ETH_ALEN)) + WILC_memcpy(pu8CurrByte, pstrDelAllStaParam->au8Sta_DelAllSta[i], ETH_ALEN); + else + continue; + + pu8CurrByte += ETH_ALEN; + } + + /*Sending Cfg*/ + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + if (s32Error) { + + PRINT_ER("Failed to send add station config packe\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + + WILC_CATCH(s32Error) + { + } + WILC_FREE_IF_TRUE(strWID.ps8WidVal); + + WILC_SemaphoreRelease(&hWaitResponse, NULL); +} + + +/** + * @brief Handle_DelStation + * @details Sending config packet to delete station + * @param[in] tstrHostIFDelSta* pstrDelStaParam + * @return NONE + * @author + * @date + * @version 1.0 + */ +static void Handle_DelStation(void *drvHandler, tstrHostIFDelSta *pstrDelStaParam) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + WILC_Uint8 *pu8CurrByte; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + strWID.u16WIDid = (WILC_Uint16)WID_REMOVE_STA; + strWID.enuWIDtype = WID_BIN; + strWID.s32ValueSize = ETH_ALEN; + + PRINT_D(HOSTINF_DBG, "Handling delete station \n"); + + strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize); + if (strWID.ps8WidVal == NULL) { + WILC_ERRORREPORT(s32Error, WILC_NO_MEM); + } + + pu8CurrByte = strWID.ps8WidVal; + + WILC_memcpy(pu8CurrByte, pstrDelStaParam->au8MacAddr, ETH_ALEN); + + /*Sending Cfg*/ + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_FALSE, (WILC_Uint32)pstrWFIDrv); + if (s32Error) { + + PRINT_ER("Failed to send add station config packe\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + + WILC_CATCH(s32Error) + { + } + WILC_FREE_IF_TRUE(strWID.ps8WidVal); +} + + +/** + * @brief Handle_EditStation + * @details Sending config packet to edit station + * @param[in] tstrWILC_AddStaParam* pstrStationParam + * @return NONE + * @author + * @date + * @version 1.0 + */ +static void Handle_EditStation(void *drvHandler, tstrWILC_AddStaParam *pstrStationParam) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + WILC_Uint8 *pu8CurrByte; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + strWID.u16WIDid = (WILC_Uint16)WID_EDIT_STA; + strWID.enuWIDtype = WID_BIN; + strWID.s32ValueSize = WILC_ADD_STA_LENGTH + pstrStationParam->u8NumRates; + + PRINT_D(HOSTINF_DBG, "Handling edit station\n"); + strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize); + if (strWID.ps8WidVal == NULL) { + WILC_ERRORREPORT(s32Error, WILC_NO_MEM); + } + + pu8CurrByte = strWID.ps8WidVal; + pu8CurrByte += WILC_HostIf_PackStaParam(pu8CurrByte, pstrStationParam); + + /*Sending Cfg*/ + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_FALSE, (WILC_Uint32)pstrWFIDrv); + if (s32Error) { + + PRINT_ER("Failed to send edit station config packet\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + + WILC_CATCH(s32Error) + { + } + WILC_FREE_IF_TRUE(pstrStationParam->pu8Rates); + WILC_FREE_IF_TRUE(strWID.ps8WidVal); +} +#endif /*WILC_AP_EXTERNAL_MLME*/ + +#ifdef WILC_P2P +/** + * @brief Handle_RemainOnChan + * @details Sending config packet to edit station + * @param[in] tstrWILC_AddStaParam* pstrStationParam + * @return NONE + * @author + * @date + * @version 1.0 + */ +static int Handle_RemainOnChan(void *drvHandler, tstrHostIfRemainOnChan *pstrHostIfRemainOnChan) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + WILC_Uint8 u8remain_on_chan_flag; + tstrWID strWID; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *) drvHandler; + + /*If it's a pendig remain-on-channel, don't overwrite gWFiDrvHandle values (since incoming msg is garbbage)*/ + if (!pstrWFIDrv->u8RemainOnChan_pendingreq) { + pstrWFIDrv->strHostIfRemainOnChan.pVoid = pstrHostIfRemainOnChan->pVoid; + pstrWFIDrv->strHostIfRemainOnChan.pRemainOnChanExpired = pstrHostIfRemainOnChan->pRemainOnChanExpired; + pstrWFIDrv->strHostIfRemainOnChan.pRemainOnChanReady = pstrHostIfRemainOnChan->pRemainOnChanReady; + pstrWFIDrv->strHostIfRemainOnChan.u16Channel = pstrHostIfRemainOnChan->u16Channel; + pstrWFIDrv->strHostIfRemainOnChan.u32ListenSessionID = pstrHostIfRemainOnChan->u32ListenSessionID; + } else { + /*Set the channel to use it as a wid val*/ + pstrHostIfRemainOnChan->u16Channel = pstrWFIDrv->strHostIfRemainOnChan.u16Channel; + } + + if (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult != NULL) { + PRINT_INFO(GENERIC_DBG, "Required to remain on chan while scanning return\n"); + pstrWFIDrv->u8RemainOnChan_pendingreq = 1; + WILC_ERRORREPORT(s32Error, WILC_BUSY); + } + if (pstrWFIDrv->enuHostIFstate == HOST_IF_WAITING_CONN_RESP) { + PRINT_INFO(GENERIC_DBG, "Required to remain on chan while connecting return\n"); + WILC_ERRORREPORT(s32Error, WILC_BUSY); + } + + #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP + if (g_obtainingIP || connecting) { + PRINT_D(GENERIC_DBG, "[handle_scan]: Don't do obss scan until IP adresss is obtained\n"); + WILC_ERRORREPORT(s32Error, WILC_BUSY); + } + #endif + + PRINT_D(HOSTINF_DBG, "Setting channel :%d\n", pstrHostIfRemainOnChan->u16Channel); + + u8remain_on_chan_flag = WILC_TRUE; + strWID.u16WIDid = (WILC_Uint16)WID_REMAIN_ON_CHAN; + strWID.enuWIDtype = WID_STR; + strWID.s32ValueSize = 2; + strWID.ps8WidVal = (WILC_Sint8 *)WILC_MALLOC(strWID.s32ValueSize); + + if (strWID.ps8WidVal == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_NO_MEM); + } + + strWID.ps8WidVal[0] = u8remain_on_chan_flag; + strWID.ps8WidVal[1] = (WILC_Sint8)pstrHostIfRemainOnChan->u16Channel; + + /*Sending Cfg*/ + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + if (s32Error != WILC_SUCCESS) { + PRINT_ER("Failed to set remain on channel\n"); + } + + WILC_CATCH(-1) + { + P2P_LISTEN_STATE = 1; + WILC_TimerStart(&(pstrWFIDrv->hRemainOnChannel), pstrHostIfRemainOnChan->u32duration, (void *)pstrWFIDrv, WILC_NULL); + + /*Calling CFG ready_on_channel*/ + if (pstrWFIDrv->strHostIfRemainOnChan.pRemainOnChanReady) { + pstrWFIDrv->strHostIfRemainOnChan.pRemainOnChanReady(pstrWFIDrv->strHostIfRemainOnChan.pVoid); + } + + if (pstrWFIDrv->u8RemainOnChan_pendingreq) + pstrWFIDrv->u8RemainOnChan_pendingreq = 0; + } + return s32Error; +} + +/** + * @brief Handle_RegisterFrame + * @details + * @param[in] + * @return NONE + * @author + * @date + * @version 1.0 + */ +static int Handle_RegisterFrame(void *drvHandler, tstrHostIfRegisterFrame *pstrHostIfRegisterFrame) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + WILC_Uint8 *pu8CurrByte; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + PRINT_D(HOSTINF_DBG, "Handling frame register Flag : %d FrameType: %d\n", pstrHostIfRegisterFrame->bReg, pstrHostIfRegisterFrame->u16FrameType); + + /*prepare configuration packet*/ + strWID.u16WIDid = (WILC_Uint16)WID_REGISTER_FRAME; + strWID.enuWIDtype = WID_STR; + strWID.ps8WidVal = WILC_MALLOC(sizeof(WILC_Uint16) + 2); + if (strWID.ps8WidVal == NULL) { + WILC_ERRORREPORT(s32Error, WILC_NO_MEM); + } + + pu8CurrByte = strWID.ps8WidVal; + + *pu8CurrByte++ = pstrHostIfRegisterFrame->bReg; + *pu8CurrByte++ = pstrHostIfRegisterFrame->u8Regid; + WILC_memcpy(pu8CurrByte, &(pstrHostIfRegisterFrame->u16FrameType), sizeof(WILC_Uint16)); + + + strWID.s32ValueSize = sizeof(WILC_Uint16) + 2; + + + /*Sending Cfg*/ + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + if (s32Error) { + PRINT_ER("Failed to frame register config packet\n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_STATE); + } + + + WILC_CATCH(s32Error) + { + } + + return s32Error; + +} + +/** + * @brief Handle_ListenStateExpired + * @details Handle of listen state expiration + * @param[in] NONE + * @return Error code. + * @author + * @date + * @version 1.0 + */ +#define FALSE_FRMWR_CHANNEL 100 +static WILC_Uint32 Handle_ListenStateExpired(void *drvHandler, tstrHostIfRemainOnChan *pstrHostIfRemainOnChan) +{ + WILC_Uint8 u8remain_on_chan_flag; + tstrWID strWID; + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *) drvHandler; + + PRINT_D(HOSTINF_DBG, "CANCEL REMAIN ON CHAN\n"); + + /*BugID_5477*/ + /*Make sure we are already in listen state*/ + /*This is to handle duplicate expiry messages (listen timer fired and supplicant called cancel_remain_on_channel())*/ + if (P2P_LISTEN_STATE) { + u8remain_on_chan_flag = WILC_FALSE; + strWID.u16WIDid = (WILC_Uint16)WID_REMAIN_ON_CHAN; + strWID.enuWIDtype = WID_STR; + strWID.s32ValueSize = 2; + strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize); + + if (strWID.ps8WidVal == WILC_NULL) { + PRINT_ER("Failed to allocate memory\n"); + } + + strWID.ps8WidVal[0] = u8remain_on_chan_flag; + strWID.ps8WidVal[1] = FALSE_FRMWR_CHANNEL; + + /*Sending Cfg*/ + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + if (s32Error != WILC_SUCCESS) { + PRINT_ER("Failed to set remain on channel\n"); + goto _done_; + } + + if (pstrWFIDrv->strHostIfRemainOnChan.pRemainOnChanExpired) { + pstrWFIDrv->strHostIfRemainOnChan.pRemainOnChanExpired(pstrWFIDrv->strHostIfRemainOnChan.pVoid + , pstrHostIfRemainOnChan->u32ListenSessionID); + } + P2P_LISTEN_STATE = 0; + } else { + PRINT_D(GENERIC_DBG, "Not in listen state\n"); + s32Error = WILC_FAIL; + } + +_done_: + return s32Error; +} + + +/** + * @brief ListenTimerCB + * @details Callback function of remain-on-channel timer + * @param[in] NONE + * @return Error code. + * @author + * @date + * @version 1.0 + */ +static void ListenTimerCB(void *pvArg) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrHostIFmsg strHostIFmsg; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)pvArg; + /*Stopping remain-on-channel timer*/ + WILC_TimerStop(&(pstrWFIDrv->hRemainOnChannel), WILC_NULL); + + /* prepare the Timer Callback message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + strHostIFmsg.u16MsgId = HOST_IF_MSG_LISTEN_TIMER_FIRED; + strHostIFmsg.drvHandler = pstrWFIDrv; + strHostIFmsg.uniHostIFmsgBody.strHostIfRemainOnChan.u32ListenSessionID = pstrWFIDrv->strHostIfRemainOnChan.u32ListenSessionID; + + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + WILC_ERRORREPORT(s32Error, s32Error); + } + WILC_CATCH(s32Error) + { + + } +} +#endif + + +/** + * @brief Handle_EditStation + * @details Sending config packet to edit station + * @param[in] tstrWILC_AddStaParam* pstrStationParam + * @return NONE + * @author + * @date + * @version 1.0 + */ +static void Handle_PowerManagement(void *drvHandler, tstrHostIfPowerMgmtParam *strPowerMgmtParam) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + WILC_Sint8 s8PowerMode; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + strWID.u16WIDid = (WILC_Uint16)WID_POWER_MANAGEMENT; + + if (strPowerMgmtParam->bIsEnabled == WILC_TRUE) { + s8PowerMode = MIN_FAST_PS; + } else { + s8PowerMode = NO_POWERSAVE; + } + PRINT_D(HOSTINF_DBG, "Handling power mgmt to %d\n", s8PowerMode); + strWID.ps8WidVal = &s8PowerMode; + strWID.s32ValueSize = sizeof(WILC_Char); + + PRINT_D(HOSTINF_DBG, "Handling Power Management\n"); + + /*Sending Cfg*/ + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + if (s32Error) { + PRINT_ER("Failed to send power management config packet\n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_STATE); + } + + WILC_CATCH(s32Error) + { + + } +} + +/** + * @brief Handle_SetMulticastFilter + * @details Set Multicast filter in firmware + * @param[in] tstrHostIFSetMulti* strHostIfSetMulti + * @return NONE + * @author asobhy + * @date + * @version 1.0 + */ +static void Handle_SetMulticastFilter(void *drvHandler, tstrHostIFSetMulti *strHostIfSetMulti) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + WILC_Uint8 *pu8CurrByte; + + PRINT_D(HOSTINF_DBG, "Setup Multicast Filter\n"); + + strWID.u16WIDid = (WILC_Uint16)WID_SETUP_MULTICAST_FILTER; + strWID.enuWIDtype = WID_BIN; + strWID.s32ValueSize = sizeof(tstrHostIFSetMulti) + ((strHostIfSetMulti->u32count) * ETH_ALEN); + strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize); + if (strWID.ps8WidVal == NULL) { + WILC_ERRORREPORT(s32Error, WILC_NO_MEM); + } + + pu8CurrByte = strWID.ps8WidVal; + *pu8CurrByte++ = (strHostIfSetMulti->bIsEnabled & 0xFF); + *pu8CurrByte++ = ((strHostIfSetMulti->bIsEnabled >> 8) & 0xFF); + *pu8CurrByte++ = ((strHostIfSetMulti->bIsEnabled >> 16) & 0xFF); + *pu8CurrByte++ = ((strHostIfSetMulti->bIsEnabled >> 24) & 0xFF); + + *pu8CurrByte++ = (strHostIfSetMulti->u32count & 0xFF); + *pu8CurrByte++ = ((strHostIfSetMulti->u32count >> 8) & 0xFF); + *pu8CurrByte++ = ((strHostIfSetMulti->u32count >> 16) & 0xFF); + *pu8CurrByte++ = ((strHostIfSetMulti->u32count >> 24) & 0xFF); + + if ((strHostIfSetMulti->u32count) > 0) + memcpy(pu8CurrByte, gau8MulticastMacAddrList, ((strHostIfSetMulti->u32count) * ETH_ALEN)); + + /*Sending Cfg*/ + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_FALSE, (WILC_Uint32)drvHandler); + if (s32Error) { + PRINT_ER("Failed to send setup multicast config packet\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + + WILC_CATCH(s32Error) + { + } + WILC_FREE_IF_TRUE(strWID.ps8WidVal); + +} + + +/*BugID_5222*/ +/** + * @brief Handle_AddBASession + * @details Add block ack session + * @param[in] tstrHostIFSetMulti* strHostIfSetMulti + * @return NONE + * @author Amr Abdel-Moghny + * @date Feb. 2014 + * @version 9.0 + */ +static WILC_Sint32 Handle_AddBASession(void *drvHandler, tstrHostIfBASessionInfo *strHostIfBASessionInfo) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + int AddbaTimeout = 100; + char *ptr = NULL; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + PRINT_D(HOSTINF_DBG, "Opening Block Ack session with\nBSSID = %.2x:%.2x:%.2x \nTID=%d \nBufferSize == %d \nSessionTimeOut = %d\n", + strHostIfBASessionInfo->au8Bssid[0], + strHostIfBASessionInfo->au8Bssid[1], + strHostIfBASessionInfo->au8Bssid[2], + strHostIfBASessionInfo->u16BufferSize, + strHostIfBASessionInfo->u16SessionTimeout, + strHostIfBASessionInfo->u8Ted); + + strWID.u16WIDid = (WILC_Uint16)WID_11E_P_ACTION_REQ; + strWID.enuWIDtype = WID_STR; + strWID.ps8WidVal = (WILC_Uint8 *)WILC_MALLOC(BLOCK_ACK_REQ_SIZE); + strWID.s32ValueSize = BLOCK_ACK_REQ_SIZE; + ptr = strWID.ps8WidVal; + /* *ptr++ = 0x14; */ + *ptr++ = 0x14; + *ptr++ = 0x3; + *ptr++ = 0x0; + WILC_memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN); + ptr += ETH_ALEN; + *ptr++ = strHostIfBASessionInfo->u8Ted; + /* BA Policy*/ + *ptr++ = 1; + /* Buffer size*/ + *ptr++ = (strHostIfBASessionInfo->u16BufferSize & 0xFF); + *ptr++ = ((strHostIfBASessionInfo->u16BufferSize >> 16) & 0xFF); + /* BA timeout*/ + *ptr++ = (strHostIfBASessionInfo->u16SessionTimeout & 0xFF); + *ptr++ = ((strHostIfBASessionInfo->u16SessionTimeout >> 16) & 0xFF); + /* ADDBA timeout*/ + *ptr++ = (AddbaTimeout & 0xFF); + *ptr++ = ((AddbaTimeout >> 16) & 0xFF); + /* Group Buffer Max Frames*/ + *ptr++ = 8; + /* Group Buffer Timeout */ + *ptr++ = 0; + + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + if (s32Error) + PRINT_D(HOSTINF_DBG, "Couldn't open BA Session\n"); + + + strWID.u16WIDid = (WILC_Uint16)WID_11E_P_ACTION_REQ; + strWID.enuWIDtype = WID_STR; + strWID.s32ValueSize = 15; + ptr = strWID.ps8WidVal; + /* *ptr++ = 0x14; */ + *ptr++ = 15; + *ptr++ = 7; + *ptr++ = 0x2; + WILC_memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN); + ptr += ETH_ALEN; + /* TID*/ + *ptr++ = strHostIfBASessionInfo->u8Ted; + /* Max Num MSDU */ + *ptr++ = 8; + /* BA timeout*/ + *ptr++ = (strHostIfBASessionInfo->u16BufferSize & 0xFF); + *ptr++ = ((strHostIfBASessionInfo->u16SessionTimeout >> 16) & 0xFF); + /*Ack-Policy */ + *ptr++ = 3; + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + + if (strWID.ps8WidVal != NULL) + WILC_FREE(strWID.ps8WidVal); + + return s32Error; + +} + + +/*BugID_5222*/ +/** + * @brief Handle_DelBASession + * @details Delete block ack session + * @param[in] tstrHostIFSetMulti* strHostIfSetMulti + * @return NONE + * @author Amr Abdel-Moghny + * @date Feb. 2013 + * @version 9.0 + */ +static WILC_Sint32 Handle_DelBASession(void *drvHandler, tstrHostIfBASessionInfo *strHostIfBASessionInfo) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + char *ptr = NULL; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + PRINT_D(GENERIC_DBG, "Delete Block Ack session with\nBSSID = %.2x:%.2x:%.2x \nTID=%d\n", + strHostIfBASessionInfo->au8Bssid[0], + strHostIfBASessionInfo->au8Bssid[1], + strHostIfBASessionInfo->au8Bssid[2], + strHostIfBASessionInfo->u8Ted); + + strWID.u16WIDid = (WILC_Uint16)WID_11E_P_ACTION_REQ; + strWID.enuWIDtype = WID_STR; + strWID.ps8WidVal = (WILC_Uint8 *)WILC_MALLOC(BLOCK_ACK_REQ_SIZE); + strWID.s32ValueSize = BLOCK_ACK_REQ_SIZE; + ptr = strWID.ps8WidVal; + /* *ptr++ = 0x14; */ + *ptr++ = 0x14; + *ptr++ = 0x3; + *ptr++ = 0x2; + WILC_memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN); + ptr += ETH_ALEN; + *ptr++ = strHostIfBASessionInfo->u8Ted; + /* BA direction = recipent*/ + *ptr++ = 0; + /* Delba Reason */ + *ptr++ = 32; /* Unspecific QOS reason */ + + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + if (s32Error) + PRINT_D(HOSTINF_DBG, "Couldn't delete BA Session\n"); + + + strWID.u16WIDid = (WILC_Uint16)WID_11E_P_ACTION_REQ; + strWID.enuWIDtype = WID_STR; + strWID.s32ValueSize = 15; + ptr = strWID.ps8WidVal; + /* *ptr++ = 0x14; */ + *ptr++ = 15; + *ptr++ = 7; + *ptr++ = 0x3; + WILC_memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN); + ptr += ETH_ALEN; + /* TID*/ + *ptr++ = strHostIfBASessionInfo->u8Ted; + + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + + if (strWID.ps8WidVal != NULL) + WILC_FREE(strWID.ps8WidVal); + + /*BugID_5222*/ + WILC_SemaphoreRelease(&hWaitResponse, NULL); + + return s32Error; + +} + + +/** + * @brief Handle_DelAllRxBASessions + * @details Delete all Rx BA sessions + * @param[in] tstrHostIFSetMulti* strHostIfSetMulti + * @return NONE + * @author Abdelrahman Sobhy + * @date Feb. 2013 + * @version 9.0 + */ +static WILC_Sint32 Handle_DelAllRxBASessions(void *drvHandler, tstrHostIfBASessionInfo *strHostIfBASessionInfo) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + char *ptr = NULL; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + PRINT_D(GENERIC_DBG, "Delete Block Ack session with\nBSSID = %.2x:%.2x:%.2x \nTID=%d\n", + strHostIfBASessionInfo->au8Bssid[0], + strHostIfBASessionInfo->au8Bssid[1], + strHostIfBASessionInfo->au8Bssid[2], + strHostIfBASessionInfo->u8Ted); + + strWID.u16WIDid = (WILC_Uint16)WID_DEL_ALL_RX_BA; + strWID.enuWIDtype = WID_STR; + strWID.ps8WidVal = (WILC_Uint8 *)WILC_MALLOC(BLOCK_ACK_REQ_SIZE); + strWID.s32ValueSize = BLOCK_ACK_REQ_SIZE; + ptr = strWID.ps8WidVal; + *ptr++ = 0x14; + *ptr++ = 0x3; + *ptr++ = 0x2; + WILC_memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN); + ptr += ETH_ALEN; + *ptr++ = strHostIfBASessionInfo->u8Ted; + /* BA direction = recipent*/ + *ptr++ = 0; + /* Delba Reason */ + *ptr++ = 32; /* Unspecific QOS reason */ + + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + if (s32Error) + PRINT_D(HOSTINF_DBG, "Couldn't delete BA Session\n"); + + + if (strWID.ps8WidVal != NULL) + WILC_FREE(strWID.ps8WidVal); + + /*BugID_5222*/ + WILC_SemaphoreRelease(&hWaitResponse, NULL); + + return s32Error; + +} + +/** + * @brief hostIFthread + * @details Main thread to handle message queue requests + * @param[in] void* pvArg + * @return NONE + * @author + * @date + * @version 1.0 + */ +static void hostIFthread(void *pvArg) +{ + WILC_Uint32 u32Ret; + tstrHostIFmsg strHostIFmsg; + tstrWILC_WFIDrv *pstrWFIDrv; + + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + while (1) { + WILC_MsgQueueRecv(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), &u32Ret, WILC_NULL); + pstrWFIDrv = (tstrWILC_WFIDrv *)strHostIFmsg.drvHandler; + if (strHostIFmsg.u16MsgId == HOST_IF_MSG_EXIT) { + PRINT_D(GENERIC_DBG, "THREAD: Exiting HostIfThread\n"); + break; + } + + + /*Re-Queue HIF message*/ + if ((!g_wilc_initialized)) { + PRINT_D(GENERIC_DBG, "--WAIT--"); + WILC_Sleep(200); + WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + continue; + } + + if (strHostIFmsg.u16MsgId == HOST_IF_MSG_CONNECT && pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult != NULL) { + PRINT_D(HOSTINF_DBG, "Requeue connect request till scan done received\n"); + WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + WILC_Sleep(2); + continue; + } + + switch (strHostIFmsg.u16MsgId) { + case HOST_IF_MSG_Q_IDLE: + Handle_wait_msg_q_empty(); + break; + + case HOST_IF_MSG_SCAN: + Handle_Scan(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr); + break; + + case HOST_IF_MSG_CONNECT: + Handle_Connect(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr); + break; + + /*BugID_5137*/ + case HOST_IF_MSG_FLUSH_CONNECT: + Handle_FlushConnect(strHostIFmsg.drvHandler); + break; + + case HOST_IF_MSG_RCVD_NTWRK_INFO: + Handle_RcvdNtwrkInfo(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strRcvdNetworkInfo); + break; + + case HOST_IF_MSG_RCVD_GNRL_ASYNC_INFO: + Handle_RcvdGnrlAsyncInfo(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strRcvdGnrlAsyncInfo); + break; + + case HOST_IF_MSG_KEY: + Handle_Key(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr); + break; + + case HOST_IF_MSG_CFG_PARAMS: + + Handle_CfgParam(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strHostIFCfgParamAttr); + break; + + case HOST_IF_MSG_SET_CHANNEL: + Handle_SetChannel(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strHostIFSetChan); + break; + + case HOST_IF_MSG_DISCONNECT: + Handle_Disconnect(strHostIFmsg.drvHandler); + break; + + case HOST_IF_MSG_RCVD_SCAN_COMPLETE: + WILC_TimerStop(&(pstrWFIDrv->hScanTimer), WILC_NULL); + PRINT_D(HOSTINF_DBG, "scan completed successfully\n"); + + /*BugID_5213*/ + /*Allow chip sleep, only if both interfaces are not connected*/ + if (!linux_wlan_get_num_conn_ifcs()) { + chip_sleep_manually(INFINITE_SLEEP_TIME); + } + + Handle_ScanDone(strHostIFmsg.drvHandler, SCAN_EVENT_DONE); + + #ifdef WILC_P2P + if (pstrWFIDrv->u8RemainOnChan_pendingreq) + Handle_RemainOnChan(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strHostIfRemainOnChan); + #endif + + break; + + case HOST_IF_MSG_GET_RSSI: + Handle_GetRssi(strHostIFmsg.drvHandler); + break; + + case HOST_IF_MSG_GET_LINKSPEED: + Handle_GetLinkspeed(strHostIFmsg.drvHandler); + break; + + case HOST_IF_MSG_GET_STATISTICS: + Handle_GetStatistics(strHostIFmsg.drvHandler, (tstrStatistics *)strHostIFmsg.uniHostIFmsgBody.pUserData); + break; + + case HOST_IF_MSG_GET_CHNL: + Handle_GetChnl(strHostIFmsg.drvHandler); + break; + +#ifdef WILC_AP_EXTERNAL_MLME + case HOST_IF_MSG_ADD_BEACON: + Handle_AddBeacon(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strHostIFSetBeacon); + break; + + case HOST_IF_MSG_DEL_BEACON: + Handle_DelBeacon(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strHostIFDelBeacon); + break; + + case HOST_IF_MSG_ADD_STATION: + Handle_AddStation(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strAddStaParam); + break; + + case HOST_IF_MSG_DEL_STATION: + Handle_DelStation(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strDelStaParam); + break; + + case HOST_IF_MSG_EDIT_STATION: + Handle_EditStation(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strEditStaParam); + break; + + case HOST_IF_MSG_GET_INACTIVETIME: + Handle_Get_InActiveTime(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strHostIfStaInactiveT); + break; + +#endif /*WILC_AP_EXTERNAL_MLME*/ + case HOST_IF_MSG_SCAN_TIMER_FIRED: + PRINT_D(HOSTINF_DBG, "Scan Timeout\n"); + + Handle_ScanDone(strHostIFmsg.drvHandler, SCAN_EVENT_ABORTED); + break; + + case HOST_IF_MSG_CONNECT_TIMER_FIRED: + PRINT_D(HOSTINF_DBG, "Connect Timeout \n"); + Handle_ConnectTimeout(strHostIFmsg.drvHandler); + break; + + case HOST_IF_MSG_POWER_MGMT: + Handle_PowerManagement(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strPowerMgmtparam); + break; + + case HOST_IF_MSG_SET_WFIDRV_HANDLER: + Handle_SetWfiDrvHandler(&strHostIFmsg.uniHostIFmsgBody.strHostIfSetDrvHandler); + break; + + case HOST_IF_MSG_SET_OPERATION_MODE: + Handle_SetOperationMode(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strHostIfSetOperationMode); + break; + + case HOST_IF_MSG_SET_IPADDRESS: + PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_SET_IPADDRESS\n"); + Handle_set_IPAddress(strHostIFmsg.drvHandler, strHostIFmsg.uniHostIFmsgBody.strHostIfSetIP.au8IPAddr, strHostIFmsg.uniHostIFmsgBody.strHostIfSetIP.idx); + break; + + case HOST_IF_MSG_GET_IPADDRESS: + PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_SET_IPADDRESS\n"); + Handle_get_IPAddress(strHostIFmsg.drvHandler, strHostIFmsg.uniHostIFmsgBody.strHostIfSetIP.au8IPAddr, strHostIFmsg.uniHostIFmsgBody.strHostIfSetIP.idx); + break; + + /*BugID_5077*/ + case HOST_IF_MSG_SET_MAC_ADDRESS: + Handle_SetMacAddress(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strHostIfSetMacAddress); + break; + + /*BugID_5213*/ + case HOST_IF_MSG_GET_MAC_ADDRESS: + Handle_GetMacAddress(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strHostIfGetMacAddress); + break; + +#ifdef WILC_P2P + case HOST_IF_MSG_REMAIN_ON_CHAN: + PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_REMAIN_ON_CHAN\n"); + Handle_RemainOnChan(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strHostIfRemainOnChan); + break; + + case HOST_IF_MSG_REGISTER_FRAME: + PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_REGISTER_FRAME\n"); + Handle_RegisterFrame(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strHostIfRegisterFrame); + break; + + case HOST_IF_MSG_LISTEN_TIMER_FIRED: + Handle_ListenStateExpired(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strHostIfRemainOnChan); + break; + + #endif + case HOST_IF_MSG_SET_MULTICAST_FILTER: + PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_SET_MULTICAST_FILTER\n"); + Handle_SetMulticastFilter(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strHostIfSetMulti); + break; + + /*BugID_5222*/ + case HOST_IF_MSG_ADD_BA_SESSION: + Handle_AddBASession(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strHostIfBASessionInfo); + break; + + case HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS: + Handle_DelAllRxBASessions(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strHostIfBASessionInfo); + break; + + case HOST_IF_MSG_DEL_ALL_STA: + Handle_DelAllSta(strHostIFmsg.drvHandler, &strHostIFmsg.uniHostIFmsgBody.strHostIFDelAllSta); + break; + + default: + PRINT_ER("[Host Interface] undefined Received Msg ID \n"); + break; + } + } + + PRINT_D(HOSTINF_DBG, "Releasing thread exit semaphore\n"); + WILC_SemaphoreRelease(&hSemHostIFthrdEnd, WILC_NULL); + return; + /* do_exit(error); */ + /* PRINT_D(HOSTINF_DBG,"do_exit error code %d\n",error); */ + +} + +static void TimerCB_Scan(void *pvArg) +{ + tstrHostIFmsg strHostIFmsg; + + /* prepare the Timer Callback message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + strHostIFmsg.drvHandler = pvArg; + strHostIFmsg.u16MsgId = HOST_IF_MSG_SCAN_TIMER_FIRED; + + /* send the message */ + WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); +} + +static void TimerCB_Connect(void *pvArg) +{ + tstrHostIFmsg strHostIFmsg; + + /* prepare the Timer Callback message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + strHostIFmsg.drvHandler = pvArg; + strHostIFmsg.u16MsgId = HOST_IF_MSG_CONNECT_TIMER_FIRED; + + /* send the message */ + WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); +} + + +/** + * @brief removes wpa/wpa2 keys + * @details only in BSS STA mode if External Supplicant support is enabled. + * removes all WPA/WPA2 station key entries from MAC hardware. + * @param[in,out] handle to the wifi driver + * @param[in] 6 bytes of Station Adress in the station entry table + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +/* Check implementation in core adding 9 bytes to the input! */ +WILC_Sint32 host_int_remove_key(WILC_WFIDrvHandle hWFIDrv, const WILC_Uint8 *pu8StaAddress) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */ + + strWID.u16WIDid = (WILC_Uint16)WID_REMOVE_KEY; + strWID.enuWIDtype = WID_STR; + strWID.ps8WidVal = (WILC_Sint8 *)pu8StaAddress; + strWID.s32ValueSize = 6; + + return s32Error; + +} + +/** + * @brief removes WEP key + * @details valid only in BSS STA mode if External Supplicant support is enabled. + * remove a WEP key entry from MAC HW. + * The BSS Station automatically finds the index of the entry using its + * BSS ID and removes that entry from the MAC hardware. + * @param[in,out] handle to the wifi driver + * @param[in] 6 bytes of Station Adress in the station entry table + * @return Error code indicating success/failure + * @note NO need for the STA add since it is not used for processing + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_remove_wep_key(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 u8keyIdx) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + /* prepare the Remove Wep Key Message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + + strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY; + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.enuKeyType = WEP; + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.u8KeyAction = REMOVEKEY; + strHostIFmsg.drvHandler = hWFIDrv; + + + + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwepAttr.u8Wepidx = u8keyIdx; + + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) + PRINT_ER("Error in sending message queue : Request to remove WEP key \n"); + WILC_SemaphoreAcquire(&(pstrWFIDrv->hSemTestKeyBlock), NULL); + + WILC_CATCH(s32Error) + { + + } + return s32Error; +} + +/** + * @brief sets WEP default key + * @details Sets the index of the WEP encryption key in use, + * in the key table + * @param[in,out] handle to the wifi driver + * @param[in] key index ( 0, 1, 2, 3) + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_set_WEPDefaultKeyID(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 u8Index) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + /* prepare the Key Message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + + strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY; + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.enuKeyType = WEP; + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.u8KeyAction = DEFAULTKEY; + strHostIFmsg.drvHandler = hWFIDrv; + + + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwepAttr.u8Wepidx = u8Index; + + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) + PRINT_ER("Error in sending message queue : Default key index\n"); + WILC_SemaphoreAcquire(&(pstrWFIDrv->hSemTestKeyBlock), NULL); + + WILC_CATCH(s32Error) + { + + } + + return s32Error; +} + +/** + * @brief sets WEP deafault key + * @details valid only in BSS STA mode if External Supplicant support is enabled. + * sets WEP key entry into MAC hardware when it receives the + * corresponding request from NDIS. + * @param[in,out] handle to the wifi driver + * @param[in] message containing WEP Key in the following format + *|---------------------------------------| + *|Key ID Value | Key Length | Key | + *|-------------|------------|------------| + | 1byte | 1byte | Key Length | + ||---------------------------------------| + | + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_add_wep_key_bss_sta(WILC_WFIDrvHandle hWFIDrv, const WILC_Uint8 *pu8WepKey, WILC_Uint8 u8WepKeylen, WILC_Uint8 u8Keyidx) +{ + + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + + } + + /* prepare the Key Message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + + strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY; + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.enuKeyType = WEP; + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.u8KeyAction = ADDKEY; + strHostIFmsg.drvHandler = hWFIDrv; + + + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey = (WILC_Uint8 *)WILC_MALLOC(u8WepKeylen); + + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey, + pu8WepKey, u8WepKeylen); + + + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen = (u8WepKeylen); + + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwepAttr.u8Wepidx = u8Keyidx; + + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) + PRINT_ER("Error in sending message queue :WEP Key\n"); + WILC_SemaphoreAcquire(&(pstrWFIDrv->hSemTestKeyBlock), NULL); + + WILC_CATCH(s32Error) + { + + } + return s32Error; + +} + +#ifdef WILC_AP_EXTERNAL_MLME +/** + * + * @brief host_int_add_wep_key_bss_ap + * @details valid only in BSS AP mode if External Supplicant support is enabled. + * sets WEP key entry into MAC hardware when it receives the + * + * corresponding request from NDIS. + * @param[in,out] handle to the wifi driver + * + * + * @return Error code indicating success/failure + * @note + * @author mdaftedar + * @date 28 FEB 2013 + * @version 1.0 + */ +WILC_Sint32 host_int_add_wep_key_bss_ap(WILC_WFIDrvHandle hWFIDrv, const WILC_Uint8 *pu8WepKey, WILC_Uint8 u8WepKeylen, WILC_Uint8 u8Keyidx, WILC_Uint8 u8mode, AUTHTYPE_T tenuAuth_type) +{ + + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + WILC_Uint8 i; + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + + } + + /* prepare the Key Message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + if (INFO) { + for (i = 0; i < u8WepKeylen; i++) + PRINT_INFO(HOSTAPD_DBG, "KEY is %x\n", pu8WepKey[i]); + } + strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY; + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.enuKeyType = WEP; + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.u8KeyAction = ADDKEY_AP; + strHostIFmsg.drvHandler = hWFIDrv; + + + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey = (WILC_Uint8 *)WILC_MALLOC((u8WepKeylen)); + + + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey, + pu8WepKey, (u8WepKeylen)); + + + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen = (u8WepKeylen); + + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwepAttr.u8Wepidx = u8Keyidx; + + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwepAttr.u8mode = u8mode; + + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwepAttr.tenuAuth_type = tenuAuth_type; + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + + if (s32Error) + PRINT_ER("Error in sending message queue :WEP Key\n"); + WILC_SemaphoreAcquire(&(pstrWFIDrv->hSemTestKeyBlock), NULL); + + WILC_CATCH(s32Error) + { + + } + return s32Error; + +} +#endif +/** + * @brief adds ptk Key + * @details + * @param[in,out] handle to the wifi driver + * @param[in] message containing PTK Key in the following format + *|-----------------------------------------------------------------------------| + *|Station address | Key Length | Temporal Key | Rx Michael Key |Tx Michael Key | + *|----------------|------------|--------------|----------------|---------------| + | 6 bytes | 1byte | 16 bytes | 8 bytes | 8 bytes | + ||-----------------------------------------------------------------------------| + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_add_ptk(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 *pu8Ptk, WILC_Uint8 u8PtkKeylen, + const WILC_Uint8 *mac_addr, WILC_Uint8 *pu8RxMic, WILC_Uint8 *pu8TxMic, WILC_Uint8 mode, WILC_Uint8 u8Ciphermode, WILC_Uint8 u8Idx) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + WILC_Uint8 u8KeyLen = u8PtkKeylen; + WILC_Uint32 i; + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + if (pu8RxMic != NULL) { + u8KeyLen += RX_MIC_KEY_LEN; + } + if (pu8TxMic != NULL) { + u8KeyLen += TX_MIC_KEY_LEN; + } + + /* prepare the Key Message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + + strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY; + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.enuKeyType = WPAPtk; + #ifdef WILC_AP_EXTERNAL_MLME + if (mode == AP_MODE) { + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.u8KeyAction = ADDKEY_AP; + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwpaAttr.u8keyidx = u8Idx; + } + #endif + if (mode == STATION_MODE) + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.u8KeyAction = ADDKEY; + + + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwpaAttr.pu8key = (WILC_Uint8 *)WILC_MALLOC(u8PtkKeylen); + + + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key, + pu8Ptk, u8PtkKeylen); + + if (pu8RxMic != NULL) { + + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key + 16, + pu8RxMic, RX_MIC_KEY_LEN); + if (INFO) { + for (i = 0; i < RX_MIC_KEY_LEN; i++) + PRINT_INFO(CFG80211_DBG, "PairwiseRx[%d] = %x\n", i, pu8RxMic[i]); + } + } + if (pu8TxMic != NULL) { + + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key + 24, + pu8TxMic, TX_MIC_KEY_LEN); + if (INFO) { + for (i = 0; i < TX_MIC_KEY_LEN; i++) + PRINT_INFO(CFG80211_DBG, "PairwiseTx[%d] = %x\n", i, pu8TxMic[i]); + } + } + + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen = u8KeyLen; + + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwpaAttr.u8Ciphermode = u8Ciphermode; + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwpaAttr.pu8macaddr = mac_addr; + strHostIFmsg.drvHandler = hWFIDrv; + + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + + if (s32Error) + PRINT_ER("Error in sending message queue: PTK Key\n"); + + /* ////////////// */ + WILC_SemaphoreAcquire(&(pstrWFIDrv->hSemTestKeyBlock), NULL); + /* WILC_Sleep(100); */ + /* /////// */ + + WILC_CATCH(s32Error) + { + + } + + return s32Error; +} + +/** + * @brief adds Rx GTk Key + * @details + * @param[in,out] handle to the wifi driver + * @param[in] pu8RxGtk : contains temporal key | Rx Mic | Tx Mic + * u8GtkKeylen :The total key length + * + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_add_rx_gtk(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 *pu8RxGtk, WILC_Uint8 u8GtkKeylen, + WILC_Uint8 u8KeyIdx, WILC_Uint32 u32KeyRSClen, WILC_Uint8 *KeyRSC, + WILC_Uint8 *pu8RxMic, WILC_Uint8 *pu8TxMic, WILC_Uint8 mode, WILC_Uint8 u8Ciphermode) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + WILC_Uint8 u8KeyLen = u8GtkKeylen; + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + /* prepare the Key Message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + + if (pu8RxMic != NULL) { + u8KeyLen += RX_MIC_KEY_LEN; + } + if (pu8TxMic != NULL) { + u8KeyLen += TX_MIC_KEY_LEN; + } + if (KeyRSC != NULL) { + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq = (WILC_Uint8 *)WILC_MALLOC(u32KeyRSClen); + + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq, + KeyRSC, u32KeyRSClen); + } + + + strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY; + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.enuKeyType = WPARxGtk; + strHostIFmsg.drvHandler = hWFIDrv; + + #ifdef WILC_AP_EXTERNAL_MLME + if (mode == AP_MODE) { + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.u8KeyAction = ADDKEY_AP; + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.u8Ciphermode = u8Ciphermode; + } + #endif + if (mode == STATION_MODE) + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.u8KeyAction = ADDKEY; + + + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwpaAttr.pu8key = (WILC_Uint8 *)WILC_MALLOC(u8KeyLen); + + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key, + pu8RxGtk, u8GtkKeylen); + + if (pu8RxMic != NULL) { + + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key + 16, + pu8RxMic, RX_MIC_KEY_LEN); + + } + if (pu8TxMic != NULL) { + + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key + 24, + pu8TxMic, TX_MIC_KEY_LEN); + + } + + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwpaAttr.u8keyidx = u8KeyIdx; + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen = u8KeyLen; + + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwpaAttr.u8seqlen = u32KeyRSClen; + + + + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) + PRINT_ER("Error in sending message queue: RX GTK\n"); + /* ////////////// */ + WILC_SemaphoreAcquire(&(pstrWFIDrv->hSemTestKeyBlock), NULL); + /* WILC_Sleep(100); */ + /* /////// */ + + WILC_CATCH(s32Error) + { + + } + return s32Error; +} +#if 0 +/** + * @brief host_int_add_tx_gtk + * @details adds Tx GTk Key + * @param[in,out] handle to the wifi driver + * @param[in] message containing Tx GTK Key in the following format + *|----------------------------------------------------| + | KeyID | Key Length | Temporal Key | Tx Michael Key | + ||-------|------------|--------------|----------------| + ||1 byte | 1 byte | 16 bytes | 8 bytes | + ||----------------------------------------------------| + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_add_tx_gtk(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 u8KeyLen, WILC_Uint8 *pu8TxGtk, WILC_Uint8 u8KeyIdx) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + /* prepare the Key Message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY; + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.enuKeyType = WPATxGtk; + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.u8KeyAction = ADDKEY; + + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr. + uniHostIFkeyAttr.strHostIFwpaAttr.pu8key = (WILC_Uint8 *)WILC_MALLOC(u8KeyLen); + + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key, + pu8TxGtk, u8KeyLen); + + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen = u8KeyLen; + + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) + PRINT_ER("Error in sending message queue: TX GTK\n"); + + /* ////////////// */ + WILC_SemaphoreAcquire(&hSemTestKeyBlock, NULL); + WILC_Sleep(100); + /* /////// */ + + WILC_CATCH(s32Error) + { + + } + return s32Error; +} +#endif +/** + * @brief host_int_set_pmkid_info + * @details caches the pmkid valid only in BSS STA mode if External Supplicant + * support is enabled. This Function sets the PMKID in firmware + * when host drivr receives the corresponding request from NDIS. + * The firmware then includes theset PMKID in the appropriate + * management frames + * @param[in,out] handle to the wifi driver + * @param[in] message containing PMKID Info in the following format + *|-----------------------------------------------------------------| + *|NumEntries | BSSID[1] | PMKID[1] | ... | BSSID[K] | PMKID[K] | + *|-----------|------------|----------|-------|----------|----------| + | 1 | 6 | 16 | ... | 6 | 16 | + ||-----------------------------------------------------------------| + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_set_pmkid_info(WILC_WFIDrvHandle hWFIDrv, tstrHostIFpmkidAttr *pu8PmkidInfoArray) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + WILC_Uint32 i; + + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + /* prepare the Key Message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY; + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.enuKeyType = PMKSA; + strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.u8KeyAction = ADDKEY; + strHostIFmsg.drvHandler = hWFIDrv; + + for (i = 0; i < pu8PmkidInfoArray->numpmkid; i++) { + + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFpmkidAttr.pmkidlist[i].bssid, &pu8PmkidInfoArray->pmkidlist[i].bssid, + ETH_ALEN); + + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFpmkidAttr.pmkidlist[i].pmkid, &pu8PmkidInfoArray->pmkidlist[i].pmkid, + PMKID_LEN); + } + + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) + PRINT_ER(" Error in sending messagequeue: PMKID Info\n"); + + WILC_CATCH(s32Error) + { + + } + + return s32Error; +} + +/** + * @brief gets the cached the pmkid info + * @details valid only in BSS STA mode if External Supplicant + * support is enabled. This Function sets the PMKID in firmware + * when host drivr receives the corresponding request from NDIS. + * The firmware then includes theset PMKID in the appropriate + * management frames + * @param[in,out] handle to the wifi driver, + * message containing PMKID Info in the following format + *|-----------------------------------------------------------------| + *|NumEntries | BSSID[1] | PMKID[1] | ... | BSSID[K] | PMKID[K] | + *|-----------|------------|----------|-------|----------|----------| + | 1 | 6 | 16 | ... | 6 | 16 | + ||-----------------------------------------------------------------| + * @param[in] + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_get_pmkid_info(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 *pu8PmkidInfoArray, + WILC_Uint32 u32PmkidInfoLen) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */ + + strWID.u16WIDid = (WILC_Uint16)WID_PMKID_INFO; + strWID.enuWIDtype = WID_STR; + strWID.s32ValueSize = u32PmkidInfoLen; + strWID.ps8WidVal = pu8PmkidInfoArray; + + return s32Error; +} + +/** + * @brief sets the pass phrase + * @details AP/STA mode. This function gives the pass phrase used to + * generate the Pre-Shared Key when WPA/WPA2 is enabled + * The length of the field can vary from 8 to 64 bytes, + * the lower layer should get the + * @param[in,out] handle to the wifi driver, + * @param[in] String containing PSK + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_set_RSNAConfigPSKPassPhrase(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 *pu8PassPhrase, + WILC_Uint8 u8Psklength) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */ + + /* WILC_Uint8 u8Psklength = WILC_strlen(pu8PassPhrase); */ + /*validating psk length*/ + if ((u8Psklength > 7) && (u8Psklength < 65)) { + strWID.u16WIDid = (WILC_Uint16)WID_11I_PSK; + strWID.enuWIDtype = WID_STR; + strWID.ps8WidVal = pu8PassPhrase; + strWID.s32ValueSize = u8Psklength; + } + + return s32Error; +} +/** + * @brief host_int_get_MacAddress + * @details gets mac address + * @param[in,out] handle to the wifi driver, + * + * @return Error code indicating success/failure + * @note + * @author mdaftedar + * @date 19 April 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_get_MacAddress(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 *pu8MacAddress) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrHostIFmsg strHostIFmsg; + + + /* prepare the Message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_MAC_ADDRESS; + strHostIFmsg.uniHostIFmsgBody.strHostIfGetMacAddress.u8MacAddress = pu8MacAddress; + strHostIFmsg.drvHandler = hWFIDrv; + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + PRINT_ER("Failed to send get mac address\n"); + return WILC_FAIL; + } + + WILC_SemaphoreAcquire(&hWaitResponse, NULL); + return s32Error; +} + +/** + * @brief host_int_set_MacAddress + * @details sets mac address + * @param[in,out] handle to the wifi driver, + * + * @return Error code indicating success/failure + * @note + * @author mabubakr + * @date 16 July 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_set_MacAddress(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 *pu8MacAddress) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrHostIFmsg strHostIFmsg; + + PRINT_D(GENERIC_DBG, "mac addr = %x:%x:%x\n", pu8MacAddress[0], pu8MacAddress[1], pu8MacAddress[2]); + + /* prepare setting mac address message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_MAC_ADDRESS; + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIfSetMacAddress.u8MacAddress, pu8MacAddress, ETH_ALEN); + strHostIFmsg.drvHandler = hWFIDrv; + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + PRINT_ER("Failed to send message queue: Set mac address\n"); + WILC_ERRORREPORT(s32Error, s32Error); + } + WILC_CATCH(s32Error) + { + + } + + return s32Error; + +} + +/** + * @brief host_int_get_RSNAConfigPSKPassPhrase + * @details gets the pass phrase:AP/STA mode. This function gets the pass phrase used to + * generate the Pre-Shared Key when WPA/WPA2 is enabled + * The length of the field can vary from 8 to 64 bytes, + * the lower layer should get the + * @param[in,out] handle to the wifi driver, + * String containing PSK + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_get_RSNAConfigPSKPassPhrase(WILC_WFIDrvHandle hWFIDrv, + WILC_Uint8 *pu8PassPhrase, WILC_Uint8 u8Psklength) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */ + + strWID.u16WIDid = (WILC_Uint16)WID_11I_PSK; + strWID.enuWIDtype = WID_STR; + strWID.s32ValueSize = u8Psklength; + strWID.ps8WidVal = pu8PassPhrase; + + return s32Error; +} + +/** + * @brief host_int_get_site_survey_results + * @details gets the site survey results + * @param[in,out] handle to the wifi driver, + * Message containing site survey results in the + * following format + *|---------------------------------------------------| + | MsgLength | fragNo. | MsgBodyLength | MsgBody | + ||-----------|-----------|---------------|-----------| + | 1 | 1 | 1 | 1 | + | ----------------------------------------- | ---------------- + | + ||---------------------------------------| + | Network1 | Netweork2 | ... | Network5 | + ||---------------------------------------| + | 44 | 44 | ... | 44 | + | -------------------------- | --------------------------------------- + | + ||---------------------------------------------------------------------| + | SSID | BSS Type | Channel | Security Status| BSSID | RSSI |Reserved | + | + | + ||------|----------|---------|----------------|-------|------|---------| + | 33 | 1 | 1 | 1 | 6 | 1 | 1 | + ||---------------------------------------------------------------------| + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +#ifndef CONNECT_DIRECT +WILC_Sint32 host_int_get_site_survey_results(WILC_WFIDrvHandle hWFIDrv, + WILC_Uint8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZE], + WILC_Uint32 u32MaxSiteSrvyFragLen) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID astrWIDList[2]; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + + astrWIDList[0].u16WIDid = (WILC_Uint16)WID_SITE_SURVEY_RESULTS; + astrWIDList[0].enuWIDtype = WID_STR; + astrWIDList[0].ps8WidVal = ppu8RcvdSiteSurveyResults[0]; + astrWIDList[0].s32ValueSize = u32MaxSiteSrvyFragLen; + + astrWIDList[1].u16WIDid = (WILC_Uint16)WID_SITE_SURVEY_RESULTS; + astrWIDList[1].enuWIDtype = WID_STR; + astrWIDList[1].ps8WidVal = ppu8RcvdSiteSurveyResults[1]; + astrWIDList[1].s32ValueSize = u32MaxSiteSrvyFragLen; + + s32Error = SendConfigPkt(GET_CFG, astrWIDList, 2, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + + /*get the value by searching the local copy*/ + if (s32Error) { + PRINT_ER("Failed to send config packet to get survey results\n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_STATE); + } + + WILC_CATCH(s32Error) + { + + } + + return s32Error; +} +#endif + +/** + * @brief sets a start scan request + * @details + * @param[in,out] handle to the wifi driver, + * @param[in] Scan Source one of the following values + * DEFAULT_SCAN 0 + * USER_SCAN BIT0 + * OBSS_PERIODIC_SCAN BIT1 + * OBSS_ONETIME_SCAN BIT2 + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_set_start_scan_req(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 scanSource) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */ + + strWID.u16WIDid = (WILC_Uint16)WID_START_SCAN_REQ; + strWID.enuWIDtype = WID_CHAR; + strWID.ps8WidVal = (WILC_Sint8 *)&scanSource; + strWID.s32ValueSize = sizeof(WILC_Char); + + return s32Error; +} + +/** + * @brief host_int_get_start_scan_req + * @details gets a start scan request + * @param[in,out] handle to the wifi driver, + * @param[in] Scan Source one of the following values + * DEFAULT_SCAN 0 + * USER_SCAN BIT0 + * OBSS_PERIODIC_SCAN BIT1 + * OBSS_ONETIME_SCAN BIT2 + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ + +WILC_Sint32 host_int_get_start_scan_req(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 *pu8ScanSource) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */ + + strWID.u16WIDid = (WILC_Uint16)WID_START_SCAN_REQ; + strWID.enuWIDtype = WID_CHAR; + strWID.ps8WidVal = (WILC_Sint8 *)pu8ScanSource; + strWID.s32ValueSize = sizeof(WILC_Char); + + return s32Error; +} + +/** + * @brief host_int_set_join_req + * @details sets a join request + * @param[in,out] handle to the wifi driver, + * @param[in] Index of the bss descriptor + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_set_join_req(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 *pu8bssid, + WILC_Uint8 *pu8ssid, size_t ssidLen, + const WILC_Uint8 *pu8IEs, size_t IEsLen, + tWILCpfConnectResult pfConnectResult, void *pvUserArg, + WILC_Uint8 u8security, AUTHTYPE_T tenuAuth_type, + WILC_Uint8 u8channel, + void *pJoinParams) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + tenuScanConnTimer enuScanConnTimer; + + if (pstrWFIDrv == WILC_NULL || pfConnectResult == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + if (hWFIDrv == NULL) { + PRINT_ER("Driver not initialized: gWFiDrvHandle = NULL\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + + if (pJoinParams == NULL) { + PRINT_ER("Unable to Join - JoinParams is NULL\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + + } +/* + * if(gWFiDrvHandle->strWILC_UsrScanReq.u32RcvdChCount == 0) + * { + * PRINT_ER("No scan results exist: Scanning should be done\n"); + * WILC_ERRORREPORT(s32Error, WILC_FAIL); + * } + */ + /* prepare the Connect Message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + strHostIFmsg.u16MsgId = HOST_IF_MSG_CONNECT; + + strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.u8security = u8security; + strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.tenuAuth_type = tenuAuth_type; + strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.u8channel = u8channel; + strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pfConnectResult = pfConnectResult; + strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pvUserArg = pvUserArg; + strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pJoinParams = pJoinParams; + strHostIFmsg.drvHandler = hWFIDrv; + + if (pu8bssid != NULL) { + strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8bssid = (WILC_Uint8 *)WILC_MALLOC(6); /* will be deallocated by the receiving thread */ + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8bssid, + pu8bssid, 6); + } + + if (pu8ssid != NULL) { + strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.ssidLen = ssidLen; + strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8ssid = (WILC_Uint8 *)WILC_MALLOC(ssidLen); /* will be deallocated by the receiving thread */ + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8ssid, + + pu8ssid, ssidLen); + } + + if (pu8IEs != NULL) { + strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.IEsLen = IEsLen; + strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8IEs = (WILC_Uint8 *)WILC_MALLOC(IEsLen); /* will be deallocated by the receiving thread */ + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8IEs, + pu8IEs, IEsLen); + } + if (pstrWFIDrv->enuHostIFstate < HOST_IF_CONNECTING) { + pstrWFIDrv->enuHostIFstate = HOST_IF_CONNECTING; + } else + PRINT_D(GENERIC_DBG, "Don't set state to 'connecting' as state is %d\n", pstrWFIDrv->enuHostIFstate); + + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + PRINT_ER("Failed to send message queue: Set join request\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + + enuScanConnTimer = CONNECT_TIMER; + WILC_TimerStart(&(pstrWFIDrv->hConnectTimer), HOST_IF_CONNECT_TIMEOUT, (void *) hWFIDrv, WILC_NULL); + + WILC_CATCH(s32Error) + { + + } + + return s32Error; +} + +/** + * @brief Flush a join request parameters to FW, but actual connection + * @details The function is called in situation where WILC is connected to AP and + * required to switch to hybrid FW for P2P connection + * @param[in] handle to the wifi driver, + * @return Error code indicating success/failure + * @note + * @author Amr Abdel-Moghny + * @date 19 DEC 2013 + * @version 8.0 + */ + +WILC_Sint32 host_int_flush_join_req(WILC_WFIDrvHandle hWFIDrv) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrHostIFmsg strHostIFmsg; + + if (!gu8FlushedJoinReq) { + s32Error = WILC_FAIL; + return s32Error; + } + + + if (hWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + + strHostIFmsg.u16MsgId = HOST_IF_MSG_FLUSH_CONNECT; + strHostIFmsg.drvHandler = hWFIDrv; + + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + PRINT_ER("Failed to send message queue: Flush join request\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + + WILC_CATCH(s32Error) + { + + } + return s32Error; +} + +/** + * @brief host_int_disconnect + * @details disconnects from the currently associated network + * @param[in,out] handle to the wifi driver, + * @param[in] Reason Code of the Disconnection + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_disconnect(WILC_WFIDrvHandle hWFIDrv, WILC_Uint16 u16ReasonCode) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrHostIFmsg strHostIFmsg; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + + if (pstrWFIDrv == WILC_NULL) { + PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + if (pstrWFIDrv == NULL) { + PRINT_ER("gWFiDrvHandle = NULL\n"); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + + /* prepare the Disconnect Message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + strHostIFmsg.u16MsgId = HOST_IF_MSG_DISCONNECT; + strHostIFmsg.drvHandler = hWFIDrv; + + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) + PRINT_ER("Failed to send message queue: disconnect\n"); + /* ////////////// */ + WILC_SemaphoreAcquire(&(pstrWFIDrv->hSemTestDisconnectBlock), NULL); + /* /////// */ + + WILC_CATCH(s32Error) + { + + } + + return s32Error; +} + +/** + * @brief host_int_disconnect_station + * @details disconnects a sta + * @param[in,out] handle to the wifi driver, + * @param[in] Association Id of the station to be disconnected + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_disconnect_station(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 assoc_id) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */ + + strWID.u16WIDid = (WILC_Uint16)WID_DISCONNECT; + strWID.enuWIDtype = WID_CHAR; + strWID.ps8WidVal = (WILC_Sint8 *)&assoc_id; + strWID.s32ValueSize = sizeof(WILC_Char); + + return s32Error; +} + +/** + * @brief host_int_get_assoc_req_info + * @details gets a Association request info + * @param[in,out] handle to the wifi driver, + * Message containg assoc. req info in the following format + * ------------------------------------------------------------------------ + | Management Frame Format | + ||-------------------------------------------------------------------| + ||Frame Control|Duration|DA|SA|BSSID|Sequence Control|Frame Body|FCS | + ||-------------|--------|--|--|-----|----------------|----------|----| + | 2 |2 |6 |6 |6 | 2 |0 - 2312 | 4 | + ||-------------------------------------------------------------------| + | | + | Association Request Frame - Frame Body | + ||-------------------------------------------------------------------| + | Capability Information | Listen Interval | SSID | Supported Rates | + ||------------------------|-----------------|------|-----------------| + | 2 | 2 | 2-34 | 3-10 | + | --------------------------------------------------------------------- + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ + +WILC_Sint32 host_int_get_assoc_req_info(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 *pu8AssocReqInfo, + WILC_Uint32 u32AssocReqInfoLen) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */ + + strWID.u16WIDid = (WILC_Uint16)WID_ASSOC_REQ_INFO; + strWID.enuWIDtype = WID_STR; + strWID.ps8WidVal = pu8AssocReqInfo; + strWID.s32ValueSize = u32AssocReqInfoLen; + + + return s32Error; +} + +/** + * @brief gets a Association Response info + * @details + * @param[in,out] handle to the wifi driver, + * Message containg assoc. resp info + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_get_assoc_res_info(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 *pu8AssocRespInfo, + WILC_Uint32 u32MaxAssocRespInfoLen, WILC_Uint32 *pu32RcvdAssocRespInfoLen) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + + if (pstrWFIDrv == WILC_NULL) { + PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + strWID.u16WIDid = (WILC_Uint16)WID_ASSOC_RES_INFO; + strWID.enuWIDtype = WID_STR; + strWID.ps8WidVal = pu8AssocRespInfo; + strWID.s32ValueSize = u32MaxAssocRespInfoLen; + + + /* Sending Configuration packet */ + s32Error = SendConfigPkt(GET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + if (s32Error) { + PRINT_ER("Failed to send association response config packet\n"); + *pu32RcvdAssocRespInfoLen = 0; + WILC_ERRORREPORT(s32Error, WILC_INVALID_STATE); + } else { + *pu32RcvdAssocRespInfoLen = strWID.s32ValueSize; + } + + WILC_CATCH(s32Error) + { + + } + return s32Error; +} + +/** + * @brief gets a Association Response info + * @details Valid only in STA mode. This function gives the RSSI + * values observed in all the channels at the time of scanning. + * The length of the field is 1 greater that the total number of + * channels supported. Byte 0 contains the number of channels while + * each of Byte N contains the observed RSSI value for the channel index N. + * @param[in,out] handle to the wifi driver, + * array of scanned channels' RSSI + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_get_rx_power_level(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 *pu8RxPowerLevel, + WILC_Uint32 u32RxPowerLevelLen) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */ + + strWID.u16WIDid = (WILC_Uint16)WID_RX_POWER_LEVEL; + strWID.enuWIDtype = WID_STR; + strWID.ps8WidVal = pu8RxPowerLevel; + strWID.s32ValueSize = u32RxPowerLevelLen; + + + return s32Error; +} + +/** + * @brief sets a channel + * @details + * @param[in,out] handle to the wifi driver, + * @param[in] Index of the channel to be set + *|-------------------------------------------------------------------| + | CHANNEL1 CHANNEL2 .... CHANNEL14 | + | Input: 1 2 14 | + ||-------------------------------------------------------------------| + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_set_mac_chnl_num(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 u8ChNum) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + /* prepare the set channel message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_CHANNEL; + strHostIFmsg.uniHostIFmsgBody.strHostIFSetChan.u8SetChan = u8ChNum; + strHostIFmsg.drvHandler = hWFIDrv; + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + WILC_ERRORREPORT(s32Error, s32Error); + } + WILC_CATCH(s32Error) + { + + } + + return s32Error; +} + + +WILC_Sint32 host_int_wait_msg_queue_idle(void) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + + tstrHostIFmsg strHostIFmsg; + + /* prepare the set driver handler message */ + + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + strHostIFmsg.u16MsgId = HOST_IF_MSG_Q_IDLE; + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + WILC_ERRORREPORT(s32Error, s32Error); + } + WILC_CATCH(s32Error) + { + + } + + /* wait untill MSG Q is empty */ + WILC_SemaphoreAcquire(&hWaitResponse, NULL); + + return s32Error; + +} + +WILC_Sint32 host_int_set_wfi_drv_handler(WILC_Uint32 u32address) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + + tstrHostIFmsg strHostIFmsg; + + + /* prepare the set driver handler message */ + + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_WFIDRV_HANDLER; + strHostIFmsg.uniHostIFmsgBody.strHostIfSetDrvHandler.u32Address = u32address; + /* strHostIFmsg.drvHandler=hWFIDrv; */ + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + WILC_ERRORREPORT(s32Error, s32Error); + } + WILC_CATCH(s32Error) + { + + } + + return s32Error; +} + + + +WILC_Sint32 host_int_set_operation_mode(WILC_WFIDrvHandle hWFIDrv, WILC_Uint32 u32mode) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + + tstrHostIFmsg strHostIFmsg; + + + /* prepare the set driver handler message */ + + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_OPERATION_MODE; + strHostIFmsg.uniHostIFmsgBody.strHostIfSetOperationMode.u32Mode = u32mode; + strHostIFmsg.drvHandler = hWFIDrv; + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + WILC_ERRORREPORT(s32Error, s32Error); + } + WILC_CATCH(s32Error) + { + + } + + return s32Error; +} + +/** + * @brief gets the current channel index + * @details + * @param[in,out] handle to the wifi driver, + * current channel index + *|-----------------------------------------------------------------------| + | CHANNEL1 CHANNEL2 .... CHANNEL14 | + | Input: 1 2 14 | + ||-----------------------------------------------------------------------| + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_get_host_chnl_num(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 *pu8ChNo) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + + if (pstrWFIDrv == WILC_NULL) { + PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + /* prepare the Get Channel Message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_CHNL; + strHostIFmsg.drvHandler = hWFIDrv; + + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) + PRINT_ER("Failed to send get host channel param's message queue "); + WILC_SemaphoreAcquire(&(pstrWFIDrv->hSemGetCHNL), NULL); + /* gu8Chnl = 11; */ + + *pu8ChNo = gu8Chnl; + + WILC_CATCH(s32Error) + { + } + + return s32Error; + + +} + + +/** + * @brief host_int_test_set_int_wid + * @details Test function for setting wids + * @param[in,out] WILC_WFIDrvHandle hWFIDrv, WILC_Uint32 u32TestMemAddr + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_test_set_int_wid(WILC_WFIDrvHandle hWFIDrv, WILC_Uint32 u32TestMemAddr) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + + + if (pstrWFIDrv == WILC_NULL) { + PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + /*prepare configuration packet*/ + strWID.u16WIDid = (WILC_Uint16)WID_MEMORY_ADDRESS; + strWID.enuWIDtype = WID_INT; + strWID.ps8WidVal = (WILC_Char *)&u32TestMemAddr; + strWID.s32ValueSize = sizeof(WILC_Uint32); + + /*Sending Cfg*/ + s32Error = SendConfigPkt(SET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + if (s32Error) { + PRINT_ER("Test Function: Failed to set wid value\n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_STATE); + } else { + PRINT_D(HOSTINF_DBG, "Successfully set wid value\n"); + + } + + WILC_CATCH(s32Error) + { + + } + return s32Error; +} + +#ifdef WILC_AP_EXTERNAL_MLME +/** + * @brief host_int_get_inactive_time + * @details + * @param[in,out] handle to the wifi driver, + * current sta macaddress, inactive_time + * @return + * @note + * @author + * @date + * @version 1.0 + */ +WILC_Sint32 host_int_get_inactive_time(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 *mac, WILC_Uint32 *pu32InactiveTime) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + + if (pstrWFIDrv == WILC_NULL) { + PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIfStaInactiveT.mac, + mac, ETH_ALEN); + + strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_INACTIVETIME; + strHostIFmsg.drvHandler = hWFIDrv; + + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) + PRINT_ER("Failed to send get host channel param's message queue "); + + WILC_SemaphoreAcquire(&(pstrWFIDrv->hSemInactiveTime), NULL); + + *pu32InactiveTime = gu32InactiveTime; + + WILC_CATCH(s32Error) + { + } + + return s32Error; +} +#endif +/** + * @brief host_int_test_get_int_wid + * @details Test function for getting wids + * @param[in,out] WILC_WFIDrvHandle hWFIDrv, WILC_Uint32* pu32TestMemAddr + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_test_get_int_wid(WILC_WFIDrvHandle hWFIDrv, WILC_Uint32 *pu32TestMemAddr) +{ + + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWID strWID; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + + + if (pstrWFIDrv == WILC_NULL) { + PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + strWID.u16WIDid = (WILC_Uint16)WID_MEMORY_ADDRESS; + strWID.enuWIDtype = WID_INT; + strWID.ps8WidVal = (WILC_Sint8 *)pu32TestMemAddr; + strWID.s32ValueSize = sizeof(WILC_Uint32); + + s32Error = SendConfigPkt(GET_CFG, &strWID, 1, WILC_TRUE, (WILC_Uint32)pstrWFIDrv); + /*get the value by searching the local copy*/ + if (s32Error) { + PRINT_ER("Test Function: Failed to get wid value\n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_STATE); + } else { + PRINT_D(HOSTINF_DBG, "Successfully got wid value\n"); + + } + + WILC_CATCH(s32Error) + { + + } + return s32Error; +} + + +/** + * @brief host_int_get_rssi + * @details gets the currently maintained RSSI value for the station. + * The received signal strength value in dB. + * The range of valid values is -128 to 0. + * @param[in,out] handle to the wifi driver, + * rssi value in dB + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_get_rssi(WILC_WFIDrvHandle hWFIDrv, WILC_Sint8 *ps8Rssi) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrHostIFmsg strHostIFmsg; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + + + /* prepare the Get RSSI Message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_RSSI; + strHostIFmsg.drvHandler = hWFIDrv; + + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + PRINT_ER("Failed to send get host channel param's message queue "); + return WILC_FAIL; + } + + WILC_SemaphoreAcquire(&(pstrWFIDrv->hSemGetRSSI), NULL); + + + if (ps8Rssi == NULL) { + PRINT_ER("RSS pointer value is null"); + return WILC_FAIL; + } + + + *ps8Rssi = gs8Rssi; + + + return s32Error; +} + +WILC_Sint32 host_int_get_link_speed(WILC_WFIDrvHandle hWFIDrv, WILC_Sint8 *ps8lnkspd) +{ + tstrHostIFmsg strHostIFmsg; + WILC_Sint32 s32Error = WILC_SUCCESS; + + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + + + + /* prepare the Get LINKSPEED Message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_LINKSPEED; + strHostIFmsg.drvHandler = hWFIDrv; + + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + PRINT_ER("Failed to send GET_LINKSPEED to message queue "); + return WILC_FAIL; + } + + WILC_SemaphoreAcquire(&(pstrWFIDrv->hSemGetLINKSPEED), NULL); + + + if (ps8lnkspd == NULL) { + PRINT_ER("LINKSPEED pointer value is null"); + return WILC_FAIL; + } + + + *ps8lnkspd = gs8lnkspd; + + + return s32Error; +} + +WILC_Sint32 host_int_get_statistics(WILC_WFIDrvHandle hWFIDrv, tstrStatistics *pstrStatistics) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrHostIFmsg strHostIFmsg; + + + /* prepare the Get RSSI Message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_STATISTICS; + strHostIFmsg.uniHostIFmsgBody.pUserData = (WILC_Char *)pstrStatistics; + strHostIFmsg.drvHandler = hWFIDrv; + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + PRINT_ER("Failed to send get host channel param's message queue "); + return WILC_FAIL; + } + + WILC_SemaphoreAcquire(&hWaitResponse, NULL); + return s32Error; +} + + +/** + * @brief host_int_scan + * @details scans a set of channels + * @param[in,out] handle to the wifi driver, + * @param[in] Scan source + * Scan Type PASSIVE_SCAN = 0, + * ACTIVE_SCAN = 1 + * Channels Array + * Channels Array length + * Scan Callback function + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 host_int_scan(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 u8ScanSource, + WILC_Uint8 u8ScanType, WILC_Uint8 *pu8ChnlFreqList, + WILC_Uint8 u8ChnlListLen, const WILC_Uint8 *pu8IEs, + size_t IEsLen, tWILCpfScanResult ScanResult, + void *pvUserArg, tstrHiddenNetwork *pstrHiddenNetwork) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + tenuScanConnTimer enuScanConnTimer; + + if (pstrWFIDrv == WILC_NULL || ScanResult == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + + /* prepare the Scan Message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + strHostIFmsg.u16MsgId = HOST_IF_MSG_SCAN; + + if (pstrHiddenNetwork != NULL) { + strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.strHiddenNetwork.pstrHiddenNetworkInfo = pstrHiddenNetwork->pstrHiddenNetworkInfo; + strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.strHiddenNetwork.u8ssidnum = pstrHiddenNetwork->u8ssidnum; + + } else + PRINT_D(HOSTINF_DBG, "pstrHiddenNetwork IS EQUAL TO NULL\n"); + + strHostIFmsg.drvHandler = hWFIDrv; + strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.u8ScanSource = u8ScanSource; + strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.u8ScanType = u8ScanType; + strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pfScanResult = ScanResult; + strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pvUserArg = pvUserArg; + + strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.u8ChnlListLen = u8ChnlListLen; + strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pu8ChnlFreqList = (WILC_Uint8 *)WILC_MALLOC(u8ChnlListLen); /* will be deallocated by the receiving thread */ + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pu8ChnlFreqList, + pu8ChnlFreqList, u8ChnlListLen); + + strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.IEsLen = IEsLen; + strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pu8IEs = (WILC_Uint8 *)WILC_MALLOC(IEsLen); /* will be deallocated by the receiving thread */ + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pu8IEs, + pu8IEs, IEsLen); + + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + PRINT_ER("Error in sending message queue scanning parameters: Error(%d)\n", s32Error); + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + + enuScanConnTimer = SCAN_TIMER; + PRINT_D(HOSTINF_DBG, ">> Starting the SCAN timer\n"); + WILC_TimerStart(&(pstrWFIDrv->hScanTimer), HOST_IF_SCAN_TIMEOUT, (void *) hWFIDrv, WILC_NULL); + + + WILC_CATCH(s32Error) + { + + } + return s32Error; + +} +/** + * @brief hif_set_cfg + * @details sets configuration wids values + * @param[in,out] handle to the wifi driver, + * @param[in] WID, WID value + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 hif_set_cfg(WILC_WFIDrvHandle hWFIDrv, tstrCfgParamVal *pstrCfgParamVal) +{ + + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + + tstrHostIFmsg strHostIFmsg; + + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + /* prepare the WiphyParams Message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + strHostIFmsg.u16MsgId = HOST_IF_MSG_CFG_PARAMS; + strHostIFmsg.uniHostIFmsgBody.strHostIFCfgParamAttr.pstrCfgParamVal = *pstrCfgParamVal; + strHostIFmsg.drvHandler = hWFIDrv; + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + + WILC_CATCH(s32Error) + { + } + + return s32Error; + +} + + +/** + * @brief hif_get_cfg + * @details gets configuration wids values + * @param[in,out] handle to the wifi driver, + * WID value + * @param[in] WID, + * @return Error code indicating success/failure + * @note + * @author zsalah + * + * @date 8 March 2012 + * @version 1.0 + */ +WILC_Sint32 hif_get_cfg(WILC_WFIDrvHandle hWFIDrv, WILC_Uint16 u16WID, WILC_Uint16 *pu16WID_Value) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + + WILC_SemaphoreAcquire(&(pstrWFIDrv->gtOsCfgValuesSem), NULL); + + if (pstrWFIDrv == WILC_NULL) { + PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n"); + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + PRINT_D(HOSTINF_DBG, "Getting configuration parameters\n"); + switch (u16WID) { + + case WID_BSS_TYPE: + *pu16WID_Value = (WILC_Uint16)pstrWFIDrv->strCfgValues.bss_type; + break; + + case WID_AUTH_TYPE: + *pu16WID_Value = (WILC_Uint16)pstrWFIDrv->strCfgValues.auth_type; + break; + + case WID_AUTH_TIMEOUT: + *pu16WID_Value = pstrWFIDrv->strCfgValues.auth_timeout; + break; + + case WID_POWER_MANAGEMENT: + *pu16WID_Value = (WILC_Uint16)pstrWFIDrv->strCfgValues.power_mgmt_mode; + break; + + case WID_SHORT_RETRY_LIMIT: + *pu16WID_Value = pstrWFIDrv->strCfgValues.short_retry_limit; + break; + + case WID_LONG_RETRY_LIMIT: + *pu16WID_Value = pstrWFIDrv->strCfgValues.long_retry_limit; + break; + + case WID_FRAG_THRESHOLD: + *pu16WID_Value = pstrWFIDrv->strCfgValues.frag_threshold; + break; + + case WID_RTS_THRESHOLD: + *pu16WID_Value = pstrWFIDrv->strCfgValues.rts_threshold; + break; + + case WID_PREAMBLE: + *pu16WID_Value = (WILC_Uint16)pstrWFIDrv->strCfgValues.preamble_type; + break; + + case WID_SHORT_SLOT_ALLOWED: + *pu16WID_Value = (WILC_Uint16) pstrWFIDrv->strCfgValues.short_slot_allowed; + break; + + case WID_11N_TXOP_PROT_DISABLE: + *pu16WID_Value = (WILC_Uint16)pstrWFIDrv->strCfgValues.txop_prot_disabled; + break; + + case WID_BEACON_INTERVAL: + *pu16WID_Value = pstrWFIDrv->strCfgValues.beacon_interval; + break; + + case WID_DTIM_PERIOD: + *pu16WID_Value = (WILC_Uint16)pstrWFIDrv->strCfgValues.dtim_period; + break; + + case WID_SITE_SURVEY: + *pu16WID_Value = (WILC_Uint16)pstrWFIDrv->strCfgValues.site_survey_enabled; + break; + + case WID_SITE_SURVEY_SCAN_TIME: + *pu16WID_Value = pstrWFIDrv->strCfgValues.site_survey_scan_time; + break; + + case WID_ACTIVE_SCAN_TIME: + *pu16WID_Value = pstrWFIDrv->strCfgValues.active_scan_time; + break; + + case WID_PASSIVE_SCAN_TIME: + *pu16WID_Value = pstrWFIDrv->strCfgValues.passive_scan_time; + break; + + case WID_CURRENT_TX_RATE: + *pu16WID_Value = pstrWFIDrv->strCfgValues.curr_tx_rate; + break; + + default: + break; + } + + WILC_SemaphoreRelease(&(pstrWFIDrv->gtOsCfgValuesSem), NULL); + + WILC_CATCH(s32Error) + { + } + return s32Error; + +} + +/*****************************************************************************/ +/* Notification Functions */ +/*****************************************************************************/ +/** + * @brief notifies host with join and leave requests + * @details This function prepares an Information frame having the + * information about a joining/leaving station. + * @param[in,out] handle to the wifi driver, + * @param[in] 6 byte Sta Adress + * Join or leave flag: + * Join = 1, + * Leave =0 + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +void host_int_send_join_leave_info_to_host + (WILC_Uint16 assocId, WILC_Uint8 *stationAddr, WILC_Bool joining) +{ +} +/** + * @brief notifies host with stations found in scan + * @details sends the beacon/probe response from scan + * @param[in,out] handle to the wifi driver, + * @param[in] Sta Address, + * Frame length, + * Rssi of the Station found + * @return Error code indicating success/failure + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ + +void GetPeriodicRSSI(void *pvArg) +{ + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)pvArg; + if (pstrWFIDrv == NULL) { + PRINT_ER("Driver handler is NULL\n"); + return; + } + + if (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTED) { + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrHostIFmsg strHostIFmsg; + + /* prepare the Get RSSI Message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_RSSI; + strHostIFmsg.drvHandler = pstrWFIDrv; + + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + PRINT_ER("Failed to send get host channel param's message queue "); + return; + } + } + WILC_TimerStart(&(g_hPeriodicRSSI), 5000, (void *)pstrWFIDrv, NULL); +} + + +void host_int_send_network_info_to_host + (WILC_Uint8 *macStartAddress, WILC_Uint16 u16RxFrameLen, WILC_Sint8 s8Rssi) +{ +} +/** + * @brief host_int_init + * @details host interface initialization function + * @param[in,out] handle to the wifi driver, + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ +static WILC_Uint32 u32Intialized; +static WILC_Uint32 msgQ_created; +static WILC_Uint32 clients_count; + +WILC_Sint32 host_int_init(WILC_WFIDrvHandle *phWFIDrv) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv; + tstrWILC_SemaphoreAttrs strSemaphoreAttrs; + + + /*if(u32Intialized == 1) + * { + * PRINT_D(HOSTINF_DBG,"Host interface is previously initialized\n"); + * *phWFIDrv = (WILC_WFIDrvHandle)gWFiDrvHandle; //Will be adjusted later for P2P + * return 0; + * } */ + PRINT_D(HOSTINF_DBG, "Initializing host interface for client %d\n", clients_count + 1); + + gbScanWhileConnected = WILC_FALSE; + + WILC_SemaphoreFillDefault(&strSemaphoreAttrs); + + + strSemaphoreAttrs.u32InitCount = 0; + WILC_SemaphoreCreate(&hWaitResponse, &strSemaphoreAttrs); + + + + /*Allocate host interface private structure*/ + pstrWFIDrv = (tstrWILC_WFIDrv *)WILC_MALLOC(sizeof(tstrWILC_WFIDrv)); + if (pstrWFIDrv == WILC_NULL) { + /* WILC_ERRORREPORT(s32Error,WILC_NO_MEM); */ + s32Error = WILC_NO_MEM; + PRINT_ER("Failed to allocate memory\n"); + goto _fail_timer_2; + } + WILC_memset(pstrWFIDrv, 0, sizeof(tstrWILC_WFIDrv)); + /*return driver handle to user*/ + *phWFIDrv = (WILC_WFIDrvHandle)pstrWFIDrv; + /*save into globl handle*/ + + #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP + + g_obtainingIP = WILC_FALSE; + #endif + + PRINT_D(HOSTINF_DBG, "Global handle pointer value=%x\n", (WILC_Uint32)pstrWFIDrv); + /* /////////////////////////////////////// */ + if (clients_count == 0) { + strSemaphoreAttrs.u32InitCount = 0; + WILC_SemaphoreCreate(&hSemHostIFthrdEnd, &strSemaphoreAttrs); + + strSemaphoreAttrs.u32InitCount = 0; + WILC_SemaphoreCreate(&hSemDeinitDrvHandle, &strSemaphoreAttrs); + + /*BugID_5348*/ + strSemaphoreAttrs.u32InitCount = 1; + WILC_SemaphoreCreate(&hSemHostIntDeinit, &strSemaphoreAttrs); + } + + strSemaphoreAttrs.u32InitCount = 0; + WILC_SemaphoreCreate(&(pstrWFIDrv->hSemTestKeyBlock), &strSemaphoreAttrs); + strSemaphoreAttrs.u32InitCount = 0; + WILC_SemaphoreCreate(&(pstrWFIDrv->hSemTestDisconnectBlock), &strSemaphoreAttrs); + strSemaphoreAttrs.u32InitCount = 0; + WILC_SemaphoreCreate(&(pstrWFIDrv->hSemGetRSSI), &strSemaphoreAttrs); + strSemaphoreAttrs.u32InitCount = 0; + WILC_SemaphoreCreate(&(pstrWFIDrv->hSemGetLINKSPEED), &strSemaphoreAttrs); + strSemaphoreAttrs.u32InitCount = 0; + WILC_SemaphoreCreate(&(pstrWFIDrv->hSemGetCHNL), &strSemaphoreAttrs); + strSemaphoreAttrs.u32InitCount = 0; + WILC_SemaphoreCreate(&(pstrWFIDrv->hSemInactiveTime), &strSemaphoreAttrs); + + /* /////////////////////////////////////// */ + + + + PRINT_D(HOSTINF_DBG, "INIT: CLIENT COUNT %d\n", clients_count); + + if (clients_count == 0) { + + s32Error = WILC_MsgQueueCreate(&gMsgQHostIF, WILC_NULL); + + + if (s32Error < 0) { + PRINT_ER("Failed to creat MQ\n"); + goto _fail_; + } + msgQ_created = 1; + s32Error = WILC_ThreadCreate(&HostIFthreadHandler, hostIFthread, WILC_NULL, WILC_NULL); + if (s32Error < 0) { + PRINT_ER("Failed to creat Thread\n"); + goto _fail_mq_; + } + s32Error = WILC_TimerCreate(&(g_hPeriodicRSSI), GetPeriodicRSSI, WILC_NULL); + if (s32Error < 0) { + PRINT_ER("Failed to creat Timer\n"); + goto _fail_timer_1; + } + WILC_TimerStart(&(g_hPeriodicRSSI), 5000, (void *)pstrWFIDrv, NULL); + + } + + + s32Error = WILC_TimerCreate(&(pstrWFIDrv->hScanTimer), TimerCB_Scan, WILC_NULL); + if (s32Error < 0) { + PRINT_ER("Failed to creat Timer\n"); + goto _fail_thread_; + } + + s32Error = WILC_TimerCreate(&(pstrWFIDrv->hConnectTimer), TimerCB_Connect, WILC_NULL); + if (s32Error < 0) { + PRINT_ER("Failed to creat Timer\n"); + goto _fail_timer_1; + } + + + #ifdef WILC_P2P + /*Remain on channel timer*/ + s32Error = WILC_TimerCreate(&(pstrWFIDrv->hRemainOnChannel), ListenTimerCB, WILC_NULL); + if (s32Error < 0) { + PRINT_ER("Failed to creat Remain-on-channel Timer\n"); + goto _fail_timer_3; + } + #endif + + WILC_SemaphoreCreate(&(pstrWFIDrv->gtOsCfgValuesSem), NULL); + WILC_SemaphoreAcquire(&(pstrWFIDrv->gtOsCfgValuesSem), NULL); + + + +#ifdef SIMULATION + TransportInit(); +#endif + + pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE; + /* gWFiDrvHandle->bPendingConnRequest = WILC_FALSE; */ + + /*Initialize CFG WIDS Defualt Values*/ + + pstrWFIDrv->strCfgValues.site_survey_enabled = SITE_SURVEY_OFF; + pstrWFIDrv->strCfgValues.scan_source = DEFAULT_SCAN; + pstrWFIDrv->strCfgValues.active_scan_time = ACTIVE_SCAN_TIME; + pstrWFIDrv->strCfgValues.passive_scan_time = PASSIVE_SCAN_TIME; + pstrWFIDrv->strCfgValues.curr_tx_rate = AUTORATE; + + + #ifdef WILC_P2P + + pstrWFIDrv->u64P2p_MgmtTimeout = 0; + + #endif + + PRINT_INFO(HOSTINF_DBG, "Initialization values, Site survey value: %d\n Scan source: %d\n Active scan time: %d\n Passive scan time: %d\nCurrent tx Rate = %d\n", + + pstrWFIDrv->strCfgValues.site_survey_enabled, pstrWFIDrv->strCfgValues.scan_source, + pstrWFIDrv->strCfgValues.active_scan_time, pstrWFIDrv->strCfgValues.passive_scan_time, + pstrWFIDrv->strCfgValues.curr_tx_rate); + + + WILC_SemaphoreRelease(&(pstrWFIDrv->gtOsCfgValuesSem), NULL); + + /*TODO Code to setup simulation to be removed later*/ + /*Intialize configurator module*/ + s32Error = CoreConfiguratorInit(); + if (s32Error < 0) { + PRINT_ER("Failed to initialize core configurator\n"); + goto _fail_mem_; + } + +#ifdef SIMULATION + /*Initialize Simulaor*/ + CoreConfigSimulatorInit(); +#endif + + u32Intialized = 1; + clients_count++; /* increase number of created entities */ + + return s32Error; + + +_fail_mem_: + if (pstrWFIDrv != WILC_NULL) + WILC_FREE(pstrWFIDrv); +#ifdef WILC_P2P +_fail_timer_3: + WILC_TimerDestroy(&(pstrWFIDrv->hRemainOnChannel), WILC_NULL); +#endif +_fail_timer_2: + WILC_SemaphoreRelease(&(pstrWFIDrv->gtOsCfgValuesSem), NULL); + WILC_TimerDestroy(&(pstrWFIDrv->hConnectTimer), WILC_NULL); +_fail_timer_1: + WILC_TimerDestroy(&(pstrWFIDrv->hScanTimer), WILC_NULL); +_fail_thread_: + WILC_ThreadDestroy(&HostIFthreadHandler, WILC_NULL); +_fail_mq_: + WILC_MsgQueueDestroy(&gMsgQHostIF, WILC_NULL); +_fail_: + return s32Error; + + +} +/** + * @brief host_int_deinit + * @details host interface initialization function + * @param[in,out] handle to the wifi driver, + * @note + * @author zsalah + * @date 8 March 2012 + * @version 1.0 + */ + +WILC_Sint32 host_int_deinit(WILC_WFIDrvHandle hWFIDrv) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrHostIFmsg strHostIFmsg; + + + /*obtain driver handle*/ + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + /*if(u32Intialized == 0) + * { + * PRINT_ER("Host Interface is not initialized\n"); + * return 0; + * }*/ + + /*BugID_5348*/ + + if (pstrWFIDrv == NULL) { + PRINT_ER("pstrWFIDrv = NULL\n"); + return 0; + } + + WILC_SemaphoreAcquire(&hSemHostIntDeinit, NULL); + + terminated_handle = pstrWFIDrv; + PRINT_D(HOSTINF_DBG, "De-initializing host interface for client %d\n", clients_count); + + /*BugID_5348*/ + /*Destroy all timers before acquiring hSemDeinitDrvHandle*/ + /*to guarantee handling all messages befor proceeding*/ + if (WILC_TimerDestroy(&(pstrWFIDrv->hScanTimer), WILC_NULL)) { + PRINT_D(HOSTINF_DBG, ">> Scan timer is active \n"); + /* msleep(HOST_IF_SCAN_TIMEOUT+1000); */ + } + + if (WILC_TimerDestroy(&(pstrWFIDrv->hConnectTimer), WILC_NULL)) { + PRINT_D(HOSTINF_DBG, ">> Connect timer is active \n"); + /* msleep(HOST_IF_CONNECT_TIMEOUT+1000); */ + } + + + if (WILC_TimerDestroy(&(g_hPeriodicRSSI), WILC_NULL)) { + PRINT_D(HOSTINF_DBG, ">> Connect timer is active \n"); + /* msleep(HOST_IF_CONNECT_TIMEOUT+1000); */ + } + + #ifdef WILC_P2P + /*Destroy Remain-onchannel Timer*/ + WILC_TimerDestroy(&(pstrWFIDrv->hRemainOnChannel), WILC_NULL); + #endif + + host_int_set_wfi_drv_handler((WILC_Uint32)WILC_NULL); + WILC_SemaphoreAcquire(&hSemDeinitDrvHandle, NULL); + + + /*Calling the CFG80211 scan done function with the abort flag set to true*/ + if (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult) { + pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult(SCAN_EVENT_ABORTED, WILC_NULL, + pstrWFIDrv->strWILC_UsrScanReq.u32UserScanPvoid, NULL); + + pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult = WILC_NULL; + } + /*deinit configurator and simulator*/ +#ifdef SIMULATION + CoreConfigSimulatorDeInit(); +#endif + CoreConfiguratorDeInit(); +#ifdef SIMULATION + TransportDeInit(); +#endif + + pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE; + + gbScanWhileConnected = WILC_FALSE; + + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + if (clients_count == 1) { + if (WILC_TimerDestroy(&g_hPeriodicRSSI, WILC_NULL)) { + PRINT_D(HOSTINF_DBG, ">> Connect timer is active \n"); + /* msleep(HOST_IF_CONNECT_TIMEOUT+1000); */ + } + strHostIFmsg.u16MsgId = HOST_IF_MSG_EXIT; + strHostIFmsg.drvHandler = hWFIDrv; + + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error != WILC_SUCCESS) { + PRINT_ER("Error in sending deinit's message queue message function: Error(%d)\n", s32Error); + } + + WILC_SemaphoreAcquire(&hSemHostIFthrdEnd, NULL); + + + + WILC_MsgQueueDestroy(&gMsgQHostIF, WILC_NULL); + msgQ_created = 0; + + + WILC_SemaphoreDestroy(&hSemHostIFthrdEnd, NULL); + WILC_SemaphoreDestroy(&hSemDeinitDrvHandle, NULL); + + } + + WILC_SemaphoreDestroy(&(pstrWFIDrv->hSemTestKeyBlock), NULL); + WILC_SemaphoreDestroy(&(pstrWFIDrv->hSemTestDisconnectBlock), NULL); + WILC_SemaphoreDestroy(&(pstrWFIDrv->hSemGetRSSI), NULL); + WILC_SemaphoreDestroy(&(pstrWFIDrv->hSemGetLINKSPEED), NULL); + WILC_SemaphoreDestroy(&(pstrWFIDrv->hSemGetCHNL), NULL); + WILC_SemaphoreDestroy(&(pstrWFIDrv->hSemInactiveTime), NULL); + WILC_SemaphoreDestroy(&hWaitResponse, NULL); + + WILC_SemaphoreAcquire(&(pstrWFIDrv->gtOsCfgValuesSem), NULL); + WILC_SemaphoreDestroy(&(pstrWFIDrv->gtOsCfgValuesSem), NULL); + + /*Setting the gloabl driver handler with NULL*/ + u32Intialized = 0; + /* gWFiDrvHandle = NULL; */ + if (pstrWFIDrv != WILC_NULL) { + WILC_FREE(pstrWFIDrv); + /* pstrWFIDrv=WILC_NULL; */ + + } + + clients_count--; /* Decrease number of created entities */ + terminated_handle = WILC_NULL; + WILC_SemaphoreRelease(&hSemHostIntDeinit, NULL); + return s32Error; +} + + +/** + * @brief NetworkInfoReceived + * @details function to to be called when network info packet is received + * @param[in] pu8Buffer the received packet + * @param[in] u32Length length of the received packet + * @return none + * @note + * @author + * @date 1 Mar 2012 + * @version 1.0 + */ +void NetworkInfoReceived(WILC_Uint8 *pu8Buffer, WILC_Uint32 u32Length) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrHostIFmsg strHostIFmsg; + WILC_Uint32 drvHandler; + tstrWILC_WFIDrv *pstrWFIDrv = WILC_NULL; + + drvHandler = ((pu8Buffer[u32Length - 4]) | (pu8Buffer[u32Length - 3] << 8) | (pu8Buffer[u32Length - 2] << 16) | (pu8Buffer[u32Length - 1] << 24)); + pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + + + + if (pstrWFIDrv == WILC_NULL || pstrWFIDrv == terminated_handle) { + PRINT_ER("NetworkInfo received but driver not init[%x]\n", (WILC_Uint32)pstrWFIDrv); + return; + } + + /* prepare the Asynchronous Network Info message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + strHostIFmsg.u16MsgId = HOST_IF_MSG_RCVD_NTWRK_INFO; + strHostIFmsg.drvHandler = pstrWFIDrv; + + strHostIFmsg.uniHostIFmsgBody.strRcvdNetworkInfo.u32Length = u32Length; + strHostIFmsg.uniHostIFmsgBody.strRcvdNetworkInfo.pu8Buffer = (WILC_Uint8 *)WILC_MALLOC(u32Length); /* will be deallocated by the receiving thread */ + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strRcvdNetworkInfo.pu8Buffer, + pu8Buffer, u32Length); + + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + PRINT_ER("Error in sending network info message queue message parameters: Error(%d)\n", s32Error); + } + + + return; +} + +/** + * @brief GnrlAsyncInfoReceived + * @details function to be called when general Asynchronous info packet is received + * @param[in] pu8Buffer the received packet + * @param[in] u32Length length of the received packet + * @return none + * @note + * @author + * @date 15 Mar 2012 + * @version 1.0 + */ +void GnrlAsyncInfoReceived(WILC_Uint8 *pu8Buffer, WILC_Uint32 u32Length) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrHostIFmsg strHostIFmsg; + WILC_Uint32 drvHandler; + tstrWILC_WFIDrv *pstrWFIDrv = WILC_NULL; + + /*BugID_5348*/ + WILC_SemaphoreAcquire(&hSemHostIntDeinit, NULL); + + drvHandler = ((pu8Buffer[u32Length - 4]) | (pu8Buffer[u32Length - 3] << 8) | (pu8Buffer[u32Length - 2] << 16) | (pu8Buffer[u32Length - 1] << 24)); + pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + PRINT_D(HOSTINF_DBG, "General asynchronous info packet received \n"); + + + if (pstrWFIDrv == NULL || pstrWFIDrv == terminated_handle) { + PRINT_D(HOSTINF_DBG, "Wifi driver handler is equal to NULL\n"); + /*BugID_5348*/ + WILC_SemaphoreRelease(&hSemHostIntDeinit, NULL); + return; + } + + if (pstrWFIDrv->strWILC_UsrConnReq.pfUserConnectResult == WILC_NULL) { + /* received mac status is not needed when there is no current Connect Request */ + PRINT_ER("Received mac status is not needed when there is no current Connect Reques\n"); + /*BugID_5348*/ + WILC_SemaphoreRelease(&hSemHostIntDeinit, NULL); + return; + } + + /* prepare the General Asynchronous Info message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + + strHostIFmsg.u16MsgId = HOST_IF_MSG_RCVD_GNRL_ASYNC_INFO; + strHostIFmsg.drvHandler = pstrWFIDrv; + + + strHostIFmsg.uniHostIFmsgBody.strRcvdGnrlAsyncInfo.u32Length = u32Length; + strHostIFmsg.uniHostIFmsgBody.strRcvdGnrlAsyncInfo.pu8Buffer = (WILC_Uint8 *)WILC_MALLOC(u32Length); /* will be deallocated by the receiving thread */ + WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strRcvdGnrlAsyncInfo.pu8Buffer, + pu8Buffer, u32Length); + + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + PRINT_ER("Error in sending message queue asynchronous message info: Error(%d)\n", s32Error); + } + + /*BugID_5348*/ + WILC_SemaphoreRelease(&hSemHostIntDeinit, NULL); + return; +} + +/** + * @brief host_int_ScanCompleteReceived + * @details Setting scan complete received notifcation in message queue + * @param[in] WILC_Uint8* pu8Buffer, WILC_Uint32 u32Length + * @return Error code. + * @author + * @date + * @version 1.0 + */ +void host_int_ScanCompleteReceived(WILC_Uint8 *pu8Buffer, WILC_Uint32 u32Length) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrHostIFmsg strHostIFmsg; + WILC_Uint32 drvHandler; + tstrWILC_WFIDrv *pstrWFIDrv = WILC_NULL; + drvHandler = ((pu8Buffer[u32Length - 4]) | (pu8Buffer[u32Length - 3] << 8) | (pu8Buffer[u32Length - 2] << 16) | (pu8Buffer[u32Length - 1] << 24)); + pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler; + + + PRINT_D(GENERIC_DBG, "Scan notification received %x\n", (WILC_Uint32)pstrWFIDrv); + + if (pstrWFIDrv == NULL || pstrWFIDrv == terminated_handle) { + return; + } + + /*if there is an ongoing scan request*/ + if (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult) { + /* prepare theScan Done message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + strHostIFmsg.u16MsgId = HOST_IF_MSG_RCVD_SCAN_COMPLETE; + strHostIFmsg.drvHandler = pstrWFIDrv; + + + /* will be deallocated by the receiving thread */ + /*no need to send message body*/ + + /*strHostIFmsg.uniHostIFmsgBody.strScanComplete.u32Length = u32Length; + * strHostIFmsg.uniHostIFmsgBody.strScanComplete.pu8Buffer = (WILC_Uint8*)WILC_MALLOC(u32Length); + * WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strScanComplete.pu8Buffer, + * pu8Buffer, u32Length); */ + + /* send the message */ + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + PRINT_ER("Error in sending message queue scan complete parameters: Error(%d)\n", s32Error); + } + } + + + return; + +} + +#ifdef WILC_P2P +/** + * @brief host_int_remain_on_channel + * @details + * @param[in] Handle to wifi driver + * Duration to remain on channel + * Channel to remain on + * Pointer to fn to be called on receive frames in listen state + * Pointer to remain-on-channel expired fn + * Priv + * @return Error code. + * @author + * @date + * @version 1.0 + */ +WILC_Sint32 host_int_remain_on_channel(WILC_WFIDrvHandle hWFIDrv, WILC_Uint32 u32SessionID, WILC_Uint32 u32duration, WILC_Uint16 chan, tWILCpfRemainOnChanExpired RemainOnChanExpired, tWILCpfRemainOnChanReady RemainOnChanReady, void *pvUserArg) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + /* prepare the remainonchan Message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + /* prepare the WiphyParams Message */ + strHostIFmsg.u16MsgId = HOST_IF_MSG_REMAIN_ON_CHAN; + strHostIFmsg.uniHostIFmsgBody.strHostIfRemainOnChan.u16Channel = chan; + strHostIFmsg.uniHostIFmsgBody.strHostIfRemainOnChan.pRemainOnChanExpired = RemainOnChanExpired; + strHostIFmsg.uniHostIFmsgBody.strHostIfRemainOnChan.pRemainOnChanReady = RemainOnChanReady; + strHostIFmsg.uniHostIFmsgBody.strHostIfRemainOnChan.pVoid = pvUserArg; + strHostIFmsg.uniHostIFmsgBody.strHostIfRemainOnChan.u32duration = u32duration; + strHostIFmsg.uniHostIFmsgBody.strHostIfRemainOnChan.u32ListenSessionID = u32SessionID; + strHostIFmsg.drvHandler = hWFIDrv; + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + WILC_ERRORREPORT(s32Error, s32Error); + } + WILC_CATCH(s32Error) + { + + } + + return s32Error; +} + +/** + * @brief host_int_ListenStateExpired + * @details + * @param[in] Handle to wifi driver + * Duration to remain on channel + * Channel to remain on + * Pointer to fn to be called on receive frames in listen state + * Pointer to remain-on-channel expired fn + * Priv + * @return Error code. + * @author + * @date + * @version 1.0 + */ +WILC_Sint32 host_int_ListenStateExpired(WILC_WFIDrvHandle hWFIDrv, WILC_Uint32 u32SessionID) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + /*Stopping remain-on-channel timer*/ + WILC_TimerStop(&(pstrWFIDrv->hRemainOnChannel), WILC_NULL); + + /* prepare the timer fire Message */ + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + strHostIFmsg.u16MsgId = HOST_IF_MSG_LISTEN_TIMER_FIRED; + strHostIFmsg.drvHandler = hWFIDrv; + strHostIFmsg.uniHostIFmsgBody.strHostIfRemainOnChan.u32ListenSessionID = u32SessionID; + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + WILC_ERRORREPORT(s32Error, s32Error); + } + WILC_CATCH(s32Error) + { + + } + return s32Error; +} + +/** + * @brief host_int_frame_register + * @details + * @param[in] Handle to wifi driver + * @return Error code. + * @author + * @date + * @version 1.0*/ +WILC_Sint32 host_int_frame_register(WILC_WFIDrvHandle hWFIDrv, WILC_Uint16 u16FrameType, WILC_Bool bReg) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + /* prepare the WiphyParams Message */ + strHostIFmsg.u16MsgId = HOST_IF_MSG_REGISTER_FRAME; + switch (u16FrameType) { + case ACTION: + PRINT_D(HOSTINF_DBG, "ACTION\n"); + strHostIFmsg.uniHostIFmsgBody.strHostIfRegisterFrame.u8Regid = ACTION_FRM_IDX; + break; + + case PROBE_REQ: + PRINT_D(HOSTINF_DBG, "PROBE REQ\n"); + strHostIFmsg.uniHostIFmsgBody.strHostIfRegisterFrame.u8Regid = PROBE_REQ_IDX; + break; + + default: + PRINT_D(HOSTINF_DBG, "Not valid frame type\n"); + break; + } + strHostIFmsg.uniHostIFmsgBody.strHostIfRegisterFrame.u16FrameType = u16FrameType; + strHostIFmsg.uniHostIFmsgBody.strHostIfRegisterFrame.bReg = bReg; + strHostIFmsg.drvHandler = hWFIDrv; + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + WILC_ERRORREPORT(s32Error, s32Error); + } + WILC_CATCH(s32Error) + { + + } + + return s32Error; + + +} +#endif + +#ifdef WILC_AP_EXTERNAL_MLME +/** + * @brief host_int_add_beacon + * @details Setting add beacon params in message queue + * @param[in] WILC_WFIDrvHandle hWFIDrv, WILC_Uint32 u32Interval, + * WILC_Uint32 u32DTIMPeriod,WILC_Uint32 u32HeadLen, WILC_Uint8* pu8Head, + * WILC_Uint32 u32TailLen, WILC_Uint8* pu8Tail + * @return Error code. + * @author + * @date + * @version 1.0 + */ +WILC_Sint32 host_int_add_beacon(WILC_WFIDrvHandle hWFIDrv, WILC_Uint32 u32Interval, + WILC_Uint32 u32DTIMPeriod, + WILC_Uint32 u32HeadLen, WILC_Uint8 *pu8Head, + WILC_Uint32 u32TailLen, WILC_Uint8 *pu8Tail) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + tstrHostIFSetBeacon *pstrSetBeaconParam = &strHostIFmsg.uniHostIFmsgBody.strHostIFSetBeacon; + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + PRINT_D(HOSTINF_DBG, "Setting adding beacon message queue params\n"); + + + /* prepare the WiphyParams Message */ + strHostIFmsg.u16MsgId = HOST_IF_MSG_ADD_BEACON; + strHostIFmsg.drvHandler = hWFIDrv; + pstrSetBeaconParam->u32Interval = u32Interval; + pstrSetBeaconParam->u32DTIMPeriod = u32DTIMPeriod; + pstrSetBeaconParam->u32HeadLen = u32HeadLen; + pstrSetBeaconParam->pu8Head = (WILC_Uint8 *)WILC_MALLOC(u32HeadLen); + if (pstrSetBeaconParam->pu8Head == NULL) { + WILC_ERRORREPORT(s32Error, WILC_NO_MEM); + } + WILC_memcpy(pstrSetBeaconParam->pu8Head, pu8Head, u32HeadLen); + pstrSetBeaconParam->u32TailLen = u32TailLen; + + /* Bug 4599 : if tail length = 0 skip allocating & copying */ + if (u32TailLen > 0) { + pstrSetBeaconParam->pu8Tail = (WILC_Uint8 *)WILC_MALLOC(u32TailLen); + if (pstrSetBeaconParam->pu8Tail == NULL) { + WILC_ERRORREPORT(s32Error, WILC_NO_MEM); + } + WILC_memcpy(pstrSetBeaconParam->pu8Tail, pu8Tail, u32TailLen); + } else { + pstrSetBeaconParam->pu8Tail = NULL; + } + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + WILC_ERRORREPORT(s32Error, s32Error); + } + + WILC_CATCH(s32Error) + { + if (pstrSetBeaconParam->pu8Head != NULL) { + WILC_FREE(pstrSetBeaconParam->pu8Head); + } + + if (pstrSetBeaconParam->pu8Tail != NULL) { + WILC_FREE(pstrSetBeaconParam->pu8Tail); + } + } + + return s32Error; + +} + + +/** + * @brief host_int_del_beacon + * @details Setting add beacon params in message queue + * @param[in] WILC_WFIDrvHandle hWFIDrv + * @return Error code. + * @author + * @date + * @version 1.0 + */ +WILC_Sint32 host_int_del_beacon(WILC_WFIDrvHandle hWFIDrv) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + /* prepare the WiphyParams Message */ + strHostIFmsg.u16MsgId = HOST_IF_MSG_DEL_BEACON; + strHostIFmsg.drvHandler = hWFIDrv; + PRINT_D(HOSTINF_DBG, "Setting deleting beacon message queue params\n"); + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + WILC_ERRORCHECK(s32Error); + + WILC_CATCH(s32Error) + { + } + return s32Error; +} + + +/** + * @brief host_int_add_station + * @details Setting add station params in message queue + * @param[in] WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam* pstrStaParams + * @return Error code. + * @author + * @date + * @version 1.0 + */ +WILC_Sint32 host_int_add_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrStaParams) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + tstrWILC_AddStaParam *pstrAddStationMsg = &strHostIFmsg.uniHostIFmsgBody.strAddStaParam; + + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + PRINT_D(HOSTINF_DBG, "Setting adding station message queue params\n"); + + + /* prepare the WiphyParams Message */ + strHostIFmsg.u16MsgId = HOST_IF_MSG_ADD_STATION; + strHostIFmsg.drvHandler = hWFIDrv; + + WILC_memcpy(pstrAddStationMsg, pstrStaParams, sizeof(tstrWILC_AddStaParam)); + if (pstrAddStationMsg->u8NumRates > 0) { + pstrAddStationMsg->pu8Rates = WILC_MALLOC(pstrAddStationMsg->u8NumRates); + WILC_NULLCHECK(s32Error, pstrAddStationMsg->pu8Rates); + + WILC_memcpy(pstrAddStationMsg->pu8Rates, pstrStaParams->pu8Rates, pstrAddStationMsg->u8NumRates); + } + + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + WILC_ERRORREPORT(s32Error, s32Error); + } + + WILC_CATCH(s32Error) + { + } + return s32Error; +} + +/** + * @brief host_int_del_station + * @details Setting delete station params in message queue + * @param[in] WILC_WFIDrvHandle hWFIDrv, WILC_Uint8* pu8MacAddr + * @return Error code. + * @author + * @date + * @version 1.0 + */ +WILC_Sint32 host_int_del_station(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 *pu8MacAddr) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + tstrHostIFDelSta *pstrDelStationMsg = &strHostIFmsg.uniHostIFmsgBody.strDelStaParam; + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + PRINT_D(HOSTINF_DBG, "Setting deleting station message queue params\n"); + + + + /* prepare the WiphyParams Message */ + strHostIFmsg.u16MsgId = HOST_IF_MSG_DEL_STATION; + strHostIFmsg.drvHandler = hWFIDrv; + + /*BugID_4795: Handling situation of deleting all stations*/ + if (pu8MacAddr == WILC_NULL) + WILC_memset(pstrDelStationMsg->au8MacAddr, 255, ETH_ALEN); + else + WILC_memcpy(pstrDelStationMsg->au8MacAddr, pu8MacAddr, ETH_ALEN); + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + WILC_ERRORREPORT(s32Error, s32Error); + } + + WILC_CATCH(s32Error) + { + } + return s32Error; +} +/** + * @brief host_int_del_allstation + * @details Setting del station params in message queue + * @param[in] WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 pu8MacAddr[][ETH_ALEN]s + * @return Error code. + * @author + * @date + * @version 1.0 + */ +WILC_Sint32 host_int_del_allstation(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 pu8MacAddr[][ETH_ALEN]) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + tstrHostIFDelAllSta *pstrDelAllStationMsg = &strHostIFmsg.uniHostIFmsgBody.strHostIFDelAllSta; + WILC_Uint8 au8Zero_Buff[ETH_ALEN] = {0}; + WILC_Uint32 i; + WILC_Uint8 u8AssocNumb = 0; + + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + PRINT_D(HOSTINF_DBG, "Setting deauthenticating station message queue params\n"); + + /* prepare the WiphyParams Message */ + strHostIFmsg.u16MsgId = HOST_IF_MSG_DEL_ALL_STA; + strHostIFmsg.drvHandler = hWFIDrv; + + /* Handling situation of deauthenticing all associated stations*/ + for (i = 0; i < MAX_NUM_STA; i++) { + if (memcmp(pu8MacAddr[i], au8Zero_Buff, ETH_ALEN)) { + WILC_memcpy(pstrDelAllStationMsg->au8Sta_DelAllSta[i], pu8MacAddr[i], ETH_ALEN); + PRINT_D(CFG80211_DBG, "BSSID = %x%x%x%x%x%x\n", pstrDelAllStationMsg->au8Sta_DelAllSta[i][0], pstrDelAllStationMsg->au8Sta_DelAllSta[i][1], pstrDelAllStationMsg->au8Sta_DelAllSta[i][2], pstrDelAllStationMsg->au8Sta_DelAllSta[i][3], pstrDelAllStationMsg->au8Sta_DelAllSta[i][4], + pstrDelAllStationMsg->au8Sta_DelAllSta[i][5]); + u8AssocNumb++; + } + } + if (!u8AssocNumb) { + PRINT_D(CFG80211_DBG, "NO ASSOCIATED STAS\n"); + return s32Error; + } + + pstrDelAllStationMsg->u8Num_AssocSta = u8AssocNumb; + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + + + if (s32Error) { + WILC_ERRORREPORT(s32Error, s32Error); + + } + WILC_CATCH(s32Error) + { + + } + WILC_SemaphoreAcquire(&hWaitResponse, NULL); + + return s32Error; + +} + +/** + * @brief host_int_edit_station + * @details Setting edit station params in message queue + * @param[in] WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam* pstrStaParams + * @return Error code. + * @author + * @date + * @version 1.0 + */ +WILC_Sint32 host_int_edit_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrStaParams) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + tstrWILC_AddStaParam *pstrAddStationMsg = &strHostIFmsg.uniHostIFmsgBody.strAddStaParam; + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + PRINT_D(HOSTINF_DBG, "Setting editing station message queue params\n"); + + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + + /* prepare the WiphyParams Message */ + strHostIFmsg.u16MsgId = HOST_IF_MSG_EDIT_STATION; + strHostIFmsg.drvHandler = hWFIDrv; + + WILC_memcpy(pstrAddStationMsg, pstrStaParams, sizeof(tstrWILC_AddStaParam)); + if (pstrAddStationMsg->u8NumRates > 0) { + pstrAddStationMsg->pu8Rates = WILC_MALLOC(pstrAddStationMsg->u8NumRates); + WILC_memcpy(pstrAddStationMsg->pu8Rates, pstrStaParams->pu8Rates, pstrAddStationMsg->u8NumRates); + WILC_NULLCHECK(s32Error, pstrAddStationMsg->pu8Rates); + } + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + WILC_ERRORREPORT(s32Error, s32Error); + } + WILC_CATCH(s32Error) + { + } + return s32Error; +} +#endif /*WILC_AP_EXTERNAL_MLME*/ +uint32_t wilc_get_chipid(uint8_t); + +WILC_Sint32 host_int_set_power_mgmt(WILC_WFIDrvHandle hWFIDrv, WILC_Bool bIsEnabled, WILC_Uint32 u32Timeout) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + tstrHostIfPowerMgmtParam *pstrPowerMgmtParam = &strHostIFmsg.uniHostIFmsgBody.strPowerMgmtparam; + + PRINT_INFO(HOSTINF_DBG, "\n\n>> Setting PS to %d << \n\n", bIsEnabled); + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + PRINT_D(HOSTINF_DBG, "Setting Power management message queue params\n"); + + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + + /* prepare the WiphyParams Message */ + strHostIFmsg.u16MsgId = HOST_IF_MSG_POWER_MGMT; + strHostIFmsg.drvHandler = hWFIDrv; + + pstrPowerMgmtParam->bIsEnabled = bIsEnabled; + pstrPowerMgmtParam->u32Timeout = u32Timeout; + + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + WILC_ERRORREPORT(s32Error, s32Error); + } + WILC_CATCH(s32Error) + { + } + return s32Error; +} + +WILC_Sint32 host_int_setup_multicast_filter(WILC_WFIDrvHandle hWFIDrv, WILC_Bool bIsEnabled, WILC_Uint32 u32count) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + tstrHostIFSetMulti *pstrMulticastFilterParam = &strHostIFmsg.uniHostIFmsgBody.strHostIfSetMulti; + + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + PRINT_D(HOSTINF_DBG, "Setting Multicast Filter params\n"); + + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + + /* prepare the WiphyParams Message */ + strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_MULTICAST_FILTER; + strHostIFmsg.drvHandler = hWFIDrv; + + pstrMulticastFilterParam->bIsEnabled = bIsEnabled; + pstrMulticastFilterParam->u32count = u32count; + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + WILC_ERRORREPORT(s32Error, s32Error); + } + WILC_CATCH(s32Error) + { + } + return s32Error; +} + + + +/*Bug4218: Parsing Join Param*/ +#ifdef WILC_PARSE_SCAN_IN_HOST + +/*Bug4218: Parsing Join Param*/ +/** + * @brief host_int_ParseJoinBssParam + * @details Parse Needed Join Parameters and save it in a new JoinBssParam entry + * @param[in] tstrNetworkInfo* ptstrNetworkInfo + * @return + * @author zsalah + * @date + * @version 1.0**/ +static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo) +{ + tstrJoinBssParam *pNewJoinBssParam = NULL; + WILC_Uint8 *pu8IEs; + WILC_Uint16 u16IEsLen; + WILC_Uint16 index = 0; + WILC_Uint8 suppRatesNo = 0; + WILC_Uint8 extSuppRatesNo; + WILC_Uint16 jumpOffset; + WILC_Uint8 pcipherCount; + WILC_Uint8 authCount; + WILC_Uint8 pcipherTotalCount = 0; + WILC_Uint8 authTotalCount = 0; + WILC_Uint8 i, j; + + pu8IEs = ptstrNetworkInfo->pu8IEs; + u16IEsLen = ptstrNetworkInfo->u16IEsLen; + + pNewJoinBssParam = WILC_MALLOC(sizeof(tstrJoinBssParam)); + if (pNewJoinBssParam != NULL) { + WILC_memset(pNewJoinBssParam, 0, sizeof(tstrJoinBssParam)); + pNewJoinBssParam->dtim_period = ptstrNetworkInfo->u8DtimPeriod; + pNewJoinBssParam->beacon_period = ptstrNetworkInfo->u16BeaconPeriod; + pNewJoinBssParam->cap_info = ptstrNetworkInfo->u16CapInfo; + WILC_memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->au8bssid, 6); + /*for(i=0; i<6;i++) + * PRINT_D(HOSTINF_DBG,"%c",pNewJoinBssParam->au8bssid[i]);*/ + WILC_memcpy((WILC_Uint8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->au8ssid, ptstrNetworkInfo->u8SsidLen + 1); + pNewJoinBssParam->ssidLen = ptstrNetworkInfo->u8SsidLen; + WILC_memset(pNewJoinBssParam->rsn_pcip_policy, 0xFF, 3); + WILC_memset(pNewJoinBssParam->rsn_auth_policy, 0xFF, 3); + /*for(i=0; issidLen;i++) + * PRINT_D(HOSTINF_DBG,"%c",pNewJoinBssParam->ssid[i]);*/ + + /* parse supported rates: */ + while (index < u16IEsLen) { + /* supportedRates IE */ + if (pu8IEs[index] == SUPP_RATES_IE) { + /* PRINT_D(HOSTINF_DBG, "Supported Rates\n"); */ + suppRatesNo = pu8IEs[index + 1]; + pNewJoinBssParam->supp_rates[0] = suppRatesNo; + index += 2; /* skipping ID and length bytes; */ + + for (i = 0; i < suppRatesNo; i++) { + pNewJoinBssParam->supp_rates[i + 1] = pu8IEs[index + i]; + /* PRINT_D(HOSTINF_DBG,"%0x ",pNewJoinBssParam->supp_rates[i+1]); */ + } + index += suppRatesNo; + continue; + } + /* Ext SupportedRates IE */ + else if (pu8IEs[index] == EXT_SUPP_RATES_IE) { + /* PRINT_D(HOSTINF_DBG, "Extended Supported Rates\n"); */ + /* checking if no of ext. supp and supp rates < max limit */ + extSuppRatesNo = pu8IEs[index + 1]; + if (extSuppRatesNo > (MAX_RATES_SUPPORTED - suppRatesNo)) + pNewJoinBssParam->supp_rates[0] = MAX_RATES_SUPPORTED; + else + pNewJoinBssParam->supp_rates[0] += extSuppRatesNo; + index += 2; + /* pNewJoinBssParam.supp_rates[0] contains now old number not the ext. no */ + for (i = 0; i < (pNewJoinBssParam->supp_rates[0] - suppRatesNo); i++) { + pNewJoinBssParam->supp_rates[suppRatesNo + i + 1] = pu8IEs[index + i]; + /* PRINT_D(HOSTINF_DBG,"%0x ",pNewJoinBssParam->supp_rates[suppRatesNo+i+1]); */ + } + index += extSuppRatesNo; + continue; + } + /* HT Cap. IE */ + else if (pu8IEs[index] == HT_CAPABILITY_IE) { + /* if IE found set the flag */ + pNewJoinBssParam->ht_capable = BTRUE; + index += pu8IEs[index + 1] + 2; /* ID,Length bytes and IE body */ + /* PRINT_D(HOSTINF_DBG,"HT_CAPABALE\n"); */ + continue; + } else if ((pu8IEs[index] == WMM_IE) && /* WMM Element ID */ + (pu8IEs[index + 2] == 0x00) && (pu8IEs[index + 3] == 0x50) && + (pu8IEs[index + 4] == 0xF2) && /* OUI */ + (pu8IEs[index + 5] == 0x02) && /* OUI Type */ + ((pu8IEs[index + 6] == 0x00) || (pu8IEs[index + 6] == 0x01)) && /* OUI Sub Type */ + (pu8IEs[index + 7] == 0x01)) { + /* Presence of WMM Info/Param element indicates WMM capability */ + pNewJoinBssParam->wmm_cap = BTRUE; + + /* Check if Bit 7 is set indicating U-APSD capability */ + if (pu8IEs[index + 8] & (1 << 7)) { + pNewJoinBssParam->uapsd_cap = BTRUE; + } + index += pu8IEs[index + 1] + 2; + continue; + } + #ifdef WILC_P2P + else if ((pu8IEs[index] == P2P_IE) && /* P2P Element ID */ + (pu8IEs[index + 2] == 0x50) && (pu8IEs[index + 3] == 0x6f) && + (pu8IEs[index + 4] == 0x9a) && /* OUI */ + (pu8IEs[index + 5] == 0x09) && (pu8IEs[index + 6] == 0x0c)) { /* OUI Type */ + WILC_Uint16 u16P2P_count; + pNewJoinBssParam->tsf = ptstrNetworkInfo->u32Tsf; + pNewJoinBssParam->u8NoaEnbaled = 1; + pNewJoinBssParam->u8Index = pu8IEs[index + 9]; + + /* Check if Bit 7 is set indicating Opss capability */ + if (pu8IEs[index + 10] & (1 << 7)) { + pNewJoinBssParam->u8OppEnable = 1; + pNewJoinBssParam->u8CtWindow = pu8IEs[index + 10]; + } else + pNewJoinBssParam->u8OppEnable = 0; + /* HOSTINF_DBG */ + PRINT_D(GENERIC_DBG, "P2P Dump \n"); + for (i = 0; i < pu8IEs[index + 7]; i++) + PRINT_D(GENERIC_DBG, " %x \n", pu8IEs[index + 9 + i]); + + pNewJoinBssParam->u8Count = pu8IEs[index + 11]; + u16P2P_count = index + 12; + + WILC_memcpy(pNewJoinBssParam->au8Duration, pu8IEs + u16P2P_count, 4); + u16P2P_count += 4; + + WILC_memcpy(pNewJoinBssParam->au8Interval, pu8IEs + u16P2P_count, 4); + u16P2P_count += 4; + + WILC_memcpy(pNewJoinBssParam->au8StartTime, pu8IEs + u16P2P_count, 4); + + index += pu8IEs[index + 1] + 2; + continue; + + } + #endif + else if ((pu8IEs[index] == RSN_IE) || + ((pu8IEs[index] == WPA_IE) && (pu8IEs[index + 2] == 0x00) && + (pu8IEs[index + 3] == 0x50) && (pu8IEs[index + 4] == 0xF2) && + (pu8IEs[index + 5] == 0x01))) { + WILC_Uint16 rsnIndex = index; + /*PRINT_D(HOSTINF_DBG,"RSN IE Length:%d\n",pu8IEs[rsnIndex+1]); + * for(i=0; imode_802_11i = 2; + /* PRINT_D(HOSTINF_DBG,"\nRSN_IE\n"); */ + } else { /* check if rsn was previously parsed */ + if (pNewJoinBssParam->mode_802_11i == 0) + pNewJoinBssParam->mode_802_11i = 1; + /* PRINT_D(HOSTINF_DBG,"\nWPA_IE\n"); */ + rsnIndex += 4; + } + rsnIndex += 7; /* skipping id, length, version(2B) and first 3 bytes of gcipher */ + pNewJoinBssParam->rsn_grp_policy = pu8IEs[rsnIndex]; + rsnIndex++; + /* PRINT_D(HOSTINF_DBG,"Group Policy: %0x \n",pNewJoinBssParam->rsn_grp_policy); */ + /* initialize policies with invalid values */ + + jumpOffset = pu8IEs[rsnIndex] * 4; /* total no.of bytes of pcipher field (count*4) */ + + /*parsing pairwise cipher*/ + + /* saving 3 pcipher max. */ + pcipherCount = (pu8IEs[rsnIndex] > 3) ? 3 : pu8IEs[rsnIndex]; + rsnIndex += 2; /* jump 2 bytes of pcipher count */ + + /* PRINT_D(HOSTINF_DBG,"\npcipher:%d \n",pcipherCount); */ + for (i = pcipherTotalCount, j = 0; i < pcipherCount + pcipherTotalCount && i < 3; i++, j++) { + /* each count corresponds to 4 bytes, only last byte is saved */ + pNewJoinBssParam->rsn_pcip_policy[i] = pu8IEs[rsnIndex + ((j + 1) * 4) - 1]; + /* PRINT_D(HOSTINF_DBG,"PAIR policy = [%0x,%0x]\n",pNewJoinBssParam->rsn_pcip_policy[i],i); */ + } + pcipherTotalCount += pcipherCount; + rsnIndex += jumpOffset; + + jumpOffset = pu8IEs[rsnIndex] * 4; + + /*parsing AKM suite (auth_policy)*/ + /* saving 3 auth policies max. */ + authCount = (pu8IEs[rsnIndex] > 3) ? 3 : pu8IEs[rsnIndex]; + rsnIndex += 2; /* jump 2 bytes of pcipher count */ + + for (i = authTotalCount, j = 0; i < authTotalCount + authCount; i++, j++) { + /* each count corresponds to 4 bytes, only last byte is saved */ + pNewJoinBssParam->rsn_auth_policy[i] = pu8IEs[rsnIndex + ((j + 1) * 4) - 1]; + } + authTotalCount += authCount; + rsnIndex += jumpOffset; + /*pasring rsn cap. only if rsn IE*/ + if (pu8IEs[index] == RSN_IE) { + pNewJoinBssParam->rsn_cap[0] = pu8IEs[rsnIndex]; + pNewJoinBssParam->rsn_cap[1] = pu8IEs[rsnIndex + 1]; + rsnIndex += 2; + } + pNewJoinBssParam->rsn_found = 1; + index += pu8IEs[index + 1] + 2; /* ID,Length bytes and IE body */ + continue; + } else + index += pu8IEs[index + 1] + 2; /* ID,Length bytes and IE body */ + + } + + + } + + return (void *)pNewJoinBssParam; + +} + +void host_int_freeJoinParams(void *pJoinParams) +{ + if ((tstrJoinBssParam *)pJoinParams != NULL) + WILC_FREE((tstrJoinBssParam *)pJoinParams); + else + PRINT_ER("Unable to FREE null pointer\n"); +} +#endif /*WILC_PARSE_SCAN_IN_HOST*/ + + +/** + * @brief host_int_addBASession + * @details Open a block Ack session with the given parameters + * @param[in] tstrNetworkInfo* ptstrNetworkInfo + * @return + * @author anoureldin + * @date + * @version 1.0**/ + +static int host_int_addBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID, short int BufferSize, + short int SessionTimeout, void *drvHandler) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + tstrHostIfBASessionInfo *pBASessionInfo = &strHostIFmsg.uniHostIFmsgBody.strHostIfBASessionInfo; + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + /* prepare the WiphyParams Message */ + strHostIFmsg.u16MsgId = HOST_IF_MSG_ADD_BA_SESSION; + + memcpy(pBASessionInfo->au8Bssid, pBSSID, ETH_ALEN); + pBASessionInfo->u8Ted = TID; + pBASessionInfo->u16BufferSize = BufferSize; + pBASessionInfo->u16SessionTimeout = SessionTimeout; + strHostIFmsg.drvHandler = hWFIDrv; + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + WILC_ERRORREPORT(s32Error, s32Error); + } + WILC_CATCH(s32Error) + { + + } + + return s32Error; +} + + +WILC_Sint32 host_int_delBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + tstrHostIfBASessionInfo *pBASessionInfo = &strHostIFmsg.uniHostIFmsgBody.strHostIfBASessionInfo; + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + /* prepare the WiphyParams Message */ + strHostIFmsg.u16MsgId = HOST_IF_MSG_DEL_BA_SESSION; + + memcpy(pBASessionInfo->au8Bssid, pBSSID, ETH_ALEN); + pBASessionInfo->u8Ted = TID; + strHostIFmsg.drvHandler = hWFIDrv; + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + WILC_ERRORREPORT(s32Error, s32Error); + } + WILC_CATCH(s32Error) + { + + } + + /*BugID_5222*/ + WILC_SemaphoreAcquire(&hWaitResponse, NULL); + + return s32Error; +} + +WILC_Sint32 host_int_del_All_Rx_BASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + tstrHostIfBASessionInfo *pBASessionInfo = &strHostIFmsg.uniHostIFmsgBody.strHostIfBASessionInfo; + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + /* prepare the WiphyParams Message */ + strHostIFmsg.u16MsgId = HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS; + + memcpy(pBASessionInfo->au8Bssid, pBSSID, ETH_ALEN); + pBASessionInfo->u8Ted = TID; + strHostIFmsg.drvHandler = hWFIDrv; + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + WILC_ERRORREPORT(s32Error, s32Error); + } + WILC_CATCH(s32Error) + { + + } + + /*BugID_5222*/ + WILC_SemaphoreAcquire(&hWaitResponse, NULL); + + return s32Error; +} + +/** + * @brief host_int_setup_ipaddress + * @details setup IP in firmware + * @param[in] Handle to wifi driver + * @return Error code. + * @author Abdelrahman Sobhy + * @date + * @version 1.0*/ +WILC_Sint32 host_int_setup_ipaddress(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 *u16ipadd, WILC_Uint8 idx) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + + /* TODO: Enable This feature on softap firmware */ + return 0; + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + /* prepare the WiphyParams Message */ + strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_IPADDRESS; + + strHostIFmsg.uniHostIFmsgBody.strHostIfSetIP.au8IPAddr = u16ipadd; + strHostIFmsg.drvHandler = hWFIDrv; + strHostIFmsg.uniHostIFmsgBody.strHostIfSetIP.idx = idx; + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + WILC_ERRORREPORT(s32Error, s32Error); + } + WILC_CATCH(s32Error) + { + + } + + return s32Error; + + +} + +/** + * @brief host_int_get_ipaddress + * @details Get IP from firmware + * @param[in] Handle to wifi driver + * @return Error code. + * @author Abdelrahman Sobhy + * @date + * @version 1.0*/ +WILC_Sint32 host_int_get_ipaddress(WILC_WFIDrvHandle hWFIDrv, WILC_Uint8 *u16ipadd, WILC_Uint8 idx) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; + tstrHostIFmsg strHostIFmsg; + + if (pstrWFIDrv == WILC_NULL) { + WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); + } + + WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + + /* prepare the WiphyParams Message */ + strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_IPADDRESS; + + strHostIFmsg.uniHostIFmsgBody.strHostIfSetIP.au8IPAddr = u16ipadd; + strHostIFmsg.drvHandler=hWFIDrv; + strHostIFmsg.uniHostIFmsgBody.strHostIfSetIP.idx= idx; + + s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), WILC_NULL); + if (s32Error) { + WILC_ERRORREPORT(s32Error, s32Error); + } + WILC_CATCH(s32Error) + { + + } + + return s32Error; + + +} + diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h new file mode 100644 index 000000000000..f2a348506a8b --- /dev/null +++ b/drivers/staging/wilc1000/host_interface.h @@ -0,0 +1,1344 @@ +/*! + * @file host_interface.h + * @brief File containg host interface APIs + * @author zsalah + * @sa host_interface.c + * @date 8 March 2012 + * @version 1.0 + */ + +#ifndef HOST_INT_H +#define HOST_INT_H + +#include "coreconfigurator.h" +#include "coreconfigsimulator.h" +/*****************************************************************************/ +/* Macros */ +/*****************************************************************************/ +#if 0 +#define WID_BSS_TYPE 0x0000 +#define WID_CURRENT_TX_RATE 0x0001 +#define WID_CURRENT_CHANNEL 0x0002 +#define WID_PREAMBLE 0x0003 +#define WID_STATUS 0x0005 +#define WID_SCAN_TYPE 0x0007 +#define WID_KEY_ID 0x0009 +#define WID_DTIM_PERIOD 0x0010 +#define WID_POWER_MANAGEMENT 0x000B +#define WID_AUTH_TYPE 0x000D +#define WID_SITE_SURVEY 0x000E +#define WID_DTIM_PERIOD 0x0010 +#define WID_DISCONNECT 0x0016 +#define WID_SHORT_SLOT_ALLOWED 0x001A +#define WID_START_SCAN_REQ 0x001E +#define WID_RSSI 0x001F +#define WID_JOIN_REQ 0x0020 +#define WID_11N_TXOP_PROT_DISABLE 0x00B0 +#define WID_RTS_THRESHOLD 0x1000 +#define WID_FRAG_THRESHOLD 0x1001 +#define WID_SHORT_RETRY_LIMIT 0x1002 +#define WID_LONG_RETRY_LIMIT 0x1003 +#define WID_BEACON_INTERVAL 0x1006 +#define WID_ACTIVE_SCAN_TIME 0x100C +#define WID_PASSIVE_SCAN_TIME 0x100D +#define WID_SITE_SURVEY_SCAN_TIME 0x100E +#define WID_AUTH_TIMEOUT 0x1010 +#define WID_11I_PSK 0x3008 +#define WID_SITE_SURVEY_RESULTS 0x3012 +#define WID_ADD_PTK 0x301B +#define WID_ADD_RX_GTK 0x301C +#define WID_ADD_TX_GTK 0x301D +#define WID_ADD_WEP_KEY 0x3019 +#define WID_REMOVE_WEP_KEY 0x301A +#define WID_REMOVE_KEY 0x301E +#define WID_ASSOC_REQ_INFO 0x301F +#define WID_ASSOC_RES_INFO 0x3020 +#define WID_PMKID_INFO 0x3082 +#define WID_SCAN_CHANNEL_LIST 0x4084 +#define WID_11I_MODE 0x000C +#endif +#define FAIL 0x0000 +#define SUCCESS 0x0001 + +#define IP_ALEN 4 + +#define BIT2 ((WILC_Uint32)(1 << 2)) +#define BIT1 ((WILC_Uint32)(1 << 1)) +#define BIT0 ((WILC_Uint32)(1 << 0)) + +#define AP_MODE 0x01 +#define STATION_MODE 0x02 +#define GO_MODE 0x03 +#define CLIENT_MODE 0x04 + + +#define MAX_NUM_STA 9 +#define ACTIVE_SCAN_TIME 10 +#define PASSIVE_SCAN_TIME 1200 +#define MIN_SCAN_TIME 10 +#define MAX_SCAN_TIME 1200 +#define DEFAULT_SCAN 0 +#define USER_SCAN BIT0 +#define OBSS_PERIODIC_SCAN BIT1 +#define OBSS_ONETIME_SCAN BIT2 +#define GTK_RX_KEY_BUFF_LEN 24 +#define ADDKEY 0x1 +#define REMOVEKEY 0x2 +#define DEFAULTKEY 0x4 +#define ADDKEY_AP 0x8 +#define MAX_NUM_SCANNED_NETWORKS 100 /* 30 // rachel */ +#define MAX_NUM_SCANNED_NETWORKS_SHADOW 130 +#define MAX_NUM_PROBED_SSID 10 /*One more than the number of scanned ssids*/ +#define CHANNEL_SCAN_TIME 250 /* 250 */ + +#define TX_MIC_KEY_LEN 8 +#define RX_MIC_KEY_LEN 8 +#define PTK_KEY_LEN 16 + +#define TX_MIC_KEY_MSG_LEN 26 +#define RX_MIC_KEY_MSG_LEN 48 +#define PTK_KEY_MSG_LEN 39 + +#define PMKSA_KEY_LEN 22 +#define ETH_ALEN 6 +#define PMKID_LEN 16 +#define WILC_MAX_NUM_PMKIDS 16 +#define WILC_SUPP_MCS_SET_SIZE 16 +#define WILC_ADD_STA_LENGTH 40 /* Not including the rates field cause it has variable length*/ +#define SCAN_EVENT_DONE_ABORTED +/*****************************************************************************/ +/* Data Types */ +/*****************************************************************************/ +/* typedef unsigned char uint8; */ +/* typedef signed char int8; */ +/* typedef unsigned short uint16; */ +/* typedef unsigned long uint32; */ +/* typedef uint32 Bool; */ + +#if 0 +typedef enum {WID_CHAR = 0, + WID_SHORT = 1, + WID_INT = 2, + WID_STR = 3, + WID_ADR = 4, + WID_BIN = 5, + WID_IP = 6, + WID_UNDEF = 7} WID_TYPE_T; +#endif +typedef struct { + WILC_Uint16 cfg_wid; + WID_TYPE_T cfg_type; + WILC_Sint8 *pu8Para; +} cfg_param_t; + +typedef struct _tstrStatistics { + WILC_Uint8 u8LinkSpeed; + WILC_Sint8 s8RSSI; + WILC_Uint32 u32TxCount; + WILC_Uint32 u32RxCount; + WILC_Uint32 u32TxFailureCount; + +} tstrStatistics; + + +typedef enum { + HOST_IF_IDLE = 0, + HOST_IF_SCANNING = 1, + HOST_IF_CONNECTING = 2, + HOST_IF_WAITING_CONN_RESP = 3, + HOST_IF_CONNECTED = 4, + HOST_IF_P2P_LISTEN = 5, + HOST_IF_FORCE_32BIT = 0xFFFFFFFF +} tenuHostIFstate; + +typedef struct _tstrHostIFpmkid { + WILC_Uint8 bssid[ETH_ALEN]; + WILC_Uint8 pmkid[PMKID_LEN]; +} tstrHostIFpmkid; + +typedef struct _tstrHostIFpmkidAttr { + WILC_Uint8 numpmkid; + tstrHostIFpmkid pmkidlist[WILC_MAX_NUM_PMKIDS]; +} tstrHostIFpmkidAttr; +#if 0 +/* Scan type parameter for scan request */ +typedef enum { + PASSIVE_SCAN = 0, + ACTIVE_SCAN = 1, + NUM_SCANTYPE +} tenuScanType; + +typedef enum {SITE_SURVEY_1CH = 0, + SITE_SURVEY_ALL_CH = 1, + SITE_SURVEY_OFF = 2} SITE_SURVEY_T; +#endif +typedef enum { + AUTORATE = 0, + MBPS_1 = 1, + MBPS_2 = 2, + MBPS_5_5 = 5, + MBPS_11 = 11, + MBPS_6 = 6, + MBPS_9 = 9, + MBPS_12 = 12, + MBPS_18 = 18, + MBPS_24 = 24, + MBPS_36 = 36, + MBPS_48 = 48, + MBPS_54 = 54 +} CURRENT_TX_RATE_T; + +typedef struct { + WILC_Uint32 u32SetCfgFlag; + WILC_Uint8 ht_enable; + WILC_Uint8 bss_type; + WILC_Uint8 auth_type; + WILC_Uint16 auth_timeout; + WILC_Uint8 power_mgmt_mode; + WILC_Uint16 short_retry_limit; + WILC_Uint16 long_retry_limit; + WILC_Uint16 frag_threshold; + WILC_Uint16 rts_threshold; + WILC_Uint16 preamble_type; + WILC_Uint8 short_slot_allowed; + WILC_Uint8 txop_prot_disabled; + WILC_Uint16 beacon_interval; + WILC_Uint16 dtim_period; + SITE_SURVEY_T site_survey_enabled; + WILC_Uint16 site_survey_scan_time; + WILC_Uint8 scan_source; + WILC_Uint16 active_scan_time; + WILC_Uint16 passive_scan_time; + CURRENT_TX_RATE_T curr_tx_rate; + +} tstrCfgParamVal; + +typedef enum { + RETRY_SHORT = 1 << 0, + RETRY_LONG = 1 << 1, + FRAG_THRESHOLD = 1 << 2, + RTS_THRESHOLD = 1 << 3, + BSS_TYPE = 1 << 4, + AUTH_TYPE = 1 << 5, + AUTHEN_TIMEOUT = 1 << 6, + POWER_MANAGEMENT = 1 << 7, + PREAMBLE = 1 << 8, + SHORT_SLOT_ALLOWED = 1 << 9, + TXOP_PROT_DISABLE = 1 << 10, + BEACON_INTERVAL = 1 << 11, + DTIM_PERIOD = 1 << 12, + SITE_SURVEY = 1 << 13, + SITE_SURVEY_SCAN_TIME = 1 << 14, + ACTIVE_SCANTIME = 1 << 15, + PASSIVE_SCANTIME = 1 << 16, + CURRENT_TX_RATE = 1 << 17, + HT_ENABLE = 1 << 18, +} tenuCfgParam; + +typedef struct { + WILC_Uint8 au8bssid[6]; + WILC_Sint8 s8rssi; +} tstrFoundNetworkInfo; + +typedef enum {SCAN_EVENT_NETWORK_FOUND = 0, + SCAN_EVENT_DONE = 1, + SCAN_EVENT_ABORTED = 2, + SCAN_EVENT_FORCE_32BIT = 0xFFFFFFFF} tenuScanEvent; + +typedef enum { + CONN_DISCONN_EVENT_CONN_RESP = 0, + CONN_DISCONN_EVENT_DISCONN_NOTIF = 1, + CONN_DISCONN_EVENT_FORCE_32BIT = 0xFFFFFFFF +} tenuConnDisconnEvent; + +typedef enum { + WEP, + WPARxGtk, + /* WPATxGtk, */ + WPAPtk, + PMKSA, +} tenuKeyType; + + +/*Scan callBack function definition*/ +typedef void (*tWILCpfScanResult)(tenuScanEvent, tstrNetworkInfo *, void *, void *); + +/*Connect callBack function definition*/ +typedef void (*tWILCpfConnectResult)(tenuConnDisconnEvent, + tstrConnectInfo *, + WILC_Uint8, + tstrDisconnectNotifInfo *, + void *); + +#ifdef WILC_P2P +typedef void (*tWILCpfRemainOnChanExpired)(void *, WILC_Uint32); /*Remain on channel expiration callback function*/ +typedef void (*tWILCpfRemainOnChanReady)(void *); /*Remain on channel callback function*/ +#endif + +/* typedef WILC_Uint32 WILC_WFIDrvHandle; */ +typedef struct { + WILC_Sint32 s32Dummy; +} *WILC_WFIDrvHandle; + +/*! + * @struct tstrRcvdNetworkInfo + * @brief Structure to hold Received Asynchronous Network info + * @details + * @todo + * @sa + * @author Mostafa Abu Bakr + * @date 25 March 2012 + * @version 1.0 + */ +typedef struct _tstrRcvdNetworkInfo { + WILC_Uint8 *pu8Buffer; + WILC_Uint32 u32Length; +} tstrRcvdNetworkInfo; + +/*BugID_4156*/ +typedef struct _tstrHiddenNetworkInfo { + WILC_Uint8 *pu8ssid; + WILC_Uint8 u8ssidlen; + +} tstrHiddenNetworkInfo; + +typedef struct _tstrHiddenNetwork { + /* MAX_SSID_LEN */ + tstrHiddenNetworkInfo *pstrHiddenNetworkInfo; + WILC_Uint8 u8ssidnum; + +} tstrHiddenNetwork; + +typedef struct { + /* Scan user call back function */ + tWILCpfScanResult pfUserScanResult; + + /* User specific parameter to be delivered through the Scan User Callback function */ + void *u32UserScanPvoid; + + WILC_Uint32 u32RcvdChCount; + tstrFoundNetworkInfo astrFoundNetworkInfo[MAX_NUM_SCANNED_NETWORKS]; +} tstrWILC_UsrScanReq; + +typedef struct { + WILC_Uint8 *pu8bssid; + WILC_Uint8 *pu8ssid; + WILC_Uint8 u8security; + AUTHTYPE_T tenuAuth_type; + size_t ssidLen; + WILC_Uint8 *pu8ConnReqIEs; + size_t ConnReqIEsLen; + /* Connect user call back function */ + tWILCpfConnectResult pfUserConnectResult; + WILC_Bool IsHTCapable; + /* User specific parameter to be delivered through the Connect User Callback function */ + void *u32UserConnectPvoid; +} tstrWILC_UsrConnReq; + +typedef struct { + WILC_Uint32 u32Address; +} tstrHostIfSetDrvHandler; + +typedef struct { + WILC_Uint32 u32Mode; +} tstrHostIfSetOperationMode; + +/*BugID_5077*/ +typedef struct { + WILC_Uint8 u8MacAddress[ETH_ALEN]; +} tstrHostIfSetMacAddress; + +/*BugID_5213*/ +typedef struct { + WILC_Uint8 *u8MacAddress; +} tstrHostIfGetMacAddress; + +/*BugID_5222*/ +typedef struct { + WILC_Uint8 au8Bssid[ETH_ALEN]; + WILC_Uint8 u8Ted; + WILC_Uint16 u16BufferSize; + WILC_Uint16 u16SessionTimeout; +} tstrHostIfBASessionInfo; + +#ifdef WILC_P2P +typedef struct { + WILC_Uint16 u16Channel; + WILC_Uint32 u32duration; + tWILCpfRemainOnChanExpired pRemainOnChanExpired; + tWILCpfRemainOnChanReady pRemainOnChanReady; + void *pVoid; + WILC_Uint32 u32ListenSessionID; +} tstrHostIfRemainOnChan; + +typedef struct { + + WILC_Bool bReg; + WILC_Uint16 u16FrameType; + WILC_Uint8 u8Regid; + + +} tstrHostIfRegisterFrame; + + +#define ACTION 0xD0 +#define PROBE_REQ 0x40 +#define PROBE_RESP 0x50 +#define ACTION_FRM_IDX 0 +#define PROBE_REQ_IDX 1 + + +enum p2p_listen_state { + P2P_IDLE, + P2P_LISTEN, + P2P_GRP_FORMATION +}; + +#endif +typedef struct { + /* Scan user structure */ + tstrWILC_UsrScanReq strWILC_UsrScanReq; + + /* Connect User structure */ + tstrWILC_UsrConnReq strWILC_UsrConnReq; + + #ifdef WILC_P2P + /*Remain on channel struvture*/ + tstrHostIfRemainOnChan strHostIfRemainOnChan; + WILC_Uint8 u8RemainOnChan_pendingreq; + WILC_Uint64 u64P2p_MgmtTimeout; + WILC_Uint8 u8P2PConnect; + #endif + + tenuHostIFstate enuHostIFstate; + + /* WILC_Bool bPendingConnRequest; */ + + #ifndef CONNECT_DIRECT + WILC_Uint32 u32SurveyResultsCount; + wid_site_survey_reslts_s astrSurveyResults[MAX_NUM_SCANNED_NETWORKS]; + #endif + + WILC_Uint8 au8AssociatedBSSID[ETH_ALEN]; + tstrCfgParamVal strCfgValues; +/* semaphores */ + WILC_SemaphoreHandle gtOsCfgValuesSem; + WILC_SemaphoreHandle hSemTestKeyBlock; + + WILC_SemaphoreHandle hSemTestDisconnectBlock; + WILC_SemaphoreHandle hSemGetRSSI; + WILC_SemaphoreHandle hSemGetLINKSPEED; + WILC_SemaphoreHandle hSemGetCHNL; + WILC_SemaphoreHandle hSemInactiveTime; +/* timer handlers */ + WILC_TimerHandle hScanTimer; + WILC_TimerHandle hConnectTimer; + #ifdef WILC_P2P + WILC_TimerHandle hRemainOnChannel; + #endif + + WILC_Bool IFC_UP; +} tstrWILC_WFIDrv; + +/*! + * @enum tenuWILC_StaFlag + * @brief Used to decode the station flag set and mask in tstrWILC_AddStaParam + * @details + * @todo + * @sa tstrWILC_AddStaParam, enum nl80211_sta_flags + * @author Enumeraion's creator + * @date 12 July 2012 + * @version 1.0 Description + */ + +typedef enum { + WILC_STA_FLAG_INVALID = 0, + WILC_STA_FLAG_AUTHORIZED, /*!< station is authorized (802.1X)*/ + WILC_STA_FLAG_SHORT_PREAMBLE, /*!< station is capable of receiving frames with short barker preamble*/ + WILC_STA_FLAG_WME, /*!< station is WME/QoS capable*/ + WILC_STA_FLAG_MFP, /*!< station uses management frame protection*/ + WILC_STA_FLAG_AUTHENTICATED /*!< station is authenticated*/ +} tenuWILC_StaFlag; + +typedef struct { + WILC_Uint8 au8BSSID[ETH_ALEN]; + WILC_Uint16 u16AssocID; + WILC_Uint8 u8NumRates; + WILC_Uint8 *pu8Rates; + WILC_Bool bIsHTSupported; + WILC_Uint16 u16HTCapInfo; + WILC_Uint8 u8AmpduParams; + WILC_Uint8 au8SuppMCsSet[16]; + WILC_Uint16 u16HTExtParams; + WILC_Uint32 u32TxBeamformingCap; + WILC_Uint8 u8ASELCap; + WILC_Uint16 u16FlagsMask; /**/ + WILC_Uint16 u16FlagsSet; /*> 22) & 0x1ff) + +void WILC_WFI_monitor_rx(uint8_t *buff, uint32_t size) +{ + uint32_t header, pkt_offset; + struct sk_buff *skb = NULL; + struct wilc_wfi_radiotap_hdr *hdr; + struct wilc_wfi_radiotap_cb_hdr *cb_hdr; + + PRINT_INFO(HOSTAPD_DBG, "In monitor interface receive function\n"); + + /* struct WILC_WFI_priv *priv = netdev_priv(dev); */ + + /* priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy); */ + + /* Bug 4601 */ + if (wilc_wfi_mon == NULL) + return; + + if (!netif_running(wilc_wfi_mon)) { + PRINT_INFO(HOSTAPD_DBG, "Monitor interface already RUNNING\n"); + return; + } + + /* Get WILC header */ + memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET); + + /* The packet offset field conain info about what type of managment frame */ + /* we are dealing with and ack status */ + pkt_offset = GET_PKT_OFFSET(header); + + if (pkt_offset & IS_MANAGMEMENT_CALLBACK) { + + /* hostapd callback mgmt frame */ + + skb = dev_alloc_skb(size + sizeof(struct wilc_wfi_radiotap_cb_hdr)); + if (skb == NULL) { + PRINT_INFO(HOSTAPD_DBG, "Monitor if : No memory to allocate skb"); + return; + } + + memcpy(skb_put(skb, size), buff, size); + + cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb, sizeof(*cb_hdr)); + memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr)); + + cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */ + + cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr)); + + cb_hdr->hdr.it_present = cpu_to_le32( + (1 << IEEE80211_RADIOTAP_RATE) | + (1 << IEEE80211_RADIOTAP_TX_FLAGS)); + + cb_hdr->rate = 5; /* txrate->bitrate / 5; */ + + if (pkt_offset & IS_MGMT_STATUS_SUCCES) { + /* success */ + cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_RTS; + } else { + cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_FAIL; + } + + } else { + + skb = dev_alloc_skb(size + sizeof(struct wilc_wfi_radiotap_hdr)); + + if (skb == NULL) { + PRINT_INFO(HOSTAPD_DBG, "Monitor if : No memory to allocate skb"); + return; + } + + /* skb = skb_copy_expand(tx_skb, sizeof(*hdr), 0, GFP_ATOMIC); */ + /* if (skb == NULL) */ + /* return; */ + + memcpy(skb_put(skb, size), buff, size); + hdr = (struct wilc_wfi_radiotap_hdr *) skb_push(skb, sizeof(*hdr)); + memset(hdr, 0, sizeof(struct wilc_wfi_radiotap_hdr)); + hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */ + /* hdr->hdr.it_pad = 0; */ + hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_hdr)); + PRINT_INFO(HOSTAPD_DBG, "Radiotap len %d\n", hdr->hdr.it_len); + hdr->hdr.it_present = cpu_to_le32 + (1 << IEEE80211_RADIOTAP_RATE); /* | */ + /* (1 << IEEE80211_RADIOTAP_CHANNEL)); */ + PRINT_INFO(HOSTAPD_DBG, "Presentflags %d\n", hdr->hdr.it_present); + hdr->rate = 5; /* txrate->bitrate / 5; */ + + } + +/* if(INFO || if(skb->data[9] == 0x00 || skb->data[9] == 0xb0)) + * { + * for(i=0;ilen;i++) + * PRINT_INFO(HOSTAPD_DBG,"Mon RxData[%d] = %02x\n",i,skb->data[i]); + * }*/ + + + skb->dev = wilc_wfi_mon; + skb_set_mac_header(skb, 0); + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = htons(ETH_P_802_2); + memset(skb->cb, 0, sizeof(skb->cb)); + + netif_rx(skb); + + +} + +struct tx_complete_mon_data { + int size; + void *buff; +}; + +static void mgmt_tx_complete(void *priv, int status) +{ + + /* struct sk_buff *skb2; */ + /* struct wilc_wfi_radiotap_cb_hdr *cb_hdr; */ + + struct tx_complete_mon_data *pv_data = (struct tx_complete_mon_data *)priv; + WILC_Uint8 *buf = pv_data->buff; + + + + if (status == 1) { + if (INFO || buf[0] == 0x10 || buf[0] == 0xb0) + PRINT_INFO(HOSTAPD_DBG, "Packet sent successfully - Size = %d - Address = %p.\n", pv_data->size, pv_data->buff); + } else { + PRINT_INFO(HOSTAPD_DBG, "Couldn't send packet - Size = %d - Address = %p.\n", pv_data->size, pv_data->buff); + } + + +/* //(skb->data[9] == 0x00 || skb->data[9] == 0xb0 || skb->data[9] == 0x40 || skb->data[9] == 0xd0 ) + * { + * skb2 = dev_alloc_skb(pv_data->size+sizeof(struct wilc_wfi_radiotap_cb_hdr)); + * + * memcpy(skb_put(skb2,pv_data->size),pv_data->buff, pv_data->size); + * + * cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb2, sizeof(*cb_hdr)); + * memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr)); + * + * cb_hdr->hdr.it_version = 0;//PKTHDR_RADIOTAP_VERSION; + * + * cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr)); + * + * cb_hdr->hdr.it_present = cpu_to_le32( + * (1 << IEEE80211_RADIOTAP_RATE) | + * (1 << IEEE80211_RADIOTAP_TX_FLAGS)); + * + * cb_hdr->rate = 5;//txrate->bitrate / 5; + * cb_hdr->tx_flags = 0x0004; + * + * skb2->dev = wilc_wfi_mon; + * skb_set_mac_header(skb2, 0); + * skb2->ip_summed = CHECKSUM_UNNECESSARY; + * skb2->pkt_type = PACKET_OTHERHOST; + * skb2->protocol = htons(ETH_P_802_2); + * memset(skb2->cb, 0, sizeof(skb2->cb)); + * + * netif_rx(skb2); + * }*/ + + /* incase of fully hosting mode, the freeing will be done in response to the cfg packet */ + #ifndef WILC_FULLY_HOSTING_AP + kfree(pv_data->buff); + + kfree(pv_data); + #endif +} +static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len) +{ + linux_wlan_t *nic; + struct tx_complete_mon_data *mgmt_tx = NULL; + + if (dev == NULL) { + PRINT_D(HOSTAPD_DBG, "ERROR: dev == NULL\n"); + return WILC_FAIL; + } + nic = netdev_priv(dev); + + netif_stop_queue(dev); + mgmt_tx = (struct tx_complete_mon_data *)kmalloc(sizeof(struct tx_complete_mon_data), GFP_ATOMIC); + if (mgmt_tx == NULL) { + PRINT_ER("Failed to allocate memory for mgmt_tx structure\n"); + return WILC_FAIL; + } + + #ifdef WILC_FULLY_HOSTING_AP + /* add space for the pointer to tx_complete_mon_data */ + len += sizeof(struct tx_complete_mon_data *); + #endif + + mgmt_tx->buff = (char *)kmalloc(len, GFP_ATOMIC); + if (mgmt_tx->buff == NULL) { + PRINT_ER("Failed to allocate memory for mgmt_tx buff\n"); + return WILC_FAIL; + + } + + mgmt_tx->size = len; + + #ifndef WILC_FULLY_HOSTING_AP + memcpy(mgmt_tx->buff, buf, len); + #else + memcpy(mgmt_tx->buff, buf, len - sizeof(struct tx_complete_mon_data *)); + memcpy((mgmt_tx->buff) + (len - sizeof(struct tx_complete_mon_data *)), &mgmt_tx, sizeof(struct tx_complete_mon_data *)); + + /* filter data frames to handle it's PS */ + if (filter_monitor_data_frames((mgmt_tx->buff), len) == WILC_TRUE) { + return; + } + + #endif /* WILC_FULLY_HOSTING_AP */ + + g_linux_wlan->oup.wlan_add_mgmt_to_tx_que(mgmt_tx, mgmt_tx->buff, mgmt_tx->size, mgmt_tx_complete); + + netif_wake_queue(dev); + return 0; +} + +/** + * @brief WILC_WFI_mon_xmit + * @details + * @param[in] + * @return int : Return 0 on Success + * @author mdaftedar + * @date 12 JUL 2012 + * @version 1.0 + */ +static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct ieee80211_radiotap_header *rtap_hdr; + WILC_Uint32 rtap_len, i, ret = 0; + struct WILC_WFI_mon_priv *mon_priv; + + struct sk_buff *skb2; + struct wilc_wfi_radiotap_cb_hdr *cb_hdr; + + /* Bug 4601 */ + if (wilc_wfi_mon == NULL) + return WILC_FAIL; + + /* if(skb->data[3] == 0x10 || skb->data[3] == 0xb0) */ + + mon_priv = netdev_priv(wilc_wfi_mon); + + if (mon_priv == NULL) { + PRINT_ER("Monitor interface private structure is NULL\n"); + return WILC_FAIL; + } + + rtap_hdr = (struct ieee80211_radiotap_header *)skb->data; + + rtap_len = ieee80211_get_radiotap_len(skb->data); + if (skb->len < rtap_len) { + PRINT_ER("Error in radiotap header\n"); + return -1; + } + /* skip the radiotap header */ + PRINT_INFO(HOSTAPD_DBG, "Radiotap len: %d\n", rtap_len); + + if (INFO) { + for (i = 0; i < rtap_len; i++) + PRINT_INFO(HOSTAPD_DBG, "Radiotap_hdr[%d] %02x\n", i, skb->data[i]); + } + /* Skip the ratio tap header */ + skb_pull(skb, rtap_len); + + if (skb->data[0] == 0xc0) + PRINT_INFO(HOSTAPD_DBG, "%x:%x:%x:%x:%x%x\n", skb->data[4], skb->data[5], skb->data[6], skb->data[7], skb->data[8], skb->data[9]); + + if (skb->data[0] == 0xc0 && (!(memcmp(broadcast, &skb->data[4], 6)))) { + skb2 = dev_alloc_skb(skb->len + sizeof(struct wilc_wfi_radiotap_cb_hdr)); + + memcpy(skb_put(skb2, skb->len), skb->data, skb->len); + + cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb2, sizeof(*cb_hdr)); + memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr)); + + cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */ + + cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr)); + + cb_hdr->hdr.it_present = cpu_to_le32( + (1 << IEEE80211_RADIOTAP_RATE) | + (1 << IEEE80211_RADIOTAP_TX_FLAGS)); + + cb_hdr->rate = 5; /* txrate->bitrate / 5; */ + cb_hdr->tx_flags = 0x0004; + + skb2->dev = wilc_wfi_mon; + skb_set_mac_header(skb2, 0); + skb2->ip_summed = CHECKSUM_UNNECESSARY; + skb2->pkt_type = PACKET_OTHERHOST; + skb2->protocol = htons(ETH_P_802_2); + memset(skb2->cb, 0, sizeof(skb2->cb)); + + netif_rx(skb2); + + return 0; + } + skb->dev = mon_priv->real_ndev; + + PRINT_INFO(HOSTAPD_DBG, "Skipping the radiotap header\n"); + + + + /* actual deliver of data is device-specific, and not shown here */ + PRINT_INFO(HOSTAPD_DBG, "SKB netdevice name = %s\n", skb->dev->name); + PRINT_INFO(HOSTAPD_DBG, "MONITOR real dev name = %s\n", mon_priv->real_ndev->name); + + #ifdef SIMULATION + ret = WILC_WFI_Tx(skb, mon_priv->real_ndev); + #elif USE_WIRELESS + /* Identify if Ethernet or MAC header (data or mgmt) */ + memcpy(srcAdd, &skb->data[10], 6); + memcpy(bssid, &skb->data[16], 6); + /* if source address and bssid fields are equal>>Mac header */ + /*send it to mgmt frames handler */ + if (!(memcmp(srcAdd, bssid, 6))) { + mon_mgmt_tx(mon_priv->real_ndev, skb->data, skb->len); + dev_kfree_skb(skb); + } else + ret = mac_xmit(skb, mon_priv->real_ndev); + #endif + + /* return NETDEV_TX_OK; */ + return ret; +} + +static const struct net_device_ops wilc_wfi_netdev_ops = { + .ndo_start_xmit = WILC_WFI_mon_xmit, + +}; + +#ifdef WILC_FULLY_HOSTING_AP +/* + * @brief WILC_mgm_HOSTAPD_ACK + * @details report the status of transmitted mgmt frames to HOSTAPD + * @param[in] priv : pointer to tx_complete_mon_data struct + * bStatus : status of transmission + * @author Abd Al-Rahman Diab + * @date 9 May 2013 + * @version 1.0 + */ +void WILC_mgm_HOSTAPD_ACK(void *priv, WILC_Bool bStatus) +{ + struct sk_buff *skb; + struct wilc_wfi_radiotap_cb_hdr *cb_hdr; + + struct tx_complete_mon_data *pv_data = (struct tx_complete_mon_data *)priv; + WILC_Uint8 *buf = pv_data->buff; + + /* len of the original frame without the added pointer at the tail */ + WILC_Uint16 u16len = (pv_data->size) - sizeof(struct tx_complete_mon_data *); + + + /*if(bStatus == 1){ + * if(INFO || buf[0] == 0x10 || buf[0] == 0xb0) + * PRINT_D(HOSTAPD_DBG,"Packet sent successfully - Size = %d - Address = %p.\n",u16len,pv_data->buff); + * }else{ + * PRINT_D(HOSTAPD_DBG,"Couldn't send packet - Size = %d - Address = %p.\n",u16len,pv_data->buff); + * } + */ + + /* (skb->data[9] == 0x00 || skb->data[9] == 0xb0 || skb->data[9] == 0x40 || skb->data[9] == 0xd0 ) */ + { + skb = dev_alloc_skb(u16len + sizeof(struct wilc_wfi_radiotap_cb_hdr)); + + memcpy(skb_put(skb, u16len), pv_data->buff, u16len); + + cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb, sizeof(*cb_hdr)); + memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr)); + + cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */ + + cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr)); + + cb_hdr->hdr.it_present = cpu_to_le32( + (1 << IEEE80211_RADIOTAP_RATE) | + (1 << IEEE80211_RADIOTAP_TX_FLAGS)); + + cb_hdr->rate = 5; /* txrate->bitrate / 5; */ + + + if (WILC_TRUE == bStatus) { + /* success */ + cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_RTS; + } else { + cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_FAIL; + } + + skb->dev = wilc_wfi_mon; + skb_set_mac_header(skb, 0); + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = htons(ETH_P_802_2); + memset(skb->cb, 0, sizeof(skb->cb)); + + netif_rx(skb); + } + + /* incase of fully hosting mode, the freeing will be done in response to the cfg packet */ + kfree(pv_data->buff); + + kfree(pv_data); + +} +#endif /* WILC_FULLY_HOSTING_AP */ + +/** + * @brief WILC_WFI_mon_setup + * @details + * @param[in] + * @return int : Return 0 on Success + * @author mdaftedar + * @date 12 JUL 2012 + * @version 1.0 + */ +static void WILC_WFI_mon_setup(struct net_device *dev) +{ + + dev->netdev_ops = &wilc_wfi_netdev_ops; + /* dev->destructor = free_netdev; */ + PRINT_INFO(CORECONFIG_DBG, "In Ethernet setup function\n"); + ether_setup(dev); + dev->tx_queue_len = 0; + dev->type = ARPHRD_IEEE80211_RADIOTAP; + memset(dev->dev_addr, 0, ETH_ALEN); + + #ifdef USE_WIRELESS + { + /* u8 * mac_add; */ + unsigned char mac_add[] = {0x00, 0x50, 0xc2, 0x5e, 0x10, 0x8f}; + /* priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy); */ + /* mac_add = (WILC_Uint8*)WILC_MALLOC(ETH_ALEN); */ + /* status = host_int_get_MacAddress(priv->hWILCWFIDrv,mac_add); */ + /* mac_add[ETH_ALEN-1]+=1; */ + memcpy(dev->dev_addr, mac_add, ETH_ALEN); + } + #else + dev->dev_addr[0] = 0x12; + #endif + +} + +/** + * @brief WILC_WFI_init_mon_interface + * @details + * @param[in] + * @return int : Return 0 on Success + * @author mdaftedar + * @date 12 JUL 2012 + * @version 1.0 + */ +struct net_device *WILC_WFI_init_mon_interface(char *name, struct net_device *real_dev) +{ + + + WILC_Uint32 ret = WILC_SUCCESS; + struct WILC_WFI_mon_priv *priv; + + /*If monitor interface is already initialized, return it*/ + if (wilc_wfi_mon) { + return wilc_wfi_mon; + } +#if 0 + wilc_wfi_mon = alloc_netdev(sizeof(struct WILC_WFI_mon_priv), name, WILC_WFI_mon_setup); + if (wilc_wfi_mon == NULL) { + PRINT_ER("Failed to allocate netdevice\n"); + goto failed; + } + + /* rtnl_lock(); */ + PRINT_INFO(HOSTAPD_DBG, "Monitor interface name %s\n", wilc_wfi_mon->name); + + + ret = dev_alloc_name(wilc_wfi_mon, wilc_wfi_mon->name); + if (ret < 0) + goto failed_mon; + + + priv = netdev_priv(wilc_wfi_mon); + if (priv == NULL) { + PRINT_ER("private structure is NULL\n"); + return WILC_FAIL; + } + + priv->real_ndev = real_dev; + + + ret = register_netdevice(wilc_wfi_mon); + + + if (ret < 0) { + PRINT_ER("Failed to register netdevice\n"); + goto failed_mon; + } + + + return WILC_SUCCESS; + /* rtnl_unlock(); */ + +failed: + return ret; + +failed_mon: + /* rtnl_unlock(); */ + free_netdev(wilc_wfi_mon); + return ret; +#endif + + wilc_wfi_mon = alloc_etherdev(sizeof(struct WILC_WFI_mon_priv)); + if (!wilc_wfi_mon) { + PRINT_ER("failed to allocate memory\n"); + return NULL; + + } + + wilc_wfi_mon->type = ARPHRD_IEEE80211_RADIOTAP; + strncpy(wilc_wfi_mon->name, name, IFNAMSIZ); + wilc_wfi_mon->name[IFNAMSIZ - 1] = 0; + wilc_wfi_mon->netdev_ops = &wilc_wfi_netdev_ops; + + ret = register_netdevice(wilc_wfi_mon); + if (ret) { + PRINT_ER(" register_netdevice failed (%d)\n", ret); + return NULL; + } + priv = netdev_priv(wilc_wfi_mon); + if (priv == NULL) { + PRINT_ER("private structure is NULL\n"); + return NULL; + } + + priv->real_ndev = real_dev; + + return wilc_wfi_mon; +} + +/** + * @brief WILC_WFI_deinit_mon_interface + * @details + * @param[in] + * @return int : Return 0 on Success + * @author mdaftedar + * @date 12 JUL 2012 + * @version 1.0 + */ +int WILC_WFI_deinit_mon_interface() +{ + bool rollback_lock = false; + + if (wilc_wfi_mon != NULL) { + PRINT_D(HOSTAPD_DBG, "In Deinit monitor interface\n"); + PRINT_D(HOSTAPD_DBG, "RTNL is being locked\n"); + if (rtnl_is_locked()) { + rtnl_unlock(); + rollback_lock = true; + } + PRINT_D(HOSTAPD_DBG, "Unregister netdev\n"); + unregister_netdev(wilc_wfi_mon); + /* free_netdev(wilc_wfi_mon); */ + + if (rollback_lock) { + rtnl_lock(); + rollback_lock = false; + } + wilc_wfi_mon = NULL; + } + return WILC_SUCCESS; + +} +#endif /* WILC_AP_EXTERNAL_MLME */ diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c new file mode 100644 index 000000000000..49b238a05a88 --- /dev/null +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -0,0 +1,2953 @@ +#ifndef SIMULATION +#include "wilc_wfi_cfgoperations.h" +#include "linux_wlan_common.h" +#include "wilc_wlan_if.h" +#include "wilc_wlan.h" +#ifdef USE_WIRELESS +#include "wilc_wfi_cfgoperations.h" +#endif + +#include "linux_wlan_common.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP +#include +#endif +#include +#include +#include +#include + +#include +#include + +#ifdef WILC_SDIO +#include "linux_wlan_sdio.h" +#else +#include "linux_wlan_spi.h" +#endif + +#ifdef WILC_FULLY_HOSTING_AP +#include "wilc_host_ap.h" +#endif + +#ifdef STATIC_MACADDRESS /* brandy_0724 [[ */ +#include +#include +struct task_struct *wilc_mac_thread; +unsigned char mac_add[] = {0x00, 0x80, 0xC2, 0x5E, 0xa2, 0xb2}; +#endif /* brandy_0724 ]] */ + +#if defined(CUSTOMER_PLATFORM) +/* + TODO : Write power control functions as customer platform. + */ +#else + + #define _linux_wlan_device_power_on() {} + #define _linux_wlan_device_power_off() {} + + #define _linux_wlan_device_detection() {} + #define _linux_wlan_device_removal() {} +#endif + +#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP +extern WILC_Bool g_obtainingIP; +#endif +extern WILC_Uint16 Set_machw_change_vir_if(WILC_Bool bValue); +extern void resolve_disconnect_aberration(void *drvHandler); +extern WILC_Uint8 gau8MulticastMacAddrList[WILC_MULTICAST_TABLE_SIZE][ETH_ALEN]; +void wilc1000_wlan_deinit(linux_wlan_t *nic); +#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP +extern WILC_TimerHandle hDuringIpTimer; +#endif + +static int linux_wlan_device_power(int on_off) +{ + PRINT_D(INIT_DBG, "linux_wlan_device_power.. (%d)\n", on_off); + + if (on_off) { + _linux_wlan_device_power_on(); + } else { + _linux_wlan_device_power_off(); + } + + return 0; +} + +static int linux_wlan_device_detection(int on_off) +{ + PRINT_D(INIT_DBG, "linux_wlan_device_detection.. (%d)\n", on_off); + +#ifdef WILC_SDIO + if (on_off) { + _linux_wlan_device_detection(); + } else { + _linux_wlan_device_removal(); + } +#endif + + return 0; +} + + +#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP +static int dev_state_ev_handler(struct notifier_block *this, unsigned long event, void *ptr); + +static struct notifier_block g_dev_notifier = { + .notifier_call = dev_state_ev_handler +}; +#endif + +#define wilc_wlan_deinit(nic) { if (&g_linux_wlan->oup != NULL) \ + if (g_linux_wlan->oup.wlan_cleanup != NULL) \ + g_linux_wlan->oup.wlan_cleanup(); } + + +#ifndef STA_FIRMWARE +#define STA_FIRMWARE "wifi_firmware.bin" +#endif + +#ifndef AP_FIRMWARE +#define AP_FIRMWARE "wifi_firmware_ap.bin" +#endif + +#ifndef P2P_CONCURRENCY_FIRMWARE +#define P2P_CONCURRENCY_FIRMWARE "wifi_firmware_p2p_concurrency.bin" +#endif + + + +typedef struct android_wifi_priv_cmd { + char *buf; + int used_len; + int total_len; +} android_wifi_priv_cmd; + + +#define IRQ_WAIT 1 +#define IRQ_NO_WAIT 0 +/* + * to sync between mac_close and module exit. + * don't initialize or de-initialize from init/deinitlocks + * to be initialized from module wilc_netdev_init and + * deinitialized from mdoule_exit + */ +static struct semaphore close_exit_sync; +unsigned int int_rcvdU; +unsigned int int_rcvdB; +unsigned int int_clrd; + +static int wlan_deinit_locks(linux_wlan_t *nic); +static void wlan_deinitialize_threads(linux_wlan_t *nic); +static void linux_wlan_lock(void *vp); +void linux_wlan_unlock(void *vp); +extern void WILC_WFI_monitor_rx(uint8_t *buff, uint32_t size); +extern void WILC_WFI_p2p_rx(struct net_device *dev, uint8_t *buff, uint32_t size); + + +static void *internal_alloc(uint32_t size, uint32_t flag); +static void linux_wlan_tx_complete(void *priv, int status); +void frmw_to_linux(uint8_t *buff, uint32_t size, uint32_t pkt_offset); +static int mac_init_fn(struct net_device *ndev); +int mac_xmit(struct sk_buff *skb, struct net_device *dev); +int mac_open(struct net_device *ndev); +int mac_close(struct net_device *ndev); +static struct net_device_stats *mac_stats(struct net_device *dev); +static int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd); +static void wilc_set_multicast_list(struct net_device *dev); + + + +/* + * for now - in frmw_to_linux there should be private data to be passed to it + * and this data should be pointer to net device + */ +linux_wlan_t *g_linux_wlan; +wilc_wlan_oup_t *gpstrWlanOps; +WILC_Bool bEnablePS = WILC_TRUE; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) +static const struct net_device_ops wilc_netdev_ops = { + .ndo_init = mac_init_fn, + .ndo_open = mac_open, + .ndo_stop = mac_close, + .ndo_start_xmit = mac_xmit, + .ndo_do_ioctl = mac_ioctl, + .ndo_get_stats = mac_stats, + .ndo_set_rx_mode = wilc_set_multicast_list, + +}; +#define wilc_set_netdev_ops(ndev) do { (ndev)->netdev_ops = &wilc_netdev_ops; } while (0) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) + +static const struct net_device_ops wilc_netdev_ops = { + .ndo_init = mac_init_fn, + .ndo_open = mac_open, + .ndo_stop = mac_close, + .ndo_start_xmit = mac_xmit, + .ndo_do_ioctl = mac_ioctl, + .ndo_get_stats = mac_stats, + .ndo_set_multicast_list = wilc_set_multicast_list, + +}; + +#define wilc_set_netdev_ops(ndev) do { (ndev)->netdev_ops = &wilc_netdev_ops; } while (0) + +#else + +static void wilc_set_netdev_ops(struct net_device *ndev) +{ + + ndev->init = mac_init_fn; + ndev->open = mac_open; + ndev->stop = mac_close; + ndev->hard_start_xmit = mac_xmit; + ndev->do_ioctl = mac_ioctl; + ndev->get_stats = mac_stats; + ndev->set_multicast_list = wilc_set_multicast_list, +} + +#endif +#ifdef DEBUG_MODE + +extern volatile int timeNo; + +#define DEGUG_BUFFER_LENGTH 1000 +volatile int WatchDogdebuggerCounter; +char DebugBuffer[DEGUG_BUFFER_LENGTH + 20] = {0}; +static char *ps8current = DebugBuffer; + + + +void printk_later(const char *format, ...) +{ + va_list args; + va_start (args, format); + ps8current += vsprintf (ps8current, format, args); + va_end (args); + if ((ps8current - DebugBuffer) > DEGUG_BUFFER_LENGTH) { + ps8current = DebugBuffer; + } + +} + + +void dump_logs() +{ + if (DebugBuffer[0]) { + DebugBuffer[DEGUG_BUFFER_LENGTH] = 0; + PRINT_INFO(GENERIC_DBG, "early printed\n"); + PRINT_D(GENERIC_DBG, ps8current + 1); + ps8current[1] = 0; + PRINT_INFO(GENERIC_DBG, "latest printed\n"); + PRINT_D(GENERIC_DBG, DebugBuffer); + DebugBuffer[0] = 0; + ps8current = DebugBuffer; + } +} + +void Reset_WatchDogdebugger() +{ + WatchDogdebuggerCounter = 0; +} + +static int DebuggingThreadTask(void *vp) +{ + while (1) { + while (!WatchDogdebuggerCounter) { + PRINT_D(GENERIC_DBG, "Debug Thread Running %d\n", timeNo); + WatchDogdebuggerCounter = 1; + msleep(10000); + } + dump_logs(); + WatchDogdebuggerCounter = 0; + } +} + + +#endif + + +#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP +static int dev_state_ev_handler(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct in_ifaddr *dev_iface = (struct in_ifaddr *)ptr; + struct WILC_WFI_priv *priv; + tstrWILC_WFIDrv *pstrWFIDrv; + struct net_device *dev; + WILC_Uint8 *pIP_Add_buff; + WILC_Sint32 s32status = WILC_FAIL; + perInterface_wlan_t *nic; + WILC_Uint8 null_ip[4] = {0}; + char wlan_dev_name[5] = "wlan0"; + + if (dev_iface == NULL || dev_iface->ifa_dev == NULL || dev_iface->ifa_dev->dev == NULL) { + PRINT_D(GENERIC_DBG, "dev_iface = NULL\n"); + return NOTIFY_DONE; + } + + if ((memcmp(dev_iface->ifa_label, "wlan0", 5)) && (memcmp(dev_iface->ifa_label, "p2p0", 4))) { + PRINT_D(GENERIC_DBG, "Interface is neither WLAN0 nor P2P0\n"); + return NOTIFY_DONE; + } + + dev = (struct net_device *)dev_iface->ifa_dev->dev; + if (dev->ieee80211_ptr == NULL || dev->ieee80211_ptr->wiphy == NULL) { + PRINT_D(GENERIC_DBG, "No Wireless registerd\n"); + return NOTIFY_DONE; + } + priv = wiphy_priv(dev->ieee80211_ptr->wiphy); + if (priv == NULL) { + PRINT_D(GENERIC_DBG, "No Wireless Priv\n"); + return NOTIFY_DONE; + } + pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv; + nic = netdev_priv(dev); + if (nic == NULL || pstrWFIDrv == NULL) { + PRINT_D(GENERIC_DBG, "No Wireless Priv\n"); + return NOTIFY_DONE; + } + + PRINT_INFO(GENERIC_DBG, "dev_state_ev_handler +++\n"); /* tony */ + + switch (event) { + case NETDEV_UP: + PRINT_D(GENERIC_DBG, "dev_state_ev_handler event=NETDEV_UP %p\n", dev); /* tony */ + + PRINT_INFO(GENERIC_DBG, "\n ============== IP Address Obtained ===============\n\n"); + + + /*If we are in station mode or client mode*/ + if (nic->iftype == STATION_MODE || nic->iftype == CLIENT_MODE) { + pstrWFIDrv->IFC_UP = 1; + g_obtainingIP = WILC_FALSE; + WILC_TimerStop(&hDuringIpTimer, WILC_NULL); + PRINT_D(GENERIC_DBG, "IP obtained , enable scan\n"); + } + + + + if (bEnablePS == WILC_TRUE) + host_int_set_power_mgmt((WILC_WFIDrvHandle)pstrWFIDrv, 1, 0); + + PRINT_D(GENERIC_DBG, "[%s] Up IP\n", dev_iface->ifa_label); + + pIP_Add_buff = (char *) (&(dev_iface->ifa_address)); + PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d \n", pIP_Add_buff[0], pIP_Add_buff[1], pIP_Add_buff[2], pIP_Add_buff[3]); + s32status = host_int_setup_ipaddress((WILC_WFIDrvHandle)pstrWFIDrv, pIP_Add_buff, nic->u8IfIdx); + + break; + + case NETDEV_DOWN: + PRINT_D(GENERIC_DBG, "dev_state_ev_handler event=NETDEV_DOWN %p\n", dev); /* tony */ + + PRINT_INFO(GENERIC_DBG, "\n ============== IP Address Released ===============\n\n"); + if (nic->iftype == STATION_MODE || nic->iftype == CLIENT_MODE) { + pstrWFIDrv->IFC_UP = 0; + g_obtainingIP = WILC_FALSE; + } + + if (memcmp(dev_iface->ifa_label, wlan_dev_name, 5) == 0) + host_int_set_power_mgmt((WILC_WFIDrvHandle)pstrWFIDrv, 0, 0); + + resolve_disconnect_aberration(pstrWFIDrv); + + + PRINT_D(GENERIC_DBG, "[%s] Down IP\n", dev_iface->ifa_label); + + pIP_Add_buff = null_ip; + PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d \n", pIP_Add_buff[0], pIP_Add_buff[1], pIP_Add_buff[2], pIP_Add_buff[3]); + + s32status = host_int_setup_ipaddress((WILC_WFIDrvHandle)pstrWFIDrv, pIP_Add_buff, nic->u8IfIdx); + + break; + + default: + PRINT_INFO(GENERIC_DBG, "dev_state_ev_handler event=default\n"); /* tony */ + PRINT_INFO(GENERIC_DBG, "[%s] unknown dev event: %lu\n", dev_iface->ifa_label, event); + + break; + } + + return NOTIFY_DONE; + +} +#endif + +/* + * Interrupt initialization and handling functions + */ + +void linux_wlan_enable_irq(void) +{ + +#if (RX_BH_TYPE != RX_BH_THREADED_IRQ) +#if (defined WILC_SPI) || (defined WILC_SDIO_IRQ_GPIO) + PRINT_D(INT_DBG, "Enabling IRQ ...\n"); + enable_irq(g_linux_wlan->dev_irq_num); +#endif +#endif +} + +void linux_wlan_disable_irq(int wait) +{ +#if (defined WILC_SPI) || (defined WILC_SDIO_IRQ_GPIO) + if (wait) { + PRINT_D(INT_DBG, "Disabling IRQ ...\n"); + disable_irq(g_linux_wlan->dev_irq_num); + } else { + PRINT_D(INT_DBG, "Disabling IRQ ...\n"); + disable_irq_nosync(g_linux_wlan->dev_irq_num); + } +#endif +} + +#if (defined WILC_SPI) || (defined WILC_SDIO_IRQ_GPIO) +static irqreturn_t isr_uh_routine(int irq, void *user_data) +{ + + + int_rcvdU++; +#if (RX_BH_TYPE != RX_BH_THREADED_IRQ) + linux_wlan_disable_irq(IRQ_NO_WAIT); +#endif + PRINT_D(INT_DBG, "Interrupt received UH\n"); + + /*While mac is closing cacncel the handling of any interrupts received*/ + if (g_linux_wlan->close) { + PRINT_ER("Driver is CLOSING: Can't handle UH interrupt\n"); + #if (RX_BH_TYPE == RX_BH_THREADED_IRQ) + return IRQ_HANDLED; + #else + return IRQ_NONE; + #endif + + } +#if (RX_BH_TYPE == RX_BH_WORK_QUEUE) + schedule_work(&g_linux_wlan->rx_work_queue); + return IRQ_HANDLED; +#elif (RX_BH_TYPE == RX_BH_KTHREAD) + linux_wlan_unlock(&g_linux_wlan->rx_sem); + return IRQ_HANDLED; +#elif (RX_BH_TYPE == RX_BH_THREADED_IRQ) + return IRQ_WAKE_THREAD; +#endif + +} +#endif + +#if (RX_BH_TYPE == RX_BH_WORK_QUEUE || RX_BH_TYPE == RX_BH_THREADED_IRQ) + +#if (RX_BH_TYPE == RX_BH_THREADED_IRQ) +irqreturn_t isr_bh_routine(int irq, void *userdata) +{ + linux_wlan_t *nic; + nic = (linux_wlan_t *)userdata; +#else +static void isr_bh_routine(struct work_struct *work) +{ + perInterface_wlan_t *nic; + nic = (perInterface_wlan_t *)container_of(work, linux_wlan_t, rx_work_queue); +#endif + + /*While mac is closing cacncel the handling of any interrupts received*/ + if (g_linux_wlan->close) { + PRINT_ER("Driver is CLOSING: Can't handle BH interrupt\n"); + #if (RX_BH_TYPE == RX_BH_THREADED_IRQ) + return IRQ_HANDLED; + #else + return; + #endif + + + + } + + int_rcvdB++; + PRINT_D(INT_DBG, "Interrupt received BH\n"); + if (g_linux_wlan->oup.wlan_handle_rx_isr != 0) { + g_linux_wlan->oup.wlan_handle_rx_isr(); + } else { + PRINT_ER("wlan_handle_rx_isr() hasn't been initialized\n"); + } + + +#if (RX_BH_TYPE == RX_BH_THREADED_IRQ) + return IRQ_HANDLED; +#endif +} +#elif (RX_BH_TYPE == RX_BH_KTHREAD) +static int isr_bh_routine(void *vp) +{ + linux_wlan_t *nic; + + nic = (linux_wlan_t *)vp; + + while (1) { + linux_wlan_lock(&nic->rx_sem); + if (g_linux_wlan->close) { + + while (!kthread_should_stop()) + schedule(); + + break; + } + int_rcvdB++; + PRINT_D(INT_DBG, "Interrupt received BH\n"); + if (g_linux_wlan->oup.wlan_handle_rx_isr != 0) { + g_linux_wlan->oup.wlan_handle_rx_isr(); + } else { + PRINT_ER("wlan_handle_rx_isr() hasn't been initialized\n"); + } + } + + return 0; +} +#endif + + +#if (defined WILC_SPI) || (defined WILC_SDIO_IRQ_GPIO) +static int init_irq(linux_wlan_t *p_nic) +{ + int ret = 0; + linux_wlan_t *nic = p_nic; + + /*initialize GPIO and register IRQ num*/ + /*GPIO request*/ + if ((gpio_request(GPIO_NUM, "WILC_INTR") == 0) && + (gpio_direction_input(GPIO_NUM) == 0)) { +#if defined(CUSTOMER_PLATFORM) +/* + TODO : save the registerd irq number to the private wilc context in kernel. + * + * ex) nic->dev_irq_num = gpio_to_irq(GPIO_NUM); + */ +#elif defined (NM73131_0_BOARD) + nic->dev_irq_num = IRQ_WILC1000; +#elif defined (PANDA_BOARD) + gpio_export(GPIO_NUM, 1); + nic->dev_irq_num = OMAP_GPIO_IRQ(GPIO_NUM); + irq_set_irq_type(nic->dev_irq_num, IRQ_TYPE_LEVEL_LOW); +#else + nic->dev_irq_num = gpio_to_irq(GPIO_NUM); +#endif + } else { + ret = -1; + PRINT_ER("could not obtain gpio for WILC_INTR\n"); + } + + +#if (RX_BH_TYPE == RX_BH_THREADED_IRQ) + if ((ret != -1) && (request_threaded_irq(nic->dev_irq_num, isr_uh_routine, isr_bh_routine, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, /*Without IRQF_ONESHOT the uh will remain kicked in and dont gave a chance to bh*/ + "WILC_IRQ", nic)) < 0) { + +#else + /*Request IRQ*/ + if ((ret != -1) && (request_irq(nic->dev_irq_num, isr_uh_routine, + IRQF_TRIGGER_LOW, "WILC_IRQ", nic) < 0)) { + +#endif + PRINT_ER("Failed to request IRQ for GPIO: %d\n", GPIO_NUM); + ret = -1; + } else { + + PRINT_D(INIT_DBG, "IRQ request succeeded IRQ-NUM= %d on GPIO: %d\n", + nic->dev_irq_num, GPIO_NUM); + } + + return ret; +} +#endif + +static void deinit_irq(linux_wlan_t *nic) +{ +#if (defined WILC_SPI) || (defined WILC_SDIO_IRQ_GPIO) + /* Deintialize IRQ */ + if (&nic->dev_irq_num != 0) { + free_irq(nic->dev_irq_num, g_linux_wlan); + + gpio_free(GPIO_NUM); + } +#endif +} + + +/* + * OS functions + */ +static void linux_wlan_msleep(uint32_t msc) +{ + if (msc <= 4000000) { + WILC_Uint32 u32Temp = msc * 1000; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35) + usleep_range(u32Temp, u32Temp); +#else + /* This is delay not sleep !!!, has to be changed*/ + msleep(msc); +#endif + } else { + msleep(msc); + } +} + +static void linux_wlan_atomic_msleep(uint32_t msc) +{ + mdelay(msc); +} +static void linux_wlan_dbg(uint8_t *buff) +{ + PRINT_D(INIT_DBG, "%d\n", *buff); +} + +static void *linux_wlan_malloc_atomic(uint32_t sz) +{ + char *pntr = NULL; + pntr = (char *)kmalloc(sz, GFP_ATOMIC); + PRINT_D(MEM_DBG, "Allocating %d bytes at address %p\n", sz, pntr); + return (void *)pntr; + +} +static void *linux_wlan_malloc(uint32_t sz) +{ + char *pntr = NULL; + pntr = (char *)kmalloc(sz, GFP_KERNEL); + PRINT_D(MEM_DBG, "Allocating %d bytes at address %p\n", sz, pntr); + return (void *)pntr; +} + +void linux_wlan_free(void *vp) +{ + if (vp != NULL) { + PRINT_D(MEM_DBG, "Freeing %p\n", vp); + kfree(vp); + } +} + + +static void *internal_alloc(uint32_t size, uint32_t flag) +{ + char *pntr = NULL; + pntr = (char *)kmalloc(size, flag); + PRINT_D(MEM_DBG, "Allocating %d bytes at address %p\n", size, pntr); + return (void *)pntr; +} + + +static void linux_wlan_init_lock(char *lockName, void *plock, int count) +{ + sema_init((struct semaphore *)plock, count); + PRINT_D(LOCK_DBG, "Initializing [%s][%p]\n", lockName, plock); + +} + +static void linux_wlan_deinit_lock(void *plock) +{ + /* mutex_destroy((struct mutex*)plock); */ +} + +static void linux_wlan_lock(void *vp) +{ + PRINT_D(LOCK_DBG, "Locking %p\n", vp); + if (vp != NULL) { + while (down_interruptible((struct semaphore *) vp)) + ; + } else { + PRINT_ER("Failed, mutex is NULL\n"); + } +} + +static int linux_wlan_lock_timeout(void *vp, WILC_Uint32 timeout) +{ + int error = -1; + PRINT_D(LOCK_DBG, "Locking %p\n", vp); + if (vp != NULL) { + error = down_timeout((struct semaphore *)vp, msecs_to_jiffies(timeout)); + } else { + PRINT_ER("Failed, mutex is NULL\n"); + } + return error; +} + +void linux_wlan_unlock(void *vp) +{ + PRINT_D(LOCK_DBG, "Unlocking %p\n", vp); + if (vp != NULL) { + up((struct semaphore *)vp); + } else { + PRINT_ER("Failed, mutex is NULL\n"); + } +} + + +static void linux_wlan_init_mutex(char *lockName, void *plock, int count) +{ + mutex_init((struct mutex *)plock); + PRINT_D(LOCK_DBG, "Initializing mutex [%s][%p]\n", lockName, plock); + +} + +static void linux_wlan_deinit_mutex(void *plock) +{ + mutex_destroy((struct mutex *)plock); +} + +static void linux_wlan_lock_mutex(void *vp) +{ + PRINT_D(LOCK_DBG, "Locking mutex %p\n", vp); + if (vp != NULL) { + /* + * if(mutex_is_locked((struct mutex*)vp)) + * { + * //PRINT_ER("Mutex already locked - %p \n",vp); + * } + */ + mutex_lock((struct mutex *)vp); + + } else { + PRINT_ER("Failed, mutex is NULL\n"); + } +} + +static void linux_wlan_unlock_mutex(void *vp) +{ + PRINT_D(LOCK_DBG, "Unlocking mutex %p\n", vp); + if (vp != NULL) { + + if (mutex_is_locked((struct mutex *)vp)) { + mutex_unlock((struct mutex *)vp); + } else { + /* PRINT_ER("Mutex already unlocked - %p\n",vp); */ + } + + } else { + PRINT_ER("Failed, mutex is NULL\n"); + } +} + + +/*Added by Amr - BugID_4720*/ +static void linux_wlan_init_spin_lock(char *lockName, void *plock, int count) +{ + spin_lock_init((spinlock_t *)plock); + PRINT_D(SPIN_DEBUG, "Initializing mutex [%s][%p]\n", lockName, plock); + +} + +static void linux_wlan_deinit_spin_lock(void *plock) +{ + +} +static void linux_wlan_spin_lock(void *vp, unsigned long *flags) +{ + unsigned long lflags; + PRINT_D(SPIN_DEBUG, "Lock spin %p\n", vp); + if (vp != NULL) { + spin_lock_irqsave((spinlock_t *)vp, lflags); + *flags = lflags; + } else { + PRINT_ER("Failed, spin lock is NULL\n"); + } +} +static void linux_wlan_spin_unlock(void *vp, unsigned long *flags) +{ + unsigned long lflags = *flags; + PRINT_D(SPIN_DEBUG, "Unlock spin %p\n", vp); + if (vp != NULL) { + spin_unlock_irqrestore((spinlock_t *)vp, lflags); + *flags = lflags; + } else { + PRINT_ER("Failed, spin lock is NULL\n"); + } +} + +static void linux_wlan_mac_indicate(int flag) +{ + /*I have to do it that way becuase there is no mean to encapsulate device pointer + * as a parameter + */ + linux_wlan_t *pd = g_linux_wlan; + int status; + + if (flag == WILC_MAC_INDICATE_STATUS) { + pd->oup.wlan_cfg_get_value(WID_STATUS, (unsigned char *)&status, 4); + if (pd->mac_status == WILC_MAC_STATUS_INIT) { + pd->mac_status = status; + linux_wlan_unlock(&pd->sync_event); + } else { + pd->mac_status = status; + } + + if (pd->mac_status == WILC_MAC_STATUS_CONNECT) { /* Connect */ +#if 0 + /** + * get the mac and bssid address + **/ + PRINT_D(RX_DBG, "Calling cfg_get to get MAC_ADDR\n"); + pd->oup.wlan_cfg_get(1, WID_MAC_ADDR, 0); + PRINT_D(RX_DBG, "Calling cfg_get to get BSSID\n"); + pd->oup.wlan_cfg_get(0, WID_BSSID, 1); + + /** + * get the value + **/ + pd->oup.wlan_cfg_get_value(WID_MAC_ADDR, pd->eth_src_address, 6); + pd->oup.wlan_cfg_get_value(WID_BSSID, pd->eth_dst_address, 6); + + PRINT_D(GENERIC_DBG, "Source Address = %s", pd->eth_src_address); + PRINT_D(GENERIC_DBG, "Destiation Address = %s", pd->eth_dst_address); + + /** + * launch ndis + **/ +#endif + } + + } else if (flag == WILC_MAC_INDICATE_SCAN) { + PRINT_D(GENERIC_DBG, "Scanning ...\n"); + + } + +} + +struct net_device *GetIfHandler(uint8_t *pMacHeader) +{ + uint8_t *Bssid, *Bssid1; + int i = 0; + + Bssid = pMacHeader + 10; + Bssid1 = pMacHeader + 4; + + for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) { + if (!memcmp(Bssid1, g_linux_wlan->strInterfaceInfo[i].aBSSID, ETH_ALEN) || + !memcmp(Bssid, g_linux_wlan->strInterfaceInfo[i].aBSSID, ETH_ALEN)) { + return g_linux_wlan->strInterfaceInfo[i].wilc_netdev; + } + } + PRINT_INFO(INIT_DBG, "Invalide handle\n"); + for (i = 0; i < 25; i++) { + PRINT_D(INIT_DBG, "%02x ", pMacHeader[i]); + } + Bssid = pMacHeader + 18; + Bssid1 = pMacHeader + 12; + for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) { + if (!memcmp(Bssid1, g_linux_wlan->strInterfaceInfo[i].aBSSID, ETH_ALEN) || + !memcmp(Bssid, g_linux_wlan->strInterfaceInfo[i].aBSSID, ETH_ALEN)) { + PRINT_D(INIT_DBG, "Ctx [%p]\n", g_linux_wlan->strInterfaceInfo[i].wilc_netdev); + return g_linux_wlan->strInterfaceInfo[i].wilc_netdev; + } + } + PRINT_INFO(INIT_DBG, "\n"); + return NULL; +} + +int linux_wlan_set_bssid(struct net_device *wilc_netdev, uint8_t *pBSSID) +{ + int i = 0; + int ret = -1; + + PRINT_D(INIT_DBG, "set bssid on[%p]\n", wilc_netdev); + for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) { + if (g_linux_wlan->strInterfaceInfo[i].wilc_netdev == wilc_netdev) { + PRINT_D(INIT_DBG, "set bssid [%x][%x][%x]\n", pBSSID[0], pBSSID[1], pBSSID[2]); + memcpy(g_linux_wlan->strInterfaceInfo[i].aBSSID, pBSSID, 6); + ret = 0; + break; + } + } + return ret; +} + +/*BugID_5213*/ +/*Function to get number of connected interfaces*/ +int linux_wlan_get_num_conn_ifcs(void) +{ + uint8_t i = 0; + uint8_t null_bssid[6] = {0}; + uint8_t ret_val = 0; + + for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) { + if (memcmp(g_linux_wlan->strInterfaceInfo[i].aBSSID, null_bssid, 6)) { + ret_val++; + } + } + return ret_val; +} + +static int linux_wlan_rxq_task(void *vp) +{ + + /* inform wilc1000_wlan_init that RXQ task is started. */ + linux_wlan_unlock(&g_linux_wlan->rxq_thread_started); + while (1) { + linux_wlan_lock(&g_linux_wlan->rxq_event); + /* wait_for_completion(&g_linux_wlan->rxq_event); */ + + if (g_linux_wlan->close) { + /*Unlock the mutex in the mac_close function to indicate the exiting of the RX thread */ + linux_wlan_unlock(&g_linux_wlan->rxq_thread_started); + + while (!kthread_should_stop()) + schedule(); + + PRINT_D(RX_DBG, " RX thread stopped\n"); + break; + } + PRINT_D(RX_DBG, "Calling wlan_handle_rx_que()\n"); + + g_linux_wlan->oup.wlan_handle_rx_que(); + } + return 0; +} + +#define USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS + +static int linux_wlan_txq_task(void *vp) +{ + int ret, txq_count; + +#if defined USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS +#define TX_BACKOFF_WEIGHT_INCR_STEP (1) +#define TX_BACKOFF_WEIGHT_DECR_STEP (1) +#define TX_BACKOFF_WEIGHT_MAX (7) +#define TX_BACKOFF_WEIGHT_MIN (0) +#define TX_BACKOFF_WEIGHT_UNIT_MS (10) + int backoff_weight = TX_BACKOFF_WEIGHT_MIN; + signed long timeout; +#endif + + /* inform wilc1000_wlan_init that TXQ task is started. */ + linux_wlan_unlock(&g_linux_wlan->txq_thread_started); + while (1) { + + PRINT_D(TX_DBG, "txq_task Taking a nap :)\n"); + linux_wlan_lock(&g_linux_wlan->txq_event); + /* wait_for_completion(&pd->txq_event); */ + PRINT_D(TX_DBG, "txq_task Who waked me up :$\n"); + + if (g_linux_wlan->close) { + /*Unlock the mutex in the mac_close function to indicate the exiting of the TX thread */ + linux_wlan_unlock(&g_linux_wlan->txq_thread_started); + + while (!kthread_should_stop()) + schedule(); + + PRINT_D(TX_DBG, "TX thread stopped\n"); + break; + } + PRINT_D(TX_DBG, "txq_task handle the sending packet and let me go to sleep.\n"); +#if !defined USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS + g_linux_wlan->oup.wlan_handle_tx_que(); +#else + do { + ret = g_linux_wlan->oup.wlan_handle_tx_que(&txq_count); + if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD /* && netif_queue_stopped(pd->wilc_netdev)*/) { + PRINT_D(TX_DBG, "Waking up queue\n"); + /* netif_wake_queue(pd->wilc_netdev); */ + if (netif_queue_stopped(g_linux_wlan->strInterfaceInfo[0].wilc_netdev)) + netif_wake_queue(g_linux_wlan->strInterfaceInfo[0].wilc_netdev); + if (netif_queue_stopped(g_linux_wlan->strInterfaceInfo[1].wilc_netdev)) + netif_wake_queue(g_linux_wlan->strInterfaceInfo[1].wilc_netdev); + } + + if (ret == WILC_TX_ERR_NO_BUF) { /* failed to allocate buffers in chip. */ + timeout = msecs_to_jiffies(TX_BACKOFF_WEIGHT_UNIT_MS << backoff_weight); + do { + /* Back off from sending packets for some time. */ + /* schedule_timeout will allow RX task to run and free buffers.*/ + /* set_current_state(TASK_UNINTERRUPTIBLE); */ + /* timeout = schedule_timeout(timeout); */ + msleep(TX_BACKOFF_WEIGHT_UNIT_MS << backoff_weight); + } while (/*timeout*/ 0); + backoff_weight += TX_BACKOFF_WEIGHT_INCR_STEP; + if (backoff_weight > TX_BACKOFF_WEIGHT_MAX) { + backoff_weight = TX_BACKOFF_WEIGHT_MAX; + } + } else { + if (backoff_weight > TX_BACKOFF_WEIGHT_MIN) { + backoff_weight -= TX_BACKOFF_WEIGHT_DECR_STEP; + if (backoff_weight < TX_BACKOFF_WEIGHT_MIN) { + backoff_weight = TX_BACKOFF_WEIGHT_MIN; + } + } + } + /*TODO: drop packets after a certain time/number of retry count. */ + } while (ret == WILC_TX_ERR_NO_BUF && !g_linux_wlan->close); /* retry sending packets if no more buffers in chip. */ +#endif + } + return 0; +} + +static void linux_wlan_rx_complete(void) +{ + PRINT_D(RX_DBG, "RX completed\n"); +} + +int linux_wlan_get_firmware(perInterface_wlan_t *p_nic) +{ + + perInterface_wlan_t *nic = p_nic; + int ret = 0; + const struct firmware *wilc_firmware; + char *firmware; + + + if (nic->iftype == AP_MODE) + firmware = AP_FIRMWARE; + else if (nic->iftype == STATION_MODE) + firmware = STA_FIRMWARE; + + /*BugID_5137*/ + else { + PRINT_D(INIT_DBG, "Get P2P_CONCURRENCY_FIRMWARE\n"); + firmware = P2P_CONCURRENCY_FIRMWARE; + } + + + + if (nic == NULL) { + PRINT_ER("NIC is NULL\n"); + goto _fail_; + } + + if (&nic->wilc_netdev->dev == NULL) { + PRINT_ER("&nic->wilc_netdev->dev is NULL\n"); + goto _fail_; + } + + + /* the firmare should be located in /lib/firmware in + * root file system with the name specified above */ + +#ifdef WILC_SDIO + if (request_firmware(&wilc_firmware, firmware, &g_linux_wlan->wilc_sdio_func->dev) != 0) { + PRINT_ER("%s - firmare not available\n", firmware); + ret = -1; + goto _fail_; + } +#else + if (request_firmware(&wilc_firmware, firmware, &g_linux_wlan->wilc_spidev->dev) != 0) { + PRINT_ER("%s - firmare not available\n", firmware); + ret = -1; + goto _fail_; + } +#endif + g_linux_wlan->wilc_firmware = wilc_firmware; /* Bug 4703 */ + +_fail_: + + return ret; + +} + +#ifdef COMPLEMENT_BOOT +int repeat_power_cycle(perInterface_wlan_t *nic); +#endif + +static int linux_wlan_start_firmware(perInterface_wlan_t *nic) +{ + + static int timeout = 5; + int ret = 0; + /* start firmware */ + PRINT_D(INIT_DBG, "Starting Firmware ...\n"); + ret = g_linux_wlan->oup.wlan_start(); + if (ret < 0) { + PRINT_ER("Failed to start Firmware\n"); + goto _fail_; + } + + /* wait for mac ready */ + PRINT_D(INIT_DBG, "Waiting for Firmware to get ready ...\n"); + ret = linux_wlan_lock_timeout(&g_linux_wlan->sync_event, 5000); + if (ret) { +#ifdef COMPLEMENT_BOOT + + if (timeout--) { + PRINT_D(INIT_DBG, "repeat power cycle[%d]", timeout); + ret = repeat_power_cycle(nic); + } else { + timeout = 5; + ret = -1; + goto _fail_; + } +#endif + PRINT_D(INIT_DBG, "Firmware start timed out"); + goto _fail_; + } + /* + * TODO: Driver shouoldn't wait forever for firmware to get started - + * in case of timeout this should be handled properly + */ + PRINT_D(INIT_DBG, "Firmware successfully started\n"); + +_fail_: + return ret; +} +static int linux_wlan_firmware_download(linux_wlan_t *p_nic) +{ + + int ret = 0; + + if (g_linux_wlan->wilc_firmware == NULL) { + PRINT_ER("Firmware buffer is NULL\n"); + ret = -ENOBUFS; + goto _FAIL_; + } + /** + * do the firmware download + **/ + PRINT_D(INIT_DBG, "Downloading Firmware ...\n"); + ret = g_linux_wlan->oup.wlan_firmware_download(g_linux_wlan->wilc_firmware->data, g_linux_wlan->wilc_firmware->size); + if (ret < 0) { + goto _FAIL_; + } + + /* Freeing FW buffer */ + PRINT_D(INIT_DBG, "Freeing FW buffer ...\n"); + PRINT_D(INIT_DBG, "Releasing firmware\n"); + release_firmware(g_linux_wlan->wilc_firmware); + g_linux_wlan->wilc_firmware = NULL; + + PRINT_D(INIT_DBG, "Download Succeeded \n"); + +_FAIL_: + return ret; +} + + +/* startup configuration - could be changed later using iconfig*/ +static int linux_wlan_init_test_config(struct net_device *dev, linux_wlan_t *p_nic) +{ + + unsigned char c_val[64]; + #ifndef STATIC_MACADDRESS + unsigned char mac_add[] = {0x00, 0x80, 0xC2, 0x5E, 0xa2, 0xff}; + #endif + unsigned int chipid = 0; + + /*BugID_5077*/ + struct WILC_WFI_priv *priv; + tstrWILC_WFIDrv *pstrWFIDrv; + + PRINT_D(TX_DBG, "Start configuring Firmware\n"); + #ifndef STATIC_MACADDRESS + get_random_bytes(&mac_add[5], 1); + get_random_bytes(&mac_add[4], 1); + #endif + priv = wiphy_priv(dev->ieee80211_ptr->wiphy); + pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv; + PRINT_D(INIT_DBG, "Host = %x\n", (WILC_Uint32)pstrWFIDrv); + + PRINT_D(INIT_DBG, "MAC address is : %02x-%02x-%02x-%02x-%02x-%02x\n", mac_add[0], mac_add[1], mac_add[2], mac_add[3], mac_add[4], mac_add[5]); + chipid = wilc_get_chipid(0); + + + if (g_linux_wlan->oup.wlan_cfg_set == NULL) { + PRINT_D(INIT_DBG, "Null p[ointer\n"); + goto _fail_; + } + + *(int *)c_val = (WILC_Uint32)pstrWFIDrv; + + if (!g_linux_wlan->oup.wlan_cfg_set(1, WID_SET_DRV_HANDLER, c_val, 4, 0, 0)) + goto _fail_; + + /*to tell fw that we are going to use PC test - WILC specific*/ + c_val[0] = 0; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_PC_TEST_MODE, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = INFRASTRUCTURE; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_BSS_TYPE, c_val, 1, 0, 0)) + goto _fail_; + + + /* c_val[0] = RATE_AUTO; / * bug 4275: Enable autorate and limit it to 24Mbps * / */ + c_val[0] = RATE_AUTO; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_CURRENT_TX_RATE, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = G_MIXED_11B_2_MODE; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_11G_OPERATING_MODE, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = 1; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_CURRENT_CHANNEL, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = G_SHORT_PREAMBLE; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_PREAMBLE, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = AUTO_PROT; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_11N_PROT_MECH, c_val, 1, 0, 0)) + goto _fail_; + +#ifdef SWITCH_LOG_TERMINAL + c_val[0] = AUTO_PROT; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_LOGTerminal_Switch, c_val, 1, 0, 0)) + goto _fail_; +#endif + + c_val[0] = ACTIVE_SCAN; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_SCAN_TYPE, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = SITE_SURVEY_OFF; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_SITE_SURVEY, c_val, 1, 0, 0)) + goto _fail_; + + *((int *)c_val) = 0xffff; /* Never use RTS-CTS */ + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_RTS_THRESHOLD, c_val, 2, 0, 0)) + goto _fail_; + + *((int *)c_val) = 2346; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_FRAG_THRESHOLD, c_val, 2, 0, 0)) + goto _fail_; + + /* SSID */ + /* -------------------------------------------------------------- */ + /* Configuration : String with length less than 32 bytes */ + /* Values to set : Any string with length less than 32 bytes */ + /* ( In BSS Station Set SSID to "" (null string) */ + /* to enable Broadcast SSID suppport ) */ + /* -------------------------------------------------------------- */ +#ifndef USE_WIRELESS + strcpy(c_val, "nwifi"); + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_SSID, c_val, (strlen(c_val) + 1), 0, 0)) + goto _fail_; +#endif + + c_val[0] = 0; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_BCAST_SSID, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = 1; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_QOS_ENABLE, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = NO_POWERSAVE; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_POWER_MANAGEMENT, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = NO_ENCRYPT; /* NO_ENCRYPT, 0x79 */ + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_11I_MODE, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = OPEN_SYSTEM; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_AUTH_TYPE, c_val, 1, 0, 0)) + goto _fail_; + + /* WEP/802 11I Configuration */ + /* ------------------------------------------------------------------ */ + /* Configuration : WEP Key */ + /* Values (0x) : 5 byte for WEP40 and 13 bytes for WEP104 */ + /* In case more than 5 bytes are passed on for WEP 40 */ + /* only first 5 bytes will be used as the key */ + /* ------------------------------------------------------------------ */ + + strcpy(c_val, "123456790abcdef1234567890"); + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_WEP_KEY_VALUE, c_val, (strlen(c_val) + 1), 0, 0)) + goto _fail_; + + /* WEP/802 11I Configuration */ + /* ------------------------------------------------------------------ */ + /* Configuration : AES/TKIP WPA/RSNA Pre-Shared Key */ + /* Values to set : Any string with length greater than equal to 8 bytes */ + /* and less than 64 bytes */ + /* ------------------------------------------------------------------ */ + strcpy(c_val, "12345678"); + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_11I_PSK, c_val, (strlen(c_val)), 0, 0)) + goto _fail_; + + /* IEEE802.1X Key Configuration */ + /* ------------------------------------------------------------------ */ + /* Configuration : Radius Server Access Secret Key */ + /* Values to set : Any string with length greater than equal to 8 bytes */ + /* and less than 65 bytes */ + /* ------------------------------------------------------------------ */ + strcpy(c_val, "password"); + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_1X_KEY, c_val, (strlen(c_val) + 1), 0, 0)) + goto _fail_; + + /* IEEE802.1X Server Address Configuration */ + /* ------------------------------------------------------------------ */ + /* Configuration : Radius Server IP Address */ + /* Values to set : Any valid IP Address */ + /* ------------------------------------------------------------------ */ + c_val[0] = 192; + c_val[1] = 168; + c_val[2] = 1; + c_val[3] = 112; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_1X_SERV_ADDR, c_val, 4, 0, 0)) + goto _fail_; + + c_val[0] = 3; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_LISTEN_INTERVAL, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = 3; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_DTIM_PERIOD, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = NORMAL_ACK; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_ACK_POLICY, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = 0; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_USER_CONTROL_ON_TX_POWER, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = 48; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_TX_POWER_LEVEL_11A, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = 28; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_TX_POWER_LEVEL_11B, c_val, 1, 0, 0)) + goto _fail_; + + /* Beacon Interval */ + /* -------------------------------------------------------------------- */ + /* Configuration : Sets the beacon interval value */ + /* Values to set : Any 16-bit value */ + /* -------------------------------------------------------------------- */ + + *((int *)c_val) = 100; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_BEACON_INTERVAL, c_val, 2, 0, 0)) + goto _fail_; + + c_val[0] = REKEY_DISABLE; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_REKEY_POLICY, c_val, 1, 0, 0)) + goto _fail_; + + /* Rekey Time (s) (Used only when the Rekey policy is 2 or 4) */ + /* -------------------------------------------------------------------- */ + /* Configuration : Sets the Rekey Time (s) */ + /* Values to set : 32-bit value */ + /* -------------------------------------------------------------------- */ + *((int *)c_val) = 84600; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_REKEY_PERIOD, c_val, 4, 0, 0)) + goto _fail_; + + /* Rekey Packet Count (in 1000s; used when Rekey Policy is 3) */ + /* -------------------------------------------------------------------- */ + /* Configuration : Sets Rekey Group Packet count */ + /* Values to set : 32-bit Value */ + /* -------------------------------------------------------------------- */ + *((int *)c_val) = 500; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_REKEY_PACKET_COUNT, c_val, 4, 0, 0)) + goto _fail_; + + c_val[0] = 1; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_SHORT_SLOT_ALLOWED, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = G_SELF_CTS_PROT; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_11N_ERP_PROT_TYPE, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = 1; /* Enable N */ + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_11N_ENABLE, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = HT_MIXED_MODE; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_11N_OPERATING_MODE, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = 1; /* TXOP Prot disable in N mode: No RTS-CTS on TX A-MPDUs to save air-time. */ + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_11N_TXOP_PROT_DISABLE, c_val, 1, 0, 0)) + goto _fail_; + + memcpy(c_val, mac_add, 6); + + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_MAC_ADDR, c_val, 6, 0, 0)) + goto _fail_; + + /** + * AP only + **/ + c_val[0] = DETECT_PROTECT_REPORT; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_11N_OBSS_NONHT_DETECTION, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = RTS_CTS_NONHT_PROT; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_11N_HT_PROT_TYPE, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = 0; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_11N_RIFS_PROT_ENABLE, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = MIMO_MODE; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_11N_SMPS_MODE, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = 7; + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_11N_CURRENT_TX_MCS, c_val, 1, 0, 0)) + goto _fail_; + + c_val[0] = 1; /* Enable N with immediate block ack. */ + if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_11N_IMMEDIATE_BA_ENABLED, c_val, 1, 1, (WILC_Uint32)pstrWFIDrv)) + goto _fail_; + + return 0; + +_fail_: + return -1; +} + + +/**************************/ +void wilc1000_wlan_deinit(linux_wlan_t *nic) +{ + + if (g_linux_wlan->wilc1000_initialized) { + + printk("Deinitializing wilc1000 ...\n"); + + if (nic == NULL) { + PRINT_ER("nic is NULL\n"); + return; + } + +#if defined(PLAT_ALLWINNER_A20) || defined(PLAT_ALLWINNER_A23) || defined(PLAT_ALLWINNER_A31) + /* johnny : remove */ + PRINT_D(INIT_DBG, "skip wilc_bus_set_default_speed\n"); +#else + wilc_bus_set_default_speed(); +#endif + + PRINT_D(INIT_DBG, "Disabling IRQ\n"); + #if (!defined WILC_SDIO) || (defined WILC_SDIO_IRQ_GPIO) + linux_wlan_disable_irq(IRQ_WAIT); + #else + #if defined(PLAT_ALLWINNER_A20) || defined(PLAT_ALLWINNER_A23) || defined(PLAT_ALLWINNER_A31) + + #else + linux_wlan_lock_mutex((void *)&g_linux_wlan->hif_cs); + disable_sdio_interrupt(); + linux_wlan_unlock_mutex((void *)&g_linux_wlan->hif_cs); + #endif + #endif + + + /* not sure if the following unlocks are needed or not*/ + if (&g_linux_wlan->rxq_event != NULL) { + linux_wlan_unlock(&g_linux_wlan->rxq_event); + } + + if (&g_linux_wlan->txq_event != NULL) { + linux_wlan_unlock(&g_linux_wlan->txq_event); + } + + + #if (RX_BH_TYPE == RX_BH_WORK_QUEUE) + /*Removing the work struct from the linux kernel workqueue*/ + if (&g_linux_wlan->rx_work_queue != NULL) + flush_work(&g_linux_wlan->rx_work_queue); + + #elif (RX_BH_TYPE == RX_BH_KTHREAD) + /* if(&nic->rx_sem != NULL) */ + /* linux_wlan_unlock(&nic->rx_sem); */ + #endif + + PRINT_D(INIT_DBG, "Deinitializing Threads\n"); + wlan_deinitialize_threads(nic); + + PRINT_D(INIT_DBG, "Deinitializing IRQ\n"); + deinit_irq(g_linux_wlan); + + + if (&g_linux_wlan->oup != NULL) { + if (g_linux_wlan->oup.wlan_stop != NULL) + g_linux_wlan->oup.wlan_stop(); + } + + PRINT_D(INIT_DBG, "Deinitializing WILC Wlan\n"); + wilc_wlan_deinit(nic); +#if (defined WILC_SDIO) && (!defined WILC_SDIO_IRQ_GPIO) + #if defined(PLAT_ALLWINNER_A20) || defined(PLAT_ALLWINNER_A23) || defined(PLAT_ALLWINNER_A31) + PRINT_D(INIT_DBG, "Disabling IRQ 2\n"); + + linux_wlan_lock_mutex((void *)&g_linux_wlan->hif_cs); + disable_sdio_interrupt(); + linux_wlan_unlock_mutex((void *)&g_linux_wlan->hif_cs); + #endif +#endif + + /*De-Initialize locks*/ + PRINT_D(INIT_DBG, "Deinitializing Locks\n"); + wlan_deinit_locks(g_linux_wlan); + + /* announce that wilc1000 is not initialized */ + g_linux_wlan->wilc1000_initialized = 0; + + PRINT_D(INIT_DBG, "wilc1000 deinitialization Done\n"); + + } else { + PRINT_D(INIT_DBG, "wilc1000 is not initialized\n"); + } + return; +} + +int wlan_init_locks(linux_wlan_t *p_nic) +{ + + PRINT_D(INIT_DBG, "Initializing Locks ...\n"); + + /*initialize mutexes*/ + linux_wlan_init_mutex("hif_lock/hif_cs", &g_linux_wlan->hif_cs, 1); + linux_wlan_init_mutex("rxq_lock/rxq_cs", &g_linux_wlan->rxq_cs, 1); + linux_wlan_init_mutex("txq_lock/txq_cs", &g_linux_wlan->txq_cs, 1); + + /*Added by Amr - BugID_4720*/ + linux_wlan_init_spin_lock("txq_spin_lock/txq_cs", &g_linux_wlan->txq_spinlock, 1); + + /*Added by Amr - BugID_4720*/ + linux_wlan_init_lock("txq_add_to_head_lock/txq_cs", &g_linux_wlan->txq_add_to_head_cs, 1); + + linux_wlan_init_lock("txq_wait/txq_event", &g_linux_wlan->txq_event, 0); + linux_wlan_init_lock("rxq_wait/rxq_event", &g_linux_wlan->rxq_event, 0); + + linux_wlan_init_lock("cfg_wait/cfg_event", &g_linux_wlan->cfg_event, 0); + linux_wlan_init_lock("sync_event", &g_linux_wlan->sync_event, 0); + + linux_wlan_init_lock("rxq_lock/rxq_started", &g_linux_wlan->rxq_thread_started, 0); + linux_wlan_init_lock("rxq_lock/txq_started", &g_linux_wlan->txq_thread_started, 0); + + #if (RX_BH_TYPE == RX_BH_KTHREAD) + linux_wlan_init_lock("BH_SEM", &g_linux_wlan->rx_sem, 0); + #endif + + return 0; +} + +static int wlan_deinit_locks(linux_wlan_t *nic) +{ + PRINT_D(INIT_DBG, "De-Initializing Locks\n"); + + if (&g_linux_wlan->hif_cs != NULL) + linux_wlan_deinit_mutex(&g_linux_wlan->hif_cs); + + if (&g_linux_wlan->rxq_cs != NULL) + linux_wlan_deinit_mutex(&g_linux_wlan->rxq_cs); + + if (&g_linux_wlan->txq_cs != NULL) + linux_wlan_deinit_mutex(&g_linux_wlan->txq_cs); + + /*Added by Amr - BugID_4720*/ + if (&g_linux_wlan->txq_spinlock != NULL) + linux_wlan_deinit_spin_lock(&g_linux_wlan->txq_spinlock); + + if (&g_linux_wlan->rxq_event != NULL) + linux_wlan_deinit_lock(&g_linux_wlan->rxq_event); + + if (&g_linux_wlan->txq_event != NULL) + linux_wlan_deinit_lock(&g_linux_wlan->txq_event); + + /*Added by Amr - BugID_4720*/ + if (&g_linux_wlan->txq_add_to_head_cs != NULL) + linux_wlan_deinit_lock(&g_linux_wlan->txq_add_to_head_cs); + + if (&g_linux_wlan->rxq_thread_started != NULL) + linux_wlan_deinit_lock(&g_linux_wlan->rxq_thread_started); + + if (&g_linux_wlan->txq_thread_started != NULL) + linux_wlan_deinit_lock(&g_linux_wlan->txq_thread_started); + + if (&g_linux_wlan->cfg_event != NULL) + linux_wlan_deinit_lock(&g_linux_wlan->cfg_event); + + if (&g_linux_wlan->sync_event != NULL) + linux_wlan_deinit_lock(&g_linux_wlan->sync_event); + + return 0; +} +void linux_to_wlan(wilc_wlan_inp_t *nwi, linux_wlan_t *nic) +{ + + PRINT_D(INIT_DBG, "Linux to Wlan services ...\n"); + + nwi->os_context.hif_critical_section = (void *)&g_linux_wlan->hif_cs; + nwi->os_context.os_private = (void *)nic; + nwi->os_context.tx_buffer_size = LINUX_TX_SIZE; + nwi->os_context.txq_critical_section = (void *)&g_linux_wlan->txq_cs; + + /*Added by Amr - BugID_4720*/ + nwi->os_context.txq_add_to_head_critical_section = (void *)&g_linux_wlan->txq_add_to_head_cs; + + /*Added by Amr - BugID_4720*/ + nwi->os_context.txq_spin_lock = (void *)&g_linux_wlan->txq_spinlock; + + nwi->os_context.txq_wait_event = (void *)&g_linux_wlan->txq_event; + +#if defined (MEMORY_STATIC) + nwi->os_context.rx_buffer_size = LINUX_RX_SIZE; +#endif + nwi->os_context.rxq_critical_section = (void *)&g_linux_wlan->rxq_cs; + nwi->os_context.rxq_wait_event = (void *)&g_linux_wlan->rxq_event; + nwi->os_context.cfg_wait_event = (void *)&g_linux_wlan->cfg_event; + + nwi->os_func.os_sleep = linux_wlan_msleep; + nwi->os_func.os_atomic_sleep = linux_wlan_atomic_msleep; + nwi->os_func.os_debug = linux_wlan_dbg; + nwi->os_func.os_malloc = linux_wlan_malloc; + nwi->os_func.os_malloc_atomic = linux_wlan_malloc_atomic; + nwi->os_func.os_free = linux_wlan_free; + nwi->os_func.os_lock = linux_wlan_lock; + nwi->os_func.os_unlock = linux_wlan_unlock; + nwi->os_func.os_wait = linux_wlan_lock_timeout; + nwi->os_func.os_signal = linux_wlan_unlock; + nwi->os_func.os_enter_cs = linux_wlan_lock_mutex; + nwi->os_func.os_leave_cs = linux_wlan_unlock_mutex; + + /*Added by Amr - BugID_4720*/ + nwi->os_func.os_spin_lock = linux_wlan_spin_lock; + nwi->os_func.os_spin_unlock = linux_wlan_spin_unlock; + +#ifdef WILC_SDIO + nwi->io_func.io_type = HIF_SDIO; + nwi->io_func.io_init = linux_sdio_init; + nwi->io_func.io_deinit = linux_sdio_deinit; + nwi->io_func.u.sdio.sdio_cmd52 = linux_sdio_cmd52; + nwi->io_func.u.sdio.sdio_cmd53 = linux_sdio_cmd53; + nwi->io_func.u.sdio.sdio_set_max_speed = linux_sdio_set_max_speed; + nwi->io_func.u.sdio.sdio_set_default_speed = linux_sdio_set_default_speed; +#else + nwi->io_func.io_type = HIF_SPI; + nwi->io_func.io_init = linux_spi_init; + nwi->io_func.io_deinit = linux_spi_deinit; + nwi->io_func.u.spi.spi_tx = linux_spi_write; + nwi->io_func.u.spi.spi_rx = linux_spi_read; + nwi->io_func.u.spi.spi_trx = linux_spi_write_read; + nwi->io_func.u.spi.spi_max_speed = linux_spi_set_max_speed; +#endif + + /*for now - to be revised*/ + #ifdef WILC_FULLY_HOSTING_AP + /* incase of Fully hosted AP, all non cfg pkts are processed here*/ + nwi->net_func.rx_indicate = WILC_Process_rx_frame; + #else + nwi->net_func.rx_indicate = frmw_to_linux; + #endif + nwi->net_func.rx_complete = linux_wlan_rx_complete; + nwi->indicate_func.mac_indicate = linux_wlan_mac_indicate; +} + +int wlan_initialize_threads(perInterface_wlan_t *nic) +{ + + int ret = 0; + PRINT_D(INIT_DBG, "Initializing Threads ...\n"); + +#if (RX_BH_TYPE == RX_BH_WORK_QUEUE) + /*Initialize rx work queue task*/ + INIT_WORK(&g_linux_wlan->rx_work_queue, isr_bh_routine); +#elif (RX_BH_TYPE == RX_BH_KTHREAD) + PRINT_D(INIT_DBG, "Creating kthread for Rxq BH\n"); + g_linux_wlan->rx_bh_thread = kthread_run(isr_bh_routine, (void *)g_linux_wlan, "K_RXQ_BH"); + if (g_linux_wlan->rx_bh_thread == 0) { + PRINT_ER("couldn't create RX BH thread\n"); + ret = -ENOBUFS; + goto _fail_; + } +#endif + +#ifndef TCP_ENHANCEMENTS + /* create rx task */ + PRINT_D(INIT_DBG, "Creating kthread for reception\n"); + g_linux_wlan->rxq_thread = kthread_run(linux_wlan_rxq_task, (void *)g_linux_wlan, "K_RXQ_TASK"); + if (g_linux_wlan->rxq_thread == 0) { + PRINT_ER("couldn't create RXQ thread\n"); + ret = -ENOBUFS; + goto _fail_1; + } + + /* wait for RXQ task to start. */ + linux_wlan_lock(&g_linux_wlan->rxq_thread_started); + +#endif + + /* create tx task */ + PRINT_D(INIT_DBG, "Creating kthread for transmission\n"); + g_linux_wlan->txq_thread = kthread_run(linux_wlan_txq_task, (void *)g_linux_wlan, "K_TXQ_TASK"); + if (g_linux_wlan->txq_thread == 0) { + PRINT_ER("couldn't create TXQ thread\n"); + ret = -ENOBUFS; + goto _fail_2; + } +#ifdef DEBUG_MODE + PRINT_D(INIT_DBG, "Creating kthread for Debugging\n"); + g_linux_wlan->txq_thread = kthread_run(DebuggingThreadTask, (void *)g_linux_wlan, "DebugThread"); + if (g_linux_wlan->txq_thread == 0) { + PRINT_ER("couldn't create TXQ thread\n"); + ret = -ENOBUFS; + goto _fail_2; + } +#endif + /* wait for TXQ task to start. */ + linux_wlan_lock(&g_linux_wlan->txq_thread_started); + + return 0; + +_fail_2: + /*De-Initialize 2nd thread*/ + g_linux_wlan->close = 1; + linux_wlan_unlock(&g_linux_wlan->rxq_event); + kthread_stop(g_linux_wlan->rxq_thread); + +_fail_1: + #if (RX_BH_TYPE == RX_BH_KTHREAD) + /*De-Initialize 1st thread*/ + g_linux_wlan->close = 1; + linux_wlan_unlock(&g_linux_wlan->rx_sem); + kthread_stop(g_linux_wlan->rx_bh_thread); +_fail_: + #endif + g_linux_wlan->close = 0; + return ret; +} + +static void wlan_deinitialize_threads(linux_wlan_t *nic) +{ + + g_linux_wlan->close = 1; + PRINT_D(INIT_DBG, "Deinitializing Threads\n"); + if (&g_linux_wlan->rxq_event != NULL) + linux_wlan_unlock(&g_linux_wlan->rxq_event); + + + if (g_linux_wlan->rxq_thread != NULL) { + kthread_stop(g_linux_wlan->rxq_thread); + g_linux_wlan->rxq_thread = NULL; + } + + + if (&g_linux_wlan->txq_event != NULL) + linux_wlan_unlock(&g_linux_wlan->txq_event); + + + if (g_linux_wlan->txq_thread != NULL) { + kthread_stop(g_linux_wlan->txq_thread); + g_linux_wlan->txq_thread = NULL; + } + + #if (RX_BH_TYPE == RX_BH_KTHREAD) + if (&g_linux_wlan->rx_sem != NULL) + linux_wlan_unlock(&g_linux_wlan->rx_sem); + + if (g_linux_wlan->rx_bh_thread != NULL) { + kthread_stop(g_linux_wlan->rx_bh_thread); + g_linux_wlan->rx_bh_thread = NULL; + } + #endif +} + +#ifdef STATIC_MACADDRESS +const char *path_string[] = { + "/etc/wlan", + "/data/wlan", +}; + +static int linux_wlan_read_mac_addr(void *vp) +{ + int ret = 0; + struct file *fp = (struct file *)-ENOENT; + mm_segment_t old_fs; + loff_t pos = 0; + int index; + int array_size = sizeof(path_string) / sizeof(path_string[0]); + + /* change to KERNEL_DS address limit */ + old_fs = get_fs(); + set_fs(KERNEL_DS); + + for (index = 0; index < array_size; index++) { + fp = filp_open(path_string[index], O_WRONLY, 0640); + if (!fp) { + ret = -1; + goto exit; + } + + /*No such file or directory */ + if (IS_ERR(fp) || !fp->f_op) { + get_random_bytes(&mac_add[3], 3); + /* open file to write */ + fp = filp_open(path_string[index], O_WRONLY | O_CREAT, 0640); + + if (!fp || IS_ERR(fp)) { + ret = -1; + continue; + } else { + /* write buf to file */ + fp->f_op->write(fp, mac_add, 6, &pos); + break; + } + } else { + /* read file to buf */ + fp->f_op->read(fp, mac_add, 6, &pos); + break; + } + } + + if (index == array_size) { + PRINT_ER("random MAC\n"); + } + +exit: + if (fp && !IS_ERR(fp)) { + filp_close(fp, NULL); + } + + set_fs(old_fs); + + return ret; +} +#endif + +#ifdef COMPLEMENT_BOOT + +extern volatile int probe; +extern uint8_t core_11b_ready(void); + +#define READY_CHECK_THRESHOLD 30 +extern void wilc_wlan_global_reset(void); +uint8_t wilc1000_prepare_11b_core(wilc_wlan_inp_t *nwi, wilc_wlan_oup_t *nwo, linux_wlan_t *nic) +{ + uint8_t trials = 0; + while ((core_11b_ready() && (READY_CHECK_THRESHOLD > (trials++)))) { + PRINT_D(INIT_DBG, "11b core not ready yet: %u\n", trials); + wilc_wlan_deinit(nic); + wilc_wlan_global_reset(); + sdio_unregister_driver(&wilc_bus); + + linux_wlan_device_detection(0); + + mdelay(100); + + linux_wlan_device_detection(1); + + sdio_register_driver(&wilc_bus); + + while (!probe) { + msleep(100); + } + probe = 0; + g_linux_wlan->wilc_sdio_func = local_sdio_func; + linux_to_wlan(nwi, nic); + wilc_wlan_init(nwi, nwo); + } + + if (READY_CHECK_THRESHOLD <= trials) + return 1; + else + return 0; + +} + +int repeat_power_cycle(perInterface_wlan_t *nic) +{ + int ret = 0; + wilc_wlan_inp_t nwi; + wilc_wlan_oup_t nwo; + sdio_unregister_driver(&wilc_bus); + + linux_wlan_device_detection(0); + linux_wlan_device_power(0); + msleep(100); + linux_wlan_device_power(1); + msleep(80); + linux_wlan_device_detection(1); + msleep(20); + + sdio_register_driver(&wilc_bus); + + /* msleep(1000); */ + while (!probe) { + msleep(100); + } + probe = 0; + g_linux_wlan->wilc_sdio_func = local_sdio_func; + linux_to_wlan(&nwi, g_linux_wlan); + ret = wilc_wlan_init(&nwi, &nwo); + + g_linux_wlan->mac_status = WILC_MAC_STATUS_INIT; + #if (defined WILC_SDIO) && (!defined WILC_SDIO_IRQ_GPIO) + enable_sdio_interrupt(); + #endif + + if (linux_wlan_get_firmware(nic)) { + PRINT_ER("Can't get firmware \n"); + ret = -1; + goto __fail__; + } + + /*Download firmware*/ + ret = linux_wlan_firmware_download(g_linux_wlan); + if (ret < 0) { + PRINT_ER("Failed to download firmware\n"); + goto __fail__; + } + /* Start firmware*/ + ret = linux_wlan_start_firmware(nic); + if (ret < 0) { + PRINT_ER("Failed to start firmware\n"); + } +__fail__: + return ret; +} +#endif + +int wilc1000_wlan_init(struct net_device *dev, perInterface_wlan_t *p_nic) +{ + wilc_wlan_inp_t nwi; + wilc_wlan_oup_t nwo; + perInterface_wlan_t *nic = p_nic; + int ret = 0; + + if (!g_linux_wlan->wilc1000_initialized) { + g_linux_wlan->mac_status = WILC_MAC_STATUS_INIT; + g_linux_wlan->close = 0; + g_linux_wlan->wilc1000_initialized = 0; + + wlan_init_locks(g_linux_wlan); + +#ifdef STATIC_MACADDRESS + wilc_mac_thread = kthread_run(linux_wlan_read_mac_addr, NULL, "wilc_mac_thread"); + if (wilc_mac_thread < 0) { + PRINT_ER("couldn't create Mac addr thread\n"); + } +#endif + + linux_to_wlan(&nwi, g_linux_wlan); + + ret = wilc_wlan_init(&nwi, &nwo); + if (ret < 0) { + PRINT_ER("Initializing WILC_Wlan FAILED\n"); + ret = -EIO; + goto _fail_locks_; + } + memcpy(&g_linux_wlan->oup, &nwo, sizeof(wilc_wlan_oup_t)); + + /*Save the oup structre into global pointer*/ + gpstrWlanOps = &g_linux_wlan->oup; + + + ret = wlan_initialize_threads(nic); + if (ret < 0) { + PRINT_ER("Initializing Threads FAILED\n"); + ret = -EIO; + goto _fail_wilc_wlan_; + } + +#if (defined WILC_SDIO) && (defined COMPLEMENT_BOOT) + if (wilc1000_prepare_11b_core(&nwi, &nwo, g_linux_wlan)) { + PRINT_ER("11b Core is not ready\n"); + ret = -EIO; + goto _fail_threads_; + } +#endif + +#if (!defined WILC_SDIO) || (defined WILC_SDIO_IRQ_GPIO) + if (init_irq(g_linux_wlan)) { + PRINT_ER("couldn't initialize IRQ\n"); + ret = -EIO; + goto _fail_threads_; + } +#endif + +#if (defined WILC_SDIO) && (!defined WILC_SDIO_IRQ_GPIO) + if (enable_sdio_interrupt()) { + PRINT_ER("couldn't initialize IRQ\n"); + ret = -EIO; + goto _fail_irq_init_; + } +#endif + + if (linux_wlan_get_firmware(nic)) { + PRINT_ER("Can't get firmware \n"); + ret = -EIO; + goto _fail_irq_enable_; + } + + + /*Download firmware*/ + ret = linux_wlan_firmware_download(g_linux_wlan); + if (ret < 0) { + PRINT_ER("Failed to download firmware\n"); + ret = -EIO; + goto _fail_irq_enable_; + } + + /* Start firmware*/ + ret = linux_wlan_start_firmware(nic); + if (ret < 0) { + PRINT_ER("Failed to start firmware\n"); + ret = -EIO; + goto _fail_irq_enable_; + } + + wilc_bus_set_max_speed(); + + if (g_linux_wlan->oup.wlan_cfg_get(1, WID_FIRMWARE_VERSION, 1, 0)) { + int size; + char Firmware_ver[20]; + size = g_linux_wlan->oup.wlan_cfg_get_value( + WID_FIRMWARE_VERSION, + Firmware_ver, sizeof(Firmware_ver)); + Firmware_ver[size] = '\0'; + PRINT_D(INIT_DBG, "***** Firmware Ver = %s *******\n", Firmware_ver); + } + /* Initialize firmware with default configuration */ + ret = linux_wlan_init_test_config(dev, g_linux_wlan); + + if (ret < 0) { + PRINT_ER("Failed to configure firmware\n"); + ret = -EIO; + goto _fail_fw_start_; + } + + g_linux_wlan->wilc1000_initialized = 1; + return 0; /*success*/ + + +_fail_fw_start_: + if (&g_linux_wlan->oup != NULL) { + if (g_linux_wlan->oup.wlan_stop != NULL) + g_linux_wlan->oup.wlan_stop(); + } + +_fail_irq_enable_: +#if (defined WILC_SDIO) && (!defined WILC_SDIO_IRQ_GPIO) + disable_sdio_interrupt(); +#endif +_fail_irq_init_: +#if (!defined WILC_SDIO) || (defined WILC_SDIO_IRQ_GPIO) + deinit_irq(g_linux_wlan); + +#endif +_fail_threads_: + wlan_deinitialize_threads(g_linux_wlan); +_fail_wilc_wlan_: + wilc_wlan_deinit(g_linux_wlan); +_fail_locks_: + wlan_deinit_locks(g_linux_wlan); + PRINT_ER("WLAN Iinitialization FAILED\n"); + } else { + PRINT_D(INIT_DBG, "wilc1000 already initialized\n"); + } + return ret; +} + + +/* + * - this function will be called automatically by OS when module inserted. + */ + +#if !defined (NM73131_0_BOARD) +int mac_init_fn(struct net_device *ndev) +{ + + /*Why we do this !!!*/ + netif_start_queue(ndev); /* ma */ + netif_stop_queue(ndev); /* ma */ + + return 0; +} +#else +int mac_init_fn(struct net_device *ndev) +{ + + unsigned char mac_add[] = {0x00, 0x50, 0xc2, 0x5e, 0x10, 0x00}; + /* TODO: get MAC address whenever the source is EPROM - hardcoded and copy it to ndev*/ + memcpy(ndev->dev_addr, mac_add, 6); + + if (!is_valid_ether_addr(ndev->dev_addr)) { + PRINT_ER("Error: Wrong MAC address\n"); + return -EINVAL; + } + + return 0; +} +#endif + + +void WILC_WFI_frame_register(struct wiphy *wiphy, struct net_device *dev, + u16 frame_type, bool reg); + +/* This fn is called, when this device is setup using ifconfig */ +#if !defined (NM73131_0_BOARD) +int mac_open(struct net_device *ndev) +{ + perInterface_wlan_t *nic; + + /*BugID_5213*/ + /*No need for setting mac address here anymore,*/ + /*Just set it in init_test_config()*/ + unsigned char mac_add[ETH_ALEN] = {0}; + int status; + int ret = 0; + int i = 0; + struct WILC_WFI_priv *priv; + + nic = netdev_priv(ndev); + priv = wiphy_priv(nic->wilc_netdev->ieee80211_ptr->wiphy); + PRINT_D(INIT_DBG, "MAC OPEN[%p]\n", ndev); + + #ifdef USE_WIRELESS + ret = WILC_WFI_InitHostInt(ndev); + if (ret < 0) { + PRINT_ER("Failed to initialize host interface\n"); + + return ret; + } + #endif + + /*initialize platform*/ + PRINT_D(INIT_DBG, "*** re-init ***\n"); + ret = wilc1000_wlan_init(ndev, nic); + if (ret < 0) { + PRINT_ER("Failed to initialize wilc1000\n"); + WILC_WFI_DeInitHostInt(ndev); + return ret; + } + + Set_machw_change_vir_if(WILC_FALSE); + + status = host_int_get_MacAddress(priv->hWILCWFIDrv, mac_add); + PRINT_D(INIT_DBG, "Mac address: %x:%x:%x:%x:%x:%x\n", mac_add[0], mac_add[1], mac_add[2], + mac_add[3], mac_add[4], mac_add[5]); + + /* loop through the NUM of supported devices and set the MAC address */ + for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) { + if (ndev == g_linux_wlan->strInterfaceInfo[i].wilc_netdev) { + memcpy(g_linux_wlan->strInterfaceInfo[i].aSrcAddress, mac_add, ETH_ALEN); + g_linux_wlan->strInterfaceInfo[i].drvHandler = (WILC_Uint32)priv->hWILCWFIDrv; + break; + } + } + + /* TODO: get MAC address whenever the source is EPROM - hardcoded and copy it to ndev*/ + memcpy(ndev->dev_addr, g_linux_wlan->strInterfaceInfo[i].aSrcAddress, ETH_ALEN); + + if (!is_valid_ether_addr(ndev->dev_addr)) { + PRINT_ER("Error: Wrong MAC address\n"); + ret = -EINVAL; + goto _err_; + } + + + WILC_WFI_frame_register(nic->wilc_netdev->ieee80211_ptr->wiphy, nic->wilc_netdev, + nic->g_struct_frame_reg[0].frame_type, nic->g_struct_frame_reg[0].reg); + WILC_WFI_frame_register(nic->wilc_netdev->ieee80211_ptr->wiphy, nic->wilc_netdev, + nic->g_struct_frame_reg[1].frame_type, nic->g_struct_frame_reg[1].reg); + netif_wake_queue(ndev); + g_linux_wlan->open_ifcs++; + nic->mac_opened = 1; + return 0; + +_err_: + WILC_WFI_DeInitHostInt(ndev); + wilc1000_wlan_deinit(g_linux_wlan); + return ret; +} +#else +int mac_open(struct net_device *ndev) +{ + + linux_wlan_t *nic; + nic = netdev_priv(ndev); + + /*initialize platform*/ + if (wilc1000_wlan_init(nic)) { + PRINT_ER("Failed to initialize platform\n"); + return 1; + } + /* Start the network interface queue for this device */ + PRINT_D(INIT_DBG, "Starting netifQ\n"); + netif_start_queue(ndev); +/* linux_wlan_lock(&close_exit_sync); */ + return 0; +} +#endif + +struct net_device_stats *mac_stats(struct net_device *dev) +{ + perInterface_wlan_t *nic = netdev_priv(dev); + + + return &nic->netstats; +} + +/* Setup the multicast filter */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) +static void wilc_set_multicast_list(struct net_device *dev) +{ + + struct netdev_hw_addr *ha; + struct WILC_WFI_priv *priv; + tstrWILC_WFIDrv *pstrWFIDrv; + int i = 0; + priv = wiphy_priv(dev->ieee80211_ptr->wiphy); + pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv; + + + if (!dev) + return; + + PRINT_D(INIT_DBG, "Setting Multicast List with count = %d. \n", dev->mc.count); + + if (dev->flags & IFF_PROMISC) { + /* Normally, we should configure the chip to retrive all packets + * but we don't wanna support this right now */ + /* TODO: add promiscuous mode support */ + PRINT_D(INIT_DBG, "Set promiscuous mode ON, retrive all packets \n"); + return; + } + + /* If there's more addresses than we handle, get all multicast + * packets and sort them out in software. */ + if ((dev->flags & IFF_ALLMULTI) || (dev->mc.count) > WILC_MULTICAST_TABLE_SIZE) { + PRINT_D(INIT_DBG, "Disable multicast filter, retrive all multicast packets\n"); + /* get all multicast packets */ + host_int_setup_multicast_filter((WILC_WFIDrvHandle)pstrWFIDrv, WILC_FALSE, 0); + return; + } + + /* No multicast? Just get our own stuff */ + if ((dev->mc.count) == 0) { + PRINT_D(INIT_DBG, "Enable multicast filter, retrive directed packets only.\n"); + host_int_setup_multicast_filter((WILC_WFIDrvHandle)pstrWFIDrv, WILC_TRUE, 0); + return; + } + + /* Store all of the multicast addresses in the hardware filter */ + netdev_for_each_mc_addr(ha, dev) + { + WILC_memcpy(gau8MulticastMacAddrList[i], ha->addr, ETH_ALEN); + PRINT_D(INIT_DBG, "Entry[%d]: %x:%x:%x:%x:%x:%x\n", i, + gau8MulticastMacAddrList[i][0], gau8MulticastMacAddrList[i][1], gau8MulticastMacAddrList[i][2], gau8MulticastMacAddrList[i][3], gau8MulticastMacAddrList[i][4], gau8MulticastMacAddrList[i][5]); + i++; + } + + host_int_setup_multicast_filter((WILC_WFIDrvHandle)pstrWFIDrv, WILC_TRUE, (dev->mc.count)); + + return; + +} + +#else + +static void wilc_set_multicast_list(struct net_device *dev) +{ + /* BIG Warning, Beware : Uncompiled, untested... */ + struct dev_mc_list *mc_ptr; + int i = 0; + + if (!dev) + return; + + PRINT_D(INIT_DBG, "Setting Multicast List. \n"); + PRINT_D(INIT_DBG, "dev->mc_count = %d\n", dev->mc_count); + + if (dev->flags & IFF_PROMISC) { + /* Normally, we should configure the chip to retrive all packets + * but we don't wanna support this right now */ + /* TODO: add promiscuous mode support */ + PRINT_D(INIT_DBG, "Set promiscuous mode ON, retrive all packets \n"); + return; + } + + /* If there's more addresses than we handle, get all multicast + * packets and sort them out in software. */ + if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > WILC_MULTICAST_TABLE_SIZE)) { + PRINT_D(INIT_DBG, "Disable multicast filter, retrive all multicast packets\n"); + host_int_setup_multicast_filter((WILC_WFIDrvHandle)gWFiDrvHandle, WILC_FALSE, 0); + return; + } + + /* No multicast? Just get our own stuff */ + if (dev->mc_count == 0) { + PRINT_D(INIT_DBG, "Enable multicast filter, retrive directed packets only.\n"); + host_int_setup_multicast_filter((WILC_WFIDrvHandle)gWFiDrvHandle, WILC_TRUE, 0); + return; + } + + /* Store all of the multicast addresses in the hardware filter */ + + for (mc_ptr = dev->mc_list; mc_ptr; mc_ptr = mc_ptr->next, i++) { + WILC_memcpy(gau8MulticastMacAddrList[i], mc_ptr->dmi_addr, ETH_ALEN) + i++; + } + + host_int_setup_multicast_filter((WILC_WFIDrvHandle)gWFiDrvHandle, WILC_TRUE, (dev->mc_count)); + +} +#endif + +static void linux_wlan_tx_complete(void *priv, int status) +{ + + struct tx_complete_data *pv_data = (struct tx_complete_data *)priv; + if (status == 1) { + PRINT_D(TX_DBG, "Packet sent successfully - Size = %d - Address = %p - SKB = %p\n", pv_data->size, pv_data->buff, pv_data->skb); + } else { + PRINT_D(TX_DBG, "Couldn't send packet - Size = %d - Address = %p - SKB = %p\n", pv_data->size, pv_data->buff, pv_data->skb); + } + /* Free the SK Buffer, its work is done */ + dev_kfree_skb(pv_data->skb); + linux_wlan_free(pv_data); +} + +int mac_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + perInterface_wlan_t *nic; + struct tx_complete_data *tx_data = NULL; + int QueueCount; + char *pu8UdpBuffer; + struct iphdr *ih; + struct ethhdr *eth_h; + nic = netdev_priv(ndev); + + PRINT_D(INT_DBG, "\n========\n IntUH: %d - IntBH: %d - IntCld: %d \n========\n", int_rcvdU, int_rcvdB, int_clrd); + PRINT_D(TX_DBG, "Sending packet just received from TCP/IP\n"); + + /* Stop the network interface queue */ + if (skb->dev != ndev) { + PRINT_ER("Packet not destined to this device\n"); + return 0; + } + + tx_data = (struct tx_complete_data *)internal_alloc(sizeof(struct tx_complete_data), GFP_ATOMIC); + if (tx_data == NULL) { + PRINT_ER("Failed to allocate memory for tx_data structure\n"); + dev_kfree_skb(skb); + netif_wake_queue(ndev); + return 0; + } + + tx_data->buff = skb->data; + tx_data->size = skb->len; + tx_data->skb = skb; + + eth_h = (struct ethhdr *)(skb->data); + if (eth_h->h_proto == 0x8e88) { + PRINT_D(INIT_DBG, "EAPOL transmitted\n"); + } + + /*get source and dest ip addresses*/ + ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr)); + + pu8UdpBuffer = (char *)ih + sizeof(struct iphdr); + if ((pu8UdpBuffer[1] == 68 && pu8UdpBuffer[3] == 67) || (pu8UdpBuffer[1] == 67 && pu8UdpBuffer[3] == 68)) { + PRINT_D(GENERIC_DBG, "DHCP Message transmitted, type:%x %x %x\n", pu8UdpBuffer[248], pu8UdpBuffer[249], pu8UdpBuffer[250]); + + } + PRINT_D(TX_DBG, "Sending packet - Size = %d - Address = %p - SKB = %p\n", tx_data->size, tx_data->buff, tx_data->skb); + + /* Send packet to MAC HW - for now the tx_complete function will be just status + * indicator. still not sure if I need to suspend host transmission till the tx_complete + * function called or not? + * allocated buffer will be freed in tx_complete function. + */ + PRINT_D(TX_DBG, "Adding tx packet to TX Queue\n"); + nic->netstats.tx_packets++; + nic->netstats.tx_bytes += tx_data->size; + tx_data->pBssid = g_linux_wlan->strInterfaceInfo[nic->u8IfIdx].aBSSID; + #ifndef WILC_FULLY_HOSTING_AP + QueueCount = g_linux_wlan->oup.wlan_add_to_tx_que((void *)tx_data, + tx_data->buff, + tx_data->size, + linux_wlan_tx_complete); + #else + QueueCount = WILC_Xmit_data((void *)tx_data, HOST_TO_WLAN); + #endif /* WILC_FULLY_HOSTING_AP */ + + + if (QueueCount > FLOW_CONTROL_UPPER_THRESHOLD) { + netif_stop_queue(g_linux_wlan->strInterfaceInfo[0].wilc_netdev); + netif_stop_queue(g_linux_wlan->strInterfaceInfo[1].wilc_netdev); + } + + return 0; +} + + +int mac_close(struct net_device *ndev) +{ + struct WILC_WFI_priv *priv; + perInterface_wlan_t *nic; + tstrWILC_WFIDrv *pstrWFIDrv; + + nic = netdev_priv(ndev); + + if ((nic == NULL) || (nic->wilc_netdev == NULL) || (nic->wilc_netdev->ieee80211_ptr == NULL) || (nic->wilc_netdev->ieee80211_ptr->wiphy == NULL)) { + PRINT_ER("nic = NULL\n"); + return 0; + } + + priv = wiphy_priv(nic->wilc_netdev->ieee80211_ptr->wiphy); + + if (priv == NULL) { + PRINT_ER("priv = NULL\n"); + return 0; + } + + pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv; + + + + PRINT_D(GENERIC_DBG, "Mac close\n"); + + if (g_linux_wlan == NULL) { + PRINT_ER("g_linux_wlan = NULL\n"); + return 0; + } + + if (pstrWFIDrv == NULL) { + PRINT_ER("pstrWFIDrv = NULL\n"); + return 0; + } + + if ((g_linux_wlan->open_ifcs) > 0) { + g_linux_wlan->open_ifcs--; + } else { + PRINT_ER("ERROR: MAC close called while number of opened interfaces is zero\n"); + return 0; + } + + if (nic->wilc_netdev != NULL) { + /* Stop the network interface queue */ + netif_stop_queue(nic->wilc_netdev); + + #ifdef USE_WIRELESS + WILC_WFI_DeInitHostInt(nic->wilc_netdev); + #endif + } + + if (g_linux_wlan->open_ifcs == 0) { + PRINT_D(GENERIC_DBG, "Deinitializing wilc1000\n"); + g_linux_wlan->close = 1; + wilc1000_wlan_deinit(g_linux_wlan); + #ifdef USE_WIRELESS + #ifdef WILC_AP_EXTERNAL_MLME + WILC_WFI_deinit_mon_interface(); + #endif + #endif + } + + linux_wlan_unlock(&close_exit_sync); + nic->mac_opened = 0; + + return 0; +} + + +int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd) +{ + + WILC_Uint8 *buff = NULL; + WILC_Sint8 rssi; + WILC_Uint32 size = 0, length = 0; + perInterface_wlan_t *nic; + struct WILC_WFI_priv *priv; + WILC_Sint32 s32Error = WILC_SUCCESS; + + + + /* struct iwreq *wrq = (struct iwreq *) req; // tony moved to case SIOCSIWPRIV */ + #ifdef USE_WIRELESS + nic = netdev_priv(ndev); + + if (!g_linux_wlan->wilc1000_initialized) + return 0; + + #endif + + switch (cmd) { + /* [[ added by tony for SIOCDEVPRIVATE */ + case SIOCDEVPRIVATE + 1: + { + android_wifi_priv_cmd priv_cmd; + + PRINT_INFO(GENERIC_DBG, "in SIOCDEVPRIVATE+1\n"); + + if (copy_from_user(&priv_cmd, req->ifr_data, sizeof(android_wifi_priv_cmd))) { + s32Error = -EFAULT; + goto done; + } + + buff = kmalloc(priv_cmd.total_len, GFP_KERNEL); + if (!buff) { + s32Error = -ENOMEM; + goto done; + } + + if (copy_from_user(buff, priv_cmd.buf, priv_cmd.total_len)) { + s32Error = -EFAULT; + goto done; + } + + PRINT_INFO(GENERIC_DBG, "%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, buff, req->ifr_name); + + if (strncasecmp(buff, "SCAN-ACTIVE", strlen("SCAN-ACTIVE")) == 0) { + PRINT_INFO(GENERIC_DBG, "%s, SCAN-ACTIVE command\n", __FUNCTION__); + } else if (strncasecmp(buff, "SCAN-PASSIVE", strlen("SCAN-PASSIVE")) == 0) { + PRINT_INFO(GENERIC_DBG, "%s, SCAN-PASSIVE command\n", __FUNCTION__); + } else if (strncasecmp(buff, "RXFILTER-START", strlen("RXFILTER-START")) == 0) { + PRINT_INFO(GENERIC_DBG, "%s, RXFILTER-START command\n", __FUNCTION__); + } else if (strncasecmp(buff, "RXFILTER-STOP", strlen("RXFILTER-STOP")) == 0) { + PRINT_INFO(GENERIC_DBG, "%s, RXFILTER-STOP command\n", __FUNCTION__); + } else if (strncasecmp(buff, "RXFILTER-ADD", strlen("RXFILTER-ADD")) == 0) { + int filter_num = *(buff + strlen("RXFILTER-ADD") + 1) - '0'; + PRINT_INFO(GENERIC_DBG, "%s, RXFILTER-ADD command, filter_num=%d\n", __FUNCTION__, filter_num); + } else if (strncasecmp(buff, "RXFILTER-REMOVE", strlen("RXFILTER-REMOVE")) == 0) { + int filter_num = *(buff + strlen("RXFILTER-REMOVE") + 1) - '0'; + PRINT_INFO(GENERIC_DBG, "%s, RXFILTER-REMOVE command, filter_num=%d\n", __FUNCTION__, filter_num); + } else if (strncasecmp(buff, "BTCOEXSCAN-START", strlen("BTCOEXSCAN-START")) == 0) { + PRINT_INFO(GENERIC_DBG, "%s, BTCOEXSCAN-START command\n", __FUNCTION__); + } else if (strncasecmp(buff, "BTCOEXSCAN-STOP", strlen("BTCOEXSCAN-STOP")) == 0) { + PRINT_INFO(GENERIC_DBG, "%s, BTCOEXSCAN-STOP command\n", __FUNCTION__); + } else if (strncasecmp(buff, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0) { + PRINT_INFO(GENERIC_DBG, "%s, BTCOEXMODE command\n", __FUNCTION__); + } else if (strncasecmp(buff, "SETBAND", strlen("SETBAND")) == 0) { + uint band = *(buff + strlen("SETBAND") + 1) - '0'; + PRINT_INFO(GENERIC_DBG, "%s, SETBAND command, band=%d\n", __FUNCTION__, band); + } else if (strncasecmp(buff, "GETBAND", strlen("GETBAND")) == 0) { + PRINT_INFO(GENERIC_DBG, "%s, GETBAND command\n", __FUNCTION__); + } else if (strncasecmp(buff, "COUNTRY", strlen("COUNTRY")) == 0) { + char *country_code = buff + strlen("COUNTRY") + 1; + PRINT_INFO(GENERIC_DBG, "%s, COUNTRY command, country_code=%s\n", __FUNCTION__, country_code); + } else { + PRINT_INFO(GENERIC_DBG, "%s, Unknown command\n", __FUNCTION__); + } + } break; + + /* ]] 2013-06-24 */ + case SIOCSIWPRIV: + { + struct iwreq *wrq = (struct iwreq *) req; /* added by tony */ + + size = wrq->u.data.length; + + if (size && wrq->u.data.pointer) { + buff = kmalloc(size, GFP_KERNEL); + if (!buff) { + s32Error = -ENOMEM; + goto done; + } + + if (copy_from_user + (buff, wrq->u.data.pointer, + wrq->u.data.length)) { + s32Error = -EFAULT; + goto done; + } + + if (strncasecmp(buff, "RSSI", length) == 0) { + + #ifdef USE_WIRELESS + priv = wiphy_priv(nic->wilc_netdev->ieee80211_ptr->wiphy); + s32Error = host_int_get_rssi(priv->hWILCWFIDrv, &(rssi)); + if (s32Error) + PRINT_ER("Failed to send get rssi param's message queue "); + #endif + PRINT_INFO(GENERIC_DBG, "RSSI :%d\n", rssi); + + /*Rounding up the rssi negative value*/ + rssi += 5; + + snprintf(buff, size, "rssi %d", rssi); + + if (copy_to_user(wrq->u.data.pointer, buff, size)) { + PRINT_ER("%s: failed to copy data to user buffer\n", __FUNCTION__); + s32Error = -EFAULT; + goto done; + } + } + } + } + break; + + default: + { + PRINT_INFO(GENERIC_DBG, "Command - %d - has been received\n", cmd); + s32Error = -EOPNOTSUPP; + goto done; + } + } + +done: + + if (buff != NULL) { + kfree(buff); + } + + return s32Error; +} + +void frmw_to_linux(uint8_t *buff, uint32_t size, uint32_t pkt_offset) +{ + + unsigned int frame_len = 0; + int stats; + unsigned char *buff_to_send = NULL; + struct sk_buff *skb; + char *pu8UdpBuffer; + struct iphdr *ih; + struct net_device *wilc_netdev; + perInterface_wlan_t *nic; + + wilc_netdev = GetIfHandler(buff); + if (wilc_netdev == NULL) + return; + + buff += pkt_offset; + nic = netdev_priv(wilc_netdev); + + if (size > 0) { + + frame_len = size; + buff_to_send = buff; + + + /* Need to send the packet up to the host, allocate a skb buffer */ + skb = dev_alloc_skb(frame_len); + if (skb == NULL) { + PRINT_ER("Low memory - packet droped\n"); + return; + } + + skb_reserve(skb, (unsigned int)skb->data & 0x3); + + if (g_linux_wlan == NULL || wilc_netdev == NULL) { + PRINT_ER("wilc_netdev in g_linux_wlan is NULL"); + } + skb->dev = wilc_netdev; + + if (skb->dev == NULL) { + PRINT_ER("skb->dev is NULL\n"); + } + + /* + * for(i=0;i<40;i++) + * { + * if(imonitor_flag) + * { + * WILC_WFI_monitor_rx(nic->wilc_netdev,skb); + * return; + * }*/ +#endif + skb->protocol = eth_type_trans(skb, wilc_netdev); + #ifndef TCP_ENHANCEMENTS + /*get source and dest ip addresses*/ + ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr)); + + pu8UdpBuffer = (char *)ih + sizeof(struct iphdr); + if (buff_to_send[35] == 67 && buff_to_send[37] == 68) { + PRINT_D(RX_DBG, "DHCP Message received\n"); + } + if (buff_to_send[12] == 0x88 && buff_to_send[13] == 0x8e) + PRINT_D(GENERIC_DBG, "eapol received\n"); + #endif + /* Send the packet to the stack by giving it to the bridge */ + nic->netstats.rx_packets++; + nic->netstats.rx_bytes += frame_len; + skb->ip_summed = CHECKSUM_UNNECESSARY; + stats = netif_rx(skb); + PRINT_D(RX_DBG, "netif_rx ret value is: %d\n", stats); + } + #ifndef TCP_ENHANCEMENTS + else { + PRINT_ER("Discard sending packet with len = %d\n", size); + } + #endif +} + +void WILC_WFI_mgmt_rx(uint8_t *buff, uint32_t size) +{ + int i = 0; + perInterface_wlan_t *nic; + + /*BugID_5450*/ + /*Pass the frame on the monitor interface, if any.*/ + /*Otherwise, pass it on p2p0 netdev, if registered on it*/ + for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) { + nic = netdev_priv(g_linux_wlan->strInterfaceInfo[i].wilc_netdev); + if (nic->monitor_flag) { + WILC_WFI_monitor_rx(buff, size); + return; + } + } + + #ifdef WILC_P2P + nic = netdev_priv(g_linux_wlan->strInterfaceInfo[1].wilc_netdev); /* p2p0 */ + if ((buff[0] == nic->g_struct_frame_reg[0].frame_type && nic->g_struct_frame_reg[0].reg) || + (buff[0] == nic->g_struct_frame_reg[1].frame_type && nic->g_struct_frame_reg[1].reg)) { + WILC_WFI_p2p_rx(g_linux_wlan->strInterfaceInfo[1].wilc_netdev, buff, size); + } + #endif +} + +int wilc_netdev_init(void) +{ + + int i; + perInterface_wlan_t *nic; + struct net_device *ndev; + + linux_wlan_init_lock("close_exit_sync", &close_exit_sync, 0); + + /*create the common structure*/ + g_linux_wlan = (linux_wlan_t *)WILC_MALLOC(sizeof(linux_wlan_t)); + memset(g_linux_wlan, 0, sizeof(linux_wlan_t)); + + /*Reset interrupt count debug*/ + int_rcvdU = 0; + int_rcvdB = 0; + int_clrd = 0; + #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP + register_inetaddr_notifier(&g_dev_notifier); + #endif + + for (i = 0; i < NUM_CONCURRENT_IFC; i++) { + /*allocate first ethernet device with perinterface_wlan_t as its private data*/ + ndev = alloc_etherdev(sizeof(perInterface_wlan_t)); + if (!ndev) { + PRINT_ER("Failed to allocate ethernet dev\n"); + return -1; + } + + nic = netdev_priv(ndev); + memset(nic, 0, sizeof(perInterface_wlan_t)); + + /*Name the Devices*/ + if (i == 0) { + #if defined(NM73131) /* tony, 2012-09-20 */ + strcpy(ndev->name, "wilc_eth%d"); + #elif defined(PLAT_CLM9722) /* rachel */ + strcpy(ndev->name, "eth%d"); + #else /* PANDA_BOARD, PLAT_ALLWINNER_A10, PLAT_ALLWINNER_A20, PLAT_ALLWINNER_A31, PLAT_AML8726_M3 or PLAT_WMS8304 */ + strcpy(ndev->name, "wlan%d"); + #endif + } else + strcpy(ndev->name, "p2p%d"); + + nic->u8IfIdx = g_linux_wlan->u8NoIfcs; + nic->wilc_netdev = ndev; + g_linux_wlan->strInterfaceInfo[g_linux_wlan->u8NoIfcs].wilc_netdev = ndev; + g_linux_wlan->u8NoIfcs++; + wilc_set_netdev_ops(ndev); + + #ifdef USE_WIRELESS + { + struct wireless_dev *wdev; + /*Register WiFi*/ + wdev = WILC_WFI_WiphyRegister(ndev); + + #ifdef WILC_SDIO + /* set netdev, tony */ + SET_NETDEV_DEV(ndev, &local_sdio_func->dev); + #endif + + if (wdev == NULL) { + PRINT_ER("Can't register WILC Wiphy\n"); + return -1; + } + + /*linking the wireless_dev structure with the netdevice*/ + nic->wilc_netdev->ieee80211_ptr = wdev; + nic->wilc_netdev->ml_priv = nic; + wdev->netdev = nic->wilc_netdev; + nic->netstats.rx_packets = 0; + nic->netstats.tx_packets = 0; + nic->netstats.rx_bytes = 0; + nic->netstats.tx_bytes = 0; + + } + #endif + + + if (register_netdev(ndev)) { + PRINT_ER("Device couldn't be registered - %s\n", ndev->name); + return -1; /* ERROR */ + } + + nic->iftype = STATION_MODE; + nic->mac_opened = 0; + + } + + #ifndef WILC_SDIO + if (!linux_spi_init(&g_linux_wlan->wilc_spidev)) { + PRINT_ER("Can't initialize SPI \n"); + return -1; /* ERROR */ + } + g_linux_wlan->wilc_spidev = wilc_spi_dev; + #else + g_linux_wlan->wilc_sdio_func = local_sdio_func; + #endif + + return 0; +} + + +/*The 1st function called after module inserted*/ +static int __init init_wilc_driver(void) +{ + + +#if defined (WILC_DEBUGFS) + if (wilc_debugfs_init() < 0) { + PRINT_D(GENERIC_DBG, "fail to create debugfs for wilc driver\n"); + return -1; + } +#endif + + printk("IN INIT FUNCTION\n"); + printk("*** WILC1000 driver VERSION=[%s] FW_VER=[%s] ***\n", __DRIVER_VERSION__, __DRIVER_VERSION__); + + linux_wlan_device_power(1); + msleep(100); + linux_wlan_device_detection(1); + +#ifdef WILC_SDIO + { + int ret; + + ret = sdio_register_driver(&wilc_bus); + if (ret < 0) { + PRINT_D(INIT_DBG, "init_wilc_driver: Failed register sdio driver\n"); + } + + return ret; + } +#else + PRINT_D(INIT_DBG, "Initializing netdev\n"); + if (wilc_netdev_init()) { + PRINT_ER("Couldn't initialize netdev\n"); + } + return 0; +#endif +} +late_initcall(init_wilc_driver); + +static void __exit exit_wilc_driver(void) +{ + int i = 0; + perInterface_wlan_t *nic[NUM_CONCURRENT_IFC]; + #define CLOSE_TIMEOUT (12 * 1000) + + if ((g_linux_wlan != NULL) && (((g_linux_wlan->strInterfaceInfo[0].wilc_netdev) != NULL) + || ((g_linux_wlan->strInterfaceInfo[1].wilc_netdev) != NULL))) { + #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP + unregister_inetaddr_notifier(&g_dev_notifier); + #endif + + for (i = 0; i < NUM_CONCURRENT_IFC; i++) { + nic[i] = netdev_priv(g_linux_wlan->strInterfaceInfo[i].wilc_netdev); + } + } + + + if ((g_linux_wlan != NULL) && g_linux_wlan->wilc_firmware != NULL) { + release_firmware(g_linux_wlan->wilc_firmware); + g_linux_wlan->wilc_firmware = NULL; + } + + + if ((g_linux_wlan != NULL) && (((g_linux_wlan->strInterfaceInfo[0].wilc_netdev) != NULL) + || ((g_linux_wlan->strInterfaceInfo[1].wilc_netdev) != NULL))) { + PRINT_D(INIT_DBG, "Waiting for mac_close ....\n"); + + if (linux_wlan_lock_timeout(&close_exit_sync, CLOSE_TIMEOUT) < 0) + PRINT_D(INIT_DBG, "Closed TimedOUT\n"); + else + PRINT_D(INIT_DBG, "mac_closed\n"); + + + for (i = 0; i < NUM_CONCURRENT_IFC; i++) { + /* close all opened interfaces */ + if (g_linux_wlan->strInterfaceInfo[i].wilc_netdev != NULL) { + if (nic[i]->mac_opened) { + mac_close(g_linux_wlan->strInterfaceInfo[i].wilc_netdev); + } + } + } + for (i = 0; i < NUM_CONCURRENT_IFC; i++) { + PRINT_D(INIT_DBG, "Unregistering netdev %p \n", g_linux_wlan->strInterfaceInfo[i].wilc_netdev); + unregister_netdev(g_linux_wlan->strInterfaceInfo[i].wilc_netdev); + #ifdef USE_WIRELESS + PRINT_D(INIT_DBG, "Freeing Wiphy...\n"); + WILC_WFI_WiphyFree(g_linux_wlan->strInterfaceInfo[i].wilc_netdev); + #endif + PRINT_D(INIT_DBG, "Freeing netdev...\n"); + free_netdev(g_linux_wlan->strInterfaceInfo[i].wilc_netdev); + } + } + + +#ifdef USE_WIRELESS +#ifdef WILC_AP_EXTERNAL_MLME + /* Bug 4600 : WILC_WFI_deinit_mon_interface was already called at mac_close */ + /* WILC_WFI_deinit_mon_interface(); */ +#endif +#endif + + /* if(g_linux_wlan->open_ifcs==0) */ + { + #ifndef WILC_SDIO + PRINT_D(INIT_DBG, "SPI unregsiter...\n"); + spi_unregister_driver(&wilc_bus); + #else + PRINT_D(INIT_DBG, "SDIO unregsiter...\n"); + sdio_unregister_driver(&wilc_bus); + #endif + + linux_wlan_deinit_lock(&close_exit_sync); + if (g_linux_wlan != NULL) { + WILC_FREE(g_linux_wlan); + g_linux_wlan = NULL; + } + printk("Module_exit Done.\n"); + +#if defined (WILC_DEBUGFS) + wilc_debugfs_remove(); +#endif + + linux_wlan_device_detection(0); + linux_wlan_device_power(0); + } +} +module_exit(exit_wilc_driver); + +MODULE_LICENSE("GPL"); +#endif diff --git a/drivers/staging/wilc1000/linux_wlan_common.h b/drivers/staging/wilc1000/linux_wlan_common.h new file mode 100644 index 000000000000..541f19cf44ae --- /dev/null +++ b/drivers/staging/wilc1000/linux_wlan_common.h @@ -0,0 +1,170 @@ +#ifndef LINUX_WLAN_COMMON_H +#define LINUX_WLAN_COMMON_H + +enum debug_region { + Generic_debug = 0, + Hostapd_debug, + Hostinf_debug, + CFG80211_debug, + Coreconfig_debug, + Interrupt_debug, + TX_debug, + RX_debug, + Lock_debug, + Tcp_enhance, + /*Added by amr - BugID_4720*/ + Spin_debug, + + Init_debug, + Bus_debug, + Mem_debug, + Firmware_debug, + COMP = 0xFFFFFFFF, +}; + +#define GENERIC_DBG (1 << Generic_debug) +#define HOSTAPD_DBG (1 << Hostapd_debug) +#define HOSTINF_DBG (1 << Hostinf_debug) +#define CORECONFIG_DBG (1 << Coreconfig_debug) +#define CFG80211_DBG (1 << CFG80211_debug) +#define INT_DBG (1 << Interrupt_debug) +#define TX_DBG (1 << TX_debug) +#define RX_DBG (1 << RX_debug) +#define LOCK_DBG (1 << Lock_debug) +#define TCP_ENH (1 << Tcp_enhance) + + +/*Added by Amr - BugID_4720*/ +#define SPIN_DEBUG (1 << Spin_debug) + +#define INIT_DBG (1 << Init_debug) +#define BUS_DBG (1 << Bus_debug) +#define MEM_DBG (1 << Mem_debug) +#define FIRM_DBG (1 << Firmware_debug) + +#if defined (WILC_DEBUGFS) +extern int wilc_debugfs_init(void); +extern void wilc_debugfs_remove(void); + +extern atomic_t REGION; +extern atomic_t DEBUG_LEVEL; + +#define DEBUG (1 << 0) +#define INFO (1 << 1) +#define WRN (1 << 2) +#define ERR (1 << 3) + +#define PRINT_D(region, ...) do { \ + if ((atomic_read(&DEBUG_LEVEL) & DEBUG) && ((atomic_read(®ION)) & (region))) { \ + printk("DBG [%s: %d]", __FUNCTION__, __LINE__); \ + printk(__VA_ARGS__); \ + } \ +} while (0) + +#define PRINT_INFO(region, ...) do { \ + if ((atomic_read(&DEBUG_LEVEL) & INFO) && ((atomic_read(®ION)) & (region))) { \ + printk("INFO [%s]", __FUNCTION__); \ + printk(__VA_ARGS__); \ + } \ +} while (0) + +#define PRINT_WRN(region, ...) do { \ + if ((atomic_read(&DEBUG_LEVEL) & WRN) && ((atomic_read(®ION)) & (region))) { \ + printk("WRN [%s: %d]", __FUNCTION__, __LINE__); \ + printk(__VA_ARGS__); \ + } \ +} while (0) + +#define PRINT_ER(...) do { \ + if ((atomic_read(&DEBUG_LEVEL) & ERR)) { \ + printk("ERR [%s: %d]", __FUNCTION__, __LINE__); \ + printk(__VA_ARGS__); \ + } \ +} while (0) + +#else + +#define REGION (INIT_DBG | GENERIC_DBG | CFG80211_DBG | FIRM_DBG | HOSTAPD_DBG) + +#define DEBUG 1 +#define INFO 0 +#define WRN 0 +#define PRINT_D(region, ...) do { if (DEBUG == 1 && ((REGION)&(region))) { \ + printk("DBG [%s: %d]", __FUNCTION__, __LINE__); \ + printk(__VA_ARGS__); \ + } \ + } while (0) + +#define PRINT_INFO(region, ...) do { if (INFO == 1 && ((REGION)&(region))) { \ + printk("INFO [%s]", __FUNCTION__); \ + printk(__VA_ARGS__); \ + } \ + } while (0) + +#define PRINT_WRN(region, ...) do { if (WRN == 1 && ((REGION)&(region))) { \ + printk("WRN [%s: %d]", __FUNCTION__, __LINE__); \ + printk(__VA_ARGS__); \ + } \ + } while (0) + +#define PRINT_ER(...) do { printk("ERR [%s: %d]", __FUNCTION__, __LINE__); \ + printk(__VA_ARGS__); \ + } while (0) +#endif + +#define FN_IN /* PRINT_D(">>> \n") */ +#define FN_OUT /* PRINT_D("<<<\n") */ + +#ifdef MEMORY_STATIC +#define LINUX_RX_SIZE (96 * 1024) +#endif +#define LINUX_TX_SIZE (64 * 1024) + + +#define WILC_MULTICAST_TABLE_SIZE 8 + +#if defined (NM73131_0_BOARD) + +#define MODALIAS "wilc_spi" +#define GPIO_NUM IRQ_WILC1000_GPIO + +#elif defined (BEAGLE_BOARD) + #define SPI_CHANNEL 4 + + #if SPI_CHANNEL == 4 + #define MODALIAS "wilc_spi4" + #define GPIO_NUM 162 + #else + #define MODALIAS "wilc_spi3" + #define GPIO_NUM 133 + #endif +#elif defined(PANDA_BOARD) + #define MODALIAS "WILC_SPI" + #define GPIO_NUM 139 +#elif defined(PLAT_WMS8304) /* rachel */ + #define MODALIAS "wilc_spi" + #define GPIO_NUM 139 +#elif defined (PLAT_RKXXXX) + #define MODALIAS "WILC_IRQ" + #define GPIO_NUM RK30_PIN3_PD2 /* RK30_PIN3_PA1 */ +/* RK30_PIN3_PD2 */ +/* RK2928_PIN1_PA7 */ + +#elif defined(CUSTOMER_PLATFORM) +/* + TODO : specify MODALIAS name and GPIO number. This is certainly necessary for SPI interface. + * + * ex) + * #define MODALIAS "WILC_SPI" + * #define GPIO_NUM 139 + */ + +#else +/* base on SAMA5D3_Xplained Board */ + #define MODALIAS "WILC_SPI" + #define GPIO_NUM 0x44 +#endif + + +void linux_wlan_enable_irq(void); +#endif diff --git a/drivers/staging/wilc1000/linux_wlan_sdio.c b/drivers/staging/wilc1000/linux_wlan_sdio.c new file mode 100644 index 000000000000..858e3a191bce --- /dev/null +++ b/drivers/staging/wilc1000/linux_wlan_sdio.c @@ -0,0 +1,249 @@ +#include "wilc_wfi_netdevice.h" + +#include +#include +#include +#include +#include + + + +#if defined (NM73131_0_BOARD) +#define SDIO_MODALIAS "wilc_sdio" +#else +#define SDIO_MODALIAS "wilc1000_sdio" +#endif + +#if defined (NM73131_0_BOARD) + #define MAX_SPEED 50000000 +#elif defined(CUSTOMER_PLATFORM) +/* TODO : User have to stable bus clock as user's environment. */ + #ifdef MAX_BUS_SPEED + #define MAX_SPEED MAX_BUS_SPEED + #else + #define MAX_SPEED 50000000 + #endif +#else + #define MAX_SPEED (6 * 1000000) /* Max 50M */ +#endif + + +struct sdio_func *local_sdio_func; +extern linux_wlan_t *g_linux_wlan; +extern int wilc_netdev_init(void); +extern int sdio_clear_int(void); +extern void wilc_handle_isr(void); + +static unsigned int sdio_default_speed; + +#define SDIO_VENDOR_ID_WILC 0x0296 +#define SDIO_DEVICE_ID_WILC 0x5347 + +static const struct sdio_device_id wilc_sdio_ids[] = { + { SDIO_DEVICE(SDIO_VENDOR_ID_WILC, SDIO_DEVICE_ID_WILC) }, +}; + + +static void wilc_sdio_interrupt(struct sdio_func *func) +{ +#ifndef WILC_SDIO_IRQ_GPIO + sdio_release_host(func); + wilc_handle_isr(); + sdio_claim_host(func); +#endif +} + + +int linux_sdio_cmd52(sdio_cmd52_t *cmd) +{ + struct sdio_func *func = g_linux_wlan->wilc_sdio_func; + int ret; + u8 data; + + sdio_claim_host(func); + + func->num = cmd->function; + if (cmd->read_write) { /* write */ + if (cmd->raw) { + sdio_writeb(func, cmd->data, cmd->address, &ret); + data = sdio_readb(func, cmd->address, &ret); + cmd->data = data; + } else { + sdio_writeb(func, cmd->data, cmd->address, &ret); + } + } else { /* read */ + data = sdio_readb(func, cmd->address, &ret); + cmd->data = data; + } + + sdio_release_host(func); + + if (ret < 0) { + PRINT_ER("wilc_sdio_cmd52..failed, err(%d)\n", ret); + return 0; + } + return 1; +} + + +int linux_sdio_cmd53(sdio_cmd53_t *cmd) +{ + struct sdio_func *func = g_linux_wlan->wilc_sdio_func; + int size, ret; + + sdio_claim_host(func); + + func->num = cmd->function; + func->cur_blksize = cmd->block_size; + if (cmd->block_mode) + size = cmd->count * cmd->block_size; + else + size = cmd->count; + + if (cmd->read_write) { /* write */ + ret = sdio_memcpy_toio(func, cmd->address, (void *)cmd->buffer, size); + } else { /* read */ + ret = sdio_memcpy_fromio(func, (void *)cmd->buffer, cmd->address, size); + } + + sdio_release_host(func); + + + if (ret < 0) { + PRINT_ER("wilc_sdio_cmd53..failed, err(%d)\n", ret); + return 0; + } + + return 1; +} + +volatile int probe; /* COMPLEMENT_BOOT */ +static int linux_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) +{ + PRINT_D(INIT_DBG, "probe function\n"); + +#ifdef COMPLEMENT_BOOT + if (local_sdio_func != NULL) { + local_sdio_func = func; + probe = 1; + PRINT_D(INIT_DBG, "local_sdio_func isn't NULL\n"); + return 0; + } +#endif + PRINT_D(INIT_DBG, "Initializing netdev\n"); + local_sdio_func = func; + if (wilc_netdev_init()) { + PRINT_ER("Couldn't initialize netdev\n"); + return -1; + } + + printk("Driver Initializing success\n"); + return 0; +} + +static void linux_sdio_remove(struct sdio_func *func) +{ + /** + * TODO + **/ + +} + +struct sdio_driver wilc_bus = { + .name = SDIO_MODALIAS, + .id_table = wilc_sdio_ids, + .probe = linux_sdio_probe, + .remove = linux_sdio_remove, +}; + +int enable_sdio_interrupt(void) +{ + int ret = 0; +#ifndef WILC_SDIO_IRQ_GPIO + + sdio_claim_host(local_sdio_func); + ret = sdio_claim_irq(local_sdio_func, wilc_sdio_interrupt); + sdio_release_host(local_sdio_func); + + if (ret < 0) { + PRINT_ER("can't claim sdio_irq, err(%d)\n", ret); + ret = -EIO; + } +#endif + return ret; +} + +void disable_sdio_interrupt(void) +{ + +#ifndef WILC_SDIO_IRQ_GPIO + int ret; + + PRINT_D(INIT_DBG, "disable_sdio_interrupt IN\n"); + + sdio_claim_host(local_sdio_func); + ret = sdio_release_irq(local_sdio_func); + if (ret < 0) { + PRINT_ER("can't release sdio_irq, err(%d)\n", ret); + } + sdio_release_host(local_sdio_func); + + PRINT_D(INIT_DBG, "disable_sdio_interrupt OUT\n"); +#endif +} + +static int linux_sdio_set_speed(int speed) +{ + struct mmc_ios ios; + sdio_claim_host(local_sdio_func); + + memcpy((void *)&ios, (void *)&local_sdio_func->card->host->ios, sizeof(struct mmc_ios)); + local_sdio_func->card->host->ios.clock = speed; + ios.clock = speed; + local_sdio_func->card->host->ops->set_ios(local_sdio_func->card->host, &ios); + sdio_release_host(local_sdio_func); + PRINT_INFO(INIT_DBG, "@@@@@@@@@@@@ change SDIO speed to %d @@@@@@@@@\n", speed); + + return 1; +} + +static int linux_sdio_get_speed(void) +{ + return local_sdio_func->card->host->ios.clock; +} + +int linux_sdio_init(void *pv) +{ + + /** + * TODO : + **/ + + + sdio_default_speed = linux_sdio_get_speed(); + return 1; +} + +void linux_sdio_deinit(void *pv) +{ + + /** + * TODO : + **/ + + + sdio_unregister_driver(&wilc_bus); +} + +int linux_sdio_set_max_speed(void) +{ + return linux_sdio_set_speed(MAX_SPEED); +} + +int linux_sdio_set_default_speed(void) +{ + return linux_sdio_set_speed(sdio_default_speed); +} + + + diff --git a/drivers/staging/wilc1000/linux_wlan_sdio.h b/drivers/staging/wilc1000/linux_wlan_sdio.h new file mode 100644 index 000000000000..4b515f5108e7 --- /dev/null +++ b/drivers/staging/wilc1000/linux_wlan_sdio.h @@ -0,0 +1,14 @@ +extern struct sdio_func *local_sdio_func; +extern struct sdio_driver wilc_bus; + +#include + +int linux_sdio_init(void *); +void linux_sdio_deinit(void *); +int linux_sdio_cmd52(sdio_cmd52_t *cmd); +int linux_sdio_cmd53(sdio_cmd53_t *cmd); +int enable_sdio_interrupt(void); +void disable_sdio_interrupt(void); +int linux_sdio_set_max_speed(void); +int linux_sdio_set_default_speed(void); + diff --git a/drivers/staging/wilc1000/linux_wlan_spi.c b/drivers/staging/wilc1000/linux_wlan_spi.c new file mode 100644 index 000000000000..0c30bbb5fa65 --- /dev/null +++ b/drivers/staging/wilc1000/linux_wlan_spi.c @@ -0,0 +1,510 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "linux_wlan_common.h" + +#define USE_SPI_DMA 0 /* johnny add */ + +#ifdef WILC_ASIC_A0 + #if defined(PLAT_PANDA_ES_OMAP4460) + #define MIN_SPEED 12000000 + #define MAX_SPEED 24000000 + #elif defined(PLAT_WMS8304) + #define MIN_SPEED 12000000 + #define MAX_SPEED 24000000 /* 4000000 */ + #elif defined(CUSTOMER_PLATFORM) +/* + TODO : define Clock speed under 48M. + * + * ex) + * #define MIN_SPEED 24000000 + * #define MAX_SPEED 48000000 + */ + #else + #define MIN_SPEED 24000000 + #define MAX_SPEED 48000000 + #endif +#else /* WILC_ASIC_A0 */ +/* Limit clk to 6MHz on FPGA. */ + #define MIN_SPEED 6000000 + #define MAX_SPEED 6000000 +#endif /* WILC_ASIC_A0 */ + +static uint32_t SPEED = MIN_SPEED; + +struct spi_device *wilc_spi_dev; +void linux_spi_deinit(void *vp); + +static int __init wilc_bus_probe(struct spi_device *spi) +{ + + PRINT_D(BUS_DBG, "spiModalias: %s\n", spi->modalias); + PRINT_D(BUS_DBG, "spiMax-Speed: %d\n", spi->max_speed_hz); + wilc_spi_dev = spi; + + printk("Driver Initializing success\n"); + return 0; +} + +static int __exit wilc_bus_remove(struct spi_device *spi) +{ + + /* linux_spi_deinit(NULL); */ + + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id wilc1000_of_match[] = { + { .compatible = "atmel,wilc_spi", }, + {} +}; +MODULE_DEVICE_TABLE(of, wilc1000_of_match); +#endif + +struct spi_driver wilc_bus __refdata = { + .driver = { + .name = MODALIAS, +#ifdef CONFIG_OF + .of_match_table = wilc1000_of_match, +#endif + }, + .probe = wilc_bus_probe, + .remove = __exit_p(wilc_bus_remove), +}; + + +void linux_spi_deinit(void *vp) +{ + + spi_unregister_driver(&wilc_bus); + + SPEED = MIN_SPEED; + PRINT_ER("@@@@@@@@@@@@ restore SPI speed to %d @@@@@@@@@\n", SPEED); + +} + + + +int linux_spi_init(void *vp) +{ + int ret = 1; + static int called; + + + if (called == 0) { + called++; + if (&wilc_bus == NULL) { + PRINT_ER("wilc_bus address is NULL\n"); + } + ret = spi_register_driver(&wilc_bus); + } + + /* change return value to match WILC interface */ + (ret < 0) ? (ret = 0) : (ret = 1); + + return ret; +} + +#if defined(PLAT_WMS8304) +#define TXRX_PHASE_SIZE (4096) +#endif + +#if defined (NM73131_0_BOARD) + +int linux_spi_write(uint8_t *b, uint32_t len) +{ + + int ret; + + if (len > 0 && b != NULL) { + struct spi_message msg; + PRINT_D(BUS_DBG, "Request writing %d bytes\n", len); + struct spi_transfer tr = { + .tx_buf = b, + .len = len, + .speed_hz = SPEED, + .delay_usecs = 0, + }; + + spi_message_init(&msg); + spi_message_add_tail(&tr, &msg); + ret = spi_sync(wilc_spi_dev, &msg); + if (ret < 0) { + PRINT_ER("SPI transaction failed\n"); + } + + } else { + PRINT_ER("can't write data with the following length: %d\n", len); + PRINT_ER("FAILED due to NULL buffer or ZERO length check the following length: %d\n", len); + ret = -1; + } + + /* change return value to match WILC interface */ + (ret < 0) ? (ret = 0) : (ret = 1); + + + return ret; +} + +#elif defined(TXRX_PHASE_SIZE) + +int linux_spi_write(uint8_t *b, uint32_t len) +{ + int ret; + if (len > 0 && b != NULL) { + int i = 0; + int blk = len / TXRX_PHASE_SIZE; + int remainder = len % TXRX_PHASE_SIZE; + + char *r_buffer = (char *) kzalloc(TXRX_PHASE_SIZE, GFP_KERNEL); + if (!r_buffer) { + PRINT_ER("Failed to allocate memory for r_buffer\n"); + } + + if (blk) { + while (i < blk) { + struct spi_message msg; + struct spi_transfer tr = { + .tx_buf = b + (i * TXRX_PHASE_SIZE), + /* .rx_buf = NULL, */ + .len = TXRX_PHASE_SIZE, + .speed_hz = SPEED, + .bits_per_word = 8, + .delay_usecs = 0, + }; + /* + * char *r_buffer = (char*) kzalloc(TXRX_PHASE_SIZE, GFP_KERNEL); + * if(! r_buffer){ + * PRINT_ER("Failed to allocate memory for r_buffer\n"); + * } + */ + tr.rx_buf = r_buffer; + + memset(&msg, 0, sizeof(msg)); + spi_message_init(&msg); + msg.spi = wilc_spi_dev; + msg.is_dma_mapped = USE_SPI_DMA; + + spi_message_add_tail(&tr, &msg); + ret = spi_sync(wilc_spi_dev, &msg); + if (ret < 0) { + PRINT_ER("SPI transaction failed\n"); + } + /* i += MJ_WRITE_SIZE; */ + i++; + + } + } + if (remainder) { + struct spi_message msg; + struct spi_transfer tr = { + .tx_buf = b + (blk * TXRX_PHASE_SIZE), + /* .rx_buf = NULL, */ + .len = remainder, + .speed_hz = SPEED, + .bits_per_word = 8, + .delay_usecs = 0, + }; + /* + * char *r_buffer = (char*) kzalloc(remainder, GFP_KERNEL); + * if(! r_buffer){ + * PRINT_ER("Failed to allocate memory for r_buffer\n"); + * } + */ + tr.rx_buf = r_buffer; + + memset(&msg, 0, sizeof(msg)); + spi_message_init(&msg); + msg.spi = wilc_spi_dev; + msg.is_dma_mapped = USE_SPI_DMA; /* rachel */ + + spi_message_add_tail(&tr, &msg); + ret = spi_sync(wilc_spi_dev, &msg); + if (ret < 0) { + PRINT_ER("SPI transaction failed\n"); + } + } + if (r_buffer) + kfree(r_buffer); + } else { + PRINT_ER("can't write data with the following length: %d\n", len); + PRINT_ER("FAILED due to NULL buffer or ZERO length check the following length: %d\n", len); + ret = -1; + } + + /* change return value to match WILC interface */ + (ret < 0) ? (ret = 0) : (ret = 1); + + return ret; + +} + +#else +int linux_spi_write(uint8_t *b, uint32_t len) +{ + + int ret; + struct spi_message msg; + + if (len > 0 && b != NULL) { + struct spi_transfer tr = { + .tx_buf = b, + /* .rx_buf = r_buffer, */ + .len = len, + .speed_hz = SPEED, + .delay_usecs = 0, + }; + char *r_buffer = (char *) kzalloc(len, GFP_KERNEL); + if (!r_buffer) { + PRINT_ER("Failed to allocate memory for r_buffer\n"); + } + tr.rx_buf = r_buffer; + PRINT_D(BUS_DBG, "Request writing %d bytes\n", len); + + memset(&msg, 0, sizeof(msg)); + spi_message_init(&msg); +/* [[johnny add */ + msg.spi = wilc_spi_dev; + msg.is_dma_mapped = USE_SPI_DMA; +/* ]] */ + spi_message_add_tail(&tr, &msg); + + ret = spi_sync(wilc_spi_dev, &msg); + if (ret < 0) { + PRINT_ER("SPI transaction failed\n"); + } + + kfree(r_buffer); + } else { + PRINT_ER("can't write data with the following length: %d\n", len); + PRINT_ER("FAILED due to NULL buffer or ZERO length check the following length: %d\n", len); + ret = -1; + } + + /* change return value to match WILC interface */ + (ret < 0) ? (ret = 0) : (ret = 1); + + + return ret; +} + +#endif + +#if defined (NM73131_0_BOARD) + +int linux_spi_read(unsigned char *rb, unsigned long rlen) +{ + + int ret; + + if (rlen > 0) { + struct spi_message msg; + struct spi_transfer tr = { + .rx_buf = rb, + .len = rlen, + .speed_hz = SPEED, + .delay_usecs = 0, + + }; + + spi_message_init(&msg); + spi_message_add_tail(&tr, &msg); + ret = spi_sync(wilc_spi_dev, &msg); + if (ret < 0) { + PRINT_ER("SPI transaction failed\n"); + } + } else { + PRINT_ER("can't read data with the following length: %ld\n", rlen); + ret = -1; + } + /* change return value to match WILC interface */ + (ret < 0) ? (ret = 0) : (ret = 1); + + return ret; +} + +#elif defined(TXRX_PHASE_SIZE) + +int linux_spi_read(unsigned char *rb, unsigned long rlen) +{ + int ret; + + if (rlen > 0) { + int i = 0; + + int blk = rlen / TXRX_PHASE_SIZE; + int remainder = rlen % TXRX_PHASE_SIZE; + + char *t_buffer = (char *) kzalloc(TXRX_PHASE_SIZE, GFP_KERNEL); + if (!t_buffer) { + PRINT_ER("Failed to allocate memory for t_buffer\n"); + } + + if (blk) { + while (i < blk) { + struct spi_message msg; + struct spi_transfer tr = { + /* .tx_buf = NULL, */ + .rx_buf = rb + (i * TXRX_PHASE_SIZE), + .len = TXRX_PHASE_SIZE, + .speed_hz = SPEED, + .bits_per_word = 8, + .delay_usecs = 0, + }; + tr.tx_buf = t_buffer; + + memset(&msg, 0, sizeof(msg)); + spi_message_init(&msg); + msg.spi = wilc_spi_dev; + msg.is_dma_mapped = USE_SPI_DMA; + + spi_message_add_tail(&tr, &msg); + ret = spi_sync(wilc_spi_dev, &msg); + if (ret < 0) { + PRINT_ER("SPI transaction failed\n"); + } + i++; + } + } + if (remainder) { + struct spi_message msg; + struct spi_transfer tr = { + /* .tx_buf = NULL, */ + .rx_buf = rb + (blk * TXRX_PHASE_SIZE), + .len = remainder, + .speed_hz = SPEED, + .bits_per_word = 8, + .delay_usecs = 0, + }; + /* + * char *t_buffer = (char*) kzalloc(remainder, GFP_KERNEL); + * if(! t_buffer){ + * PRINT_ER("Failed to allocate memory for t_buffer\n"); + * } + */ + tr.tx_buf = t_buffer; + + memset(&msg, 0, sizeof(msg)); + spi_message_init(&msg); + msg.spi = wilc_spi_dev; + msg.is_dma_mapped = USE_SPI_DMA; /* rachel */ + + spi_message_add_tail(&tr, &msg); + ret = spi_sync(wilc_spi_dev, &msg); + if (ret < 0) { + PRINT_ER("SPI transaction failed\n"); + } + } + + if (t_buffer) + kfree(t_buffer); + } else { + PRINT_ER("can't read data with the following length: %ld\n", rlen); + ret = -1; + } + /* change return value to match WILC interface */ + (ret < 0) ? (ret = 0) : (ret = 1); + + return ret; +} + +#else +int linux_spi_read(unsigned char *rb, unsigned long rlen) +{ + + int ret; + + if (rlen > 0) { + struct spi_message msg; + struct spi_transfer tr = { + /* .tx_buf = t_buffer, */ + .rx_buf = rb, + .len = rlen, + .speed_hz = SPEED, + .delay_usecs = 0, + + }; + char *t_buffer = (char *) kzalloc(rlen, GFP_KERNEL); + if (!t_buffer) { + PRINT_ER("Failed to allocate memory for t_buffer\n"); + } + tr.tx_buf = t_buffer; + + memset(&msg, 0, sizeof(msg)); + spi_message_init(&msg); +/* [[ johnny add */ + msg.spi = wilc_spi_dev; + msg.is_dma_mapped = USE_SPI_DMA; +/* ]] */ + spi_message_add_tail(&tr, &msg); + + ret = spi_sync(wilc_spi_dev, &msg); + if (ret < 0) { + PRINT_ER("SPI transaction failed\n"); + } + kfree(t_buffer); + } else { + PRINT_ER("can't read data with the following length: %ld\n", rlen); + ret = -1; + } + /* change return value to match WILC interface */ + (ret < 0) ? (ret = 0) : (ret = 1); + + return ret; +} + +#endif + +int linux_spi_write_read(unsigned char *wb, unsigned char *rb, unsigned int rlen) +{ + + int ret; + + if (rlen > 0) { + struct spi_message msg; + struct spi_transfer tr = { + .rx_buf = rb, + .tx_buf = wb, + .len = rlen, + .speed_hz = SPEED, + .bits_per_word = 8, + .delay_usecs = 0, + + }; + + memset(&msg, 0, sizeof(msg)); + spi_message_init(&msg); + msg.spi = wilc_spi_dev; + msg.is_dma_mapped = USE_SPI_DMA; + + spi_message_add_tail(&tr, &msg); + ret = spi_sync(wilc_spi_dev, &msg); + if (ret < 0) { + PRINT_ER("SPI transaction failed\n"); + } + } else { + PRINT_ER("can't read data with the following length: %d\n", rlen); + ret = -1; + } + /* change return value to match WILC interface */ + (ret < 0) ? (ret = 0) : (ret = 1); + + return ret; +} + +int linux_spi_set_max_speed(void) +{ + SPEED = MAX_SPEED; + + PRINT_INFO(BUS_DBG, "@@@@@@@@@@@@ change SPI speed to %d @@@@@@@@@\n", SPEED); + return 1; +} diff --git a/drivers/staging/wilc1000/linux_wlan_spi.h b/drivers/staging/wilc1000/linux_wlan_spi.h new file mode 100644 index 000000000000..0ecad477de1c --- /dev/null +++ b/drivers/staging/wilc1000/linux_wlan_spi.h @@ -0,0 +1,14 @@ +#ifndef LINUX_WLAN_SPI_H +#define LINUX_WLAN_SPI_H + +#include +extern struct spi_device *wilc_spi_dev; +extern struct spi_driver wilc_bus; + +int linux_spi_init(void *vp); +void linux_spi_deinit(void *vp); +int linux_spi_write(uint8_t *b, uint32_t len); +int linux_spi_read(uint8_t *rb, uint32_t rlen); +int linux_spi_write_read(unsigned char *wb, unsigned char *rb, unsigned int rlen); +int linux_spi_set_max_speed(void); +#endif diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c new file mode 100644 index 000000000000..74b9fd5ba27b --- /dev/null +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -0,0 +1,185 @@ +/* + * NewportMedia WiFi chipset driver test tools - wilc-debug + * Copyright (c) 2012 NewportMedia Inc. + * Author: SSW + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#if defined(WILC_DEBUGFS) +#include +#include +#include +#include + +#include "wilc_wlan_if.h" + + +static struct dentry *wilc_dir; + +/* + * -------------------------------------------------------------------------------- + */ + +#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | HOSTINF_DBG | CORECONFIG_DBG | CFG80211_DBG | INT_DBG | TX_DBG | RX_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG) +#define DBG_LEVEL_ALL (DEBUG | INFO | WRN | ERR) +atomic_t REGION = ATOMIC_INIT(INIT_DBG | GENERIC_DBG | CFG80211_DBG | FIRM_DBG | HOSTAPD_DBG); +atomic_t DEBUG_LEVEL = ATOMIC_INIT(ERR); + +/* + * -------------------------------------------------------------------------------- + */ + + +static ssize_t wilc_debug_level_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) +{ + char buf[128]; + int res = 0; + + /* only allow read from start */ + if (*ppos > 0) + return 0; + + res = scnprintf(buf, sizeof(buf), "Debug Level: %x\n", atomic_read(&DEBUG_LEVEL)); + + return simple_read_from_buffer(userbuf, count, ppos, buf, res); +} + +static ssize_t wilc_debug_level_write(struct file *filp, const char *buf, size_t count, loff_t *ppos) +{ + char buffer[128] = {}; + int flag = 0; + + if (copy_from_user(buffer, buf, count)) { + return -EFAULT; + } + + flag = buffer[0] - '0'; + + if (flag > 0) { + flag = DEBUG | ERR; + } else if (flag < 0) { + flag = 100; + } + + if (flag > DBG_LEVEL_ALL) { + printk("%s, value (0x%08x) is out of range, stay previous flag (0x%08x)\n", __func__, flag, atomic_read(&DEBUG_LEVEL)); + return -EFAULT; + } + + atomic_set(&DEBUG_LEVEL, (int)flag); + + if (flag == 0) { + printk("Debug-level disabled\n"); + } else { + printk("Debug-level enabled\n"); + } + return count; +} + +static ssize_t wilc_debug_region_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) +{ + char buf[128]; + int res = 0; + + /* only allow read from start */ + if (*ppos > 0) + return 0; + + res = scnprintf(buf, sizeof(buf), "Debug region: %x\n", atomic_read(®ION)); + + return simple_read_from_buffer(userbuf, count, ppos, buf, res); +} + +static ssize_t wilc_debug_region_write(struct file *filp, const char *buf, size_t count, loff_t *ppos) +{ + char buffer[128] = {}; + int flag; + + if (copy_from_user(buffer, buf, count)) { + return -EFAULT; + } + + flag = buffer[0] - '0'; + + if (flag > DBG_REGION_ALL) { + printk("%s, value (0x%08x) is out of range, stay previous flag (0x%08x)\n", __func__, flag, atomic_read(®ION)); + return -EFAULT; + } + + atomic_set(®ION, (int)flag); + printk("new debug-region is %x\n", atomic_read(®ION)); + + return count; +} + +/* + * -------------------------------------------------------------------------------- + */ + +#define FOPS(_open, _read, _write, _poll) { \ + .owner = THIS_MODULE, \ + .open = (_open), \ + .read = (_read), \ + .write = (_write), \ + .poll = (_poll), \ +} + +struct wilc_debugfs_info_t { + const char *name; + int perm; + unsigned int data; + struct file_operations fops; +}; + +static struct wilc_debugfs_info_t debugfs_info[] = { + { "wilc_debug_level", 0666, (DEBUG | ERR), FOPS(NULL, wilc_debug_level_read, wilc_debug_level_write, NULL), }, + { "wilc_debug_region", 0666, (INIT_DBG | GENERIC_DBG | CFG80211_DBG), FOPS(NULL, wilc_debug_region_read, wilc_debug_region_write, NULL), }, +}; + +int wilc_debugfs_init(void) +{ + int i; + + struct dentry *debugfs_files; + struct wilc_debugfs_info_t *info; + + wilc_dir = debugfs_create_dir("wilc_wifi", NULL); + if (wilc_dir == ERR_PTR(-ENODEV)) { + /* it's not error. the debugfs is just not being enabled. */ + printk("ERR, kernel has built without debugfs support\n"); + return 0; + } + + if (!wilc_dir) { + printk("ERR, debugfs create dir\n"); + return -1; + } + + for (i = 0; i < ARRAY_SIZE(debugfs_info); i++) { + info = &debugfs_info[i]; + debugfs_files = debugfs_create_file(info->name, + info->perm, + wilc_dir, + &info->data, + &info->fops); + + if (!debugfs_files) { + printk("ERR fail to create the debugfs file, %s\n", info->name); + debugfs_remove_recursive(wilc_dir); + return -1; + } + } + return 0; +} + +void wilc_debugfs_remove(void) +{ + debugfs_remove_recursive(wilc_dir); +} + +#endif + diff --git a/drivers/staging/wilc1000/wilc_errorsupport.h b/drivers/staging/wilc1000/wilc_errorsupport.h new file mode 100644 index 000000000000..6405ef8ad431 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_errorsupport.h @@ -0,0 +1,84 @@ +#ifndef __WILC_ERRORSUPPORT_H__ +#define __WILC_ERRORSUPPORT_H__ + +/*! + * @file wilc_errorsupport.h + * @brief Error reporting and handling support + * @author syounan + * @sa wilc_oswrapper.h top level OS wrapper file + * @date 10 Aug 2010 + * @version 1.0 + */ + +#include "linux_wlan_common.h" + +/* Psitive Numbers to indicate sucess with special status */ +#define WILC_ALREADY_EXSIT (+100) /** The requested object already exists */ + +/* Generic success will return 0 */ +#define WILC_SUCCESS 0 /** Generic success */ + +/* Negative numbers to indicate failures */ +#define WILC_FAIL -100 /** Generic Fail */ +#define WILC_BUSY -101 /** Busy with another operation*/ +#define WILC_INVALID_ARGUMENT -102 /** A given argument is invalid*/ +#define WILC_INVALID_STATE -103 /** An API request would violate the Driver state machine (i.e. to start PID while not camped)*/ +#define WILC_BUFFER_OVERFLOW -104 /** In copy operations if the copied data is larger than the allocated buffer*/ +#define WILC_NULL_PTR -105 /** null pointer is passed or used */ +#define WILC_EMPTY -107 +#define WILC_FULL -108 +#define WILC_TIMEOUT -109 +#define WILC_CANCELED -110 /** The required operation have been canceled by the user*/ +#define WILC_INVALID_FILE -112 /** The Loaded file is corruped or having an invalid format */ +#define WILC_NOT_FOUND -113 /** Cant find the file to load */ +#define WILC_NO_MEM -114 +#define WILC_UNSUPPORTED_VERSION -115 +#define WILC_FILE_EOF -116 + + +/* Error type */ +typedef WILC_Sint32 WILC_ErrNo; + +#define WILC_IS_ERR(__status__) (__status__ < WILC_SUCCESS) + +#define WILC_ERRORCHECK(__status__) do { \ + if (WILC_IS_ERR(__status__)) { \ + PRINT_ER("PRINT_ER(%d)\n", __status__); \ + goto ERRORHANDLER; \ + } \ +} while (0) + +#define WILC_ERRORREPORT(__status__, __err__) do { \ + PRINT_ER("PRINT_ER(%d)\n", __err__); \ + __status__ = __err__; \ + goto ERRORHANDLER; \ +} while (0) + +#define WILC_NULLCHECK(__status__, __ptr__) do { \ + if (__ptr__ == WILC_NULL) { \ + WILC_ERRORREPORT(__status__, WILC_NULL_PTR); \ + } \ +} while (0) + +#define WILC_CATCH(__status__) \ +ERRORHANDLER: \ + if (WILC_IS_ERR(__status__)) \ + +#ifdef CONFIG_WILC_ASSERTION_SUPPORT + +/** + * @brief prints a diagnostic message and aborts the program + * @param[in] pcExpression The expression that triggered the assertion + * @param[in] pcFileName The name of the current source file. + * @param[in] u32LineNumber The line number in the current source file. + * @warning DO NOT CALL DIRECTLY. USE EQUIVALENT MACRO FUNCTION INSTEAD. + */ +void WILC_assert_INTERNAL(WILC_Char *pcExpression, WILC_Char *pcFileName, WILC_Uint32 u32LineNumber); + +#define WILC_assert(__expression__) (void)(!!(__expression__) || (WILC_assert_INTERNAL((# __expression__), __WILC_FILE__, __WILC_LINE__), 0)) + +#else +#define WILC_assert(__expression__) ((void)0) +#endif + +#endif diff --git a/drivers/staging/wilc1000/wilc_event.h b/drivers/staging/wilc1000/wilc_event.h new file mode 100644 index 000000000000..94e0f7c0bed5 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_event.h @@ -0,0 +1,123 @@ +#ifndef __WILC_EVENT_H__ +#define __WILC_EVENT_H__ + +/*! + * @file wilc_event.h + * @brief Event OS wrapper functionality + * @author syounan + * @sa wilc_oswrapper.h top level OS wrapper file + * @date 10 Oct 2010 + * @version 1.0 + */ + +#ifndef CONFIG_WILC_EVENT_FEATURE +#error the feature CONFIG_WILC_EVENT_FEATURE must be supported to include this file +#endif + + +/*! + * @struct tstrWILC_TimerAttrs + * @brief Timer API options + * @author syounan + * @date 10 Oct 2010 + * @version 1.0 + */ +typedef struct { + /* a dummy member to avoid compiler errors*/ + WILC_Uint8 dummy; + + #ifdef CONFIG_WILC_EVENT_TIMEOUT + /*!< + * Timeout for use with WILC_EventWait, 0 to return immediately and + * WILC_OS_INFINITY to wait forever. default is WILC_OS_INFINITY + */ + WILC_Uint32 u32TimeOut; + #endif + +} tstrWILC_EventAttrs; + +/*! + * @brief Fills the WILC_TimerAttrs with default parameters + * @param[out] pstrAttrs structure to be filled + * @sa WILC_TimerAttrs + * @author syounan + * @date 10 Oct 2010 + * @version 1.0 + */ +static void WILC_EventFillDefault(tstrWILC_EventAttrs *pstrAttrs) +{ + #ifdef CONFIG_WILC_EVENT_TIMEOUT + pstrAttrs->u32TimeOut = WILC_OS_INFINITY; + #endif +} + +/*! + * @brief Creates a new Event + * @details the Event is an object that allows a thread to wait until an external + * event occuers, Event objects have 2 states, either TRIGGERED or + * UNTRIGGERED + * @param[out] pHandle handle to the newly created event object + * @param[in] pstrAttrs Optional attributes, NULL for default + * @return Error code indicating sucess/failure + * @sa tstrWILC_EventAttrs + * @author syounan + * @date 10 Oct 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_EventCreate(WILC_EventHandle *pHandle, tstrWILC_EventAttrs *pstrAttrs); + + +/*! + * @brief Destroys a given event + * @details This will destroy a given event freeing any resources used by it + * if there are any thread blocked by the WILC_EventWait call the the + * behaviour is undefined + * @param[in] pHandle handle to the event object + * @param[in] pstrAttrs Optional attributes, NULL for default + * @return Error code indicating sucess/failure + * @sa tstrWILC_EventAttrs + * @author syounan + * @date 10 Oct 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_EventDestroy(WILC_EventHandle *pHandle, + tstrWILC_EventAttrs *pstrAttrs); + +/*! + * @brief Triggers a given event + * @details This function will set the given event into the TRIGGERED state, + * if the event is already in TRIGGERED, this function will have no + * effect + * @param[in] pHandle handle to the event object + * @param[in] pstrAttrs Optional attributes, NULL for default + * @return Error code indicating sucess/failure + * @sa tstrWILC_EventAttrs + * @author syounan + * @date 10 Oct 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_EventTrigger(WILC_EventHandle *pHandle, + tstrWILC_EventAttrs *pstrAttrs); + + +/*! + * @brief waits until a given event is triggered + * @details This function will block the calling thread until the event becomes + * in the TRIGGERED state. the call will retun the event into the + * UNTRIGGERED state upon completion + * if multible threads are waiting on the same event at the same time, + * behaviour is undefined + * @param[in] pHandle handle to the event object + * @param[in] pstrAttrs Optional attributes, NULL for default + * @return Error code indicating sucess/failure + * @sa tstrWILC_EventAttrs + * @author syounan + * @date 10 Oct 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_EventWait(WILC_EventHandle *pHandle, + tstrWILC_EventAttrs *pstrAttrs); + + + +#endif \ No newline at end of file diff --git a/drivers/staging/wilc1000/wilc_exported_buf.c b/drivers/staging/wilc1000/wilc_exported_buf.c new file mode 100644 index 000000000000..529457816f65 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_exported_buf.c @@ -0,0 +1,76 @@ +#include +#include +#include +#include +#include + +#define LINUX_RX_SIZE (96 * 1024) +#define LINUX_TX_SIZE (64 * 1024) +#define WILC1000_FW_SIZE (4 * 1024) + +#define DECLARE_WILC_BUFFER(name) \ + void *exported_ ## name = NULL; + +#define MALLOC_WILC_BUFFER(name, size) \ + exported_ ## name = kmalloc(size, GFP_KERNEL); \ + if (!exported_ ## name) { \ + printk("fail to alloc: %s memory\n", exported_ ## name); \ + return -ENOBUFS; \ + } + +#define FREE_WILC_BUFFER(name) \ + kfree(exported_ ## name); + +/* + * Add necessary buffer pointers + */ +DECLARE_WILC_BUFFER(g_tx_buf) +DECLARE_WILC_BUFFER(g_rx_buf) +DECLARE_WILC_BUFFER(g_fw_buf) + +void *get_tx_buffer(void) +{ + return exported_g_tx_buf; +} +EXPORT_SYMBOL(get_tx_buffer); + +void *get_rx_buffer(void) +{ + return exported_g_rx_buf; +} +EXPORT_SYMBOL(get_rx_buffer); + +void *get_fw_buffer(void) +{ + return exported_g_fw_buf; +} +EXPORT_SYMBOL(get_fw_buffer); + +static int __init wilc_module_init(void) +{ + printk("wilc_module_init\n"); + /* + * alloc necessary memory + */ + MALLOC_WILC_BUFFER(g_tx_buf, LINUX_TX_SIZE) + MALLOC_WILC_BUFFER(g_rx_buf, LINUX_RX_SIZE) + MALLOC_WILC_BUFFER(g_fw_buf, WILC1000_FW_SIZE) + + return 0; +} + +static void __exit wilc_module_deinit(void) +{ + printk("wilc_module_deinit\n"); + FREE_WILC_BUFFER(g_tx_buf) + FREE_WILC_BUFFER(g_rx_buf) + FREE_WILC_BUFFER(g_fw_buf) + + return; +} + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Tony Cho"); +MODULE_DESCRIPTION("WILC1xxx Memory Manager"); +pure_initcall(wilc_module_init); +module_exit(wilc_module_deinit); \ No newline at end of file diff --git a/drivers/staging/wilc1000/wilc_log.h b/drivers/staging/wilc1000/wilc_log.h new file mode 100644 index 000000000000..2269ebdec129 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_log.h @@ -0,0 +1,47 @@ +#ifndef __WILC_LOG_H__ +#define __WILC_LOG_H__ + +/* Errors will always get printed */ +#define WILC_ERROR(...) do { WILC_PRINTF("(ERR)(%s:%d) ", __WILC_FUNCTION__, __WILC_LINE__); \ + WILC_PRINTF(__VA_ARGS__); \ + } while (0) + +/* Wraning only printed if verbosity is 1 or more */ +#if (WILC_LOG_VERBOSITY_LEVEL > 0) +#define WILC_WARN(...) do { WILC_PRINTF("(WRN)"); \ + WILC_PRINTF(__VA_ARGS__); \ + } while (0) +#else +#define WILC_WARN(...) (0) +#endif + +/* Info only printed if verbosity is 2 or more */ +#if (WILC_LOG_VERBOSITY_LEVEL > 1) +#define WILC_INFO(...) do { WILC_PRINTF("(INF)"); \ + WILC_PRINTF(__VA_ARGS__); \ + } while (0) +#else +#define WILC_INFO(...) (0) +#endif + +/* Debug is only printed if verbosity is 3 or more */ +#if (WILC_LOG_VERBOSITY_LEVEL > 2) +#define WILC_DBG(...) do { WILC_PRINTF("(DBG)(%s:%d) ", __WILC_FUNCTION__, __WILC_LINE__); \ + WILC_PRINTF(__VA_ARGS__); \ + } while (0) + +#else +#define WILC_DBG(...) (0) +#endif + +/* Function In/Out is only printed if verbosity is 4 or more */ +#if (WILC_LOG_VERBOSITY_LEVEL > 3) +#define WILC_FN_IN do { WILC_PRINTF("(FIN) (%s:%d) \n", __WILC_FUNCTION__, __WILC_LINE__); } while (0) +#define WILC_FN_OUT(ret) do { WILC_PRINTF("(FOUT) (%s:%d) %d.\n", __WILC_FUNCTION__, __WILC_LINE__, (ret)); } while (0) +#else +#define WILC_FN_IN (0) +#define WILC_FN_OUT(ret) (0) +#endif + + +#endif \ No newline at end of file diff --git a/drivers/staging/wilc1000/wilc_memory.c b/drivers/staging/wilc1000/wilc_memory.c new file mode 100644 index 000000000000..cf0976b443b8 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_memory.c @@ -0,0 +1,63 @@ + +#include "wilc_oswrapper.h" + +#ifdef CONFIG_WILC_MEMORY_FEATURE + + +/*! + * @author syounan + * @date 18 Aug 2010 + * @version 1.0 + */ +void *WILC_MemoryAlloc(WILC_Uint32 u32Size, tstrWILC_MemoryAttrs *strAttrs, + WILC_Char *pcFileName, WILC_Uint32 u32LineNo) +{ + if (u32Size > 0) { + return kmalloc(u32Size, GFP_ATOMIC); + } else { + return WILC_NULL; + } +} + +/*! + * @author syounan + * @date 18 Aug 2010 + * @version 1.0 + */ +void *WILC_MemoryCalloc(WILC_Uint32 u32Size, tstrWILC_MemoryAttrs *strAttrs, + WILC_Char *pcFileName, WILC_Uint32 u32LineNo) +{ + return kcalloc(u32Size, 1, GFP_KERNEL); +} + +/*! + * @author syounan + * @date 18 Aug 2010 + * @version 1.0 + */ +void *WILC_MemoryRealloc(void *pvOldBlock, WILC_Uint32 u32NewSize, + tstrWILC_MemoryAttrs *strAttrs, WILC_Char *pcFileName, WILC_Uint32 u32LineNo) +{ + if (u32NewSize == 0) { + kfree(pvOldBlock); + return WILC_NULL; + } else if (pvOldBlock == WILC_NULL) { + return kmalloc(u32NewSize, GFP_KERNEL); + } else { + return krealloc(pvOldBlock, u32NewSize, GFP_KERNEL); + } + +} + +/*! + * @author syounan + * @date 18 Aug 2010 + * @version 1.0 + */ +void WILC_MemoryFree(void *pvBlock, tstrWILC_MemoryAttrs *strAttrs, + WILC_Char *pcFileName, WILC_Uint32 u32LineNo) +{ + kfree(pvBlock); +} + +#endif diff --git a/drivers/staging/wilc1000/wilc_memory.h b/drivers/staging/wilc1000/wilc_memory.h new file mode 100644 index 000000000000..1e45641af454 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_memory.h @@ -0,0 +1,330 @@ +#ifndef __WILC_MEMORY_H__ +#define __WILC_MEMORY_H__ + +/*! + * @file wilc_memory.h + * @brief Memory OS wrapper functionality + * @author syounan + * @sa wilc_oswrapper.h top level OS wrapper file + * @date 16 Aug 2010 + * @version 1.0 + */ + +#ifndef CONFIG_WILC_MEMORY_FEATURE +#error the feature CONFIG_WILC_MEMORY_FEATURE must be supported to include this file +#endif + +/*! + * @struct tstrWILC_MemoryAttrs + * @brief Memory API options + * @author syounan + * @date 16 Aug 2010 + * @version 1.0 + */ +typedef struct { + #ifdef CONFIG_WILC_MEMORY_POOLS + /*!< the allocation pool to use for this memory, NULL for system + * allocation. Default is NULL + */ + WILC_MemoryPoolHandle *pAllocationPool; + #endif + + /* a dummy member to avoid compiler errors*/ + WILC_Uint8 dummy; +} tstrWILC_MemoryAttrs; + +/*! + * @brief Fills the tstrWILC_MemoryAttrs with default parameters + * @param[out] pstrAttrs structure to be filled + * @sa tstrWILC_MemoryAttrs + * @author syounan + * @date 16 Aug 2010 + * @version 1.0 + */ +static void WILC_MemoryFillDefault(tstrWILC_MemoryAttrs *pstrAttrs) +{ + #ifdef CONFIG_WILC_MEMORY_POOLS + pstrAttrs->pAllocationPool = WILC_NULL; + #endif +} + +/*! + * @brief Allocates a given size of bytes + * @param[in] u32Size size of memory in bytes to be allocated + * @param[in] strAttrs Optional attributes, NULL for default + * if not NULL, pAllocationPool should point to the pool to use for + * this allocation. if NULL memory will be allocated directly from + * the system + * @param[in] pcFileName file name of the calling code for debugging + * @param[in] u32LineNo line number of the calling code for debugging + * @return The new allocated block, NULL if allocation fails + * @note It is recommended to use of of the wrapper macros instead of + * calling this function directly + * @sa sttrWILC_MemoryAttrs + * @sa WILC_MALLOC + * @sa WILC_MALLOC_EX + * @sa WILC_NEW + * @sa WILC_NEW_EX + * @author syounan + * @date 16 Aug 2010 + * @version 1.0 + */ +void *WILC_MemoryAlloc(WILC_Uint32 u32Size, tstrWILC_MemoryAttrs *strAttrs, + WILC_Char *pcFileName, WILC_Uint32 u32LineNo); + +/*! + * @brief Allocates a given size of bytes and zero filling it + * @param[in] u32Size size of memory in bytes to be allocated + * @param[in] strAttrs Optional attributes, NULL for default + * if not NULL, pAllocationPool should point to the pool to use for + * this allocation. if NULL memory will be allocated directly from + * the system + * @param[in] pcFileName file name of the calling code for debugging + * @param[in] u32LineNo line number of the calling code for debugging + * @return The new allocated block, NULL if allocation fails + * @note It is recommended to use of of the wrapper macros instead of + * calling this function directly + * @sa sttrWILC_MemoryAttrs + * @sa WILC_CALLOC + * @sa WILC_CALLOC_EX + * @sa WILC_NEW_0 + * @sa WILC_NEW_0_EX + * @author syounan + * @date 16 Aug 2010 + * @version 1.0 + */ +void *WILC_MemoryCalloc(WILC_Uint32 u32Size, tstrWILC_MemoryAttrs *strAttrs, + WILC_Char *pcFileName, WILC_Uint32 u32LineNo); + +/*! + * @brief Reallocates a given block to a new size + * @param[in] pvOldBlock the old memory block, if NULL then this function + * behaves as a new allocation function + * @param[in] u32NewSize size of the new memory block in bytes, if zero then + * this function behaves as a free function + * @param[in] strAttrs Optional attributes, NULL for default + * if pAllocationPool!=NULL and pvOldBlock==NULL, pAllocationPool + * should point to the pool to use for this allocation. + * if pAllocationPool==NULL and pvOldBlock==NULL memory will be + * allocated directly from the system + * if and pvOldBlock!=NULL, pAllocationPool will not be inspected + * and reallocation is done from the same pool as the original block + * @param[in] pcFileName file name of the calling code for debugging + * @param[in] u32LineNo line number of the calling code for debugging + * @return The new allocated block, possibly same as pvOldBlock + * @note It is recommended to use of of the wrapper macros instead of + * calling this function directly + * @sa sttrWILC_MemoryAttrs + * @sa WILC_REALLOC + * @sa WILC_REALLOC_EX + * @author syounan + * @date 16 Aug 2010 + * @version 1.0 + */ +void *WILC_MemoryRealloc(void *pvOldBlock, WILC_Uint32 u32NewSize, + tstrWILC_MemoryAttrs *strAttrs, WILC_Char *pcFileName, WILC_Uint32 u32LineNo); + +/*! + * @brief Frees given block + * @param[in] pvBlock the memory block to be freed + * @param[in] strAttrs Optional attributes, NULL for default + * @param[in] pcFileName file name of the calling code for debugging + * @param[in] u32LineNo line number of the calling code for debugging + * @note It is recommended to use of of the wrapper macros instead of + * calling this function directly + * @sa sttrWILC_MemoryAttrs + * @sa WILC_FREE + * @sa WILC_FREE_EX + * @sa WILC_FREE_SET_NULL + * @sa WILC_FREE_IF_TRUE + * @author syounan + * @date 16 Aug 2010 + * @version 1.0 + */ +void WILC_MemoryFree(void *pvBlock, tstrWILC_MemoryAttrs *strAttrs, + WILC_Char *pcFileName, WILC_Uint32 u32LineNo); + +/*! + * @brief Creates a new memory pool + * @param[out] pHandle the handle to the new Pool + * @param[in] u32PoolSize The pool size in bytes + * @param[in] strAttrs Optional attributes, NULL for default + * @return Error code indicating sucess/failure + * @sa sttrWILC_MemoryAttrs + * @author syounan + * @date 16 Aug 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_MemoryNewPool(WILC_MemoryPoolHandle *pHandle, WILC_Uint32 u32PoolSize, + tstrWILC_MemoryAttrs *strAttrs); + +/*! + * @brief Deletes a memory pool, freeing all memory allocated from it as well + * @param[in] pHandle the handle to the deleted Pool + * @param[in] strAttrs Optional attributes, NULL for default + * @return Error code indicating sucess/failure + * @sa sttrWILC_MemoryAttrs + * @author syounan + * @date 16 Aug 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_MemoryDelPool(WILC_MemoryPoolHandle *pHandle, tstrWILC_MemoryAttrs *strAttrs); + + +#ifdef CONFIG_WILC_MEMORY_DEBUG + +/*! + * @brief standrad malloc wrapper with custom attributes + */ + #define WILC_MALLOC_EX(__size__, __attrs__) \ + (WILC_MemoryAlloc( \ + (__size__), __attrs__, \ + (WILC_Char *)__WILC_FILE__, (WILC_Uint32)__WILC_LINE__)) + +/*! + * @brief standrad calloc wrapper with custom attributes + */ + #define WILC_CALLOC_EX(__size__, __attrs__) \ + (WILC_MemoryCalloc( \ + (__size__), __attrs__, \ + (WILC_Char *)__WILC_FILE__, (WILC_Uint32)__WILC_LINE__)) + +/*! + * @brief standrad realloc wrapper with custom attributes + */ + #define WILC_REALLOC_EX(__ptr__, __new_size__, __attrs__) \ + (WILC_MemoryRealloc( \ + (__ptr__), (__new_size__), __attrs__, \ + (WILC_Char *)__WILC_FILE__, (WILC_Uint32)__WILC_LINE__)) + +/*! + * @brief standrad free wrapper with custom attributes + */ + #define WILC_FREE_EX(__ptr__, __attrs__) \ + (WILC_MemoryFree( \ + (__ptr__), __attrs__, \ + (WILC_Char *)__WILC_FILE__, (WILC_Uint32)__WILC_LINE__)) + +#else + +/*! + * @brief standrad malloc wrapper with custom attributes + */ + #define WILC_MALLOC_EX(__size__, __attrs__) \ + (WILC_MemoryAlloc( \ + (__size__), __attrs__, WILC_NULL, 0)) + +/*! + * @brief standrad calloc wrapper with custom attributes + */ + #define WILC_CALLOC_EX(__size__, __attrs__) \ + (WILC_MemoryCalloc( \ + (__size__), __attrs__, WILC_NULL, 0)) + +/*! + * @brief standrad realloc wrapper with custom attributes + */ + #define WILC_REALLOC_EX(__ptr__, __new_size__, __attrs__) \ + (WILC_MemoryRealloc( \ + (__ptr__), (__new_size__), __attrs__, WILC_NULL, 0)) +/*! + * @brief standrad free wrapper with custom attributes + */ + #define WILC_FREE_EX(__ptr__, __attrs__) \ + (WILC_MemoryFree( \ + (__ptr__), __attrs__, WILC_NULL, 0)) + +#endif + +/*! + * @brief Allocates a block (with custom attributes) of given type and number of + * elements + */ +#define WILC_NEW_EX(__struct_type__, __n_structs__, __attrs__) \ + ((__struct_type__ *)WILC_MALLOC_EX( \ + sizeof(__struct_type__) * (WILC_Uint32)(__n_structs__), __attrs__)) + +/*! + * @brief Allocates a block (with custom attributes) of given type and number of + * elements and Zero-fills it + */ +#define WILC_NEW_0_EX(__struct_type__, __n_structs__, __attrs__) \ + ((__struct_type__ *)WILC_CALLOC_EX( \ + sizeof(__struct_type__) * (WILC_Uint32)(__n_structs__), __attrs__)) + +/*! + * @brief Frees a block (with custom attributes), also setting the original pointer + * to NULL + */ +#define WILC_FREE_SET_NULL_EX(__ptr__, __attrs__) do { \ + if (__ptr__ != WILC_NULL) { \ + WILC_FREE_EX(__ptr__, __attrs__); \ + __ptr__ = WILC_NULL; \ + } \ +} while (0) + +/*! + * @brief Frees a block (with custom attributes) if the pointer expression evaluates + * to true + */ +#define WILC_FREE_IF_TRUE_EX(__ptr__, __attrs__) do { \ + if (__ptr__ != WILC_NULL) { \ + WILC_FREE_EX(__ptr__, __attrs__); \ + } \ +} while (0) + +/*! + * @brief standrad malloc wrapper with default attributes + */ +#define WILC_MALLOC(__size__) \ + WILC_MALLOC_EX(__size__, WILC_NULL) + +/*! + * @brief standrad calloc wrapper with default attributes + */ +#define WILC_CALLOC(__size__) \ + WILC_CALLOC_EX(__size__, WILC_NULL) + +/*! + * @brief standrad realloc wrapper with default attributes + */ +#define WILC_REALLOC(__ptr__, __new_size__) \ + WILC_REALLOC_EX(__ptr__, __new_size__, WILC_NULL) + +/*! + * @brief standrad free wrapper with default attributes + */ +#define WILC_FREE(__ptr__) \ + WILC_FREE_EX(__ptr__, WILC_NULL) + +/*! + * @brief Allocates a block (with default attributes) of given type and number of + * elements + */ +#define WILC_NEW(__struct_type__, __n_structs__) \ + WILC_NEW_EX(__struct_type__, __n_structs__, WILC_NULL) + +/*! + * @brief Allocates a block (with default attributes) of given type and number of + * elements and Zero-fills it + */ +#define WILC_NEW_0(__struct_type__, __n_structs__) \ + WILC_NEW_O_EX(__struct_type__, __n_structs__, WILC_NULL) + +/*! + * @brief Frees a block (with default attributes), also setting the original pointer + * to NULL + */ +#define WILC_FREE_SET_NULL(__ptr__) \ + WILC_FREE_SET_NULL_EX(__ptr__, WILC_NULL) + +/*! + * @brief Frees a block (with default attributes) if the pointer expression evaluates + * to true + */ +#define WILC_FREE_IF_TRUE(__ptr__) \ + WILC_FREE_IF_TRUE_EX(__ptr__, WILC_NULL) + + +#endif + diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c new file mode 100644 index 000000000000..c1d0dabed479 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -0,0 +1,211 @@ + +#include "wilc_oswrapper.h" +#include +#ifdef CONFIG_WILC_MSG_QUEUE_FEATURE + + +/*! + * @author syounan + * @date 1 Sep 2010 + * @note copied from FLO glue implementatuion + * @version 1.0 + */ +WILC_ErrNo WILC_MsgQueueCreate(WILC_MsgQueueHandle *pHandle, + tstrWILC_MsgQueueAttrs *pstrAttrs) +{ + tstrWILC_SemaphoreAttrs strSemAttrs; + WILC_SemaphoreFillDefault(&strSemAttrs); + strSemAttrs.u32InitCount = 0; + + spin_lock_init(&pHandle->strCriticalSection); + if ((WILC_SemaphoreCreate(&pHandle->hSem, &strSemAttrs) == WILC_SUCCESS)) { + + pHandle->pstrMessageList = NULL; + pHandle->u32ReceiversCount = 0; + pHandle->bExiting = WILC_FALSE; + + return WILC_SUCCESS; + } else { + return WILC_FAIL; + } +} + +/*! + * @author syounan + * @date 1 Sep 2010 + * @note copied from FLO glue implementatuion + * @version 1.0 + */ +WILC_ErrNo WILC_MsgQueueDestroy(WILC_MsgQueueHandle *pHandle, + tstrWILC_MsgQueueAttrs *pstrAttrs) +{ + + pHandle->bExiting = WILC_TRUE; + + /* Release any waiting receiver thread. */ + while (pHandle->u32ReceiversCount > 0) { + WILC_SemaphoreRelease(&(pHandle->hSem), WILC_NULL); + pHandle->u32ReceiversCount--; + } + + WILC_SemaphoreDestroy(&pHandle->hSem, WILC_NULL); + + while (pHandle->pstrMessageList != NULL) { + Message *pstrMessge = pHandle->pstrMessageList->pstrNext; + WILC_FREE(pHandle->pstrMessageList); + pHandle->pstrMessageList = pstrMessge; + } + + return WILC_SUCCESS; +} + +/*! + * @author syounan + * @date 1 Sep 2010 + * @note copied from FLO glue implementatuion + * @version 1.0 + */ +WILC_ErrNo WILC_MsgQueueSend(WILC_MsgQueueHandle *pHandle, + const void *pvSendBuffer, WILC_Uint32 u32SendBufferSize, + tstrWILC_MsgQueueAttrs *pstrAttrs) +{ + WILC_ErrNo s32RetStatus = WILC_SUCCESS; + unsigned long flags; + Message *pstrMessage = NULL; + + if ((pHandle == NULL) || (u32SendBufferSize == 0) || (pvSendBuffer == NULL)) { + WILC_ERRORREPORT(s32RetStatus, WILC_INVALID_ARGUMENT); + } + + if (pHandle->bExiting == WILC_TRUE) { + WILC_ERRORREPORT(s32RetStatus, WILC_FAIL); + } + + spin_lock_irqsave(&pHandle->strCriticalSection, flags); + + /* construct a new message */ + pstrMessage = WILC_NEW(Message, 1); + WILC_NULLCHECK(s32RetStatus, pstrMessage); + pstrMessage->u32Length = u32SendBufferSize; + pstrMessage->pstrNext = NULL; + pstrMessage->pvBuffer = WILC_MALLOC(u32SendBufferSize); + WILC_NULLCHECK(s32RetStatus, pstrMessage->pvBuffer); + WILC_memcpy(pstrMessage->pvBuffer, pvSendBuffer, u32SendBufferSize); + + + /* add it to the message queue */ + if (pHandle->pstrMessageList == NULL) { + pHandle->pstrMessageList = pstrMessage; + } else { + Message *pstrTailMsg = pHandle->pstrMessageList; + while (pstrTailMsg->pstrNext != NULL) { + pstrTailMsg = pstrTailMsg->pstrNext; + } + pstrTailMsg->pstrNext = pstrMessage; + } + + spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); + + WILC_SemaphoreRelease(&pHandle->hSem, WILC_NULL); + + WILC_CATCH(s32RetStatus) + { + /* error occured, free any allocations */ + if (pstrMessage != NULL) { + if (pstrMessage->pvBuffer != NULL) { + WILC_FREE(pstrMessage->pvBuffer); + } + WILC_FREE(pstrMessage); + } + } + + return s32RetStatus; +} + + + +/*! + * @author syounan + * @date 1 Sep 2010 + * @note copied from FLO glue implementatuion + * @version 1.0 + */ +WILC_ErrNo WILC_MsgQueueRecv(WILC_MsgQueueHandle *pHandle, + void *pvRecvBuffer, WILC_Uint32 u32RecvBufferSize, + WILC_Uint32 *pu32ReceivedLength, + tstrWILC_MsgQueueAttrs *pstrAttrs) +{ + + Message *pstrMessage; + WILC_ErrNo s32RetStatus = WILC_SUCCESS; + tstrWILC_SemaphoreAttrs strSemAttrs; + unsigned long flags; + if ((pHandle == NULL) || (u32RecvBufferSize == 0) + || (pvRecvBuffer == NULL) || (pu32ReceivedLength == NULL)) { + WILC_ERRORREPORT(s32RetStatus, WILC_INVALID_ARGUMENT); + } + + if (pHandle->bExiting == WILC_TRUE) { + WILC_ERRORREPORT(s32RetStatus, WILC_FAIL); + } + + spin_lock_irqsave(&pHandle->strCriticalSection, flags); + pHandle->u32ReceiversCount++; + spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); + + WILC_SemaphoreFillDefault(&strSemAttrs); + #ifdef CONFIG_WILC_MSG_QUEUE_TIMEOUT + if (pstrAttrs != WILC_NULL) { + strSemAttrs.u32TimeOut = pstrAttrs->u32Timeout; + } + #endif + s32RetStatus = WILC_SemaphoreAcquire(&(pHandle->hSem), &strSemAttrs); + if (s32RetStatus == WILC_TIMEOUT) { + /* timed out, just exit without consumeing the message */ + spin_lock_irqsave(&pHandle->strCriticalSection, flags); + pHandle->u32ReceiversCount--; + spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); + } else { + /* other non-timeout scenarios */ + WILC_ERRORCHECK(s32RetStatus); + + if (pHandle->bExiting) { + WILC_ERRORREPORT(s32RetStatus, WILC_FAIL); + } + + spin_lock_irqsave(&pHandle->strCriticalSection, flags); + + pstrMessage = pHandle->pstrMessageList; + if (pstrMessage == NULL) { + spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); + WILC_ERRORREPORT(s32RetStatus, WILC_FAIL); + } + /* check buffer size */ + if (u32RecvBufferSize < pstrMessage->u32Length) { + spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); + WILC_SemaphoreRelease(&pHandle->hSem, WILC_NULL); + WILC_ERRORREPORT(s32RetStatus, WILC_BUFFER_OVERFLOW); + } + + /* consume the message */ + pHandle->u32ReceiversCount--; + WILC_memcpy(pvRecvBuffer, pstrMessage->pvBuffer, pstrMessage->u32Length); + *pu32ReceivedLength = pstrMessage->u32Length; + + pHandle->pstrMessageList = pstrMessage->pstrNext; + + WILC_FREE(pstrMessage->pvBuffer); + WILC_FREE(pstrMessage); + + spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); + + } + + WILC_CATCH(s32RetStatus) + { + } + + return s32RetStatus; +} + +#endif diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h new file mode 100644 index 000000000000..a48be533aad9 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -0,0 +1,133 @@ +#ifndef __WILC_MSG_QUEUE_H__ +#define __WILC_MSG_QUEUE_H__ + +/*! + * @file wilc_msgqueue.h + * @brief Message Queue OS wrapper functionality + * @author syounan + * @sa wilc_oswrapper.h top level OS wrapper file + * @date 30 Aug 2010 + * @version 1.0 + */ + +#ifndef CONFIG_WILC_MSG_QUEUE_FEATURE +#error the feature CONFIG_WILC_MSG_QUEUE_FEATURE must be supported to include this file +#endif + +/*! + * @struct tstrWILC_MsgQueueAttrs + * @brief Message Queue API options + * @author syounan + * @date 30 Aug 2010 + * @version 1.0 + */ +typedef struct { + #ifdef CONFIG_WILC_MSG_QUEUE_IPC_NAME + WILC_Char *pcName; + #endif + + #ifdef CONFIG_WILC_MSG_QUEUE_TIMEOUT + WILC_Uint32 u32Timeout; + #endif + + /* a dummy member to avoid compiler errors*/ + WILC_Uint8 dummy; + +} tstrWILC_MsgQueueAttrs; + +/*! + * @brief Fills the MsgQueueAttrs with default parameters + * @param[out] pstrAttrs structure to be filled + * @sa WILC_TimerAttrs + * @author syounan + * @date 30 Aug 2010 + * @version 1.0 + */ +static void WILC_MsgQueueFillDefault(tstrWILC_MsgQueueAttrs *pstrAttrs) +{ + #ifdef CONFIG_WILC_MSG_QUEUE_IPC_NAME + pstrAttrs->pcName = WILC_NULL; + #endif + + #ifdef CONFIG_WILC_MSG_QUEUE_TIMEOUT + pstrAttrs->u32Timeout = WILC_OS_INFINITY; + #endif +} +/*! + * @brief Creates a new Message queue + * @details Creates a new Message queue, if the feature + * CONFIG_WILC_MSG_QUEUE_IPC_NAME is enabled and pstrAttrs->pcName + * is not Null, then this message queue can be used for IPC with + * any other message queue having the same name in the system + * @param[in,out] pHandle handle to the message queue object + * @param[in] pstrAttrs Optional attributes, NULL for default + * @return Error code indicating sucess/failure + * @sa tstrWILC_MsgQueueAttrs + * @author syounan + * @date 30 Aug 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_MsgQueueCreate(WILC_MsgQueueHandle *pHandle, + tstrWILC_MsgQueueAttrs *pstrAttrs); + + +/*! + * @brief Sends a message + * @details Sends a message, this API will block unil the message is + * actually sent or until it is timedout (as long as the feature + * CONFIG_WILC_MSG_QUEUE_TIMEOUT is enabled and pstrAttrs->u32Timeout + * is not set to WILC_OS_INFINITY), zero timeout is a valid value + * @param[in] pHandle handle to the message queue object + * @param[in] pvSendBuffer pointer to the data to send + * @param[in] u32SendBufferSize the size of the data to send + * @param[in] pstrAttrs Optional attributes, NULL for default + * @return Error code indicating sucess/failure + * @sa tstrWILC_MsgQueueAttrs + * @author syounan + * @date 30 Aug 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_MsgQueueSend(WILC_MsgQueueHandle *pHandle, + const void *pvSendBuffer, WILC_Uint32 u32SendBufferSize, + tstrWILC_MsgQueueAttrs *pstrAttrs); + + +/*! + * @brief Receives a message + * @details Receives a message, this API will block unil a message is + * received or until it is timedout (as long as the feature + * CONFIG_WILC_MSG_QUEUE_TIMEOUT is enabled and pstrAttrs->u32Timeout + * is not set to WILC_OS_INFINITY), zero timeout is a valid value + * @param[in] pHandle handle to the message queue object + * @param[out] pvRecvBuffer pointer to a buffer to fill with the received message + * @param[in] u32RecvBufferSize the size of the receive buffer + * @param[out] pu32ReceivedLength the length of received data + * @param[in] pstrAttrs Optional attributes, NULL for default + * @return Error code indicating sucess/failure + * @sa tstrWILC_MsgQueueAttrs + * @author syounan + * @date 30 Aug 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_MsgQueueRecv(WILC_MsgQueueHandle *pHandle, + void *pvRecvBuffer, WILC_Uint32 u32RecvBufferSize, + WILC_Uint32 *pu32ReceivedLength, + tstrWILC_MsgQueueAttrs *pstrAttrs); + + +/*! + * @brief Destroys an existing Message queue + * @param[in] pHandle handle to the message queue object + * @param[in] pstrAttrs Optional attributes, NULL for default + * @return Error code indicating sucess/failure + * @sa tstrWILC_MsgQueueAttrs + * @author syounan + * @date 30 Aug 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_MsgQueueDestroy(WILC_MsgQueueHandle *pHandle, + tstrWILC_MsgQueueAttrs *pstrAttrs); + + + +#endif diff --git a/drivers/staging/wilc1000/wilc_osconfig.h b/drivers/staging/wilc1000/wilc_osconfig.h new file mode 100644 index 000000000000..8e89702c79be --- /dev/null +++ b/drivers/staging/wilc1000/wilc_osconfig.h @@ -0,0 +1,55 @@ +/* + * Automatically generated C config: don't edit + * Tue Aug 10 19:52:12 2010 + */ + +/* OSes supported */ +#define WILC_WIN32 0 +#define WILC_NU 1 +#define WILC_MTK 2 +#define WILC_LINUX 3 +#define WILC_LINUXKERNEL 4 +/* the current OS */ +/* #define WILC_PLATFORM WILC_LINUXKERNEL */ + + +/* Logs options */ +#define WILC_LOGS_NOTHING 0 +#define WILC_LOGS_WARN 1 +#define WILC_LOGS_WARN_INFO 2 +#define WILC_LOGS_WARN_INFO_DBG 3 +#define WILC_LOGS_WARN_INFO_DBG_FN 4 +#define WILC_LOGS_ALL 5 + +#define WILC_LOG_VERBOSITY_LEVEL WILC_LOGS_ALL + +/* OS features supported */ + +#define CONFIG_WILC_THREAD_FEATURE 1 +/* #define CONFIG_WILC_THREAD_SUSPEND_CONTROL 1 */ +/* #define CONFIG_WILC_THREAD_STRICT_PRIORITY 1 */ +#define CONFIG_WILC_SEMAPHORE_FEATURE 1 +/* #define CONFIG_WILC_SEMAPHORE_TIMEOUT 1 */ +#define CONFIG_WILC_SLEEP_FEATURE 1 +#define CONFIG_WILC_SLEEP_HI_RES 1 +#define CONFIG_WILC_TIMER_FEATURE 1 +/* #define CONFIG_WILC_TIMER_PERIODIC 1 */ +#define CONFIG_WILC_MEMORY_FEATURE 1 +/* #define CONFIG_WILC_MEMORY_POOLS 1 */ +/* #define CONFIG_WILC_MEMORY_DEBUG 1 */ +/* #define CONFIG_WILC_ASSERTION_SUPPORT 1 */ +#define CONFIG_WILC_STRING_UTILS 1 +#define CONFIG_WILC_MSG_QUEUE_FEATURE +/* #define CONFIG_WILC_MSG_QUEUE_IPC_NAME */ +/* #define CONFIG_WILC_MSG_QUEUE_TIMEOUT */ +/* #define CONFIG_WILC_FILE_OPERATIONS_FEATURE */ +/* #define CONFIG_WILC_FILE_OPERATIONS_STRING_API */ +/* #define CONFIG_WILC_FILE_OPERATIONS_PATH_API */ +#define CONFIG_WILC_TIME_FEATURE +/* #define CONFIG_WILC_EVENT_FEATURE */ +/* #define CONFIG_WILC_EVENT_TIMEOUT */ +/* #define CONFIG_WILC_SOCKET_FEATURE */ +/* #define CONFIG_WILC_MATH_OPERATIONS_FEATURE */ +/* #define CONFIG_WILC_EXTENDED_FILE_OPERATIONS */ +/* #define CONFIG_WILC_EXTENDED_STRING_OPERATIONS */ +/* #define CONFIG_WILC_EXTENDED_TIME_OPERATIONS */ diff --git a/drivers/staging/wilc1000/wilc_oswrapper.h b/drivers/staging/wilc1000/wilc_oswrapper.h new file mode 100644 index 000000000000..e50267ec1ef4 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_oswrapper.h @@ -0,0 +1,133 @@ +#ifndef __WILC_OSWRAPPER_H__ +#define __WILC_OSWRAPPER_H__ + +/*! + * @file wilc_oswrapper.h + * @brief Top level OS Wrapper, include this file and it will include all + * other files as necessary + * @author syounan + * @date 10 Aug 2010 + * @version 1.0 + */ + +/* OS Wrapper interface version */ +#define WILC_OSW_INTERFACE_VER 2 + +/* Integer Types */ +typedef unsigned char WILC_Uint8; +typedef unsigned short WILC_Uint16; +typedef unsigned int WILC_Uint32; +typedef unsigned long long WILC_Uint64; +typedef signed char WILC_Sint8; +typedef signed short WILC_Sint16; +typedef signed int WILC_Sint32; +typedef signed long long WILC_Sint64; + +/* Floating types */ +typedef float WILC_Float; +typedef double WILC_Double; + +/* Boolean type */ +typedef enum { + WILC_FALSE = 0, + WILC_TRUE = 1 +} WILC_Bool; + +/* Character types */ +typedef char WILC_Char; +typedef WILC_Uint16 WILC_WideChar; + +#define WILC_OS_INFINITY (~((WILC_Uint32)0)) +#define WILC_NULL ((void *)0) + +/* standard min and max macros */ +#define WILC_MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define WILC_MAX(a, b) (((a) > (b)) ? (a) : (b)) + +/* Os Configuration File */ +#include "wilc_osconfig.h" + +/* Platform specific include */ +#if WILC_PLATFORM == WILC_WIN32 +#include "wilc_platform.h" +#elif WILC_PLATFORM == WILC_NU +#include "wilc_platform.h" +#elif WILC_PLATFORM == WILC_MTK +#include "wilc_platform.h" +#elif WILC_PLATFORM == WILC_LINUX +#include "wilc_platform.h" +#elif WILC_PLATFORM == WILC_LINUXKERNEL +#include "wilc_platform.h" +#else +#error "OS not supported" +#endif + +/* Logging Functions */ +#include "wilc_log.h" + +/* Error reporting and handling support */ +#include "wilc_errorsupport.h" + +/* Thread support */ +#ifdef CONFIG_WILC_THREAD_FEATURE +#include "wilc_thread.h" +#endif + +/* Semaphore support */ +#ifdef CONFIG_WILC_SEMAPHORE_FEATURE +#include "wilc_semaphore.h" +#endif + +/* Sleep support */ +#ifdef CONFIG_WILC_SLEEP_FEATURE +#include "wilc_sleep.h" +#endif + +/* Timer support */ +#ifdef CONFIG_WILC_TIMER_FEATURE +#include "wilc_timer.h" +#endif + +/* Memory support */ +#ifdef CONFIG_WILC_MEMORY_FEATURE +#include "wilc_memory.h" +#endif + +/* String Utilities */ +#ifdef CONFIG_WILC_STRING_UTILS +#include "wilc_strutils.h" +#endif + +/* Message Queue */ +#ifdef CONFIG_WILC_MSG_QUEUE_FEATURE +#include "wilc_msgqueue.h" +#endif + +/* File operations */ +#ifdef CONFIG_WILC_FILE_OPERATIONS_FEATURE +#include "wilc_fileops.h" +#endif + +/* Time operations */ +#ifdef CONFIG_WILC_TIME_FEATURE +#include "wilc_time.h" +#endif + +/* Event support */ +#ifdef CONFIG_WILC_EVENT_FEATURE +#include "wilc_event.h" +#endif + +/* Socket operations */ +#ifdef CONFIG_WILC_SOCKET_FEATURE +#include "wilc_socket.h" +#endif + +/* Math operations */ +#ifdef CONFIG_WILC_MATH_OPERATIONS_FEATURE +#include "wilc_math.h" +#endif + + + +#endif diff --git a/drivers/staging/wilc1000/wilc_platform.h b/drivers/staging/wilc1000/wilc_platform.h new file mode 100644 index 000000000000..31d5034cb7fa --- /dev/null +++ b/drivers/staging/wilc1000/wilc_platform.h @@ -0,0 +1,181 @@ +#ifndef __WILC_platfrom_H__ +#define __WILC_platfrom_H__ + +/*! + * @file wilc_platform.h + * @brief platform specific file for Linux port + * @author syounan + * @sa wilc_oswrapper.h top level OS wrapper file + * @date 15 Dec 2010 + * @version 1.0 + */ + + +/****************************************************************** + * Feature support checks + *******************************************************************/ + +/* CONFIG_WILC_THREAD_FEATURE is implemented */ + +/* remove the following block when implementing its feature */ +#ifdef CONFIG_WILC_THREAD_SUSPEND_CONTROL +#error This feature is not supported by this OS +#endif + +/* remove the following block when implementing its feature */ +#ifdef CONFIG_WILC_THREAD_STRICT_PRIORITY +#error This feature is not supported by this OS +#endif + +/* CONFIG_WILC_SEMAPHORE_FEATURE is implemented */ + +/* remove the following block when implementing its feature + * #ifdef CONFIG_WILC_SEMAPHORE_TIMEOUT + * #error This feature is not supported by this OS + #endif*/ + +/* CONFIG_WILC_SLEEP_FEATURE is implemented */ + +/* remove the following block when implementing its feature */ +/* #ifdef CONFIG_WILC_SLEEP_HI_RES */ +/* #error This feature is not supported by this OS */ +/* #endif */ + +/* CONFIG_WILC_TIMER_FEATURE is implemented */ + +/* CONFIG_WILC_TIMER_PERIODIC is implemented */ + +/* CONFIG_WILC_MEMORY_FEATURE is implemented */ + +/* remove the following block when implementing its feature */ +#ifdef CONFIG_WILC_MEMORY_POOLS +#error This feature is not supported by this OS +#endif + +/* remove the following block when implementing its feature */ +#ifdef CONFIG_WILC_MEMORY_DEBUG +#error This feature is not supported by this OS +#endif + +/* remove the following block when implementing its feature */ +#ifdef CONFIG_WILC_ASSERTION_SUPPORT +#error This feature is not supported by this OS +#endif + +/* CONFIG_WILC_STRING_UTILS is implemented */ + +/* CONFIG_WILC_MSG_QUEUE_FEATURE is implemented */ + +/* remove the following block when implementing its feature */ +#ifdef CONFIG_WILC_MSG_QUEUE_IPC_NAME +#error This feature is not supported by this OS +#endif + +/* remove the following block when implementing its feature */ +/*#ifdef CONFIG_WILC_MSG_QUEUE_TIMEOUT + * #error This feature is not supported by this OS + #endif*/ + +/* CONFIG_WILC_FILE_OPERATIONS_FEATURE is implemented */ + +/* CONFIG_WILC_FILE_OPERATIONS_STRING_API is implemented */ + +/* remove the following block when implementing its feature */ +#ifdef CONFIG_WILC_FILE_OPERATIONS_PATH_API +#error This feature is not supported by this OS +#endif + +/* CONFIG_WILC_TIME_FEATURE is implemented */ + +/* remove the following block when implementing its feature */ +#ifdef CONFIG_WILC_TIME_UTC_SINCE_1970 +#error This feature is not supported by this OS +#endif + +/* remove the following block when implementing its feature */ +#ifdef CONFIG_WILC_TIME_CALENDER +#error This feature is not supported by this OS +#endif + +/* remove the following block when implementing its feature */ +#ifdef CONFIG_WILC_EVENT_FEATURE +#error This feature is not supported by this OS +#endif + +/* remove the following block when implementing its feature */ +#ifdef CONFIG_WILC_EVENT_TIMEOUT +#error This feature is not supported by this OS +#endif + +/* CONFIG_WILC_MATH_OPERATIONS_FEATURE is implemented */ + +/* CONFIG_WILC_EXTENDED_FILE_OPERATIONS is implemented */ + +/* CONFIG_WILC_EXTENDED_STRING_OPERATIONS is implemented */ + +/* CONFIG_WILC_EXTENDED_TIME_OPERATIONS is implemented */ + +/* remove the following block when implementing its feature */ +#ifdef CONFIG_WILC_SOCKET_FEATURE +#error This feature is not supported by this OS +#endif + +/****************************************************************** + * OS specific includes + *******************************************************************/ +#define _XOPEN_SOURCE 600 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "linux/string.h" +/****************************************************************** + * OS specific types + *******************************************************************/ + +typedef struct task_struct *WILC_ThreadHandle; + +typedef void *WILC_MemoryPoolHandle; +typedef struct semaphore WILC_SemaphoreHandle; + +typedef struct timer_list WILC_TimerHandle; + + + +/* Message Queue type is a structure */ +typedef struct __Message_struct { + void *pvBuffer; + WILC_Uint32 u32Length; + struct __Message_struct *pstrNext; +} Message; + +typedef struct __MessageQueue_struct { + WILC_SemaphoreHandle hSem; + spinlock_t strCriticalSection; + WILC_Bool bExiting; + WILC_Uint32 u32ReceiversCount; + Message *pstrMessageList; +} WILC_MsgQueueHandle; + + + +/*Time represented in 64 bit format*/ +typedef time_t WILC_Time; + + +/******************************************************************* + * others + ********************************************************************/ + +/* Generic printf function */ +#define __WILC_FILE__ __FILE__ +#define __WILC_FUNCTION__ __FUNCTION__ +#define __WILC_LINE__ __LINE__ +#endif diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c new file mode 100644 index 000000000000..d96abb05a83e --- /dev/null +++ b/drivers/staging/wilc1000/wilc_sdio.c @@ -0,0 +1,1298 @@ +/* ////////////////////////////////////////////////////////////////////////// */ +/* */ +/* Copyright (c) Atmel Corporation. All rights reserved. */ +/* */ +/* Module Name: wilc_sdio.c */ +/* */ +/* */ +/* //////////////////////////////////////////////////////////////////////////// */ + +#include "wilc_wlan_if.h" +#include "wilc_wlan.h" + + +#ifdef WILC1000_SINGLE_TRANSFER +#define WILC_SDIO_BLOCK_SIZE 256 +#else + #if defined(PLAT_AML8726_M3) /* johnny */ + #define WILC_SDIO_BLOCK_SIZE 512 + #define MAX_SEG_SIZE (1 << 12) /* 4096 */ + #else + #define WILC_SDIO_BLOCK_SIZE 512 + #endif +#endif + +typedef struct { + void *os_context; + wilc_wlan_os_func_t os_func; + uint32_t block_size; + int (*sdio_cmd52)(sdio_cmd52_t *); + int (*sdio_cmd53)(sdio_cmd53_t *); + int (*sdio_set_max_speed)(void); + int (*sdio_set_default_speed)(void); + wilc_debug_func dPrint; + int nint; +#define MAX_NUN_INT_THRPT_ENH2 (5) /* Max num interrupts allowed in registers 0xf7, 0xf8 */ + int has_thrpt_enh3; +} wilc_sdio_t; + +static wilc_sdio_t g_sdio; + +#ifdef WILC_SDIO_IRQ_GPIO +static int sdio_write_reg(uint32_t addr, uint32_t data); +static int sdio_read_reg(uint32_t addr, uint32_t *data); +#endif +extern unsigned int int_clrd; + +/******************************************** + * + * Function 0 + * + ********************************************/ + +static int sdio_set_func0_csa_address(uint32_t adr) +{ + sdio_cmd52_t cmd; + + /** + * Review: BIG ENDIAN + **/ + cmd.read_write = 1; + cmd.function = 0; + cmd.raw = 0; + cmd.address = 0x10c; + cmd.data = (uint8_t)adr; + if (!g_sdio.sdio_cmd52(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x10c data...\n"); + goto _fail_; + } + + cmd.address = 0x10d; + cmd.data = (uint8_t)(adr >> 8); + if (!g_sdio.sdio_cmd52(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x10d data...\n"); + goto _fail_; + } + + cmd.address = 0x10e; + cmd.data = (uint8_t)(adr >> 16); + if (!g_sdio.sdio_cmd52(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x10e data...\n"); + goto _fail_; + } + + return 1; +_fail_: + return 0; +} + +static int sdio_set_func0_csa_address_byte0(uint32_t adr) +{ + sdio_cmd52_t cmd; + + + /** + * Review: BIG ENDIAN + **/ + cmd.read_write = 1; + cmd.function = 0; + cmd.raw = 0; + cmd.address = 0x10c; + cmd.data = (uint8_t)adr; + if (!g_sdio.sdio_cmd52(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x10c data...\n"); + goto _fail_; + } + + return 1; +_fail_: + return 0; +} +static int sdio_set_func0_block_size(uint32_t block_size) +{ + sdio_cmd52_t cmd; + + cmd.read_write = 1; + cmd.function = 0; + cmd.raw = 0; + cmd.address = 0x10; + cmd.data = (uint8_t)block_size; + if (!g_sdio.sdio_cmd52(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x10 data...\n"); + goto _fail_; + } + + cmd.address = 0x11; + cmd.data = (uint8_t)(block_size >> 8); + if (!g_sdio.sdio_cmd52(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x11 data...\n"); + goto _fail_; + } + + return 1; +_fail_: + return 0; +} + +/******************************************** + * + * Function 1 + * + ********************************************/ + +static int sdio_set_func1_block_size(uint32_t block_size) +{ + sdio_cmd52_t cmd; + + cmd.read_write = 1; + cmd.function = 0; + cmd.raw = 0; + cmd.address = 0x110; + cmd.data = (uint8_t)block_size; + if (!g_sdio.sdio_cmd52(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x110 data...\n"); + goto _fail_; + } + cmd.address = 0x111; + cmd.data = (uint8_t)(block_size >> 8); + if (!g_sdio.sdio_cmd52(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x111 data...\n"); + goto _fail_; + } + + return 1; +_fail_: + return 0; +} + +static int sdio_clear_int(void) +{ +#ifndef WILC_SDIO_IRQ_GPIO + /* uint32_t sts; */ + sdio_cmd52_t cmd; + cmd.read_write = 0; + cmd.function = 1; + cmd.raw = 0; + cmd.address = 0x4; + cmd.data = 0; + g_sdio.sdio_cmd52(&cmd); + int_clrd++; + + return cmd.data; +#else + uint32_t reg; + if (!sdio_read_reg(WILC_HOST_RX_CTRL_0, ®)) { + g_sdio.dPrint(N_ERR, "[wilc spi]: Failed read reg (%08x)...\n", WILC_HOST_RX_CTRL_0); + return 0; + } + reg &= ~0x1; + sdio_write_reg(WILC_HOST_RX_CTRL_0, reg); + int_clrd++; + return 1; +#endif + +} + +uint32_t sdio_xfer_cnt(void) +{ + uint32_t cnt = 0; + sdio_cmd52_t cmd; + cmd.read_write = 0; + cmd.function = 1; + cmd.raw = 0; + cmd.address = 0x1C; + cmd.data = 0; + g_sdio.sdio_cmd52(&cmd); + cnt = cmd.data; + + cmd.read_write = 0; + cmd.function = 1; + cmd.raw = 0; + cmd.address = 0x1D; + cmd.data = 0; + g_sdio.sdio_cmd52(&cmd); + cnt |= (cmd.data << 8); + + cmd.read_write = 0; + cmd.function = 1; + cmd.raw = 0; + cmd.address = 0x1E; + cmd.data = 0; + g_sdio.sdio_cmd52(&cmd); + cnt |= (cmd.data << 16); + + return cnt; + + +} + +/******************************************** + * + * Sdio interfaces + * + ********************************************/ +int sdio_check_bs(void) +{ + sdio_cmd52_t cmd; + + /** + * poll until BS is 0 + **/ + cmd.read_write = 0; + cmd.function = 0; + cmd.raw = 0; + cmd.address = 0xc; + cmd.data = 0; + if (!g_sdio.sdio_cmd52(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd 52, get BS register...\n"); + goto _fail_; + } + + return 1; + +_fail_: + + return 0; +} + +static int sdio_write_reg(uint32_t addr, uint32_t data) +{ +#ifdef BIG_ENDIAN + data = BYTE_SWAP(data); +#endif + + if ((addr >= 0xf0) && (addr <= 0xff)) { + sdio_cmd52_t cmd; + cmd.read_write = 1; + cmd.function = 0; + cmd.raw = 0; + cmd.address = addr; + cmd.data = data; + if (!g_sdio.sdio_cmd52(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd 52, read reg (%08x) ...\n", addr); + goto _fail_; + } + } else { + sdio_cmd53_t cmd; + + /** + * set the AHB address + **/ + if (!sdio_set_func0_csa_address(addr)) + goto _fail_; + + cmd.read_write = 1; + cmd.function = 0; + cmd.address = 0x10f; + cmd.block_mode = 0; + cmd.increment = 1; + cmd.count = 4; + cmd.buffer = (uint8_t *)&data; + cmd.block_size = g_sdio.block_size; /* johnny : prevent it from setting unexpected value */ + + if (!g_sdio.sdio_cmd53(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53, write reg (%08x)...\n", addr); + goto _fail_; + } + +#if 0 + if (!sdio_check_bs()) + goto _fail_; +#else + /* g_sdio.os_func.os_sleep(1); */ +#endif + } + + return 1; + +_fail_: + + return 0; +} + +static int sdio_write(uint32_t addr, uint8_t *buf, uint32_t size) +{ + uint32_t block_size = g_sdio.block_size; + sdio_cmd53_t cmd; + int nblk, nleft; + + cmd.read_write = 1; + if (addr > 0) { + /** + * has to be word aligned... + **/ + if (size & 0x3) { + size += 4; + size &= ~0x3; + } + + /** + * func 0 access + **/ + cmd.function = 0; + cmd.address = 0x10f; + } else { +#ifdef WILC1000_SINGLE_TRANSFER + /** + * has to be block aligned... + **/ + nleft = size % block_size; + if (nleft > 0) { + size += block_size; + size &= ~(block_size - 1); + } +#else + /** + * has to be word aligned... + **/ + if (size & 0x3) { + size += 4; + size &= ~0x3; + } +#endif + + /** + * func 1 access + **/ + cmd.function = 1; + cmd.address = 0; + } + + nblk = size / block_size; + nleft = size % block_size; + + if (nblk > 0) { + +#if defined(PLAT_AML8726_M3_BACKUP) /* johnny */ + int i; + + for (i = 0; i < nblk; i++) { + cmd.block_mode = 0; /* 1; */ + cmd.increment = 1; + cmd.count = block_size; /* nblk; */ + cmd.buffer = buf; + cmd.block_size = block_size; + if (addr > 0) { + if (!sdio_set_func0_csa_address(addr)) + goto _fail_; + } + if (!g_sdio.sdio_cmd53(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block send...\n", addr); + goto _fail_; + } + + if (addr > 0) + addr += block_size; /* addr += nblk*block_size; */ + + buf += block_size; /* buf += nblk*block_size; */ + } + +#elif defined(PLAT_AML8726_M3) /* johnny */ + + int i; + int rest; + int seg_cnt; + + seg_cnt = (nblk * block_size) / MAX_SEG_SIZE; + rest = (nblk * block_size) & (MAX_SEG_SIZE - 1); + + for (i = 0; i < seg_cnt; i++) { + cmd.block_mode = 1; + cmd.increment = 1; + cmd.count = MAX_SEG_SIZE / block_size; + cmd.buffer = buf; + cmd.block_size = block_size; + + if (addr > 0) { + if (!sdio_set_func0_csa_address(addr)) + goto _fail_; + } + if (!g_sdio.sdio_cmd53(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block send...\n", addr); + goto _fail_; + } + + if (addr > 0) + addr += MAX_SEG_SIZE; + + buf += MAX_SEG_SIZE; + + } + + + if (rest > 0) { + cmd.block_mode = 1; + cmd.increment = 1; + cmd.count = rest / block_size; + cmd.buffer = buf; + cmd.block_size = block_size; /* johnny : prevent it from setting unexpected value */ + + if (addr > 0) { + if (!sdio_set_func0_csa_address(addr)) + goto _fail_; + } + if (!g_sdio.sdio_cmd53(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], bytes send...\n", addr); + goto _fail_; + } + + if (addr > 0) + addr += rest; + + buf += rest; + + } + +#else + + cmd.block_mode = 1; + cmd.increment = 1; + cmd.count = nblk; + cmd.buffer = buf; + cmd.block_size = block_size; + if (addr > 0) { + if (!sdio_set_func0_csa_address(addr)) + goto _fail_; + } + if (!g_sdio.sdio_cmd53(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block send...\n", addr); + goto _fail_; + } + if (addr > 0) + addr += nblk * block_size; + buf += nblk * block_size; + +#endif /* platform */ + +#if 0 + if (!sdio_check_bs()) + goto _fail_; +#else + /* g_sdio.os_func.os_sleep(1); */ +#endif + + } + + + if (nleft > 0) { + cmd.block_mode = 0; + cmd.increment = 1; + cmd.count = nleft; + cmd.buffer = buf; + + cmd.block_size = block_size; /* johnny : prevent it from setting unexpected value */ + + if (addr > 0) { + if (!sdio_set_func0_csa_address(addr)) + goto _fail_; + } + if (!g_sdio.sdio_cmd53(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], bytes send...\n", addr); + goto _fail_; + } + +#if 0 + if (!sdio_check_bs()) + goto _fail_; +#else + /* g_sdio.os_func.os_sleep(1); */ +#endif + } + + return 1; + +_fail_: + + return 0; +} + +static int sdio_read_reg(uint32_t addr, uint32_t *data) +{ + if ((addr >= 0xf0) && (addr <= 0xff)) { + sdio_cmd52_t cmd; + cmd.read_write = 0; + cmd.function = 0; + cmd.raw = 0; + cmd.address = addr; + if (!g_sdio.sdio_cmd52(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd 52, read reg (%08x) ...\n", addr); + goto _fail_; + } + *data = cmd.data; + } else { + sdio_cmd53_t cmd; + + if (!sdio_set_func0_csa_address(addr)) + goto _fail_; + + cmd.read_write = 0; + cmd.function = 0; + cmd.address = 0x10f; + cmd.block_mode = 0; + cmd.increment = 1; + cmd.count = 4; + cmd.buffer = (uint8_t *)data; + + cmd.block_size = g_sdio.block_size; /* johnny : prevent it from setting unexpected value */ + + if (!g_sdio.sdio_cmd53(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53, read reg (%08x)...\n", addr); + goto _fail_; + } + +#if 0 + if (!sdio_check_bs()) + goto _fail_; +#else + /* g_sdio.os_func.os_sleep(1); */ +#endif + } + +#ifdef BIG_ENDIAN + *data = BYTE_SWAP(*data); +#endif + + return 1; + +_fail_: + + return 0; +} + +static int sdio_read(uint32_t addr, uint8_t *buf, uint32_t size) +{ + uint32_t block_size = g_sdio.block_size; + sdio_cmd53_t cmd; + int nblk, nleft; + + cmd.read_write = 0; + if (addr > 0) { + /** + * has to be word aligned... + **/ + if (size & 0x3) { + size += 4; + size &= ~0x3; + } + + /** + * func 0 access + **/ + cmd.function = 0; + cmd.address = 0x10f; + } else { +#ifdef WILC1000_SINGLE_TRANSFER + /** + * has to be block aligned... + **/ + nleft = size % block_size; + if (nleft > 0) { + size += block_size; + size &= ~(block_size - 1); + } +#else + /** + * has to be word aligned... + **/ + if (size & 0x3) { + size += 4; + size &= ~0x3; + } +#endif + + /** + * func 1 access + **/ + cmd.function = 1; + cmd.address = 0; + } + + nblk = size / block_size; + nleft = size % block_size; + + if (nblk > 0) { + +#if defined(PLAT_AML8726_M3_BACKUP) /* johnny */ + + int i; + + for (i = 0; i < nblk; i++) { + cmd.block_mode = 0; /* 1; */ + cmd.increment = 1; + cmd.count = block_size; /* nblk; */ + cmd.buffer = buf; + cmd.block_size = block_size; + if (addr > 0) { + if (!sdio_set_func0_csa_address(addr)) + goto _fail_; + } + if (!g_sdio.sdio_cmd53(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block read...\n", addr); + goto _fail_; + } + if (addr > 0) + addr += block_size; /* addr += nblk*block_size; */ + buf += block_size; /* buf += nblk*block_size; */ + } + +#elif defined(PLAT_AML8726_M3) /* johnny */ + + int i; + int rest; + int seg_cnt; + + seg_cnt = (nblk * block_size) / MAX_SEG_SIZE; + rest = (nblk * block_size) & (MAX_SEG_SIZE - 1); + + for (i = 0; i < seg_cnt; i++) { + cmd.block_mode = 1; + cmd.increment = 1; + cmd.count = MAX_SEG_SIZE / block_size; + cmd.buffer = buf; + cmd.block_size = block_size; + + + if (addr > 0) { + if (!sdio_set_func0_csa_address(addr)) + goto _fail_; + } + if (!g_sdio.sdio_cmd53(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block read...\n", addr); + goto _fail_; + } + + if (addr > 0) + addr += MAX_SEG_SIZE; + + buf += MAX_SEG_SIZE; + + } + + + if (rest > 0) { + cmd.block_mode = 1; + cmd.increment = 1; + cmd.count = rest / block_size; + cmd.buffer = buf; + cmd.block_size = block_size; /* johnny : prevent it from setting unexpected value */ + + if (addr > 0) { + if (!sdio_set_func0_csa_address(addr)) + goto _fail_; + } + if (!g_sdio.sdio_cmd53(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block read...\n", addr); + goto _fail_; + } + + if (addr > 0) + addr += rest; + + buf += rest; + + } + +#else + + cmd.block_mode = 1; + cmd.increment = 1; + cmd.count = nblk; + cmd.buffer = buf; + cmd.block_size = block_size; + if (addr > 0) { + if (!sdio_set_func0_csa_address(addr)) + goto _fail_; + } + if (!g_sdio.sdio_cmd53(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block read...\n", addr); + goto _fail_; + } + if (addr > 0) + addr += nblk * block_size; + buf += nblk * block_size; + +#endif /* platform */ + +#if 0 + if (!sdio_check_bs()) + goto _fail_; +#else + /* g_sdio.os_func.os_sleep(1); */ +#endif + + } /* if (nblk > 0) */ + + if (nleft > 0) { + cmd.block_mode = 0; + cmd.increment = 1; + cmd.count = nleft; + cmd.buffer = buf; + + cmd.block_size = block_size; /* johnny : prevent it from setting unexpected value */ + + if (addr > 0) { + if (!sdio_set_func0_csa_address(addr)) + goto _fail_; + } + if (!g_sdio.sdio_cmd53(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], bytes read...\n", addr); + goto _fail_; + } + +#if 0 + if (!sdio_check_bs()) + goto _fail_; +#else + /* g_sdio.os_func.os_sleep(1); */ +#endif + } + + return 1; + +_fail_: + + return 0; +} + +/******************************************** + * + * Bus interfaces + * + ********************************************/ + +static int sdio_deinit(void *pv) +{ + return 1; +} + +static int sdio_sync(void) +{ + uint32_t reg; + + /** + * Disable power sequencer + **/ + if (!sdio_read_reg(WILC_MISC, ®)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed read misc reg...\n"); + return 0; + } + + reg &= ~(1 << 8); + if (!sdio_write_reg(WILC_MISC, reg)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write misc reg...\n"); + return 0; + } + +#ifdef WILC_SDIO_IRQ_GPIO + { + uint32_t reg; + int ret; + + /** + * interrupt pin mux select + **/ + ret = sdio_read_reg(WILC_PIN_MUX_0, ®); + if (!ret) { + g_sdio.dPrint(N_ERR, "[wilc spi]: Failed read reg (%08x)...\n", WILC_PIN_MUX_0); + return 0; + } + reg |= (1 << 8); + ret = sdio_write_reg(WILC_PIN_MUX_0, reg); + if (!ret) { + g_sdio.dPrint(N_ERR, "[wilc spi]: Failed write reg (%08x)...\n", WILC_PIN_MUX_0); + return 0; + } + + /** + * interrupt enable + **/ + ret = sdio_read_reg(WILC_INTR_ENABLE, ®); + if (!ret) { + g_sdio.dPrint(N_ERR, "[wilc spi]: Failed read reg (%08x)...\n", WILC_INTR_ENABLE); + return 0; + } + reg |= (1 << 16); + ret = sdio_write_reg(WILC_INTR_ENABLE, reg); + if (!ret) { + g_sdio.dPrint(N_ERR, "[wilc spi]: Failed write reg (%08x)...\n", WILC_INTR_ENABLE); + return 0; + } + } +#endif + + return 1; +} + +static int sdio_init(wilc_wlan_inp_t *inp, wilc_debug_func func) +{ + sdio_cmd52_t cmd; + int loop; + uint32_t chipid; + memset(&g_sdio, 0, sizeof(wilc_sdio_t)); + + g_sdio.dPrint = func; + g_sdio.os_context = inp->os_context.os_private; + memcpy((void *)&g_sdio.os_func, (void *)&inp->os_func, sizeof(wilc_wlan_os_func_t)); + + if (inp->io_func.io_init) { + if (!inp->io_func.io_init(g_sdio.os_context)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed io init bus...\n"); + return 0; + } + } else { + return 0; + } + + g_sdio.sdio_cmd52 = inp->io_func.u.sdio.sdio_cmd52; + g_sdio.sdio_cmd53 = inp->io_func.u.sdio.sdio_cmd53; + g_sdio.sdio_set_max_speed = inp->io_func.u.sdio.sdio_set_max_speed; + g_sdio.sdio_set_default_speed = inp->io_func.u.sdio.sdio_set_default_speed; + + /** + * function 0 csa enable + **/ + cmd.read_write = 1; + cmd.function = 0; + cmd.raw = 1; + cmd.address = 0x100; + cmd.data = 0x80; + if (!g_sdio.sdio_cmd52(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd 52, enable csa...\n"); + goto _fail_; + } + + /** + * function 0 block size + **/ + if (!sdio_set_func0_block_size(WILC_SDIO_BLOCK_SIZE)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd 52, set func 0 block size...\n"); + goto _fail_; + } + g_sdio.block_size = WILC_SDIO_BLOCK_SIZE; + + /** + * enable func1 IO + **/ + cmd.read_write = 1; + cmd.function = 0; + cmd.raw = 1; + cmd.address = 0x2; + cmd.data = 0x2; + if (!g_sdio.sdio_cmd52(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio] Fail cmd 52, set IOE register...\n"); + goto _fail_; + } + + /** + * make sure func 1 is up + **/ + cmd.read_write = 0; + cmd.function = 0; + cmd.raw = 0; + cmd.address = 0x3; + loop = 3; + do { + cmd.data = 0; + if (!g_sdio.sdio_cmd52(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd 52, get IOR register...\n"); + goto _fail_; + } + if (cmd.data == 0x2) + break; + } while (loop--); + + if (loop <= 0) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail func 1 is not ready...\n"); + goto _fail_; + } + + /** + * func 1 is ready, set func 1 block size + **/ + if (!sdio_set_func1_block_size(WILC_SDIO_BLOCK_SIZE)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail set func 1 block size...\n"); + goto _fail_; + } + + /** + * func 1 interrupt enable + **/ + cmd.read_write = 1; + cmd.function = 0; + cmd.raw = 1; + cmd.address = 0x4; + cmd.data = 0x3; + if (!g_sdio.sdio_cmd52(&cmd)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd 52, set IEN register...\n"); + goto _fail_; + } + + /** + * make sure can read back chip id correctly + **/ + if (!sdio_read_reg(0x1000, &chipid)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd read chip id...\n"); + goto _fail_; + } + g_sdio.dPrint(N_ERR, "[wilc sdio]: chipid (%08x)\n", chipid); + if ((chipid & 0xfff) > 0x2a0) { + g_sdio.has_thrpt_enh3 = 1; + } else { + g_sdio.has_thrpt_enh3 = 0; + } + g_sdio.dPrint(N_ERR, "[wilc sdio]: has_thrpt_enh3 = %d...\n", g_sdio.has_thrpt_enh3); + + + return 1; + +_fail_: + + return 0; +} + +static void sdio_set_max_speed(void) +{ + g_sdio.sdio_set_max_speed(); +} + +static void sdio_set_default_speed(void) +{ + g_sdio.sdio_set_default_speed(); +} + +static int sdio_read_size(uint32_t *size) +{ + + uint32_t tmp; + sdio_cmd52_t cmd; + + /** + * Read DMA count in words + **/ + { + cmd.read_write = 0; + cmd.function = 0; + cmd.raw = 0; + cmd.address = 0xf2; + cmd.data = 0; + g_sdio.sdio_cmd52(&cmd); + tmp = cmd.data; + + /* cmd.read_write = 0; */ + /* cmd.function = 0; */ + /* cmd.raw = 0; */ + cmd.address = 0xf3; + cmd.data = 0; + g_sdio.sdio_cmd52(&cmd); + tmp |= (cmd.data << 8); + } + + *size = tmp; + return 1; +} + +static int sdio_read_int(uint32_t *int_status) +{ + + uint32_t tmp; + sdio_cmd52_t cmd; + + sdio_read_size(&tmp); + + /** + * Read IRQ flags + **/ +#ifndef WILC_SDIO_IRQ_GPIO + /* cmd.read_write = 0; */ + cmd.function = 1; + /* cmd.raw = 0; */ + cmd.address = 0x04; + cmd.data = 0; + g_sdio.sdio_cmd52(&cmd); + + if (cmd.data & (1 << 0)) { + tmp |= INT_0; + } + if (cmd.data & (1 << 2)) { + tmp |= INT_1; + } + if (cmd.data & (1 << 3)) { + tmp |= INT_2; + } + if (cmd.data & (1 << 4)) { + tmp |= INT_3; + } + if (cmd.data & (1 << 5)) { + tmp |= INT_4; + } + if (cmd.data & (1 << 6)) { + tmp |= INT_5; + } + { + int i; + for (i = g_sdio.nint; i < MAX_NUM_INT; i++) { + if ((tmp >> (IRG_FLAGS_OFFSET + i)) & 0x1) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Unexpected interrupt (1) : tmp=%x, data=%x\n", tmp, cmd.data); + break; + } + } + } +#else + { + uint32_t irq_flags; + + cmd.read_write = 0; + cmd.function = 0; + cmd.raw = 0; + cmd.address = 0xf7; + cmd.data = 0; + g_sdio.sdio_cmd52(&cmd); + irq_flags = cmd.data & 0x1f; + tmp |= ((irq_flags >> 0) << IRG_FLAGS_OFFSET); + } + +#endif + + *int_status = tmp; + + return 1; +} + +static int sdio_clear_int_ext(uint32_t val) +{ + int ret; + + if (g_sdio.has_thrpt_enh3) { + uint32_t reg; + +#ifdef WILC_SDIO_IRQ_GPIO + { + uint32_t flags; + flags = val & ((1 << MAX_NUN_INT_THRPT_ENH2) - 1); + reg = flags; + } +#else + reg = 0; +#endif + /* select VMM table 0 */ + if ((val & SEL_VMM_TBL0) == SEL_VMM_TBL0) + reg |= (1 << 5); + /* select VMM table 1 */ + if ((val & SEL_VMM_TBL1) == SEL_VMM_TBL1) + reg |= (1 << 6); + /* enable VMM */ + if ((val & EN_VMM) == EN_VMM) + reg |= (1 << 7); + if (reg) { + sdio_cmd52_t cmd; + cmd.read_write = 1; + cmd.function = 0; + cmd.raw = 0; + cmd.address = 0xf8; + cmd.data = reg; + + ret = g_sdio.sdio_cmd52(&cmd); + if (!ret) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0xf8 data (%d) ...\n", __LINE__); + goto _fail_; + } + + } + } else { +#ifdef WILC_SDIO_IRQ_GPIO + { + /* see below. has_thrpt_enh2 uses register 0xf8 to clear interrupts. */ + /* Cannot clear multiple interrupts. Must clear each interrupt individually */ + uint32_t flags; + flags = val & ((1 << MAX_NUM_INT) - 1); + if (flags) { + int i; + + ret = 1; + for (i = 0; i < g_sdio.nint; i++) { + if (flags & 1) { + sdio_cmd52_t cmd; + cmd.read_write = 1; + cmd.function = 0; + cmd.raw = 0; + cmd.address = 0xf8; + cmd.data = (1 << i); + + ret = g_sdio.sdio_cmd52(&cmd); + if (!ret) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0xf8 data (%d) ...\n", __LINE__); + goto _fail_; + } + + } + if (!ret) + break; + flags >>= 1; + } + if (!ret) { + goto _fail_; + } + for (i = g_sdio.nint; i < MAX_NUM_INT; i++) { + if (flags & 1) + g_sdio.dPrint(N_ERR, "[wilc sdio]: Unexpected interrupt cleared %d...\n", i); + flags >>= 1; + } + } + } +#endif /* WILC_SDIO_IRQ_GPIO */ + + + { + uint32_t vmm_ctl; + + vmm_ctl = 0; + /* select VMM table 0 */ + if ((val & SEL_VMM_TBL0) == SEL_VMM_TBL0) + vmm_ctl |= (1 << 0); + /* select VMM table 1 */ + if ((val & SEL_VMM_TBL1) == SEL_VMM_TBL1) + vmm_ctl |= (1 << 1); + /* enable VMM */ + if ((val & EN_VMM) == EN_VMM) + vmm_ctl |= (1 << 2); + + if (vmm_ctl) { + sdio_cmd52_t cmd; + + cmd.read_write = 1; + cmd.function = 0; + cmd.raw = 0; + cmd.address = 0xf6; + cmd.data = vmm_ctl; + ret = g_sdio.sdio_cmd52(&cmd); + if (!ret) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0xf6 data (%d) ...\n", __LINE__); + goto _fail_; + } + } + } + } + + return 1; +_fail_: + return 0; +} + +static int sdio_sync_ext(int nint /* how mant interrupts to enable. */) +{ + uint32_t reg; + + + if (nint > MAX_NUM_INT) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Too many interupts (%d)...\n", nint); + return 0; + } + if (nint > MAX_NUN_INT_THRPT_ENH2) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Error: Cannot support more than 5 interrupts when has_thrpt_enh2=1.\n"); + return 0; + } + + + g_sdio.nint = nint; + + /** + * Disable power sequencer + **/ + if (!sdio_read_reg(WILC_MISC, ®)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed read misc reg...\n"); + return 0; + } + + reg &= ~(1 << 8); + if (!sdio_write_reg(WILC_MISC, reg)) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write misc reg...\n"); + return 0; + } + +#ifdef WILC_SDIO_IRQ_GPIO + { + uint32_t reg; + int ret, i; + + + /** + * interrupt pin mux select + **/ + ret = sdio_read_reg(WILC_PIN_MUX_0, ®); + if (!ret) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed read reg (%08x)...\n", WILC_PIN_MUX_0); + return 0; + } + reg |= (1 << 8); + ret = sdio_write_reg(WILC_PIN_MUX_0, reg); + if (!ret) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write reg (%08x)...\n", WILC_PIN_MUX_0); + return 0; + } + + /** + * interrupt enable + **/ + ret = sdio_read_reg(WILC_INTR_ENABLE, ®); + if (!ret) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed read reg (%08x)...\n", WILC_INTR_ENABLE); + return 0; + } + + for (i = 0; (i < 5) && (nint > 0); i++, nint--) { + reg |= (1 << (27 + i)); + } + ret = sdio_write_reg(WILC_INTR_ENABLE, reg); + if (!ret) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write reg (%08x)...\n", WILC_INTR_ENABLE); + return 0; + } + if (nint) { + ret = sdio_read_reg(WILC_INTR2_ENABLE, ®); + if (!ret) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed read reg (%08x)...\n", WILC_INTR2_ENABLE); + return 0; + } + + for (i = 0; (i < 3) && (nint > 0); i++, nint--) { + reg |= (1 << i); + } + + ret = sdio_read_reg(WILC_INTR2_ENABLE, ®); + if (!ret) { + g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write reg (%08x)...\n", WILC_INTR2_ENABLE); + return 0; + } + } + } +#endif /* WILC_SDIO_IRQ_GPIO */ + return 1; +} + + +/******************************************** + * + * Global sdio HIF function table + * + ********************************************/ + +wilc_hif_func_t hif_sdio = { + sdio_init, + sdio_deinit, + sdio_read_reg, + sdio_write_reg, + sdio_read, + sdio_write, + sdio_sync, + sdio_clear_int, + sdio_read_int, + sdio_clear_int_ext, + sdio_read_size, + sdio_write, + sdio_read, + sdio_sync_ext, + + sdio_set_max_speed, + sdio_set_default_speed, +}; + diff --git a/drivers/staging/wilc1000/wilc_semaphore.c b/drivers/staging/wilc1000/wilc_semaphore.c new file mode 100644 index 000000000000..637107bfb877 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_semaphore.c @@ -0,0 +1,70 @@ + +#include "wilc_oswrapper.h" +#ifdef CONFIG_WILC_SEMAPHORE_FEATURE + + +WILC_ErrNo WILC_SemaphoreCreate(WILC_SemaphoreHandle *pHandle, + tstrWILC_SemaphoreAttrs *pstrAttrs) +{ + tstrWILC_SemaphoreAttrs strDefaultAttrs; + if (pstrAttrs == WILC_NULL) { + WILC_SemaphoreFillDefault(&strDefaultAttrs); + pstrAttrs = &strDefaultAttrs; + } + + sema_init(pHandle, pstrAttrs->u32InitCount); + return WILC_SUCCESS; + +} + + +WILC_ErrNo WILC_SemaphoreDestroy(WILC_SemaphoreHandle *pHandle, + tstrWILC_SemaphoreAttrs *pstrAttrs) +{ + /* nothing to be done ! */ + + return WILC_SUCCESS; + +} + + +WILC_ErrNo WILC_SemaphoreAcquire(WILC_SemaphoreHandle *pHandle, + tstrWILC_SemaphoreAttrs *pstrAttrs) +{ + WILC_ErrNo s32RetStatus = WILC_SUCCESS; + + #ifndef CONFIG_WILC_SEMAPHORE_TIMEOUT + while (down_interruptible(pHandle)) + ; + + #else + if (pstrAttrs == WILC_NULL) { + down(pHandle); + } else { + + s32RetStatus = down_timeout(pHandle, msecs_to_jiffies(pstrAttrs->u32TimeOut)); + } + #endif + + if (s32RetStatus == 0) { + return WILC_SUCCESS; + } else if (s32RetStatus == -ETIME) { + return WILC_TIMEOUT; + } else { + return WILC_FAIL; + } + + return WILC_SUCCESS; + +} + +WILC_ErrNo WILC_SemaphoreRelease(WILC_SemaphoreHandle *pHandle, + tstrWILC_SemaphoreAttrs *pstrAttrs) +{ + + up(pHandle); + return WILC_SUCCESS; + +} + +#endif diff --git a/drivers/staging/wilc1000/wilc_semaphore.h b/drivers/staging/wilc1000/wilc_semaphore.h new file mode 100644 index 000000000000..3006f9f20c4d --- /dev/null +++ b/drivers/staging/wilc1000/wilc_semaphore.h @@ -0,0 +1,115 @@ +#ifndef __WILC_SEMAPHORE_H__ +#define __WILC_SEMAPHORE_H__ + +/*! + * @file wilc_semaphore.h + * @brief Semaphore OS Wrapper functionality + * @author syounan + * @sa wilc_oswrapper.h top level OS wrapper file + * @date 10 Aug 2010 + * @version 1.0 + */ + + +#ifndef CONFIG_WILC_SEMAPHORE_FEATURE +#error the feature WILC_OS_FEATURE_SEMAPHORE must be supported to include this file +#endif + +/*! + * @struct WILC_SemaphoreAttrs + * @brief Semaphore API options + * @author syounan + * @date 10 Aug 2010 + * @version 1.0 + */ +typedef struct { + /*!< + * Initial count when the semaphore is created. default is 1 + */ + WILC_Uint32 u32InitCount; + + #ifdef CONFIG_WILC_SEMAPHORE_TIMEOUT + /*!< + * Timeout for use with WILC_SemaphoreAcquire, 0 to return immediately and + * WILC_OS_INFINITY to wait forever. default is WILC_OS_INFINITY + */ + WILC_Uint32 u32TimeOut; + #endif + +} tstrWILC_SemaphoreAttrs; + + +/*! + * @brief Fills the WILC_SemaphoreAttrs with default parameters + * @param[out] pstrAttrs structure to be filled + * @sa WILC_SemaphoreAttrs + * @author syounan + * @date 10 Aug 2010 + * @version 1.0 + */ +static void WILC_SemaphoreFillDefault(tstrWILC_SemaphoreAttrs *pstrAttrs) +{ + pstrAttrs->u32InitCount = 1; + #ifdef CONFIG_WILC_SEMAPHORE_TIMEOUT + pstrAttrs->u32TimeOut = WILC_OS_INFINITY; + #endif +} +/*! + * @brief Creates a new Semaphore object + * @param[out] pHandle handle to the newly created semaphore + * @param[in] pstrAttrs Optional attributes, NULL for defaults + * pstrAttrs->u32InitCount controls the initial count + * @return Error code indicating success/failure + * @sa WILC_SemaphoreAttrs + * @author syounan + * @date 10 Aug 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_SemaphoreCreate(WILC_SemaphoreHandle *pHandle, + tstrWILC_SemaphoreAttrs *pstrAttrs); + +/*! + * @brief Destroyes an existing Semaphore, releasing any resources + * @param[in] pHandle handle to the semaphore object + * @param[in] pstrAttrs Optional attributes, NULL for defaults + * @return Error code indicating success/failure + * @sa WILC_SemaphoreAttrs + * @todo need to define behaviour if the semaphore delayed while it is pending + * @author syounan + * @date 10 Aug 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_SemaphoreDestroy(WILC_SemaphoreHandle *pHandle, + tstrWILC_SemaphoreAttrs *pstrAttrs); + +/*! + * @brief Acquire the Semaphore object + * @details This function will block until it can Acquire the given + * semaphore, if the feature WILC_OS_FEATURE_SEMAPHORE_TIMEOUT is + * eanbled a timeout value can be passed in pstrAttrs + * @param[in] pHandle handle to the semaphore object + * @param[in] pstrAttrs Optional attributes, NULL for default + * @return Error code indicating success/failure + * @sa WILC_SemaphoreAttrs + * @author syounan + * @date 10 Aug 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_SemaphoreAcquire(WILC_SemaphoreHandle *pHandle, + tstrWILC_SemaphoreAttrs *pstrAttrs); + +/*! + * @brief Release the Semaphore object + * @param[in] pHandle handle to the semaphore object + * @param[in] pstrAttrs Optional attributes, NULL for default + * @return Error code indicating sucess/failure + * @sa WILC_SemaphoreAttrs + * @author syounan + * @date 10 Aug 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_SemaphoreRelease(WILC_SemaphoreHandle *pHandle, + tstrWILC_SemaphoreAttrs *pstrAttrs); + + +#endif diff --git a/drivers/staging/wilc1000/wilc_sleep.c b/drivers/staging/wilc1000/wilc_sleep.c new file mode 100644 index 000000000000..368157175f40 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_sleep.c @@ -0,0 +1,36 @@ + +#include "wilc_oswrapper.h" + +#ifdef CONFIG_WILC_SLEEP_FEATURE + +/* + * @author mdaftedar + * @date 10 Aug 2010 + * @version 1.0 + */ +void WILC_Sleep(WILC_Uint32 u32TimeMilliSec) +{ + if (u32TimeMilliSec <= 4000000) { + WILC_Uint32 u32Temp = u32TimeMilliSec * 1000; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35) + usleep_range(u32Temp, u32Temp); +#else + udelay(u32Temp); +#endif + } else { + msleep(u32TimeMilliSec); + } + +} +#endif + +/* #ifdef CONFIG_WILC_SLEEP_HI_RES */ +void WILC_SleepMicrosec(WILC_Uint32 u32TimeMicoSec) +{ + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35) + usleep_range(u32TimeMicoSec, u32TimeMicoSec); + #else + udelay(u32TimeMicoSec); + #endif +} +/* #endif */ diff --git a/drivers/staging/wilc1000/wilc_sleep.h b/drivers/staging/wilc1000/wilc_sleep.h new file mode 100644 index 000000000000..d640fb553aca --- /dev/null +++ b/drivers/staging/wilc1000/wilc_sleep.h @@ -0,0 +1,45 @@ +#ifndef __WILC_SLEEP_H__ +#define __WILC_SLEEP_H__ + +/*! + * @file wilc_sleep.h + * @brief Sleep OS Wrapper functionality + * @author syounan + * @sa wilc_oswrapper.h top level OS wrapper file + * @date 10 Aug 2010 + * @version 1.0 + */ + +#ifndef CONFIG_WILC_SLEEP_FEATURE +#error the feature WILC_OS_FEATURE_SLEEP must be supported to include this file +#endif + +/*! + * @brief forces the current thread to sleep until the given time has elapsed + * @param[in] u32TimeMilliSec Time to sleep in Milli seconds + * @sa WILC_SleepMicrosec + * @author syounan + * @date 10 Aug 2010 + * @version 1.0 + * @note This function offers a relatively innacurate and low resolution + * sleep, for accurate high resolution sleep use u32TimeMicoSec + */ +void WILC_Sleep(WILC_Uint32 u32TimeMilliSec); + +#ifdef CONFIG_WILC_SLEEP_HI_RES +/*! + * @brief forces the current thread to sleep until the given time has elapsed + * @param[in] u32TimeMicoSec Time to sleep in Micro seconds + * @sa WILC_Sleep + * @author syounan + * @date 10 Aug 2010 + * @version 1.0 + * @note This function offers an acurare high resolution sleep, depends on + * the feature WILC_OS_FEATURE_SLEEP_HI_RES and may not be supported + * on all Operating Systems + */ +void WILC_SleepMicrosec(WILC_Uint32 u32TimeMicoSec); +#endif + + +#endif diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c new file mode 100644 index 000000000000..2f38ddabc654 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_spi.c @@ -0,0 +1,1475 @@ +/* ////////////////////////////////////////////////////////////////////////// */ +/* */ +/* Copyright (c) Atmel Corporation. All rights reserved. */ +/* */ +/* Module Name: wilc_spi.c */ +/* */ +/* */ +/* //////////////////////////////////////////////////////////////////////////// */ + +#include "wilc_wlan_if.h" +#include "wilc_wlan.h" + +extern unsigned int int_clrd; + +/* + * #include + * #include + */ +typedef struct { + void *os_context; + int (*spi_tx)(uint8_t *, uint32_t); + int (*spi_rx)(uint8_t *, uint32_t); + int (*spi_trx)(uint8_t *, uint8_t *, uint32_t); + int (*spi_max_speed)(void); + wilc_debug_func dPrint; + int crc_off; + int nint; + int has_thrpt_enh; +} wilc_spi_t; + +static wilc_spi_t g_spi; + +static int spi_read(uint32_t, uint8_t *, uint32_t); +static int spi_write(uint32_t, uint8_t *, uint32_t); + +/******************************************** + * + * Crc7 + * + ********************************************/ + +static const uint8_t crc7_syndrome_table[256] = { + 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, + 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, + 0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26, + 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e, + 0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d, + 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45, + 0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14, + 0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c, + 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b, + 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13, + 0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42, + 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a, + 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69, + 0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21, + 0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70, + 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38, + 0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e, + 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36, + 0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67, + 0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f, + 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, + 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, + 0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55, + 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d, + 0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a, + 0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52, + 0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03, + 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b, + 0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28, + 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60, + 0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31, + 0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79 +}; + +static uint8_t crc7_byte(uint8_t crc, uint8_t data) +{ + return crc7_syndrome_table[(crc << 1) ^ data]; +} + +static uint8_t crc7(uint8_t crc, const uint8_t *buffer, uint32_t len) +{ + while (len--) + crc = crc7_byte(crc, *buffer++); + return crc; +} + +/******************************************** + * + * Spi protocol Function + * + ********************************************/ + +#define CMD_DMA_WRITE 0xc1 +#define CMD_DMA_READ 0xc2 +#define CMD_INTERNAL_WRITE 0xc3 +#define CMD_INTERNAL_READ 0xc4 +#define CMD_TERMINATE 0xc5 +#define CMD_REPEAT 0xc6 +#define CMD_DMA_EXT_WRITE 0xc7 +#define CMD_DMA_EXT_READ 0xc8 +#define CMD_SINGLE_WRITE 0xc9 +#define CMD_SINGLE_READ 0xca +#define CMD_RESET 0xcf + +#define N_OK 1 +#define N_FAIL 0 +#define N_RESET -1 +#define N_RETRY -2 + +#define DATA_PKT_SZ_256 256 +#define DATA_PKT_SZ_512 512 +#define DATA_PKT_SZ_1K 1024 +#define DATA_PKT_SZ_4K (4 * 1024) +#define DATA_PKT_SZ_8K (8 * 1024) +#define DATA_PKT_SZ DATA_PKT_SZ_8K + +static int spi_cmd(uint8_t cmd, uint32_t adr, uint32_t data, uint32_t sz, uint8_t clockless) +{ + uint8_t bc[9]; + int len = 5; + int result = N_OK; + + bc[0] = cmd; + switch (cmd) { + case CMD_SINGLE_READ: /* single word (4 bytes) read */ + bc[1] = (uint8_t)(adr >> 16); + bc[2] = (uint8_t)(adr >> 8); + bc[3] = (uint8_t)adr; + len = 5; + break; + + case CMD_INTERNAL_READ: /* internal register read */ + bc[1] = (uint8_t)(adr >> 8); + if (clockless) + bc[1] |= (1 << 7); + bc[2] = (uint8_t)adr; + bc[3] = 0x00; + len = 5; + break; + + case CMD_TERMINATE: /* termination */ + bc[1] = 0x00; + bc[2] = 0x00; + bc[3] = 0x00; + len = 5; + break; + + case CMD_REPEAT: /* repeat */ + bc[1] = 0x00; + bc[2] = 0x00; + bc[3] = 0x00; + len = 5; + break; + + case CMD_RESET: /* reset */ + bc[1] = 0xff; + bc[2] = 0xff; + bc[3] = 0xff; + len = 5; + break; + + case CMD_DMA_WRITE: /* dma write */ + case CMD_DMA_READ: /* dma read */ + bc[1] = (uint8_t)(adr >> 16); + bc[2] = (uint8_t)(adr >> 8); + bc[3] = (uint8_t)adr; + bc[4] = (uint8_t)(sz >> 8); + bc[5] = (uint8_t)(sz); + len = 7; + break; + + case CMD_DMA_EXT_WRITE: /* dma extended write */ + case CMD_DMA_EXT_READ: /* dma extended read */ + bc[1] = (uint8_t)(adr >> 16); + bc[2] = (uint8_t)(adr >> 8); + bc[3] = (uint8_t)adr; + bc[4] = (uint8_t)(sz >> 16); + bc[5] = (uint8_t)(sz >> 8); + bc[6] = (uint8_t)(sz); + len = 8; + break; + + case CMD_INTERNAL_WRITE: /* internal register write */ + bc[1] = (uint8_t)(adr >> 8); + if (clockless) + bc[1] |= (1 << 7); + bc[2] = (uint8_t)(adr); + bc[3] = (uint8_t)(data >> 24); + bc[4] = (uint8_t)(data >> 16); + bc[5] = (uint8_t)(data >> 8); + bc[6] = (uint8_t)(data); + len = 8; + break; + + case CMD_SINGLE_WRITE: /* single word write */ + bc[1] = (uint8_t)(adr >> 16); + bc[2] = (uint8_t)(adr >> 8); + bc[3] = (uint8_t)(adr); + bc[4] = (uint8_t)(data >> 24); + bc[5] = (uint8_t)(data >> 16); + bc[6] = (uint8_t)(data >> 8); + bc[7] = (uint8_t)(data); + len = 9; + break; + + default: + result = N_FAIL; + break; + } + + if (result) { + if (!g_spi.crc_off) + bc[len - 1] = (crc7(0x7f, (const uint8_t *)&bc[0], len - 1)) << 1; + else + len -= 1; + + if (!g_spi.spi_tx(bc, len)) { + PRINT_ER("[wilc spi]: Failed cmd write, bus error...\n"); + result = N_FAIL; + } + } + + return result; +} + +static int spi_cmd_rsp(uint8_t cmd) +{ + uint8_t rsp; + int result = N_OK; + + /** + * Command/Control response + **/ + if ((cmd == CMD_RESET) || + (cmd == CMD_TERMINATE) || + (cmd == CMD_REPEAT)) { + if (!g_spi.spi_rx(&rsp, 1)) { + result = N_FAIL; + goto _fail_; + } + } + + if (!g_spi.spi_rx(&rsp, 1)) { + PRINT_ER("[wilc spi]: Failed cmd response read, bus error...\n"); + result = N_FAIL; + goto _fail_; + } + + if (rsp != cmd) { + PRINT_ER("[wilc spi]: Failed cmd response, cmd (%02x), resp (%02x)\n", cmd, rsp); + result = N_FAIL; + goto _fail_; + } + + /** + * State response + **/ + if (!g_spi.spi_rx(&rsp, 1)) { + PRINT_ER("[wilc spi]: Failed cmd state read, bus error...\n"); + result = N_FAIL; + goto _fail_; + } + + if (rsp != 0x00) { + PRINT_ER("[wilc spi]: Failed cmd state response state (%02x)\n", rsp); + result = N_FAIL; + } + +_fail_: + + return result; +} + +static int spi_cmd_complete(uint8_t cmd, uint32_t adr, uint8_t *b, uint32_t sz, uint8_t clockless) +{ + uint8_t wb[32], rb[32]; + uint8_t wix, rix; + uint32_t len2; + uint8_t rsp; + int len = 0; + int result = N_OK; + + wb[0] = cmd; + switch (cmd) { + case CMD_SINGLE_READ: /* single word (4 bytes) read */ + wb[1] = (uint8_t)(adr >> 16); + wb[2] = (uint8_t)(adr >> 8); + wb[3] = (uint8_t)adr; + len = 5; + break; + + case CMD_INTERNAL_READ: /* internal register read */ + wb[1] = (uint8_t)(adr >> 8); + if (clockless == 1) + wb[1] |= (1 << 7); + wb[2] = (uint8_t)adr; + wb[3] = 0x00; + len = 5; + break; + + case CMD_TERMINATE: /* termination */ + wb[1] = 0x00; + wb[2] = 0x00; + wb[3] = 0x00; + len = 5; + break; + + case CMD_REPEAT: /* repeat */ + wb[1] = 0x00; + wb[2] = 0x00; + wb[3] = 0x00; + len = 5; + break; + + case CMD_RESET: /* reset */ + wb[1] = 0xff; + wb[2] = 0xff; + wb[3] = 0xff; + len = 5; + break; + + case CMD_DMA_WRITE: /* dma write */ + case CMD_DMA_READ: /* dma read */ + wb[1] = (uint8_t)(adr >> 16); + wb[2] = (uint8_t)(adr >> 8); + wb[3] = (uint8_t)adr; + wb[4] = (uint8_t)(sz >> 8); + wb[5] = (uint8_t)(sz); + len = 7; + break; + + case CMD_DMA_EXT_WRITE: /* dma extended write */ + case CMD_DMA_EXT_READ: /* dma extended read */ + wb[1] = (uint8_t)(adr >> 16); + wb[2] = (uint8_t)(adr >> 8); + wb[3] = (uint8_t)adr; + wb[4] = (uint8_t)(sz >> 16); + wb[5] = (uint8_t)(sz >> 8); + wb[6] = (uint8_t)(sz); + len = 8; + break; + + case CMD_INTERNAL_WRITE: /* internal register write */ + wb[1] = (uint8_t)(adr >> 8); + if (clockless == 1) + wb[1] |= (1 << 7); + wb[2] = (uint8_t)(adr); + wb[3] = b[3]; + wb[4] = b[2]; + wb[5] = b[1]; + wb[6] = b[0]; + len = 8; + break; + + case CMD_SINGLE_WRITE: /* single word write */ + wb[1] = (uint8_t)(adr >> 16); + wb[2] = (uint8_t)(adr >> 8); + wb[3] = (uint8_t)(adr); + wb[4] = b[3]; + wb[5] = b[2]; + wb[6] = b[1]; + wb[7] = b[0]; + len = 9; + break; + + default: + result = N_FAIL; + break; + } + + if (result != N_OK) { + return result; + } + + if (!g_spi.crc_off) { + wb[len - 1] = (crc7(0x7f, (const uint8_t *)&wb[0], len - 1)) << 1; + } else { + len -= 1; + } + +#define NUM_SKIP_BYTES (1) +#define NUM_RSP_BYTES (2) +#define NUM_DATA_HDR_BYTES (1) +#define NUM_DATA_BYTES (4) +#define NUM_CRC_BYTES (2) +#define NUM_DUMMY_BYTES (3) + if ((cmd == CMD_RESET) || + (cmd == CMD_TERMINATE) || + (cmd == CMD_REPEAT)) { + len2 = len + (NUM_SKIP_BYTES + NUM_RSP_BYTES + NUM_DUMMY_BYTES); + } else if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ)) { + if (!g_spi.crc_off) { + len2 = len + (NUM_RSP_BYTES + NUM_DATA_HDR_BYTES + NUM_DATA_BYTES + + NUM_CRC_BYTES + NUM_DUMMY_BYTES); + } else { + len2 = len + (NUM_RSP_BYTES + NUM_DATA_HDR_BYTES + NUM_DATA_BYTES + + NUM_DUMMY_BYTES); + } + } else { + len2 = len + (NUM_RSP_BYTES + NUM_DUMMY_BYTES); + } +#undef NUM_DUMMY_BYTES + + if (len2 > (sizeof(wb) / sizeof(wb[0]))) { + PRINT_ER("[wilc spi]: spi buffer size too small (%d) (%d)\n", + len2, (sizeof(wb) / sizeof(wb[0]))); + result = N_FAIL; + return result; + } + /* zero spi write buffers. */ + for (wix = len; wix < len2; wix++) { + wb[wix] = 0; + } + rix = len; + + if (!g_spi.spi_trx(wb, rb, len2)) { + PRINT_ER("[wilc spi]: Failed cmd write, bus error...\n"); + result = N_FAIL; + return result; + } + +#if 0 + { + int jj; + PRINT_D(BUS_DBG, "--- cnd = %x, len=%d, len2=%d\n", cmd, len, len2); + for (jj = 0; jj < sizeof(wb) / sizeof(wb[0]); jj++) { + + if (jj >= len2) + break; + if (((jj + 1) % 16) != 0) { + if ((jj % 16) == 0) { + PRINT_D(BUS_DBG, "wb[%02x]: %02x ", jj, wb[jj]); + } else { + PRINT_D(BUS_DBG, "%02x ", wb[jj]); + } + } else { + PRINT_D(BUS_DBG, "%02x\n", wb[jj]); + } + } + + for (jj = 0; jj < sizeof(rb) / sizeof(rb[0]); jj++) { + + if (jj >= len2) + break; + if (((jj + 1) % 16) != 0) { + if ((jj % 16) == 0) { + PRINT_D(BUS_DBG, "rb[%02x]: %02x ", jj, rb[jj]); + } else { + PRINT_D(BUS_DBG, "%02x ", rb[jj]); + } + } else { + PRINT_D(BUS_DBG, "%02x\n", rb[jj]); + } + } + } +#endif + + /** + * Command/Control response + **/ + if ((cmd == CMD_RESET) || + (cmd == CMD_TERMINATE) || + (cmd == CMD_REPEAT)) { + rix++; /* skip 1 byte */ + } + + /* do { */ + rsp = rb[rix++]; + /* if(rsp == cmd) break; */ + /* } while(&rptr[1] <= &rb[len2]); */ + + if (rsp != cmd) { + PRINT_ER("[wilc spi]: Failed cmd response, cmd (%02x)" + ", resp (%02x)\n", cmd, rsp); + result = N_FAIL; + return result; + } + + /** + * State response + **/ + rsp = rb[rix++]; + if (rsp != 0x00) { + PRINT_ER("[wilc spi]: Failed cmd state response " + "state (%02x)\n", rsp); + result = N_FAIL; + return result; + } + + if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ) + || (cmd == CMD_DMA_READ) || (cmd == CMD_DMA_EXT_READ)) { + int retry; + /* uint16_t crc1, crc2; */ + uint8_t crc[2]; + /** + * Data Respnose header + **/ + retry = 100; + do { + /* ensure there is room in buffer later to read data and crc */ + if (rix < len2) { + rsp = rb[rix++]; + } else { + retry = 0; + break; + } + if (((rsp >> 4) & 0xf) == 0xf) + break; + } while (retry--); + + if (retry <= 0) { + PRINT_ER("[wilc spi]: Error, data read " + "response (%02x)\n", rsp); + result = N_RESET; + return result; + } + + if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ)) { + /** + * Read bytes + **/ + if ((rix + 3) < len2) { + b[0] = rb[rix++]; + b[1] = rb[rix++]; + b[2] = rb[rix++]; + b[3] = rb[rix++]; + } else { + PRINT_ER("[wilc spi]: buffer overrun when reading data.\n"); + result = N_FAIL; + return result; + } + + if (!g_spi.crc_off) { + /** + * Read Crc + **/ + if ((rix + 1) < len2) { + crc[0] = rb[rix++]; + crc[1] = rb[rix++]; + } else { + PRINT_ER("[wilc spi]: buffer overrun when reading crc.\n"); + result = N_FAIL; + return result; + } + } + } else if ((cmd == CMD_DMA_READ) || (cmd == CMD_DMA_EXT_READ)) { + int ix; + + /* some data may be read in response to dummy bytes. */ + for (ix = 0; (rix < len2) && (ix < sz); ) { + b[ix++] = rb[rix++]; + } +#if 0 + if (ix) + PRINT_D(BUS_DBG, "ttt %d %d\n", sz, ix); +#endif + sz -= ix; + + if (sz > 0) { + int nbytes; + + if (sz <= (DATA_PKT_SZ - ix)) { + nbytes = sz; + } else { + nbytes = DATA_PKT_SZ - ix; + } + + /** + * Read bytes + **/ + if (!g_spi.spi_rx(&b[ix], nbytes)) { + PRINT_ER("[wilc spi]: Failed data block read, bus error...\n"); + result = N_FAIL; + goto _error_; + } + + /** + * Read Crc + **/ + if (!g_spi.crc_off) { + if (!g_spi.spi_rx(crc, 2)) { + PRINT_ER("[wilc spi]: Failed data block crc read, bus error...\n"); + result = N_FAIL; + goto _error_; + } + } + + + ix += nbytes; + sz -= nbytes; + } + + /* if any data in left unread, then read the rest using normal DMA code.*/ + while (sz > 0) { + int nbytes; + +#if 0 + PRINT_INFO(BUS_DBG, "rrr %d %d\n", sz, ix); +#endif + if (sz <= DATA_PKT_SZ) { + nbytes = sz; + } else { + nbytes = DATA_PKT_SZ; + } + + /** + * read data response only on the next DMA cycles not + * the first DMA since data response header is already + * handled above for the first DMA. + **/ + /** + * Data Respnose header + **/ + retry = 10; + do { + if (!g_spi.spi_rx(&rsp, 1)) { + PRINT_ER("[wilc spi]: Failed data response read, bus error...\n"); + result = N_FAIL; + break; + } + if (((rsp >> 4) & 0xf) == 0xf) + break; + } while (retry--); + + if (result == N_FAIL) + break; + + + /** + * Read bytes + **/ + if (!g_spi.spi_rx(&b[ix], nbytes)) { + PRINT_ER("[wilc spi]: Failed data block read, bus error...\n"); + result = N_FAIL; + break; + } + + /** + * Read Crc + **/ + if (!g_spi.crc_off) { + if (!g_spi.spi_rx(crc, 2)) { + PRINT_ER("[wilc spi]: Failed data block crc read, bus error...\n"); + result = N_FAIL; + break; + } + } + + ix += nbytes; + sz -= nbytes; + } + } + } +_error_: + return result; +} + +static int spi_data_read(uint8_t *b, uint32_t sz) +{ + int retry, ix, nbytes; + int result = N_OK; + uint8_t crc[2]; + uint8_t rsp; + + /** + * Data + **/ + ix = 0; + do { + if (sz <= DATA_PKT_SZ) + nbytes = sz; + else + nbytes = DATA_PKT_SZ; + + /** + * Data Respnose header + **/ + retry = 10; + do { + if (!g_spi.spi_rx(&rsp, 1)) { + PRINT_ER("[wilc spi]: Failed data response read, bus error...\n"); + result = N_FAIL; + break; + } + if (((rsp >> 4) & 0xf) == 0xf) + break; + } while (retry--); + + if (result == N_FAIL) + break; + + if (retry <= 0) { + PRINT_ER("[wilc spi]: Failed data response read...(%02x)\n", rsp); + result = N_FAIL; + break; + } + + /** + * Read bytes + **/ + if (!g_spi.spi_rx(&b[ix], nbytes)) { + PRINT_ER("[wilc spi]: Failed data block read, bus error...\n"); + result = N_FAIL; + break; + } + + /** + * Read Crc + **/ + if (!g_spi.crc_off) { + if (!g_spi.spi_rx(crc, 2)) { + PRINT_ER("[wilc spi]: Failed data block crc read, bus error...\n"); + result = N_FAIL; + break; + } + } + + ix += nbytes; + sz -= nbytes; + + } while (sz); + + return result; +} + +static int spi_data_write(uint8_t *b, uint32_t sz) +{ + int ix, nbytes; + int result = 1; + uint8_t cmd, order, crc[2] = {0}; + /* uint8_t rsp; */ + + /** + * Data + **/ + ix = 0; + do { + if (sz <= DATA_PKT_SZ) + nbytes = sz; + else + nbytes = DATA_PKT_SZ; + + /** + * Write command + **/ + cmd = 0xf0; + if (ix == 0) { + if (sz <= DATA_PKT_SZ) + + order = 0x3; + else + order = 0x1; + } else { + if (sz <= DATA_PKT_SZ) + order = 0x3; + else + order = 0x2; + } + cmd |= order; + if (!g_spi.spi_tx(&cmd, 1)) { + PRINT_ER("[wilc spi]: Failed data block cmd write, bus error...\n"); + result = N_FAIL; + break; + } + + /** + * Write data + **/ + if (!g_spi.spi_tx(&b[ix], nbytes)) { + PRINT_ER("[wilc spi]: Failed data block write, bus error...\n"); + result = N_FAIL; + break; + } + + /** + * Write Crc + **/ + if (!g_spi.crc_off) { + if (!g_spi.spi_tx(crc, 2)) { + PRINT_ER("[wilc spi]: Failed data block crc write, bus error...\n"); + result = N_FAIL; + break; + } + } + + /** + * No need to wait for response + **/ +#if 0 + /** + * Respnose + **/ + if (!g_spi.spi_rx(&rsp, 1)) { + PRINT_ER("[wilc spi]: Failed data block write, response read, bus error...\n"); + result = N_FAIL; + break; + } + + if (((rsp >> 4) & 0xf) != 0xc) { + result = N_FAIL; + PRINT_ER("[wilc spi]: Failed data block write response...(%02x)\n", rsp); + break; + } + + /** + * State + **/ + if (!g_spi.spi_rx(&rsp, 1)) { + PRINT_ER("[wilc spi]: Failed data block write, read state, bus error...\n"); + result = N_FAIL; + break; + } +#endif + + ix += nbytes; + sz -= nbytes; + } while (sz); + + + return result; +} + +/******************************************** + * + * Spi Internal Read/Write Function + * + ********************************************/ + +static int spi_internal_write(uint32_t adr, uint32_t dat) +{ + int result; + +#if defined USE_OLD_SPI_SW + /** + * Command + **/ + result = spi_cmd(CMD_INTERNAL_WRITE, adr, dat, 4, 0); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed internal write cmd...\n"); + return 0; + } + + result = spi_cmd_rsp(CMD_INTERNAL_WRITE, 0); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed internal write cmd response...\n"); + } +#else + +#ifdef BIG_ENDIAN + dat = BYTE_SWAP(dat); +#endif + result = spi_cmd_complete(CMD_INTERNAL_WRITE, adr, (uint8_t *)&dat, 4, 0); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed internal write cmd...\n"); + } + +#endif + return result; +} + +static int spi_internal_read(uint32_t adr, uint32_t *data) +{ + int result; + +#if defined USE_OLD_SPI_SW + result = spi_cmd(CMD_INTERNAL_READ, adr, 0, 4, 0); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed internal read cmd...\n"); + return 0; + } + + result = spi_cmd_rsp(CMD_INTERNAL_READ, 0); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed internal read cmd response...\n"); + return 0; + } + + /** + * Data + **/ + result = spi_data_read((uint8_t *)data, 4); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed internal read data...\n"); + return 0; + } +#else + result = spi_cmd_complete(CMD_INTERNAL_READ, adr, (uint8_t *)data, 4, 0); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed internal read cmd...\n"); + return 0; + } +#endif + + +#ifdef BIG_ENDIAN + *data = BYTE_SWAP(*data); +#endif + + return 1; +} + +/******************************************** + * + * Spi interfaces + * + ********************************************/ + +static int spi_write_reg(uint32_t addr, uint32_t data) +{ + int result = N_OK; + uint8_t cmd = CMD_SINGLE_WRITE; + uint8_t clockless = 0; + + +#if defined USE_OLD_SPI_SW + { + result = spi_cmd(cmd, addr, data, 4, 0); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed cmd, write reg (%08x)...\n", addr); + return 0; + } + + result = spi_cmd_rsp(cmd, 0); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed cmd response, write reg (%08x)...\n", addr); + return 0; + } + + return 1; + } +#else +#ifdef BIG_ENDIAN + data = BYTE_SWAP(data); +#endif + if (addr < 0x30) { + /* Clockless register*/ + cmd = CMD_INTERNAL_WRITE; + clockless = 1; + } + + result = spi_cmd_complete(cmd, addr, (uint8_t *)&data, 4, clockless); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed cmd, write reg (%08x)...\n", addr); + } + + return result; +#endif + +} + +static int spi_write(uint32_t addr, uint8_t *buf, uint32_t size) +{ + int result; + uint8_t cmd = CMD_DMA_EXT_WRITE; + + /** + * has to be greated than 4 + **/ + if (size <= 4) + return 0; + +#if defined USE_OLD_SPI_SW + /** + * Command + **/ + result = spi_cmd(cmd, addr, 0, size, 0); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed cmd, write block (%08x)...\n", addr); + return 0; + } + + result = spi_cmd_rsp(cmd, 0); + if (result != N_OK) { + PRINT_ER("[wilc spi ]: Failed cmd response, write block (%08x)...\n", addr); + return 0; + } +#else + result = spi_cmd_complete(cmd, addr, NULL, size, 0); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed cmd, write block (%08x)...\n", addr); + return 0; + } +#endif + + /** + * Data + **/ + result = spi_data_write(buf, size); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed block data write...\n"); + } + + return 1; +} + +static int spi_read_reg(uint32_t addr, uint32_t *data) +{ + int result = N_OK; + uint8_t cmd = CMD_SINGLE_READ; + uint8_t clockless = 0; + +#if defined USE_OLD_SPI_SW + result = spi_cmd(cmd, addr, 0, 4, 0); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed cmd, read reg (%08x)...\n", addr); + return 0; + } + result = spi_cmd_rsp(cmd, 0); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed cmd response, read reg (%08x)...\n", addr); + return 0; + } + + result = spi_data_read((uint8_t *)data, 4); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed data read...\n"); + return 0; + } +#else + if (addr < 0x30) { + /* PRINT_ER("***** read addr %d\n\n", addr); */ + /* Clockless register*/ + cmd = CMD_INTERNAL_READ; + clockless = 1; + } + + result = spi_cmd_complete(cmd, addr, (uint8_t *)data, 4, clockless); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed cmd, read reg (%08x)...\n", addr); + return 0; + } +#endif + + +#ifdef BIG_ENDIAN + *data = BYTE_SWAP(*data); +#endif + + return 1; +} + +static int spi_read(uint32_t addr, uint8_t *buf, uint32_t size) +{ + uint8_t cmd = CMD_DMA_EXT_READ; + int result; + + if (size <= 4) + return 0; + +#if defined USE_OLD_SPI_SW + /** + * Command + **/ + result = spi_cmd(cmd, addr, 0, size, 0); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed cmd, read block (%08x)...\n", addr); + return 0; + } + + result = spi_cmd_rsp(cmd, 0); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed cmd response, read block (%08x)...\n", addr); + return 0; + } + + /** + * Data + **/ + result = spi_data_read(buf, size); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed block data read...\n"); + return 0; + } +#else + result = spi_cmd_complete(cmd, addr, buf, size, 0); + if (result != N_OK) { + PRINT_ER("[wilc spi]: Failed cmd, read block (%08x)...\n", addr); + return 0; + } +#endif + + + return 1; +} + +/******************************************** + * + * Bus interfaces + * + ********************************************/ + +static int spi_clear_int(void) +{ + uint32_t reg; + if (!spi_read_reg(WILC_HOST_RX_CTRL_0, ®)) { + PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_HOST_RX_CTRL_0); + return 0; + } + reg &= ~0x1; + spi_write_reg(WILC_HOST_RX_CTRL_0, reg); + int_clrd++; + return 1; +} + +static int spi_deinit(void *pv) +{ + /** + * TODO: + **/ + return 1; +} + +static int spi_sync(void) +{ + uint32_t reg; + int ret; + + /** + * interrupt pin mux select + **/ + ret = spi_read_reg(WILC_PIN_MUX_0, ®); + if (!ret) { + PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_PIN_MUX_0); + return 0; + } + reg |= (1 << 8); + ret = spi_write_reg(WILC_PIN_MUX_0, reg); + if (!ret) { + PRINT_ER("[wilc spi]: Failed write reg (%08x)...\n", WILC_PIN_MUX_0); + return 0; + } + + /** + * interrupt enable + **/ + ret = spi_read_reg(WILC_INTR_ENABLE, ®); + if (!ret) { + PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_INTR_ENABLE); + return 0; + } + reg |= (1 << 16); + ret = spi_write_reg(WILC_INTR_ENABLE, reg); + if (!ret) { + PRINT_ER("[wilc spi]: Failed write reg (%08x)...\n", WILC_INTR_ENABLE); + return 0; + } + + return 1; +} + +static int spi_init(wilc_wlan_inp_t *inp, wilc_debug_func func) +{ + uint32_t reg; + uint32_t chipid; + + static int isinit; + + if (isinit) { + + if (!spi_read_reg(0x1000, &chipid)) { + PRINT_ER("[wilc spi]: Fail cmd read chip id...\n"); + return 0; + } + return 1; + } + + memset(&g_spi, 0, sizeof(wilc_spi_t)); + + g_spi.dPrint = func; + g_spi.os_context = inp->os_context.os_private; + if (inp->io_func.io_init) { + if (!inp->io_func.io_init(g_spi.os_context)) { + PRINT_ER("[wilc spi]: Failed io init bus...\n"); + return 0; + } + } else { + return 0; + } + g_spi.spi_tx = inp->io_func.u.spi.spi_tx; + g_spi.spi_rx = inp->io_func.u.spi.spi_rx; + g_spi.spi_trx = inp->io_func.u.spi.spi_trx; + g_spi.spi_max_speed = inp->io_func.u.spi.spi_max_speed; + + /** + * configure protocol + **/ + g_spi.crc_off = 0; + + /* TODO: We can remove the CRC trials if there is a definite way to reset */ + /* the SPI to it's initial value. */ + if (!spi_internal_read(WILC_SPI_PROTOCOL_OFFSET, ®)) { + /* Read failed. Try with CRC off. This might happen when module + * is removed but chip isn't reset*/ + g_spi.crc_off = 1; + PRINT_ER("[wilc spi]: Failed internal read protocol with CRC on, retyring with CRC off...\n", __LINE__); + if (!spi_internal_read(WILC_SPI_PROTOCOL_OFFSET, ®)) { + /* Reaad failed with both CRC on and off, something went bad */ + PRINT_ER("[wilc spi]: Failed internal read protocol...\n", __LINE__); + return 0; + } + } + if (g_spi.crc_off == 0) { + reg &= ~0xc; /* disable crc checking */ + reg &= ~0x70; + reg |= (0x5 << 4); + if (!spi_internal_write(WILC_SPI_PROTOCOL_OFFSET, reg)) { + PRINT_ER("[wilc spi %d]: Failed internal write protocol reg...\n", __LINE__); + return 0; + } + g_spi.crc_off = 1; + } + + + /** + * make sure can read back chip id correctly + **/ + if (!spi_read_reg(0x1000, &chipid)) { + PRINT_ER("[wilc spi]: Fail cmd read chip id...\n"); + return 0; + } + /* PRINT_ER("[wilc spi]: chipid (%08x)\n", chipid); */ + + g_spi.has_thrpt_enh = 1; + + isinit = 1; + + return 1; +} + +static void spi_max_bus_speed(void) +{ + g_spi.spi_max_speed(); +} + +static void spi_default_bus_speed(void) +{ +} + +static int spi_read_size(uint32_t *size) +{ + int ret; + if (g_spi.has_thrpt_enh) { + ret = spi_internal_read(0xe840 - WILC_SPI_REG_BASE, size); + *size = *size & IRQ_DMA_WD_CNT_MASK; + } else { + uint32_t tmp; + uint32_t byte_cnt; + + ret = spi_read_reg(WILC_VMM_TO_HOST_SIZE, &byte_cnt); + if (!ret) { + PRINT_ER("[wilc spi]: Failed read WILC_VMM_TO_HOST_SIZE ...\n"); + goto _fail_; + } + tmp = (byte_cnt >> 2) & IRQ_DMA_WD_CNT_MASK; + *size = tmp; + } + + + +_fail_: + return ret; +} + + + +static int spi_read_int(uint32_t *int_status) +{ + int ret; + if (g_spi.has_thrpt_enh) { + ret = spi_internal_read(0xe840 - WILC_SPI_REG_BASE, int_status); + } else { + uint32_t tmp; + uint32_t byte_cnt; + + ret = spi_read_reg(WILC_VMM_TO_HOST_SIZE, &byte_cnt); + if (!ret) { + PRINT_ER("[wilc spi]: Failed read WILC_VMM_TO_HOST_SIZE ...\n"); + goto _fail_; + } + tmp = (byte_cnt >> 2) & IRQ_DMA_WD_CNT_MASK; + + { + int happended, j; + + j = 0; + do { + uint32_t irq_flags; + + happended = 0; + + spi_read_reg(0x1a90, &irq_flags); + tmp |= ((irq_flags >> 27) << IRG_FLAGS_OFFSET); + + if (g_spi.nint > 5) { + spi_read_reg(0x1a94, &irq_flags); + tmp |= (((irq_flags >> 0) & 0x7) << (IRG_FLAGS_OFFSET + 5)); + } + + { + uint32_t unkmown_mask; + + unkmown_mask = ~((1ul << g_spi.nint) - 1); + + if ((tmp >> IRG_FLAGS_OFFSET) & unkmown_mask) { + PRINT_ER("[wilc spi]: Unexpected interrupt (2): j=%d, tmp=%x, mask=%x\n", j, tmp, unkmown_mask); + happended = 1; + } + } + j++; + } while (happended); + } + + *int_status = tmp; + + } + +_fail_: + return ret; +} + +static int spi_clear_int_ext(uint32_t val) +{ + int ret; + + if (g_spi.has_thrpt_enh) { + ret = spi_internal_write(0xe844 - WILC_SPI_REG_BASE, val); + } else { + uint32_t flags; + flags = val & ((1 << MAX_NUM_INT) - 1); + if (flags) { + int i; + + ret = 1; + for (i = 0; i < g_spi.nint; i++) { + /* No matter what you write 1 or 0, it will clear interrupt. */ + if (flags & 1) + ret = spi_write_reg(0x10c8 + i * 4, 1); + if (!ret) + break; + flags >>= 1; + } + if (!ret) { + PRINT_ER("[wilc spi]: Failed spi_write_reg, set reg %x ...\n", 0x10c8 + i * 4); + goto _fail_; + } + for (i = g_spi.nint; i < MAX_NUM_INT; i++) { + if (flags & 1) + PRINT_ER("[wilc spi]: Unexpected interrupt cleared %d...\n", i); + flags >>= 1; + } + } + + { + uint32_t tbl_ctl; + + tbl_ctl = 0; + /* select VMM table 0 */ + if ((val & SEL_VMM_TBL0) == SEL_VMM_TBL0) + tbl_ctl |= (1 << 0); + /* select VMM table 1 */ + if ((val & SEL_VMM_TBL1) == SEL_VMM_TBL1) + tbl_ctl |= (1 << 1); + + ret = spi_write_reg(WILC_VMM_TBL_CTL, tbl_ctl); + if (!ret) { + PRINT_ER("[wilc spi]: fail write reg vmm_tbl_ctl...\n"); + goto _fail_; + } + + if ((val & EN_VMM) == EN_VMM) { + /** + * enable vmm transfer. + **/ + ret = spi_write_reg(WILC_VMM_CORE_CTL, 1); + if (!ret) { + PRINT_ER("[wilc spi]: fail write reg vmm_core_ctl...\n"); + goto _fail_; + } + } + } + } +_fail_: + return ret; +} + +static int spi_sync_ext(int nint /* how mant interrupts to enable. */) +{ + uint32_t reg; + int ret, i; + + if (nint > MAX_NUM_INT) { + PRINT_ER("[wilc spi]: Too many interupts (%d)...\n", nint); + return 0; + } + + g_spi.nint = nint; + + /** + * interrupt pin mux select + **/ + ret = spi_read_reg(WILC_PIN_MUX_0, ®); + if (!ret) { + PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_PIN_MUX_0); + return 0; + } + reg |= (1 << 8); + ret = spi_write_reg(WILC_PIN_MUX_0, reg); + if (!ret) { + PRINT_ER("[wilc spi]: Failed write reg (%08x)...\n", WILC_PIN_MUX_0); + return 0; + } + + /** + * interrupt enable + **/ + ret = spi_read_reg(WILC_INTR_ENABLE, ®); + if (!ret) { + PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_INTR_ENABLE); + return 0; + } + + for (i = 0; (i < 5) && (nint > 0); i++, nint--) { + reg |= (1 << (27 + i)); + } + ret = spi_write_reg(WILC_INTR_ENABLE, reg); + if (!ret) { + PRINT_ER("[wilc spi]: Failed write reg (%08x)...\n", WILC_INTR_ENABLE); + return 0; + } + if (nint) { + ret = spi_read_reg(WILC_INTR2_ENABLE, ®); + if (!ret) { + PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_INTR2_ENABLE); + return 0; + } + + for (i = 0; (i < 3) && (nint > 0); i++, nint--) { + reg |= (1 << i); + } + + ret = spi_read_reg(WILC_INTR2_ENABLE, ®); + if (!ret) { + PRINT_ER("[wilc spi]: Failed write reg (%08x)...\n", WILC_INTR2_ENABLE); + return 0; + } + } + + return 1; +} +/******************************************** + * + * Global spi HIF function table + * + ********************************************/ +wilc_hif_func_t hif_spi = { + spi_init, + spi_deinit, + spi_read_reg, + spi_write_reg, + spi_read, + spi_write, + spi_sync, + spi_clear_int, + spi_read_int, + spi_clear_int_ext, + spi_read_size, + spi_write, + spi_read, + spi_sync_ext, + spi_max_bus_speed, + spi_default_bus_speed, +}; + diff --git a/drivers/staging/wilc1000/wilc_strutils.c b/drivers/staging/wilc1000/wilc_strutils.c new file mode 100644 index 000000000000..9e525d56feb8 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_strutils.c @@ -0,0 +1,431 @@ + +#define _CRT_SECURE_NO_DEPRECATE + +#include "wilc_oswrapper.h" + +#ifdef CONFIG_WILC_STRING_UTILS + + +/*! + * @author syounan + * @date 18 Aug 2010 + * @version 1.0 + */ +WILC_Sint32 WILC_memcmp(const void *pvArg1, const void *pvArg2, WILC_Uint32 u32Count) +{ + return memcmp(pvArg1, pvArg2, u32Count); +} + + +/*! + * @author syounan + * @date 18 Aug 2010 + * @version 1.0 + */ +void WILC_memcpy_INTERNAL(void *pvTarget, const void *pvSource, WILC_Uint32 u32Count) +{ + memcpy(pvTarget, pvSource, u32Count); +} + +/*! + * @author syounan + * @date 18 Aug 2010 + * @version 1.0 + */ +void *WILC_memset(void *pvTarget, WILC_Uint8 u8SetValue, WILC_Uint32 u32Count) +{ + return memset(pvTarget, u8SetValue, u32Count); +} + +/*! + * @author syounan + * @date 18 Aug 2010 + * @version 1.0 + */ +WILC_Char *WILC_strncat(WILC_Char *pcTarget, const WILC_Char *pcSource, + WILC_Uint32 u32Count) +{ + return strncat(pcTarget, pcSource, u32Count); +} + +/*! + * @author syounan + * @date 18 Aug 2010 + * @version 1.0 + */ +WILC_Char *WILC_strncpy(WILC_Char *pcTarget, const WILC_Char *pcSource, + WILC_Uint32 u32Count) +{ + return strncpy(pcTarget, pcSource, u32Count); +} + +/*! + * @author syounan + * @date 18 Aug 2010 + * @version 1.0 + */ +WILC_Sint32 WILC_strcmp(const WILC_Char *pcStr1, const WILC_Char *pcStr2) +{ + WILC_Sint32 s32Result; + + if (pcStr1 == WILC_NULL && pcStr2 == WILC_NULL) { + s32Result = 0; + } else if (pcStr1 == WILC_NULL) { + s32Result = -1; + } else if (pcStr2 == WILC_NULL) { + s32Result = 1; + } else { + s32Result = strcmp(pcStr1, pcStr2); + if (s32Result < 0) { + s32Result = -1; + } else if (s32Result > 0) { + s32Result = 1; + } + } + + return s32Result; +} + +WILC_Sint32 WILC_strncmp(const WILC_Char *pcStr1, const WILC_Char *pcStr2, + WILC_Uint32 u32Count) +{ + WILC_Sint32 s32Result; + + if (pcStr1 == WILC_NULL && pcStr2 == WILC_NULL) { + s32Result = 0; + } else if (pcStr1 == WILC_NULL) { + s32Result = -1; + } else if (pcStr2 == WILC_NULL) { + s32Result = 1; + } else { + s32Result = strncmp(pcStr1, pcStr2, u32Count); + if (s32Result < 0) { + s32Result = -1; + } else if (s32Result > 0) { + s32Result = 1; + } + } + + return s32Result; +} + +/* + * @author syounan + * @date 1 Nov 2010 + * @version 2.0 + */ +WILC_Sint32 WILC_strcmp_IgnoreCase(const WILC_Char *pcStr1, const WILC_Char *pcStr2) +{ + WILC_Sint32 s32Result; + + if (pcStr1 == WILC_NULL && pcStr2 == WILC_NULL) { + s32Result = 0; + } else if (pcStr1 == WILC_NULL) { + s32Result = -1; + } else if (pcStr2 == WILC_NULL) { + s32Result = 1; + } else { + WILC_Char cTestedChar1, cTestedChar2; + do { + cTestedChar1 = *pcStr1; + if ((*pcStr1 >= 'a') && (*pcStr1 <= 'z')) { + /* turn a lower case character to an upper case one */ + cTestedChar1 -= 32; + } + + cTestedChar2 = *pcStr2; + if ((*pcStr2 >= 'a') && (*pcStr2 <= 'z')) { + /* turn a lower case character to an upper case one */ + cTestedChar2 -= 32; + } + + pcStr1++; + pcStr2++; + + } while ((cTestedChar1 == cTestedChar2) + && (cTestedChar1 != 0) + && (cTestedChar2 != 0)); + + if (cTestedChar1 > cTestedChar2) { + s32Result = 1; + } else if (cTestedChar1 < cTestedChar2) { + s32Result = -1; + } else { + s32Result = 0; + } + } + + return s32Result; +} + +/*! + * @author aabozaeid + * @date 8 Dec 2010 + * @version 1.0 + */ +WILC_Sint32 WILC_strncmp_IgnoreCase(const WILC_Char *pcStr1, const WILC_Char *pcStr2, + WILC_Uint32 u32Count) +{ + WILC_Sint32 s32Result; + + if (pcStr1 == WILC_NULL && pcStr2 == WILC_NULL) { + s32Result = 0; + } else if (pcStr1 == WILC_NULL) { + s32Result = -1; + } else if (pcStr2 == WILC_NULL) { + s32Result = 1; + } else { + WILC_Char cTestedChar1, cTestedChar2; + do { + cTestedChar1 = *pcStr1; + if ((*pcStr1 >= 'a') && (*pcStr1 <= 'z')) { + /* turn a lower case character to an upper case one */ + cTestedChar1 -= 32; + } + + cTestedChar2 = *pcStr2; + if ((*pcStr2 >= 'a') && (*pcStr2 <= 'z')) { + /* turn a lower case character to an upper case one */ + cTestedChar2 -= 32; + } + + pcStr1++; + pcStr2++; + u32Count--; + + } while ((u32Count > 0) + && (cTestedChar1 == cTestedChar2) + && (cTestedChar1 != 0) + && (cTestedChar2 != 0)); + + if (cTestedChar1 > cTestedChar2) { + s32Result = 1; + } else if (cTestedChar1 < cTestedChar2) { + s32Result = -1; + } else { + s32Result = 0; + } + } + + return s32Result; + +} + +/*! + * @author syounan + * @date 18 Aug 2010 + * @version 1.0 + */ +WILC_Uint32 WILC_strlen(const WILC_Char *pcStr) +{ + return (WILC_Uint32)strlen(pcStr); +} + +/*! + * @author bfahmy + * @date 28 Aug 2010 + * @version 1.0 + */ +WILC_Sint32 WILC_strtoint(const WILC_Char *pcStr) +{ + return (WILC_Sint32)(simple_strtol(pcStr, NULL, 10)); +} + +/* + * @author syounan + * @date 1 Nov 2010 + * @version 2.0 + */ +WILC_ErrNo WILC_snprintf(WILC_Char *pcTarget, WILC_Uint32 u32Size, + const WILC_Char *pcFormat, ...) +{ + va_list argptr; + va_start(argptr, pcFormat); + if (vsnprintf(pcTarget, u32Size, pcFormat, argptr) < 0) { + /* if turncation happens windows does not properly terminate strings */ + pcTarget[u32Size - 1] = 0; + } + va_end(argptr); + + /* I find no sane way of detecting errors in windows, so let it all succeed ! */ + return WILC_SUCCESS; +} + +#ifdef CONFIG_WILC_EXTENDED_STRING_OPERATIONS + +/** + * @brief + * @details Searches for the first occurrence of the character c in the first n bytes + * of the string pointed to by the argument str. + * Returns a pointer pointing to the first matching character, + * or null if no match was found. + * @param[in] + * @return + * @note + * @author remil + * @date 3 Nov 2010 + * @version 1.0 + */ +WILC_Char *WILC_memchr(const void *str, WILC_Char c, WILC_Sint32 n) +{ + return (WILC_Char *) memchr(str, c, (size_t)n); +} + +/** + * @brief + * @details Searches for the first occurrence of the character c (an unsigned char) + * in the string pointed to by the argument str. + * The terminating null character is considered to be part of the string. + * Returns a pointer pointing to the first matching character, + * or null if no match was found. + * @param[in] + * @return + * @note + * @author remil + * @date 3 Nov 2010 + * @version 1.0 + */ +WILC_Char *WILC_strchr(const WILC_Char *str, WILC_Char c) +{ + return strchr(str, c); +} + +/** + * @brief + * @details Appends the string pointed to by str2 to the end of the string pointed to by str1. + * The terminating null character of str1 is overwritten. + * Copying stops once the terminating null character of str2 is copied. If overlapping occurs, the result is undefined. + * The argument str1 is returned. + * @param[in] WILC_Char* str1, + * @param[in] WILC_Char* str2, + * @return WILC_Char* + * @note + * @author remil + * @date 3 Nov 2010 + * @version 1.0 + */ +WILC_Char *WILC_strcat(WILC_Char *str1, const WILC_Char *str2) +{ + return strcat(str1, str2); +} + +/** + * @brief + * @details Copy pcSource to pcTarget + * @param[in] WILC_Char* pcTarget + * @param[in] const WILC_Char* pcSource + * @return WILC_Char* + * @note + * @author remil + * @date 3 Nov 2010 + * @version 1.0 + */ +WILC_Char *WILC_strcpy(WILC_Char *pcTarget, const WILC_Char *pcSource) +{ + return strncpy(pcTarget, pcSource, strlen(pcSource)); +} + +/** + * @brief + * @details Finds the first sequence of characters in the string str1 that + * does not contain any character specified in str2. + * Returns the length of this first sequence of characters found that + * do not match with str2. + * @param[in] const WILC_Char *str1 + * @param[in] const WILC_Char *str2 + * @return WILC_Uint32 + * @note + * @author remil + * @date 3 Nov 2010 + * @version 1.0 + */ +WILC_Uint32 WILC_strcspn(const WILC_Char *str1, const WILC_Char *str2) +{ + return (WILC_Uint32)strcspn(str1, str2); +} +#if 0 +/** + * @brief + * @details Searches an internal array for the error number errnum and returns a pointer + * to an error message string. + * Returns a pointer to an error message string. + * @param[in] WILC_Sint32 errnum + * @return WILC_Char* + * @note + * @author remil + * @date 3 Nov 2010 + * @version 1.0 + */ +WILC_Char *WILC_strerror(WILC_Sint32 errnum) +{ + return strerror(errnum); +} +#endif + +/** + * @brief + * @details Finds the first occurrence of the entire string str2 + * (not including the terminating null character) which appears in the string str1. + * Returns a pointer to the first occurrence of str2 in str1. + * If no match was found, then a null pointer is returned. + * If str2 points to a string of zero length, then the argument str1 is returned. + * @param[in] const WILC_Char *str1 + * @param[in] const WILC_Char *str2 + * @return WILC_Char* + * @note + * @author remil + * @date 3 Nov 2010 + * @version 1.0 + */ +WILC_Char *WILC_strstr(const WILC_Char *str1, const WILC_Char *str2) +{ + return strstr(str1, str2); +} +#if 0 +/** + * @brief + * @details Parses the C string str interpreting its content as a floating point + * number and returns its value as a double. + * If endptr is not a null pointer, the function also sets the value pointed + * by endptr to point to the first character after the number. + * @param[in] const WILC_Char* str + * @param[in] WILC_Char** endptr + * @return WILC_Double + * @note + * @author remil + * @date 11 Nov 2010 + * @version 1.0 + */ +WILC_Double WILC_StringToDouble(const WILC_Char *str, WILC_Char **endptr) +{ + return strtod (str, endptr); +} +#endif + +/** + * @brief Parses the C string str interpreting its content as an unsigned integral + * number of the specified base, which is returned as an unsigned long int value. + * @details The function first discards as many whitespace characters as necessary + * until the first non-whitespace character is found. + * Then, starting from this character, takes as many characters as possible + * that are valid following a syntax that depends on the base parameter, + * and interprets them as a numerical value. + * Finally, a pointer to the first character following the integer + * representation in str is stored in the object pointed by endptr. + * @param[in] const WILC_Char *str + * @param[in] WILC_Char **endptr + * @param[in] WILC_Sint32 base + * @return WILC_Uint32 + * @note + * @author remil + * @date 11 Nov 2010 + * @version 1.0 + */ +WILC_Uint32 WILC_StringToUint32(const WILC_Char *str, WILC_Char **endptr, WILC_Sint32 base) +{ + return simple_strtoul(str, endptr, base); +} + +#endif + +#endif diff --git a/drivers/staging/wilc1000/wilc_strutils.h b/drivers/staging/wilc1000/wilc_strutils.h new file mode 100644 index 000000000000..3a973a5ec61b --- /dev/null +++ b/drivers/staging/wilc1000/wilc_strutils.h @@ -0,0 +1,412 @@ +#ifndef __WILC_STRUTILS_H__ +#define __WILC_STRUTILS_H__ + +/*! + * @file wilc_strutils.h + * @brief Basic string utilities + * @author syounan + * @sa wilc_oswrapper.h top level OS wrapper file + * @date 16 Aug 2010 + * @version 1.0 + */ + +#ifndef CONFIG_WILC_STRING_UTILS +#error the feature CONFIG_WILC_STRING_UTILS must be supported to include this file +#endif + +/*! + * @brief Compares two memory buffers + * @param[in] pvArg1 pointer to the first memory location + * @param[in] pvArg2 pointer to the second memory location + * @param[in] u32Count the size of the memory buffers + * @return 0 if the 2 buffers are equal, 1 if pvArg1 is bigger than pvArg2, + * -1 if pvArg1 smaller than pvArg2 + * @note this function repeats the functionality of standard memcmp + * @author syounan + * @date 18 Aug 2010 + * @version 1.0 + */ +WILC_Sint32 WILC_memcmp(const void *pvArg1, const void *pvArg2, WILC_Uint32 u32Count); + +/*! + * @brief Internal implementation for memory copy + * @param[in] pvTarget the target buffer to which the data is copied into + * @param[in] pvSource pointer to the second memory location + * @param[in] u32Count the size of the data to copy + * @note this function should not be used directly, use WILC_memcpy instead + * @author syounan + * @date 18 Aug 2010 + * @version 1.0 + */ +void WILC_memcpy_INTERNAL(void *pvTarget, const void *pvSource, WILC_Uint32 u32Count); + +/*! + * @brief Copies the contents of a memory buffer into another + * @param[in] pvTarget the target buffer to which the data is copied into + * @param[in] pvSource pointer to the second memory location + * @param[in] u32Count the size of the data to copy + * @return WILC_SUCCESS if copy is successfully handeled + * WILC_FAIL if copy failed + * @note this function repeats the functionality of standard memcpy, + * however memcpy is undefined if the two buffers overlap but this + * implementation will check for overlap and report error + * @author syounan + * @date 18 Aug 2010 + * @version 1.0 + */ +static WILC_ErrNo WILC_memcpy(void *pvTarget, const void *pvSource, WILC_Uint32 u32Count) +{ + if ( + (((WILC_Uint8 *)pvTarget <= (WILC_Uint8 *)pvSource) + && (((WILC_Uint8 *)pvTarget + u32Count) > (WILC_Uint8 *)pvSource)) + + || (((WILC_Uint8 *)pvSource <= (WILC_Uint8 *)pvTarget) + && (((WILC_Uint8 *)pvSource + u32Count) > (WILC_Uint8 *)pvTarget)) + ) { + /* ovelapped memory, return Error */ + return WILC_FAIL; + } else { + WILC_memcpy_INTERNAL(pvTarget, pvSource, u32Count); + return WILC_SUCCESS; + } +} + +/*! + * @brief Sets the contents of a memory buffer with the given value + * @param[in] pvTarget the target buffer which contsnts will be set + * @param[in] u8SetValue the value to be used + * @param[in] u32Count the size of the memory buffer + * @return value of pvTarget + * @note this function repeats the functionality of standard memset + * @author syounan + * @date 18 Aug 2010 + * @version 1.0 + */ +void *WILC_memset(void *pvTarget, WILC_Uint8 u8SetValue, WILC_Uint32 u32Count); + +/*! + * @brief Concatenates the contents of 2 strings up to a given count + * @param[in] pcTarget the target string, its null character will be overwritten + * and contents of pcSource will be concatentaed to it + * @param[in] pcSource the source string the will be concatentaed + * @param[in] u32Count copying will proceed until a null character in pcSource + * is encountered or u32Count of bytes copied + * @return value of pcTarget + * @note this function repeats the functionality of standard strncat + * @author syounan + * @date 18 Aug 2010 + * @version 1.0 + */ +WILC_Char *WILC_strncat(WILC_Char *pcTarget, const WILC_Char *pcSource, + WILC_Uint32 u32Count); + +/*! + * @brief copies the contents of source string into the target string + * @param[in] pcTarget the target string buffer + * @param[in] pcSource the source string the will be copied + * @param[in] u32Count copying will proceed until a null character in pcSource + * is encountered or u32Count of bytes copied + * @return value of pcTarget + * @note this function repeats the functionality of standard strncpy + * @author syounan + * @date 18 Aug 2010 + * @version 1.0 + */ +WILC_Char *WILC_strncpy(WILC_Char *pcTarget, const WILC_Char *pcSource, + WILC_Uint32 u32Count); + +/*! + * @brief Compares two strings + * @details Compares 2 strings reporting which is bigger, WILC_NULL is considered + * the smallest string, then a zero length string then all other + * strings depending on thier ascii characters order + * @param[in] pcStr1 the first string, WILC_NULL is valid and considered smaller + * than any other non-NULL string (incliding zero lenght strings) + * @param[in] pcStr2 the second string, WILC_NULL is valid and considered smaller + * than any other non-NULL string (incliding zero lenght strings) + * @return 0 if the 2 strings are equal, 1 if pcStr1 is bigger than pcStr2, + * -1 if pcStr1 smaller than pcStr2 + * @note this function repeats the functionality of standard strcmp + * @author syounan + * @date 18 Aug 2010 + * @version 1.0 + */ +WILC_Sint32 WILC_strcmp(const WILC_Char *pcStr1, const WILC_Char *pcStr2); + +/*! + * @brief Compares two strings up to u32Count characters + * @details Compares 2 strings reporting which is bigger, WILC_NULL is considered + * the smallest string, then a zero length string then all other + * strings depending on thier ascii characters order with small case + * converted to uppder case + * @param[in] pcStr1 the first string, WILC_NULL is valid and considered smaller + * than any other non-NULL string (incliding zero lenght strings) + * @param[in] pcStr2 the second string, WILC_NULL is valid and considered smaller + * than any other non-NULL string (incliding zero lenght strings) + * @param[in] u32Count copying will proceed until a null character in pcStr1 or + * pcStr2 is encountered or u32Count of bytes copied + * @return 0 if the 2 strings are equal, 1 if pcStr1 is bigger than pcStr2, + * -1 if pcStr1 smaller than pcStr2 + * @author aabozaeid + * @date 7 Dec 2010 + * @version 1.0 + */ +WILC_Sint32 WILC_strncmp(const WILC_Char *pcStr1, const WILC_Char *pcStr2, + WILC_Uint32 u32Count); + +/*! + * @brief Compares two strings ignoring the case of its latin letters + * @details Compares 2 strings reporting which is bigger, WILC_NULL is considered + * the smallest string, then a zero length string then all other + * strings depending on thier ascii characters order with small case + * converted to uppder case + * @param[in] pcStr1 the first string, WILC_NULL is valid and considered smaller + * than any other non-NULL string (incliding zero lenght strings) + * @param[in] pcStr2 the second string, WILC_NULL is valid and considered smaller + * than any other non-NULL string (incliding zero lenght strings) + * @return 0 if the 2 strings are equal, 1 if pcStr1 is bigger than pcStr2, + * -1 if pcStr1 smaller than pcStr2 + * @author syounan + * @date 1 Nov 2010 + * @version 2.0 + */ +WILC_Sint32 WILC_strcmp_IgnoreCase(const WILC_Char *pcStr1, const WILC_Char *pcStr2); + +/*! + * @brief Compares two strings ignoring the case of its latin letters up to + * u32Count characters + * @details Compares 2 strings reporting which is bigger, WILC_NULL is considered + * the smallest string, then a zero length string then all other + * strings depending on thier ascii characters order with small case + * converted to uppder case + * @param[in] pcStr1 the first string, WILC_NULL is valid and considered smaller + * than any other non-NULL string (incliding zero lenght strings) + * @param[in] pcStr2 the second string, WILC_NULL is valid and considered smaller + * than any other non-NULL string (incliding zero lenght strings) + * @param[in] u32Count copying will proceed until a null character in pcStr1 or + * pcStr2 is encountered or u32Count of bytes copied + * @return 0 if the 2 strings are equal, 1 if pcStr1 is bigger than pcStr2, + * -1 if pcStr1 smaller than pcStr2 + * @author aabozaeid + * @date 7 Dec 2010 + * @version 1.0 + */ +WILC_Sint32 WILC_strncmp_IgnoreCase(const WILC_Char *pcStr1, const WILC_Char *pcStr2, + WILC_Uint32 u32Count); + +/*! + * @brief gets the length of a string + * @param[in] pcStr the string + * @return the length + * @note this function repeats the functionality of standard strlen + * @author syounan + * @date 18 Aug 2010 + * @version 1.0 + */ +WILC_Uint32 WILC_strlen(const WILC_Char *pcStr); + +/*! + * @brief convert string to integer + * @param[in] pcStr the string + * @return the value of string + * @note this function repeats the functionality of the libc atoi + * @author bfahmy + * @date 28 Aug 2010 + * @version 1.0 + */ +WILC_Sint32 WILC_strtoint(const WILC_Char *pcStr); + +/*! + * @brief print a formatted string into a buffer + * @param[in] pcTarget the buffer where the resulting string is written + * @param[in] u32Size size of the output beffer including the \0 terminating + * character + * @param[in] pcFormat format of the string + * @return number of character written or would have been written if the + * string were not truncated + * @note this function repeats the functionality of standard snprintf + * @author syounan + * @date 1 Nov 2010 + * @version 2.0 + */ +WILC_Sint32 WILC_snprintf(WILC_Char *pcTarget, WILC_Uint32 u32Size, + const WILC_Char *pcFormat, ...); + + +#ifdef CONFIG_WILC_EXTENDED_STRING_OPERATIONS + + +/** + * @brief + * @details Searches for the first occurrence of the character c in the first n bytes + * of the string pointed to by the argument str. + * Returns a pointer pointing to the first matching character, + * or null if no match was found. + * @param[in] + * @return + * @note + * @author remil + * @date 3 Nov 2010 + * @version 1.0 + */ +WILC_Char *WILC_memchr(const void *str, WILC_Char c, WILC_Sint32 n); + +/** + * @brief + * @details Searches for the first occurrence of the character c (an unsigned char) + * in the string pointed to by the argument str. + * The terminating null character is considered to be part of the string. + * Returns a pointer pointing to the first matching character, + * or null if no match was found. + * @param[in] + * @return + * @note + * @author remil + * @date 3 Nov 2010 + * @version 1.0 + */ +WILC_Char *WILC_strchr(const WILC_Char *str, WILC_Char c); + +/** + * @brief + * @details Appends the string pointed to by str2 to the end of the string pointed to by str1. + * The terminating null character of str1 is overwritten. + * Copying stops once the terminating null character of str2 is copied. If overlapping occurs, the result is undefined. + * The argument str1 is returned. + * @param[in] WILC_Char* str1, + * @param[in] WILC_Char* str2, + * @return WILC_Char* + * @note + * @author remil + * @date 3 Nov 2010 + * @version 1.0 + */ +WILC_Char *WILC_strcat(WILC_Char *str1, const WILC_Char *str2); + + +/** + * @brief + * @details Copy pcSource to pcTarget + * @param[in] WILC_Char* pcTarget + * @param[in] const WILC_Char* pcSource + * @return WILC_Char* + * @note + * @author remil + * @date 3 Nov 2010 + * @version 1.0 + */ +WILC_Char *WILC_strcpy(WILC_Char *pcTarget, const WILC_Char *pcSource); + + + +/** + * @brief + * @details Finds the first sequence of characters in the string str1 that + * does not contain any character specified in str2. + * Returns the length of this first sequence of characters found that + * do not match with str2. + * @param[in] const WILC_Char *str1 + * @param[in] const WILC_Char *str2 + * @return WILC_Uint32 + * @note + * @author remil + * @date 3 Nov 2010 + * @version 1.0 + */ +WILC_Uint32 WILC_strcspn(const WILC_Char *str1, const WILC_Char *str2); + + +/** + * @brief + * @details Searches an internal array for the error number errnum and returns a pointer + * to an error message string. + * Returns a pointer to an error message string. + * @param[in] WILC_Sint32 errnum + * @return WILC_Char* + * @note + * @author remil + * @date 3 Nov 2010 + * @version 1.0 + */ +WILC_Char *WILC_strerror(WILC_Sint32 errnum); + +/** + * @brief + * @details Finds the first occurrence of the entire string str2 + * (not including the terminating null character) which appears in the string str1. + * Returns a pointer to the first occurrence of str2 in str1. + * If no match was found, then a null pointer is returned. + * If str2 points to a string of zero length, then the argument str1 is returned. + * @param[in] const WILC_Char *str1 + * @param[in] const WILC_Char *str2 + * @return WILC_Char* + * @note + * @author remil + * @date 3 Nov 2010 + * @version 1.0 + */ +WILC_Char *WILC_strstr(const WILC_Char *str1, const WILC_Char *str2); + +/** + * @brief + * @details Searches for the first occurrence of the character c (an unsigned char) + * in the string pointed to by the argument str. + * The terminating null character is considered to be part of the string. + * Returns a pointer pointing to the first matching character, + * or null if no match was found. + * @param[in] + * @return + * @note + * @author remil + * @date 3 Nov 2010 + * @version 1.0 + */ +WILC_Char *WILC_strchr(const WILC_Char *str, WILC_Char c); + + +/** + * @brief + * @details Parses the C string str interpreting its content as a floating point + * number and returns its value as a double. + * If endptr is not a null pointer, the function also sets the value pointed + * by endptr to point to the first character after the number. + * @param[in] const WILC_Char* str + * @param[in] WILC_Char** endptr + * @return WILC_Double + * @note + * @author remil + * @date 11 Nov 2010 + * @version 1.0 + */ +WILC_Double WILC_StringToDouble(const WILC_Char *str, + WILC_Char **endptr); + + +/** + * @brief Parses the C string str interpreting its content as an unsigned integral + * number of the specified base, which is returned as an unsigned long int value. + * @details The function first discards as many whitespace characters as necessary + * until the first non-whitespace character is found. + * Then, starting from this character, takes as many characters as possible + * that are valid following a syntax that depends on the base parameter, + * and interprets them as a numerical value. + * Finally, a pointer to the first character following the integer + * representation in str is stored in the object pointed by endptr. + * @param[in] const WILC_Char *str + * @param[in] WILC_Char **endptr + * @param[in] WILC_Sint32 base + * @return WILC_Uint32 + * @note + * @author remil + * @date 11 Nov 2010 + * @version 1.0 + */ +WILC_Uint32 WILC_StringToUint32(const WILC_Char *str, + WILC_Char **endptr, + WILC_Sint32 base); + + + +#endif + +#endif diff --git a/drivers/staging/wilc1000/wilc_thread.c b/drivers/staging/wilc1000/wilc_thread.c new file mode 100644 index 000000000000..5eb04e839309 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_thread.c @@ -0,0 +1,35 @@ + +#include "wilc_oswrapper.h" + +#ifdef CONFIG_WILC_THREAD_FEATURE + + + +WILC_ErrNo WILC_ThreadCreate(WILC_ThreadHandle *pHandle, tpfWILC_ThreadFunction pfEntry, + void *pvArg, tstrWILC_ThreadAttrs *pstrAttrs) +{ + + + *pHandle = kthread_run((int (*)(void *))pfEntry, pvArg, "WILC_kthread"); + + + if (IS_ERR(*pHandle)) { + return WILC_FAIL; + } else { + return WILC_SUCCESS; + } + +} + +WILC_ErrNo WILC_ThreadDestroy(WILC_ThreadHandle *pHandle, + tstrWILC_ThreadAttrs *pstrAttrs) +{ + WILC_ErrNo s32RetStatus = WILC_SUCCESS; + + kthread_stop(*pHandle); + return s32RetStatus; +} + + + +#endif diff --git a/drivers/staging/wilc1000/wilc_thread.h b/drivers/staging/wilc1000/wilc_thread.h new file mode 100644 index 000000000000..c862cd544dd4 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_thread.h @@ -0,0 +1,153 @@ +#ifndef __WILC_THREAD_H__ +#define __WILC_THREAD_H__ + +/*! + * @file wilc_thread.h + * @brief Thread OS Wrapper functionality + * @author syounan + * @sa wilc_oswrapper.h top level OS wrapper file + * @date 10 Aug 2010 + * @version 1.0 + */ + +#ifndef CONFIG_WILC_THREAD_FEATURE +#error the feature WILC_OS_FEATURE_THREAD must be supported to include this file +#endif + +typedef void (*tpfWILC_ThreadFunction)(void *); + +typedef enum { + #ifdef CONFIG_WILC_THREAD_STRICT_PRIORITY + WILC_OS_THREAD_PIORITY_0 = 0, + WILC_OS_THREAD_PIORITY_1 = 1, + WILC_OS_THREAD_PIORITY_2 = 2, + WILC_OS_THREAD_PIORITY_3 = 3, + WILC_OS_THREAD_PIORITY_4 = 4, + #endif + + WILC_OS_THREAD_PIORITY_HIGH = 0, + WILC_OS_THREAD_PIORITY_NORMAL = 2, + WILC_OS_THREAD_PIORITY_LOW = 4 +} tenuWILC_ThreadPiority; + +/*! + * @struct WILC_ThreadAttrs + * @brief Thread API options + * @author syounan + * @date 10 Aug 2010 + * @version 1.0 + */ +typedef struct { + /*!< + * stack size for use with WILC_ThreadCreate, default is WILC_OS_THREAD_DEFAULT_STACK + */ + WILC_Uint32 u32StackSize; + + /*!< + * piority for the thread, if WILC_OS_FEATURE_THREAD_STRICT_PIORITY is defined + * this value is strictly observed and can take a larger resolution + */ + tenuWILC_ThreadPiority enuPiority; + + #ifdef CONFIG_WILC_THREAD_SUSPEND_CONTROL + /*! + * if true the thread will be created suspended + */ + WILC_Bool bStartSuspended; + #endif + +} tstrWILC_ThreadAttrs; + +#define WILC_OS_THREAD_DEFAULT_STACK (10 * 1024) + +/*! + * @brief Fills the WILC_ThreadAttrs with default parameters + * @param[out] pstrAttrs structure to be filled + * @sa WILC_ThreadAttrs + * @author syounan + * @date 10 Aug 2010 + * @version 1.0 + */ + +static void WILC_ThreadFillDefault(tstrWILC_ThreadAttrs *pstrAttrs) +{ + pstrAttrs->u32StackSize = WILC_OS_THREAD_DEFAULT_STACK; + pstrAttrs->enuPiority = WILC_OS_THREAD_PIORITY_NORMAL; + + #ifdef CONFIG_WILC_THREAD_SUSPEND_CONTROL + pstrAttrs->bStartSuspended = WILC_FALSE; + #endif +} + +/*! + * @brief Creates a new thread + * @details if the feature WILC_OS_FEATURE_THREAD_SUSPEND_CONTROL is + * defined and tstrWILC_ThreadAttrs.bStartSuspended is set to true + * the new thread will be created in suspended state, otherwise + * it will start executing immeadiately + * if the feature WILC_OS_FEATURE_THREAD_STRICT_PIORITY is defined + * piorities are strictly observed, otherwise the underlaying OS + * may not observe piorities + * @param[out] pHandle handle to the newly created thread object + * @param[in] pfEntry pointer to the entry point of the new thread + * @param[in] pstrAttrs Optional attributes, NULL for default + * @return Error code indicating sucess/failure + * @sa WILC_ThreadAttrs + * @author syounan + * @date 10 Aug 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_ThreadCreate(WILC_ThreadHandle *pHandle, tpfWILC_ThreadFunction pfEntry, + void *pvArg, tstrWILC_ThreadAttrs *pstrAttrs); + +/*! + * @brief Destroys the Thread object + * @details This function is used for clean up and freeing any used resources + * This function will block until the destroyed thread exits cleanely, + * so, the thread code thould handle an exit case before this calling + * this function + * @param[in] pHandle handle to the thread object + * @param[in] pstrAttrs Optional attributes, NULL for default + * @return Error code indicating sucess/failure + * @sa WILC_ThreadAttrs + * @author syounan + * @date 10 Aug 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_ThreadDestroy(WILC_ThreadHandle *pHandle, + tstrWILC_ThreadAttrs *pstrAttrs); + +#ifdef CONFIG_WILC_THREAD_SUSPEND_CONTROL + +/*! + * @brief Suspends an executing Thread object + * @param[in] pHandle handle to the thread object + * @param[in] pstrAttrs Optional attributes, NULL for default + * @return Error code indicating sucess/failure + * @sa WILC_ThreadAttrs + * @note Optional part, WILC_OS_FEATURE_THREAD_SUSPEND_CONTROL must be enabled + * @author syounan + * @date 10 Aug 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_ThreadSuspend(WILC_ThreadHandle *pHandle, + tstrWILC_ThreadAttrs *pstrAttrs); + +/*! + * @brief Resumes a suspened Thread object + * @param[in] pHandle handle to the thread object + * @param[in] pstrAttrs Optional attributes, NULL for default + * @return Error code indicating sucess/failure + * @sa WILC_ThreadAttrs + * @note Optional part, WILC_OS_FEATURE_THREAD_SUSPEND_CONTROL must be enabled + * @author syounan + * @date 10 Aug 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_ThreadResume(WILC_ThreadHandle *pHandle, + tstrWILC_ThreadAttrs *pstrAttrs); + +#endif + + +#endif diff --git a/drivers/staging/wilc1000/wilc_time.c b/drivers/staging/wilc1000/wilc_time.c new file mode 100644 index 000000000000..27c252b462ac --- /dev/null +++ b/drivers/staging/wilc1000/wilc_time.c @@ -0,0 +1,163 @@ + +#define _CRT_SECURE_NO_DEPRECATE +#include "wilc_oswrapper.h" + +#ifdef CONFIG_WILC_TIME_FEATURE + + +WILC_Uint32 WILC_TimeMsec(void) +{ + WILC_Uint32 u32Time = 0; + struct timespec current_time; + + current_time = current_kernel_time(); + u32Time = current_time.tv_sec * 1000; + u32Time += current_time.tv_nsec / 1000000; + + + return u32Time; +} + + +#ifdef CONFIG_WILC_EXTENDED_TIME_OPERATIONS + +/** + * @brief + * @details function returns the implementation's best approximation to the + * processor time used by the process since the beginning of an + * implementation-dependent time related only to the process invocation. + * @return WILC_Uint32 + * @note + * @author remil + * @date 11 Nov 2010 + * @version 1.0 + */ +WILC_Uint32 WILC_Clock() +{ + +} + + +/** + * @brief + * @details The difftime() function computes the difference between two calendar + * times (as returned by WILC_GetTime()): time1 - time0. + * @param[in] WILC_Time time1 + * @param[in] WILC_Time time0 + * @return WILC_Double + * @note + * @author remil + * @date 11 Nov 2010 + * @version 1.0 + */ +WILC_Double WILC_DiffTime(WILC_Time time1, WILC_Time time0) +{ + +} + + + +/** + * @brief + * @details The gmtime() function converts the time in seconds since + * the Epoch pointed to by timer into a broken-down time, + * expressed as Coordinated Universal Time (UTC). + * @param[in] const WILC_Time* timer + * @return WILC_tm* + * @note + * @author remil + * @date 11 Nov 2010 + * @version 1.0 + */ +WILC_tm *WILC_GmTime(const WILC_Time *timer) +{ + +} + + +/** + * @brief + * @details The localtime() function converts the time in seconds since + * the Epoch pointed to by timer into a broken-down time, expressed + * as a local time. The function corrects for the timezone and any + * seasonal time adjustments. Local timezone information is used as + * though localtime() calls tzset(). + * @param[in] const WILC_Time* timer + * @return WILC_tm* + * @note + * @author remil + * @date 11 Nov 2010 + * @version 1.0 + */ +WILC_tm *WILC_LocalTime(const WILC_Time *timer) +{ + +} + + +/** + * @brief + * @details The mktime() function converts the broken-down time, + * expressed as local time, in the structure pointed to by timeptr, + * into a time since the Epoch value with the same encoding as that + * of the values returned by time(). The original values of the tm_wday + * and tm_yday components of the structure are ignored, and the original + * values of the other components are not restricted to the ranges described + * in the entry. + * @param[in] WILC_tm* timer + * @return WILC_Time + * @note + * @author remil + * @date 11 Nov 2010 + * @version 1.0 + */ +WILC_Time WILC_MkTime(WILC_tm *timer) +{ + +} + + +/** + * @brief + * @details The strftime() function places bytes into the array + * pointed to by s as controlled by the string pointed to by format. + * @param[in] WILC_Char* s + * @param[in] WILC_Uint32 maxSize + * @param[in] const WILC_Char* format + * @param[in] const WILC_tm* timptr + * @return WILC_Uint32 + * @note + * @author remil + * @date 11 Nov 2010 + * @version 1.0 + */ +WILC_Uint32 WILC_StringFormatTime(WILC_Char *s, + WILC_Uint32 maxSize, + const WILC_Char *format, + const WILC_tm *timptr) +{ + +} + + +/** + * @brief The WILC_GetTime() function returns the value of time in seconds since the Epoch. + * @details The tloc argument points to an area where the return value is also stored. + * If tloc is a null pointer, no value is stored. + * @param[in] WILC_Time* tloc + * @return WILC_Time + * @note + * @author remil + * @date 11 Nov 2010 + * @version 1.0 + */ +WILC_Time WILC_GetTime(WILC_Time *tloc) +{ + +} + + +#endif +#endif + + diff --git a/drivers/staging/wilc1000/wilc_time.h b/drivers/staging/wilc1000/wilc_time.h new file mode 100644 index 000000000000..787df7ded75c --- /dev/null +++ b/drivers/staging/wilc1000/wilc_time.h @@ -0,0 +1,205 @@ +#ifndef __WILC_TIME_H__ +#define __WILC_TIME_H__ + +/*! +* @file wilc_time.h +* @brief Time retrival functionality +* @author syounan +* @sa wilc_oswrapper.h top level OS wrapper file +* @date 2 Sep 2010 +* @version 1.0 +*/ + +#ifndef CONFIG_WILC_TIME_FEATURE +#error the feature CONFIG_WILC_TIME_FEATURE must be supported to include this file +#endif + +/*! +* @struct WILC_ThreadAttrs +* @brief Thread API options +* @author syounan +* @date 2 Sep 2010 +* @version 1.0 +*/ +typedef struct { + /* a dummy type to prevent compile errors on empty structure*/ + WILC_Uint8 dummy; +} tstrWILC_TimeAttrs; + +typedef struct { + /*!< current year */ + WILC_Uint16 u16Year; + /*!< current month */ + WILC_Uint8 u8Month; + /*!< current day */ + WILC_Uint8 u8Day; + + /*!< current hour (in 24H format) */ + WILC_Uint8 u8Hour; + /*!< current minute */ + WILC_Uint8 u8Miute; + /*!< current second */ + WILC_Uint8 u8Second; + +} tstrWILC_TimeCalender; + +/*! +* @brief returns the number of msec elapsed since system start up +* @return number of msec elapsed singe system start up +* @note since this returned value is 32 bit, the caller must handle + wraparounds in values every about 49 of continous operations +* @author syounan +* @date 2 Sep 2010 +* @version 1.0 +*/ +WILC_Uint32 WILC_TimeMsec(void); + + + +#ifdef CONFIG_WILC_EXTENDED_TIME_OPERATIONS +/** +* @brief +* @details function returns the implementation's best approximation to the + processor time used by the process since the beginning of an + implementation-dependent time related only to the process invocation. +* @return WILC_Uint32 +* @note +* @author remil +* @date 11 Nov 2010 +* @version 1.0 +*/ +WILC_Uint32 WILC_Clock(); + +/** +* @brief +* @details The difftime() function computes the difference between two calendar + times (as returned by WILC_GetTime()): time1 - time0. +* @param[in] WILC_Time time1 +* @param[in] WILC_Time time0 +* @return WILC_Double +* @note +* @author remil +* @date 11 Nov 2010 +* @version 1.0 +*/ +WILC_Double WILC_DiffTime(WILC_Time time1, WILC_Time time0); + +/** +* @brief +* @details The gmtime() function converts the time in seconds since + the Epoch pointed to by timer into a broken-down time, + expressed as Coordinated Universal Time (UTC). +* @param[in] const WILC_Time* timer +* @return WILC_tm* +* @note +* @author remil +* @date 11 Nov 2010 +* @version 1.0 +*/ +WILC_tm *WILC_GmTime(const WILC_Time *timer); + + +/** +* @brief +* @details The localtime() function converts the time in seconds since + the Epoch pointed to by timer into a broken-down time, expressed + as a local time. The function corrects for the timezone and any + seasonal time adjustments. Local timezone information is used as + though localtime() calls tzset(). +* @param[in] const WILC_Time* timer +* @return WILC_tm* +* @note +* @author remil +* @date 11 Nov 2010 +* @version 1.0 +*/ +WILC_tm *WILC_LocalTime(const WILC_Time *timer); + + +/** +* @brief +* @details The mktime() function converts the broken-down time, + expressed as local time, in the structure pointed to by timeptr, + into a time since the Epoch value with the same encoding as that + of the values returned by time(). The original values of the tm_wday + and tm_yday components of the structure are ignored, and the original + values of the other components are not restricted to the ranges described + in the entry. +* @param[in] WILC_tm* timer +* @return WILC_Time +* @note +* @author remil +* @date 11 Nov 2010 +* @version 1.0 +*/ +WILC_Time WILC_MkTime(WILC_tm *timer); + + +/** +* @brief +* @details The strftime() function places bytes into the array + pointed to by s as controlled by the string pointed to by format. +* @param[in] WILC_Char* s +* @param[in] WILC_Uint32 maxSize +* @param[in] const WILC_Char* format +* @param[in] const WILC_tm* timptr +* @return WILC_Uint32 +* @note +* @author remil +* @date 11 Nov 2010 +* @version 1.0 +*/ +WILC_Uint32 WILC_StringFormatTime(WILC_Char *s, + WILC_Uint32 maxSize, + const WILC_Char *format, + const WILC_tm *timptr); + + +/** +* @brief The WILC_GetTime() function returns the value of time in seconds since the Epoch. +* @details The tloc argument points to an area where the return value is also stored. + If tloc is a null pointer, no value is stored. +* @param[in] WILC_Time* tloc +* @return WILC_Time +* @note +* @author remil +* @date 11 Nov 2010 +* @version 1.0 +*/ +WILC_Time WILC_GetTime(WILC_Time *tloc); + +#endif + +#ifdef CONFIG_WILC_TIME_UTC_SINCE_1970 + +/*! +* @brief returns the number of seconds elapsed since 1970 (in UTC) +* @param[in] pstrAttrs Optional attributes, NULL for default +* @return number of seconds elapsed since 1970 (in UTC) +* @sa tstrWILC_TimeAttrs +* @author syounan +* @date 2 Sep 2010 +* @version 1.0 +*/ +WILC_Uint32 WILC_TimeUtcSince1970(tstrWILC_TimeAttrs *pstrAttrs); + +#endif + +#ifdef CONFIG_WILC_TIME_CALENDER + +/*! +* @brief gets the current calender time +* @return number of seconds elapsed since 1970 (in UTC) +* @param[out] ptstrCalender calender structure to be filled with time +* @param[in] pstrAttrs Optional attributes, NULL for default +* @sa WILC_ThreadAttrs +* @author syounan +* @date 2 Sep 2010 +* @version 1.0 +*/ +WILC_ErrNo WILC_TimeCalender(tstrWILC_TimeCalender *ptstrCalender, + tstrWILC_TimeAttrs *pstrAttrs); + +#endif + +#endif diff --git a/drivers/staging/wilc1000/wilc_timer.c b/drivers/staging/wilc1000/wilc_timer.c new file mode 100644 index 000000000000..477986dcff0a --- /dev/null +++ b/drivers/staging/wilc1000/wilc_timer.c @@ -0,0 +1,51 @@ + +#include "wilc_oswrapper.h" + +#ifdef CONFIG_WILC_TIMER_FEATURE + + + +WILC_ErrNo WILC_TimerCreate(WILC_TimerHandle *pHandle, + tpfWILC_TimerFunction pfCallback, tstrWILC_TimerAttrs *pstrAttrs) +{ + WILC_ErrNo s32RetStatus = WILC_SUCCESS; + setup_timer(pHandle, (void(*)(unsigned long))pfCallback, 0); + + return s32RetStatus; +} + +WILC_ErrNo WILC_TimerDestroy(WILC_TimerHandle *pHandle, + tstrWILC_TimerAttrs *pstrAttrs) +{ + WILC_ErrNo s32RetStatus = WILC_FAIL; + if (pHandle != NULL) { + s32RetStatus = del_timer_sync(pHandle); + pHandle = NULL; + } + + return s32RetStatus; +} + + +WILC_ErrNo WILC_TimerStart(WILC_TimerHandle *pHandle, WILC_Uint32 u32Timeout, + void *pvArg, tstrWILC_TimerAttrs *pstrAttrs) +{ + WILC_ErrNo s32RetStatus = WILC_FAIL; + if (pHandle != NULL) { + pHandle->data = (unsigned long)pvArg; + s32RetStatus = mod_timer(pHandle, (jiffies + msecs_to_jiffies(u32Timeout))); + } + return s32RetStatus; +} + +WILC_ErrNo WILC_TimerStop(WILC_TimerHandle *pHandle, + tstrWILC_TimerAttrs *pstrAttrs) +{ + WILC_ErrNo s32RetStatus = WILC_FAIL; + if (pHandle != NULL) + s32RetStatus = del_timer(pHandle); + + return s32RetStatus; +} + +#endif diff --git a/drivers/staging/wilc1000/wilc_timer.h b/drivers/staging/wilc1000/wilc_timer.h new file mode 100644 index 000000000000..1080ce24a045 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_timer.h @@ -0,0 +1,153 @@ +#ifndef __WILC_TIMER_H__ +#define __WILC_TIMER_H__ + +/*! + * @file wilc_timer.h + * @brief Timer (One Shot and Periodic) OS wrapper functionality + * @author syounan + * @sa wilc_oswrapper.h top level OS wrapper file + * @date 16 Aug 2010 + * @version 1.0 + */ + +#ifndef CONFIG_WILC_TIMER_FEATURE +#error the feature CONFIG_WILC_TIMER_FEATURE must be supported to include this file +#endif + +typedef void (*tpfWILC_TimerFunction)(void *); + +/*! + * @struct tstrWILC_TimerAttrs + * @brief Timer API options + * @author syounan + * @date 16 Aug 2010 + * @version 1.0 + */ +typedef struct { + /*!< if set to WILC_TRUE the callback function will be called + * periodically. */ + #ifdef CONFIG_WILC_TIMER_PERIODIC + WILC_Bool bPeriodicTimer; + #endif + + /* a dummy member to avoid compiler errors*/ + WILC_Uint8 dummy; +} tstrWILC_TimerAttrs; + +/*! + * @brief Fills the WILC_TimerAttrs with default parameters + * @param[out] pstrAttrs structure to be filled + * @sa WILC_TimerAttrs + * @author syounan + * @date 16 Aug 2010 + * @version 1.0 + */ + +static void WILC_TimerFillDefault(tstrWILC_TimerAttrs *pstrAttrs) +{ + #ifdef CONFIG_WILC_TIMER_PERIODIC + pstrAttrs->bPeriodicTimer = WILC_FALSE; + #endif +} + + +/*! + * @brief Creates a new timer + * @details Timers are a useful utility to execute some callback function + * in the future. + * A timer object has 3 states : IDLE, PENDING and EXECUTING + * IDLE : initial timer state after creation, no execution for the + * callback function is planned + * PENDING : a request to execute the callback function is made + * using WILC_TimerStart. + * EXECUTING : the timer has expired and its callback is now + * executing, when execution is done the timer returns to PENDING + * if the feature CONFIG_WILC_TIMER_PERIODIC is enabled and + * the flag tstrWILC_TimerAttrs.bPeriodicTimer is set. otherwise the + * timer will return to IDLE + * @param[out] pHandle handle to the newly created timer object + * @param[in] pfEntry pointer to the callback function to be called when the + * timer expires + * the underlaying OS may put many restrictions on what can be + * called inside a timer's callback, as a general rule no blocking + * operations (IO or semaphore Acquision) should be perfomred + * It is recommended that the callback will be as short as possible + * and only flags other threads to do the actual work + * also it should be noted that the underlaying OS maynot give any + * guarentees on which contect this callback will execute in + * @param[in] pstrAttrs Optional attributes, NULL for default + * @return Error code indicating sucess/failure + * @sa WILC_TimerAttrs + * @author syounan + * @date 16 Aug 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_TimerCreate(WILC_TimerHandle *pHandle, + tpfWILC_TimerFunction pfCallback, tstrWILC_TimerAttrs *pstrAttrs); + + +/*! + * @brief Destroys a given timer + * @details This will destroy a given timer freeing any resources used by it + * if the timer was PENDING Then must be cancelled as well(i.e. + * goes to IDLE, same effect as calling WILC_TimerCancel first) + * if the timer was EXECUTING then the callback will be allowed to + * finish first then all resources are freed + * @param[in] pHandle handle to the timer object + * @param[in] pstrAttrs Optional attributes, NULL for default + * @return Error code indicating sucess/failure + * @sa WILC_TimerAttrs + * @author syounan + * @date 16 Aug 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_TimerDestroy(WILC_TimerHandle *pHandle, + tstrWILC_TimerAttrs *pstrAttrs); + +/*! + * @brief Starts a given timer + * @details This function will move the timer to the PENDING state until the + * given time expires (in msec) then the callback function will be + * executed (timer in EXECUTING state) after execution is dene the + * timer either goes to IDLE (if bPeriodicTimer==WILC_FALSE) or + * PENDING with same timeout value (if bPeriodicTimer==WILC_TRUE) + * @param[in] pHandle handle to the timer object + * @param[in] u32Timeout timeout value in msec after witch the callback + * function will be executed. Timeout value of 0 is not allowed for + * periodic timers + * @param[in] pstrAttrs Optional attributes, NULL for default, + * set bPeriodicTimer to run this timer as a periodic timer + * @return Error code indicating sucess/failure + * @sa WILC_TimerAttrs + * @author syounan + * @date 16 Aug 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_TimerStart(WILC_TimerHandle *pHandle, WILC_Uint32 u32Timeout, void *pvArg, + tstrWILC_TimerAttrs *pstrAttrs); + + +/*! + * @brief Stops a given timer + * @details This function will move the timer to the IDLE state cancelling + * any sheduled callback execution. + * if this function is called on a timer already in the IDLE state + * it will have no effect. + * if this function is called on a timer in EXECUTING state + * (callback has already started) it will wait until executing is + * done then move the timer to the IDLE state (which is trivial + * work if the timer is non periodic) + * @param[in] pHandle handle to the timer object + * @param[in] pstrAttrs Optional attributes, NULL for default, + * @return Error code indicating sucess/failure + * @sa WILC_TimerAttrs + * @author syounan + * @date 16 Aug 2010 + * @version 1.0 + */ +WILC_ErrNo WILC_TimerStop(WILC_TimerHandle *pHandle, + tstrWILC_TimerAttrs *pstrAttrs); + + + +#endif diff --git a/drivers/staging/wilc1000/wilc_type.h b/drivers/staging/wilc1000/wilc_type.h new file mode 100644 index 000000000000..5f36e7f92cd1 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_type.h @@ -0,0 +1,34 @@ +/* ////////////////////////////////////////////////////////////////////////// */ +/* */ +/* Copyright (c) Atmel Corporation. All rights reserved. */ +/* */ +/* Module Name: wilc_type.h */ +/* */ +/* */ +/* //////////////////////////////////////////////////////////////////////////// */ +#ifndef WILC_TYPE_H +#define WILC_TYPE_H + +/******************************************** + * + * Type Defines + * + ********************************************/ +#ifdef WIN32 +typedef char int8_t; +typedef short int16_t; +typedef long int32_t; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned long uint32_t; +#else +#ifdef _linux_ +/*typedef unsigned char uint8_t; + * typedef unsigned short uint16_t; + * typedef unsigned long uint32_t;*/ +#include +#else +#include "wilc_oswrapper.h" +#endif +#endif +#endif diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c new file mode 100644 index 000000000000..648472925de0 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -0,0 +1,4592 @@ +/*! + * @file wilc_wfi_cfgopertaions.c + * @brief CFG80211 Function Implementation functionality + * @author aabouzaeid + * mabubakr + * mdaftedar + * zsalah + * @sa wilc_wfi_cfgopertaions.h top level OS wrapper file + * @date 31 Aug 2010 + * @version 1.0 + */ + +#include "wilc_wfi_cfgoperations.h" +#include "wilc_wlan.c" +#ifdef WILC_SDIO +#include "linux_wlan_sdio.h" /* tony : for set_wiphy_dev() */ +#endif + + +#define IS_MANAGMEMENT 0x100 +#define IS_MANAGMEMENT_CALLBACK 0x080 +#define IS_MGMT_STATUS_SUCCES 0x040 +#define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff) + +extern void linux_wlan_free(void *vp); +extern int linux_wlan_get_firmware(perInterface_wlan_t *p_nic); +extern void linux_wlan_unlock(void *vp); +extern WILC_Uint16 Set_machw_change_vir_if(WILC_Bool bValue); + +extern int mac_open(struct net_device *ndev); +extern int mac_close(struct net_device *ndev); + +tstrNetworkInfo astrLastScannedNtwrksShadow[MAX_NUM_SCANNED_NETWORKS_SHADOW]; +WILC_Uint32 u32LastScannedNtwrksCountShadow; +#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP +WILC_TimerHandle hDuringIpTimer; +#endif +WILC_TimerHandle hAgingTimer; +static WILC_Uint8 op_ifcs; +extern WILC_Uint8 u8ConnectedSSID[6]; + +/*BugID_5137*/ +WILC_Uint8 g_wilc_initialized = 1; +extern linux_wlan_t *g_linux_wlan; +#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP +extern WILC_Bool g_obtainingIP; +#endif + +#define CHAN2G(_channel, _freq, _flags) { \ + .band = IEEE80211_BAND_2GHZ, \ + .center_freq = (_freq), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +/*Frequency range for channels*/ +static struct ieee80211_channel WILC_WFI_2ghz_channels[] = { + CHAN2G(1, 2412, 0), + CHAN2G(2, 2417, 0), + CHAN2G(3, 2422, 0), + CHAN2G(4, 2427, 0), + CHAN2G(5, 2432, 0), + CHAN2G(6, 2437, 0), + CHAN2G(7, 2442, 0), + CHAN2G(8, 2447, 0), + CHAN2G(9, 2452, 0), + CHAN2G(10, 2457, 0), + CHAN2G(11, 2462, 0), + CHAN2G(12, 2467, 0), + CHAN2G(13, 2472, 0), + CHAN2G(14, 2484, 0), +}; + +#define RATETAB_ENT(_rate, _hw_value, _flags) { \ + .bitrate = (_rate), \ + .hw_value = (_hw_value), \ + .flags = (_flags), \ +} + + +/* Table 6 in section 3.2.1.1 */ +static struct ieee80211_rate WILC_WFI_rates[] = { + RATETAB_ENT(10, 0, 0), + RATETAB_ENT(20, 1, 0), + RATETAB_ENT(55, 2, 0), + RATETAB_ENT(110, 3, 0), + RATETAB_ENT(60, 9, 0), + RATETAB_ENT(90, 6, 0), + RATETAB_ENT(120, 7, 0), + RATETAB_ENT(180, 8, 0), + RATETAB_ENT(240, 9, 0), + RATETAB_ENT(360, 10, 0), + RATETAB_ENT(480, 11, 0), + RATETAB_ENT(540, 12, 0), +}; + +#ifdef WILC_P2P +struct p2p_mgmt_data { + int size; + u8 *buff; +}; + +/*Global variable used to state the current connected STA channel*/ +WILC_Uint8 u8WLANChannel = INVALID_CHANNEL; + +/*BugID_5442*/ +WILC_Uint8 u8CurrChannel; + +WILC_Uint8 u8P2P_oui[] = {0x50, 0x6f, 0x9A, 0x09}; +WILC_Uint8 u8P2Plocalrandom = 0x01; +WILC_Uint8 u8P2Precvrandom = 0x00; +WILC_Uint8 u8P2P_vendorspec[] = {0xdd, 0x05, 0x00, 0x08, 0x40, 0x03}; +WILC_Bool bWilc_ie = WILC_FALSE; +#endif + +static struct ieee80211_supported_band WILC_WFI_band_2ghz = { + .channels = WILC_WFI_2ghz_channels, + .n_channels = ARRAY_SIZE(WILC_WFI_2ghz_channels), + .bitrates = WILC_WFI_rates, + .n_bitrates = ARRAY_SIZE(WILC_WFI_rates), +}; + + +/*BugID_5137*/ +struct add_key_params { + u8 key_idx; + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) + bool pairwise; + #endif + u8 *mac_addr; +}; +struct add_key_params g_add_gtk_key_params; +struct wilc_wfi_key g_key_gtk_params; +struct add_key_params g_add_ptk_key_params; +struct wilc_wfi_key g_key_ptk_params; +struct wilc_wfi_wep_key g_key_wep_params; +WILC_Uint8 g_flushing_in_progress; +WILC_Bool g_ptk_keys_saved = WILC_FALSE; +WILC_Bool g_gtk_keys_saved = WILC_FALSE; +WILC_Bool g_wep_keys_saved = WILC_FALSE; + +#define AGING_TIME (9 * 1000) +#define duringIP_TIME 15000 + +void clear_shadow_scan(void *pUserVoid) +{ + struct WILC_WFI_priv *priv; + int i; + priv = (struct WILC_WFI_priv *)pUserVoid; + if (op_ifcs == 0) { + WILC_TimerDestroy(&hAgingTimer, WILC_NULL); + PRINT_INFO(CORECONFIG_DBG, "destroy aging timer\n"); + + for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) { + if (astrLastScannedNtwrksShadow[u32LastScannedNtwrksCountShadow].pu8IEs != NULL) { + WILC_FREE(astrLastScannedNtwrksShadow[i].pu8IEs); + astrLastScannedNtwrksShadow[u32LastScannedNtwrksCountShadow].pu8IEs = NULL; + } + + host_int_freeJoinParams(astrLastScannedNtwrksShadow[i].pJoinParams); + astrLastScannedNtwrksShadow[i].pJoinParams = NULL; + } + u32LastScannedNtwrksCountShadow = 0; + } + +} + +uint32_t get_rssi_avg(tstrNetworkInfo *pstrNetworkInfo) +{ + uint8_t i; + int rssi_v = 0; + uint8_t num_rssi = (pstrNetworkInfo->strRssi.u8Full) ? NUM_RSSI : (pstrNetworkInfo->strRssi.u8Index); + + for (i = 0; i < num_rssi; i++) + rssi_v += pstrNetworkInfo->strRssi.as8RSSI[i]; + + rssi_v /= num_rssi; + return rssi_v; +} + +void refresh_scan(void *pUserVoid, uint8_t all, WILC_Bool bDirectScan) +{ + struct WILC_WFI_priv *priv; + struct wiphy *wiphy; + struct cfg80211_bss *bss = NULL; + int i; + int rssi = 0; + + priv = (struct WILC_WFI_priv *)pUserVoid; + wiphy = priv->dev->ieee80211_ptr->wiphy; + + for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) { + tstrNetworkInfo *pstrNetworkInfo; + pstrNetworkInfo = &(astrLastScannedNtwrksShadow[i]); + + + if ((!pstrNetworkInfo->u8Found) || all) { + WILC_Sint32 s32Freq; + struct ieee80211_channel *channel; + + if (pstrNetworkInfo != WILC_NULL) { + + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) + s32Freq = ieee80211_channel_to_frequency((WILC_Sint32)pstrNetworkInfo->u8channel, IEEE80211_BAND_2GHZ); + #else + s32Freq = ieee80211_channel_to_frequency((WILC_Sint32)pstrNetworkInfo->u8channel); + #endif + + channel = ieee80211_get_channel(wiphy, s32Freq); + + rssi = get_rssi_avg(pstrNetworkInfo); + if (WILC_memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7) || bDirectScan) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) + bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, pstrNetworkInfo->au8bssid, pstrNetworkInfo->u64Tsf, pstrNetworkInfo->u16CapInfo, + pstrNetworkInfo->u16BeaconPeriod, (const u8 *)pstrNetworkInfo->pu8IEs, + (size_t)pstrNetworkInfo->u16IEsLen, (((WILC_Sint32)rssi) * 100), GFP_KERNEL); +#else + bss = cfg80211_inform_bss(wiphy, channel, pstrNetworkInfo->au8bssid, pstrNetworkInfo->u64Tsf, pstrNetworkInfo->u16CapInfo, + pstrNetworkInfo->u16BeaconPeriod, (const u8 *)pstrNetworkInfo->pu8IEs, + (size_t)pstrNetworkInfo->u16IEsLen, (((WILC_Sint32)rssi) * 100), GFP_KERNEL); +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) + cfg80211_put_bss(wiphy, bss); +#else + cfg80211_put_bss(bss); +#endif + } + } + + } + } + +} + +void reset_shadow_found(void *pUserVoid) +{ + struct WILC_WFI_priv *priv; + int i; + priv = (struct WILC_WFI_priv *)pUserVoid; + for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) { + astrLastScannedNtwrksShadow[i].u8Found = 0; + + } +} + +void update_scan_time(void *pUserVoid) +{ + struct WILC_WFI_priv *priv; + int i; + priv = (struct WILC_WFI_priv *)pUserVoid; + for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) { + astrLastScannedNtwrksShadow[i].u32TimeRcvdInScan = jiffies; + } +} + +void remove_network_from_shadow(void *pUserVoid) +{ + struct WILC_WFI_priv *priv; + unsigned long now = jiffies; + int i, j; + + priv = (struct WILC_WFI_priv *)pUserVoid; + + for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) { + if (time_after(now, astrLastScannedNtwrksShadow[i].u32TimeRcvdInScan + (unsigned long)(SCAN_RESULT_EXPIRE))) { + PRINT_D(CFG80211_DBG, "Network expired in ScanShadow: %s \n", astrLastScannedNtwrksShadow[i].au8ssid); + + if (astrLastScannedNtwrksShadow[i].pu8IEs != NULL) { + WILC_FREE(astrLastScannedNtwrksShadow[i].pu8IEs); + astrLastScannedNtwrksShadow[i].pu8IEs = NULL; + } + + host_int_freeJoinParams(astrLastScannedNtwrksShadow[i].pJoinParams); + + for (j = i; (j < u32LastScannedNtwrksCountShadow - 1); j++) { + astrLastScannedNtwrksShadow[j] = astrLastScannedNtwrksShadow[j + 1]; + } + u32LastScannedNtwrksCountShadow--; + } + } + + PRINT_D(CFG80211_DBG, "Number of cached networks: %d\n", u32LastScannedNtwrksCountShadow); + if (u32LastScannedNtwrksCountShadow != 0) + WILC_TimerStart(&(hAgingTimer), AGING_TIME, pUserVoid, WILC_NULL); + else + PRINT_D(CFG80211_DBG, "No need to restart Aging timer\n"); +} + +#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP +void clear_duringIP(void *pUserVoid) +{ + PRINT_D(GENERIC_DBG, "GO:IP Obtained , enable scan\n"); + g_obtainingIP = WILC_FALSE; +} +#endif + +int8_t is_network_in_shadow(tstrNetworkInfo *pstrNetworkInfo, void *pUserVoid) +{ + struct WILC_WFI_priv *priv; + int8_t state = -1; + int i; + + priv = (struct WILC_WFI_priv *)pUserVoid; + if (u32LastScannedNtwrksCountShadow == 0) { + PRINT_D(CFG80211_DBG, "Starting Aging timer\n"); + WILC_TimerStart(&(hAgingTimer), AGING_TIME, pUserVoid, WILC_NULL); + state = -1; + } else { + /* Linear search for now */ + for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) { + if (WILC_memcmp(astrLastScannedNtwrksShadow[i].au8bssid, + pstrNetworkInfo->au8bssid, 6) == 0) { + state = i; + break; + } + } + } + return state; +} + +void add_network_to_shadow(tstrNetworkInfo *pstrNetworkInfo, void *pUserVoid, void *pJoinParams) +{ + struct WILC_WFI_priv *priv; + int8_t ap_found = is_network_in_shadow(pstrNetworkInfo, pUserVoid); + uint32_t ap_index = 0; + uint8_t rssi_index = 0; + priv = (struct WILC_WFI_priv *)pUserVoid; + + if (u32LastScannedNtwrksCountShadow >= MAX_NUM_SCANNED_NETWORKS_SHADOW) { + PRINT_D(CFG80211_DBG, "Shadow network reached its maximum limit\n"); + return; + } + if (ap_found == -1) { + ap_index = u32LastScannedNtwrksCountShadow; + u32LastScannedNtwrksCountShadow++; + + } else { + ap_index = ap_found; + } + rssi_index = astrLastScannedNtwrksShadow[ap_index].strRssi.u8Index; + astrLastScannedNtwrksShadow[ap_index].strRssi.as8RSSI[rssi_index++] = pstrNetworkInfo->s8rssi; + if (rssi_index == NUM_RSSI) { + rssi_index = 0; + astrLastScannedNtwrksShadow[ap_index].strRssi.u8Full = 1; + } + astrLastScannedNtwrksShadow[ap_index].strRssi.u8Index = rssi_index; + + astrLastScannedNtwrksShadow[ap_index].s8rssi = pstrNetworkInfo->s8rssi; + astrLastScannedNtwrksShadow[ap_index].u16CapInfo = pstrNetworkInfo->u16CapInfo; + + astrLastScannedNtwrksShadow[ap_index].u8SsidLen = pstrNetworkInfo->u8SsidLen; + WILC_memcpy(astrLastScannedNtwrksShadow[ap_index].au8ssid, + pstrNetworkInfo->au8ssid, pstrNetworkInfo->u8SsidLen); + + WILC_memcpy(astrLastScannedNtwrksShadow[ap_index].au8bssid, + pstrNetworkInfo->au8bssid, ETH_ALEN); + + astrLastScannedNtwrksShadow[ap_index].u16BeaconPeriod = pstrNetworkInfo->u16BeaconPeriod; + astrLastScannedNtwrksShadow[ap_index].u8DtimPeriod = pstrNetworkInfo->u8DtimPeriod; + astrLastScannedNtwrksShadow[ap_index].u8channel = pstrNetworkInfo->u8channel; + + astrLastScannedNtwrksShadow[ap_index].u16IEsLen = pstrNetworkInfo->u16IEsLen; + astrLastScannedNtwrksShadow[ap_index].u64Tsf = pstrNetworkInfo->u64Tsf; + if (ap_found != -1) + WILC_FREE(astrLastScannedNtwrksShadow[ap_index].pu8IEs); + astrLastScannedNtwrksShadow[ap_index].pu8IEs = + (WILC_Uint8 *)WILC_MALLOC(pstrNetworkInfo->u16IEsLen); /* will be deallocated by the WILC_WFI_CfgScan() function */ + WILC_memcpy(astrLastScannedNtwrksShadow[ap_index].pu8IEs, + pstrNetworkInfo->pu8IEs, pstrNetworkInfo->u16IEsLen); + + astrLastScannedNtwrksShadow[ap_index].u32TimeRcvdInScan = jiffies; + astrLastScannedNtwrksShadow[ap_index].u32TimeRcvdInScanCached = jiffies; + astrLastScannedNtwrksShadow[ap_index].u8Found = 1; + if (ap_found != -1) + host_int_freeJoinParams(astrLastScannedNtwrksShadow[ap_index].pJoinParams); + astrLastScannedNtwrksShadow[ap_index].pJoinParams = pJoinParams; + +} + + +/** + * @brief CfgScanResult + * @details Callback function which returns the scan results found + * + * @param[in] tenuScanEvent enuScanEvent: enum, indicating the scan event triggered, whether that is + * SCAN_EVENT_NETWORK_FOUND or SCAN_EVENT_DONE + * tstrNetworkInfo* pstrNetworkInfo: structure holding the scan results information + * void* pUserVoid: Private structure associated with the wireless interface + * @return NONE + * @author mabubakr + * @date + * @version 1.0 + */ +static void CfgScanResult(tenuScanEvent enuScanEvent, tstrNetworkInfo *pstrNetworkInfo, void *pUserVoid, void *pJoinParams) +{ + struct WILC_WFI_priv *priv; + struct wiphy *wiphy; + WILC_Sint32 s32Freq; + struct ieee80211_channel *channel; + WILC_Sint32 s32Error = WILC_SUCCESS; + struct cfg80211_bss *bss = NULL; + + priv = (struct WILC_WFI_priv *)pUserVoid; + if (priv->bCfgScanning == WILC_TRUE) { + if (enuScanEvent == SCAN_EVENT_NETWORK_FOUND) { + wiphy = priv->dev->ieee80211_ptr->wiphy; + WILC_NULLCHECK(s32Error, wiphy); + if (wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC + && + ((((WILC_Sint32)pstrNetworkInfo->s8rssi) * 100) < 0 + || + (((WILC_Sint32)pstrNetworkInfo->s8rssi) * 100) > 100) + ) { + WILC_ERRORREPORT(s32Error, WILC_FAIL); + } + + if (pstrNetworkInfo != WILC_NULL) { + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) + s32Freq = ieee80211_channel_to_frequency((WILC_Sint32)pstrNetworkInfo->u8channel, IEEE80211_BAND_2GHZ); + #else + s32Freq = ieee80211_channel_to_frequency((WILC_Sint32)pstrNetworkInfo->u8channel); + #endif + channel = ieee80211_get_channel(wiphy, s32Freq); + + WILC_NULLCHECK(s32Error, channel); + + PRINT_INFO(CFG80211_DBG, "Network Info:: CHANNEL Frequency: %d, RSSI: %d, CapabilityInfo: %d," + "BeaconPeriod: %d \n", channel->center_freq, (((WILC_Sint32)pstrNetworkInfo->s8rssi) * 100), + pstrNetworkInfo->u16CapInfo, pstrNetworkInfo->u16BeaconPeriod); + + if (pstrNetworkInfo->bNewNetwork == WILC_TRUE) { + if (priv->u32RcvdChCount < MAX_NUM_SCANNED_NETWORKS) { /* TODO: mostafa: to be replaced by */ + /* max_scan_ssids */ + PRINT_D(CFG80211_DBG, "Network %s found\n", pstrNetworkInfo->au8ssid); + + + priv->u32RcvdChCount++; + + + + if (pJoinParams == NULL) { + PRINT_INFO(CORECONFIG_DBG, ">> Something really bad happened\n"); + } + add_network_to_shadow(pstrNetworkInfo, priv, pJoinParams); + + /*P2P peers are sent to WPA supplicant and added to shadow table*/ + + if (!(WILC_memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7))) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) + bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, pstrNetworkInfo->au8bssid, pstrNetworkInfo->u64Tsf, pstrNetworkInfo->u16CapInfo, + pstrNetworkInfo->u16BeaconPeriod, (const u8 *)pstrNetworkInfo->pu8IEs, + (size_t)pstrNetworkInfo->u16IEsLen, (((WILC_Sint32)pstrNetworkInfo->s8rssi) * 100), GFP_KERNEL); +#else + bss = cfg80211_inform_bss(wiphy, channel, pstrNetworkInfo->au8bssid, pstrNetworkInfo->u64Tsf, pstrNetworkInfo->u16CapInfo, + pstrNetworkInfo->u16BeaconPeriod, (const u8 *)pstrNetworkInfo->pu8IEs, + (size_t)pstrNetworkInfo->u16IEsLen, (((WILC_Sint32)pstrNetworkInfo->s8rssi) * 100), GFP_KERNEL); +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) + cfg80211_put_bss(wiphy, bss); +#else + cfg80211_put_bss(bss); +#endif + } + + + } else { + PRINT_ER("Discovered networks exceeded the max limit\n"); + } + } else { + WILC_Uint32 i; + /* So this network is discovered before, we'll just update its RSSI */ + for (i = 0; i < priv->u32RcvdChCount; i++) { + if (WILC_memcmp(astrLastScannedNtwrksShadow[i].au8bssid, pstrNetworkInfo->au8bssid, 6) == 0) { + PRINT_D(CFG80211_DBG, "Update RSSI of %s \n", astrLastScannedNtwrksShadow[i].au8ssid); + + astrLastScannedNtwrksShadow[i].s8rssi = pstrNetworkInfo->s8rssi; + astrLastScannedNtwrksShadow[i].u32TimeRcvdInScan = jiffies; + break; + } + } + } + } + } else if (enuScanEvent == SCAN_EVENT_DONE) { + PRINT_D(CFG80211_DBG, "Scan Done[%p] \n", priv->dev); + PRINT_D(CFG80211_DBG, "Refreshing Scan ... \n"); + refresh_scan(priv, 1, WILC_FALSE); + + if (priv->u32RcvdChCount > 0) { + PRINT_D(CFG80211_DBG, "%d Network(s) found \n", priv->u32RcvdChCount); + } else { + PRINT_D(CFG80211_DBG, "No networks found \n"); + } + + WILC_SemaphoreAcquire(&(priv->hSemScanReq), NULL); + + if (priv->pstrScanReq != WILC_NULL) { + cfg80211_scan_done(priv->pstrScanReq, WILC_FALSE); + priv->u32RcvdChCount = 0; + priv->bCfgScanning = WILC_FALSE; + priv->pstrScanReq = WILC_NULL; + } + WILC_SemaphoreRelease(&(priv->hSemScanReq), NULL); + + } + /*Aborting any scan operation during mac close*/ + else if (enuScanEvent == SCAN_EVENT_ABORTED) { + WILC_SemaphoreAcquire(&(priv->hSemScanReq), NULL); + + PRINT_D(CFG80211_DBG, "Scan Aborted \n"); + if (priv->pstrScanReq != WILC_NULL) { + + update_scan_time(priv); + refresh_scan(priv, 1, WILC_FALSE); + + cfg80211_scan_done(priv->pstrScanReq, WILC_FALSE); + priv->bCfgScanning = WILC_FALSE; + priv->pstrScanReq = WILC_NULL; + } + WILC_SemaphoreRelease(&(priv->hSemScanReq), NULL); + } + } + + + WILC_CATCH(s32Error) + { + } +} + + +/** + * @brief WILC_WFI_Set_PMKSA + * @details Check if pmksa is cached and set it. + * @param[in] + * @return int : Return 0 on Success + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +int WILC_WFI_Set_PMKSA(WILC_Uint8 *bssid, struct WILC_WFI_priv *priv) +{ + WILC_Uint32 i; + WILC_Sint32 s32Error = WILC_SUCCESS; + + + for (i = 0; i < priv->pmkid_list.numpmkid; i++) { + + if (!WILC_memcmp(bssid, priv->pmkid_list.pmkidlist[i].bssid, + ETH_ALEN)) { + PRINT_D(CFG80211_DBG, "PMKID successful comparison"); + + /*If bssid is found, set the values*/ + s32Error = host_int_set_pmkid_info(priv->hWILCWFIDrv, &priv->pmkid_list); + + if (s32Error != WILC_SUCCESS) + PRINT_ER("Error in pmkid\n"); + + break; + } + } + + return s32Error; + + +} +int linux_wlan_set_bssid(struct net_device *wilc_netdev, uint8_t *pBSSID); + + +/** + * @brief CfgConnectResult + * @details + * @param[in] tenuConnDisconnEvent enuConnDisconnEvent: Type of connection response either + * connection response or disconnection notification. + * tstrConnectInfo* pstrConnectInfo: COnnection information. + * WILC_Uint8 u8MacStatus: Mac Status from firmware + * tstrDisconnectNotifInfo* pstrDisconnectNotifInfo: Disconnection Notification + * void* pUserVoid: Private data associated with wireless interface + * @return NONE + * @author mabubakr + * @date 01 MAR 2012 + * @version 1.0 + */ +int connecting; + +static void CfgConnectResult(tenuConnDisconnEvent enuConnDisconnEvent, + tstrConnectInfo *pstrConnectInfo, + WILC_Uint8 u8MacStatus, + tstrDisconnectNotifInfo *pstrDisconnectNotifInfo, + void *pUserVoid) +{ + struct WILC_WFI_priv *priv; + struct net_device *dev; + #ifdef WILC_P2P + tstrWILC_WFIDrv *pstrWFIDrv; + #endif + WILC_Uint8 NullBssid[ETH_ALEN] = {0}; + connecting = 0; + + priv = (struct WILC_WFI_priv *)pUserVoid; + dev = priv->dev; + #ifdef WILC_P2P + pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv; + #endif + + if (enuConnDisconnEvent == CONN_DISCONN_EVENT_CONN_RESP) { + /*Initialization*/ + WILC_Uint16 u16ConnectStatus = WLAN_STATUS_SUCCESS; + + u16ConnectStatus = pstrConnectInfo->u16ConnectStatus; + + PRINT_D(CFG80211_DBG, " Connection response received = %d\n", u8MacStatus); + + if ((u8MacStatus == MAC_DISCONNECTED) && + (pstrConnectInfo->u16ConnectStatus == SUCCESSFUL_STATUSCODE)) { + /* The case here is that our station was waiting for association response frame and has just received it containing status code + * = SUCCESSFUL_STATUSCODE, while mac status is MAC_DISCONNECTED (which means something wrong happened) */ + u16ConnectStatus = WLAN_STATUS_UNSPECIFIED_FAILURE; + linux_wlan_set_bssid(priv->dev, NullBssid); + WILC_memset(u8ConnectedSSID, 0, ETH_ALEN); + + /*BugID_5457*/ + /*Invalidate u8WLANChannel value on wlan0 disconnect*/ + #ifdef WILC_P2P + if (!pstrWFIDrv->u8P2PConnect) + u8WLANChannel = INVALID_CHANNEL; + #endif + + PRINT_ER("Unspecified failure: Connection status %d : MAC status = %d \n", u16ConnectStatus, u8MacStatus); + } + + if (u16ConnectStatus == WLAN_STATUS_SUCCESS) { + WILC_Bool bNeedScanRefresh = WILC_FALSE; + WILC_Uint32 i; + + PRINT_INFO(CFG80211_DBG, "Connection Successful:: BSSID: %x%x%x%x%x%x\n", pstrConnectInfo->au8bssid[0], + pstrConnectInfo->au8bssid[1], pstrConnectInfo->au8bssid[2], pstrConnectInfo->au8bssid[3], pstrConnectInfo->au8bssid[4], pstrConnectInfo->au8bssid[5]); + WILC_memcpy(priv->au8AssociatedBss, pstrConnectInfo->au8bssid, ETH_ALEN); + + /* set bssid in frame filter */ + /* linux_wlan_set_bssid(dev,pstrConnectInfo->au8bssid); */ + + /* BugID_4209: if this network has expired in the scan results in the above nl80211 layer, refresh them here by calling + * cfg80211_inform_bss() with the last Scan results before calling cfg80211_connect_result() to avoid + * Linux kernel warning generated at the nl80211 layer */ + + for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) { + if (WILC_memcmp(astrLastScannedNtwrksShadow[i].au8bssid, + pstrConnectInfo->au8bssid, ETH_ALEN) == 0) { + unsigned long now = jiffies; + + if (time_after(now, + astrLastScannedNtwrksShadow[i].u32TimeRcvdInScanCached + (unsigned long)(nl80211_SCAN_RESULT_EXPIRE - (1 * HZ)))) { + bNeedScanRefresh = WILC_TRUE; + } + + break; + } + } + + if (bNeedScanRefresh == WILC_TRUE) { + /* RefreshScanResult(priv); */ + /*BugID_5418*/ + /*Also, refrsh DIRECT- results if */ + refresh_scan(priv, 1, WILC_TRUE); + + } + + } + + + PRINT_D(CFG80211_DBG, "Association request info elements length = %d\n", pstrConnectInfo->ReqIEsLen); + + PRINT_D(CFG80211_DBG, "Association response info elements length = %d\n", pstrConnectInfo->u16RespIEsLen); + + cfg80211_connect_result(dev, pstrConnectInfo->au8bssid, + pstrConnectInfo->pu8ReqIEs, pstrConnectInfo->ReqIEsLen, + pstrConnectInfo->pu8RespIEs, pstrConnectInfo->u16RespIEsLen, + u16ConnectStatus, GFP_KERNEL); /* TODO: mostafa: u16ConnectStatus to */ + /* be replaced by pstrConnectInfo->u16ConnectStatus */ + } else if (enuConnDisconnEvent == CONN_DISCONN_EVENT_DISCONN_NOTIF) { + #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP + g_obtainingIP = WILC_FALSE; + #endif + PRINT_ER("Received MAC_DISCONNECTED from firmware with reason %d on dev [%p]\n", + pstrDisconnectNotifInfo->u16reason, priv->dev); + u8P2Plocalrandom = 0x01; + u8P2Precvrandom = 0x00; + bWilc_ie = WILC_FALSE; + WILC_memset(priv->au8AssociatedBss, 0, ETH_ALEN); + linux_wlan_set_bssid(priv->dev, NullBssid); + WILC_memset(u8ConnectedSSID, 0, ETH_ALEN); + + /*BugID_5457*/ + /*Invalidate u8WLANChannel value on wlan0 disconnect*/ + #ifdef WILC_P2P + if (!pstrWFIDrv->u8P2PConnect) + u8WLANChannel = INVALID_CHANNEL; + #endif + /*BugID_5315*/ + /*Incase "P2P CLIENT Connected" send deauthentication reason by 3 to force the WPA_SUPPLICANT to directly change + * virtual interface to station*/ + if ((pstrWFIDrv->IFC_UP) && (dev == g_linux_wlan->strInterfaceInfo[1].wilc_netdev)) { + pstrDisconnectNotifInfo->u16reason = 3; + } + /*BugID_5315*/ + /*Incase "P2P CLIENT during connection(not connected)" send deauthentication reason by 1 to force the WPA_SUPPLICANT + * to scan again and retry the connection*/ + else if ((!pstrWFIDrv->IFC_UP) && (dev == g_linux_wlan->strInterfaceInfo[1].wilc_netdev)) { + pstrDisconnectNotifInfo->u16reason = 1; + } + cfg80211_disconnected(dev, pstrDisconnectNotifInfo->u16reason, pstrDisconnectNotifInfo->ie, + pstrDisconnectNotifInfo->ie_len, GFP_KERNEL); + + } + +} + + +/** + * @brief WILC_WFI_CfgSetChannel + * @details Set channel for a given wireless interface. Some devices + * may support multi-channel operation (by channel hopping) so cfg80211 + * doesn't verify much. Note, however, that the passed netdev may be + * %NULL as well if the user requested changing the channel for the + * device itself, or for a monitor interface. + * @param[in] + * @return int : Return 0 on Success + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) +/* + * struct changed from v3.8.0 + * tony, sswd, WILC-KR, 2013-10-29 + * struct cfg80211_chan_def { + * struct ieee80211_channel *chan; + * enum nl80211_chan_width width; + * u32 center_freq1; + * u32 center_freq2; + * }; + */ +static int WILC_WFI_CfgSetChannel(struct wiphy *wiphy, + struct cfg80211_chan_def *chandef) +#else +static int WILC_WFI_CfgSetChannel(struct wiphy *wiphy, + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32) + struct net_device *netdev, + #endif + struct ieee80211_channel *channel, + enum nl80211_channel_type channel_type) +#endif +{ + + WILC_Uint32 channelnum = 0; + struct WILC_WFI_priv *priv; + WILC_Sint32 s32Error = WILC_SUCCESS; + priv = wiphy_priv(wiphy); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) /* tony for v3.8.0 support */ + channelnum = ieee80211_frequency_to_channel(chandef->chan->center_freq); + PRINT_D(CFG80211_DBG, "Setting channel %d with frequency %d\n", channelnum, chandef->chan->center_freq); +#else + channelnum = ieee80211_frequency_to_channel(channel->center_freq); + + PRINT_D(CFG80211_DBG, "Setting channel %d with frequency %d\n", channelnum, channel->center_freq); +#endif + + u8CurrChannel = channelnum; + s32Error = host_int_set_mac_chnl_num(priv->hWILCWFIDrv, channelnum); + + if (s32Error != WILC_SUCCESS) + PRINT_ER("Error in setting channel %d\n", channelnum); + + return s32Error; +} + +/** + * @brief WILC_WFI_CfgScan + * @details Request to do a scan. If returning zero, the scan request is given + * the driver, and will be valid until passed to cfg80211_scan_done(). + * For scan results, call cfg80211_inform_bss(); you can call this outside + * the scan/scan_done bracket too. + * @param[in] + * @return int : Return 0 on Success + * @author mabubakr + * @date 01 MAR 2012 + * @version 1.0 + */ + +/* + * kernel version 3.8.8 supported + * tony, sswd, WILC-KR, 2013-10-29 + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) +static int WILC_WFI_CfgScan(struct wiphy *wiphy, struct cfg80211_scan_request *request) +#else +static int WILC_WFI_CfgScan(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_scan_request *request) +#endif +{ + struct WILC_WFI_priv *priv; + WILC_Uint32 i; + WILC_Sint32 s32Error = WILC_SUCCESS; + WILC_Uint8 au8ScanChanList[MAX_NUM_SCANNED_NETWORKS]; + tstrHiddenNetwork strHiddenNetwork; + + priv = wiphy_priv(wiphy); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) + PRINT_D(CORECONFIG_DBG, "Scan on netdev [%p] host if [%x]\n", dev, (WILC_Uint32)priv->hWILCWFIDrv); +#endif + + /*if(connecting) + * return -EBUSY; */ + + /*BugID_4800: if in AP mode, return.*/ + /*This check is to handle the situation when user*/ + /*requests "create group" during a running scan*/ + /* host_int_set_wfi_drv_handler(priv->hWILCWFIDrv); */ +#if 0 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) /* tony for v3.8.0 support */ + if (priv->dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) { + PRINT_D(GENERIC_DBG, "Required scan while in AP mode"); + return s32Error; + } +#else + if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) { + PRINT_D(GENERIC_DBG, "Required scan while in AP mode"); + s32Error = WILC_BUSY; + return s32Error; + } +#endif +#endif /* end of if 0 */ + priv->pstrScanReq = request; + + priv->u32RcvdChCount = 0; + + host_int_set_wfi_drv_handler((WILC_Uint32)priv->hWILCWFIDrv); + + + reset_shadow_found(priv); + + priv->bCfgScanning = WILC_TRUE; + if (request->n_channels <= MAX_NUM_SCANNED_NETWORKS) { /* TODO: mostafa: to be replaced by */ + /* max_scan_ssids */ + for (i = 0; i < request->n_channels; i++) { + au8ScanChanList[i] = (WILC_Uint8)ieee80211_frequency_to_channel(request->channels[i]->center_freq); + PRINT_INFO(CFG80211_DBG, "ScanChannel List[%d] = %d,", i, au8ScanChanList[i]); + } + + PRINT_D(CFG80211_DBG, "Requested num of scan channel %d\n", request->n_channels); + PRINT_D(CFG80211_DBG, "Scan Request IE len = %d\n", request->ie_len); + + PRINT_D(CFG80211_DBG, "Number of SSIDs %d\n", request->n_ssids); + + if (request->n_ssids >= 1) { + + + strHiddenNetwork.pstrHiddenNetworkInfo = WILC_MALLOC(request->n_ssids * sizeof(tstrHiddenNetwork)); + strHiddenNetwork.u8ssidnum = request->n_ssids; + + + /*BugID_4156*/ + for (i = 0; i < request->n_ssids; i++) { + + if (request->ssids[i].ssid != NULL && request->ssids[i].ssid_len != 0) { + strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid = WILC_MALLOC(request->ssids[i].ssid_len); + WILC_memcpy(strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid, request->ssids[i].ssid, request->ssids[i].ssid_len); + strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen = request->ssids[i].ssid_len; + } else { + PRINT_D(CFG80211_DBG, "Received one NULL SSID \n"); + strHiddenNetwork.u8ssidnum -= 1; + } + } + PRINT_D(CFG80211_DBG, "Trigger Scan Request \n"); + s32Error = host_int_scan(priv->hWILCWFIDrv, USER_SCAN, ACTIVE_SCAN, + au8ScanChanList, request->n_channels, + (const WILC_Uint8 *)request->ie, request->ie_len, + CfgScanResult, (void *)priv, &strHiddenNetwork); + } else { + PRINT_D(CFG80211_DBG, "Trigger Scan Request \n"); + s32Error = host_int_scan(priv->hWILCWFIDrv, USER_SCAN, ACTIVE_SCAN, + au8ScanChanList, request->n_channels, + (const WILC_Uint8 *)request->ie, request->ie_len, + CfgScanResult, (void *)priv, NULL); + } + + } else { + PRINT_ER("Requested num of scanned channels is greater than the max, supported" + " channels \n"); + } + + if (s32Error != WILC_SUCCESS) { + s32Error = -EBUSY; + PRINT_WRN(CFG80211_DBG, "Device is busy: Error(%d)\n", s32Error); + } + + return s32Error; +} + +/** + * @brief WILC_WFI_CfgConnect + * @details Connect to the ESS with the specified parameters. When connected, + * call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS. + * If the connection fails for some reason, call cfg80211_connect_result() + * with the status from the AP. + * @param[in] + * @return int : Return 0 on Success + * @author mabubakr + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_CfgConnect(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_connect_params *sme) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + WILC_Uint32 i; + /* SECURITY_T tenuSecurity_t = NO_SECURITY; */ + WILC_Uint8 u8security = NO_ENCRYPT; + AUTHTYPE_T tenuAuth_type = ANY; + WILC_Char *pcgroup_encrypt_val; + WILC_Char *pccipher_group; + WILC_Char *pcwpa_version; + + struct WILC_WFI_priv *priv; + tstrWILC_WFIDrv *pstrWFIDrv; + tstrNetworkInfo *pstrNetworkInfo = NULL; + + + connecting = 1; + priv = wiphy_priv(wiphy); + pstrWFIDrv = (tstrWILC_WFIDrv *)(priv->hWILCWFIDrv); + + host_int_set_wfi_drv_handler((WILC_Uint32)priv->hWILCWFIDrv); + + /* host_int_set_wfi_drv_handler((WILC_Uint32)priv->hWILCWFIDrv); */ + PRINT_D(CFG80211_DBG, "Connecting to SSID [%s] on netdev [%p] host if [%x]\n", sme->ssid, dev, (WILC_Uint32)priv->hWILCWFIDrv); + #ifdef WILC_P2P + if (!(WILC_strncmp(sme->ssid, "DIRECT-", 7))) { + PRINT_D(CFG80211_DBG, "Connected to Direct network,OBSS disabled\n"); + pstrWFIDrv->u8P2PConnect = 1; + } else + pstrWFIDrv->u8P2PConnect = 0; + #endif + PRINT_INFO(CFG80211_DBG, "Required SSID = %s\n , AuthType = %d \n", sme->ssid, sme->auth_type); + + for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) { + if ((sme->ssid_len == astrLastScannedNtwrksShadow[i].u8SsidLen) && + WILC_memcmp(astrLastScannedNtwrksShadow[i].au8ssid, + sme->ssid, + sme->ssid_len) == 0) { + PRINT_INFO(CFG80211_DBG, "Network with required SSID is found %s\n", sme->ssid); + if (sme->bssid == NULL) { + /* BSSID is not passed from the user, so decision of matching + * is done by SSID only */ + PRINT_INFO(CFG80211_DBG, "BSSID is not passed from the user\n"); + break; + } else { + /* BSSID is also passed from the user, so decision of matching + * should consider also this passed BSSID */ + if (WILC_memcmp(astrLastScannedNtwrksShadow[i].au8bssid, + sme->bssid, + ETH_ALEN) == 0) { + PRINT_INFO(CFG80211_DBG, "BSSID is passed from the user and matched\n"); + break; + } + } + } + } + + if (i < u32LastScannedNtwrksCountShadow) { + PRINT_D(CFG80211_DBG, "Required bss is in scan results\n"); + + pstrNetworkInfo = &(astrLastScannedNtwrksShadow[i]); + + PRINT_INFO(CFG80211_DBG, "network BSSID to be associated: %x%x%x%x%x%x\n", + pstrNetworkInfo->au8bssid[0], pstrNetworkInfo->au8bssid[1], + pstrNetworkInfo->au8bssid[2], pstrNetworkInfo->au8bssid[3], + pstrNetworkInfo->au8bssid[4], pstrNetworkInfo->au8bssid[5]); + } else { + s32Error = -ENOENT; + if (u32LastScannedNtwrksCountShadow == 0) + PRINT_D(CFG80211_DBG, "No Scan results yet\n"); + else + PRINT_D(CFG80211_DBG, "Required bss not in scan results: Error(%d)\n", s32Error); + + goto done; + } + + priv->WILC_WFI_wep_default = 0; + WILC_memset(priv->WILC_WFI_wep_key, 0, sizeof(priv->WILC_WFI_wep_key)); + WILC_memset(priv->WILC_WFI_wep_key_len, 0, sizeof(priv->WILC_WFI_wep_key_len)); + + PRINT_INFO(CFG80211_DBG, "sme->crypto.wpa_versions=%x\n", sme->crypto.wpa_versions); + PRINT_INFO(CFG80211_DBG, "sme->crypto.cipher_group=%x\n", sme->crypto.cipher_group); + + PRINT_INFO(CFG80211_DBG, "sme->crypto.n_ciphers_pairwise=%d\n", sme->crypto.n_ciphers_pairwise); + + if (INFO) { + for (i = 0; i < sme->crypto.n_ciphers_pairwise; i++) + PRINT_D(CORECONFIG_DBG, "sme->crypto.ciphers_pairwise[%d]=%x\n", i, sme->crypto.ciphers_pairwise[i]); + } + + if (sme->crypto.cipher_group != NO_ENCRYPT) { + /* To determine the u8security value, first we check the group cipher suite then {in case of WPA or WPA2} + * we will add to it the pairwise cipher suite(s) */ + pcwpa_version = "Default"; + PRINT_D(CORECONFIG_DBG, ">> sme->crypto.wpa_versions: %x\n", sme->crypto.wpa_versions); + /* case NL80211_WPA_VERSION_1: */ + if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) { + /* tenuSecurity_t = WEP_40; */ + u8security = ENCRYPT_ENABLED | WEP; + pcgroup_encrypt_val = "WEP40"; + pccipher_group = "WLAN_CIPHER_SUITE_WEP40"; + PRINT_INFO(CFG80211_DBG, "WEP Default Key Idx = %d\n", sme->key_idx); + + if (INFO) { + for (i = 0; i < sme->key_len; i++) + PRINT_D(CORECONFIG_DBG, "WEP Key Value[%d] = %d\n", i, sme->key[i]); + } + priv->WILC_WFI_wep_default = sme->key_idx; + priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len; + WILC_memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len); + + /*BugID_5137*/ + g_key_wep_params.key_len = sme->key_len; + g_key_wep_params.key = WILC_MALLOC(sme->key_len); + memcpy(g_key_wep_params.key, sme->key, sme->key_len); + g_key_wep_params.key_idx = sme->key_idx; + g_wep_keys_saved = WILC_TRUE; + + host_int_set_WEPDefaultKeyID(priv->hWILCWFIDrv, sme->key_idx); + host_int_add_wep_key_bss_sta(priv->hWILCWFIDrv, sme->key, sme->key_len, sme->key_idx); + } else if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104) { + /* tenuSecurity_t = WEP_104; */ + u8security = ENCRYPT_ENABLED | WEP | WEP_EXTENDED; + pcgroup_encrypt_val = "WEP104"; + pccipher_group = "WLAN_CIPHER_SUITE_WEP104"; + + priv->WILC_WFI_wep_default = sme->key_idx; + priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len; + WILC_memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len); + + /*BugID_5137*/ + g_key_wep_params.key_len = sme->key_len; + g_key_wep_params.key = WILC_MALLOC(sme->key_len); + memcpy(g_key_wep_params.key, sme->key, sme->key_len); + g_key_wep_params.key_idx = sme->key_idx; + g_wep_keys_saved = WILC_TRUE; + + host_int_set_WEPDefaultKeyID(priv->hWILCWFIDrv, sme->key_idx); + host_int_add_wep_key_bss_sta(priv->hWILCWFIDrv, sme->key, sme->key_len, sme->key_idx); + } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) { + /* case NL80211_WPA_VERSION_2: */ + if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP) { + /* tenuSecurity_t = WPA2_TKIP; */ + u8security = ENCRYPT_ENABLED | WPA2 | TKIP; + pcgroup_encrypt_val = "WPA2_TKIP"; + pccipher_group = "TKIP"; + } else { /* TODO: mostafa: here we assume that any other encryption type is AES */ + /* tenuSecurity_t = WPA2_AES; */ + u8security = ENCRYPT_ENABLED | WPA2 | AES; + pcgroup_encrypt_val = "WPA2_AES"; + pccipher_group = "AES"; + } + pcwpa_version = "WPA_VERSION_2"; + } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) { + if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP) { + /* tenuSecurity_t = WPA_TKIP; */ + u8security = ENCRYPT_ENABLED | WPA | TKIP; + pcgroup_encrypt_val = "WPA_TKIP"; + pccipher_group = "TKIP"; + } else { /* TODO: mostafa: here we assume that any other encryption type is AES */ + /* tenuSecurity_t = WPA_AES; */ + u8security = ENCRYPT_ENABLED | WPA | AES; + pcgroup_encrypt_val = "WPA_AES"; + pccipher_group = "AES"; + + } + pcwpa_version = "WPA_VERSION_1"; + + /* break; */ + } else { + s32Error = -ENOTSUPP; + PRINT_ER("Not supported cipher: Error(%d)\n", s32Error); + + goto done; + } + + } + + /* After we set the u8security value from checking the group cipher suite, {in case of WPA or WPA2} we will + * add to it the pairwise cipher suite(s) */ + if ((sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) + || (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)) { + for (i = 0; i < sme->crypto.n_ciphers_pairwise; i++) { + if (sme->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP) { + u8security = u8security | TKIP; + } else { /* TODO: mostafa: here we assume that any other encryption type is AES */ + u8security = u8security | AES; + } + } + } + + PRINT_D(CFG80211_DBG, "Adding key with cipher group = %x\n", sme->crypto.cipher_group); + + PRINT_D(CFG80211_DBG, "Authentication Type = %d\n", sme->auth_type); + switch (sme->auth_type) { + case NL80211_AUTHTYPE_OPEN_SYSTEM: + PRINT_D(CFG80211_DBG, "In OPEN SYSTEM\n"); + tenuAuth_type = OPEN_SYSTEM; + break; + + case NL80211_AUTHTYPE_SHARED_KEY: + tenuAuth_type = SHARED_KEY; + PRINT_D(CFG80211_DBG, "In SHARED KEY\n"); + break; + + default: + PRINT_D(CFG80211_DBG, "Automatic Authentation type = %d\n", sme->auth_type); + } + + + /* ai: key_mgmt: enterprise case */ + if (sme->crypto.n_akm_suites) { + switch (sme->crypto.akm_suites[0]) { + case WLAN_AKM_SUITE_8021X: + tenuAuth_type = IEEE8021; + break; + + default: + break; + } + } + + + PRINT_INFO(CFG80211_DBG, "Required Channel = %d\n", pstrNetworkInfo->u8channel); + + PRINT_INFO(CFG80211_DBG, "Group encryption value = %s\n Cipher Group = %s\n WPA version = %s\n", + pcgroup_encrypt_val, pccipher_group, pcwpa_version); + + /*BugID_5442*/ + u8CurrChannel = pstrNetworkInfo->u8channel; + + if (!pstrWFIDrv->u8P2PConnect) { + u8WLANChannel = pstrNetworkInfo->u8channel; + } + + linux_wlan_set_bssid(dev, pstrNetworkInfo->au8bssid); + + s32Error = host_int_set_join_req(priv->hWILCWFIDrv, pstrNetworkInfo->au8bssid, sme->ssid, + sme->ssid_len, sme->ie, sme->ie_len, + CfgConnectResult, (void *)priv, u8security, + tenuAuth_type, pstrNetworkInfo->u8channel, + pstrNetworkInfo->pJoinParams); + if (s32Error != WILC_SUCCESS) { + PRINT_ER("host_int_set_join_req(): Error(%d) \n", s32Error); + s32Error = -ENOENT; + goto done; + } + +done: + + return s32Error; +} + + +/** + * @brief WILC_WFI_disconnect + * @details Disconnect from the BSS/ESS. + * @param[in] + * @return int : Return 0 on Success + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + struct WILC_WFI_priv *priv; + #ifdef WILC_P2P + tstrWILC_WFIDrv *pstrWFIDrv; + #endif + uint8_t NullBssid[ETH_ALEN] = {0}; + connecting = 0; + priv = wiphy_priv(wiphy); + + /*BugID_5457*/ + /*Invalidate u8WLANChannel value on wlan0 disconnect*/ + #ifdef WILC_P2P + pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv; + if (!pstrWFIDrv->u8P2PConnect) + u8WLANChannel = INVALID_CHANNEL; + #endif + linux_wlan_set_bssid(priv->dev, NullBssid); + + PRINT_D(CFG80211_DBG, "Disconnecting with reason code(%d)\n", reason_code); + + u8P2Plocalrandom = 0x01; + u8P2Precvrandom = 0x00; + bWilc_ie = WILC_FALSE; + #ifdef WILC_P2P + pstrWFIDrv->u64P2p_MgmtTimeout = 0; + #endif + + s32Error = host_int_disconnect(priv->hWILCWFIDrv, reason_code); + if (s32Error != WILC_SUCCESS) { + PRINT_ER("Error in disconnecting: Error(%d)\n", s32Error); + s32Error = -EINVAL; + } + + return s32Error; +} + +/** + * @brief WILC_WFI_add_key + * @details Add a key with the given parameters. @mac_addr will be %NULL + * when adding a group key. + * @param[in] key : key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key, 8-byte Rx Mic Key + * @return int : Return 0 on Success + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) + bool pairwise, + #endif + const u8 *mac_addr, struct key_params *params) + +{ + WILC_Sint32 s32Error = WILC_SUCCESS, KeyLen = params->key_len; + WILC_Uint32 i; + struct WILC_WFI_priv *priv; + WILC_Uint8 *pu8RxMic = NULL; + WILC_Uint8 *pu8TxMic = NULL; + WILC_Uint8 u8mode = NO_ENCRYPT; + #ifdef WILC_AP_EXTERNAL_MLME + WILC_Uint8 u8gmode = NO_ENCRYPT; + WILC_Uint8 u8pmode = NO_ENCRYPT; + AUTHTYPE_T tenuAuth_type = ANY; + #endif + + priv = wiphy_priv(wiphy); + + PRINT_D(CFG80211_DBG, "Adding key with cipher suite = %x\n", params->cipher); + + /*BugID_5137*/ + PRINT_D(CFG80211_DBG, "%x %x %d\n", (WILC_Uint32)wiphy, (WILC_Uint32)netdev, key_index); + + PRINT_D(CFG80211_DBG, "key %x %x %x\n", params->key[0], + params->key[1], + params->key[2]); + + + switch (params->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + #ifdef WILC_AP_EXTERNAL_MLME + if (priv->wdev->iftype == NL80211_IFTYPE_AP) { + + priv->WILC_WFI_wep_default = key_index; + priv->WILC_WFI_wep_key_len[key_index] = params->key_len; + WILC_memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len); + + PRINT_D(CFG80211_DBG, "Adding AP WEP Default key Idx = %d\n", key_index); + PRINT_D(CFG80211_DBG, "Adding AP WEP Key len= %d\n", params->key_len); + + for (i = 0; i < params->key_len; i++) + PRINT_D(CFG80211_DBG, "WEP AP key val[%d] = %x\n", i, params->key[i]); + + tenuAuth_type = OPEN_SYSTEM; + + if (params->cipher == WLAN_CIPHER_SUITE_WEP40) + u8mode = ENCRYPT_ENABLED | WEP; + else + u8mode = ENCRYPT_ENABLED | WEP | WEP_EXTENDED; + + host_int_add_wep_key_bss_ap(priv->hWILCWFIDrv, params->key, params->key_len, key_index, u8mode, tenuAuth_type); + break; + } + #endif + if (WILC_memcmp(params->key, priv->WILC_WFI_wep_key[key_index], params->key_len)) { + priv->WILC_WFI_wep_default = key_index; + priv->WILC_WFI_wep_key_len[key_index] = params->key_len; + WILC_memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len); + + PRINT_D(CFG80211_DBG, "Adding WEP Default key Idx = %d\n", key_index); + PRINT_D(CFG80211_DBG, "Adding WEP Key length = %d\n", params->key_len); + if (INFO) { + for (i = 0; i < params->key_len; i++) + PRINT_INFO(CFG80211_DBG, "WEP key value[%d] = %d\n", i, params->key[i]); + } + host_int_add_wep_key_bss_sta(priv->hWILCWFIDrv, params->key, params->key_len, key_index); + } + + break; + + case WLAN_CIPHER_SUITE_TKIP: + case WLAN_CIPHER_SUITE_CCMP: + #ifdef WILC_AP_EXTERNAL_MLME + if (priv->wdev->iftype == NL80211_IFTYPE_AP || priv->wdev->iftype == NL80211_IFTYPE_P2P_GO) { + + if (priv->wilc_gtk[key_index] == NULL) { + priv->wilc_gtk[key_index] = (struct wilc_wfi_key *)WILC_MALLOC(sizeof(struct wilc_wfi_key)); + priv->wilc_gtk[key_index]->key = WILC_NULL; + priv->wilc_gtk[key_index]->seq = WILC_NULL; + + } + if (priv->wilc_ptk[key_index] == NULL) { + priv->wilc_ptk[key_index] = (struct wilc_wfi_key *)WILC_MALLOC(sizeof(struct wilc_wfi_key)); + priv->wilc_ptk[key_index]->key = WILC_NULL; + priv->wilc_ptk[key_index]->seq = WILC_NULL; + } + + + + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) + if (!pairwise) + #else + if (!mac_addr || is_broadcast_ether_addr(mac_addr)) + #endif + { + if (params->cipher == WLAN_CIPHER_SUITE_TKIP) + u8gmode = ENCRYPT_ENABLED | WPA | TKIP; + else + u8gmode = ENCRYPT_ENABLED | WPA2 | AES; + + priv->wilc_groupkey = u8gmode; + + if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) { + + pu8TxMic = params->key + 24; + pu8RxMic = params->key + 16; + KeyLen = params->key_len - 16; + } + /* if there has been previous allocation for the same index through its key, free that memory and allocate again*/ + if (priv->wilc_gtk[key_index]->key) + WILC_FREE(priv->wilc_gtk[key_index]->key); + + priv->wilc_gtk[key_index]->key = (WILC_Uint8 *)WILC_MALLOC(params->key_len); + WILC_memcpy(priv->wilc_gtk[key_index]->key, params->key, params->key_len); + + /* if there has been previous allocation for the same index through its seq, free that memory and allocate again*/ + if (priv->wilc_gtk[key_index]->seq) + WILC_FREE(priv->wilc_gtk[key_index]->seq); + + if ((params->seq_len) > 0) { + priv->wilc_gtk[key_index]->seq = (WILC_Uint8 *)WILC_MALLOC(params->seq_len); + WILC_memcpy(priv->wilc_gtk[key_index]->seq, params->seq, params->seq_len); + } + + priv->wilc_gtk[key_index]->cipher = params->cipher; + priv->wilc_gtk[key_index]->key_len = params->key_len; + priv->wilc_gtk[key_index]->seq_len = params->seq_len; + + if (INFO) { + for (i = 0; i < params->key_len; i++) + PRINT_INFO(CFG80211_DBG, "Adding group key value[%d] = %x\n", i, params->key[i]); + for (i = 0; i < params->seq_len; i++) + PRINT_INFO(CFG80211_DBG, "Adding group seq value[%d] = %x\n", i, params->seq[i]); + } + + + host_int_add_rx_gtk(priv->hWILCWFIDrv, params->key, KeyLen, + key_index, params->seq_len, params->seq, pu8RxMic, pu8TxMic, AP_MODE, u8gmode); + + } else { + PRINT_INFO(CFG80211_DBG, "STA Address: %x%x%x%x%x\n", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4]); + + if (params->cipher == WLAN_CIPHER_SUITE_TKIP) + u8pmode = ENCRYPT_ENABLED | WPA | TKIP; + else + u8pmode = priv->wilc_groupkey | AES; + + + if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) { + + pu8TxMic = params->key + 24; + pu8RxMic = params->key + 16; + KeyLen = params->key_len - 16; + } + + if (priv->wilc_ptk[key_index]->key) + WILC_FREE(priv->wilc_ptk[key_index]->key); + + priv->wilc_ptk[key_index]->key = (WILC_Uint8 *)WILC_MALLOC(params->key_len); + + if (priv->wilc_ptk[key_index]->seq) + WILC_FREE(priv->wilc_ptk[key_index]->seq); + + if ((params->seq_len) > 0) + priv->wilc_ptk[key_index]->seq = (WILC_Uint8 *)WILC_MALLOC(params->seq_len); + + if (INFO) { + for (i = 0; i < params->key_len; i++) + PRINT_INFO(CFG80211_DBG, "Adding pairwise key value[%d] = %x\n", i, params->key[i]); + + for (i = 0; i < params->seq_len; i++) + PRINT_INFO(CFG80211_DBG, "Adding group seq value[%d] = %x\n", i, params->seq[i]); + } + + WILC_memcpy(priv->wilc_ptk[key_index]->key, params->key, params->key_len); + + if ((params->seq_len) > 0) + WILC_memcpy(priv->wilc_ptk[key_index]->seq, params->seq, params->seq_len); + + priv->wilc_ptk[key_index]->cipher = params->cipher; + priv->wilc_ptk[key_index]->key_len = params->key_len; + priv->wilc_ptk[key_index]->seq_len = params->seq_len; + + host_int_add_ptk(priv->hWILCWFIDrv, params->key, KeyLen, mac_addr, + pu8RxMic, pu8TxMic, AP_MODE, u8pmode, key_index); + } + break; + } + #endif + + { + u8mode = 0; + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) + if (!pairwise) + #else + if (!mac_addr || is_broadcast_ether_addr(mac_addr)) + #endif + { + if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) { + /* swap the tx mic by rx mic */ + pu8RxMic = params->key + 24; + pu8TxMic = params->key + 16; + KeyLen = params->key_len - 16; + } + + /*BugID_5137*/ + /*save keys only on interface 0 (wifi interface)*/ + if (!g_gtk_keys_saved && netdev == g_linux_wlan->strInterfaceInfo[0].wilc_netdev) { + g_add_gtk_key_params.key_idx = key_index; + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) + g_add_gtk_key_params.pairwise = pairwise; + #endif + if (!mac_addr) { + g_add_gtk_key_params.mac_addr = NULL; + } else { + g_add_gtk_key_params.mac_addr = WILC_MALLOC(ETH_ALEN); + memcpy(g_add_gtk_key_params.mac_addr, mac_addr, ETH_ALEN); + } + g_key_gtk_params.key_len = params->key_len; + g_key_gtk_params.seq_len = params->seq_len; + g_key_gtk_params.key = WILC_MALLOC(params->key_len); + memcpy(g_key_gtk_params.key, params->key, params->key_len); + if (params->seq_len > 0) { + g_key_gtk_params.seq = WILC_MALLOC(params->seq_len); + memcpy(g_key_gtk_params.seq, params->seq, params->seq_len); + } + g_key_gtk_params.cipher = params->cipher; + + PRINT_D(CFG80211_DBG, "key %x %x %x\n", g_key_gtk_params.key[0], + g_key_gtk_params.key[1], + g_key_gtk_params.key[2]); + g_gtk_keys_saved = WILC_TRUE; + } + + host_int_add_rx_gtk(priv->hWILCWFIDrv, params->key, KeyLen, + key_index, params->seq_len, params->seq, pu8RxMic, pu8TxMic, STATION_MODE, u8mode); + /* host_int_add_tx_gtk(priv->hWILCWFIDrv,params->key_len,params->key,key_index); */ + } else { + if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) { + /* swap the tx mic by rx mic */ + pu8RxMic = params->key + 24; + pu8TxMic = params->key + 16; + KeyLen = params->key_len - 16; + } + + /*BugID_5137*/ + /*save keys only on interface 0 (wifi interface)*/ + if (!g_ptk_keys_saved && netdev == g_linux_wlan->strInterfaceInfo[0].wilc_netdev) { + g_add_ptk_key_params.key_idx = key_index; + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) + g_add_ptk_key_params.pairwise = pairwise; + #endif + if (!mac_addr) { + g_add_ptk_key_params.mac_addr = NULL; + } else { + g_add_ptk_key_params.mac_addr = WILC_MALLOC(ETH_ALEN); + memcpy(g_add_ptk_key_params.mac_addr, mac_addr, ETH_ALEN); + } + g_key_ptk_params.key_len = params->key_len; + g_key_ptk_params.seq_len = params->seq_len; + g_key_ptk_params.key = WILC_MALLOC(params->key_len); + memcpy(g_key_ptk_params.key, params->key, params->key_len); + if (params->seq_len > 0) { + g_key_ptk_params.seq = WILC_MALLOC(params->seq_len); + memcpy(g_key_ptk_params.seq, params->seq, params->seq_len); + } + g_key_ptk_params.cipher = params->cipher; + + PRINT_D(CFG80211_DBG, "key %x %x %x\n", g_key_ptk_params.key[0], + g_key_ptk_params.key[1], + g_key_ptk_params.key[2]); + g_ptk_keys_saved = WILC_TRUE; + } + + host_int_add_ptk(priv->hWILCWFIDrv, params->key, KeyLen, mac_addr, + pu8RxMic, pu8TxMic, STATION_MODE, u8mode, key_index); + PRINT_D(CFG80211_DBG, "Adding pairwise key\n"); + if (INFO) { + for (i = 0; i < params->key_len; i++) + PRINT_INFO(CFG80211_DBG, "Adding pairwise key value[%d] = %d\n", i, params->key[i]); + } + } + } + break; + + default: + PRINT_ER("Not supported cipher: Error(%d)\n", s32Error); + s32Error = -ENOTSUPP; + + } + + return s32Error; +} + +/** + * @brief WILC_WFI_del_key + * @details Remove a key given the @mac_addr (%NULL for a group key) + * and @key_index, return -ENOENT if the key doesn't exist. + * @param[in] + * @return int : Return 0 on Success + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_del_key(struct wiphy *wiphy, struct net_device *netdev, + u8 key_index, + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) + bool pairwise, + #endif + const u8 *mac_addr) +{ + struct WILC_WFI_priv *priv; + WILC_Sint32 s32Error = WILC_SUCCESS; + + priv = wiphy_priv(wiphy); + + /*BugID_5137*/ + /*delete saved keys, if any*/ + if (netdev == g_linux_wlan->strInterfaceInfo[0].wilc_netdev) { + g_ptk_keys_saved = WILC_FALSE; + g_gtk_keys_saved = WILC_FALSE; + g_wep_keys_saved = WILC_FALSE; + + /*Delete saved WEP keys params, if any*/ + if (g_key_wep_params.key != NULL) { + WILC_FREE(g_key_wep_params.key); + g_key_wep_params.key = NULL; + } + + /*freeing memory allocated by "wilc_gtk" and "wilc_ptk" in "WILC_WIFI_ADD_KEY"*/ + + #ifdef WILC_AP_EXTERNAL_MLME + if ((priv->wilc_gtk[key_index]) != NULL) { + + if (priv->wilc_gtk[key_index]->key != NULL) { + + WILC_FREE(priv->wilc_gtk[key_index]->key); + priv->wilc_gtk[key_index]->key = NULL; + } + if (priv->wilc_gtk[key_index]->seq) { + + WILC_FREE(priv->wilc_gtk[key_index]->seq); + priv->wilc_gtk[key_index]->seq = NULL; + } + + WILC_FREE(priv->wilc_gtk[key_index]); + priv->wilc_gtk[key_index] = NULL; + + } + + if ((priv->wilc_ptk[key_index]) != NULL) { + + if (priv->wilc_ptk[key_index]->key) { + + WILC_FREE(priv->wilc_ptk[key_index]->key); + priv->wilc_ptk[key_index]->key = NULL; + } + if (priv->wilc_ptk[key_index]->seq) { + + WILC_FREE(priv->wilc_ptk[key_index]->seq); + priv->wilc_ptk[key_index]->seq = NULL; + } + WILC_FREE(priv->wilc_ptk[key_index]); + priv->wilc_ptk[key_index] = NULL; + } + #endif + + /*Delete saved PTK and GTK keys params, if any*/ + if (g_key_ptk_params.key != NULL) { + WILC_FREE(g_key_ptk_params.key); + g_key_ptk_params.key = NULL; + } + if (g_key_ptk_params.seq != NULL) { + WILC_FREE(g_key_ptk_params.seq); + g_key_ptk_params.seq = NULL; + } + + if (g_key_gtk_params.key != NULL) { + WILC_FREE(g_key_gtk_params.key); + g_key_gtk_params.key = NULL; + } + if (g_key_gtk_params.seq != NULL) { + WILC_FREE(g_key_gtk_params.seq); + g_key_gtk_params.seq = NULL; + } + + /*Reset WILC_CHANGING_VIR_IF register to allow adding futrue keys to CE H/W*/ + Set_machw_change_vir_if(WILC_FALSE); + } + + if (key_index >= 0 && key_index <= 3) { + WILC_memset(priv->WILC_WFI_wep_key[key_index], 0, priv->WILC_WFI_wep_key_len[key_index]); + priv->WILC_WFI_wep_key_len[key_index] = 0; + + PRINT_D(CFG80211_DBG, "Removing WEP key with index = %d\n", key_index); + host_int_remove_wep_key(priv->hWILCWFIDrv, key_index); + } else { + PRINT_D(CFG80211_DBG, "Removing all installed keys\n"); + host_int_remove_key(priv->hWILCWFIDrv, mac_addr); + } + + return s32Error; +} + +/** + * @brief WILC_WFI_get_key + * @details Get information about the key with the given parameters. + * @mac_addr will be %NULL when requesting information for a group + * key. All pointers given to the @callback function need not be valid + * after it returns. This function should return an error if it is + * not possible to retrieve the key, -ENOENT if it doesn't exist. + * @param[in] + * @return int : Return 0 on Success + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) + bool pairwise, + #endif + const u8 *mac_addr, void *cookie, void (*callback)(void *cookie, struct key_params *)) +{ + + WILC_Sint32 s32Error = WILC_SUCCESS; + + struct WILC_WFI_priv *priv; + struct key_params key_params; + WILC_Uint32 i; + priv = wiphy_priv(wiphy); + + + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) + if (!pairwise) + #else + if (!mac_addr || is_broadcast_ether_addr(mac_addr)) + #endif + { + PRINT_D(CFG80211_DBG, "Getting group key idx: %x\n", key_index); + + key_params.key = priv->wilc_gtk[key_index]->key; + key_params.cipher = priv->wilc_gtk[key_index]->cipher; + key_params.key_len = priv->wilc_gtk[key_index]->key_len; + key_params.seq = priv->wilc_gtk[key_index]->seq; + key_params.seq_len = priv->wilc_gtk[key_index]->seq_len; + if (INFO) { + for (i = 0; i < key_params.key_len; i++) + PRINT_INFO(CFG80211_DBG, "Retrieved key value %x\n", key_params.key[i]); + } + } else { + PRINT_D(CFG80211_DBG, "Getting pairwise key\n"); + + key_params.key = priv->wilc_ptk[key_index]->key; + key_params.cipher = priv->wilc_ptk[key_index]->cipher; + key_params.key_len = priv->wilc_ptk[key_index]->key_len; + key_params.seq = priv->wilc_ptk[key_index]->seq; + key_params.seq_len = priv->wilc_ptk[key_index]->seq_len; + } + + callback(cookie, &key_params); + + return s32Error; /* priv->wilc_gtk->key_len ?0 : -ENOENT; */ +} + +/** + * @brief WILC_WFI_set_default_key + * @details Set the default management frame key on an interface + * @param[in] + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_set_default_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 37) + , bool unicast, bool multicast + #endif + ) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + struct WILC_WFI_priv *priv; + + + priv = wiphy_priv(wiphy); + + PRINT_D(CFG80211_DBG, "Setting default key with idx = %d \n", key_index); + + if (key_index != priv->WILC_WFI_wep_default) { + + host_int_set_WEPDefaultKeyID(priv->hWILCWFIDrv, key_index); + } + + return s32Error; +} + +/** + * @brief WILC_WFI_dump_survey + * @details Get site survey information + * @param[in] + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_dump_survey(struct wiphy *wiphy, struct net_device *netdev, + int idx, struct survey_info *info) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + + + if (idx != 0) { + s32Error = -ENOENT; + PRINT_ER("Error Idx value doesn't equal zero: Error(%d)\n", s32Error); + + } + + return s32Error; +} + + +/** + * @brief WILC_WFI_get_station + * @details Get station information for the station identified by @mac + * @param[in] NONE + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ + +extern uint32_t Statisitcs_totalAcks, Statisitcs_DroppedAcks; +static int WILC_WFI_get_station(struct wiphy *wiphy, struct net_device *dev, + u8 *mac, struct station_info *sinfo) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + struct WILC_WFI_priv *priv; + perInterface_wlan_t *nic; + #ifdef WILC_AP_EXTERNAL_MLME + WILC_Uint32 i = 0; + WILC_Uint32 associatedsta = 0; + WILC_Uint32 inactive_time = 0; + #endif + priv = wiphy_priv(wiphy); + nic = netdev_priv(dev); + + #ifdef WILC_AP_EXTERNAL_MLME + if (nic->iftype == AP_MODE || nic->iftype == GO_MODE) { + PRINT_D(HOSTAPD_DBG, "Getting station parameters\n"); + + PRINT_INFO(HOSTAPD_DBG, ": %x%x%x%x%x\n", mac[0], mac[1], mac[2], mac[3], mac[4]); + + for (i = 0; i < NUM_STA_ASSOCIATED; i++) { + + if (!(memcmp(mac, priv->assoc_stainfo.au8Sta_AssociatedBss[i], ETH_ALEN))) { + associatedsta = i; + break; + } + + } + + if (associatedsta == -1) { + s32Error = -ENOENT; + PRINT_ER("Station required is not associated : Error(%d)\n", s32Error); + + return s32Error; + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) //0421 + sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME); +#else + sinfo->filled |= STATION_INFO_INACTIVE_TIME; +#endif + + host_int_get_inactive_time(priv->hWILCWFIDrv, mac, &(inactive_time)); + sinfo->inactive_time = 1000 * inactive_time; + PRINT_D(CFG80211_DBG, "Inactive time %d\n", sinfo->inactive_time); + + } + #endif + + if (nic->iftype == STATION_MODE) { + tstrStatistics strStatistics; + host_int_get_statistics(priv->hWILCWFIDrv, &strStatistics); + + /* + * tony: 2013-11-13 + * tx_failed introduced more than + * kernel version 3.0.0 + */ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) //0421 + sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL) | + BIT( NL80211_STA_INFO_RX_PACKETS) | + BIT(NL80211_STA_INFO_TX_PACKETS) | + BIT(NL80211_STA_INFO_TX_FAILED) | + BIT(NL80211_STA_INFO_TX_BITRATE); + #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) + sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_RX_PACKETS | STATION_INFO_TX_PACKETS + | STATION_INFO_TX_FAILED | STATION_INFO_TX_BITRATE; + #else + sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_RX_PACKETS | STATION_INFO_TX_PACKETS + | STATION_INFO_TX_BITRATE; + #endif + + sinfo->signal = strStatistics.s8RSSI; + sinfo->rx_packets = strStatistics.u32RxCount; + sinfo->tx_packets = strStatistics.u32TxCount + strStatistics.u32TxFailureCount; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) + sinfo->tx_failed = strStatistics.u32TxFailureCount; + #endif + sinfo->txrate.legacy = strStatistics.u8LinkSpeed * 10; + +#ifdef TCP_ENHANCEMENTS + if ((strStatistics.u8LinkSpeed > TCP_ACK_FILTER_LINK_SPEED_THRESH) && (strStatistics.u8LinkSpeed != DEFAULT_LINK_SPEED)) { + Enable_TCP_ACK_Filter(WILC_TRUE); + } else if (strStatistics.u8LinkSpeed != DEFAULT_LINK_SPEED) { + Enable_TCP_ACK_Filter(WILC_FALSE); + } +#endif + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) + PRINT_D(CORECONFIG_DBG, "*** stats[%d][%d][%d][%d][%d]\n", sinfo->signal, sinfo->rx_packets, sinfo->tx_packets, + sinfo->tx_failed, sinfo->txrate.legacy); + #else + PRINT_D(CORECONFIG_DBG, "*** stats[%d][%d][%d][%d]\n", sinfo->signal, sinfo->rx_packets, sinfo->tx_packets, + sinfo->txrate.legacy); + #endif + } + return s32Error; +} + + +/** + * @brief WILC_WFI_change_bss + * @details Modify parameters for a given BSS. + * @param[in] + * -use_cts_prot: Whether to use CTS protection + * (0 = no, 1 = yes, -1 = do not change) + * -use_short_preamble: Whether the use of short preambles is allowed + * (0 = no, 1 = yes, -1 = do not change) + * -use_short_slot_time: Whether the use of short slot time is allowed + * (0 = no, 1 = yes, -1 = do not change) + * -basic_rates: basic rates in IEEE 802.11 format + * (or NULL for no change) + * -basic_rates_len: number of basic rates + * -ap_isolate: do not forward packets between connected stations + * -ht_opmode: HT Operation mode + * (u16 = opmode, -1 = do not change) + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_change_bss(struct wiphy *wiphy, struct net_device *dev, + struct bss_parameters *params) +{ + PRINT_D(CFG80211_DBG, "Changing Bss parametrs\n"); + return 0; +} + +/** + * @brief WILC_WFI_auth + * @details Request to authenticate with the specified peer + * @param[in] + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_auth(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_auth_request *req) +{ + PRINT_D(CFG80211_DBG, "In Authentication Function\n"); + return 0; +} + +/** + * @brief WILC_WFI_assoc + * @details Request to (re)associate with the specified peer + * @param[in] + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_assoc(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_assoc_request *req) +{ + PRINT_D(CFG80211_DBG, "In Association Function\n"); + return 0; +} + +/** + * @brief WILC_WFI_deauth + * @details Request to deauthenticate from the specified peer + * @param[in] + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_deauth(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_deauth_request *req, void *cookie) +{ + PRINT_D(CFG80211_DBG, "In De-authentication Function\n"); + return 0; +} + +/** + * @brief WILC_WFI_disassoc + * @details Request to disassociate from the specified peer + * @param[in] + * @return int : Return 0 on Success + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_disassoc(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_disassoc_request *req, void *cookie) +{ + PRINT_D(CFG80211_DBG, "In Disassociation Function\n"); + return 0; +} + +/** + * @brief WILC_WFI_set_wiphy_params + * @details Notify that wiphy parameters have changed; + * @param[in] Changed bitfield (see &enum wiphy_params_flags) describes which values + * have changed. + * @return int : Return 0 on Success + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_set_wiphy_params(struct wiphy *wiphy, u32 changed) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrCfgParamVal pstrCfgParamVal; + struct WILC_WFI_priv *priv; + + priv = wiphy_priv(wiphy); +/* priv = netdev_priv(priv->wdev->netdev); */ + + pstrCfgParamVal.u32SetCfgFlag = 0; + PRINT_D(CFG80211_DBG, "Setting Wiphy params \n"); + + if (changed & WIPHY_PARAM_RETRY_SHORT) { + PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_RETRY_SHORT %d\n", + priv->dev->ieee80211_ptr->wiphy->retry_short); + pstrCfgParamVal.u32SetCfgFlag |= RETRY_SHORT; + pstrCfgParamVal.short_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_short; + } + if (changed & WIPHY_PARAM_RETRY_LONG) { + + PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_RETRY_LONG %d\n", priv->dev->ieee80211_ptr->wiphy->retry_long); + pstrCfgParamVal.u32SetCfgFlag |= RETRY_LONG; + pstrCfgParamVal.long_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_long; + + } + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { + PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_FRAG_THRESHOLD %d\n", priv->dev->ieee80211_ptr->wiphy->frag_threshold); + pstrCfgParamVal.u32SetCfgFlag |= FRAG_THRESHOLD; + pstrCfgParamVal.frag_threshold = priv->dev->ieee80211_ptr->wiphy->frag_threshold; + + } + + if (changed & WIPHY_PARAM_RTS_THRESHOLD) { + PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_RTS_THRESHOLD %d\n", priv->dev->ieee80211_ptr->wiphy->rts_threshold); + + pstrCfgParamVal.u32SetCfgFlag |= RTS_THRESHOLD; + pstrCfgParamVal.rts_threshold = priv->dev->ieee80211_ptr->wiphy->rts_threshold; + + } + + PRINT_D(CFG80211_DBG, "Setting CFG params in the host interface\n"); + s32Error = hif_set_cfg(priv->hWILCWFIDrv, &pstrCfgParamVal); + if (s32Error) + PRINT_ER("Error in setting WIPHY PARAMS\n"); + + + return s32Error; +} +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32) +/** + * @brief WILC_WFI_set_bitrate_mask + * @details set the bitrate mask configuration + * @param[in] + * @return int : Return 0 on Success + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_set_bitrate_mask(struct wiphy *wiphy, + struct net_device *dev, const u8 *peer, + const struct cfg80211_bitrate_mask *mask) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + /* strCfgParamVal pstrCfgParamVal; */ + /* struct WILC_WFI_priv* priv; */ + + PRINT_D(CFG80211_DBG, "Setting Bitrate mask function\n"); +#if 0 + priv = wiphy_priv(wiphy); + /* priv = netdev_priv(priv->wdev->netdev); */ + + pstrCfgParamVal.curr_tx_rate = mask->control[IEEE80211_BAND_2GHZ].legacy; + + PRINT_D(CFG80211_DBG, "Tx rate = %d\n", pstrCfgParamVal.curr_tx_rate); + s32Error = hif_set_cfg(priv->hWILCWFIDrv, &pstrCfgParamVal); + + if (s32Error) + PRINT_ER("Error in setting bitrate\n"); +#endif + return s32Error; + +} + +/** + * @brief WILC_WFI_set_pmksa + * @details Cache a PMKID for a BSSID. This is mostly useful for fullmac + * devices running firmwares capable of generating the (re) association + * RSN IE. It allows for faster roaming between WPA2 BSSIDs. + * @param[in] + * @return int : Return 0 on Success + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_set_pmksa(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_pmksa *pmksa) +{ + WILC_Uint32 i; + WILC_Sint32 s32Error = WILC_SUCCESS; + WILC_Uint8 flag = 0; + + struct WILC_WFI_priv *priv = wiphy_priv(wiphy); + + PRINT_D(CFG80211_DBG, "Setting PMKSA\n"); + + + for (i = 0; i < priv->pmkid_list.numpmkid; i++) { + if (!WILC_memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid, + ETH_ALEN)) { + /*If bssid already exists and pmkid value needs to reset*/ + flag = PMKID_FOUND; + PRINT_D(CFG80211_DBG, "PMKID already exists\n"); + break; + } + } + if (i < WILC_MAX_NUM_PMKIDS) { + PRINT_D(CFG80211_DBG, "Setting PMKID in private structure\n"); + WILC_memcpy(priv->pmkid_list.pmkidlist[i].bssid, pmksa->bssid, + ETH_ALEN); + WILC_memcpy(priv->pmkid_list.pmkidlist[i].pmkid, pmksa->pmkid, + PMKID_LEN); + if (!(flag == PMKID_FOUND)) + priv->pmkid_list.numpmkid++; + } else { + PRINT_ER("Invalid PMKID index\n"); + s32Error = -EINVAL; + } + + if (!s32Error) { + PRINT_D(CFG80211_DBG, "Setting pmkid in the host interface\n"); + s32Error = host_int_set_pmkid_info(priv->hWILCWFIDrv, &priv->pmkid_list); + } + return s32Error; +} + +/** + * @brief WILC_WFI_del_pmksa + * @details Delete a cached PMKID. + * @param[in] + * @return int : Return 0 on Success + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_del_pmksa(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_pmksa *pmksa) +{ + + WILC_Uint32 i; + WILC_Uint8 flag = 0; + WILC_Sint32 s32Error = WILC_SUCCESS; + + struct WILC_WFI_priv *priv = wiphy_priv(wiphy); + /* priv = netdev_priv(priv->wdev->netdev); */ + + PRINT_D(CFG80211_DBG, "Deleting PMKSA keys\n"); + + for (i = 0; i < priv->pmkid_list.numpmkid; i++) { + if (!WILC_memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid, + ETH_ALEN)) { + /*If bssid is found, reset the values*/ + PRINT_D(CFG80211_DBG, "Reseting PMKID values\n"); + WILC_memset(&priv->pmkid_list.pmkidlist[i], 0, sizeof(tstrHostIFpmkid)); + flag = PMKID_FOUND; + break; + } + } + + if (i < priv->pmkid_list.numpmkid && priv->pmkid_list.numpmkid > 0) { + for (; i < (priv->pmkid_list.numpmkid - 1); i++) { + WILC_memcpy(priv->pmkid_list.pmkidlist[i].bssid, + priv->pmkid_list.pmkidlist[i + 1].bssid, + ETH_ALEN); + WILC_memcpy(priv->pmkid_list.pmkidlist[i].pmkid, + priv->pmkid_list.pmkidlist[i].pmkid, + PMKID_LEN); + } + priv->pmkid_list.numpmkid--; + } else { + s32Error = -EINVAL; + } + + return s32Error; +} + +/** + * @brief WILC_WFI_flush_pmksa + * @details Flush all cached PMKIDs. + * @param[in] + * @return int : Return 0 on Success + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) +{ + struct WILC_WFI_priv *priv = wiphy_priv(wiphy); + /* priv = netdev_priv(priv->wdev->netdev); */ + + PRINT_D(CFG80211_DBG, "Flushing PMKID key values\n"); + + /*Get cashed Pmkids and set all with zeros*/ + WILC_memset(&priv->pmkid_list, 0, sizeof(tstrHostIFpmkidAttr)); + + return 0; +} +#endif + +#ifdef WILC_P2P + +/** + * @brief WILC_WFI_CfgParseRxAction + * @details Function parses the received frames and modifies the following attributes: + * -GO Intent + * -Channel list + * -Operating Channel + * + * @param[in] u8* Buffer, u32 length + * @return NONE. + * @author mdaftedar + * @date 12 DEC 2012 + * @version + */ + +void WILC_WFI_CfgParseRxAction(WILC_Uint8 *buf, WILC_Uint32 len) +{ + WILC_Uint32 index = 0; + WILC_Uint32 i = 0, j = 0; + + /*BugID_5460*/ + #ifdef USE_SUPPLICANT_GO_INTENT + WILC_Uint8 intent; + WILC_Uint8 tie_breaker; + WILC_Bool is_wilc_go = WILC_TRUE; + #endif + WILC_Uint8 op_channel_attr_index = 0; + WILC_Uint8 channel_list_attr_index = 0; + + while (index < len) { + if (buf[index] == GO_INTENT_ATTR_ID) { + #ifdef USE_SUPPLICANT_GO_INTENT + /*BugID_5460*/ + /*Case 1: If we are going to be p2p client, no need to modify channels attributes*/ + /*In negotiation frames, go intent attr value determines who will be GO*/ + intent = GET_GO_INTENT(buf[index + 3]); + tie_breaker = GET_TIE_BREAKER(buf[index + 3]); + if (intent > SUPPLICANT_GO_INTENT + || (intent == SUPPLICANT_GO_INTENT && tie_breaker == 1)) { + PRINT_D(GENERIC_DBG, "WILC will be client (intent %d tie breaker %d)\n", intent, tie_breaker); + is_wilc_go = WILC_FALSE; + } else { + PRINT_D(GENERIC_DBG, "WILC will be GO (intent %d tie breaker %d)\n", intent, tie_breaker); + is_wilc_go = WILC_TRUE; + } + + #else /* USE_SUPPLICANT_GO_INTENT */ + #ifdef FORCE_P2P_CLIENT + buf[index + 3] = (buf[index + 3] & 0x01) | (0x0f << 1); + #else + buf[index + 3] = (buf[index + 3] & 0x01) | (0x00 << 1); + #endif + #endif /* USE_SUPPLICANT_GO_INTENT */ + } + + #ifdef USE_SUPPLICANT_GO_INTENT + /*Case 2: If group bssid attribute is present, no need to modify channels attributes*/ + /*In invitation req and rsp, group bssid attr presence determines who will be GO*/ + if (buf[index] == GROUP_BSSID_ATTR_ID) { + PRINT_D(GENERIC_DBG, "Group BSSID: %2x:%2x:%2x\n", buf[index + 3] + , buf[index + 4] + , buf[index + 5]); + is_wilc_go = WILC_FALSE; + } + #endif /* USE_SUPPLICANT_GO_INTENT */ + + if (buf[index] == CHANLIST_ATTR_ID) { + channel_list_attr_index = index; + } else if (buf[index] == OPERCHAN_ATTR_ID) { + op_channel_attr_index = index; + } + index += buf[index + 1] + 3; /* ID,Length byte */ + } + + #ifdef USE_SUPPLICANT_GO_INTENT + if (u8WLANChannel != INVALID_CHANNEL && is_wilc_go) + #else + if (u8WLANChannel != INVALID_CHANNEL) + #endif + { + /*Modify channel list attribute*/ + if (channel_list_attr_index) { + PRINT_D(GENERIC_DBG, "Modify channel list attribute\n"); + for (i = channel_list_attr_index + 3; i < ((channel_list_attr_index + 3) + buf[channel_list_attr_index + 1]); i++) { + if (buf[i] == 0x51) { + for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++) { + buf[j] = u8WLANChannel; + } + break; + } + } + } + /*Modify operating channel attribute*/ + if (op_channel_attr_index) { + PRINT_D(GENERIC_DBG, "Modify operating channel attribute\n"); + buf[op_channel_attr_index + 6] = 0x51; + buf[op_channel_attr_index + 7] = u8WLANChannel; + } + } +} + +/** + * @brief WILC_WFI_CfgParseTxAction + * @details Function parses the transmitted action frames and modifies the + * GO Intent attribute + * @param[in] u8* Buffer, u32 length, bool bOperChan, u8 iftype + * @return NONE. + * @author mdaftedar + * @date 12 DEC 2012 + * @version + */ +void WILC_WFI_CfgParseTxAction(WILC_Uint8 *buf, WILC_Uint32 len, WILC_Bool bOperChan, WILC_Uint8 iftype) +{ + WILC_Uint32 index = 0; + WILC_Uint32 i = 0, j = 0; + + WILC_Uint8 op_channel_attr_index = 0; + WILC_Uint8 channel_list_attr_index = 0; + #ifdef USE_SUPPLICANT_GO_INTENT + WILC_Bool is_wilc_go = WILC_FALSE; + + /*BugID_5460*/ + /*Case 1: If we are already p2p client, no need to modify channels attributes*/ + /*This to handle the case of inviting a p2p peer to join an existing group which we are a member in*/ + if (iftype == CLIENT_MODE) + return; + #endif + + while (index < len) { + #ifdef USE_SUPPLICANT_GO_INTENT + /*Case 2: If group bssid attribute is present, no need to modify channels attributes*/ + /*In invitation req and rsp, group bssid attr presence determines who will be GO*/ + /*Note: If we are already p2p client, group bssid attr may also be present (handled in Case 1)*/ + if (buf[index] == GROUP_BSSID_ATTR_ID) { + PRINT_D(GENERIC_DBG, "Group BSSID: %2x:%2x:%2x\n", buf[index + 3] + , buf[index + 4] + , buf[index + 5]); + is_wilc_go = WILC_TRUE; + } + + #else /* USE_SUPPLICANT_GO_INTENT */ + if (buf[index] == GO_INTENT_ATTR_ID) { + #ifdef FORCE_P2P_CLIENT + buf[index + 3] = (buf[index + 3] & 0x01) | (0x00 << 1); + #else + buf[index + 3] = (buf[index + 3] & 0x01) | (0x0f << 1); + #endif + + break; + } + #endif + + if (buf[index] == CHANLIST_ATTR_ID) { + channel_list_attr_index = index; + } else if (buf[index] == OPERCHAN_ATTR_ID) { + op_channel_attr_index = index; + } + index += buf[index + 1] + 3; /* ID,Length byte */ + } + + #ifdef USE_SUPPLICANT_GO_INTENT + /*No need to check bOperChan since only transmitted invitation frames are parsed*/ + if (u8WLANChannel != INVALID_CHANNEL && is_wilc_go) + #else + if (u8WLANChannel != INVALID_CHANNEL && bOperChan) + #endif + { + /*Modify channel list attribute*/ + if (channel_list_attr_index) { + PRINT_D(GENERIC_DBG, "Modify channel list attribute\n"); + for (i = channel_list_attr_index + 3; i < ((channel_list_attr_index + 3) + buf[channel_list_attr_index + 1]); i++) { + if (buf[i] == 0x51) { + for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++) { + buf[j] = u8WLANChannel; + } + break; + } + } + } + /*Modify operating channel attribute*/ + if (op_channel_attr_index) { + PRINT_D(GENERIC_DBG, "Modify operating channel attribute\n"); + buf[op_channel_attr_index + 6] = 0x51; + buf[op_channel_attr_index + 7] = u8WLANChannel; + } + } +} + +/* @brief WILC_WFI_p2p_rx + * @details + * @param[in] + * + * @return None + * @author Mai Daftedar + * @date 2 JUN 2013 + * @version 1.0 + */ + +void WILC_WFI_p2p_rx (struct net_device *dev, uint8_t *buff, uint32_t size) +{ + + struct WILC_WFI_priv *priv; + WILC_Uint32 header, pkt_offset; + tstrWILC_WFIDrv *pstrWFIDrv; + WILC_Uint32 i = 0; + WILC_Sint32 s32Freq; + priv = wiphy_priv(dev->ieee80211_ptr->wiphy); + pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv; + + /* Get WILC header */ + WILC_memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET); + + /* The packet offset field conain info about what type of managment frame */ + /* we are dealing with and ack status */ + pkt_offset = GET_PKT_OFFSET(header); + + if (pkt_offset & IS_MANAGMEMENT_CALLBACK) { + if (buff[FRAME_TYPE_ID] == IEEE80211_STYPE_PROBE_RESP) { + PRINT_D(GENERIC_DBG, "Probe response ACK\n"); + #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) + cfg80211_mgmt_tx_status(dev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL); + #else + cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL); + #endif + return; + } else { + if (pkt_offset & IS_MGMT_STATUS_SUCCES) { + PRINT_D(GENERIC_DBG, "Success Ack - Action frame category: %x Action Subtype: %d Dialog T: %x OR %x\n", buff[ACTION_CAT_ID], buff[ACTION_SUBTYPE_ID], + buff[ACTION_SUBTYPE_ID + 1], buff[P2P_PUB_ACTION_SUBTYPE + 1]); + #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) + cfg80211_mgmt_tx_status(dev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL); + #else + cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL); + #endif + } else { + PRINT_D(GENERIC_DBG, "Fail Ack - Action frame category: %x Action Subtype: %d Dialog T: %x OR %x\n", buff[ACTION_CAT_ID], buff[ACTION_SUBTYPE_ID], + buff[ACTION_SUBTYPE_ID + 1], buff[P2P_PUB_ACTION_SUBTYPE + 1]); + #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) + cfg80211_mgmt_tx_status(dev, priv->u64tx_cookie, buff, size, false, GFP_KERNEL); + #else + cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, false, GFP_KERNEL); + #endif + } + return; + } + } else { + + PRINT_D(GENERIC_DBG, "Rx Frame Type:%x\n", buff[FRAME_TYPE_ID]); + + /*BugID_5442*/ + /*Upper layer is informed that the frame is received on this freq*/ + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) + s32Freq = ieee80211_channel_to_frequency(u8CurrChannel, IEEE80211_BAND_2GHZ); + #else + s32Freq = ieee80211_channel_to_frequency(u8CurrChannel); + #endif + + if (ieee80211_is_action(buff[FRAME_TYPE_ID])) { + PRINT_D(GENERIC_DBG, "Rx Action Frame Type: %x %x\n", buff[ACTION_SUBTYPE_ID], buff[P2P_PUB_ACTION_SUBTYPE]); + + if (priv->bCfgScanning == WILC_TRUE && jiffies >= pstrWFIDrv->u64P2p_MgmtTimeout) { + PRINT_D(GENERIC_DBG, "Receiving action frames from wrong channels\n"); + return; + } + if (buff[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) { + + switch (buff[ACTION_SUBTYPE_ID]) { + case GAS_INTIAL_REQ: + PRINT_D(GENERIC_DBG, "GAS INITIAL REQ %x\n", buff[ACTION_SUBTYPE_ID]); + break; + + case GAS_INTIAL_RSP: + PRINT_D(GENERIC_DBG, "GAS INITIAL RSP %x\n", buff[ACTION_SUBTYPE_ID]); + break; + + case PUBLIC_ACT_VENDORSPEC: + /*Now we have a public action vendor specific action frame, check if its a p2p public action frame + * based on the standard its should have the p2p_oui attribute with the following values 50 6f 9A 09*/ + if (!WILC_memcmp(u8P2P_oui, &buff[ACTION_SUBTYPE_ID + 1], 4)) { + if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP)) { + if (!bWilc_ie) { + for (i = P2P_PUB_ACTION_SUBTYPE; i < size; i++) { + if (!WILC_memcmp(u8P2P_vendorspec, &buff[i], 6)) { + u8P2Precvrandom = buff[i + 6]; + bWilc_ie = WILC_TRUE; + PRINT_D(GENERIC_DBG, "WILC Vendor specific IE:%02x\n", u8P2Precvrandom); + break; + } + } + } + } + if (u8P2Plocalrandom > u8P2Precvrandom) { + if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP + || buff[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)) { + for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < size; i++) { + if (buff[i] == P2PELEM_ATTR_ID && !(WILC_memcmp(u8P2P_oui, &buff[i + 2], 4))) { + WILC_WFI_CfgParseRxAction(&buff[i + 6], size - (i + 6)); + break; + } + } + } + } else + PRINT_D(GENERIC_DBG, "PEER WILL BE GO LocaRand=%02x RecvRand %02x\n", u8P2Plocalrandom, u8P2Precvrandom); + } + + + if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP) && (bWilc_ie)) { + PRINT_D(GENERIC_DBG, "Sending P2P to host without extra elemnt\n"); + /* extra attribute for sig_dbm: signal strength in mBm, or 0 if unknown */ + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) + cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0); + #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) + cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0, GFP_ATOMIC); + #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, GFP_ATOMIC); + #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) + cfg80211_rx_mgmt(dev, s32Freq, 0, buff, size - 7, GFP_ATOMIC); /* rachel */ + #elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) + cfg80211_rx_mgmt(dev, s32Freq, buff, size - 7, GFP_ATOMIC); + #endif + + return; + } + break; + + default: + PRINT_D(GENERIC_DBG, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buff[ACTION_SUBTYPE_ID]); + break; + } + } + } + + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) + cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0); + #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) + cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0, GFP_ATOMIC); + #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size, GFP_ATOMIC); + #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) + cfg80211_rx_mgmt(dev, s32Freq, 0, buff, size, GFP_ATOMIC); + #elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) + cfg80211_rx_mgmt(dev, s32Freq, buff, size, GFP_ATOMIC); + #endif + } +} + +/** + * @brief WILC_WFI_mgmt_tx_complete + * @details Returns result of writing mgmt frame to VMM (Tx buffers are freed here) + * @param[in] priv + * transmitting status + * @return None + * @author Amr Abdelmoghny + * @date 20 MAY 2013 + * @version 1.0 + */ +static void WILC_WFI_mgmt_tx_complete(void *priv, int status) +{ + struct p2p_mgmt_data *pv_data = (struct p2p_mgmt_data *)priv; + + + kfree(pv_data->buff); + kfree(pv_data); +} + +/** + * @brief WILC_WFI_RemainOnChannelReady + * @details Callback function, called from handle_remain_on_channel on being ready on channel + * @param + * @return none + * @author Amr abdelmoghny + * @date 9 JUNE 2013 + * @version + */ + +static void WILC_WFI_RemainOnChannelReady(void *pUserVoid) +{ + struct WILC_WFI_priv *priv; + priv = (struct WILC_WFI_priv *)pUserVoid; + + PRINT_D(HOSTINF_DBG, "Remain on channel ready \n"); + + priv->bInP2PlistenState = WILC_TRUE; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) + cfg80211_ready_on_channel(priv->wdev, + priv->strRemainOnChanParams.u64ListenCookie, + priv->strRemainOnChanParams.pstrListenChan, + priv->strRemainOnChanParams.u32ListenDuration, + GFP_KERNEL); +#else + cfg80211_ready_on_channel(priv->dev, + priv->strRemainOnChanParams.u64ListenCookie, + priv->strRemainOnChanParams.pstrListenChan, + priv->strRemainOnChanParams.tenuChannelType, + priv->strRemainOnChanParams.u32ListenDuration, + GFP_KERNEL); +#endif +} + +/** + * @brief WILC_WFI_RemainOnChannelExpired + * @details Callback function, called on expiration of remain-on-channel duration + * @param + * @return none + * @author Amr abdelmoghny + * @date 15 MAY 2013 + * @version + */ + +static void WILC_WFI_RemainOnChannelExpired(void *pUserVoid, WILC_Uint32 u32SessionID) +{ + struct WILC_WFI_priv *priv; + priv = (struct WILC_WFI_priv *)pUserVoid; + + /*BugID_5477*/ + if (u32SessionID == priv->strRemainOnChanParams.u32ListenSessionID) { + PRINT_D(GENERIC_DBG, "Remain on channel expired \n"); + + priv->bInP2PlistenState = WILC_FALSE; + + /*Inform wpas of remain-on-channel expiration*/ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) + cfg80211_remain_on_channel_expired(priv->wdev, + priv->strRemainOnChanParams.u64ListenCookie, + priv->strRemainOnChanParams.pstrListenChan, + GFP_KERNEL); + #else + cfg80211_remain_on_channel_expired(priv->dev, + priv->strRemainOnChanParams.u64ListenCookie, + priv->strRemainOnChanParams.pstrListenChan, + priv->strRemainOnChanParams.tenuChannelType, + GFP_KERNEL); + #endif + } else { + PRINT_D(GENERIC_DBG, "Received ID 0x%x Expected ID 0x%x (No match)\n", u32SessionID + , priv->strRemainOnChanParams.u32ListenSessionID); + } +} + + +/** + * @brief WILC_WFI_remain_on_channel + * @details Request the driver to remain awake on the specified + * channel for the specified duration to complete an off-channel + * operation (e.g., public action frame exchange). When the driver is + * ready on the requested channel, it must indicate this with an event + * notification by calling cfg80211_ready_on_channel(). + * @param[in] + * @return int : Return 0 on Success + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_remain_on_channel(struct wiphy *wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + struct wireless_dev *wdev, +#else + struct net_device *dev, +#endif + struct ieee80211_channel *chan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) + enum nl80211_channel_type channel_type, +#endif + unsigned int duration, u64 *cookie) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + struct WILC_WFI_priv *priv; + priv = wiphy_priv(wiphy); + + PRINT_D(GENERIC_DBG, "Remaining on channel %d\n", chan->hw_value); + + /*BugID_4800: if in AP mode, return.*/ + /*This check is to handle the situation when user*/ + /*requests "create group" during a running scan*/ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + if (wdev->iftype == NL80211_IFTYPE_AP) { + PRINT_D(GENERIC_DBG, "Required remain-on-channel while in AP mode"); + return s32Error; + } +#else + if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) { + PRINT_D(GENERIC_DBG, "Required remain-on-channel while in AP mode"); + return s32Error; + } +#endif + + u8CurrChannel = chan->hw_value; + + /*Setting params needed by WILC_WFI_RemainOnChannelExpired()*/ + priv->strRemainOnChanParams.pstrListenChan = chan; + priv->strRemainOnChanParams.u64ListenCookie = *cookie; + #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) + priv->strRemainOnChanParams.tenuChannelType = channel_type; + #endif + priv->strRemainOnChanParams.u32ListenDuration = duration; + priv->strRemainOnChanParams.u32ListenSessionID++; + + s32Error = host_int_remain_on_channel(priv->hWILCWFIDrv + , priv->strRemainOnChanParams.u32ListenSessionID + , duration + , chan->hw_value + , WILC_WFI_RemainOnChannelExpired + , WILC_WFI_RemainOnChannelReady + , (void *)priv); + + return s32Error; +} + +/** + * @brief WILC_WFI_cancel_remain_on_channel + * @details Cancel an on-going remain-on-channel operation. + * This allows the operation to be terminated prior to timeout based on + * the duration value. + * @param[in] struct wiphy *wiphy, + * @param[in] struct net_device *dev + * @param[in] u64 cookie, + * @return int : Return 0 on Success + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_cancel_remain_on_channel(struct wiphy *wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + struct wireless_dev *wdev, +#else + struct net_device *dev, +#endif + u64 cookie) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + struct WILC_WFI_priv *priv; + priv = wiphy_priv(wiphy); + + PRINT_D(CFG80211_DBG, "Cancel remain on channel\n"); + + s32Error = host_int_ListenStateExpired(priv->hWILCWFIDrv, priv->strRemainOnChanParams.u32ListenSessionID); + return s32Error; +} +/** + * @brief WILC_WFI_add_wilcvendorspec + * @details Adding WILC information elemet to allow two WILC devices to + * identify each other and connect + * @param[in] WILC_Uint8 * buf + * @return void + * @author mdaftedar + * @date 01 JAN 2014 + * @version 1.0 + */ +void WILC_WFI_add_wilcvendorspec(WILC_Uint8 *buff) +{ + WILC_memcpy(buff, u8P2P_vendorspec, sizeof(u8P2P_vendorspec)); +} +/** + * @brief WILC_WFI_mgmt_tx_frame + * @details + * + * @param[in] + * @return NONE. + * @author mdaftedar + * @date 01 JUL 2012 + * @version + */ +extern linux_wlan_t *g_linux_wlan; +extern WILC_Bool bEnablePS; +int WILC_WFI_mgmt_tx(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + bool offchan, + unsigned int wait, + const u8 *buf, + size_t len, + bool no_cck, + bool dont_wait_for_ack, u64 *cookie) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + struct wireless_dev *wdev, + struct ieee80211_channel *chan, bool offchan, + enum nl80211_channel_type channel_type, + bool channel_type valid, + unsigned int wait, const u8 *buf, + size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) + struct net_device *dev, + struct ieee80211_channel *chan, bool offchan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, + unsigned int wait, const u8 *buf, + size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) + struct net_device *dev, + struct ieee80211_channel *chan, bool offchan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, + unsigned int wait, const u8 *buf, + size_t len, bool no_cck, u64 *cookie) +#else + struct net_device *dev, + struct ieee80211_channel *chan, bool offchan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, + unsigned int wait, const u8 *buf, + size_t len, u64 *cookie) +#endif +{ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) + struct ieee80211_channel *chan = params->chan; + unsigned int wait = params->wait; + const u8 *buf = params->buf; + size_t len = params->len; + #endif + const struct ieee80211_mgmt *mgmt; + struct p2p_mgmt_data *mgmt_tx; + struct WILC_WFI_priv *priv; + WILC_Sint32 s32Error = WILC_SUCCESS; + tstrWILC_WFIDrv *pstrWFIDrv; + WILC_Uint32 i; + perInterface_wlan_t *nic; + WILC_Uint32 buf_len = len + sizeof(u8P2P_vendorspec) + sizeof(u8P2Plocalrandom); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + nic = netdev_priv(wdev->netdev); +#else + nic = netdev_priv(dev); +#endif + priv = wiphy_priv(wiphy); + pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv; + + *cookie = (unsigned long)buf; + priv->u64tx_cookie = *cookie; + mgmt = (const struct ieee80211_mgmt *) buf; + + if (ieee80211_is_mgmt(mgmt->frame_control)) { + + /*mgmt frame allocation*/ + mgmt_tx = (struct p2p_mgmt_data *)WILC_MALLOC(sizeof(struct p2p_mgmt_data)); + if (mgmt_tx == NULL) { + PRINT_ER("Failed to allocate memory for mgmt_tx structure\n"); + return WILC_FAIL; + } + mgmt_tx->buff = (char *)WILC_MALLOC(buf_len); + if (mgmt_tx->buff == NULL) { + PRINT_ER("Failed to allocate memory for mgmt_tx buff\n"); + return WILC_FAIL; + } + WILC_memcpy(mgmt_tx->buff, buf, len); + mgmt_tx->size = len; + + + if (ieee80211_is_probe_resp(mgmt->frame_control)) { + PRINT_D(GENERIC_DBG, "TX: Probe Response\n"); + PRINT_D(GENERIC_DBG, "Setting channel: %d\n", chan->hw_value); + host_int_set_mac_chnl_num(priv->hWILCWFIDrv, chan->hw_value); + /*Save the current channel after we tune to it*/ + u8CurrChannel = chan->hw_value; + } else if (ieee80211_is_action(mgmt->frame_control)) { + PRINT_D(GENERIC_DBG, "ACTION FRAME:%x\n", (WILC_Uint16)mgmt->frame_control); + + + /*BugID_4847*/ + if (buf[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) { + /*BugID_4847*/ + /*Only set the channel, if not a negotiation confirmation frame + * (If Negotiation confirmation frame, force it + * to be transmitted on the same negotiation channel)*/ + + if (buf[ACTION_SUBTYPE_ID] != PUBLIC_ACT_VENDORSPEC || + buf[P2P_PUB_ACTION_SUBTYPE] != GO_NEG_CONF) { + PRINT_D(GENERIC_DBG, "Setting channel: %d\n", chan->hw_value); + host_int_set_mac_chnl_num(priv->hWILCWFIDrv, chan->hw_value); + /*Save the current channel after we tune to it*/ + u8CurrChannel = chan->hw_value; + } + switch (buf[ACTION_SUBTYPE_ID]) { + case GAS_INTIAL_REQ: + { + PRINT_D(GENERIC_DBG, "GAS INITIAL REQ %x\n", buf[ACTION_SUBTYPE_ID]); + break; + } + + case GAS_INTIAL_RSP: + { + PRINT_D(GENERIC_DBG, "GAS INITIAL RSP %x\n", buf[ACTION_SUBTYPE_ID]); + break; + } + + case PUBLIC_ACT_VENDORSPEC: + { + /*Now we have a public action vendor specific action frame, check if its a p2p public action frame + * based on the standard its should have the p2p_oui attribute with the following values 50 6f 9A 09*/ + if (!WILC_memcmp(u8P2P_oui, &buf[ACTION_SUBTYPE_ID + 1], 4)) { + /*For the connection of two WILC's connection generate a rand number to determine who will be a GO*/ + if ((buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP)) { + if (u8P2Plocalrandom == 1 && u8P2Precvrandom < u8P2Plocalrandom) { + get_random_bytes(&u8P2Plocalrandom, 1); + /*Increment the number to prevent if its 0*/ + u8P2Plocalrandom++; + } + } + + if ((buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP + || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)) { + if (u8P2Plocalrandom > u8P2Precvrandom) { + PRINT_D(GENERIC_DBG, "LOCAL WILL BE GO LocaRand=%02x RecvRand %02x\n", u8P2Plocalrandom, u8P2Precvrandom); + + /*Search for the p2p information information element , after the Public action subtype theres a byte for teh dialog token, skip that*/ + for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < len; i++) { + if (buf[i] == P2PELEM_ATTR_ID && !(WILC_memcmp(u8P2P_oui, &buf[i + 2], 4))) { + if (buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP) + WILC_WFI_CfgParseTxAction(&mgmt_tx->buff[i + 6], len - (i + 6), WILC_TRUE, nic->iftype); + + /*BugID_5460*/ + /*If using supplicant go intent, no need at all*/ + /*to parse transmitted negotiation frames*/ + #ifndef USE_SUPPLICANT_GO_INTENT + else + WILC_WFI_CfgParseTxAction(&mgmt_tx->buff[i + 6], len - (i + 6), WILC_FALSE, nic->iftype); + #endif + break; + } + } + + if (buf[P2P_PUB_ACTION_SUBTYPE] != P2P_INV_REQ && buf[P2P_PUB_ACTION_SUBTYPE] != P2P_INV_RSP) { + WILC_WFI_add_wilcvendorspec(&mgmt_tx->buff[len]); + mgmt_tx->buff[len + sizeof(u8P2P_vendorspec)] = u8P2Plocalrandom; + mgmt_tx->size = buf_len; + } + } else + PRINT_D(GENERIC_DBG, "PEER WILL BE GO LocaRand=%02x RecvRand %02x\n", u8P2Plocalrandom, u8P2Precvrandom); + } + + } else { + PRINT_D(GENERIC_DBG, "Not a P2P public action frame\n"); + } + + break; + } + + default: + { + PRINT_D(GENERIC_DBG, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buf[ACTION_SUBTYPE_ID]); + break; + } + } + + } + + PRINT_D(GENERIC_DBG, "TX: ACTION FRAME Type:%x : Chan:%d\n", buf[ACTION_SUBTYPE_ID], chan->hw_value); + pstrWFIDrv->u64P2p_MgmtTimeout = (jiffies + msecs_to_jiffies(wait)); + + PRINT_D(GENERIC_DBG, "Current Jiffies: %lu Timeout:%llu\n", jiffies, pstrWFIDrv->u64P2p_MgmtTimeout); + + } + + g_linux_wlan->oup.wlan_add_mgmt_to_tx_que(mgmt_tx, mgmt_tx->buff, mgmt_tx->size, WILC_WFI_mgmt_tx_complete); + } else { + PRINT_D(GENERIC_DBG, "This function transmits only management frames\n"); + } + return s32Error; +} + +int WILC_WFI_mgmt_tx_cancel_wait(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) + struct wireless_dev *wdev, +#else + struct net_device *dev, +#endif + u64 cookie) +{ + struct WILC_WFI_priv *priv; + tstrWILC_WFIDrv *pstrWFIDrv; + priv = wiphy_priv(wiphy); + pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv; + + + PRINT_D(GENERIC_DBG, "Tx Cancel wait :%lu\n", jiffies); + pstrWFIDrv->u64P2p_MgmtTimeout = jiffies; + + if (priv->bInP2PlistenState == WILC_FALSE) { + /* Bug 5504: This is just to avoid connection failure when getting stuck when the supplicant + * considers the driver falsely that it is in Listen state */ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) + cfg80211_remain_on_channel_expired(priv->wdev, + priv->strRemainOnChanParams.u64ListenCookie, + priv->strRemainOnChanParams.pstrListenChan, + GFP_KERNEL); + #else + cfg80211_remain_on_channel_expired(priv->dev, + priv->strRemainOnChanParams.u64ListenCookie, + priv->strRemainOnChanParams.pstrListenChan, + priv->strRemainOnChanParams.tenuChannelType, + GFP_KERNEL); + #endif + + } + + return 0; +} + +/** + * @brief WILC_WFI_action + * @details Transmit an action frame + * @param[in] + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 JUL 2012 + * @version 1.0 + * */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) +int WILC_WFI_action(struct wiphy *wiphy, struct net_device *dev, + struct ieee80211_channel *chan, enum nl80211_channel_type channel_type, + const u8 *buf, size_t len, u64 *cookie) +{ + PRINT_D(HOSTAPD_DBG, "In action function\n"); + return WILC_SUCCESS; +} +#endif +#else + +/** + * @brief WILC_WFI_frame_register + * @details Notify driver that a management frame type was + * registered. Note that this callback may not sleep, and cannot run + * concurrently with itself. + * @param[in] + * @return NONE. + * @author mdaftedar + * @date 01 JUL 2012 + * @version + */ +void WILC_WFI_frame_register(struct wiphy *wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + struct wireless_dev *wdev, +#else + struct net_device *dev, +#endif + u16 frame_type, bool reg) +{ + + struct WILC_WFI_priv *priv; + perInterface_wlan_t *nic; + + + priv = wiphy_priv(wiphy); + nic = netdev_priv(priv->wdev->netdev); + + + + /*BugID_5137*/ + if (!frame_type) + return; + + PRINT_D(GENERIC_DBG, "Frame registering Frame Type: %x: Boolean: %d\n", frame_type, reg); + switch (frame_type) { + case PROBE_REQ: + { + nic->g_struct_frame_reg[0].frame_type = frame_type; + nic->g_struct_frame_reg[0].reg = reg; + } + break; + + case ACTION: + { + nic->g_struct_frame_reg[1].frame_type = frame_type; + nic->g_struct_frame_reg[1].reg = reg; + } + break; + + default: + { + break; + } + + } + /*If mac is closed, then return*/ + if (!g_linux_wlan->wilc1000_initialized) { + PRINT_D(GENERIC_DBG, "Return since mac is closed\n"); + return; + } + host_int_frame_register(priv->hWILCWFIDrv, frame_type, reg); + + +} +#endif +#endif /*WILC_P2P*/ + +/** + * @brief WILC_WFI_set_cqm_rssi_config + * @details Configure connection quality monitor RSSI threshold. + * @param[in] struct wiphy *wiphy: + * @param[in] struct net_device *dev: + * @param[in] s32 rssi_thold: + * @param[in] u32 rssi_hyst: + * @return int : Return 0 on Success + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_set_cqm_rssi_config(struct wiphy *wiphy, + struct net_device *dev, s32 rssi_thold, u32 rssi_hyst) +{ + PRINT_D(CFG80211_DBG, "Setting CQM RSSi Function\n"); + return 0; + +} +/** + * @brief WILC_WFI_dump_station + * @details Configure connection quality monitor RSSI threshold. + * @param[in] struct wiphy *wiphy: + * @param[in] struct net_device *dev + * @param[in] int idx + * @param[in] u8 *mac + * @param[in] struct station_info *sinfo + * @return int : Return 0 on Success + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_dump_station(struct wiphy *wiphy, struct net_device *dev, + int idx, u8 *mac, struct station_info *sinfo) +{ + struct WILC_WFI_priv *priv; + PRINT_D(CFG80211_DBG, "Dumping station information\n"); + + if (idx != 0) + return -ENOENT; + + priv = wiphy_priv(wiphy); + /* priv = netdev_priv(priv->wdev->netdev); */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) //0421 + sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); +#else + sinfo->filled |= STATION_INFO_SIGNAL; +#endif + + host_int_get_rssi(priv->hWILCWFIDrv, &(sinfo->signal)); + +#if 0 + sinfo->filled |= STATION_INFO_TX_BYTES | + STATION_INFO_TX_PACKETS | + STATION_INFO_RX_BYTES | + STATION_INFO_RX_PACKETS | STATION_INFO_SIGNAL | STATION_INFO_INACTIVE_TIME; + + WILC_SemaphoreAcquire(&SemHandleUpdateStats, NULL); + sinfo->inactive_time = priv->netstats.rx_time > priv->netstats.tx_time ? jiffies_to_msecs(jiffies - priv->netstats.tx_time) : jiffies_to_msecs(jiffies - priv->netstats.rx_time); + sinfo->rx_bytes = priv->netstats.rx_bytes; + sinfo->tx_bytes = priv->netstats.tx_bytes; + sinfo->rx_packets = priv->netstats.rx_packets; + sinfo->tx_packets = priv->netstats.tx_packets; + WILC_SemaphoreRelease(&SemHandleUpdateStats, NULL); +#endif + return 0; + +} + + +/** + * @brief WILC_WFI_set_power_mgmt + * @details + * @param[in] + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 JUL 2012 + * @version 1.0WILC_WFI_set_cqmWILC_WFI_set_cqm_rssi_configWILC_WFI_set_cqm_rssi_configWILC_WFI_set_cqm_rssi_configWILC_WFI_set_cqm_rssi_config_rssi_config + */ +int WILC_WFI_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, + bool enabled, int timeout) +{ + struct WILC_WFI_priv *priv; + PRINT_D(CFG80211_DBG, " Power save Enabled= %d , TimeOut = %d\n", enabled, timeout); + + if (wiphy == WILC_NULL) + return -ENOENT; + + priv = wiphy_priv(wiphy); + if (priv->hWILCWFIDrv == WILC_NULL) { + PRINT_ER("Driver is NULL\n"); + return -EIO; + } + + if (bEnablePS == WILC_TRUE) + host_int_set_power_mgmt(priv->hWILCWFIDrv, enabled, timeout); + + + return WILC_SUCCESS; + +} +#ifdef WILC_AP_EXTERNAL_MLME +/** + * @brief WILC_WFI_change_virt_intf + * @details Change type/configuration of virtual interface, + * keep the struct wireless_dev's iftype updated. + * @param[in] NONE + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +void wilc1000_wlan_deinit(linux_wlan_t *nic); +int wilc1000_wlan_init(struct net_device *dev, perInterface_wlan_t *p_nic); + +static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev, + enum nl80211_iftype type, u32 *flags, struct vif_params *params) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + struct WILC_WFI_priv *priv; + /* struct WILC_WFI_mon_priv* mon_priv; */ + perInterface_wlan_t *nic; + WILC_Uint8 interface_type; + WILC_Uint16 TID = 0; + #ifdef WILC_P2P + WILC_Uint8 i; + #endif + + nic = netdev_priv(dev); + priv = wiphy_priv(wiphy); + + PRINT_D(HOSTAPD_DBG, "In Change virtual interface function\n"); + PRINT_D(HOSTAPD_DBG, "Wireless interface name =%s\n", dev->name); + u8P2Plocalrandom = 0x01; + u8P2Precvrandom = 0x00; + + bWilc_ie = WILC_FALSE; + + #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP + g_obtainingIP = WILC_FALSE; + WILC_TimerStop(&hDuringIpTimer, WILC_NULL); + PRINT_D(GENERIC_DBG, "Changing virtual interface, enable scan\n"); + #endif + /*BugID_5137*/ + /*Set WILC_CHANGING_VIR_IF register to disallow adding futrue keys to CE H/W*/ + if (g_ptk_keys_saved && g_gtk_keys_saved) { + Set_machw_change_vir_if(WILC_TRUE); + } + + switch (type) { + case NL80211_IFTYPE_STATION: + connecting = 0; + PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_STATION\n"); + /* linux_wlan_set_bssid(dev,g_linux_wlan->strInterfaceInfo[0].aSrcAddress); */ + + /* send delba over wlan interface */ + + + dev->ieee80211_ptr->iftype = type; + priv->wdev->iftype = type; + nic->monitor_flag = 0; + nic->iftype = STATION_MODE; + + /*Remove the enteries of the previously connected clients*/ + memset(priv->assoc_stainfo.au8Sta_AssociatedBss, 0, MAX_NUM_STA * ETH_ALEN); + #ifndef SIMULATION + #ifdef WILC_P2P + interface_type = nic->iftype; + nic->iftype = STATION_MODE; + + if (g_linux_wlan->wilc1000_initialized) { + host_int_del_All_Rx_BASession(priv->hWILCWFIDrv, g_linux_wlan->strInterfaceInfo[0].aBSSID, TID); + /* ensure that the message Q is empty */ + host_int_wait_msg_queue_idle(); + + /*BugID_5213*/ + /*Eliminate host interface blocking state*/ + linux_wlan_unlock((void *)&g_linux_wlan->cfg_event); + + wilc1000_wlan_deinit(g_linux_wlan); + wilc1000_wlan_init(dev, nic); + g_wilc_initialized = 1; + nic->iftype = interface_type; + + /*Setting interface 1 drv handler and mac address in newly downloaded FW*/ + host_int_set_wfi_drv_handler(g_linux_wlan->strInterfaceInfo[0].drvHandler); + host_int_set_MacAddress((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler), + g_linux_wlan->strInterfaceInfo[0].aSrcAddress); + host_int_set_operation_mode(priv->hWILCWFIDrv, STATION_MODE); + + /*Add saved WEP keys, if any*/ + if (g_wep_keys_saved) { + host_int_set_WEPDefaultKeyID((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler), + g_key_wep_params.key_idx); + host_int_add_wep_key_bss_sta((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler), + g_key_wep_params.key, + g_key_wep_params.key_len, + g_key_wep_params.key_idx); + } + + /*No matter the driver handler passed here, it will be overwriiten*/ + /*in Handle_FlushConnect() with gu8FlushedJoinReqDrvHandler*/ + host_int_flush_join_req(priv->hWILCWFIDrv); + + /*Add saved PTK and GTK keys, if any*/ + if (g_ptk_keys_saved && g_gtk_keys_saved) { + PRINT_D(CFG80211_DBG, "ptk %x %x %x\n", g_key_ptk_params.key[0], + g_key_ptk_params.key[1], + g_key_ptk_params.key[2]); + PRINT_D(CFG80211_DBG, "gtk %x %x %x\n", g_key_gtk_params.key[0], + g_key_gtk_params.key[1], + g_key_gtk_params.key[2]); + WILC_WFI_add_key(g_linux_wlan->strInterfaceInfo[0].wilc_netdev->ieee80211_ptr->wiphy, + g_linux_wlan->strInterfaceInfo[0].wilc_netdev, + g_add_ptk_key_params.key_idx, + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) + g_add_ptk_key_params.pairwise, + #endif + g_add_ptk_key_params.mac_addr, + (struct key_params *)(&g_key_ptk_params)); + + WILC_WFI_add_key(g_linux_wlan->strInterfaceInfo[0].wilc_netdev->ieee80211_ptr->wiphy, + g_linux_wlan->strInterfaceInfo[0].wilc_netdev, + g_add_gtk_key_params.key_idx, + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) + g_add_gtk_key_params.pairwise, + #endif + g_add_gtk_key_params.mac_addr, + (struct key_params *)(&g_key_gtk_params)); + } + + /*BugID_4847: registered frames in firmware are now*/ + /*lost due to mac close. So re-register those frames*/ + if (g_linux_wlan->wilc1000_initialized) { + for (i = 0; i < num_reg_frame; i++) { + PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", nic->g_struct_frame_reg[i].frame_type, + nic->g_struct_frame_reg[i].reg); + host_int_frame_register(priv->hWILCWFIDrv, + nic->g_struct_frame_reg[i].frame_type, + nic->g_struct_frame_reg[i].reg); + } + } + + bEnablePS = WILC_TRUE; + host_int_set_power_mgmt(priv->hWILCWFIDrv, 1, 0); + } + #endif + #endif + break; + + case NL80211_IFTYPE_P2P_CLIENT: + bEnablePS = WILC_FALSE; + host_int_set_power_mgmt(priv->hWILCWFIDrv, 0, 0); + connecting = 0; + PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_P2P_CLIENT\n"); + /* linux_wlan_set_bssid(dev,g_linux_wlan->strInterfaceInfo[0].aSrcAddress); */ + + host_int_del_All_Rx_BASession(priv->hWILCWFIDrv, g_linux_wlan->strInterfaceInfo[0].aBSSID, TID); + + dev->ieee80211_ptr->iftype = type; + priv->wdev->iftype = type; + nic->monitor_flag = 0; + + #ifndef SIMULATION + #ifdef WILC_P2P + + PRINT_D(HOSTAPD_DBG, "Downloading P2P_CONCURRENCY_FIRMWARE\n"); + nic->iftype = CLIENT_MODE; + + + if (g_linux_wlan->wilc1000_initialized) { + /* ensure that the message Q is empty */ + host_int_wait_msg_queue_idle(); + + wilc1000_wlan_deinit(g_linux_wlan); + wilc1000_wlan_init(dev, nic); + g_wilc_initialized = 1; + + host_int_set_wfi_drv_handler(g_linux_wlan->strInterfaceInfo[0].drvHandler); + host_int_set_MacAddress((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler), + g_linux_wlan->strInterfaceInfo[0].aSrcAddress); + host_int_set_operation_mode(priv->hWILCWFIDrv, STATION_MODE); + + /*Add saved WEP keys, if any*/ + if (g_wep_keys_saved) { + host_int_set_WEPDefaultKeyID((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler), + g_key_wep_params.key_idx); + host_int_add_wep_key_bss_sta((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler), + g_key_wep_params.key, + g_key_wep_params.key_len, + g_key_wep_params.key_idx); + } + + /*No matter the driver handler passed here, it will be overwriiten*/ + /*in Handle_FlushConnect() with gu8FlushedJoinReqDrvHandler*/ + host_int_flush_join_req(priv->hWILCWFIDrv); + + /*Add saved PTK and GTK keys, if any*/ + if (g_ptk_keys_saved && g_gtk_keys_saved) { + PRINT_D(CFG80211_DBG, "ptk %x %x %x\n", g_key_ptk_params.key[0], + g_key_ptk_params.key[1], + g_key_ptk_params.key[2]); + PRINT_D(CFG80211_DBG, "gtk %x %x %x\n", g_key_gtk_params.key[0], + g_key_gtk_params.key[1], + g_key_gtk_params.key[2]); + WILC_WFI_add_key(g_linux_wlan->strInterfaceInfo[0].wilc_netdev->ieee80211_ptr->wiphy, + g_linux_wlan->strInterfaceInfo[0].wilc_netdev, + g_add_ptk_key_params.key_idx, + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) + g_add_ptk_key_params.pairwise, + #endif + g_add_ptk_key_params.mac_addr, + (struct key_params *)(&g_key_ptk_params)); + + WILC_WFI_add_key(g_linux_wlan->strInterfaceInfo[0].wilc_netdev->ieee80211_ptr->wiphy, + g_linux_wlan->strInterfaceInfo[0].wilc_netdev, + g_add_gtk_key_params.key_idx, + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) + g_add_gtk_key_params.pairwise, + #endif + g_add_gtk_key_params.mac_addr, + (struct key_params *)(&g_key_gtk_params)); + } + + /*Refresh scan, to refresh the scan results to the wpa_supplicant. Set MachHw to false to enable further key installments*/ + refresh_scan(priv, 1, WILC_TRUE); + Set_machw_change_vir_if(WILC_FALSE); + + /*BugID_4847: registered frames in firmware are now lost + * due to mac close. So re-register those frames */ + if (g_linux_wlan->wilc1000_initialized) { + for (i = 0; i < num_reg_frame; i++) { + PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", nic->g_struct_frame_reg[i].frame_type, + nic->g_struct_frame_reg[i].reg); + host_int_frame_register(priv->hWILCWFIDrv, + nic->g_struct_frame_reg[i].frame_type, + nic->g_struct_frame_reg[i].reg); + } + } + } + #endif + #endif + break; + + case NL80211_IFTYPE_AP: + /* connecting = 1; */ + bEnablePS = WILC_FALSE; + PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_AP %d\n", type); + /* linux_wlan_set_bssid(dev,g_linux_wlan->strInterfaceInfo[0].aSrcAddress); */ + /* mon_priv = netdev_priv(dev); */ + /* mon_priv->real_ndev = dev; */ + dev->ieee80211_ptr->iftype = type; + priv->wdev->iftype = type; + nic->iftype = AP_MODE; + PRINT_D(CORECONFIG_DBG, "(WILC_Uint32)priv->hWILCWFIDrv[%x]\n", (WILC_Uint32)priv->hWILCWFIDrv); + + #ifndef SIMULATION + PRINT_D(HOSTAPD_DBG, "Downloading AP firmware\n"); + linux_wlan_get_firmware(nic); + #ifdef WILC_P2P + /*If wilc is running, then close-open to actually get new firmware running (serves P2P)*/ + if (g_linux_wlan->wilc1000_initialized) { + nic->iftype = AP_MODE; + g_linux_wlan->wilc1000_initialized = 1; + mac_close(dev); + mac_open(dev); + + /* wilc1000_wlan_deinit(g_linux_wlan); */ + /* wilc1000_wlan_init(dev,nic); */ + /* repeat_power_cycle(nic); */ + /* nic->iftype = STATION_MODE; */ + + /*BugID_4847: registered frames in firmware are now lost + * due to mac close. So re-register those frames */ + for (i = 0; i < num_reg_frame; i++) { + PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", nic->g_struct_frame_reg[i].frame_type, + nic->g_struct_frame_reg[i].reg); + host_int_frame_register(priv->hWILCWFIDrv, + nic->g_struct_frame_reg[i].frame_type, + nic->g_struct_frame_reg[i].reg); + } + } + #endif + #endif + break; + + case NL80211_IFTYPE_P2P_GO: + PRINT_D(GENERIC_DBG, "start duringIP timer\n"); + + #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP + g_obtainingIP = WILC_TRUE; + WILC_TimerStart(&hDuringIpTimer, duringIP_TIME, WILC_NULL, WILC_NULL); + #endif + host_int_set_power_mgmt(priv->hWILCWFIDrv, 0, 0); + /*BugID_5222*/ + /*Delete block ack has to be the latest config packet*/ + /*sent before downloading new FW. This is because it blocks on*/ + /*hWaitResponse semaphore, which allows previous config*/ + /*packets to actually take action on old FW*/ + host_int_del_All_Rx_BASession(priv->hWILCWFIDrv, g_linux_wlan->strInterfaceInfo[0].aBSSID, TID); + bEnablePS = WILC_FALSE; + PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_GO\n"); + /* linux_wlan_set_bssid(dev,g_linux_wlan->strInterfaceInfo[0].aSrcAddress); */ + /* mon_priv = netdev_priv(dev); */ + /* mon_priv->real_ndev = dev; */ + dev->ieee80211_ptr->iftype = type; + priv->wdev->iftype = type; + + PRINT_D(CORECONFIG_DBG, "(WILC_Uint32)priv->hWILCWFIDrv[%x]\n", (WILC_Uint32)priv->hWILCWFIDrv); + /* host_int_set_operation_mode((WILC_Uint32)priv->hWILCWFIDrv,AP_MODE); */ + + #ifndef SIMULATION + #ifdef WILC_P2P + PRINT_D(HOSTAPD_DBG, "Downloading P2P_CONCURRENCY_FIRMWARE\n"); + + + #if 1 + nic->iftype = GO_MODE; + + /* ensure that the message Q is empty */ + host_int_wait_msg_queue_idle(); + + /*while(!g_hif_thread_idle) + * { + * PRINT_D(GENERIC_DBG, "Wait for host IF idle\n"); + * WILC_Sleep(10); + * }*/ + wilc1000_wlan_deinit(g_linux_wlan); + /* repeat_power_cycle_partially(g_linux_wlan); */ + wilc1000_wlan_init(dev, nic); + g_wilc_initialized = 1; + + + /*Setting interface 1 drv handler and mac address in newly downloaded FW*/ + host_int_set_wfi_drv_handler(g_linux_wlan->strInterfaceInfo[0].drvHandler); + host_int_set_MacAddress((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler), + g_linux_wlan->strInterfaceInfo[0].aSrcAddress); + host_int_set_operation_mode(priv->hWILCWFIDrv, AP_MODE); + + /*Add saved WEP keys, if any*/ + if (g_wep_keys_saved) { + host_int_set_WEPDefaultKeyID((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler), + g_key_wep_params.key_idx); + host_int_add_wep_key_bss_sta((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler), + g_key_wep_params.key, + g_key_wep_params.key_len, + g_key_wep_params.key_idx); + } + + /*No matter the driver handler passed here, it will be overwriiten*/ + /*in Handle_FlushConnect() with gu8FlushedJoinReqDrvHandler*/ + host_int_flush_join_req(priv->hWILCWFIDrv); + + /*Add saved PTK and GTK keys, if any*/ + if (g_ptk_keys_saved && g_gtk_keys_saved) { + PRINT_D(CFG80211_DBG, "ptk %x %x %x cipher %x\n", g_key_ptk_params.key[0], + g_key_ptk_params.key[1], + g_key_ptk_params.key[2], + g_key_ptk_params.cipher); + PRINT_D(CFG80211_DBG, "gtk %x %x %x cipher %x\n", g_key_gtk_params.key[0], + g_key_gtk_params.key[1], + g_key_gtk_params.key[2], + g_key_gtk_params.cipher); + #if 1 + WILC_WFI_add_key(g_linux_wlan->strInterfaceInfo[0].wilc_netdev->ieee80211_ptr->wiphy, + g_linux_wlan->strInterfaceInfo[0].wilc_netdev, + g_add_ptk_key_params.key_idx, + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) + g_add_ptk_key_params.pairwise, + #endif + g_add_ptk_key_params.mac_addr, + (struct key_params *)(&g_key_ptk_params)); + + WILC_WFI_add_key(g_linux_wlan->strInterfaceInfo[0].wilc_netdev->ieee80211_ptr->wiphy, + g_linux_wlan->strInterfaceInfo[0].wilc_netdev, + g_add_gtk_key_params.key_idx, + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) + g_add_gtk_key_params.pairwise, + #endif + g_add_gtk_key_params.mac_addr, + (struct key_params *)(&g_key_gtk_params)); + #endif + } + #endif + + /*BugID_4847: registered frames in firmware are now*/ + /*lost due to mac close. So re-register those frames*/ + if (g_linux_wlan->wilc1000_initialized) { + for (i = 0; i < num_reg_frame; i++) { + PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", nic->g_struct_frame_reg[i].frame_type, + nic->g_struct_frame_reg[i].reg); + host_int_frame_register(priv->hWILCWFIDrv, + nic->g_struct_frame_reg[i].frame_type, + nic->g_struct_frame_reg[i].reg); + } + } + #endif + #endif + break; + + default: + PRINT_ER("Unknown interface type= %d\n", type); + s32Error = -EINVAL; + return s32Error; + break; + } + + return s32Error; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +/* (austin.2013-07-23) + * + * To support revised cfg80211_ops + * + * add_beacon --> start_ap + * set_beacon --> change_beacon + * del_beacon --> stop_ap + * + * beacon_parameters --> cfg80211_ap_settings + * cfg80211_beacon_data + * + * applicable for linux kernel 3.4+ + */ + +/** + * @brief WILC_WFI_start_ap + * @details Add a beacon with given parameters, @head, @interval + * and @dtim_period will be valid, @tail is optional. + * @param[in] wiphy + * @param[in] dev The net device structure + * @param[in] settings cfg80211_ap_settings parameters for the beacon to be added + * @return int : Return 0 on Success. + * @author austin + * @date 23 JUL 2013 + * @version 1.0 + */ +static int WILC_WFI_start_ap(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_ap_settings *settings) +{ + struct cfg80211_beacon_data *beacon = &(settings->beacon); + struct WILC_WFI_priv *priv; + WILC_Sint32 s32Error = WILC_SUCCESS; + + priv = wiphy_priv(wiphy); + PRINT_D(HOSTAPD_DBG, "Starting ap\n"); + + PRINT_D(HOSTAPD_DBG, "Interval = %d \n DTIM period = %d\n Head length = %d Tail length = %d\n", + settings->beacon_interval, settings->dtim_period, beacon->head_len, beacon->tail_len); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) + s32Error = WILC_WFI_CfgSetChannel(wiphy, &settings->chandef); + + if (s32Error != WILC_SUCCESS) + PRINT_ER("Error in setting channel\n"); +#endif + + linux_wlan_set_bssid(dev, g_linux_wlan->strInterfaceInfo[0].aSrcAddress); + + #ifndef WILC_FULLY_HOSTING_AP + s32Error = host_int_add_beacon(priv->hWILCWFIDrv, + settings->beacon_interval, + settings->dtim_period, + beacon->head_len, (WILC_Uint8 *)beacon->head, + beacon->tail_len, (WILC_Uint8 *)beacon->tail); + #else + s32Error = host_add_beacon(priv->hWILCWFIDrv, + settings->beacon_interval, + settings->dtim_period, + beacon->head_len, (WILC_Uint8 *)beacon->head, + beacon->tail_len, (WILC_Uint8 *)beacon->tail); + #endif + + return s32Error; +} + +/** + * @brief WILC_WFI_change_beacon + * @details Add a beacon with given parameters, @head, @interval + * and @dtim_period will be valid, @tail is optional. + * @param[in] wiphy + * @param[in] dev The net device structure + * @param[in] beacon cfg80211_beacon_data for the beacon to be changed + * @return int : Return 0 on Success. + * @author austin + * @date 23 JUL 2013 + * @version 1.0 + */ +static int WILC_WFI_change_beacon(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_beacon_data *beacon) +{ + struct WILC_WFI_priv *priv; + WILC_Sint32 s32Error = WILC_SUCCESS; + + priv = wiphy_priv(wiphy); + PRINT_D(HOSTAPD_DBG, "Setting beacon\n"); + + +#ifndef WILC_FULLY_HOSTING_AP + s32Error = host_int_add_beacon(priv->hWILCWFIDrv, + 0, + 0, + beacon->head_len, (WILC_Uint8 *)beacon->head, + beacon->tail_len, (WILC_Uint8 *)beacon->tail); +#else + s32Error = host_add_beacon(priv->hWILCWFIDrv, + 0, + 0, + beacon->head_len, (WILC_Uint8 *)beacon->head, + beacon->tail_len, (WILC_Uint8 *)beacon->tail); +#endif + + return s32Error; +} + +/** + * @brief WILC_WFI_stop_ap + * @details Remove beacon configuration and stop sending the beacon. + * @param[in] + * @return int : Return 0 on Success. + * @author austin + * @date 23 JUL 2013 + * @version 1.0 + */ +static int WILC_WFI_stop_ap(struct wiphy *wiphy, struct net_device *dev) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + struct WILC_WFI_priv *priv; + WILC_Uint8 NullBssid[ETH_ALEN] = {0}; + + + WILC_NULLCHECK(s32Error, wiphy); + + priv = wiphy_priv(wiphy); + + PRINT_D(HOSTAPD_DBG, "Deleting beacon\n"); + + /*BugID_5188*/ + linux_wlan_set_bssid(dev, NullBssid); + + #ifndef WILC_FULLY_HOSTING_AP + s32Error = host_int_del_beacon(priv->hWILCWFIDrv); + #else + s32Error = host_del_beacon(priv->hWILCWFIDrv); + #endif + + WILC_ERRORCHECK(s32Error); + + WILC_CATCH(s32Error) + { + } + return s32Error; +} + +#else /* here belows are original for < kernel 3.3 (austin.2013-07-23) */ + +/** + * @brief WILC_WFI_add_beacon + * @details Add a beacon with given parameters, @head, @interval + * and @dtim_period will be valid, @tail is optional. + * @param[in] wiphy + * @param[in] dev The net device structure + * @param[in] info Parameters for the beacon to be added + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_add_beacon(struct wiphy *wiphy, struct net_device *dev, + struct beacon_parameters *info) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + struct WILC_WFI_priv *priv; + + + + priv = wiphy_priv(wiphy); + PRINT_D(HOSTAPD_DBG, "Adding Beacon\n"); + + PRINT_D(HOSTAPD_DBG, "Interval = %d \n DTIM period = %d\n Head length = %d Tail length = %d\n", info->interval, info->dtim_period, info->head_len, info->tail_len); + + linux_wlan_set_bssid(dev, g_linux_wlan->strInterfaceInfo[0].aSrcAddress); + + #ifndef WILC_FULLY_HOSTING_AP + s32Error = host_int_add_beacon(priv->hWILCWFIDrv, info->interval, + info->dtim_period, + info->head_len, info->head, + info->tail_len, info->tail); + + #else + s32Error = host_add_beacon(priv->hWILCWFIDrv, info->interval, + info->dtim_period, + info->head_len, info->head, + info->tail_len, info->tail); + #endif + + return s32Error; +} + +/** + * @brief WILC_WFI_set_beacon + * @details Change the beacon parameters for an access point mode + * interface. This should reject the call when no beacon has been + * configured. + * @param[in] + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_set_beacon(struct wiphy *wiphy, struct net_device *dev, + struct beacon_parameters *info) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + + + PRINT_D(HOSTAPD_DBG, "Setting beacon\n"); + + s32Error = WILC_WFI_add_beacon(wiphy, dev, info); + + return s32Error; +} + +/** + * @brief WILC_WFI_del_beacon + * @details Remove beacon configuration and stop sending the beacon. + * @param[in] + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_del_beacon(struct wiphy *wiphy, struct net_device *dev) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + struct WILC_WFI_priv *priv; + WILC_Uint8 NullBssid[ETH_ALEN] = {0}; + + + WILC_NULLCHECK(s32Error, wiphy); + + priv = wiphy_priv(wiphy); + + PRINT_D(HOSTAPD_DBG, "Deleting beacon\n"); + + /*BugID_5188*/ + linux_wlan_set_bssid(dev, NullBssid); + + #ifndef WILC_FULLY_HOSTING_AP + s32Error = host_int_del_beacon(priv->hWILCWFIDrv); + #else + s32Error = host_del_beacon(priv->hWILCWFIDrv); + #endif + + WILC_ERRORCHECK(s32Error); + + WILC_CATCH(s32Error) + { + } + return s32Error; +} + +#endif /* linux kernel 3.4+ (austin.2013-07-23) */ + +/** + * @brief WILC_WFI_add_station + * @details Add a new station. + * @param[in] + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_add_station(struct wiphy *wiphy, struct net_device *dev, + u8 *mac, struct station_parameters *params) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + struct WILC_WFI_priv *priv; + tstrWILC_AddStaParam strStaParams = {{0}}; + perInterface_wlan_t *nic; + + + WILC_NULLCHECK(s32Error, wiphy); + + priv = wiphy_priv(wiphy); + nic = netdev_priv(dev); + + if (nic->iftype == AP_MODE || nic->iftype == GO_MODE) { + #ifndef WILC_FULLY_HOSTING_AP + + WILC_memcpy(strStaParams.au8BSSID, mac, ETH_ALEN); + WILC_memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid], mac, ETH_ALEN); + strStaParams.u16AssocID = params->aid; + strStaParams.u8NumRates = params->supported_rates_len; + strStaParams.pu8Rates = params->supported_rates; + + PRINT_D(CFG80211_DBG, "Adding station parameters %d\n", params->aid); + + PRINT_D(CFG80211_DBG, "BSSID = %x%x%x%x%x%x\n", priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][0], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][1], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][2], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][3], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][4], + priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][5]); + PRINT_D(HOSTAPD_DBG, "ASSOC ID = %d\n", strStaParams.u16AssocID); + PRINT_D(HOSTAPD_DBG, "Number of supported rates = %d\n", strStaParams.u8NumRates); + + if (params->ht_capa == WILC_NULL) { + strStaParams.bIsHTSupported = WILC_FALSE; + } else { + strStaParams.bIsHTSupported = WILC_TRUE; + strStaParams.u16HTCapInfo = params->ht_capa->cap_info; + strStaParams.u8AmpduParams = params->ht_capa->ampdu_params_info; + WILC_memcpy(strStaParams.au8SuppMCsSet, ¶ms->ht_capa->mcs, WILC_SUPP_MCS_SET_SIZE); + strStaParams.u16HTExtParams = params->ht_capa->extended_ht_cap_info; + strStaParams.u32TxBeamformingCap = params->ht_capa->tx_BF_cap_info; + strStaParams.u8ASELCap = params->ht_capa->antenna_selection_info; + } + + strStaParams.u16FlagsMask = params->sta_flags_mask; + strStaParams.u16FlagsSet = params->sta_flags_set; + + PRINT_D(HOSTAPD_DBG, "IS HT supported = %d\n", strStaParams.bIsHTSupported); + PRINT_D(HOSTAPD_DBG, "Capability Info = %d\n", strStaParams.u16HTCapInfo); + PRINT_D(HOSTAPD_DBG, "AMPDU Params = %d\n", strStaParams.u8AmpduParams); + PRINT_D(HOSTAPD_DBG, "HT Extended params = %d\n", strStaParams.u16HTExtParams); + PRINT_D(HOSTAPD_DBG, "Tx Beamforming Cap = %d\n", strStaParams.u32TxBeamformingCap); + PRINT_D(HOSTAPD_DBG, "Antenna selection info = %d\n", strStaParams.u8ASELCap); + PRINT_D(HOSTAPD_DBG, "Flag Mask = %d\n", strStaParams.u16FlagsMask); + PRINT_D(HOSTAPD_DBG, "Flag Set = %d\n", strStaParams.u16FlagsSet); + + s32Error = host_int_add_station(priv->hWILCWFIDrv, &strStaParams); + WILC_ERRORCHECK(s32Error); + + #else + PRINT_D(CFG80211_DBG, "Adding station parameters %d\n", params->aid); + WILC_memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid], mac, ETH_ALEN); + + PRINT_D(CFG80211_DBG, "BSSID = %x%x%x%x%x%x\n", priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][0], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][1], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][2], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][3], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][4], + priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][5]); + + WILC_AP_AddSta(mac, params); + WILC_ERRORCHECK(s32Error); + #endif /* WILC_FULLY_HOSTING_AP */ + + } + + WILC_CATCH(s32Error) + { + } + return s32Error; +} + +/** + * @brief WILC_WFI_del_station + * @details Remove a station; @mac may be NULL to remove all stations. + * @param[in] + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_del_station(struct wiphy *wiphy, struct net_device *dev, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) + struct station_del_parameters *params) +#else + u8 *mac) +#endif +{ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) + u8 *mac = params->mac; + #endif + WILC_Sint32 s32Error = WILC_SUCCESS; + struct WILC_WFI_priv *priv; + perInterface_wlan_t *nic; + WILC_NULLCHECK(s32Error, wiphy); + /*BugID_4795: mac may be null pointer to indicate deleting all stations, so avoid null check*/ + /* WILC_NULLCHECK(s32Error, mac); */ + + priv = wiphy_priv(wiphy); + nic = netdev_priv(dev); + + if (nic->iftype == AP_MODE || nic->iftype == GO_MODE) { + PRINT_D(HOSTAPD_DBG, "Deleting station\n"); + + + if (mac == WILC_NULL) { + PRINT_D(HOSTAPD_DBG, "All associated stations \n"); + s32Error = host_int_del_allstation(priv->hWILCWFIDrv, priv->assoc_stainfo.au8Sta_AssociatedBss); + } else { + PRINT_D(HOSTAPD_DBG, "With mac address: %x%x%x%x%x%x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + } + + #ifndef WILC_FULLY_HOSTING_AP + s32Error = host_int_del_station(priv->hWILCWFIDrv, mac); + #else + WILC_AP_RemoveSta(mac); + #endif /* WILC_FULLY_HOSTING_AP */ + + WILC_ERRORCHECK(s32Error); + } + WILC_CATCH(s32Error) + { + } + return s32Error; +} + +/** + * @brief WILC_WFI_change_station + * @details Modify a given station. + * @param[in] + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_change_station(struct wiphy *wiphy, struct net_device *dev, + u8 *mac, struct station_parameters *params) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + struct WILC_WFI_priv *priv; + tstrWILC_AddStaParam strStaParams = {{0}}; + perInterface_wlan_t *nic; + + + PRINT_D(HOSTAPD_DBG, "Change station paramters\n"); + + WILC_NULLCHECK(s32Error, wiphy); + + priv = wiphy_priv(wiphy); + nic = netdev_priv(dev); + + if (nic->iftype == AP_MODE || nic->iftype == GO_MODE) { + #ifndef WILC_FULLY_HOSTING_AP + + WILC_memcpy(strStaParams.au8BSSID, mac, ETH_ALEN); + strStaParams.u16AssocID = params->aid; + strStaParams.u8NumRates = params->supported_rates_len; + strStaParams.pu8Rates = params->supported_rates; + + PRINT_D(HOSTAPD_DBG, "BSSID = %x%x%x%x%x%x\n", strStaParams.au8BSSID[0], strStaParams.au8BSSID[1], strStaParams.au8BSSID[2], strStaParams.au8BSSID[3], strStaParams.au8BSSID[4], + strStaParams.au8BSSID[5]); + PRINT_D(HOSTAPD_DBG, "ASSOC ID = %d\n", strStaParams.u16AssocID); + PRINT_D(HOSTAPD_DBG, "Number of supported rates = %d\n", strStaParams.u8NumRates); + + if (params->ht_capa == WILC_NULL) { + strStaParams.bIsHTSupported = WILC_FALSE; + } else { + strStaParams.bIsHTSupported = WILC_TRUE; + strStaParams.u16HTCapInfo = params->ht_capa->cap_info; + strStaParams.u8AmpduParams = params->ht_capa->ampdu_params_info; + WILC_memcpy(strStaParams.au8SuppMCsSet, ¶ms->ht_capa->mcs, WILC_SUPP_MCS_SET_SIZE); + strStaParams.u16HTExtParams = params->ht_capa->extended_ht_cap_info; + strStaParams.u32TxBeamformingCap = params->ht_capa->tx_BF_cap_info; + strStaParams.u8ASELCap = params->ht_capa->antenna_selection_info; + + } + + strStaParams.u16FlagsMask = params->sta_flags_mask; + strStaParams.u16FlagsSet = params->sta_flags_set; + + PRINT_D(HOSTAPD_DBG, "IS HT supported = %d\n", strStaParams.bIsHTSupported); + PRINT_D(HOSTAPD_DBG, "Capability Info = %d\n", strStaParams.u16HTCapInfo); + PRINT_D(HOSTAPD_DBG, "AMPDU Params = %d\n", strStaParams.u8AmpduParams); + PRINT_D(HOSTAPD_DBG, "HT Extended params = %d\n", strStaParams.u16HTExtParams); + PRINT_D(HOSTAPD_DBG, "Tx Beamforming Cap = %d\n", strStaParams.u32TxBeamformingCap); + PRINT_D(HOSTAPD_DBG, "Antenna selection info = %d\n", strStaParams.u8ASELCap); + PRINT_D(HOSTAPD_DBG, "Flag Mask = %d\n", strStaParams.u16FlagsMask); + PRINT_D(HOSTAPD_DBG, "Flag Set = %d\n", strStaParams.u16FlagsSet); + + s32Error = host_int_edit_station(priv->hWILCWFIDrv, &strStaParams); + WILC_ERRORCHECK(s32Error); + + #else + WILC_AP_EditSta(mac, params); + WILC_ERRORCHECK(s32Error); + #endif /* WILC_FULLY_HOSTING_AP */ + + } + WILC_CATCH(s32Error) + { + } + return s32Error; +} + + +/** + * @brief WILC_WFI_add_virt_intf + * @details + * @param[in] + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 JUL 2012 + * @version 1.0 + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) +struct wireless_dev *WILC_WFI_add_virt_intf(struct wiphy *wiphy, const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) /* tony for v3.8 support */ +struct wireless_dev *WILC_WFI_add_virt_intf(struct wiphy *wiphy, const char *name, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) /* tony for v3.6 support */ +struct wireless_dev *WILC_WFI_add_virt_intf(struct wiphy *wiphy, char *name, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) +int WILC_WFI_add_virt_intf(struct wiphy *wiphy, char *name, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +#else +struct net_device *WILC_WFI_add_virt_intf(struct wiphy *wiphy, char *name, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +#endif +{ + perInterface_wlan_t *nic; + struct WILC_WFI_priv *priv; + /* struct WILC_WFI_mon_priv* mon_priv; */ + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) + WILC_Sint32 s32Error = WILC_SUCCESS; + #endif + struct net_device *new_ifc = NULL; + priv = wiphy_priv(wiphy); + + + + PRINT_D(HOSTAPD_DBG, "Adding monitor interface[%p]\n", priv->wdev->netdev); + + nic = netdev_priv(priv->wdev->netdev); + + + if (type == NL80211_IFTYPE_MONITOR) { + PRINT_D(HOSTAPD_DBG, "Monitor interface mode: Initializing mon interface virtual device driver\n"); + PRINT_D(HOSTAPD_DBG, "Adding monitor interface[%p]\n", nic->wilc_netdev); + new_ifc = WILC_WFI_init_mon_interface(name, nic->wilc_netdev); + if (new_ifc != NULL) { + PRINT_D(HOSTAPD_DBG, "Setting monitor flag in private structure\n"); + #ifdef SIMULATION + priv = netdev_priv(priv->wdev->netdev); + priv->monitor_flag = 1; + #else + nic = netdev_priv(priv->wdev->netdev); + nic->monitor_flag = 1; + #endif + } else + PRINT_ER("Error in initializing monitor interface\n "); + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) /* tony for v3.8 support */ + return priv->wdev; +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) + return s32Error; +#else + /* return priv->wdev->netdev; */ + PRINT_D(HOSTAPD_DBG, "IFC[%p] created\n", new_ifc); + return new_ifc; +#endif + +} + +/** + * @brief WILC_WFI_del_virt_intf + * @details + * @param[in] + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 JUL 2012 + * @version 1.0 + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) +int WILC_WFI_del_virt_intf(struct wiphy *wiphy, struct wireless_dev *wdev) /* tony for v3.8 support */ +#else +int WILC_WFI_del_virt_intf(struct wiphy *wiphy, struct net_device *dev) +#endif +{ + PRINT_D(HOSTAPD_DBG, "Deleting virtual interface\n"); + return WILC_SUCCESS; +} + + + +#endif /*WILC_AP_EXTERNAL_MLME*/ +static struct cfg80211_ops WILC_WFI_cfg80211_ops = { + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) + /* + * replaced set_channel by set_monitor_channel + * from v3.6 + * tony, 2013-10-29 + */ + .set_monitor_channel = WILC_WFI_CfgSetChannel, +#else + .set_channel = WILC_WFI_CfgSetChannel, +#endif + .scan = WILC_WFI_CfgScan, + .connect = WILC_WFI_CfgConnect, + .disconnect = WILC_WFI_disconnect, + .add_key = WILC_WFI_add_key, + .del_key = WILC_WFI_del_key, + .get_key = WILC_WFI_get_key, + .set_default_key = WILC_WFI_set_default_key, +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32) + /* .dump_survey = WILC_WFI_dump_survey, */ +#endif + #ifdef WILC_AP_EXTERNAL_MLME + .add_virtual_intf = WILC_WFI_add_virt_intf, + .del_virtual_intf = WILC_WFI_del_virt_intf, + .change_virtual_intf = WILC_WFI_change_virt_intf, + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) + .add_beacon = WILC_WFI_add_beacon, + .set_beacon = WILC_WFI_set_beacon, + .del_beacon = WILC_WFI_del_beacon, +#else + /* supports kernel 3.4+ change. austin.2013-07-23 */ + .start_ap = WILC_WFI_start_ap, + .change_beacon = WILC_WFI_change_beacon, + .stop_ap = WILC_WFI_stop_ap, +#endif + .add_station = WILC_WFI_add_station, + .del_station = WILC_WFI_del_station, + .change_station = WILC_WFI_change_station, + #endif /* WILC_AP_EXTERNAL_MLME*/ + #ifndef WILC_FULLY_HOSTING_AP + .get_station = WILC_WFI_get_station, + #endif + .dump_station = WILC_WFI_dump_station, + .change_bss = WILC_WFI_change_bss, + /* .auth = WILC_WFI_auth, */ + /* .assoc = WILC_WFI_assoc, */ + /* .deauth = WILC_WFI_deauth, */ + /* .disassoc = WILC_WFI_disassoc, */ + .set_wiphy_params = WILC_WFI_set_wiphy_params, + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32) + /* .set_bitrate_mask = WILC_WFI_set_bitrate_mask, */ + .set_pmksa = WILC_WFI_set_pmksa, + .del_pmksa = WILC_WFI_del_pmksa, + .flush_pmksa = WILC_WFI_flush_pmksa, +#ifdef WILC_P2P + .remain_on_channel = WILC_WFI_remain_on_channel, + .cancel_remain_on_channel = WILC_WFI_cancel_remain_on_channel, + .mgmt_tx_cancel_wait = WILC_WFI_mgmt_tx_cancel_wait, + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) + .action = WILC_WFI_action, + #endif + #else + .mgmt_tx = WILC_WFI_mgmt_tx, + .mgmt_frame_register = WILC_WFI_frame_register, + #endif +#endif + /* .mgmt_tx_cancel_wait = WILC_WFI_mgmt_tx_cancel_wait, */ + .set_power_mgmt = WILC_WFI_set_power_mgmt, + .set_cqm_rssi_config = WILC_WFI_set_cqm_rssi_config, +#endif + +}; + + + + + +/** + * @brief WILC_WFI_update_stats + * @details Modify parameters for a given BSS. + * @param[in] + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0WILC_WFI_set_cqmWILC_WFI_set_cqm_rssi_configWILC_WFI_set_cqm_rssi_configWILC_WFI_set_cqm_rssi_configWILC_WFI_set_cqm_rssi_config_rssi_config + */ +int WILC_WFI_update_stats(struct wiphy *wiphy, u32 pktlen, u8 changed) +{ + + struct WILC_WFI_priv *priv; + + priv = wiphy_priv(wiphy); + /* WILC_SemaphoreAcquire(&SemHandleUpdateStats,NULL); */ +#if 1 + switch (changed) { + + case WILC_WFI_RX_PKT: + { + /* MI_PRINTF("In Rx Receive Packet\n"); */ + priv->netstats.rx_packets++; + priv->netstats.rx_bytes += pktlen; + priv->netstats.rx_time = get_jiffies_64(); + } + break; + + case WILC_WFI_TX_PKT: + { + priv->netstats.tx_packets++; + priv->netstats.tx_bytes += pktlen; + priv->netstats.tx_time = get_jiffies_64(); + + } + break; + + default: + break; + } + /* WILC_SemaphoreRelease(&SemHandleUpdateStats,NULL); */ +#endif + return 0; +} +/** + * @brief WILC_WFI_InitPriv + * @details Initialization of the net device, private data + * @param[in] NONE + * @return NONE + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +void WILC_WFI_InitPriv(struct net_device *dev) +{ + + struct WILC_WFI_priv *priv; + priv = netdev_priv(dev); + + priv->netstats.rx_packets = 0; + priv->netstats.tx_packets = 0; + priv->netstats.rx_bytes = 0; + priv->netstats.rx_bytes = 0; + priv->netstats.rx_time = 0; + priv->netstats.tx_time = 0; + + +} +/** + * @brief WILC_WFI_CfgAlloc + * @details Allocation of the wireless device structure and assigning it + * to the cfg80211 operations structure. + * @param[in] NONE + * @return wireless_dev : Returns pointer to wireless_dev structure. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +struct wireless_dev *WILC_WFI_CfgAlloc(void) +{ + + struct wireless_dev *wdev; + + + PRINT_D(CFG80211_DBG, "Allocating wireless device\n"); + /*Allocating the wireless device structure*/ + wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!wdev) { + PRINT_ER("Cannot allocate wireless device\n"); + goto _fail_; + } + + /*Creating a new wiphy, linking wireless structure with the wiphy structure*/ + wdev->wiphy = wiphy_new(&WILC_WFI_cfg80211_ops, sizeof(struct WILC_WFI_priv)); + if (!wdev->wiphy) { + PRINT_ER("Cannot allocate wiphy\n"); + goto _fail_mem_; + + } + + #ifdef WILC_AP_EXTERNAL_MLME + /* enable 802.11n HT */ + WILC_WFI_band_2ghz.ht_cap.ht_supported = 1; + WILC_WFI_band_2ghz.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); + WILC_WFI_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff; + WILC_WFI_band_2ghz.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K; + WILC_WFI_band_2ghz.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE; + #endif + + /*wiphy bands*/ + wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &WILC_WFI_band_2ghz; + + return wdev; + +_fail_mem_: + kfree(wdev); +_fail_: + return NULL; + +} +/** + * @brief WILC_WFI_WiphyRegister + * @details Registering of the wiphy structure and interface modes + * @param[in] NONE + * @return NONE + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +struct wireless_dev *WILC_WFI_WiphyRegister(struct net_device *net) +{ + struct WILC_WFI_priv *priv; + struct wireless_dev *wdev; + WILC_Sint32 s32Error = WILC_SUCCESS; + + PRINT_D(CFG80211_DBG, "Registering wifi device\n"); + + wdev = WILC_WFI_CfgAlloc(); + if (wdev == NULL) { + PRINT_ER("CfgAlloc Failed\n"); + return NULL; + } + + + /*Return hardware description structure (wiphy)'s priv*/ + priv = wdev_priv(wdev); + WILC_SemaphoreCreate(&(priv->SemHandleUpdateStats), NULL); + + /*Link the wiphy with wireless structure*/ + priv->wdev = wdev; + + /*Maximum number of probed ssid to be added by user for the scan request*/ + wdev->wiphy->max_scan_ssids = MAX_NUM_PROBED_SSID; + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32) + /*Maximum number of pmkids to be cashed*/ + wdev->wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS; + PRINT_INFO(CFG80211_DBG, "Max number of PMKIDs = %d\n", wdev->wiphy->max_num_pmkids); + #endif + + wdev->wiphy->max_scan_ie_len = 1000; + + /*signal strength in mBm (100*dBm) */ + wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + + /*Set the availaible cipher suites*/ + wdev->wiphy->cipher_suites = cipher_suites; + wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) + /*Setting default managment types: for register action frame: */ + wdev->wiphy->mgmt_stypes = wilc_wfi_cfg80211_mgmt_types; +#endif + +#ifdef WILC_P2P + wdev->wiphy->max_remain_on_channel_duration = 500; + /*Setting the wiphy interfcae mode and type before registering the wiphy*/ + wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR) | BIT(NL80211_IFTYPE_P2P_GO) | + BIT(NL80211_IFTYPE_P2P_CLIENT); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) + + wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; +#endif +#else + wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR); +#endif + wdev->iftype = NL80211_IFTYPE_STATION; + + + + PRINT_INFO(CFG80211_DBG, "Max scan ids = %d,Max scan IE len = %d,Signal Type = %d,Interface Modes = %d,Interface Type = %d\n", + wdev->wiphy->max_scan_ssids, wdev->wiphy->max_scan_ie_len, wdev->wiphy->signal_type, + wdev->wiphy->interface_modes, wdev->iftype); + + #ifdef WILC_SDIO + set_wiphy_dev(wdev->wiphy, &local_sdio_func->dev); /* tony */ + #endif + + /*Register wiphy structure*/ + s32Error = wiphy_register(wdev->wiphy); + if (s32Error) { + PRINT_ER("Cannot register wiphy device\n"); + /*should define what action to be taken in such failure*/ + } else { + PRINT_D(CFG80211_DBG, "Successful Registering\n"); + } + +#if 0 + /*wdev[i]->wiphy->interface_modes = + * BIT(NL80211_IFTYPE_AP); + * wdev[i]->iftype = NL80211_IFTYPE_AP; + */ + + /*Pointing the priv structure the netdev*/ + priv = netdev_priv(net); + + /*linking the wireless_dev structure with the netdevice*/ + priv->dev->ieee80211_ptr = wdev; + priv->dev->ml_priv = priv; + wdev->netdev = priv->dev; +#endif + priv->dev = net; +#if 0 + ret = host_int_init(&priv->hWILCWFIDrv); + if (ret) { + PRINT_ER("Error Init Driver\n"); + } +#endif + return wdev; + + +} +/** + * @brief WILC_WFI_WiphyFree + * @details Freeing allocation of the wireless device structure + * @param[in] NONE + * @return NONE + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +int WILC_WFI_InitHostInt(struct net_device *net) +{ + + WILC_Sint32 s32Error = WILC_SUCCESS; + + struct WILC_WFI_priv *priv; + + tstrWILC_SemaphoreAttrs strSemaphoreAttrs; + + PRINT_D(INIT_DBG, "Host[%p][%p]\n", net, net->ieee80211_ptr); + priv = wdev_priv(net->ieee80211_ptr); + if (op_ifcs == 0) { + s32Error = WILC_TimerCreate(&(hAgingTimer), remove_network_from_shadow, WILC_NULL); + #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP + s32Error = WILC_TimerCreate(&(hDuringIpTimer), clear_duringIP, WILC_NULL); + #endif + } + op_ifcs++; + if (s32Error < 0) { + PRINT_ER("Failed to creat refresh Timer\n"); + return s32Error; + } + + WILC_SemaphoreFillDefault(&strSemaphoreAttrs); + + /* /////////////////////////////////////// */ + /* strSemaphoreAttrs.u32InitCount = 0; */ + + + priv->gbAutoRateAdjusted = WILC_FALSE; + + priv->bInP2PlistenState = WILC_FALSE; + + WILC_SemaphoreCreate(&(priv->hSemScanReq), &strSemaphoreAttrs); + s32Error = host_int_init(&priv->hWILCWFIDrv); + /* s32Error = host_int_init(&priv->hWILCWFIDrv_2); */ + if (s32Error) { + PRINT_ER("Error while initializing hostinterface\n"); + } + return s32Error; +} + +/** + * @brief WILC_WFI_WiphyFree + * @details Freeing allocation of the wireless device structure + * @param[in] NONE + * @return NONE + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +int WILC_WFI_DeInitHostInt(struct net_device *net) +{ + WILC_Sint32 s32Error = WILC_SUCCESS; + + struct WILC_WFI_priv *priv; + priv = wdev_priv(net->ieee80211_ptr); + + + + + + + WILC_SemaphoreDestroy(&(priv->hSemScanReq), NULL); + + priv->gbAutoRateAdjusted = WILC_FALSE; + + priv->bInP2PlistenState = WILC_FALSE; + + op_ifcs--; + + s32Error = host_int_deinit(priv->hWILCWFIDrv); + /* s32Error = host_int_deinit(priv->hWILCWFIDrv_2); */ + + /* Clear the Shadow scan */ + clear_shadow_scan(priv); + #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP + if (op_ifcs == 0) { + PRINT_D(CORECONFIG_DBG, "destroy during ip\n"); + WILC_TimerDestroy(&hDuringIpTimer, WILC_NULL); + } + #endif + + if (s32Error) { + PRINT_ER("Error while deintializing host interface\n"); + } + return s32Error; +} + + +/** + * @brief WILC_WFI_WiphyFree + * @details Freeing allocation of the wireless device structure + * @param[in] NONE + * @return NONE + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +void WILC_WFI_WiphyFree(struct net_device *net) +{ + + PRINT_D(CFG80211_DBG, "Unregistering wiphy\n"); + + if (net == NULL) { + PRINT_D(INIT_DBG, "net_device is NULL\n"); + return; + } + + if (net->ieee80211_ptr == NULL) { + PRINT_D(INIT_DBG, "ieee80211_ptr is NULL\n"); + return; + } + + if (net->ieee80211_ptr->wiphy == NULL) { + PRINT_D(INIT_DBG, "wiphy is NULL\n"); + return; + } + + wiphy_unregister(net->ieee80211_ptr->wiphy); + + PRINT_D(INIT_DBG, "Freeing wiphy\n"); + wiphy_free(net->ieee80211_ptr->wiphy); + kfree(net->ieee80211_ptr); + +} diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h new file mode 100644 index 000000000000..9eb8f37542d0 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h @@ -0,0 +1,134 @@ +/*! + * @file wilc_wfi_cfgoperations.h + * @brief Definitions for the network module + * @author syounan + * @sa wilc_oswrapper.h top level OS wrapper file + * @date 31 Aug 2010 + * @version 1.0 + */ +#ifndef NM_WFI_CFGOPERATIONS +#define NM_WFI_CFGOPERATIONS +#include "wilc_wfi_netdevice.h" + +#ifdef WILC_FULLY_HOSTING_AP +#include "wilc_host_ap.h" +#endif + + +/* The following macros describe the bitfield map used by the firmware to determine its 11i mode */ +#define NO_ENCRYPT 0 +#define ENCRYPT_ENABLED (1 << 0) +#define WEP (1 << 1) +#define WEP_EXTENDED (1 << 2) +#define WPA (1 << 3) +#define WPA2 (1 << 4) +#define AES (1 << 5) +#define TKIP (1 << 6) + +#ifdef WILC_P2P +/* #define USE_SUPPLICANT_GO_INTENT */ + +/*Public action frame index IDs*/ +#define FRAME_TYPE_ID 0 +#define ACTION_CAT_ID 24 +#define ACTION_SUBTYPE_ID 25 +#define P2P_PUB_ACTION_SUBTYPE 30 + +/*Public action frame Attribute IDs*/ +#define ACTION_FRAME 0xd0 +#define GO_INTENT_ATTR_ID 0x04 +#define CHANLIST_ATTR_ID 0x0b +#define OPERCHAN_ATTR_ID 0x11 +#ifdef USE_SUPPLICANT_GO_INTENT +#define GROUP_BSSID_ATTR_ID 0x07 +#endif +#define PUB_ACTION_ATTR_ID 0x04 +#define P2PELEM_ATTR_ID 0xdd + +/*Public action subtype values*/ +#define GO_NEG_REQ 0x00 +#define GO_NEG_RSP 0x01 +#define GO_NEG_CONF 0x02 +#define P2P_INV_REQ 0x03 +#define P2P_INV_RSP 0x04 +#define PUBLIC_ACT_VENDORSPEC 0x09 +#define GAS_INTIAL_REQ 0x0a +#define GAS_INTIAL_RSP 0x0b + +#define INVALID_CHANNEL 0 +#ifdef USE_SUPPLICANT_GO_INTENT +#define SUPPLICANT_GO_INTENT 6 +#define GET_GO_INTENT(a) (((a) >> 1) & 0x0f) +#define GET_TIE_BREAKER(a) (((a)) & 0x01) +#else +/* #define FORCE_P2P_CLIENT */ +#endif +#endif + +#define nl80211_SCAN_RESULT_EXPIRE (3 * HZ) +#define SCAN_RESULT_EXPIRE (40 * HZ) + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 30) +static const u32 cipher_suites[] = { + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, + WLAN_CIPHER_SUITE_AES_CMAC, +}; +#endif + + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) +static const struct ieee80211_txrx_stypes + wilc_wfi_cfg80211_mgmt_types[NL80211_IFTYPE_MAX] = { + [NL80211_IFTYPE_STATION] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_AP] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | + BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_P2P_CLIENT] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) + } +}; +#endif +/* Time to stay on the channel */ +#define WILC_WFI_DWELL_PASSIVE 100 +#define WILC_WFI_DWELL_ACTIVE 40 + +struct wireless_dev *WILC_WFI_CfgAlloc(void); +struct wireless_dev *WILC_WFI_WiphyRegister(struct net_device *net); +void WILC_WFI_WiphyFree(struct net_device *net); +int WILC_WFI_update_stats(struct wiphy *wiphy, u32 pktlen, u8 changed); +int WILC_WFI_DeInitHostInt(struct net_device *net); +int WILC_WFI_InitHostInt(struct net_device *net); +void WILC_WFI_monitor_rx(uint8_t *buff, uint32_t size); +int WILC_WFI_deinit_mon_interface(void); +struct net_device *WILC_WFI_init_mon_interface(char *name, struct net_device *real_dev); + +#ifdef TCP_ENHANCEMENTS +#define TCP_ACK_FILTER_LINK_SPEED_THRESH 54 +#define DEFAULT_LINK_SPEED 72 +extern void Enable_TCP_ACK_Filter(WILC_Bool value); +#endif + +#endif diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.c b/drivers/staging/wilc1000/wilc_wfi_netdevice.c new file mode 100644 index 000000000000..fbc4b857aa35 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.c @@ -0,0 +1,960 @@ +/*! + * @file wilc_wfi_netdevice.c + * @brief File Operations OS wrapper functionality + * @author mdaftedar + * @sa wilc_wfi_netdevice.h + * @date 01 MAR 2012 + * @version 1.0 + */ + +#ifdef SIMULATION + +#include "wilc_wfi_cfgoperations.h" +#include "host_interface.h" + + +MODULE_AUTHOR("Mai Daftedar"); +MODULE_LICENSE("Dual BSD/GPL"); + + +struct net_device *WILC_WFI_devs[2]; + +/* + * Transmitter lockup simulation, normally disabled. + */ +static int lockup; +module_param(lockup, int, 0); + +static int timeout = WILC_WFI_TIMEOUT; +module_param(timeout, int, 0); + +/* + * Do we run in NAPI mode? + */ +static int use_napi ; +module_param(use_napi, int, 0); + + +/* + * A structure representing an in-flight packet. + */ +struct WILC_WFI_packet { + struct WILC_WFI_packet *next; + struct net_device *dev; + int datalen; + u8 data[ETH_DATA_LEN]; +}; + + + +int pool_size = 8; +module_param(pool_size, int, 0); + + +static void WILC_WFI_TxTimeout(struct net_device *dev); +static void (*WILC_WFI_Interrupt)(int, void *, struct pt_regs *); + +/** + * @brief WILC_WFI_SetupPool + * @details Set up a device's packet pool. + * @param[in] struct net_device *dev : Network Device Pointer + * @return NONE + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +void WILC_WFI_SetupPool(struct net_device *dev) +{ + struct WILC_WFI_priv *priv = netdev_priv(dev); + int i; + struct WILC_WFI_packet *pkt; + + priv->ppool = NULL; + for (i = 0; i < pool_size; i++) { + pkt = kmalloc (sizeof (struct WILC_WFI_packet), GFP_KERNEL); + if (pkt == NULL) { + PRINT_D(RX_DBG, "Ran out of memory allocating packet pool\n"); + return; + } + pkt->dev = dev; + pkt->next = priv->ppool; + priv->ppool = pkt; + } +} + +/** + * @brief WILC_WFI_TearDownPool + * @details Internal cleanup function that's called after the network device + * driver is unregistered + * @param[in] struct net_device *dev : Network Device Driver + * @return NONE + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +void WILC_WFI_TearDownPool(struct net_device *dev) +{ + struct WILC_WFI_priv *priv = netdev_priv(dev); + struct WILC_WFI_packet *pkt; + + while ((pkt = priv->ppool)) { + priv->ppool = pkt->next; + kfree (pkt); + /* FIXME - in-flight packets ? */ + } +} + +/** + * @brief WILC_WFI_GetTxBuffer + * @details Buffer/pool management + * @param[in] net_device *dev : Network Device Driver Structure + * @return struct WILC_WFI_packet + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +struct WILC_WFI_packet *WILC_WFI_GetTxBuffer(struct net_device *dev) +{ + struct WILC_WFI_priv *priv = netdev_priv(dev); + unsigned long flags; + struct WILC_WFI_packet *pkt; + + spin_lock_irqsave(&priv->lock, flags); + pkt = priv->ppool; + priv->ppool = pkt->next; + if (priv->ppool == NULL) { + PRINT_INFO(RX_DBG, "Pool empty\n"); + netif_stop_queue(dev); + } + spin_unlock_irqrestore(&priv->lock, flags); + return pkt; +} +/** + * @brief WILC_WFI_ReleaseBuffer + * @details Buffer/pool management + * @param[in] WILC_WFI_packet *pkt : Structure holding in-flight packet + * @return NONE + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +void WILC_WFI_ReleaseBuffer(struct WILC_WFI_packet *pkt) +{ + unsigned long flags; + struct WILC_WFI_priv *priv = netdev_priv(pkt->dev); + + spin_lock_irqsave(&priv->lock, flags); + pkt->next = priv->ppool; + priv->ppool = pkt; + spin_unlock_irqrestore(&priv->lock, flags); + if (netif_queue_stopped(pkt->dev) && pkt->next == NULL) + netif_wake_queue(pkt->dev); +} + +/** + * @brief WILC_WFI_EnqueueBuf + * @details Enqueuing packets in an RX buffer queue + * @param[in] WILC_WFI_packet *pkt : Structure holding in-flight packet + * @param[in] net_device *dev : Network Device Driver Structure + * @return NONE + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +void WILC_WFI_EnqueueBuf(struct net_device *dev, struct WILC_WFI_packet *pkt) +{ + unsigned long flags; + struct WILC_WFI_priv *priv = netdev_priv(dev); + + spin_lock_irqsave(&priv->lock, flags); + pkt->next = priv->rx_queue; /* FIXME - misorders packets */ + priv->rx_queue = pkt; + spin_unlock_irqrestore(&priv->lock, flags); +} + +/** + * @brief WILC_WFI_DequeueBuf + * @details Dequeuing packets from the RX buffer queue + * @param[in] net_device *dev : Network Device Driver Structure + * @return WILC_WFI_packet *pkt : Structure holding in-flight pac + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +struct WILC_WFI_packet *WILC_WFI_DequeueBuf(struct net_device *dev) +{ + struct WILC_WFI_priv *priv = netdev_priv(dev); + struct WILC_WFI_packet *pkt; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + pkt = priv->rx_queue; + if (pkt != NULL) + priv->rx_queue = pkt->next; + spin_unlock_irqrestore(&priv->lock, flags); + return pkt; +} +/** + * @brief WILC_WFI_RxInts + * @details Enable and disable receive interrupts. + * @param[in] net_device *dev : Network Device Driver Structure + * @param[in] enable : Enable/Disable flag + * @return NONE + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static void WILC_WFI_RxInts(struct net_device *dev, int enable) +{ + struct WILC_WFI_priv *priv = netdev_priv(dev); + priv->rx_int_enabled = enable; +} + +/** + * @brief WILC_WFI_Open + * @details Open Network Device Driver, called when the network + * interface is opened. It starts the interface's transmit queue. + * @param[in] net_device *dev : Network Device Driver Structure + * @param[in] enable : Enable/Disable flag + * @return int : Returns 0 upon success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +int WILC_WFI_Open(struct net_device *dev) +{ + /* request_region(), request_irq(), .... (like fops->open) */ + /* + * Assign the hardware address of the board: use "\0SNULx", where + * x is 0 or 1. The first byte is '\0' to avoid being a multicast + * address (the first byte of multicast addrs is odd). + */ + memcpy(dev->dev_addr, "\0WLAN0", ETH_ALEN); + if (dev == WILC_WFI_devs[1]) + dev->dev_addr[ETH_ALEN - 1]++; /* \0SNUL1 */ + + WILC_WFI_InitHostInt(dev); + netif_start_queue(dev); + return 0; +} +/** + * @brief WILC_WFI_Release + * @details Release Network Device Driver, called when the network + * interface is stopped or brought down. This function marks + * the network driver as not being able to transmit + * @param[in] net_device *dev : Network Device Driver Structure + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +int WILC_WFI_Release(struct net_device *dev) +{ + /* release ports, irq and such -- like fops->close */ + + netif_stop_queue(dev); /* can't transmit any more */ + + return 0; +} +/** + * @brief WILC_WFI_Config + * @details Configuration changes (passed on by ifconfig) + * @param[in] net_device *dev : Network Device Driver Structure + * @param[in] struct ifmap *map : Contains the ioctl implementation for the + * network driver. + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +int WILC_WFI_Config(struct net_device *dev, struct ifmap *map) +{ + if (dev->flags & IFF_UP) /* can't act on a running interface */ + return -EBUSY; + + /* Don't allow changing the I/O address */ + if (map->base_addr != dev->base_addr) { + PRINT_D(RX_DBG, KERN_WARNING "WILC_WFI: Can't change I/O address\n"); + return -EOPNOTSUPP; + } + + /* Allow changing the IRQ */ + if (map->irq != dev->irq) { + dev->irq = map->irq; + /* request_irq() is delayed to open-time */ + } + + /* ignore other fields */ + return 0; +} +/** + * @brief WILC_WFI_Rx + * @details Receive a packet: retrieve, encapsulate and pass over to upper + * levels + * @param[in] net_device *dev : Network Device Driver Structure + * @param[in] WILC_WFI_packet : + * @return NONE + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +void WILC_WFI_Rx(struct net_device *dev, struct WILC_WFI_packet *pkt) +{ + int i; + struct sk_buff *skb; + struct WILC_WFI_priv *priv = netdev_priv(dev); + s8 rssi; + /* + * The packet has been retrieved from the transmission + * medium. Build an skb around it, so upper layers can handle it + */ + + + skb = dev_alloc_skb(pkt->datalen + 2); + if (!skb) { + if (printk_ratelimit()) + PRINT_D(RX_DBG, "WILC_WFI rx: low on mem - packet dropped\n"); + priv->stats.rx_dropped++; + goto out; + } + skb_reserve(skb, 2); /* align IP on 16B boundary */ + memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen); + + if (priv->monitor_flag) { + PRINT_INFO(RX_DBG, "In monitor device name %s\n", dev->name); + priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy); + PRINT_D(RX_DBG, "VALUE PASSED IN OF HRWD %p\n", priv->hWILCWFIDrv); + /* host_int_get_rssi(priv->hWILCWFIDrv, &(rssi)); */ + if (INFO) { + for (i = 14; i < skb->len; i++) + PRINT_INFO(RX_DBG, "RXdata[%d] %02x\n", i, skb->data[i]); + } + WILC_WFI_monitor_rx(dev, skb); + return; + } +#if 0 + PRINT_D(RX_DBG, "In RX NORMAl Device name %s\n", dev->name); + /* Write metadata, and then pass to the receive level */ + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */ + WILC_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy, pkt->datalen, WILC_WFI_RX_PKT); + netif_rx(skb); +#endif +out: + return; +} + +/** + * @brief WILC_WFI_Poll + * @details The poll implementation + * @param[in] struct napi_struct *napi : + * @param[in] int budget : + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static int WILC_WFI_Poll(struct napi_struct *napi, int budget) +{ + int npackets = 0; + struct sk_buff *skb; + struct WILC_WFI_priv *priv = container_of(napi, struct WILC_WFI_priv, napi); + struct net_device *dev = priv->dev; + struct WILC_WFI_packet *pkt; + + while (npackets < budget && priv->rx_queue) { + pkt = WILC_WFI_DequeueBuf(dev); + skb = dev_alloc_skb(pkt->datalen + 2); + if (!skb) { + if (printk_ratelimit()) + PRINT_D(RX_DBG, "WILC_WFI: packet dropped\n"); + priv->stats.rx_dropped++; + WILC_WFI_ReleaseBuffer(pkt); + continue; + } + skb_reserve(skb, 2); /* align IP on 16B boundary */ + memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen); + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */ + netif_receive_skb(skb); + /* Maintain stats */ + npackets++; + WILC_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy, pkt->datalen, WILC_WFI_RX_PKT); + WILC_WFI_ReleaseBuffer(pkt); + } + /* If we processed all packets, we're done; tell the kernel and re-enable ints */ + if (npackets < budget) { + napi_complete(napi); + WILC_WFI_RxInts(dev, 1); + } + return npackets; +} + +/** + * @brief WILC_WFI_Poll + * @details The typical interrupt entry point + * @param[in] struct napi_struct *napi : + * @param[in] int budget : + * @return int : Return 0 on Success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static void WILC_WFI_RegularInterrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + int statusword; + struct WILC_WFI_priv *priv; + struct WILC_WFI_packet *pkt = NULL; + /* + * As usual, check the "device" pointer to be sure it is + * really interrupting. + * Then assign "struct device *dev" + */ + struct net_device *dev = (struct net_device *)dev_id; + /* ... and check with hw if it's really ours */ + + /* paranoid */ + if (!dev) + return; + + /* Lock the device */ + priv = netdev_priv(dev); + spin_lock(&priv->lock); + + /* retrieve statusword: real netdevices use I/O instructions */ + statusword = priv->status; + priv->status = 0; + if (statusword & WILC_WFI_RX_INTR) { + /* send it to WILC_WFI_rx for handling */ + pkt = priv->rx_queue; + if (pkt) { + priv->rx_queue = pkt->next; + WILC_WFI_Rx(dev, pkt); + } + } + if (statusword & WILC_WFI_TX_INTR) { + /* a transmission is over: free the skb */ + WILC_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy, priv->tx_packetlen, WILC_WFI_TX_PKT); + dev_kfree_skb(priv->skb); + } + + /* Unlock the device and we are done */ + spin_unlock(&priv->lock); + if (pkt) + WILC_WFI_ReleaseBuffer(pkt); /* Do this outside the lock! */ + return; +} +/** + * @brief WILC_WFI_NapiInterrupt + * @details A NAPI interrupt handler + * @param[in] irq: + * @param[in] dev_id: + * @param[in] pt_regs: + * @return NONE + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +static void WILC_WFI_NapiInterrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + int statusword; + struct WILC_WFI_priv *priv; + + /* + * As usual, check the "device" pointer for shared handlers. + * Then assign "struct device *dev" + */ + struct net_device *dev = (struct net_device *)dev_id; + /* ... and check with hw if it's really ours */ + + /* paranoid */ + if (!dev) + return; + + /* Lock the device */ + priv = netdev_priv(dev); + spin_lock(&priv->lock); + + /* retrieve statusword: real netdevices use I/O instructions */ + statusword = priv->status; + priv->status = 0; + if (statusword & WILC_WFI_RX_INTR) { + WILC_WFI_RxInts(dev, 0); /* Disable further interrupts */ + napi_schedule(&priv->napi); + } + if (statusword & WILC_WFI_TX_INTR) { + /* a transmission is over: free the skb */ + + WILC_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy, priv->tx_packetlen, WILC_WFI_TX_PKT); + dev_kfree_skb(priv->skb); + } + + /* Unlock the device and we are done */ + spin_unlock(&priv->lock); + return; +} + +/** + * @brief MI_WFI_HwTx + * @details Transmit a packet (low level interface) + * @param[in] buf: + * @param[in] len: + * @param[in] net_device *dev: + * @return NONE + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +void WILC_WFI_HwTx(char *buf, int len, struct net_device *dev) +{ + /* + * This function deals with hw details. This interface loops + * back the packet to the other WILC_WFI interface (if any). + * In other words, this function implements the WILC_WFI behaviour, + * while all other procedures are rather device-independent + */ + struct iphdr *ih; + struct net_device *dest; + struct WILC_WFI_priv *priv; + u32 *saddr, *daddr; + struct WILC_WFI_packet *tx_buffer; + + + /* I am paranoid. Ain't I? */ + if (len < sizeof(struct ethhdr) + sizeof(struct iphdr)) { + PRINT_D(RX_DBG, "WILC_WFI: Hmm... packet too short (%i octets)\n", + len); + return; + } + + if (0) { /* enable this conditional to look at the data */ + int i; + PRINT_D(RX_DBG, "len is %i", len); + for (i = 14; i < len; i++) + PRINT_D(RX_DBG, "TXdata[%d] %02x\n", i, buf[i] & 0xff); + /* PRINT_D(RX_DBG, "\n"); */ + } + /* + * Ethhdr is 14 bytes, but the kernel arranges for iphdr + * to be aligned (i.e., ethhdr is unaligned) + */ + ih = (struct iphdr *)(buf + sizeof(struct ethhdr)); + saddr = &ih->saddr; + daddr = &ih->daddr; + + ((u8 *)saddr)[2] ^= 1; /* change the third octet (class C) */ + ((u8 *)daddr)[2] ^= 1; + + ih->check = 0; /* and rebuild the checksum (ip needs it) */ + ih->check = ip_fast_csum((unsigned char *)ih, ih->ihl); + + + if (dev == WILC_WFI_devs[0]) + PRINT_D(RX_DBG, "%08x:%05i --> %08x:%05i\n", + ntohl(ih->saddr), ntohs(((struct tcphdr *)(ih + 1))->source), + ntohl(ih->daddr), ntohs(((struct tcphdr *)(ih + 1))->dest)); + else + PRINT_D(RX_DBG, "%08x:%05i <-- %08x:%05i\n", + ntohl(ih->daddr), ntohs(((struct tcphdr *)(ih + 1))->dest), + ntohl(ih->saddr), ntohs(((struct tcphdr *)(ih + 1))->source)); + + /* + * Ok, now the packet is ready for transmission: first simulate a + * receive interrupt on the twin device, then a + * transmission-done on the transmitting device + */ + dest = WILC_WFI_devs[dev == WILC_WFI_devs[0] ? 1 : 0]; + priv = netdev_priv(dest); + + tx_buffer = WILC_WFI_GetTxBuffer(dev); + tx_buffer->datalen = len; + memcpy(tx_buffer->data, buf, len); + WILC_WFI_EnqueueBuf(dest, tx_buffer); + if (priv->rx_int_enabled) { + priv->status |= WILC_WFI_RX_INTR; + WILC_WFI_Interrupt(0, dest, NULL); + } + + priv = netdev_priv(dev); + priv->tx_packetlen = len; + priv->tx_packetdata = buf; + priv->status |= WILC_WFI_TX_INTR; + if (lockup && ((priv->stats.tx_packets + 1) % lockup) == 0) { + /* Simulate a dropped transmit interrupt */ + netif_stop_queue(dev); + PRINT_D(RX_DBG, "Simulate lockup at %ld, txp %ld\n", jiffies, + (unsigned long) priv->stats.tx_packets); + } else + WILC_WFI_Interrupt(0, dev, NULL); + +} + +/** + * @brief WILC_WFI_Tx + * @details Transmit a packet (called by the kernel) + * @param[in] sk_buff *skb: + * @param[in] net_device *dev: + * @return NONE + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +int WILC_WFI_Tx(struct sk_buff *skb, struct net_device *dev) +{ + int len; + char *data, shortpkt[ETH_ZLEN]; + struct WILC_WFI_priv *priv = netdev_priv(dev); + + /* priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy); */ + + /* if(priv->monitor_flag) */ + /* mac80211_hwsim_monitor_rx(skb); */ + + + data = skb->data; + len = skb->len; + + if (len < ETH_ZLEN) { + memset(shortpkt, 0, ETH_ZLEN); + memcpy(shortpkt, skb->data, skb->len); + len = ETH_ZLEN; + data = shortpkt; + } + dev->trans_start = jiffies; /* save the timestamp */ + + /* Remember the skb, so we can free it at interrupt time */ + priv->skb = skb; + + /* actual deliver of data is device-specific, and not shown here */ + WILC_WFI_HwTx(data, len, dev); + + return 0; /* Our simple device can not fail */ +} + +/** + * @brief WILC_WFI_TxTimeout + * @details Deal with a transmit timeout. + * @param[in] net_device *dev: + * @return NONE + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +void WILC_WFI_TxTimeout(struct net_device *dev) +{ + struct WILC_WFI_priv *priv = netdev_priv(dev); + + PRINT_D(RX_DBG, "Transmit timeout at %ld, latency %ld\n", jiffies, + jiffies - dev->trans_start); + /* Simulate a transmission interrupt to get things moving */ + priv->status = WILC_WFI_TX_INTR; + WILC_WFI_Interrupt(0, dev, NULL); + priv->stats.tx_errors++; + netif_wake_queue(dev); + return; +} + +/** + * @brief WILC_WFI_Ioctl + * @details Ioctl commands + * @param[in] net_device *dev: + * @param[in] ifreq *rq + * @param[in] cmd: + * @return int : Return 0 on Success + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +int WILC_WFI_Ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + PRINT_D(RX_DBG, "ioctl\n"); + return 0; +} + +/** + * @brief WILC_WFI_Stat + * @details Return statistics to the caller + * @param[in] net_device *dev: + * @return WILC_WFI_Stats : Return net_device_stats stucture with the + * network device driver private data contents. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +struct net_device_stats *WILC_WFI_Stats(struct net_device *dev) +{ + struct WILC_WFI_priv *priv = netdev_priv(dev); + return &priv->stats; +} + +/** + * @brief WILC_WFI_RebuildHeader + * @details This function is called to fill up an eth header, since arp is not + * available on the interface + * @param[in] sk_buff *skb: + * @return int : Return 0 on Success + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +int WILC_WFI_RebuildHeader(struct sk_buff *skb) +{ + struct ethhdr *eth = (struct ethhdr *) skb->data; + struct net_device *dev = skb->dev; + + memcpy(eth->h_source, dev->dev_addr, dev->addr_len); + memcpy(eth->h_dest, dev->dev_addr, dev->addr_len); + eth->h_dest[ETH_ALEN - 1] ^= 0x01; /* dest is us xor 1 */ + return 0; +} +/** + * @brief WILC_WFI_RebuildHeader + * @details This function is called to fill up an eth header, since arp is not + * available on the interface + * @param[in] sk_buff *skb: + * @param[in] struct net_device *dev: + * @param[in] unsigned short type: + * @param[in] const void *saddr, + * @param[in] const void *daddr: + * @param[in] unsigned int len + * @return int : Return 0 on Success + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +int WILC_WFI_Header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, const void *daddr, const void *saddr, + unsigned int len) +{ + struct ethhdr *eth = (struct ethhdr *)skb_push(skb, ETH_HLEN); + + eth->h_proto = htons(type); + memcpy(eth->h_source, saddr ? saddr : dev->dev_addr, dev->addr_len); + memcpy(eth->h_dest, daddr ? daddr : dev->dev_addr, dev->addr_len); + eth->h_dest[ETH_ALEN - 1] ^= 0x01; /* dest is us xor 1 */ + return dev->hard_header_len; +} + +/** + * @brief WILC_WFI_ChangeMtu + * @details The "change_mtu" method is usually not needed. + * If you need it, it must be like this. + * @param[in] net_device *dev : Network Device Driver Structure + * @param[in] new_mtu : + * @return int : Returns 0 on Success. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +int WILC_WFI_ChangeMtu(struct net_device *dev, int new_mtu) +{ + unsigned long flags; + struct WILC_WFI_priv *priv = netdev_priv(dev); + spinlock_t *lock = &priv->lock; + + /* check ranges */ + if ((new_mtu < 68) || (new_mtu > 1500)) + return -EINVAL; + /* + * Do anything you need, and the accept the value + */ + spin_lock_irqsave(lock, flags); + dev->mtu = new_mtu; + spin_unlock_irqrestore(lock, flags); + return 0; /* success */ +} + +static const struct header_ops WILC_WFI_header_ops = { + .create = WILC_WFI_Header, + .rebuild = WILC_WFI_RebuildHeader, + .cache = NULL, /* disable caching */ +}; + + +static const struct net_device_ops WILC_WFI_netdev_ops = { + .ndo_open = WILC_WFI_Open, + .ndo_stop = WILC_WFI_Release, + .ndo_set_config = WILC_WFI_Config, + .ndo_start_xmit = WILC_WFI_Tx, + .ndo_do_ioctl = WILC_WFI_Ioctl, + .ndo_get_stats = WILC_WFI_Stats, + .ndo_change_mtu = WILC_WFI_ChangeMtu, + .ndo_tx_timeout = WILC_WFI_TxTimeout, +}; + +/** + * @brief WILC_WFI_Init + * @details The init function (sometimes called probe). + * It is invoked by register_netdev() + * @param[in] net_device *dev: + * @return NONE + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +void WILC_WFI_Init(struct net_device *dev) +{ + struct WILC_WFI_priv *priv; + + + /* + * Then, assign other fields in dev, using ether_setup() and some + * hand assignments + */ + ether_setup(dev); /* assign some of the fields */ + /* 1- Allocate space */ + + dev->netdev_ops = &WILC_WFI_netdev_ops; + dev->header_ops = &WILC_WFI_header_ops; + dev->watchdog_timeo = timeout; + /* keep the default flags, just add NOARP */ + dev->flags |= IFF_NOARP; + dev->features |= NETIF_F_NO_CSUM; + /* + * Then, initialize the priv field. This encloses the statistics + * and a few private fields. + */ + priv = netdev_priv(dev); + memset(priv, 0, sizeof(struct WILC_WFI_priv)); + priv->dev = dev; + netif_napi_add(dev, &priv->napi, WILC_WFI_Poll, 2); + /* The last parameter above is the NAPI "weight". */ + spin_lock_init(&priv->lock); + WILC_WFI_RxInts(dev, 1); /* enable receive interrupts */ + WILC_WFI_SetupPool(dev); +} + +/** + * @brief WILC_WFI_Stat + * @details Return statistics to the caller + * @param[in] net_device *dev: + * @return WILC_WFI_Stats : Return net_device_stats stucture with the + * network device driver private data contents. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ + +void WILC_WFI_Cleanup(void) +{ + int i; + struct WILC_WFI_priv *priv[2]; + + /*if(hwsim_mon!=NULL) + * { + * PRINT_D(RX_DBG, "Freeing monitor interface\n"); + * unregister_netdev(hwsim_mon); + * free_netdev(hwsim_mon); + * }*/ + for (i = 0; i < 2; i++) { + priv[i] = netdev_priv(WILC_WFI_devs[i]); + + if (WILC_WFI_devs[i]) { + PRINT_D(RX_DBG, "Unregistering\n"); + unregister_netdev(WILC_WFI_devs[i]); + WILC_WFI_TearDownPool(WILC_WFI_devs[i]); + free_netdev(WILC_WFI_devs[i]); + PRINT_D(RX_DBG, "[NETDEV]Stopping interface\n"); + WILC_WFI_DeInitHostInt(WILC_WFI_devs[i]); + WILC_WFI_WiphyFree(WILC_WFI_devs[i]); + } + + } + /* unregister_netdev(hwsim_mon); */ + WILC_WFI_deinit_mon_interface(); + return; +} + + +void StartConfigSim(void); + + + + + + + +/** + * @brief WILC_WFI_Stat + * @details Return statistics to the caller + * @param[in] net_device *dev: + * @return WILC_WFI_Stats : Return net_device_stats stucture with the + * network device driver private data contents. + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +int WILC_WFI_InitModule(void) +{ + + int result, i, ret = -ENOMEM; + struct WILC_WFI_priv *priv[2], *netpriv; + struct wireless_dev *wdev; + WILC_WFI_Interrupt = use_napi ? WILC_WFI_NapiInterrupt : WILC_WFI_RegularInterrupt; + char buf[IFNAMSIZ]; + + for (i = 0; i < 2; i++) { + + /* Allocate the net devices */ + WILC_WFI_devs[i] = alloc_netdev(sizeof(struct WILC_WFI_priv), "wlan%d", + WILC_WFI_Init); + if (WILC_WFI_devs[i] == NULL) + goto out; + /* priv[i] = netdev_priv(WILC_WFI_devs[i]); */ + + wdev = WILC_WFI_WiphyRegister(WILC_WFI_devs[i]); + WILC_WFI_devs[i]->ieee80211_ptr = wdev; + netpriv = netdev_priv(WILC_WFI_devs[i]); + netpriv->dev->ieee80211_ptr = wdev; + netpriv->dev->ml_priv = netpriv; + wdev->netdev = netpriv->dev; + + /*Registering the net device*/ + result = register_netdev(WILC_WFI_devs[i]); + if (result) + PRINT_D(RX_DBG, "WILC_WFI: error %i registering device \"%s\"\n", + result, WILC_WFI_devs[i]->name); + else + ret = 0; + } + + + /*init atmel driver */ + priv[0] = netdev_priv(WILC_WFI_devs[0]); + priv[1] = netdev_priv(WILC_WFI_devs[1]); + + if (priv[1]->dev->ieee80211_ptr->wiphy->interface_modes && BIT(NL80211_IFTYPE_MONITOR)) { + /* snprintf(buf, IFNAMSIZ, "mon.%s", priv[1]->dev->name); */ + /* WILC_WFI_init_mon_interface(); */ + /* priv[1]->monitor_flag = 1; */ + + } + priv[0]->bCfgScanning = WILC_FALSE; + priv[0]->u32RcvdChCount = 0; + + WILC_memset(priv[0]->au8AssociatedBss, 0xFF, ETH_ALEN); + + + /* ret = host_int_init(&priv[0]->hWILCWFIDrv); */ + /*copy handle to the other driver*/ + /* priv[1]->hWILCWFIDrv = priv[0]->hWILCWFIDrv; */ + if (ret) { + PRINT_ER("Error Init Driver\n"); + } + + +out: + if (ret) + WILC_WFI_Cleanup(); + return ret; + + +} + + +module_init(WILC_WFI_InitModule); +module_exit(WILC_WFI_Cleanup); + +#endif diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h new file mode 100644 index 000000000000..aa30de932ca4 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -0,0 +1,277 @@ +/*! + * @file wilc_wfi_netdevice.h + * @brief Definitions for the network module + * @author mdaftedar + * @date 01 MAR 2012 + * @version 1.0 + */ +#ifndef WILC_WFI_NETDEVICE +#define WILC_WFI_NETDEVICE + +/* These are the flags in the statusword */ +#define WILC_WFI_RX_INTR 0x0001 +#define WILC_WFI_TX_INTR 0x0002 + +/* Default timeout period */ +#define WILC_WFI_TIMEOUT 5 /* In jiffies */ +#define WILC_MAX_NUM_PMKIDS 16 +#define PMKID_LEN 16 +#define PMKID_FOUND 1 + #define NUM_STA_ASSOCIATED 8 + +#include +#include +#include +#include +#include +#include /* kmalloc() */ +#include /* error codes */ +#include /* size_t */ +#include /* mark_bh */ +#include +#include +#include /* struct device, and other headers */ +#include /* eth_type_trans */ +#include /* struct iphdr */ +#include /* struct tcphdr */ +#include + +#include +#include + +#include +#include +#include +#include + + +#include +#include +#include "host_interface.h" +#include "wilc_wlan.h" +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 30) +#include +#else +#include /* tony, 2013-06-12 */ +#endif + + +#define FLOW_CONTROL_LOWER_THRESHOLD 128 +#define FLOW_CONTROL_UPPER_THRESHOLD 256 + +/*iftype*/ + + +enum stats_flags { + WILC_WFI_RX_PKT = 1 << 0, + WILC_WFI_TX_PKT = 1 << 1, +}; + +struct WILC_WFI_stats { + + unsigned long rx_packets; + unsigned long tx_packets; + unsigned long rx_bytes; + unsigned long tx_bytes; + u64 rx_time; + u64 tx_time; + +}; + +/* + * This structure is private to each device. It is used to pass + * packets in and out, so there is place for a packet + */ + +#define RX_BH_KTHREAD 0 +#define RX_BH_WORK_QUEUE 1 +#define RX_BH_THREADED_IRQ 2 +#define num_reg_frame 2 +/* + * If you use RX_BH_WORK_QUEUE on LPC3131: You may lose the first interrupt on + * LPC3131 which is important to get the MAC start status when you are blocked inside + * linux_wlan_firmware_download() which blocks mac_open(). + */ +#if defined (NM73131_0_BOARD) + #define RX_BH_TYPE RX_BH_KTHREAD +#elif defined (PANDA_BOARD) + #define RX_BH_TYPE RX_BH_THREADED_IRQ +#else + #define RX_BH_TYPE RX_BH_KTHREAD +#endif + +struct wilc_wfi_key { + u8 *key; + u8 *seq; + int key_len; + int seq_len; + u32 cipher; +}; +struct wilc_wfi_wep_key { + u8 *key; + u8 key_len; + u8 key_idx; +}; + +struct sta_info { + WILC_Uint8 au8Sta_AssociatedBss[MAX_NUM_STA][ETH_ALEN]; +}; + +#ifdef WILC_P2P +/*Parameters needed for host interface for remaining on channel*/ +struct wilc_wfi_p2pListenParams { + struct ieee80211_channel *pstrListenChan; + enum nl80211_channel_type tenuChannelType; + WILC_Uint32 u32ListenDuration; + WILC_Uint64 u64ListenCookie; + WILC_Uint32 u32ListenSessionID; +}; + +#endif /*WILC_P2P*/ + +struct WILC_WFI_priv { + struct wireless_dev *wdev; + struct cfg80211_scan_request *pstrScanReq; + + #ifdef WILC_P2P + struct wilc_wfi_p2pListenParams strRemainOnChanParams; + WILC_Uint64 u64tx_cookie; + + #endif + + WILC_Bool bCfgScanning; + WILC_Uint32 u32RcvdChCount; + + + + WILC_Uint8 au8AssociatedBss[ETH_ALEN]; + struct sta_info assoc_stainfo; + struct net_device_stats stats; + WILC_Uint8 monitor_flag; + int status; + struct WILC_WFI_packet *ppool; + struct WILC_WFI_packet *rx_queue; /* List of incoming packets */ + int rx_int_enabled; + int tx_packetlen; + u8 *tx_packetdata; + struct sk_buff *skb; + spinlock_t lock; + struct net_device *dev; + struct napi_struct napi; + WILC_WFIDrvHandle hWILCWFIDrv; + WILC_WFIDrvHandle hWILCWFIDrv_2; + tstrHostIFpmkidAttr pmkid_list; + struct WILC_WFI_stats netstats; + WILC_Uint8 WILC_WFI_wep_default; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) +#define WLAN_KEY_LEN_WEP104 13 +#endif + WILC_Uint8 WILC_WFI_wep_key[4][WLAN_KEY_LEN_WEP104]; + WILC_Uint8 WILC_WFI_wep_key_len[4]; + struct net_device *real_ndev; /* The real interface that the monitor is on */ + struct wilc_wfi_key *wilc_gtk[MAX_NUM_STA]; + struct wilc_wfi_key *wilc_ptk[MAX_NUM_STA]; + WILC_Uint8 wilc_groupkey; + /* semaphores */ + WILC_SemaphoreHandle SemHandleUpdateStats; + WILC_SemaphoreHandle hSemScanReq; + /* */ + WILC_Bool gbAutoRateAdjusted; + + WILC_Bool bInP2PlistenState; + +}; + +typedef struct { + WILC_Uint16 frame_type; + WILC_Bool reg; + +} struct_frame_reg; + + +#define NUM_CONCURRENT_IFC 2 +typedef struct { + uint8_t aSrcAddress[ETH_ALEN]; + uint8_t aBSSID[ETH_ALEN]; + uint32_t drvHandler; + struct net_device *wilc_netdev; +} tstrInterfaceInfo; +typedef struct { + int mac_status; + int wilc1000_initialized; + + + #if (!defined WILC_SDIO) || (defined WILC_SDIO_IRQ_GPIO) + unsigned short dev_irq_num; + #endif + wilc_wlan_oup_t oup; + int close; + uint8_t u8NoIfcs; + tstrInterfaceInfo strInterfaceInfo[NUM_CONCURRENT_IFC]; + uint8_t open_ifcs; + struct mutex txq_cs; + + /*Added by Amr - BugID_4720*/ + struct mutex txq_add_to_head_cs; + spinlock_t txq_spinlock; + + struct mutex rxq_cs; + struct mutex hif_cs; + + /* struct mutex txq_event; */ + struct semaphore rxq_event; + struct semaphore cfg_event; + struct semaphore sync_event; + + struct semaphore txq_event; + /* struct completion txq_event; */ + +#if (RX_BH_TYPE == RX_BH_WORK_QUEUE) + struct work_struct rx_work_queue; +#elif (RX_BH_TYPE == RX_BH_KTHREAD) + struct task_struct *rx_bh_thread; + struct semaphore rx_sem; +#endif + + + + struct semaphore rxq_thread_started; + struct semaphore txq_thread_started; + + struct task_struct *rxq_thread; + struct task_struct *txq_thread; + + unsigned char eth_src_address[NUM_CONCURRENT_IFC][6]; + /* unsigned char eth_dst_address[6]; */ + + const struct firmware *wilc_firmware; /* Bug 4703 */ + + struct net_device *real_ndev; +#ifdef WILC_SDIO + int already_claim; + struct sdio_func *wilc_sdio_func; +#else + struct spi_device *wilc_spidev; +#endif + +} linux_wlan_t; + +typedef struct { + uint8_t u8IfIdx; + WILC_Uint8 iftype; + int monitor_flag; + int mac_opened; + #ifdef WILC_P2P + struct_frame_reg g_struct_frame_reg[num_reg_frame]; + #endif + struct net_device *wilc_netdev; + struct net_device_stats netstats; + +} perInterface_wlan_t; + +struct WILC_WFI_mon_priv { + struct net_device *real_ndev; +}; +extern struct net_device *WILC_WFI_devs[]; + +#endif diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c new file mode 100644 index 000000000000..92ed42ad49ac --- /dev/null +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -0,0 +1,2434 @@ +/* ////////////////////////////////////////////////////////////////////////// */ +/* */ +/* Copyright (c) Atmel Corporation. All rights reserved. */ +/* */ +/* Module Name: wilc_wlan.c */ +/* */ +/* */ +/* //////////////////////////////////////////////////////////////////////////// */ + +#include "wilc_wlan_if.h" +#include "wilc_wlan.h" +#define INLINE static __inline + +/******************************************** + * + * Global + * + ********************************************/ +extern unsigned int int_clrd; +extern wilc_hif_func_t hif_sdio; +extern wilc_hif_func_t hif_spi; +extern wilc_cfg_func_t mac_cfg; +#if defined(PLAT_RK3026_TCHIP) +extern WILC_Uint8 g_wilc_initialized; /* AMR : 0422 RK3026 Crash issue */ +#endif +extern void WILC_WFI_mgmt_rx(uint8_t *buff, uint32_t size); +extern void frmw_to_linux(uint8_t *buff, uint32_t size); +int sdio_xfer_cnt(void); +uint32_t wilc_get_chipid(uint8_t update); +WILC_Uint16 Set_machw_change_vir_if(WILC_Bool bValue); + +/* static uint32_t vmm_table[WILC_VMM_TBL_SIZE]; */ +/* static uint32_t vmm_table_rbk[WILC_VMM_TBL_SIZE]; */ + +/* static uint32_t vmm_table_rbk[WILC_VMM_TBL_SIZE]; */ + + +typedef struct { + int quit; + + /** + * input interface functions + **/ + wilc_wlan_os_func_t os_func; + wilc_wlan_io_func_t io_func; + wilc_wlan_net_func_t net_func; + wilc_wlan_indicate_func_t indicate_func; + + /** + * host interface functions + **/ + wilc_hif_func_t hif_func; + void *hif_lock; + + /** + * configuration interface functions + **/ + wilc_cfg_func_t cif_func; + int cfg_frame_in_use; + wilc_cfg_frame_t cfg_frame; + uint32_t cfg_frame_offset; + int cfg_seq_no; + void *cfg_wait; + + /** + * RX buffer + **/ + #ifdef MEMORY_STATIC + uint32_t rx_buffer_size; + uint8_t *rx_buffer; + uint32_t rx_buffer_offset; + #endif + /** + * TX buffer + **/ + uint32_t tx_buffer_size; + uint8_t *tx_buffer; + uint32_t tx_buffer_offset; + + /** + * TX queue + **/ + void *txq_lock; + + /*Added by Amr - BugID_4720*/ + void *txq_add_to_head_lock; + void *txq_spinlock; + unsigned long txq_spinlock_flags; + + struct txq_entry_t *txq_head; + struct txq_entry_t *txq_tail; + int txq_entries; + void *txq_wait; + int txq_exit; + + /** + * RX queue + **/ + void *rxq_lock; + struct rxq_entry_t *rxq_head; + struct rxq_entry_t *rxq_tail; + int rxq_entries; + void *rxq_wait; + int rxq_exit; + + +} wilc_wlan_dev_t; + +static wilc_wlan_dev_t g_wlan; + +INLINE void chip_allow_sleep(void); +INLINE void chip_wakeup(void); +/******************************************** + * + * Debug + * + ********************************************/ + +static uint32_t dbgflag = N_INIT | N_ERR | N_INTR | N_TXQ | N_RXQ; + +static void wilc_debug(uint32_t flag, char *fmt, ...) +{ + char buf[256]; + va_list args; + int len; + + if (flag & dbgflag) { + va_start(args, fmt); + len = vsprintf(buf, fmt, args); + va_end(args); + + if (g_wlan.os_func.os_debug) + g_wlan.os_func.os_debug(buf); + } + + return; +} + +static CHIP_PS_STATE_T genuChipPSstate = CHIP_WAKEDUP; + +/*BugID_5213*/ +/*acquire_bus() and release_bus() are made INLINE functions*/ +/*as a temporary workaround to fix a problem of receiving*/ +/*unknown interrupt from FW*/ +INLINE void acquire_bus(BUS_ACQUIRE_T acquire) +{ + + g_wlan.os_func.os_enter_cs(g_wlan.hif_lock); + #ifndef WILC_OPTIMIZE_SLEEP_INT + if (genuChipPSstate != CHIP_WAKEDUP) + #endif + { + if (acquire == ACQUIRE_AND_WAKEUP) + chip_wakeup(); + } + +} +INLINE void release_bus(BUS_RELEASE_T release) +{ + #ifdef WILC_OPTIMIZE_SLEEP_INT + if (release == RELEASE_ALLOW_SLEEP) + chip_allow_sleep(); + #endif + g_wlan.os_func.os_leave_cs(g_wlan.hif_lock); +} +/******************************************** + * + * Queue + * + ********************************************/ + +static void wilc_wlan_txq_remove(struct txq_entry_t *tqe) +{ + + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + /* unsigned long flags; */ + /* p->os_func.os_spin_lock(p->txq_spinlock, &flags); */ + if (tqe == p->txq_head) { + + p->txq_head = tqe->next; + if (p->txq_head) + p->txq_head->prev = NULL; + + + } else if (tqe == p->txq_tail) { + p->txq_tail = (tqe->prev); + if (p->txq_tail) + p->txq_tail->next = NULL; + } else { + tqe->prev->next = tqe->next; + tqe->next->prev = tqe->prev; + } + p->txq_entries -= 1; + /* p->os_func.os_spin_unlock(p->txq_spinlock, &flags); */ + +} + +static struct txq_entry_t *wilc_wlan_txq_remove_from_head(void) +{ + struct txq_entry_t *tqe; + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + unsigned long flags; + p->os_func.os_spin_lock(p->txq_spinlock, &flags); + if (p->txq_head) { + /* p->os_func.os_enter_cs(p->txq_lock); */ + tqe = p->txq_head; + p->txq_head = tqe->next; + if (p->txq_head) { + p->txq_head->prev = NULL; + } + p->txq_entries -= 1; + + /*Added by Amr - BugID_4720*/ + + + /* p->os_func.os_leave_cs(p->txq_lock); */ + + } else { + tqe = NULL; + } + p->os_func.os_spin_unlock(p->txq_spinlock, &flags); + return tqe; +} + +static void wilc_wlan_txq_add_to_tail(struct txq_entry_t *tqe) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + unsigned long flags; + /*Added by Amr - BugID_4720*/ + p->os_func.os_spin_lock(p->txq_spinlock, &flags); + +/* p->os_func.os_enter_cs(p->txq_lock); */ + if (p->txq_head == NULL) { + tqe->next = NULL; + tqe->prev = NULL; + p->txq_head = tqe; + p->txq_tail = tqe; + /* p->os_func.os_signal(p->txq_wait); */ + } else { + tqe->next = NULL; + tqe->prev = p->txq_tail; + p->txq_tail->next = tqe; + p->txq_tail = tqe; + } + p->txq_entries += 1; + PRINT_D(TX_DBG, "Number of entries in TxQ = %d\n", p->txq_entries); +/* p->os_func.os_leave_cs(p->txq_lock); */ + + /*Added by Amr - BugID_4720*/ + p->os_func.os_spin_unlock(p->txq_spinlock, &flags); + + /** + * wake up TX queue + **/ + PRINT_D(TX_DBG, "Wake the txq_handling\n"); + + p->os_func.os_signal(p->txq_wait); + + +} + +static int wilc_wlan_txq_add_to_head(struct txq_entry_t *tqe) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + unsigned long flags; + /*Added by Amr - BugID_4720*/ + if (p->os_func.os_wait(p->txq_add_to_head_lock, CFG_PKTS_TIMEOUT)) + return -1; + + p->os_func.os_spin_lock(p->txq_spinlock, &flags); + + /* p->os_func.os_enter_cs(p->txq_lock); */ + if (p->txq_head == NULL) { + tqe->next = NULL; + tqe->prev = NULL; + p->txq_head = tqe; + p->txq_tail = tqe; + } else { + tqe->next = p->txq_head; + tqe->prev = NULL; + p->txq_head->prev = tqe; + p->txq_head = tqe; + } + p->txq_entries += 1; + PRINT_D(TX_DBG, "Number of entries in TxQ = %d\n", p->txq_entries); + /* p->os_func.os_leave_cs(p->txq_lock); */ + + /*Added by Amr - BugID_4720*/ + p->os_func.os_spin_unlock(p->txq_spinlock, &flags); + p->os_func.os_signal(p->txq_add_to_head_lock); + + + /** + * wake up TX queue + **/ + p->os_func.os_signal(p->txq_wait); + PRINT_D(TX_DBG, "Wake up the txq_handler\n"); +/* complete(p->txq_wait); */ + + /*Added by Amr - BugID_4720*/ + return 0; + +} + +uint32_t Statisitcs_totalAcks = 0, Statisitcs_DroppedAcks = 0; + +#ifdef TCP_ACK_FILTER +struct Ack_session_info; +typedef struct Ack_session_info { + uint32_t Ack_seq_num; + uint32_t Bigger_Ack_num; + uint16_t src_port; + uint16_t dst_port; + uint16_t status; + /* struct Ack_session_info * next; */ + /* struct Ack_session_info * prev; */ +} Ack_session_info_t; + +typedef struct { + uint32_t ack_num; + /* uint32_t seq_num; */ + /* uint16_t src_port; */ + /* uint16_t dst_port; */ + /* uint32_t dst_ip_addr; */ + uint32_t Session_index; + struct txq_entry_t *txqe; + /* Ack_session_info * Ack_session; */ +} Pending_Acks_info_t /*Ack_info_t*/; + + + + +struct Ack_session_info *Free_head; +struct Ack_session_info *Alloc_head; + +#define TCP_FIN_MASK (1 << 0) +#define TCP_SYN_MASK (1 << 1) +#define TCP_Ack_MASK (1 << 4) +#define NOT_TCP_ACK (-1) + +#define MAX_TCP_SESSION 25 +#define MAX_PENDING_ACKS 256 +Ack_session_info_t Acks_keep_track_info[2 * MAX_TCP_SESSION]; +Pending_Acks_info_t Pending_Acks_info[MAX_PENDING_ACKS]; + +uint32_t PendingAcks_arrBase; +uint32_t Opened_TCP_session; +uint32_t Pending_Acks; + + + +static __inline int Init_TCP_tracking(void) +{ + + /*uint32_t i; + * Free_head=&Acks_keep_track_info[0]; + * i=1; + * Acks_keep_track_info[0].next=&Acks_keep_track_info[1]; + * for(i=1<;i Acks_keep_track_info[index].Bigger_Ack_num) { + Acks_keep_track_info[index].Bigger_Ack_num = Ack; + } + return 0; + +} +static __inline int add_TCP_Pending_Ack(uint32_t Ack, uint32_t Session_index, struct txq_entry_t *txqe) +{ + Statisitcs_totalAcks++; + if (Pending_Acks < MAX_PENDING_ACKS) { + Pending_Acks_info[PendingAcks_arrBase + Pending_Acks].ack_num = Ack; + Pending_Acks_info[PendingAcks_arrBase + Pending_Acks].txqe = txqe; + Pending_Acks_info[PendingAcks_arrBase + Pending_Acks].Session_index = Session_index; + txqe->tcp_PendingAck_index = PendingAcks_arrBase + Pending_Acks; + Pending_Acks++; + + } else { + + } + return 0; +} +static __inline int remove_TCP_related(void) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + unsigned long flags; + p->os_func.os_spin_lock(p->txq_spinlock, &flags); + + p->os_func.os_spin_unlock(p->txq_spinlock, &flags); + return 0; +} + +static __inline int tcp_process(struct txq_entry_t *tqe) +{ + int ret; + uint8_t *eth_hdr_ptr; + uint8_t *buffer = tqe->buffer; + unsigned short h_proto; + int i; + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + unsigned long flags; + p->os_func.os_spin_lock(p->txq_spinlock, &flags); + + eth_hdr_ptr = &buffer[0]; + h_proto = ntohs(*((unsigned short *)ð_hdr_ptr[12])); + if (h_proto == 0x0800) { /* IP */ + uint8_t *ip_hdr_ptr; + uint8_t protocol; + + ip_hdr_ptr = &buffer[ETHERNET_HDR_LEN]; + protocol = ip_hdr_ptr[9]; + + + if (protocol == 0x06) { + uint8_t *tcp_hdr_ptr; + uint32_t IHL, Total_Length, Data_offset; + tcp_hdr_ptr = &ip_hdr_ptr[IP_HDR_LEN]; + IHL = (ip_hdr_ptr[0] & 0xf) << 2; + Total_Length = (((uint32_t)ip_hdr_ptr[2]) << 8) + ((uint32_t)ip_hdr_ptr[3]); + Data_offset = (((uint32_t)tcp_hdr_ptr[12] & 0xf0) >> 2); + if (Total_Length == (IHL + Data_offset)) { /*we want to recognize the clear Acks(packet only carry Ack infos not with data) so data size must be equal zero*/ + uint32_t seq_no, Ack_no; + seq_no = (((uint32_t)tcp_hdr_ptr[4]) << 24) + (((uint32_t)tcp_hdr_ptr[5]) << 16) + (((uint32_t)tcp_hdr_ptr[6]) << 8) + ((uint32_t)tcp_hdr_ptr[7]); + + Ack_no = (((uint32_t)tcp_hdr_ptr[8]) << 24) + (((uint32_t)tcp_hdr_ptr[9]) << 16) + (((uint32_t)tcp_hdr_ptr[10]) << 8) + ((uint32_t)tcp_hdr_ptr[11]); + + + for (i = 0; i < Opened_TCP_session; i++) { + if (Acks_keep_track_info[i].Ack_seq_num == seq_no) { + Update_TCP_track_session(i, Ack_no); + break; + } + } + if (i == Opened_TCP_session) { + add_TCP_track_session(0, 0, seq_no); + } + add_TCP_Pending_Ack(Ack_no, i, tqe); + + + } + + } else { + ret = 0; + } + } else { + ret = 0; + } + p->os_func.os_spin_unlock(p->txq_spinlock, &flags); + return ret; +} + + +static int wilc_wlan_txq_filter_dup_tcp_ack(void) +{ + + uint32_t i = 0; + uint32_t Dropped = 0; + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + + p->os_func.os_spin_lock(p->txq_spinlock, &p->txq_spinlock_flags); + for (i = PendingAcks_arrBase; i < (PendingAcks_arrBase + Pending_Acks); i++) { + if (Pending_Acks_info[i].ack_num < Acks_keep_track_info[Pending_Acks_info[i].Session_index].Bigger_Ack_num) { + struct txq_entry_t *tqe; + PRINT_D(TCP_ENH, "DROP ACK: %u \n", Pending_Acks_info[i].ack_num); + tqe = Pending_Acks_info[i].txqe; + if (tqe) { + wilc_wlan_txq_remove(tqe); + Statisitcs_DroppedAcks++; + tqe->status = 1; /* mark the packet send */ + if (tqe->tx_complete_func) + tqe->tx_complete_func(tqe->priv, tqe->status); + p->os_func.os_free(tqe); + Dropped++; + /* p->txq_entries -= 1; */ + } + } + } + Pending_Acks = 0; + Opened_TCP_session = 0; + + if (PendingAcks_arrBase == 0) { + PendingAcks_arrBase = MAX_TCP_SESSION; + } else { + PendingAcks_arrBase = 0; + } + + + p->os_func.os_spin_unlock(p->txq_spinlock, &p->txq_spinlock_flags); + + while (Dropped > 0) { + /*consume the semaphore count of the removed packet*/ + p->os_func.os_wait(p->txq_wait, 1); + Dropped--; + } + + return 1; +} +#endif + +#ifdef TCP_ENHANCEMENTS +WILC_Bool EnableTCPAckFilter = WILC_FALSE; + +void Enable_TCP_ACK_Filter(WILC_Bool value) +{ + EnableTCPAckFilter = value; +} + +WILC_Bool is_TCP_ACK_Filter_Enabled(void) +{ + return EnableTCPAckFilter; +} +#endif + +static int wilc_wlan_txq_add_cfg_pkt(uint8_t *buffer, uint32_t buffer_size) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + struct txq_entry_t *tqe; + + PRINT_D(TX_DBG, "Adding config packet ...\n"); + if (p->quit) { + PRINT_D(TX_DBG, "Return due to clear function\n"); + p->os_func.os_signal(p->cfg_wait); + return 0; + } + + tqe = (struct txq_entry_t *)p->os_func.os_malloc_atomic(sizeof(struct txq_entry_t)); + if (tqe == NULL) { + PRINT_ER("Failed to allocate memory\n"); + return 0; + } + + tqe->type = WILC_CFG_PKT; + tqe->buffer = buffer; + tqe->buffer_size = buffer_size; + tqe->tx_complete_func = NULL; + tqe->priv = NULL; +#ifdef TCP_ACK_FILTER + tqe->tcp_PendingAck_index = NOT_TCP_ACK; +#endif + /** + * Configuration packet always at the front + **/ + PRINT_D(TX_DBG, "Adding the config packet at the Queue tail\n"); + + /*Edited by Amr - BugID_4720*/ + if (wilc_wlan_txq_add_to_head(tqe)) + return 0; + /* wilc_wlan_txq_add_to_tail(tqe); */ + return 1; +} + +static int wilc_wlan_txq_add_net_pkt(void *priv, uint8_t *buffer, uint32_t buffer_size, wilc_tx_complete_func_t func) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + struct txq_entry_t *tqe; + + if (p->quit) + return 0; + + tqe = (struct txq_entry_t *)p->os_func.os_malloc_atomic(sizeof(struct txq_entry_t)); + + if (tqe == NULL) + return 0; + tqe->type = WILC_NET_PKT; + tqe->buffer = buffer; + tqe->buffer_size = buffer_size; + tqe->tx_complete_func = func; + tqe->priv = priv; + + PRINT_D(TX_DBG, "Adding mgmt packet at the Queue tail\n"); +#ifdef TCP_ACK_FILTER + tqe->tcp_PendingAck_index = NOT_TCP_ACK; +#ifdef TCP_ENHANCEMENTS + if (is_TCP_ACK_Filter_Enabled() == WILC_TRUE) +#endif + tcp_process(tqe); +#endif + wilc_wlan_txq_add_to_tail(tqe); + /*return number of itemes in the queue*/ + return p->txq_entries; +} +/*Bug3959: transmitting mgmt frames received from host*/ +#if defined(WILC_AP_EXTERNAL_MLME) || defined(WILC_P2P) +int wilc_wlan_txq_add_mgmt_pkt(void *priv, uint8_t *buffer, uint32_t buffer_size, wilc_tx_complete_func_t func) +{ + + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + struct txq_entry_t *tqe; + + if (p->quit) + return 0; + + tqe = (struct txq_entry_t *)p->os_func.os_malloc_atomic(sizeof(struct txq_entry_t)); + + if (tqe == NULL) + return 0; + tqe->type = WILC_MGMT_PKT; + tqe->buffer = buffer; + tqe->buffer_size = buffer_size; + tqe->tx_complete_func = func; + tqe->priv = priv; +#ifdef TCP_ACK_FILTER + tqe->tcp_PendingAck_index = NOT_TCP_ACK; +#endif + PRINT_D(TX_DBG, "Adding Network packet at the Queue tail\n"); + wilc_wlan_txq_add_to_tail(tqe); + return 1; +} + +#ifdef WILC_FULLY_HOSTING_AP +int wilc_FH_wlan_txq_add_net_pkt(void *priv, uint8_t *buffer, uint32_t buffer_size, wilc_tx_complete_func_t func) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + struct txq_entry_t *tqe; + + if (p->quit) + return 0; + + tqe = (struct txq_entry_t *)p->os_func.os_malloc_atomic(sizeof(struct txq_entry_t)); + + if (tqe == NULL) + return 0; + tqe->type = WILC_FH_DATA_PKT; + tqe->buffer = buffer; + tqe->buffer_size = buffer_size; + tqe->tx_complete_func = func; + tqe->priv = priv; + PRINT_D(TX_DBG, "Adding mgmt packet at the Queue tail\n"); + wilc_wlan_txq_add_to_tail(tqe); + /*return number of itemes in the queue*/ + return p->txq_entries; +} +#endif /* WILC_FULLY_HOSTING_AP*/ +#endif /*WILC_AP_EXTERNAL_MLME*/ +static struct txq_entry_t *wilc_wlan_txq_get_first(void) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + struct txq_entry_t *tqe; + unsigned long flags; + + /*Added by Amr - BugID_4720*/ + p->os_func.os_spin_lock(p->txq_spinlock, &flags); + + /* p->os_func.os_enter_cs(p->txq_lock); */ + tqe = p->txq_head; + + /*Added by Amr - BugID_4720*/ + p->os_func.os_spin_unlock(p->txq_spinlock, &flags); + + /* p->os_func.os_leave_cs(p->txq_lock); */ + + return tqe; +} + +static struct txq_entry_t *wilc_wlan_txq_get_next(struct txq_entry_t *tqe) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + unsigned long flags; + /*Added by Amr - BugID_4720*/ + p->os_func.os_spin_lock(p->txq_spinlock, &flags); + + /* p->os_func.os_enter_cs(p->txq_lock); */ + tqe = tqe->next; + + /*Added by Amr - BugID_4720*/ + p->os_func.os_spin_unlock(p->txq_spinlock, &flags); + + /* p->os_func.os_leave_cs(p->txq_lock); */ + + return tqe; +} + +static int wilc_wlan_rxq_add(struct rxq_entry_t *rqe) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + + if (p->quit) + return 0; + + p->os_func.os_enter_cs(p->rxq_lock); + if (p->rxq_head == NULL) { + PRINT_D(RX_DBG, "Add to Queue head\n"); + rqe->next = NULL; + p->rxq_head = rqe; + p->rxq_tail = rqe; + } else { + PRINT_D(RX_DBG, "Add to Queue tail\n"); + p->rxq_tail->next = rqe; + rqe->next = NULL; + p->rxq_tail = rqe; + } + p->rxq_entries += 1; + PRINT_D(RX_DBG, "Number of queue entries: %d\n", p->rxq_entries); + p->os_func.os_leave_cs(p->rxq_lock); + return p->rxq_entries; +} + +static struct rxq_entry_t *wilc_wlan_rxq_remove(void) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + + PRINT_D(RX_DBG, "Getting rxQ element\n"); + if (p->rxq_head) { + struct rxq_entry_t *rqe; + + p->os_func.os_enter_cs(p->rxq_lock); + rqe = p->rxq_head; + p->rxq_head = p->rxq_head->next; + p->rxq_entries -= 1; + PRINT_D(RX_DBG, "RXQ entries decreased\n"); + p->os_func.os_leave_cs(p->rxq_lock); + return rqe; + } + PRINT_D(RX_DBG, "Nothing to get from Q\n"); + return NULL; +} + + +/******************************************** + * + * Power Save handle functions + * + ********************************************/ + + + +#ifdef WILC_OPTIMIZE_SLEEP_INT + +INLINE void chip_allow_sleep(void) +{ + uint32_t reg = 0; + + /* Clear bit 1 */ + g_wlan.hif_func.hif_read_reg(0xf0, ®); + + g_wlan.hif_func.hif_write_reg(0xf0, reg & ~(1 << 0)); +} + +INLINE void chip_wakeup(void) +{ + uint32_t reg, clk_status_reg, trials = 0; + uint32_t sleep_time; + + if ((g_wlan.io_func.io_type & 0x1) == HIF_SPI) { + do { + g_wlan.hif_func.hif_read_reg(1, ®); + /* Set bit 1 */ + g_wlan.hif_func.hif_write_reg(1, reg | (1 << 1)); + + /* Clear bit 1*/ + g_wlan.hif_func.hif_write_reg(1, reg & ~(1 << 1)); + + do { + /* Wait for the chip to stabilize*/ + WILC_Sleep(2); + /* Make sure chip is awake. This is an extra step that can be removed */ + /* later to avoid the bus access overhead */ + if ((wilc_get_chipid(WILC_TRUE) == 0)) { + wilc_debug(N_ERR, "Couldn't read chip id. Wake up failed\n"); + } + } while ((wilc_get_chipid(WILC_TRUE) == 0) && ((++trials % 3) == 0)); + + } while (wilc_get_chipid(WILC_TRUE) == 0); + } else if ((g_wlan.io_func.io_type & 0x1) == HIF_SDIO) { + g_wlan.hif_func.hif_read_reg(0xf0, ®); + do { + /* Set bit 1 */ + g_wlan.hif_func.hif_write_reg(0xf0, reg | (1 << 0)); + + /* Check the clock status */ + g_wlan.hif_func.hif_read_reg(0xf1, &clk_status_reg); + + /* in case of clocks off, wait 2ms, and check it again. */ + /* if still off, wait for another 2ms, for a total wait of 6ms. */ + /* If still off, redo the wake up sequence */ + while (((clk_status_reg & 0x1) == 0) && (((++trials) % 3) == 0)) { + /* Wait for the chip to stabilize*/ + WILC_Sleep(2); + + /* Make sure chip is awake. This is an extra step that can be removed */ + /* later to avoid the bus access overhead */ + g_wlan.hif_func.hif_read_reg(0xf1, &clk_status_reg); + + if ((clk_status_reg & 0x1) == 0) { + wilc_debug(N_ERR, "clocks still OFF. Wake up failed\n"); + } + } + /* in case of failure, Reset the wakeup bit to introduce a new edge on the next loop */ + if ((clk_status_reg & 0x1) == 0) { + /* Reset bit 0 */ + g_wlan.hif_func.hif_write_reg(0xf0, reg & (~(1 << 0))); + } + } while ((clk_status_reg & 0x1) == 0); + } + + + if (genuChipPSstate == CHIP_SLEEPING_MANUAL) { + g_wlan.hif_func.hif_read_reg(0x1C0C, ®); + reg &= ~(1 << 0); + g_wlan.hif_func.hif_write_reg(0x1C0C, reg); + + if (wilc_get_chipid(WILC_FALSE) >= 0x1002b0) { + /* Enable PALDO back right after wakeup */ + uint32_t val32; + g_wlan.hif_func.hif_read_reg(0x1e1c, &val32); + val32 |= (1 << 6); + g_wlan.hif_func.hif_write_reg(0x1e1c, val32); + + g_wlan.hif_func.hif_read_reg(0x1e9c, &val32); + val32 |= (1 << 6); + g_wlan.hif_func.hif_write_reg(0x1e9c, val32); + } + } + genuChipPSstate = CHIP_WAKEDUP; +} +#else +INLINE void chip_wakeup(void) +{ + uint32_t reg, trials = 0; + do { + if ((g_wlan.io_func.io_type & 0x1) == HIF_SPI) { + g_wlan.hif_func.hif_read_reg(1, ®); + /* Make sure bit 1 is 0 before we start. */ + g_wlan.hif_func.hif_write_reg(1, reg & ~(1 << 1)); + /* Set bit 1 */ + g_wlan.hif_func.hif_write_reg(1, reg | (1 << 1)); + /* Clear bit 1*/ + g_wlan.hif_func.hif_write_reg(1, reg & ~(1 << 1)); + } else if ((g_wlan.io_func.io_type & 0x1) == HIF_SDIO) { + /* Make sure bit 0 is 0 before we start. */ + g_wlan.hif_func.hif_read_reg(0xf0, ®); + g_wlan.hif_func.hif_write_reg(0xf0, reg & ~(1 << 0)); + /* Set bit 1 */ + g_wlan.hif_func.hif_write_reg(0xf0, reg | (1 << 0)); + /* Clear bit 1 */ + g_wlan.hif_func.hif_write_reg(0xf0, reg & ~(1 << 0)); + } + + do { + /* Wait for the chip to stabilize*/ +/* WILC_Sleep(2); */ + mdelay(3); + + /* Make sure chip is awake. This is an extra step that can be removed */ + /* later to avoid the bus access overhead */ + if ((wilc_get_chipid(WILC_TRUE) == 0)) { + wilc_debug(N_ERR, "Couldn't read chip id. Wake up failed\n"); + } + } while ((wilc_get_chipid(WILC_TRUE) == 0) && ((++trials % 3) == 0)); + + } while (wilc_get_chipid(WILC_TRUE) == 0); + + if (genuChipPSstate == CHIP_SLEEPING_MANUAL) { + g_wlan.hif_func.hif_read_reg(0x1C0C, ®); + reg &= ~(1 << 0); + g_wlan.hif_func.hif_write_reg(0x1C0C, reg); + + if (wilc_get_chipid(WILC_FALSE) >= 0x1002b0) { + /* Enable PALDO back right after wakeup */ + uint32_t val32; + g_wlan.hif_func.hif_read_reg(0x1e1c, &val32); + val32 |= (1 << 6); + g_wlan.hif_func.hif_write_reg(0x1e1c, val32); + + g_wlan.hif_func.hif_read_reg(0x1e9c, &val32); + val32 |= (1 << 6); + g_wlan.hif_func.hif_write_reg(0x1e9c, val32); + } + } + genuChipPSstate = CHIP_WAKEDUP; +} +#endif +void chip_sleep_manually(WILC_Uint32 u32SleepTime) +{ + uint32_t val32; + + if (genuChipPSstate != CHIP_WAKEDUP) { + /* chip is already sleeping. Do nothing */ + return; + } + acquire_bus(ACQUIRE_ONLY); + +#ifdef WILC_OPTIMIZE_SLEEP_INT + chip_allow_sleep(); +#endif + + /* Trigger the manual sleep interrupt */ + g_wlan.hif_func.hif_write_reg(0x10a8, 1); + + genuChipPSstate = CHIP_SLEEPING_MANUAL; + release_bus(RELEASE_ONLY); + +} + + +/******************************************** + * + * Tx, Rx queue handle functions + * + ********************************************/ +static int wilc_wlan_handle_txq(uint32_t *pu32TxqCount) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + int i, entries = 0; + uint32_t sum; + uint32_t reg; + uint8_t *txb = p->tx_buffer; + uint32_t offset = 0; + int vmm_sz = 0; + struct txq_entry_t *tqe; + int ret = 0; + int counter; + int timeout; + uint32_t vmm_table[WILC_VMM_TBL_SIZE]; + p->txq_exit = 0; + do { + if (p->quit) + break; + + /*Added by Amr - BugID_4720*/ + p->os_func.os_wait(p->txq_add_to_head_lock, CFG_PKTS_TIMEOUT); +#ifdef TCP_ACK_FILTER + wilc_wlan_txq_filter_dup_tcp_ack(); +#endif + /** + * build the vmm list + **/ + PRINT_D(TX_DBG, "Getting the head of the TxQ\n"); + tqe = wilc_wlan_txq_get_first(); + i = 0; + sum = 0; + do { + /* if ((tqe != NULL) && (i < (8)) && */ + /* if ((tqe != NULL) && (i < (WILC_VMM_TBL_SIZE-1)) && */ + if ((tqe != NULL) && (i < (WILC_VMM_TBL_SIZE - 1)) /* reserve last entry to 0 */) { + + if (tqe->type == WILC_CFG_PKT) { + vmm_sz = ETH_CONFIG_PKT_HDR_OFFSET; + } + /*Bug3959: transmitting mgmt frames received from host*/ + /*vmm_sz will only be equal to tqe->buffer_size + 4 bytes (HOST_HDR_OFFSET)*/ + /* in other cases WILC_MGMT_PKT and WILC_DATA_PKT_MAC_HDR*/ + else if (tqe->type == WILC_NET_PKT) { + vmm_sz = ETH_ETHERNET_HDR_OFFSET; + } +#ifdef WILC_FULLY_HOSTING_AP + else if (tqe->type == WILC_FH_DATA_PKT) { + vmm_sz = FH_TX_HOST_HDR_OFFSET; + } +#endif +#ifdef WILC_AP_EXTERNAL_MLME + else { + vmm_sz = HOST_HDR_OFFSET; + } +#endif + vmm_sz += tqe->buffer_size; + PRINT_D(TX_DBG, "VMM Size before alignment = %d\n", vmm_sz); + if (vmm_sz & 0x3) { /* has to be word aligned */ + vmm_sz = (vmm_sz + 4) & ~0x3; + } + if ((sum + vmm_sz) > p->tx_buffer_size) { + break; + } + PRINT_D(TX_DBG, "VMM Size AFTER alignment = %d\n", vmm_sz); + vmm_table[i] = vmm_sz / 4; /* table take the word size */ + PRINT_D(TX_DBG, "VMMTable entry size = %d\n", vmm_table[i]); + + if (tqe->type == WILC_CFG_PKT) { + vmm_table[i] |= (1 << 10); + PRINT_D(TX_DBG, "VMMTable entry changed for CFG packet = %d\n", vmm_table[i]); + } +#ifdef BIG_ENDIAN + vmm_table[i] = BYTE_SWAP(vmm_table[i]); +#endif + /* p->hif_func.hif_write_reg(0x1160,vmm_table[0]); */ + + /* wilc_debug(N_TXQ, "[wilc txq]: vmm table[%d] = %08x\n", i, vmm_table[i]); */ + i++; + sum += vmm_sz; + PRINT_D(TX_DBG, "sum = %d\n", sum); + tqe = wilc_wlan_txq_get_next(tqe); + } else { + break; + } + } while (1); + + if (i == 0) { /* nothing in the queue */ + PRINT_D(TX_DBG, "Nothing in TX-Q\n"); + break; + } else { + PRINT_D(TX_DBG, "Mark the last entry in VMM table - number of previous entries = %d\n", i); + vmm_table[i] = 0x0; /* mark the last element to 0 */ + } + acquire_bus(ACQUIRE_AND_WAKEUP); + counter = 0; + do { + + ret = p->hif_func.hif_read_reg(WILC_HOST_TX_CTRL, ®); + if (!ret) { + wilc_debug(N_ERR, "[wilc txq]: fail can't read reg vmm_tbl_entry..\n"); + break; + } + + if ((reg & 0x1) == 0) { + /** + * write to vmm table + **/ + PRINT_D(TX_DBG, "Writing VMM table ... with Size = %d\n", ((i + 1) * 4)); + break; + } else { + counter++; + if (counter > 200) { + counter = 0; + PRINT_D(TX_DBG, "Looping in tx ctrl , forcce quit\n"); + ret = p->hif_func.hif_write_reg(WILC_HOST_TX_CTRL, 0); + break; + } + /** + * wait for vmm table is ready + **/ + PRINT_WRN(GENERIC_DBG, "[wilc txq]: warn, vmm table not clear yet, wait... \n"); + release_bus(RELEASE_ALLOW_SLEEP); + p->os_func.os_sleep(3); /* wait 3 ms */ + acquire_bus(ACQUIRE_AND_WAKEUP); + } + } while (!p->quit); + + if (!ret) { + goto _end_; + } + + timeout = 200; + do { + + /** + * write to vmm table + **/ + ret = p->hif_func.hif_block_tx(WILC_VMM_TBL_RX_SHADOW_BASE, (uint8_t *)vmm_table, ((i + 1) * 4)); /* Bug 4477 fix */ + if (!ret) { + wilc_debug(N_ERR, "ERR block TX of VMM table.\n"); + break; + } + + + /** + * interrupt firmware + **/ + ret = p->hif_func.hif_write_reg(WILC_HOST_VMM_CTL, 0x2); + if (!ret) { + wilc_debug(N_ERR, "[wilc txq]: fail can't write reg host_vmm_ctl..\n"); + break; + } + + /** + * wait for confirm... + **/ + + do { + ret = p->hif_func.hif_read_reg(WILC_HOST_VMM_CTL, ®); + if (!ret) { + wilc_debug(N_ERR, "[wilc txq]: fail can't read reg host_vmm_ctl..\n"); + break; + } + if ((reg >> 2) & 0x1) { + /** + * Get the entries + **/ + entries = ((reg >> 3) & 0x3f); + /* entries = ((reg>>3)&0x2f); */ + break; + } else { + release_bus(RELEASE_ALLOW_SLEEP); + p->os_func.os_sleep(3); /* wait 3 ms */ + acquire_bus(ACQUIRE_AND_WAKEUP); + PRINT_WRN(GENERIC_DBG, "Can't get VMM entery - reg = %2x\n", reg); + } + } while (--timeout); + if (timeout <= 0) { + ret = p->hif_func.hif_write_reg(WILC_HOST_VMM_CTL, 0x0); + break; + } + + if (!ret) { + break; + } + + if (entries == 0) { + PRINT_WRN(GENERIC_DBG, "[wilc txq]: no more buffer in the chip (reg: %08x), retry later [[ %d, %x ]] \n", reg, i, vmm_table[i - 1]); + + /* undo the transaction. */ + ret = p->hif_func.hif_read_reg(WILC_HOST_TX_CTRL, ®); + if (!ret) { + wilc_debug(N_ERR, "[wilc txq]: fail can't read reg WILC_HOST_TX_CTRL..\n"); + break; + } + reg &= ~(1ul << 0); + ret = p->hif_func.hif_write_reg(WILC_HOST_TX_CTRL, reg); + if (!ret) { + wilc_debug(N_ERR, "[wilc txq]: fail can't write reg WILC_HOST_TX_CTRL..\n"); + break; + } + break; + } else { + break; + } + } while (1); + + if (!ret) { + goto _end_; + } + if (entries == 0) { + ret = WILC_TX_ERR_NO_BUF; + goto _end_; + } + + /* since copying data into txb takes some time, then + * allow the bus lock to be released let the RX task go. */ + release_bus(RELEASE_ALLOW_SLEEP); + + /** + * Copy data to the TX buffer + **/ + offset = 0; + i = 0; + do { + tqe = wilc_wlan_txq_remove_from_head(); + if (tqe != NULL && (vmm_table[i] != 0)) { + uint32_t header, buffer_offset; + +#ifdef BIG_ENDIAN + vmm_table[i] = BYTE_SWAP(vmm_table[i]); +#endif + vmm_sz = (vmm_table[i] & 0x3ff); /* in word unit */ + vmm_sz *= 4; + header = (tqe->type << 31) | (tqe->buffer_size << 15) | vmm_sz; + /*Bug3959: transmitting mgmt frames received from host*/ + /*setting bit 30 in the host header to indicate mgmt frame*/ +#ifdef WILC_AP_EXTERNAL_MLME + if (tqe->type == WILC_MGMT_PKT) { + header |= (1 << 30); + } else { + header &= ~(1 << 30); + } +#endif + /*else if(tqe->type == WILC_DATA_PKT_MAC_HDR) + * { + * header |= (1<< 29); + * }*/ + /* wilc_debug(N_TXQ, "[wilc txq]: header (%08x), real size (%d), vmm size (%d)\n", header, tqe->buffer_size, vmm_sz); */ + +#ifdef BIG_ENDIAN + header = BYTE_SWAP(header); +#endif + memcpy(&txb[offset], &header, 4); + if (tqe->type == WILC_CFG_PKT) { + buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET; + } + /*Bug3959: transmitting mgmt frames received from host*/ + /*buffer offset = HOST_HDR_OFFSET in other cases: WILC_MGMT_PKT*/ + /* and WILC_DATA_PKT_MAC_HDR*/ + else if (tqe->type == WILC_NET_PKT) { + char *pBSSID = ((struct tx_complete_data *)(tqe->priv))->pBssid; + buffer_offset = ETH_ETHERNET_HDR_OFFSET; + /* copy the bssid at the sart of the buffer */ + memcpy(&txb[offset + 4], pBSSID, 6); + } +#ifdef WILC_FULLY_HOSTING_AP + else if (tqe->type == WILC_FH_DATA_PKT) { + buffer_offset = FH_TX_HOST_HDR_OFFSET; + } +#endif + else { + buffer_offset = HOST_HDR_OFFSET; + } + + memcpy(&txb[offset + buffer_offset], tqe->buffer, tqe->buffer_size); + offset += vmm_sz; + i++; + tqe->status = 1; /* mark the packet send */ + if (tqe->tx_complete_func) + tqe->tx_complete_func(tqe->priv, tqe->status); + #ifdef TCP_ACK_FILTER + if (tqe->tcp_PendingAck_index != NOT_TCP_ACK) { + Pending_Acks_info[tqe->tcp_PendingAck_index].txqe = NULL; + } + #endif + p->os_func.os_free(tqe); + } else { + break; + } + } while (--entries); + + /** + * lock the bus + **/ + acquire_bus(ACQUIRE_AND_WAKEUP); + + ret = p->hif_func.hif_clear_int_ext(ENABLE_TX_VMM); + if (!ret) { + wilc_debug(N_ERR, "[wilc txq]: fail can't start tx VMM ...\n"); + goto _end_; + } + + /** + * transfer + **/ + ret = p->hif_func.hif_block_tx_ext(0, txb, offset); + if (!ret) { + wilc_debug(N_ERR, "[wilc txq]: fail can't block tx ext...\n"); + goto _end_; + } + +_end_: + + release_bus(RELEASE_ALLOW_SLEEP); + if (ret != 1) + break; + } while (0); + /* remove_TCP_related(); */ + /*Added by Amr - BugID_4720*/ + p->os_func.os_signal(p->txq_add_to_head_lock); + + p->txq_exit = 1; + PRINT_D(TX_DBG, "THREAD: Exiting txq\n"); + /* return tx[]q count */ + *pu32TxqCount = p->txq_entries; + return ret; +} + +static void wilc_wlan_handle_rxq(void) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + int offset = 0, size, has_packet = 0; + uint8_t *buffer; + struct rxq_entry_t *rqe; + + p->rxq_exit = 0; + + + + + do { + if (p->quit) { + PRINT_D(RX_DBG, "exit 1st do-while due to Clean_UP function \n"); + p->os_func.os_signal(p->cfg_wait); + break; + } + rqe = wilc_wlan_rxq_remove(); + if (rqe == NULL) { + PRINT_D(RX_DBG, "nothing in the queue - exit 1st do-while\n"); + break; + } + buffer = rqe->buffer; + size = rqe->buffer_size; + PRINT_D(RX_DBG, "rxQ entery Size = %d - Address = %p\n", size, buffer); + offset = 0; + + + + do { + uint32_t header; + uint32_t pkt_len, pkt_offset, tp_len; + int is_cfg_packet; + PRINT_D(RX_DBG, "In the 2nd do-while\n"); + memcpy(&header, &buffer[offset], 4); +#ifdef BIG_ENDIAN + header = BYTE_SWAP(header); +#endif + PRINT_D(RX_DBG, "Header = %04x - Offset = %d\n", header, offset); + + + + is_cfg_packet = (header >> 31) & 0x1; + pkt_offset = (header >> 22) & 0x1ff; + tp_len = (header >> 11) & 0x7ff; + pkt_len = header & 0x7ff; + + if (pkt_len == 0 || tp_len == 0) { + wilc_debug(N_RXQ, "[wilc rxq]: data corrupt, packet len or tp_len is 0 [%d][%d]\n", pkt_len, tp_len); + break; + } + +/*bug 3887: [AP] Allow Management frames to be passed to the host*/ + #if defined(WILC_AP_EXTERNAL_MLME) || defined(WILC_P2P) + #define IS_MANAGMEMENT 0x100 + #define IS_MANAGMEMENT_CALLBACK 0x080 + #define IS_MGMT_STATUS_SUCCES 0x040 + + + if (pkt_offset & IS_MANAGMEMENT) { + /* reset mgmt indicator bit, to use pkt_offeset in furthur calculations */ + pkt_offset &= ~(IS_MANAGMEMENT | IS_MANAGMEMENT_CALLBACK | IS_MGMT_STATUS_SUCCES); + +#ifdef USE_WIRELESS + WILC_WFI_mgmt_rx(&buffer[offset + HOST_HDR_OFFSET], pkt_len); + +#endif + + } + /* BUG4530 fix */ + else + #endif + { + /* wilc_debug(N_RXQ, "[wilc rxq]: packet, tp len(%d), len (%d), offset (%d), cfg (%d)\n", tp_len, pkt_len, pkt_offset, is_cfg_packet); */ + + if (!is_cfg_packet) { + + if (p->net_func.rx_indicate) { + if (pkt_len > 0) { + p->net_func.rx_indicate(&buffer[offset], pkt_len, pkt_offset); + has_packet = 1; + } + } + } else { + wilc_cfg_rsp_t rsp; + + + + p->cif_func.rx_indicate(&buffer[pkt_offset + offset], pkt_len, &rsp); + if (rsp.type == WILC_CFG_RSP) { + /** + * wake up the waiting task... + **/ + PRINT_D(RX_DBG, "p->cfg_seq_no = %d - rsp.seq_no = %d\n", p->cfg_seq_no, rsp.seq_no); + if (p->cfg_seq_no == rsp.seq_no) { + p->os_func.os_signal(p->cfg_wait); + } + /* p->os_func.os_signal(p->cfg_wait); */ + } else if (rsp.type == WILC_CFG_RSP_STATUS) { + /** + * Call back to indicate status... + **/ + if (p->indicate_func.mac_indicate) { + p->indicate_func.mac_indicate(WILC_MAC_INDICATE_STATUS); + } + + } else if (rsp.type == WILC_CFG_RSP_SCAN) { + if (p->indicate_func.mac_indicate) + p->indicate_func.mac_indicate(WILC_MAC_INDICATE_SCAN); + } + } + } + offset += tp_len; + if (offset >= size) + break; + } while (1); + + +#ifndef MEMORY_STATIC + if (buffer != NULL) + p->os_func.os_free((void *)buffer); +#endif + if (rqe != NULL) + p->os_func.os_free((void *)rqe); + + if (has_packet) { + if (p->net_func.rx_complete) + p->net_func.rx_complete(); + } + } while (1); + + p->rxq_exit = 1; + PRINT_D(RX_DBG, "THREAD: Exiting RX thread \n"); + return; +} + +/******************************************** + * + * Fast DMA Isr + * + ********************************************/ +static void wilc_unknown_isr_ext(void) +{ + g_wlan.hif_func.hif_clear_int_ext(0); +} +static void wilc_pllupdate_isr_ext(uint32_t int_stats) +{ + + int trials = 10; + + g_wlan.hif_func.hif_clear_int_ext(PLL_INT_CLR); + + /* Waiting for PLL */ + g_wlan.os_func.os_atomic_sleep(WILC_PLL_TO); + + /* poll till read a valid data */ + while (!(ISWILC1000(wilc_get_chipid(WILC_TRUE)) && --trials)) { + PRINT_D(TX_DBG, "PLL update retrying\n"); + g_wlan.os_func.os_atomic_sleep(1); + } +} + +static void wilc_sleeptimer_isr_ext(uint32_t int_stats1) +{ + g_wlan.hif_func.hif_clear_int_ext(SLEEP_INT_CLR); +#ifndef WILC_OPTIMIZE_SLEEP_INT + genuChipPSstate = CHIP_SLEEPING_AUTO; +#endif +} + +static void wilc_wlan_handle_isr_ext(uint32_t int_status) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; +#ifdef MEMORY_STATIC + uint32_t offset = p->rx_buffer_offset; +#endif + uint8_t *buffer = NULL; + uint32_t size; + uint32_t retries = 0; + int ret = 0; + struct rxq_entry_t *rqe; + + + /** + * Get the rx size + **/ + + size = ((int_status & 0x7fff) << 2); + + while (!size && retries < 10) { + uint32_t time = 0; + /*looping more secure*/ + /*zero size make a crashe because the dma will not happen and that will block the firmware*/ + wilc_debug(N_ERR, "RX Size equal zero ... Trying to read it again for %d time\n", time++); + p->hif_func.hif_read_size(&size); + size = ((size & 0x7fff) << 2); + retries++; + + } + + if (size > 0) { +#ifdef MEMORY_STATIC + if (p->rx_buffer_size - offset < size) + offset = 0; + + if (p->rx_buffer) + buffer = &p->rx_buffer[offset]; + else { + wilc_debug(N_ERR, "[wilc isr]: fail Rx Buffer is NULL...drop the packets (%d)\n", size); + goto _end_; + } + +#else + buffer = p->os_func.os_malloc(size); + if (buffer == NULL) { + wilc_debug(N_ERR, "[wilc isr]: fail alloc host memory...drop the packets (%d)\n", size); + WILC_Sleep(100); + goto _end_; + } +#endif + + /** + * clear the chip's interrupt after getting size some register getting corrupted after clear the interrupt + **/ + p->hif_func.hif_clear_int_ext(DATA_INT_CLR | ENABLE_RX_VMM); + + + /** + * start transfer + **/ + ret = p->hif_func.hif_block_rx_ext(0, buffer, size); + + if (!ret) { + wilc_debug(N_ERR, "[wilc isr]: fail block rx...\n"); + goto _end_; + } +_end_: + + + if (ret) { +#ifdef MEMORY_STATIC + offset += size; + p->rx_buffer_offset = offset; +#endif + /** + * add to rx queue + **/ + rqe = (struct rxq_entry_t *)p->os_func.os_malloc(sizeof(struct rxq_entry_t)); + if (rqe != NULL) { + rqe->buffer = buffer; + rqe->buffer_size = size; + PRINT_D(RX_DBG, "rxq entery Size= %d - Address = %p\n", rqe->buffer_size, rqe->buffer); + wilc_wlan_rxq_add(rqe); + p->os_func.os_signal(p->rxq_wait); + } + } else { +#ifndef MEMORY_STATIC + if (buffer != NULL) + p->os_func.os_free(buffer); +#endif + } + } +#ifdef TCP_ENHANCEMENTS + wilc_wlan_handle_rxq(); +#endif +} + +void wilc_handle_isr(void) +{ + uint32_t int_status; + + acquire_bus(ACQUIRE_AND_WAKEUP); + g_wlan.hif_func.hif_read_int(&int_status); + + if (int_status & PLL_INT_EXT) { + wilc_pllupdate_isr_ext(int_status); + } + if (int_status & DATA_INT_EXT) { + wilc_wlan_handle_isr_ext(int_status); + #ifndef WILC_OPTIMIZE_SLEEP_INT + /* Chip is up and talking*/ + genuChipPSstate = CHIP_WAKEDUP; + #endif + } + if (int_status & SLEEP_INT_EXT) { + wilc_sleeptimer_isr_ext(int_status); + } + + if (!(int_status & (ALL_INT_EXT))) { +#ifdef WILC_SDIO + PRINT_D(TX_DBG, ">> UNKNOWN_INTERRUPT - 0x%08x\n", int_status); +#endif + wilc_unknown_isr_ext(); + } +#if ((!defined WILC_SDIO) || (defined WILC_SDIO_IRQ_GPIO)) + linux_wlan_enable_irq(); +#endif + release_bus(RELEASE_ALLOW_SLEEP); +} + +/******************************************** + * + * Firmware download + * + ********************************************/ +static int wilc_wlan_firmware_download(const uint8_t *buffer, uint32_t buffer_size) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + uint32_t offset; + uint32_t addr, size, size2, blksz; + uint8_t *dma_buffer; + int ret = 0; + + blksz = (1ul << 12); /* Bug 4703: 4KB Good enough size for most platforms = PAGE_SIZE. */ + /* Allocate a DMA coherent buffer. */ + +#if (defined WILC_PREALLOC_AT_BOOT) + { + extern void *get_fw_buffer(void); + dma_buffer = (uint8_t *)get_fw_buffer(); + PRINT_D(TX_DBG, "fw_buffer = 0x%x\n", dma_buffer); + } +#else + dma_buffer = (uint8_t *)g_wlan.os_func.os_malloc(blksz); +#endif + if (dma_buffer == NULL) { + /*EIO 5*/ + ret = -5; + PRINT_ER("Can't allocate buffer for firmware download IO error\n "); + goto _fail_1; + } + + PRINT_D(INIT_DBG, "Downloading firmware size = %d ...\n", buffer_size); + /** + * load the firmware + **/ + offset = 0; + do { + memcpy(&addr, &buffer[offset], 4); + memcpy(&size, &buffer[offset + 4], 4); +#ifdef BIG_ENDIAN + addr = BYTE_SWAP(addr); + size = BYTE_SWAP(size); +#endif + acquire_bus(ACQUIRE_ONLY); + offset += 8; + while (((int)size) && (offset < buffer_size)) { + if (size <= blksz) { + size2 = size; + } else { + size2 = blksz; + } + /* Copy firmware into a DMA coherent buffer */ + memcpy(dma_buffer, &buffer[offset], size2); + ret = p->hif_func.hif_block_tx(addr, dma_buffer, size2); + if (!ret) + break; + + addr += size2; + offset += size2; + size -= size2; + } + release_bus(RELEASE_ONLY); + + if (!ret) { + /*EIO 5*/ + ret = -5; + PRINT_ER("Can't download firmware IO error\n "); + goto _fail_; + } + PRINT_D(INIT_DBG, "Offset = %d\n", offset); + } while (offset < buffer_size); + +_fail_: + +#if (defined WILC_PREALLOC_AT_BOOT) + +#else + if (dma_buffer) + g_wlan.os_func.os_free(dma_buffer); +#endif + +_fail_1: + + return (ret < 0) ? ret : 0; +} + +/******************************************** + * + * Common + * + ********************************************/ +static int wilc_wlan_start(void) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + uint32_t reg = 0; + int ret; + uint32_t chipid; + + /** + * Set the host interface + **/ +#ifdef OLD_FPGA_BITFILE + acquire_bus(ACQUIRE_ONLY); + ret = p->hif_func.hif_read_reg(WILC_VMM_CORE_CTL, ®); + if (!ret) { + wilc_debug(N_ERR, "[wilc start]: fail read reg vmm_core_ctl...\n"); + release_bus(RELEASE_ALLOW_SLEEP); + return ret; + } + reg |= (p->io_func.io_type << 2); + ret = p->hif_func.hif_write_reg(WILC_VMM_CORE_CTL, reg); + if (!ret) { + wilc_debug(N_ERR, "[wilc start]: fail write reg vmm_core_ctl...\n"); + release_bus(RELEASE_ONLY); + return ret; + } +#else + if (p->io_func.io_type == HIF_SDIO) { + reg = 0; + reg |= (1 << 3); /* bug 4456 and 4557 */ + } else if (p->io_func.io_type == HIF_SPI) { + reg = 1; + } + acquire_bus(ACQUIRE_ONLY); + ret = p->hif_func.hif_write_reg(WILC_VMM_CORE_CFG, reg); + if (!ret) { + wilc_debug(N_ERR, "[wilc start]: fail write reg vmm_core_cfg...\n"); + release_bus(RELEASE_ONLY); + /* EIO 5*/ + ret = -5; + return ret; + } + reg = 0; +#ifdef WILC_SDIO_IRQ_GPIO + reg |= WILC_HAVE_SDIO_IRQ_GPIO; +#endif + +#ifdef WILC_DISABLE_PMU +#else + reg |= WILC_HAVE_USE_PMU; +#endif + +#ifdef WILC_SLEEP_CLK_SRC_XO + reg |= WILC_HAVE_SLEEP_CLK_SRC_XO; +#elif defined WILC_SLEEP_CLK_SRC_RTC + reg |= WILC_HAVE_SLEEP_CLK_SRC_RTC; +#endif + +#ifdef WILC_EXT_PA_INV_TX_RX + reg |= WILC_HAVE_EXT_PA_INV_TX_RX; +#endif + + reg |= WILC_HAVE_LEGACY_RF_SETTINGS; + + +/*BugID_5257*/ +/*Set oscillator frequency*/ +#ifdef XTAL_24 + reg |= WILC_HAVE_XTAL_24; +#endif + +/*BugID_5271*/ +/*Enable/Disable GPIO configuration for FW logs*/ +#ifdef DISABLE_WILC_UART + reg |= WILC_HAVE_DISABLE_WILC_UART; +#endif + + ret = p->hif_func.hif_write_reg(WILC_GP_REG_1, reg); + if (!ret) { + wilc_debug(N_ERR, "[wilc start]: fail write WILC_GP_REG_1 ...\n"); + release_bus(RELEASE_ONLY); + /* EIO 5*/ + ret = -5; + return ret; + } +#endif + + + /** + * Bus related + **/ + p->hif_func.hif_sync_ext(NUM_INT_EXT); + + ret = p->hif_func.hif_read_reg(0x1000, &chipid); + if (!ret) { + wilc_debug(N_ERR, "[wilc start]: fail read reg 0x1000 ...\n"); + release_bus(RELEASE_ONLY); + /* EIO 5*/ + ret = -5; + return ret; + } + + /** + * Go... + **/ + + /* p->hif_func.hif_write_reg(0x150014, reg); */ + + p->hif_func.hif_read_reg(WILC_GLB_RESET_0, ®); + if ((reg & (1ul << 10)) == (1ul << 10)) { + reg &= ~(1ul << 10); + p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg); + p->hif_func.hif_read_reg(WILC_GLB_RESET_0, ®); + } + + reg |= (1ul << 10); + ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg); + p->hif_func.hif_read_reg(WILC_GLB_RESET_0, ®); + release_bus(RELEASE_ONLY); + + return (ret < 0) ? ret : 0; +} + +void wilc_wlan_global_reset(void) +{ + + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + acquire_bus(ACQUIRE_AND_WAKEUP); + p->hif_func.hif_write_reg(WILC_GLB_RESET_0, 0x0); + release_bus(RELEASE_ONLY); +} +static int wilc_wlan_stop(void) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + uint32_t reg = 0; + int ret; + uint8_t timeout = 10; + /** + * TODO: stop the firmware, need a re-download + **/ + acquire_bus(ACQUIRE_AND_WAKEUP); + + ret = p->hif_func.hif_read_reg(WILC_GLB_RESET_0, ®); + if (!ret) { + PRINT_ER("Error while reading reg\n"); + release_bus(RELEASE_ALLOW_SLEEP); + return ret; + } + + reg &= ~(1 << 10); + + + ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg); + if (!ret) { + PRINT_ER("Error while writing reg\n"); + release_bus(RELEASE_ALLOW_SLEEP); + return ret; + } + + + + do { + ret = p->hif_func.hif_read_reg(WILC_GLB_RESET_0, ®); + if (!ret) { + PRINT_ER("Error while reading reg\n"); + release_bus(RELEASE_ALLOW_SLEEP); + return ret; + } + PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n", reg, timeout); + /*Workaround to ensure that the chip is actually reset*/ + if ((reg & (1 << 10))) { + PRINT_D(GENERIC_DBG, "Bit 10 not reset : Retry %d\n", timeout); + reg &= ~(1 << 10); + ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg); + timeout--; + } else { + PRINT_D(GENERIC_DBG, "Bit 10 reset after : Retry %d\n", timeout); + ret = p->hif_func.hif_read_reg(WILC_GLB_RESET_0, ®); + if (!ret) { + PRINT_ER("Error while reading reg\n"); + release_bus(RELEASE_ALLOW_SLEEP); + return ret; + } + PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n", reg, timeout); + break; + } + + } while (timeout); +#if 1 +/******************************************************************************/ +/* This was add at Bug 4595 to reset the chip while maintaining the bus state */ +/******************************************************************************/ + reg = ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 8) | (1 << 9) | (1 << 26) | (1 << 29) | (1 << 30) | (1 << 31)); /**/ + /**/ + ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg); /**/ + reg = ~(1 << 10); /**/ + /**/ + ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg); /**/ +/******************************************************************************/ +#endif + + release_bus(RELEASE_ALLOW_SLEEP); + + return ret; +} + +static void wilc_wlan_cleanup(void) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + struct txq_entry_t *tqe; + struct rxq_entry_t *rqe; + uint32_t reg = 0; + int ret; + + p->quit = 1; + /** + * wait for queue end + **/ + /* p->os_func.os_signal(p->txq_wait); */ + /* p->os_func.os_signal(p->rxq_wait); */ + + /* complete(p->txq_wait); */ + /* complete(p->rxq_wait); */ + /*do { + * if (p->txq_exit && p->rxq_exit) + * break; + * } while (1);*/ + + /** + * clean up the queue + **/ + do { + tqe = wilc_wlan_txq_remove_from_head(); + if (tqe == NULL) + break; + if (tqe->tx_complete_func) + tqe->tx_complete_func(tqe->priv, 0); + p->os_func.os_free((void *)tqe); + } while (1); + + do { + rqe = wilc_wlan_rxq_remove(); + if (rqe == NULL) + break; +#ifdef MEMORY_DYNAMIC + p->os_func.os_free((void *)tqe->buffer); +#endif + p->os_func.os_free((void *)rqe); + } while (1); + + /** + * clean up buffer + **/ + +#if (defined WILC_PREALLOC_AT_BOOT) + +#else + #ifdef MEMORY_STATIC + if (p->rx_buffer) { + p->os_func.os_free(p->rx_buffer); + p->rx_buffer = WILC_NULL; + } + #endif + if (p->tx_buffer) { + p->os_func.os_free(p->tx_buffer); + p->tx_buffer = WILC_NULL; + } +#endif + + acquire_bus(ACQUIRE_AND_WAKEUP); + + + ret = p->hif_func.hif_read_reg(WILC_GP_REG_0, ®); + if (!ret) { + PRINT_ER("Error while reading reg\n"); + release_bus(RELEASE_ALLOW_SLEEP); + } + PRINT_ER("Writing ABORT reg\n"); + ret = p->hif_func.hif_write_reg(WILC_GP_REG_0, (reg | ABORT_INT)); + if (!ret) { + PRINT_ER("Error while writing reg\n"); + release_bus(RELEASE_ALLOW_SLEEP); + } + release_bus(RELEASE_ALLOW_SLEEP); + /** + * io clean up + **/ + p->hif_func.hif_deinit(NULL); + +} + +static int wilc_wlan_cfg_commit(int type, uint32_t drvHandler) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + wilc_cfg_frame_t *cfg = &p->cfg_frame; + int total_len = p->cfg_frame_offset + 4 + DRIVER_HANDLER_SIZE; + int seq_no = p->cfg_seq_no % 256; + int driver_handler = (WILC_Uint32)drvHandler; + + + /** + * Set up header + **/ + if (type == WILC_CFG_SET) { /* Set */ + cfg->wid_header[0] = 'W'; + } else { /* Query */ + cfg->wid_header[0] = 'Q'; + } + cfg->wid_header[1] = seq_no; /* sequence number */ + cfg->wid_header[2] = (uint8_t)total_len; + cfg->wid_header[3] = (uint8_t)(total_len >> 8); + cfg->wid_header[4] = (uint8_t)driver_handler; + cfg->wid_header[5] = (uint8_t)(driver_handler >> 8); + cfg->wid_header[6] = (uint8_t)(driver_handler >> 16); + cfg->wid_header[7] = (uint8_t)(driver_handler >> 24); + p->cfg_seq_no = seq_no; + + /** + * Add to TX queue + **/ + + /*Edited by Amr - BugID_4720*/ + if (!wilc_wlan_txq_add_cfg_pkt(&cfg->wid_header[0], total_len)) + return -1; + + return 0; +} + +static int wilc_wlan_cfg_set(int start, uint32_t wid, uint8_t *buffer, uint32_t buffer_size, int commit, uint32_t drvHandler) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + uint32_t offset; + int ret_size; + + + if (p->cfg_frame_in_use) + return 0; + + if (start) + p->cfg_frame_offset = 0; + + offset = p->cfg_frame_offset; + ret_size = p->cif_func.cfg_wid_set(p->cfg_frame.frame, offset, (uint16_t)wid, buffer, buffer_size); + offset += ret_size; + p->cfg_frame_offset = offset; + + if (commit) { + PRINT_D(TX_DBG, "[WILC]PACKET Commit with sequence number %d\n", p->cfg_seq_no); + PRINT_D(RX_DBG, "Processing cfg_set()\n"); + p->cfg_frame_in_use = 1; + + /*Edited by Amr - BugID_4720*/ + if (wilc_wlan_cfg_commit(WILC_CFG_SET, drvHandler)) + ret_size = 0; /* BugID_5213 */ + + if (p->os_func.os_wait(p->cfg_wait, CFG_PKTS_TIMEOUT)) { + PRINT_D(TX_DBG, "Set Timed Out\n"); + ret_size = 0; + } + p->cfg_frame_in_use = 0; + p->cfg_frame_offset = 0; + p->cfg_seq_no += 1; + + } + + return ret_size; +} +static int wilc_wlan_cfg_get(int start, uint32_t wid, int commit, uint32_t drvHandler) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + uint32_t offset; + int ret_size; + + + if (p->cfg_frame_in_use) + return 0; + + if (start) + p->cfg_frame_offset = 0; + + offset = p->cfg_frame_offset; + ret_size = p->cif_func.cfg_wid_get(p->cfg_frame.frame, offset, (uint16_t)wid); + offset += ret_size; + p->cfg_frame_offset = offset; + + if (commit) { + p->cfg_frame_in_use = 1; + + /*Edited by Amr - BugID_4720*/ + if (wilc_wlan_cfg_commit(WILC_CFG_QUERY, drvHandler)) + ret_size = 0; /* BugID_5213 */ + + + if (p->os_func.os_wait(p->cfg_wait, CFG_PKTS_TIMEOUT)) { + PRINT_D(TX_DBG, "Get Timed Out\n"); + ret_size = 0; + } + PRINT_D(GENERIC_DBG, "[WILC]Get Response received\n"); + p->cfg_frame_in_use = 0; + p->cfg_frame_offset = 0; + p->cfg_seq_no += 1; + } + + return ret_size; +} + +static int wilc_wlan_cfg_get_val(uint32_t wid, uint8_t *buffer, uint32_t buffer_size) +{ + wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan; + int ret; + + ret = p->cif_func.cfg_wid_get_val((uint16_t)wid, buffer, buffer_size); + + return ret; +} + +void wilc_bus_set_max_speed(void) +{ + + /* Increase bus speed to max possible. */ + g_wlan.hif_func.hif_set_max_bus_speed(); +} + +void wilc_bus_set_default_speed(void) +{ + + /* Restore bus speed to default. */ + g_wlan.hif_func.hif_set_default_bus_speed(); +} +uint32_t init_chip(void) +{ + uint32_t chipid; + uint32_t reg, ret = 0; + +#if defined(PLAT_RK3026_TCHIP) + acquire_bus(ACQUIRE_AND_WAKEUP); /* AMR : 0422 RK3026 Crash issue */ +#else + acquire_bus(ACQUIRE_ONLY); +#endif + + chipid = wilc_get_chipid(WILC_TRUE); + + + + if ((chipid & 0xfff) != 0xa0) { + /** + * Avoid booting from boot ROM. Make sure that Drive IRQN [SDIO platform] + * or SD_DAT3 [SPI platform] to ?1? + **/ + /* Set cortus reset register to register control. */ + ret = g_wlan.hif_func.hif_read_reg(0x1118, ®); + if (!ret) { + wilc_debug(N_ERR, "[wilc start]: fail read reg 0x1118 ...\n"); + return ret; + } + reg |= (1 << 0); + ret = g_wlan.hif_func.hif_write_reg(0x1118, reg); + if (!ret) { + wilc_debug(N_ERR, "[wilc start]: fail write reg 0x1118 ...\n"); + return ret; + } + /** + * Write branch intruction to IRAM (0x71 trap) at location 0xFFFF0000 + * (Cortus map) or C0000 (AHB map). + **/ + ret = g_wlan.hif_func.hif_write_reg(0xc0000, 0x71); + if (!ret) { + wilc_debug(N_ERR, "[wilc start]: fail write reg 0xc0000 ...\n"); + return ret; + } + } + + + #if 0 + if ((chipid & 0xfff) < 0xf0) { + /* Setting MUX to probe sleep signal on pin 6 of J216*/ + g_wlan.hif_func.hif_write_reg(0x1060, 0x1); + g_wlan.hif_func.hif_write_reg(0x1180, 0x33333333); + g_wlan.hif_func.hif_write_reg(0x1184, 0x33333333); + g_wlan.hif_func.hif_read_reg(0x1408, ®); + /* set MUX for GPIO_4 (pin 4) to cortus GPIO*/ + reg &= ~((0x7 << 16)); + g_wlan.hif_func.hif_write_reg(0x1408, (reg | (0x7 << 12))); + } else { + /* Enable test bus*/ + g_wlan.hif_func.hif_write_reg(0x1060, 0x1); + /* Rotate bus signals to get sleep signal on pin 6 like it was on previous chips*/ + g_wlan.hif_func.hif_write_reg(0x1188, 0x70); + /* Set output of pin 6 to test bus 0x1*/ + /* Set output of pin 9 to test bus 0x2*/ + g_wlan.hif_func.hif_write_reg(0x1180, 0x200100); + g_wlan.hif_func.hif_read_reg(0x1408, ®); + + /* set MUX for GPIO_4 (pin 4) to cortus GPIO*/ + reg &= ~((0x7 << 16)); + /* set MUX for GPIO_3 (pin 6) to test bus*/ + reg |= (0x7 << 12) | (0x7 << 24); + g_wlan.hif_func.hif_write_reg(0x1408, reg); + } + #endif + + + + release_bus(RELEASE_ONLY); + + return ret; + +} + +uint32_t wilc_get_chipid(uint8_t update) +{ + static uint32_t chipid; + /* SDIO can't read into global variables */ + /* Use this variable as a temp, then copy to the global */ + uint32_t tempchipid = 0; + uint32_t rfrevid; + + if (chipid == 0 || update != 0) { + g_wlan.hif_func.hif_read_reg(0x1000, &tempchipid); + g_wlan.hif_func.hif_read_reg(0x13f4, &rfrevid); + if (!ISWILC1000(tempchipid)) { + chipid = 0; + goto _fail_; + } + if (tempchipid == 0x1002a0) { + if (rfrevid == 0x1) { /* 1002A0 */ + } else { /* if (rfrevid == 0x2) */ /* 1002A1 */ + tempchipid = 0x1002a1; + } + } else if (tempchipid == 0x1002b0) { + if (rfrevid == 3) { /* 1002B0 */ + } else if (rfrevid == 4) { /* 1002B1 */ + tempchipid = 0x1002b1; + } else { /* if(rfrevid == 5) */ /* 1002B2 */ + tempchipid = 0x1002b2; + } + } else { + } + + chipid = tempchipid; + } +_fail_: + return chipid; +} + +#ifdef COMPLEMENT_BOOT +uint8_t core_11b_ready(void) +{ + uint32_t reg_val; + + acquire_bus(ACQUIRE_ONLY); + g_wlan.hif_func.hif_write_reg(0x16082c, 1); + g_wlan.hif_func.hif_write_reg(0x161600, 0x90); + g_wlan.hif_func.hif_read_reg(0x161600, ®_val); + release_bus(RELEASE_ONLY); + + if (reg_val == 0x90) + return 0; + else + return 1; +} +#endif + +int wilc_wlan_init(wilc_wlan_inp_t *inp, wilc_wlan_oup_t *oup) +{ + + int ret = 0; + + PRINT_D(INIT_DBG, "Initializing WILC_Wlan ...\n"); + + memset((void *)&g_wlan, 0, sizeof(wilc_wlan_dev_t)); + + /** + * store the input + **/ + memcpy((void *)&g_wlan.os_func, (void *)&inp->os_func, sizeof(wilc_wlan_os_func_t)); + memcpy((void *)&g_wlan.io_func, (void *)&inp->io_func, sizeof(wilc_wlan_io_func_t)); + memcpy((void *)&g_wlan.net_func, (void *)&inp->net_func, sizeof(wilc_wlan_net_func_t)); + memcpy((void *)&g_wlan.indicate_func, (void *)&inp->indicate_func, sizeof(wilc_wlan_net_func_t)); + g_wlan.hif_lock = inp->os_context.hif_critical_section; + g_wlan.txq_lock = inp->os_context.txq_critical_section; + + /*Added by Amr - BugID_4720*/ + g_wlan.txq_add_to_head_lock = inp->os_context.txq_add_to_head_critical_section; + + /*Added by Amr - BugID_4720*/ + g_wlan.txq_spinlock = inp->os_context.txq_spin_lock; + + g_wlan.rxq_lock = inp->os_context.rxq_critical_section; + g_wlan.txq_wait = inp->os_context.txq_wait_event; + g_wlan.rxq_wait = inp->os_context.rxq_wait_event; + g_wlan.cfg_wait = inp->os_context.cfg_wait_event; + g_wlan.tx_buffer_size = inp->os_context.tx_buffer_size; +#if defined (MEMORY_STATIC) + g_wlan.rx_buffer_size = inp->os_context.rx_buffer_size; +#endif + /* g_wlan.os_func.os_lock(g_wlan.cfg_wait); */ + /*** + * host interface init + **/ +#if defined(PLAT_RK3026_TCHIP) /* AMR : 0422 RK3026 Crash issue */ + if (!g_wilc_initialized) { + custom_lock_bus(g_mac_open); + custom_wakeup(g_mac_open); + } +#endif + + if ((inp->io_func.io_type & 0x1) == HIF_SDIO) { + if (!hif_sdio.hif_init(inp, wilc_debug)) { + /* EIO 5 */ + ret = -5; + goto _fail_; + } + memcpy((void *)&g_wlan.hif_func, &hif_sdio, sizeof(wilc_hif_func_t)); + } else { + if ((inp->io_func.io_type & 0x1) == HIF_SPI) { + /** + * TODO: + **/ + if (!hif_spi.hif_init(inp, wilc_debug)) { + /* EIO 5 */ + ret = -5; + goto _fail_; + } + memcpy((void *)&g_wlan.hif_func, &hif_spi, sizeof(wilc_hif_func_t)); + } else { + /* EIO 5 */ + ret = -5; + goto _fail_; + } + } + + /*** + * mac interface init + **/ + if (!mac_cfg.cfg_init(wilc_debug)) { + /* ENOBUFS 105 */ + ret = -105; + goto _fail_; + } + memcpy((void *)&g_wlan.cif_func, &mac_cfg, sizeof(wilc_cfg_func_t)); + + + /** + * alloc tx, rx buffer + **/ +#if (defined WILC_PREALLOC_AT_BOOT) + extern void *get_tx_buffer(void); + extern void *get_rx_buffer(void); + + PRINT_D(TX_DBG, "malloc before, g_wlan.tx_buffer = 0x%x, g_wlan.rx_buffer = 0x%x\n", g_wlan.tx_buffer, g_wlan.rx_buffer); +#endif + + + + if (g_wlan.tx_buffer == WILC_NULL) +#if (defined WILC_PREALLOC_AT_BOOT) + g_wlan.tx_buffer = (uint8_t *)get_tx_buffer(); +#else + g_wlan.tx_buffer = (uint8_t *)g_wlan.os_func.os_malloc(g_wlan.tx_buffer_size); +#endif + PRINT_D(TX_DBG, "g_wlan.tx_buffer = 0x%x\n", g_wlan.tx_buffer); + + if (g_wlan.tx_buffer == WILC_NULL) { + /* ENOBUFS 105 */ + ret = -105; + PRINT_ER("Can't allocate Tx Buffer"); + goto _fail_; + } + +/* rx_buffer is not used unless we activate USE_MEM STATIC which is not applicable, allocating such memory is useless*/ +#if defined (MEMORY_STATIC) + if (g_wlan.rx_buffer == WILC_NULL) + #if (defined WILC_PREALLOC_AT_BOOT) + g_wlan.rx_buffer = (uint8_t *)get_rx_buffer(); + #else + g_wlan.rx_buffer = (uint8_t *)g_wlan.os_func.os_malloc(g_wlan.rx_buffer_size); + #endif + PRINT_D(TX_DBG, "g_wlan.rx_buffer =0x%x\n", g_wlan.rx_buffer); + if (g_wlan.rx_buffer == WILC_NULL) { + /* ENOBUFS 105 */ + ret = -105; + PRINT_ER("Can't allocate Rx Buffer"); + goto _fail_; + } +#endif + + /** + * export functions + **/ + oup->wlan_firmware_download = wilc_wlan_firmware_download; + oup->wlan_start = wilc_wlan_start; + oup->wlan_stop = wilc_wlan_stop; + oup->wlan_add_to_tx_que = wilc_wlan_txq_add_net_pkt; + oup->wlan_handle_tx_que = wilc_wlan_handle_txq; + oup->wlan_handle_rx_que = wilc_wlan_handle_rxq; + /* oup->wlan_handle_rx_isr = wilc_wlan_handle_isr; */ + oup->wlan_handle_rx_isr = wilc_handle_isr; + oup->wlan_cleanup = wilc_wlan_cleanup; + oup->wlan_cfg_set = wilc_wlan_cfg_set; + oup->wlan_cfg_get = wilc_wlan_cfg_get; + oup->wlan_cfg_get_value = wilc_wlan_cfg_get_val; + + /*Bug3959: transmitting mgmt frames received from host*/ + #if defined(WILC_AP_EXTERNAL_MLME) || defined(WILC_P2P) + oup->wlan_add_mgmt_to_tx_que = wilc_wlan_txq_add_mgmt_pkt; + + #ifdef WILC_FULLY_HOSTING_AP + oup->wlan_add_data_to_tx_que = wilc_FH_wlan_txq_add_net_pkt; + #endif + #endif + + if (!init_chip()) { + /* EIO 5 */ + ret = -5; + goto _fail_; + } +#ifdef TCP_ACK_FILTER + Init_TCP_tracking(); +#endif + +#if defined(PLAT_RK3026_TCHIP) /* AMR : 0422 RK3026 Crash issue */ + if (!g_wilc_initialized) + custom_unlock_bus(g_mac_open); +#endif + + return 1; + +_fail_: + +#if (defined WILC_PREALLOC_AT_BOOT) + +#else + #ifdef MEMORY_STATIC + if (g_wlan.rx_buffer) { + g_wlan.os_func.os_free(g_wlan.rx_buffer); + g_wlan.rx_buffer = WILC_NULL; + } + #endif + if (g_wlan.tx_buffer) { + g_wlan.os_func.os_free(g_wlan.tx_buffer); + g_wlan.tx_buffer = WILC_NULL; + } +#endif + +#if defined(PLAT_RK3026_TCHIP) /* AMR : 0422 RK3026 Crash issue */ + if (!g_wilc_initialized) + custom_unlock_bus(g_mac_open); +#endif + + return ret; + +} + +#define BIT31 (1 << 31) +WILC_Uint16 Set_machw_change_vir_if(WILC_Bool bValue) +{ + WILC_Uint16 ret; + WILC_Uint32 reg; + + /*Reset WILC_CHANGING_VIR_IF register to allow adding futrue keys to CE H/W*/ + (&g_wlan)->os_func.os_enter_cs((&g_wlan)->hif_lock); + ret = (&g_wlan)->hif_func.hif_read_reg(WILC_CHANGING_VIR_IF, ®); + if (!ret) { + PRINT_ER("Error while Reading reg WILC_CHANGING_VIR_IF\n"); + } + + if (bValue == WILC_TRUE) { + reg |= (BIT31); + } else { + reg &= ~(BIT31); + } + + ret = (&g_wlan)->hif_func.hif_write_reg(WILC_CHANGING_VIR_IF, reg); + + if (!ret) { + PRINT_ER("Error while writing reg WILC_CHANGING_VIR_IF\n"); + } + (&g_wlan)->os_func.os_leave_cs((&g_wlan)->hif_lock); + + return ret; +} + +#ifdef WILC_FULLY_HOSTING_AP +wilc_wlan_dev_t *Get_wlan_context(WILC_Uint16 *pu16size) +{ + *pu16size = sizeof(wilc_wlan_dev_t); + return &g_wlan; +} +#endif + diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h new file mode 100644 index 000000000000..0ba7ec69e2b4 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -0,0 +1,321 @@ +#ifndef WILC_WLAN_H +#define WILC_WLAN_H + +#include "wilc_type.h" + + +#define ISWILC1000(id) (((id & 0xfffff000) == 0x100000) ? 1 : 0) + + +/******************************************** + * + * Mac eth header length + * + ********************************************/ +#define DRIVER_HANDLER_SIZE 4 +#define MAX_MAC_HDR_LEN 26 /* QOS_MAC_HDR_LEN */ +#define SUB_MSDU_HEADER_LENGTH 14 +#define SNAP_HDR_LEN 8 +#define ETHERNET_HDR_LEN 14 +#define WORD_ALIGNMENT_PAD 0 + +#define ETH_ETHERNET_HDR_OFFSET (MAX_MAC_HDR_LEN + SUB_MSDU_HEADER_LENGTH + \ + SNAP_HDR_LEN - ETHERNET_HDR_LEN + WORD_ALIGNMENT_PAD) + +/*Bug3959: transmitting mgmt frames received from host*/ +#define HOST_HDR_OFFSET 4 +#define ETHERNET_HDR_LEN 14 +#define IP_HDR_LEN 20 +#define IP_HDR_OFFSET ETHERNET_HDR_LEN +#define UDP_HDR_OFFSET (IP_HDR_LEN + IP_HDR_OFFSET) +#define UDP_HDR_LEN 8 +#define UDP_DATA_OFFSET (UDP_HDR_OFFSET + UDP_HDR_LEN) +#define ETH_CONFIG_PKT_HDR_LEN UDP_DATA_OFFSET + +#define ETH_CONFIG_PKT_HDR_OFFSET (ETH_ETHERNET_HDR_OFFSET + \ + ETH_CONFIG_PKT_HDR_LEN) +#define ACTION 0xD0 +#define PROBE_REQ 0x40 +#ifdef WILC_FULLY_HOSTING_AP +#define FH_TX_HOST_HDR_OFFSET 24 +#endif + +/******************************************** + * + * Endian Conversion + * + ********************************************/ + +#define BYTE_SWAP(val) ((((val) & 0x000000FF) << 24) + \ + (((val) & 0x0000FF00) << 8) + \ + (((val) & 0x00FF0000) >> 8) + \ + (((val) & 0xFF000000) >> 24)) + +/******************************************** + * + * Register Defines + * + ********************************************/ +#define WILC_PERIPH_REG_BASE 0x1000 +/*BugID_5137*/ +#define WILC_CHANGING_VIR_IF (0x108c) +#define WILC_CHIPID (WILC_PERIPH_REG_BASE) +#define WILC_GLB_RESET_0 (WILC_PERIPH_REG_BASE + 0x400) +#define WILC_PIN_MUX_0 (WILC_PERIPH_REG_BASE + 0x408) +#define WILC_HOST_TX_CTRL (WILC_PERIPH_REG_BASE + 0x6c) +#define WILC_HOST_RX_CTRL_0 (WILC_PERIPH_REG_BASE + 0x70) +#define WILC_HOST_RX_CTRL_1 (WILC_PERIPH_REG_BASE + 0x74) +#define WILC_HOST_VMM_CTL (WILC_PERIPH_REG_BASE + 0x78) +#define WILC_HOST_RX_CTRL (WILC_PERIPH_REG_BASE + 0x80) +#define WILC_HOST_RX_EXTRA_SIZE (WILC_PERIPH_REG_BASE + 0x84) +#define WILC_HOST_TX_CTRL_1 (WILC_PERIPH_REG_BASE + 0x88) +#define WILC_MISC (WILC_PERIPH_REG_BASE + 0x428) +#define WILC_INTR_REG_BASE (WILC_PERIPH_REG_BASE + 0xa00) +#define WILC_INTR_ENABLE (WILC_INTR_REG_BASE) +#define WILC_INTR2_ENABLE (WILC_INTR_REG_BASE + 4) + +#define WILC_INTR_POLARITY (WILC_INTR_REG_BASE + 0x10) +#define WILC_INTR_TYPE (WILC_INTR_REG_BASE + 0x20) +#define WILC_INTR_CLEAR (WILC_INTR_REG_BASE + 0x30) +#define WILC_INTR_STATUS (WILC_INTR_REG_BASE + 0x40) + +#define WILC_VMM_TBL_SIZE 64 +#define WILC_VMM_TX_TBL_BASE (0x150400) +#define WILC_VMM_RX_TBL_BASE (0x150500) + +#define WILC_VMM_BASE 0x150000 +#define WILC_VMM_CORE_CTL (WILC_VMM_BASE) +#define WILC_VMM_TBL_CTL (WILC_VMM_BASE + 0x4) +#define WILC_VMM_TBL_ENTRY (WILC_VMM_BASE + 0x8) +#define WILC_VMM_TBL0_SIZE (WILC_VMM_BASE + 0xc) +#define WILC_VMM_TO_HOST_SIZE (WILC_VMM_BASE + 0x10) +#define WILC_VMM_CORE_CFG (WILC_VMM_BASE + 0x14) +#define WILC_VMM_TBL_ACTIVE (WILC_VMM_BASE + 040) +#define WILC_VMM_TBL_STATUS (WILC_VMM_BASE + 0x44) + +#define WILC_SPI_REG_BASE 0xe800 +#define WILC_SPI_CTL (WILC_SPI_REG_BASE) +#define WILC_SPI_MASTER_DMA_ADDR (WILC_SPI_REG_BASE + 0x4) +#define WILC_SPI_MASTER_DMA_COUNT (WILC_SPI_REG_BASE + 0x8) +#define WILC_SPI_SLAVE_DMA_ADDR (WILC_SPI_REG_BASE + 0xc) +#define WILC_SPI_SLAVE_DMA_COUNT (WILC_SPI_REG_BASE + 0x10) +#define WILC_SPI_TX_MODE (WILC_SPI_REG_BASE + 0x20) +#define WILC_SPI_PROTOCOL_CONFIG (WILC_SPI_REG_BASE + 0x24) +#define WILC_SPI_INTR_CTL (WILC_SPI_REG_BASE + 0x2c) + +#define WILC_SPI_PROTOCOL_OFFSET (WILC_SPI_PROTOCOL_CONFIG - WILC_SPI_REG_BASE) + +#define WILC_AHB_DATA_MEM_BASE 0x30000 +#define WILC_AHB_SHARE_MEM_BASE 0xd0000 + +#define WILC_VMM_TBL_RX_SHADOW_BASE WILC_AHB_SHARE_MEM_BASE /* Bug 4477 fix */ +#define WILC_VMM_TBL_RX_SHADOW_SIZE (256) /* Bug 4477 fix */ + +#define WILC_GP_REG_0 0x149c +#define WILC_GP_REG_1 0x14a0 + +#define rHAVE_SDIO_IRQ_GPIO_BIT (0) +#define rHAVE_USE_PMU_BIT (1) +#define rHAVE_SLEEP_CLK_SRC_RTC_BIT (2) +#define rHAVE_SLEEP_CLK_SRC_XO_BIT (3) +#define rHAVE_EXT_PA_INV_TX_RX_BIT (4) +#define rHAVE_LEGACY_RF_SETTINGS_BIT (5) +#define rHAVE_XTAL_24_BIT (6) +#define rHAVE_DISABLE_WILC_UART_BIT (7) + + +#define WILC_HAVE_SDIO_IRQ_GPIO (1 << rHAVE_SDIO_IRQ_GPIO_BIT) +#define WILC_HAVE_USE_PMU (1 << rHAVE_USE_PMU_BIT) +#define WILC_HAVE_SLEEP_CLK_SRC_RTC (1 << rHAVE_SLEEP_CLK_SRC_RTC_BIT) +#define WILC_HAVE_SLEEP_CLK_SRC_XO (1 << rHAVE_SLEEP_CLK_SRC_XO_BIT) +#define WILC_HAVE_EXT_PA_INV_TX_RX (1 << rHAVE_EXT_PA_INV_TX_RX_BIT) +#define WILC_HAVE_LEGACY_RF_SETTINGS (1 << rHAVE_LEGACY_RF_SETTINGS_BIT) +#define WILC_HAVE_XTAL_24 (1 << rHAVE_XTAL_24_BIT) +#define WILC_HAVE_DISABLE_WILC_UART (1 << rHAVE_DISABLE_WILC_UART_BIT) + + +/******************************************** + * + * Wlan Defines + * + ********************************************/ +#define WILC_CFG_PKT 1 +#define WILC_NET_PKT 0 +/*Bug3959: transmitting mgmt frames received from host*/ +#ifdef WILC_AP_EXTERNAL_MLME +#define WILC_MGMT_PKT 2 + +#ifdef WILC_FULLY_HOSTING_AP +#define WILC_FH_DATA_PKT 4 +#endif + +#endif /*WILC_AP_EXTERNAL_MLME*/ +#define WILC_CFG_SET 1 +#define WILC_CFG_QUERY 0 + +#define WILC_CFG_RSP 1 +#define WILC_CFG_RSP_STATUS 2 +#define WILC_CFG_RSP_SCAN 3 + +#ifdef WILC_SDIO +#define WILC_PLL_TO 4 +#else +#define WILC_PLL_TO 2 +#endif + + +#define ABORT_INT (1 << 31) + +/*******************************************/ +/* E0 and later Interrupt flags. */ +/*******************************************/ +/*******************************************/ +/* E0 and later Interrupt flags. */ +/* IRQ Status word */ +/* 15:0 = DMA count in words. */ +/* 16: INT0 flag */ +/* 17: INT1 flag */ +/* 18: INT2 flag */ +/* 19: INT3 flag */ +/* 20: INT4 flag */ +/* 21: INT5 flag */ +/*******************************************/ +#define IRG_FLAGS_OFFSET 16 +#define IRQ_DMA_WD_CNT_MASK ((1ul << IRG_FLAGS_OFFSET) - 1) +#define INT_0 (1 << (IRG_FLAGS_OFFSET)) +#define INT_1 (1 << (IRG_FLAGS_OFFSET + 1)) +#define INT_2 (1 << (IRG_FLAGS_OFFSET + 2)) +#define INT_3 (1 << (IRG_FLAGS_OFFSET + 3)) +#define INT_4 (1 << (IRG_FLAGS_OFFSET + 4)) +#define INT_5 (1 << (IRG_FLAGS_OFFSET + 5)) +#define MAX_NUM_INT (6) + +/*******************************************/ +/* E0 and later Interrupt flags. */ +/* IRQ Clear word */ +/* 0: Clear INT0 */ +/* 1: Clear INT1 */ +/* 2: Clear INT2 */ +/* 3: Clear INT3 */ +/* 4: Clear INT4 */ +/* 5: Clear INT5 */ +/* 6: Select VMM table 1 */ +/* 7: Select VMM table 2 */ +/* 8: Enable VMM */ +/*******************************************/ +#define CLR_INT0 (1 << 0) +#define CLR_INT1 (1 << 1) +#define CLR_INT2 (1 << 2) +#define CLR_INT3 (1 << 3) +#define CLR_INT4 (1 << 4) +#define CLR_INT5 (1 << 5) +#define SEL_VMM_TBL0 (1 << 6) +#define SEL_VMM_TBL1 (1 << 7) +#define EN_VMM (1 << 8) + +#define DATA_INT_EXT INT_0 +#define PLL_INT_EXT INT_1 +#define SLEEP_INT_EXT INT_2 +#define ALL_INT_EXT (DATA_INT_EXT | PLL_INT_EXT | SLEEP_INT_EXT) +#define NUM_INT_EXT (3) + +#define DATA_INT_CLR CLR_INT0 +#define PLL_INT_CLR CLR_INT1 +#define SLEEP_INT_CLR CLR_INT2 + +#define ENABLE_RX_VMM (SEL_VMM_TBL1 | EN_VMM) +#define ENABLE_TX_VMM (SEL_VMM_TBL0 | EN_VMM) + + +/*time for expiring the semaphores of cfg packets*/ +#define CFG_PKTS_TIMEOUT 2000 +/******************************************** + * + * Debug Type + * + ********************************************/ +typedef void (*wilc_debug_func)(uint32_t, char *, ...); + +/******************************************** + * + * Tx/Rx Queue Structure + * + ********************************************/ + +struct txq_entry_t { + struct txq_entry_t *next; + struct txq_entry_t *prev; + int type; + int tcp_PendingAck_index; + uint8_t *buffer; + int buffer_size; + void *priv; + int status; + void (*tx_complete_func)(void *, int); +}; + +struct rxq_entry_t { + struct rxq_entry_t *next; + uint8_t *buffer; + int buffer_size; +}; + +/******************************************** + * + * Host IF Structure + * + ********************************************/ + +typedef struct { + int (*hif_init)(wilc_wlan_inp_t *, wilc_debug_func); + int (*hif_deinit)(void *); + int (*hif_read_reg)(uint32_t, uint32_t *); + int (*hif_write_reg)(uint32_t, uint32_t); + int (*hif_block_rx)(uint32_t, uint8_t *, uint32_t); + int (*hif_block_tx)(uint32_t, uint8_t *, uint32_t); + int (*hif_sync)(void); + int (*hif_clear_int)(void); + int (*hif_read_int)(uint32_t *); + int (*hif_clear_int_ext)(uint32_t); + int (*hif_read_size)(uint32_t *); + int (*hif_block_tx_ext)(uint32_t, uint8_t *, uint32_t); + int (*hif_block_rx_ext)(uint32_t, uint8_t *, uint32_t); + int (*hif_sync_ext)(int); + void (*hif_set_max_bus_speed)(void); + void (*hif_set_default_bus_speed)(void); +} wilc_hif_func_t; + +/******************************************** + * + * Configuration Structure + * + ********************************************/ + +#define MAX_CFG_FRAME_SIZE 1468 + +typedef struct { + uint8_t ether_header[14]; + uint8_t ip_header[20]; + uint8_t udp_header[8]; + uint8_t wid_header[8]; + uint8_t frame[MAX_CFG_FRAME_SIZE]; +} wilc_cfg_frame_t; + +typedef struct { + int (*wlan_tx)(uint8_t *, uint32_t, wilc_tx_complete_func_t); +} wilc_wlan_cfg_func_t; + +typedef struct { + int type; + uint32_t seq_no; +} wilc_cfg_rsp_t; + +typedef struct { + int (*cfg_wid_set)(uint8_t *, uint32_t, uint16_t, uint8_t *, int); + int (*cfg_wid_get)(uint8_t *, uint32_t, uint16_t); + int (*cfg_wid_get_val)(uint16_t, uint8_t *, uint32_t); + int (*rx_indicate)(uint8_t *, int, wilc_cfg_rsp_t *); + int (*cfg_init)(wilc_debug_func); +} wilc_cfg_func_t; + +#endif diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.c b/drivers/staging/wilc1000/wilc_wlan_cfg.c new file mode 100644 index 000000000000..a627c5870960 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.c @@ -0,0 +1,643 @@ +/* ////////////////////////////////////////////////////////////////////////// */ +/* */ +/* Copyright (c) Atmel Corporation. All rights reserved. */ +/* */ +/* Module Name: wilc_wlan_cfg.c */ +/* */ +/* */ +/* ///////////////////////////////////////////////////////////////////////// */ + +#include "wilc_wlan_if.h" +#include "wilc_wlan.h" +#include "wilc_wlan_cfg.h" +#include "coreconfigurator.h" + +#ifdef WILC_FULLY_HOSTING_AP +#include "wilc_host_ap.h" +void WILC_mgm_HOSTAPD_ACK(void *priv, WILC_Bool bStatus); +#endif + +/******************************************** + * + * Global Data + * + ********************************************/ + +typedef struct { + wilc_debug_func dPrint; + + int mac_status; + uint8_t mac_address[7]; + uint8_t ip_address[5]; + uint8_t bssid[7]; + uint8_t ssid[34]; + uint8_t firmware_version[129]; + uint8_t supp_rate[24]; + uint8_t wep_key[28]; + uint8_t i_psk[66]; + uint8_t hardwareProductVersion[33]; + uint8_t phyversion[17]; + uint8_t supp_username[21]; + uint8_t supp_password[64]; + uint8_t assoc_req[256]; + uint8_t assoc_rsp[256]; + uint8_t firmware_info[8]; + uint8_t scan_result[256]; + uint8_t scan_result1[256]; +} wilc_mac_cfg_t; + +static wilc_mac_cfg_t g_mac; + +static wilc_cfg_byte_t g_cfg_byte[] = { + {WID_BSS_TYPE, 0}, + {WID_CURRENT_TX_RATE, 0}, + {WID_CURRENT_CHANNEL, 0}, + {WID_PREAMBLE, 0}, + {WID_11G_OPERATING_MODE, 0}, + {WID_STATUS, 0}, + {WID_SCAN_TYPE, 0}, + {WID_KEY_ID, 0}, + {WID_QOS_ENABLE, 0}, + {WID_POWER_MANAGEMENT, 0}, + {WID_11I_MODE, 0}, + {WID_AUTH_TYPE, 0}, + {WID_SITE_SURVEY, 0}, + {WID_LISTEN_INTERVAL, 0}, + {WID_DTIM_PERIOD, 0}, + {WID_ACK_POLICY, 0}, + {WID_BCAST_SSID, 0}, + {WID_REKEY_POLICY, 0}, + {WID_SHORT_SLOT_ALLOWED, 0}, + {WID_START_SCAN_REQ, 0}, + {WID_RSSI, 0}, + {WID_LINKSPEED, 0}, + {WID_AUTO_RX_SENSITIVITY, 0}, + {WID_DATAFLOW_CONTROL, 0}, + {WID_SCAN_FILTER, 0}, + {WID_11N_PROT_MECH, 0}, + {WID_11N_ERP_PROT_TYPE, 0}, + {WID_11N_ENABLE, 0}, + {WID_11N_OPERATING_MODE, 0}, + {WID_11N_OBSS_NONHT_DETECTION, 0}, + {WID_11N_HT_PROT_TYPE, 0}, + {WID_11N_RIFS_PROT_ENABLE, 0}, + {WID_11N_SMPS_MODE, 0}, + {WID_11N_CURRENT_TX_MCS, 0}, + {WID_11N_SHORT_GI_ENABLE, 0}, + {WID_RIFS_MODE, 0}, + {WID_TX_ABORT_CONFIG, 0}, + {WID_11N_IMMEDIATE_BA_ENABLED, 0}, + {WID_11N_TXOP_PROT_DISABLE, 0}, + {WID_NIL, 0} +}; + +static wilc_cfg_hword_t g_cfg_hword[] = { + {WID_LINK_LOSS_THRESHOLD, 0}, + {WID_RTS_THRESHOLD, 0}, + {WID_FRAG_THRESHOLD, 0}, + {WID_SHORT_RETRY_LIMIT, 0}, + {WID_LONG_RETRY_LIMIT, 0}, + {WID_BEACON_INTERVAL, 0}, + {WID_RX_SENSE, 0}, + {WID_ACTIVE_SCAN_TIME, 0}, + {WID_PASSIVE_SCAN_TIME, 0}, + {WID_SITE_SURVEY_SCAN_TIME, 0}, + {WID_JOIN_START_TIMEOUT, 0}, + {WID_AUTH_TIMEOUT, 0}, + {WID_ASOC_TIMEOUT, 0}, + {WID_11I_PROTOCOL_TIMEOUT, 0}, + {WID_EAPOL_RESPONSE_TIMEOUT, 0}, + {WID_11N_SIG_QUAL_VAL, 0}, + {WID_CCA_THRESHOLD, 0}, + {WID_NIL, 0} +}; + +static wilc_cfg_word_t g_cfg_word[] = { + {WID_FAILED_COUNT, 0}, + {WID_RETRY_COUNT, 0}, + {WID_MULTIPLE_RETRY_COUNT, 0}, + {WID_FRAME_DUPLICATE_COUNT, 0}, + {WID_ACK_FAILURE_COUNT, 0}, + {WID_RECEIVED_FRAGMENT_COUNT, 0}, + {WID_MCAST_RECEIVED_FRAME_COUNT, 0}, + {WID_FCS_ERROR_COUNT, 0}, + {WID_SUCCESS_FRAME_COUNT, 0}, + {WID_TX_FRAGMENT_COUNT, 0}, + {WID_TX_MULTICAST_FRAME_COUNT, 0}, + {WID_RTS_SUCCESS_COUNT, 0}, + {WID_RTS_FAILURE_COUNT, 0}, + {WID_WEP_UNDECRYPTABLE_COUNT, 0}, + {WID_REKEY_PERIOD, 0}, + {WID_REKEY_PACKET_COUNT, 0}, + {WID_HW_RX_COUNT, 0}, + {WID_GET_INACTIVE_TIME, 0}, + {WID_NIL, 0} + +}; + +static wilc_cfg_str_t g_cfg_str[] = { + {WID_SSID, g_mac.ssid}, /* 33 + 1 bytes */ + {WID_FIRMWARE_VERSION, g_mac.firmware_version}, + {WID_OPERATIONAL_RATE_SET, g_mac.supp_rate}, + {WID_BSSID, g_mac.bssid}, /* 6 bytes */ + {WID_WEP_KEY_VALUE, g_mac.wep_key}, /* 27 bytes */ + {WID_11I_PSK, g_mac.i_psk}, /* 65 bytes */ + /* {WID_11E_P_ACTION_REQ, g_mac.action_req}, */ + {WID_HARDWARE_VERSION, g_mac.hardwareProductVersion}, + {WID_MAC_ADDR, g_mac.mac_address}, + {WID_PHY_VERSION, g_mac.phyversion}, + {WID_SUPP_USERNAME, g_mac.supp_username}, + {WID_SUPP_PASSWORD, g_mac.supp_password}, + {WID_SITE_SURVEY_RESULTS, g_mac.scan_result}, + {WID_SITE_SURVEY_RESULTS, g_mac.scan_result1}, + /* {WID_RX_POWER_LEVEL, g_mac.channel_rssi}, */ + {WID_ASSOC_REQ_INFO, g_mac.assoc_req}, + {WID_ASSOC_RES_INFO, g_mac.assoc_rsp}, + /* {WID_11N_P_ACTION_REQ, g_mac.action_req}, */ + {WID_FIRMWARE_INFO, g_mac.firmware_version}, + {WID_IP_ADDRESS, g_mac.ip_address}, + {WID_NIL, NULL} +}; + +/******************************************** + * + * Configuration Functions + * + ********************************************/ + +static int wilc_wlan_cfg_set_byte(uint8_t *frame, uint32_t offset, uint16_t id, uint8_t val8) +{ + uint8_t *buf; + + if ((offset + 4) >= MAX_CFG_FRAME_SIZE) + return 0; + + buf = &frame[offset]; + + buf[0] = (uint8_t)id; + buf[1] = (uint8_t)(id >> 8); + buf[2] = 1; + buf[3] = val8; + return 4; +} + +static int wilc_wlan_cfg_set_hword(uint8_t *frame, uint32_t offset, uint16_t id, uint16_t val16) +{ + uint8_t *buf; + + if ((offset + 5) >= MAX_CFG_FRAME_SIZE) + return 0; + + buf = &frame[offset]; + + buf[0] = (uint8_t)id; + buf[1] = (uint8_t)(id >> 8); + buf[2] = 2; + buf[3] = (uint8_t)val16; + buf[4] = (uint8_t)(val16 >> 8); + + return 5; +} + +static int wilc_wlan_cfg_set_word(uint8_t *frame, uint32_t offset, uint16_t id, uint32_t val32) +{ + uint8_t *buf; + + if ((offset + 7) >= MAX_CFG_FRAME_SIZE) + return 0; + + buf = &frame[offset]; + + buf[0] = (uint8_t)id; + buf[1] = (uint8_t)(id >> 8); + buf[2] = 4; + buf[3] = (uint8_t)val32; + buf[4] = (uint8_t)(val32 >> 8); + buf[5] = (uint8_t)(val32 >> 16); + buf[6] = (uint8_t)(val32 >> 24); + + return 7; +} + +static int wilc_wlan_cfg_set_str(uint8_t *frame, uint32_t offset, uint16_t id, uint8_t *str, uint32_t size) +{ + uint8_t *buf; + + if ((offset + size + 3) >= MAX_CFG_FRAME_SIZE) + return 0; + + buf = &frame[offset]; + + buf[0] = (uint8_t)id; + buf[1] = (uint8_t)(id >> 8); + buf[2] = (uint8_t)size; + + if ((str != NULL) && (size != 0)) + memcpy(&buf[3], str, size); + + return (size + 3); +} + +static int wilc_wlan_cfg_set_bin(uint8_t *frame, uint32_t offset, uint16_t id, uint8_t *b, uint32_t size) +{ + uint8_t *buf; + uint32_t i; + uint8_t checksum = 0; + + if ((offset + size + 5) >= MAX_CFG_FRAME_SIZE) + return 0; + + buf = &frame[offset]; + buf[0] = (uint8_t)id; + buf[1] = (uint8_t)(id >> 8); + buf[2] = (uint8_t)size; + buf[3] = (uint8_t)(size >> 8); + + if ((b != NULL) && (size != 0)) { + memcpy(&buf[4], b, size); + for (i = 0; i < size; i++) { + checksum += buf[i + 4]; + } + } + + buf[size + 4] = checksum; + + return (size + 5); +} + +/******************************************** + * + * Configuration Response Functions + * + ********************************************/ + +static void wilc_wlan_parse_response_frame(uint8_t *info, int size) +{ + uint32_t wid, len = 0, i = 0; + static int seq; + + while (size > 0) { + i = 0; + wid = info[0] | (info[1] << 8); +#ifdef BIG_ENDIAN + wid = BYTE_SWAP(wid); +#endif + PRINT_INFO(GENERIC_DBG, "Processing response for %d seq %d\n", wid, seq++); + switch ((wid >> 12) & 0x7) { + case WID_CHAR: + do { + if (g_cfg_byte[i].id == WID_NIL) + break; + + if (g_cfg_byte[i].id == wid) { + g_cfg_byte[i].val = info[3]; + break; + } + i++; + } while (1); + len = 2; + break; + + case WID_SHORT: + do { + if (g_cfg_hword[i].id == WID_NIL) + break; + + if (g_cfg_hword[i].id == wid) { +#ifdef BIG_ENDIAN + g_cfg_hword[i].val = (info[3] << 8) | (info[4]); +#else + g_cfg_hword[i].val = info[3] | (info[4] << 8); +#endif + break; + } + i++; + } while (1); + len = 3; + break; + + case WID_INT: + do { + if (g_cfg_word[i].id == WID_NIL) + break; + + if (g_cfg_word[i].id == wid) { +#ifdef BIG_ENDIAN + g_cfg_word[i].val = (info[3] << 24) | (info[4] << 16) | (info[5] << 8) | (info[6]); +#else + g_cfg_word[i].val = info[3] | (info[4] << 8) | (info[5] << 16) | (info[6] << 24); +#endif + break; + } + i++; + } while (1); + len = 5; + break; + + case WID_STR: + do { + if (g_cfg_str[i].id == WID_NIL) + break; + + if (g_cfg_str[i].id == wid) { + if (wid == WID_SITE_SURVEY_RESULTS) { + static int toggle; + PRINT_INFO(GENERIC_DBG, "Site survey results received[%d]\n", + size); + + PRINT_INFO(GENERIC_DBG, "Site survey results value[%d]toggle[%d]\n", size, toggle); + i += toggle; + toggle ^= 1; + } + memcpy(g_cfg_str[i].str, &info[2], (info[2] + 1)); + break; + } + i++; + } while (1); + len = 1 + info[2]; + break; + + default: + break; + } + size -= (2 + len); + info += (2 + len); + } + + return; +} + +static int wilc_wlan_parse_info_frame(uint8_t *info, int size) +{ + wilc_mac_cfg_t *pd = (wilc_mac_cfg_t *)&g_mac; + uint32_t wid, len; + int type = WILC_CFG_RSP_STATUS; + + wid = info[0] | (info[1] << 8); +#if 0 +#ifdef BIG_ENDIAN + wid = BYTE_SWAP(wid); +#endif +#endif + + len = info[2]; + PRINT_INFO(GENERIC_DBG, "Status Len = %d Id= %d\n", len, wid); + if ((len == 1) && (wid == WID_STATUS)) { + pd->mac_status = info[3]; + type = WILC_CFG_RSP_STATUS; + } + + return type; +} + +#if 0 +static int wilc_wlan_parse_network_frame(uint8_t *info, int size) +{ + wilc_mac_cfg_t *priv = (wilc_mac_cfg_t *)&g_mac; + uint32_t wid, len; + + wid = info[0] | (info[1] << 8); + len = info[2] | (info[3] << 8); + + /** + * Review: this message is only for AP mode. + * TBD + **/ + if (wid == WID_NETWORK_INFO) { /* not send by the firmware */ + + } + + return; +} +#endif + +/******************************************** + * + * Configuration Exported Functions + * + ********************************************/ + +static int wilc_wlan_cfg_set_wid(uint8_t *frame, uint32_t offset, uint16_t id, uint8_t *buf, int size) +{ + uint8_t type = (id >> 12) & 0xf; + int ret = 0; + + if (type == 0) { /* byte command */ + if (size >= 1) + ret = wilc_wlan_cfg_set_byte(frame, offset, id, *buf); + } else if (type == 1) { /* half word command */ + if (size >= 2) + ret = wilc_wlan_cfg_set_hword(frame, offset, id, *((uint16_t *)buf)); + } else if (type == 2) { /* word command */ + if (size >= 4) + ret = wilc_wlan_cfg_set_word(frame, offset, id, *((uint32_t *)buf)); + } else if (type == 3) { /* string command */ + ret = wilc_wlan_cfg_set_str(frame, offset, id, buf, size); + } else if (type == 4) { /* binary command */ + ret = wilc_wlan_cfg_set_bin(frame, offset, id, buf, size); + } else { + g_mac.dPrint(N_ERR, "illegal id\n"); + } + + return ret; +} + +static int wilc_wlan_cfg_get_wid(uint8_t *frame, uint32_t offset, uint16_t id) +{ + uint8_t *buf; + + if ((offset + 2) >= MAX_CFG_FRAME_SIZE) + return 0; + + buf = &frame[offset]; + + buf[0] = (uint8_t)id; + buf[1] = (uint8_t)(id >> 8); + + return 2; +} + +static int wilc_wlan_cfg_get_wid_value(uint16_t wid, uint8_t *buffer, uint32_t buffer_size) +{ + uint32_t type = (wid >> 12) & 0xf; + int i, ret = 0; + + if (wid == WID_STATUS) { + *((uint32_t *)buffer) = g_mac.mac_status; + return 4; + } + + i = 0; + if (type == 0) { /* byte command */ + do { + if (g_cfg_byte[i].id == WID_NIL) + break; + + if (g_cfg_byte[i].id == wid) { + memcpy(buffer, &g_cfg_byte[i].val, 1); + ret = 1; + break; + } + i++; + } while (1); + } else if (type == 1) { /* half word command */ + do { + if (g_cfg_hword[i].id == WID_NIL) + break; + + if (g_cfg_hword[i].id == wid) { + memcpy(buffer, &g_cfg_hword[i].val, 2); + ret = 2; + break; + } + i++; + } while (1); + } else if (type == 2) { /* word command */ + do { + if (g_cfg_word[i].id == WID_NIL) + break; + + if (g_cfg_word[i].id == wid) { + memcpy(buffer, &g_cfg_word[i].val, 4); + ret = 4; + break; + } + i++; + } while (1); + } else if (type == 3) { /* string command */ + do { + if (g_cfg_str[i].id == WID_NIL) + break; + + if (g_cfg_str[i].id == wid) { + uint32_t size = g_cfg_str[i].str[0]; + if (buffer_size >= size) { + if (g_cfg_str[i].id == WID_SITE_SURVEY_RESULTS) { + static int toggle; + PRINT_INFO(GENERIC_DBG, "Site survey results value[%d]\n", + size); + i += toggle; + toggle ^= 1; + + } + memcpy(buffer, &g_cfg_str[i].str[1], size); + ret = size; + } + break; + } + i++; + } while (1); + } else { + g_mac.dPrint(N_ERR, "[CFG]: illegal type (%08x)\n", wid); + } + + return ret; +} + +static int wilc_wlan_cfg_indicate_rx(uint8_t *frame, int size, wilc_cfg_rsp_t *rsp) +{ + int ret = 1; + uint8_t msg_type; + uint8_t msg_id; + uint16_t msg_len; + #ifdef WILC_FULLY_HOSTING_AP + WILC_Uint32 *ptru32Frame; + WILC_Bool bStatus = frame[2]; + + #ifdef BIG_ENDIAN + ptru32Frame = (frame[4] << 24) | (frame[5] << 16) | (frame[6] << 8) | frame[7]; + #else + ptru32Frame = (frame[7] << 24) | (frame[6] << 16) | (frame[5] << 8) | frame[4]; + #endif /* BIG_ENDIAN */ + + #endif /* WILC_FULLY_HOSTING_AP */ + + msg_type = frame[0]; + msg_id = frame[1]; /* seq no */ +#ifdef BIG_ENDIAN + msg_len = (frame[2] << 8) | frame[3]; +#else + msg_len = (frame[3] << 8) | frame[2]; +#endif + frame += 4; + size -= 4; + + /** + * The valid types of response messages are 'R' (Response), 'I' (Information), and 'N' (Network Information) + **/ + + switch (msg_type) { + case 'R': + wilc_wlan_parse_response_frame(frame, size); + rsp->type = WILC_CFG_RSP; + rsp->seq_no = msg_id; + break; + + case 'I': + rsp->type = wilc_wlan_parse_info_frame(frame, size); + rsp->seq_no = msg_id; + /*call host interface info parse as well*/ + PRINT_INFO(RX_DBG, "Info message received\n"); + GnrlAsyncInfoReceived(frame - 4, size + 4); + break; + + case 'L': +#ifndef SWITCH_LOG_TERMINAL + PRINT_ER("Unexpected firmware log message received \n"); +#else + PRINT_D(FIRM_DBG, "\nFIRMWARE LOGS :\n<<\n%s\n>>\n", frame); + break; + +#endif +#if 1 + case 'N': + NetworkInfoReceived(frame - 4, size + 4); + rsp->type = 0; + break; + +#endif +/*bug3819:*/ + case 'S': + PRINT_INFO(RX_DBG, "Scan Notification Received \n"); + host_int_ScanCompleteReceived(frame - 4, size + 4); + break; + +#ifdef WILC_FULLY_HOSTING_AP + case 'T': + PRINT_INFO(RX_DBG, "TBTT Notification Received \n"); + process_tbtt_isr(); + break; + + case 'A': + PRINT_INFO(RX_DBG, "HOSTAPD ACK Notification Received \n"); + WILC_mgm_HOSTAPD_ACK(ptru32Frame, bStatus); + break; +#endif + + default: + PRINT_INFO(RX_DBG, "Receive unknown message type[%d-%d-%d-%d-%d-%d-%d-%d]\n", + frame[0], frame[1], frame[2], frame[3], frame[4], + frame[5], frame[6], frame[7]); + rsp->type = 0; + rsp->seq_no = msg_id; + ret = 0; + break; + } + + return ret; +} + +static int wilc_wlan_cfg_init(wilc_debug_func func) +{ + memset((void *)&g_mac, 0, sizeof(wilc_mac_cfg_t)); + g_mac.dPrint = func; + return 1; +} + +wilc_cfg_func_t mac_cfg = { + wilc_wlan_cfg_set_wid, + wilc_wlan_cfg_get_wid, + wilc_wlan_cfg_get_wid_value, + wilc_wlan_cfg_indicate_rx, + wilc_wlan_cfg_init, +}; diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.h b/drivers/staging/wilc1000/wilc_wlan_cfg.h new file mode 100644 index 000000000000..8906611b2930 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.h @@ -0,0 +1,33 @@ +/* ////////////////////////////////////////////////////////////////////////// */ +/* */ +/* Copyright (c) Atmel Corporation. All rights reserved. */ +/* */ +/* Module Name: wilc_wlan_cfg.h */ +/* */ +/* */ +/* ///////////////////////////////////////////////////////////////////////// */ + +#ifndef WILC_WLAN_CFG_H +#define WILC_WLAN_CFG_H + +typedef struct { + uint16_t id; + uint16_t val; +} wilc_cfg_byte_t; + +typedef struct { + uint16_t id; + uint16_t val; +} wilc_cfg_hword_t; + +typedef struct { + uint32_t id; + uint32_t val; +} wilc_cfg_word_t; + +typedef struct { + uint32_t id; + uint8_t *str; +} wilc_cfg_str_t; + +#endif diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h new file mode 100644 index 000000000000..dd86ca7dd3f3 --- /dev/null +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -0,0 +1,991 @@ +/* ////////////////////////////////////////////////////////////////////////// */ +/* */ +/* Copyright (c) Atmel Corporation. All rights reserved. */ +/* */ +/* Module Name: wilc_wlan_if.h */ +/* */ +/* */ +/* ///////////////////////////////////////////////////////////////////////// */ + + +#ifndef WILC_WLAN_IF_H +#define WILC_WLAN_IF_H + +/*bug 3887: [AP] Allow Management frames to be passed to the host*/ +#define WILC_AP_EXTERNAL_MLME +#define WILC_P2P +#define TCP_ENHANCEMENTS +/* #define MEMORY_STATIC */ +/* #define WILC_FULLY_HOSTING_AP */ +/* #define USE_OLD_SPI_SW */ + + +#include "wilc_type.h" +#include "linux_wlan_common.h" + + +/******************************************** + * + * Debug Flags + * + ********************************************/ + +#define N_INIT 0x00000001 +#define N_ERR 0x00000002 +#define N_TXQ 0x00000004 +#define N_INTR 0x00000008 +#define N_RXQ 0x00000010 + +/******************************************** + * + * Host Interface Defines + * + ********************************************/ + +#define HIF_SDIO (0) +#define HIF_SPI (1 << 0) +#define HIF_SDIO_GPIO_IRQ (1 << 2) + + +/******************************************** + * + * Tx/Rx Buffer Size Defines + * + ********************************************/ + +#define CE_TX_BUFFER_SIZE (64 * 1024) +#define CE_RX_BUFFER_SIZE (384 * 1024) + +/******************************************** + * + * Wlan Interface Defines + * + ********************************************/ + +typedef struct { + uint32_t read_write: 1; + uint32_t function: 3; + uint32_t raw: 1; + uint32_t address: 17; + uint32_t data: 8; +} sdio_cmd52_t; + +typedef struct { + /* struct { */ + uint32_t read_write: 1; + uint32_t function: 3; + uint32_t block_mode: 1; + uint32_t increment: 1; + uint32_t address: 17; + uint32_t count: 9; + /* } bit; */ + uint8_t *buffer; + uint32_t block_size; +} sdio_cmd53_t; + +typedef struct { + void (*os_sleep)(uint32_t); + void (*os_atomic_sleep)(uint32_t); + void (*os_debug)(uint8_t *); + void *(*os_malloc)(uint32_t); + void *(*os_malloc_atomic)(uint32_t); + void (*os_free)(void *); + void (*os_lock)(void *); + void (*os_unlock)(void *); + int (*os_wait)(void *, WILC_Uint32); + void (*os_signal)(void *); + void (*os_enter_cs)(void *); + void (*os_leave_cs)(void *); + + /*Added by Amr - BugID_4720*/ + void (*os_spin_lock)(void *, unsigned long *); + void (*os_spin_unlock)(void *, unsigned long *); + +} wilc_wlan_os_func_t; + +typedef struct { + int io_type; + int (*io_init)(void *); + void (*io_deinit)(void *); + union { + struct { + int (*sdio_cmd52)(sdio_cmd52_t *); + int (*sdio_cmd53)(sdio_cmd53_t *); + int (*sdio_set_max_speed)(void); + int (*sdio_set_default_speed)(void); + } sdio; + struct { + int (*spi_max_speed)(void); + int (*spi_tx)(uint8_t *, uint32_t); + int (*spi_rx)(uint8_t *, uint32_t); + int (*spi_trx)(uint8_t *, uint8_t *, uint32_t); + } spi; + } u; +} wilc_wlan_io_func_t; + +typedef struct { + void (*rx_indicate)(uint8_t *, uint32_t, uint32_t); + void (*rx_complete)(void); +} wilc_wlan_net_func_t; + +typedef struct { + void (*mac_indicate)(int); +} wilc_wlan_indicate_func_t; +#define WILC_MAC_INDICATE_STATUS 0x1 +#define WILC_MAC_STATUS_INIT -1 +#define WILC_MAC_STATUS_READY 0 +#define WILC_MAC_STATUS_CONNECT 1 + +#define WILC_MAC_INDICATE_SCAN 0x2 + +typedef struct { + void *os_private; + + void *hif_critical_section; + + uint32_t tx_buffer_size; + void *txq_critical_section; + + /*Added by Amr - BugID_4720*/ + void *txq_add_to_head_critical_section; + void *txq_spin_lock; + + void *txq_wait_event; + +#if defined(MEMORY_STATIC) + uint32_t rx_buffer_size; +#endif + void *rxq_critical_section; + void *rxq_wait_event; + + void *cfg_wait_event; +} wilc_wlan_os_context_t; + +typedef struct { + wilc_wlan_os_context_t os_context; + wilc_wlan_os_func_t os_func; + wilc_wlan_io_func_t io_func; + wilc_wlan_net_func_t net_func; + wilc_wlan_indicate_func_t indicate_func; +} wilc_wlan_inp_t; + +#if 0 +typedef struct { + int start; + uint32_t id; + void *buffer; + uint32_t buffer_size; + int commit; +} wilc_wlan_cfg_set_t; + +typedef struct { + int start; + uint32_t id; + int commit; +} wilc_wlan_cfg_get_t; + +typedef struct { + uint32_t id; + void *buffer; + uint32_t buffer_size; +} wilc_wlan_cfg_val_t; +#endif + +struct tx_complete_data { + #ifdef WILC_FULLY_HOSTING_AP + struct tx_complete_data *next; + #endif + int size; + void *buff; + uint8_t *pBssid; + struct sk_buff *skb; +}; + + +typedef void (*wilc_tx_complete_func_t)(void *, int); + +#define WILC_TX_ERR_NO_BUF (-2) + +typedef struct { + int (*wlan_firmware_download)(const uint8_t *, uint32_t); + int (*wlan_start)(void); + int (*wlan_stop)(void); + int (*wlan_add_to_tx_que)(void *, uint8_t *, uint32_t, wilc_tx_complete_func_t); + int (*wlan_handle_tx_que)(uint32_t *); + void (*wlan_handle_rx_que)(void); + void (*wlan_handle_rx_isr)(void); + void (*wlan_cleanup)(void); + int (*wlan_cfg_set)(int, uint32_t, uint8_t *, uint32_t, int, uint32_t); + int (*wlan_cfg_get)(int, uint32_t, int, uint32_t); + int (*wlan_cfg_get_value)(uint32_t, uint8_t *, uint32_t); + /*Bug3959: transmitting mgmt frames received from host*/ + #if defined(WILC_AP_EXTERNAL_MLME) || defined(WILC_P2P) + int (*wlan_add_mgmt_to_tx_que)(void *, uint8_t *, uint32_t, wilc_tx_complete_func_t); + + #ifdef WILC_FULLY_HOSTING_AP + int (*wlan_add_data_to_tx_que)(void *, uint8_t *, uint32_t, wilc_tx_complete_func_t); + #endif + + #endif +} wilc_wlan_oup_t; + +/******************************************** + * + * Wlan Configuration ID + * + ********************************************/ + +#define MAX_SSID_LEN 33 +#define MAX_RATES_SUPPORTED 12 + +#define INFINITE_SLEEP_TIME ((WILC_Uint32)0xFFFFFFFF) + +#ifdef WILC_PARSE_SCAN_IN_HOST +typedef enum { + SUPP_RATES_IE = 1, + EXT_SUPP_RATES_IE = 50, + HT_CAPABILITY_IE = 45, + RSN_IE = 48, + WPA_IE = 221, + WMM_IE = 221, + #ifdef WILC_P2P + P2P_IE = 221, + #endif +} BEACON_IE; +#endif +typedef enum { + INFRASTRUCTURE = 0, + INDEPENDENT, + AP, +} BSSTYPE_T; + +typedef enum { + RATE_AUTO = 0, + RATE_1MB = 1, + RATE_2MB = 2, + RATE_5MB = 5, + RATE_6MB = 6, + RATE_9MB = 9, + RATE_11MB = 11, + RATE_12MB = 12, + RATE_18MB = 18, + RATE_24MB = 24, + RATE_26MB = 36, + RATE_48MB = 48, + RATE_54MB = 54 +} TX_RATE_T; + +typedef enum { + B_ONLY_MODE = 0, /* basic rate: 1, 2 Mbps, otherwise: 5, 11 Mbps */ + G_ONLY_MODE, /* basic rate: 6, 12, 24 Mbps, otherwise: 9, 18, 36, 48, 54 Mbps */ + G_MIXED_11B_1_MODE, /* basic rate: 1, 2, 5.5, 11 Mbps, otherwise: all on */ + G_MIXED_11B_2_MODE, /* basic rate: 1, 2, 5, 11, 6, 12, 24 Mbps, otherwise: all on */ +} G_OPERATING_MODE_T; + +typedef enum { + G_SHORT_PREAMBLE = 0, /* Short Preamble */ + G_LONG_PREAMBLE = 1, /* Long Preamble */ + G_AUTO_PREAMBLE = 2, /* Auto Preamble Selection */ +} G_PREAMBLE_T; + +#define MAC_CONNECTED 1 +#define MAC_DISCONNECTED 0 + +/*bug3819: */ +#define SCAN_DONE TRUE +typedef enum { + PASSIVE_SCAN = 0, + ACTIVE_SCAN = 1, +} SCANTYPE_T; + +typedef enum { + NO_POWERSAVE = 0, + MIN_FAST_PS = 1, + MAX_FAST_PS = 2, + MIN_PSPOLL_PS = 3, + MAX_PSPOLL_PS = 4 +} USER_PS_MODE_T; + +typedef enum { + CHIP_WAKEDUP = 0, + CHIP_SLEEPING_AUTO = 1, + CHIP_SLEEPING_MANUAL = 2 +} CHIP_PS_STATE_T; + +typedef enum { + ACQUIRE_ONLY = 0, + ACQUIRE_AND_WAKEUP = 1, +} BUS_ACQUIRE_T; + +typedef enum { + RELEASE_ONLY = 0, + RELEASE_ALLOW_SLEEP = 1, +} BUS_RELEASE_T; + +typedef enum { + NO_SECURITY = 0, + WEP_40 = 0x3, + WEP_104 = 0x7, + WPA_AES = 0x29, + WPA_TKIP = 0x49, + WPA_AES_TKIP = 0x69, /* Aes or Tkip */ + WPA2_AES = 0x31, + WPA2_TKIP = 0x51, + WPA2_AES_TKIP = 0x71, /* Aes or Tkip */ +} SECURITY_T; + +typedef enum { + OPEN_SYSTEM = 1, + SHARED_KEY = 2, + ANY = 3, + IEEE8021 = 5 +} AUTHTYPE_T; + +typedef enum { + SITE_SURVEY_1CH = 0, + SITE_SURVEY_ALL_CH = 1, + SITE_SURVEY_OFF = 2 +} SITE_SURVEY_T; + +typedef enum { + NORMAL_ACK = 0, + NO_ACK, +} ACK_POLICY_T; + +typedef enum { + DONT_RESET = 0, + DO_RESET = 1, + NO_REQUEST = 2, +} RESET_REQ_T; + +typedef enum { + REKEY_DISABLE = 1, + REKEY_TIME_BASE, + REKEY_PKT_BASE, + REKEY_TIME_PKT_BASE +} RSNA_REKEY_POLICY_T; + +typedef enum { + FILTER_NO = 0x00, + FILTER_AP_ONLY = 0x01, + FILTER_STA_ONLY = 0x02 +} SCAN_CLASS_FITLER_T; + +typedef enum { + PRI_HIGH_RSSI = 0x00, + PRI_LOW_RSSI = 0x04, + PRI_DETECT = 0x08 +} SCAN_PRI_T; + +typedef enum { + CH_FILTER_OFF = 0x00, + CH_FILTER_ON = 0x10 +} CH_FILTER_T; + +typedef enum { + AUTO_PROT = 0, /* Auto */ + NO_PROT, /* Do not use any protection */ + ERP_PROT, /* Protect all ERP frame exchanges */ + HT_PROT, /* Protect all HT frame exchanges */ + GF_PROT, /* Protect all GF frame exchanges */ +} N_PROTECTION_MODE_T; + +typedef enum { + G_SELF_CTS_PROT, + G_RTS_CTS_PROT, +} G_PROTECTION_MODE_T; + +typedef enum { + HT_MIXED_MODE = 1, + HT_ONLY_20MHZ_MODE, + HT_ONLY_20_40MHZ_MODE, +} N_OPERATING_MODE_T; + +typedef enum { + NO_DETECT = 0, + DETECT_ONLY = 1, + DETECT_PROTECT = 2, + DETECT_PROTECT_REPORT = 3, +} N_OBSS_DETECTION_T; + +typedef enum { + RTS_CTS_NONHT_PROT = 0, /* RTS-CTS at non-HT rate */ + FIRST_FRAME_NONHT_PROT, /* First frame at non-HT rate */ + LSIG_TXOP_PROT, /* LSIG TXOP Protection */ + FIRST_FRAME_MIXED_PROT, /* First frame at Mixed format */ +} N_PROTECTION_TYPE_T; + +typedef enum { + STATIC_MODE = 1, + DYNAMIC_MODE = 2, + MIMO_MODE = 3, /* power save disable */ +} N_SMPS_MODE_T; + +typedef enum { + DISABLE_SELF_CTS, + ENABLE_SELF_CTS, + DISABLE_TX_ABORT, + ENABLE_TX_ABORT, + HW_TRIGGER_ABORT, + SW_TRIGGER_ABORT, +} TX_ABORT_OPTION_T; + +typedef enum { + WID_CHAR = 0, + WID_SHORT = 1, + WID_INT = 2, + WID_STR = 3, + WID_BIN_DATA = 4, + WID_BIN = 5, + WID_IP = 6, + WID_ADR = 7, + WID_UNDEF = 8, + WID_TYPE_FORCE_32BIT = 0xFFFFFFFF + +} WID_TYPE_T, tenuWIDtype; + +typedef enum { + WID_NIL = 0xffff, + + + /* BSS Type */ + /* -------------------------------------------------------------- */ + /* Configuration : Infrastructure Independent Access Point */ + /* Values to set : 0 1 2 */ + /* -------------------------------------------------------------- */ + WID_BSS_TYPE = 0x0000, + + /* Transmit Rate */ + /* -------------------------------------------------------------- */ + /* Configuration : 1 2 5.5 11 6 9 12 18 24 36 48 54 */ + /* Values to set : 1 2 5 11 6 9 12 18 24 36 48 54 */ + /* -------------------------------------------------------------- */ + WID_CURRENT_TX_RATE = 0x0001, + + /* Channel */ + /* ------------------------------------------------------------------- */ + /* Configuration(g) : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 */ + /* Values to set : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 */ + /* -------------------------------------------------------------------- */ + WID_CURRENT_CHANNEL = 0x0002, + + /* Preamble */ + /* -------------------------------------------------------------- */ + /* Configuration : short long Auto */ + /* Values to set : 0 1 2 */ + /* -------------------------------------------------------------- */ + WID_PREAMBLE = 0x0003, + + /* 11g operating mode (ignored if 11g not present) */ + /* -------------------------------------------------------------- */ + /* Configuration : HighPerf Compat(RSet #1) Compat(RSet #2) */ + /* Values to set : 1 2 3 */ + /* -------------------------------------------------------------- */ + WID_11G_OPERATING_MODE = 0x0004, + + /* Mac status (response only) */ + /* -------------------------------------------------------------- */ + /* Configuration : disconnect connect */ + /* Values to get : 0 1 */ + /* -------------------------------------------------------------- */ + WID_STATUS = 0x0005, + + /* Scan type */ + /* -------------------------------------------------------------- */ + /* Configuration : Passive Scanning Active Scanning */ + /* Values to set : 0 1 */ + /* -------------------------------------------------------------- */ + WID_SCAN_TYPE = 0x0007, + + /* Key Id (WEP default key Id) */ + /* -------------------------------------------------------------- */ + /* Configuration : Any value between 0 to 3 */ + /* Values to set : Same value. Default is 0 */ + /* -------------------------------------------------------------- */ + WID_KEY_ID = 0x0009, + + /* QoS Enable */ + /* -------------------------------------------------------------- */ + /* Configuration : QoS Disable WMM Enable */ + /* Values to set : 0 1 */ + /* -------------------------------------------------------------- */ + WID_QOS_ENABLE = 0x000A, + + /* Power Management */ + /* ------------------------------------------------------------------ */ + /* Configuration : NO_POWERSAVE MIN_POWERSAVE MAX_POWERSAVE */ + /* Values to set : 0 1 2 */ + /* ------------------------------------------------------------------ */ + WID_POWER_MANAGEMENT = 0x000B, + + /* WEP/802 11I Configuration */ + /* ------------------------------------------------------------------ */ + /* Configuration : Disable WP40 WP104 WPA-AES WPA-TKIP RSN-AES RSN-TKIP */ + /* Values (0x) : 00 03 07 29 49 31 51 */ + /* */ + /* Configuration : WPA-AES+TKIP RSN-AES+TKIP */ + /* Values (0x) : 69 71 */ + /* ------------------------------------------------------------------ */ + WID_11I_MODE = 0x000C, + + /* WEP Configuration: Used in BSS STA mode only when WEP is enabled */ + /* ------------------------------------------------------------------ */ + /* Configuration : Open System Shared Key Any Type | 802.1x Auth */ + /* Values (0x) : 01 02 03 | BIT2 */ + /* ------------------------------------------------------------------ */ + WID_AUTH_TYPE = 0x000D, + + /* Site Survey Type */ + /* -------------------------------------------------------------- */ + /* Configuration : Values to set */ + /* Survey 1 Channel : 0 */ + /* survey all Channels : 1 */ + /* Disable Site Survey : 2 */ + /* -------------------------------------------------------------- */ + WID_SITE_SURVEY = 0x000E, + + /* Listen Interval */ + /* -------------------------------------------------------------- */ + /* Configuration : Any value between 1 to 255 */ + /* Values to set : Same value. Default is 3 */ + /* -------------------------------------------------------------- */ + WID_LISTEN_INTERVAL = 0x000F, + + /* DTIM Period */ + /* -------------------------------------------------------------- */ + /* Configuration : Any value between 1 to 255 */ + /* Values to set : Same value. Default is 3 */ + /* -------------------------------------------------------------- */ + WID_DTIM_PERIOD = 0x0010, + + /* ACK Policy */ + /* -------------------------------------------------------------- */ + /* Configuration : Normal Ack No Ack */ + /* Values to set : 0 1 */ + /* -------------------------------------------------------------- */ + WID_ACK_POLICY = 0x0011, + + /* Reset MAC (Set only) */ + /* -------------------------------------------------------------- */ + /* Configuration : Don't Reset Reset No Request */ + /* Values to set : 0 1 2 */ + /* -------------------------------------------------------------- */ + WID_RESET = 0x0012, + + /* Broadcast SSID Option: Setting this will adhere to "" SSID element */ + /* ------------------------------------------------------------------ */ + /* Configuration : Enable Disable */ + /* Values to set : 1 0 */ + /* ------------------------------------------------------------------ */ + WID_BCAST_SSID = 0x0015, + + /* Disconnect (Station) */ + /* ------------------------------------------------------------------ */ + /* Configuration : Association ID */ + /* Values to set : Association ID */ + /* ------------------------------------------------------------------ */ + WID_DISCONNECT = 0x0016, + + /* 11a Tx Power Level */ + /* -------------------------------------------------------------------- */ + /* Configuration : Sets TX Power (Higher the value greater the power) */ + /* Values to set : Any value between 0 and 63 (inclusive; Default is 48)*/ + /* -------------------------------------------------------------------- */ + WID_TX_POWER_LEVEL_11A = 0x0018, + + /* Group Key Update Policy Selection */ + /* -------------------------------------------------------------------- */ + /* Configuration : Disabled timeBased packetBased timePacketBased */ + /* Values to set : 1 2 3 4 */ + /* -------------------------------------------------------------------- */ + WID_REKEY_POLICY = 0x0019, + + /* Allow Short Slot */ + /* -------------------------------------------------------------- */ + /* Configuration : Disallow Short Slot Allow Short Slot */ + /* (Enable Only Long Slot) (Enable Short Slot if applicable)*/ + /* Values to set : 0 1 */ + /* -------------------------------------------------------------- */ + WID_SHORT_SLOT_ALLOWED = 0x001A, + + WID_PHY_ACTIVE_REG = 0x001B, + + /* 11b Tx Power Level */ + /* -------------------------------------------------------------------- */ + /* Configuration : Sets TX Power (Higher the value greater the power) */ + /* Values to set : Any value between 0 and 63 (inclusive; Default is 48)*/ + /* -------------------------------------------------------------------- */ + WID_TX_POWER_LEVEL_11B = 0x001D, + + /* Scan Request */ + /* -------------------------------------------------------------------- */ + /* Configuration : Request default scan */ + /* Values to set : 0 */ + /* -------------------------------------------------------------------- */ + WID_START_SCAN_REQ = 0x001E, + + /* Rssi (get only) */ + /* -------------------------------------------------------------------- */ + /* Configuration : */ + /* Values to get : Rssi value */ + /* -------------------------------------------------------------------- */ + WID_RSSI = 0x001F, + + /* Join Request */ + /* -------------------------------------------------------------------- */ + /* Configuration : Request to join */ + /* Values to set : index of scan result */ + /* -------------------------------------------------------------------- */ + WID_JOIN_REQ = 0x0020, + + WID_LINKSPEED = 0x0026, + + /* Enable User Control of TX Power */ + /* -------------------------------------------------------------------- */ + /* Configuration : Disable Enable */ + /* Values to set : 0 1 */ + /* -------------------------------------------------------------------- */ + WID_USER_CONTROL_ON_TX_POWER = 0x0027, + + WID_MEMORY_ACCESS_8BIT = 0x0029, + + /* Enable Auto RX Sensitivity feature */ + /* -------------------------------------------------------------------- */ + /* Configuration : Disable Enable */ + /* Values to set : 0 1 */ + /* -------------------------------------------------------------------- */ + WID_AUTO_RX_SENSITIVITY = 0x0032, + + /* Receive Buffer Based Ack */ + /* -------------------------------------------------------------------- */ + /* Configuration : Disable Enable */ + /* Values to set : 0 1 */ + /* -------------------------------------------------------------------- */ + WID_DATAFLOW_CONTROL = 0x0033, + + /* Scan Filter */ + /* -------------------------------------------------------------------- */ + /* Configuration : Class No filter AP only Station Only */ + /* Values to set : 0 1 2 */ + /* Configuration : Priority High Rssi Low Rssi Detect */ + /* Values to set : 0 0x4 0x08 */ + /* Configuration : Channel filter off filter on */ + /* Values to set : 0 0x10 */ + /* -------------------------------------------------------------------- */ + WID_SCAN_FILTER = 0x0036, + + /* Link Loss Threshold (measure in the beacon period) */ + /* -------------------------------------------------------------------- */ + /* Configuration : Any value between 10 and 254 (Set to 255 to disable it) */ + /* Values to set : Same value. Default is 10 */ + /* -------------------------------------------------------------------- */ + WID_LINK_LOSS_THRESHOLD = 0x0037, + + /*BugID_4978*/ + WID_ABORT_RUNNING_SCAN = 0x003E, + + /* NMAC Character WID list */ + WID_WPS_START = 0x0043, + + /* Protection mode for MAC */ + /* -------------------------------------------------------------- */ + /* Configuration : Auto No protection ERP HT GF */ + /* Values to set : 0 1 2 3 4 */ + /* -------------------------------------------------------------- */ + WID_11N_PROT_MECH = 0x0080, + + /* ERP Protection type for MAC */ + /* -------------------------------------------------------------- */ + /* Configuration : Self-CTS RTS-CTS */ + /* Values to set : 0 1 */ + /* -------------------------------------------------------------- */ + WID_11N_ERP_PROT_TYPE = 0x0081, + + /* HT Option Enable */ + /* -------------------------------------------------------------- */ + /* Configuration : HT Enable HT Disable */ + /* Values to set : 1 0 */ + /* -------------------------------------------------------------- */ + WID_11N_ENABLE = 0x0082, + + /* 11n Operating mode (Note that 11g operating mode will also be */ + /* used in addition to this, if this is set to HT Mixed mode) */ + /* -------------------------------------------------------------- */ + /* Configuration : HT Mixed HT Only-20MHz HT Only-20/40MHz */ + /* Values to set : 1 2 3 */ + /* -------------------------------------------------------------- */ + WID_11N_OPERATING_MODE = 0x0083, + + /* 11n OBSS non-HT STA Detection flag */ + /* -------------------------------------------------------------- */ + /* Configuration : Do not detect */ + /* Values to set : 0 */ + /* Configuration : Detect, do not protect or report */ + /* Values to set : 1 */ + /* Configuration : Detect, protect and do not report */ + /* Values to set : 2 */ + /* Configuration : Detect, protect and report to other BSS */ + /* Values to set : 3 */ + /* -------------------------------------------------------------- */ + WID_11N_OBSS_NONHT_DETECTION = 0x0084, + + /* 11n HT Protection Type */ + /* -------------------------------------------------------------- */ + /* Configuration : RTS-CTS First Frame Exchange at non-HT-rate */ + /* Values to set : 0 1 */ + /* Configuration : LSIG TXOP First Frame Exchange in Mixed Fmt */ + /* Values to set : 2 3 */ + /* -------------------------------------------------------------- */ + WID_11N_HT_PROT_TYPE = 0x0085, + + /* 11n RIFS Protection Enable Flag */ + /* -------------------------------------------------------------- */ + /* Configuration : Disable Enable */ + /* Values to set : 0 1 */ + /* -------------------------------------------------------------- */ + WID_11N_RIFS_PROT_ENABLE = 0x0086, + + /* SMPS Mode */ + /* -------------------------------------------------------------- */ + /* Configuration : Static Dynamic MIMO (Power Save Disabled) */ + /* Values to set : 1 2 3 */ + /* -------------------------------------------------------------- */ + WID_11N_SMPS_MODE = 0x0087, + + /* Current transmit MCS */ + /* -------------------------------------------------------------- */ + /* Configuration : MCS Index for data rate */ + /* Values to set : 0 to 7 */ + /* -------------------------------------------------------------- */ + WID_11N_CURRENT_TX_MCS = 0x0088, + + WID_11N_PRINT_STATS = 0x0089, + + /* 11n Short GI Enable Flag */ + /* -------------------------------------------------------------- */ + /* Configuration : Disable Enable */ + /* Values to set : 0 1 */ + /* -------------------------------------------------------------- */ + WID_11N_SHORT_GI_ENABLE = 0x008D, + + /* 11n RIFS Enable Flag */ + /* -------------------------------------------------------------- */ + /* Configuration : Disable Enable */ + /* Values to set : 0 1 */ + /* -------------------------------------------------------------- */ + WID_RIFS_MODE = 0x0094, + + /* TX Abort Feature */ + /* -------------------------------------------------------------- */ + /* Configuration : Disable Self CTS Enable Self CTS */ + /* Values to set : 0 1 */ + /* Configuration : Disable TX Abort Enable TX Abort */ + /* Values to set : 2 3 */ + /* Configuration : Enable HW TX Abort Enable SW TX Abort */ + /* Values to set : 4 5 */ + /* -------------------------------------------------------------- */ + WID_TX_ABORT_CONFIG = 0x00A1, + + WID_REG_TSSI_11B_VALUE = 0x00A6, + WID_REG_TSSI_11G_VALUE = 0x00A7, + WID_REG_TSSI_11N_VALUE = 0x00A8, + WID_TX_CALIBRATION = 0x00A9, + WID_DSCR_TSSI_11B_VALUE = 0x00AA, + WID_DSCR_TSSI_11G_VALUE = 0x00AB, + WID_DSCR_TSSI_11N_VALUE = 0x00AC, + + /* Immediate Block-Ack Support */ + /* -------------------------------------------------------------- */ + /* Configuration : Disable Enable */ + /* Values to set : 0 1 */ + /* -------------------------------------------------------------- */ + WID_11N_IMMEDIATE_BA_ENABLED = 0x00AF, + + /* TXOP Disable Flag */ + /* -------------------------------------------------------------- */ + /* Configuration : Disable Enable */ + /* Values to set : 1 0 */ + /* -------------------------------------------------------------- */ + WID_11N_TXOP_PROT_DISABLE = 0x00B0, + + + WID_TX_POWER_LEVEL_11N = 0x00B1, + + /* Custom Character WID list */ + WID_PC_TEST_MODE = 0x00C8, + /*bug3819: */ + /* SCAN Complete notification WID*/ + WID_SCAN_COMPLETE = 0x00C9, + +#ifdef WILC_AP_EXTERNAL_MLME + WID_DEL_BEACON = 0x00CA, +#endif + + WID_LOGTerminal_Switch = 0x00CD, + /* EMAC Short WID list */ + /* RTS Threshold */ + /* -------------------------------------------------------------- */ + /* Configuration : Any value between 256 to 2347 */ + /* Values to set : Same value. Default is 2347 */ + /* -------------------------------------------------------------- */ + WID_RTS_THRESHOLD = 0x1000, + + /* Fragmentation Threshold */ + /* -------------------------------------------------------------- */ + /* Configuration : Any value between 256 to 2346 */ + /* Values to set : Same value. Default is 2346 */ + /* -------------------------------------------------------------- */ + WID_FRAG_THRESHOLD = 0x1001, + + WID_SHORT_RETRY_LIMIT = 0x1002, + WID_LONG_RETRY_LIMIT = 0x1003, + WID_BEACON_INTERVAL = 0x1006, + WID_MEMORY_ACCESS_16BIT = 0x1008, + WID_RX_SENSE = 0x100B, + WID_ACTIVE_SCAN_TIME = 0x100C, + WID_PASSIVE_SCAN_TIME = 0x100D, + + WID_SITE_SURVEY_SCAN_TIME = 0x100E, + WID_JOIN_START_TIMEOUT = 0x100F, + WID_AUTH_TIMEOUT = 0x1010, + WID_ASOC_TIMEOUT = 0x1011, + WID_11I_PROTOCOL_TIMEOUT = 0x1012, + WID_EAPOL_RESPONSE_TIMEOUT = 0x1013, + + /* NMAC Short WID list */ + WID_11N_SIG_QUAL_VAL = 0x1085, + WID_CCA_THRESHOLD = 0x1087, + + /* Custom Short WID list */ + + /* EMAC Integer WID list */ + WID_FAILED_COUNT = 0x2000, + WID_RETRY_COUNT = 0x2001, + WID_MULTIPLE_RETRY_COUNT = 0x2002, + WID_FRAME_DUPLICATE_COUNT = 0x2003, + WID_ACK_FAILURE_COUNT = 0x2004, + WID_RECEIVED_FRAGMENT_COUNT = 0x2005, + WID_MCAST_RECEIVED_FRAME_COUNT = 0x2006, + WID_FCS_ERROR_COUNT = 0x2007, + WID_SUCCESS_FRAME_COUNT = 0x2008, + WID_HUT_TX_COUNT = 0x200A, + WID_TX_FRAGMENT_COUNT = 0x200B, + WID_TX_MULTICAST_FRAME_COUNT = 0x200C, + WID_RTS_SUCCESS_COUNT = 0x200D, + WID_RTS_FAILURE_COUNT = 0x200E, + WID_WEP_UNDECRYPTABLE_COUNT = 0x200F, + WID_REKEY_PERIOD = 0x2010, + WID_REKEY_PACKET_COUNT = 0x2011, + WID_1X_SERV_ADDR = 0x2012, + WID_STACK_IP_ADDR = 0x2013, + WID_STACK_NETMASK_ADDR = 0x2014, + WID_HW_RX_COUNT = 0x2015, + WID_MEMORY_ADDRESS = 0x201E, + WID_MEMORY_ACCESS_32BIT = 0x201F, + WID_RF_REG_VAL = 0x2021, + + + /* NMAC Integer WID list */ + WID_11N_PHY_ACTIVE_REG_VAL = 0x2080, + + /* Custom Integer WID list */ + WID_GET_INACTIVE_TIME = 0x2084, + WID_SET_DRV_HANDLER = 0X2085, + WID_SET_OPERATION_MODE = 0X2086, + /* EMAC String WID list */ + WID_SSID = 0x3000, + WID_FIRMWARE_VERSION = 0x3001, + WID_OPERATIONAL_RATE_SET = 0x3002, + WID_BSSID = 0x3003, + WID_WEP_KEY_VALUE = 0x3004, + WID_11I_PSK = 0x3008, + WID_11E_P_ACTION_REQ = 0x3009, + WID_1X_KEY = 0x300A, + WID_HARDWARE_VERSION = 0x300B, + WID_MAC_ADDR = 0x300C, + WID_HUT_DEST_ADDR = 0x300D, + WID_PHY_VERSION = 0x300F, + WID_SUPP_USERNAME = 0x3010, + WID_SUPP_PASSWORD = 0x3011, + WID_SITE_SURVEY_RESULTS = 0x3012, + WID_RX_POWER_LEVEL = 0x3013, + WID_DEL_ALL_RX_BA = 0x3014, + WID_SET_STA_MAC_INACTIVE_TIME = 0x3017, + WID_ADD_WEP_KEY = 0x3019, + WID_REMOVE_WEP_KEY = 0x301A, + WID_ADD_PTK = 0x301B, + WID_ADD_RX_GTK = 0x301C, + WID_ADD_TX_GTK = 0x301D, + WID_REMOVE_KEY = 0x301E, + WID_ASSOC_REQ_INFO = 0x301F, + WID_ASSOC_RES_INFO = 0x3020, + WID_MANUFACTURER = 0x3026, /*Added for CAPI tool */ + WID_MODEL_NAME = 0x3027, /*Added for CAPI tool */ + WID_MODEL_NUM = 0x3028, /*Added for CAPI tool */ + WID_DEVICE_NAME = 0x3029, /*Added for CAPI tool */ + + /* NMAC String WID list */ + WID_11N_P_ACTION_REQ = 0x3080, + WID_HUT_TEST_ID = 0x3081, + WID_PMKID_INFO = 0x3082, + WID_FIRMWARE_INFO = 0x3083, + #ifdef WILC_P2P + WID_REGISTER_FRAME = 0x3084, + #endif + WID_DEL_ALL_STA = 0x3085, + #ifdef WILC_P2P + WID_REMAIN_ON_CHAN = 0x3996, + #endif + /*BugID_4156*/ + WID_SSID_PROBE_REQ = 0x3997, + /*BugID_4124 WID to trigger modified Join Request using SSID and BSSID instead of bssListIdx (used by WID_JOIN_REQ)*/ + WID_JOIN_REQ_EXTENDED = 0x3998, + + /* BugID 4951: WID toset IP address in firmware */ + WID_IP_ADDRESS = 0x3999, + + + + /* Custom String WID list */ + + /* EMAC Binary WID list */ + WID_UAPSD_CONFIG = 0x4001, + WID_UAPSD_STATUS = 0x4002, + WID_WMM_AP_AC_PARAMS = 0x4003, + WID_WMM_STA_AC_PARAMS = 0x4004, + WID_NETWORK_INFO = 0x4005, + WID_STA_JOIN_INFO = 0x4006, + WID_CONNECTED_STA_LIST = 0x4007, + + /* NMAC Binary WID list */ + WID_11N_AUTORATE_TABLE = 0x4080, + + + /*Added here by Amr - BugID 4134*/ + WID_SCAN_CHANNEL_LIST = 0x4084, + + /*BugID_3746 WID to add IE to be added in next probe request*/ + WID_INFO_ELEMENT_PROBE = 0x4085, + /*BugID_3746 WID to add IE to be added in next associate request*/ + WID_INFO_ELEMENT_ASSOCIATE = 0x4086, + WID_ADD_STA = 0X4087, + WID_REMOVE_STA = 0X4088, + WID_EDIT_STA = 0X4089, + WID_ADD_BEACON = 0x408a, + + /* BugID 5108 */ + WID_SETUP_MULTICAST_FILTER = 0x408b, + + /* Miscellaneous WIDs */ + WID_ALL = 0x7FFE, + WID_MAX = 0xFFFF +} WID_T; + +int wilc_wlan_init(wilc_wlan_inp_t *inp, wilc_wlan_oup_t *oup); + +void wilc_bus_set_max_speed(void); +void wilc_bus_set_default_speed(void); +uint32_t wilc_get_chipid(uint8_t update); + + +#endif