diff --git a/src/common/wireless_copy.h b/src/common/wireless_copy.h
index ad76466..8045b44 100644
--- a/src/common/wireless_copy.h
+++ b/src/common/wireless_copy.h
@@ -86,11 +86,13 @@
 #else
 #include <sys/types.h>
 #include <net/if.h>
+#if 0
 typedef __uint32_t __u32;
 typedef __int32_t __s32;
 typedef __uint16_t __u16;
 typedef __int16_t __s16;
 typedef __uint8_t __u8;
+#endif
 #ifndef __user
 #define __user
 #endif /* __user */
diff --git a/src/common/wpa_ctrl.c b/src/common/wpa_ctrl.c
index 2b4e3aa..7e33bb3 100644
--- a/src/common/wpa_ctrl.c
+++ b/src/common/wpa_ctrl.c
@@ -19,6 +19,11 @@
 #ifdef CONFIG_CTRL_IFACE_UNIX
 #include <sys/un.h>
 #endif /* CONFIG_CTRL_IFACE_UNIX */
+#include <dirent.h>
+#include <linux/limits.h>
+#include <cutils/sockets.h>
+#include <cutils/memory.h>
+#include "private/android_filesystem_config.h"
 
 #include "wpa_ctrl.h"
 #include "common.h"
@@ -26,9 +31,10 @@
 
 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
 #define CTRL_IFACE_SOCKET
+static const char *local_socket_dir = "/data/misc/wifi/sockets";
+static const char *local_socket_prefix = "wpa_ctrl_";
 #endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */
 
-
 /**
  * struct wpa_ctrl - Internal structure for control interface library
  *
@@ -81,7 +87,8 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
 	counter++;
 try_again:
 	ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
-			  "/tmp/wpa_ctrl_%d-%d", getpid(), counter);
+			  "%s/%s%d-%d", local_socket_dir, local_socket_prefix,
+			  getpid(), counter);
 	if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) {
 		close(ctrl->s);
 		os_free(ctrl);
@@ -105,6 +112,29 @@ try_again:
 		return NULL;
 	}
 
+	chmod(ctrl->local.sun_path, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
+	chown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI);
+	/*
+	 * If the ctrl_path isn't an absolute pathname, assume that
+	 * it's the name of a socket in the Android reserved namespace.
+	 * Otherwise, it's a normal UNIX domain socket appearing in the
+	 * filesystem.
+	 */
+	if (ctrl_path != NULL && *ctrl_path != '/') {
+		os_snprintf(ctrl->dest.sun_path, sizeof(ctrl->dest.sun_path), "wpa_%s",
+			    ctrl_path);
+		if (socket_local_client_connect(ctrl->s,
+						ctrl->dest.sun_path,
+						ANDROID_SOCKET_NAMESPACE_RESERVED,
+						SOCK_DGRAM) < 0) {
+			close(ctrl->s);
+			unlink(ctrl->local.sun_path);
+			os_free(ctrl);
+			return NULL;
+		}
+		return ctrl;
+	}
+
 	ctrl->dest.sun_family = AF_UNIX;
 	res = os_strlcpy(ctrl->dest.sun_path, ctrl_path,
 			 sizeof(ctrl->dest.sun_path));
@@ -132,9 +162,45 @@ void wpa_ctrl_close(struct wpa_ctrl *ctrl)
 	os_free(ctrl);
 }
 
