gscan.cpp revision 27a89dc4e3256ded710cf7bea77aed3b8cd168e2
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> 17642bfbe829f5438db3d99ce4678bcb770359a632Vinit Deshpande#include <netlink/handlers.h> 181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include "sync.h" 201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#define LOG_TAG "WifiHAL" 221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <utils/Log.h> 241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include "wifi_hal.h" 261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include "common.h" 271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include "cpp_bindings.h" 281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndetypedef enum { 301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START, 321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_SUBCMD_SET_CONFIG, /* 0x1001 */ 341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_SUBCMD_SET_SCAN_CONFIG, /* 0x1002 */ 361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_SUBCMD_ENABLE_GSCAN, /* 0x1003 */ 371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_SUBCMD_GET_SCAN_RESULTS, /* 0x1004 */ 381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_SUBCMD_SCAN_RESULTS, /* 0x1005 */ 391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_SUBCMD_SET_HOTLIST, /* 0x1006 */ 411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG, /* 0x1007 */ 43922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, /* 0x1008 */ 4427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin GSCAN_SUBCMD_GET_CHANNEL_LIST, /* 0x1009 */ 451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* Add more sub commands here */ 471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin GSCAN_SUBCMD_MAX /* 0x100A */ 491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} GSCAN_SUB_COMMAND; 511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndetypedef enum { 531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_NUM_BUCKETS = 10, 551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_BASE_PERIOD, 56922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde GSCAN_ATTRIBUTE_BUCKETS_BAND, 571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_BUCKET_ID, 581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_BUCKET_PERIOD, 591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, 601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_BUCKET_CHANNELS, 611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, 621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_REPORT_THRESHOLD, 631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, 6427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin GSCAN_ATTRIBUTE_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND, 651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20, 671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, /* indicates no more results */ 681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_FLUSH_FEATURE, /* Flush all the configs */ 69922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde GSCAN_ENABLE_FULL_SCAN_RESULTS, 70922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde GSCAN_ATTRIBUTE_REPORT_EVENTS, 711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* remaining reserved for additional attributes */ 731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30, 741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_FLUSH_RESULTS, 751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SCAN_RESULTS, /* flat array of wifi_scan_result */ 761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SCAN_ID, /* indicates scan number */ 771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SCAN_FLAGS, /* indicates if scan was aborted */ 781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_AP_FLAGS, /* flags on significant change event */ 7927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin GSCAN_ATTRIBUTE_NUM_CHANNELS, 8027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin GSCAN_ATTRIBUTE_CHANNEL_LIST, 811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* remaining reserved for additional attributes */ 831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SSID = 40, 851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_BSSID, 861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_CHANNEL, 871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_RSSI, 881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_TIMESTAMP, 891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_RTT, 901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_RTTSD, 911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* remaining reserved for additional attributes */ 931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50, 951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_RSSI_LOW, 961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_RSSI_HIGH, 971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_HOTLIST_ELEM, 981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* remaining reserved for additional attributes */ 1011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60, 1021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, 1031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_MIN_BREACHING, 1041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS, 1051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_MAX 1081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} GSCAN_ATTRIBUTE; 1101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 111922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 112922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde// helper methods 113922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndewifi_error wifi_enable_full_scan_results(wifi_request_id id, wifi_interface_handle iface, 114922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result_handler handler); 115922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndewifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface); 116922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 117922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 1181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde///////////////////////////////////////////////////////////////////////////// 1191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass GetCapabilitiesCommand : public WifiCommand 1211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 1221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_gscan_capabilities *mCapabilities; 1231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic: 1241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GetCapabilitiesCommand(wifi_interface_handle iface, wifi_gscan_capabilities *capabitlites) 1251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde : WifiCommand(iface, 0), mCapabilities(capabitlites) 1261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde { 1271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memset(mCapabilities, 0, sizeof(*mCapabilities)); 1281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int create() { 1311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Creating message to get scan capablities; iface = %d", mIfaceInfo->id); 1321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int ret = mMsg.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_CAPABILITIES); 1341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (ret < 0) { 1351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return ret; 1361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return ret; 1391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeprotected: 1421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleResponse(WifiEvent& reply) { 1431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("In GetCapabilities::handleResponse"); 1451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (reply.get_cmd() != NL80211_CMD_VENDOR) { 1471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); 1481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 1491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int id = reply.get_vendor_id(); 1521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int subcmd = reply.get_vendor_subcmd(); 1531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde void *data = reply.get_vendor_data(); 1551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int len = reply.get_vendor_data_len(); 1561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 157e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len, 158e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande sizeof(*mCapabilities)); 159e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande 160e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities))); 1611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_OK; 1631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}; 1651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle, 1681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_gscan_capabilities *capabilities) 1691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 1701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GetCapabilitiesCommand command(handle, capabilities); 1711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return (wifi_error) command.requestResponse(); 1721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 1731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 17427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwinclass GetChannelListCommand : public WifiCommand 17527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin{ 17627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin wifi_channel *channels; 17727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin int max_channels; 17827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin int *num_channels; 17927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin int band; 18027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwinpublic: 18127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin GetChannelListCommand(wifi_interface_handle iface, wifi_channel *channel_buf, int *ch_num, 18227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin int num_max_ch, int band) 18327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin : WifiCommand(iface, 0), channels(channel_buf), max_channels(num_max_ch), num_channels(ch_num), 18427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin band(band) 18527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin { 18627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin memset(channels, 0, sizeof(wifi_channel) * max_channels); 18727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } 18827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin virtual int create() { 18927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin ALOGD("Creating message to get channel list; iface = %d", mIfaceInfo->id); 19027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 19127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin int ret = mMsg.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_CHANNEL_LIST); 19227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin if (ret < 0) { 19327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin return ret; 19427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } 19527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 19627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA); 19727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin ret = mMsg.put_u32(GSCAN_ATTRIBUTE_BAND, band); 19827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin if (ret < 0) { 19927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin return ret; 20027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } 20127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 20227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin mMsg.attr_end(data); 20327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 20427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin return ret; 20527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } 20627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 20727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwinprotected: 20827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin virtual int handleResponse(WifiEvent& reply) { 20927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 21027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin ALOGD("In GetChannelList::handleResponse"); 21127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 21227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin if (reply.get_cmd() != NL80211_CMD_VENDOR) { 21327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); 21427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin return NL_SKIP; 21527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } 21627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 21727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin int id = reply.get_vendor_id(); 21827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin int subcmd = reply.get_vendor_subcmd(); 21927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin int num_channels_to_copy = 0; 22027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 22127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA); 22227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin int len = reply.get_vendor_data_len(); 22327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 22427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin ALOGD("Id = %0x, subcmd = %d, len = %d", id, subcmd, len); 22527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin if (vendor_data == NULL || len == 0) { 22627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin ALOGE("no vendor data in GetChannelList response; ignoring it"); 22727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin return NL_SKIP; 22827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } 22927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 23027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin for (nl_iterator it(vendor_data); it.has_next(); it.next()) { 23127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin if (it.get_type() == GSCAN_ATTRIBUTE_NUM_CHANNELS) { 23227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin num_channels_to_copy = it.get_u32(); 23327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin ALOGI("Got channel list with %d channels", num_channels_to_copy); 23427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin if(num_channels_to_copy > max_channels) 23527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin num_channels_to_copy = max_channels; 23627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin *num_channels = num_channels_to_copy; 23727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } else if (it.get_type() == GSCAN_ATTRIBUTE_CHANNEL_LIST && num_channels_to_copy) { 23827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin memcpy(channels, it.get_data(), sizeof(int) * num_channels_to_copy); 23927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } else { 24027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin ALOGW("Ignoring invalid attribute type = %d, size = %d", 24127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin it.get_type(), it.get_len()); 24227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } 24327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } 24427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 24527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin return NL_OK; 24627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } 24727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin}; 24827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 24927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwinwifi_error wifi_get_valid_channels(wifi_interface_handle handle, 25027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin int band, int max_channels, wifi_channel *channels, int *num_channels) 25127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin{ 25227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin GetChannelListCommand command(handle, channels, num_channels, 25327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin max_channels, band); 25427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin return (wifi_error) command.requestResponse(); 25527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin} 2561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde///////////////////////////////////////////////////////////////////////////// 2571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde/* helper functions */ 2591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndestatic int parseScanResults(wifi_scan_result *results, int num, nlattr *attr) 2611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 2621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memset(results, 0, sizeof(wifi_scan_result) * num); 2631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int i = 0; 2651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (nl_iterator it(attr); it.has_next() && i < num; it.next(), i++) { 2661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int index = it.get_type(); 2681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("retrieved scan result %d", index); 2691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *sc_data = (nlattr *) it.get_data(); 2701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result *result = results + i; 2711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (nl_iterator it2(sc_data); it2.has_next(); it2.next()) { 2731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int type = it2.get_type(); 2741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (type == GSCAN_ATTRIBUTE_SSID) { 2751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde strncpy(result->ssid, (char *) it2.get_data(), it2.get_len()); 2761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->ssid[it2.get_len()] = 0; 2771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (type == GSCAN_ATTRIBUTE_BSSID) { 2781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memcpy(result->bssid, (byte *) it2.get_data(), sizeof(mac_addr)); 2791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (type == GSCAN_ATTRIBUTE_TIMESTAMP) { 2801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->ts = it2.get_u64(); 2811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (type == GSCAN_ATTRIBUTE_CHANNEL) { 2821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->ts = it2.get_u16(); 2831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (type == GSCAN_ATTRIBUTE_RSSI) { 2841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->rssi = it2.get_u8(); 2851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (type == GSCAN_ATTRIBUTE_RTT) { 2861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->rtt = it2.get_u64(); 2871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (type == GSCAN_ATTRIBUTE_RTTSD) { 2881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->rtt_sd = it2.get_u64(); 2891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 2901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 2911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 2931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (i >= num) { 2951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("Got too many results; skipping some"); 2961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 2971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return i; 2991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 3001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 3011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeint createFeatureRequest(WifiRequest& request, int subcmd, int enable) { 3021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 3031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, subcmd); 3041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 3051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 3061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 3071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 3081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 3091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_ENABLE_FEATURE, enable); 3101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 3111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 3121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 3131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 3141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 3151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 3161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 3171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 3181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde///////////////////////////////////////////////////////////////////////////// 319922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndeclass FullScanResultsCommand : public WifiCommand 320922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde{ 321922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int *mParams; 322922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result_handler mHandler; 323922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndepublic: 324922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde FullScanResultsCommand(wifi_interface_handle iface, int id, int *params, 325922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result_handler handler) 326922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde : WifiCommand(iface, id), mParams(params), mHandler(handler) 327922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde { } 328922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 329922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int createRequest(WifiRequest& request, int subcmd, int enable) { 330922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int result = request.create(GOOGLE_OUI, subcmd); 331922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result < 0) { 332922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 333922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 334922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 335922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 336922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = request.put_u32(GSCAN_ENABLE_FULL_SCAN_RESULTS, enable); 337922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result < 0) { 338922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 339922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 340922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 341922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde request.attr_end(data); 342922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 343922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 344922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 345922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 346922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int start() { 347922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGD("Enabling Full scan results"); 348922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde WifiRequest request(familyId(), ifaceId()); 349922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 1); 350922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result != WIFI_SUCCESS) { 351922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGE("failed to create request; result = %d", result); 352922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 353922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 354922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 355922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); 356922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 357922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = requestResponse(request); 358922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result != WIFI_SUCCESS) { 359922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGE("failed to enable full scan results; result = %d", result); 360922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); 361922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 362922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 363922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 364922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 365922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 366922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 367922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde virtual int cancel() { 368922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGD("Disabling Full scan results"); 369922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 370922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde WifiRequest request(familyId(), ifaceId()); 371922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 0); 372922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result != WIFI_SUCCESS) { 373922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGE("failed to create request; result = %d", result); 374922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } else { 375922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = requestResponse(request); 376922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result != WIFI_SUCCESS) { 377922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGE("failed to disable full scan results;result = %d", result); 378922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 379922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 380922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 381922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); 382922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 383922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 384922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 385922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde virtual int handleResponse(WifiEvent& reply) { 386922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGD("Request complete!"); 387922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde /* Nothing to do on response! */ 388922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return NL_SKIP; 389922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 390922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 391922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde virtual int handleEvent(WifiEvent& event) { 392922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("Full scan results: Got an event"); 393922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 394922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde event.log(); 395922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 396922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 397922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde unsigned int len = event.get_vendor_data_len(); 398922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 399922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (vendor_data == NULL || len < sizeof(wifi_scan_result)) { 400922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("No scan results found"); 401922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return NL_SKIP; 402922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 403922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 404922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result *result = (wifi_scan_result *)event.get_vendor_data(); 405922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 40627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin if(*mHandler.on_full_scan_result) 40727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin (*mHandler.on_full_scan_result)(id(), result); 40827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 409922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%-32s\t", result->ssid); 410922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 411922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%02x:%02x:%02x:%02x:%02x:%02x ", result->bssid[0], result->bssid[1], 412922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result->bssid[2], result->bssid[3], result->bssid[4], result->bssid[5]); 413922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 414922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%d\t", result->rssi); 415922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%d\t", result->channel); 416922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%lld\t", result->ts); 417922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%lld\t", result->rtt); 418922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%lld\n", result->rtt_sd); 419922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 420922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 421922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return NL_SKIP; 422922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 423922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 424922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde}; 425922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde///////////////////////////////////////////////////////////////////////////// 4261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass ScanCommand : public WifiCommand 4281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 4291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_cmd_params *mParams; 4301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result_handler mHandler; 431922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde static unsigned mGlobalFullScanBuckets; 432922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde bool mLocalFullScanBuckets; 4331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic: 4341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ScanCommand(wifi_interface_handle iface, int id, wifi_scan_cmd_params *params, 4351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result_handler handler) 436922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde : WifiCommand(iface, id), mParams(params), mHandler(handler), 437922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde mLocalFullScanBuckets(0) 4381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde { } 4391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createSetupRequest(WifiRequest& request) { 4411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_CONFIG); 4421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 4431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 4441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 4471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_BASE_PERIOD, mParams->base_period); 4481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 4491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 4501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_NUM_BUCKETS, mParams->num_buckets); 4531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 4541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 4551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (int i = 0; i < mParams->num_buckets; i++) { 4581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr * bucket = request.attr_start(i); // next bucket 4591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_ID, mParams->buckets[i].bucket); 4601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 4611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 4621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_PERIOD, mParams->buckets[i].period); 4641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 4651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 4661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 467922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_BUCKETS_BAND, 468922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde mParams->buckets[i].band); 469922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result < 0) { 470922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 471922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 472922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 473922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_EVENTS, 474922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde mParams->buckets[i].report_events); 475922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result < 0) { 476922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 477922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 478922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 4791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, 4801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde mParams->buckets[i].num_channels); 4811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 4821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 4831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 485922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (mParams->buckets[i].num_channels) { 486922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde nlattr *channels = request.attr_start(GSCAN_ATTRIBUTE_BUCKET_CHANNELS); 487922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde for (int j = 0; j < mParams->buckets[i].num_channels; j++) { 488922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = request.put_u32(j, mParams->buckets[i].channels[j].channel); 489922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result < 0) { 490922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 491922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 4921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 493922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde request.attr_end(channels); 4941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(bucket); 4971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 5001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 5011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createScanConfigRequest(WifiRequest& request) { 5041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SCAN_CONFIG); 5051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 5061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 5071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 5101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, mParams->max_ap_per_scan); 5111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 5121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 5131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD, mParams->report_threshold); 5161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 5171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 5181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 520e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande int num_scans = 20; 52109f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde for (int i = 0; i < mParams->num_buckets; i++) { 522922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (mParams->buckets[i].report_events == 1) { 523e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande ALOGD("Setting num_scans to 1"); 52409f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde num_scans = 1; 52509f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde break; 52609f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde } 52709f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde } 52809f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde 52909f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, num_scans); 5301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 5311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 5321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 5351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 5361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createStartRequest(WifiRequest& request) { 5391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1); 5401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createStopRequest(WifiRequest& request) { 5431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 0); 5441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 546922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int enableFullScanResultsIfRequired() { 547922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde /* temporary workaround till we have full support for per bucket scans */ 548922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 549922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("enabling full scan results if needed"); 550922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int nBuckets = 0; 551922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde for (int i = 0; i < mParams->num_buckets; i++) { 552922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (mParams->buckets[i].report_events == 2) { 553922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde nBuckets++; 554922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 555922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 556922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 557922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (mGlobalFullScanBuckets == 0 && nBuckets != 0) { 558922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int result = wifi_enable_full_scan_results(0x1000, ifaceHandle(), mHandler); 559922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result != WIFI_SUCCESS) { 560922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("failed to enable full scan results"); 561922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 562922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } else { 563922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("successfully enabled full scan results"); 564922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 565922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } else { 566922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("mGlobalFullScanBuckets = %d, nBuckets = %d", mGlobalFullScanBuckets, nBuckets); 567922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 568922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 569922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde mLocalFullScanBuckets = nBuckets; 570922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde mGlobalFullScanBuckets += nBuckets; 571922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 572922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 573922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 574922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int disableFullScanResultsIfRequired() { 575922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde /* temporary workaround till we have full support for per bucket scans */ 576922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 577922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (mLocalFullScanBuckets == 0) { 578922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 579922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 580922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 581922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde mGlobalFullScanBuckets -= mLocalFullScanBuckets; 582922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (mGlobalFullScanBuckets == 0) { 583922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int result = wifi_disable_full_scan_results(0x1000, ifaceHandle()); 584922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result != WIFI_SUCCESS) { 585922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("failed to disable full scan results"); 586922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } else { 587922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("successfully disable full scan results"); 588922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 589922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 590922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 591922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 592922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 593922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 5941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int start() { 5951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Setting configuration"); 5961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 5971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = createSetupRequest(request); 5981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 5991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to create setup request; result = %d", result); 6001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 6011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 6041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 6051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to configure setup; result = %d", result); 6061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 6071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.destroy(); 6101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = createScanConfigRequest(request); 6121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 6131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to create scan config request; result = %d", result); 6141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 6151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 6181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 6191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to configure scan; result = %d", result); 6201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 6211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Starting scan"); 6241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = createStartRequest(request); 6261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 6271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to create start request; result = %d", result); 6281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 6291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE); 6321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 6341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 6351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to start scan; result = %d", result); 6361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE); 6371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 6381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 640922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = enableFullScanResultsIfRequired(); 6411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 6421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int cancel() { 6451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Stopping scan"); 6461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 6481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = createStopRequest(request); 6491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 6501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to create stop request; result = %d", result); 6511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else { 6521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 6531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 6541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to stop scan; result = %d", result); 6551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE); 659922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde disableFullScanResultsIfRequired(); 660922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 6611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 6621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleResponse(WifiEvent& reply) { 6651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* Nothing to do on response! */ 6661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 6671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleEvent(WifiEvent& event) { 6701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Got a scan results event"); 6711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 67209f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde // event.log(); 6731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 6751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int len = event.get_vendor_data_len(); 6761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (vendor_data == NULL || len != 4) { 6781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("No scan results found"); 6791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 6801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int num = event.get_u32(NL80211_ATTR_VENDOR_DATA); 6831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Found %d scan results", num); 6841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde (*mHandler.on_scan_results_available)(id(), num); 6851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 6861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}; 6881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 689922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndeunsigned ScanCommand::mGlobalFullScanBuckets = 0; 690922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 6911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_start_gscan( 6921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_request_id id, 6931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_interface_handle iface, 6941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_cmd_params params, 6951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result_handler handler) 6961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 6971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_handle handle = getWifiHandle(iface); 6981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Starting GScan, halHandle = %p", handle); 7001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ScanCommand *cmd = new ScanCommand(iface, id, ¶ms, handler); 7021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_register_cmd(handle, id, cmd); 7031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return (wifi_error)cmd->start(); 7041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 7051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_stop_gscan(wifi_request_id id, wifi_interface_handle iface) 7071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 7081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Stopping GScan"); 7091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_handle handle = getWifiHandle(iface); 7101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 711922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if(id == -1) { 712922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result_handler handler; 713922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_cmd_params dummy_params; 714922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_handle handle = getWifiHandle(iface); 715922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde memset(&handler, 0, sizeof(handler)); 716922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 717922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ScanCommand *cmd = new ScanCommand(iface, id, &dummy_params, handler); 718922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde cmd->cancel(); 719922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde delete cmd; 720922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 721922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 722922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 723922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 7241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiCommand *cmd = wifi_unregister_cmd(handle, id); 7251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (cmd) { 7261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde cmd->cancel(); 7271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde delete cmd; 7281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 7291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 7301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_ERROR_INVALID_ARGS; 7321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 7331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 734922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 735922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndewifi_error wifi_enable_full_scan_results( 736922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_request_id id, 737922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_interface_handle iface, 738922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result_handler handler) 739922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde{ 740922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_handle handle = getWifiHandle(iface); 741922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int params_dummy; 742922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGD("Enabling full scan results, halHandle = %p", handle); 743922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 744922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, id, ¶ms_dummy, handler); 745922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_register_cmd(handle, id, cmd); 746922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 747922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return (wifi_error)cmd->start(); 748922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde} 749922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 750922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndewifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface) 751922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde{ 752922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGD("Disabling full scan results"); 753922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_handle handle = getWifiHandle(iface); 754922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 755922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if(id == -1) { 756922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result_handler handler; 757922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_handle handle = getWifiHandle(iface); 758922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int params_dummy; 759922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 760922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde memset(&handler, 0, sizeof(handler)); 761922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, 0, ¶ms_dummy, handler); 762922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde cmd->cancel(); 763922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde delete cmd; 764922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 765922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 766922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 767922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde WifiCommand *cmd = wifi_unregister_cmd(handle, id); 768922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (cmd) { 769922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde cmd->cancel(); 770922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde delete cmd; 771922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 772922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 773922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 774922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_ERROR_INVALID_ARGS; 775922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde} 776922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 777922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 7781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde///////////////////////////////////////////////////////////////////////////// 7791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass GetScanResultsCommand : public WifiCommand { 7811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result *mResults; 782e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande int mMax; 7831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int *mNum; 7841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int mRetrieved; 7851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde byte mFlush; 7861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int mCompleted; 7871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic: 7881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GetScanResultsCommand(wifi_interface_handle iface, byte flush, 789e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande wifi_scan_result *results, int max, int *num) 790e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande : WifiCommand(iface, -1), mResults(results), mMax(max), mNum(num), 7911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde mRetrieved(0), mFlush(flush), mCompleted(0) 7921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde { } 7931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createRequest(WifiRequest& request, int num, byte flush) { 7951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_SCAN_RESULTS); 7961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 7971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 7981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 7991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 8011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num); 8021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 8031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 8041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u8(GSCAN_ATTRIBUTE_FLUSH_RESULTS, flush); 8071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 8081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 8091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 8121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 8131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int execute() { 8161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 817e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande ALOGI("retrieving %d scan results", mMax); 8181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 819e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande for (int i = 0; i < 10 && mRetrieved < mMax; i++) { 820e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande int result = createRequest(request, (mMax - mRetrieved), mFlush); 8211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 8221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to create request"); 8231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 8241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int prev_retrieved = mRetrieved; 8271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 8291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 8311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to retrieve scan results; result = %d", result); 8321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 8331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (mRetrieved == prev_retrieved || mCompleted) { 8361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* no more items left to retrieve */ 8371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde break; 8381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.destroy(); 8411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("GetScanResults read %d results", mRetrieved); 8441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde *mNum = mRetrieved; 8451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 8461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleResponse(WifiEvent& reply) { 8491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("In GetScanResultsCommand::handleResponse"); 8501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (reply.get_cmd() != NL80211_CMD_VENDOR) { 8521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); 8531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 8541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int id = reply.get_vendor_id(); 8571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int subcmd = reply.get_vendor_subcmd(); 8581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Id = %0x, subcmd = %d", id, subcmd); 8601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* 8621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (subcmd != GSCAN_SUBCMD_SCAN_RESULTS) { 8631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("Invalid response to GetScanResultsCommand; ignoring it"); 8641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 8651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde */ 8671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA); 8691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int len = reply.get_vendor_data_len(); 8701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (vendor_data == NULL || len == 0) { 8721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("no vendor data in GetScanResults response; ignoring it"); 8731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 8741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (nl_iterator it(vendor_data); it.has_next(); it.next()) { 8771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE) { 8781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde mCompleted = it.get_u8(); 8791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("retrieved mCompleted flag : %d", mCompleted); 8801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS || it.get_type() == 0) { 8811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) { 8821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int scan_id = 0, flags = 0, num = 0; 8831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_ID) { 8841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde scan_id = it.get_u32(); 8851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_FLAGS) { 8861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde flags = it.get_u8(); 8871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (it2.get_type() == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) { 8881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde num = it2.get_u32(); 8891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS) { 8901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde num = it2.get_len() / sizeof(wifi_scan_result); 8911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde num = min(*mNum - mRetrieved, num); 8921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memcpy(mResults + mRetrieved, it2.get_data(), 8931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde sizeof(wifi_scan_result) * num); 8941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Retrieved %d scan results", num); 8951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result *results = (wifi_scan_result *)it2.get_data(); 8961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (int i = 0; i < num; i++) { 8971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result *result = results + i; 89809f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde ALOGI("%02d %-32s %02x:%02x:%02x:%02x:%02x:%02x %04d", i, 8991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->ssid, result->bssid[0], result->bssid[1], result->bssid[2], 90009f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde result->bssid[3], result->bssid[4], result->bssid[5], 90109f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde result->rssi); 9021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde mRetrieved += num; 9041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else { 9051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGW("Ignoring invalid attribute type = %d, size = %d", 9061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde it.get_type(), it.get_len()); 9071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else { 9101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGW("Ignoring invalid attribute type = %d, size = %d", 9111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde it.get_type(), it.get_len()); 9121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_OK; 9161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}; 9181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface, byte flush, 920e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande int max, wifi_scan_result *results, int *num) { 9211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Getting cached scan results, iface handle = %p, num = %d", iface, *num); 9231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 924e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande GetScanResultsCommand *cmd = new GetScanResultsCommand(iface, flush, results, max, num); 9251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return (wifi_error)cmd->execute(); 9261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 9271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde///////////////////////////////////////////////////////////////////////////// 9291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass BssidHotlistCommand : public WifiCommand 9311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 9321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeprivate: 9331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_bssid_hotlist_params mParams; 9341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_hotlist_ap_found_handler mHandler; 9351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde static const int MAX_RESULTS = 64; 9361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result mResults[MAX_RESULTS]; 9371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic: 9381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde BssidHotlistCommand(wifi_interface_handle handle, int id, 9391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler) 9401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde : WifiCommand(handle, id), mParams(params), mHandler(handler) 9411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde { } 9421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createSetupRequest(WifiRequest& request) { 9441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST); 9451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 9501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1); 9511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS); 956e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande for (int i = 0; i < mParams.num_ap; i++) { 9571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *attr2 = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM); 9581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (attr2 == NULL) { 9591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_ERROR_OUT_OF_MEMORY; 9601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 961e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid); 9621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 965e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high); 9661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 969e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low); 9701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(attr2); 9741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(attr); 9771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 9781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createTeardownRequest(WifiRequest& request) { 9821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST); 9831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 9881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1); 9891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS); 9941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(attr); 9951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 9961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int start() { 1000e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande ALOGI("Executing hotlist setup request, num = %d", mParams.num_ap); 10011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 10021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = createSetupRequest(request); 10031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 10041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 10081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 10091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Failed to execute hotlist setup request, result = %d", result); 10101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS); 10111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1014e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande ALOGI("Successfully set %d APs in the hotlist", mParams.num_ap); 10151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1); 10161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 10171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS); 10211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 10231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 10241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS); 10251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("successfully restarted the scan"); 10291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int cancel() { 10331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* unregister event handler */ 10341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS); 10351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* create set hotlist message with empty hotlist */ 10371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 10381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = createTeardownRequest(request); 10391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 10401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 10441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 10451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Successfully reset APs in current hotlist"); 10491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleResponse(WifiEvent& reply) { 10531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* Nothing to do on response! */ 10541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 10551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleEvent(WifiEvent& event) { 10581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Got a hotlist ap found event"); 10591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 106009f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde // event.log(); 10611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 10631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int len = event.get_vendor_data_len(); 10641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (vendor_data == NULL || len == 0) { 10661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("No scan results found"); 10671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 10681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memset(mResults, 0, sizeof(wifi_scan_result) * MAX_RESULTS); 10711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int num = len / sizeof(wifi_scan_result); 10731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde num = min(MAX_RESULTS, num); 10741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memcpy(mResults, event.get_vendor_data(), num * sizeof(wifi_scan_result)); 10751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Retrieved %d hot APs", num); 10761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde (*mHandler.on_hotlist_ap_found)(id(), num, mResults); 10781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 10791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}; 10811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_set_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface, 10831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler) 10841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 10851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_handle handle = getWifiHandle(iface); 10861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde BssidHotlistCommand *cmd = new BssidHotlistCommand(iface, id, params, handler); 10881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_register_cmd(handle, id, cmd); 10891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return (wifi_error)cmd->start(); 10901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 10911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_reset_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface) 10931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 10941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_handle handle = getWifiHandle(iface); 10951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiCommand *cmd = wifi_unregister_cmd(handle, id); 10971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (cmd) { 10981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde cmd->cancel(); 10991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde delete cmd; 11001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 11011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_ERROR_INVALID_ARGS; 11041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 11051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde///////////////////////////////////////////////////////////////////////////// 11081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass SignificantWifiChangeCommand : public WifiCommand 11101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 1111e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande typedef struct { 1112e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande mac_addr bssid; // BSSID 1113e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande wifi_channel channel; // channel frequency in MHz 1114e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande int num_rssi; // number of rssi samples 1115e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande wifi_rssi rssi[8]; // RSSI history in db 1116e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande } wifi_significant_change_result_internal; 1117e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande 11181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeprivate: 11191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_significant_change_params mParams; 11201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_significant_change_handler mHandler; 11211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde static const int MAX_RESULTS = 64; 1122e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande wifi_significant_change_result_internal mResultsBuffer[MAX_RESULTS]; 1123e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande wifi_significant_change_result *mResults[MAX_RESULTS]; 11241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic: 11251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde SignificantWifiChangeCommand(wifi_interface_handle handle, int id, 11261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_significant_change_params params, wifi_significant_change_handler handler) 11271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde : WifiCommand(handle, id), mParams(params), mHandler(handler) 11281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde { } 11291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createSetupRequest(WifiRequest& request) { 11311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG); 11321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 11371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u8(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1); 11381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE, mParams.rssi_sample_size); 11421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size); 11461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING, mParams.min_breaching); 11501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS); 11551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1156e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande for (int i = 0; i < mParams.num_ap; i++) { 11571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *attr2 = request.attr_start(i); 11591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (attr2 == NULL) { 11601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_ERROR_OUT_OF_MEMORY; 11611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1162e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid); 11631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1166e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high); 11671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1170e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low); 11711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(attr2); 11751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(attr); 11781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 11791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createTeardownRequest(WifiRequest& request) { 11841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG); 11851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 11901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u16(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1); 11911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 11961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int start() { 12001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Set significant wifi change config"); 12011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 12021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = createSetupRequest(request); 12041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 12051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 12061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 12091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 12101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("failed to set significant wifi change config %d", result); 12111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 12121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("successfully set significant wifi change config"); 12151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1); 12171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 12181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 12191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); 12221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 12241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 12251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); 12261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 12271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("successfully restarted the scan"); 12301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 12311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int cancel() { 12341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* unregister event handler */ 12351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); 12361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* create set significant change monitor message with empty hotlist */ 12381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 12391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = createTeardownRequest(request); 12411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 12421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 12431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 12461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 12471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 12481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("successfully reset significant wifi change config"); 12511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 12521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleResponse(WifiEvent& reply) { 12551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* Nothing to do on response! */ 12561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 12571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleEvent(WifiEvent& event) { 12601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Got a significant wifi change event"); 12611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 12631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int len = event.get_vendor_data_len(); 12641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (vendor_data == NULL || len == 0) { 12661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("No scan results found"); 12671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 12681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde typedef struct { 12711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde uint16_t flags; 12721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde uint16_t channel; 12731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde mac_addr bssid; 12741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde byte rssi_history[8]; 12751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } ChangeInfo; 12761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int num = min(len / sizeof(ChangeInfo), MAX_RESULTS); 12781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ChangeInfo *ci = (ChangeInfo *)event.get_vendor_data(); 12791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (int i = 0; i < num; i++) { 1281e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande memcpy(mResultsBuffer[i].bssid, ci[i].bssid, sizeof(mac_addr)); 1282e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande mResultsBuffer[i].channel = ci[i].channel; 1283e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande mResultsBuffer[i].num_rssi = 8; 1284e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande memcpy(mResultsBuffer[i].rssi, ci[i].rssi_history, 8); 1285e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande mResults[i] = reinterpret_cast<wifi_significant_change_result *>(&(mResultsBuffer[i])); 12861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Retrieved %d scan results", num); 12891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (num != 0) { 12911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde (*mHandler.on_significant_change)(id(), num, mResults); 12921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else { 12931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGW("No significant change reported"); 12941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 12971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}; 12991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 13001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_set_significant_change_handler(wifi_request_id id, wifi_interface_handle iface, 13011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_significant_change_params params, wifi_significant_change_handler handler) 13021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 13031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_handle handle = getWifiHandle(iface); 13041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 13051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde SignificantWifiChangeCommand *cmd = new SignificantWifiChangeCommand( 13061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde iface, id, params, handler); 13071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_register_cmd(handle, id, cmd); 13081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return (wifi_error)cmd->start(); 13091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 13101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 13111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface) 13121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 13131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_handle handle = getWifiHandle(iface); 13141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 13151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiCommand *cmd = wifi_unregister_cmd(handle, id); 13161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (cmd) { 13171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde cmd->cancel(); 13181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde delete cmd; 13191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 13201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 13211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 13221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_ERROR_INVALID_ARGS; 13231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 1324