add private_lib for NL80211 and wext driver.

Copied from hardware/broadcom/wlan/bcmdhd/wpa_supplicant_8_lib and modified
to work with generic wext driver.

Change-Id: Id33647ac6c8ae7faa9ed0b7cd24c59e0c76fdd85
Signed-off-by: Vishal Bhoj <vishal.bhoj@linaro.org>
diff --git a/private_lib/Android.mk b/private_lib/Android.mk
new file mode 100644
index 0000000..73529ff
--- /dev/null
+++ b/private_lib/Android.mk
@@ -0,0 +1,65 @@
+#
+# 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.
+#
+ifeq ($(WPA_SUPPLICANT_VERSION),VER_0_8_X)
+
+LOCAL_PATH := $(call my-dir)
+
+ifneq ($(BOARD_WPA_SUPPLICANT_DRIVER),)
+  CONFIG_DRIVER_$(BOARD_WPA_SUPPLICANT_DRIVER) := y
+endif
+
+WPA_SUPPL_DIR = $(LOCAL_PATH)/..
+WPA_SRC_FILE :=
+
+include $(WPA_SUPPL_DIR)/wpa_supplicant/android.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-headers
+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 := private_lib_driver_cmd
+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
diff --git a/private_lib/MODULE_LICENSE_BSD b/private_lib/MODULE_LICENSE_BSD
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/private_lib/MODULE_LICENSE_BSD
diff --git a/private_lib/NOTICE b/private_lib/NOTICE
new file mode 100644
index 0000000..58b094c
--- /dev/null
+++ b/private_lib/NOTICE
@@ -0,0 +1,43 @@
+
+Copyright (c) 2005-2010, The Android Open Source Project
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+ * Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in
+   the documentation and/or other materials provided with the
+   distribution.
+ * Neither the name of The Android Open Source Project nor the names
+   of its contributors may be used to endorse or promote products
+   derived from this software without specific prior written
+   permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+ * 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.
diff --git a/private_lib/driver_cmd_common.h b/private_lib/driver_cmd_common.h
new file mode 100644
index 0000000..03ce253
--- /dev/null
+++ b/private_lib/driver_cmd_common.h
@@ -0,0 +1,58 @@
+/*
+ * Driver interaction for private interface
+ *
+ * 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_COMMON_H
+#define DRIVER_CMD_COMMON_H
+
+#include "config_ssid.h"
+
+#define MAX_DRV_CMD_SIZE		248
+#define DRV_NUMBER_SEQUENTIAL_ERRORS	4
+
+#define RSSI_CMD			"RSSI"
+#define LINKSPEED_CMD			"LINKSPEED"
+
+#define MAX_WPSP2PIE_CMD_SIZE		384
+
+#define WEXT_PNOSETUP_HEADER		"PNOSETUP "
+#define WEXT_PNOSETUP_HEADER_SIZE	9
+#define WEXT_PNO_TLV_PREFIX		'S'
+#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 + MAX_SSID_LEN) \
+					+ WEXT_PNO_NONSSID_SECTIONS_SIZE + 1)
+
+#endif /* DRIVER_CMD_COMMON_H */
diff --git a/private_lib/driver_cmd_nl80211.c b/private_lib/driver_cmd_nl80211.c
new file mode 100644
index 0000000..663ca0b
--- /dev/null
+++ b/private_lib/driver_cmd_nl80211.c
@@ -0,0 +1,366 @@
+/*
+ * 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"
+#include "driver_cmd_common.h"
+
+#include "wpa_supplicant_i.h"
+#include "config.h"
+
+#define WPA_EVENT_DRIVER_STATE		"CTRL-EVENT-DRIVER-STATE "
+
+#define WPA_PS_ENABLED		0
+#define WPA_PS_DISABLED		1
+
+typedef struct android_wifi_priv_cmd {
+	char *buf;
+	int used_len;
+	int total_len;
+} android_wifi_priv_cmd;
+
+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 drv_errors = 0;
+
+static void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv)
+{
+	drv_errors++;
+	if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {
+		drv_errors = 0;
+		wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
+	}
+}
+
+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;
+}
+
+static int wpa_driver_set_backgroundscan_params(void *priv)
+{
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct wpa_supplicant *wpa_s;
+	struct ifreq ifr;
+	android_wifi_priv_cmd priv_cmd;
+	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++] = WEXT_PNO_TLV_PREFIX;
+	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 + MAX_SSID_LEN + WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int)sizeof(buf))
+			break;
+		if ((!ssid_conf->disabled) && (ssid_conf->ssid_len <= MAX_SSID_LEN)){
+			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;
+
+	memset(&ifr, 0, sizeof(ifr));
+	memset(&priv_cmd, 0, sizeof(priv_cmd));
+	os_strncpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
+
+	priv_cmd.buf = buf;
+	priv_cmd.used_len = bp;
+	priv_cmd.total_len = bp;
+	ifr.ifr_data = &priv_cmd;
+
+	ret = ioctl(drv->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
+
+	if (ret < 0) {
+		wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d", ret);
+		wpa_driver_send_hang_msg(drv);
+	} else {
+		drv_errors = 0;
+	}
+	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;
+	struct ifreq ifr;
+	android_wifi_priv_cmd priv_cmd;
+	int ret = 0;
+
+	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);
+		if (ret < 0)
+			wpa_driver_send_hang_msg(drv);
+		else
+			drv_errors = 0;
+	} 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);
+			drv_errors = 0;
+		} else {
+			wpa_driver_send_hang_msg(drv);
+		}
+	} else { /* Use private command */
+		if (os_strcasecmp(cmd, "BGSCAN-START") == 0) {
+			ret = wpa_driver_set_backgroundscan_params(priv);
+			if (ret < 0) {
+				return ret;
+			}
+			os_memcpy(buf, "PNOFORCE 1", 11);
+		} else if (os_strcasecmp(cmd, "BGSCAN-STOP") == 0) {
+			os_memcpy(buf, "PNOFORCE 0", 11);
+		} else {
+			os_memcpy(buf, cmd, strlen(cmd) + 1);
+		}
+		memset(&ifr, 0, sizeof(ifr));
+		memset(&priv_cmd, 0, sizeof(priv_cmd));
+		os_strncpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
+
+		priv_cmd.buf = buf;
+		priv_cmd.used_len = buf_len;
+		priv_cmd.total_len = buf_len;
+		ifr.ifr_data = &priv_cmd;
+
+#ifndef __i386__ /* we don't support SIOCDEVPRIVATE */
+		if ((ret = ioctl(drv->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr)) < 0) {
+			wpa_printf(MSG_ERROR, "%s: failed to issue private commands\n", __func__);
+			wpa_driver_send_hang_msg(drv);
+		} else {
+			drv_errors = 0;
+			ret = 0;
+			if ((os_strcasecmp(cmd, "LINKSPEED") == 0) ||
+			    (os_strcasecmp(cmd, "RSSI") == 0) ||
+			    (os_strcasecmp(cmd, "GETBAND") == 0) ||
+			    (os_strcasecmp(cmd, "P2P_GET_NOA") == 0))
+				ret = strlen(buf);
+
+			wpa_printf(MSG_DEBUG, "%s %s len = %d, %d", __func__, buf, ret, strlen(buf));
+		}
+#endif
+	}
+	return ret;
+}
+
+int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration)
+{
+	char buf[MAX_DRV_CMD_SIZE];
+
+	memset(buf, 0, sizeof(buf));
+	wpa_printf(MSG_DEBUG, "%s: Entry", __func__);
+	snprintf(buf, sizeof(buf), "P2P_SET_NOA %d %d %d", count, start, duration);
+	return wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(buf)+1);
+}
+
+int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len)
+{
+	char rbuf[MAX_DRV_CMD_SIZE];
+	char *cmd = "P2P_GET_NOA";
+	int ret;
+
+	wpa_printf(MSG_DEBUG, "%s: Entry", __func__);
+	os_memset(buf, 0, len);
+	ret = wpa_driver_nl80211_driver_cmd(priv, cmd, rbuf, sizeof(rbuf));
+	if (ret <= 0)
+		return 0;
+	ret >>= 1;
+	if (ret > (int)len)
+		ret = (int)len;
+	hexstr2bin(rbuf, buf, ret);
+	return ret;
+}
+
+int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow)
+{
+	char buf[MAX_DRV_CMD_SIZE];
+
+	memset(buf, 0, sizeof(buf));
+	wpa_printf(MSG_DEBUG, "%s: Entry", __func__);
+	snprintf(buf, sizeof(buf), "P2P_SET_PS %d %d %d", legacy_ps, opp_ps, ctwindow);
+	return wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(buf) + 1);
+}
+
+int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon,
+				 const struct wpabuf *proberesp,
+				 const struct wpabuf *assocresp)
+{
+	char buf[MAX_WPSP2PIE_CMD_SIZE];
+	struct wpabuf *ap_wps_p2p_ie = NULL;
+	char *_cmd = "SET_AP_WPS_P2P_IE";
+	char *pbuf;
+	int ret = 0;
+	int i;
+	struct cmd_desc {
+		int cmd;
+		const struct wpabuf *src;
+	} cmd_arr[] = {
+		{0x1, beacon},
+		{0x2, proberesp},
+		{0x4, assocresp},
+		{-1, NULL}
+	};
+
+	wpa_printf(MSG_DEBUG, "%s: Entry", __func__);
+	for (i = 0; cmd_arr[i].cmd != -1; i++) {
+		os_memset(buf, 0, sizeof(buf));
+		pbuf = buf;
+		pbuf += sprintf(pbuf, "%s %d", _cmd, cmd_arr[i].cmd);
+		*pbuf++ = '\0';
+		ap_wps_p2p_ie = cmd_arr[i].src ?
+			wpabuf_dup(cmd_arr[i].src) : NULL;
+		if (ap_wps_p2p_ie) {
+			os_memcpy(pbuf, wpabuf_head(ap_wps_p2p_ie), wpabuf_len(ap_wps_p2p_ie));
+			ret = wpa_driver_nl80211_driver_cmd(priv, buf, buf,
+				strlen(_cmd) + 3 + wpabuf_len(ap_wps_p2p_ie));
+			wpabuf_free(ap_wps_p2p_ie);
+			if (ret < 0)
+				break;
+		}
+	}
+
+	return ret;
+}
diff --git a/private_lib/driver_cmd_wext.c b/private_lib/driver_cmd_wext.c
new file mode 100644
index 0000000..cbce858
--- /dev/null
+++ b/private_lib/driver_cmd_wext.c
@@ -0,0 +1,367 @@
+/*
+ * 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 "linux/wireless.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"
+#include "driver_cmd_common.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;
+        const u8 *ssid=(params->ssids[0]).ssid;
+        size_t ssid_len=(params->ssids[0]).ssid_len;
+
+	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__);
+	struct iw_scan_req req;
+	int scan_probe_flag = 0;
+
+	if (ssid_len > IW_ESSID_MAX_SIZE) {
+		wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)",
+			   __FUNCTION__, (unsigned long) ssid_len);
+		return -1;
+	}
+
+	os_memset(&iwr, 0, sizeof(iwr));
+	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+#ifdef ANDROID
+	if (wpa_s->prev_scan_ssid != WILDCARD_SSID_SCAN) {
+		scan_probe_flag = wpa_s->prev_scan_ssid->scan_ssid;
+	}
+	wpa_printf(MSG_DEBUG, "%s: specific scan = %d", __func__,
+		(scan_probe_flag && (ssid && ssid_len)) ? 1 : 0);
+	if (scan_probe_flag && (ssid && ssid_len)) {
+#else
+	if (ssid && ssid_len) {
+#endif
+		os_memset(&req, 0, sizeof(req));
+		req.essid_len = ssid_len;
+		req.bssid.sa_family = ARPHRD_ETHER;
+		os_memset(req.bssid.sa_data, 0xff, ETH_ALEN);
+		os_memcpy(req.essid, ssid, ssid_len);
+		iwr.u.data.pointer = (caddr_t) &req;
+		iwr.u.data.length = sizeof(req);
+		iwr.u.data.flags = IW_SCAN_THIS_ESSID;
+	}
+
+        ret = ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr);
+	if (ret < 0) {
+		wpa_printf(MSG_ERROR, "ioctl[SIOCSIWSCAN] ret = ",ret);
+		ret = -1;
+	}
+
+	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, "start") == 0) {
+        wpa_printf(MSG_DEBUG,"Start command");
+        return -1;
+    }
+    if (os_strcasecmp(cmd, "macaddr") == 0) {
+        struct ifreq ifr;
+        os_memset(&ifr, 0, sizeof(ifr));
+        os_strncpy(ifr.ifr_name, drv->ifname, IFNAMSIZ);
+        if (ioctl(drv->ioctl_sock, SIOCGIFHWADDR, &ifr) < 0) {
+            perror("ioctl[SIOCGIFHWADDR]");
+            ret = -1;
+        } else {
+            u8 *macaddr = (u8 *) ifr.ifr_hwaddr.sa_data;
+            ret = snprintf(buf, buf_len, "Macaddr = " MACSTR "\n",
+                    MAC2STR(macaddr));
+        }
+        return ret;
+    }
+    else if (os_strcasecmp(cmd, "scan-passive") == 0) {
+        wpa_printf(MSG_DEBUG,"Scan Passive command");
+        return 0;
+    }
+    else if (os_strcasecmp(cmd, "SETBAND") == 0) {
+        wpa_printf(MSG_DEBUG,"Setband command");
+        ret=0;
+        return 0;
+    }
+    else if (os_strcasecmp(cmd, "scan-active") == 0) {
+        wpa_printf(MSG_DEBUG,"Scan Active command");
+        ret=0;
+        return 0;
+    }
+    else if (os_strcasecmp(cmd, "linkspeed") == 0) {
+        struct iwreq wrq;
+        unsigned int linkspeed;
+        os_strncpy(wrq.ifr_name, drv->ifname, IFNAMSIZ);
+        if (ioctl(drv->ioctl_sock, SIOCGIWRATE, &wrq) < 0) {
+            perror("ioctl[SIOCGIWRATE]");
+            ret = -1;
+        } else {
+            linkspeed = wrq.u.bitrate.value / 1000000;
+            ret = snprintf(buf, buf_len, "LinkSpeed %d\n", linkspeed);
+            wpa_printf(MSG_DEBUG, "[REPLY]: %s", buf);
+        }
+        return 0;
+    }
+    else if (os_strncasecmp(cmd, "scan-channels", 13) == 0) {
+    }
+    else if (os_strncasecmp(cmd, "rssi", 4) == 0) {
+        /* Matches both rssi and rssi-approx */
+        struct iwreq wrq;
+        struct iw_statistics stats;
+        signed int rssi;
+
+        wrq.u.data.pointer = (caddr_t) &stats;
+        wrq.u.data.length = sizeof(stats);
+        wrq.u.data.flags = 1; /* Clear updated flag */
+        strncpy(wrq.ifr_name, drv->ifname, IFNAMSIZ);
+
+
+        if (ioctl(drv->ioctl_sock, SIOCGIWSTATS, &wrq) < 0) {
+            perror("ioctl[SIOCGIWSTATS]");
+            ret = -1;
+        } else {
+            if (stats.qual.updated & IW_QUAL_DBM) {
+                /* Values in dBm, stored in u8 with range 63 : -192 */
+                rssi = ( stats.qual.level > 63 ) ?
+                    stats.qual.level - 0x100 :
+                    stats.qual.level;
+            } else {
+                rssi = stats.qual.level;
+            }
+            if (wpa_s->conf->ssid->ssid_len != 0 && wpa_s->conf->ssid->ssid_len < buf_len) {
+                os_memcpy((void *) buf, (void *) (wpa_s->conf->ssid->ssid),
+                        wpa_s->conf->ssid->ssid_len );
+                ret = wpa_s->conf->ssid->ssid_len;
+                ret += snprintf(&buf[ret], buf_len-ret,
+                        " rssi %d\n", rssi);
+                wpa_printf(MSG_DEBUG, "[REPLY]: %s", buf);
+                if (ret < (int)buf_len) {
+                    return ret;
+                }
+            } else {
+                ret = -1;
+            }
+
+        }
+
+    }
+    else if (os_strncasecmp(cmd, "powermode", 9) == 0) {
+    }
+    else if (os_strncasecmp(cmd, "getpower", 8) == 0) {
+    }
+    else if (os_strncasecmp(cmd, "get-rts-threshold", 17) == 0) {
+        struct iwreq wrq;
+        unsigned int rtsThreshold;
+
+        strncpy(wrq.ifr_name, drv->ifname, IFNAMSIZ);
+
+        if (ioctl(drv->ioctl_sock, SIOCGIWRTS, &wrq) < 0) {
+            perror("ioctl[SIOCGIWRTS]");
+            ret = -1;
+        } else {
+            rtsThreshold = wrq.u.rts.value;
+            wpa_printf(MSG_DEBUG,"Get RTS Threshold command = %d",
+                    rtsThreshold);
+            ret = snprintf(buf, buf_len, "rts-threshold = %u\n",
+                    rtsThreshold);
+            if (ret < (int)buf_len) {
+                return ret;
+            }
+        }
+    }
+    else if (os_strncasecmp(cmd, "set-rts-threshold", 17) == 0) {
+        struct iwreq wrq;
+        unsigned int rtsThreshold;
+        char *cp = cmd + 17;
+        char *endp;
+
+        strncpy(wrq.ifr_name, drv->ifname, IFNAMSIZ);
+
+        if (*cp != '\0') {
+            rtsThreshold = (unsigned int)strtol(cp, &endp, 0);
+            if (endp != cp) {
+                wrq.u.rts.value = rtsThreshold;
+                wrq.u.rts.fixed = 1;
+                wrq.u.rts.disabled = 0;
+
+                if (ioctl(drv->ioctl_sock, SIOCSIWRTS, &wrq) < 0) {
+                    perror("ioctl[SIOCGIWRTS]");
+                    ret = -1;
+                } else {
+                    rtsThreshold = wrq.u.rts.value;
+                    wpa_printf(MSG_DEBUG,"Set RTS Threshold command = %d", rtsThreshold);
+                    ret = 0;
+                }
+            }
+        }
+    }
+    else if (os_strcasecmp(cmd, "btcoexscan-start") == 0) {
+    }
+    else if (os_strcasecmp(cmd, "btcoexscan-stop") == 0) {
+    }
+    else if (os_strcasecmp(cmd, "rxfilter-start") == 0) {
+        wpa_printf(MSG_DEBUG,"Rx Data Filter Start command");
+    }
+    else if (os_strcasecmp(cmd, "rxfilter-stop") == 0) {
+        wpa_printf(MSG_DEBUG,"Rx Data Filter Stop command");
+    }
+    else if (os_strcasecmp(cmd, "rxfilter-statistics") == 0) {
+    }
+    else if (os_strncasecmp(cmd, "rxfilter-add", 12) == 0 ) {
+    }
+    else if (os_strncasecmp(cmd, "rxfilter-remove",15) == 0) {
+    }
+    else if (os_strcasecmp(cmd, "snr") == 0) {
+        struct iwreq wrq;
+        struct iw_statistics stats;
+        int snr, rssi, noise;
+
+        wrq.u.data.pointer = (caddr_t) &stats;
+        wrq.u.data.length = sizeof(stats);
+        wrq.u.data.flags = 1; /* Clear updated flag */
+        strncpy(wrq.ifr_name, drv->ifname, IFNAMSIZ);
+
+        if (ioctl(drv->ioctl_sock, SIOCGIWSTATS, &wrq) < 0) {
+            perror("ioctl[SIOCGIWSTATS]");
+            ret = -1;
+        } else {
+            if (stats.qual.updated & IW_QUAL_DBM) {
+                /* Values in dBm, stored in u8 with range 63 : -192 */
+                rssi = ( stats.qual.level > 63 ) ?
+                    stats.qual.level - 0x100 :
+                    stats.qual.level;
+                noise = ( stats.qual.noise > 63 ) ?
+                    stats.qual.noise - 0x100 :
+                    stats.qual.noise;
+            } else {
+                rssi = stats.qual.level;
+                noise = stats.qual.noise;
+            }
+
+            snr = rssi - noise;
+
+            ret = snprintf(buf, buf_len, "snr = %u\n", (unsigned int)snr);
+            if (ret < (int)buf_len) {
+                return ret;
+            }
+        }
+    }
+    else if (os_strncasecmp(cmd, "btcoexmode", 10) == 0) {
+    }
+    else if( os_strcasecmp(cmd, "btcoexstat") == 0 ) {
+    }
+    else {
+        wpa_printf(MSG_DEBUG,"Unsupported command");
+
+    }
+    return ret;
+}
+
+int wpa_driver_signal_poll(void *priv, struct wpa_signal_info *si)
+{
+	char buf[MAX_DRV_CMD_SIZE];
+	struct wpa_driver_wext_data *drv = priv;
+	char *prssi;
+	int res;
+
+	os_memset(si, 0, sizeof(*si));
+	res = wpa_driver_wext_driver_cmd(priv, RSSI_CMD, buf, sizeof(buf));
+	/* Answer: SSID rssi -Val */
+	if (res < 0)
+		return res;
+	prssi = strcasestr(buf, RSSI_CMD);
+	if (!prssi)
+		return -1;
+	si->current_signal = atoi(prssi + strlen(RSSI_CMD) + 1);
+
+	res = wpa_driver_wext_driver_cmd(priv, LINKSPEED_CMD, buf, sizeof(buf));
+	/* Answer: LinkSpeed Val */
+	if (res < 0)
+		return res;
+	si->current_txrate = atoi(buf + strlen(LINKSPEED_CMD) + 1) * 1000;
+
+	return 0;
+}
diff --git a/private_lib/driver_cmd_wext.h b/private_lib/driver_cmd_wext.h
new file mode 100644
index 0000000..1c6e8a1
--- /dev/null
+++ b/private_lib/driver_cmd_wext.h
@@ -0,0 +1,38 @@
+/*
+ * 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 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
+
+#endif /* DRIVER_CMD_WEXT_H */
diff --git a/private_lib/driver_nl80211.h b/private_lib/driver_nl80211.h
new file mode 100644
index 0000000..7d19995
--- /dev/null
+++ b/private_lib/driver_nl80211.h
@@ -0,0 +1,150 @@
+/*
+ * 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 no_monitor_iface_capab;
+	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;
+	unsigned int ap_oper_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