+/**
+ * wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that
+ * may be left over from clients that were previously connected to
+ * wpa_supplicant. This keeps these files from being orphaned in the
+ * event of crashes that prevented them from being removed as part
+ * of the normal orderly shutdown.
+ */
+void wpa_ctrl_cleanup()
+{
+    DIR *dir;
+    struct dirent entry;
+    struct dirent *result;
+    size_t dirnamelen;
+    int prefixlen = strlen(local_socket_prefix);
+    size_t maxcopy;
+    char pathname[PATH_MAX];
+    char *namep;
+
+    if ((dir = opendir(local_socket_dir)) == NULL)
+        return;
+
+    dirnamelen = (size_t)snprintf(pathname, sizeof(pathname), "%s/", local_socket_dir);
+    if (dirnamelen >= sizeof(pathname)) {
+        closedir(dir);
+        return;
+    }
+    namep = pathname + dirnamelen;
+    maxcopy = PATH_MAX-dirnamelen;
+    while (readdir_r(dir, &entry, &result) == 0 && result != NULL) {
+        if (strncmp(entry.d_name, local_socket_prefix, prefixlen) == 0) {
+            if (strlcpy(namep, entry.d_name, maxcopy) < maxcopy) {
+                unlink(pathname);
+            }
+        }
+    }
+    closedir(dir);
+}
 #endif /* CONFIG_CTRL_IFACE_UNIX */
 
-
 #ifdef CONFIG_CTRL_IFACE_UDP
 
 struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index d3bda18..7a3dc5a 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1017,6 +1017,18 @@ struct wpa_driver_ops {
 	 * failure
 	 */
 	struct wpa_interface_info * (*get_interfaces)(void *global_priv);
+
+	/**
+	 * driver_cmd - execute driver-specific command
+	 * @priv: private driver interface data from init()
+	 * @cmd: command to execute
+	 * @buf: return buffer
+	 * @buf_len: buffer length
+	 *
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 */
+	int (*driver_cmd)(void *priv, char *cmd, char *buf, size_t buf_len);
 };
 
 /* Function to check whether a driver is for wired connections */
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 2646270..8ee6e73 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -2901,6 +2901,108 @@ nla_put_failure:
 
 #endif /* CONFIG_CLIENT_MLME */
 
