From 7753f181fe657dd4f1d1a4eb65e453a3e6e5a5a5 Mon Sep 17 00:00:00 2001 From: Debasish Das Date: Thu, 21 Apr 2016 17:15:30 +0530 Subject: [PATCH] [7570] wlbt: Convert files from Dos to Unix file format WLAN HAL files are converted from Dos to Unix file format Change-Id: I9b2333a6c55ea1316570687decfa87c0c9ee8e9f SCSC-Bug-Id: SSB-15880 Signed-off-by: Debasish Das --- common.cpp | 424 ++++----- common.h | 328 +++---- cpp_bindings.cpp | 1412 ++++++++++++++-------------- cpp_bindings.h | 692 +++++++------- gscan.cpp | 2124 +++++++++++++++++++++--------------------- link_layer_stats.cpp | 62 +- rtt.cpp | 104 +-- sync.h | 106 +-- wifi_hal.cpp | 1482 ++++++++++++++--------------- 9 files changed, 3367 insertions(+), 3367 deletions(-) diff --git a/common.cpp b/common.cpp index 751c782..1a72425 100755 --- a/common.cpp +++ b/common.cpp @@ -1,212 +1,212 @@ - -#include -#include -#include - -#include "wifi_hal.h" -#include "common.h" - -interface_info *getIfaceInfo(wifi_interface_handle handle) -{ - return (interface_info *)handle; -} - -wifi_handle getWifiHandle(wifi_interface_handle handle) -{ - return getIfaceInfo(handle)->handle; -} - -hal_info *getHalInfo(wifi_handle handle) -{ - return (hal_info *)handle; -} - -hal_info *getHalInfo(wifi_interface_handle handle) -{ - return getHalInfo(getWifiHandle(handle)); -} - -wifi_handle getWifiHandle(hal_info *info) -{ - return (wifi_handle)info; -} - -wifi_interface_handle getIfaceHandle(interface_info *info) -{ - return (wifi_interface_handle)info; -} - -wifi_error wifi_register_handler(wifi_handle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg) -{ - hal_info *info = (hal_info *)handle; - - /* TODO: check for multiple handlers? */ - pthread_mutex_lock(&info->cb_lock); - - wifi_error result = WIFI_ERROR_OUT_OF_MEMORY; - - if (info->num_event_cb < info->alloc_event_cb) { - info->event_cb[info->num_event_cb].nl_cmd = cmd; - info->event_cb[info->num_event_cb].vendor_id = 0; - info->event_cb[info->num_event_cb].vendor_subcmd = 0; - info->event_cb[info->num_event_cb].cb_func = func; - info->event_cb[info->num_event_cb].cb_arg = arg; - ALOGI("Successfully added event handler %p:%p for command %d at %d", - arg, func, cmd, info->num_event_cb); - info->num_event_cb++; - result = WIFI_SUCCESS; - } - - pthread_mutex_unlock(&info->cb_lock); - return result; -} - -wifi_error wifi_register_vendor_handler(wifi_handle handle, - uint32_t id, int subcmd, nl_recvmsg_msg_cb_t func, void *arg) -{ - hal_info *info = (hal_info *)handle; - -//ALOGD("GSCAN register handle wifi_register_vendor_handler %p", handle); - /* TODO: check for multiple handlers? */ - pthread_mutex_lock(&info->cb_lock); - ALOGI("Added event handler %p", info); - - wifi_error result = WIFI_ERROR_OUT_OF_MEMORY; - - // ALOGD("register_vendor_handler: handle = %p", handle); - if (info->num_event_cb < info->alloc_event_cb) { - info->event_cb[info->num_event_cb].nl_cmd = NL80211_CMD_VENDOR; - info->event_cb[info->num_event_cb].vendor_id = id; - info->event_cb[info->num_event_cb].vendor_subcmd = subcmd; - info->event_cb[info->num_event_cb].cb_func = func; - info->event_cb[info->num_event_cb].cb_arg = arg; - ALOGI("Added event handler %p:%p for vendor 0x%0x and subcmd 0x%0x at %d", - arg, func, id, subcmd, info->num_event_cb); - info->num_event_cb++; - result = WIFI_SUCCESS; - } - - pthread_mutex_unlock(&info->cb_lock); - return result; -} - -void wifi_unregister_handler(wifi_handle handle, int cmd) -{ - hal_info *info = (hal_info *)handle; - - if (cmd == NL80211_CMD_VENDOR) { - ALOGE("Must use wifi_unregister_vendor_handler to remove vendor handlers"); - return; - } - - pthread_mutex_lock(&info->cb_lock); - - for (int i = 0; i < info->num_event_cb; i++) { - if (info->event_cb[i].nl_cmd == cmd) { - ALOGI("Successfully removed event handler %p:%p for cmd = 0x%0x from %d", - info->event_cb[i].cb_arg, info->event_cb[i].cb_func, cmd, i); - - memmove(&info->event_cb[i], &info->event_cb[i+1], - (info->num_event_cb - i - 1) * sizeof(cb_info)); - info->num_event_cb--; - break; - } - } - - pthread_mutex_unlock(&info->cb_lock); -} - -void wifi_unregister_vendor_handler(wifi_handle handle, uint32_t id, int subcmd) -{ - hal_info *info = (hal_info *)handle; - - pthread_mutex_lock(&info->cb_lock); - - for (int i = 0; i < info->num_event_cb; i++) { - - if (info->event_cb[i].nl_cmd == NL80211_CMD_VENDOR - && info->event_cb[i].vendor_id == id - && info->event_cb[i].vendor_subcmd == subcmd) { - ALOGI("Successfully removed event handler %p:%p for vendor 0x%0x, subcmd 0x%0x from %d", - info->event_cb[i].cb_arg, info->event_cb[i].cb_func, id, subcmd, i); - memmove(&info->event_cb[i], &info->event_cb[i+1], - (info->num_event_cb - i - 1) * sizeof(cb_info)); - info->num_event_cb--; - break; - } - } - - pthread_mutex_unlock(&info->cb_lock); -} - - -wifi_error wifi_register_cmd(wifi_handle handle, int id, WifiCommand *cmd) -{ - hal_info *info = (hal_info *)handle; - - ALOGD("registering command %d", id); - - wifi_error result = WIFI_ERROR_OUT_OF_MEMORY; - - if (info->num_cmd < info->alloc_cmd) { - info->cmd[info->num_cmd].id = id; - info->cmd[info->num_cmd].cmd = cmd; - ALOGI("Successfully added command %d: %p at %d", id, cmd, info->num_cmd); - info->num_cmd++; - result = WIFI_SUCCESS; - } - - return result; -} - -WifiCommand *wifi_unregister_cmd(wifi_handle handle, int id) -{ - hal_info *info = (hal_info *)handle; - - ALOGD("un-registering command %d", id); - - WifiCommand *cmd = NULL; - - for (int i = 0; i < info->num_cmd; i++) { - if (info->cmd[i].id == id) { - cmd = info->cmd[i].cmd; - memmove(&info->cmd[i], &info->cmd[i+1], (info->num_cmd - i) * sizeof(cmd_info)); - info->num_cmd--; - ALOGI("Successfully removed command %d: %p from %d", id, cmd, i); - break; - } - } - - return cmd; -} - -WifiCommand *wifi_get_cmd(wifi_handle handle, int id) -{ - hal_info *info = (hal_info *)handle; - - WifiCommand *cmd = NULL; - - for (int i = 0; i < info->num_cmd; i++) { - if (info->cmd[i].id == id) { - cmd = info->cmd[i].cmd; - break; - } - } - - return cmd; -} - -void wifi_unregister_cmd(wifi_handle handle, WifiCommand *cmd) -{ - hal_info *info = (hal_info *)handle; - - for (int i = 0; i < info->num_cmd; i++) { - if (info->cmd[i].cmd == cmd) { - int id = info->cmd[i].id; - memmove(&info->cmd[i], &info->cmd[i+1], (info->num_cmd - i) * sizeof(cmd_info)); - info->num_cmd--; - ALOGI("Successfully removed command %d: %p from %d", id, cmd, i); - break; - } - } -} + +#include +#include +#include + +#include "wifi_hal.h" +#include "common.h" + +interface_info *getIfaceInfo(wifi_interface_handle handle) +{ + return (interface_info *)handle; +} + +wifi_handle getWifiHandle(wifi_interface_handle handle) +{ + return getIfaceInfo(handle)->handle; +} + +hal_info *getHalInfo(wifi_handle handle) +{ + return (hal_info *)handle; +} + +hal_info *getHalInfo(wifi_interface_handle handle) +{ + return getHalInfo(getWifiHandle(handle)); +} + +wifi_handle getWifiHandle(hal_info *info) +{ + return (wifi_handle)info; +} + +wifi_interface_handle getIfaceHandle(interface_info *info) +{ + return (wifi_interface_handle)info; +} + +wifi_error wifi_register_handler(wifi_handle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg) +{ + hal_info *info = (hal_info *)handle; + + /* TODO: check for multiple handlers? */ + pthread_mutex_lock(&info->cb_lock); + + wifi_error result = WIFI_ERROR_OUT_OF_MEMORY; + + if (info->num_event_cb < info->alloc_event_cb) { + info->event_cb[info->num_event_cb].nl_cmd = cmd; + info->event_cb[info->num_event_cb].vendor_id = 0; + info->event_cb[info->num_event_cb].vendor_subcmd = 0; + info->event_cb[info->num_event_cb].cb_func = func; + info->event_cb[info->num_event_cb].cb_arg = arg; + ALOGI("Successfully added event handler %p:%p for command %d at %d", + arg, func, cmd, info->num_event_cb); + info->num_event_cb++; + result = WIFI_SUCCESS; + } + + pthread_mutex_unlock(&info->cb_lock); + return result; +} + +wifi_error wifi_register_vendor_handler(wifi_handle handle, + uint32_t id, int subcmd, nl_recvmsg_msg_cb_t func, void *arg) +{ + hal_info *info = (hal_info *)handle; + +//ALOGD("GSCAN register handle wifi_register_vendor_handler %p", handle); + /* TODO: check for multiple handlers? */ + pthread_mutex_lock(&info->cb_lock); + ALOGI("Added event handler %p", info); + + wifi_error result = WIFI_ERROR_OUT_OF_MEMORY; + + // ALOGD("register_vendor_handler: handle = %p", handle); + if (info->num_event_cb < info->alloc_event_cb) { + info->event_cb[info->num_event_cb].nl_cmd = NL80211_CMD_VENDOR; + info->event_cb[info->num_event_cb].vendor_id = id; + info->event_cb[info->num_event_cb].vendor_subcmd = subcmd; + info->event_cb[info->num_event_cb].cb_func = func; + info->event_cb[info->num_event_cb].cb_arg = arg; + ALOGI("Added event handler %p:%p for vendor 0x%0x and subcmd 0x%0x at %d", + arg, func, id, subcmd, info->num_event_cb); + info->num_event_cb++; + result = WIFI_SUCCESS; + } + + pthread_mutex_unlock(&info->cb_lock); + return result; +} + +void wifi_unregister_handler(wifi_handle handle, int cmd) +{ + hal_info *info = (hal_info *)handle; + + if (cmd == NL80211_CMD_VENDOR) { + ALOGE("Must use wifi_unregister_vendor_handler to remove vendor handlers"); + return; + } + + pthread_mutex_lock(&info->cb_lock); + + for (int i = 0; i < info->num_event_cb; i++) { + if (info->event_cb[i].nl_cmd == cmd) { + ALOGI("Successfully removed event handler %p:%p for cmd = 0x%0x from %d", + info->event_cb[i].cb_arg, info->event_cb[i].cb_func, cmd, i); + + memmove(&info->event_cb[i], &info->event_cb[i+1], + (info->num_event_cb - i - 1) * sizeof(cb_info)); + info->num_event_cb--; + break; + } + } + + pthread_mutex_unlock(&info->cb_lock); +} + +void wifi_unregister_vendor_handler(wifi_handle handle, uint32_t id, int subcmd) +{ + hal_info *info = (hal_info *)handle; + + pthread_mutex_lock(&info->cb_lock); + + for (int i = 0; i < info->num_event_cb; i++) { + + if (info->event_cb[i].nl_cmd == NL80211_CMD_VENDOR + && info->event_cb[i].vendor_id == id + && info->event_cb[i].vendor_subcmd == subcmd) { + ALOGI("Successfully removed event handler %p:%p for vendor 0x%0x, subcmd 0x%0x from %d", + info->event_cb[i].cb_arg, info->event_cb[i].cb_func, id, subcmd, i); + memmove(&info->event_cb[i], &info->event_cb[i+1], + (info->num_event_cb - i - 1) * sizeof(cb_info)); + info->num_event_cb--; + break; + } + } + + pthread_mutex_unlock(&info->cb_lock); +} + + +wifi_error wifi_register_cmd(wifi_handle handle, int id, WifiCommand *cmd) +{ + hal_info *info = (hal_info *)handle; + + ALOGD("registering command %d", id); + + wifi_error result = WIFI_ERROR_OUT_OF_MEMORY; + + if (info->num_cmd < info->alloc_cmd) { + info->cmd[info->num_cmd].id = id; + info->cmd[info->num_cmd].cmd = cmd; + ALOGI("Successfully added command %d: %p at %d", id, cmd, info->num_cmd); + info->num_cmd++; + result = WIFI_SUCCESS; + } + + return result; +} + +WifiCommand *wifi_unregister_cmd(wifi_handle handle, int id) +{ + hal_info *info = (hal_info *)handle; + + ALOGD("un-registering command %d", id); + + WifiCommand *cmd = NULL; + + for (int i = 0; i < info->num_cmd; i++) { + if (info->cmd[i].id == id) { + cmd = info->cmd[i].cmd; + memmove(&info->cmd[i], &info->cmd[i+1], (info->num_cmd - i) * sizeof(cmd_info)); + info->num_cmd--; + ALOGI("Successfully removed command %d: %p from %d", id, cmd, i); + break; + } + } + + return cmd; +} + +WifiCommand *wifi_get_cmd(wifi_handle handle, int id) +{ + hal_info *info = (hal_info *)handle; + + WifiCommand *cmd = NULL; + + for (int i = 0; i < info->num_cmd; i++) { + if (info->cmd[i].id == id) { + cmd = info->cmd[i].cmd; + break; + } + } + + return cmd; +} + +void wifi_unregister_cmd(wifi_handle handle, WifiCommand *cmd) +{ + hal_info *info = (hal_info *)handle; + + for (int i = 0; i < info->num_cmd; i++) { + if (info->cmd[i].cmd == cmd) { + int id = info->cmd[i].id; + memmove(&info->cmd[i], &info->cmd[i+1], (info->num_cmd - i) * sizeof(cmd_info)); + info->num_cmd--; + ALOGI("Successfully removed command %d: %p from %d", id, cmd, i); + break; + } + } +} diff --git a/common.h b/common.h index 82208c2..32e226a 100755 --- a/common.h +++ b/common.h @@ -1,164 +1,164 @@ - -#include "wifi_hal.h" - -#ifndef __WIFI_HAL_COMMON_H__ -#define __WIFI_HAL_COMMON_H__ - -#define LOG_TAG "WifiHAL" - -#include -#include "nl80211_copy.h" -#include "sync.h" - -#define SOCKET_BUFFER_SIZE (32768U) -#define RECV_BUF_SIZE (4096) -#define DEFAULT_EVENT_CB_SIZE (64) -#define DEFAULT_CMD_SIZE (64) -#define DOT11_OUI_LEN 3 - -/* - Vendor OUI - This is a unique identifier that identifies organization. Lets - code Android specific functions with Google OUI; although vendors can do more - with their own OUI's as well. - */ - -const uint32_t GOOGLE_OUI = 0x001A11; -/* TODO: define vendor OUI here */ - - -/* - This enum defines ranges for various commands; commands themselves - can be defined in respective feature headers; i.e. find gscan command - definitions in gscan.cpp - */ - -typedef enum { - /* don't use 0 as a valid subcommand */ - VENDOR_NL80211_SUBCMD_UNSPECIFIED, - - /* define all vendor startup commands between 0x0 and 0x0FFF */ - VENDOR_NL80211_SUBCMD_RANGE_START = 0x0001, - VENDOR_NL80211_SUBCMD_RANGE_END = 0x0FFF, - - /* define all GScan related commands between 0x1000 and 0x10FF */ - ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START = 0x1000, - ANDROID_NL80211_SUBCMD_GSCAN_RANGE_END = 0x10FF, - - /* define all NearbyDiscovery related commands between 0x1100 and 0x11FF */ - ANDROID_NL80211_SUBCMD_NBD_RANGE_START = 0x1100, - ANDROID_NL80211_SUBCMD_NBD_RANGE_END = 0x11FF, - - /* define all RTT related commands between 0x1100 and 0x11FF */ - ANDROID_NL80211_SUBCMD_RTT_RANGE_START = 0x1100, - ANDROID_NL80211_SUBCMD_RTT_RANGE_END = 0x11FF, - - ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START = 0x1200, - ANDROID_NL80211_SUBCMD_LSTATS_RANGE_END = 0x12FF, - - /* This is reserved for future usage */ - -} ANDROID_VENDOR_SUB_COMMAND; - -typedef enum { - SLSI_NL80211_VENDOR_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START, - SLSI_NL80211_VENDOR_SUBCMD_GET_VALID_CHANNELS, - SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN, - SLSI_NL80211_VENDOR_SUBCMD_DEL_GSCAN, - SLSI_NL80211_VENDOR_SUBCMD_GET_SCAN_RESULTS, - SLSI_NL80211_VENDOR_SUBCMD_SET_BSSID_HOTLIST, - SLSI_NL80211_VENDOR_SUBCMD_RESET_BSSID_HOTLIST, - SLSI_NL80211_VENDOR_SUBCMD_GET_HOTLIST_RESULTS, - SLSI_NL80211_VENDOR_SUBCMD_SET_SIGNIFICANT_CHANGE, - SLSI_NL80211_VENDOR_SUBCMD_RESET_SIGNIFICANT_CHANGE, - SLSI_NL80211_VENDOR_SUBCMD_SET_GSCAN_OUI, - SLSI_NL80211_VENDOR_SUBCMD_SET_NODFS -} WIFI_SUB_COMMAND; - -typedef enum { - GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS , - GSCAN_EVENT_HOTLIST_RESULTS_FOUND, - GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, - GSCAN_EVENT_FULL_SCAN_RESULTS, - GSCAN_EVENT_COMPLETE_SCAN, - GSCAN_EVENT_HOTLIST_RESULTS_LOST -} WIFI_EVENT; - -typedef void (*wifi_internal_event_handler) (wifi_handle handle, int events); - -class WifiCommand; - -typedef struct { - int nl_cmd; - uint32_t vendor_id; - int vendor_subcmd; - nl_recvmsg_msg_cb_t cb_func; - void *cb_arg; -} cb_info; - -typedef struct { - wifi_request_id id; - WifiCommand *cmd; -} cmd_info; - -typedef struct { - wifi_handle handle; // handle to wifi data - char name[8+1]; // interface name + trailing null - int id; // id to use when talking to driver -} interface_info; - -typedef struct { - - struct nl_sock *cmd_sock; // command socket object - struct nl_sock *event_sock; // event socket object - int nl80211_family_id; // family id for 80211 driver - int cleanup_socks[2]; // sockets used to implement wifi_cleanup - - bool in_event_loop; // Indicates that event loop is active - bool clean_up; // Indication to clean up the socket - - wifi_internal_event_handler event_handler; // default event handler - wifi_cleaned_up_handler cleaned_up_handler; // socket cleaned up handler - - cb_info *event_cb; // event callbacks - int num_event_cb; // number of event callbacks - int alloc_event_cb; // number of allocated callback objects - pthread_mutex_t cb_lock; // mutex for the event_cb access - - cmd_info *cmd; // Outstanding commands - int num_cmd; // number of commands - int alloc_cmd; // number of commands allocated - - interface_info **interfaces; // array of interfaces - int num_interfaces; // number of interfaces - - - // add other details -} hal_info; - -wifi_error wifi_register_handler(wifi_handle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg); -wifi_error wifi_register_vendor_handler(wifi_handle handle, - uint32_t id, int subcmd, nl_recvmsg_msg_cb_t func, void *arg); - -void wifi_unregister_handler(wifi_handle handle, int cmd); -void wifi_unregister_vendor_handler(wifi_handle handle, uint32_t id, int subcmd); - -wifi_error wifi_register_cmd(wifi_handle handle, int id, WifiCommand *cmd); -WifiCommand *wifi_unregister_cmd(wifi_handle handle, int id); -WifiCommand *wifi_get_cmd(wifi_handle handle, int id); -void wifi_unregister_cmd(wifi_handle handle, WifiCommand *cmd); - -interface_info *getIfaceInfo(wifi_interface_handle); -wifi_handle getWifiHandle(wifi_interface_handle handle); -hal_info *getHalInfo(wifi_handle handle); -hal_info *getHalInfo(wifi_interface_handle handle); -wifi_handle getWifiHandle(hal_info *info); -wifi_interface_handle getIfaceHandle(interface_info *info); - - -// some common macros - -#define min(x, y) ((x) < (y) ? (x) : (y)) -#define max(x, y) ((x) > (y) ? (x) : (y)) - -#endif - + +#include "wifi_hal.h" + +#ifndef __WIFI_HAL_COMMON_H__ +#define __WIFI_HAL_COMMON_H__ + +#define LOG_TAG "WifiHAL" + +#include +#include "nl80211_copy.h" +#include "sync.h" + +#define SOCKET_BUFFER_SIZE (32768U) +#define RECV_BUF_SIZE (4096) +#define DEFAULT_EVENT_CB_SIZE (64) +#define DEFAULT_CMD_SIZE (64) +#define DOT11_OUI_LEN 3 + +/* + Vendor OUI - This is a unique identifier that identifies organization. Lets + code Android specific functions with Google OUI; although vendors can do more + with their own OUI's as well. + */ + +const uint32_t GOOGLE_OUI = 0x001A11; +/* TODO: define vendor OUI here */ + + +/* + This enum defines ranges for various commands; commands themselves + can be defined in respective feature headers; i.e. find gscan command + definitions in gscan.cpp + */ + +typedef enum { + /* don't use 0 as a valid subcommand */ + VENDOR_NL80211_SUBCMD_UNSPECIFIED, + + /* define all vendor startup commands between 0x0 and 0x0FFF */ + VENDOR_NL80211_SUBCMD_RANGE_START = 0x0001, + VENDOR_NL80211_SUBCMD_RANGE_END = 0x0FFF, + + /* define all GScan related commands between 0x1000 and 0x10FF */ + ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START = 0x1000, + ANDROID_NL80211_SUBCMD_GSCAN_RANGE_END = 0x10FF, + + /* define all NearbyDiscovery related commands between 0x1100 and 0x11FF */ + ANDROID_NL80211_SUBCMD_NBD_RANGE_START = 0x1100, + ANDROID_NL80211_SUBCMD_NBD_RANGE_END = 0x11FF, + + /* define all RTT related commands between 0x1100 and 0x11FF */ + ANDROID_NL80211_SUBCMD_RTT_RANGE_START = 0x1100, + ANDROID_NL80211_SUBCMD_RTT_RANGE_END = 0x11FF, + + ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START = 0x1200, + ANDROID_NL80211_SUBCMD_LSTATS_RANGE_END = 0x12FF, + + /* This is reserved for future usage */ + +} ANDROID_VENDOR_SUB_COMMAND; + +typedef enum { + SLSI_NL80211_VENDOR_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START, + SLSI_NL80211_VENDOR_SUBCMD_GET_VALID_CHANNELS, + SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN, + SLSI_NL80211_VENDOR_SUBCMD_DEL_GSCAN, + SLSI_NL80211_VENDOR_SUBCMD_GET_SCAN_RESULTS, + SLSI_NL80211_VENDOR_SUBCMD_SET_BSSID_HOTLIST, + SLSI_NL80211_VENDOR_SUBCMD_RESET_BSSID_HOTLIST, + SLSI_NL80211_VENDOR_SUBCMD_GET_HOTLIST_RESULTS, + SLSI_NL80211_VENDOR_SUBCMD_SET_SIGNIFICANT_CHANGE, + SLSI_NL80211_VENDOR_SUBCMD_RESET_SIGNIFICANT_CHANGE, + SLSI_NL80211_VENDOR_SUBCMD_SET_GSCAN_OUI, + SLSI_NL80211_VENDOR_SUBCMD_SET_NODFS +} WIFI_SUB_COMMAND; + +typedef enum { + GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS , + GSCAN_EVENT_HOTLIST_RESULTS_FOUND, + GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, + GSCAN_EVENT_FULL_SCAN_RESULTS, + GSCAN_EVENT_COMPLETE_SCAN, + GSCAN_EVENT_HOTLIST_RESULTS_LOST +} WIFI_EVENT; + +typedef void (*wifi_internal_event_handler) (wifi_handle handle, int events); + +class WifiCommand; + +typedef struct { + int nl_cmd; + uint32_t vendor_id; + int vendor_subcmd; + nl_recvmsg_msg_cb_t cb_func; + void *cb_arg; +} cb_info; + +typedef struct { + wifi_request_id id; + WifiCommand *cmd; +} cmd_info; + +typedef struct { + wifi_handle handle; // handle to wifi data + char name[8+1]; // interface name + trailing null + int id; // id to use when talking to driver +} interface_info; + +typedef struct { + + struct nl_sock *cmd_sock; // command socket object + struct nl_sock *event_sock; // event socket object + int nl80211_family_id; // family id for 80211 driver + int cleanup_socks[2]; // sockets used to implement wifi_cleanup + + bool in_event_loop; // Indicates that event loop is active + bool clean_up; // Indication to clean up the socket + + wifi_internal_event_handler event_handler; // default event handler + wifi_cleaned_up_handler cleaned_up_handler; // socket cleaned up handler + + cb_info *event_cb; // event callbacks + int num_event_cb; // number of event callbacks + int alloc_event_cb; // number of allocated callback objects + pthread_mutex_t cb_lock; // mutex for the event_cb access + + cmd_info *cmd; // Outstanding commands + int num_cmd; // number of commands + int alloc_cmd; // number of commands allocated + + interface_info **interfaces; // array of interfaces + int num_interfaces; // number of interfaces + + + // add other details +} hal_info; + +wifi_error wifi_register_handler(wifi_handle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg); +wifi_error wifi_register_vendor_handler(wifi_handle handle, + uint32_t id, int subcmd, nl_recvmsg_msg_cb_t func, void *arg); + +void wifi_unregister_handler(wifi_handle handle, int cmd); +void wifi_unregister_vendor_handler(wifi_handle handle, uint32_t id, int subcmd); + +wifi_error wifi_register_cmd(wifi_handle handle, int id, WifiCommand *cmd); +WifiCommand *wifi_unregister_cmd(wifi_handle handle, int id); +WifiCommand *wifi_get_cmd(wifi_handle handle, int id); +void wifi_unregister_cmd(wifi_handle handle, WifiCommand *cmd); + +interface_info *getIfaceInfo(wifi_interface_handle); +wifi_handle getWifiHandle(wifi_interface_handle handle); +hal_info *getHalInfo(wifi_handle handle); +hal_info *getHalInfo(wifi_interface_handle handle); +wifi_handle getWifiHandle(hal_info *info); +wifi_interface_handle getIfaceHandle(interface_info *info); + + +// some common macros + +#define min(x, y) ((x) < (y) ? (x) : (y)) +#define max(x, y) ((x) > (y) ? (x) : (y)) + +#endif + diff --git a/cpp_bindings.cpp b/cpp_bindings.cpp index bcfebca..fba1ca2 100755 --- a/cpp_bindings.cpp +++ b/cpp_bindings.cpp @@ -1,706 +1,706 @@ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include "wifi_hal.h" -#include "common.h" -#include "cpp_bindings.h" - -void appendFmt(char *buf, int &offset, const char *fmt, ...) -{ - va_list params; - va_start(params, fmt); - offset += vsprintf(buf + offset, fmt, params); - va_end(params); -} - -#define C2S(x) case x: return #x; - -static const char *cmdToString(int cmd) -{ - switch (cmd) { - C2S(NL80211_CMD_UNSPEC) - C2S(NL80211_CMD_GET_WIPHY) - C2S(NL80211_CMD_SET_WIPHY) - C2S(NL80211_CMD_NEW_WIPHY) - C2S(NL80211_CMD_DEL_WIPHY) - C2S(NL80211_CMD_GET_INTERFACE) - C2S(NL80211_CMD_SET_INTERFACE) - C2S(NL80211_CMD_NEW_INTERFACE) - C2S(NL80211_CMD_DEL_INTERFACE) - C2S(NL80211_CMD_GET_KEY) - C2S(NL80211_CMD_SET_KEY) - C2S(NL80211_CMD_NEW_KEY) - C2S(NL80211_CMD_DEL_KEY) - C2S(NL80211_CMD_GET_BEACON) - C2S(NL80211_CMD_SET_BEACON) - C2S(NL80211_CMD_START_AP) - C2S(NL80211_CMD_STOP_AP) - C2S(NL80211_CMD_GET_STATION) - C2S(NL80211_CMD_SET_STATION) - C2S(NL80211_CMD_NEW_STATION) - C2S(NL80211_CMD_DEL_STATION) - C2S(NL80211_CMD_GET_MPATH) - C2S(NL80211_CMD_SET_MPATH) - C2S(NL80211_CMD_NEW_MPATH) - C2S(NL80211_CMD_DEL_MPATH) - C2S(NL80211_CMD_SET_BSS) - C2S(NL80211_CMD_SET_REG) - C2S(NL80211_CMD_REQ_SET_REG) - C2S(NL80211_CMD_GET_MESH_CONFIG) - C2S(NL80211_CMD_SET_MESH_CONFIG) - C2S(NL80211_CMD_SET_MGMT_EXTRA_IE) - C2S(NL80211_CMD_GET_REG) - C2S(NL80211_CMD_GET_SCAN) - C2S(NL80211_CMD_TRIGGER_SCAN) - C2S(NL80211_CMD_NEW_SCAN_RESULTS) - C2S(NL80211_CMD_SCAN_ABORTED) - C2S(NL80211_CMD_REG_CHANGE) - C2S(NL80211_CMD_AUTHENTICATE) - C2S(NL80211_CMD_ASSOCIATE) - C2S(NL80211_CMD_DEAUTHENTICATE) - C2S(NL80211_CMD_DISASSOCIATE) - C2S(NL80211_CMD_MICHAEL_MIC_FAILURE) - C2S(NL80211_CMD_REG_BEACON_HINT) - C2S(NL80211_CMD_JOIN_IBSS) - C2S(NL80211_CMD_LEAVE_IBSS) - C2S(NL80211_CMD_TESTMODE) - C2S(NL80211_CMD_CONNECT) - C2S(NL80211_CMD_ROAM) - C2S(NL80211_CMD_DISCONNECT) - C2S(NL80211_CMD_SET_WIPHY_NETNS) - C2S(NL80211_CMD_GET_SURVEY) - C2S(NL80211_CMD_NEW_SURVEY_RESULTS) - C2S(NL80211_CMD_SET_PMKSA) - C2S(NL80211_CMD_DEL_PMKSA) - C2S(NL80211_CMD_FLUSH_PMKSA) - C2S(NL80211_CMD_REMAIN_ON_CHANNEL) - C2S(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL) - C2S(NL80211_CMD_SET_TX_BITRATE_MASK) - C2S(NL80211_CMD_REGISTER_FRAME) - C2S(NL80211_CMD_FRAME) - C2S(NL80211_CMD_FRAME_TX_STATUS) - C2S(NL80211_CMD_SET_POWER_SAVE) - C2S(NL80211_CMD_GET_POWER_SAVE) - C2S(NL80211_CMD_SET_CQM) - C2S(NL80211_CMD_NOTIFY_CQM) - C2S(NL80211_CMD_SET_CHANNEL) - C2S(NL80211_CMD_SET_WDS_PEER) - C2S(NL80211_CMD_FRAME_WAIT_CANCEL) - C2S(NL80211_CMD_JOIN_MESH) - C2S(NL80211_CMD_LEAVE_MESH) - C2S(NL80211_CMD_UNPROT_DEAUTHENTICATE) - C2S(NL80211_CMD_UNPROT_DISASSOCIATE) - C2S(NL80211_CMD_NEW_PEER_CANDIDATE) - C2S(NL80211_CMD_GET_WOWLAN) - C2S(NL80211_CMD_SET_WOWLAN) - C2S(NL80211_CMD_START_SCHED_SCAN) - C2S(NL80211_CMD_STOP_SCHED_SCAN) - C2S(NL80211_CMD_SCHED_SCAN_RESULTS) - C2S(NL80211_CMD_SCHED_SCAN_STOPPED) - C2S(NL80211_CMD_SET_REKEY_OFFLOAD) - C2S(NL80211_CMD_PMKSA_CANDIDATE) - C2S(NL80211_CMD_TDLS_OPER) - C2S(NL80211_CMD_TDLS_MGMT) - C2S(NL80211_CMD_UNEXPECTED_FRAME) - C2S(NL80211_CMD_PROBE_CLIENT) - C2S(NL80211_CMD_REGISTER_BEACONS) - C2S(NL80211_CMD_UNEXPECTED_4ADDR_FRAME) - C2S(NL80211_CMD_SET_NOACK_MAP) - C2S(NL80211_CMD_CH_SWITCH_NOTIFY) - C2S(NL80211_CMD_START_P2P_DEVICE) - C2S(NL80211_CMD_STOP_P2P_DEVICE) - C2S(NL80211_CMD_CONN_FAILED) - C2S(NL80211_CMD_SET_MCAST_RATE) - C2S(NL80211_CMD_SET_MAC_ACL) - C2S(NL80211_CMD_RADAR_DETECT) - C2S(NL80211_CMD_GET_PROTOCOL_FEATURES) - C2S(NL80211_CMD_UPDATE_FT_IES) - C2S(NL80211_CMD_FT_EVENT) - C2S(NL80211_CMD_CRIT_PROTOCOL_START) - C2S(NL80211_CMD_CRIT_PROTOCOL_STOP) - C2S(NL80211_CMD_VENDOR) - default: - return "NL80211_CMD_UNKNOWN"; - } -} - -const char *attributeToString(int attribute) -{ - switch (attribute) { - C2S(NL80211_ATTR_UNSPEC) - - C2S(NL80211_ATTR_WIPHY) - C2S(NL80211_ATTR_WIPHY_NAME) - - C2S(NL80211_ATTR_IFINDEX) - C2S(NL80211_ATTR_IFNAME) - C2S(NL80211_ATTR_IFTYPE) - - C2S(NL80211_ATTR_MAC) - - C2S(NL80211_ATTR_KEY_DATA) - C2S(NL80211_ATTR_KEY_IDX) - C2S(NL80211_ATTR_KEY_CIPHER) - C2S(NL80211_ATTR_KEY_SEQ) - C2S(NL80211_ATTR_KEY_DEFAULT) - - C2S(NL80211_ATTR_BEACON_INTERVAL) - C2S(NL80211_ATTR_DTIM_PERIOD) - C2S(NL80211_ATTR_BEACON_HEAD) - C2S(NL80211_ATTR_BEACON_TAIL) - - C2S(NL80211_ATTR_STA_AID) - C2S(NL80211_ATTR_STA_FLAGS) - C2S(NL80211_ATTR_STA_LISTEN_INTERVAL) - C2S(NL80211_ATTR_STA_SUPPORTED_RATES) - C2S(NL80211_ATTR_STA_VLAN) - C2S(NL80211_ATTR_STA_INFO) - - C2S(NL80211_ATTR_WIPHY_BANDS) - - C2S(NL80211_ATTR_MNTR_FLAGS) - - C2S(NL80211_ATTR_MESH_ID) - C2S(NL80211_ATTR_STA_PLINK_ACTION) - C2S(NL80211_ATTR_MPATH_NEXT_HOP) - C2S(NL80211_ATTR_MPATH_INFO) - - C2S(NL80211_ATTR_BSS_CTS_PROT) - C2S(NL80211_ATTR_BSS_SHORT_PREAMBLE) - C2S(NL80211_ATTR_BSS_SHORT_SLOT_TIME) - - C2S(NL80211_ATTR_HT_CAPABILITY) - - C2S(NL80211_ATTR_SUPPORTED_IFTYPES) - - C2S(NL80211_ATTR_REG_ALPHA2) - C2S(NL80211_ATTR_REG_RULES) - - C2S(NL80211_ATTR_MESH_CONFIG) - - C2S(NL80211_ATTR_BSS_BASIC_RATES) - - C2S(NL80211_ATTR_WIPHY_TXQ_PARAMS) - C2S(NL80211_ATTR_WIPHY_FREQ) - C2S(NL80211_ATTR_WIPHY_CHANNEL_TYPE) - - C2S(NL80211_ATTR_KEY_DEFAULT_MGMT) - - C2S(NL80211_ATTR_MGMT_SUBTYPE) - C2S(NL80211_ATTR_IE) - - C2S(NL80211_ATTR_MAX_NUM_SCAN_SSIDS) - - C2S(NL80211_ATTR_SCAN_FREQUENCIES) - C2S(NL80211_ATTR_SCAN_SSIDS) - C2S(NL80211_ATTR_GENERATION) /* replaces old SCAN_GENERATION */ - C2S(NL80211_ATTR_BSS) - - C2S(NL80211_ATTR_REG_INITIATOR) - C2S(NL80211_ATTR_REG_TYPE) - - C2S(NL80211_ATTR_SUPPORTED_COMMANDS) - - C2S(NL80211_ATTR_FRAME) - C2S(NL80211_ATTR_SSID) - C2S(NL80211_ATTR_AUTH_TYPE) - C2S(NL80211_ATTR_REASON_CODE) - - C2S(NL80211_ATTR_KEY_TYPE) - - C2S(NL80211_ATTR_MAX_SCAN_IE_LEN) - C2S(NL80211_ATTR_CIPHER_SUITES) - - C2S(NL80211_ATTR_FREQ_BEFORE) - C2S(NL80211_ATTR_FREQ_AFTER) - - C2S(NL80211_ATTR_FREQ_FIXED) - - - C2S(NL80211_ATTR_WIPHY_RETRY_SHORT) - C2S(NL80211_ATTR_WIPHY_RETRY_LONG) - C2S(NL80211_ATTR_WIPHY_FRAG_THRESHOLD) - C2S(NL80211_ATTR_WIPHY_RTS_THRESHOLD) - - C2S(NL80211_ATTR_TIMED_OUT) - - C2S(NL80211_ATTR_USE_MFP) - - C2S(NL80211_ATTR_STA_FLAGS2) - - C2S(NL80211_ATTR_CONTROL_PORT) - - C2S(NL80211_ATTR_TESTDATA) - - C2S(NL80211_ATTR_PRIVACY) - - C2S(NL80211_ATTR_DISCONNECTED_BY_AP) - C2S(NL80211_ATTR_STATUS_CODE) - - C2S(NL80211_ATTR_CIPHER_SUITES_PAIRWISE) - C2S(NL80211_ATTR_CIPHER_SUITE_GROUP) - C2S(NL80211_ATTR_WPA_VERSIONS) - C2S(NL80211_ATTR_AKM_SUITES) - - C2S(NL80211_ATTR_REQ_IE) - C2S(NL80211_ATTR_RESP_IE) - - C2S(NL80211_ATTR_PREV_BSSID) - - C2S(NL80211_ATTR_KEY) - C2S(NL80211_ATTR_KEYS) - - C2S(NL80211_ATTR_PID) - - C2S(NL80211_ATTR_4ADDR) - - C2S(NL80211_ATTR_SURVEY_INFO) - - C2S(NL80211_ATTR_PMKID) - C2S(NL80211_ATTR_MAX_NUM_PMKIDS) - - C2S(NL80211_ATTR_DURATION) - - C2S(NL80211_ATTR_COOKIE) - - C2S(NL80211_ATTR_WIPHY_COVERAGE_CLASS) - - C2S(NL80211_ATTR_TX_RATES) - - C2S(NL80211_ATTR_FRAME_MATCH) - - C2S(NL80211_ATTR_ACK) - - C2S(NL80211_ATTR_PS_STATE) - - C2S(NL80211_ATTR_CQM) - - C2S(NL80211_ATTR_LOCAL_STATE_CHANGE) - - C2S(NL80211_ATTR_AP_ISOLATE) - - C2S(NL80211_ATTR_WIPHY_TX_POWER_SETTING) - C2S(NL80211_ATTR_WIPHY_TX_POWER_LEVEL) - - C2S(NL80211_ATTR_TX_FRAME_TYPES) - C2S(NL80211_ATTR_RX_FRAME_TYPES) - C2S(NL80211_ATTR_FRAME_TYPE) - - C2S(NL80211_ATTR_CONTROL_PORT_ETHERTYPE) - C2S(NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT) - - C2S(NL80211_ATTR_SUPPORT_IBSS_RSN) - - C2S(NL80211_ATTR_WIPHY_ANTENNA_TX) - C2S(NL80211_ATTR_WIPHY_ANTENNA_RX) - - C2S(NL80211_ATTR_MCAST_RATE) - - C2S(NL80211_ATTR_OFFCHANNEL_TX_OK) - - C2S(NL80211_ATTR_BSS_HT_OPMODE) - - C2S(NL80211_ATTR_KEY_DEFAULT_TYPES) - - C2S(NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION) - - C2S(NL80211_ATTR_MESH_SETUP) - - C2S(NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX) - C2S(NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX) - - C2S(NL80211_ATTR_SUPPORT_MESH_AUTH) - C2S(NL80211_ATTR_STA_PLINK_STATE) - - C2S(NL80211_ATTR_WOWLAN_TRIGGERS) - C2S(NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED) - - C2S(NL80211_ATTR_SCHED_SCAN_INTERVAL) - - C2S(NL80211_ATTR_INTERFACE_COMBINATIONS) - C2S(NL80211_ATTR_SOFTWARE_IFTYPES) - - C2S(NL80211_ATTR_REKEY_DATA) - - C2S(NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS) - C2S(NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN) - - C2S(NL80211_ATTR_SCAN_SUPP_RATES) - - C2S(NL80211_ATTR_HIDDEN_SSID) - - C2S(NL80211_ATTR_IE_PROBE_RESP) - C2S(NL80211_ATTR_IE_ASSOC_RESP) - - C2S(NL80211_ATTR_STA_WME) - C2S(NL80211_ATTR_SUPPORT_AP_UAPSD) - - C2S(NL80211_ATTR_ROAM_SUPPORT) - - C2S(NL80211_ATTR_SCHED_SCAN_MATCH) - C2S(NL80211_ATTR_MAX_MATCH_SETS) - - C2S(NL80211_ATTR_PMKSA_CANDIDATE) - - C2S(NL80211_ATTR_TX_NO_CCK_RATE) - - C2S(NL80211_ATTR_TDLS_ACTION) - C2S(NL80211_ATTR_TDLS_DIALOG_TOKEN) - C2S(NL80211_ATTR_TDLS_OPERATION) - C2S(NL80211_ATTR_TDLS_SUPPORT) - C2S(NL80211_ATTR_TDLS_EXTERNAL_SETUP) - - C2S(NL80211_ATTR_DEVICE_AP_SME) - - C2S(NL80211_ATTR_DONT_WAIT_FOR_ACK) - - C2S(NL80211_ATTR_FEATURE_FLAGS) - - C2S(NL80211_ATTR_PROBE_RESP_OFFLOAD) - - C2S(NL80211_ATTR_PROBE_RESP) - - C2S(NL80211_ATTR_DFS_REGION) - - C2S(NL80211_ATTR_DISABLE_HT) - C2S(NL80211_ATTR_HT_CAPABILITY_MASK) - - C2S(NL80211_ATTR_NOACK_MAP) - - C2S(NL80211_ATTR_INACTIVITY_TIMEOUT) - - C2S(NL80211_ATTR_RX_SIGNAL_DBM) - - C2S(NL80211_ATTR_BG_SCAN_PERIOD) - - C2S(NL80211_ATTR_WDEV) - - C2S(NL80211_ATTR_USER_REG_HINT_TYPE) - - C2S(NL80211_ATTR_CONN_FAILED_REASON) - - C2S(NL80211_ATTR_SAE_DATA) - - C2S(NL80211_ATTR_VHT_CAPABILITY) - - C2S(NL80211_ATTR_SCAN_FLAGS) - - C2S(NL80211_ATTR_CHANNEL_WIDTH) - C2S(NL80211_ATTR_CENTER_FREQ1) - C2S(NL80211_ATTR_CENTER_FREQ2) - - C2S(NL80211_ATTR_P2P_CTWINDOW) - C2S(NL80211_ATTR_P2P_OPPPS) - - C2S(NL80211_ATTR_LOCAL_MESH_POWER_MODE) - - C2S(NL80211_ATTR_ACL_POLICY) - - C2S(NL80211_ATTR_MAC_ADDRS) - - C2S(NL80211_ATTR_MAC_ACL_MAX) - - C2S(NL80211_ATTR_RADAR_EVENT) - - C2S(NL80211_ATTR_EXT_CAPA) - C2S(NL80211_ATTR_EXT_CAPA_MASK) - - C2S(NL80211_ATTR_STA_CAPABILITY) - C2S(NL80211_ATTR_STA_EXT_CAPABILITY) - - C2S(NL80211_ATTR_PROTOCOL_FEATURES) - C2S(NL80211_ATTR_SPLIT_WIPHY_DUMP) - - C2S(NL80211_ATTR_DISABLE_VHT) - C2S(NL80211_ATTR_VHT_CAPABILITY_MASK) - - C2S(NL80211_ATTR_MDID) - C2S(NL80211_ATTR_IE_RIC) - - C2S(NL80211_ATTR_CRIT_PROT_ID) - C2S(NL80211_ATTR_MAX_CRIT_PROT_DURATION) - - C2S(NL80211_ATTR_PEER_AID) - - - //S(NL80211_ATTR_VENDOR_ID) - C2S(NL80211_ATTR_VENDOR_SUBCMD) - C2S(NL80211_ATTR_VENDOR_DATA) - C2S(NL80211_ATTR_VENDOR_EVENTS) - - default: - return "NL80211_ATTR_UNKNOWN"; - } -} - -void WifiEvent::log() { - parse(); - - byte *data = (byte *)genlmsg_attrdata(mHeader, 0); - int len = genlmsg_attrlen(mHeader, 0); - ALOGD("cmd = %s, len = %d", get_cmdString(), len); - ALOGD("vendor_id = %04x, vendor_subcmd = %d", get_vendor_id(), get_vendor_subcmd()); - - for (int i = 0; i < len; i += 16) { - char line[81]; - int linelen = min(16, len - i); - int offset = 0; - appendFmt(line, offset, "%02x", data[i]); - for (int j = 1; j < linelen; j++) { - appendFmt(line, offset, " %02x", data[i+j]); - } - - for (int j = linelen; j < 16; j++) { - appendFmt(line, offset, " "); - } - - line[23] = '-'; - - appendFmt(line, offset, " "); - - for (int j = 0; j < linelen; j++) { - if (isprint(data[i+j])) { - appendFmt(line, offset, "%c", data[i+j]); - } else { - appendFmt(line, offset, "-"); - } - } - - ALOGD("%s", line); - } - - for (unsigned i = 0; i < NL80211_ATTR_MAX_INTERNAL; i++) { - if (mAttributes[i] != NULL) { - ALOGD("found attribute %s", attributeToString(i)); - } - } - - ALOGD("-- End of message --"); -} - -const char *WifiEvent::get_cmdString() { - return cmdToString(get_cmd()); -} - - -int WifiEvent::parse() { - if (mHeader != NULL) { - return WIFI_SUCCESS; - } - mHeader = (genlmsghdr *)nlmsg_data(nlmsg_hdr(mMsg)); - int result = nla_parse(mAttributes, NL80211_ATTR_MAX_INTERNAL, genlmsg_attrdata(mHeader, 0), - genlmsg_attrlen(mHeader, 0), NULL); - - ALOGD("event len = %d", nlmsg_hdr(mMsg)->nlmsg_len); - return result; -} - -int WifiRequest::create(int family, uint8_t cmd, int flags, int hdrlen) { - mMsg = nlmsg_alloc(); - if (mMsg != NULL) { - genlmsg_put(mMsg, /* pid = */ 0, /* seq = */ 0, family, - hdrlen, flags, cmd, /* version = */ 0); - return WIFI_SUCCESS; - } else { - return WIFI_ERROR_OUT_OF_MEMORY; - } -} - -int WifiRequest::create(uint32_t id, int subcmd) { - int res = create(NL80211_CMD_VENDOR); - if (res < 0) { - return res; - } - - res = put_u32(NL80211_ATTR_VENDOR_ID, id); - if (res < 0) { - return res; - } - - res = put_u32(NL80211_ATTR_VENDOR_SUBCMD, subcmd); - if (res < 0) { - return res; - } - - if (mIface != -1) { - res = set_iface_id(mIface); - } - - return res; -} - - -static int no_seq_check(struct nl_msg *msg, void *arg) -{ - return NL_OK; -} - -int WifiCommand::requestResponse() { - int err = create(); /* create the message */ - if (err < 0) { - return err; - } - - return requestResponse(mMsg); -} - -int WifiCommand::requestResponse(WifiRequest& request) { - int err = 0; - - struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT); - if (!cb) - goto out; - - err = nl_send_auto_complete(mInfo->cmd_sock, request.getMessage()); /* send message */ - if (err < 0) - goto out; - - err = 1; - - nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); - 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); - nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, response_handler, this); - - while (err > 0) { /* wait for reply */ - int res = nl_recvmsgs(mInfo->cmd_sock, cb); - if (res) { - ALOGE("nl80211: %s->nl_recvmsgs failed: %d", __func__, res); - } - } -out: - nl_cb_put(cb); - return err; -} - -int WifiCommand::requestEvent(int cmd) { - - ALOGD("requesting event %d", cmd); - - int res = wifi_register_handler(wifiHandle(), cmd, event_handler, this); - if (res < 0) { - return res; - } - - res = create(); /* create the message */ - if (res < 0) - goto out; - - ALOGD("waiting for response %d", cmd); - - res = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage()); /* send message */ - if (res < 0) - goto out; - - ALOGD("waiting for event %d", cmd); - res = mCondition.wait(); - if (res < 0) - goto out; - -out: - wifi_unregister_handler(wifiHandle(), cmd); - return res; -} - -int WifiCommand::requestVendorEvent(uint32_t id, int subcmd) { - - int res = wifi_register_vendor_handler(wifiHandle(), id, subcmd, event_handler, this); - if (res < 0) { - return res; - } - - res = create(); /* create the message */ - if (res < 0) - goto out; - - res = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage()); /* send message */ - if (res < 0) - goto out; - - res = mCondition.wait(); - if (res < 0) - goto out; - -out: - wifi_unregister_vendor_handler(wifiHandle(), id, subcmd); - return res; -} - -/* Event handlers */ -int WifiCommand::response_handler(struct nl_msg *msg, void *arg) { - ALOGD("response_handler called"); - WifiCommand *cmd = (WifiCommand *)arg; - WifiEvent reply(msg); - int res = reply.parse(); - if (res < 0) { - ALOGE("Failed to parse reply message = %d", res); - return NL_SKIP; - } else { - // reply.log(); - return cmd->handleResponse(reply); - } -} - -int WifiCommand::event_handler(struct nl_msg *msg, void *arg) { - WifiCommand *cmd = (WifiCommand *)arg; - WifiEvent event(msg); - int res = event.parse(); - if (res < 0) { - ALOGE("Failed to parse event = %d", res); - res = NL_SKIP; - } else { - res = cmd->handleEvent(event); - } - - cmd->mCondition.signal(); - return res; -} - -/* Other event handlers */ -int WifiCommand::valid_handler(struct nl_msg *msg, void *arg) { - ALOGD("valid_handler called"); - int *err = (int *)arg; - *err = 0; - return NL_SKIP; -} - -int WifiCommand::ack_handler(struct nl_msg *msg, void *arg) { - ALOGD("ack_handler called"); - int *err = (int *)arg; - *err = 0; - return NL_STOP; -} - -int WifiCommand::finish_handler(struct nl_msg *msg, void *arg) { - ALOGD("finish_handler called"); - int *ret = (int *)arg; - *ret = 0; - return NL_SKIP; -} - -int WifiCommand::error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) { - int *ret = (int *)arg; - *ret = err->error; - - ALOGD("error_handler received : %d", err->error); - return NL_SKIP; -} + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "wifi_hal.h" +#include "common.h" +#include "cpp_bindings.h" + +void appendFmt(char *buf, int &offset, const char *fmt, ...) +{ + va_list params; + va_start(params, fmt); + offset += vsprintf(buf + offset, fmt, params); + va_end(params); +} + +#define C2S(x) case x: return #x; + +static const char *cmdToString(int cmd) +{ + switch (cmd) { + C2S(NL80211_CMD_UNSPEC) + C2S(NL80211_CMD_GET_WIPHY) + C2S(NL80211_CMD_SET_WIPHY) + C2S(NL80211_CMD_NEW_WIPHY) + C2S(NL80211_CMD_DEL_WIPHY) + C2S(NL80211_CMD_GET_INTERFACE) + C2S(NL80211_CMD_SET_INTERFACE) + C2S(NL80211_CMD_NEW_INTERFACE) + C2S(NL80211_CMD_DEL_INTERFACE) + C2S(NL80211_CMD_GET_KEY) + C2S(NL80211_CMD_SET_KEY) + C2S(NL80211_CMD_NEW_KEY) + C2S(NL80211_CMD_DEL_KEY) + C2S(NL80211_CMD_GET_BEACON) + C2S(NL80211_CMD_SET_BEACON) + C2S(NL80211_CMD_START_AP) + C2S(NL80211_CMD_STOP_AP) + C2S(NL80211_CMD_GET_STATION) + C2S(NL80211_CMD_SET_STATION) + C2S(NL80211_CMD_NEW_STATION) + C2S(NL80211_CMD_DEL_STATION) + C2S(NL80211_CMD_GET_MPATH) + C2S(NL80211_CMD_SET_MPATH) + C2S(NL80211_CMD_NEW_MPATH) + C2S(NL80211_CMD_DEL_MPATH) + C2S(NL80211_CMD_SET_BSS) + C2S(NL80211_CMD_SET_REG) + C2S(NL80211_CMD_REQ_SET_REG) + C2S(NL80211_CMD_GET_MESH_CONFIG) + C2S(NL80211_CMD_SET_MESH_CONFIG) + C2S(NL80211_CMD_SET_MGMT_EXTRA_IE) + C2S(NL80211_CMD_GET_REG) + C2S(NL80211_CMD_GET_SCAN) + C2S(NL80211_CMD_TRIGGER_SCAN) + C2S(NL80211_CMD_NEW_SCAN_RESULTS) + C2S(NL80211_CMD_SCAN_ABORTED) + C2S(NL80211_CMD_REG_CHANGE) + C2S(NL80211_CMD_AUTHENTICATE) + C2S(NL80211_CMD_ASSOCIATE) + C2S(NL80211_CMD_DEAUTHENTICATE) + C2S(NL80211_CMD_DISASSOCIATE) + C2S(NL80211_CMD_MICHAEL_MIC_FAILURE) + C2S(NL80211_CMD_REG_BEACON_HINT) + C2S(NL80211_CMD_JOIN_IBSS) + C2S(NL80211_CMD_LEAVE_IBSS) + C2S(NL80211_CMD_TESTMODE) + C2S(NL80211_CMD_CONNECT) + C2S(NL80211_CMD_ROAM) + C2S(NL80211_CMD_DISCONNECT) + C2S(NL80211_CMD_SET_WIPHY_NETNS) + C2S(NL80211_CMD_GET_SURVEY) + C2S(NL80211_CMD_NEW_SURVEY_RESULTS) + C2S(NL80211_CMD_SET_PMKSA) + C2S(NL80211_CMD_DEL_PMKSA) + C2S(NL80211_CMD_FLUSH_PMKSA) + C2S(NL80211_CMD_REMAIN_ON_CHANNEL) + C2S(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL) + C2S(NL80211_CMD_SET_TX_BITRATE_MASK) + C2S(NL80211_CMD_REGISTER_FRAME) + C2S(NL80211_CMD_FRAME) + C2S(NL80211_CMD_FRAME_TX_STATUS) + C2S(NL80211_CMD_SET_POWER_SAVE) + C2S(NL80211_CMD_GET_POWER_SAVE) + C2S(NL80211_CMD_SET_CQM) + C2S(NL80211_CMD_NOTIFY_CQM) + C2S(NL80211_CMD_SET_CHANNEL) + C2S(NL80211_CMD_SET_WDS_PEER) + C2S(NL80211_CMD_FRAME_WAIT_CANCEL) + C2S(NL80211_CMD_JOIN_MESH) + C2S(NL80211_CMD_LEAVE_MESH) + C2S(NL80211_CMD_UNPROT_DEAUTHENTICATE) + C2S(NL80211_CMD_UNPROT_DISASSOCIATE) + C2S(NL80211_CMD_NEW_PEER_CANDIDATE) + C2S(NL80211_CMD_GET_WOWLAN) + C2S(NL80211_CMD_SET_WOWLAN) + C2S(NL80211_CMD_START_SCHED_SCAN) + C2S(NL80211_CMD_STOP_SCHED_SCAN) + C2S(NL80211_CMD_SCHED_SCAN_RESULTS) + C2S(NL80211_CMD_SCHED_SCAN_STOPPED) + C2S(NL80211_CMD_SET_REKEY_OFFLOAD) + C2S(NL80211_CMD_PMKSA_CANDIDATE) + C2S(NL80211_CMD_TDLS_OPER) + C2S(NL80211_CMD_TDLS_MGMT) + C2S(NL80211_CMD_UNEXPECTED_FRAME) + C2S(NL80211_CMD_PROBE_CLIENT) + C2S(NL80211_CMD_REGISTER_BEACONS) + C2S(NL80211_CMD_UNEXPECTED_4ADDR_FRAME) + C2S(NL80211_CMD_SET_NOACK_MAP) + C2S(NL80211_CMD_CH_SWITCH_NOTIFY) + C2S(NL80211_CMD_START_P2P_DEVICE) + C2S(NL80211_CMD_STOP_P2P_DEVICE) + C2S(NL80211_CMD_CONN_FAILED) + C2S(NL80211_CMD_SET_MCAST_RATE) + C2S(NL80211_CMD_SET_MAC_ACL) + C2S(NL80211_CMD_RADAR_DETECT) + C2S(NL80211_CMD_GET_PROTOCOL_FEATURES) + C2S(NL80211_CMD_UPDATE_FT_IES) + C2S(NL80211_CMD_FT_EVENT) + C2S(NL80211_CMD_CRIT_PROTOCOL_START) + C2S(NL80211_CMD_CRIT_PROTOCOL_STOP) + C2S(NL80211_CMD_VENDOR) + default: + return "NL80211_CMD_UNKNOWN"; + } +} + +const char *attributeToString(int attribute) +{ + switch (attribute) { + C2S(NL80211_ATTR_UNSPEC) + + C2S(NL80211_ATTR_WIPHY) + C2S(NL80211_ATTR_WIPHY_NAME) + + C2S(NL80211_ATTR_IFINDEX) + C2S(NL80211_ATTR_IFNAME) + C2S(NL80211_ATTR_IFTYPE) + + C2S(NL80211_ATTR_MAC) + + C2S(NL80211_ATTR_KEY_DATA) + C2S(NL80211_ATTR_KEY_IDX) + C2S(NL80211_ATTR_KEY_CIPHER) + C2S(NL80211_ATTR_KEY_SEQ) + C2S(NL80211_ATTR_KEY_DEFAULT) + + C2S(NL80211_ATTR_BEACON_INTERVAL) + C2S(NL80211_ATTR_DTIM_PERIOD) + C2S(NL80211_ATTR_BEACON_HEAD) + C2S(NL80211_ATTR_BEACON_TAIL) + + C2S(NL80211_ATTR_STA_AID) + C2S(NL80211_ATTR_STA_FLAGS) + C2S(NL80211_ATTR_STA_LISTEN_INTERVAL) + C2S(NL80211_ATTR_STA_SUPPORTED_RATES) + C2S(NL80211_ATTR_STA_VLAN) + C2S(NL80211_ATTR_STA_INFO) + + C2S(NL80211_ATTR_WIPHY_BANDS) + + C2S(NL80211_ATTR_MNTR_FLAGS) + + C2S(NL80211_ATTR_MESH_ID) + C2S(NL80211_ATTR_STA_PLINK_ACTION) + C2S(NL80211_ATTR_MPATH_NEXT_HOP) + C2S(NL80211_ATTR_MPATH_INFO) + + C2S(NL80211_ATTR_BSS_CTS_PROT) + C2S(NL80211_ATTR_BSS_SHORT_PREAMBLE) + C2S(NL80211_ATTR_BSS_SHORT_SLOT_TIME) + + C2S(NL80211_ATTR_HT_CAPABILITY) + + C2S(NL80211_ATTR_SUPPORTED_IFTYPES) + + C2S(NL80211_ATTR_REG_ALPHA2) + C2S(NL80211_ATTR_REG_RULES) + + C2S(NL80211_ATTR_MESH_CONFIG) + + C2S(NL80211_ATTR_BSS_BASIC_RATES) + + C2S(NL80211_ATTR_WIPHY_TXQ_PARAMS) + C2S(NL80211_ATTR_WIPHY_FREQ) + C2S(NL80211_ATTR_WIPHY_CHANNEL_TYPE) + + C2S(NL80211_ATTR_KEY_DEFAULT_MGMT) + + C2S(NL80211_ATTR_MGMT_SUBTYPE) + C2S(NL80211_ATTR_IE) + + C2S(NL80211_ATTR_MAX_NUM_SCAN_SSIDS) + + C2S(NL80211_ATTR_SCAN_FREQUENCIES) + C2S(NL80211_ATTR_SCAN_SSIDS) + C2S(NL80211_ATTR_GENERATION) /* replaces old SCAN_GENERATION */ + C2S(NL80211_ATTR_BSS) + + C2S(NL80211_ATTR_REG_INITIATOR) + C2S(NL80211_ATTR_REG_TYPE) + + C2S(NL80211_ATTR_SUPPORTED_COMMANDS) + + C2S(NL80211_ATTR_FRAME) + C2S(NL80211_ATTR_SSID) + C2S(NL80211_ATTR_AUTH_TYPE) + C2S(NL80211_ATTR_REASON_CODE) + + C2S(NL80211_ATTR_KEY_TYPE) + + C2S(NL80211_ATTR_MAX_SCAN_IE_LEN) + C2S(NL80211_ATTR_CIPHER_SUITES) + + C2S(NL80211_ATTR_FREQ_BEFORE) + C2S(NL80211_ATTR_FREQ_AFTER) + + C2S(NL80211_ATTR_FREQ_FIXED) + + + C2S(NL80211_ATTR_WIPHY_RETRY_SHORT) + C2S(NL80211_ATTR_WIPHY_RETRY_LONG) + C2S(NL80211_ATTR_WIPHY_FRAG_THRESHOLD) + C2S(NL80211_ATTR_WIPHY_RTS_THRESHOLD) + + C2S(NL80211_ATTR_TIMED_OUT) + + C2S(NL80211_ATTR_USE_MFP) + + C2S(NL80211_ATTR_STA_FLAGS2) + + C2S(NL80211_ATTR_CONTROL_PORT) + + C2S(NL80211_ATTR_TESTDATA) + + C2S(NL80211_ATTR_PRIVACY) + + C2S(NL80211_ATTR_DISCONNECTED_BY_AP) + C2S(NL80211_ATTR_STATUS_CODE) + + C2S(NL80211_ATTR_CIPHER_SUITES_PAIRWISE) + C2S(NL80211_ATTR_CIPHER_SUITE_GROUP) + C2S(NL80211_ATTR_WPA_VERSIONS) + C2S(NL80211_ATTR_AKM_SUITES) + + C2S(NL80211_ATTR_REQ_IE) + C2S(NL80211_ATTR_RESP_IE) + + C2S(NL80211_ATTR_PREV_BSSID) + + C2S(NL80211_ATTR_KEY) + C2S(NL80211_ATTR_KEYS) + + C2S(NL80211_ATTR_PID) + + C2S(NL80211_ATTR_4ADDR) + + C2S(NL80211_ATTR_SURVEY_INFO) + + C2S(NL80211_ATTR_PMKID) + C2S(NL80211_ATTR_MAX_NUM_PMKIDS) + + C2S(NL80211_ATTR_DURATION) + + C2S(NL80211_ATTR_COOKIE) + + C2S(NL80211_ATTR_WIPHY_COVERAGE_CLASS) + + C2S(NL80211_ATTR_TX_RATES) + + C2S(NL80211_ATTR_FRAME_MATCH) + + C2S(NL80211_ATTR_ACK) + + C2S(NL80211_ATTR_PS_STATE) + + C2S(NL80211_ATTR_CQM) + + C2S(NL80211_ATTR_LOCAL_STATE_CHANGE) + + C2S(NL80211_ATTR_AP_ISOLATE) + + C2S(NL80211_ATTR_WIPHY_TX_POWER_SETTING) + C2S(NL80211_ATTR_WIPHY_TX_POWER_LEVEL) + + C2S(NL80211_ATTR_TX_FRAME_TYPES) + C2S(NL80211_ATTR_RX_FRAME_TYPES) + C2S(NL80211_ATTR_FRAME_TYPE) + + C2S(NL80211_ATTR_CONTROL_PORT_ETHERTYPE) + C2S(NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT) + + C2S(NL80211_ATTR_SUPPORT_IBSS_RSN) + + C2S(NL80211_ATTR_WIPHY_ANTENNA_TX) + C2S(NL80211_ATTR_WIPHY_ANTENNA_RX) + + C2S(NL80211_ATTR_MCAST_RATE) + + C2S(NL80211_ATTR_OFFCHANNEL_TX_OK) + + C2S(NL80211_ATTR_BSS_HT_OPMODE) + + C2S(NL80211_ATTR_KEY_DEFAULT_TYPES) + + C2S(NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION) + + C2S(NL80211_ATTR_MESH_SETUP) + + C2S(NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX) + C2S(NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX) + + C2S(NL80211_ATTR_SUPPORT_MESH_AUTH) + C2S(NL80211_ATTR_STA_PLINK_STATE) + + C2S(NL80211_ATTR_WOWLAN_TRIGGERS) + C2S(NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED) + + C2S(NL80211_ATTR_SCHED_SCAN_INTERVAL) + + C2S(NL80211_ATTR_INTERFACE_COMBINATIONS) + C2S(NL80211_ATTR_SOFTWARE_IFTYPES) + + C2S(NL80211_ATTR_REKEY_DATA) + + C2S(NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS) + C2S(NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN) + + C2S(NL80211_ATTR_SCAN_SUPP_RATES) + + C2S(NL80211_ATTR_HIDDEN_SSID) + + C2S(NL80211_ATTR_IE_PROBE_RESP) + C2S(NL80211_ATTR_IE_ASSOC_RESP) + + C2S(NL80211_ATTR_STA_WME) + C2S(NL80211_ATTR_SUPPORT_AP_UAPSD) + + C2S(NL80211_ATTR_ROAM_SUPPORT) + + C2S(NL80211_ATTR_SCHED_SCAN_MATCH) + C2S(NL80211_ATTR_MAX_MATCH_SETS) + + C2S(NL80211_ATTR_PMKSA_CANDIDATE) + + C2S(NL80211_ATTR_TX_NO_CCK_RATE) + + C2S(NL80211_ATTR_TDLS_ACTION) + C2S(NL80211_ATTR_TDLS_DIALOG_TOKEN) + C2S(NL80211_ATTR_TDLS_OPERATION) + C2S(NL80211_ATTR_TDLS_SUPPORT) + C2S(NL80211_ATTR_TDLS_EXTERNAL_SETUP) + + C2S(NL80211_ATTR_DEVICE_AP_SME) + + C2S(NL80211_ATTR_DONT_WAIT_FOR_ACK) + + C2S(NL80211_ATTR_FEATURE_FLAGS) + + C2S(NL80211_ATTR_PROBE_RESP_OFFLOAD) + + C2S(NL80211_ATTR_PROBE_RESP) + + C2S(NL80211_ATTR_DFS_REGION) + + C2S(NL80211_ATTR_DISABLE_HT) + C2S(NL80211_ATTR_HT_CAPABILITY_MASK) + + C2S(NL80211_ATTR_NOACK_MAP) + + C2S(NL80211_ATTR_INACTIVITY_TIMEOUT) + + C2S(NL80211_ATTR_RX_SIGNAL_DBM) + + C2S(NL80211_ATTR_BG_SCAN_PERIOD) + + C2S(NL80211_ATTR_WDEV) + + C2S(NL80211_ATTR_USER_REG_HINT_TYPE) + + C2S(NL80211_ATTR_CONN_FAILED_REASON) + + C2S(NL80211_ATTR_SAE_DATA) + + C2S(NL80211_ATTR_VHT_CAPABILITY) + + C2S(NL80211_ATTR_SCAN_FLAGS) + + C2S(NL80211_ATTR_CHANNEL_WIDTH) + C2S(NL80211_ATTR_CENTER_FREQ1) + C2S(NL80211_ATTR_CENTER_FREQ2) + + C2S(NL80211_ATTR_P2P_CTWINDOW) + C2S(NL80211_ATTR_P2P_OPPPS) + + C2S(NL80211_ATTR_LOCAL_MESH_POWER_MODE) + + C2S(NL80211_ATTR_ACL_POLICY) + + C2S(NL80211_ATTR_MAC_ADDRS) + + C2S(NL80211_ATTR_MAC_ACL_MAX) + + C2S(NL80211_ATTR_RADAR_EVENT) + + C2S(NL80211_ATTR_EXT_CAPA) + C2S(NL80211_ATTR_EXT_CAPA_MASK) + + C2S(NL80211_ATTR_STA_CAPABILITY) + C2S(NL80211_ATTR_STA_EXT_CAPABILITY) + + C2S(NL80211_ATTR_PROTOCOL_FEATURES) + C2S(NL80211_ATTR_SPLIT_WIPHY_DUMP) + + C2S(NL80211_ATTR_DISABLE_VHT) + C2S(NL80211_ATTR_VHT_CAPABILITY_MASK) + + C2S(NL80211_ATTR_MDID) + C2S(NL80211_ATTR_IE_RIC) + + C2S(NL80211_ATTR_CRIT_PROT_ID) + C2S(NL80211_ATTR_MAX_CRIT_PROT_DURATION) + + C2S(NL80211_ATTR_PEER_AID) + + + //S(NL80211_ATTR_VENDOR_ID) + C2S(NL80211_ATTR_VENDOR_SUBCMD) + C2S(NL80211_ATTR_VENDOR_DATA) + C2S(NL80211_ATTR_VENDOR_EVENTS) + + default: + return "NL80211_ATTR_UNKNOWN"; + } +} + +void WifiEvent::log() { + parse(); + + byte *data = (byte *)genlmsg_attrdata(mHeader, 0); + int len = genlmsg_attrlen(mHeader, 0); + ALOGD("cmd = %s, len = %d", get_cmdString(), len); + ALOGD("vendor_id = %04x, vendor_subcmd = %d", get_vendor_id(), get_vendor_subcmd()); + + for (int i = 0; i < len; i += 16) { + char line[81]; + int linelen = min(16, len - i); + int offset = 0; + appendFmt(line, offset, "%02x", data[i]); + for (int j = 1; j < linelen; j++) { + appendFmt(line, offset, " %02x", data[i+j]); + } + + for (int j = linelen; j < 16; j++) { + appendFmt(line, offset, " "); + } + + line[23] = '-'; + + appendFmt(line, offset, " "); + + for (int j = 0; j < linelen; j++) { + if (isprint(data[i+j])) { + appendFmt(line, offset, "%c", data[i+j]); + } else { + appendFmt(line, offset, "-"); + } + } + + ALOGD("%s", line); + } + + for (unsigned i = 0; i < NL80211_ATTR_MAX_INTERNAL; i++) { + if (mAttributes[i] != NULL) { + ALOGD("found attribute %s", attributeToString(i)); + } + } + + ALOGD("-- End of message --"); +} + +const char *WifiEvent::get_cmdString() { + return cmdToString(get_cmd()); +} + + +int WifiEvent::parse() { + if (mHeader != NULL) { + return WIFI_SUCCESS; + } + mHeader = (genlmsghdr *)nlmsg_data(nlmsg_hdr(mMsg)); + int result = nla_parse(mAttributes, NL80211_ATTR_MAX_INTERNAL, genlmsg_attrdata(mHeader, 0), + genlmsg_attrlen(mHeader, 0), NULL); + + ALOGD("event len = %d", nlmsg_hdr(mMsg)->nlmsg_len); + return result; +} + +int WifiRequest::create(int family, uint8_t cmd, int flags, int hdrlen) { + mMsg = nlmsg_alloc(); + if (mMsg != NULL) { + genlmsg_put(mMsg, /* pid = */ 0, /* seq = */ 0, family, + hdrlen, flags, cmd, /* version = */ 0); + return WIFI_SUCCESS; + } else { + return WIFI_ERROR_OUT_OF_MEMORY; + } +} + +int WifiRequest::create(uint32_t id, int subcmd) { + int res = create(NL80211_CMD_VENDOR); + if (res < 0) { + return res; + } + + res = put_u32(NL80211_ATTR_VENDOR_ID, id); + if (res < 0) { + return res; + } + + res = put_u32(NL80211_ATTR_VENDOR_SUBCMD, subcmd); + if (res < 0) { + return res; + } + + if (mIface != -1) { + res = set_iface_id(mIface); + } + + return res; +} + + +static int no_seq_check(struct nl_msg *msg, void *arg) +{ + return NL_OK; +} + +int WifiCommand::requestResponse() { + int err = create(); /* create the message */ + if (err < 0) { + return err; + } + + return requestResponse(mMsg); +} + +int WifiCommand::requestResponse(WifiRequest& request) { + int err = 0; + + struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT); + if (!cb) + goto out; + + err = nl_send_auto_complete(mInfo->cmd_sock, request.getMessage()); /* send message */ + if (err < 0) + goto out; + + err = 1; + + nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); + 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); + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, response_handler, this); + + while (err > 0) { /* wait for reply */ + int res = nl_recvmsgs(mInfo->cmd_sock, cb); + if (res) { + ALOGE("nl80211: %s->nl_recvmsgs failed: %d", __func__, res); + } + } +out: + nl_cb_put(cb); + return err; +} + +int WifiCommand::requestEvent(int cmd) { + + ALOGD("requesting event %d", cmd); + + int res = wifi_register_handler(wifiHandle(), cmd, event_handler, this); + if (res < 0) { + return res; + } + + res = create(); /* create the message */ + if (res < 0) + goto out; + + ALOGD("waiting for response %d", cmd); + + res = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage()); /* send message */ + if (res < 0) + goto out; + + ALOGD("waiting for event %d", cmd); + res = mCondition.wait(); + if (res < 0) + goto out; + +out: + wifi_unregister_handler(wifiHandle(), cmd); + return res; +} + +int WifiCommand::requestVendorEvent(uint32_t id, int subcmd) { + + int res = wifi_register_vendor_handler(wifiHandle(), id, subcmd, event_handler, this); + if (res < 0) { + return res; + } + + res = create(); /* create the message */ + if (res < 0) + goto out; + + res = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage()); /* send message */ + if (res < 0) + goto out; + + res = mCondition.wait(); + if (res < 0) + goto out; + +out: + wifi_unregister_vendor_handler(wifiHandle(), id, subcmd); + return res; +} + +/* Event handlers */ +int WifiCommand::response_handler(struct nl_msg *msg, void *arg) { + ALOGD("response_handler called"); + WifiCommand *cmd = (WifiCommand *)arg; + WifiEvent reply(msg); + int res = reply.parse(); + if (res < 0) { + ALOGE("Failed to parse reply message = %d", res); + return NL_SKIP; + } else { + // reply.log(); + return cmd->handleResponse(reply); + } +} + +int WifiCommand::event_handler(struct nl_msg *msg, void *arg) { + WifiCommand *cmd = (WifiCommand *)arg; + WifiEvent event(msg); + int res = event.parse(); + if (res < 0) { + ALOGE("Failed to parse event = %d", res); + res = NL_SKIP; + } else { + res = cmd->handleEvent(event); + } + + cmd->mCondition.signal(); + return res; +} + +/* Other event handlers */ +int WifiCommand::valid_handler(struct nl_msg *msg, void *arg) { + ALOGD("valid_handler called"); + int *err = (int *)arg; + *err = 0; + return NL_SKIP; +} + +int WifiCommand::ack_handler(struct nl_msg *msg, void *arg) { + ALOGD("ack_handler called"); + int *err = (int *)arg; + *err = 0; + return NL_STOP; +} + +int WifiCommand::finish_handler(struct nl_msg *msg, void *arg) { + ALOGD("finish_handler called"); + int *ret = (int *)arg; + *ret = 0; + return NL_SKIP; +} + +int WifiCommand::error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) { + int *ret = (int *)arg; + *ret = err->error; + + ALOGD("error_handler received : %d", err->error); + return NL_SKIP; +} diff --git a/cpp_bindings.h b/cpp_bindings.h index 65f0f4e..491c398 100755 --- a/cpp_bindings.h +++ b/cpp_bindings.h @@ -1,346 +1,346 @@ - -#include "wifi_hal.h" -#include "common.h" -#include "sync.h" - -class WifiEvent -{ - /* TODO: remove this when nl headers are updated */ - static const unsigned NL80211_ATTR_MAX_INTERNAL = 256; -private: - struct nl_msg *mMsg; - struct genlmsghdr *mHeader; - struct nlattr *mAttributes[NL80211_ATTR_MAX_INTERNAL + 1]; - -public: - WifiEvent(nl_msg *msg) { - mMsg = msg; - mHeader = NULL; - memset(mAttributes, 0, sizeof(mAttributes)); - } - ~WifiEvent() { - /* don't destroy mMsg; it doesn't belong to us */ - } - - void log(); - - int parse(); - - genlmsghdr *header() { - return mHeader; - } - - int get_cmd() { - return mHeader->cmd; - } - - int get_vendor_id() { - return get_u32(NL80211_ATTR_VENDOR_ID); - } - - int get_vendor_subcmd() { - return get_u32(NL80211_ATTR_VENDOR_SUBCMD); - } - - void *get_vendor_data() { - return get_data(NL80211_ATTR_VENDOR_DATA); - } - - int get_vendor_data_len() { - return get_len(NL80211_ATTR_VENDOR_DATA); - } - - const char *get_cmdString(); - - nlattr ** attributes() { - return mAttributes; - } - - nlattr *get_attribute(int attribute) { - return mAttributes[attribute]; - } - - uint8_t get_u8(int attribute) { - return mAttributes[attribute] ? nla_get_u8(mAttributes[attribute]) : 0; - } - - uint16_t get_u16(int attribute) { - return mAttributes[attribute] ? nla_get_u16(mAttributes[attribute]) : 0; - } - - uint32_t get_u32(int attribute) { - return mAttributes[attribute] ? nla_get_u32(mAttributes[attribute]) : 0; - } - - uint64_t get_u64(int attribute) { - return mAttributes[attribute] ? nla_get_u64(mAttributes[attribute]) : 0; - } - - int get_len(int attribute) { - return mAttributes[attribute] ? nla_len(mAttributes[attribute]) : 0; - } - - void *get_data(int attribute) { - return mAttributes[attribute] ? nla_data(mAttributes[attribute]) : NULL; - } - -private: - WifiEvent(const WifiEvent&); // hide copy constructor to prevent copies -}; - -class nl_iterator { - struct nlattr *pos; - int rem; -public: - nl_iterator(struct nlattr *attr) { - pos = (struct nlattr *)nla_data(attr); - rem = nla_len(attr); - } - bool has_next() { - return nla_ok(pos, rem); - } - void next() { - pos = (struct nlattr *)nla_next(pos, &(rem)); - } - struct nlattr *get() { - return pos; - } - uint16_t get_type() { - return pos->nla_type; - } - uint8_t get_u8() { - return nla_get_u8(pos); - } - uint16_t get_u16() { - return nla_get_u16(pos); - } - uint32_t get_u32() { - return nla_get_u32(pos); - } - uint64_t get_u64() { - return nla_get_u64(pos); - } - void* get_data() { - return nla_data(pos); - } - int get_len() { - return nla_len(pos); - } -private: - nl_iterator(const nl_iterator&); // hide copy constructor to prevent copies -}; - -class WifiRequest -{ -private: - int mFamily; - int mIface; - struct nl_msg *mMsg; - -public: - WifiRequest(int family) { - mMsg = NULL; - mFamily = family; - mIface = -1; - } - - WifiRequest(int family, int iface) { - mMsg = NULL; - mFamily = family; - mIface = iface; - } - - ~WifiRequest() { - destroy(); - } - - void destroy() { - if (mMsg) { - nlmsg_free(mMsg); - mMsg = NULL; - } - } - - nl_msg *getMessage() { - return mMsg; - } - - /* Command assembly helpers */ - int create(int family, uint8_t cmd, int flags, int hdrlen); - int create(uint8_t cmd) { - return create(mFamily, cmd, 0, 0); - } - - int create(uint32_t id, int subcmd); - - int put(int attribute, void *ptr, unsigned len) { - return nla_put(mMsg, attribute, len, ptr); - } - int put_u8(int attribute, uint8_t value) { - return nla_put(mMsg, attribute, sizeof(value), &value); - } - int put_u16(int attribute, uint16_t value) { - return nla_put(mMsg, attribute, sizeof(value), &value); - } - int put_u32(int attribute, uint32_t value) { - return nla_put(mMsg, attribute, sizeof(value), &value); - } - int put_u64(int attribute, uint64_t value) { - return nla_put(mMsg, attribute, sizeof(value), &value); - } - int put_string(int attribute, const char *value) { - return nla_put(mMsg, attribute, strlen(value) + 1, value); - } - int put_addr(int attribute, mac_addr value) { - return nla_put(mMsg, attribute, sizeof(mac_addr), value); - } - - struct nlattr * attr_start(int attribute) { - return nla_nest_start(mMsg, attribute); - } - void attr_end(struct nlattr *attr) { - nla_nest_end(mMsg, attr); - } - - int set_iface_id(int ifindex) { - return put_u32(NL80211_ATTR_IFINDEX, ifindex); - } -private: - WifiRequest(const WifiRequest&); // hide copy constructor to prevent copies - -}; - -class WifiCommand -{ -protected: - hal_info *mInfo; - WifiRequest mMsg; - Condition mCondition; - wifi_request_id mId; - interface_info *mIfaceInfo; - int mRefs; -public: - WifiCommand(wifi_handle handle, wifi_request_id id) - : mMsg(getHalInfo(handle)->nl80211_family_id), mId(id), mRefs(1) - { - mIfaceInfo = NULL; - mInfo = getHalInfo(handle); - // ALOGD("WifiCommand %p created, mInfo = %p, mIfaceInfo = %p", this, mInfo, mIfaceInfo); - } - - WifiCommand(wifi_interface_handle iface, wifi_request_id id) - : mMsg(getHalInfo(iface)->nl80211_family_id, getIfaceInfo(iface)->id), mId(id), mRefs(1) - { - mIfaceInfo = getIfaceInfo(iface); - mInfo = getHalInfo(iface); - // ALOGD("WifiCommand %p created, mInfo = %p, mIfaceInfo = %p", this, mInfo, mIfaceInfo); - } - - virtual ~WifiCommand() { - // ALOGD("WifiCommand %p destroyed", this); - } - - wifi_request_id id() { - return mId; - } - - virtual void addRef() { - int refs = __sync_add_and_fetch(&mRefs, 1); - // ALOGD("addRef: WifiCommand %p has %d references", this, refs); - } - - virtual void releaseRef() { - int refs = __sync_sub_and_fetch(&mRefs, 1); - if (refs == 0) { - delete this; - } else { - // ALOGD("releaseRef: WifiCommand %p has %d references", this, refs); - } - } - - virtual int create() { - /* by default there is no way to cancel */ - ALOGD("WifiCommand %p can't be created", this); - return WIFI_ERROR_NOT_SUPPORTED; - } - - virtual int cancel() { - /* by default there is no way to cancel */ - return WIFI_ERROR_NOT_SUPPORTED; - } - - int requestResponse(); - int requestEvent(int cmd); - int requestVendorEvent(uint32_t id, int subcmd); - int requestResponse(WifiRequest& request); - -protected: - wifi_handle wifiHandle() { - return getWifiHandle(mInfo); - } - - wifi_interface_handle ifaceHandle() { - return getIfaceHandle(mIfaceInfo); - } - - int familyId() { - return mInfo->nl80211_family_id; - } - - int ifaceId() { - return mIfaceInfo->id; - } - - /* Override this method to parse reply and dig out data; save it in the object */ - virtual int handleResponse(WifiEvent& reply) { - ALOGI("skipping a response"); - return NL_SKIP; - } - - /* Override this method to parse event and dig out data; save it in the object */ - virtual int handleEvent(WifiEvent& event) { - ALOGI("skipping an event"); - return NL_SKIP; - } - - int registerHandler(int cmd) { - return wifi_register_handler(wifiHandle(), cmd, &event_handler, this); - } - - void unregisterHandler(int cmd) { - wifi_unregister_handler(wifiHandle(), cmd); - } - - int registerVendorHandler(uint32_t id, int subcmd) { - return wifi_register_vendor_handler(wifiHandle(), id, subcmd, &event_handler, this); - } - - void unregisterVendorHandler(uint32_t id, int subcmd) { - wifi_unregister_vendor_handler(wifiHandle(), id, subcmd); - } - -private: - WifiCommand(const WifiCommand& ); // hide copy constructor to prevent copies - - /* Event handling */ - static int response_handler(struct nl_msg *msg, void *arg); - - static int event_handler(struct nl_msg *msg, void *arg); - - /* Other event handlers */ - static int valid_handler(struct nl_msg *msg, void *arg); - - static int ack_handler(struct nl_msg *msg, void *arg); - - static int finish_handler(struct nl_msg *msg, void *arg); - - static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg); -}; - -/* nl message processing macros (required to pass C++ type checks) */ - -#define for_each_attr(pos, nla, rem) \ - for (pos = (nlattr *)nla_data(nla), rem = nla_len(nla); \ - nla_ok(pos, rem); \ - pos = (nlattr *)nla_next(pos, &(rem))) - + +#include "wifi_hal.h" +#include "common.h" +#include "sync.h" + +class WifiEvent +{ + /* TODO: remove this when nl headers are updated */ + static const unsigned NL80211_ATTR_MAX_INTERNAL = 256; +private: + struct nl_msg *mMsg; + struct genlmsghdr *mHeader; + struct nlattr *mAttributes[NL80211_ATTR_MAX_INTERNAL + 1]; + +public: + WifiEvent(nl_msg *msg) { + mMsg = msg; + mHeader = NULL; + memset(mAttributes, 0, sizeof(mAttributes)); + } + ~WifiEvent() { + /* don't destroy mMsg; it doesn't belong to us */ + } + + void log(); + + int parse(); + + genlmsghdr *header() { + return mHeader; + } + + int get_cmd() { + return mHeader->cmd; + } + + int get_vendor_id() { + return get_u32(NL80211_ATTR_VENDOR_ID); + } + + int get_vendor_subcmd() { + return get_u32(NL80211_ATTR_VENDOR_SUBCMD); + } + + void *get_vendor_data() { + return get_data(NL80211_ATTR_VENDOR_DATA); + } + + int get_vendor_data_len() { + return get_len(NL80211_ATTR_VENDOR_DATA); + } + + const char *get_cmdString(); + + nlattr ** attributes() { + return mAttributes; + } + + nlattr *get_attribute(int attribute) { + return mAttributes[attribute]; + } + + uint8_t get_u8(int attribute) { + return mAttributes[attribute] ? nla_get_u8(mAttributes[attribute]) : 0; + } + + uint16_t get_u16(int attribute) { + return mAttributes[attribute] ? nla_get_u16(mAttributes[attribute]) : 0; + } + + uint32_t get_u32(int attribute) { + return mAttributes[attribute] ? nla_get_u32(mAttributes[attribute]) : 0; + } + + uint64_t get_u64(int attribute) { + return mAttributes[attribute] ? nla_get_u64(mAttributes[attribute]) : 0; + } + + int get_len(int attribute) { + return mAttributes[attribute] ? nla_len(mAttributes[attribute]) : 0; + } + + void *get_data(int attribute) { + return mAttributes[attribute] ? nla_data(mAttributes[attribute]) : NULL; + } + +private: + WifiEvent(const WifiEvent&); // hide copy constructor to prevent copies +}; + +class nl_iterator { + struct nlattr *pos; + int rem; +public: + nl_iterator(struct nlattr *attr) { + pos = (struct nlattr *)nla_data(attr); + rem = nla_len(attr); + } + bool has_next() { + return nla_ok(pos, rem); + } + void next() { + pos = (struct nlattr *)nla_next(pos, &(rem)); + } + struct nlattr *get() { + return pos; + } + uint16_t get_type() { + return pos->nla_type; + } + uint8_t get_u8() { + return nla_get_u8(pos); + } + uint16_t get_u16() { + return nla_get_u16(pos); + } + uint32_t get_u32() { + return nla_get_u32(pos); + } + uint64_t get_u64() { + return nla_get_u64(pos); + } + void* get_data() { + return nla_data(pos); + } + int get_len() { + return nla_len(pos); + } +private: + nl_iterator(const nl_iterator&); // hide copy constructor to prevent copies +}; + +class WifiRequest +{ +private: + int mFamily; + int mIface; + struct nl_msg *mMsg; + +public: + WifiRequest(int family) { + mMsg = NULL; + mFamily = family; + mIface = -1; + } + + WifiRequest(int family, int iface) { + mMsg = NULL; + mFamily = family; + mIface = iface; + } + + ~WifiRequest() { + destroy(); + } + + void destroy() { + if (mMsg) { + nlmsg_free(mMsg); + mMsg = NULL; + } + } + + nl_msg *getMessage() { + return mMsg; + } + + /* Command assembly helpers */ + int create(int family, uint8_t cmd, int flags, int hdrlen); + int create(uint8_t cmd) { + return create(mFamily, cmd, 0, 0); + } + + int create(uint32_t id, int subcmd); + + int put(int attribute, void *ptr, unsigned len) { + return nla_put(mMsg, attribute, len, ptr); + } + int put_u8(int attribute, uint8_t value) { + return nla_put(mMsg, attribute, sizeof(value), &value); + } + int put_u16(int attribute, uint16_t value) { + return nla_put(mMsg, attribute, sizeof(value), &value); + } + int put_u32(int attribute, uint32_t value) { + return nla_put(mMsg, attribute, sizeof(value), &value); + } + int put_u64(int attribute, uint64_t value) { + return nla_put(mMsg, attribute, sizeof(value), &value); + } + int put_string(int attribute, const char *value) { + return nla_put(mMsg, attribute, strlen(value) + 1, value); + } + int put_addr(int attribute, mac_addr value) { + return nla_put(mMsg, attribute, sizeof(mac_addr), value); + } + + struct nlattr * attr_start(int attribute) { + return nla_nest_start(mMsg, attribute); + } + void attr_end(struct nlattr *attr) { + nla_nest_end(mMsg, attr); + } + + int set_iface_id(int ifindex) { + return put_u32(NL80211_ATTR_IFINDEX, ifindex); + } +private: + WifiRequest(const WifiRequest&); // hide copy constructor to prevent copies + +}; + +class WifiCommand +{ +protected: + hal_info *mInfo; + WifiRequest mMsg; + Condition mCondition; + wifi_request_id mId; + interface_info *mIfaceInfo; + int mRefs; +public: + WifiCommand(wifi_handle handle, wifi_request_id id) + : mMsg(getHalInfo(handle)->nl80211_family_id), mId(id), mRefs(1) + { + mIfaceInfo = NULL; + mInfo = getHalInfo(handle); + // ALOGD("WifiCommand %p created, mInfo = %p, mIfaceInfo = %p", this, mInfo, mIfaceInfo); + } + + WifiCommand(wifi_interface_handle iface, wifi_request_id id) + : mMsg(getHalInfo(iface)->nl80211_family_id, getIfaceInfo(iface)->id), mId(id), mRefs(1) + { + mIfaceInfo = getIfaceInfo(iface); + mInfo = getHalInfo(iface); + // ALOGD("WifiCommand %p created, mInfo = %p, mIfaceInfo = %p", this, mInfo, mIfaceInfo); + } + + virtual ~WifiCommand() { + // ALOGD("WifiCommand %p destroyed", this); + } + + wifi_request_id id() { + return mId; + } + + virtual void addRef() { + int refs = __sync_add_and_fetch(&mRefs, 1); + // ALOGD("addRef: WifiCommand %p has %d references", this, refs); + } + + virtual void releaseRef() { + int refs = __sync_sub_and_fetch(&mRefs, 1); + if (refs == 0) { + delete this; + } else { + // ALOGD("releaseRef: WifiCommand %p has %d references", this, refs); + } + } + + virtual int create() { + /* by default there is no way to cancel */ + ALOGD("WifiCommand %p can't be created", this); + return WIFI_ERROR_NOT_SUPPORTED; + } + + virtual int cancel() { + /* by default there is no way to cancel */ + return WIFI_ERROR_NOT_SUPPORTED; + } + + int requestResponse(); + int requestEvent(int cmd); + int requestVendorEvent(uint32_t id, int subcmd); + int requestResponse(WifiRequest& request); + +protected: + wifi_handle wifiHandle() { + return getWifiHandle(mInfo); + } + + wifi_interface_handle ifaceHandle() { + return getIfaceHandle(mIfaceInfo); + } + + int familyId() { + return mInfo->nl80211_family_id; + } + + int ifaceId() { + return mIfaceInfo->id; + } + + /* Override this method to parse reply and dig out data; save it in the object */ + virtual int handleResponse(WifiEvent& reply) { + ALOGI("skipping a response"); + return NL_SKIP; + } + + /* Override this method to parse event and dig out data; save it in the object */ + virtual int handleEvent(WifiEvent& event) { + ALOGI("skipping an event"); + return NL_SKIP; + } + + int registerHandler(int cmd) { + return wifi_register_handler(wifiHandle(), cmd, &event_handler, this); + } + + void unregisterHandler(int cmd) { + wifi_unregister_handler(wifiHandle(), cmd); + } + + int registerVendorHandler(uint32_t id, int subcmd) { + return wifi_register_vendor_handler(wifiHandle(), id, subcmd, &event_handler, this); + } + + void unregisterVendorHandler(uint32_t id, int subcmd) { + wifi_unregister_vendor_handler(wifiHandle(), id, subcmd); + } + +private: + WifiCommand(const WifiCommand& ); // hide copy constructor to prevent copies + + /* Event handling */ + static int response_handler(struct nl_msg *msg, void *arg); + + static int event_handler(struct nl_msg *msg, void *arg); + + /* Other event handlers */ + static int valid_handler(struct nl_msg *msg, void *arg); + + static int ack_handler(struct nl_msg *msg, void *arg); + + static int finish_handler(struct nl_msg *msg, void *arg); + + static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg); +}; + +/* nl message processing macros (required to pass C++ type checks) */ + +#define for_each_attr(pos, nla, rem) \ + for (pos = (nlattr *)nla_data(nla), rem = nla_len(nla); \ + nla_ok(pos, rem); \ + pos = (nlattr *)nla_next(pos, &(rem))) + diff --git a/gscan.cpp b/gscan.cpp index a0e7313..a303ddc 100755 --- a/gscan.cpp +++ b/gscan.cpp @@ -1,1062 +1,1062 @@ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "sync.h" - -#define LOG_TAG "WifiHAL" - -#include - -#include "wifi_hal.h" -#include "common.h" -#include "cpp_bindings.h" - -typedef enum { - - GSCAN_ATTRIBUTE_NUM_BUCKETS = 10, - GSCAN_ATTRIBUTE_BASE_PERIOD, - GSCAN_ATTRIBUTE_BUCKETS_BAND, - GSCAN_ATTRIBUTE_BUCKET_ID, - GSCAN_ATTRIBUTE_BUCKET_PERIOD, - GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, - GSCAN_ATTRIBUTE_BUCKET_CHANNELS, - GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, - GSCAN_ATTRIBUTE_REPORT_THRESHOLD, - GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, - GSCAN_ATTRIBUTE_REPORT_THRESHOLD_NUM_SCANS, - GSCAN_ATTRIBUTE_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND, - - GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20, - GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, /* indicates no more results */ - GSCAN_ATTRIBUTE_REPORT_EVENTS, - - /* remaining reserved for additional attributes */ - GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30, - GSCAN_ATTRIBUTE_SCAN_RESULTS, /* flat array of wifi_scan_result */ - GSCAN_ATTRIBUTE_NUM_CHANNELS, - GSCAN_ATTRIBUTE_CHANNEL_LIST, - GSCAN_ATTRIBUTE_SCAN_ID, - GSCAN_ATTRIBUTE_SCAN_FLAGS, - - /* remaining reserved for additional attributes */ - - GSCAN_ATTRIBUTE_SSID = 40, - GSCAN_ATTRIBUTE_BSSID, - GSCAN_ATTRIBUTE_CHANNEL, - GSCAN_ATTRIBUTE_RSSI, - GSCAN_ATTRIBUTE_TIMESTAMP, - GSCAN_ATTRIBUTE_RTT, - GSCAN_ATTRIBUTE_RTTSD, - - /* remaining reserved for additional attributes */ - - GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50, - GSCAN_ATTRIBUTE_RSSI_LOW, - GSCAN_ATTRIBUTE_RSSI_HIGH, - GSCAN_ATTRIBUTE_HOTLIST_ELEM, - GSCAN_ATTRIBUTE_HOTLIST_FLUSH, - GSCAN_ATTRIBUTE_CHANNEL_NUMBER, - - /* remaining reserved for additional attributes */ - GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60, - GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, - GSCAN_ATTRIBUTE_MIN_BREACHING, - GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS, - - GSCAN_ATTRIBUTE_MAX - -} GSCAN_ATTRIBUTE; - - -class GetCapabilitiesCommand : public WifiCommand -{ - wifi_gscan_capabilities *mCapabilities; -public: - GetCapabilitiesCommand(wifi_interface_handle iface, wifi_gscan_capabilities *capabitlites) - : WifiCommand(iface, 0), mCapabilities(capabitlites) - { - memset(mCapabilities, 0, sizeof(*mCapabilities)); - } - - virtual int create() { - ALOGD("Creating message to get scan capablities; iface = %d", mIfaceInfo->id); - - int ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_GET_CAPABILITIES); - if (ret < 0) { - ALOGD("NL message creation failed"); - return ret; - } - - return ret; - } - -protected: - virtual int handleResponse(WifiEvent& reply) { - - ALOGD("In GetCapabilities::handleResponse"); - - if (reply.get_cmd() != NL80211_CMD_VENDOR) { - ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); - return NL_SKIP; - } - - int id = reply.get_vendor_id(); - int subcmd = reply.get_vendor_subcmd(); - - void *data = reply.get_vendor_data(); - int len = reply.get_vendor_data_len(); - - ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len, - sizeof(*mCapabilities)); - - memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities))); - - return NL_OK; - } -}; - - -wifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle, - wifi_gscan_capabilities *capabilities) -{ - GetCapabilitiesCommand command(handle, capabilities); - return (wifi_error) command.requestResponse(); -} - -class GetChannelListCommand : public WifiCommand -{ - wifi_channel *channels; - int max_channels; - int *num_channels; - int band; -public: - GetChannelListCommand(wifi_interface_handle iface, wifi_channel *channel_buf, int *ch_num, - int num_max_ch, int band) - : WifiCommand(iface, 0), channels(channel_buf), max_channels(num_max_ch), num_channels(ch_num), - band(band) - { - memset(channels, 0, sizeof(wifi_channel) * max_channels); - } - virtual int create() { - ALOGD("Creating message to get channel list; iface = %d", mIfaceInfo->id); - - int ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_GET_VALID_CHANNELS); - if (ret < 0) { - return ret; - } - - nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA); - ret = mMsg.put_u32(GSCAN_ATTRIBUTE_BAND, band); - if (ret < 0) { - return ret; - } - - mMsg.attr_end(data); - - return ret; - } - -protected: - virtual int handleResponse(WifiEvent& reply) { - - ALOGD("In GetChannelList::handleResponse"); - - if (reply.get_cmd() != NL80211_CMD_VENDOR) { - ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); - return NL_SKIP; - } - - int id = reply.get_vendor_id(); - int subcmd = reply.get_vendor_subcmd(); - int num_channels_to_copy = 0; - - nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA); - int len = reply.get_vendor_data_len(); - - ALOGD("Id = %0x, subcmd = %d, len = %d", id, subcmd, len); - if (vendor_data == NULL || len == 0) { - ALOGE("no vendor data in GetChannelList response; ignoring it"); - return NL_SKIP; - } - - for (nl_iterator it(vendor_data); it.has_next(); it.next()) { - if (it.get_type() == GSCAN_ATTRIBUTE_NUM_CHANNELS) { - num_channels_to_copy = it.get_u32(); - ALOGD("Got channel list with %d channels", num_channels_to_copy); - if(num_channels_to_copy > max_channels) - num_channels_to_copy = max_channels; - *num_channels = num_channels_to_copy; - } else if (it.get_type() == GSCAN_ATTRIBUTE_CHANNEL_LIST && num_channels_to_copy) { - memcpy(channels, it.get_data(), sizeof(int) * num_channels_to_copy); - } else { - ALOGW("Ignoring invalid attribute type = %d, size = %d", - it.get_type(), it.get_len()); - } - } - - return NL_OK; - } -}; - -wifi_error wifi_get_valid_channels(wifi_interface_handle handle, - int band, int max_channels, wifi_channel *channels, int *num_channels) -{ - GetChannelListCommand command(handle, channels, num_channels, - max_channels, band); - return (wifi_error) command.requestResponse(); -} -///////////////////////////////////////////////////////////////////////////// - -/* helper functions */ - -static int parseScanResults(wifi_scan_result *results, int num, nlattr *attr) -{ - memset(results, 0, sizeof(wifi_scan_result) * num); - - int i = 0; - for (nl_iterator it(attr); it.has_next() && i < num; it.next(), i++) { - - int index = it.get_type(); - ALOGD("retrieved scan result %d", index); - nlattr *sc_data = (nlattr *) it.get_data(); - wifi_scan_result *result = results + i; - - for (nl_iterator it2(sc_data); it2.has_next(); it2.next()) { - int type = it2.get_type(); - if (type == GSCAN_ATTRIBUTE_SSID) { - strncpy(result->ssid, (char *) it2.get_data(), it2.get_len()); - result->ssid[it2.get_len()] = 0; - } else if (type == GSCAN_ATTRIBUTE_BSSID) { - memcpy(result->bssid, (byte *) it2.get_data(), sizeof(mac_addr)); - } else if (type == GSCAN_ATTRIBUTE_TIMESTAMP) { - result->ts = it2.get_u64(); - } else if (type == GSCAN_ATTRIBUTE_CHANNEL) { - result->ts = it2.get_u16(); - } else if (type == GSCAN_ATTRIBUTE_RSSI) { - result->rssi = it2.get_u8(); - } else if (type == GSCAN_ATTRIBUTE_RTT) { - result->rtt = it2.get_u64(); - } else if (type == GSCAN_ATTRIBUTE_RTTSD) { - result->rtt_sd = it2.get_u64(); - } - } - - } - - if (i >= num) { - ALOGE("Got too many results; skipping some"); - } - - return i; -} - -int createFeatureRequest(WifiRequest& request, int subcmd) { - - int result = request.create(GOOGLE_OUI, subcmd); - if (result < 0) { - return result; - } - - return WIFI_SUCCESS; -} - -class ScanCommand : public WifiCommand -{ - wifi_scan_cmd_params *mParams; - wifi_scan_result_handler mHandler; - static unsigned mGlobalFullScanBuckets; - bool mLocalFullScanBuckets; -public: - ScanCommand(wifi_interface_handle iface, int id, wifi_scan_cmd_params *params, - wifi_scan_result_handler handler) - : WifiCommand(iface, id), mParams(params), mHandler(handler), - mLocalFullScanBuckets(0) - { } - - int createSetupRequest(WifiRequest& request) { - int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN); - if (result < 0) { - return result; - } - - nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); - result = request.put_u32(GSCAN_ATTRIBUTE_BASE_PERIOD, mParams->base_period); - if (result < 0) { - return result; - } - - result = request.put_u32(GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, mParams->max_ap_per_scan); - if (result < 0) { - return result; - } - - result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD, mParams->report_threshold_percent); - if (result < 0) { - return result; - } - - result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD_NUM_SCANS, mParams->report_threshold_num_scans); - if (result < 0) { - return result; - } - - result = request.put_u32(GSCAN_ATTRIBUTE_NUM_BUCKETS, mParams->num_buckets); - if (result < 0) { - return result; - } - - for (int i = 0; i < mParams->num_buckets; i++) { - nlattr * bucket = request.attr_start(i); // next bucket - result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_ID, mParams->buckets[i].bucket); - if (result < 0) { - return result; - } - result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_PERIOD, mParams->buckets[i].period); - if (result < 0) { - return result; - } - result = request.put_u32(GSCAN_ATTRIBUTE_BUCKETS_BAND, - mParams->buckets[i].band); - if (result < 0) { - return result; - } - - result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_EVENTS, - mParams->buckets[i].report_events); - if (result < 0) { - return result; - } - - result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, - mParams->buckets[i].num_channels); - if (result < 0) { - return result; - } - - if (mParams->buckets[i].num_channels) { - nlattr *channels = request.attr_start(GSCAN_ATTRIBUTE_BUCKET_CHANNELS); - for (int j = 0; j < mParams->buckets[i].num_channels; j++) { - result = request.put_u32(j, mParams->buckets[i].channels[j].channel); - if (result < 0) { - return result; - } - } - request.attr_end(channels); - } - - request.attr_end(bucket); - } - - request.attr_end(data); - return WIFI_SUCCESS; - } - - int createStartRequest(WifiRequest& request) { - return createFeatureRequest(request, SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN); - } - - int createStopRequest(WifiRequest& request) { - return createFeatureRequest(request, SLSI_NL80211_VENDOR_SUBCMD_DEL_GSCAN); - } - - int start() { - ALOGD(" sending scan req to driver"); - WifiRequest request(familyId(), ifaceId()); - int result = createSetupRequest(request); - if (result != WIFI_SUCCESS) { - ALOGE("failed to create setup request; result = %d", result); - return result; - } - ALOGD("Starting scan"); - - registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE); - registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN); - - int nBuckets = 0; - for (int i = 0; i < mParams->num_buckets; i++) { - if (mParams->buckets[i].report_events == 2) { - nBuckets++; - } - } - - if (nBuckets != 0) { - ALOGI("Full scan requested with nBuckets = %d", nBuckets); - registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); - } - result = requestResponse(request); - if (result != WIFI_SUCCESS) { - ALOGE("failed to start scan; result = %d", result); - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN); - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE); - return result; - } - - - return result; - } - - virtual int cancel() { - ALOGD("Stopping scan"); - - WifiRequest request(familyId(), ifaceId()); - int result = createStopRequest(request); - if (result != WIFI_SUCCESS) { - ALOGE("failed to create stop request; result = %d", result); - } else { - result = requestResponse(request); - if (result != WIFI_SUCCESS) { - ALOGE("failed to stop scan; result = %d", result); - } - } - - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN); - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE); - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); - - return WIFI_SUCCESS; - } - - virtual int handleResponse(WifiEvent& reply) { - /* Nothing to do on response! */ - return NL_SKIP; - } - - virtual int handleEvent(WifiEvent& event) { - ALOGD("Got a scan results event"); - - event.log(); - - nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); - unsigned int len = event.get_vendor_data_len(); - int event_id = event.get_vendor_subcmd(); - ALOGD("handleEvent, event_id = %d", event_id); - - if(event_id == GSCAN_EVENT_COMPLETE_SCAN) { - if (vendor_data == NULL || len != 4) { - ALOGD("Scan complete type not mentioned!"); - return NL_SKIP; - } - wifi_scan_event evt_type; - - evt_type = (wifi_scan_event) event.get_u32(NL80211_ATTR_VENDOR_DATA); - ALOGD("Scan complete: Received event type %d", evt_type); - if(*mHandler.on_scan_event) - (*mHandler.on_scan_event)(evt_type, evt_type); - } else if(event_id == GSCAN_EVENT_FULL_SCAN_RESULTS) { - if (vendor_data == NULL || len < sizeof(wifi_scan_result)) { - ALOGD("No scan results found"); - return NL_SKIP; - } - wifi_scan_result *result = (wifi_scan_result *)event.get_vendor_data(); - - if(*mHandler.on_full_scan_result) - (*mHandler.on_full_scan_result)(id(), result); - - ALOGD("%-32s\t", result->ssid); - - ALOGD("%02x:%02x:%02x:%02x:%02x:%02x ", result->bssid[0], result->bssid[1], - result->bssid[2], result->bssid[3], result->bssid[4], result->bssid[5]); - - ALOGD("%d\t", result->rssi); - ALOGD("%d\t", result->channel); - ALOGD("%lld\t", result->ts); - ALOGD("%lld\t", result->rtt); - ALOGD("%lld\n", result->rtt_sd); - } else { - - if (vendor_data == NULL || len != 4) { - ALOGD("No scan results found"); - return NL_SKIP; - } - - int num = event.get_u32(NL80211_ATTR_VENDOR_DATA); - ALOGD("Found %d scan results", num); - if(*mHandler.on_scan_results_available) - (*mHandler.on_scan_results_available)(id(), num); - } - return NL_SKIP; - } -}; - -unsigned ScanCommand::mGlobalFullScanBuckets = 0; - -wifi_error wifi_start_gscan( - wifi_request_id id, - wifi_interface_handle iface, - wifi_scan_cmd_params params, - wifi_scan_result_handler handler) -{ - wifi_handle handle = getWifiHandle(iface); - - ALOGD("Starting GScan, halHandle = %p", handle); - - ScanCommand *cmd = new ScanCommand(iface, id, ¶ms, handler); - wifi_register_cmd(handle, id, cmd); - return (wifi_error)cmd->start(); -} - -wifi_error wifi_stop_gscan(wifi_request_id id, wifi_interface_handle iface) -{ - ALOGD("Stopping GScan"); - wifi_handle handle = getWifiHandle(iface); - - if(id == -1) { - wifi_scan_result_handler handler; - wifi_scan_cmd_params dummy_params; - wifi_handle handle = getWifiHandle(iface); - memset(&handler, 0, sizeof(handler)); - - ScanCommand *cmd = new ScanCommand(iface, id, &dummy_params, handler); - cmd->cancel(); - cmd->releaseRef(); - return WIFI_SUCCESS; - } - - - WifiCommand *cmd = wifi_unregister_cmd(handle, id); - if (cmd) { - cmd->cancel(); - cmd->releaseRef(); - return WIFI_SUCCESS; - } - - return WIFI_ERROR_INVALID_ARGS; -} - -class GetScanResultsCommand : public WifiCommand { - wifi_cached_scan_results *mScans; - int mMax; - int *mNum; - int mRetrieved; - byte mFlush; - int mCompleted; - static const int MAX_RESULTS = 320; - wifi_scan_result mScanResults[MAX_RESULTS]; - int mNextScanResult; -public: - GetScanResultsCommand(wifi_interface_handle iface, byte flush, - wifi_cached_scan_results *results, int max, int *num) - : WifiCommand(iface, -1), mScans(results), mMax(max), mNum(num), - mRetrieved(0), mFlush(flush), mCompleted(0) - { } - - int createRequest(WifiRequest& request, int num, byte flush) { - int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_GET_SCAN_RESULTS); - if (result < 0) { - return result; - } - - nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); - result = request.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num); - if (result < 0) { - return result; - } - - request.attr_end(data); - return WIFI_SUCCESS; - } - - int execute() { - WifiRequest request(familyId(), ifaceId()); - ALOGD("retrieving %d scan results", mMax); - - for (int i = 0; i < 10 && mRetrieved < mMax; i++) { - int result = createRequest(request, (mMax - mRetrieved), mFlush); - if (result < 0) { - ALOGE("failed to create request"); - return result; - } - - int prev_retrieved = mRetrieved; - - result = requestResponse(request); - - if (result != WIFI_SUCCESS) { - ALOGE("failed to retrieve scan results; result = %d", result); - return result; - } - - if (mRetrieved == prev_retrieved || mCompleted) { - /* no more items left to retrieve */ - break; - } - - request.destroy(); - } - - ALOGE("GetScanResults read %d results", mRetrieved); - *mNum = mRetrieved; - return WIFI_SUCCESS; - } - - virtual int handleResponse(WifiEvent& reply) { - ALOGD("In GetScanResultsCommand::handleResponse"); - - if (reply.get_cmd() != NL80211_CMD_VENDOR) { - ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); - return NL_SKIP; - } - - int id = reply.get_vendor_id(); - int subcmd = reply.get_vendor_subcmd(); - - ALOGD("Id = %0x, subcmd = %d", id, subcmd); - - nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA); - int len = reply.get_vendor_data_len(); - - if (vendor_data == NULL || len == 0) { - ALOGE("no vendor data in GetScanResults response; ignoring it"); - return NL_SKIP; - } - - for (nl_iterator it(vendor_data); it.has_next(); it.next()) { - if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE) { - mCompleted = it.get_u8(); - ALOGD("retrieved mCompleted flag : %d", mCompleted); - } else if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS || it.get_type() == 0) { - int scan_id = 0, flags = 0, num = 0; - for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) { - if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_ID) { - scan_id = it2.get_u32(); - ALOGD("retrieved scan_id : 0x%0x", scan_id); - } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_FLAGS) { - flags = it2.get_u8(); - ALOGD("retrieved scan_flags : 0x%0x", flags); - } else if (it2.get_type() == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) { - num = it2.get_u32(); - ALOGD("retrieved num_results: %d", num); - } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS) { - if (mRetrieved >= mMax) { - ALOGW("Stored %d scans, ignoring excess results", mRetrieved); - break; - } - num = it2.get_len() / sizeof(wifi_scan_result); - num = min(MAX_RESULTS - mNextScanResult, num); - num = min((int)MAX_AP_CACHE_PER_SCAN, num); - memcpy(mScanResults + mNextScanResult, it2.get_data(), - sizeof(wifi_scan_result) * num); - ALOGD("Retrieved %d scan results", num); - wifi_scan_result *results = (wifi_scan_result *)it2.get_data(); - for (int i = 0; i < num; i++) { - wifi_scan_result *result = results + i; - ALOGD("%02d %-32s %02x:%02x:%02x:%02x:%02x:%02x %04d", i, - result->ssid, result->bssid[0], result->bssid[1], result->bssid[2], - result->bssid[3], result->bssid[4], result->bssid[5], - result->rssi); - } - mScans[mRetrieved].scan_id = scan_id; - mScans[mRetrieved].flags = flags; - mScans[mRetrieved].num_results = num; - ALOGD("Setting result of scan_id : 0x%0x", mScans[mRetrieved].scan_id); - memcpy(mScans[mRetrieved].results, - &(mScanResults[mNextScanResult]), num * sizeof(wifi_scan_result)); - mNextScanResult += num; - mRetrieved++; - } else { - ALOGW("Ignoring invalid attribute type = %d, size = %d", - it.get_type(), it.get_len()); - } - } - } else { - ALOGW("Ignoring invalid attribute type = %d, size = %d", - it.get_type(), it.get_len()); - } - } - - return NL_OK; - } -}; - -wifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface, byte flush, - int max, wifi_cached_scan_results *results, int *num) { - ALOGD("Getting cached scan results, iface handle = %p, num = %d", iface, *num); - - GetScanResultsCommand *cmd = new GetScanResultsCommand(iface, flush, results, max, num); - return (wifi_error)cmd->execute(); -} - -///////////////////////////////////////////////////////////////////////////// - -class BssidHotlistCommand : public WifiCommand -{ -private: - wifi_bssid_hotlist_params mParams; - wifi_hotlist_ap_found_handler mHandler; - static const int MAX_RESULTS = 64; - wifi_scan_result mResults[MAX_RESULTS]; -public: - BssidHotlistCommand(wifi_interface_handle handle, int id, - wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler) - : WifiCommand(handle, id), mParams(params), mHandler(handler) - { } - - int createSetupRequest(WifiRequest& request) { - int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_BSSID_HOTLIST); - if (result < 0) { - return result; - } - - nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); - - result = request.put_u32(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size); - if (result < 0) { - return result; - } - - struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS); - for (int i = 0; i < mParams.num_bssid; i++) { - nlattr *attr2 = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM); - if (attr2 == NULL) { - return WIFI_ERROR_OUT_OF_MEMORY; - } - result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid); - if (result < 0) { - return result; - } - result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high); - if (result < 0) { - return result; - } - result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low); - if (result < 0) { - return result; - } - request.attr_end(attr2); - } - - request.attr_end(attr); - request.attr_end(data); - return result; - } - - int createTeardownRequest(WifiRequest& request) { - int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_RESET_BSSID_HOTLIST); - if (result < 0) { - return result; - } - - return result; - } - - int start() { - ALOGD("Executing hotlist setup request, num = %d", mParams.num_bssid); - WifiRequest request(familyId(), ifaceId()); - int result = createSetupRequest(request); - if (result < 0) { - return result; - } - - result = requestResponse(request); - if (result < 0) { - ALOGD("Failed to execute hotlist setup request, result = %d", result); - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND); - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST); - return result; - } - - ALOGD("Successfully set %d APs in the hotlist", mParams.num_bssid); - - registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND); - registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST); - - return result; - } - - virtual int cancel() { - /* unregister event handler */ - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND); - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST); - /* create set hotlist message with empty hotlist */ - WifiRequest request(familyId(), ifaceId()); - int result = createTeardownRequest(request); - if (result < 0) { - return result; - } - - result = requestResponse(request); - if (result < 0) { - return result; - } - - ALOGD("Successfully reset APs in current hotlist"); - return result; - } - - virtual int handleResponse(WifiEvent& reply) { - /* Nothing to do on response! */ - return NL_SKIP; - } - - virtual int handleEvent(WifiEvent& event) { - ALOGD("Hotlist AP event"); - int event_id = event.get_vendor_subcmd(); - event.log(); - - nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); - int len = event.get_vendor_data_len(); - - if (vendor_data == NULL || len == 0) { - ALOGD("No scan results found"); - return NL_SKIP; - } - - memset(mResults, 0, sizeof(wifi_scan_result) * MAX_RESULTS); - - int num = len / sizeof(wifi_scan_result); - num = min(MAX_RESULTS, num); - memcpy(mResults, event.get_vendor_data(), num * sizeof(wifi_scan_result)); - - if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_FOUND) { - ALOGD("FOUND %d hotlist APs", num); - if (*mHandler.on_hotlist_ap_found) - (*mHandler.on_hotlist_ap_found)(id(), num, mResults); - } else if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_LOST) { - ALOGD("LOST %d hotlist APs", num); - if (*mHandler.on_hotlist_ap_lost) - (*mHandler.on_hotlist_ap_lost)(id(), num, mResults); - } - return NL_SKIP; - } -}; - -wifi_error wifi_set_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface, - wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler) -{ - wifi_handle handle = getWifiHandle(iface); - - BssidHotlistCommand *cmd = new BssidHotlistCommand(iface, id, params, handler); - wifi_register_cmd(handle, id, cmd); - return (wifi_error)cmd->start(); -} - -wifi_error wifi_reset_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface) -{ - wifi_handle handle = getWifiHandle(iface); - - WifiCommand *cmd = wifi_unregister_cmd(handle, id); - if (cmd) { - cmd->cancel(); - cmd->releaseRef(); - return WIFI_SUCCESS; - } - - return WIFI_ERROR_INVALID_ARGS; -} - - -///////////////////////////////////////////////////////////////////////////// - -class SignificantWifiChangeCommand : public WifiCommand -{ - typedef struct { - mac_addr bssid; // BSSID - wifi_channel channel; // channel frequency in MHz - int num_rssi; // number of rssi samples - wifi_rssi rssi[8]; // RSSI history in db - } wifi_significant_change_result_internal; - -private: - wifi_significant_change_params mParams; - wifi_significant_change_handler mHandler; - static const int MAX_RESULTS = 64; - wifi_significant_change_result_internal mResultsBuffer[MAX_RESULTS]; - wifi_significant_change_result *mResults[MAX_RESULTS]; -public: - SignificantWifiChangeCommand(wifi_interface_handle handle, int id, - wifi_significant_change_params params, wifi_significant_change_handler handler) - : WifiCommand(handle, id), mParams(params), mHandler(handler) - { } - - int createSetupRequest(WifiRequest& request) { - int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_SIGNIFICANT_CHANGE); - if (result < 0) { - return result; - } - - nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); - - result = request.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE, mParams.rssi_sample_size); - if (result < 0) { - return result; - } - result = request.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size); - if (result < 0) { - return result; - } - result = request.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING, mParams.min_breaching); - if (result < 0) { - return result; - } - - struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS); - - for (int i = 0; i < mParams.num_bssid; i++) { - - nlattr *attr2 = request.attr_start(i); - if (attr2 == NULL) { - return WIFI_ERROR_OUT_OF_MEMORY; - } - result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid); - if (result < 0) { - return result; - } - result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high); - if (result < 0) { - return result; - } - result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low); - if (result < 0) { - return result; - } - request.attr_end(attr2); - } - - request.attr_end(attr); - request.attr_end(data); - - return result; - } - - int createTeardownRequest(WifiRequest& request) { - int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_RESET_SIGNIFICANT_CHANGE); - if (result < 0) { - return result; - } - - return result; - } - - int start() { - ALOGD("Set significant wifi change"); - WifiRequest request(familyId(), ifaceId()); - - int result = createSetupRequest(request); - if (result < 0) { - return result; - } - - result = requestResponse(request); - if (result < 0) { - ALOGD("failed to set significant wifi change %d", result); - return result; - } - registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); - - return result; - } - - virtual int cancel() { - /* unregister event handler */ - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); - - /* create set significant change monitor message with empty hotlist */ - WifiRequest request(familyId(), ifaceId()); - - int result = createTeardownRequest(request); - if (result < 0) { - return result; - } - - result = requestResponse(request); - if (result < 0) { - return result; - } - - ALOGD("successfully reset significant wifi change"); - return result; - } - - virtual int handleResponse(WifiEvent& reply) { - /* Nothing to do on response! */ - return NL_SKIP; - } - - virtual int handleEvent(WifiEvent& event) { - ALOGD("Got a significant wifi change event"); - - nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); - int len = event.get_vendor_data_len(); - - if (vendor_data == NULL || len == 0) { - ALOGD("No scan results found"); - return NL_SKIP; - } - - typedef struct { - uint16_t channel; - mac_addr bssid; - int16_t rssi_history[8]; - } ChangeInfo; - - int num = min(len / sizeof(ChangeInfo), MAX_RESULTS); - ChangeInfo *ci = (ChangeInfo *)event.get_vendor_data(); - - for (int i = 0; i < num; i++) { - memcpy(mResultsBuffer[i].bssid, ci[i].bssid, sizeof(mac_addr)); - mResultsBuffer[i].channel = ci[i].channel; - /* Driver sends N samples and the rest 8-N are filled 0x7FFF - * N = no of rssi samples to average sent in significant change request. */ - int num_rssi = 0; - for (int j = 0; j < 8; j++) { - if (ci[i].rssi_history[j] == 0x7FFF) { - num_rssi = j; - break; - } - mResultsBuffer[i].rssi[j] = (int) ci[i].rssi_history[j]; - } - mResultsBuffer[i].num_rssi = num_rssi; - mResults[i] = reinterpret_cast(&(mResultsBuffer[i])); - } - - ALOGD("Retrieved %d scan results", num); - - if (num != 0) { - (*mHandler.on_significant_change)(id(), num, mResults); - } else { - ALOGW("No significant change reported"); - } - - return NL_SKIP; - } -}; - -wifi_error wifi_set_significant_change_handler(wifi_request_id id, wifi_interface_handle iface, - wifi_significant_change_params params, wifi_significant_change_handler handler) -{ - wifi_handle handle = getWifiHandle(iface); - - SignificantWifiChangeCommand *cmd = new SignificantWifiChangeCommand( - iface, id, params, handler); - wifi_register_cmd(handle, id, cmd); - return (wifi_error)cmd->start(); -} - -wifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface) -{ - wifi_handle handle = getWifiHandle(iface); - - WifiCommand *cmd = wifi_unregister_cmd(handle, id); - if (cmd) { - cmd->cancel(); - cmd->releaseRef(); - return WIFI_SUCCESS; - } - - return WIFI_ERROR_INVALID_ARGS; -} + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "sync.h" + +#define LOG_TAG "WifiHAL" + +#include + +#include "wifi_hal.h" +#include "common.h" +#include "cpp_bindings.h" + +typedef enum { + + GSCAN_ATTRIBUTE_NUM_BUCKETS = 10, + GSCAN_ATTRIBUTE_BASE_PERIOD, + GSCAN_ATTRIBUTE_BUCKETS_BAND, + GSCAN_ATTRIBUTE_BUCKET_ID, + GSCAN_ATTRIBUTE_BUCKET_PERIOD, + GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, + GSCAN_ATTRIBUTE_BUCKET_CHANNELS, + GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, + GSCAN_ATTRIBUTE_REPORT_THRESHOLD, + GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, + GSCAN_ATTRIBUTE_REPORT_THRESHOLD_NUM_SCANS, + GSCAN_ATTRIBUTE_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND, + + GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20, + GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, /* indicates no more results */ + GSCAN_ATTRIBUTE_REPORT_EVENTS, + + /* remaining reserved for additional attributes */ + GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30, + GSCAN_ATTRIBUTE_SCAN_RESULTS, /* flat array of wifi_scan_result */ + GSCAN_ATTRIBUTE_NUM_CHANNELS, + GSCAN_ATTRIBUTE_CHANNEL_LIST, + GSCAN_ATTRIBUTE_SCAN_ID, + GSCAN_ATTRIBUTE_SCAN_FLAGS, + + /* remaining reserved for additional attributes */ + + GSCAN_ATTRIBUTE_SSID = 40, + GSCAN_ATTRIBUTE_BSSID, + GSCAN_ATTRIBUTE_CHANNEL, + GSCAN_ATTRIBUTE_RSSI, + GSCAN_ATTRIBUTE_TIMESTAMP, + GSCAN_ATTRIBUTE_RTT, + GSCAN_ATTRIBUTE_RTTSD, + + /* remaining reserved for additional attributes */ + + GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50, + GSCAN_ATTRIBUTE_RSSI_LOW, + GSCAN_ATTRIBUTE_RSSI_HIGH, + GSCAN_ATTRIBUTE_HOTLIST_ELEM, + GSCAN_ATTRIBUTE_HOTLIST_FLUSH, + GSCAN_ATTRIBUTE_CHANNEL_NUMBER, + + /* remaining reserved for additional attributes */ + GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60, + GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, + GSCAN_ATTRIBUTE_MIN_BREACHING, + GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS, + + GSCAN_ATTRIBUTE_MAX + +} GSCAN_ATTRIBUTE; + + +class GetCapabilitiesCommand : public WifiCommand +{ + wifi_gscan_capabilities *mCapabilities; +public: + GetCapabilitiesCommand(wifi_interface_handle iface, wifi_gscan_capabilities *capabitlites) + : WifiCommand(iface, 0), mCapabilities(capabitlites) + { + memset(mCapabilities, 0, sizeof(*mCapabilities)); + } + + virtual int create() { + ALOGD("Creating message to get scan capablities; iface = %d", mIfaceInfo->id); + + int ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_GET_CAPABILITIES); + if (ret < 0) { + ALOGD("NL message creation failed"); + return ret; + } + + return ret; + } + +protected: + virtual int handleResponse(WifiEvent& reply) { + + ALOGD("In GetCapabilities::handleResponse"); + + if (reply.get_cmd() != NL80211_CMD_VENDOR) { + ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); + return NL_SKIP; + } + + int id = reply.get_vendor_id(); + int subcmd = reply.get_vendor_subcmd(); + + void *data = reply.get_vendor_data(); + int len = reply.get_vendor_data_len(); + + ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len, + sizeof(*mCapabilities)); + + memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities))); + + return NL_OK; + } +}; + + +wifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle, + wifi_gscan_capabilities *capabilities) +{ + GetCapabilitiesCommand command(handle, capabilities); + return (wifi_error) command.requestResponse(); +} + +class GetChannelListCommand : public WifiCommand +{ + wifi_channel *channels; + int max_channels; + int *num_channels; + int band; +public: + GetChannelListCommand(wifi_interface_handle iface, wifi_channel *channel_buf, int *ch_num, + int num_max_ch, int band) + : WifiCommand(iface, 0), channels(channel_buf), max_channels(num_max_ch), num_channels(ch_num), + band(band) + { + memset(channels, 0, sizeof(wifi_channel) * max_channels); + } + virtual int create() { + ALOGD("Creating message to get channel list; iface = %d", mIfaceInfo->id); + + int ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_GET_VALID_CHANNELS); + if (ret < 0) { + return ret; + } + + nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA); + ret = mMsg.put_u32(GSCAN_ATTRIBUTE_BAND, band); + if (ret < 0) { + return ret; + } + + mMsg.attr_end(data); + + return ret; + } + +protected: + virtual int handleResponse(WifiEvent& reply) { + + ALOGD("In GetChannelList::handleResponse"); + + if (reply.get_cmd() != NL80211_CMD_VENDOR) { + ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); + return NL_SKIP; + } + + int id = reply.get_vendor_id(); + int subcmd = reply.get_vendor_subcmd(); + int num_channels_to_copy = 0; + + nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA); + int len = reply.get_vendor_data_len(); + + ALOGD("Id = %0x, subcmd = %d, len = %d", id, subcmd, len); + if (vendor_data == NULL || len == 0) { + ALOGE("no vendor data in GetChannelList response; ignoring it"); + return NL_SKIP; + } + + for (nl_iterator it(vendor_data); it.has_next(); it.next()) { + if (it.get_type() == GSCAN_ATTRIBUTE_NUM_CHANNELS) { + num_channels_to_copy = it.get_u32(); + ALOGD("Got channel list with %d channels", num_channels_to_copy); + if(num_channels_to_copy > max_channels) + num_channels_to_copy = max_channels; + *num_channels = num_channels_to_copy; + } else if (it.get_type() == GSCAN_ATTRIBUTE_CHANNEL_LIST && num_channels_to_copy) { + memcpy(channels, it.get_data(), sizeof(int) * num_channels_to_copy); + } else { + ALOGW("Ignoring invalid attribute type = %d, size = %d", + it.get_type(), it.get_len()); + } + } + + return NL_OK; + } +}; + +wifi_error wifi_get_valid_channels(wifi_interface_handle handle, + int band, int max_channels, wifi_channel *channels, int *num_channels) +{ + GetChannelListCommand command(handle, channels, num_channels, + max_channels, band); + return (wifi_error) command.requestResponse(); +} +///////////////////////////////////////////////////////////////////////////// + +/* helper functions */ + +static int parseScanResults(wifi_scan_result *results, int num, nlattr *attr) +{ + memset(results, 0, sizeof(wifi_scan_result) * num); + + int i = 0; + for (nl_iterator it(attr); it.has_next() && i < num; it.next(), i++) { + + int index = it.get_type(); + ALOGD("retrieved scan result %d", index); + nlattr *sc_data = (nlattr *) it.get_data(); + wifi_scan_result *result = results + i; + + for (nl_iterator it2(sc_data); it2.has_next(); it2.next()) { + int type = it2.get_type(); + if (type == GSCAN_ATTRIBUTE_SSID) { + strncpy(result->ssid, (char *) it2.get_data(), it2.get_len()); + result->ssid[it2.get_len()] = 0; + } else if (type == GSCAN_ATTRIBUTE_BSSID) { + memcpy(result->bssid, (byte *) it2.get_data(), sizeof(mac_addr)); + } else if (type == GSCAN_ATTRIBUTE_TIMESTAMP) { + result->ts = it2.get_u64(); + } else if (type == GSCAN_ATTRIBUTE_CHANNEL) { + result->ts = it2.get_u16(); + } else if (type == GSCAN_ATTRIBUTE_RSSI) { + result->rssi = it2.get_u8(); + } else if (type == GSCAN_ATTRIBUTE_RTT) { + result->rtt = it2.get_u64(); + } else if (type == GSCAN_ATTRIBUTE_RTTSD) { + result->rtt_sd = it2.get_u64(); + } + } + + } + + if (i >= num) { + ALOGE("Got too many results; skipping some"); + } + + return i; +} + +int createFeatureRequest(WifiRequest& request, int subcmd) { + + int result = request.create(GOOGLE_OUI, subcmd); + if (result < 0) { + return result; + } + + return WIFI_SUCCESS; +} + +class ScanCommand : public WifiCommand +{ + wifi_scan_cmd_params *mParams; + wifi_scan_result_handler mHandler; + static unsigned mGlobalFullScanBuckets; + bool mLocalFullScanBuckets; +public: + ScanCommand(wifi_interface_handle iface, int id, wifi_scan_cmd_params *params, + wifi_scan_result_handler handler) + : WifiCommand(iface, id), mParams(params), mHandler(handler), + mLocalFullScanBuckets(0) + { } + + int createSetupRequest(WifiRequest& request) { + int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN); + if (result < 0) { + return result; + } + + nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); + result = request.put_u32(GSCAN_ATTRIBUTE_BASE_PERIOD, mParams->base_period); + if (result < 0) { + return result; + } + + result = request.put_u32(GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, mParams->max_ap_per_scan); + if (result < 0) { + return result; + } + + result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD, mParams->report_threshold_percent); + if (result < 0) { + return result; + } + + result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD_NUM_SCANS, mParams->report_threshold_num_scans); + if (result < 0) { + return result; + } + + result = request.put_u32(GSCAN_ATTRIBUTE_NUM_BUCKETS, mParams->num_buckets); + if (result < 0) { + return result; + } + + for (int i = 0; i < mParams->num_buckets; i++) { + nlattr * bucket = request.attr_start(i); // next bucket + result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_ID, mParams->buckets[i].bucket); + if (result < 0) { + return result; + } + result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_PERIOD, mParams->buckets[i].period); + if (result < 0) { + return result; + } + result = request.put_u32(GSCAN_ATTRIBUTE_BUCKETS_BAND, + mParams->buckets[i].band); + if (result < 0) { + return result; + } + + result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_EVENTS, + mParams->buckets[i].report_events); + if (result < 0) { + return result; + } + + result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, + mParams->buckets[i].num_channels); + if (result < 0) { + return result; + } + + if (mParams->buckets[i].num_channels) { + nlattr *channels = request.attr_start(GSCAN_ATTRIBUTE_BUCKET_CHANNELS); + for (int j = 0; j < mParams->buckets[i].num_channels; j++) { + result = request.put_u32(j, mParams->buckets[i].channels[j].channel); + if (result < 0) { + return result; + } + } + request.attr_end(channels); + } + + request.attr_end(bucket); + } + + request.attr_end(data); + return WIFI_SUCCESS; + } + + int createStartRequest(WifiRequest& request) { + return createFeatureRequest(request, SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN); + } + + int createStopRequest(WifiRequest& request) { + return createFeatureRequest(request, SLSI_NL80211_VENDOR_SUBCMD_DEL_GSCAN); + } + + int start() { + ALOGD(" sending scan req to driver"); + WifiRequest request(familyId(), ifaceId()); + int result = createSetupRequest(request); + if (result != WIFI_SUCCESS) { + ALOGE("failed to create setup request; result = %d", result); + return result; + } + ALOGD("Starting scan"); + + registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE); + registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN); + + int nBuckets = 0; + for (int i = 0; i < mParams->num_buckets; i++) { + if (mParams->buckets[i].report_events == 2) { + nBuckets++; + } + } + + if (nBuckets != 0) { + ALOGI("Full scan requested with nBuckets = %d", nBuckets); + registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); + } + result = requestResponse(request); + if (result != WIFI_SUCCESS) { + ALOGE("failed to start scan; result = %d", result); + unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN); + unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE); + return result; + } + + + return result; + } + + virtual int cancel() { + ALOGD("Stopping scan"); + + WifiRequest request(familyId(), ifaceId()); + int result = createStopRequest(request); + if (result != WIFI_SUCCESS) { + ALOGE("failed to create stop request; result = %d", result); + } else { + result = requestResponse(request); + if (result != WIFI_SUCCESS) { + ALOGE("failed to stop scan; result = %d", result); + } + } + + unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN); + unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE); + unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); + + return WIFI_SUCCESS; + } + + virtual int handleResponse(WifiEvent& reply) { + /* Nothing to do on response! */ + return NL_SKIP; + } + + virtual int handleEvent(WifiEvent& event) { + ALOGD("Got a scan results event"); + + event.log(); + + nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); + unsigned int len = event.get_vendor_data_len(); + int event_id = event.get_vendor_subcmd(); + ALOGD("handleEvent, event_id = %d", event_id); + + if(event_id == GSCAN_EVENT_COMPLETE_SCAN) { + if (vendor_data == NULL || len != 4) { + ALOGD("Scan complete type not mentioned!"); + return NL_SKIP; + } + wifi_scan_event evt_type; + + evt_type = (wifi_scan_event) event.get_u32(NL80211_ATTR_VENDOR_DATA); + ALOGD("Scan complete: Received event type %d", evt_type); + if(*mHandler.on_scan_event) + (*mHandler.on_scan_event)(evt_type, evt_type); + } else if(event_id == GSCAN_EVENT_FULL_SCAN_RESULTS) { + if (vendor_data == NULL || len < sizeof(wifi_scan_result)) { + ALOGD("No scan results found"); + return NL_SKIP; + } + wifi_scan_result *result = (wifi_scan_result *)event.get_vendor_data(); + + if(*mHandler.on_full_scan_result) + (*mHandler.on_full_scan_result)(id(), result); + + ALOGD("%-32s\t", result->ssid); + + ALOGD("%02x:%02x:%02x:%02x:%02x:%02x ", result->bssid[0], result->bssid[1], + result->bssid[2], result->bssid[3], result->bssid[4], result->bssid[5]); + + ALOGD("%d\t", result->rssi); + ALOGD("%d\t", result->channel); + ALOGD("%lld\t", result->ts); + ALOGD("%lld\t", result->rtt); + ALOGD("%lld\n", result->rtt_sd); + } else { + + if (vendor_data == NULL || len != 4) { + ALOGD("No scan results found"); + return NL_SKIP; + } + + int num = event.get_u32(NL80211_ATTR_VENDOR_DATA); + ALOGD("Found %d scan results", num); + if(*mHandler.on_scan_results_available) + (*mHandler.on_scan_results_available)(id(), num); + } + return NL_SKIP; + } +}; + +unsigned ScanCommand::mGlobalFullScanBuckets = 0; + +wifi_error wifi_start_gscan( + wifi_request_id id, + wifi_interface_handle iface, + wifi_scan_cmd_params params, + wifi_scan_result_handler handler) +{ + wifi_handle handle = getWifiHandle(iface); + + ALOGD("Starting GScan, halHandle = %p", handle); + + ScanCommand *cmd = new ScanCommand(iface, id, ¶ms, handler); + wifi_register_cmd(handle, id, cmd); + return (wifi_error)cmd->start(); +} + +wifi_error wifi_stop_gscan(wifi_request_id id, wifi_interface_handle iface) +{ + ALOGD("Stopping GScan"); + wifi_handle handle = getWifiHandle(iface); + + if(id == -1) { + wifi_scan_result_handler handler; + wifi_scan_cmd_params dummy_params; + wifi_handle handle = getWifiHandle(iface); + memset(&handler, 0, sizeof(handler)); + + ScanCommand *cmd = new ScanCommand(iface, id, &dummy_params, handler); + cmd->cancel(); + cmd->releaseRef(); + return WIFI_SUCCESS; + } + + + WifiCommand *cmd = wifi_unregister_cmd(handle, id); + if (cmd) { + cmd->cancel(); + cmd->releaseRef(); + return WIFI_SUCCESS; + } + + return WIFI_ERROR_INVALID_ARGS; +} + +class GetScanResultsCommand : public WifiCommand { + wifi_cached_scan_results *mScans; + int mMax; + int *mNum; + int mRetrieved; + byte mFlush; + int mCompleted; + static const int MAX_RESULTS = 320; + wifi_scan_result mScanResults[MAX_RESULTS]; + int mNextScanResult; +public: + GetScanResultsCommand(wifi_interface_handle iface, byte flush, + wifi_cached_scan_results *results, int max, int *num) + : WifiCommand(iface, -1), mScans(results), mMax(max), mNum(num), + mRetrieved(0), mFlush(flush), mCompleted(0) + { } + + int createRequest(WifiRequest& request, int num, byte flush) { + int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_GET_SCAN_RESULTS); + if (result < 0) { + return result; + } + + nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); + result = request.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num); + if (result < 0) { + return result; + } + + request.attr_end(data); + return WIFI_SUCCESS; + } + + int execute() { + WifiRequest request(familyId(), ifaceId()); + ALOGD("retrieving %d scan results", mMax); + + for (int i = 0; i < 10 && mRetrieved < mMax; i++) { + int result = createRequest(request, (mMax - mRetrieved), mFlush); + if (result < 0) { + ALOGE("failed to create request"); + return result; + } + + int prev_retrieved = mRetrieved; + + result = requestResponse(request); + + if (result != WIFI_SUCCESS) { + ALOGE("failed to retrieve scan results; result = %d", result); + return result; + } + + if (mRetrieved == prev_retrieved || mCompleted) { + /* no more items left to retrieve */ + break; + } + + request.destroy(); + } + + ALOGE("GetScanResults read %d results", mRetrieved); + *mNum = mRetrieved; + return WIFI_SUCCESS; + } + + virtual int handleResponse(WifiEvent& reply) { + ALOGD("In GetScanResultsCommand::handleResponse"); + + if (reply.get_cmd() != NL80211_CMD_VENDOR) { + ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); + return NL_SKIP; + } + + int id = reply.get_vendor_id(); + int subcmd = reply.get_vendor_subcmd(); + + ALOGD("Id = %0x, subcmd = %d", id, subcmd); + + nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA); + int len = reply.get_vendor_data_len(); + + if (vendor_data == NULL || len == 0) { + ALOGE("no vendor data in GetScanResults response; ignoring it"); + return NL_SKIP; + } + + for (nl_iterator it(vendor_data); it.has_next(); it.next()) { + if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE) { + mCompleted = it.get_u8(); + ALOGD("retrieved mCompleted flag : %d", mCompleted); + } else if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS || it.get_type() == 0) { + int scan_id = 0, flags = 0, num = 0; + for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) { + if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_ID) { + scan_id = it2.get_u32(); + ALOGD("retrieved scan_id : 0x%0x", scan_id); + } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_FLAGS) { + flags = it2.get_u8(); + ALOGD("retrieved scan_flags : 0x%0x", flags); + } else if (it2.get_type() == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) { + num = it2.get_u32(); + ALOGD("retrieved num_results: %d", num); + } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS) { + if (mRetrieved >= mMax) { + ALOGW("Stored %d scans, ignoring excess results", mRetrieved); + break; + } + num = it2.get_len() / sizeof(wifi_scan_result); + num = min(MAX_RESULTS - mNextScanResult, num); + num = min((int)MAX_AP_CACHE_PER_SCAN, num); + memcpy(mScanResults + mNextScanResult, it2.get_data(), + sizeof(wifi_scan_result) * num); + ALOGD("Retrieved %d scan results", num); + wifi_scan_result *results = (wifi_scan_result *)it2.get_data(); + for (int i = 0; i < num; i++) { + wifi_scan_result *result = results + i; + ALOGD("%02d %-32s %02x:%02x:%02x:%02x:%02x:%02x %04d", i, + result->ssid, result->bssid[0], result->bssid[1], result->bssid[2], + result->bssid[3], result->bssid[4], result->bssid[5], + result->rssi); + } + mScans[mRetrieved].scan_id = scan_id; + mScans[mRetrieved].flags = flags; + mScans[mRetrieved].num_results = num; + ALOGD("Setting result of scan_id : 0x%0x", mScans[mRetrieved].scan_id); + memcpy(mScans[mRetrieved].results, + &(mScanResults[mNextScanResult]), num * sizeof(wifi_scan_result)); + mNextScanResult += num; + mRetrieved++; + } else { + ALOGW("Ignoring invalid attribute type = %d, size = %d", + it.get_type(), it.get_len()); + } + } + } else { + ALOGW("Ignoring invalid attribute type = %d, size = %d", + it.get_type(), it.get_len()); + } + } + + return NL_OK; + } +}; + +wifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface, byte flush, + int max, wifi_cached_scan_results *results, int *num) { + ALOGD("Getting cached scan results, iface handle = %p, num = %d", iface, *num); + + GetScanResultsCommand *cmd = new GetScanResultsCommand(iface, flush, results, max, num); + return (wifi_error)cmd->execute(); +} + +///////////////////////////////////////////////////////////////////////////// + +class BssidHotlistCommand : public WifiCommand +{ +private: + wifi_bssid_hotlist_params mParams; + wifi_hotlist_ap_found_handler mHandler; + static const int MAX_RESULTS = 64; + wifi_scan_result mResults[MAX_RESULTS]; +public: + BssidHotlistCommand(wifi_interface_handle handle, int id, + wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler) + : WifiCommand(handle, id), mParams(params), mHandler(handler) + { } + + int createSetupRequest(WifiRequest& request) { + int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_BSSID_HOTLIST); + if (result < 0) { + return result; + } + + nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); + + result = request.put_u32(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size); + if (result < 0) { + return result; + } + + struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS); + for (int i = 0; i < mParams.num_bssid; i++) { + nlattr *attr2 = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM); + if (attr2 == NULL) { + return WIFI_ERROR_OUT_OF_MEMORY; + } + result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid); + if (result < 0) { + return result; + } + result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high); + if (result < 0) { + return result; + } + result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low); + if (result < 0) { + return result; + } + request.attr_end(attr2); + } + + request.attr_end(attr); + request.attr_end(data); + return result; + } + + int createTeardownRequest(WifiRequest& request) { + int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_RESET_BSSID_HOTLIST); + if (result < 0) { + return result; + } + + return result; + } + + int start() { + ALOGD("Executing hotlist setup request, num = %d", mParams.num_bssid); + WifiRequest request(familyId(), ifaceId()); + int result = createSetupRequest(request); + if (result < 0) { + return result; + } + + result = requestResponse(request); + if (result < 0) { + ALOGD("Failed to execute hotlist setup request, result = %d", result); + unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND); + unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST); + return result; + } + + ALOGD("Successfully set %d APs in the hotlist", mParams.num_bssid); + + registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND); + registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST); + + return result; + } + + virtual int cancel() { + /* unregister event handler */ + unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND); + unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST); + /* create set hotlist message with empty hotlist */ + WifiRequest request(familyId(), ifaceId()); + int result = createTeardownRequest(request); + if (result < 0) { + return result; + } + + result = requestResponse(request); + if (result < 0) { + return result; + } + + ALOGD("Successfully reset APs in current hotlist"); + return result; + } + + virtual int handleResponse(WifiEvent& reply) { + /* Nothing to do on response! */ + return NL_SKIP; + } + + virtual int handleEvent(WifiEvent& event) { + ALOGD("Hotlist AP event"); + int event_id = event.get_vendor_subcmd(); + event.log(); + + nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); + int len = event.get_vendor_data_len(); + + if (vendor_data == NULL || len == 0) { + ALOGD("No scan results found"); + return NL_SKIP; + } + + memset(mResults, 0, sizeof(wifi_scan_result) * MAX_RESULTS); + + int num = len / sizeof(wifi_scan_result); + num = min(MAX_RESULTS, num); + memcpy(mResults, event.get_vendor_data(), num * sizeof(wifi_scan_result)); + + if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_FOUND) { + ALOGD("FOUND %d hotlist APs", num); + if (*mHandler.on_hotlist_ap_found) + (*mHandler.on_hotlist_ap_found)(id(), num, mResults); + } else if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_LOST) { + ALOGD("LOST %d hotlist APs", num); + if (*mHandler.on_hotlist_ap_lost) + (*mHandler.on_hotlist_ap_lost)(id(), num, mResults); + } + return NL_SKIP; + } +}; + +wifi_error wifi_set_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface, + wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler) +{ + wifi_handle handle = getWifiHandle(iface); + + BssidHotlistCommand *cmd = new BssidHotlistCommand(iface, id, params, handler); + wifi_register_cmd(handle, id, cmd); + return (wifi_error)cmd->start(); +} + +wifi_error wifi_reset_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface) +{ + wifi_handle handle = getWifiHandle(iface); + + WifiCommand *cmd = wifi_unregister_cmd(handle, id); + if (cmd) { + cmd->cancel(); + cmd->releaseRef(); + return WIFI_SUCCESS; + } + + return WIFI_ERROR_INVALID_ARGS; +} + + +///////////////////////////////////////////////////////////////////////////// + +class SignificantWifiChangeCommand : public WifiCommand +{ + typedef struct { + mac_addr bssid; // BSSID + wifi_channel channel; // channel frequency in MHz + int num_rssi; // number of rssi samples + wifi_rssi rssi[8]; // RSSI history in db + } wifi_significant_change_result_internal; + +private: + wifi_significant_change_params mParams; + wifi_significant_change_handler mHandler; + static const int MAX_RESULTS = 64; + wifi_significant_change_result_internal mResultsBuffer[MAX_RESULTS]; + wifi_significant_change_result *mResults[MAX_RESULTS]; +public: + SignificantWifiChangeCommand(wifi_interface_handle handle, int id, + wifi_significant_change_params params, wifi_significant_change_handler handler) + : WifiCommand(handle, id), mParams(params), mHandler(handler) + { } + + int createSetupRequest(WifiRequest& request) { + int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_SIGNIFICANT_CHANGE); + if (result < 0) { + return result; + } + + nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); + + result = request.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE, mParams.rssi_sample_size); + if (result < 0) { + return result; + } + result = request.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size); + if (result < 0) { + return result; + } + result = request.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING, mParams.min_breaching); + if (result < 0) { + return result; + } + + struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS); + + for (int i = 0; i < mParams.num_bssid; i++) { + + nlattr *attr2 = request.attr_start(i); + if (attr2 == NULL) { + return WIFI_ERROR_OUT_OF_MEMORY; + } + result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid); + if (result < 0) { + return result; + } + result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high); + if (result < 0) { + return result; + } + result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low); + if (result < 0) { + return result; + } + request.attr_end(attr2); + } + + request.attr_end(attr); + request.attr_end(data); + + return result; + } + + int createTeardownRequest(WifiRequest& request) { + int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_RESET_SIGNIFICANT_CHANGE); + if (result < 0) { + return result; + } + + return result; + } + + int start() { + ALOGD("Set significant wifi change"); + WifiRequest request(familyId(), ifaceId()); + + int result = createSetupRequest(request); + if (result < 0) { + return result; + } + + result = requestResponse(request); + if (result < 0) { + ALOGD("failed to set significant wifi change %d", result); + return result; + } + registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); + + return result; + } + + virtual int cancel() { + /* unregister event handler */ + unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); + + /* create set significant change monitor message with empty hotlist */ + WifiRequest request(familyId(), ifaceId()); + + int result = createTeardownRequest(request); + if (result < 0) { + return result; + } + + result = requestResponse(request); + if (result < 0) { + return result; + } + + ALOGD("successfully reset significant wifi change"); + return result; + } + + virtual int handleResponse(WifiEvent& reply) { + /* Nothing to do on response! */ + return NL_SKIP; + } + + virtual int handleEvent(WifiEvent& event) { + ALOGD("Got a significant wifi change event"); + + nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); + int len = event.get_vendor_data_len(); + + if (vendor_data == NULL || len == 0) { + ALOGD("No scan results found"); + return NL_SKIP; + } + + typedef struct { + uint16_t channel; + mac_addr bssid; + int16_t rssi_history[8]; + } ChangeInfo; + + int num = min(len / sizeof(ChangeInfo), MAX_RESULTS); + ChangeInfo *ci = (ChangeInfo *)event.get_vendor_data(); + + for (int i = 0; i < num; i++) { + memcpy(mResultsBuffer[i].bssid, ci[i].bssid, sizeof(mac_addr)); + mResultsBuffer[i].channel = ci[i].channel; + /* Driver sends N samples and the rest 8-N are filled 0x7FFF + * N = no of rssi samples to average sent in significant change request. */ + int num_rssi = 0; + for (int j = 0; j < 8; j++) { + if (ci[i].rssi_history[j] == 0x7FFF) { + num_rssi = j; + break; + } + mResultsBuffer[i].rssi[j] = (int) ci[i].rssi_history[j]; + } + mResultsBuffer[i].num_rssi = num_rssi; + mResults[i] = reinterpret_cast(&(mResultsBuffer[i])); + } + + ALOGD("Retrieved %d scan results", num); + + if (num != 0) { + (*mHandler.on_significant_change)(id(), num, mResults); + } else { + ALOGW("No significant change reported"); + } + + return NL_SKIP; + } +}; + +wifi_error wifi_set_significant_change_handler(wifi_request_id id, wifi_interface_handle iface, + wifi_significant_change_params params, wifi_significant_change_handler handler) +{ + wifi_handle handle = getWifiHandle(iface); + + SignificantWifiChangeCommand *cmd = new SignificantWifiChangeCommand( + iface, id, params, handler); + wifi_register_cmd(handle, id, cmd); + return (wifi_error)cmd->start(); +} + +wifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface) +{ + wifi_handle handle = getWifiHandle(iface); + + WifiCommand *cmd = wifi_unregister_cmd(handle, id); + if (cmd) { + cmd->cancel(); + cmd->releaseRef(); + return WIFI_SUCCESS; + } + + return WIFI_ERROR_INVALID_ARGS; +} diff --git a/link_layer_stats.cpp b/link_layer_stats.cpp index 87406a8..eb0b34b 100755 --- a/link_layer_stats.cpp +++ b/link_layer_stats.cpp @@ -1,31 +1,31 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "sync.h" - -#define LOG_TAG "WifiHAL" - -#include - -#include "wifi_hal.h" -#include "common.h" -#include "cpp_bindings.h" -wifi_error wifi_get_link_stats(wifi_request_id id, - wifi_interface_handle iface, wifi_stats_result_handler handler) -{ - return WIFI_ERROR_NOT_SUPPORTED; -} +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "sync.h" + +#define LOG_TAG "WifiHAL" + +#include + +#include "wifi_hal.h" +#include "common.h" +#include "cpp_bindings.h" +wifi_error wifi_get_link_stats(wifi_request_id id, + wifi_interface_handle iface, wifi_stats_result_handler handler) +{ + return WIFI_ERROR_NOT_SUPPORTED; +} diff --git a/rtt.cpp b/rtt.cpp index ef92ae5..bd323e8 100755 --- a/rtt.cpp +++ b/rtt.cpp @@ -1,52 +1,52 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "nl80211_copy.h" - -#include "sync.h" - -#define LOG_TAG "WifiHAL" - -#include - -#include "wifi_hal.h" -#include "common.h" -#include "cpp_bindings.h" -/* API to request RTT measurement */ -wifi_error wifi_rtt_range_request(wifi_request_id id, wifi_interface_handle iface, - unsigned num_rtt_config, wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler) -{ - - return WIFI_ERROR_NOT_SUPPORTED; -} - -/* API to cancel RTT measurements */ -wifi_error wifi_rtt_range_cancel(wifi_request_id id, wifi_interface_handle iface, - unsigned num_devices, mac_addr addr[]) -{ - - - return WIFI_ERROR_NOT_SUPPORTED; -} - -/* API to get RTT capability */ -wifi_error wifi_get_rtt_capabilities(wifi_interface_handle iface, - wifi_rtt_capabilities *capabilities) -{ - - return WIFI_ERROR_NOT_SUPPORTED; -} +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "nl80211_copy.h" + +#include "sync.h" + +#define LOG_TAG "WifiHAL" + +#include + +#include "wifi_hal.h" +#include "common.h" +#include "cpp_bindings.h" +/* API to request RTT measurement */ +wifi_error wifi_rtt_range_request(wifi_request_id id, wifi_interface_handle iface, + unsigned num_rtt_config, wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler) +{ + + return WIFI_ERROR_NOT_SUPPORTED; +} + +/* API to cancel RTT measurements */ +wifi_error wifi_rtt_range_cancel(wifi_request_id id, wifi_interface_handle iface, + unsigned num_devices, mac_addr addr[]) +{ + + + return WIFI_ERROR_NOT_SUPPORTED; +} + +/* API to get RTT capability */ +wifi_error wifi_get_rtt_capabilities(wifi_interface_handle iface, + wifi_rtt_capabilities *capabilities) +{ + + return WIFI_ERROR_NOT_SUPPORTED; +} diff --git a/sync.h b/sync.h index 1dc0841..cea2ea9 100755 --- a/sync.h +++ b/sync.h @@ -1,54 +1,54 @@ - -#include - -#ifndef __WIFI_HAL_SYNC_H__ -#define __WIFI_HAL_SYNC_H__ - -class Mutex -{ -private: - pthread_mutex_t mMutex; -public: - Mutex() { - pthread_mutex_init(&mMutex, NULL); - } - ~Mutex() { - pthread_mutex_destroy(&mMutex); - } - int tryLock() { - return pthread_mutex_trylock(&mMutex); - } - int lock() { - return pthread_mutex_lock(&mMutex); - } - void unlock() { - pthread_mutex_unlock(&mMutex); - } -}; - -class Condition -{ -private: - pthread_cond_t mCondition; - pthread_mutex_t mMutex; - -public: - Condition() { - pthread_mutex_init(&mMutex, NULL); - pthread_cond_init(&mCondition, NULL); - } - ~Condition() { - pthread_cond_destroy(&mCondition); - pthread_mutex_destroy(&mMutex); - } - - int wait() { - return pthread_cond_wait(&mCondition, &mMutex); - } - - void signal() { - pthread_cond_signal(&mCondition); - } -}; - + +#include + +#ifndef __WIFI_HAL_SYNC_H__ +#define __WIFI_HAL_SYNC_H__ + +class Mutex +{ +private: + pthread_mutex_t mMutex; +public: + Mutex() { + pthread_mutex_init(&mMutex, NULL); + } + ~Mutex() { + pthread_mutex_destroy(&mMutex); + } + int tryLock() { + return pthread_mutex_trylock(&mMutex); + } + int lock() { + return pthread_mutex_lock(&mMutex); + } + void unlock() { + pthread_mutex_unlock(&mMutex); + } +}; + +class Condition +{ +private: + pthread_cond_t mCondition; + pthread_mutex_t mMutex; + +public: + Condition() { + pthread_mutex_init(&mMutex, NULL); + pthread_cond_init(&mCondition, NULL); + } + ~Condition() { + pthread_cond_destroy(&mCondition); + pthread_mutex_destroy(&mMutex); + } + + int wait() { + return pthread_cond_wait(&mCondition, &mMutex); + } + + void signal() { + pthread_cond_signal(&mCondition); + } +}; + #endif \ No newline at end of file diff --git a/wifi_hal.cpp b/wifi_hal.cpp index 51c7d4a..2c2cf0b 100755 --- a/wifi_hal.cpp +++ b/wifi_hal.cpp @@ -1,741 +1,741 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "sync.h" - -#define LOG_TAG "WifiHAL" - -#include - -#include "wifi_hal.h" -#include "common.h" -#include "cpp_bindings.h" - - -#define WIFI_HAL_CMD_SOCK_PORT 644 -#define WIFI_HAL_EVENT_SOCK_PORT 645 - -#define FEATURE_SET 0 -#define FEATURE_SET_MATRIX 1 -#define ATTR_NODFS_VALUE 3 - -static void internal_event_handler(wifi_handle handle, int events); -static int internal_no_seq_check(nl_msg *msg, void *arg); -static int internal_valid_message_handler(nl_msg *msg, void *arg); -static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group); -static int wifi_add_membership(wifi_handle handle, const char *group); -static wifi_error wifi_init_interfaces(wifi_handle handle); - -typedef enum wifi_attr { - ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, - ANDR_WIFI_ATTRIBUTE_FEATURE_SET, - ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI -} wifi_attr_t; - -/* Initialize/Cleanup */ - -void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port) -{ - uint32_t pid = getpid() & 0x3FFFFF; - nl_socket_set_local_port(sock, pid + (port << 22)); -} - -static nl_sock * wifi_create_nl_socket(int port) -{ - ALOGI("Creating socket"); - struct nl_sock *sock = nl_socket_alloc(); - if (sock == NULL) { - ALOGE("Could not create handle"); - return NULL; - } - - wifi_socket_set_local_port(sock, port); - - struct sockaddr *addr = NULL; - // ALOGI("sizeof(sockaddr) = %d, sizeof(sockaddr_nl) = %d", sizeof(*addr), sizeof(*addr_nl)); - - ALOGI("Connecting socket"); - if (nl_connect(sock, NETLINK_GENERIC)) { - ALOGE("Could not connect handle"); - nl_socket_free(sock); - return NULL; - } - - ALOGI("Making socket nonblocking"); - /* - if (nl_socket_set_nonblocking(sock)) { - ALOGE("Could make socket non-blocking"); - nl_socket_free(sock); - return NULL; - } - */ - - return sock; -} - -/*initialize function pointer table with Broadcom HHAL API*/ -wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) -{ - if (fn == NULL) { - return WIFI_ERROR_UNKNOWN; - } - fn->wifi_initialize = wifi_initialize; - fn->wifi_cleanup = wifi_cleanup; - fn->wifi_event_loop = wifi_event_loop; - fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set; - fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix; - fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui; - fn->wifi_get_ifaces = wifi_get_ifaces; - fn->wifi_get_iface_name = wifi_get_iface_name; - fn->wifi_start_gscan = wifi_start_gscan; - fn->wifi_stop_gscan = wifi_stop_gscan; - fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results; - fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist; - fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist; - fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler; - fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler; - fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities; - fn->wifi_get_link_stats = wifi_get_link_stats; - fn->wifi_get_valid_channels = wifi_get_valid_channels; - fn->wifi_rtt_range_request = wifi_rtt_range_request; - fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel; - fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities; - fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag; - return WIFI_SUCCESS; -} - -wifi_error wifi_initialize(wifi_handle *handle) -{ - srand(getpid()); - - ALOGI("Initializing wifi"); - hal_info *info = (hal_info *)malloc(sizeof(hal_info)); - if (info == NULL) { - ALOGE("Could not allocate hal_info"); - return WIFI_ERROR_UNKNOWN; - } - - memset(info, 0, sizeof(*info)); - - ALOGI("Creating socket"); - if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->cleanup_socks) == -1) { - ALOGE("Could not create cleanup sockets"); - free(info); - return WIFI_ERROR_UNKNOWN; - } - - struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT); - if (cmd_sock == NULL) { - ALOGE("Could not create handle"); - free(info); - return WIFI_ERROR_UNKNOWN; - } - - struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT); - if (event_sock == NULL) { - ALOGE("Could not create handle"); - nl_socket_free(cmd_sock); - free(info); - return WIFI_ERROR_UNKNOWN; - } - - struct nl_cb *cb = nl_socket_get_cb(event_sock); - if (cb == NULL) { - ALOGE("Could not create handle"); - nl_socket_free(cmd_sock); - nl_socket_free(event_sock); - free(info); - return WIFI_ERROR_UNKNOWN; - } - -// ALOGI("cb->refcnt = %d", cb->cb_refcnt); - nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, info); - nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info); - nl_cb_put(cb); - - info->cmd_sock = cmd_sock; - info->event_sock = event_sock; - info->clean_up = false; - info->in_event_loop = false; - - info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE); - info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE; - info->num_event_cb = 0; - - info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE); - info->alloc_cmd = DEFAULT_CMD_SIZE; - info->num_cmd = 0; - - info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211"); - if (info->nl80211_family_id < 0) { - ALOGE("Could not resolve nl80211 familty id"); - nl_socket_free(cmd_sock); - nl_socket_free(event_sock); - free(info); - return WIFI_ERROR_UNKNOWN; - } - - pthread_mutex_init(&info->cb_lock, NULL); - - *handle = (wifi_handle) info; - ALOGD("wifi_initialize, handle = %p\n", handle); - ALOGD("wifi_initialize, *handle = %p\n", *handle); - ALOGD("wifi_initialize, info = %p\n", info); - ALOGD("wifi_initialize, *info = %pn", *info); - wifi_add_membership(*handle, "scan"); - wifi_add_membership(*handle, "mlme"); - wifi_add_membership(*handle, "regulatory"); - wifi_add_membership(*handle, "vendor"); - - wifi_init_interfaces(*handle); - ALOGD("Found %d interfaces", info->num_interfaces); - - - ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d", NL80211_CMD_VENDOR); - return WIFI_SUCCESS; -} - -static int wifi_add_membership(wifi_handle handle, const char *group) -{ - hal_info *info = getHalInfo(handle); - - int id = wifi_get_multicast_id(handle, "nl80211", group); - if (id < 0) { - ALOGE("Could not find group %s", group); - return id; - } - - int ret = nl_socket_add_membership(info->event_sock, id); - if (ret < 0) { - ALOGE("Could not add membership to group %s", group); - } - - ALOGI("Successfully added membership for group %s", group); - return ret; -} - -static void internal_cleaned_up_handler(wifi_handle handle) -{ - hal_info *info = getHalInfo(handle); - wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler; - - if (info->cmd_sock != 0) { - close(info->cleanup_socks[0]); - close(info->cleanup_socks[1]); - nl_socket_free(info->cmd_sock); - nl_socket_free(info->event_sock); - info->cmd_sock = NULL; - info->event_sock = NULL; - } - - (*cleaned_up_handler)(handle); - pthread_mutex_destroy(&info->cb_lock); - free(info); - - ALOGI("Internal cleanup completed"); -} - -void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler) -{ - hal_info *info = getHalInfo(handle); - char buf[64]; - - info->cleaned_up_handler = handler; - if (write(info->cleanup_socks[0], "Exit", 4) < 1) { - ALOGE("could not write to the cleanup socket"); - } else { - // Listen to the response - // Hopefully we dont get errors or get hung up - // Not much can be done in that case, but assume that - // it has rx'ed the Exit message to exit the thread. - // As a fallback set the cleanup flag to TRUE - memset(buf, 0, sizeof(buf)); - int result = read(info->cleanup_socks[0], buf, sizeof(buf)); - ALOGE("%s: Read after POLL returned %d, error no = %d", __FUNCTION__, result, errno); - if (strncmp(buf, "Done", 4) == 0) { - ALOGE("Event processing terminated"); - } else { - ALOGD("Rx'ed %s", buf); - } - } - info->clean_up = true; - pthread_mutex_lock(&info->cb_lock); - - int bad_commands = 0; - - for (int i = 0; i < info->num_event_cb; i++) { - cb_info *cbi = &(info->event_cb[i]); - WifiCommand *cmd = (WifiCommand *)cbi->cb_arg; - } - - while (info->num_cmd > bad_commands) { - int num_cmd = info->num_cmd; - cmd_info *cmdi = &(info->cmd[bad_commands]); - WifiCommand *cmd = cmdi->cmd; - if (cmd != NULL) { - pthread_mutex_unlock(&info->cb_lock); - cmd->cancel(); - pthread_mutex_lock(&info->cb_lock); - /* release reference added when command is saved */ - cmd->releaseRef(); - if (num_cmd == info->num_cmd) { - bad_commands++; - } - } - } - - for (int i = 0; i < info->num_event_cb; i++) { - cb_info *cbi = &(info->event_cb[i]); - WifiCommand *cmd = (WifiCommand *)cbi->cb_arg; - ALOGE("Leaked command %p", cmd); - } - pthread_mutex_unlock(&info->cb_lock); - internal_cleaned_up_handler(handle); -} - -static int internal_pollin_handler(wifi_handle handle) -{ - hal_info *info = getHalInfo(handle); - ALOGI("even_loop info = %p", info); - struct nl_cb *cb = nl_socket_get_cb(info->event_sock); - int res = nl_recvmsgs(info->event_sock, cb); - ALOGD("nl_recvmsgs returned %d", res); - nl_cb_put(cb); - return res; -} - -/* Run event handler */ -void wifi_event_loop(wifi_handle handle) -{ - hal_info *info = getHalInfo(handle); - ALOGI("even_loop info = %p", info); - ALOGI("even_loop info = %p", handle); - if (info->in_event_loop) { - return; - } else { - info->in_event_loop = true; - } - - pollfd pfd[2]; - memset(&pfd[0], 0, sizeof(pollfd) * 2); - - pfd[0].fd = nl_socket_get_fd(info->event_sock); - pfd[0].events = POLLIN; - pfd[1].fd = info->cleanup_socks[1]; - pfd[1].events = POLLIN; - - char buf[2048]; - - do { - int timeout = -1; /* Infinite timeout */ - pfd[0].revents = 0; - pfd[1].revents = 0; - int result = poll(pfd, 2, timeout); - if (result < 0) { - } else if (pfd[0].revents & POLLERR) { - ALOGE("POLL Error; error no = %d", errno); - int result2 = read(pfd[0].fd, buf, sizeof(buf)); - ALOGE("Read after POLL returned %d, error no = %d", result2, errno); - } else if (pfd[0].revents & POLLHUP) { - ALOGE("Remote side hung up"); - break; - } else if (pfd[0].revents & POLLIN) { - internal_pollin_handler(handle); - } else if (pfd[1].revents & POLLIN) { - memset(buf, 0, sizeof(buf)); - int result2 = read(pfd[1].fd, buf, sizeof(buf)); - ALOGE("%s: Read after POLL returned %d, error no = %d", __FUNCTION__, result2, errno); - if (strncmp(buf, "Exit", 4) == 0) { - ALOGD("Got a signal to exit!!!"); - if (write(pfd[1].fd, "Done", 4) < 1) { - ALOGE("could not write to the cleanup socket"); - } - break; - } else { - ALOGD("Rx'ed %s on the cleanup socket\n", buf); - } - } else { - ALOGE("Unknown event - %0x, %0x", pfd[0].revents, pfd[1].revents); - } - } while (!info->clean_up); - ALOGI("Exit %s", __FUNCTION__); -} - -/////////////////////////////////////////////////////////////////////////////////////// - -static int internal_no_seq_check(struct nl_msg *msg, void *arg) -{ - return NL_OK; -} - -static int internal_valid_message_handler(nl_msg *msg, void *arg) -{ - wifi_handle handle = (wifi_handle)arg; - hal_info *info = getHalInfo(handle); - ALOGI("even_loop info = %p", handle); - ALOGD("internal_valid_message_handler, info = %p", info); - - WifiEvent event(msg); - int res = event.parse(); - if (res < 0) { - ALOGE("Failed to parse event: %d", res); - return NL_SKIP; - } - - int cmd = event.get_cmd(); - uint32_t vendor_id = 0; - int subcmd = 0; - - if (cmd == NL80211_CMD_VENDOR) { - vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID); - subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD); - ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x", - event.get_cmdString(), vendor_id, subcmd); - } else { - ALOGI("event received %s", event.get_cmdString()); - } - - //ALOGI("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id); - //event.log(); - - bool dispatched = false; - - pthread_mutex_lock(&info->cb_lock); - - ALOGI("Number of events %d", info->num_event_cb); - - for (int i = 0; i < info->num_event_cb; i++) { - if (cmd == info->event_cb[i].nl_cmd) { - if (cmd == NL80211_CMD_VENDOR - && ((vendor_id != info->event_cb[i].vendor_id) - || (subcmd != info->event_cb[i].vendor_subcmd))) - { - /* event for a different vendor, ignore it */ - continue; - } - - cb_info *cbi = &(info->event_cb[i]); - nl_recvmsg_msg_cb_t cb_func = cbi->cb_func; - void *cb_arg = cbi->cb_arg; - WifiCommand *cmd = (WifiCommand *)cbi->cb_arg; - if (cmd != NULL) { - cmd->addRef(); - } - - pthread_mutex_unlock(&info->cb_lock); - if (cb_func) - (*cb_func)(msg, cb_arg); - if (cmd != NULL) { - cmd->releaseRef(); - } - - return NL_OK; - } - } - - pthread_mutex_unlock(&info->cb_lock); - return NL_OK; -} - -/////////////////////////////////////////////////////////////////////////////////////// - -class GetMulticastIdCommand : public WifiCommand -{ -private: - const char *mName; - const char *mGroup; - int mId; -public: - GetMulticastIdCommand(wifi_handle handle, const char *name, const char *group) - : WifiCommand(handle, 0) - { - mName = name; - mGroup = group; - mId = -1; - } - - int getId() { - return mId; - } - - virtual int create() { - int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl"); - ALOGI("ctrl family = %d", nlctrlFamily); - int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0); - if (ret < 0) { - return ret; - } - ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName); - return ret; - } - - virtual int handleResponse(WifiEvent& reply) { - - ALOGE("handling reponse in %s", __func__); - - struct nlattr **tb = reply.attributes(); - struct genlmsghdr *gnlh = reply.header(); - struct nlattr *mcgrp = NULL; - int i; - - if (!tb[CTRL_ATTR_MCAST_GROUPS]) { - ALOGE("No multicast groups found"); - return NL_SKIP; - } else { - ALOGE("Multicast groups attr size = %d", nla_len(tb[CTRL_ATTR_MCAST_GROUPS])); - } - - for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) { - - ALOGE("Processing group"); - struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1]; - nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp), - nla_len(mcgrp), NULL); - if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID]) { - continue; - } - - char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]); - int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]); - - ALOGE("Found group name %s", grpName); - - if (strncmp(grpName, mGroup, grpNameLen) != 0) - continue; - - mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]); - break; - } - - return NL_SKIP; - } - -}; - -class SetPnoMacAddrOuiCommand : public WifiCommand { - -private: - byte *mOui; - feature_set *fset; - feature_set *feature_matrix; - int *fm_size; - int set_size_max; -public: - SetPnoMacAddrOuiCommand(wifi_interface_handle handle, oui scan_oui) - : WifiCommand(handle, 0) - { - mOui = scan_oui; - } - - int createRequest(WifiRequest& request, int subcmd, byte *scan_oui) { - int result = request.create(GOOGLE_OUI, subcmd); - if (result < 0) { - return result; - } - - nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); - result = request.put(ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, scan_oui, DOT11_OUI_LEN); - if (result < 0) { - return result; - } - - request.attr_end(data); - return WIFI_SUCCESS; - - } - - int start() { - ALOGD("Sending mac address OUI"); - WifiRequest request(familyId(), ifaceId()); - int result = createRequest(request, SLSI_NL80211_VENDOR_SUBCMD_SET_GSCAN_OUI, mOui); - if (result != WIFI_SUCCESS) { - ALOGE("failed to create request; result = %d", result); - return result; - } - - result = requestResponse(request); - if (result != WIFI_SUCCESS) { - ALOGE("failed to set scanning mac OUI; result = %d", result); - } - - return result; - } -protected: - virtual int handleResponse(WifiEvent& reply) { - ALOGD("Request complete!"); - /* Nothing to do on response! */ - return NL_SKIP; - } -}; - -class SetNodfsCommand : public WifiCommand { - -private: - u32 mNoDfs; -public: - SetNodfsCommand(wifi_interface_handle handle, u32 nodfs) - : WifiCommand(handle, 0) { - mNoDfs = nodfs; - } - virtual int create() { - int ret; - - ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_NODFS); - if (ret < 0) { - ALOGE("Can't create message to send to driver - %d", ret); - return ret; - } - - nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA); - ret = mMsg.put_u32(ATTR_NODFS_VALUE, mNoDfs); - if (ret < 0) { - return ret; - } - - mMsg.attr_end(data); - return WIFI_SUCCESS; - } -}; - -static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group) -{ - GetMulticastIdCommand cmd(handle, name, group); - int res = cmd.requestResponse(); - if (res < 0) - return res; - else - return cmd.getId(); -} - -///////////////////////////////////////////////////////////////////////// - -static bool is_wifi_interface(const char *name) -{ - if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) { - /* not a wifi interface; ignore it */ - return false; - } else { - return true; - } -} - -static int get_interface(const char *name, interface_info *info) -{ - strcpy(info->name, name); - info->id = if_nametoindex(name); - ALOGI("found an interface : %s, id = %d", name, info->id); - return WIFI_SUCCESS; -} - -wifi_error wifi_init_interfaces(wifi_handle handle) -{ - hal_info *info = (hal_info *)handle; - ALOGD("wifi_init_interfaces, info = %p", info); - - struct dirent *de; - - DIR *d = opendir("/sys/class/net"); - if (d == 0) - return WIFI_ERROR_UNKNOWN; - - int n = 0; - while ((de = readdir(d))) { - if (de->d_name[0] == '.') - continue; - if (is_wifi_interface(de->d_name) ) { - n++; - } - } - - closedir(d); - - d = opendir("/sys/class/net"); - if (d == 0) - return WIFI_ERROR_UNKNOWN; - - info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n); - - int i = 0; - while ((de = readdir(d))) { - if (de->d_name[0] == '.') - continue; - if (is_wifi_interface(de->d_name)) { - interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info)); - if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) { - free(ifinfo); - continue; - } - ifinfo->handle = handle; - info->interfaces[i] = ifinfo; - i++; - } - } - - closedir(d); - - info->num_interfaces = n; - return WIFI_SUCCESS; -} - -wifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle **interfaces) -{ - hal_info *info = (hal_info *)handle; - - *interfaces = (wifi_interface_handle *)info->interfaces; - *num = info->num_interfaces; - - return WIFI_SUCCESS; -} - -wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size) -{ - interface_info *info = (interface_info *)handle; - strcpy(name, info->name); - return WIFI_SUCCESS; -} - -wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *set) -{ - return WIFI_ERROR_NOT_SUPPORTED; -} - -wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_size_max, - feature_set set[], int *set_size) -{ - return WIFI_ERROR_NOT_SUPPORTED; -} - -wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui) -{ - SetPnoMacAddrOuiCommand command(handle, scan_oui); - return (wifi_error)command.start(); - -} - -wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs) -{ - SetNodfsCommand command(handle, nodfs); - return (wifi_error) command.requestResponse(); -} - -///////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "sync.h" + +#define LOG_TAG "WifiHAL" + +#include + +#include "wifi_hal.h" +#include "common.h" +#include "cpp_bindings.h" + + +#define WIFI_HAL_CMD_SOCK_PORT 644 +#define WIFI_HAL_EVENT_SOCK_PORT 645 + +#define FEATURE_SET 0 +#define FEATURE_SET_MATRIX 1 +#define ATTR_NODFS_VALUE 3 + +static void internal_event_handler(wifi_handle handle, int events); +static int internal_no_seq_check(nl_msg *msg, void *arg); +static int internal_valid_message_handler(nl_msg *msg, void *arg); +static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group); +static int wifi_add_membership(wifi_handle handle, const char *group); +static wifi_error wifi_init_interfaces(wifi_handle handle); + +typedef enum wifi_attr { + ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, + ANDR_WIFI_ATTRIBUTE_FEATURE_SET, + ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI +} wifi_attr_t; + +/* Initialize/Cleanup */ + +void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port) +{ + uint32_t pid = getpid() & 0x3FFFFF; + nl_socket_set_local_port(sock, pid + (port << 22)); +} + +static nl_sock * wifi_create_nl_socket(int port) +{ + ALOGI("Creating socket"); + struct nl_sock *sock = nl_socket_alloc(); + if (sock == NULL) { + ALOGE("Could not create handle"); + return NULL; + } + + wifi_socket_set_local_port(sock, port); + + struct sockaddr *addr = NULL; + // ALOGI("sizeof(sockaddr) = %d, sizeof(sockaddr_nl) = %d", sizeof(*addr), sizeof(*addr_nl)); + + ALOGI("Connecting socket"); + if (nl_connect(sock, NETLINK_GENERIC)) { + ALOGE("Could not connect handle"); + nl_socket_free(sock); + return NULL; + } + + ALOGI("Making socket nonblocking"); + /* + if (nl_socket_set_nonblocking(sock)) { + ALOGE("Could make socket non-blocking"); + nl_socket_free(sock); + return NULL; + } + */ + + return sock; +} + +/*initialize function pointer table with Broadcom HHAL API*/ +wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) +{ + if (fn == NULL) { + return WIFI_ERROR_UNKNOWN; + } + fn->wifi_initialize = wifi_initialize; + fn->wifi_cleanup = wifi_cleanup; + fn->wifi_event_loop = wifi_event_loop; + fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set; + fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix; + fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui; + fn->wifi_get_ifaces = wifi_get_ifaces; + fn->wifi_get_iface_name = wifi_get_iface_name; + fn->wifi_start_gscan = wifi_start_gscan; + fn->wifi_stop_gscan = wifi_stop_gscan; + fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results; + fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist; + fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist; + fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler; + fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler; + fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities; + fn->wifi_get_link_stats = wifi_get_link_stats; + fn->wifi_get_valid_channels = wifi_get_valid_channels; + fn->wifi_rtt_range_request = wifi_rtt_range_request; + fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel; + fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities; + fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag; + return WIFI_SUCCESS; +} + +wifi_error wifi_initialize(wifi_handle *handle) +{ + srand(getpid()); + + ALOGI("Initializing wifi"); + hal_info *info = (hal_info *)malloc(sizeof(hal_info)); + if (info == NULL) { + ALOGE("Could not allocate hal_info"); + return WIFI_ERROR_UNKNOWN; + } + + memset(info, 0, sizeof(*info)); + + ALOGI("Creating socket"); + if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->cleanup_socks) == -1) { + ALOGE("Could not create cleanup sockets"); + free(info); + return WIFI_ERROR_UNKNOWN; + } + + struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT); + if (cmd_sock == NULL) { + ALOGE("Could not create handle"); + free(info); + return WIFI_ERROR_UNKNOWN; + } + + struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT); + if (event_sock == NULL) { + ALOGE("Could not create handle"); + nl_socket_free(cmd_sock); + free(info); + return WIFI_ERROR_UNKNOWN; + } + + struct nl_cb *cb = nl_socket_get_cb(event_sock); + if (cb == NULL) { + ALOGE("Could not create handle"); + nl_socket_free(cmd_sock); + nl_socket_free(event_sock); + free(info); + return WIFI_ERROR_UNKNOWN; + } + +// ALOGI("cb->refcnt = %d", cb->cb_refcnt); + nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, info); + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info); + nl_cb_put(cb); + + info->cmd_sock = cmd_sock; + info->event_sock = event_sock; + info->clean_up = false; + info->in_event_loop = false; + + info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE); + info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE; + info->num_event_cb = 0; + + info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE); + info->alloc_cmd = DEFAULT_CMD_SIZE; + info->num_cmd = 0; + + info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211"); + if (info->nl80211_family_id < 0) { + ALOGE("Could not resolve nl80211 familty id"); + nl_socket_free(cmd_sock); + nl_socket_free(event_sock); + free(info); + return WIFI_ERROR_UNKNOWN; + } + + pthread_mutex_init(&info->cb_lock, NULL); + + *handle = (wifi_handle) info; + ALOGD("wifi_initialize, handle = %p\n", handle); + ALOGD("wifi_initialize, *handle = %p\n", *handle); + ALOGD("wifi_initialize, info = %p\n", info); + ALOGD("wifi_initialize, *info = %pn", *info); + wifi_add_membership(*handle, "scan"); + wifi_add_membership(*handle, "mlme"); + wifi_add_membership(*handle, "regulatory"); + wifi_add_membership(*handle, "vendor"); + + wifi_init_interfaces(*handle); + ALOGD("Found %d interfaces", info->num_interfaces); + + + ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d", NL80211_CMD_VENDOR); + return WIFI_SUCCESS; +} + +static int wifi_add_membership(wifi_handle handle, const char *group) +{ + hal_info *info = getHalInfo(handle); + + int id = wifi_get_multicast_id(handle, "nl80211", group); + if (id < 0) { + ALOGE("Could not find group %s", group); + return id; + } + + int ret = nl_socket_add_membership(info->event_sock, id); + if (ret < 0) { + ALOGE("Could not add membership to group %s", group); + } + + ALOGI("Successfully added membership for group %s", group); + return ret; +} + +static void internal_cleaned_up_handler(wifi_handle handle) +{ + hal_info *info = getHalInfo(handle); + wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler; + + if (info->cmd_sock != 0) { + close(info->cleanup_socks[0]); + close(info->cleanup_socks[1]); + nl_socket_free(info->cmd_sock); + nl_socket_free(info->event_sock); + info->cmd_sock = NULL; + info->event_sock = NULL; + } + + (*cleaned_up_handler)(handle); + pthread_mutex_destroy(&info->cb_lock); + free(info); + + ALOGI("Internal cleanup completed"); +} + +void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler) +{ + hal_info *info = getHalInfo(handle); + char buf[64]; + + info->cleaned_up_handler = handler; + if (write(info->cleanup_socks[0], "Exit", 4) < 1) { + ALOGE("could not write to the cleanup socket"); + } else { + // Listen to the response + // Hopefully we dont get errors or get hung up + // Not much can be done in that case, but assume that + // it has rx'ed the Exit message to exit the thread. + // As a fallback set the cleanup flag to TRUE + memset(buf, 0, sizeof(buf)); + int result = read(info->cleanup_socks[0], buf, sizeof(buf)); + ALOGE("%s: Read after POLL returned %d, error no = %d", __FUNCTION__, result, errno); + if (strncmp(buf, "Done", 4) == 0) { + ALOGE("Event processing terminated"); + } else { + ALOGD("Rx'ed %s", buf); + } + } + info->clean_up = true; + pthread_mutex_lock(&info->cb_lock); + + int bad_commands = 0; + + for (int i = 0; i < info->num_event_cb; i++) { + cb_info *cbi = &(info->event_cb[i]); + WifiCommand *cmd = (WifiCommand *)cbi->cb_arg; + } + + while (info->num_cmd > bad_commands) { + int num_cmd = info->num_cmd; + cmd_info *cmdi = &(info->cmd[bad_commands]); + WifiCommand *cmd = cmdi->cmd; + if (cmd != NULL) { + pthread_mutex_unlock(&info->cb_lock); + cmd->cancel(); + pthread_mutex_lock(&info->cb_lock); + /* release reference added when command is saved */ + cmd->releaseRef(); + if (num_cmd == info->num_cmd) { + bad_commands++; + } + } + } + + for (int i = 0; i < info->num_event_cb; i++) { + cb_info *cbi = &(info->event_cb[i]); + WifiCommand *cmd = (WifiCommand *)cbi->cb_arg; + ALOGE("Leaked command %p", cmd); + } + pthread_mutex_unlock(&info->cb_lock); + internal_cleaned_up_handler(handle); +} + +static int internal_pollin_handler(wifi_handle handle) +{ + hal_info *info = getHalInfo(handle); + ALOGI("even_loop info = %p", info); + struct nl_cb *cb = nl_socket_get_cb(info->event_sock); + int res = nl_recvmsgs(info->event_sock, cb); + ALOGD("nl_recvmsgs returned %d", res); + nl_cb_put(cb); + return res; +} + +/* Run event handler */ +void wifi_event_loop(wifi_handle handle) +{ + hal_info *info = getHalInfo(handle); + ALOGI("even_loop info = %p", info); + ALOGI("even_loop info = %p", handle); + if (info->in_event_loop) { + return; + } else { + info->in_event_loop = true; + } + + pollfd pfd[2]; + memset(&pfd[0], 0, sizeof(pollfd) * 2); + + pfd[0].fd = nl_socket_get_fd(info->event_sock); + pfd[0].events = POLLIN; + pfd[1].fd = info->cleanup_socks[1]; + pfd[1].events = POLLIN; + + char buf[2048]; + + do { + int timeout = -1; /* Infinite timeout */ + pfd[0].revents = 0; + pfd[1].revents = 0; + int result = poll(pfd, 2, timeout); + if (result < 0) { + } else if (pfd[0].revents & POLLERR) { + ALOGE("POLL Error; error no = %d", errno); + int result2 = read(pfd[0].fd, buf, sizeof(buf)); + ALOGE("Read after POLL returned %d, error no = %d", result2, errno); + } else if (pfd[0].revents & POLLHUP) { + ALOGE("Remote side hung up"); + break; + } else if (pfd[0].revents & POLLIN) { + internal_pollin_handler(handle); + } else if (pfd[1].revents & POLLIN) { + memset(buf, 0, sizeof(buf)); + int result2 = read(pfd[1].fd, buf, sizeof(buf)); + ALOGE("%s: Read after POLL returned %d, error no = %d", __FUNCTION__, result2, errno); + if (strncmp(buf, "Exit", 4) == 0) { + ALOGD("Got a signal to exit!!!"); + if (write(pfd[1].fd, "Done", 4) < 1) { + ALOGE("could not write to the cleanup socket"); + } + break; + } else { + ALOGD("Rx'ed %s on the cleanup socket\n", buf); + } + } else { + ALOGE("Unknown event - %0x, %0x", pfd[0].revents, pfd[1].revents); + } + } while (!info->clean_up); + ALOGI("Exit %s", __FUNCTION__); +} + +/////////////////////////////////////////////////////////////////////////////////////// + +static int internal_no_seq_check(struct nl_msg *msg, void *arg) +{ + return NL_OK; +} + +static int internal_valid_message_handler(nl_msg *msg, void *arg) +{ + wifi_handle handle = (wifi_handle)arg; + hal_info *info = getHalInfo(handle); + ALOGI("even_loop info = %p", handle); + ALOGD("internal_valid_message_handler, info = %p", info); + + WifiEvent event(msg); + int res = event.parse(); + if (res < 0) { + ALOGE("Failed to parse event: %d", res); + return NL_SKIP; + } + + int cmd = event.get_cmd(); + uint32_t vendor_id = 0; + int subcmd = 0; + + if (cmd == NL80211_CMD_VENDOR) { + vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID); + subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD); + ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x", + event.get_cmdString(), vendor_id, subcmd); + } else { + ALOGI("event received %s", event.get_cmdString()); + } + + //ALOGI("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id); + //event.log(); + + bool dispatched = false; + + pthread_mutex_lock(&info->cb_lock); + + ALOGI("Number of events %d", info->num_event_cb); + + for (int i = 0; i < info->num_event_cb; i++) { + if (cmd == info->event_cb[i].nl_cmd) { + if (cmd == NL80211_CMD_VENDOR + && ((vendor_id != info->event_cb[i].vendor_id) + || (subcmd != info->event_cb[i].vendor_subcmd))) + { + /* event for a different vendor, ignore it */ + continue; + } + + cb_info *cbi = &(info->event_cb[i]); + nl_recvmsg_msg_cb_t cb_func = cbi->cb_func; + void *cb_arg = cbi->cb_arg; + WifiCommand *cmd = (WifiCommand *)cbi->cb_arg; + if (cmd != NULL) { + cmd->addRef(); + } + + pthread_mutex_unlock(&info->cb_lock); + if (cb_func) + (*cb_func)(msg, cb_arg); + if (cmd != NULL) { + cmd->releaseRef(); + } + + return NL_OK; + } + } + + pthread_mutex_unlock(&info->cb_lock); + return NL_OK; +} + +/////////////////////////////////////////////////////////////////////////////////////// + +class GetMulticastIdCommand : public WifiCommand +{ +private: + const char *mName; + const char *mGroup; + int mId; +public: + GetMulticastIdCommand(wifi_handle handle, const char *name, const char *group) + : WifiCommand(handle, 0) + { + mName = name; + mGroup = group; + mId = -1; + } + + int getId() { + return mId; + } + + virtual int create() { + int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl"); + ALOGI("ctrl family = %d", nlctrlFamily); + int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0); + if (ret < 0) { + return ret; + } + ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName); + return ret; + } + + virtual int handleResponse(WifiEvent& reply) { + + ALOGE("handling reponse in %s", __func__); + + struct nlattr **tb = reply.attributes(); + struct genlmsghdr *gnlh = reply.header(); + struct nlattr *mcgrp = NULL; + int i; + + if (!tb[CTRL_ATTR_MCAST_GROUPS]) { + ALOGE("No multicast groups found"); + return NL_SKIP; + } else { + ALOGE("Multicast groups attr size = %d", nla_len(tb[CTRL_ATTR_MCAST_GROUPS])); + } + + for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) { + + ALOGE("Processing group"); + struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1]; + nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp), + nla_len(mcgrp), NULL); + if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID]) { + continue; + } + + char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]); + int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]); + + ALOGE("Found group name %s", grpName); + + if (strncmp(grpName, mGroup, grpNameLen) != 0) + continue; + + mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]); + break; + } + + return NL_SKIP; + } + +}; + +class SetPnoMacAddrOuiCommand : public WifiCommand { + +private: + byte *mOui; + feature_set *fset; + feature_set *feature_matrix; + int *fm_size; + int set_size_max; +public: + SetPnoMacAddrOuiCommand(wifi_interface_handle handle, oui scan_oui) + : WifiCommand(handle, 0) + { + mOui = scan_oui; + } + + int createRequest(WifiRequest& request, int subcmd, byte *scan_oui) { + int result = request.create(GOOGLE_OUI, subcmd); + if (result < 0) { + return result; + } + + nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); + result = request.put(ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, scan_oui, DOT11_OUI_LEN); + if (result < 0) { + return result; + } + + request.attr_end(data); + return WIFI_SUCCESS; + + } + + int start() { + ALOGD("Sending mac address OUI"); + WifiRequest request(familyId(), ifaceId()); + int result = createRequest(request, SLSI_NL80211_VENDOR_SUBCMD_SET_GSCAN_OUI, mOui); + if (result != WIFI_SUCCESS) { + ALOGE("failed to create request; result = %d", result); + return result; + } + + result = requestResponse(request); + if (result != WIFI_SUCCESS) { + ALOGE("failed to set scanning mac OUI; result = %d", result); + } + + return result; + } +protected: + virtual int handleResponse(WifiEvent& reply) { + ALOGD("Request complete!"); + /* Nothing to do on response! */ + return NL_SKIP; + } +}; + +class SetNodfsCommand : public WifiCommand { + +private: + u32 mNoDfs; +public: + SetNodfsCommand(wifi_interface_handle handle, u32 nodfs) + : WifiCommand(handle, 0) { + mNoDfs = nodfs; + } + virtual int create() { + int ret; + + ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_NODFS); + if (ret < 0) { + ALOGE("Can't create message to send to driver - %d", ret); + return ret; + } + + nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA); + ret = mMsg.put_u32(ATTR_NODFS_VALUE, mNoDfs); + if (ret < 0) { + return ret; + } + + mMsg.attr_end(data); + return WIFI_SUCCESS; + } +}; + +static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group) +{ + GetMulticastIdCommand cmd(handle, name, group); + int res = cmd.requestResponse(); + if (res < 0) + return res; + else + return cmd.getId(); +} + +///////////////////////////////////////////////////////////////////////// + +static bool is_wifi_interface(const char *name) +{ + if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) { + /* not a wifi interface; ignore it */ + return false; + } else { + return true; + } +} + +static int get_interface(const char *name, interface_info *info) +{ + strcpy(info->name, name); + info->id = if_nametoindex(name); + ALOGI("found an interface : %s, id = %d", name, info->id); + return WIFI_SUCCESS; +} + +wifi_error wifi_init_interfaces(wifi_handle handle) +{ + hal_info *info = (hal_info *)handle; + ALOGD("wifi_init_interfaces, info = %p", info); + + struct dirent *de; + + DIR *d = opendir("/sys/class/net"); + if (d == 0) + return WIFI_ERROR_UNKNOWN; + + int n = 0; + while ((de = readdir(d))) { + if (de->d_name[0] == '.') + continue; + if (is_wifi_interface(de->d_name) ) { + n++; + } + } + + closedir(d); + + d = opendir("/sys/class/net"); + if (d == 0) + return WIFI_ERROR_UNKNOWN; + + info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n); + + int i = 0; + while ((de = readdir(d))) { + if (de->d_name[0] == '.') + continue; + if (is_wifi_interface(de->d_name)) { + interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info)); + if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) { + free(ifinfo); + continue; + } + ifinfo->handle = handle; + info->interfaces[i] = ifinfo; + i++; + } + } + + closedir(d); + + info->num_interfaces = n; + return WIFI_SUCCESS; +} + +wifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle **interfaces) +{ + hal_info *info = (hal_info *)handle; + + *interfaces = (wifi_interface_handle *)info->interfaces; + *num = info->num_interfaces; + + return WIFI_SUCCESS; +} + +wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size) +{ + interface_info *info = (interface_info *)handle; + strcpy(name, info->name); + return WIFI_SUCCESS; +} + +wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *set) +{ + return WIFI_ERROR_NOT_SUPPORTED; +} + +wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_size_max, + feature_set set[], int *set_size) +{ + return WIFI_ERROR_NOT_SUPPORTED; +} + +wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui) +{ + SetPnoMacAddrOuiCommand command(handle, scan_oui); + return (wifi_error)command.start(); + +} + +wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs) +{ + SetNodfsCommand command(handle, nodfs); + return (wifi_error) command.requestResponse(); +} + +///////////////////////////////////////////////////////////////////////////// -- 2.20.1