/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/kthread.h>
#include <linux/semaphore.h>
#include <bcmdefs.h>
#include <linux/netdevice.h>
#include <wlioctl.h>
#include <bcmutils.h>
#include <linux/if_arp.h>
#include <asm/uaccess.h>
#include <dngl_stats.h>
#include <dhd.h>
#include <dhdioctl.h>
#include <linux/ieee80211.h>
typedef const struct si_pub si_t;
#include <wlioctl.h>
#include <dngl_stats.h>
#include <dhd.h>
#define WL_ERROR(fmt, args...) printk(fmt, ##args)
#define WL_TRACE(fmt, args...) no_printk(fmt, ##args)
#define WL_INFORM(fmt, args...) no_printk(fmt, ##args)
#define WL_WSEC(fmt, args...) no_printk(fmt, ##args)
#define WL_SCAN(fmt, args...) no_printk(fmt, ##args)
#include <wl_iw.h>
#define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | \
TKIP_ENABLED | AES_ENABLED))
#include <linux/rtnetlink.h>
#define WL_IW_USE_ISCAN 1
#define ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS 1
bool g_set_essid_before_scan = true;
#define WL_IW_IOCTL_CALL(func_call) \
do { \
func_call; \
} while (0)
static int g_onoff = G_WLAN_SET_ON;
wl_iw_extra_params_t g_wl_iw_params;
extern bool wl_iw_conn_status_str(u32 event_type, u32 status,
u32 reason, char *stringBuf, uint buflen);
#define MAX_WLIW_IOCTL_LEN 1024
#ifdef CONFIG_WIRELESS_EXT
extern int dhd_wait_pend8021x(struct net_device *dev);
#endif
#if WIRELESS_EXT < 19
#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST)
#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST)
#endif
static void *g_scan;
static volatile uint g_scan_specified_ssid;
static wlc_ssid_t g_specific_ssid;
static wlc_ssid_t g_ssid;
#if defined(WL_IW_USE_ISCAN)
#define ISCAN_STATE_IDLE 0
#define ISCAN_STATE_SCANING 1
#define WLC_IW_ISCAN_MAXLEN 2048
typedef struct iscan_buf {
struct iscan_buf *next;
char iscan_buf[WLC_IW_ISCAN_MAXLEN];
} iscan_buf_t;
typedef struct iscan_info {
struct net_device *dev;
struct timer_list timer;
u32 timer_ms;
u32 timer_on;
int iscan_state;
iscan_buf_t *list_hdr;
iscan_buf_t *list_cur;
struct task_struct *sysioc_tsk;
struct semaphore sysioc_sem;
#if defined CSCAN
char ioctlbuf[WLC_IOCTL_MEDLEN];
#else
char ioctlbuf[WLC_IOCTL_SMLEN];
#endif
wl_iscan_params_t *iscan_ex_params_p;
int iscan_ex_param_size;
} iscan_info_t;
iscan_info_t *g_iscan;
static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
/* Global ASSERT type flag */
u32 g_assert_type;
static void wl_iw_timerfunc(unsigned long data);
static void wl_iw_set_event_mask(struct net_device *dev);
static int wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, u16 action);
#endif /* defined(WL_IW_USE_ISCAN) */
static int
wl_iw_set_scan(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra);
static int
wl_iw_get_scan(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *dwrq, char *extra);
static uint
wl_iw_get_scan_prep(wl_scan_results_t *list,
struct iw_request_info *info, char *extra, short max_size);
static void swap_key_from_BE(wl_wsec_key_t *key)
{
key->index = cpu_to_le32(key->index);
key->len = cpu_to_le32(key->len);
key->algo = cpu_to_le32(key->algo);
key->flags = cpu_to_le32(key->flags);
key->rxiv.hi = cpu_to_le32(key->rxiv.hi);
key->rxiv.lo = cpu_to_le16(key->rxiv.lo);
key->iv_initialized = cpu_to_le32(key->iv_initialized);
}
static void swap_key_to_BE(wl_wsec_key_t *key)
{
key->index = le32_to_cpu(key->index);
key->len = le32_to_cpu(key->len);
key->algo = le32_to_cpu(key->algo);
key->flags = le32_to_cpu(key->flags);
key->rxiv.hi = le32_to_cpu(key->rxiv.hi);
key->rxiv.lo = le16_to_cpu(key->rxiv.lo);
key->iv_initialized = le32_to_cpu(key->iv_initialized);
}
static int dev_wlc_ioctl(struct net_device *dev, int cmd, void *arg, int len)
{
struct ifreq ifr;
wl_ioctl_t ioc;
mm_segment_t fs;
int ret = -EINVAL;
if (!dev) {
WL_ERROR("%s: dev is null\n", __func__);
return ret;
}
WL_INFORM("\n%s, PID:%x: send Local IOCTL -> dhd: cmd:0x%x, buf:%p, len:%d\n",
__func__, current->pid, cmd, arg, len);
if (g_onoff == G_WLAN_SET_ON) {