Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- commit 4129e1b35461013b1f27131d23c20114599906c6
- Author: Arnd Bergmann <arnd@arndb.de>
- Date: Tue Feb 10 08:36:05 2015 +0100
- import
- commit 4129e1b35461013b1f27131d23c20114599906c6
- Author: Arnd Bergmann <arnd@arndb.de>
- Date: Tue Feb 10 08:36:05 2015 +0100
- import
- drivers/net/wireless/sprdwl/Kconfig | 7 +
- drivers/net/wireless/sprdwl/Makefile | 11 +
- .../net/wireless/sprdwl/sprdwl_mem_alloc/Kconfig | 3 +
- .../net/wireless/sprdwl/sprdwl_mem_alloc/Makefile | 1 +
- .../sprdwl/sprdwl_mem_alloc/sprdwl_mem_alloc.c | 103 +
- drivers/net/wireless/sprdwl/wlan_cfg80211.c | 2742 ++++++++++++++++++++
- drivers/net/wireless/sprdwl/wlan_cfg80211.h | 132 +
- drivers/net/wireless/sprdwl/wlan_cmd.c | 920 +++++++
- drivers/net/wireless/sprdwl/wlan_cmd.h | 352 +++
- drivers/net/wireless/sprdwl/wlan_common.h | 275 ++
- drivers/net/wireless/sprdwl/wlan_core.c | 1228 +++++++++
- drivers/net/wireless/sprdwl/wlan_event_q.c | 123 +
- drivers/net/wireless/sprdwl/wlan_event_q.h | 49 +
- drivers/net/wireless/sprdwl/wlan_fifo.c | 326 +++
- drivers/net/wireless/sprdwl/wlan_fifo.h | 106 +
- drivers/net/wireless/sprdwl/wlan_hostapd_conf.c | 227 ++
- drivers/net/wireless/sprdwl/wlan_npi.c | 173 ++
- drivers/net/wireless/sprdwl/wlan_wapi.c | 666 +++++
- drivers/net/wireless/sprdwl/wlan_wapi.h | 158 ++
- 19 files changed, 7602 insertions(+)
- diff --git a/drivers/net/wireless/sprdwl/Kconfig b/drivers/net/wireless/sprdwl/Kconfig
- new file mode 100644
- index 0000000..07c7927
- --- /dev/null
- +++ b/drivers/net/wireless/sprdwl/Kconfig
- @@ -0,0 +1,7 @@
- +config SPRDWL
- + tristate "SPRDWL Wireless Network Support"
- + depends on CFG80211
- + ---help---
- + Say Y to enable built-in wireless MAC controller in the
- + Spreadtrum SC88xx based System-on-Chip devices.
- +
- diff --git a/drivers/net/wireless/sprdwl/Makefile b/drivers/net/wireless/sprdwl/Makefile
- new file mode 100644
- index 0000000..e3c81de
- --- /dev/null
- +++ b/drivers/net/wireless/sprdwl/Makefile
- @@ -0,0 +1,11 @@
- +#ccflags-y += -Werror
- +ccflags-y += -fno-PIC
- +
- +obj-$(CONFIG_SPRDWL) += sprdwl.o
- +
- +sprdwl-objs:= wlan_core.o wlan_fifo.o \
- + wlan_event_q.o wlan_cmd.o \
- + wlan_npi.o wlan_hostapd_conf.o \
- + wlan_cfg80211.o wlan_wapi.o \
- + $(sprdwl-y)
- +
- diff --git a/drivers/net/wireless/sprdwl/sprdwl_mem_alloc/Kconfig b/drivers/net/wireless/sprdwl/sprdwl_mem_alloc/Kconfig
- new file mode 100644
- index 0000000..8380941
- --- /dev/null
- +++ b/drivers/net/wireless/sprdwl/sprdwl_mem_alloc/Kconfig
- @@ -0,0 +1,3 @@
- +config SPRDWL_MEM_ALLOC
- + bool "sprdwl mem alloc "
- + default y
- diff --git a/drivers/net/wireless/sprdwl/sprdwl_mem_alloc/Makefile b/drivers/net/wireless/sprdwl/sprdwl_mem_alloc/Makefile
- new file mode 100644
- index 0000000..c1fcb11
- --- /dev/null
- +++ b/drivers/net/wireless/sprdwl/sprdwl_mem_alloc/Makefile
- @@ -0,0 +1 @@
- +obj-$(CONFIG_SPRDWL_MEM_ALLOC) += sprdwl_mem_alloc.o
- \ No newline at end of file
- diff --git a/drivers/net/wireless/sprdwl/sprdwl_mem_alloc/sprdwl_mem_alloc.c b/drivers/net/wireless/sprdwl/sprdwl_mem_alloc/sprdwl_mem_alloc.c
- new file mode 100644
- index 0000000..4b8e662
- --- /dev/null
- +++ b/drivers/net/wireless/sprdwl/sprdwl_mem_alloc/sprdwl_mem_alloc.c
- @@ -0,0 +1,103 @@
- +#include <linux/proc_fs.h>
- +#include <linux/sipc.h>
- +#include <linux/mutex.h>
- +#include <linux/spinlock.h>
- +#include <linux/ieee80211.h>
- +#include <linux/printk.h>
- +#include <linux/inetdevice.h>
- +#include <linux/spinlock.h>
- +#include <net/cfg80211.h>
- +#include <linux/kernel.h>
- +#include <linux/errno.h>
- +#include <linux/module.h>
- +#include <linux/netdevice.h>
- +#include <linux/skbuff.h>
- +#include <net/ieee80211_radiotap.h>
- +#include <linux/etherdevice.h>
- +#include <linux/wireless.h>
- +#include <net/iw_handler.h>
- +#include <linux/string.h>
- +#include <linux/delay.h>
- +#include <linux/interrupt.h>
- +#include <linux/init.h>
- +#include <linux/wakelock.h>
- +#include <linux/workqueue.h>
- +#include <linux/ipv6.h>
- +#include <linux/ip.h>
- +#include <linux/inetdevice.h>
- +#include <asm/byteorder.h>
- +#include <linux/platform_device.h>
- +#include <linux/atomic.h>
- +#include <linux/wait.h>
- +#include <linux/semaphore.h>
- +#include <linux/vmalloc.h>
- +#include <linux/kthread.h>
- +#include <linux/time.h>
- +#include <linux/delay.h>
- +#include <linux/timer.h>
- +#include <linux/completion.h>
- +#include <asm/atomic.h>
- +#include <linux/ieee80211.h>
- +#include <linux/delay.h>
- +
- +#define WIFI_MEM_BLOCK_NUM (2)
- +
- +typedef struct
- +{
- + int status;
- + unsigned char *mem;
- +}m_mem_t;
- +
- +static m_mem_t wifi_mem[WIFI_MEM_BLOCK_NUM] = {0};
- +unsigned char *wifi_256k_alloc(void)
- +{
- + unsigned char *p= NULL;
- + int i;
- + for(i=0; i< WIFI_MEM_BLOCK_NUM; i++)
- + {
- + if( (0 == wifi_mem[i].status) && (NULL != wifi_mem[i].mem) )
- + {
- + p = wifi_mem[i].mem;
- + wifi_mem[i].status = 1;
- + printk("\001" "0" "[wifi_256k_alloc][%d][0x%x]\n", i, wifi_mem[i].mem );
- + break;
- + }
- + }
- + return p;
- +}
- +EXPORT_SYMBOL_GPL(wifi_256k_alloc);
- +
- +int wifi_256k_free(unsigned char *mem)
- +{
- + int i;
- + for(i=0; i< WIFI_MEM_BLOCK_NUM; i++)
- + {
- + if(mem == wifi_mem[i].mem)
- + {
- + wifi_mem[i].status = 0;
- + printk("\001" "0" "[wifi_256k_free][%d][0x%x]\n", i, wifi_mem[i].mem );
- + return 0;
- + }
- + }
- + return -1;
- +}
- +EXPORT_SYMBOL_GPL(wifi_256k_free);
- +
- +static int sprdwl_mem_alloc(void)
- +{
- + int i;
- + printk("[%s]\n", __func__);
- + for(i = 0; i < WIFI_MEM_BLOCK_NUM; i++)
- + {
- + wifi_mem[i].mem = kmalloc( 256*1024, GFP_ATOMIC);
- + printk("\001" "0" "[wifi_mem][%d][0x%x]\n", i, wifi_mem[i].mem );
- + }
- + return 0;
- +}
- +
- +arch_initcall(sprdwl_mem_alloc);
- +
- +MODULE_AUTHOR("jinglong.chen");
- +MODULE_DESCRIPTION("256k mem alloc");
- +MODULE_LICENSE("GPL");
- +
- diff --git a/drivers/net/wireless/sprdwl/wlan_cfg80211.c b/drivers/net/wireless/sprdwl/wlan_cfg80211.c
- new file mode 100644
- index 0000000..3d66142
- --- /dev/null
- +++ b/drivers/net/wireless/sprdwl/wlan_cfg80211.c
- @@ -0,0 +1,2742 @@
- +/*
- + * Copyright (C) 2014 Spreadtrum Communications Inc.
- + *
- + * Authors:<jinglong.chen@spreadtrum.com>
- + * Owner:
- + * jinglong.chen
- + *
- + * This software is licensed under the terms of the GNU General Public
- + * License version 2, as published by the Free Software Foundation, and
- + * may be copied, distributed, and modified under those terms.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + */
- +
- +#include "wlan_common.h"
- +#include "wlan_cfg80211.h"
- +#include "wlan_cmd.h"
- +
- +#define RATETAB_ENT(_rate, _rateid, _flags) \
- +{ \
- + .bitrate = (_rate), \
- + .hw_value = (_rateid), \
- + .flags = (_flags), \
- +}
- +
- +#define CHAN2G(_channel, _freq, _flags) { \
- + .band = IEEE80211_BAND_2GHZ, \
- + .center_freq = (_freq), \
- + .hw_value = (_channel), \
- + .flags = (_flags), \
- + .max_antenna_gain = 0, \
- + .max_power = 30, \
- +}
- +
- +#define CHAN5G(_channel, _flags) { \
- + .band = IEEE80211_BAND_5GHZ, \
- + .center_freq = 5000 + (5 * (_channel)), \
- + .hw_value = (_channel), \
- + .flags = (_flags), \
- + .max_antenna_gain = 0, \
- + .max_power = 30, \
- +}
- +
- +static struct ieee80211_rate itm_rates[] =
- +{
- + RATETAB_ENT(10, 0x1, 0),
- + RATETAB_ENT(20, 0x2, 0),
- + RATETAB_ENT(55, 0x5, 0),
- + RATETAB_ENT(110, 0xb, 0),
- + RATETAB_ENT(60, 0x6, 0),
- + RATETAB_ENT(90, 0x9, 0),
- + RATETAB_ENT(120, 0xc, 0),
- + RATETAB_ENT(180, 0x12, 0),
- + RATETAB_ENT(240, 0x18, 0),
- + RATETAB_ENT(360, 0x24, 0),
- + RATETAB_ENT(480, 0x30, 0),
- + RATETAB_ENT(540, 0x36, 0),
- +
- + RATETAB_ENT(65, 0x80, 0),
- + RATETAB_ENT(130, 0x81, 0),
- + RATETAB_ENT(195, 0x82, 0),
- + RATETAB_ENT(260, 0x83, 0),
- + RATETAB_ENT(390, 0x84, 0),
- + RATETAB_ENT(520, 0x85, 0),
- + RATETAB_ENT(585, 0x86, 0),
- + RATETAB_ENT(650, 0x87, 0),
- + RATETAB_ENT(130, 0x88, 0),
- + RATETAB_ENT(260, 0x89, 0),
- + RATETAB_ENT(390, 0x8a, 0),
- + RATETAB_ENT(520, 0x8b, 0),
- + RATETAB_ENT(780, 0x8c, 0),
- + RATETAB_ENT(1040, 0x8d, 0),
- + RATETAB_ENT(1170, 0x8e, 0),
- + RATETAB_ENT(1300, 0x8f, 0),
- +};
- +
- +#define ITM_G_RATE_NUM 28
- +#define itm_g_rates (itm_rates)
- +#define ITM_A_RATE_NUM 24
- +#define itm_a_rates (itm_rates + 4)
- +
- +#define itm_g_htcap (IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \
- + IEEE80211_HT_CAP_SGI_20 | \
- + IEEE80211_HT_CAP_SGI_40)
- +
- +static struct ieee80211_channel itm_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),
- +};
- +
- +static struct ieee80211_channel itm_5ghz_channels[] =
- +{
- + CHAN5G(34, 0), CHAN5G(36, 0),
- + CHAN5G(38, 0), CHAN5G(40, 0),
- + CHAN5G(42, 0), CHAN5G(44, 0),
- + CHAN5G(46, 0), CHAN5G(48, 0),
- + CHAN5G(52, 0), CHAN5G(56, 0),
- + CHAN5G(60, 0), CHAN5G(64, 0),
- + CHAN5G(100, 0), CHAN5G(104, 0),
- + CHAN5G(108, 0), CHAN5G(112, 0),
- + CHAN5G(116, 0), CHAN5G(120, 0),
- + CHAN5G(124, 0), CHAN5G(128, 0),
- + CHAN5G(132, 0), CHAN5G(136, 0),
- + CHAN5G(140, 0), CHAN5G(149, 0),
- + CHAN5G(153, 0), CHAN5G(157, 0),
- + CHAN5G(161, 0), CHAN5G(165, 0),
- + CHAN5G(184, 0), CHAN5G(188, 0),
- + CHAN5G(192, 0), CHAN5G(196, 0),
- + CHAN5G(200, 0), CHAN5G(204, 0),
- + CHAN5G(208, 0), CHAN5G(212, 0),
- + CHAN5G(216, 0),
- +};
- +
- +static struct ieee80211_supported_band itm_band_2ghz = {
- + .n_channels = ARRAY_SIZE(itm_2ghz_channels),
- + .channels = itm_2ghz_channels,
- + .n_bitrates = ITM_G_RATE_NUM,
- + .bitrates = itm_g_rates,
- + .ht_cap.cap = itm_g_htcap,
- + .ht_cap.ht_supported = true,
- +};
- +
- +/*static struct ieee80211_supported_band itm_band_5ghz = {
- + .n_channels = ARRAY_SIZE(itm_5ghz_channels),
- + .channels = itm_5ghz_channels,
- + .n_bitrates = ITM_A_RATE_NUM,
- + .bitrates = itm_a_rates,
- + .ht_cap.cap = itm_g_htcap,
- + .ht_cap.ht_supported = true,
- +};*/
- +
- +static const u32 itm_cipher_suites[] = {
- + WLAN_CIPHER_SUITE_WEP40,
- + WLAN_CIPHER_SUITE_WEP104,
- + WLAN_CIPHER_SUITE_TKIP,
- + WLAN_CIPHER_SUITE_CCMP,
- + WLAN_CIPHER_SUITE_SMS4,
- +#ifdef BSS_ACCESS_POINT_MODE
- + WLAN_CIPHER_SUITE_ITM_CCMP,
- + WLAN_CIPHER_SUITE_ITM_TKIP,
- +#endif
- +};
- +
- +/* Supported mgmt frame types to be advertised to cfg80211 */
- +static const struct ieee80211_txrx_stypes
- +itm_mgmt_stypes[NUM_NL80211_IFTYPES] = {
- + [NL80211_IFTYPE_STATION] = {
- + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
- + BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
- + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
- + BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
- + },
- + [NL80211_IFTYPE_AP] = {
- + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
- + BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
- + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
- + BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
- + },
- + [NL80211_IFTYPE_P2P_CLIENT] = {
- + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
- + BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
- + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
- + BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
- + },
- + [NL80211_IFTYPE_P2P_GO] = {
- + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
- + BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
- + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
- + BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
- + },
- +/* Supported mgmt frame types for p2p*/
- + [NL80211_IFTYPE_ADHOC] = {
- + .tx = 0xffff,
- + .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
- + },
- + [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_AP_VLAN] = {
- + /* copy 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)
- + },
- + [NL80211_IFTYPE_P2P_GO] = {
- + .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)
- + },
- +};
- +
- +#define WLAN_EID_VENDOR_SPECIFIC 221
- +
- +void get_ssid(unsigned char *data, unsigned char *ssid)
- +{
- + unsigned char len = 0;
- + unsigned char i = 0;
- + unsigned char j = 0;
- +
- + len = data[37];
- + j = 38;
- +
- + if(len >= 33)
- + len = 0;
- +
- + for(i = 0; i < len; i++, j++)
- + ssid[i] = data[j];
- + ssid[len] = '\0';
- +}
- +
- +void get_bssid(unsigned char *data, unsigned char *bssid)
- +{
- + if(1 == ( (data[1] & 0x02) >> 1 ) )
- + memcpy(bssid, data + 10, 6);
- + else if( (data[1] & 0x01) == 1)
- + memcpy(bssid, data + 4, 6);
- + else
- + memcpy(bssid, data + 16, 6);
- + return;
- +}
- +
- +#ifdef WIFI_DIRECT_SUPPORT
- +
- +struct ieee80211_channel global_channel;
- +u64 global_cookie;
- +
- +static int get_file_size(struct file *f)
- +{
- + int error = -EBADF;
- + struct kstat stat;
- +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
- + error = vfs_getattr(&f->f_path, &stat);
- +#else
- + error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, &stat);
- +#endif
- + if (error == 0) {
- + return stat.size;
- + } else {
- + pr_err("get conf file stat error\n");
- + return error;
- + }
- +}
- +#define P2P_MODE_PATH "/data/misc/wifi/fwpath"
- +int itm_get_p2p_mode_from_file(void)
- +{
- + struct file *fp = 0;
- + mm_segment_t fs;
- + int size = 0;
- + loff_t pos = 0;
- + u8 *buf;
- + int ret = false;
- + fp = filp_open(P2P_MODE_PATH, O_RDONLY, 0);
- + if (IS_ERR(fp)){
- + pr_err("open %s file error\n", P2P_MODE_PATH);
- + goto end;
- + }
- + fs = get_fs();
- + set_fs(KERNEL_DS);
- + size = get_file_size(fp);
- + if (size <= 0) {
- + pr_err("load file:%s error\n", P2P_MODE_PATH);
- + goto error;
- + }
- + buf = kzalloc(size + 1, GFP_KERNEL);
- + vfs_read(fp, buf, size, &pos);
- + if(strcmp(buf, "p2p_mode") == 0)
- + ret = true;
- + kfree(buf);
- +error:
- + filp_close(fp, NULL);
- + set_fs(fs);
- +end:
- + return ret;
- +}
- +
- +static bool itm_find_p2p_ie(const u8 *ie, size_t ie_len, u8 *p2p_ie,
- + size_t *p2p_ie_len)
- +{
- + bool flags = false;
- + size_t index = 0;
- +/*Find out P2P IE.*/
- +
- + if (NULL == ie || ie_len <= 0 || NULL == p2p_ie)
- + return flags;
- +
- + while (index < ie_len) {
- + if (P2P_IE_ID == ie[index]) {
- + *p2p_ie_len = ie[index + 1];
- + if (ie_len >= *p2p_ie_len &&
- + P2P_IE_OUI_BYTE0 == ie[index + 2] &&
- + P2P_IE_OUI_BYTE1 == ie[index + 3] &&
- + P2P_IE_OUI_BYTE2 == ie[index + 4] &&
- + P2P_IE_OUI_TYPE == ie[index + 5]) {
- + memcpy(p2p_ie, ie + index, *p2p_ie_len + 2);
- + *p2p_ie_len += 2;
- + return true;
- + }
- + }
- + index++;
- + }
- +
- + return false;
- +}
- +
- +static int wlan_cfg80211_remain_on_channel(struct wiphy *wiphy,
- +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
- + struct wireless_dev *dev,
- +#else
- + struct net_device *dev,
- +#endif
- + struct ieee80211_channel
- + *channel,
- + unsigned int duration,
- + u64 *cookie)
- +{
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- + int ret;
- +
- + enum nl80211_channel_type channel_type = 0;
- + vif = ndev_to_vif(dev->netdev);
- + vif_id = vif->id;
- + if(ITM_NONE_MODE == vif->mode)
- + return -EAGAIN;
- + printkd("[%s][%d] enter\n", __func__, vif_id);
- + memcpy(&global_channel, channel, sizeof(struct ieee80211_channel));
- + global_cookie = *cookie;
- +
- + /* send remain chan */
- + ret = wlan_cmd_remain_chan(vif_id, channel, channel_type, duration, cookie);
- + if(OK != ret)
- + return -1;
- +
- + /* report remain chan */
- + cfg80211_ready_on_channel(dev, *cookie, channel, duration, GFP_KERNEL);
- + return 0;
- +}
- +
- +static int wlan_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
- +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
- + struct wireless_dev *dev,
- +#else
- + struct net_device *dev,
- +#endif
- + u64 cookie)
- +{
- + int ret;
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- + vif = ndev_to_vif(dev->netdev);
- + vif_id = vif->id;
- + if(ITM_NONE_MODE == vif->mode)
- + return -EAGAIN;
- + printkd("[%s][%d] enter\n", __func__, vif_id);
- + ret = wlan_cmd_cancel_remain_chan(vif_id, cookie);
- + if (OK != ret)
- + return ERROR;
- + return OK;
- +}
- +
- +
- +static int wlan_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, u8 *mac)
- +{
- + return 0;
- +}
- +
- +static void register_frame_work_fun(struct work_struct * work)
- +{
- + unsigned char vif_id;
- + struct wlan_cmd_register_frame_t data;
- + register_frame_param_t *param = container_of(work, register_frame_param_t, work);
- + data.type = cpu_to_le16(param->frame_type);
- + data.reg = param->reg ? 1 : 0;
- + param->frame_type = 0xffff;
- + param->reg = 0;
- + vif_id = ( (wlan_vif_t *)(param->vif) )->id;
- + wlan_cmd_register_frame(vif_id, &data);
- + return;
- +}
- +
- +void init_register_frame_param(wlan_vif_t *vif )
- +{
- + register_frame_param_t *param;
- + param = &(vif->cfg80211.register_frame);
- + param->frame_type = 0xffff;
- + param->reg = 0;
- + param->vif= (void *)vif;
- + INIT_WORK(&(param->work),register_frame_work_fun);
- +}
- +
- +static int register_frame(wlan_vif_t *vif, unsigned short frame_type, bool reg)
- +{
- + vif->cfg80211.register_frame.frame_type = frame_type;
- + vif->cfg80211.register_frame.reg = reg;
- + schedule_work(&(vif->cfg80211.register_frame.work));
- + return 0;
- +}
- +
- +void cfg80211_report_remain_on_channel_expired(unsigned char vif_id, unsigned char *data, unsigned short len)
- +{
- + wlan_vif_t *vif;
- + vif = id_to_vif(vif_id);
- + cfg80211_remain_on_channel_expired(& (vif->wdev), global_cookie, &global_channel, GFP_KERNEL);
- + return ;
- +}
- +
- +
- +static void send_deauth_work_func(struct work_struct *work)
- +{
- + wlan_vif_t *vif;
- + wlan_cfg80211_t *cfg;
- + struct deauth_info *info;
- +
- + info = container_of(work, struct deauth_info, work);
- + cfg = container_of(info, wlan_cfg80211_t, deauth_info);
- + vif = container_of(cfg, wlan_vif_t, cfg80211);
- + cfg80211_send_deauth(vif->ndev, info->mac, info->len);
- +
- + return;
- +}
- +
- +void init_send_deauth_work(wlan_vif_t *vif)
- +{
- + struct deauth_info *info;
- + info = &vif->cfg80211.deauth_info;
- + memset(info, 0, sizeof(*info));
- + INIT_WORK(&info->work, send_deauth_work_func);
- +}
- +
- +void cfg80211_report_mgmt_deauth(unsigned char vif_id, unsigned char *data, unsigned short len)
- +{
- + wlan_vif_t *vif;
- + wlan_cfg80211_t *cfg;
- +
- + vif = id_to_vif(vif_id);
- + if (!vif) {
- + ASSERT("%s vif is NULL\n", __func__);
- + return;
- + }
- + cfg = &vif->cfg80211;
- + memcpy(&cfg->deauth_info.len, data, 2);
- + cfg->deauth_info.len = le16_to_cpu(cfg->deauth_info.len);
- +
- + if (cfg->deauth_info.len != sizeof(cfg->deauth_info.mac)) {
- + ASSERT("%s FIXME len:%d > max:%lu\n", __func__,
- + cfg->deauth_info.len, sizeof(cfg->deauth_info.mac));
- + return;
- + }
- + memcpy(cfg->deauth_info.mac, data + 2, cfg->deauth_info.len);
- + schedule_work(&cfg->deauth_info.work);
- +}
- +
- +void cfg80211_report_mgmt_disassoc(unsigned char vif_id, unsigned char *data, unsigned short len )
- +{
- + u8 *mac_ptr, *index;
- + u16 mac_len;
- + wlan_vif_t *vif = id_to_vif(vif_id);
- +
- + index = data;
- + memcpy(&mac_len, index, 2);
- + mac_len = le16_to_cpu(mac_len);
- + index += 2;
- + mac_ptr = index;
- + cfg80211_send_disassoc(vif->ndev, mac_ptr, mac_len);
- +}
- +
- +void cfg80211_report_new_station(unsigned char vif_id, unsigned char *data, unsigned short len )
- +{
- + u8 *req_ptr, *index;
- + u16 req_len, mac_len;
- + u8 *sta_mac;
- + u32 event_len;
- + int left;
- + struct station_info sinfo;
- + wlan_vif_t *vif = id_to_vif(vif_id);
- +
- + printkd("enter cfg80211_report_new_station\n");
- +
- + event_len = len;
- + index = data;
- +
- + left = event_len;
- +
- + /* The first byte of event data is mac */
- + memcpy(&mac_len, index, 2);
- + mac_len = le16_to_cpu(mac_len);
- + index += 2;
- + left -= 2;
- +
- + if (mac_len != 6) {
- + printkd( "channel len not equal 6 bytes\n");
- + return;
- + }
- +
- + sta_mac = index;
- + index += mac_len;
- + left -= mac_len;
- +
- + if (!left) {
- + printkd("There is no associa req frame!\n");
- + return;
- + }
- +
- + /* The second event data is associate request */
- + memcpy(&req_len, index, 2);
- + req_len = le16_to_cpu(req_len);
- + index += 2;
- + left -= 2;
- +
- + req_ptr = index;
- + left -= req_len;
- +
- + memset(&sinfo, 0, sizeof(struct station_info));
- + sinfo.assoc_req_ies = req_ptr;
- + sinfo.assoc_req_ies_len = req_len;
- + sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
- +
- + cfg80211_new_sta(vif->ndev, sta_mac, &sinfo, GFP_KERNEL);
- +
- + printkd("proccess new station event completed\n");
- +
- +}
- +
- +void cfg80211_report_frame(unsigned char vif_id, unsigned char *data, unsigned short len)
- +{
- + unsigned short mac_len;
- + unsigned char *mac_ptr = NULL;
- + unsigned char channel=0,type=0;
- + int freq;
- + struct wlan_event_report_frame_t * report_frame = NULL;
- + wlan_vif_t *vif = id_to_vif(vif_id);
- +
- + report_frame = (struct wlan_event_report_frame_t *)data;
- + channel = report_frame->channel;
- + type = report_frame->frame_type;
- + freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
- + mac_ptr = (unsigned char *) (report_frame +1);
- + mac_len = le16_to_cpu(report_frame->frame_len);
- + printkd("%s, frame_len:%d\n", __func__, mac_len);
- + cfg80211_rx_mgmt(&(vif->wdev), freq, 0, mac_ptr, mac_len,GFP_KERNEL);
- +}
- +
- +#endif /*WIFI_DIRECT_SUPPORT */
- +
- +static bool itm_is_wps_ie(const unsigned char *pos)
- +{
- + return (pos[0] == WLAN_EID_VENDOR_SPECIFIC &&
- + pos[1] >= 4 &&
- + pos[2] == 0x00 && pos[3] == 0x50 && pos[4] == 0xf2 &&
- + pos[5] == 0x04);
- +}
- +
- +static bool itm_find_wpsie(const unsigned char *ies, size_t ies_len,
- + unsigned char *buf, size_t *wps_len)
- +{
- + const unsigned char *pos;
- + size_t len = 0;
- + bool flags = false;
- +
- + /*
- + * Filter out RSN/WPA IE(s)
- + */
- + if (ies && ies_len)
- + {
- + pos = ies;
- +
- + while (pos + 1 < ies + ies_len)
- + {
- + if (pos + 2 + pos[1] > ies + ies_len)
- + break;
- +
- + if (itm_is_wps_ie(pos))
- + {
- + memcpy(buf + len, pos, 2 + pos[1]);
- + len += 2 + pos[1];
- + flags = true;
- + }
- +
- + pos += 2 + pos[1];
- + }
- + }
- +
- + *wps_len = len;
- + return flags;
- +}
- +static bool itm_find_ft_ie(const unsigned char *ies, size_t ies_len, unsigned char *buf, size_t *ie_len)
- +{
- + const unsigned char *pos;
- + size_t len = 0;
- + bool flags = false;
- + if (ies && ies_len)
- + {
- + pos = ies;
- + while (pos + 1 < ies + ies_len)
- + {
- + if (pos + 2 + pos[1] > ies + ies_len)
- + break;
- + if( (WLAN_11R_FT_IE_ID == pos[0]) || (WLAN_11R_MD_IE_ID == pos[0]) )
- + {
- + memcpy(buf + len, pos, 2 + pos[1]);
- + len += 2 + pos[1];
- + flags = true;
- + }
- +
- + pos += 2 + pos[1];
- + }
- + }
- + *ie_len = len;
- + return flags;
- +}
- +static int itm_wlan_add_cipher_key(wlan_vif_t *vif, bool pairwise, unsigned char key_index, unsigned int cipher, const unsigned char *key_seq, const unsigned char *macaddr)
- +{
- + unsigned char pn_key[16] = { 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
- + 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36
- + };
- + int ret;
- + unsigned char vif_id;
- + vif_id = vif->id;
- + printkd("%s()\n", __func__);
- + if (vif->cfg80211.key_len[pairwise][0] || vif->cfg80211.key_len[pairwise][1] ||
- + vif->cfg80211.key_len[pairwise][2] || vif->cfg80211.key_len[pairwise][3])
- + {
- + /* Only set wep keys if we have at least one of them.
- + pairwise: 0:GTK 1:PTK */
- + switch (cipher)
- + {
- + case WLAN_CIPHER_SUITE_WEP40:
- + vif->cfg80211.cipher_type = WEP40;
- + break;
- + case WLAN_CIPHER_SUITE_WEP104:
- + vif->cfg80211.cipher_type = WEP104;
- + break;
- + case WLAN_CIPHER_SUITE_TKIP:
- + vif->cfg80211.cipher_type = TKIP;
- + break;
- + case WLAN_CIPHER_SUITE_CCMP:
- + vif->cfg80211.cipher_type = CCMP;
- + break;
- + case WLAN_CIPHER_SUITE_SMS4:
- + vif->cfg80211.cipher_type = WAPI;
- + break;
- + default:
- + printkd( "Invalid cipher select: %d\n", vif->cfg80211.cipher_type);
- + return -EINVAL;
- + }
- + memcpy(vif->cfg80211.key_txrsc[pairwise], pn_key, sizeof(pn_key));
- + ret = wlan_cmd_add_key(vif_id,
- + vif->cfg80211.key[pairwise][key_index],
- + vif->cfg80211.key_len[pairwise][key_index],
- + pairwise, key_index, key_seq,
- + vif->cfg80211.cipher_type, macaddr);
- + if (ret < 0)
- + {
- + printkd("wlan_cmd_add_key failed %d\n", ret);
- + return ret;
- + }
- + }
- + return 0;
- +}
- +
- +static int wlan_cfg80211_scan(struct wiphy *wiphy,
- +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
- + struct net_device *dev,
- +#endif
- + struct cfg80211_scan_request *request)
- +{
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- + struct wireless_dev *wdev;
- + struct cfg80211_ssid *ssids;
- + struct wlan_cmd_scan_ssid *scan_ssids;
- + int scan_ssids_len = 0;
- + unsigned char *data = NULL;
- + unsigned int i, n, j;
- + int ret;
- + unsigned char channels[16] = {0};
- +
- + ssids = request->ssids;
- + wdev = request->wdev;
- + vif = ndev_to_vif(wdev->netdev);
- + vif_id = vif->id;
- + if(ITM_NONE_MODE == vif->mode)
- + return -EAGAIN;
- + printkd("[%s][%d] enter\n", __func__, vif_id);
- + if (vif->cfg80211.scan_request)
- + {
- + printkd("Already scanning\n");
- + return -EAGAIN;
- + }
- + /* check we are client side */
- + switch (wdev->iftype)
- + {
- + case NL80211_IFTYPE_AP:
- + break;
- + /* case NL80211_IFTYPE_P2P_CLIENT:
- + case NL80211_IFTYPE_P2P_GO:
- + */
- + case NL80211_IFTYPE_STATION:
- + break;
- + case NL80211_IFTYPE_P2P_CLIENT:
- + case NL80211_IFTYPE_P2P_GO:
- + case NL80211_IFTYPE_P2P_DEVICE:
- + break;
- + default:
- + {
- + printkd("%s(), end\n", __func__);
- + return -EOPNOTSUPP;
- + }
- + }
- +
- + /* set wps ie */
- + if (request->ie_len > 0)
- + {
- + if (request->ie_len > 255)
- + {
- + printkd("%s invalid ie len(%lu)\n", __func__, request->ie_len);
- + return -EOPNOTSUPP;
- + }
- + ret = wlan_cmd_set_wps_ie(vif_id, WPS_REQ_IE, request->ie, request->ie_len);
- + if (ret)
- + {
- + printkd("wlan_cmd_set_wps_ie failed with ret %d\n", ret);
- + printkd("%s(), end\n", __func__);
- + return ret;
- + }
- + }
- + else
- + {
- + printkd("%s request->ie_len is 0\n", __func__);
- + }
- + n = min(request->n_ssids, 9);
- + if (n)
- + {
- + data = kzalloc(512, GFP_KERNEL);
- + if (!data)
- + {
- + printkd("%s failed to alloc for combo ssid\n", __func__);
- + return -2;
- + }
- + scan_ssids = (struct wlan_cmd_scan_ssid *)data;
- + for (i = 0; i < n; i++)
- + {
- + if (!ssids[i].ssid_len)
- + continue;
- + scan_ssids->len = ssids[i].ssid_len;
- + memcpy(scan_ssids->ssid, ssids[i].ssid,
- + ssids[i].ssid_len);
- + scan_ssids_len += (ssids[i].ssid_len
- + + sizeof(scan_ssids->len));
- + scan_ssids = (struct wlan_cmd_scan_ssid *)
- + (data + scan_ssids_len);
- + }
- + }
- +
- + n = min(request->n_channels, 4U);
- + if(n > 15)
- + n = 15;
- + for (i = 0, j=0; i < n; i++)
- + {
- + int ch = request->channels[i]->hw_value;
- + if (ch == 0)
- + {
- + printkd("Scan requested for unknown frequency %dMhz\n", request->channels[i]->center_freq);
- + continue;
- + }
- + channels[j+1] = ch;
- + j++;
- + }
- + channels[0] = j;
- +
- + ret = wlan_cmd_scan(vif_id, data, channels, scan_ssids_len);
- + if (ret)
- + {
- + printkd("wlan_cmd_scan failed with ret %d\n", ret);
- + kfree(data);
- + return ret;
- + }
- +
- + if (vif->cfg80211.scan_done_lock.link.next == LIST_POISON1 ||
- + vif->cfg80211.scan_done_lock.link.prev == LIST_POISON2)
- + wake_lock(&vif->cfg80211.scan_done_lock);
- + /* Arm scan timeout timer */
- + mod_timer(&vif->cfg80211.scan_timeout, jiffies + ITM_SCAN_TIMER_INTERVAL_MS * HZ / 1000);
- + vif->cfg80211.scan_request = request;
- + kfree(data);
- + printkd("%s(), ok!\n", __func__);
- + return 0;
- +}
- +
- +static int wlan_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_connect_params *sme)
- +{
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- + struct wireless_dev *wdev;
- + int ret;
- + unsigned int cipher = 0;
- + unsigned char key_mgmt = 0;
- + int is_wep = (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) || (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104);
- + bool is_wapi = false;
- + int auth_type = 0;
- + unsigned char *buf = NULL;
- + size_t wps_len = 0;
- + size_t p2p_len = 0;
- + size_t ftie_len = 0;
- + vif = ndev_to_vif(ndev);
- + vif_id = vif->id;
- + wdev = &(vif->wdev);
- + if(ITM_NONE_MODE == vif->mode)
- + return -EAGAIN;
- + printkd("[%s][%d] enter\n", __func__, vif_id);
- + printkd("%s(), Begin connect: %s\n", __func__, sme->ssid);
- +
- + /* To avoid confused wapi frame */
- + vif->cfg80211.cipher_type = NONE;
- + /* Get request status, type, bss, ie and so on */
- + /* Set appending ie */
- + /* Set wps ie */
- + if (sme->ie_len > 0)
- + {
- + if (sme->ie_len > 255)
- + {
- + printkd("%s invalid sme->len(%lu)\n",__func__, sme->ie_len);
- + return -EOPNOTSUPP;
- + }
- + buf = kmalloc(sme->ie_len, GFP_KERNEL);
- + if (NULL == buf)
- + {
- + printkd("%s(), end\n",__func__);
- + return -ENOMEM;
- + }
- + if (itm_find_wpsie(sme->ie, sme->ie_len, buf, &wps_len) == true)
- + {
- + ret = wlan_cmd_set_wps_ie(vif_id, WPS_ASSOC_IE, buf, wps_len);
- + if (ret)
- + {
- + printkd("wlan_cmd_set_wps_ie failed with ret %d\n", ret);
- + return ret;
- + }
- + }
- + }
- +#ifdef WIFI_DIRECT_SUPPORT
- + if (itm_find_p2p_ie(sme->ie, sme->ie_len, buf, &p2p_len) == true)
- + {
- + ret = wlan_cmd_set_p2p_ie(vif_id,P2P_ASSOC_IE, buf, p2p_len);
- + if (ret)
- + {
- + printkd("wlan_cmd_set_p2p_ie failed with ret %d\n",ret);
- + return ret;
- + }
- + }
- +#endif/*WIFI_DIRECT_SUPPORT*/
- +#ifdef WLAN_11R_SUPPORT
- + if( itm_find_ft_ie(sme->ie, sme->ie_len, buf, &ftie_len) )
- + {
- + ret = wlan_cmd_set_ft_ie(vif_id, buf, ftie_len);
- + if (ret)
- + {
- + printkd("wlan_cmd_set_ft_ie failed with ret %d\n",ret);
- + }
- + }
- +#endif
- + /* Set WPA version */
- + printkd("Set wpa_versions %#x\n", sme->crypto.wpa_versions);
- + ret = wlan_cmd_set_wpa_version(vif_id, sme->crypto.wpa_versions);
- + if (ret < 0)
- + {
- + printkd("wlan_cmd_set_wpa_version failed with ret %d\n", ret);
- + printkd("%s(), end\n",__func__);
- + return ret;
- + }
- +
- + /* Set Auth type */
- + printkd("Set auth_type %#x\n", sme->auth_type);
- + /* Set the authorisation */
- + if ((sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) ||
- + ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && !is_wep))
- + auth_type = ITM_AUTH_OPEN;
- + else if ((sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) ||
- + ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && is_wep))
- + auth_type = ITM_AUTH_SHARED;
- + ret = wlan_cmd_set_auth_type(vif_id, auth_type);
- + if (ret < 0)
- + {
- + printkd("wlan_cmd_set_auth_type failed with ret %d\n", ret);
- + return ret;
- + }
- + /* Set cipher - pairewise and group */
- + printkd("n_ciphers_pairwise %d\n", sme->crypto.n_ciphers_pairwise);
- + if (sme->crypto.n_ciphers_pairwise)
- + {
- + switch (sme->crypto.ciphers_pairwise[0])
- + {
- + case WLAN_CIPHER_SUITE_WEP40:
- + cipher = WEP40;
- + break;
- + case WLAN_CIPHER_SUITE_WEP104:
- + cipher = WEP104;
- + break;
- + case WLAN_CIPHER_SUITE_TKIP:
- + cipher = TKIP;
- + break;
- + case WLAN_CIPHER_SUITE_CCMP:
- + cipher = CCMP;
- + break;
- + /* WAPI cipher is not processed by CP2 */
- + case WLAN_CIPHER_SUITE_SMS4:
- + cipher = WAPI;
- + is_wapi = true;
- + break;
- + default:
- + printkd("Unicast cipher suite 0x%x is not supported\n", sme->crypto.ciphers_pairwise[0]);
- + printkd("%s(), end\n",__func__);
- + return -ENOTSUPP;
- + }
- +
- + if (is_wapi != true)
- + {
- + ret = wlan_cmd_set_cipher(vif_id, cipher, WIFI_CMD_SET_PAIRWISE_CIPHER);
- + if (ret < 0)
- + {
- + printkd( "set_cipher_cmd pairwise failed with ret %d\n", ret);
- + printkd("%s(), end\n",__func__);
- + return ret;
- + }
- + }
- + }
- + else
- + {
- + /*No pairewise cipher */
- + printkd("No pairewise cipher\n");
- + }
- +
- + /* Set group cipher */
- + switch (sme->crypto.cipher_group)
- + {
- + case NONE:
- + cipher = NONE;
- + break;
- + case WLAN_CIPHER_SUITE_WEP40:
- + cipher = WEP40;
- + break;
- + case WLAN_CIPHER_SUITE_WEP104:
- + cipher = WEP104;
- + break;
- + case WLAN_CIPHER_SUITE_TKIP:
- + cipher = TKIP;
- + break;
- + case WLAN_CIPHER_SUITE_CCMP:
- + cipher = CCMP;
- + break;
- + default:
- + printkd("Group cipher suite 0x%x is not supported\n", sme->crypto.cipher_group);
- + printkd("%s(), end\n",__func__);
- + return -ENOTSUPP;
- + }
- +
- + if (is_wapi != true)
- + {
- + ret = wlan_cmd_set_cipher(vif_id, cipher, WIFI_CMD_SET_GROUP_CIPHER);
- + if (ret < 0)
- + {
- + printkd("set_cipher_cmd group failed with ret %d\n", ret);
- + printkd("%s(), end\n",__func__);
- + return ret;
- + }
- + }
- +
- + /* FIXME */
- + /* Set Auth type again because of CP2 process's differece */
- + printkd("Set auth_type %#x\n", sme->auth_type);
- + /* Set the authorisation */
- + if ((sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) ||
- + ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && !is_wep))
- + auth_type = ITM_AUTH_OPEN;
- + else if ((sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) ||
- + ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && is_wep))
- + auth_type = ITM_AUTH_SHARED;
- + ret = wlan_cmd_set_auth_type(vif_id, auth_type);
- + if (ret < 0)
- + {
- + printkd("wlan_cmd_set_auth_type failed with ret %d\n", ret);
- + printkd("%s(), end\n",__func__);
- + return ret;
- + }
- +
- + /* Set auth key management (akm) */
- + printkd("akm_suites %#x\n", sme->crypto.n_akm_suites);
- + if (sme->crypto.n_akm_suites)
- + {
- + if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_PSK)
- + key_mgmt = AKM_SUITE_PSK;
- + else if(WLAN_AKM_SUITE_FT_PSK == sme->crypto.akm_suites[0])
- + key_mgmt = AKM_SUITE_FT_PSK;
- + else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_8021X)
- + key_mgmt = AKM_SUITE_8021X;
- + /* WAPI akm is not processed by CP2 */
- + else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_WAPI_CERT)
- + key_mgmt = AKM_SUITE_WAPI_CERT;
- + else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_WAPI_PSK)
- + key_mgmt = AKM_SUITE_WAPI_PSK;
- + else if(WLAN_AKM_SUITE_FT_8021X == sme->crypto.akm_suites[0] )
- + key_mgmt = AKM_SUITE_FT_8021X;
- + else
- + {}
- + ret = wlan_cmd_set_key_management(vif_id, key_mgmt);
- + if (ret < 0)
- + {
- + printkd("wlan_cmd_set_key_management failed %d\n", ret);
- + printkd("%s(), end\n",__func__);
- + return ret;
- + }
- + }
- +
- + /* Set PSK */
- + if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40 ||
- + sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104 ||
- + sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP40 ||
- + sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP104)
- + {
- + printkd( "Don't need to set PSK since driver is using WEP\n");
- + vif->cfg80211.key_index[GROUP] = sme->key_idx;
- + vif->cfg80211.key_len[GROUP][sme->key_idx] = sme->key_len;
- + memcpy(vif->cfg80211.key[GROUP][sme->key_idx], sme->key, sme->key_len);
- + ret = itm_wlan_add_cipher_key(vif, 0, sme->key_idx, sme->crypto.ciphers_pairwise[0], NULL, NULL);
- + if (ret < 0)
- + {
- + printkd("itm_wlan_add_key failed %d\n", ret);
- + printkd("%s(), end\n",__func__);
- + return ret;
- + }
- + }
- + else
- + {
- + unsigned char psk[32];
- + int key_len = 0;
- + if (wdev->iftype == NL80211_IFTYPE_AP)
- + {
- + ret = hostap_conf_load(HOSTAP_CONF_FILE_NAME, psk);
- + if (ret)
- + {
- + printkd( "load hostap failed with ret %d\n", ret);
- + printkd("%s(), end\n",__func__);
- + return ret;
- + }
- + key_len = sizeof(psk);
- + }
- + else
- + {
- + if (sme->key_len > 32)
- + {
- + printkd("Invalid key len (%d)\n", sme->key_len);
- + printkd("%s(), end\n",__func__);
- + return -EINVAL;
- + }
- + memcpy(psk, sme->key, sme->key_len);
- + key_len = sme->key_len;
- + }
- + ret = wlan_cmd_set_psk(vif_id, psk, key_len);
- + if (ret < 0)
- + {
- + printkd("set_psk_cmd failed with ret %d\n", ret);
- + printkd("%s(), end\n",__func__);
- + return ret;
- + }
- + }
- +
- + /* Auth RX unencrypted EAPOL is not implemented, do nothing */
- + /* Set channel */
- + if (sme->channel != NULL)
- + {
- + printkd("Settting channel to %d\n", ieee80211_frequency_to_channel(sme->channel-> center_freq));
- + ret = wlan_cmd_set_channel(vif_id, ieee80211_frequency_to_channel (sme->channel->center_freq));
- + if (ret < 0)
- + {
- + printkd("wlan_cmd_set_channel failed with ret %d\n", ret);
- + printkd("%s(), end\n",__func__);
- + return ret;
- + }
- + }
- + else
- + {
- + printkd("Channel is not specified\n");
- + }
- +
- + /* Set BSSID */
- + if (sme->bssid != NULL)
- + {
- + ret = wlan_cmd_set_bssid(vif_id, sme->bssid);
- + if (ret < 0)
- + {
- + printkd("wlan_cmd_set_bssid failed with ret %d\n", ret);
- + printkd("%s(), end\n",__func__);
- + return ret;
- + }
- + memcpy(vif->cfg80211.bssid, sme->bssid, 6);
- + }
- + else
- + {
- + printkd("BSSID is not specified\n");
- + }
- +
- + /* Special process for WEP(WEP key must be set before itm_set_essid) */
- + if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40 ||
- + sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104)
- + {
- + printkd("Setting WEP group cipher\n");
- + if (sme->key_len <= 0)
- + {
- + printkd("No key is specified\n");
- + }
- + else
- + {
- + if (sme->key_len != WLAN_KEY_LEN_WEP104 &&
- + sme->key_len != WLAN_KEY_LEN_WEP40)
- + {
- + printkd("Invalid key length for WEP\n");
- + printkd("%s(), end\n",__func__);
- + return -EINVAL;
- + }
- +
- + wlan_cmd_set_key(vif_id, sme->key_idx);
- + }
- + }
- + /* Set ESSID */
- + if (sme->ssid != NULL)
- + {
- + printkd("sme->ssid:%s\n", sme->ssid);
- + ret = wlan_cmd_set_essid(vif_id, sme->ssid, (int)sme->ssid_len);
- + if (ret < 0)
- + {
- + printkd("wlan_cmd_set_essid failed with ret %d\n", ret);
- + printkd("%s(), end\n",__func__);
- + return ret;
- + }
- + memcpy(vif->cfg80211.ssid, sme->ssid, sme->ssid_len);
- + vif->cfg80211.ssid_len = sme->ssid_len;
- + }
- + vif->cfg80211.connect_status = ITM_CONNECTING;
- + printkd("%s(), ok\n",__func__);
- + return ret;
- +}
- +
- +static int wlan_cfg80211_disconnect(struct wiphy *wiphy,
- + struct net_device *ndev,
- + unsigned short reason_code)
- +{
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- + int ret;
- + vif = ndev_to_vif(ndev);
- + vif_id = vif->id;
- +
- + if(ITM_NONE_MODE == vif->mode)
- + return -EAGAIN;
- + printkd("[%s][%d] enter\n", __func__, vif_id);
- + printkd("Begin disconnect: %s\n", vif->cfg80211.ssid);
- +
- + ret = wlan_cmd_disconnect(vif_id, reason_code);
- + if (ret < 0)
- + {
- + printkd("swifi_disconnect_cmd failed with ret %d\n", ret);
- + }
- + memset(vif->cfg80211.ssid, 0, sizeof(vif->cfg80211.ssid));
- + return ret;
- +}
- +
- +static int wlan_cfg80211_add_key(struct wiphy *wiphy,
- + struct net_device *netdev, u8 idx,
- + bool pairwise, const u8 *mac_addr,
- + struct key_params *params)
- +{
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- + int ret;
- + unsigned char key[32];
- + vif = ndev_to_vif(netdev);
- + vif_id = vif->id;
- + if(ITM_NONE_MODE == vif->mode)
- + return -EAGAIN;
- + printkd("[%s][%d] enter\n", __func__, vif_id);
- + if ( vif->mode == ITM_AP_MODE && (vif->cfg80211.p2p_mode == false) ) {
- + printkd("%s line:%d\n", __func__, __LINE__);
- +
- + memset(&key[0], 0, 32);
- + ret = hostap_conf_load(HOSTAP_CONF_FILE_NAME, key);
- + if (ret != 0) {
- + printkd("%s failed to load hostapd conf!\n", __func__);
- + return ret;
- + }
- + ret = wlan_cmd_set_psk(vif_id, key, sizeof(key));
- + if (ret < 0) {
- + printkd("%s failed to set psk!\n", __func__);
- + return ret;
- + }
- + }
- + else if ((vif->mode == ITM_STATION_MODE) || vif->mode == ITM_P2P_CLIENT_MODE || vif->mode == ITM_P2P_GO_MODE)
- + {
- + vif->cfg80211.key_index[pairwise] = idx;
- + vif->cfg80211.key_len[pairwise][idx] = params->key_len;
- + memcpy(vif->cfg80211.key[pairwise][idx], params->key, params->key_len);
- + ret = itm_wlan_add_cipher_key(vif, pairwise, idx, params->cipher, params->seq, mac_addr);
- + if (ret < 0)
- + {
- + printkd("%s failed to add cipher key!\n", __func__);
- + return ret;
- + }
- + }
- +
- + return 0;
- +}
- +
- +static int wlan_cfg80211_del_key(struct wiphy *wiphy,
- + struct net_device *ndev,
- + unsigned char key_index, bool pairwise,
- + const unsigned char *mac_addr)
- +{
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- +
- + vif = ndev_to_vif(ndev);
- + vif_id = vif->id;
- + if(ITM_NONE_MODE == vif->mode)
- + return -EAGAIN;
- + printkd("[%s][%d] enter\n", __func__, vif_id);
- + if (key_index > WLAN_MAX_KEY_INDEX)
- + {
- + printkd("key index %d out of bounds\n", key_index);
- + return -ENOENT;
- + }
- + if (!vif->cfg80211.key_len[pairwise][key_index])
- + {
- + printkd("index %d is empty\n", key_index);
- + return 0;
- + }
- + vif->cfg80211.key_len[pairwise][key_index] = 0;
- + vif->cfg80211.cipher_type = NONE;
- +
- + return wlan_cmd_del_key(vif_id, key_index, mac_addr);
- +}
- +
- +static int wlan_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *ndev, unsigned char key_index, bool unicast, bool multicast)
- +{
- + int ret;
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- + vif = ndev_to_vif(ndev);
- + vif_id = vif->id;
- + if(ITM_NONE_MODE == vif->mode)
- + return -EAGAIN;
- + printkd("[%s][%d] enter\n", __func__, vif_id);
- + if (key_index < 0 || key_index > 3)
- + {
- + printkd("Invalid key index %d\n", key_index);
- + return -EINVAL;
- + }
- + ret = wlan_cmd_set_key(vif_id, key_index);
- + if (ret < 0)
- + {
- + printkd("wlan_cmd_set_key failed\n");
- + return ret;
- + }
- +
- + return 0;
- +}
- +
- +static int wlan_cfg80211_set_wiphy_params(struct wiphy *wiphy, unsigned int changed)
- +{
- + int ret;
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- + vif_id = NETIF_0_ID;
- + vif = id_to_vif(vif_id);
- + if(ITM_NONE_MODE == vif->mode)
- + return -EAGAIN;
- + printkd("[%s][%d] enter\n", __func__, vif_id);
- + if (changed & WIPHY_PARAM_RTS_THRESHOLD)
- + {
- + ret = wlan_cmd_set_rts(vif_id, wiphy->rts_threshold);
- + if (ret != 0)
- + {
- + printkd("wlan_cmd_set_rts failed\n");
- + return -EIO;
- + }
- + }
- +
- + if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
- + {
- + ret =
- + wlan_cmd_set_frag(vif_id, wiphy->frag_threshold);
- + if (ret != 0)
- + {
- + printkd("wlan_cmd_set_frag failed\n");
- + return -EIO;
- + }
- + }
- + return 0;
- +}
- +
- +static int wlan_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, unsigned char *mac, struct station_info *sinfo)
- +{
- + unsigned char signal, noise;
- + int rate, ret, i, failed;
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- + static int cfg80211_get_station_time;
- + static char cfg80211_get_station_signal;
- + static int cfg80211_get_station_txrate;
- + static int cfg80211_get_station_txfailed;
- +
- + vif = ndev_to_vif(dev);
- + vif_id = vif->id;
- + if(ITM_NONE_MODE == vif->mode)
- + return -EAGAIN;
- + if(NULL == sinfo)
- + {
- + printke("[%s][sinfo null]\n", __func__);
- + return -EAGAIN;
- + }
- +
- + sinfo->filled |= STATION_INFO_TX_BYTES | STATION_INFO_TX_PACKETS | STATION_INFO_RX_BYTES | STATION_INFO_RX_PACKETS;
- + sinfo->tx_bytes = vif->ndev->stats.tx_bytes;
- + sinfo->tx_packets = vif->ndev->stats.tx_packets;
- + sinfo->rx_bytes = vif->ndev->stats.rx_bytes;
- + sinfo->rx_packets = vif->ndev->stats.rx_packets;
- +
- + if(0 != cfg80211_get_station_time)
- + {
- + sinfo->signal = cfg80211_get_station_signal;
- + sinfo->filled |= STATION_INFO_SIGNAL;
- + sinfo->txrate.legacy = cfg80211_get_station_txrate;
- + sinfo->filled |= STATION_INFO_TX_BITRATE;
- + sinfo->tx_failed = cfg80211_get_station_txfailed;
- + sinfo->filled |= STATION_INFO_TX_FAILED;
- + if ( 2 == cfg80211_get_station_time )
- + {
- + cfg80211_get_station_time = 0;
- + }
- + else
- + {
- + cfg80211_get_station_time ++;
- + }
- + return 0;
- + }
- +
- + ret = wlan_cmd_get_rssi(vif_id, &signal, &noise);
- + if (OK == ret)
- + {
- + sinfo->signal = signal;
- + sinfo->filled |= STATION_INFO_SIGNAL;
- + }
- + else
- + {
- + printkd("wlan_cmd_get_rssi error!\n");
- + return -EIO;
- + }
- +
- + ret = wlan_cmd_get_txrate_txfailed(vif_id, &rate, &failed);
- + if (OK == ret)
- + {
- + sinfo->tx_failed = failed;
- + sinfo->filled |= STATION_INFO_TX_BITRATE | STATION_INFO_TX_FAILED;
- + }
- + else
- + {
- + printkd("wlan_cmd_get_txrate_txfailed error!\n");
- + return -EIO;
- + }
- +
- + if (!(rate & 0x7f))
- + {
- + sinfo->txrate.legacy = 10;
- + }
- + else
- + {
- + for (i = 0; i < ARRAY_SIZE(itm_rates); i++)
- + {
- + if (rate == itm_rates[i].hw_value)
- + {
- + sinfo->txrate.legacy = itm_rates[i].bitrate;
- + if (rate & 0x80)
- + sinfo->txrate.mcs = itm_rates[i].hw_value;
- + break;
- + }
- + }
- + if (i >= ARRAY_SIZE(itm_rates))
- + sinfo->txrate.legacy = 10;
- + }
- + cfg80211_get_station_signal = sinfo->signal;
- + cfg80211_get_station_txrate = sinfo->txrate.legacy;
- + cfg80211_get_station_txfailed = sinfo->tx_failed;
- + cfg80211_get_station_time ++;
- +
- + return 0;
- +}
- +
- +static int wlan_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *netdev, struct cfg80211_pmksa *pmksa)
- +{
- + int ret;
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- + vif = ndev_to_vif(netdev);
- + vif_id = vif->id;
- + if(ITM_NONE_MODE == vif->mode)
- + return -EAGAIN;
- + printkd("[%s][%d] enter\n", __func__, vif_id);
- + ret = wlan_cmd_pmksa(vif_id, pmksa->bssid, pmksa->pmkid, WIFI_CMD_SET_PMKSA);
- + return ret;
- +}
- +
- +static int wlan_cfg80211_del_pmksa(struct wiphy *wiphy,
- + struct net_device *netdev,
- + struct cfg80211_pmksa *pmksa)
- +{
- + int ret;
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- + vif = ndev_to_vif(netdev);
- + vif_id = vif->id;
- + if(ITM_NONE_MODE == vif->mode)
- + return -EAGAIN;
- + printkd("[%s][%d] enter\n", __func__, vif_id);
- + ret = wlan_cmd_pmksa(vif_id, pmksa->bssid, pmksa->pmkid, WIFI_CMD_DEL_PMKSA);
- + return ret;
- +}
- +
- +static int wlan_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
- +{
- + int ret;
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- + vif = ndev_to_vif(netdev);
- + vif_id = vif->id;
- + if(ITM_NONE_MODE == vif->mode)
- + return -EAGAIN;
- + printkd("[%s][%d] enter\n", __func__, vif_id);
- + ret = wlan_cmd_pmksa(vif_id, vif->cfg80211.bssid, NULL, WIFI_CMD_FLUSH_PMKSA);
- + return ret;
- +}
- +
- +void cfg80211_report_connect_result(unsigned char vif_id, unsigned char *pData, int len)
- +{
- + unsigned char *req_ie_ptr, *resp_ie_ptr, *bssid_ptr, *pos, *value_ptr;
- + unsigned char status_code;
- + unsigned short bssid_len;
- + unsigned char req_ie_len;
- + unsigned short resp_ie_len;
- + unsigned int event_len;
- + int left;
- + unsigned char reassociate_rsp_flag = 0;
- +
- + wlan_vif_t *vif = id_to_vif(vif_id);
- + printkd("%s(), enter\n", __func__);
- + event_len = len;
- + /* status_len 2 + status_code 1 = 3 bytes */
- + if (event_len < 3)
- + {
- + printkd("filled event len(%d) is not a valid len\n", event_len);
- + goto out;
- + }
- + pos = kmalloc(event_len, GFP_KERNEL);
- + if (pos == NULL)
- + {
- + printkd("[%s][%d][%d]\n", __func__, __LINE__, event_len);
- + if(event_len > 16384)
- + BUG_ON(1);
- + goto out;
- + }
- + /* The first byte of event data is status and len */
- + memcpy(pos, pData, event_len);
- + /* msg byte format
- + * byte [0] the length for status_code,here is 1
- + * byte [1] reassociate_rsp_flag
- + * byte [2] status_code
- + * ..... other data
- + */
- + if (1 != *pos) {
- + ASSERT("msg first byte err:%d != 1", (int)*pos);
- + kfree(pos);
- + goto out;
- + }
- + reassociate_rsp_flag = *(pos + 1);
- + status_code = *(pos + 2);
- +
- + /* FIXME later the status code should be reported by CP2 */
- + if (status_code != 0)
- + {
- + printkd("%s, Connect is failled (%d)\n", __func__, status_code);
- + kfree(pos);
- + goto out;
- + }
- +
- + value_ptr = pos + 3;
- + left = event_len - 3;
- + /* BSSID is 6 + len is 2 = 8 */
- + if (left < 8)
- + {
- + printkd("%s(), Do not have a vaild bssid\n", __func__);
- + kfree(pos);
- + goto out;
- + }
- + memcpy(&bssid_len, value_ptr, 2);
- + bssid_len = le16_to_cpu(bssid_len);
- + left -= 2;
- + bssid_ptr = value_ptr + 2;
- + left -= bssid_len;
- +
- + if (!left)
- + {
- + printkd("%s(), There is no req_ie frame!\n", __func__);
- + kfree(pos);
- + goto out;
- + }
- + req_ie_len = *(unsigned char *)(bssid_ptr + bssid_len);
- + left -= 1;
- + req_ie_ptr = bssid_ptr + bssid_len + 1;
- + left -= req_ie_len;
- + if (!left)
- + {
- + printkd("%s(), There is no resp_ie frame!\n", __func__);
- + kfree(pos);
- + goto out;
- + }
- + resp_ie_len = *(unsigned char *)(req_ie_ptr + req_ie_len) + *(unsigned char *)(req_ie_ptr + req_ie_len +1);
- + resp_ie_ptr = req_ie_ptr + req_ie_len + 2;
- +
- + if ( (vif->cfg80211.connect_status == ITM_CONNECTING) || (1 == reassociate_rsp_flag) )
- + {
- + /* inform connect result to cfg80211 */
- + vif->cfg80211.connect_status = ITM_CONNECTED;
- + if(1 == reassociate_rsp_flag)
- + {
- + vif->wdev.sme_state = CFG80211_SME_CONNECTING;
- + }
- + cfg80211_connect_result(vif->ndev, bssid_ptr, req_ie_ptr, req_ie_len, resp_ie_ptr, resp_ie_len, WLAN_STATUS_SUCCESS, GFP_KERNEL);
- + kfree(pos);
- + if (!netif_carrier_ok(vif->ndev))
- + {
- + printkd("%s(), netif_carrier_on, ssid:%s\n", __func__, vif->cfg80211.ssid);
- + netif_carrier_on(vif->ndev);
- + netif_wake_queue(vif->ndev);
- + }
- + }
- + printkd("%s(), ok\n", __func__);
- + return;
- +out:
- + if (vif->cfg80211.scan_request && (atomic_add_unless(&vif->cfg80211.scan_status, 1, 1) == 1))
- + {
- + del_timer_sync(&vif->cfg80211.scan_timeout);
- + cfg80211_scan_done(vif->cfg80211.scan_request, true);
- + vif->cfg80211.scan_request = NULL;
- + if (vif->cfg80211.scan_done_lock.link.next != LIST_POISON1 &&
- + vif->cfg80211.scan_done_lock.link.prev != LIST_POISON2)
- + wake_unlock(&vif->cfg80211.scan_done_lock);
- + atomic_dec(&vif->cfg80211.scan_status);
- + }
- + if (vif->cfg80211.connect_status == ITM_CONNECTING)
- + {
- + cfg80211_connect_result(vif->ndev, vif->cfg80211.bssid, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL);
- + }
- + else if (vif->cfg80211.connect_status == ITM_CONNECTED)
- + {
- + cfg80211_disconnected(vif->ndev, status_code, NULL, 0, GFP_KERNEL);
- + }
- +
- + printkd("%s(), err\n", __func__);
- + return;
- +}
- +
- +void cfg80211_report_disconnect_done(unsigned char vif_id, unsigned char *pData, int len)
- +{
- + struct cfg80211_bss *bss = NULL;
- + unsigned short reason_code = 0;
- + bool found = false;
- + wlan_vif_t *vif = id_to_vif(vif_id);
- + printkd("%s()\n", __func__);
- + /* This should filled if disconnect reason is not only one */
- + memcpy(&reason_code, pData, 2);
- + reason_code = le16_to_cpu(reason_code);
- + if (vif->cfg80211.scan_request && (atomic_add_unless(&vif->cfg80211.scan_status, 1, 1) == 1))
- + {
- + del_timer_sync(&vif->cfg80211.scan_timeout);
- + cfg80211_scan_done(vif->cfg80211.scan_request, true);
- + vif->cfg80211.scan_request = NULL;
- + if (vif->cfg80211.scan_done_lock.link.next != LIST_POISON1 && vif->cfg80211.scan_done_lock.link.prev != LIST_POISON2)
- + wake_unlock(&vif->cfg80211.scan_done_lock);
- + atomic_dec(&vif->cfg80211.scan_status);
- + }
- + if (vif->cfg80211.connect_status == ITM_CONNECTING)
- + {
- + cfg80211_connect_result(vif->ndev,
- + vif->cfg80211.bssid, NULL, 0,
- + NULL, 0,
- + WLAN_STATUS_UNSPECIFIED_FAILURE,
- + GFP_KERNEL);
- + }
- + else if (vif->cfg80211.connect_status == ITM_CONNECTED)
- + {
- + if (reason_code == AP_LEAVING /*||
- + reason_code == AP_DEAUTH*/)
- + {
- + do
- + {
- + bss = cfg80211_get_bss(vif->wdev.wiphy, NULL,
- + vif->cfg80211.bssid, vif->cfg80211.ssid,
- + vif->cfg80211.ssid_len,
- + WLAN_CAPABILITY_ESS,
- + WLAN_CAPABILITY_ESS);
- + if (bss)
- + {
- + cfg80211_unlink_bss(vif->wdev.wiphy,
- + bss);
- + found = true;
- + }
- + else
- + {
- + found = false;
- + }
- + }
- + while (found);
- + }
- + cfg80211_disconnected(vif->ndev, reason_code,
- + NULL, 0, GFP_KERNEL);
- + }
- +
- + vif->cfg80211.connect_status = ITM_DISCONNECTED;
- + if (netif_carrier_ok(vif->ndev))
- + {
- + printkd("netif_carrier_off\n");
- + netif_carrier_off(vif->ndev);
- + netif_stop_queue(vif->ndev);
- + }
- + return;
- +}
- +
- +static void wlan_scan_timeout(unsigned long data)
- +{
- + wlan_vif_t *vif = (wlan_vif_t *)data;
- +
- + printkd("%s()\n", __func__);
- + if (vif->cfg80211.scan_request && (atomic_add_unless(&vif->cfg80211.scan_status, 1, 1) == 1))
- + {
- + printkd("scan timer expired!\n");
- + cfg80211_scan_done(vif->cfg80211.scan_request, true);
- + vif->cfg80211.scan_request = NULL;
- + if (vif->cfg80211.scan_done_lock.link.next != LIST_POISON1 && vif->cfg80211.scan_done_lock.link.prev != LIST_POISON2)
- + wake_unlock(&vif->cfg80211.scan_done_lock);
- + atomic_dec(&vif->cfg80211.scan_status);
- + printkd("%s() end\n", __func__);
- +
- + return;
- + }
- +
- + printkd("%s() end, wrong scan timer expired!\n", __func__);
- + return;
- +}
- +
- +void cfg80211_report_scan_done(unsigned char vif_id, unsigned char *pData, int len, bool aborted)
- +{
- + struct ieee80211_mgmt *mgmt;
- + struct ieee80211_channel *channel;
- + struct ieee80211_supported_band *band;
- + struct wiphy *wiphy;
- + struct cfg80211_bss *itm_bss = NULL;
- + unsigned int mgmt_len = 0;
- + unsigned short channel_num = 0, channel_len;
- + unsigned short rssi_len;
- + short rssi;
- + int signal;
- + int freq;
- + unsigned int left = len;
- + wlan_vif_t *vif = id_to_vif(vif_id);
- + const unsigned char *pos = pData;
- +
- + wiphy = vif->wdev.wiphy;
- + printkd("%s()\n", __func__);
- + if (atomic_add_unless(&vif->cfg80211.scan_status, 1, 1) == 0)
- + {
- + printkd( "scan event is aborted\n");
- + return;
- + }
- +
- + if (!vif->cfg80211.scan_request)
- + {
- + printkd("vif->cfg80211.scan_request is null\n");
- + atomic_dec(&vif->cfg80211.scan_status);
- + return;
- + }
- +
- + if (left < 10 || aborted)
- + {
- + printkd( "filled event len(%d) is not a valid len\n", len);
- + goto out;
- + }
- +
- + mgmt = kmalloc(left, GFP_KERNEL);
- + if (mgmt == NULL)
- + {
- + printkd("[%s][%d]\n", __func__, left);
- + goto out;
- + }
- + while (left >= 10)
- + {
- + /* must use memcpy to protect unaligned */
- + /* The formate of frame is len(two bytes) + data */
- + memcpy(&channel_len, pos, 2);
- + channel_len = le16_to_cpu(channel_len);
- + pos += 2;
- + left -= 2;
- + if (channel_len > 2) {
- + ASSERT("channel_len %u > 2\n", channel_len);
- + kfree(mgmt);
- + goto out;
- + }
- + memcpy(&channel_num, pos, channel_len);
- + channel_num = le16_to_cpu(channel_num);
- + pos += channel_len;
- + left -= channel_len;
- + /* The second two value of frame is rssi */
- + memcpy(&rssi_len, pos, 2);
- + rssi_len = le16_to_cpu(rssi_len);
- + pos += 2;
- + left -= 2;
- + memcpy(&rssi, pos, rssi_len);
- + pos += rssi_len;
- + left -= rssi_len;
- + /* The third two value of frame is following data len */
- + memcpy(&mgmt_len, pos, 2);
- + mgmt_len = le16_to_cpu(mgmt_len);
- + pos += 2;
- + left -= 2;
- +
- + if (mgmt_len > left)
- + {
- + printkd("mgmt_len(0x%08x) > left(0x%08x)!\n", mgmt_len, left);
- + kfree(mgmt);
- + goto out;
- + }
- +
- + /* The following is real data */
- + memcpy(mgmt, pos, mgmt_len);
- + left -= mgmt_len;
- + pos += mgmt_len;
- +
- + /* FIXME Now only support 2GHZ */
- + band = wiphy->bands[IEEE80211_BAND_2GHZ];
- + freq = ieee80211_channel_to_frequency(channel_num, band->band);
- + channel = ieee80211_get_channel(wiphy, freq);
- + if (!channel)
- + {
- + printkd("freq is %d\n", freq);
- + continue;
- + }
- + signal = rssi;
- + //printkd("[report][%s][%d][%d]\n",ssid, channel_num, signal);
- + itm_bss = cfg80211_inform_bss_frame(wiphy, channel, mgmt, le16_to_cpu(mgmt_len), signal, GFP_KERNEL);
- +
- + if (unlikely(!itm_bss))
- + printkd("cfg80211_inform_bss_frame error\n");
- +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
- + cfg80211_put_bss(wiphy, itm_bss);
- +#else
- + cfg80211_put_bss(itm_bss);
- +#endif
- + }
- +
- + if (left)
- + {
- + kfree(mgmt);
- + goto out;
- + }
- +
- + kfree(mgmt);
- + del_timer_sync(&vif->cfg80211.scan_timeout);
- + cfg80211_scan_done(vif->cfg80211.scan_request, aborted);
- + vif->cfg80211.scan_request = NULL;
- + if (vif->cfg80211.scan_done_lock.link.next != LIST_POISON1 && vif->cfg80211.scan_done_lock.link.prev != LIST_POISON2)
- + wake_unlock(&vif->cfg80211.scan_done_lock);
- + atomic_dec(&vif->cfg80211.scan_status);
- +
- + printkd("%s(), ok!\n", __func__);
- + return;
- +
- +out:
- + del_timer_sync(&vif->cfg80211.scan_timeout);
- + cfg80211_scan_done(vif->cfg80211.scan_request, true);
- + vif->cfg80211.scan_request = NULL;
- + if (vif->cfg80211.scan_done_lock.link.next != LIST_POISON1 &&
- + vif->cfg80211.scan_done_lock.link.prev != LIST_POISON2)
- + wake_unlock(&vif->cfg80211.scan_done_lock);
- + atomic_dec(&vif->cfg80211.scan_status);
- +
- + printkd("%s(), err\n", __func__);
- + return;
- +}
- +
- +void cfg80211_report_scan_frame(unsigned char vif_id, unsigned char *pData, int len)
- +{
- + unsigned short frame_len;
- + unsigned short event_ops;
- + int i, report_null;
- + wlan_vif_t *vif;
- + buf_scan_frame_t *scan_buf;
- + struct wlan_event_scan_rsp *event;
- + unsigned char *msa;
- + unsigned char ssid[33] = {0};
- + unsigned char bssid[6] = {0};
- +
- + struct ieee80211_channel *channel = NULL;
- + struct ieee80211_supported_band *band = NULL;
- + struct wiphy *wiphy = NULL;
- + struct cfg80211_bss *itm_bss = NULL;
- + struct ieee80211_mgmt *mgmt = NULL;
- + u8 *ie;
- + size_t ielen;
- + u16 capability, beacon_interval;
- + int freq, signal;
- + u64 tsf;
- +
- + vif = id_to_vif(vif_id);
- + wiphy = vif->wdev.wiphy;
- + event = (struct wlan_event_scan_rsp *)(pData);
- + frame_len = le16_to_cpu(event->frame_len);
- + /* 64bit */
- + event_ops = le16_to_cpu(event->ops);
- + if (frame_len + sizeof(*event) > len || event_ops > 2)
- + {
- + printkd("[%s %d][line %d err]\n", __func__, vif_id, __LINE__);
- + return;
- + }
- + if (0 == event_ops)
- + {
- + if (frame_len < 37) {
- + printkd("[%s %d][line %d err]\n", __func__, vif_id, __LINE__);
- + return;
- + }
- + msa = (unsigned char *)(event + 1);
- + get_ssid(msa, ssid);
- + get_bssid(msa, bssid);
- + if(0 == strlen(ssid) )
- + {
- + printkd("[%s %d][line %d err]\n", __func__, vif_id, __LINE__);
- + return;
- + }
- + if (1024 < frame_len)
- + {
- + printkd("[%s %d][line %d err]\n", __func__, vif_id, __LINE__);
- + return;
- + }
- + for(i=0; i < MAX_SCAN_FRAME_BUF_NUM; i++)
- + {
- + scan_buf = (buf_scan_frame_t *)( vif->cfg80211.scan_frame_array + i*sizeof(buf_scan_frame_t) );
- + if(0xff != scan_buf->live)
- + continue;
- + if(0 != memcmp(bssid, scan_buf->bssid, 6) )
- + continue;
- + strcpy(scan_buf->ssid, ssid );
- + memcpy(scan_buf->msa, msa, frame_len);
- + scan_buf->msa_len = frame_len;
- + scan_buf->channel = le16_to_cpu(event->channel);
- + scan_buf->signal = (short)le16_to_cpu(event->signal);
- + scan_buf->live = 0xff;
- + scan_buf->keep = 1;
- + return;
- + }
- + for(i=0; i < MAX_SCAN_FRAME_BUF_NUM; i++)
- + {
- + scan_buf = (buf_scan_frame_t *)(vif->cfg80211.scan_frame_array + i*sizeof(buf_scan_frame_t) );
- + if(0xff == scan_buf->live)
- + continue;
- + memcpy(scan_buf->bssid, bssid, 6);
- + strcpy(scan_buf->ssid, ssid );
- + memcpy(scan_buf->msa, msa, frame_len);
- + scan_buf->msa_len = frame_len;
- + scan_buf->channel = le16_to_cpu(event->channel);
- + scan_buf->signal = (short)le16_to_cpu(event->signal);
- + scan_buf->keep = 1;
- + scan_buf->live = 0xff;
- + printkd("[netif:%d find_ssid][%s][%d][%d]\n",vif_id, scan_buf->ssid, scan_buf->channel, scan_buf->signal);
- + return;
- + }
- + return;
- + }
- + if (1 != event_ops)
- + {
- + printkd("[%s %d][line %d err]\n", __func__, vif_id, __LINE__);
- + return;
- + }
- + if (!vif->cfg80211.scan_request)
- + {
- + printkd("[%s %d][line %d err]\n", __func__, vif_id, __LINE__);
- + atomic_dec(&vif->cfg80211.scan_status);
- + return;
- + }
- + if (atomic_add_unless(&vif->cfg80211.scan_status, 1, 1) == 0)
- + {
- + printkd("[%s %d][line %d err]\n", __func__, vif_id, __LINE__);
- + return;
- + }
- + if (!vif->cfg80211.scan_request)
- + {
- + printkd("[%s %d][line %d err]\n", __func__, vif_id, __LINE__);
- + atomic_dec(&vif->cfg80211.scan_status);
- + return;
- + }
- + report_null = -1;
- + band = wiphy->bands[IEEE80211_BAND_2GHZ];
- + for (i = 0; i < MAX_SCAN_FRAME_BUF_NUM; i++) {
- + scan_buf = (buf_scan_frame_t *)( vif->cfg80211.scan_frame_array + i*sizeof(buf_scan_frame_t) );
- + if(0xff != scan_buf->live)
- + continue;
- + if(0 == scan_buf->keep)
- + {
- + printkd("[netif:%d leave_ssid][%s][%d][%d]\n",
- + vif_id, scan_buf->ssid,
- + le16_to_cpu(event->channel),
- + le16_to_cpu(event->signal));
- + memset((char *)scan_buf, 0, sizeof(buf_scan_frame_t) );
- + continue;
- + }
- + scan_buf->keep--;
- + freq = ieee80211_channel_to_frequency(scan_buf->channel, band->band);
- + channel = ieee80211_get_channel(wiphy, freq);
- + if (!channel)
- + {
- + printkd("[%s %d][line %d err]\n", __func__, vif_id, __LINE__);
- + continue;
- + }
- + mgmt = (struct ieee80211_mgmt *)(&scan_buf->msa[0]);
- + tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
- + capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
- + beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
- + ie = mgmt->u.probe_resp.variable;
- + ielen = le16_to_cpu(scan_buf->msa_len) - offsetof(struct ieee80211_mgmt,
- + u.probe_resp.variable);
- + signal = scan_buf->signal;
- + signal = signal*100;
- + wiphy_info(wiphy, " %s, " MACSTR ", channel %2u, signal %d\n",
- + ieee80211_is_probe_resp(mgmt->frame_control)
- + ? "proberesp" : "beacon ",
- + MAC2STR(mgmt->bssid), scan_buf->channel, scan_buf->signal);
- + itm_bss = cfg80211_inform_bss(wiphy, channel, mgmt->bssid,
- + tsf, capability, beacon_interval, ie,
- + ielen, signal, GFP_KERNEL);
- + if (unlikely(!itm_bss))
- + printkd("[%s %d][line %d err]\n", __func__, vif_id, __LINE__);
- +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
- + cfg80211_put_bss(wiphy, itm_bss);
- +#else
- + cfg80211_put_bss(itm_bss);
- +#endif
- + report_null = 0;
- + }
- + if(-1 == report_null)
- + {
- + printkd("[%s %d][report-ssid][NULL]\n", __func__, vif_id);
- + }
- + del_timer_sync(&vif->cfg80211.scan_timeout);
- + cfg80211_scan_done(vif->cfg80211.scan_request, false);
- + vif->cfg80211.scan_request = NULL;
- + if (vif->cfg80211.scan_done_lock.link.next != LIST_POISON1 && vif->cfg80211.scan_done_lock.link.prev != LIST_POISON2)
- + wake_unlock(&vif->cfg80211.scan_done_lock);
- + atomic_dec(&vif->cfg80211.scan_status);
- + printkd("[%s %d] ok!\n", __func__, vif_id);
- + return;
- +}
- +
- +void cfg80211_report_mic_failure(unsigned char vif_id,
- + unsigned char *pdata, int len)
- +{
- + struct wlan_event_mic_failure *mic_failure;
- + wlan_vif_t *vif;
- +
- + mic_failure = (struct wlan_event_mic_failure *)pdata;
- + vif = id_to_vif(vif_id);
- + if (vif) {
- + /* debug info,Pls remove it in the future */
- + printkd("[%s %d] is_mcast:0x%x key_id: 0x%x bssid: %x %x %x %x %x %x\n",
- + __func__, vif_id,
- + mic_failure->is_mcast, mic_failure->key_id,
- + vif->cfg80211.bssid[0], vif->cfg80211.bssid[1],
- + vif->cfg80211.bssid[2], vif->cfg80211.bssid[3],
- + vif->cfg80211.bssid[4], vif->cfg80211.bssid[5]);
- + cfg80211_michael_mic_failure(vif->ndev, vif->cfg80211.bssid,
- + (mic_failure->is_mcast ? NL80211_KEYTYPE_GROUP :
- + NL80211_KEYTYPE_PAIRWISE), mic_failure->key_id,
- + NULL, GFP_KERNEL);
- + }
- +}
- +
- +static int wlan_cfg80211_mgmt_tx(struct wiphy *wiphy,
- +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
- + struct wireless_dev *wdev,
- +#else
- + struct net_device *ndev,
- +#endif
- +#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || \
- + defined(COMPAT_KERNEL_RELEASE))
- + struct ieee80211_channel *chan,
- + bool offchan,
- +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
- + enum nl80211_channel_type channel_type,
- + bool channel_type_valid,
- +#endif
- + unsigned int wait,
- +#else /*(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) */
- + struct ieee80211_channel *chan,
- + enum nl80211_channel_type channel_type,
- +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || \
- + defined(COMPAT_KERNEL_RELEASE)
- + bool channel_type_valid,
- +#endif
- +#endif /*(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) */
- + const u8 *buf, size_t len,
- +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
- + bool no_cck,
- +#endif
- +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
- + bool dont_wait_for_ack,
- +#endif
- + u64 *cookie)
- +{
- + int ret = -1;
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- + vif = ndev_to_vif(wdev->netdev);
- + vif_id = vif->id;
- + if(ITM_NONE_MODE == vif->mode)
- + return -EAGAIN;
- + printkd("[%s][%d] enter\n", __func__, vif_id);
- + if(len > 0)
- + {
- + ret = wlan_cmd_set_tx_mgmt(vif_id, chan, wait, buf, len);
- + }
- + if(-1 == ret)
- + return -1;
- + cfg80211_mgmt_tx_status(&(vif->wdev), *cookie, buf, len, 1, GFP_KERNEL);
- + return 0;
- +}
- +
- +static void wlan_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
- +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
- + struct wireless_dev *wdev,
- +#else
- + struct net_device *ndev,
- +#endif
- + u16 frame_type, bool reg)
- +{
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- + vif = ndev_to_vif(wdev->netdev);
- + vif_id = vif->id;
- + if(ITM_NONE_MODE == vif->mode)
- + return ;
- + if(NETIF_0_ID == vif_id)
- + return;
- + printkd("[%s][%d]\n", __func__, vif_id);
- + register_frame(vif,frame_type,reg);
- + return;
- +}
- +
- +static int wlan_change_beacon(wlan_vif_t *vif,struct cfg80211_beacon_data *beacon)
- +{
- + u16 ie_len;
- + u8 *ie_ptr;
- + int ret = 0;
- + unsigned char vif_id = vif->id;
- +
- + printkd("%s enter\n", __func__);
- +#ifdef WIFI_DIRECT_SUPPORT
- + /* send beacon extra ies */
- + if (beacon->head != NULL) {
- + ie_len = beacon->head_len;
- + ie_ptr = kmalloc(ie_len, GFP_KERNEL);
- + if (ie_ptr == NULL)
- + {
- + printkd("[%s][%d][0x%p]\n", __func__, __LINE__, ie_ptr);
- + return -EINVAL;
- + }
- + memcpy(ie_ptr, beacon->head, ie_len);
- + printkd("begin send beacon head ies\n");
- +
- + ret = wlan_cmd_set_p2p_ie(vif_id, P2P_BEACON_IE_HEAD, ie_ptr, ie_len);
- + if (ret) {
- + printkd(
- + "itm_wlan_set_p2p_ie beacon_ies head failed with ret %d\n",
- + ret);
- + } else {
- + printkd("send beacon head ies successfully\n");
- + }
- +
- + kfree(ie_ptr);
- + }
- +
- + /* send beacon extra ies */
- + if (beacon->tail != NULL) {
- + ie_len = beacon->tail_len;
- +
- + ie_ptr = kmalloc(ie_len, GFP_KERNEL);
- + if (ie_ptr == NULL)
- + {
- + printkd("[%s][%d][0x%p]\n", __func__, __LINE__, ie_ptr);
- + return -EINVAL;
- + }
- + memcpy(ie_ptr, beacon->tail, ie_len);
- + printkd("begin send beacon tail ies\n");
- +
- + ret = wlan_cmd_set_p2p_ie(vif_id,
- + P2P_BEACON_IE_TAIL, ie_ptr, ie_len);
- + if (ret) {
- + printkd("wlan_cmd_set_p2p_ie beacon_ies tail failed with ret %d\n",ret);
- + } else {
- + printkd("send beacon tail ies successfully\n");
- + }
- +
- + kfree(ie_ptr);
- + }
- +
- + /* send probe response ies */
- +
- + /* send beacon extra ies */
- + if (beacon->beacon_ies != NULL) {
- + ie_len = beacon->beacon_ies_len;
- +
- + ie_ptr = kmalloc(ie_len, GFP_KERNEL);
- + if (ie_ptr == NULL)
- + {
- + printkd("[%s][%d][0x%p]\n", __func__, __LINE__, ie_ptr);
- + return -EINVAL;
- + }
- + memcpy(ie_ptr, beacon->beacon_ies, ie_len);
- + printkd("begin send beacon extra ies\n");
- +
- + ret = wlan_cmd_set_p2p_ie(vif_id, P2P_BEACON_IE, ie_ptr, ie_len);
- + if (ret) {
- + printkd( "wlan_cmd_set_p2p_ie beacon_ies failed with ret %d\n",ret);
- + } else {
- + printkd("send beacon extra ies successfully\n");
- + }
- +
- + kfree(ie_ptr);
- + }
- +
- + /* send probe response ies */
- +
- + if (beacon->proberesp_ies != NULL) {
- + printkd("%s line:%d\n", __func__, __LINE__);
- + ie_len = beacon->proberesp_ies_len;
- +
- + ie_ptr = kmalloc(ie_len, GFP_KERNEL);
- + if (ie_ptr == NULL)
- + {
- + printkd("[%s][%d][0x%p]\n", __func__, __LINE__, ie_ptr);
- + return -EINVAL;
- + }
- + memcpy(ie_ptr, beacon->proberesp_ies, ie_len);
- + printkd("begin send probe response extra ies\n");
- +
- + ret = wlan_cmd_set_p2p_ie(vif_id, P2P_PROBERESP_IE, ie_ptr, ie_len);
- + if (ret) {
- + printkd("wlan_cmd_set_p2p_ie proberesp_ies failed with ret %d\n",ret);
- + } else {
- + printkd("send probe response ies successfully\n");
- + }
- +
- + kfree(ie_ptr);
- + }
- +
- + /* send associate response ies */
- +
- + if (beacon->assocresp_ies != NULL) {
- + printkd("%s line:%d\n", __func__, __LINE__);
- + ie_len = beacon->assocresp_ies_len;
- +
- + ie_ptr = kmalloc(ie_len, GFP_KERNEL);
- + if (ie_ptr == NULL)
- + {
- + printkd("[%s][%d][0x%p]\n", __func__, __LINE__, ie_ptr);
- + return -EINVAL;
- + }
- + memcpy(ie_ptr, beacon->assocresp_ies, ie_len);
- + printkd("begin send associate response extra ies\n");
- +
- + ret = wlan_cmd_set_p2p_ie(vif_id, P2P_ASSOCRESP_IE, ie_ptr, ie_len);
- + if (ret) {
- + printkd( "wlan_cmd_set_p2p_ie assocresp_ies failed with ret %d\n",ret);
- + } else {
- + printkd("send associate response ies successfully\n");
- + }
- +
- + kfree(ie_ptr);
- + }
- +
- +#endif /*WIFI_DIRECT_SUPPORT */
- + return ret;
- +}
- +
- +static int itm_wlan_start_ap(wlan_vif_t *vif, struct cfg80211_beacon_data *beacon)
- +{
- + struct ieee80211_mgmt *mgmt;
- + u16 mgmt_len;
- + int ret;
- + unsigned char vif_id = vif->id;
- + printkd("%s enter\n", __func__);
- + wlan_change_beacon(vif,beacon);
- + if (beacon->head == NULL)
- + {
- + printke("%s line:%d err\n", __func__, __LINE__);
- + return -EINVAL;
- + }
- + mgmt_len = beacon->head_len;
- + if (beacon->tail)
- + mgmt_len += beacon->tail_len;
- +
- + mgmt = kmalloc(mgmt_len, GFP_KERNEL);
- + if (mgmt == NULL)
- + {
- + printkd("[%s][%d][0x%p]\n", __func__, __LINE__, mgmt);
- + return -EINVAL;
- + }
- + memcpy((u8 *)mgmt, beacon->head, beacon->head_len);
- + if (beacon->tail)
- + memcpy((u8 *)mgmt + beacon->head_len, beacon->tail, beacon->tail_len);
- +
- + ret = wlan_cmd_start_ap(vif_id, (unsigned char *)mgmt, mgmt_len);
- + kfree(mgmt);
- + if (ret != 0)
- + {
- + printke("%s line:%d err\n", __func__, __LINE__);
- + }
- + return ret;
- +}
- +
- +
- +static int wlan_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_ap_settings *info)
- +{
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- + vif = ndev_to_vif(ndev);
- + vif_id = vif->id;
- + if(ITM_NONE_MODE == vif->mode)
- + return -EAGAIN;
- + printkd("[%s][%d] enter\n", __func__, vif_id);
- + if (info->ssid == NULL)
- + {
- + printkd("%s line:%d\n", __func__, __LINE__);
- + return -EINVAL;
- + }
- + printkd("[cfg80211] \t ==>>>%s\n",__func__);
- + memcpy(vif->cfg80211.ssid, info->ssid, info->ssid_len);
- + vif->cfg80211.ssid_len = info->ssid_len;
- + return itm_wlan_start_ap(vif, &info->beacon);
- +}
- +
- +static int wlan_cfg80211_stop_ap(struct wiphy *wiphy,
- + struct net_device *ndev)
- +{
- + int ret;
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- + vif = ndev_to_vif(ndev);
- + vif_id = vif->id;
- + if(ITM_NONE_MODE == vif->mode)
- + return -EAGAIN;
- + printkd("[%s][%d] enter\n", __func__, vif_id);
- + ret = wlan_cmd_mac_close(vif_id, vif->mode);
- + return ret;
- +}
- +
- +static int wlan_cfg80211_change_beacon(struct wiphy *wiphy,
- + struct net_device *ndev,
- + struct cfg80211_beacon_data *beacon)
- +{
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- + vif = ndev_to_vif(ndev);
- + vif_id = vif->id;
- + if(ITM_NONE_MODE == vif->mode)
- + return -EAGAIN;
- + printkd("[%s][%d] enter\n", __func__, vif_id);
- +#ifdef WIFI_DIRECT_SUPPORT
- + return wlan_change_beacon(vif, beacon);
- +#else
- + return itm_wlan_start_ap(vif, beacon);
- +#endif
- +
- +}
- +
- +static int itm_wlan_change_mode(wlan_vif_t *vif, enum nl80211_iftype type)
- +{
- + int mode;
- + int ret;
- + unsigned char vif_id = vif->id;
- + switch (type)
- + {
- + case NL80211_IFTYPE_STATION:
- + if(NETIF_0_ID == vif->id)
- + mode = ITM_STATION_MODE;
- + else
- + mode = ITM_P2P_CLIENT_MODE;
- + break;
- + case NL80211_IFTYPE_AP:
- + if(NETIF_0_ID == vif->id)
- + mode = ITM_AP_MODE;
- + else
- + mode = ITM_P2P_GO_MODE;
- + break;
- + case NL80211_IFTYPE_P2P_CLIENT:
- + mode = ITM_P2P_CLIENT_MODE;
- + break;
- + case NL80211_IFTYPE_P2P_GO:
- + mode = ITM_P2P_GO_MODE;
- + break;
- + default:
- + printkd("invalid interface type %u\n", type);
- + return -EOPNOTSUPP;
- + }
- + vif->wdev.iftype = type;
- + if (mode == vif->mode)
- + {
- + printkd("not need change mode\n");
- + return 0;
- + }
- + vif->wdev.iftype = type;
- + vif->mode = mode;
- + printkd("[%s][%d][%d]\n", __func__, vif_id, mode );
- + ret = wlan_cmd_mac_open(vif_id, mode, vif->ndev->dev_addr );
- + if(OK != ret)
- + return -EIO;
- + vif->wdev.iftype = type;
- + vif->mode = mode;
- + return OK;
- +}
- +
- +static int wlan_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, enum nl80211_iftype type, unsigned int *flags, struct vif_params *params)
- +{
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- + vif = ndev_to_vif(ndev);
- + vif_id = vif->id;
- +#ifdef WIFI_DIRECT_SUPPORT
- + if(NETIF_1_ID == vif_id)
- + {
- + vif->cfg80211.p2p_mode = itm_get_p2p_mode_from_file();
- + printkd("[%s][%d][%d]\n", __func__, vif_id, ( vif->cfg80211.p2p_mode ? 1:0) );
- + }
- +#endif /* WIFI_DIRECT_SUPPORT */
- + return itm_wlan_change_mode(vif, type);
- +}
- +
- +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
- +static int wlan_cfg80211_set_channel(struct wiphy *wiphy,
- + struct net_device *ndev,
- + struct ieee80211_channel *channel)
- +#else
- +static int wlan_cfg80211_set_channel(struct wiphy *wiphy,
- + struct net_device *ndev,
- + struct ieee80211_channel *channel,
- + enum nl80211_channel_type channel_type)
- +#endif
- +{
- + int ret = -ENOTSUPP;
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- + vif = ndev_to_vif(ndev);
- + vif_id = vif->id;
- + if(ITM_NONE_MODE == vif->mode)
- + return -EAGAIN;
- + printkd("[%s][%d] enter\n", __func__, vif_id);
- + /*
- + * FIXME: To be handled properly when monitor mode is supported.
- + */
- + ret = wlan_cmd_set_channel(vif_id, ieee80211_frequency_to_channel(channel->center_freq) );
- + if (ret < 0)
- + {
- + printkd("wlan_cmd_set_channel failed with ret %d\n", ret);
- + return ret;
- + }
- +
- + return 0;
- +}
- +int wlan_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_update_ft_ies_params *ftie)
- +{
- + wlan_vif_t *vif;
- + unsigned char vif_id;
- + vif = ndev_to_vif(ndev);
- + vif_id = vif->id;
- + printkd("%s enter\n", __func__);
- + return wlan_cmd_update_ft_ies(vif_id, ftie);
- +}
- +
- +int lte_concur_proc_open(struct inode *inode, struct file *filp)
- +{
- + return 0;
- +}
- +
- +int lte_concur_proc_release(struct inode *inode, struct file *filp)
- +{
- + return 0;
- +}
- +/* support of 32bit userspace on 64bit platforms */
- +#ifdef CONFIG_COMPAT
- +#define COMPAT_LTE_CONCUR_REQ _IO(0, LTE_CONCUR_REQ)
- +long compat_lte_concur_proc_ioctl(struct file *file, unsigned int cmd,
- + unsigned long arg)
- +{
- + switch (cmd) {
- + case COMPAT_LTE_CONCUR_REQ:
- + cmd = LTE_CONCUR_REQ;
- + break;
- + }
- + return lte_concur_proc_ioctl(file, cmd, arg);
- +}
- +#endif
- +long lte_concur_proc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
- +{
- + int ret = 0;
- + lte_concur_data_t *val;
- + unsigned char buff[100];
- + int len;
- +
- + switch (cmd) {
- + case LTE_CONCUR_REQ:
- + if (copy_from_user(buff, (unsigned char *)arg,
- + ((lte_concur_data_t *)arg)->size + sizeof(lte_concur_data_t))) {
- + return -EFAULT;
- + }
- +
- + val = (lte_concur_data_t *)buff;
- + len = val->size;
- + ret = wlan_cmd_req_lte_concur(0, (unsigned char *)val + sizeof(lte_concur_data_t), len);
- + if (ret < 0) {
- + printkd("wlan_cmd_req_lte_concur failed with ret %d\n", ret);
- + return ret;
- + }
- + break;
- + default:
- + break;
- + }
- + return 0;
- +}
- +
- +
- +static struct cfg80211_ops wlan_cfg80211_ops =
- +{
- + .scan = wlan_cfg80211_scan,
- + .connect = wlan_cfg80211_connect,
- + .disconnect = wlan_cfg80211_disconnect,
- + .add_key = wlan_cfg80211_add_key,
- + .del_key = wlan_cfg80211_del_key,
- + .set_default_key = wlan_cfg80211_set_default_key,
- + .set_wiphy_params = wlan_cfg80211_set_wiphy_params,
- + .get_station = wlan_cfg80211_get_station,
- + .set_pmksa = wlan_cfg80211_set_pmksa,
- + .del_pmksa = wlan_cfg80211_del_pmksa,
- + .flush_pmksa = wlan_cfg80211_flush_pmksa,
- + .start_ap = wlan_cfg80211_start_ap,
- + .change_beacon = wlan_cfg80211_change_beacon,
- + .stop_ap = wlan_cfg80211_stop_ap,
- + .mgmt_tx = wlan_cfg80211_mgmt_tx,
- + .mgmt_frame_register = wlan_cfg80211_mgmt_frame_register,
- + .change_virtual_intf = wlan_cfg80211_change_iface,
- + .update_ft_ies = wlan_cfg80211_update_ft_ies,
- +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
- + .libertas_set_mesh_channel = wlan_cfg80211_set_channel,
- +#else
- + .set_channel = wlan_cfg80211_set_channel,
- +#endif
- +
- +#ifdef WIFI_DIRECT_SUPPORT
- + .remain_on_channel = wlan_cfg80211_remain_on_channel,
- + .cancel_remain_on_channel = wlan_cfg80211_cancel_remain_on_channel,
- + .del_station = wlan_cfg80211_del_station,
- +#endif
- +};
- +
- +/*Init wiphy parameters*/
- +static void init_wiphy_parameters(struct wiphy *wiphy)
- +{
- + wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
- + wiphy->mgmt_stypes = itm_mgmt_stypes;
- +
- + wiphy->max_scan_ssids = MAX_SITES_FOR_SCAN;
- + wiphy->max_scan_ie_len = SCAN_IE_LEN_MAX;
- + wiphy->max_num_pmkids = MAX_NUM_PMKIDS;
- +
- + wiphy->interface_modes = BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP);
- +
- + wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_DEVICE);
- + wiphy->max_remain_on_channel_duration = 5000;
- + wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
- + /* set AP SME flag, also needed by STA mode? */
- + wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
- + wiphy->ap_sme_capa = 1;
- +
- + wiphy->software_iftypes = BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_DEVICE) ;
- + /*Attach cipher suites */
- + wiphy->cipher_suites = itm_cipher_suites;
- + wiphy->n_cipher_suites = ARRAY_SIZE(itm_cipher_suites);
- + /*Attach bands */
- + wiphy->bands[IEEE80211_BAND_2GHZ] = &itm_band_2ghz;
- + //wiphy->bands[IEEE80211_BAND_5GHZ] = &itm_band_5ghz;
- +
- + /*Default not in powersave state */
- + wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
- +#if defined(CONFIG_PM) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
- + /*Set WoWLAN flags */
- + wiphy->wowlan.flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_DISCONNECT;
- +#endif
- +}
- +
- +int wlan_wiphy_new(wlan_info_t *wlan)
- +{
- + int ret;
- + printke("%s enter\n", __func__);
- + wlan->wiphy = wiphy_new(&wlan_cfg80211_ops, 0);
- + if (wlan->wiphy == NULL)
- + {
- + ASSERT();
- + return ERROR;
- + }
- + *(wlan_info_t **)wiphy_priv(wlan->wiphy) = wlan;
- + set_wiphy_dev(wlan->wiphy, wlan->dev );
- + init_wiphy_parameters(wlan->wiphy);
- + ret = wiphy_register(wlan->wiphy);
- + if(ret < 0)
- + {
- + printke("%s err:%d\n", __func__, ret);
- + ASSERT();
- + goto out_free_wiphy;
- + }
- + return OK;
- +out_free_wiphy:
- + wiphy_free(wlan->wiphy);
- + return ERROR;
- +}
- +
- +int wlan_wiphy_free(wlan_info_t *wlan)
- +{
- + int i;
- + wlan_vif_t *vif;
- + if(NULL == wlan)
- + return ERROR;
- + for(i=0; i<2; i++)
- + {
- + vif = &(g_wlan.netif[i]);
- + if ( vif->cfg80211.scan_request && (atomic_add_unless(&vif->cfg80211.scan_status, 1, 1) == 1) )
- + {
- + if (vif->cfg80211.scan_request->wiphy != vif->wdev.wiphy)
- + {
- + printkd("Scan request is from a wrong wiphy device\n");
- + }
- + else
- + {
- + /*If there's a pending scan request,abort it */
- + cfg80211_scan_done(vif->cfg80211.scan_request, 1);
- + }
- + vif->cfg80211.scan_request = NULL;
- + if ( vif->cfg80211.scan_done_lock.link.next != LIST_POISON1 && vif->cfg80211.scan_done_lock.link.prev != LIST_POISON2 )
- + wake_unlock(&vif->cfg80211.scan_done_lock);
- + atomic_dec(&vif->cfg80211.scan_status);
- + }
- + wake_lock_destroy(&vif->cfg80211.scan_done_lock);
- + del_timer_sync(&( vif->cfg80211.scan_timeout) );
- + vfree(vif->cfg80211.scan_frame_array);
- + vif->cfg80211.scan_frame_array = NULL;
- + }
- + wiphy_unregister(wlan->wiphy);
- + wiphy_free(wlan->wiphy);
- + wlan->wiphy = NULL;
- + return OK;
- +}
- +
- +int mac_addr_cfg(wlan_vif_t *vif, unsigned char vif_id)
- +{
- + struct file *fp = 0;
- + mm_segment_t fs;
- + loff_t *pos;
- + bool no_file = false;
- + unsigned char file_data[64] = { 0 };
- + unsigned char mac_addr[18] = { 0 };
- + unsigned char *tmp_p = NULL;
- + fs = get_fs();
- + set_fs(KERNEL_DS);
- +
- + fp = filp_open(ENG_MAC_ADDR_PATH, O_RDONLY, 0);
- + if (IS_ERR(fp))
- + {
- + random_ether_addr(vif->ndev->dev_addr);
- + fp = filp_open( ENG_MAC_ADDR_PATH, O_CREAT | O_RDWR, 0666 );
- + if (IS_ERR(fp) )
- + {
- + printke("%s %d err\n", __func__, __LINE__);
- + goto EXIT;
- + }
- + no_file = true;
- + }
- + pos = &(fp->f_pos);
- + if(false == no_file)
- + {
- + tmp_p = file_data;
- + vfs_read(fp, file_data, sizeof(file_data), pos);
- + memcpy(mac_addr, tmp_p, 18);
- + sscanf(mac_addr, "%02x:%02x:%02x:%02x:%02x:%02x",
- + (unsigned int *)&(vif->ndev->dev_addr[0]),
- + (unsigned int *)&(vif->ndev->dev_addr[1]),
- + (unsigned int *)&(vif->ndev->dev_addr[2]),
- + (unsigned int *)&(vif->ndev->dev_addr[3]),
- + (unsigned int *)&(vif->ndev->dev_addr[4]),
- + (unsigned int *)&(vif->ndev->dev_addr[5]));
- + }
- + else
- + {
- + sprintf(mac_addr, "%02x:%02x:%02x:%02x:%02x:%02x",
- + vif->ndev->dev_addr[0],
- + vif->ndev->dev_addr[1],
- + vif->ndev->dev_addr[2],
- + vif->ndev->dev_addr[3],
- + vif->ndev->dev_addr[4],
- + vif->ndev->dev_addr[4] );
- + vfs_write(fp, mac_addr, 18, pos);
- + printke("[%s write addr:%s]\n", __func__, mac_addr);
- + }
- + vif->ndev->dev_addr[5] = vif->ndev->dev_addr[5] + vif_id;
- +
- +EXIT:
- + if( ! (IS_ERR(fp)) )
- + {
- + filp_close(fp, NULL);
- + }
- + set_fs(fs);
- + return OK;
- +}
- +
- +int wlan_vif_init(wlan_vif_t *vif, int type, const char *name, void *ops)
- +{
- + int ret;
- + void **net_priv;
- + struct net_device *ndev;
- + unsigned char str[64] = {0};
- + ndev = alloc_netdev(sizeof(void *), name, ether_setup);
- + if (!ndev)
- + {
- + ASSERT();
- + return ERROR;
- + }
- + vif->ndev = ndev;
- + net_priv = netdev_priv(ndev);
- + *net_priv = vif;
- + ndev->netdev_ops = ops;
- + ndev->watchdog_timeo = 1*HZ;
- + ndev->ieee80211_ptr = &(vif->wdev);
- + vif->wdev.iftype = type;
- + init_register_frame_param(vif);
- + init_send_deauth_work(vif);
- + vif->wdev.wiphy = g_wlan.wiphy;
- + SET_NETDEV_DEV(ndev, wiphy_dev(vif->wdev.wiphy));
- + vif->wdev.netdev = ndev;
- + init_timer(&(vif->cfg80211.scan_timeout));
- + vif->cfg80211.scan_timeout.data = (unsigned long)vif;
- + vif->cfg80211.scan_timeout.function = wlan_scan_timeout;
- + vif->cfg80211.scan_request = NULL;
- + vif->cfg80211.scan_frame_array = vmalloc( MAX_SCAN_FRAME_BUF_NUM * sizeof(buf_scan_frame_t) );
- + memset(vif->cfg80211.scan_frame_array, 0, MAX_SCAN_FRAME_BUF_NUM * sizeof(buf_scan_frame_t) );
- + atomic_set(&vif->cfg80211.scan_status, 0);
- + vif->cfg80211.connect_status = ITM_DISCONNECTED;
- + memset(vif->cfg80211.bssid, 0, sizeof(vif->cfg80211.bssid));
- + vif->mode = ITM_NONE_MODE;
- + wake_lock_init(&(vif->cfg80211.scan_done_lock), WAKE_LOCK_SUSPEND, "scan_lock");
- + mac_addr_cfg(vif, vif->id);
- + ret = register_netdev(vif->ndev);
- + if(ret < 0 )
- + {
- + printkd("[%s][register_netdev err:%d]\n", __func__, ret);
- + return ERROR;
- + }
- + sprintf(str, "[%s][%d][%s][0x%p][addr]:", __func__, vif->id, vif->ndev->name, vif->ndev);
- + hex_dump(str, strlen(str), (unsigned char *)(&(vif->ndev->dev_addr[0])) , 6 );
- + return OK;
- +}
- +
- +int wlan_vif_free(wlan_vif_t *vif)
- +{
- + if(NULL == vif->ndev)
- + return ERROR;
- + printkd("[unregister_netdev][%s][0x%p]\n", __func__, vif->ndev->name);
- + cancel_work_sync(&vif->cfg80211.deauth_info.work);
- + unregister_netdev(vif->ndev);
- + printkd("[free_netdev][%s][0x%p]\n", __func__, vif->ndev->name);
- + free_netdev(vif->ndev);
- + printkd("%s(), ok\n", __func__);
- + return OK;
- +}
- +
- +wlan_vif_t *id_to_vif(unsigned char id)
- +{
- + if( (NETIF_0_ID != id) && (NETIF_1_ID != id) )
- + return NULL;
- + return &(g_wlan.netif[id]);
- +}
- diff --git a/drivers/net/wireless/sprdwl/wlan_cfg80211.h b/drivers/net/wireless/sprdwl/wlan_cfg80211.h
- new file mode 100644
- index 0000000..c349473
- --- /dev/null
- +++ b/drivers/net/wireless/sprdwl/wlan_cfg80211.h
- @@ -0,0 +1,132 @@
- +#ifndef __WLAN_CFG80211_H__
- +#define __WLAN_CFG80211_H__
- +
- +#define WIFI_DIRECT_SUPPORT
- +#define WLAN_11R_SUPPORT
- +
- +#define IP_TYPE 0x0800
- +/* auth type */
- +#define ITM_AUTH_OPEN 0
- +#define ITM_AUTH_SHARED 1
- +/*cipher type*/
- +#define NONE 0
- +#define WEP40 1
- +#define WEP104 2
- +#define TKIP 3
- +#define CCMP 4
- +#define AP_TKIP 5
- +#define AP_CCMP 6
- +#define WAPI 7
- +/*AKM suite*/
- +#define AKM_SUITE_PSK (1)
- +#define AKM_SUITE_8021X (2)
- +#define AKM_SUITE_FT_8021X (3)
- +#define AKM_SUITE_FT_PSK (4)
- +#define AKM_SUITE_WAPI_PSK (4)
- +#define AKM_SUITE_WAPI_CERT (12)
- +
- +#define P2P_IE_ID 221
- +#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
- +#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
- +#define WLAN_11R_MD_IE_ID 0x36
- +#define WLAN_11R_FT_IE_ID 0x37
- +#define P2P_IE_OUI_BYTE0 0x50
- +#define P2P_IE_OUI_BYTE1 0x6F
- +#define P2P_IE_OUI_BYTE2 0x9A
- +#define P2P_IE_OUI_TYPE 0x09
- +/*FIXME: determine the actual values for the macros below*/
- +#define SCAN_IE_LEN_MAX 2304
- +#define MAX_NUM_PMKIDS 4
- +#define MAX_SITES_FOR_SCAN 12
- +#define WLAN_MAX_SSID_SIZE 32
- +#define WLAN_MAX_KEY_INDEX 3
- +#define ITM_SCAN_TIMER_INTERVAL_MS 8000
- +/* parise or group key type */
- +#define GROUP 0
- +#define PAIRWISE 1
- +#define HOSTAP_CONF_FILE_NAME "/data/misc/wifi/hostapd.conf"
- +#define ENG_MAC_ADDR_PATH "/data/misc/wifi/wifimac.txt"
- +
- +#define MAX_SCAN_FRAME_BUF_NUM (30)
- +#define LTE_CONCUR_REQ (100)
- +
- +enum wlan_mode
- +{
- + ITM_NONE_MODE,
- + ITM_STATION_MODE,
- + ITM_AP_MODE,
- + ITM_NPI_MODE,
- + ITM_P2P_CLIENT_MODE,
- + ITM_P2P_GO_MODE,
- +};
- +
- +enum WPS_TYPE
- +{
- + WPS_REQ_IE=1,
- + WPS_ASSOC_IE,
- + P2P_ASSOC_IE,
- + P2P_BEACON_IE,
- + P2P_PROBERESP_IE,
- + P2P_ASSOCRESP_IE,
- + P2P_BEACON_IE_HEAD,
- + P2P_BEACON_IE_TAIL
- +};
- +
- +enum wlan_state
- +{
- + ITM_UNKOWN = 0,
- + ITM_SCANNING,
- + ITM_SCAN_ABORTING,
- + ITM_DISCONNECTED,
- + ITM_CONNECTING,
- + ITM_CONNECTED
- +};
- +
- +struct hostap_conf
- +{
- + char wpa_psk[128];
- + unsigned int len;
- +};
- +
- +typedef struct android_wifi_priv_cmd
- +{
- + char *buf;
- + int used_len;
- + int total_len;
- +} android_wifi_priv_cmd;
- +
- +typedef struct
- +{
- + unsigned char live;
- + unsigned char keep;
- + unsigned short channel;
- + signed short signal;
- + unsigned short msa_len;
- + unsigned char ssid[33];
- + unsigned char bssid[6];
- + unsigned char msa[1024];
- +}buf_scan_frame_t;
- +
- +typedef struct
- +{
- + unsigned int size;
- +}lte_concur_data_t;
- +
- +extern void cfg80211_report_connect_result(unsigned char vif_id, unsigned char *pData, int len);
- +extern void cfg80211_report_disconnect_done(unsigned char vif_id, unsigned char *pData, int len);
- +extern void cfg80211_report_scan_done(unsigned char vif_id, unsigned char *pData, int len, bool aborted);
- +extern void cfg80211_report_mgmt_deauth(unsigned char vif_id, unsigned char *data, unsigned short len);
- +extern void cfg80211_report_mgmt_disassoc(unsigned char vif_id, unsigned char *data, unsigned short len );
- +extern void cfg80211_report_remain_on_channel_expired(unsigned char vif_id, unsigned char *data, unsigned short len);
- +extern void cfg80211_report_new_station(unsigned char vif_id, unsigned char *data, unsigned short len );
- +extern void cfg80211_report_frame(unsigned char vif_id, unsigned char *data, unsigned short len);
- +extern void cfg80211_report_scan_frame(unsigned char vif_id, unsigned char *pData, int len);
- +extern void cfg80211_report_mic_failure(unsigned char vif_id, unsigned char *pdata, int len);
- +extern int lte_concur_proc_open(struct inode *inode, struct file *filp) ;
- +extern int lte_concur_proc_release(struct inode *inode, struct file *filp);
- +extern long lte_concur_proc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
- +#ifdef CONFIG_COMPAT
- +extern long compat_lte_concur_proc_ioctl(struct file *file, unsigned int cmd,
- + unsigned long arg);
- +#endif
- +#endif
- diff --git a/drivers/net/wireless/sprdwl/wlan_cmd.c b/drivers/net/wireless/sprdwl/wlan_cmd.c
- new file mode 100644
- index 0000000..00e1a40
- --- /dev/null
- +++ b/drivers/net/wireless/sprdwl/wlan_cmd.c
- @@ -0,0 +1,920 @@
- +/*
- + * Copyright (C) 2014 Spreadtrum Communications Inc.
- + *
- + * Authors:<jinglong.chen@spreadtrum.com>
- + * Owner:
- + * jinglong.chen
- + *
- + * This software is licensed under the terms of the GNU General Public
- + * License version 2, as published by the Free Software Foundation, and
- + * may be copied, distributed, and modified under those terms.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + */
- +
- +#include "wlan_common.h"
- +#include "wlan_cmd.h"
- +#include "wlan_cfg80211.h"
- +#define CMD_WAIT_TIMEOUT (3000)
- +#define CMD_ITEM(CMD) { CMD, (#CMD) }
- +typedef struct
- +{
- + unsigned short id;
- + char *cmd;
- +}cmd_t;
- +
- +static cmd_t g_cmd_table[] =
- +{
- + CMD_ITEM(WIFI_CMD_GET_MODE),
- + CMD_ITEM(WIFI_CMD_GET_RSSI),
- + CMD_ITEM(WIFI_CMD_GET_TXRATE_TXFAILED),
- + CMD_ITEM(WIFI_CMD_SET_SCAN),
- + CMD_ITEM(WIFI_CMD_SET_AUTH_TYPE),
- + CMD_ITEM(WIFI_CMD_SET_WPA_VERSION),
- + CMD_ITEM(WIFI_CMD_SET_PAIRWISE_CIPHER),
- + CMD_ITEM(WIFI_CMD_SET_GROUP_CIPHER),
- + CMD_ITEM(WIFI_CMD_SET_AKM_SUITE),
- + CMD_ITEM(WIFI_CMD_SET_CHANNEL),
- + CMD_ITEM(WIFI_CMD_SET_BSSID),
- + CMD_ITEM(WIFI_CMD_SET_ESSID),
- + CMD_ITEM(WIFI_CMD_KEY_ADD),
- + CMD_ITEM(WIFI_CMD_KEY_DEL),
- + CMD_ITEM(WIFI_CMD_KEY_SET),
- + CMD_ITEM(WIFI_CMD_SET_DISCONNECT),
- + CMD_ITEM(WIFI_CMD_SET_RTS_THRESHOLD),
- + CMD_ITEM(WIFI_CMD_SET_FRAG_THRESHOLD),
- + CMD_ITEM(WIFI_CMD_SET_PMKSA),
- + CMD_ITEM(WIFI_CMD_DEL_PMKSA),
- + CMD_ITEM(WIFI_CMD_FLUSH_PMKSA),
- + CMD_ITEM(WIFI_CMD_SET_DEV_OPEN),
- + CMD_ITEM(WIFI_CMD_SET_DEV_CLOSE),
- + CMD_ITEM(WIFI_CMD_SET_PSK),
- + CMD_ITEM(WIFI_CMD_START_BEACON),
- + CMD_ITEM(WIFI_CMD_SET_WPS_IE),
- + CMD_ITEM(WIFI_CMD_TX_MGMT),
- + CMD_ITEM(WIFI_CMD_REMAIN_CHAN),
- + CMD_ITEM(WIFI_CMD_CANCEL_REMAIN_CHAN),
- + CMD_ITEM(WIFI_CMD_P2P_IE),
- + CMD_ITEM(WIFI_CMD_CHANGE_BEACON),
- + CMD_ITEM(WIFI_CMD_REGISTER_FRAME),
- + CMD_ITEM(WIFI_CMD_NPI_MSG),
- + CMD_ITEM(WIFI_CMD_SET_FT_IE),
- + CMD_ITEM(WIFI_EVENT_CONNECT),
- + CMD_ITEM(WIFI_EVENT_DISCONNECT),
- + CMD_ITEM(WIFI_EVENT_SCANDONE),
- + CMD_ITEM(WIFI_EVENT_MGMT_DEAUTH),
- + CMD_ITEM(WIFI_EVENT_MGMT_DISASSOC),
- + CMD_ITEM(WIFI_EVENT_REMAIN_ON_CHAN_EXPIRED),
- + CMD_ITEM(WIFI_EVENT_NEW_STATION),
- + CMD_ITEM(WIFI_EVENT_REPORT_FRAME),
- + CMD_ITEM(WIFI_EVENT_CONNECT_AP),
- + CMD_ITEM(WIFI_CMD_ASSERT),
- + CMD_ITEM(WIFI_EVENT_SDIO_SEQ_NUM),
- + CMD_ITEM(WIFI_CMD_MAX),
- + CMD_ITEM(WIFI_EVENT_REPORT_SCAN_FRAME),
- + CMD_ITEM(WIFI_CMD_SLEEP),
- + CMD_ITEM(WIFI_CMD_GET_IP),
- + CMD_ITEM(WIFI_EVENT_REPORT_MIC_FAIL),
- + CMD_ITEM(WIFI_CMD_REQ_LTE_CONCUR),
- +};
- +char * get_cmd_name(int id)
- +{
- + int i;
- + int id_num = sizeof(g_cmd_table)/sizeof(cmd_t);
- + for( i=0; i < id_num; i++ )
- + {
- + if(id == g_cmd_table[i].id )
- + {
- + return g_cmd_table[i].cmd;
- + }
- + }
- + return "NULL";
- +}
- +
- +int wlan_cmd_init(void )
- +{
- + wlan_cmd_t *cmd = &(g_wlan.cmd);
- + cmd->mem = kmalloc( 8* 1024, GFP_KERNEL);
- + mutex_init( &(cmd->cmd_lock) );
- + init_waitqueue_head(&(cmd->waitQ));
- + cmd->wakeup = 0;
- + return OK;
- +}
- +
- +int wlan_cmd_deinit(void )
- +{
- + wlan_cmd_t *cmd = &(g_wlan.cmd);
- + if(NULL != cmd->mem)
- + {
- + kfree(cmd->mem);
- + cmd->mem = NULL;
- + }
- + mutex_destroy(&(cmd->cmd_lock));
- + return OK;
- +
- +}
- +
- +int wlan_cmd_send_to_ic(unsigned char vif_id, unsigned char *pData, int len, int subtype)
- +{
- +
- + tx_msg_t *event;
- + m_event_t *event_q;
- + wlan_cmd_t *cmd;
- + cmd = &(g_wlan.cmd);
- + event_q = &(g_wlan.netif[vif_id].event_q[EVENT_Q_ID_0]);
- + printkd("[SEND_CMD][%d][%s]\n",vif_id, get_cmd_name(subtype));
- + event = alloc_event(event_q);
- + if(NULL == event)
- + {
- + printke("%s alloc_event err\n", __func__);
- + return ERROR;
- + }
- + memset((unsigned char *)event, 0, sizeof(tx_msg_t) );
- + if((0 == len) || (NULL == pData))
- + {
- + event->hdr.mode = vif_id;
- + event->hdr.len = 0;
- + event->hdr.type = HOST_SC2331_CMD;
- + event->hdr.subtype = subtype;
- + event->slice[0].data = NULL;
- + event->slice[0].len = 0;
- + }
- + else
- + {
- + event->hdr.mode = vif_id;
- + event->hdr.len = len;
- + event->hdr.type = HOST_SC2331_CMD;
- + event->hdr.subtype = subtype;
- + event->slice[0].data = pData;
- + event->slice[0].len = len;
- + }
- + post_event( (unsigned char *)event, event_q );
- + core_up();
- + return OK;
- +}
- +
- +int wlan_timeout_recv_rsp(unsigned char *r_buf, unsigned short *r_len, unsigned int timeout)
- +{
- + int ret;
- + r_msg_hdr_t *msg;
- + wlan_cmd_t *cmd = &(g_wlan.cmd);
- + ret = wait_event_timeout( cmd->waitQ, ((1 == cmd->wakeup)||(1 == g_wlan.sync.exit)), msecs_to_jiffies(timeout) );
- + cmd->wakeup = 0;
- + msg = (r_msg_hdr_t *)(cmd->mem);
- + if(0 == ret)
- + {
- + printke("[%s][%d][err]\n", __func__, __LINE__);
- + return -1;
- + }
- + if(*r_len < msg->len)
- + {
- + printke("[%s][%d][err]\n", __func__, __LINE__);
- + msg->len = *r_len;
- + }
- + *r_len = msg->len;
- + memcpy(r_buf, cmd->mem, sizeof(r_msg_hdr_t) + msg->len );
- + return 0;
- +}
- +
- +int wlan_cmd_send_recv(unsigned char vif_id, unsigned char *pData, int len, int subtype, int timeout)
- +{
- +
- + int ret = 0;
- + r_msg_hdr_t *msg;
- + struct wlan_cmd_rsp_state_code *state;
- + wlan_cmd_t *cmd = &(g_wlan.cmd);
- + unsigned char r_buf[sizeof(r_msg_hdr_t) + sizeof(struct wlan_cmd_rsp_state_code) ] = {0};
- + unsigned short r_len = sizeof(struct wlan_cmd_rsp_state_code) ;
- +
- + msg = (r_msg_hdr_t *)(&r_buf[0]);
- +
- + if(1 == g_wlan.sync.exit )
- + {
- + printke("%s, exit flag\n", __func__);
- + return ERROR;
- + }
- +
- + mutex_lock(&(cmd->cmd_lock));
- +
- + if( (NULL == pData) || (0 == len) )
- + ret = wlan_cmd_send_to_ic(vif_id, NULL, 0, subtype);
- + else
- + ret = wlan_cmd_send_to_ic(vif_id, pData, len, subtype);
- + if(OK != ret)
- + return ERROR;
- +
- + ret = wlan_timeout_recv_rsp(r_buf, &r_len, timeout);
- + if(-1 == ret)
- + {
- + printke("[SEND_CMD %s %d ERROR][rsp timeout]\n", get_cmd_name(subtype), vif_id);
- + }
- +
- + if( (SC2331_HOST_RSP != msg->type) || (subtype != msg->subtype) )
- + {
- + printke("[SEND_CMD %s %d ERROR][rsp match %s]\n", get_cmd_name(subtype), vif_id, get_cmd_name(msg->subtype));
- + ret = -1;
- + }
- + mutex_unlock(&(cmd->cmd_lock));
- +
- + if(-1 == ret)
- + {
- + wlan_cmd_assert(vif_id, 0);
- + return ERROR;
- + }
- + /*TODO state is not use*/
- + state = (struct wlan_cmd_rsp_state_code *)( &r_buf[ sizeof(r_msg_hdr_t)]) ;
- +
- + return OK;
- +}
- +
- +int wlan_cmd_start_ap(unsigned char vif_id, unsigned char *beacon, unsigned short len)
- +{
- + int ret;
- + unsigned short dataLen;
- + struct wlan_cmd_beacon_t *beacon_ptr;
- + dataLen = sizeof(struct wlan_cmd_beacon_t) + len ;
- + beacon_ptr = kmalloc( dataLen, GFP_KERNEL);
- + beacon_ptr->len = cpu_to_le16(len);
- + memcpy(beacon_ptr->value, beacon, len);
- + ret = wlan_cmd_send_recv(vif_id, (unsigned char *)beacon_ptr, dataLen, WIFI_CMD_START_BEACON, CMD_WAIT_TIMEOUT);
- + return ret;
- +}
- +
- +int wlan_cmd_register_frame(unsigned char vif_id, struct wlan_cmd_register_frame_t *data)
- +{
- + int ret;
- + struct wlan_cmd_register_frame_t *ptr;
- + unsigned short dataLen;
- + dataLen = sizeof(struct wlan_cmd_register_frame_t);
- + ptr = kmalloc( dataLen, GFP_KERNEL);
- + memcpy((unsigned char *)ptr, (unsigned char *)(data), dataLen);
- + ret = wlan_cmd_send_recv(vif_id, (unsigned char *)ptr, dataLen, WIFI_CMD_REGISTER_FRAME, CMD_WAIT_TIMEOUT);
- + return ret;
- +}
- +
- +int wlan_cmd_set_p2p_ie(unsigned char vif_id, u8 type, const u8 *ie, u16 len)
- +{
- + struct wlan_cmd_p2p_ie_t *p2p_ptr;
- + int ret;
- + unsigned short dataLen;
- +
- + if (type != P2P_ASSOC_IE && type != P2P_BEACON_IE &&
- + type != P2P_PROBERESP_IE && type != P2P_ASSOCRESP_IE &&
- + type !=P2P_BEACON_IE_HEAD && type !=P2P_BEACON_IE_TAIL) {
- + printke("%s wrong ie type is %d\n",__func__, type);
- + return -EIO;
- + }
- + printkd("%s type:%d ie_len:%d\n", __func__,type, len);
- + dataLen = sizeof(struct wlan_cmd_p2p_ie_t) + len;
- + p2p_ptr = kmalloc( dataLen, GFP_KERNEL);
- + p2p_ptr->type = type;
- + p2p_ptr->len = cpu_to_le16(len);
- + memcpy(p2p_ptr->value, ie, len);
- + ret = wlan_cmd_send_recv(vif_id, (unsigned char *)p2p_ptr, dataLen, WIFI_CMD_P2P_IE, CMD_WAIT_TIMEOUT);
- + return ret;
- +}
- +
- +int wlan_cmd_set_ft_ie(unsigned char vif_id, const unsigned char *ies, unsigned short len)
- +{
- + unsigned char *ptr = NULL;
- + unsigned short dataLen = len + 2;
- +
- + ptr = kmalloc( dataLen, GFP_KERNEL);
- + *((unsigned short *)ptr) = len;
- + memcpy(ptr+2, ies, len);
- +
- + hex_dump("ftie:", strlen("ftie:"), ptr, dataLen);
- + return wlan_cmd_send_recv(vif_id, ptr, dataLen, WIFI_CMD_SET_FT_IE, CMD_WAIT_TIMEOUT);
- +}
- +
- +int wlan_cmd_set_tx_mgmt(unsigned char vif_id, struct ieee80211_channel *channel, unsigned int wait, const unsigned char *mac, size_t mac_len)
- +{
- + unsigned short dataLen;
- + struct wlan_cmd_mgmt_tx_t *mgmt_tx;
- + int ret;
- + unsigned char send_chan;
- +
- + dataLen = sizeof(struct wlan_cmd_mgmt_tx_t) + mac_len;
- + mgmt_tx = kmalloc( dataLen, GFP_KERNEL);
- + send_chan = ieee80211_frequency_to_channel(channel->center_freq);
- +
- +
- + mgmt_tx->chan = send_chan;
- + mgmt_tx->wait = cpu_to_le32(wait);
- + mgmt_tx->len = cpu_to_le32(mac_len);
- + memcpy(mgmt_tx->value, mac, mac_len);
- + ret = wlan_cmd_send_recv(vif_id, (unsigned char *)mgmt_tx, dataLen, WIFI_CMD_TX_MGMT, CMD_WAIT_TIMEOUT);
- + return ret;
- +}
- +
- +
- +
- +int wlan_cmd_remain_chan(unsigned char vif_id, struct ieee80211_channel *channel,
- + enum nl80211_channel_type channel_type,
- + unsigned int duration, u64 *cookie)
- +{
- + int ret;
- + unsigned short dataLen;
- + struct wlan_cmd_remain_chan_t *remain_chan;
- +
- + dataLen = sizeof(struct wlan_cmd_remain_chan_t);
- + remain_chan = kmalloc( dataLen, GFP_KERNEL);
- +
- + remain_chan->chan = ieee80211_frequency_to_channel(channel->center_freq);;
- + remain_chan->chan_type = channel_type;
- + remain_chan->duraion = cpu_to_le32(duration);
- + remain_chan->cookie = cpu_to_le64(*cookie);
- +
- + ret = wlan_cmd_send_recv(vif_id, (unsigned char *)remain_chan, dataLen, WIFI_CMD_REMAIN_CHAN, CMD_WAIT_TIMEOUT);
- + return ret;
- +}
- +int wlan_cmd_cancel_remain_chan(unsigned char vif_id, u64 cookie)
- +{
- +
- + int ret;
- + unsigned short dataLen;
- +
- + struct wlan_cmd_cancel_remain_chan_t *ptr;
- +
- +
- + dataLen = sizeof(struct wlan_cmd_cancel_remain_chan_t);
- +
- + ptr = kmalloc( dataLen, GFP_KERNEL);
- +
- + ptr->cookie = cpu_to_le64(cookie);
- +
- + ret = wlan_cmd_send_recv(vif_id, (unsigned char *)ptr, dataLen, WIFI_CMD_CANCEL_REMAIN_CHAN, CMD_WAIT_TIMEOUT);
- + return ret;
- +}
- +
- +int wlan_cmd_scan(unsigned char vif_id, const unsigned char *ssid, const unsigned char *channels, int len)
- +{
- + int dataLen;
- + struct wlan_cmd_scan *ptr;
- +
- + dataLen = sizeof(struct wlan_cmd_scan) + len;
- + ptr = kmalloc( dataLen, GFP_KERNEL);
- + //memcpy((char *)ptr, channels, 16);
- + ptr->len = cpu_to_le32(len);
- + memcpy(ptr->ssid, ssid, len);
- +
- + wlan_cmd_send_recv(vif_id, (unsigned char *)ptr, dataLen, WIFI_CMD_SET_SCAN, CMD_WAIT_TIMEOUT);
- + return 0;
- +}
- +
- +int wlan_cmd_set_wpa_version(unsigned char vif_id, unsigned int wpa_version)
- +{
- + int dataLen;
- + struct wlan_cmd_set_wpa_version *ptr;
- +
- + dataLen = sizeof(struct wlan_cmd_set_wpa_version);
- + ptr = kmalloc( dataLen, GFP_KERNEL);
- +
- + ptr->wpa_version = cpu_to_le32(wpa_version);
- +
- + wlan_cmd_send_recv(vif_id, (unsigned char *)ptr, dataLen, WIFI_CMD_SET_WPA_VERSION, CMD_WAIT_TIMEOUT);
- + return 0;
- +}
- +
- +int wlan_cmd_set_auth_type(unsigned char vif_id, unsigned int type)
- +{
- + int dataLen;
- + struct wlan_cmd_set_auth_type *ptr;
- +
- + dataLen = sizeof(struct wlan_cmd_set_auth_type);
- + ptr = kmalloc( dataLen, GFP_KERNEL);
- + ptr->type = cpu_to_le32(type);
- +
- + wlan_cmd_send_recv(vif_id, (unsigned char *)ptr, dataLen, WIFI_CMD_SET_AUTH_TYPE, CMD_WAIT_TIMEOUT);
- + return 0;
- +}
- +
- +/* unicast cipher or group cipher */
- +int wlan_cmd_set_cipher(unsigned char vif_id, unsigned int cipher, unsigned char cmd_id)
- +{
- + int dataLen;
- + struct wlan_cmd_set_cipher *ptr;
- +
- + dataLen = sizeof(struct wlan_cmd_set_cipher);
- + if ((cmd_id != WIFI_CMD_SET_PAIRWISE_CIPHER) && (cmd_id != WIFI_CMD_SET_GROUP_CIPHER))
- + {
- + printkd("not support this type cipher \n");
- + return -EINVAL;
- + }
- + ptr = kmalloc( dataLen, GFP_KERNEL);
- + ptr->cipher = cpu_to_le32(cipher);
- +
- + wlan_cmd_send_recv(vif_id, (unsigned char *)ptr, dataLen, cmd_id, CMD_WAIT_TIMEOUT);
- + return 0;
- +
- +}
- +
- +int wlan_cmd_set_key_management(unsigned char vif_id, unsigned char key_mgmt)
- +{
- + int dataLen;
- + struct wlan_cmd_set_key_management *ptr;
- +
- + dataLen = sizeof(struct wlan_cmd_set_key_management);
- + ptr = kmalloc( dataLen, GFP_KERNEL);
- + /*TODO key_mgmt is u8, but ptr->key_mgmt is __le32*/
- + ptr->key_mgmt = key_mgmt;
- +
- + wlan_cmd_send_recv(vif_id, (unsigned char *)ptr, dataLen, WIFI_CMD_SET_AKM_SUITE, CMD_WAIT_TIMEOUT);
- + return 0;
- +}
- +
- +int wlan_cmd_set_psk(unsigned char vif_id, const unsigned char *key, unsigned int key_len)
- +{
- + int dataLen;
- + struct wlan_cmd_set_psk *ptr;
- +
- + dataLen = sizeof(struct wlan_cmd_set_psk) + key_len ;
- + ptr = kmalloc( dataLen, GFP_KERNEL);
- + /*TODO key_len is u32, but ptr->len is __le16*/
- + ptr->len = (__le16)cpu_to_le32(key_len);
- + memcpy(ptr->key, key, key_len);
- +
- + wlan_cmd_send_recv(vif_id, (unsigned char *)ptr, dataLen, WIFI_CMD_SET_PSK, CMD_WAIT_TIMEOUT);
- +
- + return 0;
- +}
- +
- +int wlan_cmd_set_channel(unsigned char vif_id, unsigned int channel)
- +{
- + int dataLen;
- + struct wlan_cmd_set_channel *ptr;
- +
- + dataLen = sizeof(struct wlan_cmd_set_channel);
- + ptr = kmalloc( dataLen, GFP_KERNEL);
- + ptr->channel = cpu_to_le32(channel);
- +
- + wlan_cmd_send_recv(vif_id, (unsigned char *)ptr, dataLen, WIFI_CMD_SET_CHANNEL, CMD_WAIT_TIMEOUT);
- + return 0;
- +}
- +
- +int wlan_cmd_set_bssid(unsigned char vif_id, const unsigned char *addr)
- +{
- + int dataLen;
- + struct wlan_cmd_set_bssid *ptr;
- +
- + dataLen = sizeof(struct wlan_cmd_set_bssid);
- + ptr = kmalloc( dataLen, GFP_KERNEL);
- + memcpy(&(ptr->addr[0]), addr, 6);
- +
- + wlan_cmd_send_recv(vif_id, (unsigned char *)ptr, dataLen, WIFI_CMD_SET_BSSID, CMD_WAIT_TIMEOUT);
- + return 0;
- +}
- +
- +int wlan_cmd_get_ip(unsigned char vif_id, u8 *ip)
- +{
- + int dataLen;
- + struct wlan_cmd_get_ip *ptr;
- +
- + dataLen = sizeof(struct wlan_cmd_get_ip);
- + ptr = kmalloc( dataLen, GFP_KERNEL);
- + memcpy(&(ptr->ip[0]), ip, 4);
- + hex_dump("inetaddr ip", strlen("inetaddr ip"), ip, 4);
- +
- + wlan_cmd_send_recv(vif_id, (unsigned char *)ptr, dataLen, WIFI_CMD_GET_IP, CMD_WAIT_TIMEOUT);
- + return 0;
- +}
- +
- +int wlan_cmd_set_essid(unsigned char vif_id, const unsigned char *essid, int essid_len)
- +{
- +
- + int dataLen;
- + struct wlan_cmd_set_essid *ptr;
- +
- + dataLen = sizeof(struct wlan_cmd_set_essid) + essid_len;
- + ptr = kmalloc( dataLen, GFP_KERNEL);
- + /*TODO essid_len is int, but ptr->len is __le16*/
- + ptr->len = (__le16)cpu_to_le32(essid_len);
- + memcpy(ptr->essid, essid, essid_len);
- +
- + return wlan_cmd_send_recv(vif_id, (unsigned char *)ptr, dataLen, WIFI_CMD_SET_ESSID, CMD_WAIT_TIMEOUT);
- +}
- +
- +int wlan_cmd_req_lte_concur(unsigned char vif_id, const unsigned char *val, int len)
- +{
- + unsigned char *ptr;
- + ptr = kmalloc( len, GFP_KERNEL);
- + memcpy(ptr, val, len);
- + wlan_cmd_send_recv(vif_id, (unsigned char *)ptr, len, WIFI_CMD_REQ_LTE_CONCUR, CMD_WAIT_TIMEOUT);
- + return 0;
- +}
- +
- +int wlan_cmd_pmksa(unsigned char vif_id, const unsigned char *bssid, const unsigned char *pmkid, unsigned char type)
- +{
- + int dataLen;
- + struct wlan_cmd_pmkid *cmd;
- +
- + dataLen = sizeof(struct wlan_cmd_pmkid);
- + cmd = kmalloc( dataLen, GFP_KERNEL);
- + memset((unsigned char *)cmd, 0, dataLen );
- + if(NULL != bssid)
- + memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
- + if (pmkid)
- + memcpy(cmd->pmkid, pmkid, sizeof(cmd->pmkid));
- +
- + wlan_cmd_send_recv(vif_id, (unsigned char *)cmd, dataLen, type, CMD_WAIT_TIMEOUT);
- + return 0;
- +}
- +
- +int wlan_cmd_disconnect(unsigned char vif_id, unsigned short reason_code)
- +{
- +
- + int dataLen;
- + struct wlan_cmd_disconnect *ptr;
- +
- + dataLen = sizeof(struct wlan_cmd_disconnect);
- + ptr = kmalloc( dataLen, GFP_KERNEL);
- + ptr->reason_code = cpu_to_le16(reason_code);
- +
- + wlan_cmd_send_recv(vif_id, (unsigned char *)ptr, dataLen, WIFI_CMD_SET_DISCONNECT, CMD_WAIT_TIMEOUT);
- + return 0;
- +}
- +
- +int wlan_cmd_add_key(unsigned char vif_id, const unsigned char *key_data, unsigned char key_len,
- + unsigned char pairwise, unsigned char key_index, const unsigned char *key_seq,
- + unsigned char cypher_type, const unsigned char *pmac)
- +{
- +
- + int dataLen;
- + struct wlan_cmd_add_key *ptr;
- +
- + dataLen = sizeof(struct wlan_cmd_add_key)+key_len;
- + ptr = kmalloc( dataLen, GFP_KERNEL);
- + memset(ptr, 0, dataLen);
- +
- + ptr->cypher_type = cypher_type;
- + if (key_seq != NULL)
- + memcpy(ptr->keyseq, key_seq, 8);
- + ptr->key_index = key_index;
- + ptr->key_len = key_len;
- + if (pmac != NULL)
- + memcpy(ptr->mac, pmac, 6);
- + ptr->pairwise = pairwise;
- + if(NULL != key_data)
- + memcpy(ptr->value, key_data, key_len);
- +
- + wlan_cmd_send_recv(vif_id, (unsigned char *)ptr, dataLen, WIFI_CMD_KEY_ADD, CMD_WAIT_TIMEOUT);
- +
- + return 0;
- +}
- +
- +int wlan_cmd_del_key(unsigned char vif_id, unsigned short key_index, const unsigned char *mac_addr)
- +{
- + int dataLen = 0;
- + struct wlan_cmd_del_key *ptr = NULL;
- +
- + dataLen = sizeof(struct wlan_cmd_del_key);
- + ptr = kmalloc( dataLen, GFP_KERNEL);
- + memset(ptr, 0, dataLen);
- + ptr->key_index = key_index;
- + if(NULL != mac_addr)
- + memcpy(&(ptr->mac[0]), mac_addr, 6);
- +
- + wlan_cmd_send_recv(vif_id, (unsigned char *)ptr, dataLen, WIFI_CMD_KEY_DEL, CMD_WAIT_TIMEOUT);
- +
- + return 0;
- +}
- +
- +int wlan_cmd_set_key(unsigned char vif_id, unsigned char key_index)
- +{
- +
- + int dataLen;
- + struct wlan_cmd_set_key *ptr;
- +
- + dataLen = sizeof(struct wlan_cmd_set_key);
- + ptr = kmalloc(dataLen, GFP_KERNEL);
- + ptr->key_index = cpu_to_le32(key_index);
- +
- + wlan_cmd_send_recv(vif_id, (unsigned char *)ptr, dataLen, WIFI_CMD_KEY_SET, CMD_WAIT_TIMEOUT);
- +
- + return OK;
- +}
- +
- +int wlan_cmd_set_rts(unsigned char vif_id, unsigned short rts_threshold)
- +{
- + int dataLen;
- + struct wlan_cmd_set_rts *ptr;
- + dataLen = sizeof(struct wlan_cmd_set_rts);
- + ptr = kmalloc(dataLen, GFP_KERNEL);
- + ptr->threshold = cpu_to_le16(rts_threshold);
- +
- + wlan_cmd_send_recv(vif_id, (unsigned char *)ptr, dataLen, WIFI_CMD_SET_RTS_THRESHOLD, CMD_WAIT_TIMEOUT);
- +
- + return OK;
- +}
- +
- +int wlan_cmd_set_frag(unsigned char vif_id, unsigned short frag_threshold)
- +{
- + struct wlan_cmd_set_frag *frag;
- +
- + frag = kmalloc(sizeof(struct wlan_cmd_set_frag), GFP_KERNEL);
- + frag->frag = cpu_to_le16(frag_threshold);
- +
- + wlan_cmd_send_recv(vif_id, (unsigned char *)frag, sizeof(struct wlan_cmd_set_frag), WIFI_CMD_SET_FRAG_THRESHOLD, CMD_WAIT_TIMEOUT);
- +
- + return 0;
- +}
- +
- +int wlan_cmd_set_wps_ie( unsigned char vif_id, unsigned char type, const unsigned char *ie, unsigned char len)
- +{
- + struct wlan_cmd_wps_ie *wps_ptr = NULL;
- +
- + wps_ptr = kmalloc(sizeof(struct wlan_cmd_wps_ie) + len, GFP_KERNEL);
- + wps_ptr->type = type;
- + wps_ptr->len = len;
- + memcpy(wps_ptr->value, ie, len);
- +
- + wlan_cmd_send_recv(vif_id, (unsigned char *)wps_ptr, sizeof(struct wlan_cmd_wps_ie) + len, WIFI_CMD_SET_WPS_IE, CMD_WAIT_TIMEOUT);
- +
- + return 0;
- +}
- +
- +int wlan_cmd_update_ft_ies( unsigned char vif_id, struct cfg80211_update_ft_ies_params *ft_ies)
- +{
- + int ret, dataLen;
- + struct wlan_cmd_ft_ies_params *ptr;
- + dataLen = sizeof(struct wlan_cmd_ft_ies_params) + ft_ies->ie_len;
- + ptr = kmalloc(dataLen, GFP_KERNEL);
- + if(NULL == ptr)
- + return -1;
- + ptr->md = cpu_to_le16(ft_ies->md);
- + ptr->ie_len = cpu_to_le16(ft_ies->ie_len);
- + memcpy(&(ptr->ie[0]), ft_ies->ie, ft_ies->ie_len);
- + hex_dump("update_ft_ie:", strlen("update_ft_ie:"), (unsigned char *)ptr, dataLen);
- + ret = wlan_cmd_send_recv(vif_id, (unsigned char *)ptr, dataLen, WIFI_CMD_UPDATE_FT_IE, CMD_WAIT_TIMEOUT);
- + return ret;
- +}
- +
- +int wlan_cmd_mac_open(unsigned char vif_id,
- + unsigned short mode, unsigned char *mac_addr)
- +{
- + int ret;
- + static int sync_flag = -1;
- + struct wlan_cmd_mac_open *open;
- + if(-1 == sync_flag)
- + {
- + g_wlan.hw.tx_cnt = 0;
- + g_wlan.hw.rx_cnt = 0;
- + g_wlan.hw.rx_record = 0;
- + sync_flag = 0;
- + }
- + open = kmalloc(sizeof(struct wlan_cmd_mac_open), GFP_KERNEL);
- + memset((unsigned char *)open, 0, sizeof(struct wlan_cmd_mac_open));
- + open->mode = cpu_to_le16(mode);
- +
- + if(NULL != mac_addr)
- + memcpy( (unsigned char *)(&(open->mac[0])), mac_addr, 6);
- + ret = wlan_cmd_send_recv(vif_id, (unsigned char *)open, sizeof(struct wlan_cmd_mac_open), WIFI_CMD_SET_DEV_OPEN, 8000);
- + return ret;
- +}
- +
- +int wlan_cmd_mac_close(unsigned char vif_id, unsigned char mode)
- +{
- + struct wlan_cmd_mac_close *close;
- + close = kmalloc(sizeof(struct wlan_cmd_mac_close), GFP_KERNEL);
- + close->mode = mode;
- + wlan_cmd_send_recv(vif_id, (unsigned char *)(close), sizeof(struct wlan_cmd_mac_close), WIFI_CMD_SET_DEV_CLOSE, CMD_WAIT_TIMEOUT);
- + return 0;
- +}
- +
- +int wlan_cmd_assert(unsigned char vif_id, unsigned int reason_code)
- +{
- + struct wlan_cmd_assert_t *assert_cmd = NULL;
- + unsigned int dataLen = sizeof(struct wlan_cmd_assert_t);
- +
- + assert_cmd = kmalloc(sizeof(struct wlan_cmd_assert_t), GFP_KERNEL);
- + assert_cmd->reason_code = cpu_to_le32(reason_code);
- + assert_cmd->tx_cnt = cpu_to_le32(g_wlan.hw.tx_cnt);
- + assert_cmd->rx_cnt = cpu_to_le32(g_wlan.hw.rx_cnt);
- + wlan_cmd_send_to_ic(vif_id, (unsigned char *)(assert_cmd), dataLen, WIFI_CMD_ASSERT);
- +
- + return 0;
- +}
- +
- +int wlan_cmd_sleep(int ops)
- +{
- + unsigned char *ops_code;
- + ops_code = (unsigned char *)kmalloc(4, GFP_KERNEL);
- + memcpy( ops_code, (unsigned char *)(&ops), 4);
- + wlan_cmd_send_to_ic(0, ops_code, 4, WIFI_CMD_SLEEP);
- + return 0;
- +}
- +
- +int wlan_cmd_get_rssi(unsigned char vif_id, unsigned char *signal, unsigned char *noise)
- +{
- + int ret;
- + r_msg_hdr_t *msg;
- + int *rssi = NULL;
- + wlan_cmd_t *cmd = &(g_wlan.cmd);
- + unsigned char r_buf[sizeof(r_msg_hdr_t) + 8 ] = {0};
- + unsigned short r_len = 8 ;
- + msg = (r_msg_hdr_t *)(&r_buf[0]);
- + if(1 == g_wlan.sync.exit )
- + {
- + printke("%s, exit flag\n", __func__);
- + return ERROR;
- + }
- + mutex_lock(&(cmd->cmd_lock));
- + ret = wlan_cmd_send_to_ic(vif_id, NULL, 0, WIFI_CMD_GET_RSSI);
- + ret = wlan_timeout_recv_rsp(r_buf, &r_len, CMD_WAIT_TIMEOUT);
- + if(-1 == ret)
- + {
- + printke("[SEND_CMD %s %d ERROR][rsp timeout]\n", get_cmd_name(WIFI_CMD_GET_RSSI), vif_id);
- + goto err;
- + }
- + if( (SC2331_HOST_RSP != msg->type) || (WIFI_CMD_GET_RSSI != msg->subtype) )
- + {
- + printke("[SEND_CMD %s %d ERROR][rsp match %s]\n", get_cmd_name(WIFI_CMD_GET_RSSI), vif_id, get_cmd_name(msg->subtype));
- + goto err;
- + }
- + else
- + {
- + rssi = (int *)( &r_buf[sizeof(r_msg_hdr_t) + 4] );
- + *signal = (unsigned char) (le32_to_cpu(*rssi) | 0xffff0000);
- + *noise = (unsigned char) ((le32_to_cpu(*rssi) | 0x0000ffff) >> 16);
- + }
- + mutex_unlock(&(cmd->cmd_lock));
- + return OK;
- +err:
- + wlan_cmd_assert(vif_id, 3);
- + mutex_unlock(&(cmd->cmd_lock));
- + return ERROR;
- +}
- +
- +int wlan_cmd_get_txrate_txfailed(unsigned char vif_id, unsigned int *rate, unsigned int *failed)
- +{
- + int ret;
- + r_msg_hdr_t *msg;
- + wlan_cmd_t *cmd = &(g_wlan.cmd);
- + unsigned char r_buf[sizeof(r_msg_hdr_t) + 12 ] = {0};
- + unsigned short r_len = 12;
- + msg = (r_msg_hdr_t *)(&r_buf[0]);
- + if(1 == g_wlan.sync.exit )
- + {
- + printke("%s, exit flag\n", __func__);
- + return ERROR;
- + }
- + mutex_lock(&(cmd->cmd_lock));
- + ret = wlan_cmd_send_to_ic(vif_id, NULL, 0, WIFI_CMD_GET_TXRATE_TXFAILED);
- + ret = wlan_timeout_recv_rsp(r_buf, &r_len, CMD_WAIT_TIMEOUT);
- + if(-1 == ret)
- + {
- + printke("[SEND_CMD %s %d ERROR][rsp timeout]\n", get_cmd_name(WIFI_CMD_GET_TXRATE_TXFAILED), vif_id);
- + goto err;
- + }
- + if( (SC2331_HOST_RSP != msg->type) || (WIFI_CMD_GET_TXRATE_TXFAILED != msg->subtype) )
- + {
- + printke("[SEND_CMD %s %d ERROR][rsp match %s]\n", get_cmd_name(WIFI_CMD_GET_TXRATE_TXFAILED), vif_id, get_cmd_name(msg->subtype));
- + goto err;
- + }
- + else
- + {
- + memcpy((unsigned char *)rate, &r_buf[sizeof(r_msg_hdr_t)+ 4], 4);
- + memcpy((unsigned char *)failed, &r_buf[sizeof(r_msg_hdr_t) + 8], 4);
- + *rate = le32_to_cpu(*rate);
- + *failed = le32_to_cpu(*failed);
- + }
- + mutex_unlock(&(cmd->cmd_lock));
- + return OK;
- +err:
- + mutex_unlock(&(cmd->cmd_lock));
- + return ERROR;
- +}
- +
- +int wlan_cmd_npi_send_recv(unsigned char *s_buf,unsigned short s_len, unsigned char *r_buf, unsigned short *r_len )
- +{
- + r_msg_hdr_t *msg;
- + int ret;
- + wlan_cmd_t *cmd = &(g_wlan.cmd);
- + unsigned char *s_data = NULL;
- +
- + s_data = kmalloc(s_len, GFP_KERNEL);
- + memcpy(s_data, s_buf, s_len);
- +
- + mutex_lock(&(cmd->cmd_lock));
- + ret = wlan_cmd_send_to_ic(0, s_data, s_len, WIFI_CMD_NPI_MSG);
- + if(1 == g_wlan.sync.exit)
- + {
- + printke("%s, exit flag\n", __func__);
- + goto err;
- + }
- + ret = wait_event_timeout( cmd->waitQ, ((1 == cmd->wakeup)||(1 == g_wlan.sync.exit)), msecs_to_jiffies(5000) );
- + cmd->wakeup = 0;
- + if(0 == ret)
- + {
- + printke("%s(), wait timeout\n", __func__);
- + goto err;
- + }
- + msg = (r_msg_hdr_t *)cmd->mem;
- + if((SC2331_HOST_RSP == msg->type) && (WIFI_CMD_NPI_MSG == msg->subtype))
- + {
- +
- + memcpy(r_buf, (unsigned char *)(cmd->mem) + sizeof(r_msg_hdr_t), msg->len );
- + *r_len = msg->len;
- + }
- + else
- + {
- + printke("[%s] rsp not match, rsp:[%s]\n", get_cmd_name(WIFI_CMD_NPI_MSG), get_cmd_name(msg->subtype));
- + goto err;
- + }
- + mutex_unlock(&(cmd->cmd_lock));
- + printkd("%s cmd ok!\n", get_cmd_name(WIFI_CMD_NPI_MSG) );
- + return OK;
- +err:
- + mutex_unlock(&(cmd->cmd_lock));
- + printke(" ################### %s(), ERROR ####################\n", get_cmd_name(WIFI_CMD_NPI_MSG));
- + g_dbg= 0xffffffff;
- + return ERROR;
- +
- +}
- +
- +int wlan_rx_rsp_process(const unsigned char vif_id, r_msg_hdr_t *msg)
- +{
- + wlan_cmd_t *cmd = &(g_wlan.cmd);
- +
- + printkd("[RECV_RSP][%d][%s][%d]\n",vif_id, get_cmd_name(msg->subtype), msg->len);
- + memcpy(cmd->mem, (unsigned char *)msg, msg->len + sizeof(r_msg_hdr_t) );
- + cmd->wakeup = 1;
- + wake_up(&(cmd->waitQ));
- + return OK;
- +}
- +
- +int wlan_rx_event_process(const unsigned char vif_id, unsigned char event, unsigned char *pData, unsigned short len)
- +{
- + if( (WIFI_EVENT_REPORT_SCAN_FRAME != event) && (WIFI_EVENT_SDIO_SEQ_NUM != event) )
- + printkd("[RECV_EVENT][%d][%s][%d]\n", vif_id, get_cmd_name(event), len);
- + switch(event)
- + {
- + case WIFI_EVENT_CONNECT:
- + cfg80211_report_connect_result(vif_id, pData, len);
- + break;
- + case WIFI_EVENT_DISCONNECT:
- + cfg80211_report_disconnect_done(vif_id, pData, len);
- + break;
- + case WIFI_EVENT_SCANDONE:
- + cfg80211_report_scan_done(vif_id, pData, len, false);
- + break;
- + case WIFI_EVENT_MGMT_DEAUTH:
- + cfg80211_report_mgmt_deauth(vif_id, pData, len);
- + break;
- + case WIFI_EVENT_MGMT_DISASSOC:
- + cfg80211_report_mgmt_disassoc(vif_id, pData, len);
- + break;
- + case WIFI_EVENT_REMAIN_ON_CHAN_EXPIRED:
- + cfg80211_report_remain_on_channel_expired(vif_id, pData, len);
- + break;
- + case WIFI_EVENT_NEW_STATION:
- + cfg80211_report_new_station(vif_id, pData, len);
- + break;
- + case WIFI_EVENT_REPORT_FRAME:
- + cfg80211_report_frame(vif_id, pData, len);
- + break;
- + case WIFI_EVENT_CONNECT_AP:
- + break;
- + case WIFI_EVENT_SDIO_SEQ_NUM:
- + break;
- + case WIFI_EVENT_REPORT_SCAN_FRAME:
- + cfg80211_report_scan_frame(vif_id, pData, len);
- + break;
- + case WIFI_EVENT_REPORT_MIC_FAIL:
- + cfg80211_report_mic_failure(vif_id, pData, len);
- + break;
- + default:
- + break;
- + }
- + return OK;
- +}
- +
- +int hex_dump(unsigned char *name, unsigned short nLen, unsigned char *pData, unsigned short len)
- +{
- + unsigned char *str;
- + int i, p, ret;
- + if(len > 1024)
- + len = 1024;
- + str = kmalloc( ( (len +1)*3 + nLen), GFP_KERNEL);
- + memset(str, 0, (len +1)*3 + nLen );
- + memcpy(str, name, nLen);
- + if( (NULL == pData ) || (0 == len) )
- + {
- + printke("%s\n", str);
- + kfree(str);
- + return 0;
- + }
- + p = 0;
- + for(i=0; i< len; i++)
- + {
- + ret = sprintf( (str+ nLen + p), "%02x ", *(pData+i) );
- + p = p+ret;
- + }
- + printke("%s\n", str);
- + kfree(str);
- + return 0;
- +}
- +
- diff --git a/drivers/net/wireless/sprdwl/wlan_cmd.h b/drivers/net/wireless/sprdwl/wlan_cmd.h
- new file mode 100644
- index 0000000..ea3e8ec
- --- /dev/null
- +++ b/drivers/net/wireless/sprdwl/wlan_cmd.h
- @@ -0,0 +1,352 @@
- +#ifndef __ITM_CMD_H__
- +#define __ITM_CMD_H__
- +
- +#include <linux/ieee80211.h>
- +#include "wlan_common.h"
- +#include "wlan_fifo.h"
- +
- +#define ITM_PMKID_LEN 16
- +
- +enum ITM_HOST_TROUT3_CMD_TYPE
- +{
- + HOST_SC2331_CMD = 0,
- + SC2331_HOST_RSP,
- + HOST_SC2331_PKT,
- + HOST_SC2331_WAPI,
- +};
- +
- +enum ITM_HOST_TROUT3_CMD_LIST
- +{
- + WIFI_CMD_GET_MODE = 1,
- + WIFI_CMD_GET_RSSI,
- + WIFI_CMD_GET_TXRATE_TXFAILED,
- + WIFI_CMD_SET_SCAN,
- + WIFI_CMD_SET_AUTH_TYPE,
- + WIFI_CMD_SET_WPA_VERSION,
- + WIFI_CMD_SET_PAIRWISE_CIPHER,
- + WIFI_CMD_SET_GROUP_CIPHER,
- + WIFI_CMD_SET_AKM_SUITE,
- + WIFI_CMD_SET_CHANNEL,//10-0xA
- + WIFI_CMD_SET_BSSID,
- + WIFI_CMD_SET_ESSID,
- + WIFI_CMD_KEY_ADD,
- + WIFI_CMD_KEY_DEL,
- + WIFI_CMD_KEY_SET,
- + WIFI_CMD_SET_DISCONNECT,
- + WIFI_CMD_SET_RTS_THRESHOLD,
- + WIFI_CMD_SET_FRAG_THRESHOLD,
- + WIFI_CMD_SET_PMKSA,
- + WIFI_CMD_DEL_PMKSA,//20--0x14
- + WIFI_CMD_FLUSH_PMKSA,
- + WIFI_CMD_SET_DEV_OPEN,
- + WIFI_CMD_SET_DEV_CLOSE,
- + WIFI_CMD_SET_PSK,
- + WIFI_CMD_START_BEACON,
- + WIFI_CMD_SET_WPS_IE,
- + WIFI_CMD_TX_MGMT,
- + WIFI_CMD_REMAIN_CHAN,
- + WIFI_CMD_CANCEL_REMAIN_CHAN,
- + WIFI_CMD_P2P_IE,//30---0x1e
- + WIFI_CMD_CHANGE_BEACON,
- + WIFI_CMD_REGISTER_FRAME,
- + WIFI_CMD_NPI_MSG,
- + WIFI_CMD_NPI_GET,
- + WIFI_CMD_SET_FT_IE,
- + WIFI_CMD_UPDATE_FT_IE,
- + WIFI_CMD_ASSERT,
- + WIFI_CMD_SLEEP,
- + WIFI_CMD_ADD_SOFTAP_BLACKLIST,
- + WIFI_CMD_DEL_SOFTAP_BLACKLIST,
- + WIFI_CMD_SCAN_NOR_CHANNELS,
- + WIFI_CMD_GET_IP,
- + WIFI_CMD_REQ_LTE_CONCUR,
- + WIFI_CMD_MAX,
- +
- +
- + WIFI_EVENT_CONNECT = 128,
- + WIFI_EVENT_DISCONNECT,
- + WIFI_EVENT_SCANDONE,
- + WIFI_EVENT_MGMT_DEAUTH,
- + WIFI_EVENT_MGMT_DISASSOC,
- + WIFI_EVENT_REMAIN_ON_CHAN_EXPIRED,
- + WIFI_EVENT_NEW_STATION,
- + WIFI_EVENT_REPORT_FRAME,
- + WIFI_EVENT_CONNECT_AP,
- + WIFI_EVENT_SDIO_SEQ_NUM,
- + WIFI_EVENT_REPORT_SCAN_FRAME,
- + WIFI_EVENT_REPORT_MIC_FAIL,
- + WIFI_EVENT_MAX,
- +};
- +
- +/* The reason code is defined by CP2 */
- +enum wlan_cmd_disconnect_reason
- +{
- + AP_LEAVING = 0xc1,
- + AP_DEAUTH = 0xc4,
- +};
- +
- +struct wlan_cmd_add_key
- +{
- + unsigned char mac[6];
- + unsigned char keyseq[8];
- + unsigned char pairwise;
- + unsigned char cypher_type;
- + unsigned char key_index;
- + unsigned char key_len;
- + unsigned char value[0];
- +} __packed;
- +
- +struct wlan_cmd_del_key
- +{
- + unsigned char key_index;
- + unsigned char pairwise; /* unicase or group */
- + unsigned char mac[6];
- +} __packed;
- +
- +struct wlan_cmd_pmkid
- +{
- + unsigned char bssid[ETH_ALEN];
- + unsigned char pmkid[ITM_PMKID_LEN];
- +} __packed;
- +
- +struct wlan_cmd_beacon
- +{
- + unsigned char len;
- + unsigned char value[0];
- +} __packed;
- +
- +struct wlan_cmd_mac_open
- +{
- + __le16 mode; /* AP or STATION mode */
- + unsigned char mac[6];
- +} __packed;
- +
- +struct wlan_cmd_mac_close
- +{
- + unsigned char mode; /* AP or STATION mode */
- +} __packed;
- +
- +struct wlan_cmd_wps_ie
- +{
- + unsigned char type; /* probe req ie or assoc req ie */
- + unsigned char len; /* max ie len is 255 */
- + unsigned char value[0];
- +} __packed;
- +
- +struct wlan_cmd_scan_ssid
- +{
- + unsigned char len;
- + unsigned char ssid[0];
- +} __packed;
- +
- +struct wlan_cmd_set_frag
- +{
- + __le16 frag;
- +} __packed;
- +
- +struct wlan_cmd_set_rts
- +{
- + __le16 threshold;
- +} __packed;
- +
- +struct wlan_cmd_set_key
- +{
- + __le32 key_index;
- +} __packed;
- +
- +struct wlan_cmd_disconnect
- +{
- + __le16 reason_code;
- +} __packed;
- +
- +struct wlan_cmd_set_essid
- +{
- + __le16 len;
- + unsigned char essid[0];
- +} __packed;
- +
- +struct wlan_cmd_set_bssid
- +{
- + unsigned char addr[6];
- +} __packed;
- +
- +struct wlan_cmd_get_ip
- +{
- + unsigned char ip[4];
- +} __packed;
- +
- +struct wlan_cmd_set_channel
- +{
- + __le32 channel;
- +} __packed;
- +
- +struct wlan_cmd_set_psk
- +{
- + __le16 len;
- + unsigned char key[0];
- +} __packed;
- +
- +struct wlan_cmd_set_key_management
- +{
- + __le32 key_mgmt;
- +
- +} __packed;
- +
- +struct wlan_cmd_set_cipher
- +{
- + __le32 cipher;
- +} __packed;
- +
- +struct wlan_cmd_set_auth_type
- +{
- + __le32 type;
- +} __packed;
- +
- +struct wlan_cmd_set_wpa_version
- +{
- + __le32 wpa_version;
- +} __packed;
- +
- +struct wlan_cmd_assert_t
- +{
- + __le32 reason_code;
- + __le32 tx_cnt;
- + __le32 rx_cnt;
- +} __packed;
- +
- +struct wlan_cmd_scan
- +{
- + /*
- + unsigned char channel_num;
- + unsigned char channel[15];
- + */
- + __le32 len;
- + unsigned char ssid[0];
- +} __packed;
- +
- +struct wlan_cmd_get_txrate_txfailed
- +{
- + __le32 rate;
- + __le32 failed;
- +} __packed;
- +
- +struct wlan_cmd_get_device_mode
- +{
- + __le32 mode;
- +} __packed;
- +
- +struct wlan_cmd_rsp_state_code
- +{
- + /* maybe fore it to int */
- + __le32 code;
- +} __packed;
- +
- +struct wlan_cmd_remain_chan_t {
- + unsigned char chan; /* send channel */
- + unsigned char chan_type;
- + __le32 duraion;
- + __le64 cookie;/* cookie */
- +} __packed;
- +
- +struct wlan_cmd_cancel_remain_chan_t {
- + __le64 cookie; /* cookie */
- +} __packed;
- +
- +struct wlan_cmd_mgmt_tx_t {
- + unsigned char chan; /* send channel */
- + __le32 wait; /* wait time */
- + __le32 len; /* mac length*/
- + unsigned char value[0];/* mac*/
- +} __packed;
- +
- +/* wlan_sipc wps ie struct */
- +struct wlan_cmd_p2p_ie_t {
- + unsigned char type; /* assoc req ie */
- + __le16 len; /* max ie len is 255 */
- + unsigned char value[0];
- +} __packed;
- +
- +struct wlan_cmd_register_frame_t {
- + __le16 type; /* assoc req ie */
- + unsigned char reg; /* max ie len is 255 */
- +} __packed;
- +
- +struct wlan_cmd_beacon_t {
- + __le16 len;
- + unsigned char value[0];
- +} __packed;
- +
- +struct wlan_cmd_ft_ies_params
- +{
- + __le16 md;
- + __le16 ie_len;
- + unsigned char ie[0];
- +} __packed;
- +
- +struct wlan_event_report_frame_t {
- + unsigned char channel;
- + unsigned char frame_type;
- + __le16 frame_len;
- +} __packed;
- +
- +struct wlan_event_scan_rsp
- +{
- + __le16 ops;
- + __le16 channel;
- + /* maybe fore it to short */
- + __le16 signal;
- + __le16 frame_len;
- +} __packed;
- +
- +struct wlan_event_mic_failure {
- + unsigned char key_id;
- + unsigned char is_mcast;
- +} __packed;
- +
- +extern int wlan_cmd_send_recv(unsigned char vif_id, unsigned char *pData, int len, int type, int timeout);
- +extern int wlan_cmd_start_ap(unsigned char vif_id, unsigned char *beacon, unsigned short len);
- +extern int wlan_cmd_register_frame(unsigned char vif_id, struct wlan_cmd_register_frame_t *data);
- +extern int wlan_cmd_set_p2p_ie(unsigned char vif_id, u8 type, const u8 *ie, u16 len);
- +extern int wlan_cmd_set_tx_mgmt(unsigned char vif_id, struct ieee80211_channel *channel, unsigned int wait, const u8 *mac, size_t mac_len);
- +extern int wlan_cmd_remain_chan(unsigned char vif_id, struct ieee80211_channel *channel, enum nl80211_channel_type channel_type, unsigned int duration, u64 *cookie);
- +extern int wlan_cmd_cancel_remain_chan(unsigned char vif_id, u64 cookie);
- +extern int wlan_cmd_scan(unsigned char vif_id, const unsigned char *ssid, const unsigned char *channels, int len);;
- +extern int wlan_cmd_set_wpa_version(unsigned char vif_id, unsigned int wpa_version);
- +extern int wlan_cmd_set_auth_type(unsigned char vif_id, unsigned int type);
- +extern int wlan_cmd_set_cipher(unsigned char vif_id, unsigned int cipher, unsigned char cmd_id);
- +extern int wlan_cmd_set_key_management(unsigned char vif_id, unsigned char key_mgmt);
- +extern int wlan_cmd_set_psk(unsigned char vif_id, const unsigned char *key, unsigned int key_len);
- +extern int wlan_cmd_set_channel(unsigned char vif_id, unsigned int channel);
- +extern int wlan_cmd_set_bssid(unsigned char vif_id, const unsigned char *addr);
- +extern int wlan_cmd_get_ip(unsigned char vif_id, u8 *ip);
- +extern int wlan_cmd_set_essid(unsigned char vif_id, const unsigned char *essid, int essid_len);
- +extern int wlan_cmd_pmksa(unsigned char vif_id, const unsigned char *bssid, const unsigned char *pmkid, unsigned char type);
- +extern int wlan_cmd_disconnect(unsigned char vif_id, unsigned short reason_code);
- +extern int wlan_cmd_add_key(unsigned char vif_id, const unsigned char *key_data, unsigned char key_len, unsigned char pairwise, unsigned char key_index, const unsigned char *key_seq, unsigned char cypher_type, const unsigned char *pmac);
- +extern int wlan_cmd_del_key(unsigned char vif_id, unsigned short key_index, const unsigned char *mac_addr);
- +extern int wlan_cmd_set_key(unsigned char vif_id, unsigned char key_index);
- +extern int wlan_cmd_set_rts(unsigned char vif_id, unsigned short rts_threshold);
- +extern int wlan_cmd_set_frag(unsigned char vif_id, unsigned short frag_threshold);
- +extern int wlan_cmd_set_wps_ie( unsigned char vif_id, unsigned char type, const unsigned char *ie, unsigned char len);
- +extern int
- +wlan_cmd_mac_open(unsigned char vif_id,
- + unsigned short mode,
- + unsigned char *mac_addr);
- +extern int wlan_cmd_mac_close(unsigned char vif_id, unsigned char mode);
- +extern int wlan_cmd_get_rssi(unsigned char vif_id, unsigned char *signal, unsigned char *noise);
- +extern int wlan_cmd_get_txrate_txfailed(unsigned char vif_id, unsigned int *rate, unsigned int *failed);
- +extern int wlan_cmd_get_txrate(unsigned char vif_id, unsigned int *rate);
- +extern int wlan_rx_rsp_process(const unsigned char vif_id, r_msg_hdr_t *msg);
- +extern int wlan_rx_event_process(const unsigned char vif_id, unsigned char event, unsigned char *pData, unsigned short len);
- +extern int wlan_cmd_npi_send_recv(unsigned char *s_buf,unsigned short s_len, unsigned char *r_buf, unsigned short *r_len );
- +extern int wlan_cmd_init(void );
- +extern int wlan_cmd_deinit(void );
- +extern int wlan_cmd_set_ft_ie(unsigned char vif_id, const unsigned char *ies, unsigned short len);
- +extern int wlan_cmd_update_ft_ies( unsigned char vif_id, struct cfg80211_update_ft_ies_params *ft_ies);
- +extern int wlan_cmd_assert(unsigned char vif_id, unsigned int reason_code);
- +extern void cfg80211_report_scan_frame(unsigned char vif_id, unsigned char *pData, int len);
- +extern void cfg80211_report_mic_failure(unsigned char vif_id, unsigned char *pdata, int len);
- +extern int wlan_cmd_sleep(int ops);
- +extern int wlan_cmd_req_lte_concur(unsigned char vif_id, const unsigned char *val, int len);
- +#endif
- +
- diff --git a/drivers/net/wireless/sprdwl/wlan_common.h b/drivers/net/wireless/sprdwl/wlan_common.h
- new file mode 100644
- index 0000000..e35b48e
- --- /dev/null
- +++ b/drivers/net/wireless/sprdwl/wlan_common.h
- @@ -0,0 +1,275 @@
- +#ifndef SPRD_WLAN_COMMON_H_
- +#define SPRD_WLAN_COMMON_H_
- +
- +#include <linux/proc_fs.h>
- +#include <linux/sipc.h>
- +#include <linux/mutex.h>
- +#include <linux/spinlock.h>
- +#include <linux/ieee80211.h>
- +#include <linux/printk.h>
- +#include <linux/inetdevice.h>
- +#include <linux/spinlock.h>
- +#include <net/cfg80211.h>
- +#include <linux/kernel.h>
- +#include <linux/errno.h>
- +#include <linux/module.h>
- +#include <linux/netdevice.h>
- +#include <linux/skbuff.h>
- +#include <net/ieee80211_radiotap.h>
- +#include <linux/etherdevice.h>
- +#include <linux/wireless.h>
- +#include <net/iw_handler.h>
- +#include <linux/string.h>
- +#include <linux/delay.h>
- +#include <linux/interrupt.h>
- +#include <linux/init.h>
- +#include <linux/wakelock.h>
- +#include <linux/workqueue.h>
- +#include <linux/ipv6.h>
- +#include <linux/ip.h>
- +#include <linux/inetdevice.h>
- +#include <asm/byteorder.h>
- +#include <linux/platform_device.h>
- +#include <linux/atomic.h>
- +#include <linux/wait.h>
- +#include <linux/semaphore.h>
- +#include <linux/vmalloc.h>
- +#include <linux/kthread.h>
- +#include <linux/time.h>
- +#include <linux/delay.h>
- +#include <linux/timer.h>
- +#include <linux/completion.h>
- +#include <asm/atomic.h>
- +#include <linux/ieee80211.h>
- +#include <linux/delay.h>
- +#include <linux/wakelock.h>
- +#include <linux/earlysuspend.h>
- +#include <asm/gpio.h>
- +#include "wlan_event_q.h"
- +#include "wlan_fifo.h"
- +#include "wlan_cmd.h"
- +#include "wlan_cfg80211.h"
- +
- +//#define SDIO_CHN_CHECK (1)
- +#define WIFI_DRV_WAPI
- +#define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
- +#define LINUX_VERSION_CODE KERNEL_VERSION(3, 10, 0)
- +
- +#define SDIO_ALIGN_SIZE (1024)
- +#define ALIGN_4BYTE(a) ( (((a)+3)&(~3)) )
- +#define INCR_RING_BUFF_INDX(indx,max_num) ((((indx) + 1) < (max_num)) ? ((indx) + 1) : (0) )
- +#define MAX_TX_BUFFER_ID (12)
- +#define TEST_BIT(a, k) ((a>>k)&1)
- +#define CLEAR_BIT(a, k) ({a = ( a&(~(1<<k)) );0;})
- +#define SET_BIT(a, k) ({a=( a | (1<<k) ); 0; })
- +#define WLAN_SYSTEM_DBG TEST_BIT(g_dbg, 1)
- +#define WLAN_PATH_DBG TEST_BIT(g_dbg, 2)
- +#define WLAN_HEX_DBG TEST_BIT(g_dbg, 3)
- +#define ETH_PCAP TEST_BIT(g_dbg, 4)
- +#define MAC_PCAP TEST_BIT(g_dbg, 5)
- +#define ETH_ALEN 6
- +#define SIOGETSSID 0x89F2
- +
- +#define HW_TX_SIZE (11264)
- +#define HW_RX_SIZE (15360)
- +#define PKT_AGGR_NUM (10)
- +#define SDIO_RX_GPIO (132)
- +
- +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
- +#define KERNEL_DEBUG_LEVE "\001" "0"
- +#else
- +#define KERNEL_DEBUG_LEVE "<0>"
- +#endif
- +
- +#define printkd(fmt, ...) ({if(WLAN_SYSTEM_DBG)printk(KERNEL_DEBUG_LEVE "[SC2331]" fmt, ##__VA_ARGS__); 0; })
- +#define printkp(fmt, ...) ({if(WLAN_PATH_DBG)printk(KERNEL_DEBUG_LEVE "[SC2331]" fmt, ##__VA_ARGS__); 0; })
- +#define printke(fmt, ...) ({printk(KERNEL_DEBUG_LEVE "[SC2331]" fmt, ##__VA_ARGS__); 0; })
- +#define ASSERT(fmt, ...) ({printk(KERNEL_DEBUG_LEVE "[SC2331-ASSERT][%s][%d]" fmt "\n", __func__, __LINE__, ##__VA_ARGS__); 0; })
- +
- +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
- +#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
- +
- +typedef struct
- +{
- + unsigned char chn[16];
- + unsigned char num;
- + unsigned short bit_map;
- + spinlock_t lock;
- + int gpio_high;
- + unsigned long timeout;
- + unsigned long timeout_time;
- + bool timeout_flag;
- +}sdio_chn_t;
- +
- +typedef enum
- +{
- + EVENT_Q_ID_0 = 0,
- + EVENT_Q_ID_1 = 1,
- + EVENT_Q_ID_2 = 2,
- + EVENT_Q_ID_3 = 3,
- + EVENT_Q_ID_4 = 4,
- + EVENT_Q_MAX_ID = 5,
- +}EVENT_Q_ID_T;
- +
- +typedef enum
- +{
- + NETIF_0_ID = 0,
- + NETIF_1_ID = 1,
- + WLAN_MAX_ID = 2,
- +}NETIF_ID_T;
- +
- +typedef struct
- +{
- + int exit;
- + struct semaphore sem;
- +}drv_sync_t;
- +
- +typedef struct
- +{
- + sdio_chn_t sdio_tx_chn;
- + sdio_chn_t sdio_rx_chn;
- + unsigned int tx_cnt;
- + unsigned int rx_cnt;
- + unsigned int rx_record;
- + struct wake_lock wlan_lock;
- + struct early_suspend early_suspend;
- + int wakeup;
- + struct timer_list wakeup_timer;
- + unsigned long wakeup_time;
- + int can_sleep;
- +}hw_info_t;
- +typedef struct
- +{
- + m_event_t tx_q;
- + txfifo_t tx_fifo;
- + int status;
- +}tx_buf_t;
- +
- +typedef struct
- +{
- + struct task_struct *task;
- + struct semaphore sem;
- +}wlan_thread_t;
- +
- +typedef struct
- +{
- + unsigned char mac[ETH_ALEN];
- + unsigned char netif_id;
- + unsigned char prio;
- + unsigned char wmm_supp;
- + unsigned char status;
- +}net_connect_dev_t;
- +
- +typedef struct
- +{
- + wait_queue_head_t waitQ;
- + int wakeup;
- + struct mutex cmd_lock;
- + unsigned char *mem;
- +}wlan_cmd_t;
- +
- +typedef struct
- +{
- + struct work_struct work;
- + unsigned short frame_type;
- + bool reg;
- + void *vif;
- +}register_frame_param_t;
- +
- +/* Best not to use the work to send deauth cmd
- + * FIXME in the future
- + */
- +struct deauth_info {
- + struct work_struct work;
- + /* 60 length is enough, maybe FIXME */
- + unsigned char mac[60];
- + unsigned short len;
- +};
- +
- +typedef struct
- +{
- + struct wake_lock scan_done_lock;
- + atomic_t scan_status;
- + struct cfg80211_scan_request *scan_request;
- + struct timer_list scan_timeout;
- + int connect_status;
- + int ssid_len;
- + unsigned char ssid[IEEE80211_MAX_SSID_LEN];
- + unsigned char bssid[ETH_ALEN];
- + unsigned char cipher_type;
- + unsigned char key_index[2];
- + unsigned char key[2][4][WLAN_MAX_KEY_LEN];
- + unsigned char key_len[2][4];
- + unsigned char key_txrsc[2][WLAN_MAX_KEY_LEN];
- + unsigned char *scan_frame_array;
- + int p2p_mode;
- + register_frame_param_t register_frame;
- + struct deauth_info deauth_info;
- +}wlan_cfg80211_t;
- +
- +typedef struct
- +{
- + struct net_device *ndev;
- + struct wireless_dev wdev;
- + unsigned short id;
- + unsigned char mac[ETH_ALEN];
- + int mode;
- + wlan_cfg80211_t cfg80211;
- + net_connect_dev_t connect_dev[8];
- + txfifo_t txfifo;
- + m_event_t event_q[EVENT_Q_MAX_ID];
- +}wlan_vif_t;
- +
- +typedef struct
- +{
- + struct wiphy *wiphy;
- + struct device *dev;
- + wlan_thread_t wlan_core;
- + wlan_thread_t wlan_trans;
- + hw_info_t hw;
- + wlan_cmd_t cmd;
- + drv_sync_t sync;
- + wlan_vif_t netif[2];
- + rxfifo_t rxfifo;
- +}wlan_info_t;
- +
- +static inline wlan_vif_t *ndev_to_vif(struct net_device *ndev)
- +{
- + return *(wlan_vif_t **)netdev_priv(ndev);
- +}
- +
- +extern void core_down(void);
- +extern void core_up(void);
- +extern void trans_down(void );
- +extern void trans_up(void );
- +extern void up_wlan_rx_trans(void );
- +extern int wlan_module_init(struct device *dev);
- +extern int wlan_module_exit(struct device *dev);
- +extern int hex_dump(unsigned char *name, unsigned short nLen, unsigned char *pData, unsigned short len);
- +extern void init_register_frame_param(wlan_vif_t *vif );
- +extern void init_send_deauth_work(wlan_vif_t *vif);
- +extern wlan_vif_t *id_to_vif(unsigned char id);
- +extern int hostap_conf_load(char *filename, unsigned char *key_val);
- +extern int mac_addr_cfg(wlan_vif_t *vif, unsigned char vif_id);
- +extern int wlan_vif_init(wlan_vif_t *vif, int type, const char *name, void *ops);
- +extern int wlan_wiphy_new(wlan_info_t *wlan);
- +extern int wlan_vif_free(wlan_vif_t *vif);
- +extern int wlan_wiphy_free(wlan_info_t *wlan);
- +extern void wlan_nl_init(void );
- +extern void wlan_nl_deinit(void );
- +
- +extern bool get_sdiohal_status(void);
- +extern int sdio_chn_status(unsigned short chn, unsigned short *status);
- +extern int sdio_dev_read(unsigned int chn,void* read_buf,unsigned int *count);
- +extern int sdio_dev_write(unsigned int chn,void* data_buf,unsigned int count);
- +extern int sdiodev_readchn_init(int chn, void *callback, bool with_para );
- +extern int sdio_read_wlan(unsigned int chn,void* read_buf,unsigned int *count);
- +extern int sdiodev_readchn_uninit(unsigned int chn);
- +extern void mdbg_sdio_read(void);
- +extern void marlin_pa_enable(bool enable);
- +extern int set_marlin_wakeup(unsigned int chn,unsigned int user_id);
- +extern int set_marlin_sleep(unsigned int chn,unsigned int user_id);
- +extern char * get_cmd_name(int id);
- +extern unsigned int g_dbg;
- +extern wlan_info_t g_wlan;
- +#endif
- diff --git a/drivers/net/wireless/sprdwl/wlan_core.c b/drivers/net/wireless/sprdwl/wlan_core.c
- new file mode 100644
- index 0000000..5a3a61a
- --- /dev/null
- +++ b/drivers/net/wireless/sprdwl/wlan_core.c
- @@ -0,0 +1,1228 @@
- +/*
- + * Copyright (C) 2014 Spreadtrum Communications Inc.
- + *
- + * Authors:<jinglong.chen@spreadtrum.com>
- + * Owner:
- + * jinglong.chen
- + *
- + * This software is licensed under the terms of the GNU General Public
- + * License version 2, as published by the Free Software Foundation, and
- + * may be copied, distributed, and modified under those terms.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + */
- +
- +#include "wlan_common.h"
- +#include "wlan_event_q.h"
- +#include "wlan_fifo.h"
- +#include "wlan_cmd.h"
- +#include "wlan_cfg80211.h"
- +#include "wlan_wapi.h"
- +
- +wlan_info_t g_wlan = { 0 };
- +unsigned int g_dbg = 0xFFFFFFFF;
- +
- +void core_up(void)
- +{
- + up(&(g_wlan.wlan_core.sem));
- +}
- +void core_down(void)
- +{
- + down(&(g_wlan.wlan_core.sem));
- +}
- +void trans_up(void )
- +{
- + up(&(g_wlan.wlan_trans.sem));
- +}
- +void trans_down(void )
- +{
- + down(&(g_wlan.wlan_trans.sem));
- +}
- +
- +bool stop_net(unsigned char id )
- +{
- + return false;
- + if(NULL == g_wlan.netif[id].ndev)
- + return false;
- + if( ! netif_queue_stopped(g_wlan.netif[id].ndev) )
- + {
- + netif_stop_queue(g_wlan.netif[id].ndev);
- + return true;
- + }
- + return false;
- +}
- +
- +bool wake_net(unsigned char id)
- +{
- + return false;
- + if( (NULL == g_wlan.netif[id].ndev) || (1 == g_wlan.sync.exit) )
- + return false;
- + if(netif_queue_stopped(g_wlan.netif[id].ndev) )
- + {
- + netif_wake_queue(g_wlan.netif[id].ndev);
- + return true;
- + }
- + return false;
- +}
- +
- +static int hw_rx(const unsigned short chn, unsigned char *buf, unsigned int *len)
- +{
- + int ret;
- + unsigned int read_len = 0;
- + static unsigned int cnt = 0;
- + if(NULL == buf)
- + return ERROR;
- +#if 0
- + ret = sdio_read_wlan(chn, buf, HW_RX_SIZE);
- + *len = HW_RX_SIZE;
- +#else
- + ret = sdio_dev_read(chn, buf, &read_len);
- + *len = read_len;
- +#endif
- + if(0 != ret)
- + {
- + printke("[chn %d][sdio_read] err:%d\n", chn, ret);
- + return ERROR;
- + }
- + if(WLAN_HEX_DBG)
- + {
- + unsigned char str[64] = {0};
- + printkd("[sdio_read][%d][%d][%d]\n", chn, 1024, cnt);
- + sprintf(str, "[HEX-RX][%d]:", 1024);
- + hex_dump(str, strlen(str), buf, 1024);
- + }
- + printkp("[rx][%d]\n", chn );
- + cnt++;
- + *len = read_len;
- + g_wlan.hw.rx_cnt++;
- + return OK;
- +}
- +
- +static int hw_tx(const unsigned short chn, unsigned char *buf, unsigned int len)
- +{
- + int ret;
- + static unsigned int cnt = 0;
- + static unsigned int skb = 0;
- + tx_big_hdr_t *big_hdr;
- +
- + big_hdr = (tx_big_hdr_t *)buf;
- + if( (14 < big_hdr->msg_num) || (0 == big_hdr->msg_num) )
- + {
- + ASSERT();
- + return ERROR;
- + }
- + if(WLAN_HEX_DBG)
- + {
- + unsigned char str[64] = {0};
- + sprintf(str, "[HEX-TX][%d]:", len);
- + hex_dump(str, strlen(str), buf, 128);
- + }
- + big_hdr->tx_cnt = g_wlan.hw.tx_cnt;
- + printkp("[tx][%d][%d]\n",big_hdr->tx_cnt, chn);
- + len = (len+1023)&0xFC00;
- + ret = sdio_dev_write(chn, buf, len);
- + if(0 != ret)
- + {
- + ASSERT();
- + return ERROR;
- + }
- + skb = skb + big_hdr->msg_num;
- + cnt++;
- + if(100 == cnt)
- + {
- + printkd("w%d\n", skb);
- + cnt = 0;
- + skb = 0;
- + }
- + g_wlan.hw.tx_cnt++;
- + return OK;
- +}
- +
- +static int wlan_rx_skb_process(const unsigned char vif_id, unsigned char *pData, unsigned short len)
- +{
- + struct sk_buff *skb;
- + struct net_device *ndev = g_wlan.netif[vif_id].ndev;
- + if((NULL == pData) || (0 == len) || (NULL == ndev))
- + {
- + printkd("[%s][%d][err]\n", __func__, (int )vif_id);
- + return ERROR;
- + }
- + skb = dev_alloc_skb(len + NET_IP_ALIGN);
- + if(NULL == skb)
- + return ERROR;
- + skb_reserve(skb, NET_IP_ALIGN);
- + memcpy(skb->data, pData, len);
- +
- + skb_put(skb, len);
- + skb->dev = ndev;
- + skb->protocol = eth_type_trans(skb, ndev);
- + ndev->stats.rx_packets++;
- + printkp("rx_skb:%d\n", (int)(ndev->stats.rx_packets) );
- + ndev->stats.rx_bytes += skb->len;
- + if ( in_interrupt() )
- + netif_rx(skb);
- + else
- + netif_rx_ni(skb);
- + return OK;
- +}
- +
- +static int wlan_rx_wapi_process(const unsigned char vif_id, unsigned char *pData, unsigned short len)
- +{
- + struct ieee80211_hdr_3addr *addr;
- + int decryp_data_len = 0;
- + struct sk_buff *skb;
- + u8 snap_header[6] = { 0xaa, 0xaa, 0x03,0x00, 0x00, 0x00};
- + wlan_vif_t *vif;
- + struct net_device *ndev;
- +
- + vif = &(g_wlan.netif[vif_id]);
- + ndev = vif->ndev;
- + if((NULL == pData) || (0 == len) || (NULL == ndev))
- + {
- + printkd("[%s][%d][err]\n", __func__, (int )vif_id);
- + return ERROR;
- + }
- + addr = (struct ieee80211_hdr_3addr *)pData;
- + skb = dev_alloc_skb(len + NET_IP_ALIGN);
- + if(NULL == skb)
- + return ERROR;
- + skb_reserve(skb, NET_IP_ALIGN);
- +
- + decryp_data_len = wlan_rx_wapi_decryption(vif, (unsigned char *)addr, 24, (len -24),(skb->data + 12));
- + if (decryp_data_len == 0)
- + {
- + dev_kfree_skb(skb);
- + return ERROR;
- + }
- + if ( memcmp((skb->data + 12), snap_header, sizeof(snap_header)) == 0)
- + {
- + skb_reserve(skb, 6);
- + memcpy(skb->data,addr->addr1, 6);
- + memcpy(skb->data + 6,addr->addr2, 6);
- + skb_put(skb, (decryp_data_len + 6));
- + }
- + else
- + {
- + /* copy eth header */
- + memcpy(skb->data,addr->addr3, 6);
- + memcpy(skb->data + 6, addr->addr2, 6);
- + skb_put(skb, (decryp_data_len + 12) );
- + }
- + skb->dev = ndev;
- + skb->protocol = eth_type_trans(skb, ndev);
- + ndev->stats.rx_packets++;
- + printkp("rx_skb:%d\n", (int)(ndev->stats.rx_packets) );
- + ndev->stats.rx_bytes += skb->len;
- + if ( in_interrupt() )
- + netif_rx(skb);
- + else
- + netif_rx_ni(skb);
- + return OK;
- +}
- +
- +void wlan_rx_chn_isr(int chn)
- +{
- + static unsigned int cnt = 1;
- + printkp("[irq][%d]\n", cnt);
- + cnt++;
- + trans_up();
- +}
- +
- +static unsigned char prio_to_q_id(unsigned char *eth_hdr)
- +{
- + unsigned short eth_type;
- + int priority;
- + unsigned char q_id = EVENT_Q_ID_2;
- +
- + eth_type = ( (eth_hdr[12]<<8) | eth_hdr[13] );
- + if(IP_TYPE != eth_type)
- + return q_id;
- + priority = eth_hdr[15]&0xE0;
- + switch(priority)
- + {
- + case 0x20:
- + case 0x40:
- + q_id = EVENT_Q_ID_1;
- + break;
- +
- + case 0x80:
- + case 0xA0:
- + q_id = EVENT_Q_ID_3;
- + break;
- +
- + case 0xc0:
- + case 0xe0:
- + q_id = EVENT_Q_ID_4;
- + break;
- +
- + default:
- + q_id = EVENT_Q_ID_2;
- + break;
- + }
- + return q_id;
- +}
- +
- +static int wlan_xmit(struct sk_buff *skb, struct net_device *dev)
- +{
- + unsigned char q_id;
- + int addr_len = 0;
- + wlan_vif_t *vif;
- + tx_msg_t *event;
- + m_event_t *event_q;
- + struct sk_buff *wapi_skb;
- +
- + vif = ndev_to_vif(dev);
- + q_id = EVENT_Q_ID_1;//q_id = prio_to_q_id(skb->data);
- + event_q = &(vif->event_q[q_id]);
- + if(event_q->event_cnt > event_q->highThres)
- + {
- + if( stop_net(vif->id) )
- + printke("[stop_net %d:%d][%d,%d]\n", vif->id, q_id, event_q->event_cnt, event_q->highThres);
- + }
- + event = alloc_event(event_q);
- + if(NULL == event)
- + {
- + printkd("L-PKT\n");
- + if( stop_net(vif->id) )
- + printke("[stop_net %d:%d][%d,%d]\n", vif->id, q_id, event_q->event_cnt, event_q->highThres);
- + dev_kfree_skb(skb);
- + return NETDEV_TX_OK;
- + }
- +#ifdef WIFI_DRV_WAPI
- + if (vif->cfg80211.cipher_type == WAPI && vif->cfg80211.connect_status == ITM_CONNECTED &&
- + vif->cfg80211.key_len[PAIRWISE][vif->cfg80211.key_index[PAIRWISE]] != 0 &&(*(u16 *)((u8 *)skb->data + ETH_PKT_TYPE_OFFSET) != 0xb488))
- + {
- + wapi_skb = dev_alloc_skb(skb->len+100+NET_IP_ALIGN);
- + skb_reserve(wapi_skb, NET_IP_ALIGN);
- + memcpy( wapi_skb->data, skb->data, ETHERNET_HDR_LEN );
- + addr_len = wlan_tx_wapi_encryption(vif, skb->data, (skb->len - ETHERNET_HDR_LEN), ( (unsigned char *)(wapi_skb->data) + ETHERNET_HDR_LEN) );
- + addr_len = addr_len + ETHERNET_HDR_LEN;
- + skb_put(wapi_skb, addr_len);
- + memset(event, 0, sizeof(tx_msg_t) );
- + event->p = (void *)wapi_skb;
- + event->slice[0].data = wapi_skb->data;
- + event->slice[0].len = wapi_skb->len;
- + event->hdr.mode = vif->id;
- + event->hdr.type = HOST_SC2331_PKT;
- + event->hdr.subtype = 0;
- + event->hdr.len = event->slice[0].len;
- + vif->ndev->stats.tx_bytes += wapi_skb->len;
- + vif->ndev->stats.tx_packets++;
- + dev->trans_start = jiffies;
- + dev_kfree_skb(skb);
- + }
- + else
- +#endif
- + {
- + event->p = (void *)skb;
- + event->slice[0].data = skb->data;
- + event->slice[0].len = skb->len;
- + event->hdr.mode = vif->id;
- + event->hdr.type = HOST_SC2331_PKT;
- + event->hdr.subtype = 0;
- + event->hdr.len = skb->len;
- + vif->ndev->stats.tx_bytes += skb->len;
- + vif->ndev->stats.tx_packets++;
- + dev->trans_start = jiffies;
- + }
- +
- + post_event( (unsigned char *)event, event_q );
- + core_up();
- + return NETDEV_TX_OK;
- +}
- +
- +static int wlan_rx_process(unsigned char *buf, unsigned int max_len)
- +{
- + static unsigned int cnt = 0;
- + static unsigned int skb = 0;
- + unsigned int p = 0;
- + r_msg_hdr_t *msg = NULL;
- + unsigned char vif_id;
- + unsigned char *pData = NULL;
- + unsigned short len;
- + unsigned char event;
- + if((NULL == buf) || (0 == max_len))
- + {
- + printke("[%s][ERROR]\n", __func__);
- + return OK;
- + }
- + buf = buf + 8;
- + msg = (r_msg_hdr_t *)(buf);
- + max_len = max_len - 8;
- + while(p < max_len)
- + {
- +
- + vif_id = msg->mode;
- + pData = (unsigned char *)(msg+1);
- + len = msg->len;
- +
- + if( (0xFF == msg->type) || (0xFF == msg->subtype) )
- + break;
- + if(HOST_SC2331_PKT == msg->type)
- + {
- + pData = pData + msg->subtype;
- + len = len - msg->subtype;
- + wlan_rx_skb_process(vif_id, pData, len);
- + }
- +#ifdef WIFI_DRV_WAPI
- + else if(HOST_SC2331_WAPI == msg->type)
- + {
- + wlan_rx_wapi_process(vif_id, pData, len);
- + }
- +#endif
- + else if(SC2331_HOST_RSP == msg->type)
- + {
- + wlan_rx_rsp_process(vif_id, msg);
- + }
- + else if(HOST_SC2331_CMD == msg->type)
- + {
- + event = msg->subtype;
- + wlan_rx_event_process(vif_id, event, pData, len);
- + }
- + else
- + {
- + printke("[%s][RX DATA ERR]\n", __func__);
- + break;
- + }
- + p = p + sizeof(t_msg_hdr_t) + ALIGN_4BYTE(msg->len);
- + msg = (r_msg_hdr_t *)(buf+p);
- + skb++;
- + }
- + cnt++;
- + if(100 == cnt)
- + {
- + printkd("r%d\n", skb);
- + cnt = 0;
- + skb = 0;
- + }
- + return OK;
- +}
- +
- +static int wlan_open(struct net_device *dev)
- +{
- + printkd("%s open\n", dev->name );
- + netif_start_queue(dev);
- + return 0;
- +}
- +static int wlan_close(struct net_device *dev)
- +{
- + printkd("%s %s enter\n", __func__, dev->name );
- + netif_stop_queue(dev);
- + printkd("%s %s ok\n", __func__, dev->name );
- + return 0;
- +}
- +static struct net_device_stats *wlan_status(struct net_device *dev)
- +{
- + return &(dev->stats);
- +}
- +
- +static void wlan_tx_timeout(struct net_device *dev)
- +{
- + wlan_vif_t *vif;
- + printke("%s tx timeout\n", dev->name);
- + vif = ndev_to_vif(dev);
- +
- + if (!netif_carrier_ok(dev))
- + netif_carrier_on(dev);
- + dev->trans_start = jiffies;
- + wake_net(vif->id);
- + core_up();
- + return;
- +}
- +
- +static int wlan_ioctl(struct net_device *ndev, struct ifreq *req, int cmd)
- +{
- + return 0;
- +}
- +
- +struct net_device_ops wlan_ops =
- +{
- + .ndo_open = wlan_open,
- + .ndo_stop = wlan_close,
- + .ndo_start_xmit = wlan_xmit,
- + .ndo_get_stats = wlan_status,
- + .ndo_tx_timeout = wlan_tx_timeout,
- + .ndo_do_ioctl = wlan_ioctl,
- +};
- +
- +static void wlan_early_suspend(struct early_suspend *es)
- +{
- + printkd("[%s]\n", __func__);
- + wlan_cmd_sleep(1);
- +}
- +
- +static void wlan_late_resume(struct early_suspend *es)
- +{
- + printkd("[%s]\n", __func__);
- + wlan_cmd_sleep(2);
- +}
- +
- +int wlan_wakeup(void )
- +{
- + int ret;
- + if(0 != g_wlan.hw.wakeup)
- + return OK;
- + wake_lock(&g_wlan.hw.wlan_lock);
- + printkd("time[1]\n");
- + mod_timer(&(g_wlan.hw.wakeup_timer), jiffies + msecs_to_jiffies(g_wlan.hw.wakeup_time) );
- + g_wlan.hw.wakeup = 1;
- + g_wlan.hw.can_sleep = 0;
- + return ret;
- +}
- +
- +void wlan_sleep(void )
- +{
- + int ret;
- + if( (1 != g_wlan.hw.wakeup) || (0 == g_wlan.hw.can_sleep) )
- + return;
- + g_wlan.hw.wakeup = 0;
- + printkd("time[4]\n");
- + wake_unlock(&g_wlan.hw.wlan_lock);
- + return;
- +}
- +
- +void wakeup_timer_func(unsigned long data)
- +{
- + if((g_wlan.wlan_trans.sem.count <= 0) && (0 == g_wlan.hw.can_sleep) )
- + {
- + printkd("timer[3]\n");
- + g_wlan.hw.can_sleep = 1;
- + trans_up();
- + return;
- + }
- + printkd("timer[2]\n");
- + mod_timer(&(g_wlan.hw.wakeup_timer), jiffies + msecs_to_jiffies(g_wlan.hw.wakeup_time) );
- +}
- +
- +int wlan_rx(rxfifo_t *rx_fifo, int cnt)
- +{
- + int i,num,rx_cnt,ret;
- + rx_cnt = 0;
- + num = rx_fifo_used(rx_fifo);
- + if(num > cnt)
- + num = cnt;
- + for(i=0; i < num ; i++)
- + {
- + wlan_wakeup();
- + ret = rx_fifo_out(rx_fifo, wlan_rx_process);
- + if(ERROR == ret)
- + break;
- + rx_cnt++;
- + }
- + return rx_cnt;
- +}
- +
- +int wlan_tx(txfifo_t *tx_fifo, m_event_t *event_q, int cnt)
- +{
- + int tx_cnt,i,ret;
- + tx_msg_t *event;
- + tx_cnt = 0;
- + for(i=0; i<cnt; i++)
- + {
- + event = (tx_msg_t *)get_event(event_q);
- + if(NULL == event)
- + {
- + break;
- + }
- + ret = tx_fifo_in(tx_fifo, event);
- + if(TX_FIFO_FULL == ret)
- + {
- + break;
- + }
- + trans_up();
- + if( HOST_SC2331_CMD == event->hdr.type)
- + {
- + if((event->slice[0].len > 0) &&(NULL != event->slice[0].data))
- + kfree(event->slice[0].data);
- + }
- + else if(HOST_SC2331_PKT == event->hdr.type)
- + {
- + if((NULL != event->p))
- + dev_kfree_skb((struct sk_buff *)(event->p));
- + }
- + else
- + {}
- + memset((unsigned char *)event, 0, sizeof(tx_msg_t));
- + free_event((void *)event, event_q );
- + tx_cnt++;
- + }
- + return tx_cnt;
- +}
- +
- +int wmm_calc(wlan_vif_t *vif, unsigned short *q_event_num)
- +{
- + int i,weight;
- + unsigned short event_q_array[EVENT_Q_MAX_ID][2];
- + q_event_num[EVENT_Q_ID_0] = vif->event_q[EVENT_Q_ID_0].event_cnt;
- + for(i=EVENT_Q_ID_1, weight = 0; i<EVENT_Q_MAX_ID; i++)
- + {
- + event_q_array[i][0] = vif->event_q[i].event_cnt;
- + event_q_array[i][1] = vif->event_q[i].weight;
- + if(0 == event_q_array[i][0])
- + continue;
- + weight = weight + event_q_array[i][1];
- + }
- + for(i=EVENT_Q_ID_1; i<EVENT_Q_MAX_ID; i++)
- + {
- + if(0 == weight)
- + {
- + q_event_num[i] = 0;
- + continue;
- + }
- + q_event_num[i] = (event_q_array[i][0])*(event_q_array[i][1])/weight;
- + }
- + if( (0 == weight) && (0 == q_event_num[EVENT_Q_ID_0]) )
- + return ERROR;
- + return OK;
- +}
- +
- +static int wlan_core_thread(void *data)
- +{
- + wlan_vif_t *vif;
- + rxfifo_t *rx_fifo;
- + txfifo_t *tx_fifo;
- + m_event_t *event_q;
- + unsigned long timeout;
- + unsigned int i, ret, retry, vif_id, done;
- + unsigned int sem_count, q_index, need_tx, tx_cnt, tmp;
- + short q_event_num[EVENT_Q_MAX_ID] = {0};
- + rx_fifo = &(g_wlan.rxfifo);
- + sema_init(&g_wlan.wlan_core.sem, 0);
- + printke("%s enter\n", __func__);
- + up(&(g_wlan.sync.sem));
- + core_down();
- + do
- + {
- + retry = done = 0;
- + sem_count = g_wlan.wlan_core.sem.count ;
- +
- + ret = wlan_rx(rx_fifo, 1);
- + done = done + ret;
- +
- + for(vif_id = NETIF_0_ID, tx_cnt = 0; vif_id < WLAN_MAX_ID; vif_id++)
- + {
- + vif = &(g_wlan.netif[vif_id]);
- + tx_fifo = &(vif->txfifo);
- + ret = wmm_calc(vif, q_event_num);
- + if(OK != ret)
- + {
- + continue;
- + }
- + for( q_index=EVENT_Q_ID_0; q_index<EVENT_Q_MAX_ID; q_index++ )
- + {
- + event_q = &(vif->event_q[q_index]);
- + need_tx = q_event_num[q_index];
- + timeout = jiffies + msecs_to_jiffies(need_tx);
- + while(need_tx)
- + {
- + tmp = (need_tx > PKT_AGGR_NUM)?(PKT_AGGR_NUM):(need_tx);
- + ret = wlan_tx(tx_fifo, event_q, tmp);
- + tmp = done;
- + if(ret != tmp)
- + retry++;
- + done = done + ret;
- + tx_cnt = tx_cnt + ret;
- + need_tx = need_tx - ret;
- + if(tx_cnt > PKT_AGGR_NUM)
- + {
- + ret = wlan_rx(rx_fifo, 1);
- + done = done + ret;
- + if(1 == ret)
- + tx_cnt -= PKT_AGGR_NUM;
- + }
- + if ( time_after(jiffies, timeout) )
- + {
- + retry++;
- + break;
- + }
- + }
- + }
- + }
- +
- + if(g_wlan.sync.exit)
- + break;
- + if((0 == done) && (0 == retry) )
- + done = ( (0 == sem_count)?(1):(sem_count) );
- + for(i=0; i<done; i++)
- + {
- + core_down();
- + }
- + }while(!kthread_should_stop());
- +
- + printke("%s exit!\n", __func__);
- + up(&(g_wlan.sync.sem));
- + return 0;
- +}
- +
- +static int check_valid_chn(int flag, unsigned short status, sdio_chn_t *chn_info)
- +{
- + int i,index = -1;
- + if(1 == flag)
- + status = ( status & (chn_info->bit_map) );
- + else
- + status = ( (status & chn_info->bit_map) ^ (chn_info->bit_map) );
- + if(0 == status)
- + return -1;
- + for(i=0; i < chn_info->num; i++)
- + {
- + if( status & (0x1 << chn_info->chn[i]) )
- + {
- + index = chn_info->chn[i];
- + break;
- + }
- + }
- + return index;
- +}
- +
- +static int wlan_trans_thread(void *data)
- +{
- + int i,vif_id,ret,done, retry,sem_count,send_pkt, index,pkt_num;
- + rxfifo_t *rx_fifo;
- + txfifo_t *tx_fifo;
- + wlan_vif_t *vif;
- + sdio_chn_t *tx_chn;
- + sdio_chn_t *rx_chn;
- + unsigned short status;
- + int tx_retry_cnt;
- + bool tx_retry_flag = false;
- +
- + sema_init(&g_wlan.wlan_trans.sem, 0);
- + sdiodev_readchn_init(8, (void *)wlan_rx_chn_isr, 1);
- + sdiodev_readchn_init(9, (void *)wlan_rx_chn_isr, 1);
- + rx_chn = &(g_wlan.hw.sdio_rx_chn);
- + tx_chn = &(g_wlan.hw.sdio_tx_chn);
- + rx_fifo = &(g_wlan.rxfifo);
- + up(&(g_wlan.sync.sem));
- + printke("%s enter\n", __func__);
- + trans_down();
- +
- + do
- + {
- + send_pkt = retry = done = 0;
- + sem_count = g_wlan.wlan_trans.sem.count;
- +RX:
- + if(! gpio_get_value(SDIO_RX_GPIO) )
- + {
- +#ifdef SDIO_CHN_CHECK
- + if(true == rx_chn->gpio_high)
- + {
- + rx_chn->gpio_high = false;
- + rx_chn->timeout_flag = false;
- + }
- +#endif
- + goto TX;
- + }
- + else
- + {
- +#ifdef SDIO_CHN_CHECK
- + if(false == rx_chn->gpio_high)
- + {
- + rx_chn->gpio_high = true;
- + }
- +#endif
- + }
- + wlan_wakeup();
- + set_marlin_wakeup(0, 1);
- + ret = sdio_chn_status( rx_chn->bit_map, &status);
- + index = check_valid_chn(1, status, rx_chn);
- + if(index < 0)
- + {
- +#ifdef SDIO_CHN_CHECK
- + if(false == rx_chn->timeout_flag)
- + {
- + rx_chn->timeout_flag = true;
- + rx_chn->timeout = jiffies + msecs_to_jiffies(rx_chn->timeout_time);
- + }
- + else
- + {
- + if ( time_after(jiffies, rx_chn->timeout) )
- + {
- + rx_chn->timeout = jiffies + msecs_to_jiffies(rx_chn->timeout_time);
- + printke("[SDIO_RX_CHN][TIMEOUT][%d]\n", rx_chn->timeout_time);
- + }
- + }
- +#endif
- + goto TX;
- + }
- +#ifdef SDIO_CHN_CHECK
- + if(true == rx_chn->timeout_flag)
- + {
- + rx_chn->timeout_flag = false;
- + }
- +#endif
- + if(14 == index)
- + {
- + mdbg_sdio_read();
- + goto TX;
- + }
- + ret = rx_fifo_in(index, rx_fifo, hw_rx);
- + if(OK != ret )
- + {
- + retry++;
- + goto TX;
- + }
- + core_up();
- +
- +TX:
- + for(vif_id = NETIF_0_ID; vif_id < WLAN_MAX_ID; vif_id++ )
- + {
- + vif = &(g_wlan.netif[vif_id]);
- + tx_fifo = &(vif->txfifo);
- + ret = tx_fifo_used(tx_fifo);
- + if(0 == ret)
- + continue;
- + wlan_wakeup();
- + set_marlin_wakeup(0, 1);
- + ret = sdio_chn_status(tx_chn->bit_map, &status);
- + index = check_valid_chn(0, status, tx_chn);
- + if(index < 0)
- + {
- +#ifdef SDIO_CHN_CHECK
- + if(false == tx_chn->timeout_flag)
- + {
- + tx_chn->timeout_flag = true;
- + tx_chn->timeout = jiffies + msecs_to_jiffies(tx_chn->timeout_time);
- + }
- + else
- + {
- + if ( time_after(jiffies, tx_chn->timeout) )
- + {
- + tx_chn->timeout = jiffies + msecs_to_jiffies(tx_chn->timeout_time);
- + printke("[SDIO_TX_CHN][TIMEOUT][%d]\n", tx_chn->timeout_time);
- + }
- + }
- +#endif
- + retry++;
- + continue;
- + }
- +#ifdef SDIO_CHN_CHECK
- + if(true == tx_chn->timeout_flag)
- + {
- + tx_chn->timeout_flag = false;
- + }
- +#endif
- + ret = tx_fifo_out(vif_id, index, tx_fifo, hw_tx, &send_pkt);
- + if(OK != ret)
- + {
- + if(HW_WRITE_ERROR == ret)
- + retry++;
- + continue;
- + }
- + done = done + send_pkt;
- + }
- +
- + if(g_wlan.sync.exit)
- + break;
- + wlan_sleep();
- +
- + if(gpio_get_value(SDIO_RX_GPIO))
- + {
- + if(g_wlan.wlan_trans.sem.count - done <= 1)
- + {
- + done = (g_wlan.wlan_trans.sem.count > 0)?(g_wlan.wlan_trans.sem.count-1):(0);
- + }
- + }
- + else
- + {
- + if( (0 == done) && (0 == retry) )
- + done = ( (0 == sem_count)?(1):(sem_count) );
- + }
- + for(i=0; i<done; i++)
- + {
- + trans_down();
- + }
- + }while(!kthread_should_stop());
- + sdiodev_readchn_uninit(8);
- + sdiodev_readchn_uninit(9);
- + mdbg_sdio_read();
- + del_timer_sync(&(g_wlan.hw.wakeup_timer));
- + printke("%s exit\n", __func__);
- + up(&(g_wlan.sync.sem));
- + return OK;
- +}
- +
- +static int wlan_tx_buf_alloc(wlan_vif_t *vif)
- +{
- + m_event_conf_t q_conf = {0};
- + txfifo_conf_t fifo_conf = {0};
- + int ret,q_id;
- + q_conf.event_size = sizeof(tx_msg_t);
- + q_conf.max_events = 5;
- + q_conf.highThres = 100;
- + q_conf.lowThres = 0;
- + q_conf.weight = 100;
- + ret = event_q_init(&(vif->event_q[EVENT_Q_ID_0]), &q_conf);
- + if(ERROR == ret)
- + return ERROR;
- +
- + q_conf.max_events = 150;
- + q_conf.highThres = 130;
- + q_conf.lowThres = 10;
- + for(q_id = EVENT_Q_ID_1; q_id < EVENT_Q_MAX_ID; q_id++)
- + {
- + ret = event_q_init(&(vif->event_q[q_id]), &q_conf);
- + if(ERROR == ret)
- + return ERROR;
- + }
- + vif->event_q[EVENT_Q_ID_1].weight = 40;
- + vif->event_q[EVENT_Q_ID_2].weight = 30;
- + vif->event_q[EVENT_Q_ID_3].weight = 20;
- + vif->event_q[EVENT_Q_ID_4].weight = 10;
- +
- + fifo_conf.cp2_txRam = HW_TX_SIZE - 64;
- + fifo_conf.max_msg_num = PKT_AGGR_NUM;
- + fifo_conf.size = 1024*256;
- + ret = tx_fifo_alloc(&(vif->txfifo), &fifo_conf);
- + if(ERROR == ret)
- + return ERROR;
- + return OK;
- +}
- +
- +static int wlan_tx_buf_free(wlan_vif_t *vif)
- +{
- + int q_id, num, i;
- + m_event_t *event_q;
- + tx_msg_t *event;
- + for(q_id=EVENT_Q_ID_0; q_id < EVENT_Q_MAX_ID; q_id++)
- + {
- + event_q = &(vif->event_q[q_id]);
- + num = event_q->event_cnt;
- + for(i=0; i < num; i++)
- + {
- + event = (tx_msg_t *)get_event(event_q);
- + if(NULL == event)
- + break;
- + if( HOST_SC2331_CMD == event->hdr.type)
- + {
- + if((event->slice[0].len > 0) &&(NULL != event->slice[0].data))
- + kfree(event->slice[0].data);
- + }
- + else if(HOST_SC2331_PKT == event->hdr.type)
- + {
- + if((NULL != event->p))
- + dev_kfree_skb((struct sk_buff *)(event->p));
- + }
- + else
- + {}
- + memset((unsigned char *)event, 0, sizeof(tx_msg_t) );
- + free_event((void *)event, event_q);
- + }
- + event_q_deinit(event_q);
- + }
- + tx_fifo_free(&(vif->txfifo));
- + return OK;
- +}
- +
- +static int wlan_rx_buf_alloc(void)
- +{
- + int ret;
- + rxfifo_t *rx_buf = &(g_wlan.rxfifo);
- + ret = rx_fifo_alloc(rx_buf);
- + return ret;
- +}
- +
- +static int wlan_rx_buf_free(void )
- +{
- + int ret;
- + rxfifo_t *rx_buf = &(g_wlan.rxfifo);
- + ret = rx_fifo_free(rx_buf);
- + return ret;
- +}
- +
- +static int wlan_hw_init(hw_info_t *hw)
- +{
- + memset(hw, 0, sizeof(hw_info_t) );
- +
- + hw->sdio_tx_chn.num = 3;
- + hw->sdio_tx_chn.chn[0] = 0;
- + hw->sdio_tx_chn.chn[1] = 1;
- + hw->sdio_tx_chn.chn[2] = 2;
- + hw->sdio_tx_chn.bit_map = 0x0007;
- + hw->sdio_tx_chn.timeout_time = 3000;
- + hw->sdio_tx_chn.timeout_flag = false;
- +
- + hw->sdio_rx_chn.num = 3;
- + hw->sdio_rx_chn.chn[0] = 8;
- + hw->sdio_rx_chn.chn[1] = 9;
- + hw->sdio_rx_chn.chn[2] = 14;
- + hw->sdio_rx_chn.bit_map = 0x4300;
- + hw->sdio_rx_chn.gpio_high = false;
- + hw->sdio_rx_chn.timeout_time = 3000;
- + hw->sdio_rx_chn.timeout_flag = false;
- +
- + printke("[SDIO_TX_CHN][0x%x][0x%x]\n", hw->sdio_tx_chn.bit_map, HW_TX_SIZE);
- + printke("[SDIO_RX_CHN][0x%x][0x%x]\n", hw->sdio_rx_chn.bit_map, HW_RX_SIZE);
- +
- + hw->wakeup = 0;
- + spin_lock_init(&(hw->sdio_rx_chn.lock));
- + wake_lock_init(&g_wlan.hw.wlan_lock, WAKE_LOCK_SUSPEND, "wlan_sc2331_lock");
- + init_timer(&g_wlan.hw.wakeup_timer);
- + g_wlan.hw.wakeup_timer.function = wakeup_timer_func;
- + g_wlan.hw.wakeup_time = 2000;
- + return OK;
- +}
- +static int wlan_inetaddr_event(struct notifier_block *this,
- + unsigned long event, void *ptr)
- +{
- + unsigned char vif_id;
- + wlan_vif_t *vif;
- + struct net_device *dev;
- + struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
- +
- + printkd("inetaddr callback is comming in !\n");
- +
- + dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL;
- +
- + if((dev != (id_to_vif(0)->ndev)) && (dev != (id_to_vif(1)->ndev)))
- + {
- + printkd("dev id not equal to 0 or 1!\n");
- + goto done;
- + }
- +
- + if (dev == NULL)
- + goto done;
- + printkd(" inetaddr dev not equal to null !\n");
- +
- + vif = ndev_to_vif(dev);
- + vif_id = vif->id;
- +
- + if (!vif)
- + goto done;
- + printkd("inetaddr vif not equal to null !\n");
- +
- + switch (event) {
- + case NETDEV_UP:
- + printkd("inetaddr UP event is comming in !\n");
- + wlan_cmd_get_ip(vif_id, (u8 *) & ifa->ifa_address);
- + break;
- + case NETDEV_DOWN:
- + printkd("inetaddr DOWN event is comming in !\n");
- + break;
- + default:
- + printkd("inetaddr defaut is comming in !\n");
- + break;
- + }
- +
- +done:
- + return NOTIFY_DONE;
- +}
- +
- +static struct notifier_block itm_inetaddr_cb = {
- + .notifier_call = wlan_inetaddr_event,
- +};
- +
- +static ssize_t wlan_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos)
- +{
- + int cmd, value;
- + char kbuf[32] = {0};
- + if (copy_from_user(kbuf, buffer, ( (count <= 32)?(count):(32) ) ) )
- + return -EFAULT;
- + sscanf(kbuf, "%d %d\n", &cmd, &value);
- +
- + printkd("[%s][%d][%d]\n", __func__,cmd, value);
- + switch (cmd)
- + {
- + case 1:
- + SET_BIT(g_dbg, value);
- + break;
- + case 2:
- + CLEAR_BIT(g_dbg, value);
- + break;
- + case 3:
- + wlan_cmd_mac_open(NETIF_0_ID, value, &(g_wlan.netif[NETIF_0_ID].ndev->dev_addr[0] ) );
- + break;
- + case 4:
- + wlan_cmd_mac_open(NETIF_1_ID, value, &(g_wlan.netif[NETIF_1_ID].ndev->dev_addr[0] ) );
- + break;
- + default:
- + break;
- + }
- + return count;
- +}
- +
- +static const struct file_operations wlan_proc_fops =
- +{
- + .owner = THIS_MODULE,
- + .write = wlan_proc_write,
- +};
- +
- +static const struct file_operations lte_concur_proc_fops =
- +{
- + .owner = THIS_MODULE,
- + .unlocked_ioctl = lte_concur_proc_ioctl,
- +#ifdef CONFIG_COMPAT
- + .compat_ioctl = compat_lte_concur_proc_ioctl,
- +#endif
- + .open = lte_concur_proc_open,
- + .release = lte_concur_proc_release,
- +};
- +
- +int wlan_module_init(struct device *dev)
- +{
- + int ret;
- +
- + printke("[%s] [ version:0x21 ] [ time(%s %s) ]\n", __func__, __DATE__, __TIME__);
- + if(NULL == dev)
- + return -EPERM;
- + ret = get_sdiohal_status();
- + if(1 != ret)
- + {
- + printke("######## %s sdio is not ready ##########\n", __func__);
- + return -EPERM;
- + }
- + else
- + {
- + printke("sdio is ready !!!\n");
- + }
- + //marlin_pa_enable(true);
- +
- +
- + memset((unsigned char *)(&g_wlan), 0, sizeof(wlan_info_t));
- + g_wlan.dev = dev;
- + g_wlan.netif[NETIF_0_ID].id= NETIF_0_ID;
- + g_wlan.netif[NETIF_1_ID].id= NETIF_1_ID;
- + g_wlan.sync.exit = 0;
- + sema_init(&g_wlan.sync.sem, 0);
- + wlan_hw_init(&(g_wlan.hw));
- +
- + ret = wlan_tx_buf_alloc(&(g_wlan.netif[NETIF_0_ID]));
- + if(OK != ret)
- + return -EPERM;
- + ret = wlan_tx_buf_alloc(&(g_wlan.netif[NETIF_1_ID]));
- + if(OK != ret)
- + return -EPERM;
- + ret = wlan_rx_buf_alloc();
- + if(OK != ret)
- + return -EPERM;
- +
- + wlan_cmd_init();
- +
- + g_wlan.wlan_core.task = kthread_create(wlan_core_thread, (void *)(dev), "wlan_core");
- + if(NULL != g_wlan.wlan_core.task)
- + {
- + wake_up_process(g_wlan.wlan_core.task);
- + }
- + down(&(g_wlan.sync.sem));
- +
- + g_wlan.wlan_trans.task = kthread_create(wlan_trans_thread, (void *)(dev), "wlan_trans");
- + if(NULL != g_wlan.wlan_trans.task)
- + {
- + wake_up_process(g_wlan.wlan_trans.task);
- + }
- + down(&(g_wlan.sync.sem));
- +
- + ret = wlan_wiphy_new(&(g_wlan));
- + if(OK != ret)
- + return -EPERM;
- + ret = wlan_vif_init(&(g_wlan.netif[NETIF_0_ID]), NL80211_IFTYPE_ADHOC, "wlan0", (void *)(&wlan_ops) );
- + if(OK != ret)
- + return -EPERM;
- + ret = wlan_vif_init(&(g_wlan.netif[NETIF_1_ID]), NL80211_IFTYPE_P2P_DEVICE, "p2p0", (void *)(&wlan_ops) );
- + if(OK != ret)
- + return -EPERM;
- + wlan_nl_init();
- +
- + g_wlan.hw.early_suspend.suspend = wlan_early_suspend;
- + g_wlan.hw.early_suspend.resume = wlan_late_resume;
- + g_wlan.hw.early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 1;
- + register_early_suspend(&g_wlan.hw.early_suspend);
- +
- + ret = register_inetaddr_notifier(&itm_inetaddr_cb);
- + if (ret) {
- + printke("Couldn't register inetaddr notifier \n");
- + }
- + if (!proc_create("wlan", 0666, NULL, &wlan_proc_fops))
- + {
- + printke("Couldn't create the /proc/wlan \n");
- + }
- + if (!proc_create("lte_concur", 0666, NULL, <e_concur_proc_fops))
- + {
- + printke("Couldn't create the /proc/lte_concur \n");
- + }
- + g_dbg = 0x0;
- + SET_BIT(g_dbg,1);
- + printke("%s ok!\n", __func__);
- + return OK;
- +}
- +EXPORT_SYMBOL_GPL(wlan_module_init);
- +
- +int wlan_module_exit(struct device *dev)
- +{
- + printke("%s enter\n", __func__);
- + unregister_inetaddr_notifier(&itm_inetaddr_cb);
- + //marlin_pa_enable(false);
- + if(ITM_NONE_MODE != g_wlan.netif[NETIF_0_ID].mode)
- + wlan_cmd_mac_close(NETIF_0_ID, g_wlan.netif[NETIF_0_ID].mode);
- + if(ITM_NONE_MODE != g_wlan.netif[NETIF_1_ID].mode)
- + wlan_cmd_mac_close(NETIF_1_ID, g_wlan.netif[NETIF_1_ID].mode);
- + g_wlan.sync.exit = 1;
- + core_up();
- + down(&(g_wlan.sync.sem));
- + trans_up();
- + down(&(g_wlan.sync.sem));
- +
- + wlan_vif_free(&(g_wlan.netif[NETIF_0_ID]));
- + wlan_vif_free(&(g_wlan.netif[NETIF_1_ID]));
- + wlan_wiphy_free(&g_wlan);
- + wlan_cmd_deinit();
- + wlan_tx_buf_free(&(g_wlan.netif[NETIF_0_ID]));
- + wlan_tx_buf_free(&(g_wlan.netif[NETIF_1_ID]));
- + wlan_rx_buf_free();
- + wlan_nl_deinit();
- +
- + remove_proc_entry("wlan", NULL);
- + unregister_early_suspend(&g_wlan.hw.early_suspend);
- + wake_lock_destroy(&g_wlan.hw.wlan_lock);
- + printke("%s ok!\n", __func__);
- + return OK;
- +}
- +EXPORT_SYMBOL_GPL(wlan_module_exit);
- +
- +static int sprd_wlan_probe(struct platform_device *pdev)
- +{
- + return wlan_module_init(&(pdev->dev));
- +}
- +
- +static int sprd_wlan_remove(struct platform_device *pdev)
- +{
- + return wlan_module_exit(&(pdev->dev));
- +}
- +
- +#define DEVICE_NAME "sc2331"
- +static struct platform_device *sprd_wlan_device;
- +static struct platform_driver sprd_wlan_driver =
- +{
- + .probe = sprd_wlan_probe,
- + .remove = sprd_wlan_remove,
- + .driver =
- + {
- + .owner = THIS_MODULE,
- + .name = DEVICE_NAME,
- + },
- +};
- +static int sprd_wlan_init(void)
- +{
- + sprd_wlan_device = platform_device_register_simple(DEVICE_NAME, 0, NULL, 0);
- + if (IS_ERR(sprd_wlan_device))
- + return PTR_ERR(sprd_wlan_device);
- + return platform_driver_register(&(sprd_wlan_driver));
- +}
- +
- +static void sprd_wlan_exit(void)
- +{
- + platform_driver_unregister(&sprd_wlan_driver);
- + platform_device_unregister(sprd_wlan_device);
- + sprd_wlan_device = NULL;
- +}
- +
- +module_init(sprd_wlan_init);
- +module_exit(sprd_wlan_exit);
- +MODULE_DESCRIPTION("SPRD sc2331 Wireless Network Adapter");
- +MODULE_AUTHOR("jinglong.chen");
- +MODULE_LICENSE("GPL");
- +MODULE_VERSION("1.0");
- +
- +
- diff --git a/drivers/net/wireless/sprdwl/wlan_event_q.c b/drivers/net/wireless/sprdwl/wlan_event_q.c
- new file mode 100644
- index 0000000..36baa47
- --- /dev/null
- +++ b/drivers/net/wireless/sprdwl/wlan_event_q.c
- @@ -0,0 +1,123 @@
- +/*
- + * Copyright (C) 2014 Spreadtrum Communications Inc.
- + *
- + * Authors:<jinglong.chen@spreadtrum.com>
- + * Owner:
- + * jinglong.chen
- + *
- + * This software is licensed under the terms of the GNU General Public
- + * License version 2, as published by the Free Software Foundation, and
- + * may be copied, distributed, and modified under those terms.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + */
- +
- +#include <linux/irqflags.h>
- +#include <linux/spinlock.h>
- +#include<linux/slab.h>
- +#include "wlan_common.h"
- +#include "wlan_event_q.h"
- +
- +static void update_buff_status(unsigned char *buff, unsigned short index, unsigned char status)
- +{
- + unsigned char offset = 0;
- + offset = (index & 0x3) << 1;
- + buff += (index >> 2);
- + *buff = (status << offset) | (*buff & (~(0x3 << offset)));
- +}
- +static unsigned char check_buff_status(unsigned char *buff, unsigned short index)
- +{
- + unsigned char offset = 0;
- + unsigned char status = 0;
- + offset = (index & 0x3) << 1;
- + buff += (index >> 2);
- + status = (*buff >> offset) & 0x3;
- + return status;
- +}
- +
- +void *alloc_event(m_event_t *mEventQ)
- +{
- + unsigned short index = 0;
- + unsigned char *free_event_buff = 0;
- + if(mEventQ->event_cnt == mEventQ->max_events)
- + {
- + return NULL;
- + }
- + spin_lock_bh( &(mEventQ->spinlock) );
- + index = INCR_RING_BUFF_INDX(mEventQ->tail_index, mEventQ->max_events);
- + if(check_buff_status(mEventQ->buf_status, index) == EVENT_BUFFER_FREE)
- + {
- + mEventQ->tail_index = index;
- + update_buff_status(mEventQ->buf_status, index, EVENT_BUFFER_ALLOC);
- + free_event_buff = (mEventQ->event_buf + (index * mEventQ->event_size));
- + }
- + spin_unlock_bh(&(mEventQ->spinlock));
- + return free_event_buff;
- +}
- +
- +void post_event(unsigned char *event, m_event_t *mEventQ)
- +{
- + unsigned short index = 0;
- + spin_lock_bh( &(mEventQ->spinlock) );
- + index = ((size_t)event - (size_t)mEventQ->event_buf) / mEventQ->event_size;
- + update_buff_status(mEventQ->buf_status, index, EVENT_BUFFER_VALID);
- + mEventQ->event_cnt++;
- + spin_unlock_bh(&(mEventQ->spinlock));
- +}
- +
- +unsigned char *get_event(m_event_t *mEventQ)
- +{
- + unsigned char status = 0;
- + unsigned char *head_event = NULL;
- + if(mEventQ->event_cnt == 0)
- + return NULL;
- + status = check_buff_status(mEventQ->buf_status, mEventQ->head_index);
- + if(status == EVENT_BUFFER_VALID)
- + {
- + head_event = (mEventQ->event_buf) + (mEventQ->head_index * mEventQ->event_size);
- + }
- + return head_event;
- +}
- +
- +void free_event(void *event, m_event_t *mEventQ)
- +{
- + spin_lock_bh( &(mEventQ->spinlock) );
- + update_buff_status(mEventQ->buf_status, mEventQ->head_index, EVENT_BUFFER_FREE);
- + mEventQ->head_index = INCR_RING_BUFF_INDX(mEventQ->head_index, mEventQ->max_events);
- + mEventQ->event_cnt--;
- + spin_unlock_bh(&(mEventQ->spinlock));
- +}
- +
- +int event_q_init(m_event_t *mEventQ, m_event_conf_t *conf)
- +{
- + mEventQ->event_size = conf->event_size;
- + mEventQ->max_events = conf->max_events;
- + mEventQ->tail_index = conf->max_events - 1;
- + mEventQ->head_index = 0;
- + mEventQ->highThres = conf->highThres;
- + mEventQ->lowThres = conf->lowThres;
- + mEventQ->weight = conf->weight;
- +
- + mEventQ->buf_status = kmalloc( EVENT_TOTAL_MEM_SIZE((mEventQ->max_events), (mEventQ->event_size)), GFP_KERNEL );
- + if(NULL == mEventQ->buf_status)
- + {
- + ASSERT();
- + return ERROR;
- + }
- + memset( mEventQ->buf_status, 0, EVENT_TOTAL_MEM_SIZE((mEventQ->max_events), (mEventQ->event_size)) );
- + mEventQ->event_buf = (unsigned char *)(WORD_ALIGN((size_t)(mEventQ->buf_status + EVENT_STATUS_SIZE(mEventQ->max_events) )));
- + spin_lock_init( &(mEventQ->spinlock) );
- + return OK;
- +}
- +
- +int event_q_deinit(m_event_t *mEventQ)
- +{
- + if(NULL != mEventQ->buf_status)
- + kfree(mEventQ->buf_status);
- + memset( (unsigned char *)mEventQ, 0, sizeof(m_event_t) );
- + return OK;
- +}
- +
- diff --git a/drivers/net/wireless/sprdwl/wlan_event_q.h b/drivers/net/wireless/sprdwl/wlan_event_q.h
- new file mode 100644
- index 0000000..7202352
- --- /dev/null
- +++ b/drivers/net/wireless/sprdwl/wlan_event_q.h
- @@ -0,0 +1,49 @@
- +#ifndef __EVENT_MANAGER_H__
- +#define __EVENT_MANAGER_H__
- +#include <linux/spinlock.h>
- +
- +#define WORD_ALIGN(val) (((val) & 0x03) ? ((val) + 4 - ((val) & 0x03)) : (val))
- +
- +#define MAX_WORD_ALIGNMENT_BUFFER (3)
- +#define EVENT_TOTAL_MEM_SIZE( num, size ) ( (WORD_ALIGN((num >> 2) + 1)) + ( (num)*(size) ) + (MAX_WORD_ALIGNMENT_BUFFER) )
- +#define EVENT_STATUS_SIZE(num) ( WORD_ALIGN((num >> 2) + 1) )
- +
- +typedef enum
- +{
- + EVENT_BUFFER_FREE = 0,
- + EVENT_BUFFER_ALLOC = 1,
- + EVENT_BUFFER_VALID = 2,
- +} EVENT_BUFFER_STATUS_T;
- +
- +typedef struct
- +{
- + unsigned char *event_buf; /* Base address of event buffer array */
- + unsigned char *buf_status; /* Base address of buffer status array */
- + unsigned short event_size; /* Size of the event message structure */
- + unsigned short max_events; /* Number of events can be accomadated in the queue */
- + unsigned short event_cnt; /* Current number of valid events */
- + unsigned short tail_index; /* Last index inserted */
- + unsigned short head_index; /* Next index to be read */
- + unsigned short highThres;
- + unsigned short lowThres;
- + unsigned short weight;
- + spinlock_t spinlock;
- +}m_event_t;
- +
- +typedef struct
- +{
- + unsigned short event_size;
- + unsigned short max_events;
- + unsigned short highThres;
- + unsigned short lowThres;
- + unsigned short weight;
- +}m_event_conf_t;
- +
- +extern void *alloc_event(m_event_t *mEventQ);
- +extern void post_event(unsigned char *event, m_event_t *mEventQ);
- +extern unsigned char *get_event(m_event_t *mEventQ);
- +extern void free_event(void *event, m_event_t *mEventQ);
- +extern int event_q_init(m_event_t *mEventQ, m_event_conf_t *conf);
- +extern int event_q_deinit(m_event_t *mEventQ);
- +#endif
- +
- diff --git a/drivers/net/wireless/sprdwl/wlan_fifo.c b/drivers/net/wireless/sprdwl/wlan_fifo.c
- new file mode 100644
- index 0000000..0b42f52
- --- /dev/null
- +++ b/drivers/net/wireless/sprdwl/wlan_fifo.c
- @@ -0,0 +1,326 @@
- +/*
- + * Copyright (C) 2014 Spreadtrum Communications Inc.
- + *
- + * Authors:<jinglong.chen@spreadtrum.com>
- + * Owner:
- + * jinglong.chen
- + *
- + * This software is licensed under the terms of the GNU General Public
- + * License version 2, as published by the Free Software Foundation, and
- + * may be copied, distributed, and modified under those terms.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + */
- +
- +#include<linux/slab.h>
- +#include "wlan_common.h"
- +#include "wlan_fifo.h"
- +
- +extern unsigned char *wifi_256k_alloc(void);
- +extern int wifi_256k_free(unsigned char *mem);
- +
- +unsigned char *fifo_mem_alloc(unsigned int byte)
- +{
- + unsigned char *mem = NULL;
- + if(byte > 16*1024)
- + {
- + mem = wifi_256k_alloc();
- + }
- + else
- + {
- + mem = kmalloc(byte, GFP_KERNEL);
- + printkd("kmalloc(%d):%p\n", byte, mem);
- + }
- + if(NULL == mem)
- + printke("[%s][NULL]\n", __func__);
- + return mem;
- +}
- +
- +int fifo_mem_free(unsigned char *mem, unsigned int byte)
- +{
- + if(NULL == mem)
- + return ERROR;
- + if(byte > 16*1024)
- + {
- + wifi_256k_free(mem);
- + }
- + else
- + {
- + printkd("kfree:%p\n", mem);
- + kfree(mem);
- + }
- + return OK;
- +}
- +
- +int tx_fifo_in(txfifo_t *fifo, tx_msg_t *msg )
- +{
- + int ret;
- + unsigned int unitLen;
- + unsigned char *p;
- + t_msg_hdr_t *hdr = &(msg->hdr);
- + unitLen = TX_MSG_UNIT_LEN(hdr);
- + if(fifo->WT >= fifo->RD)
- + {
- + if( unitLen > (fifo->size - fifo->WT) )
- + {
- + if( (unitLen+sizeof(tx_big_hdr_t)) > fifo->RD )
- + {
- + ret = TX_FIFO_FULL;
- + goto out;
- + }
- + spin_lock( &(fifo->lock) );
- + fifo->LASTWT = fifo->WT;
- + spin_unlock( &(fifo->lock) );
- + fifo->WT = 0;
- + }
- + }
- + else
- + {
- + if( (unitLen + sizeof(tx_big_hdr_t) > (fifo->RD - fifo->WT) ))
- + {
- + ret = TX_FIFO_FULL;
- + goto out;
- + }
- + }
- +
- + hdr = (t_msg_hdr_t *)(fifo->mem + fifo->WT);
- + memcpy((unsigned char *)hdr, (unsigned char *)(&(msg->hdr)), sizeof(t_msg_hdr_t) );
- + p = (unsigned char *)hdr + TX_MSG_HEAD_FILED(hdr);
- + if(NULL != msg->slice[0].data)
- + {
- + memcpy(p, (unsigned char *)(msg->slice[0].data), msg->hdr.len );
- + }
- + fifo->WT = fifo->WT + unitLen;
- + fifo->wt_cnt++;
- + if(HOST_SC2331_CMD == hdr->type)
- + {
- + printkp("[CMD_IN][%s]\n", get_cmd_name(hdr->subtype) );
- + }
- + ret = OK;
- +out:
- + return ret;
- +}
- +
- +int tx_fifo_out(const unsigned char netif_id,
- + const unsigned chn, txfifo_t *fifo,
- + P_FUNC_1 pfunc, unsigned int *count)
- +{
- + unsigned int len,num;
- + unsigned char *readTo, *readFrom, *readMax;
- + t_msg_hdr_t *hdr;
- + tx_big_hdr_t *big_hdr;
- + int ret = ERROR;
- +
- +restart:
- + if(fifo->RD == fifo->WT )
- + {
- + readMax = fifo->mem + fifo->LASTWT;
- + }
- + else if(fifo->WT < fifo->RD)
- + {
- + if(fifo->RD == fifo->LASTWT)
- + {
- + fifo->RD = 0;
- + spin_lock( &(fifo->lock) );
- + fifo->LASTWT = -1;
- + spin_unlock( &(fifo->lock) );
- + goto restart;
- + }
- + else
- + {
- + readMax = fifo->mem + fifo->LASTWT;
- + }
- + }
- + else
- + {
- + readMax = fifo->mem + fifo->WT;
- + }
- +
- + readTo = fifo->mem + fifo->RD;
- + readFrom = readTo - sizeof(tx_big_hdr_t);
- + big_hdr = (tx_big_hdr_t *)(readFrom);
- +
- + memset((unsigned char *)big_hdr, 0, sizeof(tx_big_hdr_t) );
- + big_hdr->mode = netif_id;
- + len = sizeof(tx_big_hdr_t);
- +
- + for(num=0; num < fifo->max_msg_num; num++)
- + {
- + hdr = (t_msg_hdr_t *)(readTo);
- + if((unsigned char *)hdr >= readMax )
- + break;
- + len = len + TX_MSG_UNIT_LEN(hdr);
- + if( len >= fifo->cp2_txRam )
- + break;
- + if(HOST_SC2331_CMD == hdr->type)
- + {
- + printkp("[CMD_OUT][%s]\n", get_cmd_name(hdr->subtype) );
- + }
- + if( (hdr->type > 2) || (hdr->subtype > 47) )
- + {
- + ASSERT();
- + }
- + memcpy( (unsigned char *)(&(big_hdr->msg[num])), readTo, sizeof(t_msg_hdr_t));
- + big_hdr->msg_num++;
- + hdr = TX_MSG_NEXT_MSG(hdr);
- + readTo = (unsigned char *)hdr;
- + }
- + *count = num;
- + len = readTo - readFrom;
- + big_hdr->len = len;
- +
- + if(len >= (sizeof(tx_big_hdr_t) + sizeof(t_msg_hdr_t)))
- + {
- + ret = pfunc(chn, readFrom, len);
- + if(OK != ret)
- + {
- + ret = HW_WRITE_ERROR;
- + goto out;
- + }
- + else
- + ret = OK;
- + }
- + else
- + {
- + ASSERT();
- + ret = -5;
- + }
- + if( (fifo->RD > fifo->WT) && ( (readMax - readTo) < sizeof(t_msg_hdr_t) ) )
- + {
- + fifo->RD = 0;
- + fifo->rd_cnt = fifo->rd_cnt + num;
- + spin_lock( &(fifo->lock) );
- + fifo->LASTWT = -1;
- + spin_unlock( &(fifo->lock) );
- + }
- + else
- + {
- + fifo->RD = readTo - fifo->mem;
- + fifo->rd_cnt = fifo->rd_cnt + num;
- + }
- +out:
- + return ret;
- +}
- +
- +unsigned int tx_fifo_in_pkt(txfifo_t *tx_fifo)
- +{
- + return tx_fifo->wt_cnt - tx_fifo->rd_cnt;
- +}
- +
- +unsigned int tx_fifo_used(txfifo_t *tx_fifo)
- +{
- + unsigned int used;
- + txfifo_t fifo = {0};
- + memcpy((unsigned char *)(&fifo), (unsigned char *)(tx_fifo), 12 );
- + used = ( (-1 == fifo.LASTWT)?(fifo.WT - fifo.RD):((fifo.LASTWT - fifo.RD) + fifo.WT) );
- + return used;
- +}
- +
- +int tx_fifo_alloc(txfifo_t *tx_fifo, txfifo_conf_t *conf)
- +{
- + tx_fifo->size = conf->size;
- + tx_fifo->cp2_txRam = conf->cp2_txRam;
- + tx_fifo->mem = fifo_mem_alloc(tx_fifo->size);
- + if(NULL == tx_fifo->mem)
- + {
- + ASSERT();
- + return ERROR;
- + }
- + tx_fifo->mem = tx_fifo->mem + sizeof(tx_big_hdr_t);
- + tx_fifo->size = tx_fifo->size - ( sizeof(tx_big_hdr_t) + SDIO_ALIGN_SIZE ) ;
- + tx_fifo->WT = 0;
- + tx_fifo->RD = 0;
- + tx_fifo->LASTWT = -1;
- + tx_fifo->max_msg_num = conf->max_msg_num;
- + spin_lock_init(&(tx_fifo->lock));
- + return OK;
- +}
- +
- +int tx_fifo_free(txfifo_t *tx_fifo)
- +{
- + unsigned char *fifo_mem = tx_fifo->mem - sizeof(tx_big_hdr_t);
- + if(NULL != fifo_mem)
- + fifo_mem_free(fifo_mem, (tx_fifo->size + sizeof(tx_big_hdr_t) + SDIO_ALIGN_SIZE ) );
- +
- + memset((unsigned char *)tx_fifo, 0, sizeof(txfifo_t) );
- + return OK;
- +}
- +
- +int rx_fifo_in(const unsigned char chn, rxfifo_t *fifo, P_FUNC_2 pfunc )
- +{
- + int ret;
- + unsigned int rx_len = -1;
- + bool full = false;
- + if(fifo->WT >= fifo->RD)
- + {
- + if( (fifo->WT - fifo->RD) >= ( fifo->block_num -1) )
- + full = true;
- + }
- + else
- + {
- + if( 1 == (fifo->RD - fifo->WT) )
- + full = true;
- + }
- + if(true == full)
- + return ERROR;
- + ret = pfunc(chn, fifo->mem[fifo->WT], &rx_len);
- + if(ERROR != ret)
- + fifo->WT = INCR_RING_BUFF_INDX(fifo->WT, fifo->block_num);
- + return ret;
- +}
- +
- +int rx_fifo_out(rxfifo_t *fifo, P_FUNC_3 pfunc )
- +{
- + int ret = OK;
- + if(fifo->WT == fifo->RD)
- + return ERROR;
- + ret = pfunc( fifo->mem[fifo->RD], fifo->block_size );
- + fifo->RD = INCR_RING_BUFF_INDX(fifo->RD, fifo->block_num );
- + return ret;
- +}
- +
- +int rx_fifo_used(rxfifo_t *fifo)
- +{
- + int ret = 0;
- + if(fifo->WT >= fifo->RD)
- + ret = fifo->WT - fifo->RD;
- + else
- + ret = fifo->block_num - (fifo->RD - fifo->WT);
- + return ret;
- +}
- +
- +int rx_fifo_alloc(rxfifo_t *fifo)
- +{
- + int i;
- + memset(fifo, 0, sizeof(rxfifo_t) ) ;
- + fifo->block_size = RX_FIFO_BLOCK_SIZE;
- + fifo->block_num = RX_FIFO_BLOCK_NUM;
- + for(i=0; i < fifo->block_num; i++)
- + {
- + fifo->mem[i] = kmalloc(fifo->block_size, GFP_KERNEL );
- + if(NULL == fifo->mem[i])
- + {
- + ASSERT();
- + return ERROR;
- + }
- + }
- + return OK;
- +}
- +
- +int rx_fifo_free(rxfifo_t *fifo )
- +{
- + int i;
- + for(i=0; i < fifo->block_num; i++)
- + {
- + if(NULL != fifo->mem[i])
- + kfree(fifo->mem[i]);
- + }
- + memset(fifo, 0, sizeof(rxfifo_t)) ;
- + return OK;
- +}
- +
- +
- +
- diff --git a/drivers/net/wireless/sprdwl/wlan_fifo.h b/drivers/net/wireless/sprdwl/wlan_fifo.h
- new file mode 100644
- index 0000000..d47b530
- --- /dev/null
- +++ b/drivers/net/wireless/sprdwl/wlan_fifo.h
- @@ -0,0 +1,106 @@
- +#ifndef __SPRD_WLAN_FIFO_H_
- +#define __SPRD_WLAN_FIFO_H_
- +
- +#include "wlan_common.h"
- +
- +#define TX_MSG_HEAD_FILED(hdr) ( ( sizeof(t_msg_hdr_t) + ( (2==((hdr)->type) )?34:0 ) ) )
- +#define TX_MSG_UNIT_LEN(hdr) ( ( ALIGN_4BYTE( TX_MSG_HEAD_FILED(hdr) + ((hdr)->len) ) ) )
- +#define TX_MSG_NEXT_MSG(hdr) ( ( (t_msg_hdr_t *)( (unsigned char *)(hdr) + TX_MSG_UNIT_LEN(hdr) ) ) )
- +
- +#define OK ( 0)
- +#define ERROR (-1)
- +#define TX_FIFO_FULL (-2)
- +#define TX_FIFO_EMPTY (-3)
- +#define HW_WRITE_ERROR (-4)
- +#define HW_READ_ERROR (-6)
- +
- +#define RX_FIFO_BLOCK_NUM (8)
- +#define RX_FIFO_BLOCK_SIZE HW_RX_SIZE
- +
- +typedef int (*P_FUNC_1)(unsigned short, unsigned char *, unsigned int );
- +typedef int (*P_FUNC_2)(unsigned short, unsigned char *, unsigned int *);
- +typedef int (*P_FUNC_3)(unsigned char *,unsigned int);
- +
- +typedef struct
- +{
- + unsigned char *data;
- + unsigned short len;
- +} dataInfo;
- +
- +typedef struct
- +{
- + unsigned char type: 7; /* CMD/RSP/USER DATA */
- + unsigned char mode: 1; /* message dest mode: 1 STA, 2 softAP, 3 P2P */
- + unsigned char subtype; /* SEARCH/ ATTACH/DETACH */
- + unsigned short len; /* Length not include common header */
- +}t_msg_hdr_t;
- +
- +typedef struct
- +{
- + unsigned char type: 7; /* CMD/RSP/USER DATA */
- + unsigned char mode: 1; /* message dest mode: 1 STA, 2 softAP, 3 P2P */
- + unsigned char subtype; /* SEARCH/ ATTACH/DETACH */
- + unsigned short len; /* Length not include common header */
- +}r_msg_hdr_t;
- +
- +typedef struct
- +{
- + unsigned char mode;
- + unsigned char msg_num;
- + unsigned short len;
- + t_msg_hdr_t msg[14];
- + /* FIXME with CP if sizeof(int)==64 */
- + unsigned int tx_cnt;
- +}tx_big_hdr_t;
- +
- +typedef struct
- +{
- + t_msg_hdr_t hdr;
- + dataInfo slice[2];
- + void *p;
- +}tx_msg_t;
- +
- +typedef struct
- +{
- + unsigned int WT;
- + unsigned int RD;
- + int LASTWT;
- + unsigned char *mem;
- + unsigned int size;
- + unsigned int cp2_txRam;
- + unsigned short max_msg_num;
- + spinlock_t lock;
- + unsigned int wt_cnt;
- + unsigned int rd_cnt;
- +}txfifo_t;
- +
- +typedef struct
- +{
- + unsigned int size;
- + unsigned int cp2_txRam;
- + unsigned short max_msg_num;
- +}txfifo_conf_t;
- +
- +typedef struct
- +{
- + unsigned int WT;
- + unsigned int RD;
- + unsigned int block_size;
- + unsigned int block_num;
- + unsigned char *mem[RX_FIFO_BLOCK_NUM];
- +}rxfifo_t;
- +extern int tx_fifo_alloc(txfifo_t *tx_fifo, txfifo_conf_t *conf);
- +extern int tx_fifo_free(txfifo_t *tx_fifo);
- +extern int tx_fifo_in(txfifo_t *fifo, tx_msg_t *msg );
- +extern int tx_fifo_out(const unsigned char netif_id,
- + const unsigned chn, txfifo_t *fifo,
- + P_FUNC_1 pfunc, unsigned int *count);
- +extern int rx_fifo_in(const unsigned char chn, rxfifo_t *fifo, P_FUNC_2 pfunc );
- +extern int rx_fifo_out(rxfifo_t *fifo, P_FUNC_3 pfunc );
- +extern int rx_fifo_used(rxfifo_t *fifo);
- +extern unsigned int tx_fifo_used(txfifo_t *fifo);
- +extern int rx_fifo_alloc(rxfifo_t *fifo);
- +extern int rx_fifo_free(rxfifo_t *fifo);
- +extern unsigned int tx_fifo_in_pkt(txfifo_t *tx_fifo);
- +#endif
- +
- diff --git a/drivers/net/wireless/sprdwl/wlan_hostapd_conf.c b/drivers/net/wireless/sprdwl/wlan_hostapd_conf.c
- new file mode 100644
- index 0000000..2b96b4b
- --- /dev/null
- +++ b/drivers/net/wireless/sprdwl/wlan_hostapd_conf.c
- @@ -0,0 +1,227 @@
- +#include <linux/types.h>
- +#include <linux/init.h>
- +#include <linux/mm.h>
- +#include <linux/fs.h>
- +#include <linux/fs_struct.h>
- +#include <linux/path.h>
- +#include <linux/uaccess.h>
- +#include <linux/slab.h>
- +#include "wlan_common.h"
- +
- +static int hex2num(char c)
- +{
- + if (c >= '0' && c <= '9')
- + return c - '0';
- +
- + if (c >= 'a' && c <= 'f')
- + return c - 'a' + 10;
- +
- + if (c >= 'A' && c <= 'F')
- + return c - 'A' + 10;
- +
- + return -1;
- +}
- +
- +static int hex2byte(const char *hex)
- +{
- + int a, b;
- +
- + a = hex2num(*hex++);
- + if (a < 0)
- + return -1;
- +
- + b = hex2num(*hex++);
- + if (b < 0)
- + return -1;
- +
- + return (a << 4) | b;
- +}
- +
- +/**
- + * hexstr2bin - Convert ASCII hex string into binary data
- + * @hex: ASCII hex string (e.g., "01ab")
- + * @buf: Buffer for the binary data
- + * @len: Length of the text to convert in bytes (of buf); hex will be double
- + * this size
- + * Returns: 0 on success, -1 on failure (invalid hex string)
- + */
- +static int hexstr2bin(const char *hex, u8 *buf, size_t len)
- +{
- + size_t i;
- + int a;
- + const char *ipos = hex;
- +
- + u8 *opos = buf;
- + for (i = 0; i < len; i++)
- + {
- + a = hex2byte(ipos);
- + if (a < 0)
- + return -1;
- + *opos++ = a;
- + ipos += 2;
- + }
- +
- + return 0;
- +}
- +
- +static struct hostap_conf *hostap_conf_create(void)
- +{
- + struct hostap_conf *conf = NULL;
- + conf = kmalloc(sizeof(struct hostap_conf), GFP_KERNEL);
- +
- + return conf;
- +}
- +
- +static int fp_size(struct file *f)
- +{
- + int error = -EBADF;
- + struct kstat stat;
- +
- +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
- + error = vfs_getattr(&f->f_path, &stat);
- +#else
- + error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, &stat);
- +#endif
- +
- + if (error == 0)
- + {
- + return stat.size;
- + }
- + else
- + {
- + pr_err("get hostapd conf file stat error\n");
- + return error;
- + }
- +}
- +
- +static int hostap_conf_read(char *filename, char **buf)
- +{
- + struct file *fp;
- + mm_segment_t fs;
- + int size = 0;
- + loff_t pos = 0;
- +
- + fp = filp_open(filename, O_RDONLY, 0);
- + if (IS_ERR(fp))
- + {
- + pr_err("open %s file error\n", filename);
- + goto end;
- + }
- +
- + fs = get_fs();
- + set_fs(KERNEL_DS);
- + size = fp_size(fp);
- + if (size <= 0)
- + {
- + pr_err("load file:%s error\n", filename);
- + goto error;
- + }
- +
- + *buf = kzalloc(size + 1, GFP_KERNEL);
- + vfs_read(fp, *buf, size, &pos);
- +
- +error:
- + filp_close(fp, NULL);
- + set_fs(fs);
- +end:
- + return size;
- +}
- +
- +static char *get_line(char *buf, char *end)
- +{
- + if (buf == NULL || buf >= end)
- + return NULL;
- + while (buf != end && *buf != '\n')
- + buf++;
- +
- + return buf;
- +}
- +
- +static unsigned char hostap_conf_parse(char *buf, int size,
- + struct hostap_conf *conf)
- +{
- + unsigned char ret = 0;
- + char *spos = buf, *epos = NULL, *pos = NULL;
- + int line = 0, errors = 0;
- +
- + if (!buf || !conf)
- + return 0;
- +
- + for (; (epos = get_line(spos, buf + size)); (spos = epos + 1))
- + {
- + line++;
- + if (spos[0] == '#')
- + continue;
- + pos = spos;
- + while (*pos != '\0' && pos <= epos)
- + {
- + if (*pos == '\n')
- + {
- + *pos = '\0';
- + break;
- + }
- + pos++;
- + }
- +
- + if (spos[0] == '\0')
- + continue;
- +
- + pos = strchr(spos, '=');
- + if (pos == NULL)
- + {
- + pr_err("Line %d: invalid line '%s'",
- + line, spos);
- + errors++;
- + continue;
- + }
- +
- + *pos = '\0';
- + pos++;
- +
- + if (strcmp(spos, "wpa_psk") == 0)
- + {
- + strlcpy(conf->wpa_psk, pos, sizeof(conf->wpa_psk));
- + conf->len = strlen(pos);
- + }
- + else
- + {
- + continue;
- + }
- + }
- +
- + return ret;
- +}
- +
- +int hostap_conf_load(char *filename, unsigned char *key_val)
- +{
- + struct hostap_conf *conf = NULL;
- + char *buf = NULL;
- + int size = 0;
- +
- + if (filename == NULL)
- + filename = HOSTAP_CONF_FILE_NAME;
- +
- + size = hostap_conf_read(filename, &buf);
- + if (size > 0)
- + {
- + conf = hostap_conf_create();
- + if (conf == NULL)
- + {
- + kfree(buf);
- + pr_err("create hostap_conf struct error.\n");
- + return -EINVAL;
- + }
- +
- + hostap_conf_parse(buf, size, conf);
- + if (conf->len > 64)
- + {
- + pr_err("wpa_psk len is error.(%d)\n", conf->len);
- + return -EINVAL;
- + }
- + hexstr2bin(conf->wpa_psk, key_val, conf->len / 2);
- + kfree(buf);
- + }
- +
- + return 0;
- +}
- +
- diff --git a/drivers/net/wireless/sprdwl/wlan_npi.c b/drivers/net/wireless/sprdwl/wlan_npi.c
- new file mode 100644
- index 0000000..44da5f9
- --- /dev/null
- +++ b/drivers/net/wireless/sprdwl/wlan_npi.c
- @@ -0,0 +1,173 @@
- +/*
- + * Copyright (C) 2014 Spreadtrum Communications Inc.
- + *
- + * Authors:<jinglong.chen@spreadtrum.com>
- + * Owner:
- + * jinglong.chen
- + *
- + * This software is licensed under the terms of the GNU General Public
- + * License version 2, as published by the Free Software Foundation, and
- + * may be copied, distributed, and modified under those terms.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + */
- +
- +#include <linux/kernel.h>
- +#include <linux/platform_device.h>
- +#include <linux/module.h>
- +#include <linux/uaccess.h>
- +#include <net/genetlink.h>
- +#include <linux/types.h>
- +#include "wlan_common.h"
- +#define WLAN_NL_GENERAL_SOCK_ID 1022
- +enum wlan_nl_commands
- +{
- + WLAN_NL_CMD_UNSPEC,
- + WLAN_NL_CMD_NPI,
- + WLAN_NL_CMD_GET_INFO,
- + WLAN_NL_CMD_MAX,
- +};
- +
- +enum wlan_nl_attrs
- +{
- + WLAN_NL_ATTR_UNSPEC,
- + WLAN_NL_ATTR_COMMON_USR_TO_DRV,
- + WLAN_NL_ATTR_COMMON_DRV_TO_USR,
- + WLAN_NL_ATTR_MAX,
- +};
- +extern unsigned int g_dbg;
- +extern wlan_info_t g_wlan;
- +static int wlan_nl_send_generic(struct genl_info *info, u8 attr, u8 cmd, u32 len, u8 *data);
- +extern int wlan_cmd_npi_send_recv(unsigned char *s_buf,unsigned short s_len, unsigned char *r_buf, unsigned short *r_len );
- +static int wlan_nl_npi_handler(struct sk_buff *skb_2, struct genl_info *info)
- +{
- + int ret = -EINVAL;
- + unsigned short s_len = 0;
- + unsigned char *s_buf = NULL;
- + /* -Werror=frame-larger-than, so kmalloc 1024 bytes*/
- + unsigned char *r_buf = NULL;
- + unsigned short r_len = 0;
- + unsigned char dbgStr[64] = {0};
- +
- + printkd("[%s][enter]\n", __func__);
- + if (info == NULL)
- + {
- + printkd("[%s][%d][ERROR]\n", __func__, __LINE__);
- + goto out;
- + }
- + if (info->attrs[WLAN_NL_ATTR_COMMON_USR_TO_DRV])
- + {
- + s_buf = nla_data(info->attrs[WLAN_NL_ATTR_COMMON_USR_TO_DRV]);
- + s_len = nla_len(info->attrs[WLAN_NL_ATTR_COMMON_USR_TO_DRV]);
- + sprintf(dbgStr, "[iwnpi][SEND][%d]:", s_len );
- + hex_dump(dbgStr, strlen(dbgStr), s_buf, s_len);
- + r_buf = kmalloc(1024, GFP_KERNEL);
- + if (!r_buf)
- + goto out;
- + wlan_cmd_npi_send_recv(s_buf, s_len, r_buf, &r_len);
- + sprintf(dbgStr, "[iwnpi][RECV][%d]:", r_len );
- + hex_dump(dbgStr, strlen(dbgStr), r_buf, r_len);
- + }
- +out:
- + ret = wlan_nl_send_generic(info,
- + WLAN_NL_ATTR_COMMON_DRV_TO_USR,
- + WLAN_NL_CMD_NPI, r_len, r_buf);
- + if (r_buf)
- + kfree(r_buf);
- + return ret;
- +}
- +
- +static int wlan_nl_get_info_handler(struct sk_buff *skb_2, struct genl_info *info)
- +{
- + int ret;
- + unsigned char r_buf[64] = {0};
- + unsigned short r_len = 0;
- + memcpy(r_buf, &( g_wlan.netif[0].ndev->dev_addr[0] ), 6 );
- + r_len = 6;
- + printkd("[%s][enter]\n", __func__ );
- + ret = wlan_nl_send_generic(info, WLAN_NL_ATTR_COMMON_DRV_TO_USR, WLAN_NL_CMD_GET_INFO, r_len, r_buf );
- + return ret;
- +}
- +
- +static struct nla_policy wlan_genl_policy[WLAN_NL_ATTR_MAX + 1] =
- +{
- + [WLAN_NL_ATTR_COMMON_USR_TO_DRV] = {.type = NLA_BINARY, .len = 1024},
- + [WLAN_NL_ATTR_COMMON_DRV_TO_USR] = {.type = NLA_BINARY, .len = 1024},
- +};
- +
- +static struct genl_ops wlan_nl_ops[] =
- +{
- + {
- + .cmd = WLAN_NL_CMD_NPI,
- + .policy = wlan_genl_policy,
- + .doit = wlan_nl_npi_handler,
- + },
- + {
- + .cmd = WLAN_NL_CMD_GET_INFO,
- + .policy = wlan_genl_policy,
- + .doit = wlan_nl_get_info_handler,
- + },
- +};
- +
- +static struct genl_family wlan_nl_genl_family =
- +{
- + .id = WLAN_NL_GENERAL_SOCK_ID,
- + .hdrsize = 0,
- + .name = "WLAN_NL",
- + .version = 1,
- + .maxattr = WLAN_NL_ATTR_MAX,
- +};
- +
- +static int wlan_nl_send_generic(struct genl_info *info, u8 attr, u8 cmd, u32 len, u8 *data)
- +{
- + struct sk_buff *skb;
- + void *hdr;
- + int ret;
- + skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
- + if (!skb)
- + return -ENOMEM;
- + hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, &wlan_nl_genl_family, 0, cmd);
- + if (IS_ERR(hdr))
- + {
- + ret = PTR_ERR(hdr);
- + goto err_put;
- + }
- + nla_put(skb, attr, len, data);
- + genlmsg_end(skb, hdr);
- + return genlmsg_reply(skb, info);
- +
- +err_put:
- + nlmsg_free(skb);
- + return ret;
- +}
- +
- +void wlan_nl_init(void )
- +{
- + int ret;
- + ret = genl_register_family_with_ops(&wlan_nl_genl_family, wlan_nl_ops, ARRAY_SIZE(wlan_nl_ops));
- + if (ret)
- + {
- + printkd("genl_register_family_with_ops error ret:%d\n", ret);
- + return;
- + }
- + printkd("%s\n", __func__);
- + return;
- +}
- +
- +void wlan_nl_deinit(void )
- +{
- + int ret;
- + ret = genl_unregister_family(&wlan_nl_genl_family);
- + if (ret)
- + {
- + printkd("genl_unregister_family error ret:%d\n", ret);
- + return;
- + }
- + printkd("%s\n", __func__);
- + return;
- +}
- +
- +
- diff --git a/drivers/net/wireless/sprdwl/wlan_wapi.c b/drivers/net/wireless/sprdwl/wlan_wapi.c
- new file mode 100644
- index 0000000..048d1cd
- --- /dev/null
- +++ b/drivers/net/wireless/sprdwl/wlan_wapi.c
- @@ -0,0 +1,666 @@
- +/*
- + * Copyright (C) 2013 Spreadtrum Communications Inc.
- + *
- + * Filename : wapi.c
- + * Abstract : This file is a implementation of WAPI decryption
- + * and encryption
- + *
- + * Authors :
- + * Wenjie.Zhang <Wenjie.Zhang@spreadtrum.com>
- + *
- + * This software is licensed under the terms of the GNU General Public
- + * License version 2, as published by the Free Software Foundation, and
- + * may be copied, distributed, and modified under those terms.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + */
- +#include "wlan_wapi.h"
- +
- +#define KEYID_LEN 1
- +#define RESERVD_LEN 1
- +#define PN_LEN 16
- +#define MIC_LEN 16
- +
- +/* little order,4, 5, 6, 11, 12, 13 should be set 0 */
- +const unsigned short frame_cntl_mask = 0x8FC7;
- +/* little order,bit 4~15 should be set 0 */
- +const unsigned short seq_cntl_mask = 0x0F00;
- +
- +#define SHA256_BLOCK_SIZE 64
- +#define SHA256_DIGEST_SIZE 32
- +
- +#define BYTES_PER_WORD 4
- +#define BYTE_LEN 8
- +#define WORD_LEN (BYTE_LEN * BYTES_PER_WORD)
- +#define TEXT_LEN 128
- +#define MK_LEN (TEXT_LEN / WORD_LEN)
- +#define RK_LEN 32
- +#define TEXT_BYTES (TEXT_LEN / BYTE_LEN)
- +
- +#define CK_INCREMENT 7
- +#define KEY_MULTIPLIER 0x80040100
- +#define TEXT_MULTIPLIER 0xa0202080
- +#define FK_PARAMETER_0 0xa3b1bac6
- +#define FK_PARAMETER_1 0x56aa3350
- +#define FK_PARAMETER_2 0x677d9197
- +#define FK_PARAMETER_3 0xb27022dc
- +
- +static const unsigned char s_box[] = {
- + 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7,
- + 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
- + 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3,
- + 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
- + 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a,
- + 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
- + 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95,
- + 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
- + 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba,
- + 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
- + 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b,
- + 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
- + 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2,
- + 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
- + 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52,
- + 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
- + 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5,
- + 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
- + 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55,
- + 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
- + 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60,
- + 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
- + 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f,
- + 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
- + 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f,
- + 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
- + 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd,
- + 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
- + 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e,
- + 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
- + 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20,
- + 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48
- +};
- +
- +static const unsigned int fk_parameter[] = { FK_PARAMETER_0, FK_PARAMETER_1,
- + FK_PARAMETER_2, FK_PARAMETER_3
- +};
- +
- +static const unsigned char s_xstate[] = {
- + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 0x00-0x0F */
- + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 0x10-0x1F */
- + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 0x20-0x2F */
- + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 0x30-0x3F */
- + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 0x40-0x4F */
- + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 0x50-0x5F */
- + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 0x60-0x6F */
- + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 0x70-0x7F */
- + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 0x80-0x8F */
- + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 0x90-0x9F */
- + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 0xA0-0xAF */
- + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 0xB0-0xBF */
- + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 0xC0-0xCF */
- + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 0xD0-0xDF */
- + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 0xE0-0xEF */
- + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 /* 0xF0-0xFF */
- +};
- +
- +static const unsigned int g_nextinputtable[RK_LEN] = {
- + 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
- + 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
- + 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
- + 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
- + 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
- + 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
- + 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
- + 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
- +};
- +
- +static const unsigned int cipherdataidx[MK_LEN][MK_LEN] = {
- + {3, 2, 1, 0},
- + {0, 3, 2, 1},
- + {1, 0, 3, 2},
- + {2, 1, 0, 3}
- +};
- +
- +#define PARITY_MACRO(value) (s_xstate[(value) >> 24] \
- + ^ s_xstate[((value) >> 16) & 0xFF] \
- + ^ s_xstate[((value) >> 8) & 0xFF] \
- + ^ s_xstate[(value) & 0xFF])
- +#define XOR_MACRO(A, B) ((A) ^ (B))
- +#define L_TRANSFORM_MACRO(word, key) multiplycircular(word, \
- + key ? KEY_MULTIPLIER : TEXT_MULTIPLIER)
- +
- +static unsigned int t_transform(unsigned int word)
- +{
- + unsigned int j;
- + unsigned int new_word;
- + int offset = 0;
- +
- + new_word = 0;
- + for (j = 0; j < MK_LEN; j++) {
- + new_word = (new_word << BYTE_LEN);
- + offset =
- + ((unsigned int)(word >> (WORD_LEN - BYTE_LEN))) &
- + ((unsigned int)((1 << BYTE_LEN) - 1));
- + new_word = new_word | (unsigned int)s_box[offset];
- + word = (word << BYTE_LEN);
- + }
- + return new_word;
- +}
- +
- +static unsigned int multiplycircular(unsigned int word, unsigned int basis)
- +{
- + unsigned int new_word;
- + unsigned int i;
- +
- + new_word = 0;
- +
- + for (i = 0; i < WORD_LEN; i++) {
- + new_word = (new_word << 1) | PARITY_MACRO(word & basis);
- +
- + basis = (basis >> 1) | ((basis & 1) << (WORD_LEN - 1));
- + }
- + return new_word;
- +}
- +
- +static unsigned int iterate(bool key, unsigned int next_input,
- + unsigned int *cipher_text, unsigned int curidx)
- +{
- + unsigned int new_state;
- +
- + new_state = next_input;
- + new_state = XOR_MACRO(new_state, cipher_text[cipherdataidx[curidx][0]]);
- + new_state = XOR_MACRO(new_state, cipher_text[cipherdataidx[curidx][1]]);
- + new_state = XOR_MACRO(new_state, cipher_text[cipherdataidx[curidx][2]]);
- + new_state = L_TRANSFORM_MACRO(t_transform(new_state), key);
- + new_state = XOR_MACRO(new_state, cipher_text[cipherdataidx[curidx][3]]);
- +
- + cipher_text[curidx] = new_state;
- +
- + return new_state;
- +}
- +
- +static void calculateenkey(unsigned char *key, unsigned int *key_store)
- +{
- + unsigned int cipher_text[MK_LEN];
- +
- + unsigned int next, i, j, next_input;
- +
- + for (j = 0; j < MK_LEN; j++) {
- + next = 0;
- + for (i = 0; i < BYTES_PER_WORD; i++) {
- + next = (next << BYTE_LEN);
- + next = next | key[(j << 2) + i];
- + }
- +
- + cipher_text[j] = XOR_MACRO(next, fk_parameter[j]);
- + }
- +
- + for (i = 0; i < RK_LEN; i++) {
- + next_input = g_nextinputtable[i];
- +
- + key_store[i] =
- + iterate(true, next_input, cipher_text, i & (MK_LEN - 1));
- + }
- +}
- +
- +static void SMS4_Run(unsigned int *key_store, unsigned char *plaintext,
- + unsigned char *ciphertext)
- +{
- + unsigned int i, j;
- + unsigned int next;
- + unsigned int next_input;
- + unsigned int plain_text[MK_LEN];
- +
- + for (j = 0; j < MK_LEN; j++) {
- + next = 0;
- + for (i = 0; i < BYTES_PER_WORD; i++) {
- + next = (next << BYTE_LEN);
- + next = next | plaintext[(j << 2) + i];
- + }
- + plain_text[j] = next;
- + }
- +
- + for (i = 0; i < RK_LEN; i++) {
- + next_input = key_store[i];
- + (void)iterate(false, next_input, plain_text, i & (MK_LEN - 1));
- + }
- +
- + for (j = 0; j < MK_LEN; j++) {
- + next = plain_text[(MK_LEN - 1) - j];
- + for (i = 0; i < BYTES_PER_WORD; i++) {
- + ciphertext[(j << 2) + i] =
- + (unsigned char)((next >> (WORD_LEN - BYTE_LEN)) &
- + ((1 << BYTE_LEN) - 1));
- + next = (next << BYTE_LEN);
- + }
- + }
- +}
- +
- +void WapiCryptoSms4(unsigned char *iv, unsigned char *key, unsigned char *input,
- + unsigned int length,
- + unsigned char *mic, unsigned char *output)
- +{
- + unsigned int i;
- + unsigned char sms4Output[TEXT_BYTES];
- + unsigned char tmp_data[TEXT_BYTES];
- +
- + unsigned int key_store[RK_LEN];
- +
- + unsigned int j = 0;
- + unsigned char *p[2];
- +
- + p[0] = sms4Output;
- + p[1] = tmp_data;
- +
- + memcpy(tmp_data, iv, TEXT_BYTES);
- +
- + calculateenkey(key, key_store);
- +
- + for (i = 0; i < length; i++) {
- + if ((i & (TEXT_BYTES - 1)) == 0) {
- + SMS4_Run(key_store, p[1 - j], p[j]);
- +
- + j = 1 - j;
- + }
- +
- + if (i < (length - 16))
- + output[i] = input[i] ^ p[1 - j][i & (TEXT_BYTES - 1)];
- + else
- + output[i] =
- + mic[i - length + 16] ^ p[1 -
- + j][i & (TEXT_BYTES - 1)];
- + }
- +}
- +
- +void WapiCryptoSms4Mic(unsigned char *iv, unsigned char *key,
- + unsigned char *header,
- + unsigned int headerlength, unsigned char *input,
- + unsigned int datalength, unsigned char *mic)
- +{
- + unsigned int i, j = 0, totallength;
- + unsigned char sms4Output[TEXT_BYTES], sms4Input[TEXT_BYTES];
- + unsigned int tmp_headerlength = 0;
- + unsigned int tmp_datalenth = 0;
- +
- + unsigned int header_cnt = 0;
- + unsigned int header0_cnt = 0;
- + unsigned int data_cnt = 0;
- + unsigned int data0_cnt = 0;
- +
- + unsigned int key_store[RK_LEN];
- +
- + memcpy(sms4Input, iv, TEXT_BYTES);
- +
- + totallength = headerlength + datalength;
- + tmp_headerlength =
- + ((headerlength & (TEXT_BYTES - 1)) ==
- + 0) ? 0 : (TEXT_BYTES - (headerlength & (TEXT_BYTES - 1)));
- + tmp_datalenth =
- + ((datalength & (TEXT_BYTES - 1)) ==
- + 0) ? 0 : (TEXT_BYTES - (datalength & (TEXT_BYTES - 1)));
- +
- + totallength += tmp_headerlength;
- + totallength += tmp_datalenth;
- +
- + calculateenkey(key, key_store);
- +
- + for (i = 0; i < totallength; i++) {
- + if ((i & (TEXT_BYTES - 1)) == 0)
- + SMS4_Run(key_store, sms4Input, sms4Output);
- +
- + if ((datalength == 0) && (headerlength == 0)) {
- + sms4Input[i & (TEXT_BYTES - 1)] =
- + 0 ^ sms4Output[i & (TEXT_BYTES - 1)];
- + data0_cnt++;
- + } else if ((headerlength == 0) && (tmp_headerlength == 0)) {
- + sms4Input[i & (TEXT_BYTES - 1)] =
- + input[j] ^ sms4Output[i & (TEXT_BYTES - 1)];
- + j++;
- + datalength--;
- + data_cnt++;
- + } else if (headerlength == 0) {
- + sms4Input[i & (TEXT_BYTES - 1)] =
- + 0 ^ sms4Output[i & (TEXT_BYTES - 1)];
- + tmp_headerlength--;
- + header0_cnt++;
- + } else {
- + sms4Input[i & (TEXT_BYTES - 1)] =
- + header[i] ^ sms4Output[i & (TEXT_BYTES - 1)];
- + headerlength--;
- + header_cnt++;
- + }
- + }
- +
- + SMS4_Run(key_store, sms4Input, mic);
- +}
- +
- +unsigned short wlan_tx_wapi_encryption(wlan_vif_t *vif,
- + unsigned char *data,
- + unsigned short len,
- + unsigned char *ouput_buf)
- +{
- + unsigned short offset = 0;
- + bool qos_in = false;
- + bool valid_addr4 = true;
- +
- + unsigned short eth_type = 0;
- + unsigned char snap_hdr[8] = { 0 };
- + unsigned char *data_pos = data + 14;
- + unsigned short data_len = len;
- + unsigned char snap_backup[8] = { 0 };
- + unsigned char arp_backup[6] = { 0 };
- + unsigned char snap_flag = 0;
- + unsigned char arp_flag = 0;
- +
- + unsigned char ptk_header[36] = { 0 };
- + unsigned short ptk_headr_len = 32;
- + unsigned char *p_ptk_header = ptk_header;
- + unsigned char *p_outputdata = ouput_buf;
- + unsigned char data_mic[16] = { 0 };
- +
- + unsigned char *iv = inc_wapi_pairwise_key_txrsc(vif);
- + unsigned char keyid = vif->cfg80211.key_index[PAIRWISE];
- +
- + int i = 0;
- +
- + /* save frame cntl */
- + *p_ptk_header = 8;
- + *(p_ptk_header + 1) = 65;
- +
- + if (*p_ptk_header & 0x80) {
- + qos_in = true;
- + /* add qos len 2 byte */
- + ptk_headr_len += 2;
- + }
- +
- + /* valid addr4 in case:ToDS==1 && FromDS==1 */
- + if ((*(p_ptk_header + 1) & 0x03) != 0x03)
- + valid_addr4 = false;
- +
- + p_ptk_header += 2;
- + offset += 2;
- +
- + /* jump over duration id */
- + offset += 2;
- + /* save addr1 addr2 */
- + memcpy(p_ptk_header, vif->cfg80211.bssid, 6);
- + memcpy(p_ptk_header + 6, data + 6, 6);
- + p_ptk_header += 12;
- + offset += 12;
- +
- + /* save seq cntl */
- + *p_ptk_header = 0;
- + *(p_ptk_header + 1) = 0;
- + p_ptk_header += 2;
- +
- + /* save addr3 */
- + memcpy(p_ptk_header, data, 6);
- + p_ptk_header += 6;
- + offset += 6;
- +
- + /* save addr4 */
- + memset(p_ptk_header, 0x00, 6);
- + p_ptk_header += 6;
- +
- + /* jump seq cntl */
- + offset += 2;
- +
- + /* save qos */
- + /*if(qos_in)
- + {
- + memcpy(p_ptk_header,&header[offset],2);
- + p_ptk_header += 2;
- + offset += 2;
- + }
- + */
- +
- + /* save keyid */
- + *p_ptk_header = keyid;
- + p_ptk_header++;
- +
- + /* reserved */
- + *p_ptk_header = 0x00;
- + p_ptk_header++;
- +
- + eth_type =
- + ((*(data + ETH_PKT_TYPE_OFFSET) << 8) |
- + *(data + ETH_PKT_TYPE_OFFSET + 1));
- + if ((eth_type == ARP_TYPE) || (eth_type == IP_TYPE) ||
- + (eth_type == ONE_X_TYPE) || (eth_type == VLAN_TYPE) ||
- + (eth_type == WAPI_TYPE) || (eth_type == IPV6_TYPE) ||
- + (eth_type == LLTD_TYPE)) {
- + snap_hdr[0] = 0xAA;
- + snap_hdr[1] = 0xAA;
- + snap_hdr[2] = 0x03;
- + snap_hdr[3] = 0x00;
- + snap_hdr[4] = 0x00;
- + snap_hdr[5] = 0x00;
- + snap_hdr[6] = *(data + 12);
- + snap_hdr[7] = *(data + 13);
- + /* An ARP request/response frame has to be dissected to modify*/
- + /* MAC address, for the host interface. MAC layer acts as an */
- + /* interface to the packets from Etherent and WLAN and takes */
- + /* responsibility of ensuring proper interfacing. */
- + /* The source MAC address is modified only if the packet is an*/
- + /* ARP Request or a Response. The appropriate bytes are checke*/
- + /* Type field (2 bytes): ARP Request (1) or an ARP Response(2)*/
- + if (eth_type == ARP_TYPE) {
- + if ((*(data + 20) == 0x00) &&
- + (*(data + 21) == 0x02 || *(data + 21) == 0x01)) {
- + /* Set Address2 field with source address */
- + memcpy(arp_backup, data + 22, 6);
- + arp_flag = 1;
- + memcpy((data + 22), data + 6, 6);
- + }
- + }
- +
- + /* Set the data length parameter to the MAC data length only */
- + /* not include headers) */
- + data_pos = data + 6;
- + data_len = len + 8;
- + memcpy(snap_backup, data_pos, sizeof(snap_hdr));
- + snap_flag = 1;
- + memcpy(data_pos, snap_hdr, sizeof(snap_hdr));
- + } else {
- + data_len = len;
- + data_pos = data + 14;
- + }
- +
- + /* save data len */
- + *p_ptk_header = (data_len >> 8);
- + *(p_ptk_header + 1) = data_len & 0xFF;
- +
- + /* calc mic */
- + WapiCryptoSms4Mic(iv,
- + mget_wapi_pairwise_mic_key(vif, keyid),
- + ptk_header, ptk_headr_len, data_pos, data_len,
- + data_mic);
- +
- + /* add mic to data */
- + data_len += 16;
- +
- + /* encryption data(inclue mic) & save keyid & iv */
- + WapiCryptoSms4(iv,
- + mget_wapi_pairwise_pkt_key(vif, keyid),
- + data_pos, data_len, data_mic, p_outputdata + 1 + 1 + 16);
- + if (snap_flag)
- + memcpy(data_pos, snap_backup, sizeof(snap_hdr));
- +
- + if (arp_flag)
- + memcpy(data + 22, arp_backup, 6);
- +
- + *p_outputdata = keyid;
- + *(p_outputdata + 1) = 0x00;
- + p_outputdata += 2;
- +
- + for (i = 15; i >= 0; i--) {
- + *p_outputdata = iv[i];
- + p_outputdata++;
- + }
- + return data_len + 1 + 1 + 16;
- +}
- +
- +unsigned short wlan_rx_wapi_decryption(wlan_vif_t *vif,
- + unsigned char *input_ptk,
- + unsigned short header_len,
- + unsigned short data_len,
- + unsigned char *output_buf)
- +{
- + unsigned short offset = 0;
- + bool qos_in = false;
- + bool valid_addr4 = true;
- + bool is_group_ptk = false;
- +
- + unsigned char ptk_header[36] = { 0 };
- + unsigned short ptk_headr_len = 32;
- + unsigned char *p_ptk_header = ptk_header;
- + unsigned char data_mic[16] = { 0 };
- + unsigned char calc_data_mic[16] = { 0 };
- + unsigned char iv[16] = { 0 };
- + unsigned char keyid = { 0 };
- +
- + unsigned short ral_data_len = 0;
- + unsigned short encryp_data_len = 0;
- +
- + int i = 0;
- +
- + /* save calc mic header */
- +
- + /* save frame cntl */
- + *p_ptk_header = input_ptk[offset] & (frame_cntl_mask >> 8);
- + *(p_ptk_header + 1) = input_ptk[offset + 1] & (frame_cntl_mask & 0xFF);
- +
- + if (*p_ptk_header & 0x80) {
- + qos_in = true;
- + /* add qos len 2 byte */
- + ptk_headr_len += 2;
- + }
- +
- + /* valid addr4 in case:ToDS==1 && FromDS==1 */
- + if ((*(p_ptk_header + 1) & 0x03) != 0x03)
- + valid_addr4 = false;
- +
- + p_ptk_header += 2;
- + offset += 2;
- +
- + /* jump over duration id */
- + offset += 2;
- +
- + /* save addr1 addr2 */
- + memcpy(p_ptk_header, &input_ptk[offset], 6);
- + memcpy(p_ptk_header + 6, vif->cfg80211.bssid, 6);
- + is_group_ptk = is_group(p_ptk_header);
- + p_ptk_header += 12;
- + offset += 12;
- +
- + /* save seq cntl */
- + *p_ptk_header = input_ptk[offset + 6] & (seq_cntl_mask >> 8);
- + *(p_ptk_header + 1) =
- + input_ptk[offset + 6 + 1] & (seq_cntl_mask & 0xFF);
- + p_ptk_header += 2;
- +
- + /* save addr3 */
- + memcpy(p_ptk_header, &input_ptk[offset], 6);
- + p_ptk_header += 6;
- + offset += 6;
- +
- + /* save addr4 */
- + if (valid_addr4) {
- + memcpy(p_ptk_header, &input_ptk[offset], 6);
- + p_ptk_header += 6;
- + offset += 6;
- + } else {
- + memset(p_ptk_header, 0x00, 6);
- + p_ptk_header += 6;
- + }
- +
- + /* jump seq cntl */
- + offset += 2;
- +
- + /* save qos */
- + if (qos_in) {
- + memcpy(p_ptk_header, &input_ptk[offset], 2);
- + p_ptk_header += 2;
- + offset += 2;
- +
- + /* mac h/w offset 2 byte to multiple of 4 */
- + offset += 2;
- + }
- +
- + /* save keyid */
- + *p_ptk_header = input_ptk[offset];
- + keyid = input_ptk[offset];
- + p_ptk_header++;
- + offset++;
- +
- + /* reserved */
- + *p_ptk_header = input_ptk[offset];
- + p_ptk_header++;
- + offset++;
- +
- + /* save data len */
- + encryp_data_len = data_len - KEYID_LEN - RESERVD_LEN - PN_LEN;
- + ral_data_len = data_len - KEYID_LEN - RESERVD_LEN - PN_LEN - MIC_LEN;
- + *p_ptk_header = (ral_data_len >> 8);
- + *(p_ptk_header + 1) = ral_data_len & 0xFF;
- +
- + /* save calc mic header over */
- +
- + /* save iv */
- + for (i = 15; i >= 0; i--) {
- + iv[i] = input_ptk[offset];
- + offset++;
- + }
- +
- + /* add adjust here,later... */
- + if (is_group_ptk) {
- + /*if( (iv[15] & 0x01) == 0x00 )
- + {
- + return 0;
- + }
- + */
- + } else {
- + if ((iv[15] & 0x01) != 0x01)
- + return 0;
- + }
- + /* decryption */
- + if (is_group_ptk) {
- + WapiCryptoSms4(iv,
- + mget_wapi_group_pkt_key(vif, keyid),
- + (input_ptk + header_len + KEYID_LEN +
- + RESERVD_LEN + PN_LEN), encryp_data_len,
- + (input_ptk + header_len + KEYID_LEN +
- + RESERVD_LEN + PN_LEN + encryp_data_len - 16),
- + output_buf);
- + } else {
- + WapiCryptoSms4(iv,
- + mget_wapi_pairwise_pkt_key(vif, keyid),
- + (input_ptk + header_len + KEYID_LEN +
- + RESERVD_LEN + PN_LEN), encryp_data_len,
- + (input_ptk + header_len + KEYID_LEN +
- + RESERVD_LEN + PN_LEN + encryp_data_len - 16),
- + output_buf);
- + }
- + memcpy(data_mic, output_buf + ral_data_len, MIC_LEN);
- +
- + /* calc mic */
- + if (is_group_ptk) {
- + WapiCryptoSms4Mic(iv,
- + mget_wapi_group_mic_key(vif, keyid),
- + ptk_header, ptk_headr_len,
- + (output_buf), ral_data_len, calc_data_mic);
- + } else {
- + WapiCryptoSms4Mic(iv,
- + mget_wapi_pairwise_mic_key(vif, keyid),
- + ptk_header, ptk_headr_len,
- + (output_buf), ral_data_len, calc_data_mic);
- + }
- +
- + if (memcmp(calc_data_mic, data_mic, MIC_LEN) != 0)
- + return 0;
- + else
- + return ral_data_len;
- +}
- \ No newline at end of file
- diff --git a/drivers/net/wireless/sprdwl/wlan_wapi.h b/drivers/net/wireless/sprdwl/wlan_wapi.h
- new file mode 100644
- index 0000000..a25d94b
- --- /dev/null
- +++ b/drivers/net/wireless/sprdwl/wlan_wapi.h
- @@ -0,0 +1,158 @@
- +/*
- + * Copyright (C) 2013 Spreadtrum Communications Inc.
- + *
- + * Filename : wapi.h
- + *
- + * Authors :
- + * Wenjie.Zhang <Wenjie.Zhang@spreadtrum.com>
- + *
- + * This software is licensed under the terms of the GNU General Public
- + * License version 2, as published by the Free Software Foundation, and
- + * may be copied, distributed, and modified under those terms.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + */
- +
- +#ifndef __WAPI_H__
- +#define __WAPI_H__
- +
- +#include "wlan_common.h"
- +
- +#ifndef false
- +#define false 0
- +#endif
- +#ifndef true
- +#define true 1
- +#endif
- +#ifndef NULL
- +#define NULL 0
- +#endif
- +
- +/* Bit Values */
- +#define BIT31 ((unsigned int)(1 << 31))
- +#define BIT30 ((unsigned int)(1 << 30))
- +#define BIT29 ((unsigned int)(1 << 29))
- +#define BIT28 ((unsigned int)(1 << 28))
- +#define BIT27 ((unsigned int)(1 << 27))
- +#define BIT26 ((unsigned int)(1 << 26))
- +#define BIT25 ((unsigned int)(1 << 25))
- +#define BIT24 ((unsigned int)(1 << 24))
- +#define BIT23 ((unsigned int)(1 << 23))
- +#define BIT22 ((unsigned int)(1 << 22))
- +#define BIT21 ((unsigned int)(1 << 21))
- +#define BIT20 ((unsigned int)(1 << 20))
- +#define BIT19 ((unsigned int)(1 << 19))
- +#define BIT18 ((unsigned int)(1 << 18))
- +#define BIT17 ((unsigned int)(1 << 17))
- +#define BIT16 ((unsigned int)(1 << 16))
- +#define BIT15 ((unsigned int)(1 << 15))
- +#define BIT14 ((unsigned int)(1 << 14))
- +#define BIT13 ((unsigned int)(1 << 13))
- +#define BIT12 ((unsigned int)(1 << 12))
- +#define BIT11 ((unsigned int)(1 << 11))
- +#define BIT10 ((unsigned int)(1 << 10))
- +#define BIT9 ((unsigned int)(1 << 9))
- +#define BIT8 ((unsigned int)(1 << 8))
- +#define BIT7 ((unsigned int)(1 << 7))
- +#define BIT6 ((unsigned int)(1 << 6))
- +#define BIT5 ((unsigned int)(1 << 5))
- +#define BIT4 ((unsigned int)(1 << 4))
- +#define BIT3 ((unsigned int)(1 << 3))
- +#define BIT2 ((unsigned int)(1 << 2))
- +#define BIT1 ((unsigned int)(1 << 1))
- +#define BIT0 ((unsigned int)(1 << 0))
- +#define ALL 0xFFFF
- +
- +#define ETH_PKT_TYPE_OFFSET 12
- +#define WAPI_TYPE 0x88B4
- +#define IPV6_TYPE 0x86DD
- +#define IP_TYPE 0x0800
- +#define ARP_TYPE 0x0806
- +#define ONE_X_TYPE 0x888E
- +#define VLAN_TYPE 0x8100
- +#define LLTD_TYPE 0x88D9
- +#define UDP_TYPE 0x11
- +#define TCP_TYPE 0x06
- +#define SNAP_HDR_LEN 8
- +#define ETHERNET_HDR_LEN 14
- +#define IP_HDR_OFFSET ETHERNET_HDR_LEN
- +#define IP_HDR_LEN 20
- +#define IP_PROT_OFFSET 23
- +#define UDP_HDR_OFFSET (IP_HDR_LEN + IP_HDR_OFFSET)
- +#define UDP_HDR_LEN 8
- +#define UDP_DATA_OFFSET (UDP_HDR_OFFSET + UDP_HDR_LEN)
- +#define UDP_SRC_PORT_OFFSET UDP_HDR_OFFSET
- +#define UDP_DST_PORT_OFFSET (UDP_HDR_OFFSET + 2)
- +#define VLAN_HDR_LEN 18
- +#define TOS_FIELD_OFFSET 15
- +#define VLAN_TID_FIELD_OFFSET 14
- +#define MAC_UDP_DATA_LEN 1472
- +#define MAX_UDP_IP_PKT_LEN (MAC_UDP_DATA_LEN + UDP_DATA_OFFSET)
- +
- +extern unsigned short wlan_tx_wapi_encryption(wlan_vif_t *vif,
- + unsigned char *data,
- + unsigned short data_len,
- + unsigned char *ouput_buf);
- +
- +extern unsigned short wlan_rx_wapi_decryption(wlan_vif_t *vif,
- + unsigned char *input_ptk,
- + unsigned short header_len,
- + unsigned short data_len,
- + unsigned char *output_buf);
- +
- +/* This function compares the address with the (last bit on air) BIT24 to */
- +/* determine if the address is a group address. */
- +/* Returns true if the input address has the group bit set. */
- +static inline bool is_group(unsigned char *addr)
- +{
- + if ((addr[0] & BIT0) != 0)
- + return true;
- +
- + return false;
- +}
- +
- +static inline unsigned char *inc_wapi_pairwise_key_txrsc(wlan_vif_t *vif)
- +{
- + int i;
- +
- + vif->cfg80211.key_txrsc[1][15] += 2;
- +
- + if (vif->cfg80211.key_txrsc[1][15] == 0x00) {
- + for (i = 14; i >= 0; i--) {
- + vif->cfg80211.key_txrsc[1][i] += 1;
- + if ((vif->cfg80211.key_txrsc[1][i]) != 0x00)
- + break;
- + }
- + }
- +
- + return vif->cfg80211.key_txrsc[1];
- +}
- +
- +static inline unsigned char *mget_wapi_group_pkt_key(wlan_vif_t *vif,
- + int index)
- +{
- + return (index >= 3) ? NULL : vif->cfg80211.key[0][index];
- +}
- +
- +static inline unsigned char *mget_wapi_pairwise_pkt_key(wlan_vif_t
- + *vif, int index)
- +{
- + return (index >= 3) ? NULL : vif->cfg80211.key[1][index];
- +}
- +
- +static inline unsigned char *mget_wapi_group_mic_key(wlan_vif_t *vif,
- + int index)
- +{
- + return (index >= 3) ? NULL : ((u8 *)vif->cfg80211.key[0][index] + 16);
- +}
- +
- +static inline unsigned char *mget_wapi_pairwise_mic_key(wlan_vif_t
- + *vif, int index)
- +{
- + return (index >= 3) ? NULL : ((u8 *)vif->cfg80211.key[1][index] + 16);
- +}
- +
- +#endif /* __WAPI_H__ */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement