gscan.cpp revision 18d4cad266ebda5f90092afd7e4f92e72533f637
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_ATTRIBUTE_NUM_BUCKETS = 10, 321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_BASE_PERIOD, 33922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde GSCAN_ATTRIBUTE_BUCKETS_BAND, 341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_BUCKET_ID, 351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_BUCKET_PERIOD, 361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, 371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_BUCKET_CHANNELS, 381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, 391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_REPORT_THRESHOLD, 401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, 4127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin GSCAN_ATTRIBUTE_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND, 421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20, 441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, /* indicates no more results */ 451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_FLUSH_FEATURE, /* Flush all the configs */ 46922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde GSCAN_ENABLE_FULL_SCAN_RESULTS, 47922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde GSCAN_ATTRIBUTE_REPORT_EVENTS, 481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* remaining reserved for additional attributes */ 501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30, 511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_FLUSH_RESULTS, 521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SCAN_RESULTS, /* flat array of wifi_scan_result */ 531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SCAN_ID, /* indicates scan number */ 541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SCAN_FLAGS, /* indicates if scan was aborted */ 551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_AP_FLAGS, /* flags on significant change event */ 5627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin GSCAN_ATTRIBUTE_NUM_CHANNELS, 5727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin GSCAN_ATTRIBUTE_CHANNEL_LIST, 581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* remaining reserved for additional attributes */ 601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SSID = 40, 621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_BSSID, 631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_CHANNEL, 641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_RSSI, 651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_TIMESTAMP, 661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_RTT, 671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_RTTSD, 681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* remaining reserved for additional attributes */ 701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50, 721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_RSSI_LOW, 731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_RSSI_HIGH, 741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_HOTLIST_ELEM, 751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* remaining reserved for additional attributes */ 781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60, 791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, 801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_MIN_BREACHING, 811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS, 821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GSCAN_ATTRIBUTE_MAX 851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} GSCAN_ATTRIBUTE; 871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 88922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 89922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde// helper methods 90922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndewifi_error wifi_enable_full_scan_results(wifi_request_id id, wifi_interface_handle iface, 91922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result_handler handler); 92922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndewifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface); 93922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 94922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde///////////////////////////////////////////////////////////////////////////// 961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass GetCapabilitiesCommand : public WifiCommand 981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_gscan_capabilities *mCapabilities; 1001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic: 1011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GetCapabilitiesCommand(wifi_interface_handle iface, wifi_gscan_capabilities *capabitlites) 1021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde : WifiCommand(iface, 0), mCapabilities(capabitlites) 1031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde { 1041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memset(mCapabilities, 0, sizeof(*mCapabilities)); 1051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int create() { 1081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Creating message to get scan capablities; iface = %d", mIfaceInfo->id); 1091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int ret = mMsg.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_CAPABILITIES); 1111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (ret < 0) { 1121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return ret; 1131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return ret; 1161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeprotected: 1191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleResponse(WifiEvent& reply) { 1201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("In GetCapabilities::handleResponse"); 1221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (reply.get_cmd() != NL80211_CMD_VENDOR) { 1241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); 1251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 1261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int id = reply.get_vendor_id(); 1291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int subcmd = reply.get_vendor_subcmd(); 1301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde void *data = reply.get_vendor_data(); 1321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int len = reply.get_vendor_data_len(); 1331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 134e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len, 135e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande sizeof(*mCapabilities)); 136e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande 137e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities))); 1381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_OK; 1401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}; 1421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle, 1451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_gscan_capabilities *capabilities) 1461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 1471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GetCapabilitiesCommand command(handle, capabilities); 1481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return (wifi_error) command.requestResponse(); 1491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 1501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 15127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwinclass GetChannelListCommand : public WifiCommand 15227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin{ 15327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin wifi_channel *channels; 15427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin int max_channels; 15527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin int *num_channels; 15627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin int band; 15727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwinpublic: 15827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin GetChannelListCommand(wifi_interface_handle iface, wifi_channel *channel_buf, int *ch_num, 15927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin int num_max_ch, int band) 16027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin : WifiCommand(iface, 0), channels(channel_buf), max_channels(num_max_ch), num_channels(ch_num), 16127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin band(band) 16227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin { 16327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin memset(channels, 0, sizeof(wifi_channel) * max_channels); 16427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } 16527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin virtual int create() { 16627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin ALOGD("Creating message to get channel list; iface = %d", mIfaceInfo->id); 16727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 16827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin int ret = mMsg.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_CHANNEL_LIST); 16927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin if (ret < 0) { 17027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin return ret; 17127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } 17227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 17327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA); 17427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin ret = mMsg.put_u32(GSCAN_ATTRIBUTE_BAND, band); 17527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin if (ret < 0) { 17627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin return ret; 17727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } 17827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 17927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin mMsg.attr_end(data); 18027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 18127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin return ret; 18227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } 18327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 18427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwinprotected: 18527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin virtual int handleResponse(WifiEvent& reply) { 18627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 18727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin ALOGD("In GetChannelList::handleResponse"); 18827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 18927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin if (reply.get_cmd() != NL80211_CMD_VENDOR) { 19027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); 19127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin return NL_SKIP; 19227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } 19327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 19427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin int id = reply.get_vendor_id(); 19527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin int subcmd = reply.get_vendor_subcmd(); 19627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin int num_channels_to_copy = 0; 19727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 19827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA); 19927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin int len = reply.get_vendor_data_len(); 20027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 20127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin ALOGD("Id = %0x, subcmd = %d, len = %d", id, subcmd, len); 20227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin if (vendor_data == NULL || len == 0) { 20327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin ALOGE("no vendor data in GetChannelList response; ignoring it"); 20427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin return NL_SKIP; 20527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } 20627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 20727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin for (nl_iterator it(vendor_data); it.has_next(); it.next()) { 20827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin if (it.get_type() == GSCAN_ATTRIBUTE_NUM_CHANNELS) { 20927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin num_channels_to_copy = it.get_u32(); 21027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin ALOGI("Got channel list with %d channels", num_channels_to_copy); 21127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin if(num_channels_to_copy > max_channels) 21227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin num_channels_to_copy = max_channels; 21327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin *num_channels = num_channels_to_copy; 21427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } else if (it.get_type() == GSCAN_ATTRIBUTE_CHANNEL_LIST && num_channels_to_copy) { 21527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin memcpy(channels, it.get_data(), sizeof(int) * num_channels_to_copy); 21627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } else { 21727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin ALOGW("Ignoring invalid attribute type = %d, size = %d", 21827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin it.get_type(), it.get_len()); 21927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } 22027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } 22127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 22227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin return NL_OK; 22327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin } 22427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin}; 22527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 22627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwinwifi_error wifi_get_valid_channels(wifi_interface_handle handle, 22727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin int band, int max_channels, wifi_channel *channels, int *num_channels) 22827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin{ 22927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin GetChannelListCommand command(handle, channels, num_channels, 23027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin max_channels, band); 23127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin return (wifi_error) command.requestResponse(); 23227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin} 2331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde///////////////////////////////////////////////////////////////////////////// 2341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde/* helper functions */ 2361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndestatic int parseScanResults(wifi_scan_result *results, int num, nlattr *attr) 2381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 2391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memset(results, 0, sizeof(wifi_scan_result) * num); 2401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int i = 0; 2421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (nl_iterator it(attr); it.has_next() && i < num; it.next(), i++) { 2431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int index = it.get_type(); 2451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("retrieved scan result %d", index); 2461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *sc_data = (nlattr *) it.get_data(); 2471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result *result = results + i; 2481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (nl_iterator it2(sc_data); it2.has_next(); it2.next()) { 2501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int type = it2.get_type(); 2511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (type == GSCAN_ATTRIBUTE_SSID) { 2521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde strncpy(result->ssid, (char *) it2.get_data(), it2.get_len()); 2531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->ssid[it2.get_len()] = 0; 2541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (type == GSCAN_ATTRIBUTE_BSSID) { 2551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memcpy(result->bssid, (byte *) it2.get_data(), sizeof(mac_addr)); 2561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (type == GSCAN_ATTRIBUTE_TIMESTAMP) { 2571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->ts = it2.get_u64(); 2581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (type == GSCAN_ATTRIBUTE_CHANNEL) { 2591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->ts = it2.get_u16(); 2601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (type == GSCAN_ATTRIBUTE_RSSI) { 2611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->rssi = it2.get_u8(); 2621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (type == GSCAN_ATTRIBUTE_RTT) { 2631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->rtt = it2.get_u64(); 2641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (type == GSCAN_ATTRIBUTE_RTTSD) { 2651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->rtt_sd = it2.get_u64(); 2661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 2671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 2681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 2701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (i >= num) { 2721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("Got too many results; skipping some"); 2731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 2741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return i; 2761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 2771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeint createFeatureRequest(WifiRequest& request, int subcmd, int enable) { 2791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, subcmd); 2811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 2821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 2831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 2841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 2861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_ENABLE_FEATURE, enable); 2871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 2881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 2891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 2901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 2921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 2931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 2941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde///////////////////////////////////////////////////////////////////////////// 296922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndeclass FullScanResultsCommand : public WifiCommand 297922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde{ 298922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int *mParams; 299922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result_handler mHandler; 300922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndepublic: 301922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde FullScanResultsCommand(wifi_interface_handle iface, int id, int *params, 302922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result_handler handler) 303922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde : WifiCommand(iface, id), mParams(params), mHandler(handler) 304922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde { } 305922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 306922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int createRequest(WifiRequest& request, int subcmd, int enable) { 307922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int result = request.create(GOOGLE_OUI, subcmd); 308922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result < 0) { 309922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 310922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 311922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 312922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 313922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = request.put_u32(GSCAN_ENABLE_FULL_SCAN_RESULTS, enable); 314922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result < 0) { 315922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 316922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 317922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 318922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde request.attr_end(data); 319922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 320922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 321922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 322922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 323922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int start() { 324922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGD("Enabling Full scan results"); 325922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde WifiRequest request(familyId(), ifaceId()); 326922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 1); 327922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result != WIFI_SUCCESS) { 328922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGE("failed to create request; result = %d", result); 329922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 330922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 331922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 332922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); 333922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 334922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = requestResponse(request); 335922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result != WIFI_SUCCESS) { 336922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGE("failed to enable full scan results; result = %d", result); 337922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); 338922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 339922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 340922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 341922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 342922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 343922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 344922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde virtual int cancel() { 345922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGD("Disabling Full scan results"); 346922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 347922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde WifiRequest request(familyId(), ifaceId()); 348922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 0); 349922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result != WIFI_SUCCESS) { 350922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGE("failed to create request; result = %d", result); 351922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } else { 352922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = requestResponse(request); 353922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result != WIFI_SUCCESS) { 354922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGE("failed to disable full scan results;result = %d", result); 355922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 356922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 357922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 358922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); 359922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 360922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 361922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 362922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde virtual int handleResponse(WifiEvent& reply) { 363922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGD("Request complete!"); 364922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde /* Nothing to do on response! */ 365922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return NL_SKIP; 366922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 367922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 368922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde virtual int handleEvent(WifiEvent& event) { 369922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("Full scan results: Got an event"); 370922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 371922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde event.log(); 372922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 373922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 374922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde unsigned int len = event.get_vendor_data_len(); 375922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 376922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (vendor_data == NULL || len < sizeof(wifi_scan_result)) { 377922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("No scan results found"); 378922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return NL_SKIP; 379922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 380922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 381922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result *result = (wifi_scan_result *)event.get_vendor_data(); 382922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 38327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin if(*mHandler.on_full_scan_result) 38427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin (*mHandler.on_full_scan_result)(id(), result); 38527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin 386922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%-32s\t", result->ssid); 387922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 388922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%02x:%02x:%02x:%02x:%02x:%02x ", result->bssid[0], result->bssid[1], 389922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result->bssid[2], result->bssid[3], result->bssid[4], result->bssid[5]); 390922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 391922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%d\t", result->rssi); 392922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%d\t", result->channel); 393922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%lld\t", result->ts); 394922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%lld\t", result->rtt); 395922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("%lld\n", result->rtt_sd); 396922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 397922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 398922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return NL_SKIP; 399922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 400922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 401922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde}; 402922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde///////////////////////////////////////////////////////////////////////////// 4031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass ScanCommand : public WifiCommand 4051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 4061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_cmd_params *mParams; 4071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result_handler mHandler; 408922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde static unsigned mGlobalFullScanBuckets; 409922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde bool mLocalFullScanBuckets; 4101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic: 4111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ScanCommand(wifi_interface_handle iface, int id, wifi_scan_cmd_params *params, 4121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result_handler handler) 413922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde : WifiCommand(iface, id), mParams(params), mHandler(handler), 414922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde mLocalFullScanBuckets(0) 4151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde { } 4161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createSetupRequest(WifiRequest& request) { 4181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_CONFIG); 4191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 4201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 4211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 4241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_BASE_PERIOD, mParams->base_period); 4251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 4261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 4271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_NUM_BUCKETS, mParams->num_buckets); 4301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 4311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 4321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (int i = 0; i < mParams->num_buckets; i++) { 4351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr * bucket = request.attr_start(i); // next bucket 4361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_ID, mParams->buckets[i].bucket); 4371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 4381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 4391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_PERIOD, mParams->buckets[i].period); 4411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 4421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 4431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 444922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_BUCKETS_BAND, 445922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde mParams->buckets[i].band); 446922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result < 0) { 447922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 448922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 449922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 450922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_EVENTS, 451922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde mParams->buckets[i].report_events); 452922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result < 0) { 453922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 454922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 455922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 4561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, 4571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde mParams->buckets[i].num_channels); 4581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 4591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 4601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 462922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (mParams->buckets[i].num_channels) { 463922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde nlattr *channels = request.attr_start(GSCAN_ATTRIBUTE_BUCKET_CHANNELS); 464922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde for (int j = 0; j < mParams->buckets[i].num_channels; j++) { 465922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = request.put_u32(j, mParams->buckets[i].channels[j].channel); 466922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result < 0) { 467922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 468922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 4691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 470922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde request.attr_end(channels); 4711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(bucket); 4741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 4771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 4781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createScanConfigRequest(WifiRequest& request) { 4811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SCAN_CONFIG); 4821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 4831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 4841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 4871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, mParams->max_ap_per_scan); 4881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 4891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 4901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 4921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD, mParams->report_threshold); 4931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 4941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 4951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 4961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 497e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande int num_scans = 20; 49818d4cad266ebda5f90092afd7e4f92e72533f637Vinit Deshpande for (int i = 0; i < mParams->num_buckets; i++) { 49918d4cad266ebda5f90092afd7e4f92e72533f637Vinit Deshpande if (mParams->buckets[i].report_events == 1) { 50018d4cad266ebda5f90092afd7e4f92e72533f637Vinit Deshpande ALOGD("Setting num_scans to 1"); 50118d4cad266ebda5f90092afd7e4f92e72533f637Vinit Deshpande num_scans = 1; 50218d4cad266ebda5f90092afd7e4f92e72533f637Vinit Deshpande break; 50318d4cad266ebda5f90092afd7e4f92e72533f637Vinit Deshpande } 50418d4cad266ebda5f90092afd7e4f92e72533f637Vinit Deshpande } 50509f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde 50609f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, num_scans); 5071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 5081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 5091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 5121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 5131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createStartRequest(WifiRequest& request) { 5161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1); 5171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createStopRequest(WifiRequest& request) { 5201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 0); 5211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 523922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int enableFullScanResultsIfRequired() { 524922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde /* temporary workaround till we have full support for per bucket scans */ 525922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 526922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("enabling full scan results if needed"); 527922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int nBuckets = 0; 528922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde for (int i = 0; i < mParams->num_buckets; i++) { 529922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (mParams->buckets[i].report_events == 2) { 530922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde nBuckets++; 531922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 532922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 533922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 534922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (mGlobalFullScanBuckets == 0 && nBuckets != 0) { 535922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int result = wifi_enable_full_scan_results(0x1000, ifaceHandle(), mHandler); 536922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result != WIFI_SUCCESS) { 537922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("failed to enable full scan results"); 538922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return result; 539922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } else { 540922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("successfully enabled full scan results"); 541922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 542922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } else { 543922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("mGlobalFullScanBuckets = %d, nBuckets = %d", mGlobalFullScanBuckets, nBuckets); 544922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 545922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 546922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde mLocalFullScanBuckets = nBuckets; 547922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde mGlobalFullScanBuckets += nBuckets; 548922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 549922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 550922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 551922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int disableFullScanResultsIfRequired() { 552922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde /* temporary workaround till we have full support for per bucket scans */ 553922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 554922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (mLocalFullScanBuckets == 0) { 555922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 556922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 557922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 558922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde mGlobalFullScanBuckets -= mLocalFullScanBuckets; 559922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (mGlobalFullScanBuckets == 0) { 560922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int result = wifi_disable_full_scan_results(0x1000, ifaceHandle()); 561922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (result != WIFI_SUCCESS) { 562922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("failed to disable full scan results"); 563922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } else { 564922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGI("successfully disable full scan results"); 565922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 566922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 567922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 568922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 569922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 570922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 5711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int start() { 5721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Setting configuration"); 5731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 5741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = createSetupRequest(request); 5751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 5761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to create setup request; result = %d", result); 5771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 5781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 5811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 5821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to configure setup; result = %d", result); 5831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 5841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.destroy(); 5871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = createScanConfigRequest(request); 5891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 5901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to create scan config request; result = %d", result); 5911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 5921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 5941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 5951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 5961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to configure scan; result = %d", result); 5971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 5981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 5991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Starting scan"); 6011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = createStartRequest(request); 6031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 6041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to create start request; result = %d", result); 6051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 6061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE); 6099a23388d5a9f58f106169700bb179de0a4af7840Ashwin registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN); 6109a23388d5a9f58f106169700bb179de0a4af7840Ashwin 6111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 6131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 6141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to start scan; result = %d", result); 6151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE); 6161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 6171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 619922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde result = enableFullScanResultsIfRequired(); 6201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 6211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int cancel() { 6241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Stopping scan"); 6251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 6271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = createStopRequest(request); 6281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 6291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to create stop request; result = %d", result); 6301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else { 6311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 6321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 6331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to stop scan; result = %d", result); 6341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE); 638922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde disableFullScanResultsIfRequired(); 639922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 6401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 6411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleResponse(WifiEvent& reply) { 6441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* Nothing to do on response! */ 6451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 6461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleEvent(WifiEvent& event) { 6491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Got a scan results event"); 6501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 65109f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde // event.log(); 6521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 6541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int len = event.get_vendor_data_len(); 6559a23388d5a9f58f106169700bb179de0a4af7840Ashwin int event_id = event.get_vendor_subcmd(); 6561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6579a23388d5a9f58f106169700bb179de0a4af7840Ashwin if(event_id == GSCAN_EVENT_COMPLETE_SCAN) { 6589a23388d5a9f58f106169700bb179de0a4af7840Ashwin if (vendor_data == NULL || len != 4) { 6599a23388d5a9f58f106169700bb179de0a4af7840Ashwin ALOGI("Scan complete type not mentioned!"); 6609a23388d5a9f58f106169700bb179de0a4af7840Ashwin return NL_SKIP; 6619a23388d5a9f58f106169700bb179de0a4af7840Ashwin } 6629a23388d5a9f58f106169700bb179de0a4af7840Ashwin wifi_scan_event evt_type; 6639a23388d5a9f58f106169700bb179de0a4af7840Ashwin 6649a23388d5a9f58f106169700bb179de0a4af7840Ashwin evt_type = (wifi_scan_event) event.get_u32(NL80211_ATTR_VENDOR_DATA); 6659a23388d5a9f58f106169700bb179de0a4af7840Ashwin ALOGI("Scan complete: Received event type %d", evt_type); 6669a23388d5a9f58f106169700bb179de0a4af7840Ashwin if(*mHandler.on_scan_event) 6679a23388d5a9f58f106169700bb179de0a4af7840Ashwin (*mHandler.on_scan_event)(evt_type, evt_type); 6689a23388d5a9f58f106169700bb179de0a4af7840Ashwin } else { 6691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6709a23388d5a9f58f106169700bb179de0a4af7840Ashwin if (vendor_data == NULL || len != 4) { 6719a23388d5a9f58f106169700bb179de0a4af7840Ashwin ALOGI("No scan results found"); 6729a23388d5a9f58f106169700bb179de0a4af7840Ashwin return NL_SKIP; 6739a23388d5a9f58f106169700bb179de0a4af7840Ashwin } 6749a23388d5a9f58f106169700bb179de0a4af7840Ashwin 6759a23388d5a9f58f106169700bb179de0a4af7840Ashwin int num = event.get_u32(NL80211_ATTR_VENDOR_DATA); 6769a23388d5a9f58f106169700bb179de0a4af7840Ashwin ALOGI("Found %d scan results", num); 6779a23388d5a9f58f106169700bb179de0a4af7840Ashwin if(*mHandler.on_scan_results_available) 6789a23388d5a9f58f106169700bb179de0a4af7840Ashwin (*mHandler.on_scan_results_available)(id(), num); 6799a23388d5a9f58f106169700bb179de0a4af7840Ashwin } 6801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 6811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 6821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}; 6831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 684922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndeunsigned ScanCommand::mGlobalFullScanBuckets = 0; 685922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 6861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_start_gscan( 6871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_request_id id, 6881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_interface_handle iface, 6891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_cmd_params params, 6901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result_handler handler) 6911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 6921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_handle handle = getWifiHandle(iface); 6931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Starting GScan, halHandle = %p", handle); 6951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 6961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ScanCommand *cmd = new ScanCommand(iface, id, ¶ms, handler); 6971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_register_cmd(handle, id, cmd); 6981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return (wifi_error)cmd->start(); 6991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 7001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_stop_gscan(wifi_request_id id, wifi_interface_handle iface) 7021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 7031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Stopping GScan"); 7041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_handle handle = getWifiHandle(iface); 7051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 706922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if(id == -1) { 707922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result_handler handler; 708922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_cmd_params dummy_params; 709922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_handle handle = getWifiHandle(iface); 710922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde memset(&handler, 0, sizeof(handler)); 711922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 712922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ScanCommand *cmd = new ScanCommand(iface, id, &dummy_params, handler); 713922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde cmd->cancel(); 714922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde delete cmd; 715922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 716922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 717922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 718922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 7191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiCommand *cmd = wifi_unregister_cmd(handle, id); 7201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (cmd) { 7211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde cmd->cancel(); 7221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde delete cmd; 7231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 7241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 7251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_ERROR_INVALID_ARGS; 7271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 7281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 729922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 730922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndewifi_error wifi_enable_full_scan_results( 731922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_request_id id, 732922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_interface_handle iface, 733922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result_handler handler) 734922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde{ 735922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_handle handle = getWifiHandle(iface); 736922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int params_dummy; 737922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGD("Enabling full scan results, halHandle = %p", handle); 738922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 739922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, id, ¶ms_dummy, handler); 740922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_register_cmd(handle, id, cmd); 741922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 742922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return (wifi_error)cmd->start(); 743922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde} 744922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 745922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndewifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface) 746922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde{ 747922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde ALOGD("Disabling full scan results"); 748922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_handle handle = getWifiHandle(iface); 749922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 750922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if(id == -1) { 751922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_scan_result_handler handler; 752922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde wifi_handle handle = getWifiHandle(iface); 753922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde int params_dummy; 754922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 755922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde memset(&handler, 0, sizeof(handler)); 756922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, 0, ¶ms_dummy, handler); 757922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde cmd->cancel(); 758922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde delete cmd; 759922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 760922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 761922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 762922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde WifiCommand *cmd = wifi_unregister_cmd(handle, id); 763922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde if (cmd) { 764922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde cmd->cancel(); 765922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde delete cmd; 766922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_SUCCESS; 767922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde } 768922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 769922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde return WIFI_ERROR_INVALID_ARGS; 770922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde} 771922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 772922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde 7731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde///////////////////////////////////////////////////////////////////////////// 7741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass GetScanResultsCommand : public WifiCommand { 7761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result *mResults; 777e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande int mMax; 7781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int *mNum; 7791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int mRetrieved; 7801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde byte mFlush; 7811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int mCompleted; 7821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic: 7831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde GetScanResultsCommand(wifi_interface_handle iface, byte flush, 784e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande wifi_scan_result *results, int max, int *num) 785e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande : WifiCommand(iface, -1), mResults(results), mMax(max), mNum(num), 7861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde mRetrieved(0), mFlush(flush), mCompleted(0) 7871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde { } 7881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createRequest(WifiRequest& request, int num, byte flush) { 7901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_SCAN_RESULTS); 7911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 7921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 7931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 7941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 7951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 7961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num); 7971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 7981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 7991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u8(GSCAN_ATTRIBUTE_FLUSH_RESULTS, flush); 8021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 8031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 8041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 8071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 8081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int execute() { 8111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 812e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande ALOGI("retrieving %d scan results", mMax); 8131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 814e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande for (int i = 0; i < 10 && mRetrieved < mMax; i++) { 815e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande int result = createRequest(request, (mMax - mRetrieved), mFlush); 8161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 8171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to create request"); 8181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 8191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int prev_retrieved = mRetrieved; 8221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 8241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result != WIFI_SUCCESS) { 8261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("failed to retrieve scan results; result = %d", result); 8271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 8281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (mRetrieved == prev_retrieved || mCompleted) { 8311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* no more items left to retrieve */ 8321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde break; 8331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.destroy(); 8361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("GetScanResults read %d results", mRetrieved); 8391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde *mNum = mRetrieved; 8401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 8411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleResponse(WifiEvent& reply) { 8441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("In GetScanResultsCommand::handleResponse"); 8451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (reply.get_cmd() != NL80211_CMD_VENDOR) { 8471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); 8481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 8491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int id = reply.get_vendor_id(); 8521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int subcmd = reply.get_vendor_subcmd(); 8531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Id = %0x, subcmd = %d", id, subcmd); 8551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* 8571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (subcmd != GSCAN_SUBCMD_SCAN_RESULTS) { 8581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("Invalid response to GetScanResultsCommand; ignoring it"); 8591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 8601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde */ 8621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA); 8641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int len = reply.get_vendor_data_len(); 8651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (vendor_data == NULL || len == 0) { 8671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("no vendor data in GetScanResults response; ignoring it"); 8681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 8691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 8711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (nl_iterator it(vendor_data); it.has_next(); it.next()) { 8721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE) { 8731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde mCompleted = it.get_u8(); 8741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("retrieved mCompleted flag : %d", mCompleted); 8751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS || it.get_type() == 0) { 8761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) { 8771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int scan_id = 0, flags = 0, num = 0; 8781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_ID) { 8791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde scan_id = it.get_u32(); 8801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_FLAGS) { 8811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde flags = it.get_u8(); 8821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (it2.get_type() == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) { 8831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde num = it2.get_u32(); 8841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS) { 8851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde num = it2.get_len() / sizeof(wifi_scan_result); 8861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde num = min(*mNum - mRetrieved, num); 8871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memcpy(mResults + mRetrieved, it2.get_data(), 8881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde sizeof(wifi_scan_result) * num); 8891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Retrieved %d scan results", num); 8901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result *results = (wifi_scan_result *)it2.get_data(); 8911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (int i = 0; i < num; i++) { 8921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result *result = results + i; 89309f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde ALOGI("%02d %-32s %02x:%02x:%02x:%02x:%02x:%02x %04d", i, 8941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result->ssid, result->bssid[0], result->bssid[1], result->bssid[2], 89509f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde result->bssid[3], result->bssid[4], result->bssid[5], 89609f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde result->rssi); 8971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 8981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde mRetrieved += num; 8991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else { 9001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGW("Ignoring invalid attribute type = %d, size = %d", 9011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde it.get_type(), it.get_len()); 9021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 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 9101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_OK; 9111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}; 9131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface, byte flush, 915e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande int max, wifi_scan_result *results, int *num) { 9161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("Getting cached scan results, iface handle = %p, num = %d", iface, *num); 9181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 919e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande GetScanResultsCommand *cmd = new GetScanResultsCommand(iface, flush, results, max, num); 9201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return (wifi_error)cmd->execute(); 9211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 9221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde///////////////////////////////////////////////////////////////////////////// 9241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass BssidHotlistCommand : public WifiCommand 9261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 9271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeprivate: 9281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_bssid_hotlist_params mParams; 9291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_hotlist_ap_found_handler mHandler; 9301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde static const int MAX_RESULTS = 64; 9311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_scan_result mResults[MAX_RESULTS]; 9321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic: 9331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde BssidHotlistCommand(wifi_interface_handle handle, int id, 9341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler) 9351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde : WifiCommand(handle, id), mParams(params), mHandler(handler) 9361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde { } 9371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createSetupRequest(WifiRequest& request) { 9391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST); 9401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 9451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1); 9461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS); 951e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande for (int i = 0; i < mParams.num_ap; i++) { 9521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *attr2 = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM); 9531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (attr2 == NULL) { 9541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_ERROR_OUT_OF_MEMORY; 9551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 956e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid); 9571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 960e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high); 9611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 964e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low); 9651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(attr2); 9691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(attr); 9721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 9731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createTeardownRequest(WifiRequest& request) { 9771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST); 9781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 9831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1); 9841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS); 9891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(attr); 9901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 9911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 9921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 9931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 9941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int start() { 995e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande ALOGI("Executing hotlist setup request, num = %d", mParams.num_ap); 9961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 9971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = createSetupRequest(request); 9981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 9991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 10031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 10041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Failed to execute hotlist setup request, result = %d", result); 10051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS); 10061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1009e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande ALOGI("Successfully set %d APs in the hotlist", mParams.num_ap); 10101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1); 10111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 10121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS); 10161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 10181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 10191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS); 10201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("successfully restarted the scan"); 10241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int cancel() { 10281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* unregister event handler */ 10291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS); 10301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* create set hotlist message with empty hotlist */ 10321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 10331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = createTeardownRequest(request); 10341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 10351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 10391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 10401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Successfully reset APs in current hotlist"); 10441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 10451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleResponse(WifiEvent& reply) { 10481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* Nothing to do on response! */ 10491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 10501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleEvent(WifiEvent& event) { 10531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Got a hotlist ap found event"); 10541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 105509f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde // event.log(); 10561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 10581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int len = event.get_vendor_data_len(); 10591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (vendor_data == NULL || len == 0) { 10611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("No scan results found"); 10621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 10631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memset(mResults, 0, sizeof(wifi_scan_result) * MAX_RESULTS); 10661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int num = len / sizeof(wifi_scan_result); 10681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde num = min(MAX_RESULTS, num); 10691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memcpy(mResults, event.get_vendor_data(), num * sizeof(wifi_scan_result)); 10701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Retrieved %d hot APs", num); 10711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde (*mHandler.on_hotlist_ap_found)(id(), num, mResults); 10731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 10741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}; 10761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_set_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface, 10781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler) 10791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 10801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_handle handle = getWifiHandle(iface); 10811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde BssidHotlistCommand *cmd = new BssidHotlistCommand(iface, id, params, handler); 10831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_register_cmd(handle, id, cmd); 10841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return (wifi_error)cmd->start(); 10851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 10861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_reset_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface) 10881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 10891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_handle handle = getWifiHandle(iface); 10901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiCommand *cmd = wifi_unregister_cmd(handle, id); 10921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (cmd) { 10931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde cmd->cancel(); 10941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde delete cmd; 10951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 10961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 10971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 10981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_ERROR_INVALID_ARGS; 10991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 11001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde///////////////////////////////////////////////////////////////////////////// 11031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass SignificantWifiChangeCommand : public WifiCommand 11051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 1106e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande typedef struct { 1107e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande mac_addr bssid; // BSSID 1108e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande wifi_channel channel; // channel frequency in MHz 1109e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande int num_rssi; // number of rssi samples 1110e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande wifi_rssi rssi[8]; // RSSI history in db 1111e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande } wifi_significant_change_result_internal; 1112e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande 11131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeprivate: 11141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_significant_change_params mParams; 11151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_significant_change_handler mHandler; 11161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde static const int MAX_RESULTS = 64; 1117e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande wifi_significant_change_result_internal mResultsBuffer[MAX_RESULTS]; 1118e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande wifi_significant_change_result *mResults[MAX_RESULTS]; 11191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic: 11201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde SignificantWifiChangeCommand(wifi_interface_handle handle, int id, 11211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_significant_change_params params, wifi_significant_change_handler handler) 11221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde : WifiCommand(handle, id), mParams(params), mHandler(handler) 11231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde { } 11241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createSetupRequest(WifiRequest& request) { 11261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG); 11271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 11321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u8(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1); 11331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE, mParams.rssi_sample_size); 11371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size); 11411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING, mParams.min_breaching); 11451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS); 11501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1151e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande for (int i = 0; i < mParams.num_ap; i++) { 11521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *attr2 = request.attr_start(i); 11541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (attr2 == NULL) { 11551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_ERROR_OUT_OF_MEMORY; 11561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1157e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid); 11581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1161e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high); 11621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1165e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low); 11661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(attr2); 11701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(attr); 11731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 11741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int createTeardownRequest(WifiRequest& request) { 11791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG); 11801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 11851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = request.put_u16(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1); 11861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 11871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde request.attr_end(data); 11911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 11921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 11931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int start() { 11951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Set significant wifi change config"); 11961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 11971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 11981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = createSetupRequest(request); 11991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 12001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 12011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 12041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 12051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("failed to set significant wifi change config %d", result); 12061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 12071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("successfully set significant wifi change config"); 12101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1); 12121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 12131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 12141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); 12171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 12191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 12201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); 12211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 12221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("successfully restarted the scan"); 12251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 12261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int cancel() { 12291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* unregister event handler */ 12301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); 12311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* create set significant change monitor message with empty hotlist */ 12331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiRequest request(familyId(), ifaceId()); 12341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int result = createTeardownRequest(request); 12361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 12371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 12381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde result = requestResponse(request); 12411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (result < 0) { 12421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 12431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("successfully reset significant wifi change config"); 12461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return result; 12471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleResponse(WifiEvent& reply) { 12501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* Nothing to do on response! */ 12511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 12521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde virtual int handleEvent(WifiEvent& event) { 12551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Got a significant wifi change event"); 12561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 12581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int len = event.get_vendor_data_len(); 12591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (vendor_data == NULL || len == 0) { 12611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("No scan results found"); 12621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 12631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde typedef struct { 12661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde uint16_t flags; 12671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde uint16_t channel; 12681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde mac_addr bssid; 12699a23388d5a9f58f106169700bb179de0a4af7840Ashwin s8 rssi_history[8]; 12701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } ChangeInfo; 12711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int num = min(len / sizeof(ChangeInfo), MAX_RESULTS); 12731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ChangeInfo *ci = (ChangeInfo *)event.get_vendor_data(); 12741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (int i = 0; i < num; i++) { 1276e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande memcpy(mResultsBuffer[i].bssid, ci[i].bssid, sizeof(mac_addr)); 1277e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande mResultsBuffer[i].channel = ci[i].channel; 1278e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande mResultsBuffer[i].num_rssi = 8; 12799a23388d5a9f58f106169700bb179de0a4af7840Ashwin for (int j = 0; j < mResultsBuffer[i].num_rssi; j++) 12809a23388d5a9f58f106169700bb179de0a4af7840Ashwin mResultsBuffer[i].rssi[j] = (int) ci[i].rssi_history[j]; 1281e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande mResults[i] = reinterpret_cast<wifi_significant_change_result *>(&(mResultsBuffer[i])); 12821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGI("Retrieved %d scan results", num); 12851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (num != 0) { 12871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde (*mHandler.on_significant_change)(id(), num, mResults); 12881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } else { 12891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGW("No significant change reported"); 12901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return NL_SKIP; 12931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 12941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}; 12951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 12961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_set_significant_change_handler(wifi_request_id id, wifi_interface_handle iface, 12971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_significant_change_params params, wifi_significant_change_handler handler) 12981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 12991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_handle handle = getWifiHandle(iface); 13001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 13011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde SignificantWifiChangeCommand *cmd = new SignificantWifiChangeCommand( 13021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde iface, id, params, handler); 13031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_register_cmd(handle, id, cmd); 13041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return (wifi_error)cmd->start(); 13051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 13061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 13071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface) 13081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 13091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde wifi_handle handle = getWifiHandle(iface); 13101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 13111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde WifiCommand *cmd = wifi_unregister_cmd(handle, id); 13121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (cmd) { 13131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde cmd->cancel(); 13141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde delete cmd; 13151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_SUCCESS; 13161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 13171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 13181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return WIFI_ERROR_INVALID_ARGS; 13191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 1320