summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/nmi_android4.4_driver/src/driver/linux')
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/Makefile177
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/allwinner_run_eval.sh4
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/ap_soft.conf30
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/include/NMI_WFI_CfgOperations.h105
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/include/NMI_WFI_NetDevice.h304
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/init_deinit_test.sh51
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/nmi_wfi_load10
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/nmi_wfi_unload6
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/panda_run_eval.sh7
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/panda_run_fpga.sh4
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/NMI_WFI_CfgOperations.c4503
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/NMI_WFI_NetDevice.c969
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_mon.c693
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_wlan.c3332
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_wlan_sdio.c277
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_wlan_sdio.h14
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_wlan_spi.c489
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_wlan_spi.h14
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/nmi_custom_gpio.c169
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/nmi_debugfs.c264
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/nmi_queue.c235
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/nmi_queue.h56
-rwxr-xr-xdrivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/nmi_wm8880_gpio.c87
23 files changed, 11800 insertions, 0 deletions
diff --git a/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/Makefile b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/Makefile
new file mode 100755
index 00000000..657a007a
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/Makefile
@@ -0,0 +1,177 @@
+# Comment/uncomment the following line to disable/enable debugging
+MAKE = make
+RM = rm
+MV = mv
+ECHO = echo
+CP = cp
+
+
+#DEBUG = y
+# Add your debugging flag (or not) to CFLAGS
+ifeq ($(DEBUG),y)
+DEBFLAGS = -O -g
+else
+DEBFLAGS = -O2
+endif
+
+#Use external 1.4V VCO
+EXTRA_CFLAGS += -DVCO_14_SUPPLY
+#EXTRA_CFLAGS += -DREG_0XF6_NOT_CLEAR_BUG_FIX
+
+EXTRA_CFLAGS += -DDISABLE_PWRSAVE_AND_SCAN_DURING_IP
+EXTRA_CFLAGS += -DAGING_ALG
+
+#Default to NMI=EVAL if NMI isn't defined
+ifeq ($(strip $(NMI)),)
+NMI=EVAL
+endif
+
+ifeq ($(NMI),EVAL)
+EXTRA_CFLAGS += -DNMC_ASIC_A0
+else ifeq ($(NMI),FPGA)
+endif
+
+EXTRA_CFLAGS += -DCONNECT_DIRECT -DNMI_PARSE_SCAN_IN_HOST
+
+ifeq ($(BUS),SDIO)
+EXTRA_CFLAGS += -DNMI_SDIO
+endif
+
+ifeq ($(SDIO_IRQ),GPIO)
+EXTRA_CFLAGS += -DNMI_SDIO_IRQ_GPIO
+endif
+
+ifeq ($(DMA_VER),VER_1)
+EXTRA_CFLAGS += -DUSE_DMA_VER_1
+endif
+
+ifeq ($(TARGET),SIMULATION)
+KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+TARGET=SIMULATION
+EXTRA_CFLAGS += -DSIMULATION -g
+OUT_ARCH = x86
+else ifeq ($(TARGET),PANDA)
+KERNELDIR ?= $(DEV_TREE)/kernel/omap
+EXTRA_CFLAGS += -DPANDA_BOARD -DUSE_WIRELESS
+ifeq ($(ANDR_VER),4.3)
+MAKE_FLAGS := CROSS_COMPILE=$(DEV_TREE)/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7/bin/arm-eabi- ARCH=arm
+else ifeq ($(ANDR_VER),4.2)
+MAKE_FLAGS := CROSS_COMPILE=$(DEV_TREE)/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi- ARCH=arm
+else
+MAKE_FLAGS := CROSS_COMPILE=$(DEV_TREE)/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi- ARCH=arm
+endif
+OUT_ARCH = ARM-3.0
+#EXTRA_CFLAGS += -DSIMULATION
+else ifeq ($(TARGET),BEAGLE)
+KERNELDIR ?= $(DEV_TREE)
+OUT_ARCH = ARM-2.6.39
+MAKE_FLAGS := CROSS_COMPILE=arm-arago-linux-gnueabi- ARCH=arm
+EXTRA_CFLAGS += -DBEAGLE_BOARD
+KERNELDIR ?= $(DEV_TREE)
+else ifeq ($(TARGET),NM73131)
+KERNELDIR ?= $(DEV_TREE_LPC)
+OUT_ARCH = ARM-2.6.28.2
+MAKE_FLAGS := CROSS_COMPILE=arm-linux- ARCH=arm
+EXTRA_CFLAGS += -DNM73131_0_BOARD
+else ifeq ($(TARGET),ALLWINNER)
+KERNELDIR ?= $(DEV_TREE)/linux-3.0
+MAKE_FLAGS := CROSS_COMPILE=$(DEV_TREE)/buildroot/output/external-toolchain/bin/arm-none-linux-gnueabi- ARCH=arm
+EXTRA_CFLAGS += -DALLWINNER_BOARD -DUSE_WIRELESS
+OUT_ARCH = ARM-3.0
+else ifeq ($(TARGET),ALLWINNER_A20)
+KERNELDIR ?= $(DEV_TREE)/linux-3.3
+MAKE_FLAGS := CROSS_COMPILE=$(DEV_TREE)/out/android/common/buildroot/external-toolchain/bin/arm-linux-gnueabi- ARCH=arm
+EXTRA_CFLAGS += -DPLAT_ALLWINNER_A20 -DUSE_WIRELESS
+OUT_ARCH = ARM-3.3
+else ifeq ($(TARGET),ALLWINNER_A23)
+KERNELDIR ?= $(DEV_TREE)/linux-3.4
+MAKE_FLAGS := CROSS_COMPILE=$(DEV_TREE)/out/android/common/buildroot/external-toolchain/bin/arm-linux-gnueabi- ARCH=arm
+EXTRA_CFLAGS += -DPLAT_ALLWINNER_A23 -DUSE_WIRELESS
+OUT_ARCH = ARM-3.4
+else
+KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+OUT_ARCH = x86
+TARGET=SIMULATION
+EXTRA_CFLAGS += -DSIMULATION
+endif
+
+ifeq ($(FIRMLOG),HOST)
+ EXTRA_CFLAGS += -DSWITCH_LOG_TERMINAL
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS) -I $(PWD)/../../NMI_OsWrapper/include/
+EXTRA_CFLAGS += -I $(PWD)/../../ -I $(PWD)/../include -I $(PWD)/../ -I $(PWD)/include
+EXTRA_CFLAGS += -DNMI_PLATFORM=NMI_LINUXKERNEL
+EXTRA_CFLAGS += -Wno-unused-function
+
+
+
+obj-m := nmi_wifi.o
+ifeq ($(TARGET),NM73131)
+ifeq ($(BUS),SDIO)
+nmi_wifi-objs := source/linux_wlan.o source/linux_wlan_sdio.o\
+source/nmi_debugfs.o source/nmi_queue.o\
+../binary/linux/$(OUT_ARCH)/NMI_WiFi_Driver.a\
+../../NMI_OsWrapper/binary/linux/$(OUT_ARCH)/NMI_OsWrapper.a
+else
+nmi_wifi-objs := source/linux_wlan.o source/linux_wlan_spi.o\
+source/nmi_debugfs.o source/nmi_queue.o\
+../binary/linux/$(OUT_ARCH)/NMI_WiFi_Driver.a\
+../../NMI_OsWrapper/binary/linux/$(OUT_ARCH)/NMI_OsWrapper.a
+endif
+
+else
+
+ifeq ($(BUS),SDIO)
+nmi_wifi-objs := source/NMI_WFI_NetDevice.o source/NMI_WFI_CfgOperations.o\
+source/linux_wlan.o source/linux_wlan_sdio.o source/linux_mon.o\
+source/nmi_debugfs.o source/nmi_queue.o\
+../binary/linux/$(OUT_ARCH)/NMI_WiFi_Driver.a\
+../../NMI_OsWrapper/binary/linux/$(OUT_ARCH)/NMI_OsWrapper.a
+else
+nmi_wifi-objs := source/NMI_WFI_NetDevice.o source/NMI_WFI_CfgOperations.o\
+source/linux_wlan.o source/linux_wlan_spi.o source/linux_mon.o\
+source/nmi_debugfs.o source/nmi_queue.o\
+../binary/linux/$(OUT_ARCH)/NMI_WiFi_Driver.a\
+../../NMI_OsWrapper/binary/linux/$(OUT_ARCH)/NMI_OsWrapper.a
+endif
+
+endif
+
+ifneq ($(KERNELRELEASE),)
+# call from kernel build system
+
+
+else
+
+#KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+PWD := $(shell pwd)
+
+default:
+ echo KERNELDIR = $(KERNELDIR)
+ $(MAKE) TARGET=$(TARGET) NMI=$(NMI) BUS=$(BUS) FULLY_HOSTING_AP=$(FULLY_HOSTING_AP) -C ../
+ @$(ECHO) "###########################################"
+ @$(ECHO) "##### Building NMI WiFi for Linux ######"
+ @$(ECHO) "##### TARGET =" $(TARGET) "######"
+ $(MAKE) -C $(KERNELDIR) M=$(PWD) modules $(MAKE_FLAGS)
+ mkdir -p binary/linux/$(OUT_ARCH)
+ $(MV) -f $(PWD)/nmi_wifi.ko binary/linux/$(OUT_ARCH)/nmi_wifi.ko
+
+endif
+
+clean:
+ $(MAKE) TARGET=$(TARGET) NMI=$(NMI) BUS=$(BUS) -C ../ clean
+ @$(ECHO) "###########################################"
+ @$(ECHO) "##### Cleaning NMI WiFi for Linux ######"
+ @$(ECHO) "##### TARGET =" $(TARGET) "######"
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) clean
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
+ rm -rf binary/linux/$(OUT_ARCH)/nmi_wifi.ko
+
+depend .depend dep:
+ $(CC) $(CFLAGS) -M *.c > .depend
+
+
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
diff --git a/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/allwinner_run_eval.sh b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/allwinner_run_eval.sh
new file mode 100755
index 00000000..879a98fc
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/allwinner_run_eval.sh
@@ -0,0 +1,4 @@
+adb push ../../core/wifi_v111/ASIC_A0/wifi_firmware.bin /system/vendor/firmware/wifi_firmware.bin
+adb push binary/linux/ARM-3.0/nmi_wifi.ko /system/vendor/modules/nmi_wifi.ko
+adb shell "echo 0 > /proc/driver/sunxi-mmc.3/insert"
+adb shell "echo 1 > /proc/driver/sunxi-mmc.3/insert" \ No newline at end of file
diff --git a/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/ap_soft.conf b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/ap_soft.conf
new file mode 100755
index 00000000..b23dbf50
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/ap_soft.conf
@@ -0,0 +1,30 @@
+interface=p2p0
+dump_file=/data/misc/wifi/hostapd.dump
+driver=nl80211
+ctrl_interface=/data/misc/wifi/hostapd
+ssid=HOSTAPD
+dtim_period=2
+beacon_int=100
+channel=6
+hw_mode=g
+ieee80211n=1
+#require_ht=1
+ht_capab=[RX-STBC01]
+max_num_sta=8
+#wmm_enabled=1
+#auth_algs=1
+ap_max_inactivity=300
+#wpa=2
+#wpa_passphrase=12345678
+#wpa_key_mgmt=WPA-PSK
+#wpa_pairwise= CCMP
+#rsn_pairwise=CCMP
+#auth_algs=3
+#ignore_broadcast_ssid=0
+#wep_default_key=0
+#wep_key0=1234567890
+#wep_key0=000102030405060708090a0b0c
+#wep_key0=0102030405060708090a0b0c0d
+#wep_key0=1234567890abcdef1234567890
+#wep_key_len_broadcast=10
+#wep_key_len_unicast=10
diff --git a/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/include/NMI_WFI_CfgOperations.h b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/include/NMI_WFI_CfgOperations.h
new file mode 100755
index 00000000..f5637324
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/include/NMI_WFI_CfgOperations.h
@@ -0,0 +1,105 @@
+/*!
+* @file NMI_WFI_CfgOperations.h
+* @brief Definitions for the network module
+* @author syounan
+* @sa NMI_OSWrapper.h top level OS wrapper file
+* @date 31 Aug 2010
+* @version 1.0
+*/
+#ifndef NM_WFI_CFGOPERATIONS
+#define NM_WFI_CFGOPERATIONS
+#include "linux/include/NMI_WFI_NetDevice.h"
+
+#ifdef NMI_FULLY_HOSTING_AP
+#include "NMI_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 NMI_P2P
+#define GO_INTENT_ATTR_ID 0x04
+#define CHANNEL_LIST_ATTR_ID 0x0b
+#define GO_NEG_REQ_ATTR_ID 0x00
+#define GO_NEG_RSP_ATTR_ID 0x01
+#define P2P_INVITE_REQ 0x03
+#define P2P_INVITE_RSP 0x04
+#define ACTION_FRAME 0xd0
+#define PUBLICACTION_CAT 0x04
+#define PUBLICACTION_FRAME 0x09
+#define DEFAULT_CHANNEL 7
+#define P2PELEM_ID 0xdd
+#define GO_INTENT_ATTR_ID 0x04
+#define CHANLIST_ATTR_ID 0x0b
+#define OPERCHAN_ATTR_ID 0x11
+#endif
+
+#define nl80211_SCAN_RESULT_EXPIRE (3 * HZ)
+#define SCAN_RESULT_EXPIRE (40 * HZ)
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)
+static const u32 cipher_suites[] = {
+ WLAN_CIPHER_SUITE_WEP40,
+ WLAN_CIPHER_SUITE_WEP104,
+ WLAN_CIPHER_SUITE_TKIP,
+ WLAN_CIPHER_SUITE_CCMP,
+ WLAN_CIPHER_SUITE_AES_CMAC,
+};
+#endif
+
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
+static const struct ieee80211_txrx_stypes
+nmi_wfi_cfg80211_mgmt_types[NL80211_IFTYPE_MAX] =
+{
+ [NL80211_IFTYPE_STATION] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+ },
+ [NL80211_IFTYPE_AP] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+ BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+ BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+ BIT(IEEE80211_STYPE_AUTH >> 4) |
+ BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+ BIT(IEEE80211_STYPE_ACTION >> 4)
+ },
+ [NL80211_IFTYPE_P2P_CLIENT] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+ BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+ BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+ BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+ BIT(IEEE80211_STYPE_AUTH >> 4) |
+ BIT(IEEE80211_STYPE_DEAUTH >> 4)
+ }
+};
+#endif
+/* Time to stay on the channel */
+#define NMI_WFI_DWELL_PASSIVE 100
+#define NMI_WFI_DWELL_ACTIVE 40
+
+struct wireless_dev* NMI_WFI_CfgAlloc(void);
+struct wireless_dev * NMI_WFI_WiphyRegister(struct net_device *net);
+void NMI_WFI_WiphyFree(struct net_device *net);
+int NMI_WFI_update_stats(struct wiphy *wiphy, u32 pktlen , u8 changed);
+int NMI_WFI_DeInitHostInt(struct net_device *net);
+int NMI_WFI_InitHostInt(struct net_device *net);
+void NMI_WFI_monitor_rx(uint8_t *buff, uint32_t size);
+int NMI_WFI_deinit_mon_interface(void);
+struct net_device * NMI_WFI_init_mon_interface(char *name, struct net_device *real_dev );
+#endif
diff --git a/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/include/NMI_WFI_NetDevice.h b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/include/NMI_WFI_NetDevice.h
new file mode 100755
index 00000000..9f99b85e
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/include/NMI_WFI_NetDevice.h
@@ -0,0 +1,304 @@
+/*!
+* @file NMI_WFI_NetDevice.h
+* @brief Definitions for the network module
+* @author mdaftedar
+* @date 01 MAR 2012
+* @version 1.0
+*/
+#ifndef NMI_WFI_NETDEVICE
+#define NMI_WFI_NETDEVICE
+/*
+* Macros to help debugging
+*/
+
+#undef PDEBUG /* undef it, just in case */
+#ifdef SNULL_DEBUG
+# ifdef __KERNEL__
+/* This one if debugging is on, and kernel space */
+# define PDEBUG(fmt, args...) printk( KERN_DEBUG "snull: " fmt, ## args)
+# else
+/* This one for user space */
+# define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
+# endif
+#else
+# define PDEBUG(fmt, args...) /* not debugging: nothing */
+#endif
+
+#undef PDEBUGG
+#define PDEBUGG(fmt, args...) /* nothing: it's a placeholder */
+
+
+/* These are the flags in the statusword */
+#define NMI_WFI_RX_INTR 0x0001
+#define NMI_WFI_TX_INTR 0x0002
+
+/* Default timeout period */
+#define NMI_WFI_TIMEOUT 5 /* In jiffies */
+#define NMI_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> /* printk() */
+#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 "nmi_wlan.h"
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,30)
+#include <net/wireless.h>
+#else
+#include <linux/wireless.h> // tony, 2013-06-12
+#endif
+
+
+#define FLOW_CONTROL_LOWER_THRESHOLD 128
+#define FLOW_CONTROL_UPPER_THRESHOLD 256
+
+/*iftype*/
+
+
+enum stats_flags
+{
+ NMI_WFI_RX_PKT = 1 << 0,
+ NMI_WFI_TX_PKT = 1 << 1,
+};
+
+struct NMI_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
+#else
+#define RX_BH_TYPE RX_BH_WORK_QUEUE
+#endif
+
+struct nmi_wfi_key {
+ u8 * key;
+ u8 * seq;
+ int key_len;
+ int seq_len;
+ u32 cipher;
+};
+struct nmi_wfi_wep_key {
+ u8 * key;
+ u8 key_len;
+ u8 key_idx;
+};
+
+struct sta_info
+{
+ NMI_Uint8 au8Sta_AssociatedBss[MAX_NUM_STA][ETH_ALEN];
+};
+
+#ifdef NMI_P2P
+/*Parameters needed for host interface for remaining on channel*/
+struct nmi_wfi_p2pListenParams
+{
+ struct ieee80211_channel * pstrListenChan;
+ enum nl80211_channel_type tenuChannelType;
+ NMI_Uint32 u32ListenDuration;
+ NMI_Uint64 u64ListenCookie;
+};
+
+#endif /*NMI_P2P*/
+
+struct NMI_WFI_priv {
+ struct wireless_dev *wdev;
+ struct cfg80211_scan_request* pstrScanReq;
+
+ #ifdef NMI_P2P
+ NMI_Uint32 u32listen_freq;
+ struct nmi_wfi_p2pListenParams strRemainOnChanParams;
+ NMI_Uint64 u64tx_cookie;
+
+ #endif
+
+ /*Added by Amr - BugID_4793*/
+ NMI_Uint8 u8CurrChannel;
+
+ NMI_Bool bCfgScanning;
+ NMI_Uint32 u32RcvdChCount;
+
+
+
+ NMI_Uint8 au8AssociatedBss[ETH_ALEN];
+ struct sta_info assoc_stainfo;
+ struct net_device_stats stats;
+ NMI_Uint8 monitor_flag;
+ int status;
+ struct NMI_WFI_packet *ppool;
+ struct NMI_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;
+ NMI_WFIDrvHandle hNMIWFIDrv;
+ NMI_WFIDrvHandle hNMIWFIDrv_2;
+ tstrHostIFpmkidAttr pmkid_list;
+ struct NMI_WFI_stats netstats;
+ NMI_Uint8 NMI_WFI_wep_default;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
+#define WLAN_KEY_LEN_WEP104 13
+#endif
+ NMI_Uint8 NMI_WFI_wep_key[4][WLAN_KEY_LEN_WEP104];
+ NMI_Uint8 NMI_WFI_wep_key_len[4];
+ struct net_device* real_ndev; /* The real interface that the monitor is on */
+ struct nmi_wfi_key* nmi_gtk[MAX_NUM_STA];
+ struct nmi_wfi_key* nmi_ptk[MAX_NUM_STA];
+ NMI_Uint8 nmi_groupkey;
+ //semaphores
+ NMI_SemaphoreHandle SemHandleUpdateStats;
+ NMI_SemaphoreHandle hSemScanReq;
+ //
+ NMI_Bool gbAutoRateAdjusted;
+
+
+};
+
+typedef struct
+{
+ NMI_Uint16 frame_type;
+ NMI_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* nmc_netdev;
+}tstrInterfaceInfo;
+typedef struct{
+ int mac_status;
+ int nmc1000_initialized;
+
+
+ #if (!defined NMI_SDIO) || (defined NMI_SDIO_IRQ_GPIO)
+ unsigned short dev_irq_num;
+ #endif
+ nmi_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* nmc_firmware; /* Bug 4703 */
+
+ struct net_device* real_ndev;
+#ifdef NMI_SDIO
+ int already_claim;
+ struct sdio_func* nmc_sdio_func;
+#else
+ struct spi_device* nmc_spidev;
+#endif
+
+} linux_wlan_t;
+
+typedef struct
+{
+ uint8_t u8IfIdx;
+ NMI_Uint8 iftype;
+ int monitor_flag;
+ int mac_opened;
+ #ifdef NMI_P2P
+ struct_frame_reg g_struct_frame_reg[num_reg_frame];
+ #endif
+struct net_device* nmc_netdev;
+struct net_device_stats netstats;
+
+}perInterface_wlan_t;
+
+struct NMI_WFI_mon_priv
+{
+ struct net_device* real_ndev;
+};
+extern struct net_device *NMI_WFI_devs[];
+
+#endif
diff --git a/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/init_deinit_test.sh b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/init_deinit_test.sh
new file mode 100755
index 00000000..31bcc7a2
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/init_deinit_test.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+num_init_iterations=0
+echo "* Starting Init/Deinit Test *"
+while [ "$num_init_iterations" -lt "20" ]
+do
+echo "*****************************************"
+echo "* initialization trial no. $((num_init_iterations+1)) *"
+echo "*****************************************"
+echo "Bringing wlan0 down"
+ret_cfg_iface=$(adb shell ifconfig wlan0 down)
+ret_cfg_iface_err=$(echo "$ret_cfg_iface" | grep 'error')
+echo "$ret_cfg_iface_err"
+if [ -n "${ret_cfg_iface_err}" ]; then
+ echo "failed in ifconfig wlan1 down"
+ echo "..Initialization failed.."
+ exit
+fi
+sleep 1
+echo "Bringing wlan0 up"
+ret_cfg_iface=$(adb shell ifconfig wlan0 up)
+ret_cfg_iface_err=$(echo "$ret_cfg_iface" | grep 'error')
+echo "$ret_cfg_iface_err"
+if [ -n "${ret_cfg_iface_err}" ]; then
+ echo "failed in ifconfig wlan1 up"
+ echo "..Initialization failed.."
+ exit
+fi
+sleep 1
+echo "Disabling Wifi"
+adb shell svc wifi disable
+sleep 5
+echo "Enabling Wifi"
+adb shell svc wifi enable
+sleep 10
+cli_status=$(adb shell wpa_cli status)
+echo cli_status
+cli_status_check=$(echo "$cli_status" | grep ^wpa_state)
+
+if [ -z "${cli_status_check}" ]; then
+ echo "failed in wpa_cli status"
+ echo "..Initialization failed.."
+ exit
+fi
+echo "succeeded"
+num_init_iterations=$((num_init_iterations+1))
+adb shell ping -i.4 -c10 192.168.11.1
+#adb shell ping -i.4 -c10 192.168.1.1
+
+done
+echo "num of succeded init/deinit trials $num_init_iterations"
+echo "* End of Init/Deinit Test *"
diff --git a/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/nmi_wfi_load b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/nmi_wfi_load
new file mode 100755
index 00000000..a4e42aa6
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/nmi_wfi_load
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+export PATH=/sbin:/bin
+# Use a pathname, as new modutils don't look in the current dir by default
+#modprobe cfg80211
+insmod /lib/modules/$(uname -r)/kernel/net/wireless/cfg80211.ko
+insmod ./binary/linux/x86/nmi_wifi.ko $*
+
+ifconfig wlan0 local0
+ifconfig wlan1 local1
diff --git a/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/nmi_wfi_unload b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/nmi_wfi_unload
new file mode 100755
index 00000000..134c9352
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/nmi_wfi_unload
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+/sbin/ifconfig wlan0 down
+/sbin/ifconfig wlan1 down
+/sbin/rmmod nmi_wifi
+rmmod cfg80211
diff --git a/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/panda_run_eval.sh b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/panda_run_eval.sh
new file mode 100755
index 00000000..f9717eb4
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/panda_run_eval.sh
@@ -0,0 +1,7 @@
+adb shell rm /system/etc/firmware/wifi_firmware.bin
+adb push ../../core/wifi_v111/ASIC_A0/wifi_firmware.bin /system/etc/firmware/wifi_firmware.bin
+adb push ../../core/wifi_v111/ASIC_A0_AP/wifi_firmware_ap.bin /system/etc/firmware/wifi_firmware_ap.bin
+adb push ../../core/wifi_v111/ASIC_A0/wifi_firmware_p2p_concurrency.bin /system/etc/firmware/wifi_firmware_p2p_concurrency.bin
+adb shell rm /data/nmi_wifi.ko
+adb push binary/linux/ARM-3.0/nmi_wifi.ko /data/nmi_wifi.ko
+adb push ./ap_soft.conf /data/misc/wifi/hostapd.conf
diff --git a/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/panda_run_fpga.sh b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/panda_run_fpga.sh
new file mode 100755
index 00000000..d8a1a897
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/panda_run_fpga.sh
@@ -0,0 +1,4 @@
+adb push ../../core/wifi_v111/FPGA_485t/wifi_firmware.bin /system/etc/firmware/wifi_firmware.bin
+adb push binary/linux/ARM-3.0/nmi_wifi.ko /sdcard/nmi_wifi.ko
+#adb push ../../../../../AdelShare/android4.0/softap.conf /data/misc/wifi/softap.conf
+adb shell insmod /sdcard/nmi_wifi.ko
diff --git a/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/NMI_WFI_CfgOperations.c b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/NMI_WFI_CfgOperations.c
new file mode 100755
index 00000000..25a6a485
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/NMI_WFI_CfgOperations.c
@@ -0,0 +1,4503 @@
+/*!
+* @file NMI_WFI_CfgOpertaions.c
+* @brief CFG80211 Function Implementation functionality
+* @author aabouzaeid
+* mabubakr
+* mdaftedar
+* zsalah
+* @sa NMI_WFI_CfgOpertaions.h top level OS wrapper file
+* @date 31 Aug 2010
+* @version 1.0
+*/
+
+#include "linux/include/NMI_WFI_CfgOperations.h"
+#include "nmi_wlan.c"
+#include "linux_wlan_sdio.h" //tony : for set_wiphy_dev()
+
+
+#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 NMI_Uint16 Set_machw_change_vir_if(NMI_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];
+NMI_Uint32 u32LastScannedNtwrksCountShadow;
+#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
+NMI_TimerHandle hDuringIpTimer;
+#endif
+NMI_TimerHandle hAgingTimer;
+static NMI_Uint8 op_ifcs=0;
+
+
+/*BugID_5137*/
+NMI_Uint8 g_nmc_initialized = 1;
+extern linux_wlan_t* g_linux_wlan;
+#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
+extern NMI_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 NMI_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 NMI_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 NMI_P2P
+struct p2p_mgmt_data{
+ int size;
+ u8* buff;
+};
+
+/*Global variable used to state the current connected STA channel*/
+NMI_Uint8 u8WLANChannel = DEFAULT_CHANNEL ;
+
+NMI_Uint8 u8P2P_oui[] ={0x50,0x6f,0x9A,0x09};
+NMI_Uint8 u8P2Plocalrandom=0x01;
+NMI_Uint8 u8P2Precvrandom=0x00;
+NMI_Uint8 u8P2P_vendorspec[]={0xdd,0x05,0x00,0x08,0x40,0x03};
+NMI_Bool bNmi_ie=NMI_FALSE;
+#endif
+
+static struct ieee80211_supported_band NMI_WFI_band_2ghz = {
+ .channels = NMI_WFI_2ghz_channels,
+ .n_channels = ARRAY_SIZE(NMI_WFI_2ghz_channels),
+ .bitrates = NMI_WFI_rates,
+ .n_bitrates = ARRAY_SIZE(NMI_WFI_rates),
+};
+
+
+/*BugID_5137*/
+struct add_key_params
+{
+ u8 key_idx;
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
+ bool pairwise;
+ #endif
+ u8* mac_addr;
+};
+struct add_key_params g_add_gtk_key_params;
+struct nmi_wfi_key g_key_gtk_params;
+struct add_key_params g_add_ptk_key_params;
+struct nmi_wfi_key g_key_ptk_params;
+struct nmi_wfi_wep_key g_key_wep_params;
+NMI_Uint8 g_flushing_in_progress = 0;
+NMI_Bool g_ptk_keys_saved = NMI_FALSE;
+NMI_Bool g_gtk_keys_saved = NMI_FALSE;
+NMI_Bool g_wep_keys_saved = NMI_FALSE;
+
+
+#define AGING_TIME 9*1000
+#define duringIP_TIME 15000
+
+void clear_shadow_scan(void* pUserVoid){
+ struct NMI_WFI_priv* priv;
+ int i;
+ priv = (struct NMI_WFI_priv*)pUserVoid;
+
+ for(i = 0; i < u32LastScannedNtwrksCountShadow; i++){
+ if(astrLastScannedNtwrksShadow[u32LastScannedNtwrksCountShadow].pu8IEs != NULL)
+ NMI_FREE(astrLastScannedNtwrksShadow[i].pu8IEs);
+
+ host_int_freeJoinParams(astrLastScannedNtwrksShadow[i].pJoinParams);
+ }
+ u32LastScannedNtwrksCountShadow = 0;
+
+ if(op_ifcs==0)
+ {
+ NMI_TimerDestroy(&hAgingTimer,NMI_NULL);
+ printk("destroy aging timer\n");
+ }
+
+}
+
+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,NMI_Bool bDirectScan){
+ struct NMI_WFI_priv* priv;
+ struct wiphy* wiphy;
+ struct cfg80211_bss* bss = NULL;
+ int i;
+ int rssi = 0;
+
+ priv = (struct NMI_WFI_priv*)pUserVoid;
+ wiphy = priv->dev->ieee80211_ptr->wiphy;
+
+ for(i = 0; i < u32LastScannedNtwrksCountShadow; i++)
+ {
+ tstrNetworkInfo* pstrNetworkInfo;
+ pstrNetworkInfo = &(astrLastScannedNtwrksShadow[i]);
+
+
+ if((!pstrNetworkInfo->u8Found) || all){
+ NMI_Sint32 s32Freq;
+ struct ieee80211_channel *channel;
+
+ if(pstrNetworkInfo != NMI_NULL)
+ {
+
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
+ s32Freq = ieee80211_channel_to_frequency((NMI_Sint32)pstrNetworkInfo->u8channel, IEEE80211_BAND_2GHZ);
+ #else
+ s32Freq = ieee80211_channel_to_frequency((NMI_Sint32)pstrNetworkInfo->u8channel);
+ #endif
+
+ channel = ieee80211_get_channel(wiphy, s32Freq);
+
+ rssi = get_rssi_avg(pstrNetworkInfo);
+ if(NMI_memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7) || bDirectScan)
+ {
+ bss = cfg80211_inform_bss(wiphy, channel, pstrNetworkInfo->au8bssid, pstrNetworkInfo->u64Tsf, pstrNetworkInfo->u16CapInfo,
+ pstrNetworkInfo->u16BeaconPeriod, (const u8*)pstrNetworkInfo->pu8IEs,
+ (size_t)pstrNetworkInfo->u16IEsLen, (((NMI_Sint32)rssi) * 100), GFP_KERNEL);
+ cfg80211_put_bss(bss);
+ }
+ }
+
+ }
+ }
+
+}
+
+void reset_shadow_found(void* pUserVoid){
+ struct NMI_WFI_priv* priv;
+ int i;
+ priv = (struct NMI_WFI_priv*)pUserVoid;
+ for(i=0;i<u32LastScannedNtwrksCountShadow;i++){
+ astrLastScannedNtwrksShadow[i].u8Found = 0;
+
+ }
+}
+
+void update_scan_time(void* pUserVoid){
+ struct NMI_WFI_priv* priv;
+ int i;
+ priv = (struct NMI_WFI_priv*)pUserVoid;
+ for(i=0;i<u32LastScannedNtwrksCountShadow;i++){
+ astrLastScannedNtwrksShadow[i].u32TimeRcvdInScan = jiffies;
+ }
+}
+
+void remove_network_from_shadow(void* pUserVoid){
+ struct NMI_WFI_priv* priv;
+ unsigned long now = jiffies;
+ int i,j;
+
+ priv = (struct NMI_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)
+ NMI_FREE(astrLastScannedNtwrksShadow[i].pu8IEs);
+
+ 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)
+ NMI_TimerStart(&(hAgingTimer), AGING_TIME, pUserVoid, NMI_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=NMI_FALSE;
+}
+#endif
+
+int8_t is_network_in_shadow(tstrNetworkInfo* pstrNetworkInfo,void* pUserVoid){
+ struct NMI_WFI_priv* priv;
+ int8_t state = -1;
+ int i;
+
+ priv = (struct NMI_WFI_priv*)pUserVoid;
+ if(u32LastScannedNtwrksCountShadow== 0){
+ PRINT_D(CFG80211_DBG,"Starting Aging timer\n");
+ NMI_TimerStart(&(hAgingTimer), AGING_TIME, pUserVoid, NMI_NULL);
+ state = -1;
+ }else{
+ /* Linear search for now */
+ for(i=0;i<u32LastScannedNtwrksCountShadow;i++){
+ if(NMI_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 NMI_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 NMI_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;
+ NMI_memcpy(astrLastScannedNtwrksShadow[ap_index].au8ssid,
+ pstrNetworkInfo->au8ssid, pstrNetworkInfo->u8SsidLen);
+
+ NMI_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)
+ NMI_FREE(astrLastScannedNtwrksShadow[ap_index].pu8IEs);
+ astrLastScannedNtwrksShadow[ap_index].pu8IEs =
+ (NMI_Uint8*)NMI_MALLOC(pstrNetworkInfo->u16IEsLen); /* will be deallocated
+ by the NMI_WFI_CfgScan() function */
+ NMI_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 NMI_WFI_priv* priv;
+ struct wiphy* wiphy;
+ NMI_Sint32 s32Freq;
+ struct ieee80211_channel *channel;
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ struct cfg80211_bss* bss = NULL;
+
+ priv = (struct NMI_WFI_priv*)pUserVoid;
+
+
+ if(priv->bCfgScanning == NMI_TRUE)
+ {
+
+
+ if(enuScanEvent == SCAN_EVENT_NETWORK_FOUND)
+ {
+
+ wiphy = priv->dev->ieee80211_ptr->wiphy;
+
+ NMI_NULLCHECK(s32Error, wiphy);
+
+ if(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC
+ &&
+ ( (((NMI_Sint32)pstrNetworkInfo->s8rssi) * 100) < 0
+ ||
+ (((NMI_Sint32)pstrNetworkInfo->s8rssi) * 100) > 100)
+ )
+ {
+ NMI_ERRORREPORT(s32Error, NMI_FAIL);
+ }
+
+
+
+ if(pstrNetworkInfo != NMI_NULL)
+ {
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
+ s32Freq = ieee80211_channel_to_frequency((NMI_Sint32)pstrNetworkInfo->u8channel, IEEE80211_BAND_2GHZ);
+ #else
+ s32Freq = ieee80211_channel_to_frequency((NMI_Sint32)pstrNetworkInfo->u8channel);
+ #endif
+ channel = ieee80211_get_channel(wiphy, s32Freq);
+
+ NMI_NULLCHECK(s32Error, channel);
+
+ PRINT_INFO(CFG80211_DBG,"Network Info:: CHANNEL Frequency: %d, RSSI: %d, CapabilityInfo: %d,"
+ "BeaconPeriod: %d \n",channel->center_freq, (((NMI_Sint32)pstrNetworkInfo->s8rssi) * 100),
+ pstrNetworkInfo->u16CapInfo, pstrNetworkInfo->u16BeaconPeriod);
+
+
+ if(pstrNetworkInfo->bNewNetwork == NMI_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){
+ printk(">> 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(!(NMI_memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7) ))
+ {
+
+ bss = cfg80211_inform_bss(wiphy, channel, pstrNetworkInfo->au8bssid, pstrNetworkInfo->u64Tsf, pstrNetworkInfo->u16CapInfo,
+ pstrNetworkInfo->u16BeaconPeriod, (const u8*)pstrNetworkInfo->pu8IEs,
+ (size_t)pstrNetworkInfo->u16IEsLen, (((NMI_Sint32)pstrNetworkInfo->s8rssi) * 100), GFP_KERNEL);
+ cfg80211_put_bss(bss);
+ }
+
+
+ }
+ else
+ {
+ PRINT_ER("Discovered networks exceeded the max limit\n");
+ }
+ }
+ else
+ {
+ NMI_Uint32 i;
+ /* So this network is discovered before, we'll just update its RSSI */
+ for(i = 0; i < priv->u32RcvdChCount; i++)
+ {
+ if(NMI_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,0);
+ refresh_scan(priv,1,NMI_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");
+ }
+
+ NMI_SemaphoreAcquire(&(priv->hSemScanReq), NULL);
+
+ if(priv->pstrScanReq != NMI_NULL)
+ {
+ cfg80211_scan_done(priv->pstrScanReq, NMI_FALSE);
+ priv->u32RcvdChCount = 0;
+ priv->bCfgScanning = NMI_FALSE;
+ priv->pstrScanReq = NMI_NULL;
+ }
+ NMI_SemaphoreRelease(&(priv->hSemScanReq), NULL);
+
+ }
+ /*Aborting any scan operation during mac close*/
+ else if(enuScanEvent == SCAN_EVENT_ABORTED)
+ {
+ NMI_SemaphoreAcquire(&(priv->hSemScanReq), NULL);
+
+ PRINT_D(CFG80211_DBG,"Scan Aborted \n");
+ if(priv->pstrScanReq != NMI_NULL)
+ {
+
+ update_scan_time(priv);
+ refresh_scan(priv,1,NMI_FALSE);
+
+ cfg80211_scan_done(priv->pstrScanReq,NMI_FALSE);
+ priv->bCfgScanning = NMI_FALSE;
+ priv->pstrScanReq = NMI_NULL;
+ }
+ NMI_SemaphoreRelease(&(priv->hSemScanReq), NULL);
+ }
+ }
+
+
+ NMI_CATCH(s32Error)
+ {
+ }
+ }
+
+
+/**
+* @brief NMI_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 NMI_WFI_Set_PMKSA(NMI_Uint8 * bssid,struct NMI_WFI_priv* priv)
+{
+ NMI_Uint32 i;
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+
+
+ for (i = 0; i < priv->pmkid_list.numpmkid; i++)
+ {
+
+ if (!NMI_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->hNMIWFIDrv,&priv->pmkid_list);
+
+ if(s32Error != NMI_SUCCESS)
+ PRINT_ER("Error in pmkid\n");
+
+ break;
+ }
+ }
+
+ return s32Error;
+
+
+}
+int linux_wlan_set_bssid(struct net_device * nmc_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.
+* NMI_Uint8 u8MacStatus: Mac Status from firmware
+* tstrDisconnectNotifInfo* pstrDisconnectNotifInfo: Disconnection Notification
+* void* pUserVoid: Private data associated with wireless interface
+* @return NONE
+* @author mabubakr
+* @date 01 MAR 2012
+* @version 1.0
+*/
+ int connecting = 0;
+
+static void CfgConnectResult(tenuConnDisconnEvent enuConnDisconnEvent,
+ tstrConnectInfo* pstrConnectInfo,
+ NMI_Uint8 u8MacStatus,
+ tstrDisconnectNotifInfo* pstrDisconnectNotifInfo,
+ void* pUserVoid)
+{
+ struct NMI_WFI_priv* priv;
+ struct net_device* dev;
+ NMI_Uint8 NullBssid[ETH_ALEN] = {0};
+ connecting = 0;
+ if(enuConnDisconnEvent == CONN_DISCONN_EVENT_CONN_RESP)
+ {
+ /*Initialization*/
+ NMI_Uint16 u16ConnectStatus = WLAN_STATUS_SUCCESS;
+
+ priv = (struct NMI_WFI_priv*)pUserVoid;
+
+ dev = priv->dev;
+
+ 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);
+
+ PRINT_ER("Unspecified failure: Connection status %d : MAC status = %d \n",u16ConnectStatus,u8MacStatus);
+ }
+
+ if(u16ConnectStatus == WLAN_STATUS_SUCCESS)
+ {
+ NMI_Bool bNeedScanRefresh = NMI_FALSE;
+ NMI_Uint32 i;
+
+ PRINT_INFO(CFG80211_DBG,"Connection Successful:: BSSID: %x%x%x%x%x%x\n",pstrConnectInfo->au8bssid[0],
+ pstrConnectInfo->au8bssid[1],pstrConnectInfo->au8bssid[2],pstrConnectInfo->au8bssid[3],pstrConnectInfo->au8bssid[4],pstrConnectInfo->au8bssid[5]);
+ NMI_memcpy(priv->au8AssociatedBss, pstrConnectInfo->au8bssid, ETH_ALEN);
+
+ //set bssid in frame filter
+ //linux_wlan_set_bssid(dev,pstrConnectInfo->au8bssid);
+
+ /* BugID_4209: if this network has expired in the scan results in the above nl80211 layer, refresh them here by calling
+ cfg80211_inform_bss() with the last Scan results before calling cfg80211_connect_result() to avoid
+ Linux kernel warning generated at the nl80211 layer */
+
+ for(i = 0; i < u32LastScannedNtwrksCountShadow; i++)
+ {
+ if(NMI_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 = NMI_TRUE;
+ }
+
+ break;
+ }
+ }
+
+ if(bNeedScanRefresh == NMI_TRUE)
+ {
+ //RefreshScanResult(priv);
+ refresh_scan(priv, 1,NMI_FALSE);
+
+ }
+
+ }
+
+
+ PRINT_D(CFG80211_DBG,"Association request info elements length = %d\n", pstrConnectInfo->ReqIEsLen);
+
+ PRINT_D(CFG80211_DBG,"Association response info elements length = %d\n", pstrConnectInfo->u16RespIEsLen);
+
+ cfg80211_connect_result(dev, pstrConnectInfo->au8bssid,
+ pstrConnectInfo->pu8ReqIEs, pstrConnectInfo->ReqIEsLen,
+ pstrConnectInfo->pu8RespIEs, pstrConnectInfo->u16RespIEsLen,
+ u16ConnectStatus, GFP_KERNEL); //TODO: mostafa: u16ConnectStatus to
+ // be replaced by pstrConnectInfo->u16ConnectStatus
+ }
+ else if(enuConnDisconnEvent == CONN_DISCONN_EVENT_DISCONN_NOTIF)
+ {
+ priv = (struct NMI_WFI_priv*)pUserVoid;
+ dev = priv->dev;
+ #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
+ g_obtainingIP=NMI_FALSE;
+ #endif
+ PRINT_ER("Received MAC_DISCONNECTED from firmware with reason %d on dev [%p]\n",
+ pstrDisconnectNotifInfo->u16reason, priv->dev);
+ u8P2Plocalrandom=0x01;
+ u8P2Precvrandom=0x00;
+ bNmi_ie = NMI_FALSE;
+ NMI_memset(priv->au8AssociatedBss, 0, ETH_ALEN);
+ linux_wlan_set_bssid(priv->dev,NullBssid);
+ cfg80211_disconnected(dev, pstrDisconnectNotifInfo->u16reason, pstrDisconnectNotifInfo->ie,
+ pstrDisconnectNotifInfo->ie_len, GFP_KERNEL);
+
+ }
+
+}
+
+
+/**
+* @brief NMI_WFI_CfgSetChannel
+* @details Set channel for a given wireless interface. Some devices
+* may support multi-channel operation (by channel hopping) so cfg80211
+* doesn't verify much. Note, however, that the passed netdev may be
+* %NULL as well if the user requested changing the channel for the
+* device itself, or for a monitor interface.
+* @param[in]
+* @return int : Return 0 on Success
+* @author mdaftedar
+* @date 01 MAR 2012
+* @version 1.0
+*/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
+/*
+* struct changed from v3.8.0
+* tony, sswd, NMI-KR, 2013-10-29
+* struct cfg80211_chan_def {
+ struct ieee80211_channel *chan;
+ enum nl80211_chan_width width;
+ u32 center_freq1;
+ u32 center_freq2;
+ };
+*/
+static int NMI_WFI_CfgSetChannel(struct wiphy *wiphy,
+ struct cfg80211_chan_def *chandef)
+#else
+static int NMI_WFI_CfgSetChannel(struct wiphy *wiphy,
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32)
+ struct net_device *netdev,
+ #endif
+ struct ieee80211_channel *channel,
+ enum nl80211_channel_type channel_type)
+#endif
+{
+
+ NMI_Uint32 channelnum = 0;
+ struct NMI_WFI_priv* priv;
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ priv = wiphy_priv(wiphy);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) /* tony for v3.8.0 support */
+ channelnum = ieee80211_frequency_to_channel(chandef->chan->center_freq);
+ PRINT_D(CFG80211_DBG,"Setting channel %d with frequency %d\n", channelnum, chandef->chan->center_freq );
+#else
+ channelnum = ieee80211_frequency_to_channel(channel->center_freq);
+ PRINT_D(CFG80211_DBG,"Setting channel %d with frequency %d\n", channelnum, channel->center_freq );
+#endif
+
+ priv->u8CurrChannel = channelnum;
+ s32Error = host_int_set_mac_chnl_num(priv->hNMIWFIDrv,channelnum);
+
+ if(s32Error != NMI_SUCCESS)
+ PRINT_ER("Error in setting channel %d\n", channelnum);
+
+ return s32Error;
+}
+
+/**
+* @brief NMI_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, NMI-KR, 2013-10-29
+*/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
+static int NMI_WFI_CfgScan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
+#else
+static int NMI_WFI_CfgScan(struct wiphy *wiphy,struct net_device *dev, struct cfg80211_scan_request *request)
+#endif
+{
+ struct NMI_WFI_priv* priv;
+ NMI_Uint32 i;
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ NMI_Uint8 au8ScanChanList[MAX_NUM_SCANNED_NETWORKS];
+ tstrHiddenNetwork strHiddenNetwork;
+
+ priv = wiphy_priv(wiphy);
+
+ printk("Scan on netdev [%p] host if [%x]\n",dev, (NMI_Uint32)priv->hNMIWFIDrv);
+
+ /*if(connecting)
+ return -EBUSY; */
+
+ /*BugID_4800: if in AP mode, return.*/
+ /*This check is to handle the situation when user*/
+ /*requests "create group" during a running scan*/
+ //host_int_set_wfi_drv_handler(priv->hNMIWFIDrv);
+#if 0
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) /* tony for v3.8.0 support */
+ if(priv->dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP)
+ {
+ PRINT_D(GENERIC_DBG,"Required scan while in AP mode");
+ return s32Error;
+ }
+#else
+ if(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP)
+ {
+ PRINT_D(GENERIC_DBG,"Required scan while in AP mode");
+ s32Error = NMI_BUSY;
+ return s32Error;
+ }
+#endif
+#endif // end of if 0
+ priv->pstrScanReq = request;
+
+ priv->u32RcvdChCount = 0;
+
+ host_int_set_wfi_drv_handler((NMI_Uint32)priv->hNMIWFIDrv);
+
+
+ reset_shadow_found(priv);
+
+ priv->bCfgScanning = NMI_TRUE;
+ priv->u8CurrChannel =-1;
+ 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] = (NMI_Uint8)ieee80211_frequency_to_channel(request->channels[i]->center_freq);
+ PRINT_INFO(CFG80211_DBG, "ScanChannel List[%d] = %d,",i,au8ScanChanList[i]);
+ }
+
+ PRINT_D(CFG80211_DBG,"Requested num of scan channel %d\n",request->n_channels);
+ PRINT_D(CFG80211_DBG,"Scan Request IE len = %d\n",request->ie_len);
+
+ PRINT_D(CFG80211_DBG,"Number of SSIDs %d\n",request->n_ssids);
+
+ if(request->n_ssids >= 1)
+ {
+
+
+ strHiddenNetwork.pstrHiddenNetworkInfo = NMI_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= NMI_MALLOC( request->ssids[i].ssid_len);
+ NMI_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->hNMIWFIDrv, USER_SCAN, ACTIVE_SCAN,
+ au8ScanChanList, request->n_channels,
+ (const NMI_Uint8*)request->ie, request->ie_len,
+ CfgScanResult, (void*)priv,&strHiddenNetwork);
+ }
+ else
+ {
+ PRINT_D(CFG80211_DBG,"Trigger Scan Request \n");
+ s32Error = host_int_scan(priv->hNMIWFIDrv, USER_SCAN, ACTIVE_SCAN,
+ au8ScanChanList, request->n_channels,
+ (const NMI_Uint8*)request->ie, request->ie_len,
+ CfgScanResult, (void*)priv,NULL);
+ }
+
+ }
+ else
+ {
+ PRINT_ER("Requested num of scanned channels is greater than the max, supported"
+ " channels \n");
+ }
+
+ if(s32Error != NMI_SUCCESS)
+ {
+ s32Error = -EBUSY;
+ PRINT_WRN(CFG80211_DBG,"Device is busy: Error(%d)\n",s32Error);
+ }
+
+ return s32Error;
+}
+
+/**
+* @brief NMI_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 NMI_WFI_CfgConnect(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_connect_params *sme)
+{
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ NMI_Uint32 i;
+ //SECURITY_T tenuSecurity_t = NO_SECURITY;
+ NMI_Uint8 u8security = NO_ENCRYPT;
+ AUTHTYPE_T tenuAuth_type = ANY;
+ NMI_Char * pcgroup_encrypt_val;
+ NMI_Char * pccipher_group;
+ NMI_Char * pcwpa_version;
+
+ struct NMI_WFI_priv* priv;
+ tstrNMI_WFIDrv * pstrWFIDrv;
+ tstrNetworkInfo* pstrNetworkInfo = NULL;
+
+
+ connecting = 1;
+ priv = wiphy_priv(wiphy);
+ pstrWFIDrv = (tstrNMI_WFIDrv *)(priv->hNMIWFIDrv);
+
+ host_int_set_wfi_drv_handler((NMI_Uint32)priv->hNMIWFIDrv);
+
+ //host_int_set_wfi_drv_handler((NMI_Uint32)priv->hNMIWFIDrv);
+ PRINT_D(CFG80211_DBG,"Connecting to SSID [%s] on netdev [%p] host if [%x]\n",sme->ssid,dev, (NMI_Uint32)priv->hNMIWFIDrv);
+ #ifdef NMI_P2P
+ if(!(NMI_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) &&
+ NMI_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(NMI_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->NMI_WFI_wep_default = 0;
+ NMI_memset(priv->NMI_WFI_wep_key, 0, sizeof(priv->NMI_WFI_wep_key));
+ NMI_memset(priv->NMI_WFI_wep_key_len, 0, sizeof(priv->NMI_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++)
+ NMI_PRINTF("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";
+ printk(">> sme->crypto.wpa_versions: %x\n",sme->crypto.wpa_versions);
+ //case NL80211_WPA_VERSION_1:
+ if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40)
+ {
+ //printk("> WEP\n");
+ //tenuSecurity_t = WEP_40;
+ u8security = ENCRYPT_ENABLED | WEP;
+ pcgroup_encrypt_val = "WEP40";
+ pccipher_group = "WLAN_CIPHER_SUITE_WEP40";
+ PRINT_INFO(CFG80211_DBG, "WEP Default Key Idx = %d\n",sme->key_idx);
+
+ if(INFO)
+ {
+ for(i=0;i<sme->key_len;i++)
+ NMI_PRINTF("WEP Key Value[%d] = %d\n", i, sme->key[i]);
+ }
+ priv->NMI_WFI_wep_default = sme->key_idx;
+ priv->NMI_WFI_wep_key_len[sme->key_idx] = sme->key_len;
+ NMI_memcpy(priv->NMI_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 = NMI_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 = NMI_TRUE;
+
+ host_int_set_WEPDefaultKeyID(priv->hNMIWFIDrv,sme->key_idx);
+ host_int_add_wep_key_bss_sta(priv->hNMIWFIDrv, sme->key,sme->key_len,sme->key_idx);
+ }
+ else if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104)
+ {
+ //printk("> WEP-WEP_EXTENDED\n");
+ //tenuSecurity_t = WEP_104;
+ u8security = ENCRYPT_ENABLED | WEP | WEP_EXTENDED;
+ pcgroup_encrypt_val = "WEP104";
+ pccipher_group = "WLAN_CIPHER_SUITE_WEP104";
+
+ priv->NMI_WFI_wep_default = sme->key_idx;
+ priv->NMI_WFI_wep_key_len[sme->key_idx] = sme->key_len;
+ NMI_memcpy(priv->NMI_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 = NMI_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 = NMI_TRUE;
+
+ host_int_set_WEPDefaultKeyID(priv->hNMIWFIDrv,sme->key_idx);
+ host_int_add_wep_key_bss_sta(priv->hNMIWFIDrv, sme->key,sme->key_len,sme->key_idx);
+ }
+ else if( sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
+ {
+ //printk("> wpa_version: NL80211_WPA_VERSION_2\n");
+ //case NL80211_WPA_VERSION_2:
+ if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP)
+ {
+ //printk("> WPA2-TKIP\n");
+ //tenuSecurity_t = WPA2_TKIP;
+ u8security = ENCRYPT_ENABLED | WPA2 | TKIP;
+ pcgroup_encrypt_val = "WPA2_TKIP";
+ pccipher_group = "TKIP";
+ }
+ else //TODO: mostafa: here we assume that any other encryption type is AES
+ {
+ //printk("> WPA2-AES\n");
+ //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)
+ {
+ //printk("> wpa_version: NL80211_WPA_VERSION_1\n");
+ if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP)
+ {
+ //printk("> WPA-TKIP\n");
+ //tenuSecurity_t = WPA_TKIP;
+ u8security = ENCRYPT_ENABLED | WPA | TKIP;
+ pcgroup_encrypt_val = "WPA_TKIP";
+ pccipher_group = "TKIP";
+ }
+ else //TODO: mostafa: here we assume that any other encryption type is AES
+ {
+ //printk("> WPA-AES\n");
+ //tenuSecurity_t = WPA_AES;
+ u8security = ENCRYPT_ENABLED | WPA | AES;
+ pcgroup_encrypt_val = "WPA_AES";
+ pccipher_group = "AES";
+
+ }
+ pcwpa_version = "WPA_VERSION_1";
+
+ //break;
+ }
+ else
+ {
+ s32Error = -ENOTSUPP;
+ PRINT_ER("Not supported cipher: Error(%d)\n",s32Error);
+ //PRINT_ER("Cipher-Group: %x\n",sme->crypto.cipher_group);
+
+ 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:
+ //PRINT_D(CFG80211_DBG, "security unhandled [%x] \n",sme->crypto.akm_suites[0]);
+ 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);
+
+ /*Added by Amr - BugID_4793*/
+ if(priv->u8CurrChannel != pstrNetworkInfo->u8channel)
+ priv->u8CurrChannel = pstrNetworkInfo->u8channel;
+
+ if(!pstrWFIDrv->u8P2PConnect)
+ {
+ //NMI_PRINTF("STA CONNECTED CHANNEL %02x %02x\n",u8WLANChannel ,pstrNetworkInfo->u8channel);
+ u8WLANChannel = pstrNetworkInfo->u8channel;
+ //NMI_PRINTF("STA CONNECTED CHANNEL %02x %02x\n",u8WLANChannel,pstrNetworkInfo->u8channel);
+ }
+
+ linux_wlan_set_bssid(dev,pstrNetworkInfo->au8bssid);
+
+ s32Error = host_int_set_join_req(priv->hNMIWFIDrv, pstrNetworkInfo->au8bssid, sme->ssid,
+ sme->ssid_len, sme->ie, sme->ie_len,
+ CfgConnectResult, (void*)priv, u8security,
+ tenuAuth_type, pstrNetworkInfo->u8channel,
+ pstrNetworkInfo->pJoinParams);
+ if(s32Error != NMI_SUCCESS)
+ {
+ PRINT_ER("host_int_set_join_req(): Error(%d) \n", s32Error);
+ s32Error = -ENOENT;
+ goto done;
+ }
+
+done:
+
+ return s32Error;
+}
+
+
+/**
+* @brief NMI_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 NMI_WFI_disconnect(struct wiphy *wiphy, struct net_device *dev,u16 reason_code)
+{
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ struct NMI_WFI_priv* priv;
+ #ifdef NMI_P2P
+ tstrNMI_WFIDrv * pstrWFIDrv;
+ #endif
+ uint8_t NullBssid[ETH_ALEN] = {0};
+ connecting = 0;
+
+
+ priv = wiphy_priv(wiphy);
+ #ifdef NMI_P2P
+ pstrWFIDrv=(tstrNMI_WFIDrv * )priv->hNMIWFIDrv;
+ #endif
+ linux_wlan_set_bssid(priv->dev,NullBssid);
+
+ PRINT_D(CFG80211_DBG,"Disconnecting with reason code(%d)\n", reason_code);
+
+ u8P2Plocalrandom=0x01;
+ u8P2Precvrandom=0x00;
+ bNmi_ie = NMI_FALSE;
+ #ifdef NMI_P2P
+ pstrWFIDrv->u64P2p_MgmtTimeout = 0;
+ #endif
+
+ s32Error = host_int_disconnect(priv->hNMIWFIDrv, reason_code);
+ if(s32Error != NMI_SUCCESS)
+ {
+ PRINT_ER("Error in disconnecting: Error(%d)\n", s32Error);
+ s32Error = -EINVAL;
+ }
+
+ return s32Error;
+}
+
+/**
+* @brief NMI_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 NMI_WFI_add_key(struct wiphy *wiphy, struct net_device *netdev,u8 key_index,
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
+ bool pairwise,
+ #endif
+ const u8 *mac_addr,struct key_params *params)
+
+{
+ NMI_Sint32 s32Error = NMI_SUCCESS,KeyLen = params->key_len;
+ NMI_Uint32 i;
+ struct NMI_WFI_priv* priv;
+ NMI_Uint8* pu8RxMic = NULL;
+ NMI_Uint8* pu8TxMic = NULL;
+ NMI_Uint8 u8mode = NO_ENCRYPT;
+ #ifdef NMI_AP_EXTERNAL_MLME
+ NMI_Uint8 u8gmode = NO_ENCRYPT;
+ NMI_Uint8 u8pmode = NO_ENCRYPT;
+ AUTHTYPE_T tenuAuth_type = ANY;
+ #endif
+
+ priv = wiphy_priv(wiphy);
+
+ PRINT_D(CFG80211_DBG,"Adding key with cipher suite = %x\n",params->cipher);
+
+ /*BugID_5137*/
+ PRINT_D(CFG80211_DBG,"%x %x %d\n",(NMI_Uint32)wiphy, (NMI_Uint32)netdev, key_index);
+
+ PRINT_D(CFG80211_DBG,"key %x %x %x\n",params->key[0],
+ params->key[1],
+ params->key[2]);
+
+
+ switch(params->cipher)
+ {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ #ifdef NMI_AP_EXTERNAL_MLME
+ if(priv->wdev->iftype == NL80211_IFTYPE_AP)
+ {
+
+ priv->NMI_WFI_wep_default = key_index;
+ priv->NMI_WFI_wep_key_len[key_index] = params->key_len;
+ NMI_memcpy(priv->NMI_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->hNMIWFIDrv,params->key,params->key_len,key_index,u8mode,tenuAuth_type);
+ break;
+ }
+ #endif
+ if(NMI_memcmp(params->key,priv->NMI_WFI_wep_key[key_index],params->key_len))
+ {
+ priv->NMI_WFI_wep_default = key_index;
+ priv->NMI_WFI_wep_key_len[key_index] = params->key_len;
+ NMI_memcpy(priv->NMI_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->hNMIWFIDrv,params->key,params->key_len,key_index);
+ }
+
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ case WLAN_CIPHER_SUITE_CCMP:
+ #ifdef NMI_AP_EXTERNAL_MLME
+ if(priv->wdev->iftype == NL80211_IFTYPE_AP || priv->wdev->iftype == NL80211_IFTYPE_P2P_GO)
+ {
+
+ if(priv->nmi_gtk[key_index] == NULL)
+ {
+ priv->nmi_gtk[key_index] = (struct nmi_wfi_key *)NMI_MALLOC(sizeof(struct nmi_wfi_key));
+ priv->nmi_gtk[key_index]->key=NMI_NULL;
+ priv->nmi_gtk[key_index]->seq=NMI_NULL;
+
+ }
+ if(priv->nmi_ptk[key_index] == NULL)
+ {
+ priv->nmi_ptk[key_index] = (struct nmi_wfi_key *)NMI_MALLOC(sizeof(struct nmi_wfi_key));
+ priv->nmi_ptk[key_index]->key=NMI_NULL;
+ priv->nmi_ptk[key_index]->seq=NMI_NULL;
+ }
+
+
+
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
+ if (!pairwise)
+ #else
+ if (!mac_addr || is_broadcast_ether_addr(mac_addr))
+ #endif
+ {
+ if(params->cipher == WLAN_CIPHER_SUITE_TKIP)
+ u8gmode = ENCRYPT_ENABLED |WPA | TKIP;
+ else
+ u8gmode = ENCRYPT_ENABLED |WPA2 | AES;
+
+ priv->nmi_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->nmi_gtk[key_index]->key)
+ NMI_FREE(priv->nmi_gtk[key_index]->key);
+
+ priv->nmi_gtk[key_index]->key = (NMI_Uint8 *)NMI_MALLOC(params->key_len);
+ NMI_memcpy(priv->nmi_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->nmi_gtk[key_index]->seq)
+ NMI_FREE(priv->nmi_gtk[key_index]->seq);
+
+ if((params->seq_len)>0)
+ {
+ priv->nmi_gtk[key_index]->seq = (NMI_Uint8 *)NMI_MALLOC(params->seq_len);
+ NMI_memcpy(priv->nmi_gtk[key_index]->seq,params->seq,params->seq_len);
+ }
+
+ priv->nmi_gtk[key_index]->cipher= params->cipher;
+ priv->nmi_gtk[key_index]->key_len=params->key_len;
+ priv->nmi_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->hNMIWFIDrv,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->nmi_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->nmi_ptk[key_index]->key)
+ NMI_FREE(priv->nmi_ptk[key_index]->key);
+
+ priv->nmi_ptk[key_index]->key = (NMI_Uint8 *)NMI_MALLOC(params->key_len);
+
+ if(priv->nmi_ptk[key_index]->seq)
+ NMI_FREE(priv->nmi_ptk[key_index]->seq);
+
+ if((params->seq_len)>0)
+ priv->nmi_ptk[key_index]->seq = (NMI_Uint8 *)NMI_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]);
+ }
+
+ NMI_memcpy(priv->nmi_ptk[key_index]->key,params->key,params->key_len);
+
+ if((params->seq_len)>0)
+ NMI_memcpy(priv->nmi_ptk[key_index]->seq,params->seq,params->seq_len);
+
+ priv->nmi_ptk[key_index]->cipher= params->cipher;
+ priv->nmi_ptk[key_index]->key_len=params->key_len;
+ priv->nmi_ptk[key_index]->seq_len=params->seq_len;
+
+ host_int_add_ptk(priv->hNMIWFIDrv,params->key,KeyLen,mac_addr,
+ pu8RxMic,pu8TxMic,AP_MODE,u8pmode,key_index);
+ }
+ break;
+ }
+ #endif
+
+ {
+ u8mode=0;
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
+ if (!pairwise)
+ #else
+ if (!mac_addr || is_broadcast_ether_addr(mac_addr))
+ #endif
+ {
+ if(params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP)
+ {
+ //swap the tx mic by rx mic
+ pu8RxMic = params->key+24;
+ pu8TxMic = params->key+16;
+ KeyLen = params->key_len - 16;
+ }
+
+ /*BugID_5137*/
+ /*save keys only on interface 0 (wifi interface)*/
+ if(!g_gtk_keys_saved && netdev == g_linux_wlan->strInterfaceInfo[0].nmc_netdev)
+ {
+ g_add_gtk_key_params.key_idx = key_index;
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
+ g_add_gtk_key_params.pairwise = pairwise;
+ #endif
+ if(!mac_addr)
+ {
+ g_add_gtk_key_params.mac_addr = NULL;
+ }
+ else
+ {
+ g_add_gtk_key_params.mac_addr = NMI_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 = NMI_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= NMI_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 = NMI_TRUE;
+ }
+
+ host_int_add_rx_gtk(priv->hNMIWFIDrv,params->key,KeyLen,
+ key_index,params->seq_len,params->seq,pu8RxMic,pu8TxMic,STATION_MODE,u8mode);
+ //host_int_add_tx_gtk(priv->hNMIWFIDrv,params->key_len,params->key,key_index);
+ }
+ else
+ {
+ if(params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP)
+ {
+ //swap the tx mic by rx mic
+ pu8RxMic = params->key+24;
+ pu8TxMic = params->key+16;
+ KeyLen = params->key_len - 16;
+ }
+
+ /*BugID_5137*/
+ /*save keys only on interface 0 (wifi interface)*/
+ if(!g_ptk_keys_saved && netdev == g_linux_wlan->strInterfaceInfo[0].nmc_netdev)
+ {
+ g_add_ptk_key_params.key_idx = key_index;
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
+ g_add_ptk_key_params.pairwise = pairwise;
+ #endif
+ if(!mac_addr)
+ {
+ g_add_ptk_key_params.mac_addr = NULL;
+ }
+ else
+ {
+ g_add_ptk_key_params.mac_addr = NMI_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 = NMI_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= NMI_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 = NMI_TRUE;
+ }
+
+ host_int_add_ptk(priv->hNMIWFIDrv,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 NMI_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 NMI_WFI_del_key(struct wiphy *wiphy, struct net_device *netdev,
+ u8 key_index,
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
+ bool pairwise,
+ #endif
+ const u8 *mac_addr)
+{
+ struct NMI_WFI_priv* priv;
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+
+ priv = wiphy_priv(wiphy);
+
+ /*BugID_5137*/
+ /*delete saved keys, if any*/
+ if(netdev == g_linux_wlan->strInterfaceInfo[0].nmc_netdev)
+ {
+ g_ptk_keys_saved = NMI_FALSE;
+ g_gtk_keys_saved = NMI_FALSE;
+ g_wep_keys_saved = NMI_FALSE;
+
+ /*Delete saved WEP keys params, if any*/
+ if(g_key_wep_params.key != NULL)
+ {
+ NMI_FREE(g_key_wep_params.key);
+ g_key_wep_params.key = NULL;
+ }
+
+ /*freeing memory allocated by "nmi_gtk" and "nmi_ptk" in "NMI_WIFI_ADD_KEY"*/
+
+ #ifdef NMI_AP_EXTERNAL_MLME
+ if((priv->nmi_gtk[key_index])!=NULL)
+ {
+
+ if(priv->nmi_gtk[key_index]->key!=NULL)
+ {
+
+ NMI_FREE(priv->nmi_gtk[key_index]->key);
+ priv->nmi_gtk[key_index]->key=NULL;
+ }
+ if(priv->nmi_gtk[key_index]->seq)
+ {
+
+ NMI_FREE(priv->nmi_gtk[key_index]->seq);
+ priv->nmi_gtk[key_index]->seq=NULL;
+ }
+
+ NMI_FREE(priv->nmi_gtk[key_index]);
+ priv->nmi_gtk[key_index]=NULL;
+
+ }
+
+ if((priv->nmi_ptk[key_index])!=NULL)
+ {
+
+ if(priv->nmi_ptk[key_index]->key)
+ {
+
+ NMI_FREE(priv->nmi_ptk[key_index]->key);
+ priv->nmi_ptk[key_index]->key=NULL;
+ }
+ if(priv->nmi_ptk[key_index]->seq)
+ {
+
+ NMI_FREE(priv->nmi_ptk[key_index]->seq);
+ priv->nmi_ptk[key_index]->seq=NULL;
+ }
+ NMI_FREE(priv->nmi_ptk[key_index]);
+ priv->nmi_ptk[key_index]=NULL;
+ }
+ #endif
+
+ /*Delete saved PTK and GTK keys params, if any*/
+ if(g_key_ptk_params.key != NULL)
+ {
+ NMI_FREE(g_key_ptk_params.key);
+ g_key_ptk_params.key = NULL;
+ }
+ if(g_key_ptk_params.seq != NULL)
+ {
+ NMI_FREE(g_key_ptk_params.seq);
+ g_key_ptk_params.seq = NULL;
+ }
+
+ if(g_key_gtk_params.key != NULL)
+ {
+ NMI_FREE(g_key_gtk_params.key);
+ g_key_gtk_params.key = NULL;
+ }
+ if(g_key_gtk_params.seq != NULL)
+ {
+ NMI_FREE(g_key_gtk_params.seq);
+ g_key_gtk_params.seq = NULL;
+ }
+
+ /*Reset NMI_CHANGING_VIR_IF register to allow adding futrue keys to CE H/W*/
+ Set_machw_change_vir_if(NMI_FALSE);
+ }
+
+ if(key_index >= 0 && key_index <=3)
+ {
+ NMI_memset(priv->NMI_WFI_wep_key[key_index], 0, priv->NMI_WFI_wep_key_len[key_index]);
+ priv->NMI_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->hNMIWFIDrv,key_index);
+ }
+ else
+ {
+ PRINT_D(CFG80211_DBG, "Removing all installed keys\n");
+ host_int_remove_key(priv->hNMIWFIDrv,mac_addr);
+ }
+
+ return s32Error;
+}
+
+/**
+* @brief NMI_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 NMI_WFI_get_key(struct wiphy *wiphy, struct net_device *netdev,u8 key_index,
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
+ bool pairwise,
+ #endif
+ const u8 *mac_addr,void *cookie,void (*callback)(void* cookie, struct key_params*))
+{
+
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+
+ struct NMI_WFI_priv* priv;
+ struct key_params key_params;
+ NMI_Uint32 i;
+ priv= wiphy_priv(wiphy);
+
+
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
+ if (!pairwise)
+ #else
+ if (!mac_addr || is_broadcast_ether_addr(mac_addr))
+ #endif
+ {
+ PRINT_D(CFG80211_DBG,"Getting group key idx: %x\n",key_index);
+
+ key_params.key=priv->nmi_gtk[key_index]->key;
+ key_params.cipher=priv->nmi_gtk[key_index]->cipher;
+ key_params.key_len=priv->nmi_gtk[key_index]->key_len;
+ key_params.seq=priv->nmi_gtk[key_index]->seq;
+ key_params.seq_len=priv->nmi_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->nmi_ptk[key_index]->key;
+ key_params.cipher=priv->nmi_ptk[key_index]->cipher;
+ key_params.key_len=priv->nmi_ptk[key_index]->key_len;
+ key_params.seq=priv->nmi_ptk[key_index]->seq;
+ key_params.seq_len=priv->nmi_ptk[key_index]->seq_len;
+ }
+
+ callback(cookie,&key_params);
+
+ return s32Error;//priv->nmi_gtk->key_len ?0 : -ENOENT;
+}
+
+/**
+* @brief NMI_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 NMI_WFI_set_default_key(struct wiphy *wiphy,struct net_device *netdev,u8 key_index
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,37)
+ ,bool unicast, bool multicast
+ #endif
+ )
+{
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ struct NMI_WFI_priv* priv;
+
+
+ priv = wiphy_priv(wiphy);
+
+ PRINT_D(CFG80211_DBG,"Setting default key with idx = %d \n", key_index);
+
+ if(key_index!= priv->NMI_WFI_wep_default)
+ {
+
+ host_int_set_WEPDefaultKeyID(priv->hNMIWFIDrv,key_index);
+ }
+
+ return s32Error;
+}
+
+/**
+* @brief NMI_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 NMI_WFI_dump_survey(struct wiphy *wiphy, struct net_device *netdev,
+ int idx, struct survey_info *info)
+{
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+
+
+ if (idx != 0)
+ {
+ s32Error = -ENOENT;
+ PRINT_ER("Error Idx value doesn't equal zero: Error(%d)\n",s32Error);
+
+ }
+
+ return s32Error;
+}
+
+
+/**
+* @brief NMI_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 NMI_WFI_get_station(struct wiphy *wiphy, struct net_device *dev,
+ u8 *mac, struct station_info *sinfo)
+{
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ struct NMI_WFI_priv* priv;
+ perInterface_wlan_t* nic;
+ #ifdef NMI_AP_EXTERNAL_MLME
+ NMI_Uint32 i =0;
+ NMI_Uint32 associatedsta = 0;
+ NMI_Uint32 inactive_time=0;
+ #endif
+ priv = wiphy_priv(wiphy);
+ nic = netdev_priv(dev);
+
+ #ifdef NMI_AP_EXTERNAL_MLME
+ if(nic->iftype == AP_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 |= STATION_INFO_INACTIVE_TIME;
+
+ host_int_get_inactive_time(priv->hNMIWFIDrv, 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;
+ #if 0
+ NMI_Sint8 s8lnkspd = 0;
+ static NMI_Uint32 u32FirstLnkSpdCnt = 0;
+
+
+ sinfo->filled |= STATION_INFO_SIGNAL;
+
+ s32Error = host_int_get_rssi(priv->hNMIWFIDrv, &(sinfo->signal));
+ if(s32Error)
+ PRINT_ER("Failed to send get host channel param's message queue ");
+
+ PRINT_D(CFG80211_DBG,"Rssi value = %d %d,%d\n",sinfo->signal,Statisitcs_DroppedAcks,Statisitcs_totalAcks);
+
+ sinfo->filled |= STATION_INFO_TX_BITRATE;
+
+ /* To get realistic Link Speed, let it fixed for first 10 times to give chance for Autorate to ramp up as traffic starts */
+
+ u32FirstLnkSpdCnt++;
+
+ if(u32FirstLnkSpdCnt > 10)
+ {
+ priv->gbAutoRateAdjusted = NMI_TRUE;
+ }
+
+ if(priv->gbAutoRateAdjusted == NMI_FALSE)
+ {
+ sinfo->txrate.legacy = 54 * 10;
+ }
+ else
+ {
+ s32Error = host_int_get_link_speed(priv->hNMIWFIDrv, &s8lnkspd);
+ if(s32Error)
+ {
+ PRINT_ER("Failed to send get host channel param's message queue ");
+ }
+ else
+ {
+ PRINT_D(CFG80211_DBG,"link_speed=%d\n", s8lnkspd);
+ sinfo->txrate.legacy = s8lnkspd * 10;
+ }
+ }
+ #else
+ host_int_get_statistics(priv->hNMIWFIDrv,&strStatistics);
+
+ /*
+ * tony: 2013-11-13
+ * tx_failed introduced more than
+ * kernel version 3.0.0
+ */
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0)
+ sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_RX_PACKETS | STATION_INFO_TX_PACKETS
+ | STATION_INFO_TX_FAILED | STATION_INFO_TX_BITRATE;
+ #else
+ sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_RX_PACKETS | STATION_INFO_TX_PACKETS
+ | STATION_INFO_TX_BITRATE;
+ #endif
+
+ sinfo->signal = strStatistics.s8RSSI;
+ sinfo->rx_packets = strStatistics.u32RxCount;
+ sinfo->tx_packets = strStatistics.u32TxCount + strStatistics.u32TxFailureCount;
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0)
+ sinfo->tx_failed = strStatistics.u32TxFailureCount;
+ #endif
+ sinfo->txrate.legacy = strStatistics.u8LinkSpeed*10;
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0)
+ printk("*** stats[%d][%d][%d][%d][%d]\n",sinfo->signal,sinfo->rx_packets,sinfo->tx_packets,
+ sinfo->tx_failed,sinfo->txrate.legacy);
+ #else
+ printk("*** stats[%d][%d][%d][%d]\n",sinfo->signal,sinfo->rx_packets,sinfo->tx_packets,
+ sinfo->txrate.legacy);
+ #endif
+
+ #endif
+
+ }
+
+
+
+ return s32Error;
+}
+
+
+/**
+* @brief NMI_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 NMI_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 NMI_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 NMI_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 NMI_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 NMI_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 NMI_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 NMI_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 NMI_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 NMI_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 NMI_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 NMI_WFI_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+{
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ tstrCfgParamVal pstrCfgParamVal;
+ struct NMI_WFI_priv* priv;
+
+ priv = wiphy_priv(wiphy);
+// priv = netdev_priv(priv->wdev->netdev);
+
+ pstrCfgParamVal.u32SetCfgFlag = 0;
+ PRINT_D(CFG80211_DBG,"Setting Wiphy params \n");
+
+ if(changed & WIPHY_PARAM_RETRY_SHORT)
+ {
+ PRINT_D(CFG80211_DBG,"Setting WIPHY_PARAM_RETRY_SHORT %d\n",
+ priv->dev->ieee80211_ptr->wiphy->retry_short);
+ pstrCfgParamVal.u32SetCfgFlag |= RETRY_SHORT;
+ pstrCfgParamVal.short_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_short;
+ }
+ if(changed & WIPHY_PARAM_RETRY_LONG)
+ {
+
+ PRINT_D(CFG80211_DBG,"Setting WIPHY_PARAM_RETRY_LONG %d\n",priv->dev->ieee80211_ptr->wiphy->retry_long);
+ pstrCfgParamVal.u32SetCfgFlag |= RETRY_LONG;
+ pstrCfgParamVal.long_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_long;
+
+ }
+ if(changed & WIPHY_PARAM_FRAG_THRESHOLD)
+ {
+ PRINT_D(CFG80211_DBG,"Setting WIPHY_PARAM_FRAG_THRESHOLD %d\n",priv->dev->ieee80211_ptr->wiphy->frag_threshold);
+ pstrCfgParamVal.u32SetCfgFlag |= FRAG_THRESHOLD;
+ pstrCfgParamVal.frag_threshold = priv->dev->ieee80211_ptr->wiphy->frag_threshold;
+
+ }
+
+ if(changed & WIPHY_PARAM_RTS_THRESHOLD)
+ {
+ PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_RTS_THRESHOLD %d\n",priv->dev->ieee80211_ptr->wiphy->rts_threshold);
+
+ pstrCfgParamVal.u32SetCfgFlag |= RTS_THRESHOLD;
+ pstrCfgParamVal.rts_threshold = priv->dev->ieee80211_ptr->wiphy->rts_threshold;
+
+ }
+
+ PRINT_D(CFG80211_DBG,"Setting CFG params in the host interface\n");
+ s32Error = hif_set_cfg(priv->hNMIWFIDrv,&pstrCfgParamVal);
+ if(s32Error)
+ PRINT_ER("Error in setting WIPHY PARAMS\n");
+
+
+ return s32Error;
+}
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32)
+/**
+* @brief NMI_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 NMI_WFI_set_bitrate_mask(struct wiphy *wiphy,
+ struct net_device *dev,const u8 *peer,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ //strCfgParamVal pstrCfgParamVal;
+ //struct NMI_WFI_priv* priv;
+
+ PRINT_D(CFG80211_DBG, "Setting Bitrate mask function\n");
+#if 0
+ priv = wiphy_priv(wiphy);
+ //priv = netdev_priv(priv->wdev->netdev);
+
+ pstrCfgParamVal.curr_tx_rate = mask->control[IEEE80211_BAND_2GHZ].legacy;
+
+ PRINT_D(CFG80211_DBG, "Tx rate = %d\n",pstrCfgParamVal.curr_tx_rate);
+ s32Error = hif_set_cfg(priv->hNMIWFIDrv,&pstrCfgParamVal);
+
+ if(s32Error)
+ PRINT_ER("Error in setting bitrate\n");
+#endif
+ return s32Error;
+
+}
+
+/**
+* @brief NMI_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 NMI_WFI_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_pmksa *pmksa)
+{
+ NMI_Uint32 i;
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ NMI_Uint8 flag = 0;
+
+ struct NMI_WFI_priv* priv = wiphy_priv(wiphy);
+
+ PRINT_D(CFG80211_DBG, "Setting PMKSA\n");
+
+
+ for (i = 0; i < priv->pmkid_list.numpmkid; i++)
+ {
+ if (!NMI_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 < NMI_MAX_NUM_PMKIDS) {
+ PRINT_D(CFG80211_DBG, "Setting PMKID in private structure\n");
+ NMI_memcpy(priv->pmkid_list.pmkidlist[i].bssid, pmksa->bssid,
+ ETH_ALEN);
+ NMI_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->hNMIWFIDrv, &priv->pmkid_list);
+ }
+ return s32Error;
+}
+
+/**
+* @brief NMI_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 NMI_WFI_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_pmksa *pmksa)
+{
+
+ NMI_Uint32 i;
+ NMI_Uint8 flag = 0;
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+
+ struct NMI_WFI_priv* priv = wiphy_priv(wiphy);
+ //priv = netdev_priv(priv->wdev->netdev);
+
+ PRINT_D(CFG80211_DBG, "Deleting PMKSA keys\n");
+
+ for (i = 0; i < priv->pmkid_list.numpmkid; i++)
+ {
+ if (!NMI_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");
+ NMI_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++) {
+ NMI_memcpy(priv->pmkid_list.pmkidlist[i].bssid,
+ priv->pmkid_list.pmkidlist[i+1].bssid,
+ ETH_ALEN);
+ NMI_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 NMI_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 NMI_WFI_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
+{
+ struct NMI_WFI_priv* priv = wiphy_priv(wiphy);
+ //priv = netdev_priv(priv->wdev->netdev);
+
+ PRINT_D(CFG80211_DBG, "Flushing PMKID key values\n");
+
+ /*Get cashed Pmkids and set all with zeros*/
+ NMI_memset(&priv->pmkid_list, 0, sizeof(tstrHostIFpmkidAttr) );
+
+ return 0;
+}
+#endif
+
+#ifdef NMI_P2P
+
+/**
+* @brief NMI_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 NMI_WFI_CfgParseRxAction(NMI_Uint8 * buf,NMI_Uint32 len)
+{
+ NMI_Uint32 index=0;
+ NMI_Uint32 i=0,j=0;
+ while(index < len)
+ {
+ if(buf[index] == GO_INTENT_ATTR_ID)
+ {
+ buf[index+3] =(buf[index+3] & 0x01) | (0x00 << 1);
+ }
+
+ else if(buf[index] == CHANLIST_ATTR_ID)
+ {
+
+ for(i=index+3;i<((index+3)+buf[index+1]);i++)
+ {
+ if(buf[i] == 0x51)
+ {
+ for(j=i+2;j<((i+2)+buf[i+1]);j++)
+ {
+ buf[j] = u8WLANChannel;
+ }
+ break;
+ }
+
+ }
+ }
+ else if(buf[index] == OPERCHAN_ATTR_ID)
+ {
+ buf[index+6]=0x51;
+ buf[index+7]=u8WLANChannel;
+ }
+
+ index+=buf[index+1]+3; //ID,Length byte
+
+ }
+
+}
+
+/**
+* @brief NMI_WFI_CfgParseTxAction
+* @details Function parses the transmitted action frames and modifies the
+* GO Intent attribute
+* @param[in] u8* Buffer, u32 length
+* @return NONE.
+* @author mdaftedar
+* @date 12 DEC 2012
+* @version
+*/
+void NMI_WFI_CfgParseTxAction(NMI_Uint8 * buf,NMI_Uint32 len,NMI_Bool bOperChan)
+{
+ NMI_Uint32 index=0;
+ NMI_Uint32 i=0,j=0;
+
+ while(index < len)
+ {
+ if(buf[index] == GO_INTENT_ATTR_ID)
+ {
+ buf[index+3] =(buf[index+3] & 0x01) | (0x0f << 1);
+ break;
+ }
+
+ /*It's required to parse the operating channel and the channel only in the P2P_INVITE case*/
+ if(bOperChan)
+ {
+ if(buf[index] == CHANLIST_ATTR_ID)
+ {
+
+ for(i=index+3;i<((index+3)+buf[index+1]);i++)
+ {
+ if(buf[i] == 0x51)
+ {
+
+ for(j=i+2;j<((i+2)+buf[i+1]);j++)
+ {
+
+ buf[j] = u8WLANChannel;
+
+ }
+ break;
+ }
+
+ }
+ }
+ else if(buf[index] == OPERCHAN_ATTR_ID)
+ {
+
+ buf[index+6]=0x51;
+ buf[index+7]=u8WLANChannel;
+
+ }
+ }
+ index+=buf[index+1]+3; //ID,Length byte
+
+ }
+}
+/* @brief NMI_WFI_p2p_rx
+* @details
+* @param[in]
+
+* @return None
+* @author Mai Daftedar
+* @date 2 JUN 2013
+* @version 1.0
+*/
+
+void NMI_WFI_p2p_rx (struct net_device *dev,uint8_t *buff, uint32_t size)
+{
+
+ struct NMI_WFI_priv* priv;
+ NMI_Uint32 header,pkt_offset;
+ tstrNMI_WFIDrv * pstrWFIDrv;
+ NMI_Uint32 i=0,j=0;
+ priv= wiphy_priv(dev->ieee80211_ptr->wiphy);
+ pstrWFIDrv = (tstrNMI_WFIDrv *)priv->hNMIWFIDrv;
+ //Get NMI 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)
+ {
+ if(buff[0]==IEEE80211_STYPE_PROBE_RESP)
+ {
+ PRINT_D(GENERIC_DBG,"Probe response ACK\n");
+ cfg80211_mgmt_tx_status(dev,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 subtype: %x Dialog token: %d FS: %x %x\n",buff[30], buff[31], buff[21], buff[22]);
+ cfg80211_mgmt_tx_status(dev,priv->u64tx_cookie,buff,size,true,GFP_KERNEL);
+ }
+ else
+ {
+ PRINT_D(GENERIC_DBG,"Fail Ack - Action frame subtype: %x Dialog token: %d FS: %x %x\n",buff[30], buff[31], buff[21], buff[22]);
+ cfg80211_mgmt_tx_status(dev,priv->u64tx_cookie,buff,size,false,GFP_KERNEL);
+ }
+ }
+
+
+ }
+ else
+ {
+ if(buff[0] == ACTION_FRAME)
+ PRINT_D(GENERIC_DBG,"Rx Action Frame Type: %x\n", buff[30]);
+
+
+ if((buff[0] == ACTION_FRAME) && ( buff[30] == GO_NEG_REQ_ATTR_ID || buff[30] == GO_NEG_RSP_ATTR_ID|| buff[30] == P2P_INVITE_REQ || buff[30] == P2P_INVITE_RSP))
+ {
+ if(!bNmi_ie)
+ {
+ for(i=0;i<size;i++)
+ {
+ if ((buff[i]==0xdd) && (buff[i+1] == 0x05) &&
+ (buff[i+2] == 0x00) && (buff[i+3] == 0x08) &&
+ (buff[i+4] == 0x40) && (buff[i+5] == 0x03))
+ {
+ u8P2Precvrandom = buff[i+6];
+ bNmi_ie=NMI_TRUE;
+ PRINT_D(GENERIC_DBG,"NMI Vendor specific IE:%02x\n",u8P2Precvrandom);
+ break;
+ }
+ }
+ }
+
+ if(u8P2Plocalrandom > u8P2Precvrandom)
+ {
+ /*Search for the P2P public action frames*/
+ for(i=1;i<size;i++)
+ {
+ if(buff[i]==PUBLICACTION_CAT && buff[i+1]==PUBLICACTION_FRAME && !(memcmp(u8P2P_oui,&buff[i+2],4)))
+ {
+ if(buff[i+6] == GO_NEG_REQ_ATTR_ID || GO_NEG_RSP_ATTR_ID || buff[i+6] == P2P_INVITE_REQ || buff[i+6] == P2P_INVITE_RSP)
+ {
+ for(j=i+8;j<size;j++)
+ {
+ if(buff[j]== P2PELEM_ID && !(memcmp(u8P2P_oui,&buff[j+2],4)) )
+ {
+ NMI_WFI_CfgParseRxAction(&buff[j+6],size-(j+6));
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ PRINT_D(GENERIC_DBG,"PEER WILL BE GO LocaRand=%02x RecvRand %02x\n",u8P2Plocalrandom,u8P2Precvrandom);
+
+ }
+
+ if(priv->bCfgScanning == NMI_TRUE && jiffies >= pstrWFIDrv->u64P2p_MgmtTimeout)
+ {
+ PRINT_D(GENERIC_DBG,"Receiving action frames from wrong channels\n");
+ return;
+ }
+
+ PRINT_D(GENERIC_DBG,"Sending P2P to host\n");
+
+ if((buff[0] == ACTION_FRAME) && ( buff[30] == GO_NEG_REQ_ATTR_ID || buff[30] == GO_NEG_RSP_ATTR_ID) && ( bNmi_ie))
+ {
+ //extra attribute for sig_dbm: signal strength in mBm, or 0 if unknown
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
+ cfg80211_rx_mgmt(dev,priv->u32listen_freq, 0, buff,size-7,GFP_ATOMIC); // rachel
+ #else
+ cfg80211_rx_mgmt(dev,priv->u32listen_freq,buff,size-7,GFP_ATOMIC);
+ #endif
+ }
+ else
+ {
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
+ cfg80211_rx_mgmt(dev,priv->u32listen_freq, 0, buff,size,GFP_ATOMIC); // rachel
+ #else
+ cfg80211_rx_mgmt(dev,priv->u32listen_freq,buff,size,GFP_ATOMIC);
+ #endif
+ }
+ }
+}
+/**
+* @brief NMI_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 NMI_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 NMI_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 NMI_WFI_RemainOnChannelReady(void* pUserVoid)
+{
+ struct NMI_WFI_priv* priv;
+ priv = (struct NMI_WFI_priv*)pUserVoid;
+
+ PRINT_D(HOSTINF_DBG, "Remain on channel ready \n");
+
+ cfg80211_ready_on_channel(priv->dev,
+ priv->strRemainOnChanParams.u64ListenCookie,
+ priv->strRemainOnChanParams.pstrListenChan,
+ priv->strRemainOnChanParams.tenuChannelType,
+ priv->strRemainOnChanParams.u32ListenDuration,
+ GFP_KERNEL);
+}
+
+/**
+* @brief NMI_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 NMI_WFI_RemainOnChannelExpired(void* pUserVoid)
+{
+ struct NMI_WFI_priv* priv;
+ priv = (struct NMI_WFI_priv*)pUserVoid;
+
+ PRINT_D(GENERIC_DBG, "Remain on channel expired \n");
+
+ /*Inform wpas of remain-on-channel expiration*/
+ cfg80211_remain_on_channel_expired(priv->dev,
+ priv->strRemainOnChanParams.u64ListenCookie,
+ priv->strRemainOnChanParams.pstrListenChan ,
+ priv->strRemainOnChanParams.tenuChannelType,
+ GFP_KERNEL);
+ priv->u8CurrChannel =-1;
+}
+
+
+/**
+* @brief NMI_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 NMI_WFI_remain_on_channel(struct wiphy *wiphy,
+ struct net_device *dev,struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type,
+ unsigned int duration,u64 *cookie)
+{
+ NMI_Sint32 freq;
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ struct NMI_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(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP)
+ {
+ PRINT_D(GENERIC_DBG,"Required remain-on-channel while in AP mode");
+ return s32Error;
+ }
+
+ if(priv->u8CurrChannel != chan->hw_value)
+ priv->u8CurrChannel = chan->hw_value;
+
+ /*Setting params needed by NMI_WFI_RemainOnChannelExpired()*/
+ priv->strRemainOnChanParams.pstrListenChan = chan;
+ priv->strRemainOnChanParams.u64ListenCookie = *cookie;
+ priv->strRemainOnChanParams.tenuChannelType = channel_type;
+
+ #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
+ freq = ieee80211_channel_to_frequency((NMI_Sint32)chan->hw_value);
+ #else
+ freq = ieee80211_channel_to_frequency((NMI_Sint32)chan->hw_value, IEEE80211_BAND_2GHZ);
+ #endif
+ priv->u32listen_freq= freq;
+
+ s32Error = host_int_remain_on_channel(priv->hNMIWFIDrv, duration,chan->hw_value,NMI_WFI_RemainOnChannelExpired,NMI_WFI_RemainOnChannelReady,(void *)priv);
+
+ return s32Error;
+}
+
+/**
+* @brief NMI_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 NMI_WFI_cancel_remain_on_channel(struct wiphy *wiphy, struct net_device *dev,
+ u64 cookie)
+{
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ struct NMI_WFI_priv* priv;
+ priv = wiphy_priv(wiphy);
+
+ PRINT_D(CFG80211_DBG, "Cancel remain on channel\n");
+
+ s32Error = host_int_ListenStateExpired(priv->hNMIWFIDrv);
+ return 0;
+}
+/**
+* @brief NMI_WFI_add_nmivendorspec
+* @details Adding NMI information elemet to allow two NMI devices to
+ identify each other and connect
+* @param[in] NMI_Uint8 * buf
+* @return void
+* @author mdaftedar
+* @date 01 JAN 2014
+* @version 1.0
+*/
+void NMI_WFI_add_nmivendorspec(NMI_Uint8 * buff)
+{
+ memcpy(buff,u8P2P_vendorspec,sizeof(u8P2P_vendorspec));
+}
+/**
+* @brief NMI_WFI_mgmt_tx_frame
+* @details
+*
+* @param[in]
+* @return NONE.
+* @author mdaftedar
+* @date 01 JUL 2012
+* @version
+*/
+extern linux_wlan_t* g_linux_wlan;
+extern NMI_Bool bEnablePS;
+#if KERNEL_VERSION(3,1,0) > LINUX_VERSION_CODE
+
+ int NMI_WFI_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
+ struct ieee80211_channel *chan, bool offchan,
+
+ enum nl80211_channel_type channel_type,
+
+ bool channel_type_valid, unsigned int wait,
+
+ const u8 *buf, size_t len, u64 *cookie)
+
+
+
+#else
+
+ int NMI_WFI_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
+
+ struct ieee80211_channel *chan, bool offchan,
+
+ enum nl80211_channel_type channel_type,
+
+ bool channel_type_valid, unsigned int wait,
+
+ const u8 *buf, size_t len, bool no_cck,
+
+ bool dont_wait_for_ack, u64 *cookie)
+
+#endif
+{
+ const struct ieee80211_mgmt *mgmt;
+ linux_wlan_t* nic;
+ struct p2p_mgmt_data *mgmt_tx;
+ struct NMI_WFI_priv* priv;
+ NMI_Uint16 fc;
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ tstrNMI_WFIDrv * pstrWFIDrv;
+ NMI_Uint32 i,j;
+
+ /*BugID_5213*/
+ /*Net length of mgmt_tx->buff (Frame passed from WPAS + Added attributes)*/
+ NMI_Uint32 buf_len = len + sizeof(u8P2P_vendorspec) + sizeof(u8P2Plocalrandom);
+
+ priv = wiphy_priv(wiphy);
+ nic =netdev_priv(dev);
+ pstrWFIDrv = (tstrNMI_WFIDrv *)priv->hNMIWFIDrv;
+ *cookie = (unsigned long)buf;
+ priv->u64tx_cookie = *cookie;
+ mgmt = (const struct ieee80211_mgmt *) buf;
+ fc = mgmt->frame_control;
+ /*mgmt frame allocation*/
+ mgmt_tx = (struct p2p_mgmt_data*)NMI_MALLOC(sizeof(struct p2p_mgmt_data));
+ if(mgmt_tx == NULL){
+ PRINT_ER("Failed to allocate memory for mgmt_tx structure\n");
+ return NMI_FAIL;
+ }
+ mgmt_tx->buff= (char*)NMI_MALLOC(buf_len);
+ if(mgmt_tx->buff == NULL)
+ {
+ PRINT_ER("Failed to allocate memory for mgmt_tx buff\n");
+ return NMI_FAIL;
+ }
+ memcpy(mgmt_tx->buff,buf,len);
+ mgmt_tx->size=len;
+
+ /*send mgmt frame to firmware*/
+
+ //if(priv->u8CurrChannel != chan->hw_value)
+
+ priv->u8CurrChannel = chan->hw_value;
+
+ /*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[0] != 0xd0 || buf[30] != 0x02)
+ {
+ PRINT_D(GENERIC_DBG,"Setting channel: %d\n",chan->hw_value);
+ host_int_set_mac_chnl_num(priv->hNMIWFIDrv, chan->hw_value);
+ }
+
+ if ( (buf[0] == ACTION_FRAME) && ( buf[30] == GO_NEG_REQ_ATTR_ID || buf[30] == GO_NEG_RSP_ATTR_ID || buf[30] == P2P_INVITE_REQ || buf[30] == P2P_INVITE_RSP))
+ {
+ if(u8P2Plocalrandom == 1 && u8P2Precvrandom<u8P2Plocalrandom)
+ {
+ get_random_bytes(&u8P2Plocalrandom, 1);
+ /*TODO:If zero?*/
+ }
+ if(u8P2Plocalrandom > u8P2Precvrandom)
+ {
+ PRINT_D(GENERIC_DBG,"LOCAL WILL BE GO LocaRand=%02x RecvRand %02x\n",u8P2Plocalrandom,u8P2Precvrandom);
+ for(i=1;i<len;i++)
+ {
+ /*Search for the P2P public action frames*/
+ if(buf[i]==PUBLICACTION_CAT && buf[i+1]==PUBLICACTION_FRAME && !(memcmp(u8P2P_oui,&buf[i+2],4)))
+ {
+ if(buf[i+6] == GO_NEG_REQ_ATTR_ID || GO_NEG_RSP_ATTR_ID || buf[i+6] == P2P_INVITE_REQ || buf[i+6] == P2P_INVITE_RSP)
+ {
+ for(j=i+8;j<len;j++)
+ {
+ if(buf[j]== P2PELEM_ID && !(memcmp(u8P2P_oui,&buf[j+2],4)) )
+ {
+ if(buf[30]==P2P_INVITE_REQ || buf[30]==P2P_INVITE_RSP)
+ NMI_WFI_CfgParseTxAction(&mgmt_tx->buff[j+6],len-(j+6),NMI_TRUE);
+ else
+ NMI_WFI_CfgParseTxAction(&mgmt_tx->buff[j+6],len-(j+6),NMI_FALSE);
+ break;
+ }
+ }
+ }
+ }
+ }
+ NMI_WFI_add_nmivendorspec(&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);
+ }
+ if(fc == IEEE80211_STYPE_ACTION)
+ {
+ PRINT_D(GENERIC_DBG,"TX: ACTION FRAME Type:%x : Chan:%d\n",buf[30], 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);
+ }
+ else if(fc == IEEE80211_STYPE_PROBE_RESP)
+ {
+ PRINT_D(GENERIC_DBG,"TX: Probe Response\n");
+ }
+
+ g_linux_wlan->oup.wlan_add_mgmt_to_tx_que(mgmt_tx,mgmt_tx->buff,mgmt_tx->size,NMI_WFI_mgmt_tx_complete);
+
+ return s32Error;
+}
+
+int NMI_WFI_mgmt_tx_cancel_wait(struct wiphy *wiphy,
+ struct net_device *dev,
+ u64 cookie)
+{
+ struct NMI_WFI_priv* priv;
+ tstrNMI_WFIDrv * pstrWFIDrv;
+ priv = wiphy_priv(wiphy);
+ pstrWFIDrv = (tstrNMI_WFIDrv *)priv->hNMIWFIDrv;
+
+
+ PRINT_D(GENERIC_DBG,"Tx Cancel wait :%lu\n",jiffies);
+ pstrWFIDrv->u64P2p_MgmtTimeout = jiffies;
+
+ return 0;
+}
+
+/**
+* @brief NMI_WFI_action
+* @details Transmit an action frame
+* @param[in]
+* @return int : Return 0 on Success.
+* @author mdaftedar
+* @date 01 JUL 2012
+* @version 1.0
+* */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)
+int NMI_WFI_action(struct wiphy *wiphy, struct net_device *dev,
+ struct ieee80211_channel *chan,enum nl80211_channel_type channel_type,
+ const u8 *buf, size_t len, u64 *cookie)
+{
+ PRINT_D(HOSTAPD_DBG,"In action function\n");
+ return NMI_SUCCESS;
+}
+#endif
+#else
+
+/**
+* @brief NMI_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 NMI_WFI_frame_register(struct wiphy *wiphy,struct net_device *dev,
+ u16 frame_type, bool reg)
+{
+
+ struct NMI_WFI_priv* priv;
+ perInterface_wlan_t* nic;
+
+
+ priv = wiphy_priv(wiphy);
+ nic = netdev_priv(priv->wdev->netdev);
+
+ /*If mac is closed, then return*/
+ /*if(!nic->nmc1000_initialized)
+ {
+ PRINT_D(GENERIC_DBG,"Return since mac is closed\n");
+ return;
+ }*/
+
+ /*BugID_5137*/
+ if(!frame_type)
+ return;
+
+ PRINT_D(GENERIC_DBG,"Frame registering Frame Type: %x: Boolean: %d\n",frame_type,reg);
+ host_int_frame_register(priv->hNMIWFIDrv,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;
+ }
+
+ }
+
+}
+#endif
+#endif /*NMI_P2P*/
+
+/**
+* @brief NMI_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 NMI_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 NMI_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 NMI_WFI_dump_station(struct wiphy *wiphy, struct net_device *dev,
+ int idx, u8 *mac, struct station_info *sinfo)
+{
+ struct NMI_WFI_priv* priv;
+ PRINT_D(CFG80211_DBG, "Dumping station information\n");
+
+ if (idx != 0)
+ return -ENOENT;
+
+ priv = wiphy_priv(wiphy);
+ //priv = netdev_priv(priv->wdev->netdev);
+
+ sinfo->filled |= STATION_INFO_SIGNAL ;
+
+ host_int_get_rssi(priv->hNMIWFIDrv, &(sinfo->signal));
+
+#if 0
+ sinfo->filled |= STATION_INFO_TX_BYTES |
+ STATION_INFO_TX_PACKETS |
+ STATION_INFO_RX_BYTES |
+ STATION_INFO_RX_PACKETS | STATION_INFO_SIGNAL | STATION_INFO_INACTIVE_TIME;
+
+ NMI_SemaphoreAcquire(&SemHandleUpdateStats,NULL);
+ sinfo->inactive_time = priv->netstats.rx_time > priv->netstats.tx_time ? jiffies_to_msecs(jiffies - priv->netstats.tx_time) : jiffies_to_msecs(jiffies - priv->netstats.rx_time);
+ sinfo->rx_bytes = priv->netstats.rx_bytes;
+ sinfo->tx_bytes = priv->netstats.tx_bytes;
+ sinfo->rx_packets = priv->netstats.rx_packets;
+ sinfo->tx_packets = priv->netstats.tx_packets;
+ NMI_SemaphoreRelease(&SemHandleUpdateStats,NULL);
+#endif
+ return 0;
+
+}
+
+
+/**
+* @brief NMI_WFI_set_power_mgmt
+* @details
+* @param[in]
+* @return int : Return 0 on Success.
+* @author mdaftedar
+* @date 01 JUL 2012
+* @version 1.0NMI_WFI_set_cqmNMI_WFI_set_cqm_rssi_configNMI_WFI_set_cqm_rssi_configNMI_WFI_set_cqm_rssi_configNMI_WFI_set_cqm_rssi_config_rssi_config
+*/
+int NMI_WFI_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
+ bool enabled, int timeout)
+{
+ struct NMI_WFI_priv* priv;
+ PRINT_D(CFG80211_DBG," Power save Enabled= %d , TimeOut = %d\n",enabled,timeout);
+
+ if (wiphy == NMI_NULL)
+ return -ENOENT;
+
+ priv = wiphy_priv(wiphy);
+ if(priv->hNMIWFIDrv == NMI_NULL)
+ {
+ NMI_ERROR("Driver is NULL\n");
+ return -EIO;
+ }
+
+ if(bEnablePS == NMI_TRUE)
+ host_int_set_power_mgmt(priv->hNMIWFIDrv, enabled, timeout);
+
+
+ return NMI_SUCCESS;
+
+}
+#ifdef NMI_AP_EXTERNAL_MLME
+/**
+* @brief NMI_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 nmc1000_wlan_deinit(linux_wlan_t *nic);
+int nmc1000_wlan_init(struct net_device *dev, perInterface_wlan_t* p_nic);
+
+static int NMI_WFI_change_virt_intf(struct wiphy *wiphy,struct net_device *dev,
+ enum nl80211_iftype type, u32 *flags,struct vif_params *params)
+{
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ struct NMI_WFI_priv* priv;
+ //struct NMI_WFI_mon_priv* mon_priv;
+ perInterface_wlan_t* nic;
+ NMI_Uint8 interface_type;
+ NMI_Uint16 TID=0;
+ #ifdef NMI_P2P
+ NMI_Uint8 i;
+ #endif
+
+ nic = netdev_priv(dev);
+ priv = wiphy_priv(wiphy);
+
+ PRINT_D(HOSTAPD_DBG,"In Change virtual interface function\n");
+ PRINT_D(HOSTAPD_DBG,"Wireless interface name =%s\n", dev->name);
+ u8P2Plocalrandom=0x01;
+ u8P2Precvrandom=0x00;
+
+ bNmi_ie= NMI_FALSE;
+
+ /*BugID_5137*/
+ /*Set NMI_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(NMI_TRUE);
+ }
+
+ switch(type)
+ {
+ case NL80211_IFTYPE_STATION:
+ connecting = 0;
+ PRINT_D(HOSTAPD_DBG,"Interface type = NL80211_IFTYPE_STATION\n");
+ //linux_wlan_set_bssid(dev,g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
+
+ dev->ieee80211_ptr->iftype = type;
+ priv->wdev->iftype = type;
+ nic->monitor_flag = 0;
+ nic->iftype = STATION_MODE;
+
+ #ifndef SIMULATION
+ #ifdef NMI_P2P
+ interface_type = nic->iftype;
+ nic->iftype = STATION_MODE;
+
+ if(g_linux_wlan->nmc1000_initialized)
+ {
+ // 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);
+
+ nmc1000_wlan_deinit(g_linux_wlan);
+ nmc1000_wlan_init(dev, nic);
+ g_nmc_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((NMI_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+ g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
+ host_int_set_operation_mode(priv->hNMIWFIDrv,STATION_MODE);
+
+ /*Add saved WEP keys, if any*/
+ if(g_wep_keys_saved)
+ {
+ host_int_set_WEPDefaultKeyID((NMI_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+ g_key_wep_params.key_idx);
+ host_int_add_wep_key_bss_sta((NMI_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->hNMIWFIDrv);
+
+ /*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]);
+ NMI_WFI_add_key(g_linux_wlan->strInterfaceInfo[0].nmc_netdev->ieee80211_ptr->wiphy,
+ g_linux_wlan->strInterfaceInfo[0].nmc_netdev,
+ g_add_ptk_key_params.key_idx,
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
+ g_add_ptk_key_params.pairwise,
+ #endif
+ g_add_ptk_key_params.mac_addr,
+ (struct key_params *)(&g_key_ptk_params));
+
+ NMI_WFI_add_key(g_linux_wlan->strInterfaceInfo[0].nmc_netdev->ieee80211_ptr->wiphy,
+ g_linux_wlan->strInterfaceInfo[0].nmc_netdev,
+ g_add_gtk_key_params.key_idx,
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
+ g_add_gtk_key_params.pairwise,
+ #endif
+ g_add_gtk_key_params.mac_addr,
+ (struct key_params *)(&g_key_gtk_params));
+ }
+
+ /*BugID_4847: registered frames in firmware are now*/
+ /*lost due to mac close. So re-register those frames*/
+ if(g_linux_wlan->nmc1000_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->hNMIWFIDrv,
+ nic->g_struct_frame_reg[i].frame_type,
+ nic->g_struct_frame_reg[i].reg);
+ }
+ }
+
+ bEnablePS = NMI_TRUE;
+ host_int_set_power_mgmt( priv->hNMIWFIDrv, 1, 0);
+ }
+ #endif
+ #endif
+ break;
+
+ case NL80211_IFTYPE_P2P_CLIENT:
+ bEnablePS = NMI_FALSE;
+ host_int_set_power_mgmt(priv->hNMIWFIDrv, 0, 0);
+ connecting = 0;
+ PRINT_D(HOSTAPD_DBG,"Interface type = NL80211_IFTYPE_P2P_CLIENT\n");
+ //linux_wlan_set_bssid(dev,g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
+
+ host_int_delBASession(priv->hNMIWFIDrv, g_linux_wlan->strInterfaceInfo[0].aBSSID, TID, (void *)priv->hNMIWFIDrv);
+
+ dev->ieee80211_ptr->iftype = type;
+ priv->wdev->iftype = type;
+ nic->monitor_flag = 0;
+ nic->iftype = STATION_MODE;
+
+
+ #ifndef SIMULATION
+ #ifdef NMI_P2P
+
+ PRINT_D(HOSTAPD_DBG,"Downloading P2P_CONCURRENCY_FIRMWARE\n");
+ nic->iftype = CLIENT_MODE;
+
+
+ if(g_linux_wlan->nmc1000_initialized)
+ {
+ // ensure that the message Q is empty
+ host_int_wait_msg_queue_idle();
+
+ nmc1000_wlan_deinit(g_linux_wlan);
+ nmc1000_wlan_init(dev, nic);
+ nic->iftype = STATION_MODE;
+ g_nmc_initialized = 1;
+
+ host_int_set_wfi_drv_handler(g_linux_wlan->strInterfaceInfo[0].drvHandler);
+ host_int_set_MacAddress((NMI_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+ g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
+ host_int_set_operation_mode(priv->hNMIWFIDrv,STATION_MODE);
+
+ /*Add saved WEP keys, if any*/
+ if(g_wep_keys_saved)
+ {
+ host_int_set_WEPDefaultKeyID((NMI_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+ g_key_wep_params.key_idx);
+ host_int_add_wep_key_bss_sta((NMI_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->hNMIWFIDrv);
+
+ /*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]);
+ NMI_WFI_add_key(g_linux_wlan->strInterfaceInfo[0].nmc_netdev->ieee80211_ptr->wiphy,
+ g_linux_wlan->strInterfaceInfo[0].nmc_netdev,
+ g_add_ptk_key_params.key_idx,
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
+ g_add_ptk_key_params.pairwise,
+ #endif
+ g_add_ptk_key_params.mac_addr,
+ (struct key_params *)(&g_key_ptk_params));
+
+ NMI_WFI_add_key(g_linux_wlan->strInterfaceInfo[0].nmc_netdev->ieee80211_ptr->wiphy,
+ g_linux_wlan->strInterfaceInfo[0].nmc_netdev,
+ g_add_gtk_key_params.key_idx,
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
+ g_add_gtk_key_params.pairwise,
+ #endif
+ g_add_gtk_key_params.mac_addr,
+ (struct key_params *)(&g_key_gtk_params));
+ }
+ /*Refresh scan, to refresh the scan results to the wpa_supplicant. Set MachHw to false to enable further key installments*/
+ refresh_scan(priv,1,NMI_TRUE);
+ Set_machw_change_vir_if(NMI_FALSE);
+
+ /*BugID_4847: registered frames in firmware are now lost
+ due to mac close. So re-register those frames */
+ if(g_linux_wlan->nmc1000_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->hNMIWFIDrv,
+ nic->g_struct_frame_reg[i].frame_type,
+ nic->g_struct_frame_reg[i].reg);
+ }
+ }
+ }
+ #endif
+ #endif
+ break;
+
+ case NL80211_IFTYPE_AP:
+ //connecting = 1;
+ bEnablePS = NMI_FALSE;
+ PRINT_D(HOSTAPD_DBG,"Interface type = NL80211_IFTYPE_AP %d\n", type);
+ //linux_wlan_set_bssid(dev,g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
+ //mon_priv = netdev_priv(dev);
+ //mon_priv->real_ndev = dev;
+ dev->ieee80211_ptr->iftype = type;
+ priv->wdev->iftype = type;
+ nic->iftype = AP_MODE;
+ printk("(NMI_Uint32)priv->hNMIWFIDrv[%x]\n",(NMI_Uint32)priv->hNMIWFIDrv);
+
+ #ifndef SIMULATION
+ PRINT_D(HOSTAPD_DBG,"Downloading AP firmware\n");
+ linux_wlan_get_firmware(nic);
+ #ifdef NMI_P2P
+ /*If nmc is running, then close-open to actually get new firmware running (serves P2P)*/
+ if(g_linux_wlan->nmc1000_initialized)
+ {
+ nic->iftype = AP_MODE;
+ g_linux_wlan->nmc1000_initialized = 1;
+ mac_close(dev);
+ mac_open(dev);
+
+ //nmc1000_wlan_deinit(g_linux_wlan);
+ //nmc1000_wlan_init(dev,nic);
+ //repeat_power_cycle(nic);
+ //nic->iftype = STATION_MODE;
+
+ /*BugID_4847: registered frames in firmware are now lost
+ due to mac close. So re-register those frames */
+ for(i=0; i<num_reg_frame; i++)
+ {
+ PRINT_D(INIT_DBG,"Frame registering Type: %x - Reg: %d\n", nic->g_struct_frame_reg[i].frame_type,
+ nic->g_struct_frame_reg[i].reg);
+ host_int_frame_register(priv->hNMIWFIDrv,
+ 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=NMI_TRUE;
+ NMI_TimerStart(&hDuringIpTimer, duringIP_TIME, NMI_NULL, NMI_NULL);
+ #endif
+ host_int_set_power_mgmt(priv->hNMIWFIDrv, 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_delBASession(priv->hNMIWFIDrv, g_linux_wlan->strInterfaceInfo[0].aBSSID, TID, (void *)priv->hNMIWFIDrv);
+ bEnablePS = NMI_FALSE;
+ PRINT_D(HOSTAPD_DBG,"Interface type = NL80211_IFTYPE_GO\n");
+ //linux_wlan_set_bssid(dev,g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
+ //mon_priv = netdev_priv(dev);
+ //mon_priv->real_ndev = dev;
+ dev->ieee80211_ptr->iftype = type;
+ priv->wdev->iftype = type;
+ nic->iftype = AP_MODE;
+ printk("(NMI_Uint32)priv->hNMIWFIDrv[%x]\n",(NMI_Uint32)priv->hNMIWFIDrv);
+ //host_int_set_operation_mode((NMI_Uint32)priv->hNMIWFIDrv,AP_MODE);
+
+ #ifndef SIMULATION
+ #ifdef NMI_P2P
+ PRINT_D(HOSTAPD_DBG,"Downloading P2P_CONCURRENCY_FIRMWARE\n");
+
+
+ #if 1
+ interface_type = nic->iftype;
+ nic->iftype = GO_MODE;
+
+ // ensure that the message Q is empty
+ host_int_wait_msg_queue_idle();
+
+ /*while(!g_hif_thread_idle)
+ {
+ PRINT_D(GENERIC_DBG, "Wait for host IF idle\n");
+ NMI_Sleep(10);
+ }*/
+ nmc1000_wlan_deinit(g_linux_wlan);
+ //repeat_power_cycle_partially(g_linux_wlan);
+ nmc1000_wlan_init(dev, nic);
+ g_nmc_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((NMI_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+ g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
+ host_int_set_operation_mode(priv->hNMIWFIDrv,AP_MODE);
+
+ /*Add saved WEP keys, if any*/
+ if(g_wep_keys_saved)
+ {
+ host_int_set_WEPDefaultKeyID((NMI_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+ g_key_wep_params.key_idx);
+ host_int_add_wep_key_bss_sta((NMI_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->hNMIWFIDrv);
+
+ /*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
+ NMI_WFI_add_key(g_linux_wlan->strInterfaceInfo[0].nmc_netdev->ieee80211_ptr->wiphy,
+ g_linux_wlan->strInterfaceInfo[0].nmc_netdev,
+ g_add_ptk_key_params.key_idx,
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
+ g_add_ptk_key_params.pairwise,
+ #endif
+ g_add_ptk_key_params.mac_addr,
+ (struct key_params *)(&g_key_ptk_params));
+
+ NMI_WFI_add_key(g_linux_wlan->strInterfaceInfo[0].nmc_netdev->ieee80211_ptr->wiphy,
+ g_linux_wlan->strInterfaceInfo[0].nmc_netdev,
+ g_add_gtk_key_params.key_idx,
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
+ g_add_gtk_key_params.pairwise,
+ #endif
+ g_add_gtk_key_params.mac_addr,
+ (struct key_params *)(&g_key_gtk_params));
+ #endif
+ }
+ #endif
+
+ /*BugID_4847: registered frames in firmware are now*/
+ /*lost due to mac close. So re-register those frames*/
+ if(g_linux_wlan->nmc1000_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->hNMIWFIDrv,
+ nic->g_struct_frame_reg[i].frame_type,
+ nic->g_struct_frame_reg[i].reg);
+ }
+ }
+ #endif
+ #endif
+ break;
+
+ default:
+ PRINT_ER("Unknown interface type= %d\n", type);
+ s32Error = -EINVAL;
+ return s32Error;
+ break;
+ }
+
+ return s32Error;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
+/* (austin.2013-07-23)
+
+ To support revised cfg80211_ops
+
+ add_beacon --> start_ap
+ set_beacon --> change_beacon
+ del_beacon --> stop_ap
+
+ beacon_parameters --> cfg80211_ap_settings
+ cfg80211_beacon_data
+
+ applicable for linux kernel 3.4+
+*/
+
+/* cache of cfg80211_ap_settings later use in change_beacon api. */
+static struct cfg80211_ap_settings *_g_pApSettings = NULL;
+
+/**
+* @brief NMI_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 NMI_WFI_start_ap(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_ap_settings *settings)
+{
+ struct cfg80211_beacon_data* beacon = &(settings->beacon);
+ struct NMI_WFI_priv* priv;
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+
+ priv = wiphy_priv(wiphy);
+ PRINT_D(HOSTAPD_DBG,"Starting ap\n");
+
+ PRINT_D(HOSTAPD_DBG,"Interval = %d \n DTIM period = %d\n Head length = %d Tail length = %d\n",
+ settings->beacon_interval , settings->dtim_period, beacon->head_len, beacon->tail_len );
+
+ linux_wlan_set_bssid(dev,g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
+
+ #ifndef NMI_FULLY_HOSTING_AP
+ s32Error = host_int_add_beacon( priv->hNMIWFIDrv,
+ settings->beacon_interval,
+ settings->dtim_period,
+ beacon->head_len, (NMI_Uint8*)beacon->head,
+ beacon->tail_len, (NMI_Uint8*)beacon->tail);
+ #else
+ s32Error = host_add_beacon( priv->hNMIWFIDrv,
+ settings->beacon_interval,
+ settings->dtim_period,
+ beacon->head_len, (NMI_Uint8*)beacon->head,
+ beacon->tail_len, (NMI_Uint8*)beacon->tail);
+ #endif
+
+ _g_pApSettings = settings;
+
+ return s32Error;
+}
+
+/**
+* @brief NMI_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 NMI_WFI_change_beacon(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_beacon_data *beacon)
+{
+ struct cfg80211_ap_settings *settings = _g_pApSettings;
+ struct NMI_WFI_priv* priv;
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+
+ priv = wiphy_priv(wiphy);
+ PRINT_D(HOSTAPD_DBG,"Setting beacon\n");
+
+ // should be call after start_ap.
+ if (!settings)
+ return NMI_INVALID_STATE;
+
+#ifndef NMI_FULLY_HOSTING_AP
+ s32Error = host_int_add_beacon( priv->hNMIWFIDrv,
+ settings->beacon_interval,
+ settings->dtim_period,
+ beacon->head_len, (NMI_Uint8*)beacon->head,
+ beacon->tail_len, (NMI_Uint8*)beacon->tail);
+#else
+ s32Error = host_add_beacon( priv->hNMIWFIDrv,
+ settings->beacon_interval,
+ settings->dtim_period,
+ beacon->head_len, (NMI_Uint8*)beacon->head,
+ beacon->tail_len, (NMI_Uint8*)beacon->tail);
+#endif
+
+ return s32Error;
+}
+
+/**
+* @brief NMI_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 NMI_WFI_stop_ap(struct wiphy *wiphy, struct net_device *dev)
+{
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ struct NMI_WFI_priv* priv;
+ NMI_Uint8 NullBssid[ETH_ALEN] = {0};
+
+
+ NMI_NULLCHECK(s32Error, wiphy);
+
+ priv = wiphy_priv(wiphy);
+
+ PRINT_D(HOSTAPD_DBG,"Deleting beacon\n");
+
+ /*BugID_5188*/
+ linux_wlan_set_bssid(dev, NullBssid);
+
+ #ifndef NMI_FULLY_HOSTING_AP
+ s32Error = host_int_del_beacon(priv->hNMIWFIDrv);
+ #else
+ s32Error = host_del_beacon(priv->hNMIWFIDrv);
+ #endif
+
+ _g_pApSettings = NULL; // better to reset primitive regardless of error.
+
+ NMI_ERRORCHECK(s32Error);
+
+ NMI_CATCH(s32Error)
+ {
+ }
+ return s32Error;
+}
+
+#else /* here belows are original for < kernel 3.3 (austin.2013-07-23) */
+
+/**
+* @brief NMI_WFI_add_beacon
+* @details Add a beacon with given parameters, @head, @interval
+* and @dtim_period will be valid, @tail is optional.
+* @param[in] wiphy
+* @param[in] dev The net device structure
+* @param[in] info Parameters for the beacon to be added
+* @return int : Return 0 on Success.
+* @author mdaftedar
+* @date 01 MAR 2012
+* @version 1.0
+*/
+static int NMI_WFI_add_beacon(struct wiphy *wiphy, struct net_device *dev,
+ struct beacon_parameters *info)
+{
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ struct NMI_WFI_priv* priv;
+
+
+
+ priv = wiphy_priv(wiphy);
+ PRINT_D(HOSTAPD_DBG,"Adding Beacon\n");
+
+ PRINT_D(HOSTAPD_DBG,"Interval = %d \n DTIM period = %d\n Head length = %d Tail length = %d\n",info->interval , info->dtim_period,info->head_len,info->tail_len );
+
+ linux_wlan_set_bssid(dev,g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
+
+ #ifndef NMI_FULLY_HOSTING_AP
+ s32Error = host_int_add_beacon(priv->hNMIWFIDrv, info->interval,
+ info->dtim_period,
+ info->head_len, info->head,
+ info->tail_len, info->tail);
+
+ #else
+ s32Error = host_add_beacon(priv->hNMIWFIDrv, info->interval,
+ info->dtim_period,
+ info->head_len, info->head,
+ info->tail_len, info->tail);
+ #endif
+
+ return s32Error;
+}
+
+/**
+* @brief NMI_WFI_set_beacon
+* @details Change the beacon parameters for an access point mode
+* interface. This should reject the call when no beacon has been
+* configured.
+* @param[in]
+* @return int : Return 0 on Success.
+* @author mdaftedar
+* @date 01 MAR 2012
+* @version 1.0
+*/
+static int NMI_WFI_set_beacon(struct wiphy *wiphy, struct net_device *dev,
+ struct beacon_parameters *info)
+{
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+
+
+ PRINT_D(HOSTAPD_DBG,"Setting beacon\n");
+
+ s32Error = NMI_WFI_add_beacon(wiphy, dev, info);
+
+ return s32Error;
+}
+
+/**
+* @brief NMI_WFI_del_beacon
+* @details Remove beacon configuration and stop sending the beacon.
+* @param[in]
+* @return int : Return 0 on Success.
+* @author mdaftedar
+* @date 01 MAR 2012
+* @version 1.0
+*/
+static int NMI_WFI_del_beacon(struct wiphy *wiphy, struct net_device *dev)
+{
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ struct NMI_WFI_priv* priv;
+ NMI_Uint8 NullBssid[ETH_ALEN] = {0};
+
+
+ NMI_NULLCHECK(s32Error, wiphy);
+
+ priv = wiphy_priv(wiphy);
+
+ PRINT_D(HOSTAPD_DBG,"Deleting beacon\n");
+
+ /*BugID_5188*/
+ linux_wlan_set_bssid(dev, NullBssid);
+
+ #ifndef NMI_FULLY_HOSTING_AP
+ s32Error = host_int_del_beacon(priv->hNMIWFIDrv);
+ #else
+ s32Error = host_del_beacon(priv->hNMIWFIDrv);
+ #endif
+
+ NMI_ERRORCHECK(s32Error);
+
+ NMI_CATCH(s32Error)
+ {
+ }
+ return s32Error;
+}
+
+#endif /* linux kernel 3.4+ (austin.2013-07-23) */
+
+/**
+* @brief NMI_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 NMI_WFI_add_station(struct wiphy *wiphy, struct net_device *dev,
+ u8 *mac, struct station_parameters *params)
+{
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ struct NMI_WFI_priv* priv;
+ tstrNMI_AddStaParam strStaParams={{0}};
+ perInterface_wlan_t* nic;
+
+
+ NMI_NULLCHECK(s32Error, wiphy);
+
+ priv = wiphy_priv(wiphy);
+ nic = netdev_priv(dev);
+
+ if(nic->iftype == AP_MODE)
+ {
+ #ifndef NMI_FULLY_HOSTING_AP
+
+ NMI_memcpy(strStaParams.au8BSSID, mac, ETH_ALEN);
+ NMI_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 == NMI_NULL)
+ {
+ strStaParams.bIsHTSupported = NMI_FALSE;
+ }
+ else
+ {
+ strStaParams.bIsHTSupported = NMI_TRUE;
+ strStaParams.u16HTCapInfo = params->ht_capa->cap_info;
+ strStaParams.u8AmpduParams = params->ht_capa->ampdu_params_info;
+ NMI_memcpy(strStaParams.au8SuppMCsSet, &params->ht_capa->mcs, NMI_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->hNMIWFIDrv, &strStaParams);
+ NMI_ERRORCHECK(s32Error);
+
+ #else
+ PRINT_D(CFG80211_DBG,"Adding station parameters %d\n",params->aid);
+ NMI_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]);
+
+ NMI_AP_AddSta(mac, params);
+ NMI_ERRORCHECK(s32Error);
+ #endif //NMI_FULLY_HOSTING_AP
+
+ }
+
+ NMI_CATCH(s32Error)
+ {
+ }
+ return s32Error;
+}
+
+/**
+* @brief NMI_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 NMI_WFI_del_station(struct wiphy *wiphy, struct net_device *dev,
+ u8 *mac)
+{
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ struct NMI_WFI_priv* priv;
+ perInterface_wlan_t* nic;
+
+
+ NMI_NULLCHECK(s32Error, wiphy);
+ /*BugID_4795: mac may be null pointer to indicate deleting all stations, so avoid null check*/
+ //NMI_NULLCHECK(s32Error, mac);
+
+ priv = wiphy_priv(wiphy);
+ nic = netdev_priv(dev);
+
+ if(nic->iftype == AP_MODE)
+ {
+ PRINT_D(HOSTAPD_DBG,"Deleting station\n");
+
+
+ if(mac == NMI_NULL)
+ PRINT_D(HOSTAPD_DBG,"All associated stations \n");
+ 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 NMI_FULLY_HOSTING_AP
+ s32Error = host_int_del_station(priv->hNMIWFIDrv , mac);
+ #else
+ NMI_AP_RemoveSta(mac);
+ #endif //NMI_FULLY_HOSTING_AP
+ NMI_ERRORCHECK(s32Error);
+ }
+ NMI_CATCH(s32Error)
+ {
+ }
+ return s32Error;
+}
+
+/**
+* @brief NMI_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 NMI_WFI_change_station(struct wiphy *wiphy, struct net_device *dev,
+ u8 *mac, struct station_parameters *params)
+{
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ struct NMI_WFI_priv* priv;
+ tstrNMI_AddStaParam strStaParams={{0}};
+ perInterface_wlan_t* nic;
+
+
+ PRINT_D(HOSTAPD_DBG,"Change station paramters\n");
+
+ NMI_NULLCHECK(s32Error, wiphy);
+
+ priv = wiphy_priv(wiphy);
+ nic = netdev_priv(dev);
+
+ if(nic->iftype == AP_MODE)
+ {
+ #ifndef NMI_FULLY_HOSTING_AP
+
+ NMI_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 == NMI_NULL)
+ {
+ strStaParams.bIsHTSupported = NMI_FALSE;
+ }
+ else
+ {
+ strStaParams.bIsHTSupported = NMI_TRUE;
+ strStaParams.u16HTCapInfo = params->ht_capa->cap_info;
+ strStaParams.u8AmpduParams = params->ht_capa->ampdu_params_info;
+ NMI_memcpy(strStaParams.au8SuppMCsSet, &params->ht_capa->mcs, NMI_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->hNMIWFIDrv, &strStaParams);
+ NMI_ERRORCHECK(s32Error);
+
+ #else
+ NMI_AP_EditSta(mac, params);
+ NMI_ERRORCHECK(s32Error);
+ #endif //NMI_FULLY_HOSTING_AP
+
+ }
+ NMI_CATCH(s32Error)
+ {
+ }
+ return s32Error;
+}
+
+
+/**
+* @brief NMI_WFI_add_virt_intf
+* @details
+* @param[in]
+* @return int : Return 0 on Success.
+* @author mdaftedar
+* @date 01 JUL 2012
+* @version 1.0
+*/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) /* tony for v3.8 support */
+struct wireless_dev * NMI_WFI_add_virt_intf(struct wiphy *wiphy, const char *name,
+ enum nl80211_iftype type, u32 *flags,
+ struct vif_params *params)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) /* tony for v3.6 support */
+struct wireless_dev * NMI_WFI_add_virt_intf(struct wiphy *wiphy, char *name,
+ enum nl80211_iftype type, u32 *flags,
+ struct vif_params *params)
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
+int NMI_WFI_add_virt_intf(struct wiphy *wiphy, char *name,
+ enum nl80211_iftype type, u32 *flags,
+ struct vif_params *params)
+#else
+struct net_device *NMI_WFI_add_virt_intf(struct wiphy *wiphy, char *name,
+ enum nl80211_iftype type, u32 *flags,
+ struct vif_params *params)
+#endif
+{
+ perInterface_wlan_t * nic;
+ struct NMI_WFI_priv* priv;
+ //struct NMI_WFI_mon_priv* mon_priv;
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+ #endif
+ struct net_device * new_ifc = NULL;
+ priv = wiphy_priv(wiphy);
+
+
+
+ PRINT_D(HOSTAPD_DBG,"Adding monitor interface[%p]\n",priv->wdev->netdev);
+
+ nic = netdev_priv(priv->wdev->netdev);
+
+
+ if(type == NL80211_IFTYPE_MONITOR)
+ {
+ PRINT_D(HOSTAPD_DBG,"Monitor interface mode: Initializing mon interface virtual device driver\n");
+ PRINT_D(HOSTAPD_DBG,"Adding monitor interface[%p]\n",nic->nmc_netdev);
+ new_ifc = NMI_WFI_init_mon_interface(name,nic->nmc_netdev);
+ if(new_ifc != NULL)
+ {
+ PRINT_D(HOSTAPD_DBG,"Setting monitor flag in private structure\n");
+ #ifdef SIMULATION
+ priv = netdev_priv(priv->wdev->netdev);
+ priv->monitor_flag = 1;
+ #else
+ nic = netdev_priv(priv->wdev->netdev);
+ nic->monitor_flag = 1;
+ #endif
+ }
+ else
+ PRINT_ER("Error in initializing monitor interface\n ");
+ }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) /* tony for v3.8 support */
+ //return priv->wdev;
+ return new_ifc; // rachel - have to check
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
+ return s32Error;
+#else
+ //return priv->wdev->netdev;
+ PRINT_D(HOSTAPD_DBG,"IFC[%p] created\n",new_ifc);
+ return new_ifc;
+#endif
+
+}
+
+/**
+* @brief NMI_WFI_del_virt_intf
+* @details
+* @param[in]
+* @return int : Return 0 on Success.
+* @author mdaftedar
+* @date 01 JUL 2012
+* @version 1.0
+*/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
+int NMI_WFI_del_virt_intf(struct wiphy *wiphy, struct wireless_dev *wdev) /* tony for v3.8 support */
+#else
+int NMI_WFI_del_virt_intf(struct wiphy *wiphy,struct net_device *dev)
+#endif
+{
+ PRINT_D(HOSTAPD_DBG,"Deleting virtual interface\n");
+ return NMI_SUCCESS;
+}
+
+
+
+#endif /*NMI_AP_EXTERNAL_MLME*/
+static struct cfg80211_ops NMI_WFI_cfg80211_ops = {
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
+ /*
+ * replaced set_channel by set_monitor_channel
+ * from v3.6
+ * tony, 2013-10-29
+ */
+ .set_monitor_channel = NMI_WFI_CfgSetChannel,
+#else
+ .set_channel = NMI_WFI_CfgSetChannel,
+#endif
+ .scan = NMI_WFI_CfgScan,
+ .connect = NMI_WFI_CfgConnect,
+ .disconnect = NMI_WFI_disconnect,
+ .add_key = NMI_WFI_add_key,
+ .del_key = NMI_WFI_del_key,
+ .get_key = NMI_WFI_get_key,
+ .set_default_key = NMI_WFI_set_default_key,
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32)
+ //.dump_survey = NMI_WFI_dump_survey,
+#endif
+ #ifdef NMI_AP_EXTERNAL_MLME
+ .add_virtual_intf = NMI_WFI_add_virt_intf,
+ .del_virtual_intf = NMI_WFI_del_virt_intf,
+ .change_virtual_intf = NMI_WFI_change_virt_intf,
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)
+ .add_beacon = NMI_WFI_add_beacon,
+ .set_beacon = NMI_WFI_set_beacon,
+ .del_beacon = NMI_WFI_del_beacon,
+#else
+ /* supports kernel 3.4+ change. austin.2013-07-23 */
+ .start_ap = NMI_WFI_start_ap,
+ .change_beacon = NMI_WFI_change_beacon,
+ .stop_ap = NMI_WFI_stop_ap,
+#endif
+ .add_station = NMI_WFI_add_station,
+ .del_station = NMI_WFI_del_station,
+ .change_station = NMI_WFI_change_station,
+ #endif /* NMI_AP_EXTERNAL_MLME*/
+ #ifndef NMI_FULLY_HOSTING_AP
+ .get_station = NMI_WFI_get_station,
+ #endif
+ .dump_station = NMI_WFI_dump_station,
+ .change_bss = NMI_WFI_change_bss,
+ //.auth = NMI_WFI_auth,
+ //.assoc = NMI_WFI_assoc,
+ //.deauth = NMI_WFI_deauth,
+ //.disassoc = NMI_WFI_disassoc,
+ .set_wiphy_params = NMI_WFI_set_wiphy_params,
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32)
+ //.set_bitrate_mask = NMI_WFI_set_bitrate_mask,
+ .set_pmksa = NMI_WFI_set_pmksa,
+ .del_pmksa = NMI_WFI_del_pmksa,
+ .flush_pmksa = NMI_WFI_flush_pmksa,
+#ifdef NMI_P2P
+ .remain_on_channel = NMI_WFI_remain_on_channel,
+ .cancel_remain_on_channel = NMI_WFI_cancel_remain_on_channel,
+ .mgmt_tx_cancel_wait = NMI_WFI_mgmt_tx_cancel_wait,
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)
+ .action = NMI_WFI_action,
+ #endif
+ #else
+ .mgmt_tx = NMI_WFI_mgmt_tx,
+ .mgmt_frame_register = NMI_WFI_frame_register,
+ #endif
+#endif
+ //.mgmt_tx_cancel_wait = NMI_WFI_mgmt_tx_cancel_wait,
+ .set_power_mgmt = NMI_WFI_set_power_mgmt,
+ .set_cqm_rssi_config = NMI_WFI_set_cqm_rssi_config,
+#endif
+
+};
+
+
+
+
+
+/**
+* @brief NMI_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.0NMI_WFI_set_cqmNMI_WFI_set_cqm_rssi_configNMI_WFI_set_cqm_rssi_configNMI_WFI_set_cqm_rssi_configNMI_WFI_set_cqm_rssi_config_rssi_config
+*/
+int NMI_WFI_update_stats(struct wiphy *wiphy, u32 pktlen , u8 changed)
+{
+
+ struct NMI_WFI_priv *priv;
+
+ priv = wiphy_priv(wiphy);
+ //NMI_SemaphoreAcquire(&SemHandleUpdateStats,NULL);
+#if 1
+ switch(changed)
+ {
+
+ case NMI_WFI_RX_PKT:
+ {
+ //MI_PRINTF("In Rx Receive Packet\n");
+ priv->netstats.rx_packets++;
+ priv->netstats.rx_bytes += pktlen;
+ priv->netstats.rx_time = get_jiffies_64();
+ }
+ break;
+ case NMI_WFI_TX_PKT:
+ {
+ //NMI_PRINTF("In Tx Receive Packet\n");
+ priv->netstats.tx_packets++;
+ priv->netstats.tx_bytes += pktlen;
+ priv->netstats.tx_time = get_jiffies_64();
+
+ }
+ break;
+
+ default:
+ break;
+ }
+ //NMI_SemaphoreRelease(&SemHandleUpdateStats,NULL);
+#endif
+ return 0;
+}
+/**
+* @brief NMI_WFI_InitPriv
+* @details Initialization of the net device, private data
+* @param[in] NONE
+* @return NONE
+* @author mdaftedar
+* @date 01 MAR 2012
+* @version 1.0
+*/
+void NMI_WFI_InitPriv(struct net_device *dev)
+{
+
+ struct NMI_WFI_priv *priv;
+ priv = netdev_priv(dev);
+
+ priv->netstats.rx_packets = 0;
+ priv->netstats.tx_packets = 0;
+ priv->netstats.rx_bytes = 0;
+ priv->netstats.rx_bytes = 0;
+ priv->netstats.rx_time = 0;
+ priv->netstats.tx_time = 0;
+
+
+}
+/**
+* @brief NMI_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* NMI_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(&NMI_WFI_cfg80211_ops, sizeof(struct NMI_WFI_priv));
+ if (!wdev->wiphy)
+ {
+ PRINT_ER("Cannot allocate wiphy\n");
+ goto _fail_mem_;
+
+ }
+
+ #ifdef NMI_AP_EXTERNAL_MLME
+ //enable 802.11n HT
+ NMI_WFI_band_2ghz.ht_cap.ht_supported = 1;
+ NMI_WFI_band_2ghz.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
+ NMI_WFI_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
+ NMI_WFI_band_2ghz.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K;
+ NMI_WFI_band_2ghz.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
+ #endif
+
+ /*wiphy bands*/
+ wdev->wiphy->bands[IEEE80211_BAND_2GHZ]= &NMI_WFI_band_2ghz;
+
+ return wdev;
+
+_fail_mem_:
+ kfree(wdev);
+_fail_:
+ return NULL;
+
+}
+/**
+* @brief NMI_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* NMI_WFI_WiphyRegister(struct net_device *net)
+{
+ struct NMI_WFI_priv *priv;
+ struct wireless_dev *wdev;
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+
+ PRINT_D(CFG80211_DBG,"Registering wifi device\n");
+
+ wdev = NMI_WFI_CfgAlloc();
+ if(wdev == NULL){
+ PRINT_ER("CfgAlloc Failed\n");
+ return NULL;
+ }
+
+
+ /*Return hardware description structure (wiphy)'s priv*/
+ priv = wdev_priv(wdev);
+ NMI_SemaphoreCreate(&(priv->SemHandleUpdateStats),NULL);
+
+ /*Added by Amr - BugID_4793*/
+ priv->u8CurrChannel = -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;
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32)
+ /*Maximum number of pmkids to be cashed*/
+ wdev->wiphy->max_num_pmkids = NMI_MAX_NUM_PMKIDS;
+ PRINT_INFO(CFG80211_DBG,"Max number of PMKIDs = %d\n",wdev->wiphy->max_num_pmkids);
+ #endif
+
+ wdev->wiphy->max_scan_ie_len = 1000;
+
+ /*signal strength in mBm (100*dBm) */
+ wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+
+ /*Set the availaible cipher suites*/
+ wdev->wiphy->cipher_suites = cipher_suites;
+ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
+ /*Setting default managment types: for register action frame: */
+ wdev->wiphy->mgmt_stypes = nmi_wfi_cfg80211_mgmt_types;
+#endif
+
+#ifdef NMI_P2P
+ wdev->wiphy->max_remain_on_channel_duration = 500;
+ /*Setting the wiphy interfcae mode and type before registering the wiphy*/
+ wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR) | BIT(NL80211_IFTYPE_P2P_GO) |
+ BIT(NL80211_IFTYPE_P2P_CLIENT);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)
+
+ wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+#endif
+#else
+ wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR);
+#endif
+ wdev->iftype = NL80211_IFTYPE_STATION;
+
+
+
+ PRINT_INFO(CFG80211_DBG,"Max scan ids = %d,Max scan IE len = %d,Signal Type = %d,Interface Modes = %d,Interface Type = %d\n",
+ wdev->wiphy->max_scan_ssids,wdev->wiphy->max_scan_ie_len,wdev->wiphy->signal_type,
+ wdev->wiphy->interface_modes, wdev->iftype);
+
+ set_wiphy_dev(wdev->wiphy, &local_sdio_func->dev); //tony
+ /*Register wiphy structure*/
+ s32Error = wiphy_register(wdev->wiphy);
+ if (s32Error){
+ PRINT_ER("Cannot register wiphy device\n");
+ /*should define what action to be taken in such failure*/
+ }
+ else
+ {
+ PRINT_D(CFG80211_DBG,"Successful Registering\n");
+ }
+
+#if 0
+ /*wdev[i]->wiphy->interface_modes =
+ BIT(NL80211_IFTYPE_AP);
+ wdev[i]->iftype = NL80211_IFTYPE_AP;
+ */
+
+ /*Pointing the priv structure the netdev*/
+ priv= netdev_priv(net);
+
+ /*linking the wireless_dev structure with the netdevice*/
+ priv->dev->ieee80211_ptr = wdev;
+ priv->dev->ml_priv = priv;
+ wdev->netdev = priv->dev;
+#endif
+ priv->dev = net;
+#if 0
+ ret = host_int_init(&priv->hNMIWFIDrv);
+ if(ret)
+ {
+ NMI_PRINTF("Error Init Driver\n");
+ }
+#endif
+ return wdev;
+
+
+}
+/**
+* @brief NMI_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 NMI_WFI_InitHostInt(struct net_device *net)
+{
+
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+
+ struct NMI_WFI_priv *priv;
+
+ tstrNMI_SemaphoreAttrs strSemaphoreAttrs;
+
+ printk("Host[%p][%p]\n",net,net->ieee80211_ptr);
+ priv = wdev_priv(net->ieee80211_ptr);
+ if(op_ifcs==0)
+ {
+ s32Error = NMI_TimerCreate(&(hAgingTimer), remove_network_from_shadow, NMI_NULL);
+ #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
+ s32Error = NMI_TimerCreate(&(hDuringIpTimer), clear_duringIP, NMI_NULL);
+ #endif
+ }
+ op_ifcs++;
+ if(s32Error < 0){
+ PRINT_ER("Failed to creat refresh Timer\n");
+ return s32Error;
+ }
+
+ NMI_SemaphoreFillDefault(&strSemaphoreAttrs);
+
+ /////////////////////////////////////////
+ //strSemaphoreAttrs.u32InitCount = 0;
+
+
+ priv->gbAutoRateAdjusted = NMI_FALSE;
+
+
+ NMI_SemaphoreCreate(&(priv->hSemScanReq), &strSemaphoreAttrs);
+ s32Error = host_int_init(&priv->hNMIWFIDrv);
+ //s32Error = host_int_init(&priv->hNMIWFIDrv_2);
+ if(s32Error)
+ {
+ PRINT_ER("Error while initializing hostinterface\n");
+ }
+ return s32Error;
+}
+
+/**
+* @brief NMI_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 NMI_WFI_DeInitHostInt(struct net_device *net)
+{
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+
+ struct NMI_WFI_priv *priv;
+ priv = wdev_priv(net->ieee80211_ptr);
+
+
+
+
+
+
+ NMI_SemaphoreDestroy(&(priv->hSemScanReq),NULL);
+
+ priv->gbAutoRateAdjusted = NMI_FALSE;
+
+
+
+ op_ifcs--;
+
+ s32Error = host_int_deinit(priv->hNMIWFIDrv);
+ //s32Error = host_int_deinit(priv->hNMIWFIDrv_2);
+
+ /* Clear the Shadow scan */
+ clear_shadow_scan(priv);
+ #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
+ if(op_ifcs==0)
+ {
+ printk("destroy during ip\n");
+ NMI_TimerDestroy(&hDuringIpTimer,NMI_NULL);
+ }
+ #endif
+
+
+ if(s32Error)
+ {
+ PRINT_ER("Error while deintializing host interface\n");
+ }
+ return s32Error;
+}
+
+
+/**
+* @brief NMI_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 NMI_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/net/wireless/nmi_android4.4_driver/src/driver/linux/source/NMI_WFI_NetDevice.c b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/NMI_WFI_NetDevice.c
new file mode 100755
index 00000000..41847cba
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/NMI_WFI_NetDevice.c
@@ -0,0 +1,969 @@
+/*!
+* @file NMI_WFI_NetDevice.c
+* @brief File Operations OS wrapper functionality
+* @author mdaftedar
+* @sa NMI_WFI_NetDevice.h
+* @date 01 MAR 2012
+* @version 1.0
+*/
+
+#ifdef SIMULATION
+
+#include "linux/include/NMI_WFI_CfgOperations.h"
+#include "host_interface.h"
+
+
+MODULE_AUTHOR("Mai Daftedar");
+MODULE_LICENSE("Dual BSD/GPL");
+
+
+struct net_device *NMI_WFI_devs[2];
+
+/*
+* Transmitter lockup simulation, normally disabled.
+*/
+static int lockup = 0;
+module_param(lockup, int, 0);
+
+static int timeout = NMI_WFI_TIMEOUT;
+module_param(timeout, int, 0);
+
+/*
+* Do we run in NAPI mode?
+*/
+static int use_napi = 0;
+module_param(use_napi, int, 0);
+
+
+/*
+* A structure representing an in-flight packet.
+*/
+struct NMI_WFI_packet {
+ struct NMI_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 NMI_WFI_TxTimeout(struct net_device *dev);
+static void (*NMI_WFI_Interrupt)(int, void *, struct pt_regs *);
+
+/**
+* @brief NMI_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 NMI_WFI_SetupPool(struct net_device *dev)
+ {
+ struct NMI_WFI_priv *priv = netdev_priv(dev);
+ int i;
+ struct NMI_WFI_packet *pkt;
+
+ priv->ppool = NULL;
+ for (i = 0; i < pool_size; i++) {
+ pkt = kmalloc (sizeof (struct NMI_WFI_packet), GFP_KERNEL);
+ if (pkt == NULL) {
+ printk (KERN_NOTICE "Ran out of memory allocating packet pool\n");
+ return;
+ }
+ pkt->dev = dev;
+ pkt->next = priv->ppool;
+ priv->ppool = pkt;
+ }
+ }
+
+/**
+* @brief NMI_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 NMI_WFI_TearDownPool(struct net_device *dev)
+ {
+ struct NMI_WFI_priv *priv = netdev_priv(dev);
+ struct NMI_WFI_packet *pkt;
+
+ while ((pkt = priv->ppool)) {
+ priv->ppool = pkt->next;
+ kfree (pkt);
+ /* FIXME - in-flight packets ? */
+ }
+ }
+
+/**
+* @brief NMI_WFI_GetTxBuffer
+* @details Buffer/pool management
+* @param[in] net_device *dev : Network Device Driver Structure
+* @return struct NMI_WFI_packet
+* @author mdaftedar
+* @date 01 MAR 2012
+* @version 1.0
+*/
+ struct NMI_WFI_packet *NMI_WFI_GetTxBuffer(struct net_device *dev)
+ {
+ struct NMI_WFI_priv *priv = netdev_priv(dev);
+ unsigned long flags;
+ struct NMI_WFI_packet *pkt;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ pkt = priv->ppool;
+ priv->ppool = pkt->next;
+ if (priv->ppool == NULL) {
+ printk (KERN_INFO "Pool empty\n");
+ netif_stop_queue(dev);
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return pkt;
+ }
+/**
+* @brief NMI_WFI_ReleaseBuffer
+* @details Buffer/pool management
+* @param[in] NMI_WFI_packet *pkt : Structure holding in-flight packet
+* @return NONE
+* @author mdaftedar
+* @date 01 MAR 2012
+* @version 1.0
+*/
+void NMI_WFI_ReleaseBuffer(struct NMI_WFI_packet *pkt)
+{
+ unsigned long flags;
+ struct NMI_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 NMI_WFI_EnqueueBuf
+* @details Enqueuing packets in an RX buffer queue
+* @param[in] NMI_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 NMI_WFI_EnqueueBuf(struct net_device *dev, struct NMI_WFI_packet *pkt)
+{
+ unsigned long flags;
+ struct NMI_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 NMI_WFI_DequeueBuf
+* @details Dequeuing packets from the RX buffer queue
+* @param[in] net_device *dev : Network Device Driver Structure
+* @return NMI_WFI_packet *pkt : Structure holding in-flight pac
+* @author mdaftedar
+* @date 01 MAR 2012
+* @version 1.0
+*/
+struct NMI_WFI_packet *NMI_WFI_DequeueBuf(struct net_device *dev)
+{
+ struct NMI_WFI_priv *priv = netdev_priv(dev);
+ struct NMI_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 NMI_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 NMI_WFI_RxInts(struct net_device *dev, int enable)
+{
+ struct NMI_WFI_priv *priv = netdev_priv(dev);
+ priv->rx_int_enabled = enable;
+}
+
+/**
+* @brief NMI_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 NMI_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 == NMI_WFI_devs[1])
+ dev->dev_addr[ETH_ALEN-1]++; /* \0SNUL1 */
+
+ NMI_WFI_InitHostInt(dev);
+ netif_start_queue(dev);
+ return 0;
+}
+/**
+* @brief NMI_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 NMI_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 NMI_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 NMI_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) {
+ printk(KERN_WARNING "NMI_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 NMI_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] NMI_WFI_packet :
+* @return NONE
+* @author mdaftedar
+* @date 01 MAR 2012
+* @version 1.0
+*/
+void NMI_WFI_Rx(struct net_device *dev, struct NMI_WFI_packet *pkt)
+{
+ int i;
+ struct sk_buff *skb;
+ struct NMI_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())
+ printk(KERN_NOTICE "NMI_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);
+ printk("VALUE PASSED IN OF HRWD %p\n", priv->hNMIWFIDrv);
+ // host_int_get_rssi(priv->hNMIWFIDrv, &(rssi));
+ // NMI_PRINTF("RSSI value is %d\n", rssi);
+ if(INFO)
+ {
+ for (i=14 ; i<skb->len; i++)
+ PRINT_INFO(RX_DBG,"RXdata[%d] %02x\n",i,skb->data[i]);
+ }
+ NMI_WFI_monitor_rx(dev, skb);
+ return;
+ }
+#if 0
+ NMI_PRINTF("In RX NORMAl Device name %s\n", dev->name);
+ /* Write metadata, and then pass to the receive level */
+ skb->dev = dev;
+ skb->protocol = eth_type_trans(skb, dev);
+ skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */
+ NMI_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy ,pkt->datalen,NMI_WFI_RX_PKT);
+ netif_rx(skb);
+#endif
+out:
+ return;
+}
+
+/**
+* @brief NMI_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 NMI_WFI_Poll(struct napi_struct *napi, int budget)
+{
+ int npackets = 0;
+ struct sk_buff *skb;
+ struct NMI_WFI_priv *priv = container_of(napi, struct NMI_WFI_priv, napi);
+ struct net_device *dev = priv->dev;
+ struct NMI_WFI_packet *pkt;
+
+ while (npackets < budget && priv->rx_queue) {
+ pkt = NMI_WFI_DequeueBuf(dev);
+ skb = dev_alloc_skb(pkt->datalen + 2);
+ if (! skb) {
+ if (printk_ratelimit())
+ printk(KERN_NOTICE "NMI_WFI: packet dropped\n");
+ priv->stats.rx_dropped++;
+ NMI_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++;
+ NMI_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy,pkt->datalen,NMI_WFI_RX_PKT);
+ NMI_WFI_ReleaseBuffer(pkt);
+ }
+ /* If we processed all packets, we're done; tell the kernel and re-enable ints */
+ if (npackets < budget) {
+ napi_complete(napi);
+ NMI_WFI_RxInts(dev, 1);
+ }
+ return npackets;
+ }
+
+/**
+* @brief NMI_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 NMI_WFI_RegularInterrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ int statusword;
+ struct NMI_WFI_priv *priv;
+ struct NMI_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 & NMI_WFI_RX_INTR) {
+ /* send it to NMI_WFI_rx for handling */
+ pkt = priv->rx_queue;
+ if (pkt) {
+ priv->rx_queue = pkt->next;
+ NMI_WFI_Rx(dev, pkt);
+ }
+ }
+ if (statusword & NMI_WFI_TX_INTR) {
+ /* a transmission is over: free the skb */
+ NMI_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy,priv->tx_packetlen,NMI_WFI_TX_PKT);
+ dev_kfree_skb(priv->skb);
+ }
+
+ /* Unlock the device and we are done */
+ spin_unlock(&priv->lock);
+ if (pkt) NMI_WFI_ReleaseBuffer(pkt); /* Do this outside the lock! */
+ return;
+}
+/**
+* @brief NMI_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 NMI_WFI_NapiInterrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ int statusword;
+ struct NMI_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 & NMI_WFI_RX_INTR) {
+ NMI_WFI_RxInts(dev, 0); /* Disable further interrupts */
+ napi_schedule(&priv->napi);
+ }
+ if (statusword & NMI_WFI_TX_INTR) {
+ /* a transmission is over: free the skb */
+
+ NMI_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy,priv->tx_packetlen,NMI_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 NMI_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 NMI_WFI interface (if any).
+ * In other words, this function implements the NMI_WFI behaviour,
+ * while all other procedures are rather device-independent
+ */
+ struct iphdr *ih;
+ struct net_device *dest;
+ struct NMI_WFI_priv *priv;
+ u32 *saddr, *daddr;
+ struct NMI_WFI_packet *tx_buffer;
+
+
+ /* I am paranoid. Ain't I? */
+ if (len < sizeof(struct ethhdr) + sizeof(struct iphdr)) {
+ printk("NMI_WFI: Hmm... packet too short (%i octets)\n",
+ len);
+ return;
+ }
+
+ if (0) { /* enable this conditional to look at the data */
+ int i;
+ printk("len is %i",len);
+ for (i=14 ; i<len; i++)
+ printk("TXdata[%d] %02x\n",i,buf[i]&0xff);
+ // printk("\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 == NMI_WFI_devs[0])
+ PDEBUGG("%08x:%05i --> %08x:%05i\n",
+ ntohl(ih->saddr),ntohs(((struct tcphdr *)(ih+1))->source),
+ ntohl(ih->daddr),ntohs(((struct tcphdr *)(ih+1))->dest));
+ else
+ PDEBUGG("%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 = NMI_WFI_devs[dev == NMI_WFI_devs[0] ? 1 : 0];
+ priv = netdev_priv(dest);
+
+ tx_buffer = NMI_WFI_GetTxBuffer(dev);
+ tx_buffer->datalen = len;
+ memcpy(tx_buffer->data, buf, len);
+ NMI_WFI_EnqueueBuf(dest, tx_buffer);
+ if (priv->rx_int_enabled) {
+ priv->status |= NMI_WFI_RX_INTR;
+ NMI_WFI_Interrupt(0, dest, NULL);
+ }
+
+ priv = netdev_priv(dev);
+ priv->tx_packetlen = len;
+ priv->tx_packetdata = buf;
+ priv->status |= NMI_WFI_TX_INTR;
+ if (lockup && ((priv->stats.tx_packets + 1) % lockup) == 0) {
+ /* Simulate a dropped transmit interrupt */
+ netif_stop_queue(dev);
+ PDEBUG("Simulate lockup at %ld, txp %ld\n", jiffies,
+ (unsigned long) priv->stats.tx_packets);
+ }
+ else
+ NMI_WFI_Interrupt(0, dev, NULL);
+
+}
+
+/**
+* @brief NMI_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 NMI_WFI_Tx(struct sk_buff *skb, struct net_device *dev)
+{
+ int len;
+ char *data, shortpkt[ETH_ZLEN];
+ struct NMI_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 */
+ NMI_WFI_HwTx(data, len, dev);
+
+ return 0; /* Our simple device can not fail */
+ }
+
+/**
+* @brief NMI_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 NMI_WFI_TxTimeout(struct net_device *dev)
+{
+ struct NMI_WFI_priv *priv = netdev_priv(dev);
+
+ PDEBUG("Transmit timeout at %ld, latency %ld\n", jiffies,
+ jiffies - dev->trans_start);
+ /* Simulate a transmission interrupt to get things moving */
+ priv->status = NMI_WFI_TX_INTR;
+ NMI_WFI_Interrupt(0, dev, NULL);
+ priv->stats.tx_errors++;
+ netif_wake_queue(dev);
+ return;
+}
+
+/**
+* @brief NMI_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 NMI_WFI_Ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ PDEBUG("ioctl\n");
+ return 0;
+}
+
+/**
+* @brief NMI_WFI_Stat
+* @details Return statistics to the caller
+* @param[in] net_device *dev:
+* @return NMI_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 *NMI_WFI_Stats(struct net_device *dev)
+{
+ struct NMI_WFI_priv *priv = netdev_priv(dev);
+ return &priv->stats;
+}
+
+/**
+* @brief NMI_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 NMI_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 NMI_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 NMI_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 NMI_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 NMI_WFI_ChangeMtu(struct net_device *dev, int new_mtu)
+{
+ unsigned long flags;
+ struct NMI_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 NMI_WFI_header_ops = {
+ .create = NMI_WFI_Header,
+ .rebuild = NMI_WFI_RebuildHeader,
+ .cache = NULL, /* disable caching */
+};
+
+
+static const struct net_device_ops NMI_WFI_netdev_ops = {
+ .ndo_open = NMI_WFI_Open,
+ .ndo_stop = NMI_WFI_Release,
+ .ndo_set_config = NMI_WFI_Config,
+ .ndo_start_xmit = NMI_WFI_Tx,
+ .ndo_do_ioctl = NMI_WFI_Ioctl,
+ .ndo_get_stats = NMI_WFI_Stats,
+ .ndo_change_mtu = NMI_WFI_ChangeMtu,
+ .ndo_tx_timeout = NMI_WFI_TxTimeout,
+ };
+
+/**
+* @brief NMI_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 NMI_WFI_Init(struct net_device *dev)
+{
+ struct NMI_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 = &NMI_WFI_netdev_ops;
+ dev->header_ops = &NMI_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 NMI_WFI_priv));
+ priv->dev = dev;
+ netif_napi_add(dev, &priv->napi, NMI_WFI_Poll, 2);
+ /* The last parameter above is the NAPI "weight". */
+ spin_lock_init(&priv->lock);
+ NMI_WFI_RxInts(dev, 1); /* enable receive interrupts */
+ NMI_WFI_SetupPool(dev);
+ }
+
+/**
+* @brief NMI_WFI_Stat
+* @details Return statistics to the caller
+* @param[in] net_device *dev:
+* @return NMI_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 NMI_WFI_Cleanup(void)
+{
+ int i;
+ struct NMI_WFI_priv *priv[2];
+
+ /*if(hwsim_mon!=NULL)
+ {
+ printk("Freeing monitor interface\n");
+ unregister_netdev(hwsim_mon);
+ free_netdev(hwsim_mon);
+ }*/
+ for (i = 0; i < 2;i++)
+ {
+ priv[i] = netdev_priv(NMI_WFI_devs[i]);
+
+ if (NMI_WFI_devs[i])
+ {
+ NMI_PRINTF("Unregistering\n");
+ unregister_netdev(NMI_WFI_devs[i]);
+ NMI_WFI_TearDownPool(NMI_WFI_devs[i]);
+ free_netdev(NMI_WFI_devs[i]);
+ NMI_PRINTF("[NETDEV]Stopping interface\n");
+ NMI_WFI_DeInitHostInt(NMI_WFI_devs[i]);
+ NMI_WFI_WiphyFree(NMI_WFI_devs[i]);
+ }
+
+ }
+ //unregister_netdev(hwsim_mon);
+ NMI_WFI_deinit_mon_interface();
+ return;
+}
+
+
+void StartConfigSim(void);
+
+
+
+
+
+
+
+/**
+* @brief NMI_WFI_Stat
+* @details Return statistics to the caller
+* @param[in] net_device *dev:
+* @return NMI_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 NMI_WFI_InitModule(void)
+{
+
+ int result, i, ret = -ENOMEM;
+ struct NMI_WFI_priv *priv[2],*netpriv;
+ struct wireless_dev *wdev;
+ NMI_WFI_Interrupt = use_napi ? NMI_WFI_NapiInterrupt : NMI_WFI_RegularInterrupt;
+ char buf[IFNAMSIZ];
+
+ for (i = 0; i < 2; i++)
+ {
+
+ /* Allocate the net devices */
+ NMI_WFI_devs[i] = alloc_netdev(sizeof(struct NMI_WFI_priv), "wlan%d",
+ NMI_WFI_Init);
+ if(NMI_WFI_devs[i] == NULL)
+ goto out;
+ //priv[i] = netdev_priv(NMI_WFI_devs[i]);
+
+ wdev = NMI_WFI_WiphyRegister(NMI_WFI_devs[i]);
+ NMI_WFI_devs[i]->ieee80211_ptr = wdev;
+ netpriv = netdev_priv(NMI_WFI_devs[i]);
+ netpriv->dev->ieee80211_ptr = wdev;
+ netpriv->dev->ml_priv = netpriv;
+ wdev->netdev = netpriv->dev;
+
+ /*Registering the net device*/
+ if ((result = register_netdev(NMI_WFI_devs[i])))
+ printk("NMI_WFI: error %i registering device \"%s\"\n",
+ result, NMI_WFI_devs[i]->name);
+ else
+ ret = 0;
+ }
+
+
+ /*init NMi driver */
+ priv[0] = netdev_priv(NMI_WFI_devs[0]);
+ priv[1] = netdev_priv(NMI_WFI_devs[1]);
+ //printk("Net dev handler in int %lu\n",&priv[0]->hNMIWFIDrv);
+
+ if(priv[1]->dev->ieee80211_ptr->wiphy->interface_modes && BIT(NL80211_IFTYPE_MONITOR) )
+ {
+ //snprintf(buf, IFNAMSIZ, "mon.%s", priv[1]->dev->name);
+ // printk("Initializing mon interface %s\n", buf);
+ // NMI_WFI_init_mon_interface();
+ // priv[1]->monitor_flag = 1;
+
+ }
+ priv[0]->bCfgScanning = NMI_FALSE;
+ priv[0]->u32RcvdChCount = 0;
+
+ NMI_memset(priv[0]->au8AssociatedBss, 0xFF, ETH_ALEN);
+
+
+ //ret = host_int_init(&priv[0]->hNMIWFIDrv);
+ /*copy handle to the other driver*/
+ //priv[1]->hNMIWFIDrv = priv[0]->hNMIWFIDrv;
+ if(ret)
+ {
+ NMI_PRINTF("Error Init Driver\n");
+ }
+
+
+ out:
+ if (ret)
+ NMI_WFI_Cleanup();
+ return ret;
+
+
+}
+
+
+module_init(NMI_WFI_InitModule);
+module_exit(NMI_WFI_Cleanup);
+
+#endif
diff --git a/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_mon.c b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_mon.c
new file mode 100755
index 00000000..6a846d24
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_mon.c
@@ -0,0 +1,693 @@
+/*!
+* @file linux_mon.c
+* @brief File Operations OS wrapper functionality
+* @author mdaftedar
+* @sa NMI_WFI_NetDevice.h
+* @date 01 MAR 2012
+* @version 1.0
+*/
+
+#ifndef SIMULATION
+#include "NMI_WFI_CfgOperations.h"
+#include "linux_wlan_common.h"
+#include "nmi_wlan_if.h"
+#include "nmi_wlan.h"
+#endif
+#ifdef NMI_FULLY_HOSTING_AP
+#include "NMI_host_AP.h"
+#endif
+#ifdef NMI_AP_EXTERNAL_MLME
+#ifdef SIMULATION
+#include "NMI_WFI_CfgOperations.h"
+#endif
+struct nmi_wfi_radiotap_hdr {
+ struct ieee80211_radiotap_header hdr;
+ u8 rate;
+ // u32 channel;
+}__attribute__((packed));
+struct nmi_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 *nmi_wfi_mon = NULL; /* global monitor netdev */
+
+#ifdef SIMULATION
+extern int NMI_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
+
+
+NMI_Uint8 srcAdd[6];
+NMI_Uint8 bssid[6];
+NMI_Uint8 broadcast[] = {0xff,0xff,0xff,0xff,0xff,0xff};
+/**
+* @brief NMI_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 NMI_WFI_monitor_rx(uint8_t *buff, uint32_t size)
+{
+ uint32_t header,pkt_offset;
+ struct sk_buff *skb = NULL;
+ struct nmi_wfi_radiotap_hdr *hdr;
+ struct nmi_wfi_radiotap_cb_hdr *cb_hdr;
+
+ PRINT_INFO(HOSTAPD_DBG,"In monitor interface receive function\n");
+
+ // struct NMI_WFI_priv *priv = netdev_priv(dev);
+
+ // priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy);
+
+ /* Bug 4601 */
+ if(nmi_wfi_mon == NULL)
+ return;
+
+ if (!netif_running(nmi_wfi_mon))
+ {
+ PRINT_INFO(HOSTAPD_DBG,"Monitor interface already RUNNING\n");
+ return;
+ }
+
+ //Get NMI 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
+
+ //if(INFO || buff[0] == 0x10 || buff[0] == 0xb0)
+ //PRINT_D(HOSTAPD_DBG,"In monitor interface callback receive function\n");
+
+
+ skb = dev_alloc_skb(size+sizeof(struct nmi_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 nmi_wfi_radiotap_cb_hdr *) skb_push(skb, sizeof(*cb_hdr));
+ memset(cb_hdr, 0, sizeof(struct nmi_wfi_radiotap_cb_hdr));
+
+ cb_hdr->hdr.it_version = 0;//PKTHDR_RADIOTAP_VERSION;
+
+ cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct nmi_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
+ {
+
+ // normal mgmt frame
+
+ //if(INFO || buff[0] == 0x00 || buff[0] == 0xb0)
+ // {
+ //PRINT_D(HOSTAPD_DBG,"In monitor interface receive function , length = %d\n",size);
+ //for(i=0;i<size;i++)
+ //PRINT_D(HOSTAPD_DBG,"Mon RxData[%d] = %02x\n",i,buff[i]);
+ // }
+
+
+ skb = dev_alloc_skb(size+sizeof(struct nmi_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);
+ //printk("--radiotap header--\n",sizeof(*hdr));
+ hdr = (struct nmi_wfi_radiotap_hdr *) skb_push(skb, sizeof(*hdr));
+ memset(hdr, 0, sizeof(struct nmi_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 nmi_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 = nmi_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 nmi_wfi_radiotap_cb_hdr *cb_hdr;
+
+ struct tx_complete_mon_data* pv_data = (struct tx_complete_mon_data*)priv;
+ NMI_Uint8 * buf= pv_data->buff;
+
+
+
+ if(status == 1){
+ if(INFO || buf[0] == 0x10 || buf[0] == 0xb0)
+ PRINT_D(HOSTAPD_DBG,"Packet sent successfully - Size = %d - Address = %p.\n",pv_data->size,pv_data->buff);
+ }else{
+ PRINT_D(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 nmi_wfi_radiotap_cb_hdr));
+
+ memcpy(skb_put(skb2,pv_data->size),pv_data->buff, pv_data->size);
+
+ cb_hdr = (struct nmi_wfi_radiotap_cb_hdr *) skb_push(skb2, sizeof(*cb_hdr));
+ memset(cb_hdr, 0, sizeof(struct nmi_wfi_radiotap_cb_hdr));
+
+ cb_hdr->hdr.it_version = 0;//PKTHDR_RADIOTAP_VERSION;
+
+ cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct nmi_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 = nmi_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 NMI_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 NMI_FAIL;
+ }
+ nic =netdev_priv(dev);
+
+ //NMI_PRINTF("--IN mon_mgmt_tx--\n");
+ netif_stop_queue(dev);
+ mgmt_tx = (struct tx_complete_mon_data*)kmalloc(sizeof(struct tx_complete_mon_data),GFP_ATOMIC);
+ if(mgmt_tx == NULL){
+ PRINT_ER("Failed to allocate memory for mgmt_tx structure\n");
+ return NMI_FAIL;
+ }
+
+ #ifdef NMI_FULLY_HOSTING_AP
+ // add space for the pointer to tx_complete_mon_data
+ len+=sizeof(struct tx_complete_mon_data*);
+ #endif
+
+ mgmt_tx->buff= (char*)kmalloc(len,GFP_ATOMIC);
+ if(mgmt_tx->buff == NULL)
+ {
+ PRINT_ER("Failed to allocate memory for mgmt_tx buff\n");
+ return NMI_FAIL;
+
+ }
+
+ mgmt_tx->size=len;
+
+ #ifndef NMI_FULLY_HOSTING_AP
+ memcpy(mgmt_tx->buff,buf,len);
+ #else
+ //printk("sizeof(struct tx_complete_mon_data*) = %d\n",sizeof(struct tx_complete_mon_data*));
+ //printk("len = %d, mgmt_tx=%x\n",len,mgmt_tx);
+ 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)== NMI_TRUE)
+ {
+ return;
+ }
+
+ #endif //NMI_FULLY_HOSTING_AP
+
+ //printk("--IN mon_mgmt_tx: Sending MGMT Pkt to tx queue--\n");
+ 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 NMI_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 NMI_WFI_mon_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct ieee80211_radiotap_header *rtap_hdr;
+ NMI_Uint32 rtap_len,i,ret=0;
+ struct NMI_WFI_mon_priv *mon_priv ;
+
+ struct sk_buff *skb2;
+ struct nmi_wfi_radiotap_cb_hdr *cb_hdr;
+
+ //PRINT_D(HOSTAPD_DBG,"Monitor xmit function b4\n");
+ /* Bug 4601 */
+ if(nmi_wfi_mon == NULL)
+ return NMI_FAIL;
+
+ //if(skb->data[3] == 0x10 || skb->data[3] == 0xb0)
+ //PRINT_D(HOSTAPD_DBG,"Monitor xmit function\n");
+
+
+
+ mon_priv = netdev_priv(nmi_wfi_mon);
+
+ if(mon_priv== NULL)
+ {
+ PRINT_ER("Monitor interface private structure is NULL\n");
+ return NMI_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)
+
+ 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 &&(!(memcmp(broadcast, &skb->data[4],6) )) )
+ {
+ skb2 = dev_alloc_skb(skb->len+sizeof(struct nmi_wfi_radiotap_cb_hdr));
+
+ memcpy(skb_put(skb2,skb->len),skb->data, skb->len);
+
+ cb_hdr = (struct nmi_wfi_radiotap_cb_hdr *) skb_push(skb2, sizeof(*cb_hdr));
+ memset(cb_hdr, 0, sizeof(struct nmi_wfi_radiotap_cb_hdr));
+
+ cb_hdr->hdr.it_version = 0;//PKTHDR_RADIOTAP_VERSION;
+
+ cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct nmi_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 = nmi_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 = NMI_WFI_Tx(skb,mon_priv->real_ndev);
+ #elif USE_WIRELESS
+ //Identify if Ethernet or MAC header (data or mgmt)
+ memcpy(srcAdd,& skb->data[11],6);
+ //NMI_PRINTF("SRC/BSSID\n");
+ memcpy(bssid, &skb->data[17],6);
+ //if source address and bssid fields are equal>>Mac header
+ /*send it to mgmt frames handler */
+ if(!(memcmp(srcAdd,bssid,6)))
+ {
+ //NMI_PRINTF("--MGMT PKT in mon_xmit--\n");
+ 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 nmi_wfi_netdev_ops = {
+ .ndo_start_xmit = NMI_WFI_mon_xmit,
+
+};
+
+#ifdef NMI_FULLY_HOSTING_AP
+/*
+* @brief NMI_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 NMI_mgm_HOSTAPD_ACK(void* priv, NMI_Bool bStatus)
+{
+ struct sk_buff *skb;
+ struct nmi_wfi_radiotap_cb_hdr *cb_hdr;
+
+ struct tx_complete_mon_data* pv_data = (struct tx_complete_mon_data*)priv;
+ NMI_Uint8 * buf= pv_data->buff;
+
+ // len of the original frame without the added pointer at the tail
+ NMI_Uint16 u16len = (pv_data->size) - sizeof(struct tx_complete_mon_data*);
+
+
+ /*if(bStatus == 1){
+ if(INFO || buf[0] == 0x10 || buf[0] == 0xb0)
+ PRINT_D(HOSTAPD_DBG,"Packet sent successfully - Size = %d - Address = %p.\n",u16len,pv_data->buff);
+ }else{
+ PRINT_D(HOSTAPD_DBG,"Couldn't send packet - Size = %d - Address = %p.\n",u16len,pv_data->buff);
+ }
+ */
+
+ //(skb->data[9] == 0x00 || skb->data[9] == 0xb0 || skb->data[9] == 0x40 || skb->data[9] == 0xd0 )
+ {
+ skb = dev_alloc_skb(u16len+sizeof(struct nmi_wfi_radiotap_cb_hdr));
+
+ memcpy(skb_put(skb,u16len),pv_data->buff, u16len);
+
+ cb_hdr = (struct nmi_wfi_radiotap_cb_hdr *) skb_push(skb, sizeof(*cb_hdr));
+ memset(cb_hdr, 0, sizeof(struct nmi_wfi_radiotap_cb_hdr));
+
+ cb_hdr->hdr.it_version = 0;//PKTHDR_RADIOTAP_VERSION;
+
+ cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct nmi_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(NMI_TRUE == bStatus)
+ {
+ //success
+ cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_RTS;
+ }
+ else
+ {
+ cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_FAIL;
+ }
+
+ skb->dev = nmi_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 //NMI_FULLY_HOSTING_AP
+
+/**
+* @brief NMI_WFI_mon_setup
+* @details
+* @param[in]
+* @return int : Return 0 on Success
+* @author mdaftedar
+* @date 12 JUL 2012
+* @version 1.0
+*/
+static void NMI_WFI_mon_setup(struct net_device *dev)
+{
+
+ dev->netdev_ops = &nmi_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 = (NMI_Uint8*)NMI_MALLOC(ETH_ALEN);
+ //status = host_int_get_MacAddress(priv->hNMIWFIDrv,mac_add);
+ //mac_add[ETH_ALEN-1]+=1;
+ memcpy(dev->dev_addr, mac_add, ETH_ALEN);
+ }
+ #else
+ dev->dev_addr[0] = 0x12;
+ #endif
+
+}
+
+/**
+* @brief NMI_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 * NMI_WFI_init_mon_interface(char *name , struct net_device *real_dev )
+ {
+
+
+ NMI_Uint32 ret = NMI_SUCCESS;
+ struct NMI_WFI_mon_priv *priv ;
+
+ /*If monitor interface is already initialized, return it*/
+ if (nmi_wfi_mon)
+ {
+ return nmi_wfi_mon;
+ }
+#if 0
+ nmi_wfi_mon = alloc_netdev(sizeof(struct NMI_WFI_mon_priv), name, NMI_WFI_mon_setup);
+ if (nmi_wfi_mon == NULL)
+ {
+ PRINT_ER("Failed to allocate netdevice\n");
+ goto failed;
+ }
+
+ //rtnl_lock();
+ PRINT_INFO(HOSTAPD_DBG,"Monitor interface name %s\n", nmi_wfi_mon->name);
+
+
+ ret = dev_alloc_name(nmi_wfi_mon, nmi_wfi_mon->name);
+ if (ret < 0)
+ goto failed_mon;
+
+
+ priv = netdev_priv(nmi_wfi_mon);
+ if(priv== NULL)
+ {
+ PRINT_ER("private structure is NULL\n");
+ return NMI_FAIL;
+ }
+
+ priv->real_ndev = real_dev;
+
+
+ ret = register_netdevice(nmi_wfi_mon);
+
+
+ if (ret < 0)
+ {
+ PRINT_ER("Failed to register netdevice\n");
+ goto failed_mon;
+ }
+
+
+ return NMI_SUCCESS;
+ // rtnl_unlock();
+
+ failed:
+ return ret;
+
+ failed_mon:
+ //rtnl_unlock();
+ free_netdev(nmi_wfi_mon);
+ return ret;
+#endif
+
+ nmi_wfi_mon = alloc_etherdev(sizeof(struct NMI_WFI_mon_priv));
+ if (!nmi_wfi_mon) {
+ PRINT_ER("failed to allocate memory\n");
+ return NULL;
+
+ }
+
+ nmi_wfi_mon->type = ARPHRD_IEEE80211_RADIOTAP;
+ strncpy(nmi_wfi_mon->name, name, IFNAMSIZ);
+ nmi_wfi_mon->name[IFNAMSIZ - 1] = 0;
+ nmi_wfi_mon->netdev_ops = &nmi_wfi_netdev_ops;
+
+ ret = register_netdevice(nmi_wfi_mon);
+ if (ret) {
+ PRINT_ER(" register_netdevice failed (%d)\n", ret);
+ return NULL;
+ }
+ priv = netdev_priv(nmi_wfi_mon);
+ if(priv== NULL)
+ {
+ PRINT_ER("private structure is NULL\n");
+ return NULL;
+ }
+
+ priv->real_ndev = real_dev;
+
+ return nmi_wfi_mon;
+}
+
+/**
+* @brief NMI_WFI_deinit_mon_interface
+* @details
+* @param[in]
+* @return int : Return 0 on Success
+* @author mdaftedar
+* @date 12 JUL 2012
+* @version 1.0
+*/
+int NMI_WFI_deinit_mon_interface()
+{
+ bool rollback_lock = false;
+
+ if(nmi_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(nmi_wfi_mon);
+ //NMI_PRINTF("Free Netdev\n");
+ //free_netdev(nmi_wfi_mon);
+
+ if (rollback_lock)
+ {
+ rtnl_lock();
+ rollback_lock = false;
+ }
+ nmi_wfi_mon = NULL;
+ }
+ return NMI_SUCCESS;
+
+}
+#endif // NMI_AP_EXTERNAL_MLME
diff --git a/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_wlan.c b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_wlan.c
new file mode 100755
index 00000000..a00a4247
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_wlan.c
@@ -0,0 +1,3332 @@
+#ifndef SIMULATION
+#include "NMI_WFI_CfgOperations.h"
+#include "linux_wlan_common.h"
+#include "nmi_wlan_if.h"
+#include "nmi_wlan.h"
+#ifdef USE_WIRELESS
+#include "NMI_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>
+#ifndef PLAT_ALLWINNER_A10 // tony
+#include <asm/gpio.h>
+#endif
+#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 NMI_SDIO
+#include "linux_wlan_sdio.h"
+#else
+#include "linux_wlan_spi.h"
+#endif
+
+#ifdef NMI_FULLY_HOSTING_AP
+#include "NMI_host_AP.h"
+#endif
+
+#include "svnrevision.h"
+#ifdef FW_VERSION_VERIFICATION
+#include "verify_fw_version.c"
+#endif
+
+#ifdef STATIC_MACADDRESS//brandy_0724 [[
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+struct task_struct* nmi_mac_thread;
+unsigned char mac_add[] = {0x00, 0x80, 0xC2, 0x5E, 0xa2, 0xb2};
+#endif //brandy_0724 ]]
+
+#if defined(PLAT_AML8726_M3)
+ #include <mach/gpio.h>
+ #include <mach/gpio_data.h>
+ #include <mach/pinmux.h>
+
+ extern void extern_wifi_set_enable(int is_on);
+ extern void sdio_reinit(void);
+
+ #define _linux_wlan_device_power_on() extern_wifi_set_enable(1)
+ #define _linux_wlan_device_power_off() extern_wifi_set_enable(0)
+
+ #define _linux_wlan_device_detection() sdio_reinit()
+ #define _linux_wlan_device_removal() ;
+
+ static int _available_irq_ready = 0; //[[ johnny : because of dummy irq
+
+#elif defined(PLAT_ALLWINNER_A10)
+ extern void mmc_pm_power(int mode, int* updown);
+ extern void sunximmc_rescan_card(unsigned id, unsigned insert);
+ extern int mmc_pm_get_io_val(char* name);
+ extern int mmc_pm_gpio_ctrl(char* name, int level);
+
+ #define NMC1000_SDIO_CARD_ID 0
+ int nmc1000_power_val = 0;
+
+ #define _linux_wlan_device_power_on() { nmc1000_power_val = 1; mmc_pm_power(NMC1000_SDIO_CARD_ID,&nmc1000_power_val); }
+ #define _linux_wlan_device_power_off() { nmc1000_power_val = 0; mmc_pm_power(NMC1000_SDIO_CARD_ID,&nmc1000_power_val); }
+
+ #define _linux_wlan_device_detection() sw_mci_rescan_card(NMC1000_SDIO_CARD_ID,1)
+ #define _linux_wlan_device_removal() sw_mci_rescan_card(NMC1000_SDIO_CARD_ID,0)
+
+#elif defined(PLAT_ALLWINNER_A20)
+ extern void sw_mci_rescan_card(unsigned id, unsigned insert);
+ extern void wifi_pm_power(int on); // tony to keep allwinner's rule
+ #define NMC1000_SDIO_CARD_ID 3
+
+ #define _linux_wlan_device_power_on() wifi_pm_power(1)
+ #define _linux_wlan_device_power_off() wifi_pm_power(0)
+
+ #define _linux_wlan_device_detection() sw_mci_rescan_card(NMC1000_SDIO_CARD_ID,1)
+ #define _linux_wlan_device_removal() sw_mci_rescan_card(NMC1000_SDIO_CARD_ID,0)
+
+#elif defined(PLAT_ALLWINNER_A23)
+ extern void sunxi_mci_rescan_card(unsigned id, unsigned insert);
+ extern void wifi_pm_power(int on);
+ #define NMC1000_SDIO_CARD_ID 1
+
+ #define _linux_wlan_device_power_on() wifi_pm_power(1)
+ #define _linux_wlan_device_power_off() wifi_pm_power(0)
+
+ #define _linux_wlan_device_detection() sunxi_mci_rescan_card(NMC1000_SDIO_CARD_ID,1)
+ #define _linux_wlan_device_removal() sunxi_mci_rescan_card(NMC1000_SDIO_CARD_ID,0)
+
+#elif defined(PLAT_ALLWINNER_A31)
+ extern void sw_mci_rescan_card(unsigned id, unsigned insert);
+ extern void wifi_pm_power(int on);
+ #define NMC1000_SDIO_CARD_ID 1
+
+ #define _linux_wlan_device_power_on() wifi_pm_power(1)
+ #define _linux_wlan_device_power_off() wifi_pm_power(0)
+
+ #define _linux_wlan_device_detection() sw_mci_rescan_card(NMC1000_SDIO_CARD_ID,1)
+ #define _linux_wlan_device_removal() sw_mci_rescan_card(NMC1000_SDIO_CARD_ID,0)
+
+#elif defined(PLAT_WMS8304) // added by rachel
+ #include "nmi_custom_gpio.c"
+
+ #define _linux_wlan_device_power_on() NmiWifiCardPower(1)
+ #define _linux_wlan_device_power_off() NmiWifiCardPower(0)
+
+#elif defined(PLAT_WM8880)
+ #include "nmi_wm8880_gpio.c"
+
+ #include <linux/wireless.h> // simon, rachel
+ #include <mach/irqs.h>
+ #include <linux/mmc/sdio.h>
+ #include <mach/hardware.h>
+ #include <asm/io.h>
+ #include <asm/irq.h>
+
+ /*simulate virtual sdio card insert and removal*/
+ extern void force_remove_sdio2(void);
+ extern void wmt_detect_sdio2(void);
+ int wmt_nmc1000_intr_num=15; //gpio 15
+
+ #define _linux_wlan_device_power_on() NmiWifiCardPower(1)
+ #define _linux_wlan_device_power_off() NmiWifiCardPower(0)
+
+ #define _linux_wlan_device_detection() wmt_detect_sdio2()
+ #define _linux_wlan_device_removal() force_remove_sdio2()
+
+#elif defined(PLAT_RKXXXX)
+extern int rk29sdk_wifi_power(int on);
+extern int rk29sdk_wifi_set_carddetect(int val);
+#define _linux_wlan_device_power_on() rk29sdk_wifi_power(1)
+#define _linux_wlan_device_power_off() rk29sdk_wifi_power(0)
+#define _linux_wlan_device_detection() rk29sdk_wifi_set_carddetect(1)
+#define _linux_wlan_device_removal() rk29sdk_wifi_set_carddetect(0)
+
+#elif defined(PLAT_CLM9722)
+#define _linux_wlan_device_power_on() {}
+#define _linux_wlan_device_power_off() {}
+
+#define _linux_wlan_device_detection() {}
+#define _linux_wlan_device_removal() {}
+
+#else
+ #define _linux_wlan_device_detection() {}
+ #define _linux_wlan_device_removal() {}
+ #define _linux_wlan_device_power_on() {}
+ #define _linux_wlan_device_power_off() {}
+
+#endif
+
+
+#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
+extern NMI_Bool g_obtainingIP;
+#endif
+
+
+extern NMI_Uint16 Set_machw_change_vir_if(NMI_Bool bValue);
+extern void resolve_disconnect_aberration(void* drvHandler);
+extern NMI_Uint8 gau8MulticastMacAddrList[NMI_MULTICAST_TABLE_SIZE][ETH_ALEN];
+
+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 NMI_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 nmi_wlan_deinit(nic) if(&g_linux_wlan->oup != NULL) \
+ if(g_linux_wlan->oup.wlan_cleanup != NULL) \
+ g_linux_wlan->oup.wlan_cleanup()
+
+//[[ johnny : enable to selecte bin file on Makefile
+#ifndef STA_FIRMWARE
+#define STA_FIRMWARE "wifi_firmware.bin"
+#endif
+
+#ifndef AP_FIRMWARE
+#define AP_FIRMWARE "wifi_firmware_ap.bin"
+#endif
+
+#ifndef P2P_CONCURRENCY_FIRMWARE
+#define P2P_CONCURRENCY_FIRMWARE "wifi_firmware_p2p_concurrency.bin"
+#endif
+//]]
+
+// [[ added by tony
+typedef struct android_wifi_priv_cmd {
+ char *buf;
+ int used_len;
+ int total_len;
+} android_wifi_priv_cmd;
+// ]] for wpa supplicant iw
+
+
+#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 nmc_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 NMI_WFI_monitor_rx(uint8_t *buff, uint32_t size);
+extern void NMI_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 nmi_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 = NULL;
+nmi_wlan_oup_t* gpstrWlanOps;
+NMI_Bool bEnablePS = NMI_TRUE;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)
+
+static const struct net_device_ops nmc_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 = nmi_set_multicast_list,
+
+};
+#define nmc_set_netdev_ops(ndev) do { (ndev)->netdev_ops = &nmc_netdev_ops; } while(0)
+
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
+
+static const struct net_device_ops nmc_netdev_ops = {
+ .ndo_init = mac_init_fn,
+ .ndo_open = mac_open,
+ .ndo_stop = mac_close,
+ .ndo_start_xmit = mac_xmit,
+ .ndo_do_ioctl = mac_ioctl,
+ .ndo_get_stats = mac_stats,
+ .ndo_set_multicast_list = nmi_set_multicast_list,
+
+};
+
+#define nmc_set_netdev_ops(ndev) do { (ndev)->netdev_ops = &nmc_netdev_ops; } while(0)
+
+#else
+
+static void nmc_set_netdev_ops(struct net_device *ndev)
+{
+
+ ndev->init = mac_init_fn;
+ ndev->open = mac_open;
+ ndev->stop = mac_close;
+ ndev->hard_start_xmit = mac_xmit;
+ ndev->do_ioctl = mac_ioctl;
+ ndev->get_stats = mac_stats;
+ ndev->set_multicast_list = nmi_set_multicast_list,
+}
+
+#endif
+#ifdef DEBUG_MODE
+
+extern volatile int timeNo;
+
+#define DEGUG_BUFFER_LENGTH 1000
+volatile int WatchDogdebuggerCounter=0;
+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;
+ printk("early printed\n");
+ printk(ps8current+1);
+ ps8current[1]=0;
+ printk("latest printed\n");
+ printk(DebugBuffer);
+ DebugBuffer[0]=0;
+ ps8current=DebugBuffer;
+ }
+}
+
+void Reset_WatchDogdebugger()
+{
+ WatchDogdebuggerCounter=0;
+}
+
+static int DebuggingThreadTask(void* vp)
+{
+ while(1){
+ while(!WatchDogdebuggerCounter)
+ {
+ printk("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 NMI_WFI_priv* priv;
+ tstrNMI_WFIDrv * pstrWFIDrv;
+ struct net_device * dev;
+ NMI_Uint8 *pIP_Add_buff;
+ NMI_Sint32 s32status = NMI_FAIL;
+ perInterface_wlan_t* nic;
+ NMI_Uint8 null_ip[4]={0};
+ char wlan_dev_name[5]="wlan0";
+
+ if(dev_iface == NULL)
+ {
+ NMI_PRINTF("dev_iface = NULL\n");
+ return NOTIFY_DONE;
+ }
+
+ dev = (struct net_device *)dev_iface->ifa_dev->dev;
+ priv= wiphy_priv(dev->ieee80211_ptr->wiphy);
+ pstrWFIDrv = (tstrNMI_WFIDrv *)priv->hNMIWFIDrv;
+ nic = netdev_priv(dev);
+
+ printk("dev_state_ev_handler +++\n"); // tony
+
+ 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;
+ }
+
+ if(pstrWFIDrv == NULL)
+ {
+ PRINT_ER("Driver handler = NULL !\n");
+ }
+
+ switch (event) {
+
+ case NETDEV_UP:
+ printk("dev_state_ev_handler event=NETDEV_UP %p\n",dev); // tony
+
+ printk("\n ============== IP Address Obtained ===============\n\n");
+
+
+ /*If we are in station mode or client mode*/
+ if(nic->iftype==STATION_MODE||nic->iftype==CLIENT_MODE)
+ {
+ g_obtainingIP=NMI_FALSE;
+ PRINT_D(GENERIC_DBG,"IP obtained , enable scan\n");
+ }
+
+
+
+ if(bEnablePS == NMI_TRUE)
+ host_int_set_power_mgmt((NMI_WFIDrvHandle)pstrWFIDrv, 1, 0);
+
+ PRINT_D(GENERIC_DBG, "[%s] Up IP\n", dev_iface->ifa_label);
+
+ pIP_Add_buff = (char *) (&(dev_iface->ifa_address));
+ printk("IP add=%d:%d:%d:%d \n",pIP_Add_buff[0],pIP_Add_buff[1],pIP_Add_buff[2],pIP_Add_buff[3]);
+ s32status = host_int_setup_ipaddress((NMI_WFIDrvHandle)pstrWFIDrv, pIP_Add_buff, nic->u8IfIdx);
+
+ break;
+
+ case NETDEV_DOWN:
+ printk("dev_state_ev_handler event=NETDEV_DOWN %p\n",dev); // tony
+
+ printk("\n ============== IP Address Released ===============\n\n");
+ if(nic->iftype==STATION_MODE||nic->iftype==CLIENT_MODE)
+ {
+ g_obtainingIP=NMI_FALSE;
+ }
+
+ if(memcmp(dev_iface->ifa_label , wlan_dev_name, 5) == 0)
+ host_int_set_power_mgmt((NMI_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;
+ printk("IP add=%d:%d:%d:%d \n",pIP_Add_buff[0],pIP_Add_buff[1],pIP_Add_buff[2],pIP_Add_buff[3]);
+ s32status = host_int_setup_ipaddress((NMI_WFIDrvHandle)pstrWFIDrv, pIP_Add_buff, nic->u8IfIdx);
+
+ break;
+
+ default:
+ printk("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 NMI_SDIO) || (defined NMI_SDIO_IRQ_GPIO)
+ PRINT_D(INT_DBG,"Enabling IRQ ...\n");
+
+ #if defined(PLAT_WMS8304) // added by rachel
+ //enable_irq(nic->dev_irq_num);
+ /*clean corresponding int status bit, or it will generate int continuously for ever*/
+ gpio_clean_irq_status_any(&gpio_irq_ctrl);
+
+ enable_irq(g_linux_wlan->dev_irq_num);
+
+ /*we should reopen this gpio pin int in order to capture the future/comming interruption*/
+ enable_gpio_int_any(&gpio_irq_ctrl, INT_EN);
+ #elif defined(PLAT_WM8880)
+
+ wmt_gpio_ack_irq(wmt_nmc1000_intr_num);
+ wmt_gpio_unmask_irq(wmt_nmc1000_intr_num);
+
+ #else
+ enable_irq(g_linux_wlan->dev_irq_num);
+ #endif
+
+#endif
+#endif
+}
+
+void linux_wlan_disable_irq(int wait){
+#if (!defined NMI_SDIO) || (defined NMI_SDIO_IRQ_GPIO)
+ if(wait) {
+ PRINT_D(INT_DBG,"Disabling IRQ ...\n");
+ #if defined(PLAT_WM8880)
+ wmt_gpio_mask_irq(wmt_nmc1000_intr_num);
+ #else
+ disable_irq(g_linux_wlan->dev_irq_num);
+ #endif
+ } else {
+ PRINT_D(INT_DBG,"Disabling IRQ ...\n");
+ #if defined(PLAT_WM8880)
+ wmt_gpio_mask_irq(wmt_nmc1000_intr_num);
+ #else
+ disable_irq_nosync(g_linux_wlan->dev_irq_num);
+ #endif
+ }
+#endif
+}
+#if (!defined NMI_SDIO) || (defined NMI_SDIO_IRQ_GPIO)
+static irqreturn_t isr_uh_routine(int irq, void* user_data){
+
+#if defined(PLAT_WMS8304)
+ int pin_state;
+ //printk("isr_uh_routine\n");
+ /*if this gpio pin int is not enable or int status bit is not toggled, it is not our interruption*/
+ if(!gpio_irq_isEnable_any(&gpio_irq_ctrl) || !gpio_irq_state_any(&gpio_irq_ctrl))
+ return IRQ_NONE;
+
+ /*be here, be sure that this int is myself, but we should disable int before handler this interruption*/
+ enable_gpio_int_any(&gpio_irq_ctrl, INT_DIS);
+
+ /*get value on gpin int pin*/
+ pin_state = gpio_get_value_any(&gpio_irq_ctrl);
+
+ if(pin_state == 0) {
+ //printk("wlan int\n");
+ //dont_deinit_irq = 0;
+ }
+ else
+ {
+ //printk("this is fake interruption!!\n");
+ enable_gpio_int_any(&gpio_irq_ctrl, INT_EN);
+ return IRQ_HANDLED;
+ }
+#elif defined(PLAT_WM8880)
+
+ if(!is_gpio_irqenable(wmt_nmc1000_intr_num) || !gpio_irqstatus(wmt_nmc1000_intr_num))
+ return IRQ_NONE;
+
+ wmt_gpio_mask_irq(wmt_nmc1000_intr_num);
+
+#endif
+
+ int_rcvdU++;
+ PRINT_D(INT_DBG,"Interrupt received UH\n");
+#if (RX_BH_TYPE != RX_BH_THREADED_IRQ)
+ linux_wlan_disable_irq(IRQ_NO_WAIT);
+#endif
+
+#if defined(PLAT_AML8726_M3)//[[ johnny : because of dummy irq
+ if ( _available_irq_ready == 0 )
+ {
+ linux_wlan_enable_irq();
+ PRINT_D(GENERIC_DBG,"johnny test : recevied dummy irq\n");
+ return IRQ_HANDLED;
+ }
+#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 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 NMI_SDIO) || (defined NMI_SDIO_IRQ_GPIO)
+static int init_irq(linux_wlan_t* p_nic){
+ int ret = 0;
+ linux_wlan_t *nic = p_nic;
+
+#if defined(PLAT_AML8726_M3) //johnny add
+ nic->dev_irq_num = INT_GPIO_4; // <== skyworth //'100' value for onda vi30 platform
+
+ ret = request_irq(nic->dev_irq_num, isr_uh_routine, IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ "NMC_IRQ", nic);
+
+ if (ret < 0) {
+ PRINT_ER("Failed to request IRQ for GPIO: %d\n",nic->dev_irq_num);
+ }
+
+#elif defined (PLAT_WMS8304) //simon
+ //system("rmmod /system/modules/3.0.8-default/kpad.ko");
+ irq_gpio_init();
+ nic->dev_irq_num = IRQ_GPIO; //(5) gpio_irq_ctrl;
+ printk("%s\n",__FUNCTION__);
+ ret = request_irq(nic->dev_irq_num, isr_uh_routine, IRQF_SHARED,
+ "NMC_IRQ", nic);
+
+ if (ret < 0) {
+ PRINT_ER("Failed to request IRQ for GPIO: %d\n",nic->dev_irq_num);
+ }
+
+ enable_gpio_int_any(&gpio_irq_ctrl,INT_EN);
+
+#elif defined(PLAT_WM8880)
+
+ printk("%s\n",__FUNCTION__);
+ wmt_gpio_setpull(wmt_nmc1000_intr_num,WMT_GPIO_PULL_UP);
+ wmt_gpio_mask_irq(wmt_nmc1000_intr_num);
+ wmt_gpio_ack_irq(wmt_nmc1000_intr_num);
+
+
+ nic->dev_irq_num = IRQ_GPIO;
+ ret = request_irq(nic->dev_irq_num, isr_uh_routine, IRQF_SHARED,
+ "NMC_IRQ", nic);
+
+ if (ret < 0) {
+ PRINT_ER("Failed to request IRQ for GPIO: %d\n",nic->dev_irq_num);
+ }
+
+ /*clear int status register before enable this int pin*/
+ wmt_gpio_ack_irq(wmt_nmc1000_intr_num);
+ /*enable this int pin*/
+ wmt_gpio_unmask_irq(wmt_nmc1000_intr_num);
+
+#elif defined (PLAT_RKXXXX)
+ if ((gpio_request(GPIO_NUM, "NMC_INTR") == 0) &&
+ (gpio_direction_input(GPIO_NUM) == 0)) {
+
+ nic->dev_irq_num = gpio_to_irq(GPIO_NUM);
+ ret = request_irq(nic->dev_irq_num, isr_uh_routine, IRQF_TRIGGER_LOW,
+ "NMC_IRQ", nic);
+ PRINT_ER("********%s() IRQ_GPIO, %s\n", __func__, __DATE__);
+ if (ret < 0) {
+ PRINT_ER("Failed to request IRQ for GPIO: %d\n",nic->dev_irq_num);
+ }
+
+ } else {
+ ret = -1;
+ PRINT_ER("could not obtain gpio for NMC_INTR\n");
+ }
+
+
+#else
+ /*initialize GPIO and register IRQ num*/
+ /*GPIO request*/
+ if ((gpio_request(GPIO_NUM, "NMC_INTR") == 0) &&
+ (gpio_direction_input(GPIO_NUM) == 0)) {
+#if defined (NM73131_0_BOARD)
+ g_linux_wlan->dev_irq_num = IRQ_NMC1000;
+#else
+ 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);
+#endif
+ } else {
+ ret = -1;
+ PRINT_ER("could not obtain gpio for NMC_INTR\n");
+ }
+
+
+#if (RX_BH_TYPE == RX_BH_THREADED_IRQ)
+ if( (ret != -1) && ( request_threaded_irq(g_linux_wlan->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*/
+ "NMC_IRQ", nic))<0){
+
+#else
+ /*Request IRQ*/
+ if( (ret != -1) && (request_irq(nic->dev_irq_num, isr_uh_routine,
+ IRQF_TRIGGER_LOW, "NMC_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",
+ g_linux_wlan->dev_irq_num,GPIO_NUM);
+ }
+
+#endif
+
+ return ret;
+}
+#endif
+
+static void deinit_irq(linux_wlan_t* nic){
+#if (!defined NMI_SDIO) || (defined NMI_SDIO_IRQ_GPIO)
+ /* Deintialize IRQ */
+ if(&g_linux_wlan->dev_irq_num != 0){
+ free_irq(g_linux_wlan->dev_irq_num, g_linux_wlan);
+ #if defined(PLAT_AML8726_M3) //johnny
+
+ #elif defined (PLAT_WMS8304)
+ irq_gpio_deinit();
+
+ #elif defined(PLAT_WM8880)
+ /* austin-0720: johnny, let me know why this is empty */
+ #else
+ gpio_free(GPIO_NUM);
+ #endif
+ }
+#endif
+}
+
+
+/*
+ OS functions
+*/
+static void linux_wlan_msleep(uint32_t msc){
+ if(msc <= 4000000)
+ {
+ NMI_Uint32 u32Temp = msc * 1000;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
+ usleep_range(u32Temp, u32Temp);
+#else
+ /* This is delay not sleep !!!, has to be changed*/
+ msleep(msc);
+#endif
+ }
+ else
+ {
+ msleep(msc);
+ }
+}
+
+static void linux_wlan_atomic_msleep(uint32_t msc){
+ mdelay(msc);
+}
+static void linux_wlan_dbg(uint8_t *buff){
+ printk(buff);
+#if defined (NMC_DEBUGFS)
+ kmsgdump_write(buff);
+#endif
+}
+
+static void* linux_wlan_malloc_atomic(uint32_t sz){
+ char* pntr = NULL;
+ pntr = (char*)kmalloc(sz,GFP_ATOMIC );
+ PRINT_D(MEM_DBG,"Allocating %d bytes at address %p\n",sz,pntr);
+ return ((void*)pntr);
+
+}
+static void* linux_wlan_malloc(uint32_t sz){
+ char* pntr = NULL;
+ pntr = (char*)kmalloc(sz,GFP_KERNEL );
+ PRINT_D(MEM_DBG,"Allocating %d bytes at address %p\n",sz,pntr);
+ return ((void*)pntr);
+}
+
+void linux_wlan_free(void* vp){
+ if(vp != NULL){
+ PRINT_D(MEM_DBG,"Freeing %p\n",vp);
+ kfree(vp);
+ }
+}
+
+
+static void* internal_alloc(uint32_t size, uint32_t flag){
+ char* pntr = NULL;
+ pntr = (char*)kmalloc(size,flag);
+ PRINT_D(MEM_DBG,"Allocating %d bytes at address %p\n",size,pntr);
+ return ((void*)pntr);
+}
+
+
+static void linux_wlan_init_lock(char* lockName, void* plock,int count)
+{
+ sema_init((struct semaphore*)plock,count);
+ PRINT_D(LOCK_DBG,"Initializing [%s][%p]\n",lockName,plock);
+
+}
+
+static void linux_wlan_deinit_lock(void* plock)
+{
+ //mutex_destroy((struct mutex*)plock);
+}
+
+static void linux_wlan_lock(void* vp)
+{
+ PRINT_D(LOCK_DBG,"Locking %p\n",vp);
+ if(vp != NULL)
+ {
+ down((struct semaphore*)vp);
+ }
+ else
+ {
+ PRINT_ER("Failed, mutex is NULL\n");
+ }
+}
+
+static int linux_wlan_lock_timeout(void* vp,NMI_Uint32 timeout)
+{
+ int error = -1;
+ PRINT_D(LOCK_DBG,"Locking %p\n",vp);
+ if(vp != NULL)
+ {
+ error = down_timeout((struct semaphore*)vp, msecs_to_jiffies(timeout));
+ }
+ else
+ {
+ PRINT_ER("Failed, mutex is NULL\n");
+ }
+ return error;
+}
+
+void linux_wlan_unlock(void* vp)
+{
+ PRINT_D(LOCK_DBG,"Unlocking %p\n",vp);
+ if(vp != NULL)
+ {
+ up((struct semaphore*)vp);
+ }
+ else
+ {
+ PRINT_ER("Failed, mutex is NULL\n");
+ }
+}
+
+
+static void linux_wlan_init_mutex(char* lockName, void* plock,int count)
+{
+ mutex_init((struct mutex*)plock);
+ PRINT_D(LOCK_DBG,"Initializing mutex [%s][%p]\n",lockName,plock);
+
+}
+
+static void linux_wlan_deinit_mutex(void* plock)
+{
+ mutex_destroy((struct mutex*)plock);
+}
+
+static void linux_wlan_lock_mutex(void* vp)
+{
+ PRINT_D(LOCK_DBG,"Locking mutex %p\n",vp);
+ if(vp != NULL)
+ {
+ /*
+ if(mutex_is_locked((struct mutex*)vp))
+ {
+ //PRINT_ER("Mutex already locked - %p \n",vp);
+ }
+*/
+ mutex_lock((struct mutex*)vp);
+
+ }else
+ {
+ PRINT_ER("Failed, mutex is NULL\n");
+ }
+}
+
+static void linux_wlan_unlock_mutex(void* vp){
+ PRINT_D(LOCK_DBG,"Unlocking mutex %p\n",vp);
+ if(vp != NULL){
+
+ if(mutex_is_locked((struct mutex*)vp)){
+ mutex_unlock((struct mutex*)vp);
+ }else{
+ //PRINT_ER("Mutex already unlocked - %p\n",vp);
+ }
+
+ }else{
+ PRINT_ER("Failed, mutex is NULL\n");
+ }
+}
+
+
+/*Added by Amr - BugID_4720*/
+static void linux_wlan_init_spin_lock(char* lockName, void* plock,int count)
+{
+ spin_lock_init((spinlock_t*)plock);
+ PRINT_D(SPIN_DEBUG,"Initializing mutex [%s][%p]\n",lockName,plock);
+
+}
+
+static void linux_wlan_deinit_spin_lock(void* plock)
+{
+
+}
+static void linux_wlan_spin_lock(void* vp, unsigned long *flags){
+ unsigned long lflags;
+ PRINT_D(SPIN_DEBUG,"Lock spin %p\n",vp);
+ if(vp != NULL){
+ spin_lock_irqsave((spinlock_t*)vp, lflags);
+ *flags = lflags;
+ }
+ else{
+ PRINT_ER("Failed, spin lock is NULL\n");
+ }
+}
+static void linux_wlan_spin_unlock(void* vp, unsigned long *flags){
+ unsigned long lflags= *flags;
+ PRINT_D(SPIN_DEBUG,"Unlock spin %p\n",vp);
+ if(vp != NULL){
+ spin_unlock_irqrestore((spinlock_t*)vp, lflags);
+ *flags = lflags;
+ }
+ else{
+ PRINT_ER("Failed, spin lock is NULL\n");
+ }
+}
+
+static void linux_wlan_mac_indicate(int flag){
+ /*I have to do it that way becuase there is no mean to encapsulate device pointer
+ as a parameter
+ */
+ linux_wlan_t *pd = g_linux_wlan;
+ int status;
+
+ if (flag == NMI_MAC_INDICATE_STATUS) {
+ pd->oup.wlan_cfg_get_value(WID_STATUS, (unsigned char*)&status, 4);
+ if (pd->mac_status == NMI_MAC_STATUS_INIT) {
+ pd->mac_status = status;
+ linux_wlan_unlock(&pd->sync_event);
+ } else {
+ pd->mac_status = status;
+ }
+
+ if (pd->mac_status == NMI_MAC_STATUS_CONNECT) { /* Connect */
+#if 0
+ /**
+ get the mac and bssid address
+ **/
+ PRINT_D(RX_DBG,"Calling cfg_get to get MAC_ADDR\n");
+ pd->oup.wlan_cfg_get(1, WID_MAC_ADDR, 0);
+ PRINT_D(RX_DBG,"Calling cfg_get to get BSSID\n");
+ pd->oup.wlan_cfg_get(0, WID_BSSID, 1);
+
+ /**
+ get the value
+ **/
+ pd->oup.wlan_cfg_get_value(WID_MAC_ADDR, pd->eth_src_address, 6);
+ pd->oup.wlan_cfg_get_value(WID_BSSID, pd->eth_dst_address, 6);
+
+ PRINT_D(GENERIC_DBG,"Source Address = %s",pd->eth_src_address);
+ PRINT_D(GENERIC_DBG,"Destiation Address = %s",pd->eth_dst_address);
+
+ /**
+ launch ndis
+ **/
+#endif
+ }
+
+ } else if (flag == NMI_MAC_INDICATE_SCAN) {
+ PRINT_D(GENERIC_DBG,"Scanning ...\n");
+
+ }
+
+}
+
+struct net_device * GetIfHandler(uint8_t* pMacHeader)
+{
+ uint8_t *Bssid,*Bssid1;
+ int i =0;
+
+ //frmds = ((pMacHeader[1] & 0x02) >> 1);
+ //if(frmds)
+ {
+ Bssid = pMacHeader+10;
+ Bssid1 = pMacHeader+4;
+ }
+ #if 0
+ else
+ {
+ Bssid = pMacHeader+4;
+ DstAddress = pMacHeader+16;
+ }
+ #endif
+
+ 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))
+ {
+ //printk("Ctx [%x]\n",g_linux_wlan->strInterfaceInfo[i].nmc_netdev);
+ return g_linux_wlan->strInterfaceInfo[i].nmc_netdev;
+ }
+ }
+ printk("Invalide handle\n");
+ for(i=0;i<25;i++)
+ {
+ printk("%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))
+ {
+ printk("Ctx [%p]\n",g_linux_wlan->strInterfaceInfo[i].nmc_netdev);
+ return g_linux_wlan->strInterfaceInfo[i].nmc_netdev;
+ }
+ }
+ printk("\n");
+ return NULL;
+}
+
+int linux_wlan_set_bssid(struct net_device * nmc_netdev,uint8_t * pBSSID)
+{
+ int i = 0;
+ int ret = -1;
+ printk("set bssid on[%p]\n",nmc_netdev);
+ for(i=0;i<g_linux_wlan->u8NoIfcs;i++)
+ {
+ if(g_linux_wlan->strInterfaceInfo[i].nmc_netdev == nmc_netdev)
+ {
+ printk("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 nmc1000_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 nmc1000_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->nmc_netdev)*/)
+ {
+ PRINT_D(TX_DBG,"Waking up queue\n");
+ //netif_wake_queue(pd->nmc_netdev);
+ if(netif_queue_stopped(g_linux_wlan->strInterfaceInfo[0].nmc_netdev))
+ netif_wake_queue(g_linux_wlan->strInterfaceInfo[0].nmc_netdev);
+ if(netif_queue_stopped(g_linux_wlan->strInterfaceInfo[1].nmc_netdev))
+ netif_wake_queue(g_linux_wlan->strInterfaceInfo[1].nmc_netdev);
+ }
+
+ if(ret == NMI_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 == NMI_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* nmc_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(GENERIC_DBG,"Get P2P_CONCURRENCY_FIRMWARE\n");
+ firmware = P2P_CONCURRENCY_FIRMWARE;
+ }
+
+
+
+ if(nic == NULL){
+ PRINT_ER("NIC is NULL\n");
+ goto _fail_;
+ }
+
+ if(&nic->nmc_netdev->dev == NULL){
+ PRINT_ER("&nic->nmc_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 NMI_SDIO
+ if( request_firmware(&nmc_firmware,firmware, &g_linux_wlan->nmc_sdio_func->dev) != 0){
+ PRINT_ER("%s - firmare not available\n",firmware);
+ ret = -1;
+ goto _fail_;
+ }
+#else
+ if( request_firmware(&nmc_firmware,firmware, &g_linux_wlan->nmc_spidev->dev) != 0){
+ PRINT_ER("%s - firmare not available\n",firmware);
+ ret = -1;
+ goto _fail_;
+ }
+#endif
+ g_linux_wlan->nmc_firmware = nmc_firmware; /* Bug 4703 */
+
+_fail_:
+
+ return ret;
+
+}
+
+#ifdef COMPLEMENT_BOOT
+int repeat_power_cycle(perInterface_wlan_t* nic);
+#endif
+
+static int linux_wlan_start_firmware(perInterface_wlan_t* nic){
+
+ static int timeout = 5;
+ int ret = 0;
+ /* start firmware */
+ PRINT_D(INIT_DBG,"Starting Firmware ...\n");
+ ret = g_linux_wlan->oup.wlan_start();
+ if(ret < 0){
+ PRINT_ER("Failed to start Firmware\n");
+ goto _fail_;
+ }
+#if defined(PLAT_AML8726_M3)//[[ johnny : because of dummy irq
+ _available_irq_ready = 1;
+#endif
+
+ /* wait for mac ready */
+ PRINT_D(INIT_DBG,"Waiting for Firmware to get ready ...\n");
+ if( (ret = linux_wlan_lock_timeout(&g_linux_wlan->sync_event,5000)) )
+ {
+#ifdef COMPLEMENT_BOOT
+ #if defined(PLAT_ALLWINNER_A20) || defined(PLAT_ALLWINNER_A23) || defined(PLAT_ALLWINNER_A31)
+
+ if(timeout--)
+ {
+ printk("repeat power cycle[%d]",timeout);
+ ret = repeat_power_cycle(nic);
+ }
+ else
+ {
+ timeout = 5;
+ ret = -1;
+ goto _fail_;
+ }
+ #endif
+#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->nmc_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->nmc_firmware->data, g_linux_wlan->nmc_firmware->size);
+ if(ret < 0){
+ goto _FAIL_;
+ }
+
+ /* Freeing FW buffer */
+ PRINT_D(INIT_DBG,"Freeing FW buffer ...\n");
+ PRINT_D(GENERIC_DBG,"Releasing firmware\n");
+ release_firmware(g_linux_wlan->nmc_firmware);
+ g_linux_wlan->nmc_firmware = NULL;
+
+ PRINT_D(INIT_DBG,"Download Succeeded \n");
+
+_FAIL_:
+ return ret;
+}
+
+
+/* startup configuration - could be changed later using iconfig*/
+static int linux_wlan_init_test_config(struct net_device *dev, linux_wlan_t* p_nic){
+
+ unsigned char c_val[64];
+ #ifndef STATIC_MACADDRESS
+ unsigned char mac_add[] = {0x00, 0x80, 0xC2, 0x5E, 0xa2, 0xff};
+ #endif
+ unsigned int chipid = 0;
+
+ /*BugID_5077*/
+ struct NMI_WFI_priv *priv;
+ tstrNMI_WFIDrv * pstrWFIDrv;
+
+ PRINT_D(TX_DBG,"Start configuring Firmware\n");
+ #ifndef STATIC_MACADDRESS
+ //get_random_bytes(&mac_add[5], 1);
+ #endif
+ priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
+ pstrWFIDrv = (tstrNMI_WFIDrv *)priv->hNMIWFIDrv;
+ PRINT_D(GENERIC_DBG, "Host = %x\n",(NMI_Uint32)pstrWFIDrv);
+
+ printk("MAC address is : %02x-%02x-%02x-%02x-%02x-%02x\n", mac_add[0],mac_add[1],mac_add[2],mac_add[3],mac_add[4],mac_add[5]);
+ chipid = nmi_get_chipid(0);
+
+
+ if(g_linux_wlan->oup.wlan_cfg_set == NULL)
+ {
+ printk("Null p[ointer\n");
+ goto _fail_;
+ }
+
+ *(int*)c_val = (NMI_Uint32)pstrWFIDrv;
+
+ if (!g_linux_wlan->oup.wlan_cfg_set(1, WID_SET_DRV_HANDLER, c_val, 4, 0,0))
+ goto _fail_;
+
+ /*to tell fw that we are going to use PC test - NMI 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_;
+
+ if((chipid & 0xfff) > 0xd0)
+ c_val[0] = 1; /* Enable N */
+ else
+ c_val[0] = 0; /* Disable 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_;
+
+
+ if(nmi_get_chipid(NMI_FALSE) >= 0x1002a0)
+ c_val[0] = 7; /* Limit TX rate below MCS-7 for NMC1000F0. Should be changed in to 7 in NMC1002. */
+ else
+ c_val[0] = 6;
+
+ 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, 0,0))
+ goto _fail_;
+
+ /*Adde by Amr - BugID 4707*/
+ /*A mandatory restart mac has to be done initially.*/
+ /*So wid reset is sent with startup configrations*/
+
+ c_val[0] = 1;
+
+ if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_RESET, c_val, 1, 1,(NMI_Uint32)pstrWFIDrv))
+ goto _fail_;
+
+
+ return 0;
+
+_fail_:
+ return -1;
+}
+
+
+/**************************/
+void nmc1000_wlan_deinit(linux_wlan_t *nic) {
+
+ if(g_linux_wlan->nmc1000_initialized)
+ {
+
+ PRINT_D(INIT_DBG,"Deinitializing nmc1000 ...\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 nmi_bus_set_default_speed\n");
+#else
+ nmi_bus_set_default_speed();
+#endif
+
+ PRINT_D(INIT_DBG,"Disabling IRQ\n");
+ #if (!defined NMI_SDIO) || (defined NMI_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 NMI Wlan\n");
+ nmi_wlan_deinit(nic);
+#if (defined NMI_SDIO) && (!defined NMI_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 nmc1000 is not initialized */
+ g_linux_wlan->nmc1000_initialized = 0;
+
+ PRINT_D(INIT_DBG,"nmc1000 deinitialization Done\n");
+
+ }else{
+ PRINT_D(INIT_DBG,"nmc1000 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(nmi_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 NMI_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 NMI_FULLY_HOSTING_AP
+ /* incase of Fully hosted AP, all non cfg pkts are processed here*/
+ nwi->net_func.rx_indicate = NMI_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
+
+ /* 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);
+
+ /* create tx task */
+ PRINT_D(INIT_DBG,"Creating kthread for transmission\n");
+ g_linux_wlan->txq_thread = kthread_run(linux_wlan_txq_task,(void*)g_linux_wlan,"K_TXQ_TASK");
+ if(g_linux_wlan->txq_thread == 0){
+ PRINT_ER("couldn't create TXQ thread\n");
+ ret = -ENOBUFS;
+ goto _fail_2;
+ }
+#ifdef DEBUG_MODE
+ PRINT_D(INIT_DBG,"Creating kthread for Debugging\n");
+ g_linux_wlan->txq_thread = kthread_run(DebuggingThreadTask,(void*)g_linux_wlan,"DebugThread");
+ if(g_linux_wlan->txq_thread == 0){
+ PRINT_ER("couldn't create TXQ thread\n");
+ ret = -ENOBUFS;
+ goto _fail_2;
+ }
+#endif
+ /* wait for TXQ task to start. */
+ linux_wlan_lock(&g_linux_wlan->txq_thread_started);
+
+ return 0;
+
+ _fail_2:
+ /*De-Initialize 2nd thread*/
+ g_linux_wlan->close = 1;
+ linux_wlan_unlock(&g_linux_wlan->rxq_event);
+ kthread_stop(g_linux_wlan->rxq_thread);
+
+ _fail_1:
+ #if(RX_BH_TYPE == RX_BH_KTHREAD)
+ /*De-Initialize 1st thread*/
+ g_linux_wlan->close = 1;
+ linux_wlan_unlock(&g_linux_wlan->rx_sem);
+ kthread_stop(g_linux_wlan->rx_bh_thread);
+ _fail_:
+ #endif
+ g_linux_wlan->close = 0;
+ return ret;
+}
+
+static void wlan_deinitialize_threads(linux_wlan_t* nic){
+
+ g_linux_wlan->close = 1;
+ PRINT_D(INIT_DBG,"Deinitializing Threads\n");
+ if(&g_linux_wlan->rxq_event != NULL)
+ linux_wlan_unlock(&g_linux_wlan->rxq_event);
+
+
+ if(g_linux_wlan->rxq_thread != NULL){
+ kthread_stop(g_linux_wlan->rxq_thread);
+ g_linux_wlan->rxq_thread = NULL;
+ }
+
+
+ if(&g_linux_wlan->txq_event != NULL)
+ linux_wlan_unlock(&g_linux_wlan->txq_event);
+
+
+ if(g_linux_wlan->txq_thread != NULL){
+ kthread_stop(g_linux_wlan->txq_thread);
+ g_linux_wlan->txq_thread = NULL;
+ }
+
+ #if(RX_BH_TYPE == RX_BH_KTHREAD)
+ if(&g_linux_wlan->rx_sem != NULL)
+ linux_wlan_unlock(&g_linux_wlan->rx_sem);
+
+ if(g_linux_wlan->rx_bh_thread != NULL){
+ kthread_stop(g_linux_wlan->rx_bh_thread);
+ g_linux_wlan->rx_bh_thread= NULL;
+ }
+ #endif
+}
+
+#ifdef STATIC_MACADDRESS
+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;
+
+ /* change to KERNEL_DS address limit */
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ do {
+#if defined(PLAT_CLM9722) // rachel
+ fp = filp_open("/etc/wlan", O_WRONLY, 0640);
+#else
+ fp = filp_open("/data/wlan", O_WRONLY, 0640);
+#endif
+ 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 */
+#if defined(PLAT_CLM9722) // rachel
+ fp = filp_open("/etc/wlan", O_WRONLY|O_CREAT, 0640);
+#else
+ fp = filp_open("/data/wlan", O_WRONLY|O_CREAT, 0640);
+#endif
+ if (!fp) {
+ ret = -1;
+ goto exit;
+ }
+
+ /* Write buf to file */
+ fp->f_op->write(fp, mac_add, 6, &pos);
+
+ }else{
+ /* read file to buf */
+ fp->f_op->read(fp, mac_add, 6, &pos);
+ }
+ }while(0);
+
+exit:
+ if (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 10
+
+uint8_t nmc1000_prepare_11b_core(nmi_wlan_inp_t *nwi, nmi_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);
+ nmi_wlan_deinit(nic);
+ sdio_unregister_driver(&nmc_bus);
+
+ linux_wlan_device_detection(0);
+ linux_wlan_device_power(0);
+
+ mdelay(100);
+
+ linux_wlan_device_power(1);
+ linux_wlan_device_detection(1);
+
+ sdio_register_driver(&nmc_bus);
+
+ while(!probe)
+ {
+ msleep(100);
+ }
+ probe = 0;
+ g_linux_wlan->nmc_sdio_func= local_sdio_func;
+ linux_to_wlan(nwi,nic);
+ nmi_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;
+ nmi_wlan_inp_t nwi;
+ nmi_wlan_oup_t nwo;
+ sdio_unregister_driver(&nmc_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(&nmc_bus);
+
+ //msleep(1000);
+ while(!probe)
+ {
+ msleep(100);
+ }
+ probe = 0;
+ g_linux_wlan->nmc_sdio_func= local_sdio_func;
+ linux_to_wlan(&nwi,g_linux_wlan);
+ ret = nmi_wlan_init(&nwi, &nwo);
+
+ g_linux_wlan->mac_status = NMI_MAC_STATUS_INIT;
+ #if (defined NMI_SDIO) && (!defined NMI_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 nmc1000_wlan_init(struct net_device *dev,perInterface_wlan_t* p_nic)
+{
+ nmi_wlan_inp_t nwi;
+ nmi_wlan_oup_t nwo;
+ perInterface_wlan_t* nic = p_nic;
+ int ret = 0;
+
+ if(!g_linux_wlan->nmc1000_initialized){
+ g_linux_wlan->mac_status = NMI_MAC_STATUS_INIT;
+ g_linux_wlan->close = 0;
+ g_linux_wlan->nmc1000_initialized = 0;
+#if defined(PLAT_AML8726_M3)
+ _available_irq_ready = 0;
+#endif
+ wlan_init_locks(g_linux_wlan);
+
+#ifdef STATIC_MACADDRESS
+ nmi_mac_thread = kthread_run(linux_wlan_read_mac_addr,NULL,"nmi_mac_thread");
+ if(nmi_mac_thread < 0){
+ PRINT_ER("couldn't create Mac addr thread\n");
+ }
+#endif
+
+ linux_to_wlan(&nwi,g_linux_wlan);
+
+ ret = nmi_wlan_init(&nwi, &nwo);
+ if (ret < 0) {
+ PRINT_ER("Initializing NMI_Wlan FAILED\n");
+ goto _fail_locks_;
+ }
+ memcpy(&g_linux_wlan->oup, &nwo, sizeof(nmi_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");
+ goto _fail_nmi_wlan_;
+ }
+
+#if (defined NMI_SDIO) && (defined COMPLEMENT_BOOT)
+ if(nmc1000_prepare_11b_core(&nwi,&nwo,g_linux_wlan)){
+ PRINT_ER("11b Core is not ready\n");
+ goto _fail_threads_;
+ }
+#endif
+
+#if (!defined NMI_SDIO) || (defined NMI_SDIO_IRQ_GPIO)
+ if(init_irq(g_linux_wlan)){
+ PRINT_ER("couldn't initialize IRQ\n");
+ ret = -EIO;
+ goto _fail_threads_;
+ }
+#endif
+
+#if (defined NMI_SDIO) && (!defined NMI_SDIO_IRQ_GPIO)
+ enable_sdio_interrupt();
+#endif
+
+ if(linux_wlan_get_firmware(nic)){
+ PRINT_ER("Can't get firmware \n");
+ goto _fail_threads_;
+ }
+
+//[[ johnny
+#ifdef FW_VERSION_VERIFICATION
+ if ( check_firmware_version( nic->iftype,
+ __DRIVER_VERSION__,
+ g_linux_wlan->nmc_firmware? g_linux_wlan->nmc_firmware->size:0 )
+ != 0 )
+ goto _fail_threads_;
+#endif
+//]]
+
+ /*Download firmware*/
+ ret = linux_wlan_firmware_download(g_linux_wlan);
+ if(ret < 0){
+ PRINT_ER("Failed to download firmware\n");
+ goto _fail_threads_;
+ }
+
+ /* Start firmware*/
+ ret = linux_wlan_start_firmware(nic);
+ if(ret < 0){
+ PRINT_ER("Failed to start firmware\n");
+ goto _fail_threads_;
+ }
+
+ nmi_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';
+ printk("***** 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");
+ goto _fail_threads_;
+ }
+
+ g_linux_wlan->nmc1000_initialized = 1;
+ return 0; /*success*/
+
+_fail_threads_:
+ wlan_deinitialize_threads(g_linux_wlan);
+
+#if (!defined NMI_SDIO) || (defined NMI_SDIO_IRQ_GPIO)
+ deinit_irq(g_linux_wlan);
+
+#endif
+_fail_nmi_wlan_:
+ nmi_wlan_deinit(g_linux_wlan);
+_fail_locks_:
+ wlan_deinit_locks(g_linux_wlan);
+ PRINT_ER("WLAN Iinitialization FAILED\n");
+ }else{
+ PRINT_D(INIT_DBG,"nmc1000 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 NMI_WFI_frame_register(struct wiphy *wiphy,struct net_device *dev,
+ u16 frame_type, bool reg);
+
+/* This fn is called, when this device is setup using ifconfig */
+#if !defined (NM73131_0_BOARD)
+int mac_open(struct net_device *ndev){
+ perInterface_wlan_t* nic;
+ /*BugID_5213*/
+ /*No need for setting mac address here anymore,*/
+ /*Just set it in init_test_config()*/
+ unsigned char mac_add[ETH_ALEN] ={0};
+ int status;
+ int ret = 0;
+ int i = 0;
+ struct NMI_WFI_priv* priv;
+
+ printk("MAC OPEN[%p]\n",ndev);
+
+
+
+ nic = netdev_priv(ndev);
+ priv = wiphy_priv(nic->nmc_netdev->ieee80211_ptr->wiphy);
+ //if (once == 1) return 0;
+ //linux_wlan_lock(&close_exit_sync);
+
+ #ifdef USE_WIRELESS
+ ret = NMI_WFI_InitHostInt(ndev);
+ if(ret < 0)
+ {
+ PRINT_ER("Failed to initialize host interface\n");
+
+ return ret;
+ }
+ #endif
+
+ /*initialize platform*/
+ printk("*** re-init ***\n");
+ ret = nmc1000_wlan_init(ndev, nic);
+ if(ret < 0)
+ {
+ PRINT_ER("Failed to initialize nmc1000\n");
+ NMI_WFI_DeInitHostInt(ndev);
+ //linux_wlan_unlock(&close_exit_sync);
+ return ret;
+ }
+ Set_machw_change_vir_if(NMI_FALSE);
+
+ //else
+ //{
+ /*BugID_5077*/
+ /*host_int_set_wfi_drv_handler((NMI_Uint32)priv->hNMIWFIDrv);
+ host_int_set_MacAddress(priv->hNMIWFIDrv, mac_add);
+
+ g_linux_wlan->nmc1000_initialized = 1;
+ once++;
+ }*/
+
+
+
+ status = host_int_get_MacAddress(priv->hNMIWFIDrv, mac_add);
+ PRINT_D(GENERIC_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].nmc_netdev)
+ {
+ memcpy(g_linux_wlan->strInterfaceInfo[i].aSrcAddress, mac_add, ETH_ALEN);
+ //linux_wlan_set_bssid(ndev,g_linux_wlan->strInterfaceInfo[i].aSrcAddress);
+ g_linux_wlan->strInterfaceInfo[i].drvHandler = (NMI_Uint32)priv->hNMIWFIDrv;
+ //change the MSB
+ //nic->strInterfaceInfo[i].aSrcAddress[0] = nic->strInterfaceInfo[i].aSrcAddress[0] + i*2;
+ 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");
+ //linux_wlan_unlock(&close_exit_sync);
+ return -EINVAL;
+ }
+ /* Start the network interface queue for this device */
+ PRINT_D(INIT_DBG,"Starting netifQ\n");
+ //netif_start_queue(ndev); ma
+ //enable interrupts
+ //enable_irq(g_linux_wlan->dev_irq_num);
+ //if(!once)
+ //host_int_set_wfi_drv_handler((NMI_Uint32)priv->hNMIWFIDrv);
+ //host_int_set_wfi_drv_handler((NMI_Uint32)priv->hNMIWFIDrv_2);
+
+ NMI_WFI_frame_register(nic->nmc_netdev->ieee80211_ptr->wiphy,nic->nmc_netdev,
+ nic->g_struct_frame_reg[0].frame_type,nic->g_struct_frame_reg[0].reg);
+
+ NMI_WFI_frame_register(nic->nmc_netdev->ieee80211_ptr->wiphy,nic->nmc_netdev,
+ nic->g_struct_frame_reg[1].frame_type,nic->g_struct_frame_reg[1].reg);
+ netif_wake_queue(ndev);
+
+ //linux_wlan_lock(&close_exit_sync);
+ g_linux_wlan->open_ifcs++;
+ nic->mac_opened=1;
+ return 0;
+}
+#else
+int mac_open(struct net_device *ndev)
+{
+
+ linux_wlan_t* nic;
+ nic = netdev_priv(ndev);
+
+ /*initialize platform*/
+ if(nmc1000_wlan_init(nic)){
+ PRINT_ER("Failed to initialize platform\n");
+ return 1;
+ }
+ /* Start the network interface queue for this device */
+ PRINT_D(INIT_DBG,"Starting netifQ\n");
+ netif_start_queue(ndev);
+// linux_wlan_lock(&close_exit_sync);
+ return 0;
+}
+#endif
+
+struct net_device_stats *mac_stats(struct net_device *dev)
+{
+ perInterface_wlan_t* nic= netdev_priv(dev);
+
+
+ return &nic->netstats;
+}
+
+// Setup the multicast filter
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
+static void nmi_set_multicast_list(struct net_device *dev)
+{
+
+ struct netdev_hw_addr *ha;
+ struct NMI_WFI_priv* priv;
+ tstrNMI_WFIDrv * pstrWFIDrv;
+ int i=0;
+ priv= wiphy_priv(dev->ieee80211_ptr->wiphy);
+ pstrWFIDrv = (tstrNMI_WFIDrv *)priv->hNMIWFIDrv;
+
+
+ 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) > NMI_MULTICAST_TABLE_SIZE)
+ {
+ PRINT_D(INIT_DBG,"Disable multicast filter, retrive all multicast packets\n");
+ // get all multicast packets
+ host_int_setup_multicast_filter((NMI_WFIDrvHandle)pstrWFIDrv, NMI_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((NMI_WFIDrvHandle)pstrWFIDrv, NMI_TRUE, 0);
+ return;
+ }
+
+ /* Store all of the multicast addresses in the hardware filter */
+ netdev_for_each_mc_addr(ha, dev)
+ {
+ NMI_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((NMI_WFIDrvHandle)pstrWFIDrv, NMI_TRUE, (dev->mc.count));
+
+ return;
+
+}
+
+#else
+
+static void nmi_set_multicast_list(struct net_device *dev)
+{
+ // BIG Warning, Beware : Uncompiled, untested...
+ struct dev_mc_list *mc_ptr;
+ int i=0;
+
+ if (!dev)
+ return;
+
+ PRINT_D(INIT_DBG,"Setting Multicast List. \n");
+ printk("dev->mc_count = %d\n",dev->mc_count);
+
+ if (dev->flags & IFF_PROMISC)
+ {
+ /* Normally, we should configure the chip to retrive all packets
+ * but we don't wanna support this right now */
+ // TODO: add promiscuous mode support
+ PRINT_D(INIT_DBG,"Set promiscuous mode ON, retrive all packets \n");
+ return;
+ }
+
+ /* If there's more addresses than we handle, get all multicast
+ packets and sort them out in software. */
+ if ( (dev->flags & IFF_ALLMULTI) ||( dev->mc_count > NMI_MULTICAST_TABLE_SIZE) )
+ {
+ PRINT_D(INIT_DBG,"Disable multicast filter, retrive all multicast packets\n");
+ host_int_setup_multicast_filter((NMI_WFIDrvHandle)gWFiDrvHandle, NMI_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((NMI_WFIDrvHandle)gWFiDrvHandle, NMI_TRUE, 0);
+ return;
+ }
+
+ /* Store all of the multicast addresses in the hardware filter */
+
+ for (mc_ptr = dev->mc_list; mc_ptr; mc_ptr = mc_ptr->next , i++)
+ {
+ NMI_memcpy(gau8MulticastMacAddrList[i], mc_ptr->dmi_addr, ETH_ALEN)
+ i++;
+ }
+
+ host_int_setup_multicast_filter((NMI_WFIDrvHandle)gWFiDrvHandle, NMI_TRUE, (dev->mc_count));
+
+}
+#endif
+
+static void linux_wlan_tx_complete(void* priv, int status){
+
+ struct tx_complete_data* pv_data = (struct tx_complete_data*)priv;
+ if(status == 1){
+ PRINT_D(TX_DBG,"Packet sent successfully - Size = %d - Address = %p - SKB = %p\n",pv_data->size,pv_data->buff, pv_data->skb);
+ } else {
+ PRINT_D(TX_DBG,"Couldn't send packet - Size = %d - Address = %p - SKB = %p\n",pv_data->size,pv_data->buff, pv_data->skb);
+ }
+ /* Free the SK Buffer, its work is done */
+ dev_kfree_skb(pv_data->skb);
+ linux_wlan_free(pv_data);
+}
+
+int mac_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+ perInterface_wlan_t* nic;
+ struct tx_complete_data* tx_data = NULL;
+ int QueueCount;
+ //char* saddr,*daddr,*pu8UdpBuffer;
+ char *pu8UdpBuffer;
+ struct iphdr *ih;
+ struct ethhdr * eth_h;
+// struct ethhdr *eth;
+// char* ethsaddr,*ethdaddr;
+// int i;
+ //char* TestBuff;
+ //printk("mac xmit on [%x]\n",ndev);
+ PRINT_D(INT_DBG,"\n========\n IntUH: %d - IntBH: %d - IntCld: %d \n========\n",int_rcvdU,int_rcvdB,int_clrd);
+ nic = netdev_priv(ndev);
+
+ PRINT_D(TX_DBG,"Sending packet just received from TCP/IP\n");
+
+ /* Stop the network interface queue */
+ // netif_stop_queue(ndev);
+
+ if(skb->dev != ndev){
+ PRINT_ER("Packet not destined to this device\n");
+ return 0;
+ }
+
+ /* allocate memory for the frame - there is no need to allocate the fixed packet size 1496.
+ * just allocat memory with the length of the packet received - also don't put any constraint
+ * on the size of the packet to be received because this restriction is already handled inside firmware.
+ */
+/*
+ if(skb->len > 1496){
+ PRINT_ER("Unable to handle this large packet - Size = %d\n",skb->len);
+ }
+
+*/
+
+ 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)
+ {
+ printk("EAPOL transmitted\n");
+ }
+
+ /*get source and dest ip addresses*/
+ ih = (struct iphdr *)(skb->data+sizeof(struct ethhdr));
+ //saddr = &ih->saddr;
+ //daddr = &ih->daddr;
+ //NMI_PRINTF("Source IP = %d:%d:%d:%d \n",saddr[0],saddr[1],
+ // saddr[2],saddr[3]);
+// NMI_PRINTF("Dest IP = %d:%d:%d:%d \n",daddr[0],daddr[1],
+ // daddr[2],daddr[3]);
+
+ 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);
+
+ /*eth = (struct ethhdr *)(skb->data);
+
+ ethsaddr = &eth->h_source;
+ ethdaddr = &eth->h_dest;
+
+ NMI_PRINTF("Source MAC = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x \n",ethsaddr[0],ethsaddr[1],
+ ethsaddr[2],ethsaddr[3],ethsaddr[4],ethsaddr[5]);
+ NMI_PRINTF("Dest MAC = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x \n",ethdaddr[0],ethdaddr[1],
+ ethdaddr[2],ethdaddr[3],ethdaddr[4],ethdaddr[5]);*/
+
+ //NMI_PRINTF("sending pkt \n");
+
+ // NMI_PRINTF("skb->data[12] = %2x, skb->data[13] = %2x \n");
+ /*TestBuff = (char*)(skb->data + sizeof(struct ethhdr));
+
+ for(i = 0; i < 30; i++)
+ {
+ if(i < skb->len)
+ {
+ NMI_PRINTF("TestBuff[%d] = %2x \n", i, TestBuff[i]);
+ }
+ }*/
+
+ /* 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 NMI_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 = NMI_Xmit_data((void*)tx_data, HOST_TO_WLAN);
+ #endif //NMI_FULLY_HOSTING_AP
+
+
+ if(QueueCount > FLOW_CONTROL_UPPER_THRESHOLD)
+ {
+ // printk("Stopping queue\n");
+ //netif_stop_queue(ndev);
+ netif_stop_queue(g_linux_wlan->strInterfaceInfo[0].nmc_netdev);
+ netif_stop_queue(g_linux_wlan->strInterfaceInfo[1].nmc_netdev);
+
+ }
+
+
+ /* Wake up the network interface queue */
+ //netif_wake_queue(ndev);
+
+
+ return 0;
+}
+
+
+int mac_close(struct net_device *ndev)
+{
+ struct NMI_WFI_priv* priv;
+ perInterface_wlan_t* nic;
+ tstrNMI_WFIDrv * pstrWFIDrv;
+
+ nic = netdev_priv(ndev);
+
+ priv = wiphy_priv(nic->nmc_netdev->ieee80211_ptr->wiphy);
+ pstrWFIDrv = (tstrNMI_WFIDrv *)priv->hNMIWFIDrv;
+
+
+
+ PRINT_D(GENERIC_DBG,"Mac close\n");
+ if((g_linux_wlan->open_ifcs)>0)
+ {
+ g_linux_wlan->open_ifcs--;
+ }
+ else
+ {
+ printk("ERROR: MAC close called while number of opened interfaces is zero\n");
+ return 0;
+ }
+
+
+
+
+ //int i = 0;
+/* for(i=0;i<g_linux_wlan->u8NoIfcs;i++)
+ {
+ if(g_linux_wlan->strInterfaceInfo[i].nmc_netdev != NULL)
+ {
+ // Stop the network interface queue
+ netif_stop_queue(g_linux_wlan->strInterfaceInfo[i].nmc_netdev);
+
+#ifdef USE_WIRELESS
+ NMI_WFI_DeInitHostInt(g_linux_wlan->strInterfaceInfo[i].nmc_netdev);
+#endif
+ }
+
+ }*/
+ if(nic->nmc_netdev != NULL)
+ {
+ // Stop the network interface queue
+ netif_stop_queue(nic->nmc_netdev);
+
+#ifdef USE_WIRELESS
+ NMI_WFI_DeInitHostInt(nic->nmc_netdev);
+#endif
+ }
+
+
+
+ if(g_linux_wlan->open_ifcs==0)
+ {
+ PRINT_D(GENERIC_DBG,"Deinitializing nmc1000\n");
+ g_linux_wlan->close = 1;
+ nmc1000_wlan_deinit(g_linux_wlan);
+ #ifdef USE_WIRELESS
+ #ifdef NMI_AP_EXTERNAL_MLME
+ NMI_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){
+
+ NMI_Uint8 *buff= NULL;
+ NMI_Sint8 rssi;
+ NMI_Uint32 size=0,length=0;
+ perInterface_wlan_t* nic;
+ struct NMI_WFI_priv* priv;
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+
+
+
+ //struct iwreq *wrq = (struct iwreq *) req; // tony moved to case SIOCSIWPRIV
+ #ifdef USE_WIRELESS
+ nic = netdev_priv(ndev);
+
+ if(!g_linux_wlan->nmc1000_initialized)
+ return 0;
+
+ #endif
+
+ switch(cmd){
+ // [[ added by tony for SIOCDEVPRIVATE
+ case SIOCDEVPRIVATE+1:
+ {
+ android_wifi_priv_cmd priv_cmd;
+
+ PRINT_INFO(GENERIC_DBG, "in SIOCDEVPRIVATE+1\n");
+
+ if (copy_from_user(&priv_cmd, req->ifr_data, sizeof(android_wifi_priv_cmd))) {
+ s32Error = -EFAULT;
+ goto done;
+ }
+
+ buff = kmalloc(priv_cmd.total_len, GFP_KERNEL);
+ if (!buff)
+ {
+ s32Error = -ENOMEM;
+ goto done;
+ }
+
+ if (copy_from_user(buff, priv_cmd.buf, priv_cmd.total_len)) {
+ s32Error = -EFAULT;
+ goto done;
+ }
+
+ PRINT_INFO(GENERIC_DBG, "%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, buff, req->ifr_name);
+
+ if (strnicmp(buff, "SCAN-ACTIVE", strlen("SCAN-ACTIVE")) == 0) {
+ PRINT_INFO(GENERIC_DBG, "%s, SCAN-ACTIVE command\n", __FUNCTION__);
+ }else if (strnicmp(buff, "SCAN-PASSIVE", strlen("SCAN-PASSIVE")) == 0) {
+ PRINT_INFO(GENERIC_DBG, "%s, SCAN-PASSIVE command\n", __FUNCTION__);
+ }else if (strnicmp(buff, "RXFILTER-START", strlen("RXFILTER-START")) == 0) {
+ PRINT_INFO(GENERIC_DBG, "%s, RXFILTER-START command\n", __FUNCTION__);
+ }else if (strnicmp(buff, "RXFILTER-STOP", strlen("RXFILTER-STOP")) == 0) {
+ PRINT_INFO(GENERIC_DBG, "%s, RXFILTER-STOP command\n", __FUNCTION__);
+ }else if (strnicmp(buff, "RXFILTER-ADD", strlen("RXFILTER-ADD")) == 0) {
+ int filter_num = *(buff + strlen("RXFILTER-ADD") + 1) - '0';
+ PRINT_INFO(GENERIC_DBG, "%s, RXFILTER-ADD command, filter_num=%d\n", __FUNCTION__, filter_num);
+ }else if (strnicmp(buff, "RXFILTER-REMOVE", strlen("RXFILTER-REMOVE")) == 0) {
+ int filter_num = *(buff + strlen("RXFILTER-REMOVE") + 1) - '0';
+ PRINT_INFO(GENERIC_DBG, "%s, RXFILTER-REMOVE command, filter_num=%d\n", __FUNCTION__, filter_num);
+ }else if (strnicmp(buff, "BTCOEXSCAN-START", strlen("BTCOEXSCAN-START")) == 0) {
+ PRINT_INFO(GENERIC_DBG, "%s, BTCOEXSCAN-START command\n", __FUNCTION__);
+ }else if (strnicmp(buff, "BTCOEXSCAN-STOP", strlen("BTCOEXSCAN-STOP")) == 0) {
+ PRINT_INFO(GENERIC_DBG, "%s, BTCOEXSCAN-STOP command\n", __FUNCTION__);
+ }else if (strnicmp(buff, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0) {
+ PRINT_INFO(GENERIC_DBG, "%s, BTCOEXMODE command\n", __FUNCTION__);
+ }else if (strnicmp(buff, "SETBAND", strlen("SETBAND")) == 0) {
+ uint band = *(buff + strlen("SETBAND") + 1) - '0';
+ PRINT_INFO(GENERIC_DBG, "%s, SETBAND command, band=%d\n", __FUNCTION__, band);
+ }else if (strnicmp(buff, "GETBAND", strlen("GETBAND")) == 0) {
+ PRINT_INFO(GENERIC_DBG, "%s, GETBAND command\n", __FUNCTION__);
+ }else if (strnicmp(buff, "COUNTRY", strlen("COUNTRY")) == 0) {
+ char *country_code = buff + strlen("COUNTRY") + 1;
+ PRINT_INFO(GENERIC_DBG, "%s, COUNTRY command, country_code=%s\n", __FUNCTION__, country_code);
+ }else {
+ PRINT_INFO(GENERIC_DBG, "%s, Unknown command\n", __FUNCTION__);
+ }
+ }break;
+ // ]] 2013-06-24
+ case SIOCSIWPRIV:
+ {
+ struct iwreq *wrq = (struct iwreq *) req; // added by tony
+
+ size = wrq->u.data.length;
+
+ if (size&& wrq->u.data.pointer)
+ {
+ buff = kmalloc(size, GFP_KERNEL);
+ if (!buff)
+ {
+ s32Error = -ENOMEM;
+ goto done;
+ }
+
+ if (copy_from_user
+ (buff, wrq->u.data.pointer,
+ wrq->u.data.length))
+ {
+ s32Error = -EFAULT;
+ goto done;
+ }
+
+ if(strnicmp(buff,"RSSI",length) == 0)
+ {
+
+ #ifdef USE_WIRELESS
+ priv = wiphy_priv(nic->nmc_netdev->ieee80211_ptr->wiphy);
+ s32Error = host_int_get_rssi(priv->hNMIWFIDrv, &(rssi));
+ if(s32Error)
+ PRINT_ER("Failed to send get rssi param's message queue ");
+ #endif
+ PRINT_INFO(GENERIC_DBG,"RSSI :%d\n",rssi);
+
+ /*Rounding up the rssi negative value*/
+ rssi+=5;
+
+ snprintf(buff, size, "rssi %d", rssi);
+
+ if (copy_to_user(wrq->u.data.pointer, buff, size)) {
+ PRINT_ER("%s: failed to copy data to user buffer\n", __FUNCTION__);
+ s32Error = -EFAULT;
+ goto done;
+ }
+ }
+ }
+ }
+ break;
+ default:
+ {
+ PRINT_INFO(GENERIC_DBG,"Command - %d - has been received\n",cmd);
+ s32Error = -EOPNOTSUPP;
+ goto done;
+ }
+ }
+
+done:
+
+ if(buff != NULL)
+ {
+ kfree(buff);
+ }
+
+ return s32Error;
+}
+
+void frmw_to_linux(uint8_t *buff, uint32_t size,uint32_t pkt_offset){
+
+ unsigned int frame_len = 0;
+ int stats;
+ unsigned char* buff_to_send = NULL;
+ struct sk_buff *skb;
+ //char *saddr,*daddr;
+ char*pu8UdpBuffer;
+ struct iphdr *ih;
+ struct net_device* nmc_netdev;
+ perInterface_wlan_t *nic;
+// static int once = 1;
+// int i;
+ nmc_netdev = GetIfHandler(buff);
+ if(nmc_netdev == NULL)
+ return;
+ buff += pkt_offset;
+ //AdjustDstAddr(nmc_netdev,buff);
+
+ nic = netdev_priv(nmc_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 || nmc_netdev == NULL){
+ PRINT_ER("nmc_netdev in g_linux_wlan is NULL");
+ }
+ skb->dev = nmc_netdev;
+
+ if(skb->dev == NULL){
+ PRINT_ER("skb->dev is NULL\n");
+ }
+
+ /*
+ for(i=0;i<40;i++)
+ {
+ if(i<frame_len)
+ NMI_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);
+
+ //NMI_PRINTF("After MEM_CPY\n");
+
+ //nic = netdev_priv(nmc_netdev);
+
+#ifdef USE_WIRELESS
+ /* if(nic->monitor_flag)
+ {
+ NMI_WFI_monitor_rx(nic->nmc_netdev,skb);
+ return;
+ }*/
+#endif
+ skb->protocol = eth_type_trans(skb, nmc_netdev);
+ /*get source and dest ip addresses*/
+ ih = (struct iphdr *)(skb->data+sizeof(struct ethhdr));
+ //saddr = &ih->saddr;
+ //daddr = &ih->daddr;
+ //NMI_PRINTF("[REC]Source IP = %.2x:%.2x:%.2x:%.2x",saddr[0],saddr[1],
+ //saddr[2],saddr[3]);
+ //NMI_PRINTF("[REC]Dest IP = %.2x:%.2x:%.2x:%.2x",daddr[0],daddr[1],
+ // daddr[2],daddr[3]);
+ //NMI_PRINTF("Protocol = %4x\n",skb->protocol);
+ pu8UdpBuffer = (char*)ih + sizeof(struct iphdr);
+ //printk("Port No = %d,%d\n",pu8UdpBuffer[1],pu8UdpBuffer[3]);
+ if(buff_to_send[35] == 67 && buff_to_send[37] == 68)
+ {
+ PRINT_D(RX_DBG,"DHCP Message received\n");
+ }
+
+ /* Send the packet to the stack by giving it to the bridge */
+ nic->netstats.rx_packets++;
+ nic->netstats.rx_bytes+=frame_len;
+ stats = netif_rx(skb);
+ //printk("netif_rx ret value is: %d\n",stats);
+ PRINT_D(RX_DBG,"netif_rx ret value is: %d\n",stats);
+ }else{
+ PRINT_ER("Discard sending packet with len = %d\n",size);
+ }
+}
+
+void NMI_WFI_mgmt_rx(uint8_t *buff, uint32_t size)
+{
+ int i = 0;
+ perInterface_wlan_t* nic;
+ //struct net_device* nmc_netdev = GetIfHandler(buff);
+ for(i = 0;i< g_linux_wlan->u8NoIfcs;i++)
+ {
+ nic = netdev_priv(g_linux_wlan->strInterfaceInfo[i].nmc_netdev);
+ if(nic->monitor_flag)
+ NMI_WFI_monitor_rx(buff,size);
+
+ #ifdef NMI_P2P
+ 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) )
+ {
+ NMI_WFI_p2p_rx(g_linux_wlan->strInterfaceInfo[i].nmc_netdev,buff,size);
+ }
+ #endif
+ }
+
+}
+int nmc_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*)NMI_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*/
+ if(! (ndev = alloc_etherdev(sizeof(perInterface_wlan_t)))){
+ PRINT_ER("Failed to allocate ethernet dev\n");
+ return -1;
+ }
+
+ nic = netdev_priv(ndev);
+ memset(nic,sizeof(perInterface_wlan_t),0);
+
+
+
+ /*Name the Devices*/
+
+ if(i==0)
+ {
+ #if defined(NM73131) // tony, 2012-09-20
+ strcpy(ndev->name,"nmc_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->nmc_netdev = ndev;
+ g_linux_wlan->strInterfaceInfo[g_linux_wlan->u8NoIfcs].nmc_netdev = ndev;
+ g_linux_wlan->u8NoIfcs++;
+ nmc_set_netdev_ops(ndev);
+
+ #ifdef USE_WIRELESS
+ {
+ struct wireless_dev *wdev;
+ /*Register WiFi*/
+ wdev = NMI_WFI_WiphyRegister(ndev);
+
+ /* set netdev, tony */
+ SET_NETDEV_DEV(ndev, &local_sdio_func->dev);
+
+ if(wdev == NULL){
+ PRINT_ER("Can't register NMI Wiphy\n");
+ return -1;
+ }
+
+ /*linking the wireless_dev structure with the netdevice*/
+ nic->nmc_netdev->ieee80211_ptr = wdev;
+ nic->nmc_netdev->ml_priv = nic;
+ wdev->netdev = nic->nmc_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 NMI_SDIO
+ if(!linux_spi_init(&g_linux_wlan->nmc_spidev)){
+ PRINT_ER("Can't initialize SPI \n");
+ return -1; /* ERROR */
+ }
+ g_linux_wlan->nmc_spidev = nmc_spi_dev;
+ #else
+ g_linux_wlan->nmc_sdio_func= local_sdio_func;
+ #endif
+
+ return 0;
+}
+
+
+/*The 1st function called after module inserted*/
+static int __init init_nmc_driver(void){
+
+
+#if defined (NMC_DEBUGFS)
+ if(nmc_debugfs_init() < 0) {
+ NMI_PRINTF("fail to create debugfs for nmc driver\n");
+ return -1;
+ }
+#endif
+
+ printk("IN INIT FUNCTION\n");
+ printk("*** NMC1000 driver VERSION=[%s] REVISON=[%s] FW_VER=[%s] ***\n", __DRIVER_VERSION__, SVNREV, STA_FIRMWARE);
+
+ linux_wlan_device_power(1);
+ msleep(100);
+ linux_wlan_device_detection(1);
+
+#ifdef NMI_SDIO
+ {
+ int ret;
+
+ ret = sdio_register_driver(&nmc_bus);
+ if (ret < 0) {
+ printk("init_nmc_driver: Failed register sdio driver\n");
+ }
+
+ return ret;
+ }
+#else
+ PRINT_D(INIT_DBG,"Initializing netdev\n");
+ if(nmc_netdev_init()){
+ PRINT_ER("Couldn't initialize netdev\n");
+ }
+
+ PRINT_D(INIT_DBG,"Device has been initialized successfully\n");
+ return 0;
+#endif
+}
+late_initcall(init_nmc_driver);
+
+static void __exit exit_nmc_driver(void)
+{
+ int i = 0;
+ perInterface_wlan_t* nic[NUM_CONCURRENT_IFC];
+ #define CLOSE_TIMEOUT 12*1000
+
+ #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].nmc_netdev);
+ }
+
+
+
+ if((g_linux_wlan != NULL) &&g_linux_wlan->nmc_firmware != NULL)
+ {
+ release_firmware(g_linux_wlan->nmc_firmware);
+ g_linux_wlan->nmc_firmware = NULL;
+ }
+
+
+ if( (g_linux_wlan != NULL) &&( ((g_linux_wlan->strInterfaceInfo[0].nmc_netdev) != NULL)
+ || ((g_linux_wlan->strInterfaceInfo[1].nmc_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++)
+ {
+
+ if(g_linux_wlan->strInterfaceInfo[i].nmc_netdev != NULL)
+ {
+ if(nic[i]->mac_opened)
+
+ {
+ mac_close(g_linux_wlan->strInterfaceInfo[i].nmc_netdev);
+ }
+
+ PRINT_D(INIT_DBG,"Unregistering netdev %p \n",g_linux_wlan->strInterfaceInfo[i].nmc_netdev);
+ unregister_netdev(g_linux_wlan->strInterfaceInfo[i].nmc_netdev);
+
+
+ #ifdef USE_WIRELESS
+ PRINT_D(INIT_DBG,"Freeing Wiphy...\n");
+ NMI_WFI_WiphyFree(g_linux_wlan->strInterfaceInfo[i].nmc_netdev);
+ #endif
+
+ PRINT_D(INIT_DBG,"Freeing netdev...\n");
+ free_netdev(g_linux_wlan->strInterfaceInfo[i].nmc_netdev);
+ }
+
+ }
+ }
+
+#ifdef USE_WIRELESS
+#ifdef NMI_AP_EXTERNAL_MLME
+ // Bug 4600 : NMI_WFI_deinit_mon_interface was already called at mac_close
+ //NMI_WFI_deinit_mon_interface();
+#endif
+#endif
+
+if(g_linux_wlan->open_ifcs==0)
+{
+ #ifndef NMI_SDIO
+ PRINT_D(INIT_DBG,"SPI unregsiter...\n");
+ spi_unregister_driver(&nmc_bus);
+ #else
+ PRINT_D(INIT_DBG,"SDIO unregsiter...\n");
+ sdio_unregister_driver(&nmc_bus);
+ #endif
+
+ linux_wlan_deinit_lock(&close_exit_sync);
+ NMI_FREE(g_linux_wlan);
+ g_linux_wlan = NULL;
+
+ PRINT_D(INIT_DBG,"Module_exit Done.\n");
+
+#if defined (NMC_DEBUGFS)
+ nmc_debugfs_remove();
+#endif
+
+ linux_wlan_device_detection(0);
+ linux_wlan_device_power(0);
+}
+}
+module_exit(exit_nmc_driver);
+
+MODULE_LICENSE("GPL");
+#endif
diff --git a/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_wlan_sdio.c b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_wlan_sdio.c
new file mode 100755
index 00000000..08865acf
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_wlan_sdio.c
@@ -0,0 +1,277 @@
+#include "NMI_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 "nmi_sdio"
+#else
+#define SDIO_MODALIAS "nmc1000_sdio"
+#endif
+
+#ifdef NMC_ASIC_A0
+#if defined (NM73131_0_BOARD)
+ #define MAX_SPEED 50000000
+#elif defined (PLAT_ALLWINNER_A10)
+ #define MAX_SPEED 50000000/*15000000*/
+#elif defined (PLAT_ALLWINNER_A20)
+ #define MAX_SPEED 45000000 //40000000 //50000000
+#elif defined (PLAT_ALLWINNER_A23)
+ #define MAX_SPEED 45000000
+#elif defined (PLAT_ALLWINNER_A31)
+ #define MAX_SPEED 45000000
+#elif defined (PLAT_PANDA_ES_OMAP4460)
+ #define MAX_SPEED 25000000 //johnny change
+#elif defined(PLAT_WM8880)
+ #define MAX_SPEED /*20000000*/50000000 /* tony increased to 50000000 */
+#elif defined (PLAT_UBUNTU_X86) // tony
+ #define MAX_SPEED 25000000
+#elif defined (PLAT_RKXXXX)
+#define MAX_SPEED 50000000
+#else
+#define MAX_SPEED 50000000
+#endif
+#else /* NMC_ASIC_A0 */
+/* Limit clk to 6MHz on FPGA. */
+#define MAX_SPEED 6000000
+#endif /* NMC_ASIC_A0 */
+
+
+struct sdio_func* local_sdio_func = NULL;
+extern linux_wlan_t* g_linux_wlan;
+extern int nmc_netdev_init(void);
+extern int sdio_clear_int(void);
+extern void nmi_handle_isr(void);
+
+static unsigned int sdio_default_speed=0;
+
+#define SDIO_VENDOR_ID_NMI 0x0296
+#define SDIO_DEVICE_ID_NMI 0x5347
+
+static const struct sdio_device_id nmi_sdio_ids[] = {
+ { SDIO_DEVICE(SDIO_VENDOR_ID_NMI,SDIO_DEVICE_ID_NMI) },
+};
+
+
+static void nmi_sdio_interrupt(struct sdio_func *func)
+{
+#ifndef NMI_SDIO_IRQ_GPIO
+ sdio_release_host(func);
+ nmi_handle_isr();
+ sdio_claim_host(func);
+#endif
+}
+
+
+int linux_sdio_cmd52(sdio_cmd52_t *cmd){
+ struct sdio_func *func = g_linux_wlan->nmc_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) {
+ printk("nmi_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->nmc_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) {
+ printk("nmi_sdio_cmd53..failed, err(%d)\n", ret);
+ return 0;
+ }
+
+ return 1;
+}
+
+volatile int probe = 0; //COMPLEMENT_BOOT
+extern void set_wifi_name(char * name);
+
+static int linux_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id){
+ printk("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(nmc_netdev_init()){
+ PRINT_ER("Couldn't initialize netdev\n");
+ return -1;
+ }
+ //added by rubbitxiao
+ set_wifi_name("nmc1000_android4.4.ko");
+
+ return 0;
+}
+
+static void linux_sdio_remove(struct sdio_func *func)
+{
+ /**
+ TODO
+ **/
+
+}
+
+struct sdio_driver nmc_bus = {
+ .name = SDIO_MODALIAS,
+ .id_table = nmi_sdio_ids,
+ .probe = linux_sdio_probe,
+ .remove = linux_sdio_remove,
+};
+
+void enable_sdio_interrupt(void){
+ int ret;
+
+#ifndef NMI_SDIO_IRQ_GPIO
+
+ sdio_claim_host(local_sdio_func);
+ ret = sdio_claim_irq(local_sdio_func, nmi_sdio_interrupt);
+ sdio_release_host(local_sdio_func);
+
+ if (ret < 0) {
+ PRINT_ER("can't claim sdio_irq, err(%d)\n", ret);
+ }
+#endif
+}
+
+void disable_sdio_interrupt(void){
+
+#ifndef NMI_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)
+{
+#if defined(PLAT_AML8726_M3)
+
+#else
+ 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_ER("@@@@@@@@@@@@ change SDIO speed to %d @@@@@@@@@\n", speed);
+#endif
+ return 1;
+}
+
+static int linux_sdio_get_speed(void)
+{
+ return local_sdio_func->card->host->ios.clock;
+}
+
+int linux_sdio_init(void* pv){
+
+#if defined(PLAT_AML8726_M3)
+//[[ rachel - copy from v.3.0 (by johnny)
+ #ifdef NMC1000_SINGLE_TRANSFER
+ #define NMI_SDIO_BLOCK_SIZE 256
+ #else
+ #define NMI_SDIO_BLOCK_SIZE 512
+ #endif
+
+ int err;
+
+ sdio_claim_host(local_sdio_func);
+
+ printk("johnny linux_sdio_init %d\n", local_sdio_func->num );
+
+ local_sdio_func->num = 0;
+ sdio_set_block_size(local_sdio_func, NMI_SDIO_BLOCK_SIZE);
+
+ local_sdio_func->num = 1;
+ sdio_enable_func(local_sdio_func);
+ sdio_set_block_size(local_sdio_func, NMI_SDIO_BLOCK_SIZE);
+
+ sdio_release_host(local_sdio_func);
+
+ printk("johnny linux_sdio_init\n");
+#endif
+
+ sdio_default_speed = linux_sdio_get_speed();
+ return 1;
+}
+
+void linux_sdio_deinit(void *pv){
+ sdio_unregister_driver(&nmc_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/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_wlan_sdio.h b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_wlan_sdio.h
new file mode 100755
index 00000000..68b3da25
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_wlan_sdio.h
@@ -0,0 +1,14 @@
+extern struct sdio_func *local_sdio_func;
+extern struct sdio_driver nmc_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);
+void 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/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_wlan_spi.c b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_wlan_spi.c
new file mode 100755
index 00000000..a6682b47
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_wlan_spi.c
@@ -0,0 +1,489 @@
+#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 NMC_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
+#else
+#define MIN_SPEED 24000000
+#define MAX_SPEED 48000000
+#endif
+#else /* NMC_ASIC_A0 */
+/* Limit clk to 6MHz on FPGA. */
+#define MIN_SPEED 6000000
+#define MAX_SPEED 6000000
+#endif /* NMC_ASIC_A0 */
+
+static uint32_t SPEED = MIN_SPEED;
+
+struct spi_device* nmc_spi_dev;
+void linux_spi_deinit(void* vp);
+
+static int __init nmc_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);
+ nmc_spi_dev = spi;
+
+ return 0;
+}
+
+static int __devexit nmc_bus_remove(struct spi_device* spi){
+
+ //linux_spi_deinit(NULL);
+
+ return 0;
+}
+
+
+struct spi_driver nmc_bus __refdata = {
+ .driver = {
+ .name = MODALIAS,
+ },
+ .probe = nmc_bus_probe,
+ .remove = __devexit_p(nmc_bus_remove),
+};
+
+
+void linux_spi_deinit(void* vp){
+
+ spi_unregister_driver(&nmc_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 = 0;
+
+
+ if(called == 0){
+ called++;
+ if(&nmc_bus == NULL){
+ PRINT_ER("nmc_bus address is NULL\n");
+ }
+ ret = spi_register_driver(&nmc_bus);
+ }
+
+ /* change return value to match NMI interface */
+ (ret<0)? (ret = 0):(ret = 1);
+
+ return ret;
+}
+
+#if defined(PLAT_WMS8304) // rachel
+#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(nmc_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 NMI interface */
+ (ret<0)? (ret = 0):(ret = 1);
+
+
+ return ret;
+}
+
+#elif defined(TXRX_PHASE_SIZE)
+
+int linux_spi_write(uint8_t* b, uint32_t len){
+ int ret;
+ if(len > 0 && b != NULL) {
+ int i = 0;
+ int blk = len/TXRX_PHASE_SIZE;
+ int remainder = len%TXRX_PHASE_SIZE;
+
+ char *r_buffer = (char*) kzalloc(TXRX_PHASE_SIZE, GFP_KERNEL);
+ if(! r_buffer){
+ PRINT_ER("Failed to allocate memory for r_buffer\n");
+ }
+
+ if(blk)
+ {
+ while(i<blk)
+ {
+ struct spi_message msg;
+ struct spi_transfer tr = {
+ .tx_buf = b + (i*TXRX_PHASE_SIZE),
+ //.rx_buf = NULL,
+ .len = TXRX_PHASE_SIZE,
+ .speed_hz = SPEED,
+ .bits_per_word = 8,
+ .delay_usecs = 0,
+ };
+ /*
+ char *r_buffer = (char*) kzalloc(TXRX_PHASE_SIZE, GFP_KERNEL);
+ if(! r_buffer){
+ PRINT_ER("Failed to allocate memory for r_buffer\n");
+ }
+ */
+ tr.rx_buf = r_buffer;
+
+ memset(&msg, 0, sizeof(msg));
+ spi_message_init(&msg);
+ msg.spi = nmc_spi_dev;
+ msg.is_dma_mapped = USE_SPI_DMA; // rachel
+
+ spi_message_add_tail(&tr, &msg);
+ ret = spi_sync(nmc_spi_dev, &msg);
+ if(ret < 0) {
+ PRINT_ER( "SPI transaction failed\n");
+ }
+ //i += MJ_WRITE_SIZE;
+ i++;
+
+ }
+ }
+ if(remainder)
+ {
+ struct spi_message msg;
+ struct spi_transfer tr = {
+ .tx_buf = b + (blk*TXRX_PHASE_SIZE),
+ //.rx_buf = NULL,
+ .len = remainder,
+ .speed_hz = SPEED,
+ .bits_per_word = 8,
+ .delay_usecs = 0,
+ };
+ /*
+ char *r_buffer = (char*) kzalloc(remainder, GFP_KERNEL);
+ if(! r_buffer){
+ PRINT_ER("Failed to allocate memory for r_buffer\n");
+ }
+ */
+ tr.rx_buf = r_buffer;
+
+ memset(&msg, 0, sizeof(msg));
+ spi_message_init(&msg);
+ msg.spi = nmc_spi_dev;
+ msg.is_dma_mapped = USE_SPI_DMA; // rachel
+
+ spi_message_add_tail(&tr, &msg);
+ ret = spi_sync(nmc_spi_dev, &msg);
+ if(ret < 0) {
+ PRINT_ER( "SPI transaction failed\n");
+ }
+ }
+ if(r_buffer)
+ kfree(r_buffer);
+ } else {
+ PRINT_ER("can't write data with the following length: %d\n",len);
+ PRINT_ER("FAILED due to NULL buffer or ZERO length check the following length: %d\n",len);
+ ret = -1;
+ }
+
+ /* change return value to match NMI interface */
+ (ret<0)? (ret = 0):(ret = 1);
+
+ return ret;
+
+}
+
+#else
+int linux_spi_write(uint8_t* b, uint32_t len){
+
+ int ret;
+ struct spi_message msg;
+
+ if(len > 0 && b != NULL){
+ struct spi_transfer tr = {
+ .tx_buf = b,
+ //.rx_buf = r_buffer,
+ .len = len,
+ .speed_hz = SPEED,
+ .delay_usecs = 0,
+ };
+ char *r_buffer = (char*) kzalloc(len, GFP_KERNEL);
+ if(! r_buffer){
+ PRINT_ER("Failed to allocate memory for r_buffer\n");
+ }
+ tr.rx_buf = r_buffer;
+ PRINT_D(BUS_DBG,"Request writing %d bytes\n",len);
+
+ memset(&msg, 0, sizeof(msg));
+ spi_message_init(&msg);
+//[[johnny add
+ msg.spi = nmc_spi_dev;
+ msg.is_dma_mapped = USE_SPI_DMA; // rachel
+//]]
+ spi_message_add_tail(&tr,&msg);
+
+ ret = spi_sync(nmc_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 NMI 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(nmc_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 NMI interface */
+ (ret<0)? (ret = 0):(ret = 1);
+
+ return ret;
+}
+
+#elif defined(TXRX_PHASE_SIZE)
+
+int linux_spi_read(unsigned char*rb, unsigned long rlen){
+ int ret;
+
+ if(rlen > 0) {
+ int i =0;
+
+ int blk = rlen/TXRX_PHASE_SIZE;
+ int remainder = rlen%TXRX_PHASE_SIZE;
+
+ char *t_buffer = (char*) kzalloc(TXRX_PHASE_SIZE, GFP_KERNEL);
+ if(! t_buffer){
+ PRINT_ER("Failed to allocate memory for t_buffer\n");
+ }
+
+ if(blk)
+ {
+ //printk(" read blk %d cnt\n", blk);
+ while(i<blk)
+ {
+ struct spi_message msg;
+ struct spi_transfer tr = {
+ //.tx_buf = NULL,
+ .rx_buf = rb + (i*TXRX_PHASE_SIZE),
+ .len = TXRX_PHASE_SIZE,
+ .speed_hz = SPEED,
+ .bits_per_word = 8,
+ .delay_usecs = 0,
+ };
+ tr.tx_buf = t_buffer;
+
+ memset(&msg, 0, sizeof(msg));
+ spi_message_init(&msg);
+ msg.spi = nmc_spi_dev;
+ msg.is_dma_mapped = USE_SPI_DMA; // rachel
+
+ spi_message_add_tail(&tr, &msg);
+ ret = spi_sync(nmc_spi_dev, &msg);
+ if(ret < 0) {
+ PRINT_ER( "SPI transaction failed\n");
+ }
+ i ++;
+ }
+ }
+ if(remainder)
+ {
+ struct spi_message msg;
+ struct spi_transfer tr = {
+ //.tx_buf = NULL,
+ .rx_buf = rb + (blk*TXRX_PHASE_SIZE),
+ .len = remainder,
+ .speed_hz = SPEED,
+ .bits_per_word = 8,
+ .delay_usecs = 0,
+ };
+ /*
+ char *t_buffer = (char*) kzalloc(remainder, GFP_KERNEL);
+ if(! t_buffer){
+ PRINT_ER("Failed to allocate memory for t_buffer\n");
+ }
+ */
+ tr.tx_buf = t_buffer;
+
+ //printk(" read remain, %d bytes\n", remainder);
+ memset(&msg, 0, sizeof(msg));
+ spi_message_init(&msg);
+ msg.spi = nmc_spi_dev;
+ msg.is_dma_mapped = USE_SPI_DMA; // rachel
+
+ spi_message_add_tail(&tr, &msg);
+ ret = spi_sync(nmc_spi_dev, &msg);
+ if(ret < 0) {
+ PRINT_ER( "SPI transaction failed\n");
+ }
+ }
+
+ if(t_buffer)
+ kfree(t_buffer);
+ }else {
+ PRINT_ER("can't read data with the following length: %ld\n",rlen);
+ ret = -1;
+ }
+ /* change return value to match NMI interface */
+ (ret<0)? (ret = 0):(ret = 1);
+
+ return ret;
+}
+
+#else
+int linux_spi_read(unsigned char*rb, unsigned long rlen){
+
+ int ret;
+
+ if(rlen > 0){
+ struct spi_message msg;
+ struct spi_transfer tr = {
+ // .tx_buf = t_buffer,
+ .rx_buf = rb,
+ .len = rlen,
+ .speed_hz = SPEED,
+ .delay_usecs = 0,
+
+ };
+ char *t_buffer = (char*) kzalloc(rlen, GFP_KERNEL);
+ if(! t_buffer){
+ PRINT_ER("Failed to allocate memory for t_buffer\n");
+ }
+ tr.tx_buf = t_buffer;
+
+ memset(&msg, 0, sizeof(msg));
+ spi_message_init(&msg);
+//[[ johnny add
+ msg.spi = nmc_spi_dev;
+ msg.is_dma_mapped = USE_SPI_DMA; // rachel
+//]]
+ spi_message_add_tail(&tr,&msg);
+
+ ret = spi_sync(nmc_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 NMI 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)); // rachel
+ spi_message_init(&msg);
+ msg.spi = nmc_spi_dev; // rachel
+ msg.is_dma_mapped = USE_SPI_DMA; // rachel for DMA
+
+ spi_message_add_tail(&tr,&msg);
+ ret = spi_sync(nmc_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 NMI interface */
+ (ret<0)? (ret = 0):(ret = 1);
+
+ return ret;
+}
+
+int linux_spi_set_max_speed(void)
+{
+ SPEED = MAX_SPEED;
+
+ PRINT_ER("@@@@@@@@@@@@ change SPI speed to %d @@@@@@@@@\n", SPEED);
+ return 1;
+}
diff --git a/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_wlan_spi.h b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/linux_wlan_spi.h
new file mode 100755
index 00000000..6f5eb1ae
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/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* nmc_spi_dev;
+extern struct spi_driver nmc_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/net/wireless/nmi_android4.4_driver/src/driver/linux/source/nmi_custom_gpio.c b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/nmi_custom_gpio.c
new file mode 100755
index 00000000..bd592f3f
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/nmi_custom_gpio.c
@@ -0,0 +1,169 @@
+/*
+
+* $Id: nmi_custom_gpio.c, Exp $
+*/
+//#include <linux/mmc/core.h>
+//#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+//#include <linux/mmc/sdio_func.h>
+//#include <linux/mmc/sdio_ids.h>
+//#include <linux/mmc/sdio.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+
+//via
+#include <mach/gpio_customize_ease.h>
+//johnny add
+#include <mach/hardware.h>
+#include <mach/wmt_gpio.h>
+
+
+
+//static struct mmc_host *mmc_host = NULL;
+
+static GPIO_CTRL gpio_pmu_ctrl;
+static GPIO_CTRL gpio_reset_ctrl;
+static GPIO_CTRL gpio_wake_ctrl;
+GPIO_CTRL gpio_irq_ctrl;
+
+//extern void sdhci_bus_scan(void);
+
+//extern int sprd_3rdparty_gpio_wifi_reset;
+//extern int sprd_3rdparty_gpio_wifi_pwd;
+//extern int sprd_3rdparty_gpio_wifi_wake;
+//extern int sprd_3rdparty_gpio_wifi_irq;
+/*
+int sprd_3rdparty_gpio_wifi_reset = 255;
+int sprd_3rdparty_gpio_wifi_pwd = 255;
+int sprd_3rdparty_gpio_wifi_wake = 255;
+int sprd_3rdparty_gpio_wifi_irq =255;
+*/
+
+void Rubbit_Chk_gpio_irq(int value)
+{
+ printk("[%d] gpio_irq_ctrl.gpio_int_ctl:%x\n",value, REG8_VAL(gpio_irq_ctrl.gpio_int_ctl.address));
+ printk("[%d] gpio_irq_ctrl.gpio_int_status:%x\n",value, REG8_VAL(gpio_irq_ctrl.gpio_int_status.address));
+ printk("[%d] gpio_get_value_any: 0x%x\n", value, gpio_get_value_any(&gpio_irq_ctrl));
+}
+
+void irq_gpio_init(void)
+{
+ //if(!gpio_irq_isEnable_any(&gpio_irq_ctrl) || !gpio_irq_state_any(&gpio_irq_ctrl))
+
+#if 1
+ printk("[MMM] irq is Enable (%d), irq state (%d)\n"
+ , gpio_irq_isEnable_any(&gpio_irq_ctrl)
+ , gpio_irq_state_any(&gpio_irq_ctrl));
+
+#endif
+
+
+ {
+ /*init gpio interruption pin: input, low trigger, pull up, disable int*/
+ gpio_enable_any(&gpio_irq_ctrl, INPUT);
+ set_gpio_irq_triger_mode_any(&gpio_irq_ctrl, IRQ_LOW);
+ gpio_pull_enable_any(&gpio_irq_ctrl,PULL_UP);
+
+ gpio_clean_irq_status_any(&gpio_irq_ctrl);
+
+ enable_gpio_int_any(&gpio_irq_ctrl,INT_DIS);
+ }
+
+}
+
+void irq_gpio_deinit(void)
+{
+ //disable_irq_wake();
+ printk("[MMM] IRQ GPIO DEINIT, called [2] ~~~~~~~~~~~~~~~~~~~\n");
+ Rubbit_Chk_gpio_irq(3);
+ /* below: no interrupt @ 2nd time
+ gpio_enable_any(&gpio_irq_ctrl, INPUT);
+ gpio_pull_enable_any(&gpio_irq_ctrl, PULL_DOWN);
+ */
+
+ // below not working (no interrupt @ 2nd time)
+ //gpio_disable_any(&gpio_irq_ctrl);
+}
+
+
+
+void wifi_gpio_reset(int high_or_low)
+{
+ printk("%s======hi= %d\n",__FUNCTION__,high_or_low);
+/*
+ if(sprd_3rdparty_gpio_wifi_reset > 0)
+ {printk("wifi reset gpio = %d\n", sprd_3rdparty_gpio_wifi_reset);
+ gpio_direction_output(sprd_3rdparty_gpio_wifi_reset, high_or_low);
+ gpio_set_value(sprd_3rdparty_gpio_wifi_reset,high_or_low);
+ }
+ */
+
+ gpio_enable_any(&gpio_reset_ctrl, OUTPUT);
+ gpio_set_value_any(&gpio_reset_ctrl,high_or_low);
+
+}
+static void wifi_card_set_gpios(int high_or_low)
+{
+/*
+ printk("%s**********hi=%d\n",__FUNCTION__,high_or_low);
+ if(sprd_3rdparty_gpio_wifi_reset > 0)
+ {printk("wifi reset gpio = %d\n", sprd_3rdparty_gpio_wifi_reset);
+ gpio_direction_output(sprd_3rdparty_gpio_wifi_reset, high_or_low);
+ gpio_set_value(sprd_3rdparty_gpio_wifi_reset,high_or_low);
+ }
+
+ if(sprd_3rdparty_gpio_wifi_pwd > 0)
+ {printk("wifi pwd gpio = %d\n",sprd_3rdparty_gpio_wifi_pwd);
+ gpio_direction_output(sprd_3rdparty_gpio_wifi_pwd,high_or_low);
+ gpio_set_value(sprd_3rdparty_gpio_wifi_pwd,high_or_low);
+ }
+ if(sprd_3rdparty_gpio_wifi_wake > 0)
+ { printk("wifi wake gpio = %d\n",sprd_3rdparty_gpio_wifi_wake);
+ gpio_direction_output(sprd_3rdparty_gpio_wifi_wake,high_or_low);
+ gpio_set_value(sprd_3rdparty_gpio_wifi_wake,high_or_low);
+ }*/
+
+ parse_gpio_ctrl_string("e3:4:5a:9a:da:49a:4da", &gpio_pmu_ctrl, "wmt.nmc.pmu");//kpadcolu0 pmu enable
+ parse_gpio_ctrl_string("e3:5:5a:9a:da:49a:4da", &gpio_reset_ctrl, "wmt.nmc.reset");//kpadcolu1 reset
+ parse_gpio_ctrl_string("e3:6:5a:9a:da:49a:4da", &gpio_wake_ctrl, "wmt.nmc.wake");//kpadcolu2 wakeup
+ parse_gpio_ctrl_string("df:6:40:80:00:306:360:480:4c0", &gpio_irq_ctrl, "wmt.nmc.irq");//irq gpio6
+ gpio_irq_ctrl.gpio_input_data.address = 0xfe110000;
+ printk("=====================\n");
+ printf_gpio_ctrl(&gpio_pmu_ctrl);
+ printf_gpio_ctrl(&gpio_reset_ctrl);
+ printf_gpio_ctrl(&gpio_wake_ctrl);
+ printf_gpio_ctrl(&gpio_irq_ctrl);
+ printk("=====================high_or_low:%x \n",high_or_low);
+
+ gpio_enable_any(&gpio_pmu_ctrl, OUTPUT);
+ gpio_set_value_any(&gpio_pmu_ctrl,high_or_low);
+
+ gpio_enable_any(&gpio_wake_ctrl, OUTPUT);
+ gpio_set_value_any(&gpio_wake_ctrl,high_or_low);
+
+ gpio_enable_any(&gpio_reset_ctrl, OUTPUT);//enable output
+ gpio_set_value_any(&gpio_reset_ctrl,high_or_low);//output hign
+
+ //gpio_enable_any(&gpio_irq_ctrl, OUTPUT);
+ //gpio_set_value_any(&gpio_irq_ctrl,high_or_low);
+
+}
+
+
+/* Customer function to control hw specific wlan gpios */
+void NmiWifiCardPower(int power)
+{
+ printk("%s, power=%d\n", __FUNCTION__, power);
+
+ wifi_card_set_gpios (power);
+ if(power){
+ wifi_gpio_reset(0);
+ msleep(100);
+ wifi_gpio_reset(1);
+ msleep(100);
+ }else{
+ wifi_gpio_reset(0);
+ }
+}
+
+
diff --git a/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/nmi_debugfs.c b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/nmi_debugfs.c
new file mode 100755
index 00000000..b11572f4
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/nmi_debugfs.c
@@ -0,0 +1,264 @@
+/*
+* NewportMedia WiFi chipset driver test tools - nmi-debug
+* Copyright (c) 2012 NewportMedia Inc.
+* Author: SSW <sswd@nmisemic.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(NMC_DEBUGFS)
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+
+#include "nmi_queue.h"
+#include "nmi_wlan_if.h"
+
+
+static struct dentry *nmc_dir;
+
+/*
+--------------------------------------------------------------------------------
+*/
+
+// [[ linux_wlan_common.h
+#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);
+
+// [[ debug level: DEBUG, INFO, WRN, added by tony 2012-01-09
+atomic_t DEBUG_LEVEL = ATOMIC_INIT(DEBUG | ERR); // if DEBUG_LEVEL is zero, silent, if DEBUG_LEVEL is 0xFFFFFFFF, verbose
+// ]]
+
+// debug_kmsg
+queue g_dumpqueue = {NULL, };
+#define DUMP_QUEUE_MAX (8*1024)
+DECLARE_WAIT_QUEUE_HEAD(nmc_msgdump_waitqueue);
+
+
+/*
+--------------------------------------------------------------------------------
+*/
+static int nmc_debug_level_open(struct inode *inode, struct file *file)
+{
+ /*DEBUG_LEVEL = *((unsigned int *)inode->i_private);*/
+ printk("nmc_debug_level_open: current debug-level=%x\n", atomic_read(&DEBUG_LEVEL));
+ return 0;
+}
+
+static int nmc_debug_region_open(struct inode *inode, struct file *file)
+{
+ /*REGION = *((unsigned int *)inode->i_private);*/
+ printk("nmc_debug_region_open: current debug-region=%x\n", atomic_read(&REGION));
+ return 0;
+}
+
+static int nmc_debug_dump_open(struct inode *inode, struct file *file)
+{
+ printk("nmc_debug_dump_open\n");
+ return 0;
+}
+
+static ssize_t nmc_debug_level_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
+{
+ if(copy_to_user(buf, (const void*)(&atomic_read(&DEBUG_LEVEL)), sizeof(unsigned int))) {
+ return -EFAULT;
+ }
+
+ return sizeof(unsigned int);
+}
+
+static ssize_t nmc_debug_level_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
+{
+ unsigned int flag = 0;
+
+ if(copy_from_user(&flag, buf, sizeof(unsigned int))) {
+ return -EFAULT;
+ }
+
+ 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);
+ printk("new debug-level is %x\n", atomic_read(&DEBUG_LEVEL));
+
+ return sizeof(unsigned int);
+}
+
+static ssize_t nmc_debug_region_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
+{
+ if(copy_to_user(buf, (const void*)(&atomic_read(&REGION)), sizeof(unsigned int))) {
+ return -EFAULT;
+ }
+
+ return sizeof(unsigned int);
+}
+
+static ssize_t nmc_debug_region_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
+{
+ uint32_t flag = 0;
+
+ if(copy_from_user(&flag, buf, sizeof(unsigned int))) {
+ return -EFAULT;
+ }
+
+ 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 sizeof(unsigned int);
+}
+
+void kmsgdump_write(char *fmt, ...)
+{
+ char buf[256] = {0,};
+ va_list args;
+ int len;
+
+ va_start(args, fmt);
+ len = vsprintf(buf, fmt, args);
+ va_end(args);
+
+ if((len>=256) || (len<0))
+ buf[256-1] = '\n';
+
+#if !defined (NM73131_0_BOARD)
+//#define LOG_TIME_STAMP //NM73131 is not support : rachel check required
+#endif
+
+#ifdef LOG_TIME_STAMP
+ {
+ char buf_t[30] = {0,};
+ unsigned long rem_nsec;
+ u64 ts = local_clock();
+
+ rem_nsec = do_div(ts, 1000000000);
+ sprintf(buf_t, "[%5lu.%06lu] ", (unsigned long)ts, rem_nsec / 1000);
+
+ queue_write(&g_dumpqueue, (void*)buf_t, strlen(buf_t));
+ }
+#endif
+
+ queue_write(&g_dumpqueue, (void*)buf, strlen(buf));
+ wake_up(&nmc_msgdump_waitqueue);
+
+}
+
+static ssize_t kmsgdump_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
+{
+ int read_size = 0;
+ int buf_size = queue_data_size(&g_dumpqueue);
+
+ if(buf_size > 0)
+ {
+ unsigned char *text = kmalloc(buf_size, GFP_KERNEL);
+ read_size = queue_read(&g_dumpqueue, (void*)text, (int)buf_size);
+ if(copy_to_user(buf, text, read_size)) {
+ kfree(text);
+ return -EFAULT;
+ }
+ kfree(text);
+ return read_size;
+ }
+ // return -EAGAIN;
+ return 0;
+}
+
+static unsigned int kmsgdump_poll(struct file *file, poll_table *wait)
+{
+ if(queue_data_size(&g_dumpqueue))
+ return POLLIN | POLLRDNORM;
+ poll_wait(file, &nmc_msgdump_waitqueue, wait);
+ if(queue_data_size(&g_dumpqueue))
+ return POLLIN | POLLRDNORM;
+ return 0;
+}
+
+
+/*
+--------------------------------------------------------------------------------
+*/
+
+#define FOPS(_open, _read, _write, _poll) { \
+ .owner = THIS_MODULE, \
+ .open = (_open), \
+ .read = (_read), \
+ .write = (_write), \
+ .poll = (_poll), \
+}
+
+struct nmc_debugfs_info_t {
+ const char *name;
+ int perm;
+ unsigned int data;
+ struct file_operations fops;
+};
+
+static struct nmc_debugfs_info_t debugfs_info[] = {
+ { "nmc_debug_level", 0666, (DEBUG | ERR), FOPS(nmc_debug_level_open, nmc_debug_level_read, nmc_debug_level_write,NULL), },
+ { "nmc_debug_region", 0666, (INIT_DBG | GENERIC_DBG | CFG80211_DBG), FOPS(nmc_debug_region_open, nmc_debug_region_read, nmc_debug_region_write, NULL), },
+ { "nmc_debug_dump", 0666, 0, FOPS(nmc_debug_dump_open, kmsgdump_read, NULL, kmsgdump_poll), },
+};
+
+int nmc_debugfs_init(void)
+{
+ int i;
+
+ struct dentry *debugfs_files;
+ struct nmc_debugfs_info_t *info;
+
+ nmc_dir = debugfs_create_dir("nmi_wifi", NULL);
+ if(nmc_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(!nmc_dir) {
+ printk("ERR, debugfs create dir\n");
+ return -1;
+ }
+
+ for(i=0; i<ARRAY_SIZE(debugfs_info) ; i++)
+ {
+ info = &debugfs_info[i];
+ printk("create the debugfs file, %s\n", info->name);
+ debugfs_files = debugfs_create_file(info->name,
+ info->perm,
+ nmc_dir,
+ &info->data,
+ &info->fops);
+
+ if(!debugfs_files) {
+ printk("fail to create the debugfs file, %s\n", info->name);
+ debugfs_remove_recursive(nmc_dir);
+ return -1;
+ }
+ }
+
+ queue_init(&g_dumpqueue, DUMP_QUEUE_MAX);
+
+ return 0;
+}
+
+void nmc_debugfs_remove(void)
+{
+ queue_deinit(&g_dumpqueue);
+
+ debugfs_remove_recursive(nmc_dir);
+}
+
+#endif
+
diff --git a/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/nmi_queue.c b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/nmi_queue.c
new file mode 100755
index 00000000..3b46fb43
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/nmi_queue.c
@@ -0,0 +1,235 @@
+/*
+ Copyright (c) Newport Media Inc. All rights reserved.
+ Copyright (c) WRG Inc. All rights reserved.
+
+ Use of this sample source code is subject to the terms of the Newport Media Inc.
+ license agreement under which you licensed this sample source code. If you did not
+ accept the terms of the license agreement, you are not authorized to use this
+ sample source code. For the terms of the license, please see the license agreement
+ between you and Newport Media Inc.
+ THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
+*/
+/**
+ @file queue.c
+ @description generic QUEUE object with auto drop.
+ @author Austin Shin (austin.shin@wrg.co.kr)
+ @date 2009-02-17
+*/
+
+//#include <stdio.h>
+//#include <stdlib.h>
+//#include <string.h>
+//#include <android/log.h> //added
+
+#include "nmi_queue.h"
+
+#ifdef _MSC_VER
+#define inline __inline
+#endif
+
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+
+static spinlock_t g_lock;
+
+/* read write option */
+#define OPTION_PARTIAL_READ // enable partial read
+//#define OPTION_PARTIAL_WRITE // enable partial write
+#define OPTION_AUTO_DROP // force write with auto dropping.
+
+
+/* debugging */
+#define ASSERT(x)
+//#define ASSERT(x) (!(x)) ? assert(x);
+
+static inline int __align(int v, unsigned int n)
+{
+ return (v + (n-1)) & ~(n-1);
+}
+
+int queue_init(queue* p, int len)
+{
+ ASSERT(p);
+ ASSERT(p->buffer);
+ ASSERT(len > 0);
+
+ spin_lock_init(&g_lock);
+
+ //p->buffer = malloc(len);
+ p->buffer = kmalloc(len, GFP_KERNEL);
+
+ if ( p->buffer == NULL )
+ {
+ return 0;
+ }
+
+ p->size = len;
+
+ queue_reset(p);
+
+ return len;
+}
+
+int queue_deinit(queue* p)
+{
+ if( p->buffer == NULL )
+ return -1;
+
+ queue_reset(p);
+
+ kfree(p->buffer); p->buffer = NULL;
+
+ return 0;
+}
+
+int queue_reset(queue* p)
+{
+ ASSERT(p);
+ ASSERT(p->buffer);
+ ASSERT(p->size > 0);
+
+ if(p->buffer == NULL)
+ return 0;
+
+ spin_lock(&g_lock);
+
+ memset(p->buffer, 0, p->size);
+ p->wr = 0;
+ p->rd = 0;
+
+ spin_unlock(&g_lock);
+
+ return 0;
+}
+
+int queue_data_size(queue* p)
+{
+ ASSERT(p);
+
+ if(p->wr >= p->rd)
+ return (p->wr - p->rd);
+ else
+ return (p->wr + (p->size - p->rd));
+}
+
+int queue_free_size(queue* p)
+{
+ ASSERT(p);
+
+ return p->size - queue_data_size(p);
+}
+
+int queue_drop(queue* p, int len)
+{
+ ASSERT(p);
+ ASSERT(len < p->size);
+
+ if(p->rd + len < p->size)
+ {
+ p->rd += len;
+ }
+ else
+ {
+ p->rd = p->rd + len - p->size;
+ }
+
+ return len;
+}
+
+int queue_write(queue* p, void* data, int len)
+{
+ int freesize;
+
+ ASSERT(p);
+ ASSERT(data);
+ ASSERT(len < p->size);
+
+ if(p->buffer == NULL)
+ return 0;
+
+ spin_lock(&g_lock);
+
+ freesize = queue_free_size(p);
+
+ if(len > freesize)
+ {
+#if defined(OPTION_PARTIAL_WRITE)
+ len = freesize;
+#elif defined(OPTION_AUTO_DROP)
+ queue_drop(p, __align(len - freesize, 1)+1);
+#else
+ spin_unlock(&g_lock);
+ return 0;
+#endif
+ }
+
+ if(p->wr + len < p->size)
+ {
+ memcpy(p->buffer + p->wr, data, len);
+ p->wr += len;
+ }
+ else
+ {
+ int part1 = p->size - p->wr;
+ int part2 = len - part1;
+
+ memcpy(p->buffer + p->wr, data, part1);
+ memcpy(p->buffer, (char*)(data) + part1, part2);
+ p->wr = part2;
+
+ }
+
+ spin_unlock(&g_lock);
+
+ return len;
+}
+
+
+int queue_read(queue* p, void* data, int len)
+{
+ int datasize;
+
+ ASSERT(p);
+ ASSERT(data);
+ ASSERT(len < p->size);
+
+ if(p->buffer == NULL)
+ return 0;
+
+ spin_lock(&g_lock);
+
+ datasize = queue_data_size(p);
+
+ if (len > datasize)
+ {
+ //printk("queue underrun\n");
+#if defined(OPTION_PARTIAL_READ)
+ len = datasize;
+#else
+ spin_unlock(&g_lock);
+
+ return 0;
+#endif
+ }
+
+ if(p->rd + len < p->size)
+ {
+ memcpy(data, p->buffer + p->rd, len);
+ p->rd += len;
+ }
+ else
+ {
+ int part1 = p->size - p->rd;
+ int part2 = len - part1;
+
+ memcpy(data, p->buffer + p->rd, part1);
+ memcpy((char*)(data) + part1, p->buffer, part2);
+ p->rd = part2;
+ }
+
+ spin_unlock(&g_lock);
+
+ return len;
+}
+
+
diff --git a/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/nmi_queue.h b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/nmi_queue.h
new file mode 100755
index 00000000..cdfc8fbe
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/nmi_queue.h
@@ -0,0 +1,56 @@
+/*
+ Copyright (c) Newport Media Inc. All rights reserved.
+ Copyright (c) WRG Inc. All rights reserved.
+
+ Use of this sample source code is subject to the terms of the Newport Media Inc.
+ license agreement under which you licensed this sample source code. If you did not
+ accept the terms of the license agreement, you are not authorized to use this
+ sample source code. For the terms of the license, please see the license agreement
+ between you and Newport Media Inc.
+ THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
+*/
+/**
+ @file queue.h
+ @description generic QUEUE object with auto drop.
+ @author Austin Shin (austin.shin@wrg.co.kr)
+ @date 2009-02-17
+*/
+
+#ifndef _QUEUE_H_
+#define _QUEUE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if 1
+#define QUE_BUFFER_MAX_SIZE ((188*16*5)+1) //(188*16*8)//(188*30*4)//8192
+#else
+#define QUE_BUFFER_MAX_SIZE (188*30*8)//(188*30*4)
+#endif
+
+typedef struct _queue
+{
+ char* buffer; // data buffer
+ int size; // buffer size
+ int rd, wr; // r/w offset.
+} queue;
+
+
+int queue_init(queue* p, int len);
+int queue_deinit(queue* p);
+int queue_reset(queue* p);
+int queue_data_size(queue* p);
+int queue_free_size(queue* p);
+int queue_write(queue* p, void* data, int len);
+int queue_read(queue* p, void* data, int len);
+int queue_drop(queue* p, int len);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _QUEUE_H_
+
+
diff --git a/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/nmi_wm8880_gpio.c b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/nmi_wm8880_gpio.c
new file mode 100755
index 00000000..a0155f55
--- /dev/null
+++ b/drivers/net/wireless/nmi_android4.4_driver/src/driver/linux/source/nmi_wm8880_gpio.c
@@ -0,0 +1,87 @@
+/*
+
+* $Id: nmi_custom_gpio.c, Exp $
+*/
+#include <linux/mmc/host.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+
+
+#include <mach/gpio_customize_ease.h>
+#include <mach/hardware.h>
+#include <mach/wmt_gpio.h>
+
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+
+
+static int gpio_chipen_ctrl = -1;
+static int gpio_reset_ctrl = -1;
+
+
+static void wifi_gpio_reset(int high_or_low)
+{
+ printk("%s======hi= %d\n",__FUNCTION__,high_or_low);
+
+ gpio_direction_output(gpio_reset_ctrl, high_or_low);
+}
+
+static void wifi_card_init_gpios(void)
+{
+ int ret;
+
+ gpio_chipen_ctrl = WMT_PIN_GP62_SUSGPIO1; // ??? simon
+ gpio_reset_ctrl = WMT_PIN_GP1_GPIO14;
+
+ ret = gpio_request(gpio_chipen_ctrl, "nmc1000 chipen pin");
+ if (ret < 0) {
+ printk("reques gpio:%x failed!!! for nmc1000\n", gpio_chipen_ctrl);
+ return ;
+ } else {
+ printk("request gpio:%d for nmc1000 success!!!\n", gpio_chipen_ctrl);
+ }
+ gpio_direction_output(gpio_chipen_ctrl, 0);
+
+ ret = gpio_request(gpio_reset_ctrl, "nmc1000 reset pin");
+ if (ret < 0) {
+ printk("reques gpio:%x failed!!! for nmc1000\n", gpio_reset_ctrl);
+ return ;
+ } else {
+ printk("request gpio:%d for nmc1000 success!!!\n", gpio_reset_ctrl);
+ }
+ gpio_direction_output(gpio_reset_ctrl, 0);
+}
+
+static void wifi_card_release_gpios(void)
+{
+ gpio_free(gpio_chipen_ctrl);
+ gpio_free(gpio_reset_ctrl);
+}
+
+static void wifi_card_chipen_gpios(int high_or_low)
+{
+ gpio_direction_output(gpio_chipen_ctrl, high_or_low);
+}
+
+/* Customer function to control hw specific wlan gpios */
+void NmiWifiCardPower(int power)
+{
+ printk("%s, power=%d\n", __FUNCTION__, power);
+
+ if(power){
+ wifi_card_init_gpios();
+ wifi_gpio_reset(0);
+ wifi_card_chipen_gpios (power);
+ msleep(35);
+ wifi_gpio_reset(1);
+ msleep(20);
+ }else{
+ wifi_gpio_reset(0);
+ msleep(10);
+ wifi_card_chipen_gpios (power);
+ msleep(10);
+ wifi_card_release_gpios();
+ }
+}
+
+