diff options
author | Mohammed Habibulla <moch@google.com> | 2015-11-06 01:01:14 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-11-06 01:01:14 +0000 |
commit | d3cf6fb150afd8011430abfecb73874b5727d300 (patch) | |
tree | af4de1c711adc31ea30ad67fb490141142829164 | |
parent | 195a418925ce947bcb0cdb37f982a284e8cb257e (diff) | |
parent | 4016edd37ebd4a5c2699b73fad8988efd80f221b (diff) | |
download | marvell-d3cf6fb150afd8011430abfecb73874b5727d300.tar.gz |
Merge "Added the Wifi HAL Module" into mnc-brillo-dev
-rw-r--r-- | peripheral/wifi/sd8xxx/driver/Android.mk | 65 | ||||
-rw-r--r-- | peripheral/wifi/sd8xxx/driver/wifi_driver_hal_sd8xxx.c | 140 | ||||
-rwxr-xr-x | peripheral/wifi/sd8xxx/peripheral.mk | 27 | ||||
-rwxr-xr-x | peripheral/wifi/sd8xxx/wlan/Android.mk | 68 | ||||
-rwxr-xr-x | peripheral/wifi/sd8xxx/wlan/driver_cmd_nl80211.c | 499 | ||||
-rwxr-xr-x | peripheral/wifi/sd8xxx/wlan/driver_cmd_wext.c | 450 | ||||
-rwxr-xr-x | peripheral/wifi/sd8xxx/wlan/driver_cmd_wext.h | 42 | ||||
-rwxr-xr-x | peripheral/wifi/sd8xxx/wlan/driver_nl80211.h | 191 | ||||
-rw-r--r-- | soc/iap140/modules/wifi_hal_module.mk | 22 |
9 files changed, 1504 insertions, 0 deletions
diff --git a/peripheral/wifi/sd8xxx/driver/Android.mk b/peripheral/wifi/sd8xxx/driver/Android.mk new file mode 100644 index 0000000..44dee38 --- /dev/null +++ b/peripheral/wifi/sd8xxx/driver/Android.mk @@ -0,0 +1,65 @@ +# Copyright (C) 2015 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(WIFI_DRIVER_HAL_PERIPHERAL), sd8xxx) + +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + wifi_driver_hal_sd8xxx.c + +LOCAL_C_INCLUDES += \ + $(LOCAL_PATH) \ + device/generic/brillo/wifi_driver_hal/include \ + hardware/bsp/marvell/peripheral/libwireless + +LOCAL_SHARED_LIBRARIES := \ + libc \ + libcutils \ + libutils \ + libMarvellWireless + +LOCAL_STATIC_LIBRARIES += + +LOCAL_MODULE:= $(WIFI_DRIVER_HAL_MODULE) +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_MODULE_TAGS := optional + +LOCAL_CFLAGS += -Wno-unused-parameter +LOCAL_PRELINK_MODULE := false + +# Make symlinks from /system/etc/firmware/mrvl to /data/misc/wireless +CONFIGS := \ + wifi_init_cfg.conf \ + bt_init_cfg.conf +SYMLINKS := $(addprefix $(TARGET_OUT)/etc/firmware/mrvl/,$(CONFIGS)) +$(SYMLINKS): CAL_BINARY := /data/misc/wireless +$(SYMLINKS): $(LOCAL_INSTALLED_MODULE) $(LOCAL_PATH)/Android.mk + @echo "Symlink: $@ -> $(CAL_BINARY)" + @mkdir -p $(dir $@) + @rm -rf $@ + $(hide) ln -sf $(CAL_BINARY)/$(notdir $@) $@ + +ALL_DEFAULT_INSTALLED_MODULES += $(SYMLINKS) + +# We need this so that the installed files could be picked up +# based on the local module's name +ALL_MODULES.$(LOCAL_MODULE).INSTALLED := \ + $(ALL_MODULES.$(LOCAL_MODULE).INSTALLED) $(SYMLINKS) + +include $(BUILD_SHARED_LIBRARY) + +endif diff --git a/peripheral/wifi/sd8xxx/driver/wifi_driver_hal_sd8xxx.c b/peripheral/wifi/sd8xxx/driver/wifi_driver_hal_sd8xxx.c new file mode 100644 index 0000000..6c9fb0a --- /dev/null +++ b/peripheral/wifi/sd8xxx/driver/wifi_driver_hal_sd8xxx.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2005. Marvell International Ltd + * + * 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. + */ + +#define LOG_TAG "wifi_driver_sd8xxx" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <cutils/log.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/un.h> +#include <stddef.h> +#include <time.h> +#include <unistd.h> +#include <errno.h> + +#include <hardware_brillo/wifi_driver_hal.h> +#include "marvell_wireless.h" + +#define SOCKERR_IO -1 +#define SOCKERR_CLOSED -2 +#define SOCKERR_INVARG -3 +#define SOCKERR_TIMEOUT -4 +#define SOCKERR_OK 0 +#define MAX_BUFFER_SIZE 256 +#define MAX_DRV_ARG_SIZE 128 + +static int wireless_send_command(const char *cmd, char *reply, size_t reply_len); +static int cli_conn(const char *name); +static int ap_mode = 0; + +static const char *local_socket_dir = "/data/misc/wireless/socket_daemon"; +const char kApDeviceName[] = "wlan0"; +const char kStationDeviceName[] = "wlan0"; +const char kDevicePathPrefix[] = "/sys/class/net"; + +static wifi_driver_error wifi_driver_initialize_sd8xxx() { + ALOGI("Do wifi_driver_initialize_sd8xxx()\n"); + if(wifi_enable()) + return WIFI_ERROR_NOT_AVAILABLE; + + return WIFI_SUCCESS; +} + +static int interface_exists(const char *interface_name) { + char interface_path[PATH_MAX]; + sprintf(interface_path, "%s/%s", kDevicePathPrefix, interface_name); + ALOGI("To test the %s accessible", interface_path); + return access(interface_path, F_OK) == 0; +} + +static wifi_driver_error wifi_driver_set_mode_sd8xxx(wifi_driver_mode mode, + char *wifi_device_name, + size_t wifi_device_name_size) { + const char *device_name = NULL; + + switch (mode) { + case WIFI_MODE_AP: + ALOGI("In %s mode and will set to AP mode\n", ap_mode ? "AP" : "STATION"); + device_name = kApDeviceName; + break; + + case WIFI_MODE_STATION: + ALOGI("In %s mode and will set to STATION mode\n", ap_mode ? "AP" : "STATION"); + device_name = kStationDeviceName; + break; + + default: + ALOGE("Unkonwn WiFi driver mode %d", mode); + return WIFI_ERROR_INVALID_ARGS; + } + + strlcpy(wifi_device_name, device_name, wifi_device_name_size); + + if(interface_exists(device_name)) + return WIFI_SUCCESS; + + return WIFI_ERROR_TIMED_OUT; +} + +static int close_sd8xxx_driver(struct hw_device_t *device) { + wifi_driver_device_t *dev = (wifi_driver_device_t *)(device); + + ALOGI("Do close_sd8xxx_driver()\n"); + if(dev) + free(dev); + + return 0; +} + +static int open_sd8xxx_driver(const struct hw_module_t *module, + const char *id, + struct hw_device_t **device) { + wifi_driver_device_t *dev = (wifi_driver_device_t *)( + calloc(1, sizeof(wifi_driver_device_t))); + + ALOGI("Do open_sd8xxx_driver()\n"); + + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = WIFI_DRIVER_DEVICE_API_VERSION_0_1; + dev->common.module = (hw_module_t *)(module); + dev->common.close = close_sd8xxx_driver; + dev->wifi_driver_initialize = wifi_driver_initialize_sd8xxx; + dev->wifi_driver_set_mode = wifi_driver_set_mode_sd8xxx; + + *device = &dev->common; + ap_mode = 0; + + return 0; +} + +static struct hw_module_methods_t sd8xxx_driver_module_methods = { + open: open_sd8xxx_driver, +}; + +hw_module_t HAL_MODULE_INFO_SYM = { + tag: HARDWARE_MODULE_TAG, + version_major: 1, + version_minor: 0, + id: WIFI_DRIVER_HARDWARE_MODULE_ID, + name: "sd8xxx module", + author: "marvell", + methods: &sd8xxx_driver_module_methods, + dso: NULL, + reserved: {0}, +}; diff --git a/peripheral/wifi/sd8xxx/peripheral.mk b/peripheral/wifi/sd8xxx/peripheral.mk new file mode 100755 index 0000000..ea88226 --- /dev/null +++ b/peripheral/wifi/sd8xxx/peripheral.mk @@ -0,0 +1,27 @@ + +# Copyright 2015 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. +# + +WLAN_BSP_SRC = hardware/bsp/marvell/peripheral/wifi/sd8xxx +WLAN_LIB_DIR = $(TOP)/vendor/bsp/marvell/device/abox + +PRODUCT_COPY_FILES += \ + $(WLAN_LIB_DIR)/hal/wifi/sd8xxx/firmware/sd8777_uapsta.bin:system/etc/firmware/mrvl/sd8777_uapsta.bin \ + $(WLAN_LIB_DIR)/hal/wifi/sd8xxx/firmware/txpwrlimit_cfg.bin:system/etc/firmware/mrvl/txpwrlimit_cfg.bin + +WIFI_DRIVER_HAL_MODULE := wifi_driver.$(soc_name) +WIFI_DRIVER_HAL_PERIPHERAL := sd8xxx + +BOARD_SEPOLICY_DIRS += $(WLAN_BSP_SRC)/sepolicy diff --git a/peripheral/wifi/sd8xxx/wlan/Android.mk b/peripheral/wifi/sd8xxx/wlan/Android.mk new file mode 100755 index 0000000..757a638 --- /dev/null +++ b/peripheral/wifi/sd8xxx/wlan/Android.mk @@ -0,0 +1,68 @@ +# +# 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 + +L_CFLAGS := +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/include +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_mrvl +LOCAL_SHARED_LIBRARIES := libc libcutils +LOCAL_CFLAGS := $(L_CFLAGS) +LOCAL_CFLAGS += -Werror=pointer-to-int-cast +LOCAL_SRC_FILES := $(WPA_SRC_FILE) +LOCAL_C_INCLUDES := $(WPA_SUPPL_DIR_INCLUDE) +include $(BUILD_STATIC_LIBRARY) + +######################## + +endif diff --git a/peripheral/wifi/sd8xxx/wlan/driver_cmd_nl80211.c b/peripheral/wifi/sd8xxx/wlan/driver_cmd_nl80211.c new file mode 100755 index 0000000..8f1785a --- /dev/null +++ b/peripheral/wifi/sd8xxx/wlan/driver_cmd_nl80211.c @@ -0,0 +1,499 @@ +/* + * Copyright (C) 2005. Marvell International Ltd + * + * 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 "driver_nl80211.h" +#include "wpa_supplicant_i.h" +#include "config.h" +#include "driver.h" +#ifdef ANDROID +#include "android_drv.h" +#endif + +#define WPA_PS_ENABLED 0 +#define WPA_PS_DISABLED 1 + +#define MAX_WPSP2PIE_CMD_SIZE 512 + +typedef struct android_wifi_priv_cmd { + u64 buf; + int used_len; + int total_len; +} android_wifi_priv_cmd; + +/* nl80211 code */ +static int ack_handler(struct nl_msg *msg, void *arg) { + int *err = arg; + *err = 0; + return NL_STOP; +} + +static int finish_handler(struct nl_msg *msg, void *arg) { + int *ret = arg; + *ret = 0; + return NL_SKIP; +} + +static int error_handler(struct sockaddr_nl *nla, + struct nlmsgerr *err, + void *arg) { + int *ret = arg; + *ret = err->error; + return NL_SKIP; +} + +static int send_and_recv(struct nl80211_global *global, + struct nl_handle *nl_handle, + struct nl_msg *msg, + int (*valid_handler)(struct nl_msg *, void *), + void *valid_data) { + struct nl_cb *cb; + int err = -ENOMEM; + + cb = nl_cb_clone(global->nl_cb); + if (!cb) + goto out; + + err = nl_send_auto_complete(nl_handle, msg); + if (err < 0) + goto out; + + err = 1; + + nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); + nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); + nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); + + if (valid_handler) + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, valid_data); + + while (err > 0) { + int res = nl_recvmsgs(nl_handle, cb); + if (res < 0) { + wpa_printf(MSG_INFO, + "nl80211: %s->nl_recvmsgs failed: %d", + __func__, + res); + } + } +out: + nl_cb_put(cb); + nlmsg_free(msg); + return err; +} + +static 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) { + return send_and_recv(drv->global, drv->global->nl, msg, + valid_handler, 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, drv->global->nl80211_id, 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, drv->global->nl80211_id, 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; +} + +#ifndef HOSTAPD +#define NL80211_BGSCAN_HEADER "BGSCAN-CONFIG " +#define NL80211_BGSCAN_HEADER_SIZE 14 +#define NL80211_SSID_AMOUNT 16 +#define NL80211_BGCAN_BUF_LEN 720 +#define NL80211_CSCAN_SSID_SECTION 'S' +#define NL80211_SSID_MAX_SIZE 32 +#define NL80211_BGSCAN_RSSI_SECTION 'R' +#define NL80211_BGSCAN_INTERVAL_SECTION 'T' +#define NL80211_BGSCAN_INTERVAL_DEF 30 +#define NL80211_BGSCAN_REPEAT_SECTION 'E' +#define NL80211_BGSCAN_REPEAT_DEF 5 + +static char *getop(char *s, int *first_time) { + const char delim[] = " \t\n"; + char *p; + if (*first_time){ + p = strtok(s, delim); + *first_time = FALSE; + } else { + p = strtok(NULL, delim); + } + + return (p); +} + +static int wpa_driver_set_backgroundscan_params(void *priv, char *cmd) { + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + struct ifreq ifr; + android_wifi_priv_cmd priv_cmd; + struct wpa_supplicant *wpa_s; + int ret = 0, i = 0, bp; + char buf[NL80211_BGCAN_BUF_LEN]; + struct wpa_ssid *ssid_conf; + int first_time = TRUE; + char *opstr = NULL; + char *ptr = NULL; + int find_ssid = 0; + int find_interval = 0; + int find_repeat = 0; + + 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 = NL80211_BGSCAN_HEADER_SIZE; + os_memcpy(buf, NL80211_BGSCAN_HEADER, bp); + + opstr = getop(cmd, &first_time); + while ((opstr = getop(cmd, &first_time)) != NULL) { + if ((ptr = strstr(opstr, "SSID=")) != NULL) { + find_ssid = 1; + ptr = ptr + strlen("SSID="); + buf[bp++] = NL80211_CSCAN_SSID_SECTION; + buf[bp++] = strlen(ptr); + os_memcpy(&buf[bp], ptr, strlen(ptr)); + bp += strlen(ptr); + i++; + } else if ((ptr = strstr(opstr, "RSSI=")) != NULL) { + ptr = ptr + strlen("RSSI="); + buf[bp++] = NL80211_BGSCAN_RSSI_SECTION; + buf[bp++] = atoi(ptr); + } else if ((ptr = strstr(opstr, "INTERVAL=")) != NULL) { + find_interval = 1; + ptr = ptr + strlen("INTERVAL="); + buf[bp++] = NL80211_BGSCAN_INTERVAL_SECTION; + buf[bp++] = (u8)atoi(ptr); + buf[bp++] = (u8)(atoi(ptr) >> 8); + } else if ((ptr = strstr(opstr, "REPEAT=")) != NULL) { + find_repeat = 1; + ptr = ptr + strlen("REPEAT="); + buf[bp++] = NL80211_BGSCAN_REPEAT_SECTION; + buf[bp++] = (u8)atoi(ptr); + } + } + + if (!find_ssid) { + while ((i < NL80211_SSID_AMOUNT) && (ssid_conf != NULL)) { + if ((!ssid_conf->disabled) && + (ssid_conf->ssid_len <= NL80211_SSID_MAX_SIZE)) { + wpa_printf(MSG_DEBUG, "For BG Scan: %s", ssid_conf->ssid); + buf[bp++] = NL80211_CSCAN_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; + } + } + + if (!find_interval) { + buf[bp++] = NL80211_BGSCAN_INTERVAL_SECTION; + buf[bp++] = NL80211_BGSCAN_INTERVAL_DEF; + buf[bp++] = (NL80211_BGSCAN_INTERVAL_DEF >> 8); + } + + if (!find_repeat) { + buf[bp++] = NL80211_BGSCAN_REPEAT_SECTION; + buf[bp++] = NL80211_BGSCAN_REPEAT_DEF; + } + + memset(&ifr, 0, sizeof(ifr)); + memset(&priv_cmd, 0, sizeof(priv_cmd)); + os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ); + u64 temp = (uintptr_t)buf; + priv_cmd.buf =temp; + priv_cmd.used_len = NL80211_BGCAN_BUF_LEN; + priv_cmd.total_len = NL80211_BGCAN_BUF_LEN; + ifr.ifr_data = &priv_cmd; + + if ((ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 14, &ifr)) < 0) { + wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (bgscan config): %d", ret); + } else { + wpa_printf(MSG_DEBUG, "%s %s len = %d, %d", __func__, buf, ret, strlen(buf)); + } + return ret; +} +#endif /* HOSTAPD */ + +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; + wpa_printf(MSG_INFO, "the nl80211 driver cmd is %s\n", cmd); + if (os_strcasecmp(cmd, "STOP") == 0) { + linux_set_iface_flags(drv->global->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->global->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->global->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 */ +#ifndef HOSTAPD + if (os_strncasecmp(cmd, "BGSCAN-START", 12) == 0) { + /* Issue a command 'BGSCAN-CONFIG' to driver */ + ret = wpa_driver_set_backgroundscan_params(priv, cmd); + if (ret < 0) { + wpa_printf(MSG_ERROR, "%s: failed to issue private command: BGSCAN-START\n", __func__); + } + return ret; + } else +#endif /* HOSTAPD */ + { + os_memcpy(buf, cmd, strlen(cmd) + 1); + } + memset(&ifr, 0, sizeof(ifr)); + memset(&priv_cmd, 0, sizeof(priv_cmd)); + os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ); + + os_memcpy(&priv_cmd.buf, &buf, sizeof(buf)); + priv_cmd.used_len = buf_len; + priv_cmd.total_len = buf_len; + ifr.ifr_data = &priv_cmd; + + if ((ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 14, &ifr)) < 0) { + wpa_printf(MSG_ERROR, "%s: failed to issue private commands\n", __func__); + wpa_printf(MSG_ERROR, "the cmd is %s\n", cmd); + wpa_printf(MSG_ERROR, "the error is [%d] [%s] \n", errno, strerror(errno)); + 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_strncasecmp(cmd, "WLS_BATCHING", 12) == 0)) + ret = strlen(buf); + else if ((os_strncasecmp(cmd, "COUNTRY", 7) == 0) || + (os_strncasecmp(cmd, "SETBAND", 7) == 0)) + wpa_supplicant_event(drv->ctx, + EVENT_CHANNEL_LIST_CHANGED, NULL); + 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) { + /* Return 0 till we handle p2p_presence request completely in the driver */ + return 0; +} + +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 = NULL; + struct wpabuf *ap_wps_p2p_ie = NULL; + char *_cmd = "SET_AP_WPS_P2P_IE"; + char *pbuf; + char *tb = NULL; + int ret = 0; + int i; + size_t buf_size, offset; + struct cmd_desc { + int cmd; + const struct wpabuf *src; + } cmd_arr[] = { + {0x1, beacon}, + {0x2, proberesp}, + {0x4, assocresp}, + {-1, NULL} + }; + + buf = os_malloc(MAX_WPSP2PIE_CMD_SIZE); + if (buf == NULL) { + wpa_printf(MSG_DEBUG, "%s: %s (%d)", __func__, strerror(errno), errno); + return errno; + } + buf_size = MAX_WPSP2PIE_CMD_SIZE; + + wpa_printf(MSG_DEBUG, "%s: Entry", __func__); + for (i = 0; cmd_arr[i].cmd != -1; i++) { + os_memset(buf, 0, buf_size); + 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) { + if ((size_t) (buf + buf_size - pbuf) < wpabuf_len(ap_wps_p2p_ie)) { + offset = pbuf - buf; + tb = os_realloc(buf, buf_size + wpabuf_len(ap_wps_p2p_ie) + 1); + if (tb == NULL) { + wpa_printf(MSG_DEBUG, "%s: %s (%d)", + __func__, strerror(errno), errno); + os_free(buf); + return errno; + } + buf = tb; + pbuf = buf + offset; + buf_size += wpabuf_len(ap_wps_p2p_ie) + 1; + os_memset(pbuf, 0, (buf_size - offset)); + wpa_printf(MSG_DEBUG, "Realloc WPS P2P IE buffer size to %u bytes", buf_size); + } + 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; + } + } + + if (buf) + os_free(buf); + return ret; +} diff --git a/peripheral/wifi/sd8xxx/wlan/driver_cmd_wext.c b/peripheral/wifi/sd8xxx/wlan/driver_cmd_wext.c new file mode 100755 index 0000000..4210e3c --- /dev/null +++ b/peripheral/wifi/sd8xxx/wlan/driver_cmd_wext.c @@ -0,0 +1,450 @@ +/* + * Copyright (C) 2005. Marvell International Ltd + * + * 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 <sys/ioctl.h> +#include <net/if_arp.h> +#include <net/if.h> + +#include "includes.h" +#include "linux_wext.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" +#ifdef ANDROID +#include "android_drv.h" +#endif /* ANDROID */ + +#define RSSI_CMD "RSSI" +#define LINKSPEED_CMD "LINKSPEED" + +/** + * 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; + + 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; +} + +#ifndef HOSTAPD +#define WEXT_BGSCAN_HEADER "BGSCAN-CONFIG " +#define WEXT_BGSCAN_HEADER_SIZE 14 +#define WEXT_SSID_AMOUNT 16 +#define WEXT_BGCAN_BUF_LEN 720 +#define WEXT_CSCAN_SSID_SECTION 'S' +#define SSID_MAX_SIZE 32 +#define WEXT_BGSCAN_RSSI_SECTION 'R' +#define WEXT_BGSCAN_INTERVAL_SECTION 'T' +#define WEXT_BGSCAN_INTERVAL_DEF 30 +#define WEXT_BGSCAN_REPEAT_SECTION 'E' +#define WEXT_BGSCAN_REPEAT_DEF 5 + +static char *getop(char *s, int *first_time) { + const char delim[] = " \t\n"; + char *p; + if (*first_time) { + p = strtok(s, delim); + *first_time = FALSE; + } else { + p = strtok(NULL, delim); + } + + return (p); +} + +static int wpa_driver_set_backgroundscan_params(void *priv, char *cmd) { + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + struct ifreq ifr; + android_wifi_priv_cmd priv_cmd; + struct wpa_supplicant *wpa_s; + int ret = 0, i = 0, bp; + char buf[WEXT_BGCAN_BUF_LEN]; + struct wpa_ssid *ssid_conf; + int first_time = TRUE; + char *opstr = NULL; + char *ptr = NULL; + int find_ssid = 0; + int find_interval = 0; + int find_repeat = 0; + + 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_BGSCAN_HEADER_SIZE; + os_memcpy(buf, WEXT_BGSCAN_HEADER, bp); + + opstr = getop(cmd, &first_time); + while ((opstr = getop(cmd, &first_time)) != NULL) { + if((ptr = strstr(opstr, "SSID=")) != NULL) { + find_ssid = 1; + ptr = ptr + strlen("SSID="); + buf[bp++] = WEXT_CSCAN_SSID_SECTION; + buf[bp++] = strlen(ptr); + os_memcpy(&buf[bp], ptr, strlen(ptr)); + bp += strlen(ptr); + i++; + } else if ((ptr = strstr(opstr, "RSSI=")) != NULL) { + ptr = ptr + strlen("RSSI="); + buf[bp++] = WEXT_BGSCAN_RSSI_SECTION; + buf[bp++] = atoi(ptr); + } else if ((ptr = strstr(opstr, "INTERVAL=")) != NULL) { + find_interval = 1; + ptr = ptr + strlen("INTERVAL="); + buf[bp++] = WEXT_BGSCAN_INTERVAL_SECTION; + buf[bp++] = (u8)atoi(ptr); + buf[bp++] = (u8)(atoi(ptr) >> 8); + } else if ((ptr = strstr(opstr, "REPEAT=")) != NULL) { + find_repeat = 1; + ptr = ptr + strlen("REPEAT="); + buf[bp++] = WEXT_BGSCAN_REPEAT_SECTION; + buf[bp++] = (u8)atoi(ptr); + } + } + + if (!find_ssid) { + while ((i < WEXT_SSID_AMOUNT) && (ssid_conf != NULL)) { + if ((!ssid_conf->disabled) && (ssid_conf->ssid_len <= SSID_MAX_SIZE)){ + wpa_printf(MSG_DEBUG, "For BG Scan: %s", ssid_conf->ssid); + buf[bp++] = WEXT_CSCAN_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; + } + } + + if (!find_interval) { + buf[bp++] = WEXT_BGSCAN_INTERVAL_SECTION; + buf[bp++] = WEXT_BGSCAN_INTERVAL_DEF; + buf[bp++] = (WEXT_BGSCAN_INTERVAL_DEF >> 8); + } + + if (!find_repeat) { + buf[bp++] = WEXT_BGSCAN_REPEAT_SECTION; + buf[bp++] = WEXT_BGSCAN_REPEAT_DEF; + } + + 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 = WEXT_BGCAN_BUF_LEN; + priv_cmd.total_len = WEXT_BGCAN_BUF_LEN; + ifr.ifr_data = &priv_cmd; + + if ((ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 14, &ifr)) < 0) { + wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (bgscan config): %d", ret); + } else { + wpa_printf(MSG_DEBUG, "%s %s len = %d, %d", __func__, buf, ret, strlen(buf)); + } + return ret; +} +#endif /* HOSTAPD */ + +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; +#ifndef HOSTAPD + } else if (os_strncasecmp(cmd, "BGSCAN-START") == 0) { + /* Issue a command 'BGSCAN-CONFIG' to driver */ + ret = wpa_driver_set_backgroundscan_params(priv); + if (ret < 0) { + wpa_printf(MSG_ERROR, "%s: failed to issue command: BGSCAN-START\n", __func__); + } + drv->bgscan_enabled = 1; + return ret; + } else if (os_strcasecmp(cmd, "BGSCAN-STOP") == 0) { + drv->bgscan_enabled = 0; + return 0; +#endif /* HOSTAPD */ + } + + 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; +}
\ No newline at end of file diff --git a/peripheral/wifi/sd8xxx/wlan/driver_cmd_wext.h b/peripheral/wifi/sd8xxx/wlan/driver_cmd_wext.h new file mode 100755 index 0000000..364e5de --- /dev/null +++ b/peripheral/wifi/sd8xxx/wlan/driver_cmd_wext.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2005. Marvell International Ltd + * + * 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. + */ + +#ifndef __WIFI_DRIVER_CMD_WEXT_H +#define __WIFI_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_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 /* __WIFI_DRIVER_CMD_WEXT_H */ diff --git a/peripheral/wifi/sd8xxx/wlan/driver_nl80211.h b/peripheral/wifi/sd8xxx/wlan/driver_nl80211.h new file mode 100755 index 0000000..45d52cc --- /dev/null +++ b/peripheral/wifi/sd8xxx/wlan/driver_nl80211.h @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2005. Marvell International Ltd + * + * 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. + */ + +#ifndef __DRIVER_NL80211_H_ +#define __DRIVER_NL80211_H_ + +#include "includes.h" +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <net/if.h> +#include <netlink/genl/genl.h> +#include <netlink/genl/family.h> +#include <netlink/genl/ctrl.h> +#include <linux/rtnetlink.h> +#include <netpacket/packet.h> +#include <linux/filter.h> +#include "nl80211_copy.h" + +#include "common.h" +#include "eloop.h" +#include "utils/list.h" +#include "common/ieee802_11_defs.h" +#include "netlink.h" +#include "linux_ioctl.h" +#include "radiotap.h" +#include "radiotap_iter.h" +#include "rfkill.h" +#include "driver.h" + +#ifdef CONFIG_LIBNL20 +/* libnl 2.0 compatibility code */ +#define nl_handle nl_sock +#define nl80211_handle_alloc nl_socket_alloc_cb +#define nl80211_handle_destroy nl_socket_free +#endif /* CONFIG_LIBNL20 */ + +#ifndef IFF_LOWER_UP +#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ +#endif +#ifndef IFF_DORMANT +#define IFF_DORMANT 0x20000 /* driver signals dormant */ +#endif + +#ifndef IF_OPER_DORMANT +#define IF_OPER_DORMANT 5 +#endif +#ifndef IF_OPER_UP +#define IF_OPER_UP 6 +#endif + +struct nl80211_global { + struct dl_list interfaces; + int if_add_ifindex; + struct netlink_data *netlink; + struct nl_cb *nl_cb; + struct nl_handle *nl; + int nl80211_id; + int ioctl_sock; /* socket for ioctl() use */ + + struct nl_handle *nl_event; +}; + +struct nl80211_wiphy_data { + struct dl_list list; + struct dl_list bsss; + struct dl_list drvs; + + struct nl_handle *nl_beacons; + struct nl_cb *nl_cb; + + int wiphy_idx; +}; + +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; + + u8 addr[ETH_ALEN]; + + int freq; + + struct nl_handle *nl_preq, *nl_mgmt; + struct nl_cb *nl_cb; + + struct nl80211_wiphy_data *wiphy_data; + struct dl_list wiphy_list; +}; + +struct wpa_driver_nl80211_data { + struct nl80211_global *global; + struct dl_list list; + struct dl_list wiphy_list; + char phyname[32]; + void *ctx; + int ifindex; + int if_removed; + int if_disabled; + int ignore_if_down_event; + struct rfkill_data *rfkill; + struct wpa_driver_capa capa; + int has_capability; + + int operstate; + + int scan_complete_events; + + struct nl_cb *nl_cb; + + u8 auth_bssid[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + int associated; + u8 ssid[32]; + size_t ssid_len; + enum nl80211_iftype nlmode; + enum nl80211_iftype ap_scan_as_station; + unsigned int assoc_freq; + + int monitor_sock; + int monitor_ifidx; + int monitor_refcount; + + unsigned int disabled_11b_rates:1; + unsigned int pending_remain_on_chan:1; + unsigned int in_interface_list:1; + unsigned int device_ap_sme:1; + unsigned int poll_command_supported:1; + unsigned int data_tx_status:1; + unsigned int scan_for_auth:1; + unsigned int retry_auth:1; + unsigned int use_monitor:1; + + u64 remain_on_chan_cookie; + u64 send_action_cookie; + + unsigned int last_mgmt_freq; + + struct wpa_driver_scan_filter *filter_ssids; + size_t num_filter_ssids; + + struct i802_bss first_bss; + + int eapol_tx_sock; + +#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 */ + + /* From failed authentication command */ + int auth_freq; + u8 auth_bssid_[ETH_ALEN]; + u8 auth_ssid[32]; + size_t auth_ssid_len; + int auth_alg; + u8 *auth_ie; + size_t auth_ie_len; + u8 auth_wep_key[4][16]; + size_t auth_wep_key_len[4]; + int auth_wep_tx_keyidx; + int auth_local_state_change; + int auth_p2p; +}; + +#endif
\ No newline at end of file diff --git a/soc/iap140/modules/wifi_hal_module.mk b/soc/iap140/modules/wifi_hal_module.mk new file mode 100644 index 0000000..550c832 --- /dev/null +++ b/soc/iap140/modules/wifi_hal_module.mk @@ -0,0 +1,22 @@ +# +# Copyright 2015 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 +BOARD_WPA_SUPPLICANT_DRIVER := NL80211 +WPA_SUPPLICANT_VERSION := VER_0_8_X +BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_mrvl +BOARD_HOSTAPD_DRIVER := NL80211 +BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_mrvl |