From 19aee7b18c2ad8141ea38adba34816eae4d20948 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Sun, 30 Dec 2012 16:55:06 +0000 Subject: [PATCH] realtek: Initial commit Unchanged from the Hardkernel odroid U2's BSP --- wlan/Android.mk | 4 + wlan/config/Android.mk | 41 + wlan/config/android_dhcpcd.conf | 6 + wlan/libhardware_legacy/wifi/wifi_realtek.c | 823 ++++++++++++++++++ wlan/wpa_supplicant_8_lib/Android.mk | 65 ++ wlan/wpa_supplicant_8_lib/MODULE_LICENSE_BSD | 0 wlan/wpa_supplicant_8_lib/NOTICE | 43 + wlan/wpa_supplicant_8_lib/driver_cmd_common.h | 58 ++ .../wpa_supplicant_8_lib/driver_cmd_nl80211.c | 364 ++++++++ wlan/wpa_supplicant_8_lib/driver_cmd_wext.c | 393 +++++++++ wlan/wpa_supplicant_8_lib/driver_cmd_wext.h | 38 + wlan/wpa_supplicant_8_lib/driver_nl80211.h | 150 ++++ 12 files changed, 1985 insertions(+) create mode 100644 wlan/Android.mk create mode 100644 wlan/config/Android.mk create mode 100644 wlan/config/android_dhcpcd.conf create mode 100644 wlan/libhardware_legacy/wifi/wifi_realtek.c create mode 100644 wlan/wpa_supplicant_8_lib/Android.mk create mode 100644 wlan/wpa_supplicant_8_lib/MODULE_LICENSE_BSD create mode 100644 wlan/wpa_supplicant_8_lib/NOTICE create mode 100644 wlan/wpa_supplicant_8_lib/driver_cmd_common.h create mode 100644 wlan/wpa_supplicant_8_lib/driver_cmd_nl80211.c create mode 100644 wlan/wpa_supplicant_8_lib/driver_cmd_wext.c create mode 100644 wlan/wpa_supplicant_8_lib/driver_cmd_wext.h create mode 100644 wlan/wpa_supplicant_8_lib/driver_nl80211.h diff --git a/wlan/Android.mk b/wlan/Android.mk new file mode 100644 index 0000000..19a2227 --- /dev/null +++ b/wlan/Android.mk @@ -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 index 0000000..468945c --- /dev/null +++ b/wlan/config/Android.mk @@ -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 index 0000000..54006c7 --- /dev/null +++ b/wlan/config/android_dhcpcd.conf @@ -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 index 0000000..46037ed --- /dev/null +++ b/wlan/libhardware_legacy/wifi/wifi_realtek.c @@ -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 +#include +#include +#include +#include +#include +#include + +#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 +#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 + * + * 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 index 0000000..fe2114b --- /dev/null +++ b/wlan/wpa_supplicant_8_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. +# +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 index 0000000..e69de29 diff --git a/wlan/wpa_supplicant_8_lib/NOTICE b/wlan/wpa_supplicant_8_lib/NOTICE new file mode 100644 index 0000000..f9d25ea --- /dev/null +++ b/wlan/wpa_supplicant_8_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 + * Copyright (c) 2003-2004, Instant802 Networks, Inc. + * Copyright (c) 2005-2006, Devicescape Software, Inc. + * Copyright (c) 2007, Johannes Berg + * 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 index 0000000..03ce253 --- /dev/null +++ b/wlan/wpa_supplicant_8_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/wlan/wpa_supplicant_8_lib/driver_cmd_nl80211.c b/wlan/wpa_supplicant_8_lib/driver_cmd_nl80211.c new file mode 100644 index 0000000..fdaca25 --- /dev/null +++ b/wlan/wpa_supplicant_8_lib/driver_cmd_nl80211.c @@ -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 index 0000000..32cffb0 --- /dev/null +++ b/wlan/wpa_supplicant_8_lib/driver_cmd_wext.c @@ -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 +#include +#include + +#include +#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 index 0000000..1c6e8a1 --- /dev/null +++ b/wlan/wpa_supplicant_8_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/wlan/wpa_supplicant_8_lib/driver_nl80211.h b/wlan/wpa_supplicant_8_lib/driver_nl80211.h new file mode 100644 index 0000000..7d19995 --- /dev/null +++ b/wlan/wpa_supplicant_8_lib/driver_nl80211.h @@ -0,0 +1,150 @@ +/* + * Driver interaction with Linux nl80211/cfg80211 + * Copyright (c) 2002-2010, Jouni Malinen + * Copyright (c) 2003-2004, Instant802 Networks, Inc. + * Copyright (c) 2005-2006, Devicescape Software, Inc. + * Copyright (c) 2007, Johannes Berg + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 -- 2.20.1