+int wpa_driver_nl80211_get_mac_addr(void *priv, u8 *addr)
+{
+	struct wpa_driver_nl80211_data *drv = priv;
+	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]");
+		return -1;
+	}
+	os_memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+	return 0;
+}
+
+int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf, size_t len)
+{
+	struct wpa_driver_nl80211_data *drv = priv;
+	int ret = -1;
+
+	wpa_printf(MSG_DEBUG, "%s %s", __func__, cmd);
+
+	if (os_strcasecmp(cmd, "start") == 0) {
+		wpa_printf(MSG_DEBUG,"Start command");
+		ret = 0;
+	} else if (os_strcasecmp(cmd, "stop") == 0) {
+		wpa_printf(MSG_DEBUG,"Stop command");
+		ret = 0;
+	} else if (os_strcasecmp(cmd, "macaddr") == 0) {
+		u8 macaddr[ETH_ALEN] = {};
+
+		ret = wpa_driver_nl80211_get_mac_addr(priv, macaddr);
+		if (ret)
+			goto out;
+
+		wpa_printf(MSG_DEBUG,"Macaddr command");
+		wpa_printf(MSG_DEBUG, "   Macaddr = " MACSTR, MAC2STR(macaddr));
+		ret = os_snprintf(buf, len, "Macaddr = " MACSTR "\n", MAC2STR(macaddr));
+	} else if (os_strcasecmp(cmd, "scan-passive") == 0) {
+		wpa_printf(MSG_DEBUG,"Scan Passive command");
+		ret = 0;
+	} else if (os_strcasecmp(cmd, "scan-active") == 0) {
+		wpa_printf(MSG_DEBUG,"Scan Active command");
+		ret = 0;
+	} else if (os_strcasecmp(cmd, "linkspeed") == 0) {
+		wpa_printf(MSG_DEBUG,"Link Speed command");
+		ret = 0;
+	} else if (os_strncasecmp(cmd, "scan-channels", 13) == 0) {
+		wpa_printf(MSG_DEBUG,"Scan Channels command");
+		ret = 0;
+	} else if (os_strcasecmp(cmd, "rssi") == 0) {
+		wpa_printf(MSG_DEBUG,"rssi command");
+		ret = 0;
+	} else if (os_strncasecmp(cmd, "powermode", 9) == 0) {
+		wpa_printf(MSG_DEBUG,"Power Mode command");
+		ret = 0;
+	} else if (os_strncasecmp(cmd, "getpower", 8) == 0) {
+		wpa_printf(MSG_DEBUG,"Get power command");
+		ret = 0;
+	} else if (os_strncasecmp(cmd, "get-rts-threshold", 17) == 0) {
+		wpa_printf(MSG_DEBUG,"Get RTS Threshold command");
+		ret = 0;
+	} else if (os_strncasecmp(cmd, "set-rts-threshold", 17) == 0) {
+		wpa_printf(MSG_DEBUG,"Set RTS Threshold command");
+		ret = 0;
+	} else if (os_strcasecmp(cmd, "btcoexscan-start") == 0) {
+		wpa_printf(MSG_DEBUG,"BT Coex Scan Start command");
+		ret = 0;
+	} else if (os_strcasecmp(cmd, "btcoexscan-stop") == 0) {
+		wpa_printf(MSG_DEBUG,"BT Coex Scan Stop command");
+		ret = 0;
+	} else if (os_strcasecmp(cmd, "rxfilter-start") == 0) {
+		wpa_printf(MSG_DEBUG,"Rx Data Filter Start command");
+		ret = 0;
+	} else if (os_strcasecmp(cmd, "rxfilter-stop") == 0) {
+		wpa_printf(MSG_DEBUG,"Rx Data Filter Stop command");
+		ret = 0;
+	} else if (os_strcasecmp(cmd, "rxfilter-statistics") == 0) {
+		wpa_printf(MSG_DEBUG,"Rx Data Filter Statistics command");
+		ret = 0;
+	} else if (os_strncasecmp(cmd, "rxfilter-add", 12) == 0) {
+		wpa_printf(MSG_DEBUG,"Rx Data Filter Add command");
+		ret = 0;
+	} else if (os_strncasecmp(cmd, "rxfilter-remove",15) == 0) {
+		wpa_printf(MSG_DEBUG,"Rx Data Filter Remove command");
+		ret = 0;
+	} else if (os_strcasecmp(cmd, "snr") == 0) {
+		wpa_printf(MSG_DEBUG,"SNR command");
+		ret = 0;
+	} else if (os_strncasecmp(cmd, "btcoexmode", 10) == 0) {
+		wpa_printf(MSG_DEBUG,"BtCoex Mode command");
+		ret = 0;
+	} else if (os_strcasecmp(cmd, "btcoexstat") == 0) {
+		wpa_printf(MSG_DEBUG,"BtCoex Status");
+		ret = 0;
+	} else {
+		wpa_printf(MSG_DEBUG,"Unsupported command");
+	}
+out:
+	return ret;
+}
 
 const struct wpa_driver_ops wpa_driver_nl80211_ops = {
 	.name = "nl80211",
@@ -2937,4 +3039,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
 	.mlme_add_sta = wpa_driver_nl80211_mlme_add_sta,
 	.mlme_remove_sta = wpa_driver_nl80211_mlme_remove_sta,
 #endif /* CONFIG_CLIENT_MLME */
+	.driver_cmd = wpa_driver_nl80211_driver_cmd,
 };
