diff options
Diffstat (limited to 'drivers/net/wireless/nmi_android4.4_driver/src/driver/linux')
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, ¶ms->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, ¶ms->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 = ð->h_source;
+ ethdaddr = ð->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(®ION));
+ 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(®ION)), 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(®ION));
+ return -EFAULT;
+ }
+
+ atomic_set(®ION, (int)flag);
+ printk("new debug-region is %x\n", atomic_read(®ION));
+
+ 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();
+ }
+}
+
+
|