gscan.cpp revision 922bc148ebc612b6ecf7233b028099aab78feae4
11a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 21a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <stdint.h> 31a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <fcntl.h> 41a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <sys/socket.h> 51a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netlink/genl/genl.h> 61a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netlink/genl/family.h> 71a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netlink/genl/ctrl.h> 81a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <linux/rtnetlink.h> 91a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netpacket/packet.h> 101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <linux/filter.h> 111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <linux/errqueue.h> 121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <linux/pkt_sched.h> 141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netlink/object-api.h> 151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netlink/netlink.h> 161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netlink/socket.h> 171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netlink-types.h> 181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include "nl80211_copy.h" 201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include "sync.h" 221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#define LOG_TAG "WifiHAL" 241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <utils/Log.h> 261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include "wifi_hal.h" 281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include "common.h" 291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include "cpp_bindings.h" 301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndetypedef enum { 321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde BRCM_RESERVED1, 331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde BRCM_RESERVED2, 341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS , 351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_EVENT_HOTLIST_RESULTS, 361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, 37922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde GSCAN_EVENT_FULL_SCAN_RESULTS 381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} GSCAN_EVENT; 401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndetypedef enum { 421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START, 441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_SUBCMD_SET_CONFIG, /* 0x1001 */ 461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_SUBCMD_SET_SCAN_CONFIG, /* 0x1002 */ 481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_SUBCMD_ENABLE_GSCAN, /* 0x1003 */ 491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_SUBCMD_GET_SCAN_RESULTS, /* 0x1004 */ 501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_SUBCMD_SCAN_RESULTS, /* 0x1005 */ 511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_SUBCMD_SET_HOTLIST, /* 0x1006 */ 531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG, /* 0x1007 */ 55922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, /* 0x1008 */ 561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* Add more sub commands here */ 581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 59922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde GSCAN_SUBCMD_MAX /* 0x1009 */ 601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} GSCAN_SUB_COMMAND; 621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndetypedef enum { 641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_NUM_BUCKETS = 10, 661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_BASE_PERIOD, 67922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde GSCAN_ATTRIBUTE_BUCKETS_BAND, 681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_BUCKET_ID, 691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_BUCKET_PERIOD, 701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, 711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_BUCKET_CHANNELS, 721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, 731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_REPORT_THRESHOLD, 741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, 751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20, 771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, /* indicates no more results */ 781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_FLUSH_FEATURE, /* Flush all the configs */ 79922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde GSCAN_ENABLE_FULL_SCAN_RESULTS, 80922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde GSCAN_ATTRIBUTE_REPORT_EVENTS, 811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* remaining reserved for additional attributes */ 831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30, 841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_FLUSH_RESULTS, 851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SCAN_RESULTS, /* flat array of wifi_scan_result */ 861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SCAN_ID, /* indicates scan number */ 871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SCAN_FLAGS, /* indicates if scan was aborted */ 881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_AP_FLAGS, /* flags on significant change event */ 891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* remaining reserved for additional attributes */ 911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SSID = 40, 931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_BSSID, 941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_CHANNEL, 951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_RSSI, 961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_TIMESTAMP, 971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_RTT, 981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_RTTSD, 991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* remaining reserved for additional attributes */ 1011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50, 1031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_RSSI_LOW, 1041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_RSSI_HIGH, 1051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_HOTLIST_ELEM, 1061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* remaining reserved for additional attributes */ 1091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60, 1101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, 1111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_MIN_BREACHING, 1121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS, 1131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_MAX 1161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} GSCAN_ATTRIBUTE; 1181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 119922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 120922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde// helper methods 121922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndewifi_error wifi_enable_full_scan_results(wifi_request_id id, wifi_interface_handle iface, 122922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result_handler handler); 123922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndewifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface); 124922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 125922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 1261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde///////////////////////////////////////////////////////////////////////////// 1271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass GetCapabilitiesCommand : public WifiCommand 1291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 1301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_gscan_capabilities *mCapabilities; 1311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic: 1321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GetCapabilitiesCommand(wifi_interface_handle iface, wifi_gscan_capabilities *capabitlites) 1331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde : WifiCommand(iface, 0), mCapabilities(capabitlites) 1341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde { 1351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memset(mCapabilities, 0, sizeof(*mCapabilities)); 1361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int create() { 1391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Creating message to get scan capablities; iface = %d", mIfaceInfo->id); 1401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int ret = mMsg.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_CAPABILITIES); 1421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (ret < 0) { 1431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return ret; 1441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return ret; 1471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeprotected: 1501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleResponse(WifiEvent& reply) { 1511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("In GetCapabilities::handleResponse"); 1531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (reply.get_cmd() != NL80211_CMD_VENDOR) { 1551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); 1561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 1571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int id = reply.get_vendor_id(); 1601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int subcmd = reply.get_vendor_subcmd(); 1611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Id = %0x, subcmd = %d", id, subcmd); 1631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde void *data = reply.get_vendor_data(); 1651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int len = reply.get_vendor_data_len(); 1661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (len == sizeof(*mCapabilities)) { 1681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("Invalid reply length"); 1691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memcpy(mCapabilities, data, len); 1701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else { 1711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("Invalid reply length: %d", len); 1721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_OK; 1751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}; 1771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle, 1801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_gscan_capabilities *capabilities) 1811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 1821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GetCapabilitiesCommand command(handle, capabilities); 1831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return (wifi_error) command.requestResponse(); 1841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 1851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde///////////////////////////////////////////////////////////////////////////// 1871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde/* helper functions */ 1891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndestatic int parseScanResults(wifi_scan_result *results, int num, nlattr *attr) 1911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 1921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memset(results, 0, sizeof(wifi_scan_result) * num); 1931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int i = 0; 1951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (nl_iterator it(attr); it.has_next() && i < num; it.next(), i++) { 1961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int index = it.get_type(); 1981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("retrieved scan result %d", index); 1991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *sc_data = (nlattr *) it.get_data(); 2001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result *result = results + i; 2011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (nl_iterator it2(sc_data); it2.has_next(); it2.next()) { 2031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int type = it2.get_type(); 2041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (type == GSCAN_ATTRIBUTE_SSID) { 2051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde strncpy(result->ssid, (char *) it2.get_data(), it2.get_len()); 2061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->ssid[it2.get_len()] = 0; 2071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (type == GSCAN_ATTRIBUTE_BSSID) { 2081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memcpy(result->bssid, (byte *) it2.get_data(), sizeof(mac_addr)); 2091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (type == GSCAN_ATTRIBUTE_TIMESTAMP) { 2101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->ts = it2.get_u64(); 2111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (type == GSCAN_ATTRIBUTE_CHANNEL) { 2121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->ts = it2.get_u16(); 2131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (type == GSCAN_ATTRIBUTE_RSSI) { 2141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->rssi = it2.get_u8(); 2151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (type == GSCAN_ATTRIBUTE_RTT) { 2161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->rtt = it2.get_u64(); 2171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (type == GSCAN_ATTRIBUTE_RTTSD) { 2181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->rtt_sd = it2.get_u64(); 2191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 2201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 2211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 2231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (i >= num) { 2251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("Got too many results; skipping some"); 2261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 2271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return i; 2291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 2301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeint createFeatureRequest(WifiRequest& request, int subcmd, int enable) { 2321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, subcmd); 2341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 2351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 2361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 2371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 2391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_ENABLE_FEATURE, enable); 2401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 2411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 2421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 2431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 2451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 2461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 2471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde///////////////////////////////////////////////////////////////////////////// 249922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndeclass FullScanResultsCommand : public WifiCommand 250922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde{ 251922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int *mParams; 252922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result_handler mHandler; 253922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndepublic: 254922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde FullScanResultsCommand(wifi_interface_handle iface, int id, int *params, 255922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result_handler handler) 256922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde : WifiCommand(iface, id), mParams(params), mHandler(handler) 257922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde { } 258922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 259922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int createRequest(WifiRequest& request, int subcmd, int enable) { 260922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int result = request.create(GOOGLE_OUI, subcmd); 261922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result < 0) { 262922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 263922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 264922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 265922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 266922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = request.put_u32(GSCAN_ENABLE_FULL_SCAN_RESULTS, enable); 267922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result < 0) { 268922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 269922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 270922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 271922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde request.attr_end(data); 272922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 273922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 274922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 275922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 276922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int start() { 277922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGD("Enabling Full scan results"); 278922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde WifiRequest request(familyId(), ifaceId()); 279922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 1); 280922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result != WIFI_SUCCESS) { 281922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGE("failed to create request; result = %d", result); 282922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 283922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 284922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 285922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); 286922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 287922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = requestResponse(request); 288922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result != WIFI_SUCCESS) { 289922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGE("failed to enable full scan results; result = %d", result); 290922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); 291922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 292922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 293922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 294922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 295922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 296922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 297922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde virtual int cancel() { 298922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGD("Disabling Full scan results"); 299922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 300922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde WifiRequest request(familyId(), ifaceId()); 301922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 0); 302922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result != WIFI_SUCCESS) { 303922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGE("failed to create request; result = %d", result); 304922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } else { 305922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = requestResponse(request); 306922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result != WIFI_SUCCESS) { 307922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGE("failed to disable full scan results;result = %d", result); 308922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 309922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 310922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 311922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); 312922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 313922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 314922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 315922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde virtual int handleResponse(WifiEvent& reply) { 316922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGD("Request complete!"); 317922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde /* Nothing to do on response! */ 318922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return NL_SKIP; 319922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 320922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 321922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde virtual int handleEvent(WifiEvent& event) { 322922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("Full scan results: Got an event"); 323922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 324922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde event.log(); 325922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 326922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 327922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde unsigned int len = event.get_vendor_data_len(); 328922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 329922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (vendor_data == NULL || len < sizeof(wifi_scan_result)) { 330922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("No scan results found"); 331922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return NL_SKIP; 332922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 333922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 334922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result *result = (wifi_scan_result *)event.get_vendor_data(); 335922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 336922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde (*mHandler.on_full_scan_result)(id(), result); 337922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%-32s\t", result->ssid); 338922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 339922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%02x:%02x:%02x:%02x:%02x:%02x ", result->bssid[0], result->bssid[1], 340922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result->bssid[2], result->bssid[3], result->bssid[4], result->bssid[5]); 341922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 342922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%d\t", result->rssi); 343922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%d\t", result->channel); 344922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%lld\t", result->ts); 345922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%lld\t", result->rtt); 346922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%lld\n", result->rtt_sd); 347922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 348922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 349922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return NL_SKIP; 350922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 351922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 352922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde}; 353922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde///////////////////////////////////////////////////////////////////////////// 3541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 3551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass ScanCommand : public WifiCommand 3561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 3571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_cmd_params *mParams; 3581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result_handler mHandler; 359922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde static unsigned mGlobalFullScanBuckets; 360922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde bool mLocalFullScanBuckets; 3611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic: 3621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ScanCommand(wifi_interface_handle iface, int id, wifi_scan_cmd_params *params, 3631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result_handler handler) 364922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde : WifiCommand(iface, id), mParams(params), mHandler(handler), 365922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde mLocalFullScanBuckets(0) 3661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde { } 3671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 3681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createSetupRequest(WifiRequest& request) { 3691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_CONFIG); 3701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 3711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 3721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 3731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 3741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 3751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_BASE_PERIOD, mParams->base_period); 3761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 3771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 3781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 3791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 3801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_NUM_BUCKETS, mParams->num_buckets); 3811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 3821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 3831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 3841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 3851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (int i = 0; i < mParams->num_buckets; i++) { 3861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr * bucket = request.attr_start(i); // next bucket 3871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_ID, mParams->buckets[i].bucket); 3881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 3891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 3901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 3911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_PERIOD, mParams->buckets[i].period); 3921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 3931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 3941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 395922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_BUCKETS_BAND, 396922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde mParams->buckets[i].band); 397922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result < 0) { 398922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 399922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 400922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 401922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_EVENTS, 402922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde mParams->buckets[i].report_events); 403922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result < 0) { 404922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 405922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 406922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 4071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, 4081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde mParams->buckets[i].num_channels); 4091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 4101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 4111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 413922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (mParams->buckets[i].num_channels) { 414922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde nlattr *channels = request.attr_start(GSCAN_ATTRIBUTE_BUCKET_CHANNELS); 415922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde for (int j = 0; j < mParams->buckets[i].num_channels; j++) { 416922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = request.put_u32(j, mParams->buckets[i].channels[j].channel); 417922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result < 0) { 418922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 419922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 4201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 421922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde request.attr_end(channels); 4221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(bucket); 4251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 4281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 4291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createScanConfigRequest(WifiRequest& request) { 4321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SCAN_CONFIG); 4331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 4341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 4351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 4381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, mParams->max_ap_per_scan); 4391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 4401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 4411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD, mParams->report_threshold); 4441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 4451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 4461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 44809f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde int num_scans = 10; 44909f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde for (int i = 0; i < mParams->num_buckets; i++) { 450922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (mParams->buckets[i].report_events == 1) { 45109f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde num_scans = 1; 45209f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde break; 45309f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde } 45409f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde } 45509f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde 45609f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, num_scans); 4571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 4581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 4591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 4621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 4631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createStartRequest(WifiRequest& request) { 4661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1); 4671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createStopRequest(WifiRequest& request) { 4701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 0); 4711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 473922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int enableFullScanResultsIfRequired() { 474922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde /* temporary workaround till we have full support for per bucket scans */ 475922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 476922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("enabling full scan results if needed"); 477922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int nBuckets = 0; 478922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde for (int i = 0; i < mParams->num_buckets; i++) { 479922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (mParams->buckets[i].report_events == 2) { 480922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde nBuckets++; 481922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 482922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 483922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 484922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (mGlobalFullScanBuckets == 0 && nBuckets != 0) { 485922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int result = wifi_enable_full_scan_results(0x1000, ifaceHandle(), mHandler); 486922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result != WIFI_SUCCESS) { 487922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("failed to enable full scan results"); 488922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 489922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } else { 490922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("successfully enabled full scan results"); 491922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 492922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } else { 493922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("mGlobalFullScanBuckets = %d, nBuckets = %d", mGlobalFullScanBuckets, nBuckets); 494922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 495922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 496922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde mLocalFullScanBuckets = nBuckets; 497922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde mGlobalFullScanBuckets += nBuckets; 498922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 499922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 500922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 501922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int disableFullScanResultsIfRequired() { 502922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde /* temporary workaround till we have full support for per bucket scans */ 503922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 504922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (mLocalFullScanBuckets == 0) { 505922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 506922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 507922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 508922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde mGlobalFullScanBuckets -= mLocalFullScanBuckets; 509922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (mGlobalFullScanBuckets == 0) { 510922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int result = wifi_disable_full_scan_results(0x1000, ifaceHandle()); 511922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result != WIFI_SUCCESS) { 512922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("failed to disable full scan results"); 513922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } else { 514922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("successfully disable full scan results"); 515922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 516922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 517922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 518922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 519922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 520922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 5211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int start() { 5221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Setting configuration"); 5231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 5241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = createSetupRequest(request); 5251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 5261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to create setup request; result = %d", result); 5271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 5281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 5311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 5321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to configure setup; result = %d", result); 5331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 5341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.destroy(); 5371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = createScanConfigRequest(request); 5391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 5401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to create scan config request; result = %d", result); 5411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 5421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 5451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 5461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to configure scan; result = %d", result); 5471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 5481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Starting scan"); 5511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = createStartRequest(request); 5531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 5541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to create start request; result = %d", result); 5551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 5561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE); 5591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 5611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 5621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to start scan; result = %d", result); 5631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE); 5641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 5651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 567922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = enableFullScanResultsIfRequired(); 5681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 5691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int cancel() { 5721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Stopping scan"); 5731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 5751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = createStopRequest(request); 5761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 5771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to create stop request; result = %d", result); 5781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else { 5791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 5801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 5811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to stop scan; result = %d", result); 5821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE); 586922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde disableFullScanResultsIfRequired(); 587922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 5881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 5891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleResponse(WifiEvent& reply) { 5921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* Nothing to do on response! */ 5931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 5941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleEvent(WifiEvent& event) { 5971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Got a scan results event"); 5981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 59909f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde // event.log(); 6001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 6021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int len = event.get_vendor_data_len(); 6031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (vendor_data == NULL || len != 4) { 6051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("No scan results found"); 6061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 6071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int num = event.get_u32(NL80211_ATTR_VENDOR_DATA); 6101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Found %d scan results", num); 6111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde (*mHandler.on_scan_results_available)(id(), num); 6121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 6131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}; 6151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 616922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndeunsigned ScanCommand::mGlobalFullScanBuckets = 0; 617922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 6181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_start_gscan( 6191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_request_id id, 6201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_interface_handle iface, 6211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_cmd_params params, 6221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result_handler handler) 6231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 6241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_handle handle = getWifiHandle(iface); 6251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Starting GScan, halHandle = %p", handle); 6271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ScanCommand *cmd = new ScanCommand(iface, id, ¶ms, handler); 6291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_register_cmd(handle, id, cmd); 6301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return (wifi_error)cmd->start(); 6311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 6321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_stop_gscan(wifi_request_id id, wifi_interface_handle iface) 6341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 6351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Stopping GScan"); 6361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_handle handle = getWifiHandle(iface); 6371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 638922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if(id == -1) { 639922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result_handler handler; 640922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_cmd_params dummy_params; 641922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_handle handle = getWifiHandle(iface); 642922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde memset(&handler, 0, sizeof(handler)); 643922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 644922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ScanCommand *cmd = new ScanCommand(iface, id, &dummy_params, handler); 645922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde cmd->cancel(); 646922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde delete cmd; 647922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 648922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 649922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 650922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 6511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiCommand *cmd = wifi_unregister_cmd(handle, id); 6521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (cmd) { 6531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde cmd->cancel(); 6541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde delete cmd; 6551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 6561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_ERROR_INVALID_ARGS; 6591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 6601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 661922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 662922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndewifi_error wifi_enable_full_scan_results( 663922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_request_id id, 664922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_interface_handle iface, 665922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result_handler handler) 666922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde{ 667922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_handle handle = getWifiHandle(iface); 668922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int params_dummy; 669922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGD("Enabling full scan results, halHandle = %p", handle); 670922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 671922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, id, ¶ms_dummy, handler); 672922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_register_cmd(handle, id, cmd); 673922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 674922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return (wifi_error)cmd->start(); 675922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde} 676922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 677922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndewifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface) 678922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde{ 679922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGD("Disabling full scan results"); 680922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_handle handle = getWifiHandle(iface); 681922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 682922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if(id == -1) { 683922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result_handler handler; 684922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_handle handle = getWifiHandle(iface); 685922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int params_dummy; 686922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 687922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde memset(&handler, 0, sizeof(handler)); 688922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, 0, ¶ms_dummy, handler); 689922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde cmd->cancel(); 690922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde delete cmd; 691922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 692922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 693922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 694922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde WifiCommand *cmd = wifi_unregister_cmd(handle, id); 695922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (cmd) { 696922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde cmd->cancel(); 697922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde delete cmd; 698922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 699922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 700922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 701922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_ERROR_INVALID_ARGS; 702922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde} 703922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 704922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 7051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde///////////////////////////////////////////////////////////////////////////// 7061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass GetScanResultsCommand : public WifiCommand { 7081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result *mResults; 7091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int *mNum; 7101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int mRetrieved; 7111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde byte mFlush; 7121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int mCompleted; 7131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic: 7141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GetScanResultsCommand(wifi_interface_handle iface, byte flush, 7151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result *results, int *num) 7161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde : WifiCommand(iface, -1), mResults(results), mNum(num), 7171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde mRetrieved(0), mFlush(flush), mCompleted(0) 7181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde { } 7191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createRequest(WifiRequest& request, int num, byte flush) { 7211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_SCAN_RESULTS); 7221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 7231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 7241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 7251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 7271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num); 7281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 7291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 7301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 7311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u8(GSCAN_ATTRIBUTE_FLUSH_RESULTS, flush); 7331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 7341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 7351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 7361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 7381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 7391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 7401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int execute() { 7421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 7431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("retrieving %d scan results", *mNum); 7441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (int i = 0; i < 10 && mRetrieved < *mNum; i++) { 7461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = createRequest(request, (*mNum - mRetrieved), mFlush); 7471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 7481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to create request"); 7491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 7501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 7511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int prev_retrieved = mRetrieved; 7531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 7551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 7571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to retrieve scan results; result = %d", result); 7581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 7591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 7601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (mRetrieved == prev_retrieved || mCompleted) { 7621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* no more items left to retrieve */ 7631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde break; 7641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 7651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.destroy(); 7671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 7681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("GetScanResults read %d results", mRetrieved); 7701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde *mNum = mRetrieved; 7711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 7721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 7731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleResponse(WifiEvent& reply) { 7751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("In GetScanResultsCommand::handleResponse"); 7761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (reply.get_cmd() != NL80211_CMD_VENDOR) { 7781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); 7791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 7801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 7811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int id = reply.get_vendor_id(); 7831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int subcmd = reply.get_vendor_subcmd(); 7841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Id = %0x, subcmd = %d", id, subcmd); 7861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* 7881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (subcmd != GSCAN_SUBCMD_SCAN_RESULTS) { 7891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("Invalid response to GetScanResultsCommand; ignoring it"); 7901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 7911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 7921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde */ 7931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA); 7951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int len = reply.get_vendor_data_len(); 7961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (vendor_data == NULL || len == 0) { 7981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("no vendor data in GetScanResults response; ignoring it"); 7991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 8001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (nl_iterator it(vendor_data); it.has_next(); it.next()) { 8031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE) { 8041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde mCompleted = it.get_u8(); 8051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("retrieved mCompleted flag : %d", mCompleted); 8061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS || it.get_type() == 0) { 8071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) { 8081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int scan_id = 0, flags = 0, num = 0; 8091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_ID) { 8101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde scan_id = it.get_u32(); 8111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_FLAGS) { 8121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde flags = it.get_u8(); 8131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (it2.get_type() == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) { 8141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde num = it2.get_u32(); 8151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS) { 8161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde num = it2.get_len() / sizeof(wifi_scan_result); 8171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde num = min(*mNum - mRetrieved, num); 8181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memcpy(mResults + mRetrieved, it2.get_data(), 8191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde sizeof(wifi_scan_result) * num); 8201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Retrieved %d scan results", num); 8211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result *results = (wifi_scan_result *)it2.get_data(); 8221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (int i = 0; i < num; i++) { 8231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result *result = results + i; 82409f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde ALOGI("%02d %-32s %02x:%02x:%02x:%02x:%02x:%02x %04d", i, 8251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->ssid, result->bssid[0], result->bssid[1], result->bssid[2], 82609f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde result->bssid[3], result->bssid[4], result->bssid[5], 82709f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde result->rssi); 8281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde mRetrieved += num; 8301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else { 8311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGW("Ignoring invalid attribute type = %d, size = %d", 8321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde it.get_type(), it.get_len()); 8331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else { 8361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGW("Ignoring invalid attribute type = %d, size = %d", 8371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde it.get_type(), it.get_len()); 8381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_OK; 8421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}; 8441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface, byte flush, 8461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result *results, int *num) { 8471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Getting cached scan results, iface handle = %p, num = %d", iface, *num); 8491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GetScanResultsCommand *cmd = new GetScanResultsCommand(iface, flush, results, num); 8511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return (wifi_error)cmd->execute(); 8521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 8531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde///////////////////////////////////////////////////////////////////////////// 8551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass BssidHotlistCommand : public WifiCommand 8571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 8581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeprivate: 8591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_bssid_hotlist_params mParams; 8601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_hotlist_ap_found_handler mHandler; 8611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde static const int MAX_RESULTS = 64; 8621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result mResults[MAX_RESULTS]; 8631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic: 8641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde BssidHotlistCommand(wifi_interface_handle handle, int id, 8651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler) 8661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde : WifiCommand(handle, id), mParams(params), mHandler(handler) 8671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde { } 8681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createSetupRequest(WifiRequest& request) { 8701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST); 8711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 8721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 8731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 8761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1); 8771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 8781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 8791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS); 8821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (int i = 0; i < mParams.num; i++) { 8831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *attr2 = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM); 8841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (attr2 == NULL) { 8851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_ERROR_OUT_OF_MEMORY; 8861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.bssids[i].bssid); 8881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 8891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 8901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.bssids[i].high); 8921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 8931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 8941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.bssids[i].low); 8961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 8971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 8981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(attr2); 9001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(attr); 9031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 9041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createTeardownRequest(WifiRequest& request) { 9081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST); 9091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 9141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1); 9151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS); 9201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(attr); 9211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 9221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int start() { 9261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Executing hotlist setup request, num = %d", mParams.num); 9271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 9281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = createSetupRequest(request); 9291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 9341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Failed to execute hotlist setup request, result = %d", result); 9361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS); 9371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Successfully set %d APs in the hotlist", mParams.num); 9411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1); 9421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS); 9471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 9491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS); 9511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("successfully restarted the scan"); 9551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int cancel() { 9591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* unregister event handler */ 9601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS); 9611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* create set hotlist message with empty hotlist */ 9631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 9641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = createTeardownRequest(request); 9651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 9701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Successfully reset APs in current hotlist"); 9751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleResponse(WifiEvent& reply) { 9791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* Nothing to do on response! */ 9801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 9811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleEvent(WifiEvent& event) { 9841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Got a hotlist ap found event"); 9851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 98609f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde // event.log(); 9871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 9891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int len = event.get_vendor_data_len(); 9901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (vendor_data == NULL || len == 0) { 9921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("No scan results found"); 9931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 9941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memset(mResults, 0, sizeof(wifi_scan_result) * MAX_RESULTS); 9971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int num = len / sizeof(wifi_scan_result); 9991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde num = min(MAX_RESULTS, num); 10001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memcpy(mResults, event.get_vendor_data(), num * sizeof(wifi_scan_result)); 10011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Retrieved %d hot APs", num); 10021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde (*mHandler.on_hotlist_ap_found)(id(), num, mResults); 10041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 10051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}; 10071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_set_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface, 10091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler) 10101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 10111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_handle handle = getWifiHandle(iface); 10121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde BssidHotlistCommand *cmd = new BssidHotlistCommand(iface, id, params, handler); 10141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_register_cmd(handle, id, cmd); 10151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return (wifi_error)cmd->start(); 10161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 10171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_reset_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface) 10191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 10201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_handle handle = getWifiHandle(iface); 10211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiCommand *cmd = wifi_unregister_cmd(handle, id); 10231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (cmd) { 10241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde cmd->cancel(); 10251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde delete cmd; 10261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 10271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_ERROR_INVALID_ARGS; 10301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 10311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde///////////////////////////////////////////////////////////////////////////// 10341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass SignificantWifiChangeCommand : public WifiCommand 10361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 10371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeprivate: 10381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_significant_change_params mParams; 10391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_significant_change_handler mHandler; 10401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde static const int MAX_RESULTS = 64; 10411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result mResults[MAX_RESULTS]; 10421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic: 10431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde SignificantWifiChangeCommand(wifi_interface_handle handle, int id, 10441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_significant_change_params params, wifi_significant_change_handler handler) 10451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde : WifiCommand(handle, id), mParams(params), mHandler(handler) 10461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde { } 10471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createSetupRequest(WifiRequest& request) { 10491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG); 10501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 10511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 10551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u8(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1); 10561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 10571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE, mParams.rssi_sample_size); 10601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 10611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size); 10641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 10651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING, mParams.min_breaching); 10681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 10691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS); 10731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (int i = 0; i < mParams.num; i++) { 10751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *attr2 = request.attr_start(i); 10771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (attr2 == NULL) { 10781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_ERROR_OUT_OF_MEMORY; 10791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.bssids[i].bssid); 10811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 10821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.bssids[i].high); 10851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 10861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.bssids[i].low); 10891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 10901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(attr2); 10931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(attr); 10961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 10971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createTeardownRequest(WifiRequest& request) { 11021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG); 11031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 11081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u16(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1); 11091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 11141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int start() { 11181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Set significant wifi change config"); 11191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 11201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = createSetupRequest(request); 11221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 11271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("failed to set significant wifi change config %d", result); 11291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("successfully set significant wifi change config"); 11331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1); 11351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); 11401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 11421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); 11441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("successfully restarted the scan"); 11481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int cancel() { 11521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* unregister event handler */ 11531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); 11541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* create set significant change monitor message with empty hotlist */ 11561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 11571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = createTeardownRequest(request); 11591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 11641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("successfully reset significant wifi change config"); 11691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleResponse(WifiEvent& reply) { 11731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* Nothing to do on response! */ 11741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 11751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleEvent(WifiEvent& event) { 11781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Got a significant wifi change event"); 11791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 11811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int len = event.get_vendor_data_len(); 11821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (vendor_data == NULL || len == 0) { 11841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("No scan results found"); 11851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 11861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde typedef struct { 11891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde uint16_t flags; 11901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde uint16_t channel; 11911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde mac_addr bssid; 11921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde byte rssi_history[8]; 11931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } ChangeInfo; 11941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int num = min(len / sizeof(ChangeInfo), MAX_RESULTS); 11961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ChangeInfo *ci = (ChangeInfo *)event.get_vendor_data(); 11971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (int i = 0; i < num; i++) { 11991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memcpy(mResults[i].bssid, ci[i].bssid, sizeof(mac_addr)); 12001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde mResults[i].rssi = ci[i].rssi_history[7]; 12011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde mResults[i].channel = ci[i].channel; 12021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Retrieved %d scan results", num); 12051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (num != 0) { 12071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde (*mHandler.on_significant_change)(id(), num, mResults); 12081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else { 12091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGW("No significant change reported"); 12101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 12131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}; 12151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_set_significant_change_handler(wifi_request_id id, wifi_interface_handle iface, 12171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_significant_change_params params, wifi_significant_change_handler handler) 12181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 12191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_handle handle = getWifiHandle(iface); 12201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde SignificantWifiChangeCommand *cmd = new SignificantWifiChangeCommand( 12221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde iface, id, params, handler); 12231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_register_cmd(handle, id, cmd); 12241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return (wifi_error)cmd->start(); 12251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 12261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface) 12281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 12291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_handle handle = getWifiHandle(iface); 12301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiCommand *cmd = wifi_unregister_cmd(handle, id); 12321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (cmd) { 12331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde cmd->cancel(); 12341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde delete cmd; 12351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 12361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_ERROR_INVALID_ARGS; 12391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 1240