bcmdhd: Initial wpa_supplicant_8 library for WEXT and CFG80211
Change-Id: Ib3052c4b7ee41bcc0d90af9e0c49e891498bf8e7
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/bcmdhd/wpa_supplicant_8_lib/Android.mk b/bcmdhd/wpa_supplicant_8_lib/Android.mk
new file mode 100644
index 0000000..a3f72d8
--- /dev/null
+++ b/bcmdhd/wpa_supplicant_8_lib/Android.mk
@@ -0,0 +1,68 @@
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LOCAL_PATH := $(call my-dir)
+
+ifeq ($(WPA_SUPPLICANT_VERSION),VER_0_8_X)
+
+ifneq ($(TARGET_SIMULATOR),true)
+
+ifneq ($(BOARD_WPA_SUPPLICANT_DRIVER),)
+ CONFIG_DRIVER_$(BOARD_WPA_SUPPLICANT_DRIVER) := y
+endif
+
+WPA_SUPPL_DIR = external/wpa_supplicant_8
+WPA_SRC_FILE :=
+
+include $(WPA_SUPPL_DIR)/wpa_supplicant/.config
+
+WPA_SUPPL_DIR_INCLUDE = $(WPA_SUPPL_DIR)/src \
+ $(WPA_SUPPL_DIR)/src/common \
+ $(WPA_SUPPL_DIR)/src/drivers \
+ $(WPA_SUPPL_DIR)/src/l2_packet \
+ $(WPA_SUPPL_DIR)/src/utils \
+ $(WPA_SUPPL_DIR)/src/wps \
+ $(WPA_SUPPL_DIR)/wpa_supplicant
+
+ifdef CONFIG_DRIVER_NL80211
+WPA_SUPPL_DIR_INCLUDE += external/libnl_2/include
+WPA_SRC_FILE += driver_cmd_nl80211.c
+endif
+
+ifdef CONFIG_DRIVER_WEXT
+WPA_SRC_FILE += driver_cmd_wext.c
+endif
+
+# To force sizeof(enum) = 4
+L_CFLAGS += -mabi=aapcs-linux
+
+ifdef CONFIG_ANDROID_LOG
+L_CFLAGS += -DCONFIG_ANDROID_LOG
+endif
+
+########################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := lib_driver_cmd_bcmdhd
+LOCAL_SHARED_LIBRARIES := libc libcutils
+LOCAL_CFLAGS := $(L_CFLAGS)
+LOCAL_SRC_FILES := $(WPA_SRC_FILE)
+LOCAL_C_INCLUDES := $(WPA_SUPPL_DIR_INCLUDE)
+include $(BUILD_STATIC_LIBRARY)
+
+########################
+
+endif
+endif
diff --git a/bcmdhd/wpa_supplicant_8_lib/driver_cmd_nl80211.c b/bcmdhd/wpa_supplicant_8_lib/driver_cmd_nl80211.c
new file mode 100644
index 0000000..481e8df
--- /dev/null
+++ b/bcmdhd/wpa_supplicant_8_lib/driver_cmd_nl80211.c
@@ -0,0 +1,166 @@
+/*
+ * Driver interaction with extended Linux CFG8021
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ */
+
+#include "driver_nl80211.h"
+
+#define WPA_EVENT_DRIVER_STATE "CTRL-EVENT-DRIVER-STATE "
+
+#define WPA_PS_ENABLED 0
+#define WPA_PS_DISABLED 1
+
+int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv, struct nl_msg *msg,
+ int (*valid_handler)(struct nl_msg *, void *),
+ void *valid_data);
+
+static int wpa_driver_set_btcoex_state(char state)
+{
+ int ret;
+ int fd;
+
+ fd = open("/sys/devices/platform/bcmdhd/bt_coex_state", O_RDWR, 0);
+ if (fd == -1)
+ return -1;
+
+ ret = write(fd, &state, sizeof(state));
+ close(fd);
+
+ wpa_printf(MSG_DEBUG, "%s: set btcoex state to '%c' result = %d",
+ __func__, state, ret);
+ return (ret > 0) ? 0 : -1;
+}
+
+static int wpa_driver_set_power_save(void *priv, int state)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ int ret = -1;
+ enum nl80211_ps_state ps_state;
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -1;
+
+ genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
+ NL80211_CMD_SET_POWER_SAVE, 0);
+
+ if (state == WPA_PS_ENABLED)
+ ps_state = NL80211_PS_ENABLED;
+ else
+ ps_state = NL80211_PS_DISABLED;
+
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+ NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE, ps_state);
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ msg = NULL;
+ if (ret < 0)
+ wpa_printf(MSG_ERROR, "nl80211: Set power mode fail: %d", ret);
+nla_put_failure:
+ nlmsg_free(msg);
+ return ret;
+}
+
+static int get_power_mode_handler(struct nl_msg *msg, void *arg)
+{
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ int *state = (int *)arg;
+
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+
+ if (!tb[NL80211_ATTR_PS_STATE])
+ return NL_SKIP;
+
+ if (state) {
+ *state = (int)nla_get_u32(tb[NL80211_ATTR_PS_STATE]);
+ wpa_printf(MSG_DEBUG, "nl80211: Get power mode = %d", *state);
+ *state = (*state == NL80211_PS_ENABLED) ?
+ WPA_PS_ENABLED : WPA_PS_DISABLED;
+ }
+
+ return NL_SKIP;
+}
+
+static int wpa_driver_get_power_save(void *priv, int *state)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ int ret = -1;
+ enum nl80211_ps_state ps_state;
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -1;
+
+ genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
+ NL80211_CMD_GET_POWER_SAVE, 0);
+
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+
+ ret = send_and_recv_msgs(drv, msg, get_power_mode_handler, state);
+ msg = NULL;
+ if (ret < 0)
+ wpa_printf(MSG_ERROR, "nl80211: Get power mode fail: %d", ret);
+nla_put_failure:
+ nlmsg_free(msg);
+ return ret;
+}
+
+int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf,
+ size_t buf_len )
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ int ret = 0;
+
+ wpa_msg(drv->ctx, MSG_INFO, "%s: %s", __func__, cmd);
+
+ if (os_strcasecmp(cmd, "STOP") == 0) {
+ linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0);
+ wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED");
+ } else if (os_strcasecmp(cmd, "START") == 0) {
+ linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1);
+ wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED");
+ } else if (os_strcasecmp(cmd, "MACADDR") == 0) {
+ u8 macaddr[ETH_ALEN] = {};
+
+ ret = linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, macaddr);
+ if (!ret)
+ ret = os_snprintf(buf, buf_len,
+ "Macaddr = " MACSTR "\n", MAC2STR(macaddr));
+ } else if (os_strcasecmp(cmd, "RELOAD") == 0) {
+ wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
+ } else if (os_strncasecmp(cmd, "POWERMODE ", 10) == 0) {
+ int state;
+
+ state = atoi(cmd + 10);
+ ret = wpa_driver_set_power_save(priv, state);
+ } else if (os_strncasecmp(cmd, "GETPOWER", 8) == 0) {
+ int state = -1;
+
+ ret = wpa_driver_get_power_save(priv, &state);
+ if (!ret && (state != -1))
+ ret = os_snprintf(buf, buf_len, "POWERMODE = %d\n", state);
+ } else if (os_strncasecmp(cmd, "BTCOEXMODE ", 11) == 0) {
+ char state = cmd[11];
+
+ ret = wpa_driver_set_btcoex_state(state);
+ } else {
+ wpa_printf(MSG_ERROR, "Unsupported command: %s", cmd);
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/bcmdhd/wpa_supplicant_8_lib/driver_cmd_wext.c b/bcmdhd/wpa_supplicant_8_lib/driver_cmd_wext.c
new file mode 100644
index 0000000..188f63a
--- /dev/null
+++ b/bcmdhd/wpa_supplicant_8_lib/driver_cmd_wext.c
@@ -0,0 +1,361 @@
+/*
+ * Driver interaction with extended Linux Wireless Extensions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ */
+
+#include "includes.h"
+#include <sys/ioctl.h>
+#include <net/if_arp.h>
+#include <net/if.h>
+
+#include "wireless_copy.h"
+#include "common.h"
+#include "driver.h"
+#include "eloop.h"
+#include "priv_netlink.h"
+#include "driver_wext.h"
+#include "ieee802_11_defs.h"
+#include "wpa_common.h"
+#include "wpa_ctrl.h"
+#include "wpa_supplicant_i.h"
+#include "config.h"
+#include "linux_ioctl.h"
+#include "scan.h"
+
+#include "driver_cmd_wext.h"
+
+/**
+ * wpa_driver_wext_set_scan_timeout - Set scan timeout to report scan completion
+ * @priv: Pointer to private wext data from wpa_driver_wext_init()
+ *
+ * This function can be used to set registered timeout when starting a scan to
+ * generate a scan completed event if the driver does not report this.
+ */
+static void wpa_driver_wext_set_scan_timeout(void *priv)
+{
+ struct wpa_driver_wext_data *drv = priv;
+ int timeout = 10; /* In case scan A and B bands it can be long */
+
+ /* Not all drivers generate "scan completed" wireless event, so try to
+ * read results after a timeout. */
+ if (drv->scan_complete_events) {
+ /*
+ * The driver seems to deliver SIOCGIWSCAN events to notify
+ * when scan is complete, so use longer timeout to avoid race
+ * conditions with scanning and following association request.
+ */
+ timeout = 30;
+ }
+ wpa_printf(MSG_DEBUG, "Scan requested - scan timeout %d seconds",
+ timeout);
+ eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);
+ eloop_register_timeout(timeout, 0, wpa_driver_wext_scan_timeout, drv,
+ drv->ctx);
+}
+
+/**
+ * wpa_driver_wext_combo_scan - Request the driver to initiate combo scan
+ * @priv: Pointer to private wext data from wpa_driver_wext_init()
+ * @params: Scan parameters
+ * Returns: 0 on success, -1 on failure
+ */
+int wpa_driver_wext_combo_scan(void *priv, struct wpa_driver_scan_params *params)
+{
+ char buf[WEXT_CSCAN_BUF_LEN];
+ struct wpa_driver_wext_data *drv = priv;
+ struct iwreq iwr;
+ int ret, bp;
+ unsigned i;
+ struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx);
+
+ if (!drv->driver_is_started) {
+ wpa_printf(MSG_DEBUG, "%s: Driver stopped", __func__);
+ return 0;
+ }
+
+ wpa_printf(MSG_DEBUG, "%s: Start", __func__);
+
+ /* Set list of SSIDs */
+ bp = WEXT_CSCAN_HEADER_SIZE;
+ os_memcpy(buf, WEXT_CSCAN_HEADER, bp);
+ for(i=0; i < params->num_ssids; i++) {
+ if ((bp + IW_ESSID_MAX_SIZE + 10) >= (int)sizeof(buf))
+ break;
+ wpa_printf(MSG_DEBUG, "For Scan: %s", params->ssids[i].ssid);
+ buf[bp++] = WEXT_CSCAN_SSID_SECTION;
+ buf[bp++] = params->ssids[i].ssid_len;
+ os_memcpy(&buf[bp], params->ssids[i].ssid, params->ssids[i].ssid_len);
+ bp += params->ssids[i].ssid_len;
+ }
+
+ /* Set list of channels */
+ buf[bp++] = WEXT_CSCAN_CHANNEL_SECTION;
+ buf[bp++] = 0;
+
+ /* Set passive dwell time (default is 250) */
+ buf[bp++] = WEXT_CSCAN_PASV_DWELL_SECTION;
+ buf[bp++] = (u8)WEXT_CSCAN_PASV_DWELL_TIME;
+ buf[bp++] = (u8)(WEXT_CSCAN_PASV_DWELL_TIME >> 8);
+
+ /* Set home dwell time (default is 40) */
+ buf[bp++] = WEXT_CSCAN_HOME_DWELL_SECTION;
+ buf[bp++] = (u8)WEXT_CSCAN_HOME_DWELL_TIME;
+ buf[bp++] = (u8)(WEXT_CSCAN_HOME_DWELL_TIME >> 8);
+
+ os_memset(&iwr, 0, sizeof(iwr));
+ os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+ iwr.u.data.pointer = buf;
+ iwr.u.data.length = bp;
+
+ if ((ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr)) < 0) {
+ wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (cscan): %d", ret);
+ }
+ return ret;
+}
+
+static int wpa_driver_wext_set_cscan_params(char *buf, size_t buf_len, char *cmd)
+{
+ char *pasv_ptr;
+ int bp, i;
+ u16 pasv_dwell = WEXT_CSCAN_PASV_DWELL_TIME_DEF;
+ u8 channel;
+
+ wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
+
+ /* Get command parameters */
+ pasv_ptr = os_strstr(cmd, ",TIME=");
+ if (pasv_ptr) {
+ *pasv_ptr = '\0';
+ pasv_ptr += 6;
+ pasv_dwell = (u16)atoi(pasv_ptr);
+ if (pasv_dwell == 0)
+ pasv_dwell = WEXT_CSCAN_PASV_DWELL_TIME_DEF;
+ }
+ channel = (u8)atoi(cmd + 5);
+
+ bp = WEXT_CSCAN_HEADER_SIZE;
+ os_memcpy(buf, WEXT_CSCAN_HEADER, bp);
+
+ /* Set list of channels */
+ buf[bp++] = WEXT_CSCAN_CHANNEL_SECTION;
+ buf[bp++] = channel;
+ if (channel != 0) {
+ i = (pasv_dwell - 1) / WEXT_CSCAN_PASV_DWELL_TIME_DEF;
+ for (; i > 0; i--) {
+ if ((size_t)(bp + 12) >= buf_len)
+ break;
+ buf[bp++] = WEXT_CSCAN_CHANNEL_SECTION;
+ buf[bp++] = channel;
+ }
+ } else {
+ if (pasv_dwell > WEXT_CSCAN_PASV_DWELL_TIME_MAX)
+ pasv_dwell = WEXT_CSCAN_PASV_DWELL_TIME_MAX;
+ }
+
+ /* Set passive dwell time (default is 250) */
+ buf[bp++] = WEXT_CSCAN_PASV_DWELL_SECTION;
+ if (channel != 0) {
+ buf[bp++] = (u8)WEXT_CSCAN_PASV_DWELL_TIME_DEF;
+ buf[bp++] = (u8)(WEXT_CSCAN_PASV_DWELL_TIME_DEF >> 8);
+ } else {
+ buf[bp++] = (u8)pasv_dwell;
+ buf[bp++] = (u8)(pasv_dwell >> 8);
+ }
+
+ /* Set home dwell time (default is 40) */
+ buf[bp++] = WEXT_CSCAN_HOME_DWELL_SECTION;
+ buf[bp++] = (u8)WEXT_CSCAN_HOME_DWELL_TIME;
+ buf[bp++] = (u8)(WEXT_CSCAN_HOME_DWELL_TIME >> 8);
+
+ /* Set cscan type */
+ buf[bp++] = WEXT_CSCAN_TYPE_SECTION;
+ buf[bp++] = WEXT_CSCAN_TYPE_PASSIVE;
+ return bp;
+}
+
+static char *wpa_driver_get_country_code(int channels)
+{
+ char *country = "US"; /* WEXT_NUMBER_SCAN_CHANNELS_FCC */
+
+ if (channels == WEXT_NUMBER_SCAN_CHANNELS_ETSI)
+ country = "EU";
+ else if( channels == WEXT_NUMBER_SCAN_CHANNELS_MKK1)
+ country = "JP";
+ return country;
+}
+
+static int wpa_driver_set_backgroundscan_params(void *priv)
+{
+ struct wpa_driver_wext_data *drv = priv;
+ struct wpa_supplicant *wpa_s;
+ struct iwreq iwr;
+ int ret = 0, i = 0, bp;
+ char buf[WEXT_PNO_MAX_COMMAND_SIZE];
+ struct wpa_ssid *ssid_conf;
+
+ if (drv == NULL) {
+ wpa_printf(MSG_ERROR, "%s: drv is NULL. Exiting", __func__);
+ return -1;
+ }
+ if (drv->ctx == NULL) {
+ wpa_printf(MSG_ERROR, "%s: drv->ctx is NULL. Exiting", __func__);
+ return -1;
+ }
+ wpa_s = (struct wpa_supplicant *)(drv->ctx);
+ if (wpa_s->conf == NULL) {
+ wpa_printf(MSG_ERROR, "%s: wpa_s->conf is NULL. Exiting", __func__);
+ return -1;
+ }
+ ssid_conf = wpa_s->conf->ssid;
+
+ bp = WEXT_PNOSETUP_HEADER_SIZE;
+ os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp);
+ buf[bp++] = 'S';
+ buf[bp++] = WEXT_PNO_TLV_VERSION;
+ buf[bp++] = WEXT_PNO_TLV_SUBVERSION;
+ buf[bp++] = WEXT_PNO_TLV_RESERVED;
+
+ while ((i < WEXT_PNO_AMOUNT) && (ssid_conf != NULL)) {
+ /* Check that there is enough space needed for 1 more SSID, the other sections and null termination */
+ if ((bp + WEXT_PNO_SSID_HEADER_SIZE + IW_ESSID_MAX_SIZE + WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int)sizeof(buf))
+ break;
+ if ((!ssid_conf->disabled) && (ssid_conf->ssid_len <= IW_ESSID_MAX_SIZE)){
+ wpa_printf(MSG_DEBUG, "For PNO Scan: %s", ssid_conf->ssid);
+ buf[bp++] = WEXT_PNO_SSID_SECTION;
+ buf[bp++] = ssid_conf->ssid_len;
+ os_memcpy(&buf[bp], ssid_conf->ssid, ssid_conf->ssid_len);
+ bp += ssid_conf->ssid_len;
+ i++;
+ }
+ ssid_conf = ssid_conf->next;
+ }
+
+ buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION;
+ os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x", WEXT_PNO_SCAN_INTERVAL);
+ bp += WEXT_PNO_SCAN_INTERVAL_LENGTH;
+
+ buf[bp++] = WEXT_PNO_REPEAT_SECTION;
+ os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x", WEXT_PNO_REPEAT);
+ bp += WEXT_PNO_REPEAT_LENGTH;
+
+ buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION;
+ os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x", WEXT_PNO_MAX_REPEAT);
+ bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1;
+
+ os_memset(&iwr, 0, sizeof(iwr));
+ os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+ iwr.u.data.pointer = buf;
+ iwr.u.data.length = bp;
+
+ ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr);
+
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d", ret);
+ drv->errors++;
+ if (drv->errors > WEXT_NUMBER_SEQUENTIAL_ERRORS) {
+ drv->errors = 0;
+ wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
+ }
+ } else {
+ drv->errors = 0;
+ }
+ return ret;
+
+}
+
+int wpa_driver_wext_driver_cmd( void *priv, char *cmd, char *buf, size_t buf_len )
+{
+ struct wpa_driver_wext_data *drv = priv;
+ struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx);
+ struct iwreq iwr;
+ int ret = 0, flags;
+
+ wpa_printf(MSG_DEBUG, "%s %s len = %d", __func__, cmd, buf_len);
+
+ if (!drv->driver_is_started && (os_strcasecmp(cmd, "START") != 0)) {
+ wpa_printf(MSG_ERROR,"WEXT: Driver not initialized yet");
+ return -1;
+ }
+
+ if (os_strcasecmp(cmd, "RSSI-APPROX") == 0) {
+ os_strncpy(cmd, "RSSI", MAX_DRV_CMD_SIZE);
+ } else if( os_strncasecmp(cmd, "SCAN-CHANNELS", 13) == 0 ) {
+ int no_of_chan;
+
+ no_of_chan = atoi(cmd + 13);
+ os_snprintf(cmd, MAX_DRV_CMD_SIZE, "COUNTRY %s",
+ wpa_driver_get_country_code(no_of_chan));
+ } else if (os_strcasecmp(cmd, "STOP") == 0) {
+ (void)linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0);
+ } else if( os_strcasecmp(cmd, "RELOAD") == 0 ) {
+ wpa_printf(MSG_DEBUG,"Reload command");
+ wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
+ return ret;
+ } else if( os_strcasecmp(cmd, "BGSCAN-START") == 0 ) {
+ ret = wpa_driver_set_backgroundscan_params(priv);
+ if (ret < 0) {
+ return ret;
+ }
+ os_strncpy(cmd, "PNOFORCE 1", MAX_DRV_CMD_SIZE);
+ drv->bgscan_enabled = 1;
+ } else if( os_strcasecmp(cmd, "BGSCAN-STOP") == 0 ) {
+ os_strncpy(cmd, "PNOFORCE 0", MAX_DRV_CMD_SIZE);
+ drv->bgscan_enabled = 0;
+ }
+
+ os_memset(&iwr, 0, sizeof(iwr));
+ os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+ os_memcpy(buf, cmd, strlen(cmd) + 1);
+ iwr.u.data.pointer = buf;
+ iwr.u.data.length = buf_len;
+
+ if( os_strncasecmp(cmd, "CSCAN", 5) == 0 ) {
+ if (!wpa_s->scanning && ((wpa_s->wpa_state <= WPA_SCANNING) ||
+ (wpa_s->wpa_state >= WPA_COMPLETED))) {
+ iwr.u.data.length = wpa_driver_wext_set_cscan_params(buf, buf_len, cmd);
+ } else {
+ wpa_printf(MSG_ERROR, "Ongoing Scan action...");
+ return ret;
+ }
+ }
+
+ ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr);
+
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR, "%s failed (%d): %s", __func__, ret, cmd);
+ drv->errors++;
+ if (drv->errors > WEXT_NUMBER_SEQUENTIAL_ERRORS) {
+ drv->errors = 0;
+ wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
+ }
+ } else {
+ drv->errors = 0;
+ ret = 0;
+ if ((os_strcasecmp(cmd, "RSSI") == 0) ||
+ (os_strcasecmp(cmd, "LINKSPEED") == 0) ||
+ (os_strcasecmp(cmd, "MACADDR") == 0) ||
+ (os_strcasecmp(cmd, "GETPOWER") == 0) ||
+ (os_strcasecmp(cmd, "GETBAND") == 0)) {
+ ret = strlen(buf);
+ } else if (os_strcasecmp(cmd, "START") == 0) {
+ drv->driver_is_started = TRUE;
+ /* os_sleep(0, WPA_DRIVER_WEXT_WAIT_US);
+ wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED"); */
+ } else if (os_strcasecmp(cmd, "STOP") == 0) {
+ drv->driver_is_started = FALSE;
+ /* wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED"); */
+ } else if (os_strncasecmp(cmd, "CSCAN", 5) == 0) {
+ wpa_driver_wext_set_scan_timeout(priv);
+ wpa_supplicant_notify_scanning(wpa_s, 1);
+ }
+ wpa_printf(MSG_DEBUG, "%s %s len = %d, %d", __func__, buf, ret, strlen(buf));
+ }
+ return ret;
+}
diff --git a/bcmdhd/wpa_supplicant_8_lib/driver_cmd_wext.h b/bcmdhd/wpa_supplicant_8_lib/driver_cmd_wext.h
new file mode 100644
index 0000000..a952d7e
--- /dev/null
+++ b/bcmdhd/wpa_supplicant_8_lib/driver_cmd_wext.h
@@ -0,0 +1,72 @@
+/*
+ * Driver interaction with extended Linux Wireless Extensions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ */
+#ifndef DRIVER_CMD_WEXT_H
+#define DRIVER_CMD_WEXT_H
+
+#define WEXT_NUMBER_SCAN_CHANNELS_FCC 11
+#define WEXT_NUMBER_SCAN_CHANNELS_ETSI 13
+#define WEXT_NUMBER_SCAN_CHANNELS_MKK1 14
+
+#define WPA_DRIVER_WEXT_WAIT_US 400000
+#define MAX_DRV_CMD_SIZE 248
+#define WEXT_NUMBER_SEQUENTIAL_ERRORS 4
+#define WEXT_CSCAN_AMOUNT 9
+#define WEXT_CSCAN_BUF_LEN 360
+#define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00"
+#define WEXT_CSCAN_HEADER_SIZE 12
+#define WEXT_CSCAN_SSID_SECTION 'S'
+#define WEXT_CSCAN_CHANNEL_SECTION 'C'
+#define WEXT_CSCAN_NPROBE_SECTION 'N'
+#define WEXT_CSCAN_ACTV_DWELL_SECTION 'A'
+#define WEXT_CSCAN_PASV_DWELL_SECTION 'P'
+#define WEXT_CSCAN_HOME_DWELL_SECTION 'H'
+#define WEXT_CSCAN_TYPE_SECTION 'T'
+#define WEXT_CSCAN_TYPE_DEFAULT 0
+#define WEXT_CSCAN_TYPE_PASSIVE 1
+#define WEXT_CSCAN_PASV_DWELL_TIME 130
+#define WEXT_CSCAN_PASV_DWELL_TIME_DEF 250
+#define WEXT_CSCAN_PASV_DWELL_TIME_MAX 3000
+#define WEXT_CSCAN_HOME_DWELL_TIME 130
+
+#define WEXT_PNOSETUP_HEADER "PNOSETUP "
+#define WEXT_PNOSETUP_HEADER_SIZE 9
+#define WEXT_PNO_TLV_VERSION '1'
+#define WEXT_PNO_TLV_SUBVERSION '2'
+#define WEXT_PNO_TLV_RESERVED '0'
+#define WEXT_PNO_VERSION_SIZE 4
+#define WEXT_PNO_AMOUNT 16
+#define WEXT_PNO_SSID_SECTION 'S'
+/* SSID header size is SSID section type above + SSID length */
+#define WEXT_PNO_SSID_HEADER_SIZE 2
+#define WEXT_PNO_SCAN_INTERVAL_SECTION 'T'
+#define WEXT_PNO_SCAN_INTERVAL_LENGTH 2
+#define WEXT_PNO_SCAN_INTERVAL 30
+/* Scan interval size is scan interval section type + scan interval length above*/
+#define WEXT_PNO_SCAN_INTERVAL_SIZE (1 + WEXT_PNO_SCAN_INTERVAL_LENGTH)
+#define WEXT_PNO_REPEAT_SECTION 'R'
+#define WEXT_PNO_REPEAT_LENGTH 1
+#define WEXT_PNO_REPEAT 4
+/* Repeat section size is Repeat section type + Repeat value length above*/
+#define WEXT_PNO_REPEAT_SIZE (1 + WEXT_PNO_REPEAT_LENGTH)
+#define WEXT_PNO_MAX_REPEAT_SECTION 'M'
+#define WEXT_PNO_MAX_REPEAT_LENGTH 1
+#define WEXT_PNO_MAX_REPEAT 3
+/* Max Repeat section size is Max Repeat section type + Max Repeat value length above*/
+#define WEXT_PNO_MAX_REPEAT_SIZE (1 + WEXT_PNO_MAX_REPEAT_LENGTH)
+/* This corresponds to the size of all sections expect SSIDs */
+#define WEXT_PNO_NONSSID_SECTIONS_SIZE (WEXT_PNO_SCAN_INTERVAL_SIZE + WEXT_PNO_REPEAT_SIZE + WEXT_PNO_MAX_REPEAT_SIZE)
+/* PNO Max command size is total of header, version, ssid and other sections + Null termination */
+#define WEXT_PNO_MAX_COMMAND_SIZE (WEXT_PNOSETUP_HEADER_SIZE + WEXT_PNO_VERSION_SIZE \
+ + WEXT_PNO_AMOUNT * (WEXT_PNO_SSID_HEADER_SIZE + IW_ESSID_MAX_SIZE) \
+ + WEXT_PNO_NONSSID_SECTIONS_SIZE + 1)
+
+#endif /* DRIVER_CMD_WEXT_H */
diff --git a/bcmdhd/wpa_supplicant_8_lib/driver_nl80211.h b/bcmdhd/wpa_supplicant_8_lib/driver_nl80211.h
new file mode 100644
index 0000000..4a19757
--- /dev/null
+++ b/bcmdhd/wpa_supplicant_8_lib/driver_nl80211.h
@@ -0,0 +1,148 @@
+/*
+ * Driver interaction with Linux nl80211/cfg80211
+ * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2004, Instant802 Networks, Inc.
+ * Copyright (c) 2005-2006, Devicescape Software, Inc.
+ * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright (c) 2009-2010, Atheros Communications
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef _DRIVER_NL80211_H_
+#define _DRIVER_NL80211_H_
+
+#include "includes.h"
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <linux/rtnetlink.h>
+#include <netpacket/packet.h>
+#include <linux/filter.h>
+#include "nl80211_copy.h"
+
+#include "common.h"
+#include "eloop.h"
+#include "utils/list.h"
+#include "common/ieee802_11_defs.h"
+#include "netlink.h"
+#include "linux_ioctl.h"
+#include "radiotap.h"
+#include "radiotap_iter.h"
+#include "rfkill.h"
+#include "driver.h"
+
+#ifdef CONFIG_LIBNL20
+/* libnl 2.0 compatibility code */
+#define nl_handle nl_sock
+#define nl80211_handle_alloc nl_socket_alloc_cb
+#define nl80211_handle_destroy nl_socket_free
+#endif /* CONFIG_LIBNL20 */
+
+#ifndef IFF_LOWER_UP
+#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */
+#endif
+#ifndef IFF_DORMANT
+#define IFF_DORMANT 0x20000 /* driver signals dormant */
+#endif
+
+#ifndef IF_OPER_DORMANT
+#define IF_OPER_DORMANT 5
+#endif
+#ifndef IF_OPER_UP
+#define IF_OPER_UP 6
+#endif
+
+struct nl80211_global {
+ struct dl_list interfaces;
+};
+
+struct i802_bss {
+ struct wpa_driver_nl80211_data *drv;
+ struct i802_bss *next;
+ int ifindex;
+ char ifname[IFNAMSIZ + 1];
+ char brname[IFNAMSIZ];
+ unsigned int beacon_set:1;
+ unsigned int added_if_into_bridge:1;
+ unsigned int added_bridge:1;
+};
+
+struct wpa_driver_nl80211_data {
+ struct nl80211_global *global;
+ struct dl_list list;
+ u8 addr[ETH_ALEN];
+ char phyname[32];
+ void *ctx;
+ struct netlink_data *netlink;
+ int ioctl_sock; /* socket for ioctl() use */
+ int ifindex;
+ int if_removed;
+ int if_disabled;
+ struct rfkill_data *rfkill;
+ struct wpa_driver_capa capa;
+ int has_capability;
+
+ int operstate;
+
+ int scan_complete_events;
+
+ struct nl_handle *nl_handle;
+ struct nl_handle *nl_handle_event;
+ struct nl_handle *nl_handle_preq;
+ struct nl_cache *nl_cache;
+ struct nl_cache *nl_cache_event;
+ struct nl_cache *nl_cache_preq;
+ struct nl_cb *nl_cb;
+ struct genl_family *nl80211;
+
+ u8 auth_bssid[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
+ int associated;
+ u8 ssid[32];
+ size_t ssid_len;
+ int nlmode;
+ int ap_scan_as_station;
+ unsigned int assoc_freq;
+
+ int monitor_sock;
+ int monitor_ifidx;
+ int disable_11b_rates;
+
+ unsigned int pending_remain_on_chan:1;
+
+ u64 remain_on_chan_cookie;
+ u64 send_action_cookie;
+
+ unsigned int last_mgmt_freq;
+
+ struct wpa_driver_scan_filter *filter_ssids;
+ size_t num_filter_ssids;
+
+ struct i802_bss first_bss;
+
+#ifdef HOSTAPD
+ int eapol_sock; /* socket for EAPOL frames */
+
+ int default_if_indices[16];
+ int *if_indices;
+ int num_if_indices;
+
+ int last_freq;
+ int last_freq_ht;
+#endif /* HOSTAPD */
+};
+
+#endif