realtek: Initial commit cm-10.1 cm-10.1-staging cm-10.2 cm-10.1-M1 cm-10.1-M2 cm-10.1-M3 cm-10.1.0 cm-10.1.0-RC1 cm-10.1.0-RC2 cm-10.1.0-RC3 cm-10.1.0-RC4 cm-10.1.0-RC5 cm-10.1.1 cm-10.1.2 cm-10.1.3 cm-10.1.3-RC1 cm-10.1.3-RC2 cm-10.2-M1
authorRicardo Cerqueira <cyanogenmod@cerqueira.org>
Sun, 30 Dec 2012 16:55:06 +0000 (16:55 +0000)
committerRicardo Cerqueira <cyanogenmod@cerqueira.org>
Sun, 30 Dec 2012 16:55:06 +0000 (16:55 +0000)
Unchanged from the Hardkernel odroid U2's BSP

12 files changed:
wlan/Android.mk [new file with mode: 0644]
wlan/config/Android.mk [new file with mode: 0644]
wlan/config/android_dhcpcd.conf [new file with mode: 0644]
wlan/libhardware_legacy/wifi/wifi_realtek.c [new file with mode: 0644]
wlan/wpa_supplicant_8_lib/Android.mk [new file with mode: 0644]
wlan/wpa_supplicant_8_lib/MODULE_LICENSE_BSD [new file with mode: 0644]
wlan/wpa_supplicant_8_lib/NOTICE [new file with mode: 0644]
wlan/wpa_supplicant_8_lib/driver_cmd_common.h [new file with mode: 0644]
wlan/wpa_supplicant_8_lib/driver_cmd_nl80211.c [new file with mode: 0644]
wlan/wpa_supplicant_8_lib/driver_cmd_wext.c [new file with mode: 0644]
wlan/wpa_supplicant_8_lib/driver_cmd_wext.h [new file with mode: 0644]
wlan/wpa_supplicant_8_lib/driver_nl80211.h [new file with mode: 0644]

