diff options
author | Ashwin <ashwin.bhat@broadcom.com> | 2015-03-19 16:07:39 -0700 |
---|---|---|
committer | Ashwin <ashwin.bhat@broadcom.com> | 2015-03-19 16:07:39 -0700 |
commit | 89a9a4cffbcee6af504c61ff575a008194070c82 (patch) | |
tree | 8a40bed60694d51541e4079d9b4490543cee64c5 /bcmdhd/wifi_hal | |
parent | 886a7c99f8664295fe233034cac84d6253324641 (diff) | |
download | hardware_broadcom_wlan-89a9a4cffbcee6af504c61ff575a008194070c82.zip hardware_broadcom_wlan-89a9a4cffbcee6af504c61ff575a008194070c82.tar.gz hardware_broadcom_wlan-89a9a4cffbcee6af504c61ff575a008194070c82.tar.bz2 |
ePNO changes
Support for ePNO changes. Can send ePNO SSIDs to driver and get results
Exponential backoff will be added in the next update
Change-Id: I6a420811c0dc503ccb2d8d1a502dbdeedcf9ca2a
Signed-off-by: Ashwin <ashwin.bhat@broadcom.com>
Diffstat (limited to 'bcmdhd/wifi_hal')
-rw-r--r-- | bcmdhd/wifi_hal/common.h | 18 | ||||
-rw-r--r-- | bcmdhd/wifi_hal/gscan.cpp | 198 |
2 files changed, 213 insertions, 3 deletions
diff --git a/bcmdhd/wifi_hal/common.h b/bcmdhd/wifi_hal/common.h index f94c16d..be1d10a 100644 --- a/bcmdhd/wifi_hal/common.h +++ b/bcmdhd/wifi_hal/common.h @@ -80,9 +80,9 @@ typedef enum { WIFI_SUBCMD_GET_FEATURE_SET_MATRIX, /* 0x100B */ WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, /* 0x100C */ WIFI_SUBCMD_NODFS_SET, /* 0x100D */ - + WIFI_SUBCMD_SET_COUNTRY, /* 0x100E */ /* Add more sub commands here */ - + GSCAN_SUBCMD_SET_EPNO_SSID, /* 0x100F */ GSCAN_SUBCMD_MAX /* 0x100D */ } WIFI_SUB_COMMAND; @@ -96,7 +96,8 @@ typedef enum { GSCAN_EVENT_FULL_SCAN_RESULTS, RTT_EVENT_COMPLETE, GSCAN_EVENT_COMPLETE_SCAN, - GSCAN_EVENT_HOTLIST_RESULTS_LOST + GSCAN_EVENT_HOTLIST_RESULTS_LOST, + GSCAN_EVENT_EPNO_EVENT } WIFI_EVENT; typedef void (*wifi_internal_event_handler) (wifi_handle handle, int events); @@ -150,6 +151,17 @@ typedef struct { // add other details } hal_info; +#define PNO_SSID_FOUND 0x1 +#define PNO_SSID_LOST 0x2 + +typedef struct wifi_pno_result { + unsigned char ssid[32]; + unsigned char ssid_len; + char rssi; + u16 channel; + u16 flags; +} wifi_pno_result_t; + 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); diff --git a/bcmdhd/wifi_hal/gscan.cpp b/bcmdhd/wifi_hal/gscan.cpp index feae078..9eedc85 100644 --- a/bcmdhd/wifi_hal/gscan.cpp +++ b/bcmdhd/wifi_hal/gscan.cpp @@ -81,6 +81,16 @@ typedef enum { GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS, GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, + /* EPNO */ + GSCAN_ATTRIBUTE_EPNO_SSID_LIST = 70, + GSCAN_ATTRIBUTE_EPNO_SSID, + GSCAN_ATTRIBUTE_EPNO_SSID_LEN, + GSCAN_ATTRIBUTE_EPNO_RSSI, + GSCAN_ATTRIBUTE_EPNO_FLAGS, + GSCAN_ATTRIBUTE_EPNO_AUTH, + GSCAN_ATTRIBUTE_EPNO_SSID_NUM, + GSCAN_ATTRIBUTE_EPNO_FLUSH, + GSCAN_ATTRIBUTE_MAX } GSCAN_ATTRIBUTE; @@ -1100,6 +1110,170 @@ public: } }; +class ePNOCommand : public WifiCommand +{ +private: + wifi_epno_network *ssid_list; + int num_ssid; + wifi_epno_handler mHandler; + static const int MAX_RESULTS = 32; + wifi_scan_result mResults[MAX_RESULTS]; +public: + ePNOCommand(wifi_interface_handle handle, int id, + int num_networks, wifi_epno_network *networks, wifi_epno_handler handler) + : WifiCommand(handle, id), mHandler(handler) + { + ssid_list = networks; + num_ssid = num_networks; + } + + int createSetupRequest(WifiRequest& request) { + int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_EPNO_SSID); + if (result < 0) { + return result; + } + + nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); + result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_FLUSH, 1); + if (result < 0) { + return result; + } + + result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_SSID_NUM, num_ssid); + if (result < 0) { + return result; + } + + struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_EPNO_SSID_LIST); + for (int i = 0; i < num_ssid; i++) { + nlattr *attr2 = request.attr_start(i); + if (attr2 == NULL) { + return WIFI_ERROR_OUT_OF_MEMORY; + } + result = request.put(GSCAN_ATTRIBUTE_EPNO_SSID, ssid_list[i].ssid, 32); + ALOGI("SSID %s", ssid_list[i].ssid); + if (result < 0) { + return result; + } + result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_SSID_LEN, strlen(ssid_list[i].ssid)); + if (result < 0) { + return result; + } + ALOGI("rssi %d", ssid_list[i].rssi_threshold); + result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_RSSI, ssid_list[i].rssi_threshold); + if (result < 0) { + return result; + } + ALOGI("flags %d", ssid_list[i].flags); + result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_FLAGS, ssid_list[i].flags); + if (result < 0) { + return result; + } + result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_AUTH, ssid_list[i].auth_bit_field); + 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, GSCAN_SUBCMD_SET_EPNO_SSID); + if (result < 0) { + return result; + } + + nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); + result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_FLUSH, 1); + if (result < 0) { + return result; + } + request.attr_end(data); + return result; + } + + int start() { + ALOGI("Executing ePNO setup request, num = %d", num_ssid); + WifiRequest request(familyId(), ifaceId()); + int result = createSetupRequest(request); + if (result < 0) { + return result; + } + + result = requestResponse(request); + if (result < 0) { + ALOGI("Failed to execute ePNO setup request, result = %d", result); + unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT); + return result; + } + + ALOGI("Successfully set %d SSIDs for ePNO", num_ssid); + registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT); + ALOGI("successfully restarted the scan"); + return result; + } + + virtual int cancel() { + /* unregister event handler */ + unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT); + /* 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; + } + + ALOGI("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) { + ALOGI("ePNO 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) { + ALOGI("No scan results found"); + return NL_SKIP; + } + + memset(mResults, 0, sizeof(wifi_scan_result) * MAX_RESULTS); + + int num = len / sizeof(wifi_pno_result_t); + int i; + num = min(MAX_RESULTS, num); + wifi_pno_result_t *res = (wifi_pno_result_t *) event.get_vendor_data(); + for (i = 0; i < num; i++) { + if (res[i].flags == PNO_SSID_FOUND) { + memcpy(mResults[i].ssid, res[i].ssid, res[i].ssid_len); + mResults[i].ssid[res[i].ssid_len] = '\0'; + mResults[i].channel = res[i].channel; + mResults[i].rssi = res[i].rssi; + } + } + if (*mHandler.on_network_found) + (*mHandler.on_network_found)(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) { @@ -1342,3 +1516,27 @@ wifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interf return WIFI_ERROR_INVALID_ARGS; } + +wifi_error wifi_set_epno_list(wifi_request_id id, wifi_interface_handle iface, + int num_networks, wifi_epno_network *networks, wifi_epno_handler handler) +{ + wifi_handle handle = getWifiHandle(iface); + + ePNOCommand *cmd = new ePNOCommand(iface, id, num_networks, networks, handler); + wifi_register_cmd(handle, id, cmd); + return (wifi_error)cmd->start(); +} + +wifi_error wifi_reset_epno_list(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; +} |