summaryrefslogtreecommitdiffstats
path: root/bcmdhd/wifi_hal
diff options
context:
space:
mode:
authorAshwin <ashwin.bhat@broadcom.com>2015-03-19 16:07:39 -0700
committerAshwin <ashwin.bhat@broadcom.com>2015-03-19 16:07:39 -0700
commit89a9a4cffbcee6af504c61ff575a008194070c82 (patch)
tree8a40bed60694d51541e4079d9b4490543cee64c5 /bcmdhd/wifi_hal
parent886a7c99f8664295fe233034cac84d6253324641 (diff)
downloadhardware_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.h18
-rw-r--r--bcmdhd/wifi_hal/gscan.cpp198
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;
+}