diff --git a/wlan/Android.mk b/wlan/Android.mk
new file mode 100644 (file)
index 0000000..19a2227
--- /dev/null
@@ -0,0 +1,4 @@
+ifeq ($(BOARD_WLAN_DEVICE), rtl8191su)
+       include $(call all-subdir-makefiles)
+endif  
+
diff --git a/wlan/config/Android.mk b/wlan/config/Android.mk
new file mode 100644 (file)
index 0000000..468945c
--- /dev/null
@@ -0,0 +1,41 @@
+#
+# 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)
+
+########################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := dhcpcd.conf
+LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/dhcpcd
+LOCAL_SRC_FILES := android_dhcpcd.conf
+include $(BUILD_PREBUILT)
+
+########################
+
+WIFI_DRIVER_SOCKET_IFACE := wlan0
+ifeq ($(strip $(WPA_SUPPLICANT_VERSION)),VER_0_8_X)
+  include external/wpa_supplicant_8/wpa_supplicant/wpa_supplicant_conf.mk
+else
+ifeq ($(strip $(WPA_SUPPLICANT_VERSION)),VER_0_6_X)
+  include external/wpa_supplicant_6/wpa_supplicant/wpa_supplicant_conf.mk
+else
+  include external/wpa_supplicant/wpa_supplicant_conf.mk
+endif
+endif
+
+########################
diff --git a/wlan/config/android_dhcpcd.conf b/wlan/config/android_dhcpcd.conf
new file mode 100644 (file)
index 0000000..54006c7
--- /dev/null
@@ -0,0 +1,6 @@
+# dhcpcd configuration for Android Wi-Fi interface
+# See dhcpcd.conf(5) for details.
+
+interface wlan0
+# dhcpcd-run-hooks uses these options.
+option subnet_mask, routers, domain_name_servers
diff --git a/wlan/libhardware_legacy/wifi/wifi_realtek.c b/wlan/libhardware_legacy/wifi/wifi_realtek.c
new file mode 100644 (file)
index 0000000..46037ed
--- /dev/null
@@ -0,0 +1,823 @@
+/*
+ * Copyright 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.
+ */
+
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <dirent.h>
+#include <sys/socket.h>
+#include <poll.h>
+
+#include "hardware_legacy/wifi.h"
+#include "libwpa_client/wpa_ctrl.h"
+
+#define LOG_TAG "WifiHW"
+#include "cutils/log.h"
+#include "cutils/memory.h"
+#include "cutils/misc.h"
+#include "cutils/properties.h"
+#include "private/android_filesystem_config.h"
+#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
+#endif
+
+static struct wpa_ctrl *ctrl_conn;
+static struct wpa_ctrl *monitor_conn;
+/* socket pair used to exit from a blocking read */
+static int exit_sockets[2] = { -1, -1 };
+
+extern int do_dhcp();
+extern int ifc_init();
+extern void ifc_close();
+extern char *dhcp_lasterror();
+extern void get_dhcp_info();
+extern int init_module(void *, unsigned long, const char *);
+extern int delete_module(const char *, unsigned int);
+
+static char iface[PROPERTY_VALUE_MAX];
+// TODO: use new ANDROID_SOCKET mechanism, once support for multiple
+// sockets is in
+
+#ifndef WIFI_DRIVER_MODULE_ARG
+#define WIFI_DRIVER_MODULE_ARG          ""
+#endif
+#ifndef WIFI_FIRMWARE_LOADER
+#define WIFI_FIRMWARE_LOADER           ""
+#endif
+#define WIFI_TEST_INTERFACE            "sta"
+
+#ifndef WIFI_DRIVER_FW_PATH_STA
+#define WIFI_DRIVER_FW_PATH_STA                NULL
+#endif
+#ifndef WIFI_DRIVER_FW_PATH_AP
+#define WIFI_DRIVER_FW_PATH_AP         NULL
+#endif
+#ifndef WIFI_DRIVER_FW_PATH_P2P
+#define WIFI_DRIVER_FW_PATH_P2P                NULL
+#endif
+
+#undef WIFI_DRIVER_FW_PATH_STA
+#define WIFI_DRIVER_FW_PATH_STA         "STA"
+#undef WIFI_DRIVER_FW_PATH_AP
+#define WIFI_DRIVER_FW_PATH_AP          "AP"
+#undef WIFI_DRIVER_FW_PATH_P2P
+#define WIFI_DRIVER_FW_PATH_P2P         "P2P"
+
+#ifndef WIFI_DRIVER_FW_PATH_PARAM
+#define WIFI_DRIVER_FW_PATH_PARAM      "/sys/module/wlan/parameters/fwpath"
+#endif
+
+#define WIFI_DRIVER_LOADER_DELAY       1000000
+
+static const char IFACE_DIR[]           = "/data/system/wpa_supplicant";
+#ifdef WIFI_DRIVER_MODULE_PATH
+static const char DRIVER_MODULE_NAME[]  = WIFI_DRIVER_MODULE_NAME;
+static const char DRIVER_MODULE_TAG[]   = WIFI_DRIVER_MODULE_NAME " ";
+static const char DRIVER_MODULE_PATH[]  = WIFI_DRIVER_MODULE_PATH;
+static const char DRIVER_MODULE_ARG[]   = WIFI_DRIVER_MODULE_ARG;
+#endif
+static const char FIRMWARE_LOADER[]     = WIFI_FIRMWARE_LOADER;
+static const char DRIVER_PROP_NAME[]    = "wlan.driver.status";
+static const char SUPPLICANT_NAME[]     = "wpa_supplicant";
+static const char SUPP_PROP_NAME[]      = "init.svc.wpa_supplicant";
+static const char SUPP_CONFIG_TEMPLATE[]= "/system/etc/wifi/wpa_supplicant.conf";
+static const char SUPP_CONFIG_FILE[]    = "/data/misc/wifi/wpa_supplicant.conf";
+static const char P2P_CONFIG_FILE[]     = "/data/misc/wifi/p2p_supplicant.conf";
+static const char CONTROL_IFACE_PATH[]  = "/data/misc/wifi";
+static const char MODULE_FILE[]         = "/proc/modules";
+
+static const char SUPP_ENTROPY_FILE[]   = WIFI_ENTROPY_FILE;
+static unsigned char dummy_key[21] = { 0x02, 0x11, 0xbe, 0x33, 0x43, 0x35,
+                                       0x68, 0x47, 0x84, 0x99, 0xa9, 0x2b,
+                                       0x1c, 0xd3, 0xee, 0xff, 0xf1, 0xe2,
+                                       0xf3, 0xf4, 0xf5 };
+
+static int insmod(const char *filename, const char *args)
+{
+    void *module;
+    unsigned int size;
+    int ret;
+
+    module = load_file(filename, &size);
+    if (!module)
+        return -1;
+
+    ret = init_module(module, size, args);
+
+    free(module);
+
+    return ret;
+}
+
+static int rmmod(const char *modname)
+{
+    int ret = -1;
+    int maxtry = 10;
+
+    while (maxtry-- > 0) {
+        ret = delete_module(modname, O_NONBLOCK | O_EXCL);
+        if (ret < 0 && errno == EAGAIN)
+            usleep(500000);
+        else
+            break;
+    }
+
+    if (ret != 0)
+        LOGD("Unable to unload driver module \"%s\": %s\n",
+             modname, strerror(errno));
+    return ret;
+}
+
+int do_dhcp_request(int *ipaddr, int *gateway, int *mask,
+                    int *dns1, int *dns2, int *server, int *lease) {
+    /* For test driver, always report success */
+    if (strcmp(iface, WIFI_TEST_INTERFACE) == 0)
+        return 0;
+
+    if (ifc_init() < 0)
+        return -1;
+
+    if (do_dhcp(iface) < 0) {
+        ifc_close();
+        return -1;
+    }
+    ifc_close();
+    get_dhcp_info(ipaddr, gateway, mask, dns1, dns2, server, lease);
+    return 0;
+}
+
+const char *get_dhcp_error_string() {
+    return dhcp_lasterror();
+}
+
+int is_wifi_driver_loaded() {
+    char driver_status[PROPERTY_VALUE_MAX];
+#ifdef WIFI_DRIVER_MODULE_PATH
+    FILE *proc;
+    char line[sizeof(DRIVER_MODULE_TAG)+10];
+#endif
+
+    if (!property_get(DRIVER_PROP_NAME, driver_status, NULL)
+            || strcmp(driver_status, "ok") != 0) {
+        return 0;  /* driver not loaded */
+    }
+#ifdef WIFI_DRIVER_MODULE_PATH
+    /*
+     * If the property says the driver is loaded, check to
+     * make sure that the property setting isn't just left
+     * over from a previous manual shutdown or a runtime
+     * crash.
+     */
+    if ((proc = fopen(MODULE_FILE, "r")) == NULL) {
+        LOGW("Could not open %s: %s", MODULE_FILE, strerror(errno));
+        property_set(DRIVER_PROP_NAME, "unloaded");
+        return 0;
+    }
+    while ((fgets(line, sizeof(line), proc)) != NULL) {
+        if (strncmp(line, DRIVER_MODULE_TAG, strlen(DRIVER_MODULE_TAG)) == 0) {
+            fclose(proc);
+            return 1;
+        }
+    }
+    fclose(proc);
+    property_set(DRIVER_PROP_NAME, "unloaded");
+    return 0;
+#else
+    return 1;
+#endif
+}
+
+int wifi_load_driver()
+{
+#ifdef WIFI_DRIVER_MODULE_PATH
+    char driver_status[PROPERTY_VALUE_MAX];
+    int count = 100; /* wait at most 20 seconds for completion */
+
+    if (is_wifi_driver_loaded()) {
+        return 0;
+    }
+
+    if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0)
+        return -1;
+
+    if (strcmp(FIRMWARE_LOADER,"") == 0) {
+        /* usleep(WIFI_DRIVER_LOADER_DELAY); */
+        property_set(DRIVER_PROP_NAME, "ok");
+    }
+    else {
+        property_set("ctl.start", FIRMWARE_LOADER);
+    }
+    sched_yield();
+    while (count-- > 0) {
+        if (property_get(DRIVER_PROP_NAME, driver_status, NULL)) {
+            if (strcmp(driver_status, "ok") == 0)
+                return 0;
+            else if (strcmp(DRIVER_PROP_NAME, "failed") == 0) {
+                wifi_unload_driver();
+                return -1;
+            }
+        }
+        usleep(200000);
+    }
+    property_set(DRIVER_PROP_NAME, "timeout");
+    wifi_unload_driver();
+    return -1;
+#else
+    property_set(DRIVER_PROP_NAME, "ok");
+    return 0;
+#endif
+}
+
+int wifi_unload_driver()
+{
+    usleep(200000); /* allow to finish interface down */
+#ifdef WIFI_DRIVER_MODULE_PATH
+    if (rmmod(DRIVER_MODULE_NAME) == 0) {
+        int count = 20; /* wait at most 10 seconds for completion */
+        while (count-- > 0) {
+            if (!is_wifi_driver_loaded())
+                break;
+            usleep(500000);
+        }
+        usleep(500000); /* allow card removal */
+        if (count) {
+            return 0;
+        }
+        return -1;
+    } else
+        return -1;
+#else
+    property_set(DRIVER_PROP_NAME, "unloaded");
+    return 0;
+#endif
+}
+
+int ensure_entropy_file_exists()
+{
+    int ret;
+    int destfd;
+
+    ret = access(SUPP_ENTROPY_FILE, R_OK|W_OK);
+    if ((ret == 0) || (errno == EACCES)) {
+        if ((ret != 0) &&
+            (chmod(SUPP_ENTROPY_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) != 0)) {
+            LOGE("Cannot set RW to \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno));
+            return -1;
+        }
+        return 0;
+    }
+    destfd = open(SUPP_ENTROPY_FILE, O_CREAT|O_RDWR, 0660);
+    if (destfd < 0) {
+        LOGE("Cannot create \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno));
+        return -1;
+    }
+
+    if (write(destfd, dummy_key, sizeof(dummy_key)) != sizeof(dummy_key)) {
+        LOGE("Error writing \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno));
+        close(destfd);
+        return -1;
+    }
+    close(destfd);
+
+    /* chmod is needed because open() didn't set permisions properly */
+    if (chmod(SUPP_ENTROPY_FILE, 0660) < 0) {
+        LOGE("Error changing permissions of %s to 0660: %s",
+             SUPP_ENTROPY_FILE, strerror(errno));
+        unlink(SUPP_ENTROPY_FILE);
+        return -1;
+    }
+
+    if (chown(SUPP_ENTROPY_FILE, AID_SYSTEM, AID_WIFI) < 0) {
+        LOGE("Error changing group ownership of %s to %d: %s",
+             SUPP_ENTROPY_FILE, AID_WIFI, strerror(errno));
+        unlink(SUPP_ENTROPY_FILE);
+        return -1;
+    }
+    return 0;
+}
+
+int update_ctrl_interface(const char *config_file) {
+
+    int srcfd, destfd;
+    int nread;
+    char ifc[PROPERTY_VALUE_MAX];
+    char *pbuf;
+    char *sptr;
+    struct stat sb;
+
+    if (stat(config_file, &sb) != 0)
+        return -1;
+
+    pbuf = malloc(sb.st_size + PROPERTY_VALUE_MAX);
+    if (!pbuf)
+        return 0;
+    srcfd = open(config_file, O_RDONLY);
+    if (srcfd < 0) {
+        LOGE("Cannot open \"%s\": %s", config_file, strerror(errno));
+        free(pbuf);
+        return 0;
+    }
+    nread = read(srcfd, pbuf, sb.st_size);
+    close(srcfd);
+    if (nread < 0) {
+        LOGE("Cannot read \"%s\": %s", config_file, strerror(errno));
+        free(pbuf);
+        return 0;
+    }
+
+    if (!strcmp(config_file, SUPP_CONFIG_FILE)) {
+        property_get("wifi.interface", ifc, WIFI_TEST_INTERFACE);
+    } else {
+        //strcpy(ifc, CONTROL_IFACE_PATH);
+        property_get("wifi.interface", ifc, WIFI_TEST_INTERFACE);
+    }
+    if ((sptr = strstr(pbuf, "ctrl_interface="))) {
+        char *iptr = sptr + strlen("ctrl_interface=");
+        int ilen = 0;
+        int mlen = strlen(ifc);
+        int nwrite;
+        if (strncmp(ifc, iptr, mlen) != 0) {
+            LOGE("ctrl_interface != %s", ifc);
+            while (((ilen + (iptr - pbuf)) < nread) && (iptr[ilen] != '\n'))
+                ilen++;
+            mlen = ((ilen >= mlen) ? ilen : mlen) + 1;
+            memmove(iptr + mlen, iptr + ilen + 1, nread - (iptr + ilen + 1 - pbuf));
+            memset(iptr, '\n', mlen);
+            memcpy(iptr, ifc, strlen(ifc));
+            destfd = open(config_file, O_RDWR, 0660);
+            if (destfd < 0) {
+                LOGE("Cannot update \"%s\": %s", config_file, strerror(errno));
+                free(pbuf);
+                return -1;
+            }
+            write(destfd, pbuf, nread + mlen - ilen -1);
+            close(destfd);
+        }
+    }
+    free(pbuf);
+    return 0;
+}
+
+int ensure_config_file_exists(const char *config_file)
+{
+    char buf[2048];
+    int srcfd, destfd;
+    struct stat sb;
+    int nread;
+    int ret;
+
+    ret = access(config_file, R_OK|W_OK);
+    if ((ret == 0) || (errno == EACCES)) {
+        if ((ret != 0) &&
+            (chmod(config_file, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) != 0)) {
+            LOGE("Cannot set RW to \"%s\": %s", config_file, strerror(errno));
+            return -1;
+        }
+        /* return if filesize is at least 10 bytes */
+        if (stat(config_file, &sb) == 0 && sb.st_size > 10) {
+            return update_ctrl_interface(config_file);
+        }
+    } else if (errno != ENOENT) {
+        LOGE("Cannot access \"%s\": %s", config_file, strerror(errno));
+        return -1;
+    }
+
+    srcfd = open(SUPP_CONFIG_TEMPLATE, O_RDONLY);
+    if (srcfd < 0) {
+        LOGE("Cannot open \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno));
+        return -1;
+    }
+
+    destfd = open(config_file, O_CREAT|O_RDWR, 0660);
+    if (destfd < 0) {
+        close(srcfd);
+        LOGE("Cannot create \"%s\": %s", config_file, strerror(errno));
+        return -1;
+    }
+
+    while ((nread = read(srcfd, buf, sizeof(buf))) != 0) {
+        if (nread < 0) {
+            LOGE("Error reading \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno));
+            close(srcfd);
+            close(destfd);
+            unlink(config_file);
+            return -1;
+        }
+        write(destfd, buf, nread);
+    }
+
+    close(destfd);
+    close(srcfd);
+
+    /* chmod is needed because open() didn't set permisions properly */
+    if (chmod(config_file, 0660) < 0) {
+        LOGE("Error changing permissions of %s to 0660: %s",
+             config_file, strerror(errno));
+        unlink(config_file);
+        return -1;
+    }
+
+    if (chown(config_file, AID_SYSTEM, AID_WIFI) < 0) {
+        LOGE("Error changing group ownership of %s to %d: %s",
+             config_file, AID_WIFI, strerror(errno));
+        unlink(config_file);
+        return -1;
+    }
+    return update_ctrl_interface(config_file);
+}
+
+/**
+ * wifi_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 wifi_wpa_ctrl_cleanup(void)
+{
+    DIR *dir;
+    struct dirent entry;
+    struct dirent *result;
+    size_t dirnamelen;
+    size_t maxcopy;
+    char pathname[PATH_MAX];
+    char *namep;
+    char *local_socket_dir = CONFIG_CTRL_IFACE_CLIENT_DIR;
+    char *local_socket_prefix = CONFIG_CTRL_IFACE_CLIENT_PREFIX;
+
+    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, strlen(local_socket_prefix)) == 0) {
+            if (strlcpy(namep, entry.d_name, maxcopy) < maxcopy) {
+                unlink(pathname);
+            }
+        }
+    }
+    closedir(dir);
+}
+
+int wifi_start_supplicant_common(const char *config_file)
+{
+    char daemon_cmd[PROPERTY_VALUE_MAX];
+    char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
+    int count = 200; /* wait at most 20 seconds for completion */
+#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
+    const prop_info *pi;
+    unsigned serial = 0;
+#endif
+
+    wifi_stop_supplicant();
+    wifi_close_supplicant_connection();
+
+    /* Check whether already running */
+    if (property_get(SUPP_PROP_NAME, supp_status, NULL)
+            && strcmp(supp_status, "running") == 0) {
+        return 0;
+    }
+
+    /* Before starting the daemon, make sure its config file exists */
+    if (ensure_config_file_exists(config_file) < 0) {
+        LOGE("Wi-Fi will not be enabled");
+        return -1;
+    }
+
+    if (ensure_entropy_file_exists() < 0) {
+        LOGE("Wi-Fi entropy file was not created");
+    }
+
+    /* Clear out any stale socket files that might be left over. */
+    wifi_wpa_ctrl_cleanup();
+
+#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
+    /*
+     * Get a reference to the status property, so we can distinguish
+     * the case where it goes stopped => running => stopped (i.e.,
+     * it start up, but fails right away) from the case in which
+     * it starts in the stopped state and never manages to start
+     * running at all.
+     */
+    pi = __system_property_find(SUPP_PROP_NAME);
+    if (pi != NULL) {
+        serial = pi->serial;
+    }
+#endif
+    property_get("wifi.interface", iface, WIFI_TEST_INTERFACE);
+    snprintf(daemon_cmd, PROPERTY_VALUE_MAX, "%s:-i%s -c%s", SUPPLICANT_NAME, iface, config_file);
+    property_set("ctl.start", daemon_cmd);
+    sched_yield();
+
+    while (count-- > 0) {
+#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
+        if (pi == NULL) {
+            pi = __system_property_find(SUPP_PROP_NAME);
+        }
+        if (pi != NULL) {
+            __system_property_read(pi, NULL, supp_status);
+            if (strcmp(supp_status, "running") == 0) {
+                return 0;
+            } else if (pi->serial != serial &&
+                    strcmp(supp_status, "stopped") == 0) {
+                return -1;
+            }
+        }
+#else
+        if (property_get(SUPP_PROP_NAME, supp_status, NULL)) {
+            if (strcmp(supp_status, "running") == 0)
+                return 0;
+        }
+#endif
+        usleep(100000);
+    }
+    return -1;
+}
+
+int wifi_start_supplicant()
+{
+    return wifi_start_supplicant_common(SUPP_CONFIG_FILE);
+}
+
+int wifi_start_p2p_supplicant()
+{
+    return wifi_start_supplicant_common(P2P_CONFIG_FILE);
+}
+
+int wifi_stop_supplicant()
+{
+    char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
+    int count = 50; /* wait at most 5 seconds for completion */
+
+    /* Check whether supplicant already stopped */
+    if (property_get(SUPP_PROP_NAME, supp_status, NULL)
+        && strcmp(supp_status, "stopped") == 0) {
+        return 0;
+    }
+
+    property_set("ctl.stop", SUPPLICANT_NAME);
+    sched_yield();
+
+    while (count-- > 0) {
+        if (property_get(SUPP_PROP_NAME, supp_status, NULL)) {
+            if (strcmp(supp_status, "stopped") == 0)
+                return 0;
+        }
+        usleep(100000);
+    }
+    return -1;
+}
+
+int wifi_connect_to_supplicant()
+{
+    char ifname[256];
+    char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
+
+    /* Make sure supplicant is running */
+    if (!property_get(SUPP_PROP_NAME, supp_status, NULL)
+            || strcmp(supp_status, "running") != 0) {
+        LOGE("Supplicant not running, cannot connect");
+        return -1;
+    }
+
+    //if (access(IFACE_DIR, F_OK) == 0) {
+    //    snprintf(ifname, sizeof(ifname), "%s/%s", IFACE_DIR, iface);
+    //} else {
+        strlcpy(ifname, iface, sizeof(ifname));
+    //}
+
+    ctrl_conn = wpa_ctrl_open(ifname);
+    if (ctrl_conn == NULL) {
+        LOGE("Unable to open connection to supplicant on \"%s\": %s",
+             ifname, strerror(errno));
+        return -1;
+    }
+    monitor_conn = wpa_ctrl_open(ifname);
+    if (monitor_conn == NULL) {
+        wpa_ctrl_close(ctrl_conn);
+        ctrl_conn = NULL;
+        return -1;
+    }
+    if (wpa_ctrl_attach(monitor_conn) != 0) {
+        wpa_ctrl_close(monitor_conn);
+        wpa_ctrl_close(ctrl_conn);
+        ctrl_conn = monitor_conn = NULL;
+        return -1;
+    }
+
+    if (socketpair(AF_UNIX, SOCK_STREAM, 0, exit_sockets) == -1) {
+        wpa_ctrl_close(monitor_conn);
+        wpa_ctrl_close(ctrl_conn);
+        ctrl_conn = monitor_conn = NULL;
+        return -1;
+    }
+
+    return 0;
+}
+
+int wifi_send_command(struct wpa_ctrl *ctrl, const char *cmd, char *reply, size_t *reply_len)
+{
+    int ret;
+
+    if (ctrl_conn == NULL) {
+        LOGV("Not connected to wpa_supplicant - \"%s\" command dropped.\n", cmd);
+        return -1;
+    }
+    ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), reply, reply_len, NULL);
+    if (ret == -2) {
+        LOGD("'%s' command timed out.\n", cmd);
+        /* unblocks the monitor receive socket for termination */
+        write(exit_sockets[0], "T", 1);
+        return -2;
+    } else if (ret < 0 || strncmp(reply, "FAIL", 4) == 0) {
+        return -1;
+    }
+    if (strncmp(cmd, "PING", 4) == 0) {
+        reply[*reply_len] = '\0';
+    }
+    return 0;
+}
+
+int wifi_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
+{
+    int res;
+    int ctrlfd = wpa_ctrl_get_fd(ctrl);
+    struct pollfd rfds[2];
+
+    memset(rfds, 0, 2 * sizeof(struct pollfd));
+    rfds[0].fd = ctrlfd;
+    rfds[0].events |= POLLIN;
+    rfds[1].fd = exit_sockets[1];
+    rfds[1].events |= POLLIN;
+    res = poll(rfds, 2, -1);
+    if (res < 0) {
+        LOGE("Error poll = %d", res);
+        return res;
+    }
+    if (rfds[0].revents & POLLIN) {
+        return wpa_ctrl_recv(ctrl, reply, reply_len);
+    } else {
+        LOGD("Received on exit socket, terminate");
+        return -1;
+    }
+    return 0;
+}
+
+int wifi_wait_for_event(char *buf, size_t buflen)
+{
+    size_t nread = buflen - 1;
+    int fd;
+    fd_set rfds;
+    int result;
+    struct timeval tval;
+    struct timeval *tptr;
+
+    if (monitor_conn == NULL) {
+        LOGD("Connection closed\n");
+        strncpy(buf, WPA_EVENT_TERMINATING " - connection closed", buflen-1);
+        buf[buflen-1] = '\0';
+        return strlen(buf);
+    }
+
+    result = wifi_ctrl_recv(monitor_conn, buf, &nread);
+    if (result < 0) {
+        LOGD("wifi_ctrl_recv failed: %s\n", strerror(errno));
+        strncpy(buf, WPA_EVENT_TERMINATING " - recv error", buflen-1);
+        buf[buflen-1] = '\0';
+        return strlen(buf);
+    }
+    buf[nread] = '\0';
+    /* LOGD("wait_for_event: result=%d nread=%d string=\"%s\"\n", result, nread, buf); */
+    /* Check for EOF on the socket */
+    if (result == 0 && nread == 0) {
+        /* Fabricate an event to pass up */
+        LOGD("Received EOF on supplicant socket\n");
+        strncpy(buf, WPA_EVENT_TERMINATING " - signal 0 received", buflen-1);
+        buf[buflen-1] = '\0';
+        return strlen(buf);
+    }
+    /*
+     * Events strings are in the format
+     *
+     *     <N>CTRL-EVENT-XXX 
+     *
+     * where N is the message level in numerical form (0=VERBOSE, 1=DEBUG,
+     * etc.) and XXX is the event name. The level information is not useful
+     * to us, so strip it off.
+     */
+    if (buf[0] == '<') {
+        char *match = strchr(buf, '>');
+        if (match != NULL) {
+            nread -= (match+1-buf);
+            memmove(buf, match+1, nread+1);
+        }
+    }
+    return nread;
+}
+
+void wifi_close_supplicant_connection()
+{
+    char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
+    int count = 50; /* wait at most 5 seconds to ensure init has stopped stupplicant */
+
+    if (ctrl_conn != NULL) {
+        wpa_ctrl_close(ctrl_conn);
+        ctrl_conn = NULL;
+    }
+    if (monitor_conn != NULL) {
+        wpa_ctrl_close(monitor_conn);
+        monitor_conn = NULL;
+    }
+
+    if (exit_sockets[0] >= 0) {
+        close(exit_sockets[0]);
+        exit_sockets[0] = -1;
+    }
+
+    if (exit_sockets[1] >= 0) {
+        close(exit_sockets[1]);
+        exit_sockets[1] = -1;
+    }
+
+    while (count-- > 0) {
+        if (property_get(SUPP_PROP_NAME, supp_status, NULL)) {
+            if (strcmp(supp_status, "stopped") == 0)
+                return;
+        }
+        usleep(100000);
+    }
+}
+
+int wifi_command(const char *command, char *reply, size_t *reply_len)
+{
+    return wifi_send_command(ctrl_conn, command, reply, reply_len);
+}
+
+const char *wifi_get_fw_path(int fw_type)
+{
+    switch (fw_type) {
+    case WIFI_GET_FW_PATH_STA:
+        return WIFI_DRIVER_FW_PATH_STA;
+    case WIFI_GET_FW_PATH_AP:
+        return WIFI_DRIVER_FW_PATH_AP;
+    case WIFI_GET_FW_PATH_P2P:
+        return WIFI_DRIVER_FW_PATH_P2P;
+    }
+    return NULL;
+}
+
+int wifi_change_fw_path(const char *fwpath)
+{
+    int len;
+    int fd;
+    int ret = 0;
+    static char previous_fwpath[4];
+
+//    if (!fwpath)
+//        return ret;
+
+    LOGE("%s: %s\n", __FUNCTION__, fwpath);
+    if(strncmp("P2P", fwpath, 3) == 0) {
+        ret = wifi_load_driver();
+    } else if(strncmp("P2P", previous_fwpath, 3) == 0) {
+        ret = wifi_unload_driver();
+    }
+
+    strncpy(previous_fwpath, fwpath, 3);
+
+#if 0
+    fd = open(WIFI_DRIVER_FW_PATH_PARAM, O_WRONLY);
+    if (fd < 0) {
+        LOGE("Failed to open wlan fw path param (%s)", strerror(errno));
+        return -1;
+    }
+    len = strlen(fwpath) + 1;
+    if (write(fd, fwpath, len) != len) {
+        LOGE("Failed to write wlan fw path param (%s)", strerror(errno));
+        ret = -1;
+    }
+    close(fd);
+#endif
+    return ret;
+}
diff --git a/wlan/wpa_supplicant_8_lib/Android.mk b/wlan/wpa_supplicant_8_lib/Android.mk
new file mode 100644 (file)
index 0000000..fe2114b
--- /dev/null
@@ -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.
+#
+LOCAL_PATH := $(call my-dir)
+
+ifeq ($(WPA_SUPPLICANT_VERSION),VER_0_8_X)
+
+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/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 := lib_driver_cmd_rtl
+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/wlan/wpa_supplicant_8_lib/MODULE_LICENSE_BSD b/wlan/wpa_supplicant_8_lib/MODULE_LICENSE_BSD
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/wlan/wpa_supplicant_8_lib/NOTICE b/wlan/wpa_supplicant_8_lib/NOTICE
new file mode 100644 (file)
index 0000000..f9d25ea
--- /dev/null
@@ -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/wlan/wpa_supplicant_8_lib/driver_cmd_common.h b/wlan/wpa_supplicant_8_lib/driver_cmd_common.h
new file mode 100644 (file)
index 0000000..03ce253
--- /dev/null
@@ -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/wlan/wpa_supplicant_8_lib/driver_cmd_nl80211.c b/wlan/wpa_supplicant_8_lib/driver_cmd_nl80211.c
new file mode 100644 (file)
index 0000000..fdaca25
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * 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;
+
+               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));
+               }
+       }
+       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/wlan/wpa_supplicant_8_lib/driver_cmd_wext.c b/wlan/wpa_supplicant_8_lib/driver_cmd_wext.c
new file mode 100644 (file)
index 0000000..32cffb0
--- /dev/null
@@ -0,0 +1,393 @@
+/*
+ * 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 "android_drv.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;
+       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) {
+               if (!drv->bgscan_enabled)
+                       wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (cscan): %d", ret);
+               else
+                       ret = 0;        /* Hide error in case of bg scan */
+       }
+       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++] = 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 + 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 > DRV_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_CMD, 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) {
+               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 > DRV_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_CMD) == 0) ||
+                   (os_strcasecmp(cmd, LINKSPEED_CMD) == 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;
+                       linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1);
+                       /* 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;
+}
+
+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/wlan/wpa_supplicant_8_lib/driver_cmd_wext.h b/wlan/wpa_supplicant_8_lib/driver_cmd_wext.h
new file mode 100644 (file)
index 0000000..1c6e8a1
--- /dev/null
@@ -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/wlan/wpa_supplicant_8_lib/driver_nl80211.h b/wlan/wpa_supplicant_8_lib/driver_nl80211.h
new file mode 100644 (file)
index 0000000..7d19995
--- /dev/null
@@ -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