[7570] wlbt: support ePNO
authorJaya Prakash Sangaru <j.sangaru@samsung.com>
Mon, 20 Jun 2016 07:48:17 +0000 (13:18 +0530)
committerTarun Karela <t.karela@samsung.com>
Mon, 4 Jun 2018 09:40:47 +0000 (10:40 +0100)
support ePNO APIs in wifi-hal

SCSC-Bug-Id:SSB-18502

Change-Id: I5bdaf739d7c631394c732fcb7f0b9e92b2d5a0ec
Signed-off-by: Jaya Prakash Sangaru <j.sangaru@samsung.com>
common.h
gscan.cpp
wifi_hal.cpp

index 61d12dcc227775fd494f6b03501214b98461f559..10471585ecd40e1e02eacc43bbe77ea8450bd2ea 100755 (executable)
--- a/common.h
+++ b/common.h
@@ -77,7 +77,11 @@ typedef enum {
     SLSI_NL80211_VENDOR_SUBCMD_SET_GSCAN_OUI,
     SLSI_NL80211_VENDOR_SUBCMD_SET_NODFS,
     SLSI_NL80211_VENDOR_SUBCMD_START_KEEP_ALIVE_OFFLOAD,
-    SLSI_NL80211_VENDOR_SUBCMD_STOP_KEEP_ALIVE_OFFLOAD
+    SLSI_NL80211_VENDOR_SUBCMD_STOP_KEEP_ALIVE_OFFLOAD,
+    SLSI_NL80211_VENDOR_SUBCMD_SET_BSSID_BLACKLIST,
+    SLSI_NL80211_VENDOR_SUBCMD_SET_EPNO_LIST,
+    SLSI_NL80211_VENDOR_SUBCMD_SET_HS_LIST,
+    SLSI_NL80211_VENDOR_SUBCMD_RESET_HS_LIST
 } WIFI_SUB_COMMAND;
 
 typedef enum {
@@ -86,7 +90,11 @@ typedef enum {
     GSCAN_EVENT_SCAN_RESULTS_AVAILABLE,
     GSCAN_EVENT_FULL_SCAN_RESULTS,
     GSCAN_EVENT_COMPLETE_SCAN,
-    GSCAN_EVENT_HOTLIST_RESULTS_LOST
+    GSCAN_EVENT_HOTLIST_RESULTS_LOST,
+    WIFI_SUBCMD_KEY_MGMT_ROAM_AUTH, /* Handled by supplicant. not in Wifi-HAL */
+    WIFI_HANGED_EVENT,
+    WIFI_EPNO_EVENT,
+    WIFI_HOTSPOT_MATCH
 } WIFI_EVENT;
 
 typedef void (*wifi_internal_event_handler) (wifi_handle handle, int events);
index 46929f084e1e0df14d82ae7dfaa9d42dc48f486c..5de04e4cd19963b7f0bbbac72ab9c6771868ab05 100755 (executable)
--- a/gscan.cpp
+++ b/gscan.cpp
@@ -1,5 +1,6 @@
 
 #include <stdint.h>
+#include <stddef.h>
 #include <fcntl.h>
 #include <sys/socket.h>
 #include <netlink/genl/genl.h>
@@ -86,6 +87,27 @@ typedef enum {
 
 } GSCAN_ATTRIBUTE;
 
+typedef enum {
+    EPNO_ATTRIBUTE_SSID_LIST,
+    EPNO_ATTRIBUTE_SSID_NUM,
+    EPNO_ATTRIBUTE_SSID,
+    EPNO_ATTRIBUTE_SSID_LEN,
+    EPNO_ATTRIBUTE_RSSI,
+    EPNO_ATTRIBUTE_FLAGS,
+    EPNO_ATTRIBUTE_AUTH,
+    EPNO_ATTRIBUTE_MAX
+} EPNO_ATTRIBUTE;
+
+typedef enum {
+    EPNO_ATTRIBUTE_HS_PARAM_LIST,
+    EPNO_ATTRIBUTE_HS_NUM,
+    EPNO_ATTRIBUTE_HS_ID,
+    EPNO_ATTRIBUTE_HS_REALM,
+    EPNO_ATTRIBUTE_HS_CONSORTIUM_IDS,
+    EPNO_ATTRIBUTE_HS_PLMN,
+    EPNO_ATTRIBUTE_HS_MAX
+} EPNO_HS_ATTRIBUTE;
+
 
 class GetCapabilitiesCommand : public WifiCommand
 {
@@ -1082,3 +1104,312 @@ wifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interf
 
     return WIFI_ERROR_INVALID_ARGS;
 }
+
+class ePNOCommand : public WifiCommand
+{
+private:
+    wifi_epno_network *ssid_list;
+    int               num_ssid;
+    wifi_epno_handler mHandler;
+    wifi_scan_result  mResults;
+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, SLSI_NL80211_VENDOR_SUBCMD_SET_EPNO_LIST);
+        if (result < 0) {
+            return result;
+        }
+
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+        result = request.put_u8(EPNO_ATTRIBUTE_SSID_NUM, num_ssid);
+        if (result < 0) {
+            return result;
+        }
+
+        struct nlattr * attr = request.attr_start(EPNO_ATTRIBUTE_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(EPNO_ATTRIBUTE_SSID, ssid_list[i].ssid, 32);
+            ALOGI("ePNO [SSID:%s rssi_thresh:%d flags:%d auth:%d]", ssid_list[i].ssid,
+                (signed char)ssid_list[i].rssi_threshold, ssid_list[i].flags,
+                ssid_list[i].auth_bit_field);
+            if (result < 0) {
+                return result;
+            }
+            result = request.put_u8(EPNO_ATTRIBUTE_SSID_LEN, strlen(ssid_list[i].ssid));
+            if (result < 0) {
+                return result;
+            }
+
+            result = request.put_u8(EPNO_ATTRIBUTE_RSSI, ssid_list[i].rssi_threshold);
+            if (result < 0) {
+                return result;
+            }
+            result = request.put_u8(EPNO_ATTRIBUTE_FLAGS, ssid_list[i].flags);
+            if (result < 0) {
+                return result;
+            }
+            result = request.put_u8(EPNO_ATTRIBUTE_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 start() {
+        ALOGI("ePNO num_network=%d", num_ssid);
+        WifiRequest request(familyId(), ifaceId());
+        int result = createSetupRequest(request);
+        if (result < 0) {
+            return result;
+        }
+
+        result = requestResponse(request);
+        if (result < 0) {
+            ALOGI("Failed: ePNO setup request, result = %d", result);
+            unregisterVendorHandler(GOOGLE_OUI, WIFI_EPNO_EVENT);
+            return result;
+        }
+
+        ALOGI("Successfully set %d SSIDs for ePNO", num_ssid);
+        registerVendorHandler(GOOGLE_OUI, WIFI_EPNO_EVENT);
+        return result;
+    }
+
+    virtual int cancel() {
+        /* unregister event handler */
+        unregisterVendorHandler(GOOGLE_OUI, WIFI_EPNO_EVENT);
+        return 0;
+    }
+
+    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;
+        }
+
+        mResults = *(wifi_scan_result *) event.get_vendor_data();
+        if (*mHandler.on_network_found)
+            (*mHandler.on_network_found)(id(), 1, &mResults);
+        return NL_SKIP;
+    }
+};
+
+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);
+     wifi_error result = (wifi_error)cmd->start();
+     if (result != WIFI_SUCCESS) {
+         wifi_unregister_cmd(handle, id);
+     }
+     return result;
+}
+
+class HsListCommand : public WifiCommand
+{
+    int num_hs;
+    wifi_passpoint_network *mNetworks;
+    wifi_passpoint_event_handler mHandler;
+public:
+    HsListCommand(wifi_request_id id, wifi_interface_handle iface,
+        int num, wifi_passpoint_network *hs_list, wifi_passpoint_event_handler handler)
+        : WifiCommand(iface, id), num_hs(num), mNetworks(hs_list),
+            mHandler(handler)
+    {
+    }
+
+    HsListCommand(wifi_request_id id, wifi_interface_handle iface,
+        int num)
+        : WifiCommand(iface, id), num_hs(num), mNetworks(NULL)
+    {
+    }
+
+    int createRequest(WifiRequest& request, int val) {
+        int result;
+
+        if (val) {
+            result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_HS_LIST);
+            result = request.put_u32(EPNO_ATTRIBUTE_HS_NUM, num_hs);
+            if (result < 0) {
+                return result;
+            }
+            nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+            struct nlattr * attr = request.attr_start(EPNO_ATTRIBUTE_HS_PARAM_LIST);
+            for (int i = 0; i < num_hs; i++) {
+                nlattr *attr2 = request.attr_start(i);
+                if (attr2 == NULL) {
+                    return WIFI_ERROR_OUT_OF_MEMORY;
+                }
+                result = request.put_u32(EPNO_ATTRIBUTE_HS_ID, mNetworks[i].id);
+                if (result < 0) {
+                    return result;
+                }
+                result = request.put(EPNO_ATTRIBUTE_HS_REALM, mNetworks[i].realm, 256);
+                if (result < 0) {
+                    return result;
+                }
+                result = request.put(EPNO_ATTRIBUTE_HS_CONSORTIUM_IDS, mNetworks[i].roamingConsortiumIds, 128);
+                if (result < 0) {
+                    return result;
+                }
+                result = request.put(EPNO_ATTRIBUTE_HS_PLMN, mNetworks[i].plmn, 3);
+                if (result < 0) {
+                    return result;
+                }
+                request.attr_end(attr2);
+            }
+            request.attr_end(attr);
+            request.attr_end(data);
+        }else {
+            result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_RESET_HS_LIST);
+            if (result < 0) {
+                return result;
+            }
+        }
+
+        return WIFI_SUCCESS;
+    }
+
+    int start() {
+
+        WifiRequest request(familyId(), ifaceId());
+        int result = createRequest(request, num_hs);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("failed to create request; result = %d", result);
+            return result;
+        }
+
+        registerVendorHandler(GOOGLE_OUI, WIFI_HOTSPOT_MATCH);
+
+        result = requestResponse(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("failed to set ANQPO networks; result = %d", result);
+            unregisterVendorHandler(GOOGLE_OUI, WIFI_HOTSPOT_MATCH);
+            return result;
+        }
+
+        return result;
+    }
+
+    virtual int cancel() {
+
+        WifiRequest request(familyId(), ifaceId());
+        int result = createRequest(request, 0);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("failed to create request; result = %d", result);
+        } else {
+            result = requestResponse(request);
+            if (result != WIFI_SUCCESS) {
+                ALOGE("failed to reset ANQPO networks;result = %d", result);
+            }
+        }
+
+        unregisterVendorHandler(GOOGLE_OUI, WIFI_HOTSPOT_MATCH);
+        return WIFI_SUCCESS;
+    }
+
+    virtual int handleResponse(WifiEvent& reply) {
+         ALOGD("Request complete!");
+        /* Nothing to do on response! */
+        return NL_SKIP;
+    }
+
+    virtual int handleEvent(WifiEvent& event) {
+
+        ALOGI("hotspot matched event");
+        nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
+        unsigned int len = event.get_vendor_data_len();
+        if (vendor_data == NULL || len < sizeof(wifi_scan_result)) {
+            ALOGE("ERROR: No scan results found");
+            return NL_SKIP;
+        }
+
+        wifi_scan_result *result = (wifi_scan_result *)event.get_vendor_data();
+        byte *anqp = (byte *)result + offsetof(wifi_scan_result, ie_data) + result->ie_length;
+        int networkId = *(int *)anqp;
+        anqp += sizeof(int);
+        int anqp_len = *(u16 *)anqp;
+        anqp += sizeof(u16);
+
+        ALOGI("%-32s\t", result->ssid);
+
+        ALOGI("%02x:%02x:%02x:%02x:%02x:%02x ", result->bssid[0], result->bssid[1],
+                result->bssid[2], result->bssid[3], result->bssid[4], result->bssid[5]);
+
+        ALOGI("%d\t", result->rssi);
+        ALOGI("%d\t", result->channel);
+        ALOGI("%lld\t", result->ts);
+        ALOGI("%lld\t", result->rtt);
+        ALOGI("%lld\n", result->rtt_sd);
+
+        if(*mHandler.on_passpoint_network_found)
+            (*mHandler.on_passpoint_network_found)(id(), networkId, result, anqp_len, anqp);
+
+        return NL_SKIP;
+    }
+};
+
+wifi_error wifi_set_passpoint_list(wifi_request_id id, wifi_interface_handle iface, int num,
+        wifi_passpoint_network *networks, wifi_passpoint_event_handler handler)
+{
+    wifi_handle handle = getWifiHandle(iface);
+    HsListCommand *cmd = new HsListCommand(id, iface, num, networks, handler);
+
+    wifi_register_cmd(handle, id, cmd);
+    wifi_error result = (wifi_error)cmd->start();
+    if (result != WIFI_SUCCESS) {
+        wifi_unregister_cmd(handle, id);
+    }
+    return result;
+}
+
+wifi_error wifi_reset_passpoint_list(wifi_request_id id, wifi_interface_handle iface)
+{
+    wifi_handle   handle = getWifiHandle(iface);
+    wifi_error    result;
+    HsListCommand *cmd = (HsListCommand *)(wifi_get_cmd(handle, id));
+
+    if (cmd == NULL) {
+        cmd = new HsListCommand(id, iface, 0);
+        wifi_register_cmd(handle, id, cmd);
+    }
+    result = (wifi_error)cmd->cancel();
+    wifi_unregister_cmd(handle, id);
+    return result;
+}
index e3b78bf401101fcbbb26d7bf0f8c28cb99a804fa..41a9131878e116a851c01da3eebb321d815ad555 100755 (executable)
@@ -111,6 +111,11 @@ wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn)
     fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
     fn->wifi_start_sending_offloaded_packet = wifi_start_sending_offloaded_packet;
     fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
+#if 0
+    fn->wifi_set_epno_list = wifi_set_epno_list;
+    fn->wifi_set_passpoint_list = wifi_set_passpoint_list;
+    fn->wifi_reset_passpoint_list = wifi_reset_passpoint_list;
+#endif
     return WIFI_SUCCESS;
 }