diff --git a/wpa_supplicant/config_android b/wpa_supplicant/config_android
new file mode 100644
index 0000000..3b16b13
--- /dev/null
+++ b/wpa_supplicant/config_android
@@ -0,0 +1,108 @@
+# Example wpa_supplicant build time configuration
+#
+# This file lists the configuration options that are used when building the
+# hostapd binary. All lines starting with # are ignored. Configuration option
+# lines must be commented out complete, if they are not to be included, i.e.,
+# just setting VARIABLE=n is not disabling that variable.
+#
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
+# be modified from here. In most cases, these lines should use += in order not
+# to override previous values of the variables.
+
+
+# Uncomment following two lines and fix the paths if you have installed OpenSSL
+# or GnuTLS in non-default location
+#CFLAGS += -I/usr/local/openssl/include
+#LIBS += -L/usr/local/openssl/lib
+
+# Some Red Hat versions seem to include kerberos header files from OpenSSL, but
+# the kerberos files are not in the default include path. Following line can be
+# used to fix build issues on such systems (krb5.h not found).
+#CFLAGS += -I/usr/include/kerberos
+
+# Example configuration for various cross-compilation platforms
+
+#### sveasoft (e.g., for Linksys WRT54G) ######################################
+#CC=mipsel-uclibc-gcc
+#CC=/opt/brcm/hndtools-mipsel-uclibc/bin/mipsel-uclibc-gcc
+#CFLAGS += -Os
+#CPPFLAGS += -I../src/include -I../../src/router/openssl/include
+#LIBS += -L/opt/brcm/hndtools-mipsel-uclibc-0.9.19/lib -lssl
+###############################################################################
+
+#### openwrt (e.g., for Linksys WRT54G) #######################################
+#CC=mipsel-uclibc-gcc
+#CC=/opt/brcm/hndtools-mipsel-uclibc/bin/mipsel-uclibc-gcc
+#CFLAGS += -Os
+#CPPFLAGS=-I../src/include -I../openssl-0.9.7d/include \
+#	-I../WRT54GS/release/src/include
+#LIBS = -lssl
+###############################################################################
+
+
+# Driver interface for Host AP driver
+#CONFIG_DRIVER_HOSTAP=y
+
+# Driver interface for Agere driver
+#CONFIG_DRIVER_HERMES=y
+# Change include directories to match with the local setup
+#CFLAGS += -I../../hcf -I../../include -I../../include/hcf
+#CFLAGS += -I../../include/wireless
+
+ANDROID=/home/bob/ext/mydroid
+ANDROID_OBJ=$(ANDROID)/out/target/product/dream/obj/
+ANDROID_LIB=$(ANDROID_OBJ)/lib
+TOOLCHAIN=$(ANDROID)/prebuilt/linux-x86/toolchain/arm-eabi-4.3.1
+BIONIC=$(ANDROID)/bionic
+
+LIBNL=/home/bob/ext/libnl
+
+CC=$(TOOLCHAIN)/bin/arm-eabi-gcc
+CFLAGS += -mabi=aapcs-linux -DWPA_IGNORE_CONFIG_ERRORS -D__linux__ -march=armv5te -mtune=xscale -fpic
+CPPFLAGS= -I$(BIONIC)/libc/kernel/common \
+ -I$(BIONIC)/libc/kernel/common \
+ -I$(LIBNL)/include \
+ -I$(BIONIC)/libc/include \
+ -I$(BIONIC)/libc/arch-arm/include \
+ -I$(BIONIC)/libc/kernel/arch-arm \
+ -I$(ANDROID)/system/core/include \
+ -I$(ANDROID)/external/openssl/include
+
+LIBS=-Wl,-rpath-link=$(ANDROID_LIB) \
+ -Wl,-T,$(ANDROID)/build/core/armelf.x \
+ -Wl,-T,$(ANDROID)/build/core/armelf.xsc \
+ -Wl,-dynamic-linker,/system/bin/linker \
+ -Wl,-z,nocopyreloc \
+ -Wl,--no-undefined \
+ -L$(ANDROID_LIB) \
+ -nostdlib \
+ $(ANDROID_LIB)/crtend_android.o \
+ $(ANDROID_LIB)/crtbegin_dynamic.o \
+ -l cutils \
+ -L$(LIBNL)/lib \
+ -lnl -lc -lm
+LIBS_p=$(LIBS)
+LIBS_c=$(LIBS)
+
+CONFIG_OS=unix
+CONFIG_IEEE8021X_EAPOL=y
+CONFIG_EAP_MD5=y
+CONFIG_EAP_MSCHAPV2=y
+CONFIG_EAP_TLS=y
+CONFIG_EAP_PEAP=y
+CONFIG_EAP_TTLS=y
+CONFIG_EAP_GTC=y
+CONFIG_EAP_OTP=y
+CONFIG_EAP_SIM=y
+CONFIG_EAP_AKA=y
+CONFIG_EAP_PSK=y
+CONFIG_EAP_SAKE=y
+CONFIG_EAP_GPSK=y
+CONFIG_EAP_PAX=y
+CONFIG_EAP_LEAP=y
+CONFIG_PKCS12=y
+CONFIG_SMARTCARD=y
+CONFIG_WIRELESS_EXTENSION=y
+CONFIG_CTRL_IFACE=y
+CONFIG_DRIVER_NL80211=y
+CONFIG_DEBUG_FILE=y
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 7bb871a..163313c 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -1498,7 +1498,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
 					 char *buf, size_t *resp_len)
 {
 	char *reply;
-	const int reply_size = 2048;
+	const int reply_size = 4096;
 	int ctrl_rsp = 0;
 	int reply_len;
 
@@ -1661,6 +1661,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
 	} else if (os_strncmp(buf, "BSS ", 4) == 0) {
 		reply_len = wpa_supplicant_ctrl_iface_bss(
 			wpa_s, buf + 4, reply, reply_size);
+	} else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
+		reply_len = wpa_drv_driver_cmd(
+			wpa_s, buf + 7, reply, reply_size);
 	} else {
 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
 		reply_len = 16;
@@ -1855,7 +1858,7 @@ char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
 						char *buf, size_t *resp_len)
 {
 	char *reply;
-	const int reply_size = 2048;
+	const int reply_size = 4096;
 	int reply_len;
 
 	wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface",
diff --git a/wpa_supplicant/ctrl_iface_unix.c b/wpa_supplicant/ctrl_iface_unix.c
index bf6328e..025dd08 100644
--- a/wpa_supplicant/ctrl_iface_unix.c
+++ b/wpa_supplicant/ctrl_iface_unix.c
@@ -16,6 +16,7 @@
 #include <sys/un.h>
 #include <sys/stat.h>
 #include <grp.h>
+#include <cutils/sockets.h>
 
 #include "common.h"
 #include "eloop.h"
@@ -277,6 +278,11 @@ wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
 	buf = os_strdup(wpa_s->conf->ctrl_interface);
 	if (buf == NULL)
 		goto fail;
+	os_snprintf(addr.sun_path, sizeof(addr.sun_path), "wpa_%s",
+			wpa_s->conf->ctrl_interface);
+	priv->sock = android_get_control_socket(addr.sun_path);
+	if (priv->sock >= 0)
+		goto havesock;
 	if (os_strncmp(buf, "DIR=", 4) == 0) {
 		dir = buf + 4;
 		gid_str = os_strstr(dir, " GROUP=");
@@ -388,6 +394,7 @@ wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
 	}
 	os_free(fname);
 
+havesock:
 	eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive,
 				 wpa_s, priv);
 	wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
@@ -627,6 +634,9 @@ wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
 	if (global->params.ctrl_interface == NULL)
 		return priv;
 
+	priv->sock = android_get_control_socket(global->params.ctrl_interface);
+	if (priv->sock >= 0)
+		goto havesock;
 	wpa_printf(MSG_DEBUG, "Global control interface '%s'",
 		   global->params.ctrl_interface);
 
@@ -671,7 +681,7 @@ wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
 			goto fail;
 		}
 	}
-
+havesock:
 	eloop_register_read_sock(priv->sock,
 				 wpa_supplicant_global_ctrl_iface_receive,
 				 global, NULL);
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index b49f23a..45180d4 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -763,4 +763,12 @@ static inline int wpa_drv_set_probe_req_ie(struct wpa_supplicant *wpa_s,
 	return -1;
 }
 
+static inline int wpa_drv_driver_cmd(struct wpa_supplicant *wpa_s,
+				     char *cmd, char *buf, size_t buf_len)
+{
+	if (wpa_s->driver->driver_cmd)
+		return wpa_s->driver->driver_cmd(wpa_s->drv_priv, cmd, buf,
+						 buf_len);
+	return -1;
+}
 #endif /* WPA_SUPPLICANT_I_H */
