summaryrefslogtreecommitdiff
path: root/drivers/staging/wilc1000
diff options
context:
space:
mode:
authorAndré Fabian Silva Delgado <emulatorman@parabola.nu>2015-09-08 01:01:14 -0300
committerAndré Fabian Silva Delgado <emulatorman@parabola.nu>2015-09-08 01:01:14 -0300
commite5fd91f1ef340da553f7a79da9540c3db711c937 (patch)
treeb11842027dc6641da63f4bcc524f8678263304a3 /drivers/staging/wilc1000
parent2a9b0348e685a63d97486f6749622b61e9e3292f (diff)
Linux-libre 4.2-gnu
Diffstat (limited to 'drivers/staging/wilc1000')
-rw-r--r--drivers/staging/wilc1000/Kconfig59
-rw-r--r--drivers/staging/wilc1000/Makefile34
-rw-r--r--drivers/staging/wilc1000/TODO14
-rw-r--r--drivers/staging/wilc1000/coreconfigsimulator.h17
-rw-r--r--drivers/staging/wilc1000/coreconfigurator.c2156
-rw-r--r--drivers/staging/wilc1000/coreconfigurator.h197
-rw-r--r--drivers/staging/wilc1000/fifo_buffer.c133
-rw-r--r--drivers/staging/wilc1000/fifo_buffer.h26
-rw-r--r--drivers/staging/wilc1000/host_interface.c7963
-rw-r--r--drivers/staging/wilc1000/host_interface.h1281
-rw-r--r--drivers/staging/wilc1000/linux_mon.c598
-rw-r--r--drivers/staging/wilc1000/linux_wlan.c2783
-rw-r--r--drivers/staging/wilc1000/linux_wlan_common.h182
-rw-r--r--drivers/staging/wilc1000/linux_wlan_sdio.c249
-rw-r--r--drivers/staging/wilc1000/linux_wlan_sdio.h14
-rw-r--r--drivers/staging/wilc1000/linux_wlan_spi.c479
-rw-r--r--drivers/staging/wilc1000/linux_wlan_spi.h14
-rw-r--r--drivers/staging/wilc1000/wilc_debugfs.c191
-rw-r--r--drivers/staging/wilc1000/wilc_errorsupport.h67
-rw-r--r--drivers/staging/wilc1000/wilc_exported_buf.c76
-rw-r--r--drivers/staging/wilc1000/wilc_log.h47
-rw-r--r--drivers/staging/wilc1000/wilc_memory.c58
-rw-r--r--drivers/staging/wilc1000/wilc_memory.h239
-rw-r--r--drivers/staging/wilc1000/wilc_msgqueue.c190
-rw-r--r--drivers/staging/wilc1000/wilc_msgqueue.h108
-rw-r--r--drivers/staging/wilc1000/wilc_osconfig.h9
-rw-r--r--drivers/staging/wilc1000/wilc_oswrapper.h41
-rw-r--r--drivers/staging/wilc1000/wilc_platform.h52
-rw-r--r--drivers/staging/wilc1000/wilc_sdio.c1254
-rw-r--r--drivers/staging/wilc1000/wilc_sleep.c18
-rw-r--r--drivers/staging/wilc1000/wilc_sleep.h20
-rw-r--r--drivers/staging/wilc1000/wilc_spi.c1406
-rw-r--r--drivers/staging/wilc1000/wilc_strutils.c80
-rw-r--r--drivers/staging/wilc1000/wilc_strutils.h134
-rw-r--r--drivers/staging/wilc1000/wilc_timer.c45
-rw-r--r--drivers/staging/wilc1000/wilc_timer.h129
-rw-r--r--drivers/staging/wilc1000/wilc_type.h34
-rw-r--r--drivers/staging/wilc1000/wilc_wfi_cfgoperations.c3957
-rw-r--r--drivers/staging/wilc1000/wilc_wfi_cfgoperations.h129
-rw-r--r--drivers/staging/wilc1000/wilc_wfi_netdevice.c951
-rw-r--r--drivers/staging/wilc1000/wilc_wfi_netdevice.h254
-rw-r--r--drivers/staging/wilc1000/wilc_wlan.c2332
-rw-r--r--drivers/staging/wilc1000/wilc_wlan.h321
-rw-r--r--drivers/staging/wilc1000/wilc_wlan_cfg.c617
-rw-r--r--drivers/staging/wilc1000/wilc_wlan_cfg.h33
-rw-r--r--drivers/staging/wilc1000/wilc_wlan_if.h969
46 files changed, 29960 insertions, 0 deletions
diff --git a/drivers/staging/wilc1000/Kconfig b/drivers/staging/wilc1000/Kconfig
new file mode 100644
index 000000000..062d9c5ca
--- /dev/null
+++ b/drivers/staging/wilc1000/Kconfig
@@ -0,0 +1,59 @@
+config WILC1000
+ tristate "WILC1000 support (WiFi only)"
+ depends on BROKEN
+ depends on !S390
+ depends on CFG80211 && WEXT_CORE && INET
+ depends on MMC || SPI
+ ---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
+ depends on 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 000000000..59b102074
--- /dev/null
+++ b/drivers/staging/wilc1000/Makefile
@@ -0,0 +1,34 @@
+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="\"/*(DEBLOBBED)*/\"" \
+ -DAP_FIRMWARE="\"/*(DEBLOBBED)*/\"" \
+ -DP2P_CONCURRENCY_FIRMWARE="\"/*(DEBLOBBED)*/\""
+
+ccflags-y += -I$(src)/ -D__CHECK_ENDIAN__ -DWILC_ASIC_A0 \
+ -DPLL_WORKAROUND -DCONNECT_DIRECT -DAGING_ALG \
+ -DWILC_PARSE_SCAN_IN_HOST -DDISABLE_PWRSAVE_AND_SCAN_DURING_IP \
+ -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_sleep.o wilc_strutils.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
diff --git a/drivers/staging/wilc1000/TODO b/drivers/staging/wilc1000/TODO
new file mode 100644
index 000000000..95199d80a
--- /dev/null
+++ b/drivers/staging/wilc1000/TODO
@@ -0,0 +1,14 @@
+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)
+- replace all semaphores with mutexes or completions
+- make spi and sdio components coexist in one build
+- turn compile-time platform configuration (BEAGLE_BOARD,
+ PANDA_BOARD, PLAT_WMS8304, PLAT_RKXXXX, CUSTOMER_PLATFORM, ...)
+ into run-time options that are read from DT
+- support soft-ap and p2p mode
+- support resume/suspend function
+- replace SIOCDEVPRIVATE commands with generic API functions
+- use wext-core handling instead of private SIOCSIWPRIV implementation
diff --git a/drivers/staging/wilc1000/coreconfigsimulator.h b/drivers/staging/wilc1000/coreconfigsimulator.h
new file mode 100644
index 000000000..5e01f8e4a
--- /dev/null
+++ b/drivers/staging/wilc1000/coreconfigsimulator.h
@@ -0,0 +1,17 @@
+
+/*!
+ * @file coreconfigsimulator.h
+ * @brief
+ * @author
+ * @sa coreconfigsimulator.c
+ * @date 1 Mar 2012
+ * @version 1.0
+ */
+
+#ifndef CORECONFIGSIMULATOR_H
+#define CORECONFIGSIMULATOR_H
+
+extern s32 CoreConfigSimulatorInit(void);
+extern s32 CoreConfigSimulatorDeInit(void);
+
+#endif
diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c
new file mode 100644
index 000000000..ed6ac45c0
--- /dev/null
+++ b/drivers/staging/wilc1000/coreconfigurator.c
@@ -0,0 +1,2156 @@
+
+/*!
+ * @file coreconfigurator.c
+ * @brief
+ * @author
+ * @sa coreconfigurator.h
+ * @date 1 Mar 2012
+ * @version 1.0
+ */
+
+
+/*****************************************************************************/
+/* File Includes */
+/*****************************************************************************/
+#include "coreconfigurator.h"
+/*****************************************************************************/
+/* Constants */
+/*****************************************************************************/
+#define INLINE static __inline
+#define PHY_802_11n
+#define MAX_CFG_PKTLEN 1450
+#define MSG_HEADER_LEN 4
+#define QUERY_MSG_TYPE 'Q'
+#define WRITE_MSG_TYPE 'W'
+#define RESP_MSG_TYPE 'R'
+#define WRITE_RESP_SUCCESS 1
+#define INVALID 255
+#define MAC_ADDR_LEN 6
+#define TAG_PARAM_OFFSET (MAC_HDR_LEN + TIME_STAMP_LEN + \
+ BEACON_INTERVAL_LEN + CAP_INFO_LEN)
+
+/*****************************************************************************/
+/* Function Macros */
+/*****************************************************************************/
+
+
+/*****************************************************************************/
+/* Type Definitions */
+/*****************************************************************************/
+
+/* Basic Frame Type Codes (2-bit) */
+typedef enum {
+ FRAME_TYPE_CONTROL = 0x04,
+ FRAME_TYPE_DATA = 0x08,
+ FRAME_TYPE_MANAGEMENT = 0x00,
+ FRAME_TYPE_RESERVED = 0x0C,
+ FRAME_TYPE_FORCE_32BIT = 0xFFFFFFFF
+} tenuBasicFrmType;
+
+/* Frame Type and Subtype Codes (6-bit) */
+typedef enum {
+ ASSOC_REQ = 0x00,
+ ASSOC_RSP = 0x10,
+ REASSOC_REQ = 0x20,
+ REASSOC_RSP = 0x30,
+ PROBE_REQ = 0x40,
+ PROBE_RSP = 0x50,
+ BEACON = 0x80,
+ ATIM = 0x90,
+ DISASOC = 0xA0,
+ AUTH = 0xB0,
+ DEAUTH = 0xC0,
+ ACTION = 0xD0,
+ PS_POLL = 0xA4,
+ RTS = 0xB4,
+ CTS = 0xC4,
+ ACK = 0xD4,
+ CFEND = 0xE4,
+ CFEND_ACK = 0xF4,
+ DATA = 0x08,
+ DATA_ACK = 0x18,
+ DATA_POLL = 0x28,
+ DATA_POLL_ACK = 0x38,
+ NULL_FRAME = 0x48,
+ CFACK = 0x58,
+ CFPOLL = 0x68,
+ CFPOLL_ACK = 0x78,
+ QOS_DATA = 0x88,
+ QOS_DATA_ACK = 0x98,
+ QOS_DATA_POLL = 0xA8,
+ QOS_DATA_POLL_ACK = 0xB8,
+ QOS_NULL_FRAME = 0xC8,
+ QOS_CFPOLL = 0xE8,
+ QOS_CFPOLL_ACK = 0xF8,
+ BLOCKACK_REQ = 0x84,
+ BLOCKACK = 0x94,
+ FRAME_SUBTYPE_FORCE_32BIT = 0xFFFFFFFF
+} tenuFrmSubtype;
+
+/* Basic Frame Classes */
+typedef enum {
+ CLASS1_FRAME_TYPE = 0x00,
+ CLASS2_FRAME_TYPE = 0x01,
+ CLASS3_FRAME_TYPE = 0x02,
+ FRAME_CLASS_FORCE_32BIT = 0xFFFFFFFF
+} tenuFrameClass;
+
+/* Element ID of various Information Elements */
+typedef enum {
+ ISSID = 0, /* Service Set Identifier */
+ ISUPRATES = 1, /* Supported Rates */
+ IFHPARMS = 2, /* FH parameter set */
+ IDSPARMS = 3, /* DS parameter set */
+ ICFPARMS = 4, /* CF parameter set */
+ ITIM = 5, /* Traffic Information Map */
+ IIBPARMS = 6, /* IBSS parameter set */
+ ICOUNTRY = 7, /* Country element */
+ IEDCAPARAMS = 12, /* EDCA parameter set */
+ ITSPEC = 13, /* Traffic Specification */
+ ITCLAS = 14, /* Traffic Classification */
+ ISCHED = 15, /* Schedule */
+ ICTEXT = 16, /* Challenge Text */
+ IPOWERCONSTRAINT = 32, /* Power Constraint */
+ IPOWERCAPABILITY = 33, /* Power Capability */
+ ITPCREQUEST = 34, /* TPC Request */
+ ITPCREPORT = 35, /* TPC Report */
+ ISUPCHANNEL = 36, /* Supported channel list */
+ ICHSWANNOUNC = 37, /* Channel Switch Announcement */
+ IMEASUREMENTREQUEST = 38, /* Measurement request */
+ IMEASUREMENTREPORT = 39, /* Measurement report */
+ IQUIET = 40, /* Quiet element Info */
+ IIBSSDFS = 41, /* IBSS DFS */
+ IERPINFO = 42, /* ERP Information */
+ ITSDELAY = 43, /* TS Delay */
+ ITCLASPROCESS = 44, /* TCLAS Processing */
+ IHTCAP = 45, /* HT Capabilities */
+ IQOSCAP = 46, /* QoS Capability */
+ IRSNELEMENT = 48, /* RSN Information Element */
+ IEXSUPRATES = 50, /* Extended Supported Rates */
+ IEXCHSWANNOUNC = 60, /* Extended Ch Switch Announcement*/
+ IHTOPERATION = 61, /* HT Information */
+ ISECCHOFF = 62, /* Secondary Channel Offeset */
+ I2040COEX = 72, /* 20/40 Coexistence IE */
+ I2040INTOLCHREPORT = 73, /* 20/40 Intolerant channel report*/
+ IOBSSSCAN = 74, /* OBSS Scan parameters */
+ IEXTCAP = 127, /* Extended capability */
+ IWMM = 221, /* WMM parameters */
+ IWPAELEMENT = 221, /* WPA Information Element */
+ INFOELEM_ID_FORCE_32BIT = 0xFFFFFFFF
+} tenuInfoElemID;
+
+
+typedef struct {
+ char *pcRespBuffer;
+ s32 s32MaxRespBuffLen;
+ s32 s32BytesRead;
+ bool bRespRequired;
+} tstrConfigPktInfo;
+
+
+
+/*****************************************************************************/
+/* Extern Variable Declarations */
+/*****************************************************************************/
+
+
+/*****************************************************************************/
+/* Extern Function Declarations */
+/*****************************************************************************/
+extern s32 SendRawPacket(s8 *ps8Packet, s32 s32PacketLen);
+extern void NetworkInfoReceived(u8 *pu8Buffer, u32 u32Length);
+extern void GnrlAsyncInfoReceived(u8 *pu8Buffer, u32 u32Length);
+extern void host_int_ScanCompleteReceived(u8 *pu8Buffer, u32 u32Length);
+/*****************************************************************************/
+/* Global Variables */
+/*****************************************************************************/
+static struct semaphore SemHandleSendPkt;
+static struct semaphore SemHandlePktResp;
+
+static s8 *gps8ConfigPacket;
+
+static tstrConfigPktInfo gstrConfigPktInfo;
+
+static u8 g_seqno;
+
+static s16 g_wid_num = -1;
+
+static u16 Res_Len;
+
+static u8 g_oper_mode = SET_CFG;
+
+/* WID Switches */
+static tstrWID gastrWIDs[] = {
+ {WID_FIRMWARE_VERSION, WID_STR},
+ {WID_PHY_VERSION, WID_STR},
+ {WID_HARDWARE_VERSION, WID_STR},
+ {WID_BSS_TYPE, WID_CHAR},
+ {WID_QOS_ENABLE, WID_CHAR},
+ {WID_11I_MODE, WID_CHAR},
+ {WID_CURRENT_TX_RATE, WID_CHAR},
+ {WID_LINKSPEED, WID_CHAR},
+ {WID_RTS_THRESHOLD, WID_SHORT},
+ {WID_FRAG_THRESHOLD, WID_SHORT},
+ {WID_SSID, WID_STR},
+ {WID_BSSID, WID_ADR},
+ {WID_BEACON_INTERVAL, WID_SHORT},
+ {WID_POWER_MANAGEMENT, WID_CHAR},
+ {WID_LISTEN_INTERVAL, WID_CHAR},
+ {WID_DTIM_PERIOD, WID_CHAR},
+ {WID_CURRENT_CHANNEL, WID_CHAR},
+ {WID_TX_POWER_LEVEL_11A, WID_CHAR},
+ {WID_TX_POWER_LEVEL_11B, WID_CHAR},
+ {WID_PREAMBLE, WID_CHAR},
+ {WID_11G_OPERATING_MODE, WID_CHAR},
+ {WID_MAC_ADDR, WID_ADR},
+ {WID_IP_ADDRESS, WID_ADR},
+ {WID_ACK_POLICY, WID_CHAR},
+ {WID_PHY_ACTIVE_REG, WID_CHAR},
+ {WID_AUTH_TYPE, WID_CHAR},
+ {WID_REKEY_POLICY, WID_CHAR},
+ {WID_REKEY_PERIOD, WID_INT},
+ {WID_REKEY_PACKET_COUNT, WID_INT},
+ {WID_11I_PSK, WID_STR},
+ {WID_1X_KEY, WID_STR},
+ {WID_1X_SERV_ADDR, WID_IP},
+ {WID_SUPP_USERNAME, WID_STR},
+ {WID_SUPP_PASSWORD, WID_STR},
+ {WID_USER_CONTROL_ON_TX_POWER, WID_CHAR},
+ {WID_MEMORY_ADDRESS, WID_INT},
+ {WID_MEMORY_ACCESS_32BIT, WID_INT},
+ {WID_MEMORY_ACCESS_16BIT, WID_SHORT},
+ {WID_MEMORY_ACCESS_8BIT, WID_CHAR},
+ {WID_SITE_SURVEY_RESULTS, WID_STR},
+ {WID_PMKID_INFO, WID_STR},
+ {WID_ASSOC_RES_INFO, WID_STR},
+ {WID_MANUFACTURER, WID_STR}, /* 4 Wids added for the CAPI tool*/
+ {WID_MODEL_NAME, WID_STR},
+ {WID_MODEL_NUM, WID_STR},
+ {WID_DEVICE_NAME, WID_STR},
+ {WID_SSID_PROBE_REQ, WID_STR},
+
+#ifdef MAC_802_11N
+ {WID_11N_ENABLE, WID_CHAR},
+ {WID_11N_CURRENT_TX_MCS, WID_CHAR},
+ {WID_TX_POWER_LEVEL_11N, WID_CHAR},
+ {WID_11N_OPERATING_MODE, WID_CHAR},
+ {WID_11N_SMPS_MODE, WID_CHAR},
+ {WID_11N_PROT_MECH, WID_CHAR},
+ {WID_11N_ERP_PROT_TYPE, WID_CHAR},
+ {WID_11N_HT_PROT_TYPE, WID_CHAR},
+ {WID_11N_PHY_ACTIVE_REG_VAL, WID_INT},
+ {WID_11N_PRINT_STATS, WID_CHAR},
+ {WID_11N_AUTORATE_TABLE, WID_BIN_DATA},
+ {WID_HOST_CONFIG_IF_TYPE, WID_CHAR},
+ {WID_HOST_DATA_IF_TYPE, WID_CHAR},
+ {WID_11N_SIG_QUAL_VAL, WID_SHORT},
+ {WID_11N_IMMEDIATE_BA_ENABLED, WID_CHAR},
+ {WID_11N_TXOP_PROT_DISABLE, WID_CHAR},
+ {WID_11N_SHORT_GI_20MHZ_ENABLE, WID_CHAR},
+ {WID_SHORT_SLOT_ALLOWED, WID_CHAR},
+ {WID_11W_ENABLE, WID_CHAR},
+ {WID_11W_MGMT_PROT_REQ, WID_CHAR},
+ {WID_2040_ENABLE, WID_CHAR},
+ {WID_2040_COEXISTENCE, WID_CHAR},
+ {WID_USER_SEC_CHANNEL_OFFSET, WID_CHAR},
+ {WID_2040_CURR_CHANNEL_OFFSET, WID_CHAR},
+ {WID_2040_40MHZ_INTOLERANT, WID_CHAR},
+ {WID_HUT_RESTART, WID_CHAR},
+ {WID_HUT_NUM_TX_PKTS, WID_INT},
+ {WID_HUT_FRAME_LEN, WID_SHORT},
+ {WID_HUT_TX_FORMAT, WID_CHAR},
+ {WID_HUT_BANDWIDTH, WID_CHAR},
+ {WID_HUT_OP_BAND, WID_CHAR},
+ {WID_HUT_STBC, WID_CHAR},
+ {WID_HUT_ESS, WID_CHAR},
+ {WID_HUT_ANTSET, WID_CHAR},
+ {WID_HUT_HT_OP_MODE, WID_CHAR},
+ {WID_HUT_RIFS_MODE, WID_CHAR},
+ {WID_HUT_SMOOTHING_REC, WID_CHAR},
+ {WID_HUT_SOUNDING_PKT, WID_CHAR},
+ {WID_HUT_HT_CODING, WID_CHAR},
+ {WID_HUT_TEST_DIR, WID_CHAR},
+ {WID_HUT_TXOP_LIMIT, WID_SHORT},
+ {WID_HUT_DEST_ADDR, WID_ADR},
+ {WID_HUT_TX_PATTERN, WID_BIN_DATA},
+ {WID_HUT_TX_TIME_TAKEN, WID_INT},
+ {WID_HUT_PHY_TEST_MODE, WID_CHAR},
+ {WID_HUT_PHY_TEST_RATE_HI, WID_CHAR},
+ {WID_HUT_PHY_TEST_RATE_LO, WID_CHAR},
+ {WID_HUT_TX_TEST_TIME, WID_INT},
+ {WID_HUT_LOG_INTERVAL, WID_INT},
+ {WID_HUT_DISABLE_RXQ_REPLENISH, WID_CHAR},
+ {WID_HUT_TEST_ID, WID_STR},
+ {WID_HUT_KEY_ORIGIN, WID_CHAR},
+ {WID_HUT_BCST_PERCENT, WID_CHAR},
+ {WID_HUT_GROUP_CIPHER_TYPE, WID_CHAR},
+ {WID_HUT_STATS, WID_BIN_DATA},
+ {WID_HUT_TSF_TEST_MODE, WID_CHAR},
+ {WID_HUT_SIG_QUAL_AVG, WID_SHORT},
+ {WID_HUT_SIG_QUAL_AVG_CNT, WID_SHORT},
+ {WID_HUT_TSSI_VALUE, WID_CHAR},
+ {WID_HUT_MGMT_PERCENT, WID_CHAR},
+ {WID_HUT_MGMT_BCST_PERCENT, WID_CHAR},
+ {WID_HUT_MGMT_ALLOW_HT, WID_CHAR},
+ {WID_HUT_UC_MGMT_TYPE, WID_CHAR},
+ {WID_HUT_BC_MGMT_TYPE, WID_CHAR},
+ {WID_HUT_UC_MGMT_FRAME_LEN, WID_SHORT},
+ {WID_HUT_BC_MGMT_FRAME_LEN, WID_SHORT},
+ {WID_HUT_11W_MFP_REQUIRED_TX, WID_CHAR},
+ {WID_HUT_11W_MFP_PEER_CAPABLE, WID_CHAR},
+ {WID_HUT_11W_TX_IGTK_ID, WID_CHAR},
+ {WID_HUT_FC_TXOP_MOD, WID_CHAR},
+ {WID_HUT_FC_PROT_TYPE, WID_CHAR},
+ {WID_HUT_SEC_CCA_ASSERT, WID_CHAR},
+#endif /* MAC_802_11N */
+};
+
+u16 g_num_total_switches = (sizeof(gastrWIDs) / sizeof(tstrWID));
+/*****************************************************************************/
+/* Static Function Declarations */
+/*****************************************************************************/
+
+
+
+/*****************************************************************************/
+/* Functions */
+/*****************************************************************************/
+INLINE u8 ascii_hex_to_dec(u8 num)
+{
+ if ((num >= '0') && (num <= '9'))
+ return (num - '0');
+ else if ((num >= 'A') && (num <= 'F'))
+ return (10 + (num - 'A'));
+ else if ((num >= 'a') && (num <= 'f'))
+ return (10 + (num - 'a'));
+
+ return INVALID;
+}
+
+INLINE u8 get_hex_char(u8 inp)
+{
+ u8 *d2htab = "0123456789ABCDEF";
+
+ return d2htab[inp & 0xF];
+}
+
+/* This function extracts the MAC address held in a string in standard format */
+/* into another buffer as integers. */
+INLINE u16 extract_mac_addr(char *str, u8 *buff)
+{
+ *buff = 0;
+ while (*str != '\0') {
+ if ((*str == ':') || (*str == '-'))
+ *(++buff) = 0;
+ else
+ *buff = (*buff << 4) + ascii_hex_to_dec(*str);
+
+ str++;
+ }
+
+ return MAC_ADDR_LEN;
+}
+
+/* This function creates MAC address in standard format from a buffer of */
+/* integers. */
+INLINE void create_mac_addr(u8 *str, u8 *buff)
+{
+ u32 i = 0;
+ u32 j = 0;
+
+ for (i = 0; i < MAC_ADDR_LEN; i++) {
+ str[j++] = get_hex_char((u8)((buff[i] >> 4) & 0x0F));
+ str[j++] = get_hex_char((u8)(buff[i] & 0x0F));
+ str[j++] = ':';
+ }
+ str[--j] = '\0';
+}
+
+/* This function converts the IP address string in dotted decimal format to */
+/* unsigned integer. This functionality is similar to the library function */
+/* inet_addr() but is reimplemented here since I could not confirm that */
+/* inet_addr is platform independent. */
+/* ips=>IP Address String in dotted decimal format */
+/* ipn=>Pointer to IP Address in integer format */
+INLINE u8 conv_ip_to_int(u8 *ips, u32 *ipn)
+{
+ u8 i = 0;
+ u8 ipb = 0;
+ *ipn = 0;
+ /* Integer to string for each component */
+ while (ips[i] != '\0') {
+ if (ips[i] == '.') {
+ *ipn = ((*ipn) << 8) | ipb;
+ ipb = 0;
+ } else {
+ ipb = ipb * 10 + ascii_hex_to_dec(ips[i]);
+ }
+
+ i++;
+ }
+
+ /* The last byte of the IP address is read in here */
+ *ipn = ((*ipn) << 8) | ipb;
+
+ return 0;
+}
+
+/* This function converts the IP address from integer format to dotted */
+/* decimal string format. Alternative to std library fn inet_ntoa(). */
+/* ips=>Buffer to hold IP Address String dotted decimal format (Min 17B) */
+/* ipn=>IP Address in integer format */
+INLINE u8 conv_int_to_ip(u8 *ips, u32 ipn)
+{
+ u8 i = 0;
+ u8 ipb = 0;
+ u8 cnt = 0;
+ u8 ipbsize = 0;
+
+ for (cnt = 4; cnt > 0; cnt--) {
+ ipb = (ipn >> (8 * (cnt - 1))) & 0xFF;
+
+ if (ipb >= 100)
+ ipbsize = 2;
+ else if (ipb >= 10)
+ ipbsize = 1;
+ else
+ ipbsize = 0;
+
+ switch (ipbsize) {
+ case 2:
+ ips[i++] = get_hex_char(ipb / 100);
+ ipb %= 100;
+
+ case 1:
+ ips[i++] = get_hex_char(ipb / 10);
+ ipb %= 10;
+
+ default:
+ ips[i++] = get_hex_char(ipb);
+ }
+
+ if (cnt > 1)
+ ips[i++] = '.';
+ }
+
+ ips[i] = '\0';
+
+ return i;
+}
+
+INLINE tenuWIDtype get_wid_type(u32 wid_num)
+{
+ /* Check for iconfig specific WID types first */
+ if ((wid_num == WID_BSSID) ||
+ (wid_num == WID_MAC_ADDR) ||
+ (wid_num == WID_IP_ADDRESS) ||
+ (wid_num == WID_HUT_DEST_ADDR)) {
+ return WID_ADR;
+ }
+
+ if ((WID_1X_SERV_ADDR == wid_num) ||
+ (WID_STACK_IP_ADDR == wid_num) ||
+ (WID_STACK_NETMASK_ADDR == wid_num)) {
+ return WID_IP;
+ }
+
+ /* Next check for standard WID types */
+ if (wid_num < 0x1000)
+ return WID_CHAR;
+ else if (wid_num < 0x2000)
+ return WID_SHORT;
+ else if (wid_num < 0x3000)
+ return WID_INT;
+ else if (wid_num < 0x4000)
+ return WID_STR;
+ else if (wid_num < 0x5000)
+ return WID_BIN_DATA;
+
+ return WID_UNDEF;
+}
+
+
+/* This function extracts the beacon period field from the beacon or probe */
+/* response frame. */
+INLINE u16 get_beacon_period(u8 *data)
+{
+ u16 bcn_per = 0;
+
+ bcn_per = data[0];
+ bcn_per |= (data[1] << 8);
+
+ return bcn_per;
+}
+
+INLINE u32 get_beacon_timestamp_lo(u8 *data)
+{
+ u32 time_stamp = 0;
+ u32 index = MAC_HDR_LEN;
+
+ time_stamp |= data[index++];
+ time_stamp |= (data[index++] << 8);
+ time_stamp |= (data[index++] << 16);
+ time_stamp |= (data[index] << 24);
+
+ return time_stamp;
+}
+
+INLINE u32 get_beacon_timestamp_hi(u8 *data)
+{
+ u32 time_stamp = 0;
+ u32 index = (MAC_HDR_LEN + 4);
+
+ time_stamp |= data[index++];
+ time_stamp |= (data[index++] << 8);
+ time_stamp |= (data[index++] << 16);
+ time_stamp |= (data[index] << 24);
+
+ return time_stamp;
+}
+
+/* This function extracts the 'frame type' bits from the MAC header of the */
+/* input frame. */
+/* Returns the value in the LSB of the returned value. */
+INLINE tenuBasicFrmType get_type(u8 *header)
+{
+ return ((tenuBasicFrmType)(header[0] & 0x0C));
+}
+
+/* This function extracts the 'frame type and sub type' bits from the MAC */
+/* header of the input frame. */
+/* Returns the value in the LSB of the returned value. */
+INLINE tenuFrmSubtype get_sub_type(u8 *header)
+{
+ return ((tenuFrmSubtype)(header[0] & 0xFC));
+}
+
+/* This function extracts the 'to ds' bit from the MAC header of the input */
+/* frame. */
+/* Returns the value in the LSB of the returned value. */
+INLINE u8 get_to_ds(u8 *header)
+{
+ return (header[1] & 0x01);
+}
+
+/* This function extracts the 'from ds' bit from the MAC header of the input */
+/* frame. */
+/* Returns the value in the LSB of the returned value. */
+INLINE u8 get_from_ds(u8 *header)
+{
+ return ((header[1] & 0x02) >> 1);
+}
+
+/* This function extracts the MAC Address in 'address1' field of the MAC */
+/* header and updates the MAC Address in the allocated 'addr' variable. */
+INLINE void get_address1(u8 *pu8msa, u8 *addr)
+{
+ 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(u8 *pu8msa, u8 *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(u8 *pu8msa, u8 *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(u8 *data, u8 *bssid)
+{
+ if (get_from_ds(data) == 1)
+ get_address2(data, bssid);
+ else if (get_to_ds(data) == 1)
+ get_address1(data, bssid);
+ else
+ get_address3(data, bssid);
+}
+
+/* This function extracts the SSID from a beacon/probe response frame */
+INLINE void get_ssid(u8 *data, u8 *ssid, u8 *p_ssid_len)
+{
+ u8 len = 0;
+ u8 i = 0;
+ u8 j = 0;
+
+ len = data[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN +
+ CAP_INFO_LEN + 1];
+ j = MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN +
+ CAP_INFO_LEN + 2;
+
+ /* If the SSID length field is set wrongly to a value greater than the */
+ /* allowed maximum SSID length limit, reset the length to 0 */
+ if (len >= MAX_SSID_LEN)
+ len = 0;
+
+ for (i = 0; i < len; i++, j++)
+ ssid[i] = data[j];
+
+ ssid[len] = '\0';
+
+ *p_ssid_len = len;
+}
+
+/* This function extracts the capability info field from the beacon or probe */
+/* response frame. */
+INLINE u16 get_cap_info(u8 *data)
+{
+ u16 cap_info = 0;
+ u16 index = MAC_HDR_LEN;
+ tenuFrmSubtype st = 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 u16 get_assoc_resp_cap_info(u8 *data)
+{
+ u16 cap_info = 0;
+
+ cap_info = data[0];
+ cap_info |= (data[1] << 8);
+
+ return cap_info;
+}
+
+/* This funcion extracts the association status code from the incoming */
+/* association response frame and returns association status code */
+INLINE u16 get_asoc_status(u8 *data)
+{
+ u16 asoc_status = 0;
+
+ asoc_status = data[3];
+ asoc_status = (asoc_status << 8) | data[2];
+
+ return asoc_status;
+}
+
+/* This function extracts association ID from the incoming association */
+/* response frame */
+INLINE u16 get_asoc_id(u8 *data)
+{
+ u16 asoc_id = 0;
+
+ asoc_id = data[4];
+ asoc_id |= (data[5] << 8);
+
+ return asoc_id;
+}
+
+/**
+ * @brief initializes the Core Configurator
+ * @details
+ * @return Error code indicating success/failure
+ * @note
+ * @author mabubakr
+ * @date 1 Mar 2012
+ * @version 1.0
+ */
+
+s32 CoreConfiguratorInit(void)
+{
+ s32 s32Error = WILC_SUCCESS;
+ PRINT_D(CORECONFIG_DBG, "CoreConfiguratorInit()\n");
+
+ sema_init(&SemHandleSendPkt, 1);
+ sema_init(&SemHandlePktResp, 0);
+
+ gps8ConfigPacket = (s8 *)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;
+}
+
+u8 *get_tim_elm(u8 *pu8msa, u16 u16RxLen, u16 u16TagParamOffset)
+{
+ u16 u16index = 0;
+
+ /*************************************************************************/
+ /* Beacon Frame - Frame Body */
+ /* --------------------------------------------------------------------- */
+ /* |Timestamp |BeaconInt |CapInfo |SSID |SupRates |DSParSet |TIM elm | */
+ /* --------------------------------------------------------------------- */
+ /* |8 |2 |2 |2-34 |3-10 |3 |4-256 | */
+ /* --------------------------------------------------------------------- */
+ /* */
+ /*************************************************************************/
+
+ u16index = u16TagParamOffset;
+
+ /* Search for the TIM Element Field and return if the element is found */
+ while (u16index < (u16RxLen - FCS_LEN)) {
+ if (pu8msa[u16index] == ITIM) {
+ return &pu8msa[u16index];
+ } else {
+ u16index += (IE_HDR_LEN + pu8msa[u16index + 1]);
+ }
+ }
+
+ return 0;
+}
+
+/* This function gets the current channel information from
+ * the 802.11n beacon/probe response frame */
+u8 get_current_channel_802_11n(u8 *pu8msa, u16 u16RxLen)
+{
+ u16 index;
+
+ index = TAG_PARAM_OFFSET;
+ while (index < (u16RxLen - FCS_LEN)) {
+ if (pu8msa[index] == IDSPARMS)
+ return pu8msa[index + 2];
+ else
+ /* Increment index by length information and header */
+ index += pu8msa[index + 1] + IE_HDR_LEN;
+ }
+
+ /* Return current channel information from the MIB, if beacon/probe */
+ /* response frame does not contain the DS parameter set IE */
+ /* return (mget_CurrentChannel() + 1); */
+ return 0; /* no MIB here */
+}
+
+u8 get_current_channel(u8 *pu8msa, u16 u16RxLen)
+{
+#ifdef PHY_802_11n
+#ifdef FIVE_GHZ_BAND
+ /* Get the current channel as its not set in */
+ /* 802.11a beacons/probe response */
+ return (get_rf_channel() + 1);
+#else /* FIVE_GHZ_BAND */
+ /* Extract current channel information from */
+ /* the beacon/probe response frame */
+ return get_current_channel_802_11n(pu8msa, u16RxLen);
+#endif /* FIVE_GHZ_BAND */
+#else
+ return 0;
+#endif /* PHY_802_11n */
+}
+
+/**
+ * @brief parses the received 'N' message
+ * @details
+ * @param[in] pu8MsgBuffer The message to be parsed
+ * @param[out] ppstrNetworkInfo pointer to pointer to the structure containing the parsed Network Info
+ * @return Error code indicating success/failure
+ * @note
+ * @author mabubakr
+ * @date 1 Mar 2012
+ * @version 1.0
+ */
+s32 ParseNetworkInfo(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrNetworkInfo *pstrNetworkInfo = NULL;
+ u8 u8MsgType = 0;
+ u8 u8MsgID = 0;
+ u16 u16MsgLen = 0;
+
+ u16 u16WidID = (u16)WID_NIL;
+ u16 u16WidLen = 0;
+ u8 *pu8WidVal = 0;
+
+ u8MsgType = pu8MsgBuffer[0];
+
+ /* Check whether the received message type is 'N' */
+ if ('N' != u8MsgType) {
+ PRINT_ER("Received Message format incorrect.\n");
+ WILC_ERRORREPORT(s32Error, WILC_FAIL);
+ }
+
+ /* Extract message ID */
+ u8MsgID = pu8MsgBuffer[1];
+
+ /* Extract message Length */
+ u16MsgLen = MAKE_WORD16(pu8MsgBuffer[2], pu8MsgBuffer[3]);
+
+ /* Extract WID ID */
+ u16WidID = MAKE_WORD16(pu8MsgBuffer[4], pu8MsgBuffer[5]);
+
+ /* Extract WID Length */
+ u16WidLen = MAKE_WORD16(pu8MsgBuffer[6], pu8MsgBuffer[7]);
+
+ /* Assign a pointer to the WID value */
+ pu8WidVal = &pu8MsgBuffer[8];
+
+ /* parse the WID value of the WID "WID_NEWORK_INFO" */
+ {
+ u8 *pu8msa = 0;
+ u16 u16RxLen = 0;
+ u8 *pu8TimElm = 0;
+ u8 *pu8IEs = 0;
+ u16 u16IEsLen = 0;
+ u8 u8index = 0;
+ u32 u32Tsf_Lo;
+ u32 u32Tsf_Hi;
+
+ pstrNetworkInfo = (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 | ((u64)u32Tsf_Hi << 32);
+
+ /* Get SSID */
+ get_ssid(pu8msa, pstrNetworkInfo->au8ssid, &(pstrNetworkInfo->u8SsidLen));
+
+ /* Get BSSID */
+ get_BSSID(pu8msa, pstrNetworkInfo->au8bssid);
+
+ /* Get the current channel */
+ pstrNetworkInfo->u8channel = get_current_channel(pu8msa, (u16RxLen + FCS_LEN));
+
+ /* Get beacon period */
+ u8index = (MAC_HDR_LEN + TIME_STAMP_LEN);
+
+ pstrNetworkInfo->u16BeaconPeriod = get_beacon_period(pu8msa + u8index);
+
+ u8index += BEACON_INTERVAL_LEN + CAP_INFO_LEN;
+
+ /* Get DTIM Period */
+ pu8TimElm = get_tim_elm(pu8msa, (u16RxLen + FCS_LEN), u8index);
+ if (pu8TimElm != 0) {
+ pstrNetworkInfo->u8DtimPeriod = pu8TimElm[3];
+ }
+ pu8IEs = &pu8msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN];
+ u16IEsLen = u16RxLen - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN);
+
+ if (u16IEsLen > 0) {
+ pstrNetworkInfo->pu8IEs = (u8 *)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
+ */
+s32 DeallocateNetworkInfo(tstrNetworkInfo *pstrNetworkInfo)
+{
+ s32 s32Error = WILC_SUCCESS;
+
+ if (pstrNetworkInfo != NULL) {
+ if (pstrNetworkInfo->pu8IEs != NULL) {
+ WILC_FREE(pstrNetworkInfo->pu8IEs);
+ pstrNetworkInfo->pu8IEs = NULL;
+ } else {
+ s32Error = WILC_FAIL;
+ }
+
+ WILC_FREE(pstrNetworkInfo);
+ pstrNetworkInfo = NULL;
+
+ } else {
+ s32Error = WILC_FAIL;
+ }
+
+ return s32Error;
+}
+
+/**
+ * @brief parses the received Association Response frame
+ * @details
+ * @param[in] pu8Buffer The Association Response frame to be parsed
+ * @param[out] ppstrConnectRespInfo pointer to pointer to the structure containing the parsed Association Response Info
+ * @return Error code indicating success/failure
+ * @note
+ * @author mabubakr
+ * @date 2 Apr 2012
+ * @version 1.0
+ */
+s32 ParseAssocRespInfo(u8 *pu8Buffer, u32 u32BufferLen,
+ tstrConnectRespInfo **ppstrConnectRespInfo)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrConnectRespInfo *pstrConnectRespInfo = NULL;
+ u16 u16AssocRespLen = 0;
+ u8 *pu8IEs = 0;
+ u16 u16IEsLen = 0;
+
+ pstrConnectRespInfo = (tstrConnectRespInfo *)WILC_MALLOC(sizeof(tstrConnectRespInfo));
+ WILC_memset((void *)(pstrConnectRespInfo), 0, sizeof(tstrConnectRespInfo));
+
+ /* u16AssocRespLen = pu8Buffer[0]; */
+ u16AssocRespLen = (u16)u32BufferLen;
+
+ /* get the status code */
+ pstrConnectRespInfo->u16ConnectStatus = get_asoc_status(pu8Buffer);
+ if (pstrConnectRespInfo->u16ConnectStatus == SUCCESSFUL_STATUSCODE) {
+
+ /* get the capability */
+ pstrConnectRespInfo->u16capability = get_assoc_resp_cap_info(pu8Buffer);
+
+ /* get the Association ID */
+ pstrConnectRespInfo->u16AssocID = get_asoc_id(pu8Buffer);
+
+ /* get the Information Elements */
+ pu8IEs = &pu8Buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN];
+ u16IEsLen = u16AssocRespLen - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN);
+
+ pstrConnectRespInfo->pu8RespIEs = (u8 *)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
+ */
+s32 DeallocateAssocRespInfo(tstrConnectRespInfo *pstrConnectRespInfo)
+{
+ s32 s32Error = WILC_SUCCESS;
+
+ if (pstrConnectRespInfo != NULL) {
+ if (pstrConnectRespInfo->pu8RespIEs != NULL) {
+ WILC_FREE(pstrConnectRespInfo->pu8RespIEs);
+ pstrConnectRespInfo->pu8RespIEs = NULL;
+ } else {
+ s32Error = WILC_FAIL;
+ }
+
+ WILC_FREE(pstrConnectRespInfo);
+ pstrConnectRespInfo = NULL;
+
+ } else {
+ s32Error = WILC_FAIL;
+ }
+
+ return s32Error;
+}
+
+#ifndef CONNECT_DIRECT
+s32 ParseSurveyResults(u8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZE],
+ wid_site_survey_reslts_s **ppstrSurveyResults,
+ u32 *pu32SurveyResultsCount)
+{
+ s32 s32Error = WILC_SUCCESS;
+ wid_site_survey_reslts_s *pstrSurveyResults = NULL;
+ u32 u32SurveyResultsCount = 0;
+ u32 u32SurveyBytesLength = 0;
+ u8 *pu8BufferPtr;
+ u32 u32RcvdSurveyResultsNum = 2;
+ u8 u8ReadSurveyResFragNum;
+ u32 i;
+ u32 j;
+
+ for (i = 0; i < u32RcvdSurveyResultsNum; i++) {
+ u32SurveyBytesLength = ppu8RcvdSiteSurveyResults[i][0];
+
+
+ for (j = 0; j < u32SurveyBytesLength; j += SURVEY_RESULT_LENGTH) {
+ u32SurveyResultsCount++;
+ }
+ }
+
+ pstrSurveyResults = (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;
+}
+
+
+s32 DeallocateSurveyResults(wid_site_survey_reslts_s *pstrSurveyResults)
+{
+ s32 s32Error = WILC_SUCCESS;
+
+ if (pstrSurveyResults != 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(char *pcPacket, s32 *ps32PktLen,
+ tstrWID *pstrWID, s8 *ps8WidVal)
+{
+ u8 *pu8val = (u8 *)ps8WidVal;
+ u8 u8val = 0;
+ s32 s32PktLen = *ps32PktLen;
+ if (pstrWID == NULL) {
+ PRINT_WRN(CORECONFIG_DBG, "Can't set CHAR val 0x%x ,NULL structure\n", u8val);
+ return;
+ }
+
+ /* WID */
+ pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF);
+ pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid >> 8) & 0xFF;
+ if (g_oper_mode == SET_CFG) {
+ u8val = *pu8val;
+
+ /* Length */
+ pcPacket[s32PktLen++] = sizeof(u8);
+
+
+ /* Value */
+ pcPacket[s32PktLen++] = u8val;
+ }
+ *ps32PktLen = s32PktLen;
+}
+
+/*****************************************************************************/
+/* */
+/* Function Name : ProcessShortWid */
+/* */
+/* Description : This function processes a WID of type WID_SHORT and */
+/* updates the cfg packet with the supplied value. */
+/* */
+/* Inputs : 1) Pointer to WID cfg structure */
+/* 2) Value to set */
+/* */
+/* Globals : */
+/* */
+/* Processing : */
+/* */
+/* Outputs : None */
+/* */
+/* Returns : None */
+/* */
+/* Issues : None */
+/* */
+/* Revision History: */
+/* */
+/* DD MM YYYY Author(s) Changes (Describe the changes made) */
+/* 08 01 2008 Ittiam Draft */
+/* */
+/*****************************************************************************/
+
+void ProcessShortWid(char *pcPacket, s32 *ps32PktLen,
+ tstrWID *pstrWID, s8 *ps8WidVal)
+{
+ u16 *pu16val = (u16 *)ps8WidVal;
+ u16 u16val = 0;
+ s32 s32PktLen = *ps32PktLen;
+ if (pstrWID == NULL) {
+ PRINT_WRN(CORECONFIG_DBG, "Can't set SHORT val 0x%x ,NULL structure\n", u16val);
+ return;
+ }
+
+ /* WID */
+ pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF);
+ pcPacket[s32PktLen++] = (u8)((pstrWID->u16WIDid >> 8) & 0xFF);
+
+ if (g_oper_mode == SET_CFG) {
+ u16val = *pu16val;
+
+ /* Length */
+ pcPacket[s32PktLen++] = sizeof(u16);
+
+ /* Value */
+ pcPacket[s32PktLen++] = (u8)(u16val & 0xFF);
+ pcPacket[s32PktLen++] = (u8)((u16val >> 8) & 0xFF);
+ }
+ *ps32PktLen = s32PktLen;
+}
+
+/*****************************************************************************/
+/* */
+/* Function Name : ProcessIntWid */
+/* */
+/* Description : This function processes a WID of type WID_INT and */
+/* updates the cfg packet with the supplied value. */
+/* */
+/* Inputs : 1) Pointer to WID cfg structure */
+/* 2) Value to set */
+/* */
+/* Globals : */
+/* */
+/* Processing : */
+/* */
+/* Outputs : None */
+/* */
+/* Returns : None */
+/* */
+/* Issues : None */
+/* */
+/* Revision History: */
+/* */
+/* DD MM YYYY Author(s) Changes (Describe the changes made) */
+/* 08 01 2008 Ittiam Draft */
+/* */
+/*****************************************************************************/
+
+void ProcessIntWid(char *pcPacket, s32 *ps32PktLen,
+ tstrWID *pstrWID, s8 *ps8WidVal)
+{
+ u32 *pu32val = (u32 *)ps8WidVal;
+ u32 u32val = 0;
+ s32 s32PktLen = *ps32PktLen;
+ if (pstrWID == NULL) {
+ PRINT_WRN(CORECONFIG_DBG, "Can't set INT val 0x%x , NULL structure\n", u32val);
+ return;
+ }
+
+ /* WID */
+ pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF);
+ pcPacket[s32PktLen++] = (u8)((pstrWID->u16WIDid >> 8) & 0xFF);
+
+ if (g_oper_mode == SET_CFG) {
+ u32val = *pu32val;
+
+ /* Length */
+ pcPacket[s32PktLen++] = sizeof(u32);
+
+ /* Value */
+ pcPacket[s32PktLen++] = (u8)(u32val & 0xFF);
+ pcPacket[s32PktLen++] = (u8)((u32val >> 8) & 0xFF);
+ pcPacket[s32PktLen++] = (u8)((u32val >> 16) & 0xFF);
+ pcPacket[s32PktLen++] = (u8)((u32val >> 24) & 0xFF);
+ }
+ *ps32PktLen = s32PktLen;
+}
+
+/*****************************************************************************/
+/* */
+/* Function Name : ProcessIPwid */
+/* */
+/* Description : This function processes a WID of type WID_IP and */
+/* updates the cfg packet with the supplied value. */
+/* */
+/* Inputs : 1) Pointer to WID cfg structure */
+/* 2) Value to set */
+/* */
+/* Globals : */
+/* */
+/* */
+/* Processing : */
+/* */
+/* Outputs : None */
+/* */
+/* Returns : None */
+/* */
+/* Issues : None */
+/* */
+/* Revision History: */
+/* */
+/* DD MM YYYY Author(s) Changes (Describe the changes made) */
+/* 08 01 2008 Ittiam Draft */
+/* */
+/*****************************************************************************/
+
+void ProcessIPwid(char *pcPacket, s32 *ps32PktLen,
+ tstrWID *pstrWID, u8 *pu8ip)
+{
+ u32 u32val = 0;
+ s32 s32PktLen = *ps32PktLen;
+
+ if (pstrWID == NULL) {
+ PRINT_WRN(CORECONFIG_DBG, "Can't set IP Addr , NULL structure\n");
+ return;
+ }
+
+ /* WID */
+ pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF);
+ pcPacket[s32PktLen++] = (u8)((pstrWID->u16WIDid >> 8) & 0xFF);
+
+ if (g_oper_mode == SET_CFG) {
+ /* Length */
+ pcPacket[s32PktLen++] = sizeof(u32);
+
+ /* Convert the IP Address String to Integer */
+ conv_ip_to_int(pu8ip, &u32val);
+
+ /* Value */
+ pcPacket[s32PktLen++] = (u8)(u32val & 0xFF);
+ pcPacket[s32PktLen++] = (u8)((u32val >> 8) & 0xFF);
+ pcPacket[s32PktLen++] = (u8)((u32val >> 16) & 0xFF);
+ pcPacket[s32PktLen++] = (u8)((u32val >> 24) & 0xFF);
+ }
+ *ps32PktLen = s32PktLen;
+}
+
+/*****************************************************************************/
+/* */
+/* Function Name : ProcessStrWid */
+/* */
+/* Description : This function processes a WID of type WID_STR and */
+/* updates the cfg packet with the supplied value. */
+/* */
+/* Inputs : 1) Pointer to WID cfg structure */
+/* 2) Value to set */
+/* */
+/* Globals : */
+/* */
+/* Processing : */
+/* */
+/* Outputs : None */
+/* */
+/* Returns : None */
+/* */
+/* Issues : None */
+/* */
+/* Revision History: */
+/* */
+/* DD MM YYYY Author(s) Changes (Describe the changes made) */
+/* 08 01 2008 Ittiam Draft */
+/* */
+/*****************************************************************************/
+
+void ProcessStrWid(char *pcPacket, s32 *ps32PktLen,
+ tstrWID *pstrWID, u8 *pu8val, s32 s32ValueSize)
+{
+ u16 u16MsgLen = 0;
+ u16 idx = 0;
+ s32 s32PktLen = *ps32PktLen;
+ if (pstrWID == NULL) {
+ PRINT_WRN(CORECONFIG_DBG, "Can't set STR val, NULL structure\n");
+ return;
+ }
+
+ /* WID */
+ pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF);
+ pcPacket[s32PktLen++] = (u8)((pstrWID->u16WIDid >> 8) & 0xFF);
+
+ if (g_oper_mode == SET_CFG) {
+ /* Message Length */
+ /* u16MsgLen = WILC_strlen(pu8val); */
+ u16MsgLen = (u16)s32ValueSize;
+
+ /* Length */
+ pcPacket[s32PktLen++] = (u8)u16MsgLen;
+
+ /* Value */
+ for (idx = 0; idx < u16MsgLen; idx++)
+ pcPacket[s32PktLen++] = pu8val[idx];
+ }
+ *ps32PktLen = s32PktLen;
+}
+
+/*****************************************************************************/
+/* */
+/* Function Name : ProcessAdrWid */
+/* */
+/* Description : This function processes a WID of type WID_ADR and */
+/* updates the cfg packet with the supplied value. */
+/* */
+/* Inputs : 1) Pointer to WID cfg structure */
+/* 2) Value to set */
+/* */
+/* Globals : */
+/* */
+/* Processing : */
+/* */
+/* Outputs : None */
+/* */
+/* Returns : None */
+/* */
+/* Issues : None */
+/* */
+/* Revision History: */
+/* */
+/* DD MM YYYY Author(s) Changes (Describe the changes made) */
+/* 08 01 2008 Ittiam Draft */
+/* */
+/*****************************************************************************/
+
+void ProcessAdrWid(char *pcPacket, s32 *ps32PktLen,
+ tstrWID *pstrWID, u8 *pu8val)
+{
+ u16 u16MsgLen = 0;
+ s32 s32PktLen = *ps32PktLen;
+
+ if (pstrWID == NULL) {
+ PRINT_WRN(CORECONFIG_DBG, "Can't set Addr WID, NULL structure\n");
+ return;
+ }
+
+ /* WID */
+ pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF);
+ pcPacket[s32PktLen++] = (u8)((pstrWID->u16WIDid >> 8) & 0xFF);
+
+ if (g_oper_mode == SET_CFG) {
+ /* Message Length */
+ u16MsgLen = MAC_ADDR_LEN;
+
+ /* Length */
+ pcPacket[s32PktLen++] = (u8)u16MsgLen;
+
+ /* Value */
+ extract_mac_addr(pu8val, pcPacket + s32PktLen);
+ s32PktLen += u16MsgLen;
+ }
+ *ps32PktLen = s32PktLen;
+}
+
+/*****************************************************************************/
+/* */
+/* Function Name : ProcessBinWid */
+/* */
+/* Description : This function processes a WID of type WID_BIN_DATA and */
+/* updates the cfg packet with the supplied value. */
+/* */
+/* Inputs : 1) Pointer to WID cfg structure */
+/* 2) Name of file containing the binary data in text mode */
+/* */
+/* Globals : */
+/* */
+/* Processing : The binary data is expected to be supplied through a */
+/* file in text mode. This file is expected to be in the */
+/* finject format. It is parsed, converted to binary format */
+/* and copied into g_cfg_pkt for further processing. This */
+/* is obviously a round-about way of processing involving */
+/* multiple (re)conversions between bin & ascii formats. */
+/* But it is done nevertheless to retain uniformity and for */
+/* ease of debugging. */
+/* */
+/* Outputs : None */
+/* */
+/* Returns : None */
+/* */
+
+/* Issues : None */
+/* */
+/* Revision History: */
+/* */
+/* DD MM YYYY Author(s) Changes (Describe the changes made) */
+/* 08 01 2008 Ittiam Draft */
+/* */
+/*****************************************************************************/
+
+void ProcessBinWid(char *pcPacket, s32 *ps32PktLen,
+ tstrWID *pstrWID, u8 *pu8val, s32 s32ValueSize)
+{
+ /* WILC_ERROR("processing Binary WIDs is not supported\n"); */
+
+ u16 u16MsgLen = 0;
+ u16 idx = 0;
+ s32 s32PktLen = *ps32PktLen;
+ u8 u8checksum = 0;
+
+ if (pstrWID == NULL) {
+ PRINT_WRN(CORECONFIG_DBG, "Can't set BIN val, NULL structure\n");
+ return;
+ }
+
+ /* WID */
+ pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF);
+ pcPacket[s32PktLen++] = (u8)((pstrWID->u16WIDid >> 8) & 0xFF);
+
+ if (g_oper_mode == SET_CFG) {
+ /* Message Length */
+ u16MsgLen = (u16)s32ValueSize;
+
+ /* Length */
+ /* pcPacket[s32PktLen++] = (u8)u16MsgLen; */
+ pcPacket[s32PktLen++] = (u8)(u16MsgLen & 0xFF);
+ pcPacket[s32PktLen++] = (u8)((u16MsgLen >> 8) & 0xFF);
+
+ /* Value */
+ for (idx = 0; idx < u16MsgLen; idx++)
+ pcPacket[s32PktLen++] = pu8val[idx];
+
+ /* checksum */
+ for (idx = 0; idx < u16MsgLen; idx++)
+ u8checksum += pcPacket[MSG_HEADER_LEN + idx + 4];
+
+ pcPacket[s32PktLen++] = u8checksum;
+ }
+ *ps32PktLen = s32PktLen;
+}
+
+
+/*****************************************************************************/
+/* */
+/* Function Name : further_process_response */
+/* */
+/* Description : This function parses the response frame got from the */
+/* device. */
+/* */
+/* Inputs : 1) The received response frame */
+/* 2) WID */
+/* 3) WID Length */
+/* 4) Output file handle */
+/* 5) Process Wid Number(i.e wid from --widn switch) */
+/* 6) Index the array in the Global Wid Structure. */
+/* */
+/* Globals : g_wid_num, gastrWIDs */
+/* */
+/* Processing : This function parses the response of the device depending*/
+/* WID type and writes it to the output file in Hex or */
+/* decimal notation depending on the --getx or --get switch.*/
+/* */
+/* Outputs : None */
+/* */
+/* Returns : 0 on Success & -2 on Failure */
+/* */
+/* Issues : None */
+/* */
+/* Revision History: */
+/* */
+/* DD MM YYYY Author(s) Changes (Describe the changes made) */
+/* 08 01 2009 Ittiam Draft */
+/* */
+/*****************************************************************************/
+
+s32 further_process_response(u8 *resp,
+ u16 u16WIDid,
+ u16 cfg_len,
+ bool process_wid_num,
+ u32 cnt,
+ tstrWID *pstrWIDresult)
+{
+ u32 retval = 0;
+ u32 idx = 0;
+ u8 cfg_chr = 0;
+ u16 cfg_sht = 0;
+ u32 cfg_int = 0;
+ u8 cfg_str[256] = {0};
+ tenuWIDtype enuWIDtype = WID_UNDEF;
+
+ if (process_wid_num) {
+ enuWIDtype = get_wid_type(g_wid_num);
+ } else {
+ enuWIDtype = gastrWIDs[cnt].enuWIDtype;
+ }
+
+
+ switch (enuWIDtype) {
+ case WID_CHAR:
+ cfg_chr = resp[idx];
+ /*Set local copy of WID*/
+ *(pstrWIDresult->ps8WidVal) = cfg_chr;
+ break;
+
+ case WID_SHORT:
+ {
+ u16 *pu16val = (u16 *)(pstrWIDresult->ps8WidVal);
+ cfg_sht = MAKE_WORD16(resp[idx], resp[idx + 1]);
+ /*Set local copy of WID*/
+ /* pstrWIDresult->ps8WidVal = (s8*)(s32)cfg_sht; */
+ *pu16val = cfg_sht;
+ break;
+ }
+
+ case WID_INT:
+ {
+ u32 *pu32val = (u32 *)(pstrWIDresult->ps8WidVal);
+ cfg_int = MAKE_WORD32(
+ MAKE_WORD16(resp[idx], resp[idx + 1]),
+ MAKE_WORD16(resp[idx + 2], resp[idx + 3])
+ );
+ /*Set local copy of WID*/
+ /* pstrWIDresult->ps8WidVal = (s8*)cfg_int; */
+ *pu32val = cfg_int;
+ break;
+ }
+
+ case WID_STR:
+ 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 (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 */
+/* */
+/*****************************************************************************/
+
+s32 ParseResponse(u8 *resp, tstrWID *pstrWIDcfgResult)
+{
+ u16 u16RespLen = 0;
+ u16 u16WIDid = 0;
+ u16 cfg_len = 0;
+ tenuWIDtype enuWIDtype = WID_UNDEF;
+ bool num_wid_processed = false;
+ u32 cnt = 0;
+ u32 idx = 0;
+ u32 ResCnt = 0;
+ /* Check whether the received frame is a valid response */
+ if (RESP_MSG_TYPE != resp[0]) {
+ PRINT_INFO(CORECONFIG_DBG, "Received Message format incorrect.\n");
+ return -1;
+ }
+
+ /* Extract Response Length */
+ u16RespLen = MAKE_WORD16(resp[2], resp[3]);
+ Res_Len = u16RespLen;
+
+ for (idx = MSG_HEADER_LEN; idx < u16RespLen; ) {
+ u16WIDid = MAKE_WORD16(resp[idx], resp[idx + 1]);
+ cfg_len = resp[idx + 2];
+ /* Incase of Bin Type Wid, the length is given by two byte field */
+ enuWIDtype = get_wid_type(u16WIDid);
+ if (WID_BIN_DATA == enuWIDtype) {
+ cfg_len |= ((u16)resp[idx + 3] << 8) & 0xFF00;
+ idx++;
+ }
+ idx += 3;
+ if ((u16WIDid == g_wid_num) && (!num_wid_processed)) {
+ num_wid_processed = true;
+
+ if (-2 == further_process_response(&resp[idx], u16WIDid, cfg_len, true, 0, &pstrWIDcfgResult[ResCnt])) {
+ return -2;
+ }
+ ResCnt++;
+ } else {
+ for (cnt = 0; cnt < g_num_total_switches; cnt++) {
+ if (gastrWIDs[cnt].u16WIDid == u16WIDid) {
+ if (-2 == further_process_response(&resp[idx], u16WIDid, cfg_len, false, cnt,
+ &pstrWIDcfgResult[ResCnt])) {
+ return -2;
+ }
+ ResCnt++;
+ }
+ }
+ }
+ idx += cfg_len;
+ /* In case if BIN type Wid, The last byte of the Cfg packet is the */
+ /* Checksum. The WID Length field does not accounts for the checksum. */
+ /* The Checksum is discarded. */
+ if (WID_BIN_DATA == enuWIDtype) {
+ idx++;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * @brief parses the write response [just detects its status: success or failure]
+ * @details
+ * @param[in] pu8RespBuffer The Response to be parsed
+ * @return Error code indicating Write Operation status:
+ * WRITE_RESP_SUCCESS (1) => Write Success.
+ * WILC_FAIL (-100) => Write Failure.
+ * @note
+ * @author Ittiam
+ * @date 11 Aug 2009
+ * @version 1.0
+ */
+
+s32 ParseWriteResponse(u8 *pu8RespBuffer)
+{
+ s32 s32Error = WILC_FAIL;
+ u16 u16RespLen = 0;
+ u16 u16WIDtype = (u16)WID_NIL;
+
+ /* Check whether the received frame is a valid response */
+ if (RESP_MSG_TYPE != pu8RespBuffer[0]) {
+ PRINT_ER("Received Message format incorrect.\n");
+ return WILC_FAIL;
+ }
+
+ /* 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
+ */
+
+s32 CreatePacketHeader(char *pcpacket, s32 *ps32PacketLength)
+{
+ s32 s32Error = WILC_SUCCESS;
+ u16 u16MsgLen = (u16)(*ps32PacketLength);
+ u16 u16MsgInd = 0;
+
+ /* The format of the message is: */
+ /* +-------------------------------------------------------------------+ */
+ /* | Message Type | Message ID | Message Length |Message body | */
+ /* +-------------------------------------------------------------------+ */
+ /* | 1 Byte | 1 Byte | 2 Bytes | Message Length - 4 | */
+ /* +-------------------------------------------------------------------+ */
+
+ /* The format of a message body of a message type 'W' is: */
+ /* +-------------------------------------------------------------------+ */
+ /* | WID0 | WID0 Length | WID0 Value | ......................... | */
+ /* +-------------------------------------------------------------------+ */
+ /* | 2 Bytes | 1 Byte | WID0 Length | ......................... | */
+ /* +-------------------------------------------------------------------+ */
+
+
+
+ /* Message Type */
+ if (g_oper_mode == SET_CFG)
+ pcpacket[u16MsgInd++] = WRITE_MSG_TYPE;
+ else
+ pcpacket[u16MsgInd++] = QUERY_MSG_TYPE;
+
+ /* Sequence Number */
+ pcpacket[u16MsgInd++] = g_seqno++;
+
+ /* Message Length */
+ pcpacket[u16MsgInd++] = (u8)(u16MsgLen & 0xFF);
+ pcpacket[u16MsgInd++] = (u8)((u16MsgLen >> 8) & 0xFF);
+
+ *ps32PacketLength = u16MsgLen;
+
+ return s32Error;
+}
+
+/**
+ * @brief creates Configuration packet based on the Input WIDs
+ * @details
+ * @param[in] pstrWIDs WIDs to be sent in the configuration packet
+ * @param[in] u32WIDsCount number of WIDs to be sent in the configuration packet
+ * @param[out] ps8packet The created Configuration Packet
+ * @param[out] ps32PacketLength Length of the created Configuration Packet
+ * @return Error code indicating success/failure
+ * @note
+ * @author
+ * @date 1 Mar 2012
+ * @version 1.0
+ */
+
+s32 CreateConfigPacket(s8 *ps8packet, s32 *ps32PacketLength,
+ tstrWID *pstrWIDs, u32 u32WIDsCount)
+{
+ s32 s32Error = WILC_SUCCESS;
+ u32 u32idx = 0;
+ *ps32PacketLength = MSG_HEADER_LEN;
+ for (u32idx = 0; u32idx < u32WIDsCount; u32idx++) {
+ switch (pstrWIDs[u32idx].enuWIDtype) {
+ case WID_CHAR:
+ ProcessCharWid(ps8packet, ps32PacketLength, &pstrWIDs[u32idx],
+ pstrWIDs[u32idx].ps8WidVal);
+ break;
+
+ case WID_SHORT:
+ ProcessShortWid(ps8packet, ps32PacketLength, &pstrWIDs[u32idx],
+ pstrWIDs[u32idx].ps8WidVal);
+ break;
+
+ case WID_INT:
+ ProcessIntWid(ps8packet, ps32PacketLength, &pstrWIDs[u32idx],
+ pstrWIDs[u32idx].ps8WidVal);
+ break;
+
+ case WID_STR:
+ ProcessStrWid(ps8packet, ps32PacketLength, &pstrWIDs[u32idx],
+ pstrWIDs[u32idx].ps8WidVal, pstrWIDs[u32idx].s32ValueSize);
+ break;
+
+ case WID_IP:
+ ProcessIPwid(ps8packet, ps32PacketLength, &pstrWIDs[u32idx],
+ pstrWIDs[u32idx].ps8WidVal);
+ break;
+
+ case WID_BIN_DATA:
+ ProcessBinWid(ps8packet, ps32PacketLength, &pstrWIDs[u32idx],
+ pstrWIDs[u32idx].ps8WidVal, pstrWIDs[u32idx].s32ValueSize);
+ break;
+
+ default:
+ PRINT_ER("ERROR: Check Config database\n");
+ }
+ }
+
+ CreatePacketHeader(ps8packet, ps32PacketLength);
+
+ return s32Error;
+}
+
+s32 ConfigWaitResponse(char *pcRespBuffer, s32 s32MaxRespBuffLen, s32 *ps32BytesRead,
+ bool bRespRequired)
+{
+ s32 s32Error = WILC_SUCCESS;
+ /*bug 3878*/
+ /*removed to caller function*/
+ /*gstrConfigPktInfo.pcRespBuffer = pcRespBuffer;
+ * gstrConfigPktInfo.s32MaxRespBuffLen = s32MaxRespBuffLen;
+ * gstrConfigPktInfo.bRespRequired = bRespRequired;*/
+
+
+ if (gstrConfigPktInfo.bRespRequired) {
+ down(&SemHandlePktResp);
+
+ *ps32BytesRead = gstrConfigPktInfo.s32BytesRead;
+ }
+
+ 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
+s32 SendConfigPkt(u8 u8Mode, tstrWID *pstrWIDs,
+ u32 u32WIDsCount, bool bRespRequired, u32 drvHandler)
+{
+ s32 s32Error = WILC_SUCCESS;
+ s32 err = WILC_SUCCESS;
+ s32 s32ConfigPacketLen = 0;
+ s32 s32RcvdRespLen = 0;
+
+ down(&SemHandleSendPkt);
+
+ /*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) {
+ /* 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:
+ up(&SemHandleSendPkt);
+
+ return s32Error;
+}
+#endif
+s32 ConfigProvideResponse(char *pcRespBuffer, s32 s32RespLen)
+{
+ s32 s32Error = WILC_SUCCESS;
+
+ if (gstrConfigPktInfo.bRespRequired) {
+ 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");
+ }
+
+ up(&SemHandlePktResp);
+ }
+
+ return s32Error;
+}
+
+/**
+ * @brief writes the received packet pu8RxPacket in the global Rx FIFO buffer
+ * @details
+ * @param[in] pu8RxPacket The received packet
+ * @param[in] s32RxPacketLen Length of the received packet
+ * @return Error code indicating success/failure
+ * @note
+ *
+ * @author mabubakr
+ * @date 1 Mar 2012
+ * @version 1.0
+ */
+
+s32 ConfigPktReceived(u8 *pu8RxPacket, s32 s32RxPacketLen)
+{
+ s32 s32Error = WILC_SUCCESS;
+ u8 u8MsgType = 0;
+
+ u8MsgType = pu8RxPacket[0];
+
+ switch (u8MsgType) {
+ case 'R':
+ ConfigProvideResponse(pu8RxPacket, s32RxPacketLen);
+
+ break;
+
+ case 'N':
+ PRINT_INFO(CORECONFIG_DBG, "NetworkInfo packet received\n");
+ NetworkInfoReceived(pu8RxPacket, s32RxPacketLen);
+ break;
+
+ case 'I':
+ GnrlAsyncInfoReceived(pu8RxPacket, s32RxPacketLen);
+ break;
+
+ case 'S':
+ host_int_ScanCompleteReceived(pu8RxPacket, s32RxPacketLen);
+ break;
+
+ default:
+ PRINT_ER("ConfigPktReceived(): invalid received msg type at the Core Configurator\n");
+ break;
+ }
+
+ return s32Error;
+}
+
+/**
+ * @brief Deinitializes the Core Configurator
+ * @details
+ * @return Error code indicating success/failure
+ * @note
+ * @author mabubakr
+ * @date 1 Mar 2012
+ * @version 1.0
+ */
+
+s32 CoreConfiguratorDeInit(void)
+{
+ s32 s32Error = WILC_SUCCESS;
+
+ PRINT_D(CORECONFIG_DBG, "CoreConfiguratorDeInit()\n");
+
+ if (gps8ConfigPacket != NULL) {
+
+ WILC_FREE(gps8ConfigPacket);
+ gps8ConfigPacket = NULL;
+ }
+
+ return s32Error;
+}
+
+
+#ifndef SIMULATION
+/*Using the global handle of the driver*/
+extern wilc_wlan_oup_t *gpstrWlanOps;
+/**
+ * @brief sends certain Configuration Packet based on the input WIDs pstrWIDs
+ * using driver config layer
+ *
+ * @details
+ * @param[in] pstrWIDs WIDs to be sent in the configuration packet
+ * @param[in] u32WIDsCount number of WIDs to be sent in the configuration packet
+ * @param[out] pu8RxResp The received Packet Response
+ * @param[out] ps32RxRespLen Length of the received Packet Response
+ * @return Error code indicating success/failure
+ * @note
+ * @author mabubakr
+ * @date 1 Mar 2012
+ * @version 1.0
+ */
+s32 SendConfigPkt(u8 u8Mode, tstrWID *pstrWIDs,
+ u32 u32WIDsCount, bool bRespRequired, u32 drvHandler)
+{
+ s32 counter = 0, ret = 0;
+ if (gpstrWlanOps == NULL) {
+ PRINT_D(CORECONFIG_DBG, "Net Dev is still not initialized\n");
+ return 1;
+ } else {
+ PRINT_D(CORECONFIG_DBG, "Net Dev is initialized\n");
+ }
+ if (gpstrWlanOps->wlan_cfg_set == NULL ||
+ gpstrWlanOps->wlan_cfg_get == NULL) {
+ PRINT_D(CORECONFIG_DBG, "Set and Get is still not initialized\n");
+ return 1;
+ } else {
+ PRINT_D(CORECONFIG_DBG, "SET is initialized\n");
+ }
+ if (u8Mode == GET_CFG) {
+ for (counter = 0; counter < u32WIDsCount; counter++) {
+ PRINT_INFO(CORECONFIG_DBG, "Sending CFG packet [%d][%d]\n", !counter,
+ (counter == u32WIDsCount - 1));
+ if (!gpstrWlanOps->wlan_cfg_get(!counter,
+ pstrWIDs[counter].u16WIDid,
+ (counter == u32WIDsCount - 1), drvHandler)) {
+ ret = -1;
+ printk("[Sendconfigpkt]Get Timed out\n");
+ break;
+ }
+ }
+ /**
+ * get the value
+ **/
+ /* 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
diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h
new file mode 100644
index 000000000..9059c8df7
--- /dev/null
+++ b/drivers/staging/wilc1000/coreconfigurator.h
@@ -0,0 +1,197 @@
+
+/*!
+ * @file coreconfigurator.h
+ * @brief
+ * @author
+ * @sa coreconfigurator.c
+ * @date 1 Mar 2012
+ * @version 1.0
+ */
+
+
+#ifndef CORECONFIGURATOR_H
+#define CORECONFIGURATOR_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 u16 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) ((((u16)(msb) << 8) & 0xFF00) | (lsb))
+#define MAKE_WORD32(lsw, msw) ((((u32)(msw) << 16) & 0xFFFF0000) | (lsw))
+
+
+/*****************************************************************************/
+/* Type Definitions */
+/*****************************************************************************/
+/* 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 {
+ u16 u16WIDid;
+ tenuWIDtype enuWIDtype;
+ s32 s32ValueSize;
+ s8 *ps8WidVal;
+
+} tstrWID;
+
+typedef struct {
+ u8 u8Full;
+ u8 u8Index;
+ s8 as8RSSI[NUM_RSSI];
+} tstrRSSI;
+/* This structure is used to support parsing of the received 'N' message */
+typedef struct {
+ s8 s8rssi;
+ u16 u16CapInfo;
+ u8 au8ssid[MAX_SSID_LEN];
+ u8 u8SsidLen;
+ u8 au8bssid[6];
+ u16 u16BeaconPeriod;
+ u8 u8DtimPeriod;
+ u8 u8channel;
+ unsigned long u32TimeRcvdInScanCached; /* of type unsigned long to be accepted by the linux kernel macro time_after() */
+ unsigned long u32TimeRcvdInScan;
+ bool bNewNetwork;
+#ifdef AGING_ALG
+ u8 u8Found;
+#endif
+#ifdef WILC_P2P
+ u32 u32Tsf; /* time-stamp [Low only 32 bit] */
+#endif
+ u8 *pu8IEs;
+ u16 u16IEsLen;
+ void *pJoinParams;
+ tstrRSSI strRssi;
+ u64 u64Tsf; /* time-stamp [Low and High 64 bit] */
+} tstrNetworkInfo;
+
+/* This structure is used to support parsing of the received Association Response frame */
+typedef struct {
+ u16 u16capability;
+ u16 u16ConnectStatus;
+ u16 u16AssocID;
+ u8 *pu8RespIEs;
+ u16 u16RespIEsLen;
+} tstrConnectRespInfo;
+
+
+typedef struct {
+ u8 au8bssid[6];
+ u8 *pu8ReqIEs;
+ size_t ReqIEsLen;
+ u8 *pu8RespIEs;
+ u16 u16RespIEsLen;
+ u16 u16ConnectStatus;
+} tstrConnectInfo;
+
+
+
+typedef struct {
+ u16 u16reason;
+ u8 *ie;
+ size_t ie_len;
+} tstrDisconnectNotifInfo;
+
+#ifndef CONNECT_DIRECT
+typedef struct wid_site_survey_reslts {
+ char SSID[MAX_SSID_LEN];
+ u8 BssType;
+ u8 Channel;
+ u8 SecurityStatus;
+ u8 BSSID[6];
+ char RxPower;
+ u8 Reserved;
+
+} wid_site_survey_reslts_s;
+#endif
+
+extern s32 CoreConfiguratorInit(void);
+extern s32 CoreConfiguratorDeInit(void);
+
+extern s32 SendConfigPkt(u8 u8Mode, tstrWID *pstrWIDs,
+ u32 u32WIDsCount, bool bRespRequired, u32 drvHandler);
+extern s32 ParseNetworkInfo(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo);
+extern s32 DeallocateNetworkInfo(tstrNetworkInfo *pstrNetworkInfo);
+
+extern s32 ParseAssocRespInfo(u8 *pu8Buffer, u32 u32BufferLen,
+ tstrConnectRespInfo **ppstrConnectRespInfo);
+extern s32 DeallocateAssocRespInfo(tstrConnectRespInfo *pstrConnectRespInfo);
+
+#ifndef CONNECT_DIRECT
+extern s32 ParseSurveyResults(u8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZE],
+ wid_site_survey_reslts_s **ppstrSurveyResults, u32 *pu32SurveyResultsCount);
+extern s32 DeallocateSurveyResults(wid_site_survey_reslts_s *pstrSurveyResults);
+#endif
+
+extern s32 SendRawPacket(s8 *pspacket, s32 s32PacketLen);
+extern void NetworkInfoReceived(u8 *pu8Buffer, u32 u32Length);
+void GnrlAsyncInfoReceived(u8 *pu8Buffer, u32 u32Length);
+void host_int_ScanCompleteReceived(u8 *pu8Buffer, u32 u32Length);
+
+#endif
diff --git a/drivers/staging/wilc1000/fifo_buffer.c b/drivers/staging/wilc1000/fifo_buffer.c
new file mode 100644
index 000000000..b6c07cfc4
--- /dev/null
+++ b/drivers/staging/wilc1000/fifo_buffer.c
@@ -0,0 +1,133 @@
+
+
+#include "fifo_buffer.h"
+
+
+
+u32 FIFO_InitBuffer(tHANDLE *hBuffer, u32 u32BufferLength)
+{
+ u32 u32Error = 0;
+ tstrFifoHandler *pstrFifoHandler = WILC_MALLOC (sizeof (tstrFifoHandler));
+ if (pstrFifoHandler) {
+ WILC_memset (pstrFifoHandler, 0, sizeof (tstrFifoHandler));
+ pstrFifoHandler->pu8Buffer = WILC_MALLOC (u32BufferLength);
+ if (pstrFifoHandler->pu8Buffer) {
+ pstrFifoHandler->u32BufferLength = u32BufferLength;
+ WILC_memset (pstrFifoHandler->pu8Buffer, 0, u32BufferLength);
+ /* create semaphore */
+ sema_init(&pstrFifoHandler->SemBuffer, 1);
+ *hBuffer = pstrFifoHandler;
+ } else {
+ *hBuffer = NULL;
+ u32Error = 1;
+ }
+ } else {
+ u32Error = 1;
+ }
+ return u32Error;
+}
+u32 FIFO_DeInit(tHANDLE hFifo)
+{
+ u32 u32Error = 0;
+ tstrFifoHandler *pstrFifoHandler = (tstrFifoHandler *) hFifo;
+ if (pstrFifoHandler) {
+ if (pstrFifoHandler->pu8Buffer) {
+ WILC_FREE (pstrFifoHandler->pu8Buffer);
+ } else {
+ u32Error = 1;
+ }
+
+ WILC_FREE (pstrFifoHandler);
+ } else {
+ u32Error = 1;
+ }
+ return u32Error;
+}
+
+u32 FIFO_ReadBytes(tHANDLE hFifo, u8 *pu8Buffer, u32 u32BytesToRead, u32 *pu32BytesRead)
+{
+ u32 u32Error = 0;
+ tstrFifoHandler *pstrFifoHandler = (tstrFifoHandler *) hFifo;
+ if (pstrFifoHandler && pu32BytesRead) {
+ if (pstrFifoHandler->u32TotalBytes) {
+ down(&pstrFifoHandler->SemBuffer);
+
+ 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 {
+ u32 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;
+ }
+ up(&pstrFifoHandler->SemBuffer);
+ } else {
+ u32Error = 1;
+ }
+ } else {
+ u32Error = 1;
+ }
+ return u32Error;
+}
+
+u32 FIFO_WriteBytes(tHANDLE hFifo, u8 *pu8Buffer, u32 u32BytesToWrite, bool bForceOverWrite)
+{
+ u32 u32Error = 0;
+ tstrFifoHandler *pstrFifoHandler = (tstrFifoHandler *) hFifo;
+ if (pstrFifoHandler) {
+ if (u32BytesToWrite < pstrFifoHandler->u32BufferLength) {
+ if ((pstrFifoHandler->u32TotalBytes + u32BytesToWrite) <= pstrFifoHandler->u32BufferLength ||
+ bForceOverWrite) {
+ down(&pstrFifoHandler->SemBuffer);
+ 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 {
+ u32 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;
+ }
+ up(&pstrFifoHandler->SemBuffer);
+ } else {
+ u32Error = 1;
+ }
+ } else {
+ u32Error = 1;
+ }
+ } else {
+ u32Error = 1;
+ }
+ return u32Error;
+}
diff --git a/drivers/staging/wilc1000/fifo_buffer.h b/drivers/staging/wilc1000/fifo_buffer.h
new file mode 100644
index 000000000..7b76998e4
--- /dev/null
+++ b/drivers/staging/wilc1000/fifo_buffer.h
@@ -0,0 +1,26 @@
+
+#include <linux/types.h>
+#include <linux/semaphore.h>
+#include "wilc_memory.h"
+#include "wilc_strutils.h"
+
+
+#define tHANDLE void *
+
+typedef struct {
+ u8 *pu8Buffer;
+ u32 u32BufferLength;
+ u32 u32WriteOffset;
+ u32 u32ReadOffset;
+ u32 u32TotalBytes;
+ struct semaphore SemBuffer;
+} tstrFifoHandler;
+
+
+extern u32 FIFO_InitBuffer(tHANDLE *hBuffer,
+ u32 u32BufferLength);
+extern u32 FIFO_DeInit(tHANDLE hFifo);
+extern u32 FIFO_ReadBytes(tHANDLE hFifo, u8 *pu8Buffer,
+ u32 u32BytesToRead, u32 *pu32BytesRead);
+extern u32 FIFO_WriteBytes(tHANDLE hFifo, u8 *pu8Buffer,
+ u32 u32BytesToWrite, bool bForceOverWrite);
diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c
new file mode 100644
index 000000000..6b10bbbe6
--- /dev/null
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -0,0 +1,7963 @@
+#include "host_interface.h"
+#include "coreconfigurator.h"
+
+extern s32 TransportInit(void);
+extern s32 TransportDeInit(void);
+extern u8 connecting;
+
+#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
+extern WILC_TimerHandle hDuringIpTimer;
+#endif
+
+extern bool bEnablePS;
+/*BugID_5137*/
+extern u8 g_wilc_initialized;
+/*****************************************************************************/
+/* Macros */
+/*****************************************************************************/
+
+/* Message types of the Host IF Message Queue*/
+#define HOST_IF_MSG_SCAN 0
+#define HOST_IF_MSG_CONNECT 1
+#define HOST_IF_MSG_RCVD_GNRL_ASYNC_INFO 2
+#define HOST_IF_MSG_KEY 3
+#define HOST_IF_MSG_RCVD_NTWRK_INFO 4
+#define HOST_IF_MSG_RCVD_SCAN_COMPLETE 5
+#define HOST_IF_MSG_CFG_PARAMS 6
+#define HOST_IF_MSG_SET_CHANNEL 7
+#define HOST_IF_MSG_DISCONNECT 8
+#define HOST_IF_MSG_GET_RSSI 9
+#define HOST_IF_MSG_GET_CHNL 10
+#define HOST_IF_MSG_ADD_BEACON 11
+#define HOST_IF_MSG_DEL_BEACON 12
+#define HOST_IF_MSG_ADD_STATION 13
+#define HOST_IF_MSG_DEL_STATION 14
+#define HOST_IF_MSG_EDIT_STATION 15
+#define HOST_IF_MSG_SCAN_TIMER_FIRED 16
+#define HOST_IF_MSG_CONNECT_TIMER_FIRED 17
+#define HOST_IF_MSG_POWER_MGMT 18
+#define HOST_IF_MSG_GET_INACTIVETIME 19
+#define HOST_IF_MSG_REMAIN_ON_CHAN 20
+#define HOST_IF_MSG_REGISTER_FRAME 21
+#define HOST_IF_MSG_LISTEN_TIMER_FIRED 22
+#define HOST_IF_MSG_GET_LINKSPEED 23
+#define HOST_IF_MSG_SET_WFIDRV_HANDLER 24
+#define HOST_IF_MSG_SET_MAC_ADDRESS 25
+#define HOST_IF_MSG_GET_MAC_ADDRESS 26
+#define HOST_IF_MSG_SET_OPERATION_MODE 27
+#define HOST_IF_MSG_SET_IPADDRESS 28
+#define HOST_IF_MSG_GET_IPADDRESS 29
+#define HOST_IF_MSG_FLUSH_CONNECT 30
+#define HOST_IF_MSG_GET_STATISTICS 31
+#define HOST_IF_MSG_SET_MULTICAST_FILTER 32
+#define HOST_IF_MSG_ADD_BA_SESSION 33
+#define HOST_IF_MSG_DEL_BA_SESSION 34
+#define HOST_IF_MSG_Q_IDLE 35
+#define HOST_IF_MSG_DEL_ALL_STA 36
+#define HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS 34
+#define HOST_IF_MSG_EXIT 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 {
+ u8 *pu8key;
+ const u8 *pu8macaddr;
+ u8 *pu8seq;
+ u8 u8seqlen;
+ u8 u8keyidx;
+ u8 u8Keylen;
+ u8 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 {
+ u8 *pu8WepKey;
+ u8 u8WepKeylen;
+ u8 u8Wepidx;
+ u8 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;
+ u8 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 {
+ u8 u8ScanSource;
+ u8 u8ScanType;
+ u8 *pu8ChnlFreqList;
+ u8 u8ChnlListLen;
+ u8 *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 {
+ u8 *pu8bssid;
+ u8 *pu8ssid;
+ size_t ssidLen;
+ u8 *pu8IEs;
+ size_t IEsLen;
+ u8 u8security;
+ tWILCpfConnectResult pfConnectResult;
+ void *pvUserArg;
+ AUTHTYPE_T tenuAuth_type;
+ u8 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 {
+ u8 *pu8Buffer;
+ u32 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 {
+ u8 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 {
+ u8 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
+ * {
+ * u8* pu8Buffer;
+ * u32 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 {
+ u32 u32Interval; /*!< Beacon Interval. Period between two successive beacons on air */
+ u32 u32DTIMPeriod; /*!< DTIM Period. Indicates how many Beacon frames
+ * (including the current frame) appear before the next DTIM */
+ u32 u32HeadLen; /*!< Length of the head buffer in bytes */
+ u8 *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 */
+ u32 u32TailLen; /*!< Length of the tail buffer in bytes */
+ u8 *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 {
+ u8 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 {
+ bool bIsEnabled;
+ u32 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 {
+ u8 au8Sta_DelAllSta[MAX_NUM_STA][ETH_ALEN];
+ u8 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 {
+ u8 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 {
+
+ bool bIsEnabled;
+ u32 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 {
+ u8 *au8IPAddr;
+ u8 idx;
+} tstrHostIFSetIPAddr;
+
+/*!
+ * @struct tstrHostIfStaInactiveT
+ * @brief Get station message body
+ * @details
+ * @todo
+ * @sa
+ * @author Mai Daftedar
+ * @date 16 April 2013
+ * @version 1.0
+ */
+typedef struct {
+ u8 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; /*! <CFG Parameter message Body> */
+ 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
+ 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 {
+ u16 u16MsgId; /*!< Message ID */
+ tuniHostIFmsgBody uniHostIFmsgBody; /*!< Message body */
+ void *drvHandler;
+} tstrHostIFmsg;
+
+#ifdef CONNECT_DIRECT
+typedef struct _tstrWidJoinReqExt {
+ char SSID[MAX_SSID_LEN];
+ u8 u8channel;
+ u8 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;
+ u8 dtim_period;
+ u16 beacon_period;
+ u16 cap_info;
+ u8 au8bssid[6];
+ char ssid[MAX_SSID_LEN];
+ u8 ssidLen;
+ u8 supp_rates[MAX_RATES_SUPPORTED + 1];
+ u8 ht_capable;
+ u8 wmm_cap;
+ u8 uapsd_cap;
+ bool rsn_found;
+ u8 rsn_grp_policy;
+ u8 mode_802_11i;
+ u8 rsn_pcip_policy[3];
+ u8 rsn_auth_policy[3];
+ u8 rsn_cap[2];
+ struct _tstrJoinParam *nextJoinBss;
+ #ifdef WILC_P2P
+ u32 tsf;
+ u8 u8NoaEnbaled;
+ u8 u8OppEnable;
+ u8 u8CtWindow;
+ u8 u8Count;
+ u8 u8Index;
+ u8 au8Duration[4];
+ u8 au8Interval[4];
+ u8 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 {
+ u8 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 = NULL;
+tstrWILC_WFIDrv *gWFiDrvHandle = NULL;
+#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
+bool g_obtainingIP = false;
+#endif
+u8 P2P_LISTEN_STATE;
+static struct task_struct *HostIFthreadHandler;
+static WILC_MsgQueueHandle gMsgQHostIF;
+static struct semaphore hSemHostIFthrdEnd;
+
+struct semaphore hSemDeinitDrvHandle;
+static struct semaphore hWaitResponse;
+struct semaphore hSemHostIntDeinit;
+WILC_TimerHandle g_hPeriodicRSSI;
+
+
+
+u8 gau8MulticastMacAddrList[WILC_MULTICAST_TABLE_SIZE][ETH_ALEN];
+
+#ifndef CONNECT_DIRECT
+static u8 gapu8RcvdSurveyResults[2][MAX_SURVEY_RESULT_FRAG_SIZE];
+#endif
+
+static u8 gapu8RcvdAssocResp[MAX_ASSOC_RESP_FRAME_SIZE];
+
+bool gbScanWhileConnected = false;
+
+static s8 gs8Rssi;
+static s8 gs8lnkspd;
+static u8 gu8Chnl;
+static u8 gs8SetIP[2][4];
+static u8 gs8GetIP[2][4];
+#ifdef WILC_AP_EXTERNAL_MLME
+static u32 gu32InactiveTime;
+static u8 gu8DelBcn;
+#endif
+#ifndef SIMULATION
+static u32 gu32WidConnRstHack;
+#endif
+
+/*BugID_5137*/
+u8 *gu8FlushedJoinReq;
+u8 *gu8FlushedInfoElemAsoc;
+u8 gu8Flushed11iMode;
+u8 gu8FlushedAuthType;
+u32 gu32FlushedJoinReqSize;
+u32 gu32FlushedInfoElemAsocSize;
+u32 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(u32 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 s32 Handle_SetChannel(void *drvHandler, tstrHostIFSetChan *pstrHostIFSetChan)
+{
+
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
+ /*prepare configuration packet*/
+ strWID.u16WIDid = (u16)WID_CURRENT_CHANNEL;
+ strWID.enuWIDtype = WID_CHAR;
+ strWID.ps8WidVal = (char *)&(pstrHostIFSetChan->u8SetChan);
+ strWID.s32ValueSize = sizeof(char);
+
+ PRINT_D(HOSTINF_DBG, "Setting channel\n");
+ /*Sending Cfg*/
+ s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)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 s32 Handle_SetWfiDrvHandler(tstrHostIfSetDrvHandler *pstrHostIfSetDrvHandler)
+{
+
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)((pstrHostIfSetDrvHandler->u32Address));
+
+
+ /*prepare configuration packet*/
+ strWID.u16WIDid = (u16)WID_SET_DRV_HANDLER;
+ strWID.enuWIDtype = WID_INT;
+ strWID.ps8WidVal = (s8 *)&(pstrHostIfSetDrvHandler->u32Address);
+ strWID.s32ValueSize = sizeof(u32);
+
+ /*Sending Cfg*/
+
+ s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
+
+
+ if ((pstrHostIfSetDrvHandler->u32Address) == (u32)NULL) {
+ up(&hSemDeinitDrvHandle);
+ }
+
+
+ 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 s32 Handle_SetOperationMode(void *drvHandler, tstrHostIfSetOperationMode *pstrHostIfSetOperationMode)
+{
+
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
+
+ /*prepare configuration packet*/
+ strWID.u16WIDid = (u16)WID_SET_OPERATION_MODE;
+ strWID.enuWIDtype = WID_INT;
+ strWID.ps8WidVal = (s8 *)&(pstrHostIfSetOperationMode->u32Mode);
+ strWID.s32ValueSize = sizeof(u32);
+
+ /*Sending Cfg*/
+ PRINT_INFO(HOSTINF_DBG, "pstrWFIDrv= %p \n", pstrWFIDrv);
+
+ s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
+
+
+ if ((pstrHostIfSetOperationMode->u32Mode) == (u32)NULL) {
+ up(&hSemDeinitDrvHandle);
+ }
+
+
+ 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, u8* pu8IPAddr
+ * @return Error code.
+ * @author
+ * @date
+ * @version 1.0
+ */
+s32 Handle_set_IPAddress(void *drvHandler, u8 *pu8IPAddr, u8 idx)
+{
+
+ s32 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 = (u16)WID_IP_ADDRESS;
+ strWID.enuWIDtype = WID_STR;
+ strWID.ps8WidVal = (u8 *)pu8IPAddr;
+ strWID.s32ValueSize = IP_ALEN;
+
+ s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)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, u8* pu8IPAddr
+ * @return Error code.
+ * @author
+ * @date
+ * @version 1.0
+ */
+s32 Handle_get_IPAddress(void *drvHandler, u8 *pu8IPAddr, u8 idx)
+{
+
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
+ /*prepare configuration packet*/
+ strWID.u16WIDid = (u16)WID_IP_ADDRESS;
+ strWID.enuWIDtype = WID_STR;
+ strWID.ps8WidVal = (u8 *)WILC_MALLOC(IP_ALEN);
+ strWID.s32ValueSize = IP_ALEN;
+
+ s32Error = SendConfigPkt(GET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
+
+ PRINT_INFO(HOSTINF_DBG, "%d.%d.%d.%d\n", (u8)(strWID.ps8WidVal[0]), (u8)(strWID.ps8WidVal[1]), (u8)(strWID.ps8WidVal[2]), (u8)(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 s32 Handle_SetMacAddress(void *drvHandler, tstrHostIfSetMacAddress *pstrHostIfSetMacAddress)
+{
+
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+ u8 *mac_buf = (u8 *)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 = (u16)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, true, (u32)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 s32 Handle_GetMacAddress(void *drvHandler, tstrHostIfGetMacAddress *pstrHostIfGetMacAddress)
+{
+
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+
+ /*prepare configuration packet*/
+ strWID.u16WIDid = (u16)WID_MAC_ADDR;
+ strWID.enuWIDtype = WID_STR;
+ strWID.ps8WidVal = pstrHostIfGetMacAddress->u8MacAddress;
+ strWID.s32ValueSize = ETH_ALEN;
+
+ /*Sending Cfg*/
+ s32Error = SendConfigPkt(GET_CFG, &strWID, 1, false, (u32)drvHandler);
+ if (s32Error) {
+ PRINT_ER("Failed to get mac address\n");
+ WILC_ERRORREPORT(s32Error, WILC_FAIL);
+ }
+ WILC_CATCH(s32Error)
+ {
+
+ }
+ up(&hWaitResponse);
+
+ 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 s32 Handle_CfgParam(void *drvHandler, tstrHostIFCfgParamAttr *strHostIFCfgParamAttr)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWIDList[32];
+ u8 u8WidCnt = 0;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
+
+ down(&(pstrWFIDrv->gtOsCfgValuesSem));
+
+
+ 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 = (s8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.bss_type;
+ strWIDList[u8WidCnt].enuWIDtype = WID_CHAR;
+ strWIDList[u8WidCnt].s32ValueSize = sizeof(char);
+ pstrWFIDrv->strCfgValues.bss_type = (u8)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 = (s8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.auth_type;
+ strWIDList[u8WidCnt].enuWIDtype = WID_CHAR;
+ strWIDList[u8WidCnt].s32ValueSize = sizeof(char);
+ pstrWFIDrv->strCfgValues.auth_type = (u8)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 = (s8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.auth_timeout;
+ strWIDList[u8WidCnt].enuWIDtype = WID_SHORT;
+ strWIDList[u8WidCnt].s32ValueSize = sizeof(u16);
+ 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 = (s8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.power_mgmt_mode;
+ strWIDList[u8WidCnt].enuWIDtype = WID_CHAR;
+ strWIDList[u8WidCnt].s32ValueSize = sizeof(char);
+ pstrWFIDrv->strCfgValues.power_mgmt_mode = (u8)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 = (s8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.short_retry_limit;
+ strWIDList[u8WidCnt].enuWIDtype = WID_SHORT;
+ strWIDList[u8WidCnt].s32ValueSize = sizeof(u16);
+ 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 = (s8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.long_retry_limit;
+
+ strWIDList[u8WidCnt].enuWIDtype = WID_SHORT;
+ strWIDList[u8WidCnt].s32ValueSize = sizeof(u16);
+ 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 = (s8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.frag_threshold;
+ strWIDList[u8WidCnt].enuWIDtype = WID_SHORT;
+ strWIDList[u8WidCnt].s32ValueSize = sizeof(u16);
+ 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 = (s8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.rts_threshold;
+ strWIDList[u8WidCnt].enuWIDtype = WID_SHORT;
+ strWIDList[u8WidCnt].s32ValueSize = sizeof(u16);
+ 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 = (s8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.preamble_type;
+ strWIDList[u8WidCnt].enuWIDtype = WID_CHAR;
+ strWIDList[u8WidCnt].s32ValueSize = sizeof(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 = (s8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.short_slot_allowed;
+ strWIDList[u8WidCnt].enuWIDtype = WID_CHAR;
+ strWIDList[u8WidCnt].s32ValueSize = sizeof(char);
+ pstrWFIDrv->strCfgValues.short_slot_allowed = (u8)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 = (s8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.txop_prot_disabled;
+ strWIDList[u8WidCnt].enuWIDtype = WID_CHAR;
+ strWIDList[u8WidCnt].s32ValueSize = sizeof(char);
+ pstrWFIDrv->strCfgValues.txop_prot_disabled = (u8)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 = (s8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.beacon_interval;
+ strWIDList[u8WidCnt].enuWIDtype = WID_SHORT;
+ strWIDList[u8WidCnt].s32ValueSize = sizeof(u16);
+ 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 = (s8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.dtim_period;
+ strWIDList[u8WidCnt].enuWIDtype = WID_CHAR;
+ strWIDList[u8WidCnt].s32ValueSize = sizeof(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 = (s8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.site_survey_enabled;
+ strWIDList[u8WidCnt].enuWIDtype = WID_CHAR;
+ strWIDList[u8WidCnt].s32ValueSize = sizeof(char);
+ pstrWFIDrv->strCfgValues.site_survey_enabled = (u8)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 = (s8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.site_survey_scan_time;
+ strWIDList[u8WidCnt].enuWIDtype = WID_SHORT;
+ strWIDList[u8WidCnt].s32ValueSize = sizeof(u16);
+ 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 = (s8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.active_scan_time;
+ strWIDList[u8WidCnt].enuWIDtype = WID_SHORT;
+ strWIDList[u8WidCnt].s32ValueSize = sizeof(u16);
+ 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 = (s8 *)&strHostIFCfgParamAttr->pstrCfgParamVal.passive_scan_time;
+ strWIDList[u8WidCnt].enuWIDtype = WID_SHORT;
+ strWIDList[u8WidCnt].s32ValueSize = sizeof(u16);
+ 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 = (s8 *)&curr_tx_rate;
+ strWIDList[u8WidCnt].enuWIDtype = WID_SHORT;
+ strWIDList[u8WidCnt].s32ValueSize = sizeof(u16);
+ pstrWFIDrv->strCfgValues.curr_tx_rate = (u8)curr_tx_rate;
+ } else {
+ WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
+ }
+ u8WidCnt++;
+ }
+ s32Error = SendConfigPkt(SET_CFG, strWIDList, u8WidCnt, false, (u32)pstrWFIDrv);
+
+ if (s32Error) {
+ PRINT_ER("Error in setting CFG params\n");
+
+ }
+ WILC_CATCH(s32Error)
+ {
+ }
+ up(&(pstrWFIDrv->gtOsCfgValuesSem));
+ 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 s32 Handle_wait_msg_q_empty(void)
+{
+ s32 s32Error = WILC_SUCCESS;
+ g_wilc_initialized = 0;
+ up(&hWaitResponse);
+ 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 s32 Handle_Scan(void *drvHandler, tstrHostIFscanAttr *pstrHostIFscanAttr)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWIDList[5];
+ u32 u32WidsCount = 0;
+ u32 i;
+ u8 *pu8Buffer;
+ u8 valuesize = 0;
+ u8 *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
+ #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 = (u16)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 != 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 = (s32)(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(char);
+ strWIDList[u32WidsCount].ps8WidVal = (s8 *)(&(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(char);
+ strWIDList[u32WidsCount].ps8WidVal = (s8 *)(&(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 = true;
+ } else if (pstrWFIDrv->enuHostIFstate == HOST_IF_IDLE) {
+ gbScanWhileConnected = false;
+ }
+
+ s32Error = SendConfigPkt(SET_CFG, strWIDList, u32WidsCount, false, (u32)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), 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 s32 Handle_ScanDone(void *drvHandler, tenuScanEvent enuEvent)
+{
+ s32 s32Error = WILC_SUCCESS;
+
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
+
+ u8 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 = (u16)WID_ABORT_RUNNING_SCAN;
+ strWID.enuWIDtype = WID_CHAR;
+ strWID.ps8WidVal = (s8 *)&u8abort_running_scan;
+ strWID.s32ValueSize = sizeof(char);
+
+ /*Sending Cfg*/
+ s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)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, 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
+ */
+u8 u8ConnectedSSID[6] = {0};
+static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFconnectAttr)
+{
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *) drvHandler;
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWIDList[8];
+ u32 u32WidsCount = 0, dummyval = 0;
+ /* char passphrase[] = "12345678"; */
+ #ifndef CONNECT_DIRECT
+ s32 s32Err = WILC_SUCCESS;
+ u32 i;
+ u8 u8bssDscListIndex;
+ wid_site_survey_reslts_s *pstrSurveyResults = NULL;
+ #else
+ u8 *pu8CurrByte = 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 = (u8 *)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 = (u8 *)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 = (u8 *)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 = (u16)WID_11I_MODE;
+ strWIDList[u32WidsCount].enuWIDtype = WID_CHAR;
+ strWIDList[u32WidsCount].s32ValueSize = sizeof(char);
+ strWIDList[u32WidsCount].ps8WidVal = (s8 *)(&(pstrWFIDrv->strWILC_UsrConnReq.u8security));
+ u32WidsCount++;
+
+ PRINT_INFO(HOSTINF_DBG, "Encrypt Mode = %x\n", pstrWFIDrv->strWILC_UsrConnReq.u8security);
+
+ strWIDList[u32WidsCount].u16WIDid = (u16)WID_AUTH_TYPE;
+ strWIDList[u32WidsCount].enuWIDtype = WID_CHAR;
+ strWIDList[u32WidsCount].s32ValueSize = sizeof(char);
+ strWIDList[u32WidsCount].ps8WidVal = (s8 *)(&pstrWFIDrv->strWILC_UsrConnReq.tenuAuth_type);
+ u32WidsCount++;
+
+ PRINT_INFO(HOSTINF_DBG, "Authentication Type = %x\n", pstrWFIDrv->strWILC_UsrConnReq.tenuAuth_type);
+ /*
+ * strWIDList[u32WidsCount].u16WIDid = (u16)WID_11I_PSK;
+ * strWIDList[u32WidsCount].enuWIDtype = WID_STR;
+ * strWIDList[u32WidsCount].s32ValueSize = sizeof(passphrase);
+ * strWIDList[u32WidsCount].ps8WidVal = (s8*)(passphrase);
+ * u32WidsCount++;
+ */
+
+ strWIDList[u32WidsCount].u16WIDid = (u16)WID_JOIN_REQ;
+ strWIDList[u32WidsCount].enuWIDtype = WID_CHAR;
+ strWIDList[u32WidsCount].s32ValueSize = sizeof(char);
+ strWIDList[u32WidsCount].ps8WidVal = (s8 *)&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, false, (u32)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 (pstrHostIFconnectAttr->pu8bssid != NULL) {
+ pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = (u8 *)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 = (u8 *)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 = (u8 *)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(u32);
+ strWIDList[u32WidsCount].ps8WidVal = (s8 *)(&(dummyval));
+ u32WidsCount++;
+
+ strWIDList[u32WidsCount].u16WIDid = WID_RECEIVED_FRAGMENT_COUNT;
+ strWIDList[u32WidsCount].enuWIDtype = WID_INT;
+ strWIDList[u32WidsCount].s32ValueSize = sizeof(u32);
+ strWIDList[u32WidsCount].ps8WidVal = (s8 *)(&(dummyval));
+ u32WidsCount++;
+
+ strWIDList[u32WidsCount].u16WIDid = WID_FAILED_COUNT;
+ strWIDList[u32WidsCount].enuWIDtype = WID_INT;
+ strWIDList[u32WidsCount].s32ValueSize = sizeof(u32);
+ strWIDList[u32WidsCount].ps8WidVal = (s8 *)(&(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 = (u16)WID_11I_MODE;
+ strWIDList[u32WidsCount].enuWIDtype = WID_CHAR;
+ strWIDList[u32WidsCount].s32ValueSize = sizeof(char);
+ strWIDList[u32WidsCount].ps8WidVal = (s8 *)(&(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 = (u16)WID_AUTH_TYPE;
+ strWIDList[u32WidsCount].enuWIDtype = WID_CHAR;
+ strWIDList[u32WidsCount].s32ValueSize = sizeof(char);
+ strWIDList[u32WidsCount].ps8WidVal = (s8 *)(&pstrWFIDrv->strWILC_UsrConnReq.tenuAuth_type);
+ u32WidsCount++;
+
+ /*BugID_5137*/
+ if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7))
+ gu8FlushedAuthType = (u8)pstrWFIDrv->strWILC_UsrConnReq.tenuAuth_type;
+
+ PRINT_INFO(HOSTINF_DBG, "Authentication Type = %x\n", pstrWFIDrv->strWILC_UsrConnReq.tenuAuth_type);
+ /*
+ * strWIDList[u32WidsCount].u16WIDid = (u16)WID_11I_PSK;
+ * strWIDList[u32WidsCount].enuWIDtype = WID_STR;
+ * strWIDList[u32WidsCount].s32ValueSize = sizeof(passphrase);
+ * strWIDList[u32WidsCount].ps8WidVal = (s8*)(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 = (u16)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 == 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 = (u16)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 == 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 = (u32)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, false, (u32)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), 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 = (u8 *)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 != 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 s32 Handle_FlushConnect(void *drvHandler)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWIDList[5];
+ u32 u32WidsCount = 0;
+ u8 *pu8CurrByte = 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 = (u16)WID_11I_MODE;
+ strWIDList[u32WidsCount].enuWIDtype = WID_CHAR;
+ strWIDList[u32WidsCount].s32ValueSize = sizeof(char);
+ strWIDList[u32WidsCount].ps8WidVal = (s8 *)(&(gu8Flushed11iMode));
+ u32WidsCount++;
+
+
+
+ strWIDList[u32WidsCount].u16WIDid = (u16)WID_AUTH_TYPE;
+ strWIDList[u32WidsCount].enuWIDtype = WID_CHAR;
+ strWIDList[u32WidsCount].s32ValueSize = sizeof(char);
+ strWIDList[u32WidsCount].ps8WidVal = (s8 *)(&gu8FlushedAuthType);
+ u32WidsCount++;
+
+
+ #ifdef WILC_PARSE_SCAN_IN_HOST
+ strWIDList[u32WidsCount].u16WIDid = (u16)WID_JOIN_REQ_EXTENDED;
+ strWIDList[u32WidsCount].enuWIDtype = WID_STR;
+ strWIDList[u32WidsCount].s32ValueSize = gu32FlushedJoinReqSize;
+ strWIDList[u32WidsCount].ps8WidVal = (s8 *)gu8FlushedJoinReq;
+ pu8CurrByte = strWIDList[u32WidsCount].ps8WidVal;
+
+ pu8CurrByte += FLUSHED_BYTE_POS;
+ *(pu8CurrByte) = FLUSHED_JOIN_REQ;
+
+ u32WidsCount++;
+
+ #endif
+
+ s32Error = SendConfigPkt(SET_CFG, strWIDList, u32WidsCount, 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 s32 Handle_ConnectTimeout(void *drvHandler)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrConnectInfo strConnectInfo;
+ tstrWID strWID;
+ u16 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 = 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 = (u8 *)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 = (u16)WID_DISCONNECT;
+ strWID.enuWIDtype = WID_CHAR;
+ strWID.ps8WidVal = (s8 *)&u16DummyReasonCode;
+ strWID.s32ValueSize = sizeof(char);
+
+ PRINT_D(HOSTINF_DBG, "Sending disconnect request\n");
+
+ s32Error = SendConfigPkt(SET_CFG, &strWID, 1, false, (u32)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 == (u32)drvHandler) {
+ WILC_FREE(gu8FlushedJoinReq);
+ gu8FlushedJoinReq = NULL;
+ }
+ if (gu8FlushedInfoElemAsoc != NULL && gu8FlushedJoinReqDrvHandler == (u32)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 s32 Handle_RcvdNtwrkInfo(void *drvHandler, tstrRcvdNetworkInfo *pstrRcvdNetworkInfo)
+{
+ u32 i;
+ bool bNewNtwrkFound;
+
+
+
+ s32 s32Error = WILC_SUCCESS;
+ tstrNetworkInfo *pstrNetworkInfo = NULL;
+ void *pJoinParams = NULL;
+
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
+
+
+ bNewNtwrkFound = 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 == 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 = false;
+ break;
+ }
+ }
+ }
+ }
+
+ if (bNewNtwrkFound == 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 = 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 = 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 != NULL) {
+ DeallocateNetworkInfo(pstrNetworkInfo);
+ pstrNetworkInfo = 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 s32 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 */
+ s32 s32Error = WILC_SUCCESS;
+ u8 u8MsgType = 0;
+ u8 u8MsgID = 0;
+ u16 u16MsgLen = 0;
+ u16 u16WidID = (u16)WID_NIL;
+ u8 u8WidLen = 0;
+ u8 u8MacStatus;
+ u8 u8MacStatusReasonCode;
+ u8 u8MacStatusAdditionalInfo;
+ tstrConnectInfo strConnectInfo;
+ tstrDisconnectNotifInfo strDisconnectNotifInfo;
+ s32 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 == 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 */
+ u32 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 = (u8 *)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 = (u8 *)WILC_MALLOC(pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen);
+ WILC_memcpy(strConnectInfo.pu8ReqIEs,
+ pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs,
+ pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen);
+ }
+
+
+ WILC_TimerStop(&(pstrWFIDrv->hConnectTimer), 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 = true;
+ WILC_TimerStart(&hDuringIpTimer, 10000, NULL, 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 = 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), 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 = 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 == (u32)drvHandler) {
+ WILC_FREE(gu8FlushedJoinReq);
+ gu8FlushedJoinReq = NULL;
+ }
+ if (gu8FlushedInfoElemAsoc != NULL && gu8FlushedJoinReqDrvHandler == (u32)drvHandler) {
+ WILC_FREE(gu8FlushedInfoElemAsoc);
+ gu8FlushedInfoElemAsoc = NULL;
+ }
+
+ pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE;
+ gbScanWhileConnected = 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), 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)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ #ifdef WILC_AP_EXTERNAL_MLME
+ tstrWID strWIDList[5];
+ #endif
+ u8 i;
+ u8 *pu8keybuf;
+ s8 s8idxarray[1];
+ s8 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 = (u16)WID_11I_MODE;
+ strWIDList[0].enuWIDtype = WID_CHAR;
+ strWIDList[0].s32ValueSize = sizeof(char);
+ strWIDList[0].ps8WidVal = (s8 *)(&(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8mode));
+
+ strWIDList[1].u16WIDid = WID_AUTH_TYPE;
+ strWIDList[1].enuWIDtype = WID_CHAR;
+ strWIDList[1].s32ValueSize = sizeof(char);
+ strWIDList[1].ps8WidVal = (s8 *)(&(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.tenuAuth_type));
+
+ strWIDList[2].u16WIDid = (u16)WID_KEY_ID;
+ strWIDList[2].enuWIDtype = WID_CHAR;
+
+ strWIDList[2].ps8WidVal = (s8 *)(&(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8Wepidx));
+ strWIDList[2].s32ValueSize = sizeof(char);
+
+
+ pu8keybuf = (u8 *)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 = (u16)WID_WEP_KEY_VALUE;
+ strWIDList[3].enuWIDtype = WID_STR;
+ strWIDList[3].s32ValueSize = pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen;
+ strWIDList[3].ps8WidVal = (s8 *)pu8keybuf;
+
+
+ s32Error = SendConfigPkt(SET_CFG, strWIDList, 4, true, (u32)pstrWFIDrv);
+ WILC_FREE(pu8keybuf);
+
+
+ }
+#endif
+
+ if (pstrHostIFkeyAttr->u8KeyAction & ADDKEY) {
+ PRINT_D(HOSTINF_DBG, "Handling WEP key\n");
+ pu8keybuf = (u8 *)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 = (u16)WID_ADD_WEP_KEY;
+ strWID.enuWIDtype = WID_STR;
+ strWID.ps8WidVal = (s8 *)pu8keybuf;
+ strWID.s32ValueSize = pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen + 2;
+
+ s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
+ WILC_FREE(pu8keybuf);
+ } else if (pstrHostIFkeyAttr->u8KeyAction & REMOVEKEY) {
+
+ PRINT_D(HOSTINF_DBG, "Removing key\n");
+ strWID.u16WIDid = (u16)WID_REMOVE_WEP_KEY;
+ strWID.enuWIDtype = WID_STR;
+
+ s8idxarray[0] = (s8)pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8Wepidx;
+ strWID.ps8WidVal = s8idxarray;
+ strWID.s32ValueSize = 1;
+
+ s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
+ } else {
+ strWID.u16WIDid = (u16)WID_KEY_ID;
+ strWID.enuWIDtype = WID_CHAR;
+ strWID.ps8WidVal = (s8 *)(&(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8Wepidx));
+ strWID.s32ValueSize = sizeof(char);
+
+ PRINT_D(HOSTINF_DBG, "Setting default key index\n");
+
+ s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
+ }
+ up(&(pstrWFIDrv->hSemTestKeyBlock));
+ break;
+
+ case WPARxGtk:
+ #ifdef WILC_AP_EXTERNAL_MLME
+ if (pstrHostIFkeyAttr->u8KeyAction & ADDKEY_AP) {
+ pu8keybuf = (u8 *)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 = (u16)WID_11I_MODE;
+ strWIDList[0].enuWIDtype = WID_CHAR;
+ strWIDList[0].s32ValueSize = sizeof(char);
+ strWIDList[0].ps8WidVal = (s8 *)(&(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Ciphermode));
+
+ strWIDList[1].u16WIDid = (u16)WID_ADD_RX_GTK;
+ strWIDList[1].enuWIDtype = WID_STR;
+ strWIDList[1].ps8WidVal = (s8 *)pu8keybuf;
+ strWIDList[1].s32ValueSize = RX_MIC_KEY_MSG_LEN;
+
+ s32Error = SendConfigPkt(SET_CFG, strWIDList, 2, true, (u32)pstrWFIDrv);
+
+ WILC_FREE(pu8keybuf);
+
+ /* ////////////////////////// */
+ up(&(pstrWFIDrv->hSemTestKeyBlock));
+ /* ///////////////////////// */
+ }
+
+ #endif
+ if (pstrHostIFkeyAttr->u8KeyAction & ADDKEY) {
+ PRINT_D(HOSTINF_DBG, "Handling group key(Rx) function\n");
+
+ pu8keybuf = (u8 *)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 = (u16)WID_ADD_RX_GTK;
+ strWID.enuWIDtype = WID_STR;
+ strWID.ps8WidVal = (s8 *)pu8keybuf;
+ strWID.s32ValueSize = RX_MIC_KEY_MSG_LEN;
+
+ s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
+
+ WILC_FREE(pu8keybuf);
+
+ /* ////////////////////////// */
+ up(&(pstrWFIDrv->hSemTestKeyBlock));
+ /* ///////////////////////// */
+ }
+_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 = (u8 *)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 = (u16)WID_11I_MODE;
+ strWIDList[0].enuWIDtype = WID_CHAR;
+ strWIDList[0].s32ValueSize = sizeof(char);
+ strWIDList[0].ps8WidVal = (s8 *)(&(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Ciphermode));
+
+ strWIDList[1].u16WIDid = (u16)WID_ADD_PTK;
+ strWIDList[1].enuWIDtype = WID_STR;
+ strWIDList[1].ps8WidVal = (s8 *)pu8keybuf;
+ strWIDList[1].s32ValueSize = PTK_KEY_MSG_LEN + 1;
+
+ s32Error = SendConfigPkt(SET_CFG, strWIDList, 2, true, (u32)pstrWFIDrv);
+ WILC_FREE(pu8keybuf);
+
+ /* ////////////////////////// */
+ up(&(pstrWFIDrv->hSemTestKeyBlock));
+ /* ///////////////////////// */
+ }
+ #endif
+ if (pstrHostIFkeyAttr->u8KeyAction & ADDKEY) {
+
+
+ pu8keybuf = (u8 *)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 = (u16)WID_ADD_PTK;
+ strWID.enuWIDtype = WID_STR;
+ strWID.ps8WidVal = (s8 *)pu8keybuf;
+ strWID.s32ValueSize = PTK_KEY_MSG_LEN;
+
+ s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
+ WILC_FREE(pu8keybuf);
+
+ /* ////////////////////////// */
+ up(&(pstrWFIDrv->hSemTestKeyBlock));
+ /* ///////////////////////// */
+ }
+
+_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 = (u8 *)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 = (u16)WID_PMKID_INFO;
+ strWID.enuWIDtype = WID_STR;
+ strWID.ps8WidVal = (s8 *)pu8keybuf;
+ strWID.s32ValueSize = (pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.numpmkid * PMKSA_KEY_LEN) + 1;
+
+ s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)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;
+
+ s32 s32Error = WILC_SUCCESS;
+ u16 u16DummyReasonCode = 0;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
+
+ strWID.u16WIDid = (u16)WID_DISCONNECT;
+ strWID.enuWIDtype = WID_CHAR;
+ strWID.ps8WidVal = (s8 *)&u16DummyReasonCode;
+ strWID.s32ValueSize = sizeof(char);
+
+
+
+ PRINT_D(HOSTINF_DBG, "Sending disconnect request\n");
+
+ #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
+
+ g_obtainingIP = false;
+ host_int_set_power_mgmt((WILC_WFIDrvHandle)pstrWFIDrv, 0, 0);
+ #endif
+
+ WILC_memset(u8ConnectedSSID, 0, ETH_ALEN);
+
+ s32Error = SendConfigPkt(SET_CFG, &strWID, 1, false, (u32)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), NULL);
+ pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult(SCAN_EVENT_ABORTED, NULL,
+ pstrWFIDrv->strWILC_UsrScanReq.u32UserScanPvoid, NULL);
+
+ pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult = 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), 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 = 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 == (u32)drvHandler) {
+ WILC_FREE(gu8FlushedJoinReq);
+ gu8FlushedJoinReq = NULL;
+ }
+ if (gu8FlushedInfoElemAsoc != NULL && gu8FlushedJoinReqDrvHandler == (u32)drvHandler) {
+ WILC_FREE(gu8FlushedInfoElemAsoc);
+ gu8FlushedInfoElemAsoc = NULL;
+ }
+
+ }
+
+ WILC_CATCH(s32Error)
+ {
+
+ }
+
+ /* ////////////////////////// */
+ up(&(pstrWFIDrv->hSemTestDisconnectBlock));
+ /* ///////////////////////// */
+
+}
+
+
+void resolve_disconnect_aberration(void *drvHandler)
+{
+ tstrWILC_WFIDrv *pstrWFIDrv;
+
+ pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+ if (pstrWFIDrv == 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 s32 Switch_Log_Terminal(void *drvHandler)
+{
+
+
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ static char dummy = 9;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
+ strWID.u16WIDid = (u16)WID_LOGTerminal_Switch;
+ strWID.enuWIDtype = WID_CHAR;
+ strWID.ps8WidVal = &dummy;
+ strWID.s32ValueSize = sizeof(char);
+
+ s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)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 s32 Handle_GetChnl(void *drvHandler)
+{
+
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+ strWID.u16WIDid = (u16)WID_CURRENT_CHANNEL;
+ strWID.enuWIDtype = WID_CHAR;
+ strWID.ps8WidVal = (s8 *)&gu8Chnl;
+ strWID.s32ValueSize = sizeof(char);
+
+ PRINT_D(HOSTINF_DBG, "Getting channel value\n");
+
+ s32Error = SendConfigPkt(GET_CFG, &strWID, 1, true, (u32)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)
+ {
+
+ }
+ up(&(pstrWFIDrv->hSemGetCHNL));
+
+ 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)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
+ strWID.u16WIDid = (u16)WID_RSSI;
+ strWID.enuWIDtype = WID_CHAR;
+ strWID.ps8WidVal = &gs8Rssi;
+ strWID.s32ValueSize = sizeof(char);
+
+ /*Sending Cfg*/
+ PRINT_D(HOSTINF_DBG, "Getting RSSI value\n");
+
+ s32Error = SendConfigPkt(GET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
+ if (s32Error) {
+ PRINT_ER("Failed to get RSSI value\n");
+ WILC_ERRORREPORT(s32Error, WILC_FAIL);
+ }
+
+ WILC_CATCH(s32Error)
+ {
+
+ }
+ up(&(pstrWFIDrv->hSemGetRSSI));
+
+
+}
+
+
+static void Handle_GetLinkspeed(void *drvHandler)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
+ gs8lnkspd = 0;
+
+ strWID.u16WIDid = (u16)WID_LINKSPEED;
+ strWID.enuWIDtype = WID_CHAR;
+ strWID.ps8WidVal = &gs8lnkspd;
+ strWID.s32ValueSize = sizeof(char);
+ /*Sending Cfg*/
+ PRINT_D(HOSTINF_DBG, "Getting LINKSPEED value\n");
+
+ s32Error = SendConfigPkt(GET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
+ if (s32Error) {
+ PRINT_ER("Failed to get LINKSPEED value\n");
+ WILC_ERRORREPORT(s32Error, WILC_FAIL);
+ }
+
+ WILC_CATCH(s32Error)
+ {
+
+ }
+ up(&(pstrWFIDrv->hSemGetLINKSPEED));
+
+
+}
+
+s32 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(char);
+ strWIDList[u32WidsCount].ps8WidVal = (s8 *)(&(pstrStatistics->u8LinkSpeed));
+ u32WidsCount++;
+
+ strWIDList[u32WidsCount].u16WIDid = WID_RSSI;
+ strWIDList[u32WidsCount].enuWIDtype = WID_CHAR;
+ strWIDList[u32WidsCount].s32ValueSize = sizeof(char);
+ strWIDList[u32WidsCount].ps8WidVal = (s8 *)(&(pstrStatistics->s8RSSI));
+ u32WidsCount++;
+
+ strWIDList[u32WidsCount].u16WIDid = WID_SUCCESS_FRAME_COUNT;
+ strWIDList[u32WidsCount].enuWIDtype = WID_INT;
+ strWIDList[u32WidsCount].s32ValueSize = sizeof(u32);
+ strWIDList[u32WidsCount].ps8WidVal = (s8 *)(&(pstrStatistics->u32TxCount));
+ u32WidsCount++;
+
+ strWIDList[u32WidsCount].u16WIDid = WID_RECEIVED_FRAGMENT_COUNT;
+ strWIDList[u32WidsCount].enuWIDtype = WID_INT;
+ strWIDList[u32WidsCount].s32ValueSize = sizeof(u32);
+ strWIDList[u32WidsCount].ps8WidVal = (s8 *)(&(pstrStatistics->u32RxCount));
+ u32WidsCount++;
+
+ strWIDList[u32WidsCount].u16WIDid = WID_FAILED_COUNT;
+ strWIDList[u32WidsCount].enuWIDtype = WID_INT;
+ strWIDList[u32WidsCount].s32ValueSize = sizeof(u32);
+ strWIDList[u32WidsCount].ps8WidVal = (s8 *)(&(pstrStatistics->u32TxFailureCount));
+ u32WidsCount++;
+
+ s32Error = SendConfigPkt(GET_CFG, strWIDList, u32WidsCount, false, (u32)drvHandler);
+
+ if (s32Error) {
+ PRINT_ER("Failed to send scan paramters config packet\n");
+ /* WILC_ERRORREPORT(s32Error, s32Error); */
+ }
+ up(&hWaitResponse);
+ 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 s32 Handle_Get_InActiveTime(void *drvHandler, tstrHostIfStaInactiveT *strHostIfStaInactiveT)
+{
+
+ s32 s32Error = WILC_SUCCESS;
+ u8 *stamac;
+ tstrWID strWID;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
+
+ strWID.u16WIDid = (u16)WID_SET_STA_MAC_INACTIVE_TIME;
+ strWID.enuWIDtype = WID_STR;
+ strWID.s32ValueSize = ETH_ALEN;
+ strWID.ps8WidVal = (u8 *)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, true, (u32)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 = (u16)WID_GET_INACTIVE_TIME;
+ strWID.enuWIDtype = WID_INT;
+ strWID.ps8WidVal = (s8 *)&gu32InactiveTime;
+ strWID.s32ValueSize = sizeof(u32);
+
+
+ s32Error = SendConfigPkt(GET_CFG, &strWID, 1, true, (u32)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);
+
+ up(&(pstrWFIDrv->hSemInactiveTime));
+ 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)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ u8 *pu8CurrByte;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+ PRINT_D(HOSTINF_DBG, "Adding BEACON\n");
+
+ strWID.u16WIDid = (u16)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, false, (u32)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)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ u8 *pu8CurrByte;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+ strWID.u16WIDid = (u16)WID_DEL_BEACON;
+ strWID.enuWIDtype = WID_CHAR;
+ strWID.s32ValueSize = sizeof(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, false, (u32)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] u8* pu8Buffer, tstrWILC_AddStaParam* pstrStationParam
+ * @return NONE
+ * @author
+ * @date
+ * @version 1.0
+ */
+static u32 WILC_HostIf_PackStaParam(u8 *pu8Buffer, tstrWILC_AddStaParam *pstrStationParam)
+{
+ u8 *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)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ u8 *pu8CurrByte;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+ PRINT_D(HOSTINF_DBG, "Handling add station\n");
+ strWID.u16WIDid = (u16)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, false, (u32)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)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ u8 *pu8CurrByte;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+ u8 i;
+ u8 au8Zero_Buff[6] = {0};
+ strWID.u16WIDid = (u16)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, true, (u32)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);
+
+ up(&hWaitResponse);
+}
+
+
+/**
+ * @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)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ u8 *pu8CurrByte;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
+ strWID.u16WIDid = (u16)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, false, (u32)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)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ u8 *pu8CurrByte;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
+ strWID.u16WIDid = (u16)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, false, (u32)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)
+{
+ s32 s32Error = WILC_SUCCESS;
+ u8 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 = true;
+ strWID.u16WIDid = (u16)WID_REMAIN_ON_CHAN;
+ strWID.enuWIDtype = WID_STR;
+ strWID.s32ValueSize = 2;
+ strWID.ps8WidVal = (s8 *)WILC_MALLOC(strWID.s32ValueSize);
+
+ if (strWID.ps8WidVal == NULL) {
+ WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
+ }
+
+ strWID.ps8WidVal[0] = u8remain_on_chan_flag;
+ strWID.ps8WidVal[1] = (s8)pstrHostIfRemainOnChan->u16Channel;
+
+ /*Sending Cfg*/
+ s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)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, 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)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ u8 *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 = (u16)WID_REGISTER_FRAME;
+ strWID.enuWIDtype = WID_STR;
+ strWID.ps8WidVal = WILC_MALLOC(sizeof(u16) + 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(u16));
+
+
+ strWID.s32ValueSize = sizeof(u16) + 2;
+
+
+ /*Sending Cfg*/
+ s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)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 u32 Handle_ListenStateExpired(void *drvHandler, tstrHostIfRemainOnChan *pstrHostIfRemainOnChan)
+{
+ u8 u8remain_on_chan_flag;
+ tstrWID strWID;
+ s32 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 = false;
+ strWID.u16WIDid = (u16)WID_REMAIN_ON_CHAN;
+ strWID.enuWIDtype = WID_STR;
+ strWID.s32ValueSize = 2;
+ strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize);
+
+ if (strWID.ps8WidVal == 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, true, (u32)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)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrHostIFmsg strHostIFmsg;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)pvArg;
+ /*Stopping remain-on-channel timer*/
+ WILC_TimerStop(&(pstrWFIDrv->hRemainOnChannel), 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), 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)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ s8 s8PowerMode;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+ strWID.u16WIDid = (u16)WID_POWER_MANAGEMENT;
+
+ if (strPowerMgmtParam->bIsEnabled == 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(char);
+
+ PRINT_D(HOSTINF_DBG, "Handling Power Management\n");
+
+ /*Sending Cfg*/
+ s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)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)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ u8 *pu8CurrByte;
+
+ PRINT_D(HOSTINF_DBG, "Setup Multicast Filter\n");
+
+ strWID.u16WIDid = (u16)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, false, (u32)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 s32 Handle_AddBASession(void *drvHandler, tstrHostIfBASessionInfo *strHostIfBASessionInfo)
+{
+ s32 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 = (u16)WID_11E_P_ACTION_REQ;
+ strWID.enuWIDtype = WID_STR;
+ strWID.ps8WidVal = (u8 *)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, true, (u32)pstrWFIDrv);
+ if (s32Error)
+ PRINT_D(HOSTINF_DBG, "Couldn't open BA Session\n");
+
+
+ strWID.u16WIDid = (u16)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, true, (u32)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 s32 Handle_DelBASession(void *drvHandler, tstrHostIfBASessionInfo *strHostIfBASessionInfo)
+{
+ s32 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 = (u16)WID_11E_P_ACTION_REQ;
+ strWID.enuWIDtype = WID_STR;
+ strWID.ps8WidVal = (u8 *)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, true, (u32)pstrWFIDrv);
+ if (s32Error)
+ PRINT_D(HOSTINF_DBG, "Couldn't delete BA Session\n");
+
+
+ strWID.u16WIDid = (u16)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, true, (u32)pstrWFIDrv);
+
+ if (strWID.ps8WidVal != NULL)
+ WILC_FREE(strWID.ps8WidVal);
+
+ /*BugID_5222*/
+ up(&hWaitResponse);
+
+ 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 s32 Handle_DelAllRxBASessions(void *drvHandler, tstrHostIfBASessionInfo *strHostIfBASessionInfo)
+{
+ s32 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 = (u16)WID_DEL_ALL_RX_BA;
+ strWID.enuWIDtype = WID_STR;
+ strWID.ps8WidVal = (u8 *)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, true, (u32)pstrWFIDrv);
+ if (s32Error)
+ PRINT_D(HOSTINF_DBG, "Couldn't delete BA Session\n");
+
+
+ if (strWID.ps8WidVal != NULL)
+ WILC_FREE(strWID.ps8WidVal);
+
+ /*BugID_5222*/
+ up(&hWaitResponse);
+
+ return s32Error;
+
+}
+
+/**
+ * @brief hostIFthread
+ * @details Main thread to handle message queue requests
+ * @param[in] void* pvArg
+ * @return NONE
+ * @author
+ * @date
+ * @version 1.0
+ */
+static int hostIFthread(void *pvArg)
+{
+ u32 u32Ret;
+ tstrHostIFmsg strHostIFmsg;
+ tstrWILC_WFIDrv *pstrWFIDrv;
+
+ WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+
+ while (1) {
+ WILC_MsgQueueRecv(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), &u32Ret, 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), 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), 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), 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");
+ up(&hSemHostIFthrdEnd);
+ return 0;
+}
+
+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), 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), 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! */
+s32 host_int_remove_key(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8StaAddress)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */
+
+ strWID.u16WIDid = (u16)WID_REMOVE_KEY;
+ strWID.enuWIDtype = WID_STR;
+ strWID.ps8WidVal = (s8 *)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
+ */
+s32 host_int_remove_wep_key(WILC_WFIDrvHandle hWFIDrv, u8 u8keyIdx)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+
+
+ if (pstrWFIDrv == 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), NULL);
+ if (s32Error)
+ PRINT_ER("Error in sending message queue : Request to remove WEP key \n");
+ down(&(pstrWFIDrv->hSemTestKeyBlock));
+
+ 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
+ */
+s32 host_int_set_WEPDefaultKeyID(WILC_WFIDrvHandle hWFIDrv, u8 u8Index)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+
+
+ if (pstrWFIDrv == 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), NULL);
+ if (s32Error)
+ PRINT_ER("Error in sending message queue : Default key index\n");
+ down(&(pstrWFIDrv->hSemTestKeyBlock));
+
+ 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
+ */
+s32 host_int_add_wep_key_bss_sta(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx)
+{
+
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+
+ if (pstrWFIDrv == 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 = (u8 *)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), NULL);
+ if (s32Error)
+ PRINT_ER("Error in sending message queue :WEP Key\n");
+ down(&(pstrWFIDrv->hSemTestKeyBlock));
+
+ 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
+ */
+s32 host_int_add_wep_key_bss_ap(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx, u8 u8mode, AUTHTYPE_T tenuAuth_type)
+{
+
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+ u8 i;
+
+ if (pstrWFIDrv == 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 = (u8 *)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), NULL);
+
+ if (s32Error)
+ PRINT_ER("Error in sending message queue :WEP Key\n");
+ down(&(pstrWFIDrv->hSemTestKeyBlock));
+
+ 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
+ */
+s32 host_int_add_ptk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8Ptk, u8 u8PtkKeylen,
+ const u8 *mac_addr, const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode, u8 u8Ciphermode, u8 u8Idx)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+ u8 u8KeyLen = u8PtkKeylen;
+ u32 i;
+ if (pstrWFIDrv == 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 = (u8 *)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), NULL);
+
+ if (s32Error)
+ PRINT_ER("Error in sending message queue: PTK Key\n");
+
+ /* ////////////// */
+ down(&(pstrWFIDrv->hSemTestKeyBlock));
+ /* 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
+ */
+s32 host_int_add_rx_gtk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8RxGtk, u8 u8GtkKeylen,
+ u8 u8KeyIdx, u32 u32KeyRSClen, const u8 *KeyRSC,
+ const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode, u8 u8Ciphermode)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+ u8 u8KeyLen = u8GtkKeylen;
+
+ if (pstrWFIDrv == 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 = (u8 *)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 = (u8 *)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), NULL);
+ if (s32Error)
+ PRINT_ER("Error in sending message queue: RX GTK\n");
+ /* ////////////// */
+ down(&(pstrWFIDrv->hSemTestKeyBlock));
+ /* WILC_Sleep(100); */
+ /* /////// */
+
+ WILC_CATCH(s32Error)
+ {
+
+ }
+ return s32Error;
+}
+
+/**
+ * @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
+ */
+s32 host_int_set_pmkid_info(WILC_WFIDrvHandle hWFIDrv, tstrHostIFpmkidAttr *pu8PmkidInfoArray)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+ u32 i;
+
+
+ if (pstrWFIDrv == 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), 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
+ */
+s32 host_int_get_pmkid_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8PmkidInfoArray,
+ u32 u32PmkidInfoLen)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */
+
+ strWID.u16WIDid = (u16)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
+ */
+s32 host_int_set_RSNAConfigPSKPassPhrase(WILC_WFIDrvHandle hWFIDrv, u8 *pu8PassPhrase,
+ u8 u8Psklength)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */
+
+ /* u8 u8Psklength = WILC_strlen(pu8PassPhrase); */
+ /*validating psk length*/
+ if ((u8Psklength > 7) && (u8Psklength < 65)) {
+ strWID.u16WIDid = (u16)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
+ */
+s32 host_int_get_MacAddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8MacAddress)
+{
+ s32 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), NULL);
+ if (s32Error) {
+ PRINT_ER("Failed to send get mac address\n");
+ return WILC_FAIL;
+ }
+
+ down(&hWaitResponse);
+ 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
+ */
+s32 host_int_set_MacAddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8MacAddress)
+{
+ s32 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), 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
+ */
+s32 host_int_get_RSNAConfigPSKPassPhrase(WILC_WFIDrvHandle hWFIDrv,
+ u8 *pu8PassPhrase, u8 u8Psklength)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */
+
+ strWID.u16WIDid = (u16)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
+s32 host_int_get_site_survey_results(WILC_WFIDrvHandle hWFIDrv,
+ u8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZE],
+ u32 u32MaxSiteSrvyFragLen)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID astrWIDList[2];
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+
+ astrWIDList[0].u16WIDid = (u16)WID_SITE_SURVEY_RESULTS;
+ astrWIDList[0].enuWIDtype = WID_STR;
+ astrWIDList[0].ps8WidVal = ppu8RcvdSiteSurveyResults[0];
+ astrWIDList[0].s32ValueSize = u32MaxSiteSrvyFragLen;
+
+ astrWIDList[1].u16WIDid = (u16)WID_SITE_SURVEY_RESULTS;
+ astrWIDList[1].enuWIDtype = WID_STR;
+ astrWIDList[1].ps8WidVal = ppu8RcvdSiteSurveyResults[1];
+ astrWIDList[1].s32ValueSize = u32MaxSiteSrvyFragLen;
+
+ s32Error = SendConfigPkt(GET_CFG, astrWIDList, 2, true, (u32)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
+ */
+s32 host_int_set_start_scan_req(WILC_WFIDrvHandle hWFIDrv, u8 scanSource)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */
+
+ strWID.u16WIDid = (u16)WID_START_SCAN_REQ;
+ strWID.enuWIDtype = WID_CHAR;
+ strWID.ps8WidVal = (s8 *)&scanSource;
+ strWID.s32ValueSize = sizeof(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
+ */
+
+s32 host_int_get_start_scan_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8ScanSource)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */
+
+ strWID.u16WIDid = (u16)WID_START_SCAN_REQ;
+ strWID.enuWIDtype = WID_CHAR;
+ strWID.ps8WidVal = (s8 *)pu8ScanSource;
+ strWID.s32ValueSize = sizeof(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
+ */
+s32 host_int_set_join_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8bssid,
+ const u8 *pu8ssid, size_t ssidLen,
+ const u8 *pu8IEs, size_t IEsLen,
+ tWILCpfConnectResult pfConnectResult, void *pvUserArg,
+ u8 u8security, AUTHTYPE_T tenuAuth_type,
+ u8 u8channel,
+ void *pJoinParams)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+ tenuScanConnTimer enuScanConnTimer;
+
+ if (pstrWFIDrv == NULL || pfConnectResult == 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 = (u8 *)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 = (u8 *)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 = (u8 *)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), 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, 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
+ */
+
+s32 host_int_flush_join_req(WILC_WFIDrvHandle hWFIDrv)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrHostIFmsg strHostIFmsg;
+
+ if (!gu8FlushedJoinReq) {
+ s32Error = WILC_FAIL;
+ return s32Error;
+ }
+
+
+ if (hWFIDrv == 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), 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
+ */
+s32 host_int_disconnect(WILC_WFIDrvHandle hWFIDrv, u16 u16ReasonCode)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrHostIFmsg strHostIFmsg;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+
+ if (pstrWFIDrv == 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), NULL);
+ if (s32Error)
+ PRINT_ER("Failed to send message queue: disconnect\n");
+ /* ////////////// */
+ down(&(pstrWFIDrv->hSemTestDisconnectBlock));
+ /* /////// */
+
+ 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
+ */
+s32 host_int_disconnect_station(WILC_WFIDrvHandle hWFIDrv, u8 assoc_id)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */
+
+ strWID.u16WIDid = (u16)WID_DISCONNECT;
+ strWID.enuWIDtype = WID_CHAR;
+ strWID.ps8WidVal = (s8 *)&assoc_id;
+ strWID.s32ValueSize = sizeof(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
+ */
+
+s32 host_int_get_assoc_req_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8AssocReqInfo,
+ u32 u32AssocReqInfoLen)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */
+
+ strWID.u16WIDid = (u16)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
+ */
+s32 host_int_get_assoc_res_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8AssocRespInfo,
+ u32 u32MaxAssocRespInfoLen, u32 *pu32RcvdAssocRespInfoLen)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+
+ if (pstrWFIDrv == NULL) {
+ PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n");
+ WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
+ }
+
+ strWID.u16WIDid = (u16)WID_ASSOC_RES_INFO;
+ strWID.enuWIDtype = WID_STR;
+ strWID.ps8WidVal = pu8AssocRespInfo;
+ strWID.s32ValueSize = u32MaxAssocRespInfoLen;
+
+
+ /* Sending Configuration packet */
+ s32Error = SendConfigPkt(GET_CFG, &strWID, 1, true, (u32)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
+ */
+s32 host_int_get_rx_power_level(WILC_WFIDrvHandle hWFIDrv, u8 *pu8RxPowerLevel,
+ u32 u32RxPowerLevelLen)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */
+
+ strWID.u16WIDid = (u16)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
+ */
+s32 host_int_set_mac_chnl_num(WILC_WFIDrvHandle hWFIDrv, u8 u8ChNum)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+
+ if (pstrWFIDrv == 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), NULL);
+ if (s32Error) {
+ WILC_ERRORREPORT(s32Error, s32Error);
+ }
+ WILC_CATCH(s32Error)
+ {
+
+ }
+
+ return s32Error;
+}
+
+
+s32 host_int_wait_msg_queue_idle(void)
+{
+ s32 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), NULL);
+ if (s32Error) {
+ WILC_ERRORREPORT(s32Error, s32Error);
+ }
+ WILC_CATCH(s32Error)
+ {
+
+ }
+
+ /* wait untill MSG Q is empty */
+ down(&hWaitResponse);
+
+ return s32Error;
+
+}
+
+s32 host_int_set_wfi_drv_handler(u32 u32address)
+{
+ s32 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), NULL);
+ if (s32Error) {
+ WILC_ERRORREPORT(s32Error, s32Error);
+ }
+ WILC_CATCH(s32Error)
+ {
+
+ }
+
+ return s32Error;
+}
+
+
+
+s32 host_int_set_operation_mode(WILC_WFIDrvHandle hWFIDrv, u32 u32mode)
+{
+ s32 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), 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
+ */
+s32 host_int_get_host_chnl_num(WILC_WFIDrvHandle hWFIDrv, u8 *pu8ChNo)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+
+ if (pstrWFIDrv == 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), NULL);
+ if (s32Error)
+ PRINT_ER("Failed to send get host channel param's message queue ");
+ down(&(pstrWFIDrv->hSemGetCHNL));
+ /* 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, u32 u32TestMemAddr
+ * @return Error code indicating success/failure
+ * @note
+ * @author zsalah
+ * @date 8 March 2012
+ * @version 1.0
+ */
+s32 host_int_test_set_int_wid(WILC_WFIDrvHandle hWFIDrv, u32 u32TestMemAddr)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+
+
+ if (pstrWFIDrv == NULL) {
+ PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n");
+ WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
+ }
+
+ /*prepare configuration packet*/
+ strWID.u16WIDid = (u16)WID_MEMORY_ADDRESS;
+ strWID.enuWIDtype = WID_INT;
+ strWID.ps8WidVal = (char *)&u32TestMemAddr;
+ strWID.s32ValueSize = sizeof(u32);
+
+ /*Sending Cfg*/
+ s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)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
+ */
+s32 host_int_get_inactive_time(WILC_WFIDrvHandle hWFIDrv, const u8 *mac, u32 *pu32InactiveTime)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+
+ if (pstrWFIDrv == 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), NULL);
+ if (s32Error)
+ PRINT_ER("Failed to send get host channel param's message queue ");
+
+ down(&(pstrWFIDrv->hSemInactiveTime));
+
+ *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, u32* pu32TestMemAddr
+ * @return Error code indicating success/failure
+ * @note
+ * @author zsalah
+ * @date 8 March 2012
+ * @version 1.0
+ */
+s32 host_int_test_get_int_wid(WILC_WFIDrvHandle hWFIDrv, u32 *pu32TestMemAddr)
+{
+
+ s32 s32Error = WILC_SUCCESS;
+ tstrWID strWID;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+
+
+ if (pstrWFIDrv == NULL) {
+ PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n");
+ WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
+ }
+
+ strWID.u16WIDid = (u16)WID_MEMORY_ADDRESS;
+ strWID.enuWIDtype = WID_INT;
+ strWID.ps8WidVal = (s8 *)pu32TestMemAddr;
+ strWID.s32ValueSize = sizeof(u32);
+
+ s32Error = SendConfigPkt(GET_CFG, &strWID, 1, true, (u32)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
+ */
+s32 host_int_get_rssi(WILC_WFIDrvHandle hWFIDrv, s8 *ps8Rssi)
+{
+ s32 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), NULL);
+ if (s32Error) {
+ PRINT_ER("Failed to send get host channel param's message queue ");
+ return WILC_FAIL;
+ }
+
+ down(&(pstrWFIDrv->hSemGetRSSI));
+
+
+ if (ps8Rssi == NULL) {
+ PRINT_ER("RSS pointer value is null");
+ return WILC_FAIL;
+ }
+
+
+ *ps8Rssi = gs8Rssi;
+
+
+ return s32Error;
+}
+
+s32 host_int_get_link_speed(WILC_WFIDrvHandle hWFIDrv, s8 *ps8lnkspd)
+{
+ tstrHostIFmsg strHostIFmsg;
+ s32 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), NULL);
+ if (s32Error) {
+ PRINT_ER("Failed to send GET_LINKSPEED to message queue ");
+ return WILC_FAIL;
+ }
+
+ down(&(pstrWFIDrv->hSemGetLINKSPEED));
+
+
+ if (ps8lnkspd == NULL) {
+ PRINT_ER("LINKSPEED pointer value is null");
+ return WILC_FAIL;
+ }
+
+
+ *ps8lnkspd = gs8lnkspd;
+
+
+ return s32Error;
+}
+
+s32 host_int_get_statistics(WILC_WFIDrvHandle hWFIDrv, tstrStatistics *pstrStatistics)
+{
+ s32 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 = (char *)pstrStatistics;
+ strHostIFmsg.drvHandler = hWFIDrv;
+ /* send the message */
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ if (s32Error) {
+ PRINT_ER("Failed to send get host channel param's message queue ");
+ return WILC_FAIL;
+ }
+
+ down(&hWaitResponse);
+ 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
+ */
+s32 host_int_scan(WILC_WFIDrvHandle hWFIDrv, u8 u8ScanSource,
+ u8 u8ScanType, u8 *pu8ChnlFreqList,
+ u8 u8ChnlListLen, const u8 *pu8IEs,
+ size_t IEsLen, tWILCpfScanResult ScanResult,
+ void *pvUserArg, tstrHiddenNetwork *pstrHiddenNetwork)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+ tenuScanConnTimer enuScanConnTimer;
+
+ if (pstrWFIDrv == NULL || ScanResult == 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 = (u8 *)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 = (u8 *)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), 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, 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
+ */
+s32 hif_set_cfg(WILC_WFIDrvHandle hWFIDrv, tstrCfgParamVal *pstrCfgParamVal)
+{
+
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+
+ tstrHostIFmsg strHostIFmsg;
+
+
+ if (pstrWFIDrv == 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), 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
+ */
+s32 hif_get_cfg(WILC_WFIDrvHandle hWFIDrv, u16 u16WID, u16 *pu16WID_Value)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+
+ down(&(pstrWFIDrv->gtOsCfgValuesSem));
+
+ if (pstrWFIDrv == 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 = (u16)pstrWFIDrv->strCfgValues.bss_type;
+ break;
+
+ case WID_AUTH_TYPE:
+ *pu16WID_Value = (u16)pstrWFIDrv->strCfgValues.auth_type;
+ break;
+
+ case WID_AUTH_TIMEOUT:
+ *pu16WID_Value = pstrWFIDrv->strCfgValues.auth_timeout;
+ break;
+
+ case WID_POWER_MANAGEMENT:
+ *pu16WID_Value = (u16)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 = (u16)pstrWFIDrv->strCfgValues.preamble_type;
+ break;
+
+ case WID_SHORT_SLOT_ALLOWED:
+ *pu16WID_Value = (u16) pstrWFIDrv->strCfgValues.short_slot_allowed;
+ break;
+
+ case WID_11N_TXOP_PROT_DISABLE:
+ *pu16WID_Value = (u16)pstrWFIDrv->strCfgValues.txop_prot_disabled;
+ break;
+
+ case WID_BEACON_INTERVAL:
+ *pu16WID_Value = pstrWFIDrv->strCfgValues.beacon_interval;
+ break;
+
+ case WID_DTIM_PERIOD:
+ *pu16WID_Value = (u16)pstrWFIDrv->strCfgValues.dtim_period;
+ break;
+
+ case WID_SITE_SURVEY:
+ *pu16WID_Value = (u16)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;
+ }
+
+ up(&(pstrWFIDrv->gtOsCfgValuesSem));
+
+ 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
+ (u16 assocId, u8 *stationAddr, 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) {
+ s32 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), 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
+ (u8 *macStartAddress, u16 u16RxFrameLen, s8 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 u32 u32Intialized;
+static u32 msgQ_created;
+static u32 clients_count;
+
+s32 host_int_init(WILC_WFIDrvHandle *phWFIDrv)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv;
+
+ /*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 = false;
+
+ sema_init(&hWaitResponse, 0);
+
+
+
+ /*Allocate host interface private structure*/
+ pstrWFIDrv = (tstrWILC_WFIDrv *)WILC_MALLOC(sizeof(tstrWILC_WFIDrv));
+ if (pstrWFIDrv == 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 = false;
+ #endif
+
+ PRINT_D(HOSTINF_DBG, "Global handle pointer value=%p\n", pstrWFIDrv);
+ /* /////////////////////////////////////// */
+ if (clients_count == 0) {
+ sema_init(&hSemHostIFthrdEnd, 0);
+ sema_init(&hSemDeinitDrvHandle, 0);
+ /*BugID_5348*/
+ sema_init(&hSemHostIntDeinit, 1);
+ }
+
+ sema_init(&(pstrWFIDrv->hSemTestKeyBlock), 0);
+ sema_init(&(pstrWFIDrv->hSemTestDisconnectBlock), 0);
+ sema_init(&(pstrWFIDrv->hSemGetRSSI), 0);
+ sema_init(&(pstrWFIDrv->hSemGetLINKSPEED), 0);
+ sema_init(&(pstrWFIDrv->hSemGetCHNL), 0);
+ sema_init(&(pstrWFIDrv->hSemInactiveTime), 0);
+
+ /* /////////////////////////////////////// */
+
+
+
+ PRINT_D(HOSTINF_DBG, "INIT: CLIENT COUNT %d\n", clients_count);
+
+ if (clients_count == 0) {
+
+ s32Error = WILC_MsgQueueCreate(&gMsgQHostIF, NULL);
+
+
+ if (s32Error < 0) {
+ PRINT_ER("Failed to creat MQ\n");
+ goto _fail_;
+ }
+ msgQ_created = 1;
+ HostIFthreadHandler = kthread_run(hostIFthread, NULL, "WILC_kthread");
+ if (IS_ERR(HostIFthreadHandler)) {
+ PRINT_ER("Failed to creat Thread\n");
+ s32Error = WILC_FAIL;
+ goto _fail_mq_;
+ }
+ s32Error = WILC_TimerCreate(&(g_hPeriodicRSSI), GetPeriodicRSSI, 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, NULL);
+ if (s32Error < 0) {
+ PRINT_ER("Failed to creat Timer\n");
+ goto _fail_thread_;
+ }
+
+ s32Error = WILC_TimerCreate(&(pstrWFIDrv->hConnectTimer), TimerCB_Connect, 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, NULL);
+ if (s32Error < 0) {
+ PRINT_ER("Failed to creat Remain-on-channel Timer\n");
+ goto _fail_timer_3;
+ }
+ #endif
+
+ sema_init(&(pstrWFIDrv->gtOsCfgValuesSem), 1);
+ down(&(pstrWFIDrv->gtOsCfgValuesSem));
+
+
+
+#ifdef SIMULATION
+ TransportInit();
+#endif
+
+ pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE;
+ /* gWFiDrvHandle->bPendingConnRequest = 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);
+
+
+ up(&(pstrWFIDrv->gtOsCfgValuesSem));
+
+ /*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 != NULL)
+ WILC_FREE(pstrWFIDrv);
+#ifdef WILC_P2P
+_fail_timer_3:
+ WILC_TimerDestroy(&(pstrWFIDrv->hRemainOnChannel), NULL);
+#endif
+_fail_timer_2:
+ up(&(pstrWFIDrv->gtOsCfgValuesSem));
+ WILC_TimerDestroy(&(pstrWFIDrv->hConnectTimer), NULL);
+_fail_timer_1:
+ WILC_TimerDestroy(&(pstrWFIDrv->hScanTimer), NULL);
+_fail_thread_:
+ kthread_stop(HostIFthreadHandler);
+_fail_mq_:
+ WILC_MsgQueueDestroy(&gMsgQHostIF, 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
+ */
+
+s32 host_int_deinit(WILC_WFIDrvHandle hWFIDrv)
+{
+ s32 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;
+ }
+
+ down(&hSemHostIntDeinit);
+
+ 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), NULL)) {
+ PRINT_D(HOSTINF_DBG, ">> Scan timer is active \n");
+ /* msleep(HOST_IF_SCAN_TIMEOUT+1000); */
+ }
+
+ if (WILC_TimerDestroy(&(pstrWFIDrv->hConnectTimer), NULL)) {
+ PRINT_D(HOSTINF_DBG, ">> Connect timer is active \n");
+ /* msleep(HOST_IF_CONNECT_TIMEOUT+1000); */
+ }
+
+
+ if (WILC_TimerDestroy(&(g_hPeriodicRSSI), 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), NULL);
+ #endif
+
+ host_int_set_wfi_drv_handler((u32)NULL);
+ down(&hSemDeinitDrvHandle);
+
+
+ /*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, NULL,
+ pstrWFIDrv->strWILC_UsrScanReq.u32UserScanPvoid, NULL);
+
+ pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult = NULL;
+ }
+ /*deinit configurator and simulator*/
+#ifdef SIMULATION
+ CoreConfigSimulatorDeInit();
+#endif
+ CoreConfiguratorDeInit();
+#ifdef SIMULATION
+ TransportDeInit();
+#endif
+
+ pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE;
+
+ gbScanWhileConnected = false;
+
+ WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+
+ if (clients_count == 1) {
+ if (WILC_TimerDestroy(&g_hPeriodicRSSI, 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), NULL);
+ if (s32Error != WILC_SUCCESS) {
+ PRINT_ER("Error in sending deinit's message queue message function: Error(%d)\n", s32Error);
+ }
+
+ down(&hSemHostIFthrdEnd);
+
+
+
+ WILC_MsgQueueDestroy(&gMsgQHostIF, NULL);
+ msgQ_created = 0;
+ }
+
+ down(&(pstrWFIDrv->gtOsCfgValuesSem));
+
+ /*Setting the gloabl driver handler with NULL*/
+ u32Intialized = 0;
+ /* gWFiDrvHandle = NULL; */
+ if (pstrWFIDrv != NULL) {
+ WILC_FREE(pstrWFIDrv);
+ /* pstrWFIDrv=NULL; */
+
+ }
+
+ clients_count--; /* Decrease number of created entities */
+ terminated_handle = NULL;
+ up(&hSemHostIntDeinit);
+ 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(u8 *pu8Buffer, u32 u32Length)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrHostIFmsg strHostIFmsg;
+ u32 drvHandler;
+ tstrWILC_WFIDrv *pstrWFIDrv = NULL;
+
+ drvHandler = ((pu8Buffer[u32Length - 4]) | (pu8Buffer[u32Length - 3] << 8) | (pu8Buffer[u32Length - 2] << 16) | (pu8Buffer[u32Length - 1] << 24));
+ pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
+
+
+
+ if (pstrWFIDrv == NULL || pstrWFIDrv == terminated_handle) {
+ PRINT_ER("NetworkInfo received but driver not init[%p]\n", 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 = (u8 *)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), 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(u8 *pu8Buffer, u32 u32Length)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrHostIFmsg strHostIFmsg;
+ u32 drvHandler;
+ tstrWILC_WFIDrv *pstrWFIDrv = NULL;
+
+ /*BugID_5348*/
+ down(&hSemHostIntDeinit);
+
+ 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*/
+ up(&hSemHostIntDeinit);
+ return;
+ }
+
+ if (pstrWFIDrv->strWILC_UsrConnReq.pfUserConnectResult == 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*/
+ up(&hSemHostIntDeinit);
+ 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 = (u8 *)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), NULL);
+ if (s32Error) {
+ PRINT_ER("Error in sending message queue asynchronous message info: Error(%d)\n", s32Error);
+ }
+
+ /*BugID_5348*/
+ up(&hSemHostIntDeinit);
+ return;
+}
+
+/**
+ * @brief host_int_ScanCompleteReceived
+ * @details Setting scan complete received notifcation in message queue
+ * @param[in] u8* pu8Buffer, u32 u32Length
+ * @return Error code.
+ * @author
+ * @date
+ * @version 1.0
+ */
+void host_int_ScanCompleteReceived(u8 *pu8Buffer, u32 u32Length)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrHostIFmsg strHostIFmsg;
+ u32 drvHandler;
+ tstrWILC_WFIDrv *pstrWFIDrv = 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 %p\n", 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 = (u8*)WILC_MALLOC(u32Length);
+ * WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strScanComplete.pu8Buffer,
+ * pu8Buffer, u32Length); */
+
+ /* send the message */
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), 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
+ */
+s32 host_int_remain_on_channel(WILC_WFIDrvHandle hWFIDrv, u32 u32SessionID, u32 u32duration, u16 chan, tWILCpfRemainOnChanExpired RemainOnChanExpired, tWILCpfRemainOnChanReady RemainOnChanReady, void *pvUserArg)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+
+ if (pstrWFIDrv == 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), 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
+ */
+s32 host_int_ListenStateExpired(WILC_WFIDrvHandle hWFIDrv, u32 u32SessionID)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+
+ if (pstrWFIDrv == NULL) {
+ WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
+ }
+
+ /*Stopping remain-on-channel timer*/
+ WILC_TimerStop(&(pstrWFIDrv->hRemainOnChannel), 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), 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*/
+s32 host_int_frame_register(WILC_WFIDrvHandle hWFIDrv, u16 u16FrameType, bool bReg)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+
+ if (pstrWFIDrv == 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), 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, u32 u32Interval,
+ * u32 u32DTIMPeriod,u32 u32HeadLen, u8* pu8Head,
+ * u32 u32TailLen, u8* pu8Tail
+ * @return Error code.
+ * @author
+ * @date
+ * @version 1.0
+ */
+s32 host_int_add_beacon(WILC_WFIDrvHandle hWFIDrv, u32 u32Interval,
+ u32 u32DTIMPeriod,
+ u32 u32HeadLen, u8 *pu8Head,
+ u32 u32TailLen, u8 *pu8Tail)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+ tstrHostIFSetBeacon *pstrSetBeaconParam = &strHostIFmsg.uniHostIFmsgBody.strHostIFSetBeacon;
+
+ if (pstrWFIDrv == 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 = (u8 *)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 = (u8 *)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), 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
+ */
+s32 host_int_del_beacon(WILC_WFIDrvHandle hWFIDrv)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+
+ if (pstrWFIDrv == 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), 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
+ */
+s32 host_int_add_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrStaParams)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+ tstrWILC_AddStaParam *pstrAddStationMsg = &strHostIFmsg.uniHostIFmsgBody.strAddStaParam;
+
+
+ if (pstrWFIDrv == 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) {
+ u8 *rates = WILC_MALLOC(pstrAddStationMsg->u8NumRates);
+ WILC_NULLCHECK(s32Error, rates);
+
+ WILC_memcpy(rates, pstrStaParams->pu8Rates, pstrAddStationMsg->u8NumRates);
+ pstrAddStationMsg->pu8Rates = rates;
+ }
+
+
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), 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, u8* pu8MacAddr
+ * @return Error code.
+ * @author
+ * @date
+ * @version 1.0
+ */
+s32 host_int_del_station(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8MacAddr)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+ tstrHostIFDelSta *pstrDelStationMsg = &strHostIFmsg.uniHostIFmsgBody.strDelStaParam;
+
+ if (pstrWFIDrv == 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 == NULL)
+ WILC_memset(pstrDelStationMsg->au8MacAddr, 255, ETH_ALEN);
+ else
+ WILC_memcpy(pstrDelStationMsg->au8MacAddr, pu8MacAddr, ETH_ALEN);
+
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), 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, u8 pu8MacAddr[][ETH_ALEN]s
+ * @return Error code.
+ * @author
+ * @date
+ * @version 1.0
+ */
+s32 host_int_del_allstation(WILC_WFIDrvHandle hWFIDrv, u8 pu8MacAddr[][ETH_ALEN])
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+ tstrHostIFDelAllSta *pstrDelAllStationMsg = &strHostIFmsg.uniHostIFmsgBody.strHostIFDelAllSta;
+ u8 au8Zero_Buff[ETH_ALEN] = {0};
+ u32 i;
+ u8 u8AssocNumb = 0;
+
+
+ if (pstrWFIDrv == 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), NULL);
+
+
+ if (s32Error) {
+ WILC_ERRORREPORT(s32Error, s32Error);
+
+ }
+ WILC_CATCH(s32Error)
+ {
+
+ }
+ down(&hWaitResponse);
+
+ 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
+ */
+s32 host_int_edit_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrStaParams)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+ tstrWILC_AddStaParam *pstrAddStationMsg = &strHostIFmsg.uniHostIFmsgBody.strAddStaParam;
+
+ if (pstrWFIDrv == 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) {
+ u8 *rates = WILC_MALLOC(pstrAddStationMsg->u8NumRates);
+ WILC_NULLCHECK(s32Error, rates);
+ WILC_memcpy(rates, pstrStaParams->pu8Rates, pstrAddStationMsg->u8NumRates);
+ pstrAddStationMsg->pu8Rates = rates;
+ }
+
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ if (s32Error) {
+ WILC_ERRORREPORT(s32Error, s32Error);
+ }
+ WILC_CATCH(s32Error)
+ {
+ }
+ return s32Error;
+}
+#endif /*WILC_AP_EXTERNAL_MLME*/
+uint32_t wilc_get_chipid(uint8_t);
+
+s32 host_int_set_power_mgmt(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled, u32 u32Timeout)
+{
+ s32 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 == 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), NULL);
+ if (s32Error) {
+ WILC_ERRORREPORT(s32Error, s32Error);
+ }
+ WILC_CATCH(s32Error)
+ {
+ }
+ return s32Error;
+}
+
+s32 host_int_setup_multicast_filter(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled, u32 u32count)
+{
+ s32 s32Error = WILC_SUCCESS;
+
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+ tstrHostIFSetMulti *pstrMulticastFilterParam = &strHostIFmsg.uniHostIFmsgBody.strHostIfSetMulti;
+
+
+ if (pstrWFIDrv == 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), 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;
+ u8 *pu8IEs;
+ u16 u16IEsLen;
+ u16 index = 0;
+ u8 suppRatesNo = 0;
+ u8 extSuppRatesNo;
+ u16 jumpOffset;
+ u8 pcipherCount;
+ u8 authCount;
+ u8 pcipherTotalCount = 0;
+ u8 authTotalCount = 0;
+ u8 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((u8 *)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; i<pNewJoinBssParam->ssidLen;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 = true;
+ 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 = true;
+
+ /* Check if Bit 7 is set indicating U-APSD capability */
+ if (pu8IEs[index + 8] & (1 << 7)) {
+ pNewJoinBssParam->uapsd_cap = true;
+ }
+ 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 */
+ u16 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))) {
+ u16 rsnIndex = index;
+ /*PRINT_D(HOSTINF_DBG,"RSN IE Length:%d\n",pu8IEs[rsnIndex+1]);
+ * for(i=0; i<pu8IEs[rsnIndex+1]; i++)
+ * {
+ * PRINT_D(HOSTINF_DBG,"%0x ",pu8IEs[rsnIndex+2+i]);
+ * }*/
+ if (pu8IEs[rsnIndex] == RSN_IE) {
+ pNewJoinBssParam->mode_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 = true;
+ 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)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+ tstrHostIfBASessionInfo *pBASessionInfo = &strHostIFmsg.uniHostIFmsgBody.strHostIfBASessionInfo;
+
+ if (pstrWFIDrv == 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), NULL);
+ if (s32Error) {
+ WILC_ERRORREPORT(s32Error, s32Error);
+ }
+ WILC_CATCH(s32Error)
+ {
+
+ }
+
+ return s32Error;
+}
+
+
+s32 host_int_delBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+ tstrHostIfBASessionInfo *pBASessionInfo = &strHostIFmsg.uniHostIFmsgBody.strHostIfBASessionInfo;
+
+ if (pstrWFIDrv == 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), NULL);
+ if (s32Error) {
+ WILC_ERRORREPORT(s32Error, s32Error);
+ }
+ WILC_CATCH(s32Error)
+ {
+
+ }
+
+ /*BugID_5222*/
+ down(&hWaitResponse);
+
+ return s32Error;
+}
+
+s32 host_int_del_All_Rx_BASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+ tstrHostIfBASessionInfo *pBASessionInfo = &strHostIFmsg.uniHostIFmsgBody.strHostIfBASessionInfo;
+
+ if (pstrWFIDrv == 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), NULL);
+ if (s32Error) {
+ WILC_ERRORREPORT(s32Error, s32Error);
+ }
+ WILC_CATCH(s32Error)
+ {
+
+ }
+
+ /*BugID_5222*/
+ down(&hWaitResponse);
+
+ 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*/
+s32 host_int_setup_ipaddress(WILC_WFIDrvHandle hWFIDrv, u8 *u16ipadd, u8 idx)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+
+ /* TODO: Enable This feature on softap firmware */
+ return 0;
+
+ if (pstrWFIDrv == 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), 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*/
+s32 host_int_get_ipaddress(WILC_WFIDrvHandle hWFIDrv, u8 *u16ipadd, u8 idx)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
+ tstrHostIFmsg strHostIFmsg;
+
+ if (pstrWFIDrv == 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), 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 000000000..38db74074
--- /dev/null
+++ b/drivers/staging/wilc1000/host_interface.h
@@ -0,0 +1,1281 @@
+/*!
+ * @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 */
+/*****************************************************************************/
+#define FAIL 0x0000
+#define SUCCESS 0x0001
+
+#define IP_ALEN 4
+
+#define BIT2 ((u32)(1 << 2))
+#define BIT1 ((u32)(1 << 1))
+#define BIT0 ((u32)(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; */
+
+typedef struct {
+ u16 cfg_wid;
+ WID_TYPE_T cfg_type;
+ s8 *pu8Para;
+} cfg_param_t;
+
+typedef struct _tstrStatistics {
+ u8 u8LinkSpeed;
+ s8 s8RSSI;
+ u32 u32TxCount;
+ u32 u32RxCount;
+ u32 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 {
+ u8 bssid[ETH_ALEN];
+ u8 pmkid[PMKID_LEN];
+} tstrHostIFpmkid;
+
+typedef struct _tstrHostIFpmkidAttr {
+ u8 numpmkid;
+ tstrHostIFpmkid pmkidlist[WILC_MAX_NUM_PMKIDS];
+} tstrHostIFpmkidAttr;
+
+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 {
+ u32 u32SetCfgFlag;
+ u8 ht_enable;
+ u8 bss_type;
+ u8 auth_type;
+ u16 auth_timeout;
+ u8 power_mgmt_mode;
+ u16 short_retry_limit;
+ u16 long_retry_limit;
+ u16 frag_threshold;
+ u16 rts_threshold;
+ u16 preamble_type;
+ u8 short_slot_allowed;
+ u8 txop_prot_disabled;
+ u16 beacon_interval;
+ u16 dtim_period;
+ SITE_SURVEY_T site_survey_enabled;
+ u16 site_survey_scan_time;
+ u8 scan_source;
+ u16 active_scan_time;
+ u16 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 {
+ u8 au8bssid[6];
+ s8 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 *,
+ u8,
+ tstrDisconnectNotifInfo *,
+ void *);
+
+#ifdef WILC_P2P
+typedef void (*tWILCpfRemainOnChanExpired)(void *, u32); /*Remain on channel expiration callback function*/
+typedef void (*tWILCpfRemainOnChanReady)(void *); /*Remain on channel callback function*/
+#endif
+
+/* typedef u32 WILC_WFIDrvHandle; */
+typedef struct {
+ s32 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 {
+ u8 *pu8Buffer;
+ u32 u32Length;
+} tstrRcvdNetworkInfo;
+
+/*BugID_4156*/
+typedef struct _tstrHiddenNetworkInfo {
+ u8 *pu8ssid;
+ u8 u8ssidlen;
+
+} tstrHiddenNetworkInfo;
+
+typedef struct _tstrHiddenNetwork {
+ /* MAX_SSID_LEN */
+ tstrHiddenNetworkInfo *pstrHiddenNetworkInfo;
+ u8 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;
+
+ u32 u32RcvdChCount;
+ tstrFoundNetworkInfo astrFoundNetworkInfo[MAX_NUM_SCANNED_NETWORKS];
+} tstrWILC_UsrScanReq;
+
+typedef struct {
+ u8 *pu8bssid;
+ u8 *pu8ssid;
+ u8 u8security;
+ AUTHTYPE_T tenuAuth_type;
+ size_t ssidLen;
+ u8 *pu8ConnReqIEs;
+ size_t ConnReqIEsLen;
+ /* Connect user call back function */
+ tWILCpfConnectResult pfUserConnectResult;
+ bool IsHTCapable;
+ /* User specific parameter to be delivered through the Connect User Callback function */
+ void *u32UserConnectPvoid;
+} tstrWILC_UsrConnReq;
+
+typedef struct {
+ u32 u32Address;
+} tstrHostIfSetDrvHandler;
+
+typedef struct {
+ u32 u32Mode;
+} tstrHostIfSetOperationMode;
+
+/*BugID_5077*/
+typedef struct {
+ u8 u8MacAddress[ETH_ALEN];
+} tstrHostIfSetMacAddress;
+
+/*BugID_5213*/
+typedef struct {
+ u8 *u8MacAddress;
+} tstrHostIfGetMacAddress;
+
+/*BugID_5222*/
+typedef struct {
+ u8 au8Bssid[ETH_ALEN];
+ u8 u8Ted;
+ u16 u16BufferSize;
+ u16 u16SessionTimeout;
+} tstrHostIfBASessionInfo;
+
+#ifdef WILC_P2P
+typedef struct {
+ u16 u16Channel;
+ u32 u32duration;
+ tWILCpfRemainOnChanExpired pRemainOnChanExpired;
+ tWILCpfRemainOnChanReady pRemainOnChanReady;
+ void *pVoid;
+ u32 u32ListenSessionID;
+} tstrHostIfRemainOnChan;
+
+typedef struct {
+
+ bool bReg;
+ u16 u16FrameType;
+ u8 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;
+ u8 u8RemainOnChan_pendingreq;
+ u64 u64P2p_MgmtTimeout;
+ u8 u8P2PConnect;
+ #endif
+
+ tenuHostIFstate enuHostIFstate;
+
+ /* bool bPendingConnRequest; */
+
+ #ifndef CONNECT_DIRECT
+ u32 u32SurveyResultsCount;
+ wid_site_survey_reslts_s astrSurveyResults[MAX_NUM_SCANNED_NETWORKS];
+ #endif
+
+ u8 au8AssociatedBSSID[ETH_ALEN];
+ tstrCfgParamVal strCfgValues;
+/* semaphores */
+ struct semaphore gtOsCfgValuesSem;
+ struct semaphore hSemTestKeyBlock;
+
+ struct semaphore hSemTestDisconnectBlock;
+ struct semaphore hSemGetRSSI;
+ struct semaphore hSemGetLINKSPEED;
+ struct semaphore hSemGetCHNL;
+ struct semaphore hSemInactiveTime;
+/* timer handlers */
+ WILC_TimerHandle hScanTimer;
+ WILC_TimerHandle hConnectTimer;
+ #ifdef WILC_P2P
+ WILC_TimerHandle hRemainOnChannel;
+ #endif
+
+ 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 {
+ u8 au8BSSID[ETH_ALEN];
+ u16 u16AssocID;
+ u8 u8NumRates;
+ const u8 *pu8Rates;
+ bool bIsHTSupported;
+ u16 u16HTCapInfo;
+ u8 u8AmpduParams;
+ u8 au8SuppMCsSet[16];
+ u16 u16HTExtParams;
+ u32 u32TxBeamformingCap;
+ u8 u8ASELCap;
+ u16 u16FlagsMask; /*<! Determines which of u16FlagsSet were changed>*/
+ u16 u16FlagsSet; /*<! Decoded according to tenuWILC_StaFlag */
+} tstrWILC_AddStaParam;
+
+/* extern void CfgDisconnected(void* pUserVoid, u16 u16reason, u8 * ie, size_t ie_len); */
+
+/*****************************************************************************/
+/* */
+/* Host Interface API */
+/* */
+/*****************************************************************************/
+
+/**
+ * @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
+ */
+s32 host_int_remove_key(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8StaAddress);
+/**
+ * @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
+ */
+s32 host_int_remove_wep_key(WILC_WFIDrvHandle hWFIDrv, u8 u8Index);
+/**
+ * @brief sets WEP deafault 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
+ */
+s32 host_int_set_WEPDefaultKeyID(WILC_WFIDrvHandle hWFIDrv, u8 u8Index);
+
+/**
+ * @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
+ */
+s32 host_int_add_wep_key_bss_sta(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx);
+/**
+ * @brief host_int_add_wep_key_bss_ap
+ * @details valid only in 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
+ */
+s32 host_int_add_wep_key_bss_ap(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx, u8 u8mode, AUTHTYPE_T tenuAuth_type);
+
+/**
+ * @brief adds ptk Key
+ * @details
+ * @param[in,out] handle to the wifi driver
+ * @param[in] message containing PTK Key in the following format
+ *|-------------------------------------------------------------------------|
+ *|Sta Adress | 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
+ */
+s32 host_int_add_ptk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8Ptk, u8 u8PtkKeylen,
+ const u8 *mac_addr, const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode, u8 u8Ciphermode, u8 u8Idx);
+
+/**
+ * @brief host_int_get_inactive_time
+ * @details
+ * @param[in,out] handle to the wifi driver
+ * @param[in] message containing inactive time
+ *
+ * @return Error code indicating success/failure
+ * @note
+ * @author mdaftedar
+ * @date 15 April 2013
+ * @version 1.0
+ */
+s32 host_int_get_inactive_time(WILC_WFIDrvHandle hWFIDrv, const u8 *mac, u32 *pu32InactiveTime);
+
+/**
+ * @brief adds Rx GTk Key
+ * @details
+ * @param[in,out] handle to the wifi driver
+ * @param[in] message containing Rx GTK Key in the following format
+ *|----------------------------------------------------------------------------|
+ *|Sta Address | Key RSC | KeyID | Key Length | Temporal Key | Rx Michael Key |
+ *|------------|---------|-------|------------|---------------|----------------|
+ | 6 bytes | 8 byte |1 byte | 1 byte | 16 bytes | 8 bytes |
+ ||----------------------------------------------------------------------------|
+ * @return Error code indicating success/failure
+ * @note
+ * @author zsalah
+ * @date 8 March 2012
+ * @version 1.0
+ */
+s32 host_int_add_rx_gtk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8RxGtk, u8 u8GtkKeylen,
+ u8 u8KeyIdx, u32 u32KeyRSClen, const u8 *KeyRSC,
+ const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode, u8 u8Ciphermode);
+
+
+/**
+ * @brief adds Tx GTk Key
+ * @details
+ * @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
+ */
+s32 host_int_add_tx_gtk(WILC_WFIDrvHandle hWFIDrv, u8 u8KeyLen, u8 *pu8TxGtk, u8 u8KeyIdx);
+
+/**
+ * @brief caches the pmkid
+ * @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
+ * @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
+ */
+
+s32 host_int_set_pmkid_info(WILC_WFIDrvHandle hWFIDrv, tstrHostIFpmkidAttr *pu8PmkidInfoArray);
+/**
+ * @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
+ */
+
+s32 host_int_get_pmkid_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8PmkidInfoArray,
+ u32 u32PmkidInfoLen);
+
+/**
+ * @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
+ */
+s32 host_int_set_RSNAConfigPSKPassPhrase(WILC_WFIDrvHandle hWFIDrv, u8 *pu8PassPhrase,
+ u8 u8Psklength);
+/**
+ * @brief gets the pass phrase
+ * @details 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
+ */
+s32 host_int_get_RSNAConfigPSKPassPhrase(WILC_WFIDrvHandle hWFIDrv,
+ u8 *pu8PassPhrase, u8 u8Psklength);
+
+/**
+ * @brief gets mac address
+ * @details
+ * @param[in,out] handle to the wifi driver,
+ *
+ * @return Error code indicating success/failure
+ * @note
+ * @author mdaftedar
+ * @date 19 April 2012
+ * @version 1.0
+ */
+s32 host_int_get_MacAddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8MacAddress);
+
+/**
+ * @brief sets mac address
+ * @details
+ * @param[in,out] handle to the wifi driver,
+ *
+ * @return Error code indicating success/failure
+ * @note
+ * @author mabubakr
+ * @date 16 July 2012
+ * @version 1.0
+ */
+s32 host_int_set_MacAddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8MacAddress);
+
+/**
+ * @brief wait until msg q is empty
+ * @details
+ * @param[in,out]
+ *
+ * @return Error code indicating success/failure
+ * @note
+ * @author asobhy
+ * @date 19 march 2014
+ * @version 1.0
+ */
+s32 host_int_wait_msg_queue_idle(void);
+
+/**
+ * @brief gets the site survey results
+ * @details
+ * @param[in,out] handle to the wifi driver,
+ * Message containing site survey results in the
+ * following formate
+ *|---------------------------------------------------|
+ | 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
+s32 host_int_get_site_survey_results(WILC_WFIDrvHandle hWFIDrv,
+ u8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZE],
+ u32 u32MaxSiteSrvyFragLen);
+#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
+ */
+
+s32 host_int_set_start_scan_req(WILC_WFIDrvHandle hWFIDrv, u8 scanSource);
+/**
+ * @brief gets scan source of the last scan
+ * @details
+ * @param[in,out] handle to the wifi driver,
+ * 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
+ */
+s32 host_int_get_start_scan_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8ScanSource);
+
+/**
+ * @brief sets a join request
+ * @details
+ * @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
+ */
+
+s32 host_int_set_join_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8bssid,
+ const u8 *pu8ssid, size_t ssidLen,
+ const u8 *pu8IEs, size_t IEsLen,
+ tWILCpfConnectResult pfConnectResult, void *pvUserArg,
+ u8 u8security, AUTHTYPE_T tenuAuth_type,
+ u8 u8channel,
+ void *pJoinParams);
+
+/**
+ * @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
+ */
+
+s32 host_int_flush_join_req(WILC_WFIDrvHandle hWFIDrv);
+
+
+/**
+ * @brief disconnects from the currently associated network
+ * @details
+ * @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
+ */
+s32 host_int_disconnect(WILC_WFIDrvHandle hWFIDrv, u16 u16ReasonCode);
+
+/**
+ * @brief disconnects a sta
+ * @details
+ * @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
+ */
+s32 host_int_disconnect_station(WILC_WFIDrvHandle hWFIDrv, u8 assoc_id);
+/**
+ * @brief gets a Association request info
+ * @details
+ * @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
+ */
+
+s32 host_int_get_assoc_req_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8AssocReqInfo,
+ u32 u32AssocReqInfoLen);
+/**
+ * @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
+ */
+
+s32 host_int_get_assoc_res_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8AssocRespInfo,
+ u32 u32MaxAssocRespInfoLen, u32 *pu32RcvdAssocRespInfoLen);
+/**
+ * @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
+ */
+s32 host_int_get_rx_power_level(WILC_WFIDrvHandle hWFIDrv, u8 *pu8RxPowerLevel,
+ u32 u32RxPowerLevelLen);
+
+/**
+ * @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
+ */
+s32 host_int_set_mac_chnl_num(WILC_WFIDrvHandle hWFIDrv, u8 u8ChNum);
+
+/**
+ * @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
+ */
+s32 host_int_get_host_chnl_num(WILC_WFIDrvHandle hWFIDrv, u8 *pu8ChNo);
+/**
+ * @brief gets the sta 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
+ */
+s32 host_int_get_rssi(WILC_WFIDrvHandle hWFIDrv, s8 *ps8Rssi);
+s32 host_int_get_link_speed(WILC_WFIDrvHandle hWFIDrv, s8 *ps8lnkspd);
+/**
+ * @brief scans a set of channels
+ * @details
+ * @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
+ * User Argument to be delivered back through the Scan Cllback function
+ * @return Error code indicating success/failure
+ * @note
+ * @author zsalah
+ * @date 8 March 2012
+ * @version 1.0
+ */
+s32 host_int_scan(WILC_WFIDrvHandle hWFIDrv, u8 u8ScanSource,
+ u8 u8ScanType, u8 *pu8ChnlFreqList,
+ u8 u8ChnlListLen, const u8 *pu8IEs,
+ size_t IEsLen, tWILCpfScanResult ScanResult,
+ void *pvUserArg, tstrHiddenNetwork *pstrHiddenNetwork);
+/**
+ * @brief sets configuration wids values
+ * @details
+ * @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
+ */
+s32 hif_set_cfg(WILC_WFIDrvHandle hWFIDrv, tstrCfgParamVal *pstrCfgParamVal);
+
+/**
+ * @brief gets configuration wids values
+ * @details
+ * @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
+ */
+s32 hif_get_cfg(WILC_WFIDrvHandle hWFIDrv, u16 u16WID, u16 *pu16WID_Value);
+/*****************************************************************************/
+/* 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
+ (u16 assocId, u8 *stationAddr, 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 host_int_send_network_info_to_host
+ (u8 *macStartAddress, u16 u16RxFrameLen, s8 s8Rssi);
+
+/**
+ * @brief host interface initialization function
+ * @details
+ * @param[in,out] handle to the wifi driver,
+ * @note
+ * @author zsalah
+ * @date 8 March 2012
+ * @version 1.0
+ */
+s32 host_int_init(WILC_WFIDrvHandle *phWFIDrv);
+
+/**
+ * @brief host interface initialization function
+ * @details
+ * @param[in,out] handle to the wifi driver,
+ * @note
+ * @author zsalah
+ * @date 8 March 2012
+ * @version 1.0
+ */
+s32 host_int_deinit(WILC_WFIDrvHandle hWFIDrv);
+
+
+/*!
+ * @fn s32 host_int_add_beacon(WILC_WFIDrvHandle hWFIDrv,u8 u8Index)
+ * @brief Sends a beacon to the firmware to be transmitted over the air
+ * @details
+ * @param[in,out] hWFIDrv handle to the wifi driver
+ * @param[in] u32Interval Beacon Interval. Period between two successive beacons on air
+ * @param[in] u32DTIMPeriod DTIM Period. Indicates how many Beacon frames
+ * (including the current frame) appear before the next DTIM
+ * @param[in] u32Headlen Length of the head buffer in bytes
+ * @param[in] 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
+ * @param[in] u32Taillen Length of the tail buffer in bytes
+ * @param[in] pu8Tail Pointer to the beacon's tail buffer. Beacon's tail
+ * starts just after the TIM inormation element
+ * @return 0 for Success, error otherwise
+ * @todo
+ * @sa
+ * @author Adham Abozaeid
+ * @date 10 Julys 2012
+ * @version 1.0 Description
+ *
+ */
+s32 host_int_add_beacon(WILC_WFIDrvHandle hWFIDrv, u32 u32Interval,
+ u32 u32DTIMPeriod,
+ u32 u32HeadLen, u8 *pu8Head,
+ u32 u32TailLen, u8 *pu8tail);
+
+
+/*!
+ * @fn s32 host_int_del_beacon(WILC_WFIDrvHandle hWFIDrv)
+ * @brief Removes the beacon and stops trawilctting it over the air
+ * @details
+ * @param[in,out] hWFIDrv handle to the wifi driver
+ * @return 0 for Success, error otherwise
+ * @todo
+ * @sa
+ * @author Adham Abozaeid
+ * @date 10 Julys 2012
+ * @version 1.0 Description
+ */
+s32 host_int_del_beacon(WILC_WFIDrvHandle hWFIDrv);
+
+/*!
+ * @fn s32 host_int_add_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam strStaParams)
+ * @brief Notifies the firmware with a new associated stations
+ * @details
+ * @param[in,out] hWFIDrv handle to the wifi driver
+ * @param[in] pstrStaParams Station's parameters
+ * @return 0 for Success, error otherwise
+ * @todo
+ * @sa
+ * @author Adham Abozaeid
+ * @date 12 July 2012
+ * @version 1.0 Description
+ */
+s32 host_int_add_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrStaParams);
+
+/*!
+ * @fn s32 host_int_del_allstation(WILC_WFIDrvHandle hWFIDrv, const u8* pu8MacAddr)
+ * @brief Deauthenticates clients when group is terminating
+ * @details
+ * @param[in,out] hWFIDrv handle to the wifi driver
+ * @param[in] pu8MacAddr Station's mac address
+ * @return 0 for Success, error otherwise
+ * @todo
+ * @sa
+ * @author Mai Daftedar
+ * @date 09 April 2014
+ * @version 1.0 Description
+ */
+s32 host_int_del_allstation(WILC_WFIDrvHandle hWFIDrv, u8 pu8MacAddr[][ETH_ALEN]);
+
+/*!
+ * @fn s32 host_int_del_station(WILC_WFIDrvHandle hWFIDrv, u8* pu8MacAddr)
+ * @brief Notifies the firmware with a new deleted station
+ * @details
+ * @param[in,out] hWFIDrv handle to the wifi driver
+ * @param[in] pu8MacAddr Station's mac address
+ * @return 0 for Success, error otherwise
+ * @todo
+ * @sa
+ * @author Adham Abozaeid
+ * @date 15 July 2012
+ * @version 1.0 Description
+ */
+s32 host_int_del_station(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8MacAddr);
+
+/*!
+ * @fn s32 host_int_edit_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam strStaParams)
+ * @brief Notifies the firmware with new parameters of an already associated station
+ * @details
+ * @param[in,out] hWFIDrv handle to the wifi driver
+ * @param[in] pstrStaParams Station's parameters
+ * @return 0 for Success, error otherwise
+ * @todo
+ * @sa
+ * @author Adham Abozaeid
+ * @date 15 July 2012
+ * @version 1.0 Description
+ */
+s32 host_int_edit_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrStaParams);
+
+/*!
+ * @fn s32 host_int_set_power_mgmt(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled, u32 u32Timeout)
+ * @brief Set the power management mode to enabled or disabled
+ * @details
+ * @param[in,out] hWFIDrv handle to the wifi driver
+ * @param[in] bIsEnabled TRUE if enabled, FALSE otherwise
+ * @param[in] u32Timeout A timeout value of -1 allows the driver to adjust
+ * the dynamic ps timeout value
+ * @return 0 for Success, error otherwise
+ * @todo
+ * @sa
+ * @author Adham Abozaeid
+ * @date 24 November 2012
+ * @version 1.0 Description
+ */
+s32 host_int_set_power_mgmt(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled, u32 u32Timeout);
+/* @param[in,out] hWFIDrv handle to the wifi driver
+ * @param[in] bIsEnabled TRUE if enabled, FALSE otherwise
+ * @param[in] u8count count of mac address entries in the filter table
+ *
+ * @return 0 for Success, error otherwise
+ * @todo
+ * @sa
+ * @author Adham Abozaeid
+ * @date 24 November 2012
+ * @version 1.0 Description
+ */
+s32 host_int_setup_multicast_filter(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled, u32 u32count);
+/**
+ * @brief host_int_setup_ipaddress
+ * @details set IP address on firmware
+ * @param[in]
+ * @return Error code.
+ * @author Abdelrahman Sobhy
+ * @date
+ * @version 1.0
+ */
+s32 host_int_setup_ipaddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8IPAddr, u8 idx);
+
+
+/**
+ * @brief host_int_delBASession
+ * @details Delete single Rx BA session
+ * @param[in]
+ * @return Error code.
+ * @author Abdelrahman Sobhy
+ * @date
+ * @version 1.0
+ */
+s32 host_int_delBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID);
+
+/**
+ * @brief host_int_delBASession
+ * @details Delete all Rx BA session
+ * @param[in]
+ * @return Error code.
+ * @author Abdelrahman Sobhy
+ * @date
+ * @version 1.0
+ */
+s32 host_int_del_All_Rx_BASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID);
+
+
+/**
+ * @brief host_int_get_ipaddress
+ * @details get IP address on firmware
+ * @param[in]
+ * @return Error code.
+ * @author Abdelrahman Sobhy
+ * @date
+ * @version 1.0
+ */
+s32 host_int_get_ipaddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8IPAddr, u8 idx);
+
+#ifdef WILC_P2P
+/**
+ * @brief host_int_remain_on_channel
+ * @details
+ * @param[in]
+ * @return Error code.
+ * @author
+ * @date
+ * @version 1.0
+ */
+s32 host_int_remain_on_channel(WILC_WFIDrvHandle hWFIDrv, u32 u32SessionID, u32 u32duration, u16 chan, tWILCpfRemainOnChanExpired RemainOnChanExpired, tWILCpfRemainOnChanReady RemainOnChanReady, void *pvUserArg);
+
+/**
+ * @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
+ */
+s32 host_int_ListenStateExpired(WILC_WFIDrvHandle hWFIDrv, u32 u32SessionID);
+
+/**
+ * @brief host_int_frame_register
+ * @details
+ * @param[in]
+ * @return Error code.
+ * @author
+ * @date
+ * @version 1.0
+ */
+s32 host_int_frame_register(WILC_WFIDrvHandle hWFIDrv, u16 u16FrameType, bool bReg);
+#endif
+/**
+ * @brief host_int_set_wfi_drv_handler
+ * @details
+ * @param[in]
+ * @return Error code.
+ * @author
+ * @date
+ * @version 1.0
+ */
+s32 host_int_set_wfi_drv_handler(u32 u32address);
+s32 host_int_set_operation_mode(WILC_WFIDrvHandle hWFIDrv, u32 u32mode);
+
+static s32 Handle_ScanDone(void *drvHandler, tenuScanEvent enuEvent);
+
+static int host_int_addBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID, short int BufferSize,
+ short int SessionTimeout, void *drvHandler);
+
+
+void host_int_freeJoinParams(void *pJoinParams);
+
+s32 host_int_get_statistics(WILC_WFIDrvHandle hWFIDrv, tstrStatistics *pstrStatistics);
+
+/*****************************************************************************/
+/* */
+/* EOF */
+/* */
+/*****************************************************************************/
+#endif
diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c
new file mode 100644
index 000000000..f5296f53a
--- /dev/null
+++ b/drivers/staging/wilc1000/linux_mon.c
@@ -0,0 +1,598 @@
+/*!
+ * @file linux_mon.c
+ * @brief File Operations OS wrapper functionality
+ * @author mdaftedar
+ * @sa wilc_wfi_netdevice.h
+ * @date 01 MAR 2012
+ * @version 1.0
+ */
+
+#ifndef SIMULATION
+#include "wilc_wfi_cfgoperations.h"
+#include "linux_wlan_common.h"
+#include "wilc_wlan_if.h"
+#include "wilc_wlan.h"
+#endif
+#ifdef WILC_FULLY_HOSTING_AP
+#include "wilc_host_ap.h"
+#endif
+#ifdef WILC_AP_EXTERNAL_MLME
+#ifdef SIMULATION
+#include "wilc_wfi_cfgoperations.h"
+#endif
+
+struct wilc_wfi_radiotap_hdr {
+ struct ieee80211_radiotap_header hdr;
+ u8 rate;
+ /* u32 channel; */
+} __attribute__((packed));
+
+struct wilc_wfi_radiotap_cb_hdr {
+ struct ieee80211_radiotap_header hdr;
+ u8 rate;
+ u8 dump;
+ u16 tx_flags;
+ /* u32 channel; */
+} __attribute__((packed));
+
+extern linux_wlan_t *g_linux_wlan;
+
+static struct net_device *wilc_wfi_mon; /* global monitor netdev */
+
+#ifdef SIMULATION
+extern int WILC_WFI_Tx(struct sk_buff *skb, struct net_device *dev);
+#elif USE_WIRELESS
+extern int mac_xmit(struct sk_buff *skb, struct net_device *dev);
+#endif
+
+
+u8 srcAdd[6];
+u8 bssid[6];
+u8 broadcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+/**
+ * @brief WILC_WFI_monitor_rx
+ * @details
+ * @param[in]
+ * @return int : Return 0 on Success
+ * @author mdaftedar
+ * @date 12 JUL 2012
+ * @version 1.0
+ */
+
+#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
+#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive*/
+#define IS_MANAGMEMENT 0x100
+#define IS_MANAGMEMENT_CALLBACK 0x080
+#define IS_MGMT_STATUS_SUCCES 0x040
+#define GET_PKT_OFFSET(a) (((a) >> 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;i<skb->len;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;
+ u8 *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 = 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 = 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) == 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;
+ u32 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, 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;
+ u8 *buf = pv_data->buff;
+
+ /* len of the original frame without the added pointer at the tail */
+ u16 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 (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 = (u8*)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(const char *name, struct net_device *real_dev)
+{
+
+
+ u32 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;
+ }
+
+ 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 000000000..e52534ce1
--- /dev/null
+++ b/drivers/staging/wilc1000/linux_wlan.c
@@ -0,0 +1,2783 @@
+#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 <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+
+#include <linux/kthread.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
+#include <linux/inetdevice.h>
+#endif
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+
+#include <linux/version.h>
+#include <linux/semaphore.h>
+
+#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 <linux/vmalloc.h>
+#include <linux/fs.h>
+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 bool g_obtainingIP;
+#endif
+extern u16 Set_machw_change_vir_if(bool bValue);
+extern void resolve_disconnect_aberration(void *drvHandler);
+extern u8 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 "/*(DEBLOBBED)*/"
+#endif
+
+#ifndef AP_FIRMWARE
+#define AP_FIRMWARE "/*(DEBLOBBED)*/"
+#endif
+
+#ifndef P2P_CONCURRENCY_FIRMWARE
+#define P2P_CONCURRENCY_FIRMWARE "/*(DEBLOBBED)*/"
+#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;
+bool bEnablePS = true;
+
+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,
+
+};
+
+#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;
+ u8 *pIP_Add_buff;
+ perInterface_wlan_t *nic;
+ u8 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 = false;
+ WILC_TimerStop(&hDuringIpTimer, NULL);
+ PRINT_D(GENERIC_DBG, "IP obtained , enable scan\n");
+ }
+
+
+
+ if (bEnablePS)
+ 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]);
+ 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 = 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]);
+
+ 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) {
+ u32 u32Temp = msc * 1000;
+ usleep_range(u32Temp, u32Temp);
+ } 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 = 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 = 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 = 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, u32 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 */
+ }
+
+ } 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 (reject_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 (reject_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)
+{
+
+ 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
+ static int timeout = 5;
+
+ 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
+
+ /*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 = %p\n", 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]);
+ 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 = (u32)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, (u32)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);
+
+#ifndef TCP_ENHANCEMENTS
+_fail_1:
+#endif
+ #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 = ARRAY_SIZE(path_string);
+
+ /* 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();
+_fail_irq_init_:
+#endif
+#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 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(false);
+
+ 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 = (u32)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 */
+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, 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, 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, true, (dev->mc.count));
+
+ return;
+
+}
+
+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)
+{
+
+ u8 *buff = NULL;
+ s8 rssi;
+ u32 size = 0, length = 0;
+ perInterface_wlan_t *nic;
+ struct WILC_WFI_priv *priv;
+ s32 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) {
+
+ /* ]] 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 = memdup_user(wrq->u.data.pointer, wrq->u.data.length);
+ if (IS_ERR(buff)) {
+ s32Error = PTR_ERR(buff);
+ 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", __func__);
+ 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;
+#ifndef TCP_ENHANCEMENTS
+ char *pu8UdpBuffer;
+ struct iphdr *ih;
+#endif
+ 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(i<frame_len)
+ * WILC_PRINTF("buff_to_send[%d]=%2x\n",i,buff_to_send[i]);
+ *
+ * }*/
+
+ /* skb_put(skb, frame_len); */
+ memcpy(skb_put(skb, frame_len), buff_to_send, frame_len);
+
+ /* WILC_PRINTF("After MEM_CPY\n"); */
+
+ /* nic = netdev_priv(wilc_netdev); */
+
+#ifdef USE_WIRELESS
+ /* if(nic->monitor_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++;
+ ndev->netdev_ops = &wilc_netdev_ops;
+
+ #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=[10.2] FW_VER=[10.2] ***\n");
+
+ 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] = {NULL,};
+ #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 000000000..2476bfda1
--- /dev/null
+++ b/drivers/staging/wilc1000/linux_wlan_common.h
@@ -0,0 +1,182 @@
+#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)
+#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(&REGION)) & (region))) { \
+ printk("DBG [%s: %d]", __func__, __LINE__); \
+ printk(__VA_ARGS__); \
+ } \
+ } while (0)
+
+#define PRINT_INFO(region, ...) \
+ do { \
+ if ((atomic_read(&DEBUG_LEVEL) & INFO) && \
+ ((atomic_read(&REGION)) & (region))) { \
+ printk("INFO [%s]", __func__); \
+ printk(__VA_ARGS__); \
+ } \
+ } while (0)
+
+#define PRINT_WRN(region, ...) \
+ do { \
+ if ((atomic_read(&DEBUG_LEVEL) & WRN) && \
+ ((atomic_read(&REGION)) & (region))) { \
+ printk("WRN [%s: %d]", __func__, __LINE__); \
+ printk(__VA_ARGS__); \
+ } \
+ } while (0)
+
+#define PRINT_ER(...) \
+ do { \
+ if ((atomic_read(&DEBUG_LEVEL) & ERR)) { \
+ printk("ERR [%s: %d]", __func__, __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]", __func__, __LINE__); \
+ printk(__VA_ARGS__); \
+ } \
+ } while (0)
+
+#define PRINT_INFO(region, ...) \
+ do { \
+ if (INFO == 1 && ((REGION)&(region))) { \
+ printk("INFO [%s]", __func__); \
+ printk(__VA_ARGS__); \
+ } \
+ } while (0)
+
+#define PRINT_WRN(region, ...) \
+ do { \
+ if (WRN == 1 && ((REGION)&(region))) { \
+ printk("WRN [%s: %d]", __func__, __LINE__); \
+ printk(__VA_ARGS__); \
+ } \
+ } while (0)
+
+#define PRINT_ER(...) \
+ do { \
+ printk("ERR [%s: %d]", __func__, __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 000000000..858e3a191
--- /dev/null
+++ b/drivers/staging/wilc1000/linux_wlan_sdio.c
@@ -0,0 +1,249 @@
+#include "wilc_wfi_netdevice.h"
+
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/host.h>
+
+
+
+#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 000000000..4b515f510
--- /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 <linux/mmc/sdio_func.h>
+
+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 000000000..236669cfc
--- /dev/null
+++ b/drivers/staging/wilc1000/linux_wlan_spi.c
@@ -0,0 +1,479 @@
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/cdev.h>
+#include <asm/uaccess.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+
+#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)
+{
+
+ 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++;
+ 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 = 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),
+ .len = TXRX_PHASE_SIZE,
+ .speed_hz = SPEED,
+ .bits_per_word = 8,
+ .delay_usecs = 0,
+ };
+
+ 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++;
+
+ }
+ }
+ if (remainder) {
+ struct spi_message msg;
+ struct spi_transfer tr = {
+ .tx_buf = b + (blk * TXRX_PHASE_SIZE),
+ .len = remainder,
+ .speed_hz = SPEED,
+ .bits_per_word = 8,
+ .delay_usecs = 0,
+ };
+ 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");
+ }
+ }
+ 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,
+ .len = len,
+ .speed_hz = SPEED,
+ .delay_usecs = 0,
+ };
+ char *r_buffer = 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 = 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 = {
+ .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 = {
+ .rx_buf = rb + (blk * TXRX_PHASE_SIZE),
+ .len = remainder,
+ .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; /* rachel */
+
+ 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;
+}
+
+#else
+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,
+
+ };
+ char *t_buffer = 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 000000000..0ecad477d
--- /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 <linux/spi/spi.h>
+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 000000000..c328208cd
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_debugfs.c
@@ -0,0 +1,191 @@
+/*
+ * NewportMedia WiFi chipset driver test tools - wilc-debug
+ * Copyright (c) 2012 NewportMedia Inc.
+ * Author: SSW <sswd@wilcsemic.com>
+ *
+ * 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 <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+
+#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 (count > sizeof(buffer))
+ return -EINVAL;
+
+ 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(&REGION));
+
+ 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 (count > sizeof(buffer))
+ return -EINVAL;
+
+ 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(&REGION));
+ return -EFAULT;
+ }
+
+ atomic_set(&REGION, (int)flag);
+ printk("new debug-region is %x\n", atomic_read(&REGION));
+
+ 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 000000000..b9517dc7f
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_errorsupport.h
@@ -0,0 +1,67 @@
+#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 s32 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__ == NULL) { \
+ WILC_ERRORREPORT(__status__, WILC_NULL_PTR); \
+ } \
+} while (0)
+
+#define WILC_CATCH(__status__) \
+ERRORHANDLER: \
+ if (WILC_IS_ERR(__status__)) \
+
+#endif
diff --git a/drivers/staging/wilc1000/wilc_exported_buf.c b/drivers/staging/wilc1000/wilc_exported_buf.c
new file mode 100644
index 000000000..529457816
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_exported_buf.c
@@ -0,0 +1,76 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#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 000000000..2269ebdec
--- /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 000000000..c70707fef
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_memory.c
@@ -0,0 +1,58 @@
+
+#include "wilc_memory.h"
+
+/*!
+ * @author syounan
+ * @date 18 Aug 2010
+ * @version 1.0
+ */
+void *WILC_MemoryAlloc(u32 u32Size, tstrWILC_MemoryAttrs *strAttrs,
+ char *pcFileName, u32 u32LineNo)
+{
+ if (u32Size > 0) {
+ return kmalloc(u32Size, GFP_ATOMIC);
+ } else {
+ return NULL;
+ }
+}
+
+/*!
+ * @author syounan
+ * @date 18 Aug 2010
+ * @version 1.0
+ */
+void *WILC_MemoryCalloc(u32 u32Size, tstrWILC_MemoryAttrs *strAttrs,
+ char *pcFileName, u32 u32LineNo)
+{
+ return kcalloc(u32Size, 1, GFP_KERNEL);
+}
+
+/*!
+ * @author syounan
+ * @date 18 Aug 2010
+ * @version 1.0
+ */
+void *WILC_MemoryRealloc(void *pvOldBlock, u32 u32NewSize,
+ tstrWILC_MemoryAttrs *strAttrs, char *pcFileName, u32 u32LineNo)
+{
+ if (u32NewSize == 0) {
+ kfree(pvOldBlock);
+ return NULL;
+ } else if (pvOldBlock == 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(const void *pvBlock, tstrWILC_MemoryAttrs *strAttrs,
+ char *pcFileName, u32 u32LineNo)
+{
+ kfree(pvBlock);
+}
diff --git a/drivers/staging/wilc1000/wilc_memory.h b/drivers/staging/wilc1000/wilc_memory.h
new file mode 100644
index 000000000..372d7053e
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_memory.h
@@ -0,0 +1,239 @@
+#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
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+
+/*!
+ * @struct tstrWILC_MemoryAttrs
+ * @brief Memory API options
+ * @author syounan
+ * @date 16 Aug 2010
+ * @version 1.0
+ */
+typedef struct {
+} tstrWILC_MemoryAttrs;
+
+/*!
+ * @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(u32 u32Size, tstrWILC_MemoryAttrs *strAttrs,
+ char *pcFileName, u32 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(u32 u32Size, tstrWILC_MemoryAttrs *strAttrs,
+ char *pcFileName, u32 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, u32 u32NewSize,
+ tstrWILC_MemoryAttrs *strAttrs, char *pcFileName, u32 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(const void *pvBlock, tstrWILC_MemoryAttrs *strAttrs,
+ char *pcFileName, u32 u32LineNo);
+
+/*!
+ * @brief standrad malloc wrapper with custom attributes
+ */
+ #define WILC_MALLOC_EX(__size__, __attrs__) \
+ (WILC_MemoryAlloc( \
+ (__size__), __attrs__, NULL, 0))
+
+/*!
+ * @brief standrad calloc wrapper with custom attributes
+ */
+ #define WILC_CALLOC_EX(__size__, __attrs__) \
+ (WILC_MemoryCalloc( \
+ (__size__), __attrs__, NULL, 0))
+
+/*!
+ * @brief standrad realloc wrapper with custom attributes
+ */
+ #define WILC_REALLOC_EX(__ptr__, __new_size__, __attrs__) \
+ (WILC_MemoryRealloc( \
+ (__ptr__), (__new_size__), __attrs__, NULL, 0))
+/*!
+ * @brief standrad free wrapper with custom attributes
+ */
+ #define WILC_FREE_EX(__ptr__, __attrs__) \
+ (WILC_MemoryFree( \
+ (__ptr__), __attrs__, NULL, 0))
+
+/*!
+ * @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__) * (u32)(__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__) * (u32)(__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__ != NULL) { \
+ WILC_FREE_EX(__ptr__, __attrs__); \
+ __ptr__ = 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__ != NULL) { \
+ WILC_FREE_EX(__ptr__, __attrs__); \
+ } \
+} while (0)
+
+/*!
+ * @brief standrad malloc wrapper with default attributes
+ */
+#define WILC_MALLOC(__size__) \
+ WILC_MALLOC_EX(__size__, NULL)
+
+/*!
+ * @brief standrad calloc wrapper with default attributes
+ */
+#define WILC_CALLOC(__size__) \
+ WILC_CALLOC_EX(__size__, NULL)
+
+/*!
+ * @brief standrad realloc wrapper with default attributes
+ */
+#define WILC_REALLOC(__ptr__, __new_size__) \
+ WILC_REALLOC_EX(__ptr__, __new_size__, NULL)
+
+/*!
+ * @brief standrad free wrapper with default attributes
+ */
+#define WILC_FREE(__ptr__) \
+ WILC_FREE_EX(__ptr__, 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__, 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__, 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__, 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__, NULL)
+
+
+#endif
diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c
new file mode 100644
index 000000000..16bcef4b5
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_msgqueue.c
@@ -0,0 +1,190 @@
+
+#include "wilc_msgqueue.h"
+#include <linux/spinlock.h>
+
+/*!
+ * @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)
+{
+ spin_lock_init(&pHandle->strCriticalSection);
+ sema_init(&pHandle->hSem, 0);
+ pHandle->pstrMessageList = NULL;
+ pHandle->u32ReceiversCount = 0;
+ pHandle->bExiting = false;
+ return WILC_SUCCESS;
+}
+
+/*!
+ * @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 = true;
+
+ /* Release any waiting receiver thread. */
+ while (pHandle->u32ReceiversCount > 0) {
+ up(&(pHandle->hSem));
+ pHandle->u32ReceiversCount--;
+ }
+
+ 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, u32 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 == 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);
+
+ up(&pHandle->hSem);
+
+ 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, u32 u32RecvBufferSize,
+ u32 *pu32ReceivedLength,
+ tstrWILC_MsgQueueAttrs *pstrAttrs)
+{
+
+ Message *pstrMessage;
+ WILC_ErrNo s32RetStatus = WILC_SUCCESS;
+ unsigned long flags;
+ if ((pHandle == NULL) || (u32RecvBufferSize == 0)
+ || (pvRecvBuffer == NULL) || (pu32ReceivedLength == NULL)) {
+ WILC_ERRORREPORT(s32RetStatus, WILC_INVALID_ARGUMENT);
+ }
+
+ if (pHandle->bExiting == true) {
+ WILC_ERRORREPORT(s32RetStatus, WILC_FAIL);
+ }
+
+ spin_lock_irqsave(&pHandle->strCriticalSection, flags);
+ pHandle->u32ReceiversCount++;
+ spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
+
+ down(&(pHandle->hSem));
+
+ 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);
+ up(&pHandle->hSem);
+ 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;
+}
diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h
new file mode 100644
index 000000000..35b10019e
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_msgqueue.h
@@ -0,0 +1,108 @@
+#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
+ */
+
+#include "wilc_platform.h"
+#include "wilc_errorsupport.h"
+#include "wilc_memory.h"
+#include "wilc_strutils.h"
+
+/*!
+ * @struct tstrWILC_MsgQueueAttrs
+ * @brief Message Queue API options
+ * @author syounan
+ * @date 30 Aug 2010
+ * @version 1.0
+ */
+typedef struct {
+ /* a dummy member to avoid compiler errors*/
+ u8 dummy;
+
+} tstrWILC_MsgQueueAttrs;
+
+/*!
+ * @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, u32 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, u32 u32RecvBufferSize,
+ u32 *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 000000000..f9c251403
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_osconfig.h
@@ -0,0 +1,9 @@
+/* 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
diff --git a/drivers/staging/wilc1000/wilc_oswrapper.h b/drivers/staging/wilc1000/wilc_oswrapper.h
new file mode 100644
index 000000000..e97aa9600
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_oswrapper.h
@@ -0,0 +1,41 @@
+#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
+
+/* Os Configuration File */
+#include "wilc_osconfig.h"
+#include "wilc_platform.h"
+
+/* Logging Functions */
+#include "wilc_log.h"
+
+/* Error reporting and handling support */
+#include "wilc_errorsupport.h"
+
+/* Sleep support */
+#include "wilc_sleep.h"
+
+/* Timer support */
+#include "wilc_timer.h"
+
+/* Memory support */
+#include "wilc_memory.h"
+
+/* String Utilities */
+#include "wilc_strutils.h"
+
+/* Message Queue */
+#include "wilc_msgqueue.h"
+
+#endif
diff --git a/drivers/staging/wilc1000/wilc_platform.h b/drivers/staging/wilc1000/wilc_platform.h
new file mode 100644
index 000000000..d03532cc3
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_platform.h
@@ -0,0 +1,52 @@
+#ifndef __WILC_platfrom_H__
+#define __WILC_platfrom_H__
+
+#include <linux/kthread.h>
+#include <linux/semaphore.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/stat.h>
+#include <linux/time.h>
+#include <linux/version.h>
+#include "linux/string.h"
+/******************************************************************
+ * OS specific types
+ *******************************************************************/
+
+typedef struct timer_list WILC_TimerHandle;
+
+
+
+/* Message Queue type is a structure */
+typedef struct __Message_struct {
+ void *pvBuffer;
+ u32 u32Length;
+ struct __Message_struct *pstrNext;
+} Message;
+
+typedef struct __MessageQueue_struct {
+ struct semaphore hSem;
+ spinlock_t strCriticalSection;
+ bool bExiting;
+ u32 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__ __func__
+#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 000000000..897e47e31
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_sdio.c
@@ -0,0 +1,1254 @@
+/* ////////////////////////////////////////////////////////////////////////// */
+/* */
+/* 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, &reg)) {
+ 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_;
+ }
+ }
+
+ 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 (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_;
+ }
+ }
+
+ 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_;
+ }
+ }
+
+#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 (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_;
+ }
+ }
+
+ 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, &reg)) {
+ 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, &reg);
+ 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, &reg);
+ 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, &reg)) {
+ 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, &reg);
+ 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, &reg);
+ 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, &reg);
+ 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, &reg);
+ 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_sleep.c b/drivers/staging/wilc1000/wilc_sleep.c
new file mode 100644
index 000000000..adab3cac6
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_sleep.c
@@ -0,0 +1,18 @@
+
+#include "wilc_sleep.h"
+
+/*
+ * @author mdaftedar
+ * @date 10 Aug 2010
+ * @version 1.0
+ */
+void WILC_Sleep(u32 u32TimeMilliSec)
+{
+ if (u32TimeMilliSec <= 4000000) {
+ u32 u32Temp = u32TimeMilliSec * 1000;
+ usleep_range(u32Temp, u32Temp);
+ } else {
+ msleep(u32TimeMilliSec);
+ }
+
+}
diff --git a/drivers/staging/wilc1000/wilc_sleep.h b/drivers/staging/wilc1000/wilc_sleep.h
new file mode 100644
index 000000000..cf9047f70
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_sleep.h
@@ -0,0 +1,20 @@
+#ifndef __WILC_SLEEP_H__
+#define __WILC_SLEEP_H__
+
+#include <linux/types.h>
+#include <linux/delay.h>
+
+/*!
+ * @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
+ */
+/* TODO: remove and open-code in callers */
+void WILC_Sleep(u32 u32TimeMilliSec);
+
+#endif
diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c
new file mode 100644
index 000000000..abea5df65
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_spi.c
@@ -0,0 +1,1406 @@
+/* ////////////////////////////////////////////////////////////////////////// */
+/* */
+/* 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 <linux/kernel.h>
+ * #include <linux/string.h>
+ */
+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) (%zu)\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;
+ }
+
+ /**
+ * 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++];
+ }
+
+ 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 (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
+ **/
+ 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, &reg)) {
+ 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, &reg);
+ 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, &reg);
+ 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, &reg)) {
+ /* 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");
+ if (!spi_internal_read(WILC_SPI_PROTOCOL_OFFSET, &reg)) {
+ /* Reaad failed with both CRC on and off, something went bad */
+ PRINT_ER("[wilc spi]: Failed internal read protocol...\n");
+ 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, &reg);
+ 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, &reg);
+ 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, &reg);
+ 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, &reg);
+ 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 000000000..e0145953c
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_strutils.c
@@ -0,0 +1,80 @@
+
+#define _CRT_SECURE_NO_DEPRECATE
+
+#include "wilc_strutils.h"
+
+
+/*!
+ * @author syounan
+ * @date 18 Aug 2010
+ * @version 1.0
+ */
+s32 WILC_memcmp(const void *pvArg1, const void *pvArg2, u32 u32Count)
+{
+ return memcmp(pvArg1, pvArg2, u32Count);
+}
+
+
+/*!
+ * @author syounan
+ * @date 18 Aug 2010
+ * @version 1.0
+ */
+void WILC_memcpy_INTERNAL(void *pvTarget, const void *pvSource, u32 u32Count)
+{
+ memcpy(pvTarget, pvSource, u32Count);
+}
+
+/*!
+ * @author syounan
+ * @date 18 Aug 2010
+ * @version 1.0
+ */
+void *WILC_memset(void *pvTarget, u8 u8SetValue, u32 u32Count)
+{
+ return memset(pvTarget, u8SetValue, u32Count);
+}
+
+/*!
+ * @author syounan
+ * @date 18 Aug 2010
+ * @version 1.0
+ */
+char *WILC_strncpy(char *pcTarget, const char *pcSource,
+ u32 u32Count)
+{
+ return strncpy(pcTarget, pcSource, u32Count);
+}
+
+s32 WILC_strncmp(const char *pcStr1, const char *pcStr2,
+ u32 u32Count)
+{
+ s32 s32Result;
+
+ if (pcStr1 == NULL && pcStr2 == NULL) {
+ s32Result = 0;
+ } else if (pcStr1 == NULL) {
+ s32Result = -1;
+ } else if (pcStr2 == 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 18 Aug 2010
+ * @version 1.0
+ */
+u32 WILC_strlen(const char *pcStr)
+{
+ return (u32)strlen(pcStr);
+}
diff --git a/drivers/staging/wilc1000/wilc_strutils.h b/drivers/staging/wilc1000/wilc_strutils.h
new file mode 100644
index 000000000..d1445575a
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_strutils.h
@@ -0,0 +1,134 @@
+#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
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include "wilc_errorsupport.h"
+
+/*!
+ * @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
+ */
+s32 WILC_memcmp(const void *pvArg1, const void *pvArg2, u32 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, u32 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, u32 u32Count)
+{
+ if (
+ (((u8 *)pvTarget <= (u8 *)pvSource)
+ && (((u8 *)pvTarget + u32Count) > (u8 *)pvSource))
+
+ || (((u8 *)pvSource <= (u8 *)pvTarget)
+ && (((u8 *)pvSource + u32Count) > (u8 *)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, u8 u8SetValue, u32 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
+ */
+char *WILC_strncpy(char *pcTarget, const char *pcSource,
+ u32 u32Count);
+
+/*!
+ * @brief Compares two strings up to u32Count characters
+ * @details Compares 2 strings reporting which is bigger, 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, NULL is valid and considered smaller
+ * than any other non-NULL string (incliding zero lenght strings)
+ * @param[in] pcStr2 the second string, 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
+ */
+s32 WILC_strncmp(const char *pcStr1, const char *pcStr2,
+ u32 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
+ */
+u32 WILC_strlen(const char *pcStr);
+
+#endif
diff --git a/drivers/staging/wilc1000/wilc_timer.c b/drivers/staging/wilc1000/wilc_timer.c
new file mode 100644
index 000000000..dc71157f9
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_timer.c
@@ -0,0 +1,45 @@
+
+#include "wilc_timer.h"
+
+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, u32 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;
+}
diff --git a/drivers/staging/wilc1000/wilc_timer.h b/drivers/staging/wilc1000/wilc_timer.h
new file mode 100644
index 000000000..931269db3
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_timer.h
@@ -0,0 +1,129 @@
+#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
+ */
+
+#include "wilc_platform.h"
+#include "wilc_errorsupport.h"
+
+typedef void (*tpfWILC_TimerFunction)(void *);
+
+/*!
+ * @struct tstrWILC_TimerAttrs
+ * @brief Timer API options
+ * @author syounan
+ * @date 16 Aug 2010
+ * @version 1.0
+ */
+typedef struct {
+ /* a dummy member to avoid compiler errors*/
+ u8 dummy;
+} tstrWILC_TimerAttrs;
+
+/*!
+ * @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==false) or
+ * PENDING with same timeout value (if bPeriodicTimer==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, u32 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 000000000..5f36e7f92
--- /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 <stdint.h>
+#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 000000000..92064db9e
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
@@ -0,0 +1,3957 @@
+/*!
+ * @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 u16 Set_machw_change_vir_if(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];
+u32 u32LastScannedNtwrksCountShadow;
+#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
+WILC_TimerHandle hDuringIpTimer;
+#endif
+WILC_TimerHandle hAgingTimer;
+static u8 op_ifcs;
+extern u8 u8ConnectedSSID[6];
+
+/*BugID_5137*/
+u8 g_wilc_initialized = 1;
+extern linux_wlan_t *g_linux_wlan;
+#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
+extern 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*/
+u8 u8WLANChannel = INVALID_CHANNEL;
+
+/*BugID_5442*/
+u8 u8CurrChannel;
+
+u8 u8P2P_oui[] = {0x50, 0x6f, 0x9A, 0x09};
+u8 u8P2Plocalrandom = 0x01;
+u8 u8P2Precvrandom = 0x00;
+u8 u8P2P_vendorspec[] = {0xdd, 0x05, 0x00, 0x08, 0x40, 0x03};
+bool bWilc_ie = 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;
+ bool pairwise;
+ 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;
+u8 g_flushing_in_progress;
+bool g_ptk_keys_saved = false;
+bool g_gtk_keys_saved = false;
+bool g_wep_keys_saved = 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, 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, 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) {
+ s32 s32Freq;
+ struct ieee80211_channel *channel;
+
+ if (pstrNetworkInfo != NULL) {
+
+ s32Freq = ieee80211_channel_to_frequency((s32)pstrNetworkInfo->u8channel, IEEE80211_BAND_2GHZ);
+ channel = ieee80211_get_channel(wiphy, s32Freq);
+
+ rssi = get_rssi_avg(pstrNetworkInfo);
+ if (WILC_memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7) || bDirectScan) {
+ 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, (((s32)rssi) * 100), GFP_KERNEL);
+ cfg80211_put_bss(wiphy, bss);
+ }
+ }
+
+ }
+ }
+
+}
+
+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, 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 = 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, 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 =
+ (u8 *)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;
+ s32 s32Freq;
+ struct ieee80211_channel *channel;
+ s32 s32Error = WILC_SUCCESS;
+ struct cfg80211_bss *bss = NULL;
+
+ priv = (struct WILC_WFI_priv *)pUserVoid;
+ if (priv->bCfgScanning == 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
+ &&
+ ((((s32)pstrNetworkInfo->s8rssi) * 100) < 0
+ ||
+ (((s32)pstrNetworkInfo->s8rssi) * 100) > 100)
+ ) {
+ WILC_ERRORREPORT(s32Error, WILC_FAIL);
+ }
+
+ if (pstrNetworkInfo != NULL) {
+ s32Freq = ieee80211_channel_to_frequency((s32)pstrNetworkInfo->u8channel, IEEE80211_BAND_2GHZ);
+ 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, (((s32)pstrNetworkInfo->s8rssi) * 100),
+ pstrNetworkInfo->u16CapInfo, pstrNetworkInfo->u16BeaconPeriod);
+
+ if (pstrNetworkInfo->bNewNetwork == 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))) {
+ 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, (((s32)pstrNetworkInfo->s8rssi) * 100), GFP_KERNEL);
+ cfg80211_put_bss(wiphy, bss);
+ }
+
+
+ } else {
+ PRINT_ER("Discovered networks exceeded the max limit\n");
+ }
+ } else {
+ u32 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, 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");
+ }
+
+ down(&(priv->hSemScanReq));
+
+ if (priv->pstrScanReq != NULL) {
+ cfg80211_scan_done(priv->pstrScanReq, false);
+ priv->u32RcvdChCount = 0;
+ priv->bCfgScanning = false;
+ priv->pstrScanReq = NULL;
+ }
+ up(&(priv->hSemScanReq));
+
+ }
+ /*Aborting any scan operation during mac close*/
+ else if (enuScanEvent == SCAN_EVENT_ABORTED) {
+ down(&(priv->hSemScanReq));
+
+ PRINT_D(CFG80211_DBG, "Scan Aborted \n");
+ if (priv->pstrScanReq != NULL) {
+
+ update_scan_time(priv);
+ refresh_scan(priv, 1, false);
+
+ cfg80211_scan_done(priv->pstrScanReq, false);
+ priv->bCfgScanning = false;
+ priv->pstrScanReq = NULL;
+ }
+ up(&(priv->hSemScanReq));
+ }
+ }
+
+
+ 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(u8 *bssid, struct WILC_WFI_priv *priv)
+{
+ u32 i;
+ s32 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.
+ * u8 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,
+ u8 u8MacStatus,
+ tstrDisconnectNotifInfo *pstrDisconnectNotifInfo,
+ void *pUserVoid)
+{
+ struct WILC_WFI_priv *priv;
+ struct net_device *dev;
+ #ifdef WILC_P2P
+ tstrWILC_WFIDrv *pstrWFIDrv;
+ #endif
+ u8 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*/
+ u16 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) {
+ bool bNeedScanRefresh = false;
+ u32 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);
+
+ /* 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 = true;
+ }
+
+ break;
+ }
+ }
+
+ if (bNeedScanRefresh) {
+ /*BugID_5418*/
+ /*Also, refrsh DIRECT- results if */
+ refresh_scan(priv, 1, true);
+
+ }
+
+ }
+
+
+ PRINT_D(CFG80211_DBG, "Association request info elements length = %zu\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 = 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 = 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
+ */
+static int WILC_WFI_CfgSetChannel(struct wiphy *wiphy,
+ struct cfg80211_chan_def *chandef)
+{
+
+ u32 channelnum = 0;
+ struct WILC_WFI_priv *priv;
+ s32 s32Error = WILC_SUCCESS;
+ priv = wiphy_priv(wiphy);
+
+ 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);
+
+ 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
+ */
+static int WILC_WFI_CfgScan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
+{
+ struct WILC_WFI_priv *priv;
+ u32 i;
+ s32 s32Error = WILC_SUCCESS;
+ u8 au8ScanChanList[MAX_NUM_SCANNED_NETWORKS];
+ tstrHiddenNetwork strHiddenNetwork;
+
+ priv = wiphy_priv(wiphy);
+
+ priv->pstrScanReq = request;
+
+ priv->u32RcvdChCount = 0;
+
+ host_int_set_wfi_drv_handler((u32)priv->hWILCWFIDrv);
+
+
+ reset_shadow_found(priv);
+
+ priv->bCfgScanning = 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] = (u8)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 = %zu\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 u8 *)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 u8 *)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)
+{
+ s32 s32Error = WILC_SUCCESS;
+ u32 i;
+ u8 u8security = NO_ENCRYPT;
+ AUTHTYPE_T tenuAuth_type = ANY;
+ char *pcgroup_encrypt_val = NULL;
+ char *pccipher_group = NULL;
+ char *pcwpa_version = NULL;
+
+ 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((u32)priv->hWILCWFIDrv);
+
+ PRINT_D(CFG80211_DBG, "Connecting to SSID [%s] on netdev [%p] host if [%p]\n", sme->ssid, dev, 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);
+ if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) {
+ 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 = 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) {
+ 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 = 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) {
+ if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_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) {
+ 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";
+
+ } 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)
+{
+ s32 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 = 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,
+ bool pairwise,
+ const u8 *mac_addr, struct key_params *params)
+
+{
+ s32 s32Error = WILC_SUCCESS, KeyLen = params->key_len;
+ u32 i;
+ struct WILC_WFI_priv *priv;
+ const u8 *pu8RxMic = NULL;
+ const u8 *pu8TxMic = NULL;
+ u8 u8mode = NO_ENCRYPT;
+ #ifdef WILC_AP_EXTERNAL_MLME
+ u8 u8gmode = NO_ENCRYPT;
+ u8 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, "%p %p %d\n", wiphy, 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 = NULL;
+ priv->wilc_gtk[key_index]->seq = 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 = NULL;
+ priv->wilc_ptk[key_index]->seq = NULL;
+ }
+
+
+
+ if (!pairwise)
+ {
+ 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 = (u8 *)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 = (u8 *)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 = (u8 *)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 = (u8 *)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 (!pairwise)
+ {
+ 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;
+ g_add_gtk_key_params.pairwise = pairwise;
+ 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 = true;
+ }
+
+ host_int_add_rx_gtk(priv->hWILCWFIDrv, params->key, KeyLen,
+ key_index, params->seq_len, params->seq, pu8RxMic, pu8TxMic, STATION_MODE, u8mode);
+ } 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;
+ g_add_ptk_key_params.pairwise = pairwise;
+ 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 = 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,
+ bool pairwise,
+ const u8 *mac_addr)
+{
+ struct WILC_WFI_priv *priv;
+ s32 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 = false;
+ g_gtk_keys_saved = false;
+ g_wep_keys_saved = 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(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,
+ bool pairwise,
+ const u8 *mac_addr, void *cookie, void (*callback)(void *cookie, struct key_params *))
+{
+
+ s32 s32Error = WILC_SUCCESS;
+
+ struct WILC_WFI_priv *priv;
+ struct key_params key_params;
+ u32 i;
+ priv = wiphy_priv(wiphy);
+
+
+ if (!pairwise)
+ {
+ 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,
+ bool unicast, bool multicast)
+{
+ s32 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)
+{
+ s32 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,
+ const u8 *mac, struct station_info *sinfo)
+{
+ s32 s32Error = WILC_SUCCESS;
+ struct WILC_WFI_priv *priv;
+ perInterface_wlan_t *nic;
+ #ifdef WILC_AP_EXTERNAL_MLME
+ u32 i = 0;
+ u32 associatedsta = 0;
+ u32 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;
+ }
+
+ sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME);
+
+ 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
+ */
+ 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);
+
+ sinfo->signal = strStatistics.s8RSSI;
+ sinfo->rx_packets = strStatistics.u32RxCount;
+ sinfo->tx_packets = strStatistics.u32TxCount + strStatistics.u32TxFailureCount;
+ sinfo->tx_failed = strStatistics.u32TxFailureCount;
+ 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(true);
+ } else if (strStatistics.u8LinkSpeed != DEFAULT_LINK_SPEED) {
+ Enable_TCP_ACK_Filter(false);
+ }
+#endif
+
+ 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);
+ }
+ 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)
+{
+ s32 s32Error = WILC_SUCCESS;
+ tstrCfgParamVal pstrCfgParamVal;
+ struct WILC_WFI_priv *priv;
+
+ priv = wiphy_priv(wiphy);
+
+ 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;
+}
+
+/**
+ * @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)
+{
+ s32 s32Error = WILC_SUCCESS;
+
+ PRINT_D(CFG80211_DBG, "Setting Bitrate mask function\n");
+ 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)
+{
+ u32 i;
+ s32 s32Error = WILC_SUCCESS;
+ u8 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)
+{
+
+ u32 i;
+ u8 flag = 0;
+ s32 s32Error = WILC_SUCCESS;
+
+ struct WILC_WFI_priv *priv = wiphy_priv(wiphy);
+
+ 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);
+
+ 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;
+}
+
+#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(u8 *buf, u32 len)
+{
+ u32 index = 0;
+ u32 i = 0, j = 0;
+
+ /*BugID_5460*/
+ #ifdef USE_SUPPLICANT_GO_INTENT
+ u8 intent;
+ u8 tie_breaker;
+ bool is_wilc_go = true;
+ #endif
+ u8 op_channel_attr_index = 0;
+ u8 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 = false;
+ } else {
+ PRINT_D(GENERIC_DBG, "WILC will be GO (intent %d tie breaker %d)\n", intent, tie_breaker);
+ is_wilc_go = 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 = 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(u8 *buf, u32 len, bool bOperChan, u8 iftype)
+{
+ u32 index = 0;
+ u32 i = 0, j = 0;
+
+ u8 op_channel_attr_index = 0;
+ u8 channel_list_attr_index = 0;
+ #ifdef USE_SUPPLICANT_GO_INTENT
+ bool is_wilc_go = 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 = 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;
+ u32 header, pkt_offset;
+ tstrWILC_WFIDrv *pstrWFIDrv;
+ u32 i = 0;
+ s32 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");
+ cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL);
+ 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]);
+ cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL);
+ } 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]);
+ cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, false, GFP_KERNEL);
+ }
+ 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*/
+ s32Freq = ieee80211_channel_to_frequency(u8CurrChannel, IEEE80211_BAND_2GHZ);
+
+ 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 == true && time_after_eq(jiffies, (unsigned long)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 = 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 */
+ cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0);
+ return;
+ }
+ break;
+
+ default:
+ PRINT_D(GENERIC_DBG, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buff[ACTION_SUBTYPE_ID]);
+ break;
+ }
+ }
+ }
+
+ cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0);
+ }
+}
+
+/**
+ * @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 = true;
+
+ cfg80211_ready_on_channel(priv->wdev,
+ priv->strRemainOnChanParams.u64ListenCookie,
+ priv->strRemainOnChanParams.pstrListenChan,
+ priv->strRemainOnChanParams.u32ListenDuration,
+ GFP_KERNEL);
+}
+
+/**
+ * @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, u32 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 = false;
+
+ /*Inform wpas of remain-on-channel expiration*/
+ cfg80211_remain_on_channel_expired(priv->wdev,
+ priv->strRemainOnChanParams.u64ListenCookie,
+ priv->strRemainOnChanParams.pstrListenChan,
+ GFP_KERNEL);
+ } 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,
+ struct wireless_dev *wdev,
+ struct ieee80211_channel *chan,
+ unsigned int duration, u64 *cookie)
+{
+ s32 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 (wdev->iftype == NL80211_IFTYPE_AP) {
+ PRINT_D(GENERIC_DBG, "Required remain-on-channel while in AP mode");
+ return s32Error;
+ }
+
+ u8CurrChannel = chan->hw_value;
+
+ /*Setting params needed by WILC_WFI_RemainOnChannelExpired()*/
+ priv->strRemainOnChanParams.pstrListenChan = chan;
+ priv->strRemainOnChanParams.u64ListenCookie = *cookie;
+ 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,
+ struct wireless_dev *wdev,
+ u64 cookie)
+{
+ s32 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] u8 * buf
+ * @return void
+ * @author mdaftedar
+ * @date 01 JAN 2014
+ * @version 1.0
+ */
+void WILC_WFI_add_wilcvendorspec(u8 *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 bool bEnablePS;
+int WILC_WFI_mgmt_tx(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ struct cfg80211_mgmt_tx_params *params,
+ u64 *cookie)
+{
+ struct ieee80211_channel *chan = params->chan;
+ unsigned int wait = params->wait;
+ const u8 *buf = params->buf;
+ size_t len = params->len;
+ const struct ieee80211_mgmt *mgmt;
+ struct p2p_mgmt_data *mgmt_tx;
+ struct WILC_WFI_priv *priv;
+ s32 s32Error = WILC_SUCCESS;
+ tstrWILC_WFIDrv *pstrWFIDrv;
+ u32 i;
+ perInterface_wlan_t *nic;
+ u32 buf_len = len + sizeof(u8P2P_vendorspec) + sizeof(u8P2Plocalrandom);
+
+ nic = netdev_priv(wdev->netdev);
+ 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", (u16)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), 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), 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,
+ struct wireless_dev *wdev,
+ 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 == 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 */
+ cfg80211_remain_on_channel_expired(priv->wdev,
+ priv->strRemainOnChanParams.u64ListenCookie,
+ priv->strRemainOnChanParams.pstrListenChan,
+ GFP_KERNEL);
+ }
+
+ return 0;
+}
+
+/**
+ * @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,
+ struct wireless_dev *wdev,
+ 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 /*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);
+
+ sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
+
+ host_int_get_rssi(priv->hWILCWFIDrv, &(sinfo->signal));
+
+ 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 == NULL)
+ return -ENOENT;
+
+ priv = wiphy_priv(wiphy);
+ if (priv->hWILCWFIDrv == NULL) {
+ PRINT_ER("Driver is NULL\n");
+ return -EIO;
+ }
+
+ if (bEnablePS)
+ 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)
+{
+ s32 s32Error = WILC_SUCCESS;
+ struct WILC_WFI_priv *priv;
+ perInterface_wlan_t *nic;
+ u8 interface_type;
+ u16 TID = 0;
+ #ifdef WILC_P2P
+ u8 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 = false;
+
+ #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
+ g_obtainingIP = false;
+ WILC_TimerStop(&hDuringIpTimer, 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(true);
+ }
+
+ switch (type) {
+ case NL80211_IFTYPE_STATION:
+ connecting = 0;
+ PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_STATION\n");
+
+ /* 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,
+ g_add_ptk_key_params.pairwise,
+ 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,
+ g_add_gtk_key_params.pairwise,
+ 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 = true;
+ host_int_set_power_mgmt(priv->hWILCWFIDrv, 1, 0);
+ }
+ #endif
+ #endif
+ break;
+
+ case NL80211_IFTYPE_P2P_CLIENT:
+ bEnablePS = false;
+ host_int_set_power_mgmt(priv->hWILCWFIDrv, 0, 0);
+ connecting = 0;
+ PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_P2P_CLIENT\n");
+
+ 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,
+ g_add_ptk_key_params.pairwise,
+ 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,
+ g_add_gtk_key_params.pairwise,
+ 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, true);
+ Set_machw_change_vir_if(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:
+ bEnablePS = false;
+ PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_AP %d\n", type);
+ dev->ieee80211_ptr->iftype = type;
+ priv->wdev->iftype = type;
+ nic->iftype = AP_MODE;
+ PRINT_D(CORECONFIG_DBG, "priv->hWILCWFIDrv[%p]\n", 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);
+
+ /*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 = true;
+ WILC_TimerStart(&hDuringIpTimer, duringIP_TIME, NULL, 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 = false;
+ PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_GO\n");
+ dev->ieee80211_ptr->iftype = type;
+ priv->wdev->iftype = type;
+
+ PRINT_D(CORECONFIG_DBG, "priv->hWILCWFIDrv[%p]\n", priv->hWILCWFIDrv);
+
+ #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();
+ wilc1000_wlan_deinit(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,
+ g_add_ptk_key_params.pairwise,
+ 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,
+ g_add_gtk_key_params.pairwise,
+ 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;
+}
+
+/* (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;
+ s32 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 = %zu Tail length = %zu\n",
+ settings->beacon_interval, settings->dtim_period, beacon->head_len, beacon->tail_len);
+
+ s32Error = WILC_WFI_CfgSetChannel(wiphy, &settings->chandef);
+
+ if (s32Error != WILC_SUCCESS)
+ PRINT_ER("Error in setting channel\n");
+
+ 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, (u8 *)beacon->head,
+ beacon->tail_len, (u8 *)beacon->tail);
+ #else
+ s32Error = host_add_beacon(priv->hWILCWFIDrv,
+ settings->beacon_interval,
+ settings->dtim_period,
+ beacon->head_len, (u8 *)beacon->head,
+ beacon->tail_len, (u8 *)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;
+ s32 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, (u8 *)beacon->head,
+ beacon->tail_len, (u8 *)beacon->tail);
+#else
+ s32Error = host_add_beacon(priv->hWILCWFIDrv,
+ 0,
+ 0,
+ beacon->head_len, (u8 *)beacon->head,
+ beacon->tail_len, (u8 *)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)
+{
+ s32 s32Error = WILC_SUCCESS;
+ struct WILC_WFI_priv *priv;
+ u8 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;
+}
+
+/**
+ * @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,
+ const u8 *mac, struct station_parameters *params)
+{
+ s32 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 == NULL) {
+ strStaParams.bIsHTSupported = false;
+ } else {
+ strStaParams.bIsHTSupported = true;
+ strStaParams.u16HTCapInfo = params->ht_capa->cap_info;
+ strStaParams.u8AmpduParams = params->ht_capa->ampdu_params_info;
+ WILC_memcpy(strStaParams.au8SuppMCsSet, &params->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,
+ struct station_del_parameters *params)
+{
+ const u8 *mac = params->mac;
+ s32 s32Error = WILC_SUCCESS;
+ struct WILC_WFI_priv *priv;
+ 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) {
+ PRINT_D(HOSTAPD_DBG, "Deleting station\n");
+
+
+ if (mac == 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,
+ const u8 *mac, struct station_parameters *params)
+{
+ s32 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 == NULL) {
+ strStaParams.bIsHTSupported = false;
+ } else {
+ strStaParams.bIsHTSupported = true;
+ strStaParams.u16HTCapInfo = params->ht_capa->cap_info;
+ strStaParams.u8AmpduParams = params->ht_capa->ampdu_params_info;
+ WILC_memcpy(strStaParams.au8SuppMCsSet, &params->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
+ */
+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)
+{
+ perInterface_wlan_t *nic;
+ struct WILC_WFI_priv *priv;
+ 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 ");
+ }
+ return priv->wdev;
+}
+
+/**
+ * @brief WILC_WFI_del_virt_intf
+ * @details
+ * @param[in]
+ * @return int : Return 0 on Success.
+ * @author mdaftedar
+ * @date 01 JUL 2012
+ * @version 1.0
+ */
+int WILC_WFI_del_virt_intf(struct wiphy *wiphy, struct wireless_dev *wdev) /* tony for v3.8 support */
+{
+ PRINT_D(HOSTAPD_DBG, "Deleting virtual interface\n");
+ return WILC_SUCCESS;
+}
+
+
+
+#endif /*WILC_AP_EXTERNAL_MLME*/
+static struct cfg80211_ops WILC_WFI_cfg80211_ops = {
+
+ .set_monitor_channel = WILC_WFI_CfgSetChannel,
+ .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,
+ #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,
+
+ .start_ap = WILC_WFI_start_ap,
+ .change_beacon = WILC_WFI_change_beacon,
+ .stop_ap = WILC_WFI_stop_ap,
+ .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,
+ .set_wiphy_params = WILC_WFI_set_wiphy_params,
+
+ .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,
+ .mgmt_tx = WILC_WFI_mgmt_tx,
+ .mgmt_frame_register = WILC_WFI_frame_register,
+ .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);
+#if 1
+ switch (changed) {
+
+ case WILC_WFI_RX_PKT:
+ {
+ 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;
+ }
+#endif
+ return 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;
+ s32 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);
+ sema_init(&(priv->SemHandleUpdateStats), 1);
+
+ /*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;
+ /*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);
+
+ 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);
+ /*Setting default managment types: for register action frame: */
+ wdev->wiphy->mgmt_stypes = wilc_wfi_cfg80211_mgmt_types;
+
+#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);
+ wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+#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");
+ }
+
+ priv->dev = net;
+ 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)
+{
+
+ s32 s32Error = WILC_SUCCESS;
+
+ struct WILC_WFI_priv *priv;
+
+ 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, NULL);
+ #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
+ s32Error = WILC_TimerCreate(&(hDuringIpTimer), clear_duringIP, NULL);
+ #endif
+ }
+ op_ifcs++;
+ if (s32Error < 0) {
+ PRINT_ER("Failed to creat refresh Timer\n");
+ return s32Error;
+ }
+
+ priv->gbAutoRateAdjusted = false;
+
+ priv->bInP2PlistenState = false;
+
+ sema_init(&(priv->hSemScanReq), 1);
+ s32Error = host_int_init(&priv->hWILCWFIDrv);
+ 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)
+{
+ s32 s32Error = WILC_SUCCESS;
+
+ struct WILC_WFI_priv *priv;
+ priv = wdev_priv(net->ieee80211_ptr);
+
+ priv->gbAutoRateAdjusted = false;
+
+ priv->bInP2PlistenState = false;
+
+ op_ifcs--;
+
+ s32Error = host_int_deinit(priv->hWILCWFIDrv);
+
+ /* 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, 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 000000000..c25350cb5
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h
@@ -0,0 +1,129 @@
+/*!
+ * @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)
+
+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,
+};
+
+static const struct ieee80211_txrx_stypes
+ wilc_wfi_cfg80211_mgmt_types[NUM_NL80211_IFTYPES] = {
+ [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)
+ }
+};
+
+/* 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(const 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(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 000000000..ab66ce4bd
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.c
@@ -0,0 +1,951 @@
+/*!
+ * @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;
+ }
+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 = 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 000000000..d413fa386
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
@@ -0,0 +1,254 @@
+/*!
+ * @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 <linux/module.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/slab.h> /* kmalloc() */
+#include <linux/errno.h> /* error codes */
+#include <linux/types.h> /* size_t */
+#include <linux/interrupt.h> /* mark_bh */
+#include <linux/time.h>
+#include <linux/in.h>
+#include <linux/netdevice.h> /* struct device, and other headers */
+#include <linux/etherdevice.h> /* eth_type_trans */
+#include <linux/ip.h> /* struct iphdr */
+#include <linux/tcp.h> /* struct tcphdr */
+#include <linux/skbuff.h>
+#include <linux/ieee80211.h>
+#include <net/cfg80211.h>
+#include <linux/ieee80211.h>
+#include <net/cfg80211.h>
+#include <net/ieee80211_radiotap.h>
+#include <linux/if_arp.h>
+#include <linux/in6.h>
+#include <asm/checksum.h>
+#include "host_interface.h"
+#include "wilc_wlan.h"
+#include <linux/wireless.h> /* tony, 2013-06-12 */
+
+#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 {
+ u8 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;
+ u32 u32ListenDuration;
+ u64 u64ListenCookie;
+ u32 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;
+ u64 u64tx_cookie;
+ #endif
+
+ bool bCfgScanning;
+ u32 u32RcvdChCount;
+
+ u8 au8AssociatedBss[ETH_ALEN];
+ struct sta_info assoc_stainfo;
+ struct net_device_stats stats;
+ u8 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;
+ u8 WILC_WFI_wep_default;
+ u8 WILC_WFI_wep_key[4][WLAN_KEY_LEN_WEP104];
+ u8 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];
+ u8 wilc_groupkey;
+ /* semaphores */
+ struct semaphore SemHandleUpdateStats;
+ struct semaphore hSemScanReq;
+ /* */
+ bool gbAutoRateAdjusted;
+
+ bool bInP2PlistenState;
+
+};
+
+typedef struct {
+ u16 frame_type;
+ 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;
+ u8 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 000000000..3af91f770
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_wlan.c
@@ -0,0 +1,2332 @@
+/* ////////////////////////////////////////////////////////////////////////// */
+/* */
+/* 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 u8 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);
+u16 Set_machw_change_vir_if(bool bValue);
+
+
+
+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; */
+ 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;
+
+}
+
+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) {
+ 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*/
+
+
+
+ } 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);
+
+ if (p->txq_head == NULL) {
+ tqe->next = NULL;
+ tqe->prev = NULL;
+ p->txq_head = tqe;
+ p->txq_tail = tqe;
+ } 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);
+
+ /*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);
+
+ 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);
+
+ /*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");
+
+ /*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;
+} Ack_session_info_t;
+
+typedef struct {
+ uint32_t ack_num;
+ uint32_t Session_index;
+ struct txq_entry_t *txqe;
+} 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)
+{
+
+ return 0;
+
+}
+static __inline int add_TCP_track_session(uint32_t src_prt, uint32_t dst_prt, uint32_t seq)
+{
+ Acks_keep_track_info[Opened_TCP_session].Ack_seq_num = seq;
+ Acks_keep_track_info[Opened_TCP_session].Bigger_Ack_num = 0;
+ Acks_keep_track_info[Opened_TCP_session].src_port = src_prt;
+ Acks_keep_track_info[Opened_TCP_session].dst_port = dst_prt;
+ Opened_TCP_session++;
+
+ PRINT_D(TCP_ENH, "TCP Session %d to Ack %d\n", Opened_TCP_session, seq);
+ return 0;
+}
+
+static __inline int Update_TCP_track_session(uint32_t index, uint32_t Ack)
+{
+
+ if (Ack > 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 *)&eth_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++;
+ }
+ }
+ }
+ 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
+bool EnableTCPAckFilter = false;
+
+void Enable_TCP_ACK_Filter(bool value)
+{
+ EnableTCPAckFilter = value;
+}
+
+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;
+ 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())
+#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);
+
+ tqe = p->txq_head;
+
+ /*Added by Amr - BugID_4720*/
+ p->os_func.os_spin_unlock(p->txq_spinlock, &flags);
+
+
+ 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);
+
+ tqe = tqe->next;
+ /*Added by Amr - BugID_4720*/
+ p->os_func.os_spin_unlock(p->txq_spinlock, &flags);
+
+
+ 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, &reg);
+
+ 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, &reg);
+ /* 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(true) == 0)) {
+ wilc_debug(N_ERR, "Couldn't read chip id. Wake up failed\n");
+ }
+ } while ((wilc_get_chipid(true) == 0) && ((++trials % 3) == 0));
+
+ } while (wilc_get_chipid(true) == 0);
+ } else if ((g_wlan.io_func.io_type & 0x1) == HIF_SDIO) {
+ g_wlan.hif_func.hif_read_reg(0xf0, &reg);
+ 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);
+ reg &= ~(1 << 0);
+ g_wlan.hif_func.hif_write_reg(0x1C0C, reg);
+
+ if (wilc_get_chipid(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, &reg);
+ /* 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, &reg);
+ 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*/
+ 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(true) == 0)) {
+ wilc_debug(N_ERR, "Couldn't read chip id. Wake up failed\n");
+ }
+ } while ((wilc_get_chipid(true) == 0) && ((++trials % 3) == 0));
+
+ } while (wilc_get_chipid(true) == 0);
+
+ if (genuChipPSstate == CHIP_SLEEPING_MANUAL) {
+ g_wlan.hif_func.hif_read_reg(0x1C0C, &reg);
+ reg &= ~(1 << 0);
+ g_wlan.hif_func.hif_write_reg(0x1C0C, reg);
+
+ if (wilc_get_chipid(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(u32 u32SleepTime)
+{
+ 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
+
+ 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, &reg);
+ 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, &reg);
+ 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, &reg);
+ 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
+
+#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);
+ /*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
+ {
+
+ 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);
+ }
+ } 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(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, &reg);
+ 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_read_reg(WILC_GLB_RESET_0, &reg);
+ 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);
+ }
+
+ 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, &reg);
+ 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, &reg);
+ 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, &reg);
+ 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, &reg);
+ 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;
+ 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 = NULL;
+ }
+ #endif
+ if (p->tx_buffer) {
+ p->os_func.os_free(p->tx_buffer);
+ p->tx_buffer = NULL;
+ }
+#endif
+
+ acquire_bus(ACQUIRE_AND_WAKEUP);
+
+
+ ret = p->hif_func.hif_read_reg(WILC_GP_REG_0, &reg);
+ 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 = (u32)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(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, &reg);
+ 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;
+ }
+ }
+
+ 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, &reg_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
+ /***
+ * 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 == 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 = %p\n", g_wlan.tx_buffer);
+
+ if (g_wlan.tx_buffer == 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 == 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 =%p\n", g_wlan.rx_buffer);
+ if (g_wlan.rx_buffer == 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_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 = NULL;
+ }
+ #endif
+ if (g_wlan.tx_buffer) {
+ g_wlan.os_func.os_free(g_wlan.tx_buffer);
+ g_wlan.tx_buffer = 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)
+u16 Set_machw_change_vir_if(bool bValue)
+{
+ u16 ret;
+ u32 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, &reg);
+ if (!ret) {
+ PRINT_ER("Error while Reading reg WILC_CHANGING_VIR_IF\n");
+ }
+
+ if (bValue) {
+ 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(u16 *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 000000000..0ba7ec69e
--- /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 000000000..3cffe55b3
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_wlan_cfg.c
@@ -0,0 +1,617 @@
+/* ////////////////////////////////////////////////////////////////////////// */
+/* */
+/* 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, 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);
+
+ 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;
+}
+
+/********************************************
+ *
+ * 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
+ u32 *ptru32Frame;
+ 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 000000000..8906611b2
--- /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 000000000..8ed51e385
--- /dev/null
+++ b/drivers/staging/wilc1000/wilc_wlan_if.h
@@ -0,0 +1,969 @@
+/* ////////////////////////////////////////////////////////////////////////// */
+/* */
+/* 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 *, u32);
+ 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;
+
+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 ((u32)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