Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

initialized

  • Loading branch information...
commit d705a55dd6a4ca5ce136667d744ecb9e7a4c8b95 0 parents
chengjie-he authored
4 wlan/Android.mk
@@ -0,0 +1,4 @@
+ifeq ($(BOARD_WIFI_VENDOR), realtek)
+ include $(call all-subdir-makefiles)
+endif
+
38 wlan/config/Android.mk
@@ -0,0 +1,38 @@
+#
+# 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 := wpa_supplicant.conf
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/wifi
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
+
+########################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := dhcpcd.conf
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/dhcpcd
+LOCAL_SRC_FILES := android_dhcpcd.conf
+include $(BUILD_PREBUILT)
+
+########################
6 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
4 wlan/config/wpa_supplicant.conf
@@ -0,0 +1,4 @@
+update_config=1
+#ctrl_interface=DIR=/data/misc/wifi/wpa_supplicant GROUP=wifi
+ctrl_interface=DIR=/data/misc/wifi/wpa_supplicant
+ap_scan=1
1,094 wlan/libhardware_legacy/wifi/wifi_realtek.c
@@ -0,0 +1,1094 @@
+/*
+ * 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 <sys/wait.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 int ifc_up(const char *name);
+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 g_ifname[PROPERTY_VALUE_MAX];
+// TODO: use new ANDROID_SOCKET mechanism, once support for multiple
+// sockets is in
+
+#define WIFI_DRIVER_IFNAME "wlan%d"
+#define WIFI_DRIVER_IFNAME_AP "wlap%d"
+#define WIFI_DRIVER_IFNAME_DISABLE "disable%d"
+
+#ifndef WIFI_DRIVER_MODULE_ARG
+#define WIFI_DRIVER_MODULE_ARG ""
+#endif
+#ifndef WIFI_DRIVER_MODULE_ARG_AP
+#define WIFI_DRIVER_MODULE_ARG_AP "ifname=" WIFI_DRIVER_IFNAME_AP
+#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
+
+#ifndef WIFI_DRIVER_FW_PATH_PARAM
+#define WIFI_DRIVER_FW_PATH_PARAM "/sys/module/wlan/parameters/fwpath"
+#endif
+
+#define WIFI_DRIVER_LOADER_DELAY 1000000
+
+#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;
+static const char DRIVER_MODULE_ARG_AP[] = WIFI_DRIVER_MODULE_ARG_AP;
+#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_CTRL_DIR[] = "/data/misc/wifi/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 };
+
+//realtek
+int detect_wifi_ifname_from_proc()
+{
+ char linebuf[1024];
+ FILE *f = fopen("/proc/net/wireless", "r");
+
+ g_ifname[0] = '\0';
+ if (f) {
+ while(fgets(linebuf, sizeof(linebuf)-1, f)) {
+
+ if (strchr(linebuf, ':')) {
+ char *dest = g_ifname;
+ char *p = linebuf;
+
+ while(*p && (*p==' ' ||*p=='\t'))
+ ++p;
+ while (*p && *p != ':') {
+ *dest++ = *p++;
+ }
+ *dest = '\0';
+ //LOGD("DetectWifiIfNameFromProc: %s\n", g_ifname);
+ fclose(f);
+ return 0;
+ }
+ }
+ fclose(f);
+ }
+ return -1;
+}
+
+
+char *get_wifi_ifname()
+{
+ detect_wifi_ifname_from_proc();
+ return g_ifname;
+}
+
+#include <linux/wireless.h>
+int get_priv_func_num(int sockfd, const char *ifname, const char *fname)
+{
+ struct iwreq wrq;
+ struct iw_priv_args *priv_ptr;
+ int i, ret;
+ char *buf;
+
+ if( NULL == (buf=(char *)malloc(4096)) ) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ strncpy(wrq.ifr_name, ifname, sizeof(wrq.ifr_name));
+ wrq.u.data.pointer = buf;
+ wrq.u.data.length = 4096 / sizeof(struct iw_priv_args);
+ wrq.u.data.flags = 0;
+ if ((ret = ioctl(sockfd, SIOCGIWPRIV, &wrq)) < 0) {
+ LOGE("SIOCGIPRIV failed: %d %s", ret, strerror(errno));
+ goto exit;
+ }
+
+ ret = -EOPNOTSUPP;
+ priv_ptr = (struct iw_priv_args *)wrq.u.data.pointer;
+ for(i=0;(i < wrq.u.data.length);i++) {
+ if (strcmp(priv_ptr[i].name, fname) == 0) {
+ ret = priv_ptr[i].cmd;
+ break;
+ }
+ }
+
+exit:
+ if(buf)
+ free(buf);
+
+ return ret;
+}
+
+int rtl871x_drv_rereg_nd_name_fd(int sockfd, const char *ifname, const char * new_ifname)
+{
+ struct iwreq wrq;
+ int ret;
+
+ int fnum;
+ char *fname = "rereg_nd_name";
+
+ char ifname_buf[IFNAMSIZ];
+
+ ret = fnum = get_priv_func_num(sockfd, ifname, fname);
+ if(ret < 0) {
+ LOGE("get_priv_func_num(%s) return %d", fname, ret);
+ goto exit;
+ }
+
+ strncpy(wrq.ifr_name, ifname, sizeof(wrq.ifr_name));
+
+ strncpy(ifname_buf, new_ifname, IFNAMSIZ);
+ ifname_buf[IFNAMSIZ-1] = 0;
+ wrq.u.data.pointer = ifname_buf;
+ wrq.u.data.length = strlen(ifname_buf)+1;
+ wrq.u.data.flags = 0;
+
+ ret = ioctl(sockfd, fnum, &wrq);
+ if (ret) {
+ LOGE("ioctl - failed: %d %s", ret, strerror(errno));
+ }
+exit:
+ return ret;
+}
+
+int rtl871x_drv_rereg_nd_name(const char *ifname, const char *new_ifname)
+{
+ int sockfd;
+ int ret;
+
+ sockfd = socket(PF_INET, SOCK_DGRAM, 0);
+ if (sockfd< 0) {
+ perror("socket[PF_INET,SOCK_DGRAM]");
+ ret = -1;
+ goto bad;
+ }
+
+ ret = rtl871x_drv_rereg_nd_name_fd(
+ sockfd
+ , ifname
+ , new_ifname
+ );
+
+ close(sockfd);
+bad:
+ return ret;
+}
+
+int rtl871x_drv_set_pid_fd(int sockfd, const char *ifname, const int index, const int pid)
+{
+ struct iwreq wrq;
+ int ret;
+ int fnum;
+ char *fname = "setpid";
+
+ int req[2];
+
+ ret = fnum = get_priv_func_num(sockfd, ifname, fname);
+ if(ret < 0) {
+ LOGE("get_priv_func_num(%s) return %d", fname, ret);
+ goto exit;
+ }
+
+ strncpy(wrq.ifr_name, ifname, sizeof(wrq.ifr_name));
+
+ req[0]=index;
+ req[1]=pid;
+ memcpy(wrq.u.name,req,sizeof(int)*2);
+
+ ret = ioctl(sockfd, fnum, &wrq);
+ if (ret) {
+ LOGE("ioctl - failed: %d %s", ret, strerror(errno));
+ }
+exit:
+ return ret;
+}
+
+int rtl871x_drv_set_pid(const char *ifname, const int index, const int pid)
+{
+ int sockfd;
+ int ret;
+
+ sockfd = socket(PF_INET, SOCK_DGRAM, 0);
+ if (sockfd< 0) {
+ perror("socket[PF_INET,SOCK_DGRAM]");
+ ret = -1;
+ goto bad;
+ }
+
+ ret = rtl871x_drv_set_pid_fd(
+ sockfd
+ , ifname
+ , index
+ , pid
+ );
+
+ close(sockfd);
+bad:
+ return ret;
+}
+//realtek
+
+static int insmod(const char *filename, const char *args)
+{
+ void *module;
+ unsigned int size;
+ int ret;
+
+ module = load_file(filename, &size);
+ if (!module) {
+ LOGE("load_file(%s) failed: %s", filename, strerror(errno));
+ 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)
+ LOGE("Unable to unload driver module \"%s\": %s\n",
+ modname, strerror(errno));
+
+ if(errno == ENOENT)
+ ret=0;
+
+ 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(get_wifi_ifname(), WIFI_TEST_INTERFACE) == 0)
+ return 0;
+
+ if (ifc_init() < 0)
+ return -1;
+
+ if (do_dhcp(get_wifi_ifname()) < 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
+}
+
+static int load_driver(const char *module_path, const char *module_arg)
+{
+ pid_t pid;
+
+ if (insmod(module_path, module_arg)!=0) {
+ LOGE("insmod(%s, %s): %s\n", module_path, module_arg, strerror(errno));
+ goto err_exit;
+ }
+ LOGE("insmod(%s, %s): success\n", module_path, module_arg);
+
+ pid = vfork();
+ if (pid!=0) {
+
+ int ret;
+ int status;
+ int cnt = 10;
+
+ while ( (ret=waitpid(pid, &status, WNOHANG)) == 0 && cnt-- > 0 ) {
+ usleep(200000);
+ }
+
+ LOGE("waitpid finished ret %d\n", ret);
+ if (ret>0) {
+ if (WIFEXITED(status)) {
+ LOGE("child process exited normally, with exit code %d\n", WEXITSTATUS(status));
+ } else {
+ LOGE("child process exited abnormally\n");
+ goto err_exit;
+ }
+ return 0;
+ }
+ goto err_exit;
+
+ } else {
+ char local_ifname[PROPERTY_VALUE_MAX];
+
+ if(*get_wifi_ifname() == '\0') {
+ LOGE("load_driver: get_wifi_ifname fail");
+ _exit(-1);
+ }
+
+ strncpy(local_ifname, get_wifi_ifname(),PROPERTY_VALUE_MAX);
+ local_ifname[PROPERTY_VALUE_MAX-1]=0;
+
+
+ //do ifup here, and let parent to monitor the result...
+ if (strcmp(local_ifname, WIFI_TEST_INTERFACE) == 0)
+ _exit(0);
+
+ if (ifc_init() < 0)
+ _exit(-1);
+
+ if (ifc_up(local_ifname)) {
+ LOGE("failed to bring up interface %s: %s\n", local_ifname, strerror(errno));
+ _exit(-1);
+ }
+ ifc_close();
+ _exit(0);
+ }
+
+err_exit:
+ return -1;
+}
+
+int wifi_load_ap_driver()
+{
+ pid_t pid;
+#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()) {
+ if(*get_wifi_ifname() == '\0') {
+ LOGD("wifi_load_ap_driver: get_wifi_ifname fail");
+ return -1;
+ }
+ rtl871x_drv_rereg_nd_name(get_wifi_ifname(), WIFI_DRIVER_IFNAME_AP);
+ return 0;
+ }
+
+ if (load_driver(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG_AP) == 0) {
+ property_set(DRIVER_PROP_NAME, "ok");
+ return 0;
+ }
+
+ property_set(DRIVER_PROP_NAME, "timeout");
+ wifi_unload_driver();
+ return -1;
+#else
+ rtl871x_drv_rereg_nd_name(get_wifi_ifname(), WIFI_DRIVER_IFNAME_AP);
+ property_set(DRIVER_PROP_NAME, "ok");
+ return 0;
+#endif
+}
+
+int wifi_load_driver()
+{
+ pid_t pid;
+#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()) {
+ if(*get_wifi_ifname() == '\0') {
+ LOGD("wifi_load_ap_driver: get_wifi_ifname fail");
+ return -1;
+ }
+ rtl871x_drv_rereg_nd_name(get_wifi_ifname(), WIFI_DRIVER_IFNAME_AP);
+ return 0;
+ }
+
+ if (load_driver(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) == 0) {
+ property_set(DRIVER_PROP_NAME, "ok");
+ return 0;
+ }
+
+ property_set(DRIVER_PROP_NAME, "timeout");
+ wifi_unload_driver();
+ return -1;
+#else
+ rtl871x_drv_rereg_nd_name(get_wifi_ifname(), WIFI_DRIVER_IFNAME);
+ 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;
+
+ return 0;
+
+ 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, get_wifi_ifname());
+ } else {
+ strcpy(ifc, CONTROL_IFACE_PATH);
+ }
+ 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
+
+ /* 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
+ snprintf(daemon_cmd, PROPERTY_VALUE_MAX, "%s:-i%s -c%s", SUPPLICANT_NAME, get_wifi_ifname(), 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 ctrl_conn_path[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(*get_wifi_ifname() == '\0') {
+ LOGE("%s: get_wifi_ifname fail", __FUNCTION__);
+ return -1;
+ }
+
+ if (access(SUPP_CTRL_DIR, F_OK) == 0) {
+ snprintf(ctrl_conn_path, sizeof(ctrl_conn_path), "%s/%s", SUPP_CTRL_DIR, get_wifi_ifname());
+ } else {
+ strlcpy(ctrl_conn_path, get_wifi_ifname(), sizeof(ctrl_conn_path));
+ }
+
+ ctrl_conn = wpa_ctrl_open(ctrl_conn_path);
+ if (ctrl_conn == NULL) {
+ LOGE("Unable to open connection to supplicant on \"%s\": %s",
+ ctrl_conn_path, strerror(errno));
+ return -1;
+ }
+ monitor_conn = wpa_ctrl_open(ctrl_conn_path);
+ 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;
+
+ if (!fwpath)
+ return ret;
+ 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);
+ return ret;
+}
613 wlan/netd/SoftapController_realtek.cpp
@@ -0,0 +1,613 @@
+/*
+ * 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.
+ */
+/*
+ * [WIFI] Enable Wi-Fi Support, Please reference [PROJECT]/device/$(OEM)/$(TARGET_DEVICE)/BoardConfig.mk
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <linux/wireless.h>
+
+#include <openssl/evp.h>
+#include <openssl/sha.h>
+
+#define LOG_TAG "SoftapController"
+#include <cutils/log.h>
+
+#include "SoftapController.h"
+
+
+//#define CONFIG_DAEMON_CMD_WITH_PARA
+#define CONFIG_WLAN_RTK_WIFI_HOSTAPD
+#ifdef CONFIG_WLAN_RTK_WIFI_HOSTAPD /* [WIFI] Wi-Fi Support ++ */
+
+//#define START_HOSTAPD_INSIDE
+
+#include <ctype.h>
+#include "private/android_filesystem_config.h"
+#include "cutils/properties.h"
+#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#endif
+
+#include <sys/_system_properties.h>
+#include <libhostapd_client/wpa_ctrl.h>
+
+extern "C" int wifi_load_ap_driver();
+extern "C" int ensure_config_file_exists(const char *conf_file, const char *tmplate);
+extern "C" char *get_wifi_ifname();
+
+static const char HOSTAPD_NAME[] = "hostapd";
+static const char HOSTAPD_PROP_NAME[] = "init.svc.hostapd";
+static const char HOSTAPD_CTRL_DIR[] = "/data/misc/wifi/hostapd";
+static const char HOSTAPD_CONFIG_TEMPLATE[] = "/system/etc/wifi/hostapd.conf";
+static const char HOSTAPD_CONFIG_FILE[] = "/data/misc/wifi/hostapd.conf";
+
+#define WIFI_DEFAULT_BI 100 /* in TU */
+#define WIFI_DEFAULT_DTIM 1 /* in beacon */
+#define WIFI_DEFAULT_CHANNEL 6
+#define WIFI_DEFAULT_MAX_STA 8
+#define WIFI_DEFAULT_PREAMBLE 0
+
+static struct wpa_ctrl *ctrl_conn;
+
+int mProfileValid;
+
+static int set_hostapd_config_file(const char *conf_file, int argc, char *argv[])
+{
+ int fd;
+ char buf[80];
+ int len;
+
+ fd = open(conf_file, O_CREAT|O_WRONLY|O_TRUNC, 0660);
+ if (fd < 0) {
+ LOGE("Cannot create \"%s\": %s", conf_file, strerror(errno));
+ return -1;
+ }
+
+ if(*get_wifi_ifname() == '\0') {
+ LOGD("set_hostapd_config_file: get_wifi_ifname fail");
+ return -1;
+ }
+
+ //len = snprintf(buf, sizeof(buf), "interface=%s\n",argv[3]);
+ len = snprintf(buf, sizeof(buf), "interface=%s\n", get_wifi_ifname());
+ write(fd, buf, len);
+ len = snprintf(buf, sizeof(buf), "ctrl_interface=%s\n", HOSTAPD_CTRL_DIR);
+ write(fd, buf, len);
+
+ /* for CU-series flag */
+ len = snprintf(buf, sizeof(buf), "driver=rtl871xdrv\n");
+ write(fd, buf, len);
+ len = snprintf(buf, sizeof(buf), "wme_enabled=1\n");
+ write(fd, buf, len);
+ len = snprintf(buf, sizeof(buf), "hw_mode=g\n");
+ write(fd, buf, len);
+ len = snprintf(buf, sizeof(buf), "ieee80211n=1\n");
+ write(fd, buf, len);
+ len = snprintf(buf, sizeof(buf), "ht_capab=[SHORT-GI-20][SHORT-GI-40]\n");
+ write(fd, buf, len);
+
+ if (argc > 4) {
+ len = snprintf(buf, sizeof(buf), "ssid=%s\n",argv[4]);
+ } else {
+ len = snprintf(buf, sizeof(buf), "ssid=AndroidAP\n");
+ }
+
+ /* set open auth */
+ write(fd, buf, len);
+ len = snprintf(buf, sizeof(buf), "auth_algs=1\n");
+ write(fd, buf, len);
+ len = snprintf(buf, sizeof(buf), "max_num_sta=%d\n", WIFI_DEFAULT_MAX_STA);
+ write(fd, buf, len);
+ len = snprintf(buf, sizeof(buf), "beacon_int=%d\n", WIFI_DEFAULT_BI);
+ write(fd, buf, len);
+ len = snprintf(buf, sizeof(buf), "dtim_period=%d\n", WIFI_DEFAULT_DTIM);
+ write(fd, buf, len);
+
+ if (argc > 5) {
+ if (strncmp(argv[5], "wpa2-psk", 8) == 0) {
+ len = snprintf(buf, sizeof(buf), "wpa=2\n");
+ write(fd, buf, len);
+ len = snprintf(buf, sizeof(buf), "wpa_key_mgmt=WPA-PSK\n");
+ write(fd, buf, len);
+ len = snprintf(buf, sizeof(buf), "wpa_pairwise=CCMP\n");
+ write(fd, buf, len);
+
+ if (argc > 6) {
+ len = snprintf(buf, sizeof(buf), "wpa_passphrase=%s\n",argv[6]);
+ write(fd, buf, len);
+ } else {
+ len = snprintf(buf, sizeof(buf), "wpa_passphrase=12345678\n");
+ write(fd, buf, len);
+ }
+ }
+ }
+
+ if (argc > 7) {
+ len = snprintf(buf, sizeof(buf), "channel=%s\n",argv[7]);
+ write(fd, buf, len);
+ } else {
+ len = snprintf(buf, sizeof(buf), "channel=%d\n",WIFI_DEFAULT_CHANNEL);
+ write(fd, buf, len);
+ }
+
+ if (argc > 8) {
+ len = snprintf(buf, sizeof(buf), "preamble=%s\n",argv[8]);
+ write(fd, buf, len);
+ } else {
+ len = snprintf(buf, sizeof(buf), "preamble=%d\n",WIFI_DEFAULT_PREAMBLE);
+ write(fd, buf, len);
+ }
+
+ mProfileValid = 1;
+ close(fd);
+
+ return 0;
+}
+
+static int wifi_start_hostapd()
+{
+ char daemon_cmd[PROPERTY_VALUE_MAX];
+ char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
+ int count = 200; /* wait at most 20 seconds for completion */
+ char mac_buff[15] = {'\0'};
+#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
+ const prop_info *pi;
+ unsigned serial = 0;
+#endif
+
+ LOGD("SoftapController::wifi_start_hostapd");
+
+ /* Check whether already running */
+ if (property_get(HOSTAPD_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(HOSTAPD_CONFIG_FILE, HOSTAPD_CONFIG_TEMPLATE) < 0) {
+ LOGE("configuration file missing");
+ return -1;
+ }
+
+ /* Clear out any stale socket files that might be left over. */
+ 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(HOSTAPD_PROP_NAME);
+ if (pi != NULL) {
+ serial = pi->serial;
+ }
+#endif
+
+ #ifdef CONFIG_DAEMON_CMD_WITH_PARA
+ snprintf(daemon_cmd, PROPERTY_VALUE_MAX, "%s:%s", HOSTAPD_NAME, HOSTAPD_CONFIG_FILE);
+ #else
+ snprintf(daemon_cmd, PROPERTY_VALUE_MAX, "%s", HOSTAPD_NAME);
+ #endif
+
+ property_set("ctl.start", daemon_cmd);
+ LOGD("hostapd daemon_cmd = %s\n", daemon_cmd);
+ sched_yield();
+
+ while (count-- > 0) {
+#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
+ if (pi == NULL) {
+ pi = __system_property_find(HOSTAPD_PROP_NAME);
+ }
+ if (pi != NULL) {
+ __system_property_read(pi, NULL, supp_status);
+ if (strcmp(supp_status, "running") == 0) {
+ LOGD("hostapd running 1");
+ return 0;
+ } else if (pi->serial != serial && strcmp(supp_status, "stopped") == 0) {
+ LOGI("wifi_start_supplicant stopped pi->serial %u serial %u leave", pi->serial, serial);
+ if (serial==0) { /* no initialized, skip it */
+ serial = pi->serial;
+ } else {
+ LOGE("HAVE_LIBC_SYSTEM_PROPERTIES: return -1");
+ return -1;
+ }
+ }
+ }
+#else
+ if (property_get(HOSTAPD_PROP_NAME, supp_status, NULL)) {
+ if (strcmp(supp_status, "running") == 0) {
+ LOGD("hostapd running 2");
+ return 0;
+ }
+ }
+#endif
+ usleep(100000);
+ }
+ LOGI("wifi_start_hostapd is NOT running. timeout. leave" );
+ return -1;
+}
+
+static int wifi_stop_hostapd()
+{
+ char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
+ int count = 50; /* wait at most 5 seconds for completion */
+
+ /* Check whether hostapd already stopped */
+ if (property_get(HOSTAPD_PROP_NAME, supp_status, NULL)
+ && strcmp(supp_status, "stopped") == 0) {
+ return 0;
+ }
+
+ property_set("ctl.stop", HOSTAPD_NAME);
+ sched_yield();
+
+ while (count-- > 0) {
+ if (property_get(HOSTAPD_PROP_NAME, supp_status, NULL)) {
+ if (strcmp(supp_status, "stopped") == 0)
+ return 0;
+ }
+ usleep(100000);
+ }
+ return -1;
+}
+
+static int wifi_connect_to_hostapd()
+{
+ char defIfname[256];
+ char ctrl_conn_path[256];
+ char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
+ int retry_times = 20;
+
+ /* Make sure hostapd is running */
+ #ifdef START_HOSTAPD_INSIDE
+ if (hostapdPid == 0) {
+ #else
+ if (!property_get(HOSTAPD_PROP_NAME, supp_status, NULL)
+ || strcmp(supp_status, "running") != 0) {
+ #endif
+ LOGE("hostapd not running, cannot connect");
+ return -1;
+ }
+
+ if(*get_wifi_ifname() == '\0') {
+ LOGD("wifi_connect_to_hostapd: getWifiIfname fail");
+ return -1;
+ }
+
+ snprintf(ctrl_conn_path, sizeof(ctrl_conn_path), "%s/%s", HOSTAPD_CTRL_DIR, get_wifi_ifname());
+ LOGD("ctrl_conn_path = %s\n", ctrl_conn_path);
+
+
+ { /* check iface file is ready */
+ int cnt = 160; /* 8 seconds (160*50)*/
+ sched_yield();
+ while ( access(ctrl_conn_path, F_OK|W_OK)!=0 && cnt-- > 0) {
+ usleep(50000);
+ }
+ if (access(ctrl_conn_path, F_OK|W_OK)==0) {
+ LOGD("ctrl_conn_path %s is ready to read/write cnt=%d\n", ctrl_conn_path, cnt);
+ } else {
+ LOGD("ctrl_conn_path %s is not ready, cnt=%d\n", ctrl_conn_path, cnt);
+ }
+ }
+
+ while (retry_times--){
+ ctrl_conn = wpa_ctrl_open(ctrl_conn_path);
+ if (NULL == ctrl_conn) {
+ usleep(1000 * 500);
+ LOGD("Retry to wpa_ctrl_open \n");
+ } else {
+ break;
+ }
+ }
+
+ if (NULL == ctrl_conn) {
+ LOGE("Unable to open connection to supplicant on \"%s\": %s",
+ ctrl_conn_path, strerror(errno));
+ return -1;
+ }
+
+ if (wpa_ctrl_attach(ctrl_conn) != 0) {
+ wpa_ctrl_close(ctrl_conn);
+ ctrl_conn = NULL;
+ return -1;
+ }
+ return 0;
+}
+
+static void wifi_close_hostapd_connection()
+{
+ if (ctrl_conn != NULL) {
+ wpa_ctrl_close(ctrl_conn);
+ ctrl_conn = NULL;
+ }
+}
+
+static int wifi_load_profile(bool started)
+{
+ if ((started) && (mProfileValid)) {
+ if (ctrl_conn == NULL) {
+ LOGE("wifi_load_profile(): ctrl_conn == NULL");
+ return -1;
+ } else {
+ LOGE("wpa_ctrl_reload(ctrl_conn)...");
+ return wpa_ctrl_reload(ctrl_conn);
+ }
+ }
+ return 0;
+}
+
+#endif /* CONFIG_WLAN_RTK_WIFI_HOSTAPD [WIFI] Wi-Fi Support -- */
+
+
+SoftapController::SoftapController() {
+ mPid = 0;
+ mSock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (mSock < 0)
+ LOGE("Failed to open socket");
+
+ memset(mIface, 0, sizeof(mIface));
+
+#ifdef CONFIG_WLAN_RTK_WIFI_HOSTAPD /* [WIFI] Wi-Fi Support ++ */
+ mProfileValid = 0;
+ ctrl_conn = NULL;
+#endif /* CONFIG_WLAN_RTK_WIFI_HOSTAPD [WIFI] Wi-Fi Support -- */
+}
+
+SoftapController::~SoftapController() {
+ if (mSock >= 0)
+ close(mSock);
+}
+
+int SoftapController::startDriver(char *iface) {
+ int ret = 0;
+ LOGD("SoftapController::startDriver");
+ if (mSock < 0) {
+ LOGE("Softap driver start - failed to open socket");
+ return -1;
+ }
+ if (!iface || (iface[0] == '\0')) {
+ LOGD("Softap driver start - wrong interface");
+ iface = mIface;
+ }
+
+ ret = wifi_load_ap_driver();
+
+ LOGD("Softap driver start: %d", ret);
+
+ return ret;
+}
+
+int SoftapController::stopDriver(char *iface) {
+ int ret = 0;
+ LOGE("SoftapController::stopDriver");
+
+ if (mSock < 0) {
+ LOGE("Softap driver stop - failed to open socket");
+ return -1;
+ }
+ if (!iface || (iface[0] == '\0')) {
+ LOGD("Softap driver stop - wrong interface");
+ iface = mIface;
+ }
+
+ LOGD("Softap driver stop: %d", ret);
+ return ret;
+}
+
+int SoftapController::startSoftap() {
+ struct iwreq wrq;
+ pid_t pid = 1;
+ int fnum, ret = 0;
+
+ LOGD("SoftapController::startSoftap");
+
+ if (mPid) {
+ LOGE("Softap already started");
+ return 0;
+ }
+
+ if (mSock < 0) {
+ LOGE("Softap startap - failed to open socket");
+ return -1;
+ }
+
+ if ((ret = wifi_start_hostapd()) < 0) {
+ LOGE("Softap startap - starting hostapd fails");
+ return -1;
+ }
+
+ if ((ret = wifi_connect_to_hostapd()) < 0) {
+ LOGE("Softap startap - connect to hostapd fails");
+ return -1;
+ }
+
+ if ((ret = wifi_load_profile(true)) < 0) {
+ LOGE("Softap startap - load new configuration fails");
+ return -1;
+ }
+
+ if (ret) {
+ LOGE("Softap startap - failed: %d", ret);
+ }
+ else {
+ mPid = pid;
+ LOGD("Softap startap - Ok");
+ //usleep(AP_BSS_START_DELAY);
+ }
+ return ret;
+
+}
+
+int SoftapController::stopSoftap() {
+ struct iwreq wrq;
+ int fnum, ret;
+
+ LOGD("softapcontroller->stopSoftap");
+
+ if (mPid == 0) {
+ LOGE("Softap already stopped");
+ return 0;
+ }
+ if (mSock < 0) {
+ LOGE("Softap stopap - failed to open socket");
+ return -1;
+ }
+
+ wifi_close_hostapd_connection();
+ ret = wifi_stop_hostapd();
+
+ mPid = 0;
+ LOGD("Softap service stopped: %d", ret);
+ //usleep(AP_BSS_STOP_DELAY);
+
+ return ret;
+}
+
+bool SoftapController::isSoftapStarted() {
+ return (mPid != 0 ? true : false);
+}
+
+int SoftapController::addParam(int pos, const char *cmd, const char *arg)
+{
+ if (pos < 0)
+ return pos;
+ if ((unsigned)(pos + strlen(cmd) + strlen(arg) + 1) >= sizeof(mBuf)) {
+ LOGE("Command line is too big");
+ return -1;
+ }
+ pos += sprintf(&mBuf[pos], "%s=%s,", cmd, arg);
+ return pos;
+}
+
+/*
+ * Arguments:
+ * argv[2] - wlan interface
+ * argv[3] - softap interface
+ * argv[4] - SSID
+ * argv[5] - Security
+ * argv[6] - Key
+ * argv[7] - Channel
+ * argv[8] - Preamble
+ * argv[9] - Max SCB
+ */
+int SoftapController::setSoftap(int argc, char *argv[]) {
+ unsigned char psk[SHA256_DIGEST_LENGTH];
+ char psk_str[2*SHA256_DIGEST_LENGTH+1];
+ struct iwreq wrq;
+ int fnum, ret, i = 0;
+ char *ssid;
+
+ if (mSock < 0) {
+ LOGE("Softap set - failed to open socket");
+ return -1;
+ }
+ if (argc < 4) {
+ LOGE("Softap set - missing arguments");
+ return -1;
+ }
+
+ if ((ret = set_hostapd_config_file(HOSTAPD_CONFIG_FILE, argc, argv)) < 0) {
+ LOGE("Softap set - set_hostapd_config_file fails");
+ return -1;
+ }
+
+ if ((ret = wifi_load_profile(isSoftapStarted())) < 0) {
+ LOGE("Softap set - load new configuration fails");
+ return -1;
+ }
+
+ if (ret) {
+ LOGE("Softap set - failed: %d", ret);
+ } else {
+ LOGD("Softap set - Ok");
+ //usleep(AP_SET_CFG_DELAY);
+ }
+ return ret;
+}
+
+/*
+ * Arguments:
+ * argv[2] - interface name
+ * argv[3] - AP or STA
+ */
+int SoftapController::fwReloadSoftap(int argc, char *argv[])
+{
+ struct iwreq wrq;
+ int fnum, ret, i = 0;
+ char *iface;
+
+ if (mSock < 0) {
+ LOGE("Softap fwrealod - failed to open socket");
+ return -1;
+ }
+ if (argc < 4) {
+ LOGE("Softap fwreload - missing arguments");
+ return -1;
+ }
+
+ ret = 0;
+
+ if (ret) {
+ LOGE("Softap fwReload - failed: %d", ret);
+ }
+ else {
+ LOGD("Softap fwReload - Ok");
+ }
+ return ret;
+}
+
+void SoftapController::generatePsk(char *ssid, char *passphrase, char *psk_str) {
+}
+
+int SoftapController::setCommand(char *iface, const char *fname, unsigned buflen) {
+ return 0;
+}
+
+int SoftapController::clientsSoftap(char **retbuf)
+{
+ int ret;
+
+ if (mSock < 0) {
+ LOGE("Softap clients - failed to open socket");
+ return -1;
+ }
+ *mBuf = 0;
+ ret = setCommand(mIface, "AP_GET_STA_LIST", SOFTAP_MAX_BUFFER_SIZE);
+ if (ret) {
+ LOGE("Softap clients - failed: %d", ret);
+ } else {
+ asprintf(retbuf, "Softap clients:%s", mBuf);
+ LOGD("Softap clients:%s", mBuf);
+ }
+ return ret;
+}
+
55 wlan/wpa_supplicant_8_lib/Android.mk
@@ -0,0 +1,55 @@
+#
+# 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
+
+include $(WPA_SUPPL_DIR)/wpa_supplicant/.config
+
+WPA_SUPPL_DIR_INCLUDE = $(WPA_SUPPL_DIR)/src \
+ $(WPA_SUPPL_DIR)/src/common \
+ $(WPA_SUPPL_DIR)/src/drivers \
+ $(WPA_SUPPL_DIR)/src/l2_packet \
+ $(WPA_SUPPL_DIR)/src/utils \
+ $(WPA_SUPPL_DIR)/src/wps \
+ $(WPA_SUPPL_DIR)/wpa_supplicant
+
+# 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_wext_rtl
+LOCAL_SHARED_LIBRARIES := libc libcutils
+LOCAL_CFLAGS := $(L_CFLAGS)
+LOCAL_SRC_FILES := driver_cmd_wext_rtl.c
+LOCAL_C_INCLUDES := $(WPA_SUPPL_DIR_INCLUDE)
+include $(BUILD_STATIC_LIBRARY)
+
+########################
+
+endif
0  wlan/wpa_supplicant_8_lib/MODULE_LICENSE_BSD
No changes.
37 wlan/wpa_supplicant_8_lib/NOTICE
@@ -0,0 +1,37 @@
+
+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.
+
+ * 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.
391 wlan/wpa_supplicant_8_lib/driver_cmd_wext_rtl.c
@@ -0,0 +1,391 @@
+/*
+ * Driver interaction with extended Linux Wireless Extensions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ */
+
+#include "includes.h"
+#include <sys/ioctl.h>
+#include <net/if_arp.h>
+#include <net/if.h>
+
+#include "wireless_copy.h"
+#include "common.h"
+#include "driver.h"
+#include "eloop.h"
+#include "priv_netlink.h"
+#include "driver_wext.h"
+#include "ieee802_11_defs.h"
+#include "wpa_common.h"
+#include "wpa_ctrl.h"
+#include "wpa_supplicant_i.h"
+#include "config.h"
+#include "linux_ioctl.h"
+#include "scan.h"
+
+#include "driver_cmd_wext_rtl.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 > WEXT_NUMBER_SEQUENTIAL_ERRORS) {
+ drv->errors = 0;
+ wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
+ }
+ } else {
+ drv->errors = 0;
+ }
+ return ret;
+
+}
+
+int wpa_driver_wext_driver_cmd( void *priv, char *cmd, char *buf, size_t buf_len )
+{
+ struct wpa_driver_wext_data *drv = priv;
+ struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx);
+ struct iwreq iwr;
+ int ret = 0, flags;
+
+ wpa_printf(MSG_DEBUG, "%s %s len = %d", __func__, cmd, buf_len);
+
+ if (!drv->driver_is_started && (os_strcasecmp(cmd, "START") != 0)) {
+ wpa_printf(MSG_ERROR,"WEXT: Driver not initialized yet");
+ return -1;
+ }
+
+ if (os_strcasecmp(cmd, "RSSI-APPROX") == 0) {
+ os_strncpy(cmd, RSSI_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 > WEXT_NUMBER_SEQUENTIAL_ERRORS) {
+ drv->errors = 0;
+ wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
+ }
+ } else {
+ drv->errors = 0;
+ ret = 0;
+ if ((os_strcasecmp(cmd, RSSI_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;
+}
76 wlan/wpa_supplicant_8_lib/driver_cmd_wext_rtl.h
@@ -0,0 +1,76 @@
+/*
+ * 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 RSSI_CMD "RSSI"
+#define LINKSPEED_CMD "LINKSPEED"
+
+#define WPA_DRIVER_WEXT_WAIT_US 400000
+#define MAX_DRV_CMD_SIZE 248
+#define WEXT_NUMBER_SEQUENTIAL_ERRORS 4
+#define WEXT_CSCAN_AMOUNT 9
+#define WEXT_CSCAN_BUF_LEN 360
+#define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00"
+#define WEXT_CSCAN_HEADER_SIZE 12
+#define WEXT_CSCAN_SSID_SECTION 'S'
+#define WEXT_CSCAN_CHANNEL_SECTION 'C'
+#define WEXT_CSCAN_NPROBE_SECTION 'N'
+#define WEXT_CSCAN_ACTV_DWELL_SECTION 'A'
+#define WEXT_CSCAN_PASV_DWELL_SECTION 'P'
+#define WEXT_CSCAN_HOME_DWELL_SECTION 'H'
+#define WEXT_CSCAN_TYPE_SECTION 'T'
+#define WEXT_CSCAN_TYPE_DEFAULT 0
+#define WEXT_CSCAN_TYPE_PASSIVE 1
+#define WEXT_CSCAN_PASV_DWELL_TIME 130
+#define WEXT_CSCAN_PASV_DWELL_TIME_DEF 250
+#define WEXT_CSCAN_PASV_DWELL_TIME_MAX 3000
+#define WEXT_CSCAN_HOME_DWELL_TIME 130
+
+#define WEXT_PNOSETUP_HEADER "PNOSETUP "
+#define WEXT_PNOSETUP_HEADER_SIZE 9
+#define WEXT_PNO_TLV_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