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
371bd06406dceb430cca32ae2aa195fbf37b10d58b0Vinit Deshpande        // 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        result = requestResponse(request);
6121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result != WIFI_SUCCESS) {
6131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGE("failed to start scan; result = %d", result);
614082cb621b1dd1ad150a747d5010fed0888ae416cVinit Deshpande            registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
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
637082cb621b1dd1ad150a747d5010fed0888ae416cVinit Deshpande        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
6381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
639922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        disableFullScanResultsIfRequired();
640922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
6411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return WIFI_SUCCESS;
6421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
6431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
6441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int handleResponse(WifiEvent& reply) {
6451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        /* Nothing to do on response! */
6461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return NL_SKIP;
6471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
6481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
6491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int handleEvent(WifiEvent& event) {
6501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGI("Got a scan results event");
6511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
65209f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde        // event.log();
6531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
6541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
6551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int len = event.get_vendor_data_len();
6569a23388d5a9f58f106169700bb179de0a4af7840Ashwin        int event_id = event.get_vendor_subcmd();
6571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
6589a23388d5a9f58f106169700bb179de0a4af7840Ashwin        if(event_id == GSCAN_EVENT_COMPLETE_SCAN) {
6599a23388d5a9f58f106169700bb179de0a4af7840Ashwin            if (vendor_data == NULL || len != 4) {
6609a23388d5a9f58f106169700bb179de0a4af7840Ashwin                ALOGI("Scan complete type not mentioned!");
6619a23388d5a9f58f106169700bb179de0a4af7840Ashwin                return NL_SKIP;
6629a23388d5a9f58f106169700bb179de0a4af7840Ashwin            }
6639a23388d5a9f58f106169700bb179de0a4af7840Ashwin            wifi_scan_event evt_type;
6649a23388d5a9f58f106169700bb179de0a4af7840Ashwin
6659a23388d5a9f58f106169700bb179de0a4af7840Ashwin            evt_type = (wifi_scan_event) event.get_u32(NL80211_ATTR_VENDOR_DATA);
6669a23388d5a9f58f106169700bb179de0a4af7840Ashwin            ALOGI("Scan complete: Received event type %d", evt_type);
6679a23388d5a9f58f106169700bb179de0a4af7840Ashwin            if(*mHandler.on_scan_event)
6689a23388d5a9f58f106169700bb179de0a4af7840Ashwin                (*mHandler.on_scan_event)(evt_type, evt_type);
6699a23388d5a9f58f106169700bb179de0a4af7840Ashwin        } else {
6701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
6719a23388d5a9f58f106169700bb179de0a4af7840Ashwin            if (vendor_data == NULL || len != 4) {
6729a23388d5a9f58f106169700bb179de0a4af7840Ashwin                ALOGI("No scan results found");
6739a23388d5a9f58f106169700bb179de0a4af7840Ashwin                return NL_SKIP;
6749a23388d5a9f58f106169700bb179de0a4af7840Ashwin            }
6759a23388d5a9f58f106169700bb179de0a4af7840Ashwin
6769a23388d5a9f58f106169700bb179de0a4af7840Ashwin            int num = event.get_u32(NL80211_ATTR_VENDOR_DATA);
6779a23388d5a9f58f106169700bb179de0a4af7840Ashwin            ALOGI("Found %d scan results", num);
6789a23388d5a9f58f106169700bb179de0a4af7840Ashwin            if(*mHandler.on_scan_results_available)
6799a23388d5a9f58f106169700bb179de0a4af7840Ashwin                (*mHandler.on_scan_results_available)(id(), num);
6809a23388d5a9f58f106169700bb179de0a4af7840Ashwin        }
6811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return NL_SKIP;
6821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
6831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde};
6841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
685922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndeunsigned ScanCommand::mGlobalFullScanBuckets = 0;
686922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
6871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_start_gscan(
6881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        wifi_request_id id,
6891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        wifi_interface_handle iface,
6901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        wifi_scan_cmd_params params,
6911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        wifi_scan_result_handler handler)
6921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
6931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_handle handle = getWifiHandle(iface);
6941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
6951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    ALOGD("Starting GScan, halHandle = %p", handle);
6961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
6971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    ScanCommand *cmd = new ScanCommand(iface, id, &params, handler);
6981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_register_cmd(handle, id, cmd);
6991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    return (wifi_error)cmd->start();
7001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
7011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
7021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_stop_gscan(wifi_request_id id, wifi_interface_handle iface)
7031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
7041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    ALOGD("Stopping GScan");
7051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_handle handle = getWifiHandle(iface);
7061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
707922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    if(id == -1) {
708922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        wifi_scan_result_handler handler;
709922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        wifi_scan_cmd_params dummy_params;
710922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        wifi_handle handle = getWifiHandle(iface);
711922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        memset(&handler, 0, sizeof(handler));
712922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
713922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        ScanCommand *cmd = new ScanCommand(iface, id, &dummy_params, handler);
714922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        cmd->cancel();
71528237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande        cmd->releaseRef();
716922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        return WIFI_SUCCESS;
717922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    }
718922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
719922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
7201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    WifiCommand *cmd = wifi_unregister_cmd(handle, id);
7211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (cmd) {
7221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        cmd->cancel();
72328237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande        cmd->releaseRef();
7241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return WIFI_SUCCESS;
7251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
7261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
7271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    return WIFI_ERROR_INVALID_ARGS;
7281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
7291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
730922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
731922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndewifi_error wifi_enable_full_scan_results(
732922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        wifi_request_id id,
733922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        wifi_interface_handle iface,
734922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        wifi_scan_result_handler handler)
735922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde{
736922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    wifi_handle handle = getWifiHandle(iface);
737922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    int params_dummy;
738922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    ALOGD("Enabling full scan results, halHandle = %p", handle);
739922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
740922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, id, &params_dummy, handler);
741922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    wifi_register_cmd(handle, id, cmd);
742922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
743922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    return (wifi_error)cmd->start();
744922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde}
745922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
746922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndewifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface)
747922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde{
748922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    ALOGD("Disabling full scan results");
749922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    wifi_handle handle = getWifiHandle(iface);
750922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
751922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    if(id == -1) {
752922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        wifi_scan_result_handler handler;
753922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        wifi_handle handle = getWifiHandle(iface);
754922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        int params_dummy;
755922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
756922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        memset(&handler, 0, sizeof(handler));
757922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, 0, &params_dummy, handler);
758922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        cmd->cancel();
75928237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande        cmd->releaseRef();
760922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        return WIFI_SUCCESS;
761922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    }
762922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
763922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    WifiCommand *cmd = wifi_unregister_cmd(handle, id);
764922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    if (cmd) {
765922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        cmd->cancel();
76628237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande        cmd->releaseRef();
767922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        return WIFI_SUCCESS;
768922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    }
769922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
770922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    return WIFI_ERROR_INVALID_ARGS;
771922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde}
772922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
773922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
7741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde/////////////////////////////////////////////////////////////////////////////
7751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
7761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass GetScanResultsCommand : public WifiCommand {
7771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_scan_result *mResults;
778e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande    int mMax;
7791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int *mNum;
7801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int mRetrieved;
7811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    byte mFlush;
7821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int mCompleted;
7831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic:
7841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GetScanResultsCommand(wifi_interface_handle iface, byte flush,
785e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande            wifi_scan_result *results, int max, int *num)
786e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande        : WifiCommand(iface, -1), mResults(results), mMax(max), mNum(num),
7871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                mRetrieved(0), mFlush(flush), mCompleted(0)
7881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    { }
7891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
7901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int createRequest(WifiRequest& request, int num, byte flush) {
7911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_SCAN_RESULTS);
7921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
7931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
7941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
7951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
7961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
7971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = request.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num);
7981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
7991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
8001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
8011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = request.put_u8(GSCAN_ATTRIBUTE_FLUSH_RESULTS, flush);
8031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
8041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
8051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
8061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        request.attr_end(data);
8081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return WIFI_SUCCESS;
8091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
8101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int execute() {
8121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        WifiRequest request(familyId(), ifaceId());
813e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande        ALOGI("retrieving %d scan results", mMax);
8141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
815e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande        for (int i = 0; i < 10 && mRetrieved < mMax; i++) {
816e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande            int result = createRequest(request, (mMax - mRetrieved), mFlush);
8171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (result < 0) {
8181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                ALOGE("failed to create request");
8191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                return result;
8201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
8211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            int prev_retrieved = mRetrieved;
8231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            result = requestResponse(request);
8251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (result != WIFI_SUCCESS) {
8271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                ALOGE("failed to retrieve scan results; result = %d", result);
8281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                return result;
8291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
8301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (mRetrieved == prev_retrieved || mCompleted) {
8321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                /* no more items left to retrieve */
8331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                break;
8341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
8351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            request.destroy();
8371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
8381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGE("GetScanResults read %d results", mRetrieved);
8401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        *mNum = mRetrieved;
8411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return WIFI_SUCCESS;
8421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
8431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int handleResponse(WifiEvent& reply) {
8451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGD("In GetScanResultsCommand::handleResponse");
8461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
8481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
8491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return NL_SKIP;
8501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
8511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int id = reply.get_vendor_id();
8531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int subcmd = reply.get_vendor_subcmd();
8541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGD("Id = %0x, subcmd = %d", id, subcmd);
8561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        /*
8581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (subcmd != GSCAN_SUBCMD_SCAN_RESULTS) {
8591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGE("Invalid response to GetScanResultsCommand; ignoring it");
8601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return NL_SKIP;
8611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
8621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        */
8631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
8651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int len = reply.get_vendor_data_len();
8661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (vendor_data == NULL || len == 0) {
8681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGE("no vendor data in GetScanResults response; ignoring it");
8691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return NL_SKIP;
8701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
8711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
8731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE) {
8741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                mCompleted = it.get_u8();
8751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                ALOGI("retrieved mCompleted flag : %d", mCompleted);
8761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            } else if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS || it.get_type() == 0) {
8771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) {
8781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                    int scan_id = 0, flags = 0, num = 0;
8791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                    if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_ID) {
8801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                        scan_id = it.get_u32();
8811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                    } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_FLAGS) {
8821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                        flags = it.get_u8();
8831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                    } else if (it2.get_type() == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) {
8841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                        num = it2.get_u32();
8851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                    } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS) {
8861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                        num = it2.get_len() / sizeof(wifi_scan_result);
8871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                        num = min(*mNum - mRetrieved, num);
8881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                        memcpy(mResults + mRetrieved, it2.get_data(),
8891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                                sizeof(wifi_scan_result) * num);
8901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                        ALOGI("Retrieved %d scan results", num);
8911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                        wifi_scan_result *results = (wifi_scan_result *)it2.get_data();
8921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                        for (int i = 0; i < num; i++) {
8931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                            wifi_scan_result *result = results + i;
89409f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde                            ALOGI("%02d  %-32s  %02x:%02x:%02x:%02x:%02x:%02x  %04d", i,
8951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                                result->ssid, result->bssid[0], result->bssid[1], result->bssid[2],
89609f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde                                result->bssid[3], result->bssid[4], result->bssid[5],
89709f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde                                result->rssi);
8981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                        }
8991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                        mRetrieved += num;
9001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                    } else {
9011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                        ALOGW("Ignoring invalid attribute type = %d, size = %d",
9021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                                it.get_type(), it.get_len());
9031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                    }
9041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                }
9051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            } else {
9061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                ALOGW("Ignoring invalid attribute type = %d, size = %d",
9071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                        it.get_type(), it.get_len());
9081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
9091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
9101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
9111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return NL_OK;
9121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
9131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde};
9141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
9151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface, byte flush,
916e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande        int max, wifi_scan_result *results, int *num) {
9171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
9181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    ALOGD("Getting cached scan results, iface handle = %p, num = %d", iface, *num);
9191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
920e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande    GetScanResultsCommand *cmd = new GetScanResultsCommand(iface, flush, results, max, num);
9211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    return (wifi_error)cmd->execute();
9221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
9231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
9241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde/////////////////////////////////////////////////////////////////////////////
9251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
9261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass BssidHotlistCommand : public WifiCommand
9271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
9281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeprivate:
9291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_bssid_hotlist_params mParams;
9301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_hotlist_ap_found_handler mHandler;
9311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    static const int MAX_RESULTS = 64;
9321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_scan_result mResults[MAX_RESULTS];
9331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic:
9341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    BssidHotlistCommand(wifi_interface_handle handle, int id,
9351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler)
9361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        : WifiCommand(handle, id), mParams(params), mHandler(handler)
9371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    { }
9381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
9391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int createSetupRequest(WifiRequest& request) {
9401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST);
9411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
9421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
9431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
9441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
9451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
9461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1);
9471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
9481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
9491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
9501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
951f0d5070a931327e6356d765478069b9e66452a5bAshwin        result = request.put_u32(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size);
952f0d5070a931327e6356d765478069b9e66452a5bAshwin        if (result < 0) {
953f0d5070a931327e6356d765478069b9e66452a5bAshwin            return result;
954f0d5070a931327e6356d765478069b9e66452a5bAshwin        }
955f0d5070a931327e6356d765478069b9e66452a5bAshwin
9561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS);
957e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande        for (int i = 0; i < mParams.num_ap; i++) {
9581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            nlattr *attr2 = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM);
9591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (attr2 == NULL) {
9601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                return WIFI_ERROR_OUT_OF_MEMORY;
9611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
962e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande            result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid);
9631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (result < 0) {
9641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                return result;
9651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
966e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande            result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high);
9671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (result < 0) {
9681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                return result;
9691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
970e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande            result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low);
9711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (result < 0) {
9721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                return result;
9731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
9741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            request.attr_end(attr2);
9751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
9761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
9771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        request.attr_end(attr);
9781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        request.attr_end(data);
9791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return result;
9801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
9811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
9821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int createTeardownRequest(WifiRequest& request) {
9831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST);
9841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
9851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
9861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
9871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
9881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
9891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1);
9901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
9911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
9921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
9931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
9941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS);
9951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        request.attr_end(attr);
9961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        request.attr_end(data);
9971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return result;
9981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
9991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int start() {
1001e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande        ALOGI("Executing hotlist setup request, num = %d", mParams.num_ap);
10021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        WifiRequest request(familyId(), ifaceId());
10031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = createSetupRequest(request);
10041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
10051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
10061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
10071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = requestResponse(request);
10091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
10101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGI("Failed to execute hotlist setup request, result = %d", result);
1011f0d5070a931327e6356d765478069b9e66452a5bAshwin            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
1012f0d5070a931327e6356d765478069b9e66452a5bAshwin            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
10131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
10141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
10151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
1016e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande        ALOGI("Successfully set %d APs in the hotlist", mParams.num_ap);
10171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
10181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
10191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
10201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
10211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
1022f0d5070a931327e6356d765478069b9e66452a5bAshwin        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
1023f0d5070a931327e6356d765478069b9e66452a5bAshwin        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
10241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = requestResponse(request);
10261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
1027f0d5070a931327e6356d765478069b9e66452a5bAshwin            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
1028f0d5070a931327e6356d765478069b9e66452a5bAshwin            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
10291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
10301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
10311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGI("successfully restarted the scan");
10331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return result;
10341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
10351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int cancel() {
10371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        /* unregister event handler */
1038f0d5070a931327e6356d765478069b9e66452a5bAshwin        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
1039f0d5070a931327e6356d765478069b9e66452a5bAshwin        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
10401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        /* create set hotlist message with empty hotlist */
10411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        WifiRequest request(familyId(), ifaceId());
10421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = createTeardownRequest(request);
10431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
10441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
10451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
10461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = requestResponse(request);
10481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
10491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
10501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
10511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGI("Successfully reset APs in current hotlist");
10531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return result;
10541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
10551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int handleResponse(WifiEvent& reply) {
10571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        /* Nothing to do on response! */
10581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return NL_SKIP;
10591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
10601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int handleEvent(WifiEvent& event) {
1062f0d5070a931327e6356d765478069b9e66452a5bAshwin        ALOGI("Hotlist AP event");
1063f0d5070a931327e6356d765478069b9e66452a5bAshwin        int event_id = event.get_vendor_subcmd();
106409f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde        // event.log();
10651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
10671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int len = event.get_vendor_data_len();
10681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (vendor_data == NULL || len == 0) {
10701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGI("No scan results found");
10711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return NL_SKIP;
10721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
10731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        memset(mResults, 0, sizeof(wifi_scan_result) * MAX_RESULTS);
10751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int num = len / sizeof(wifi_scan_result);
10771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        num = min(MAX_RESULTS, num);
10781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        memcpy(mResults, event.get_vendor_data(), num * sizeof(wifi_scan_result));
10791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
1080f0d5070a931327e6356d765478069b9e66452a5bAshwin        if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_FOUND) {
1081f0d5070a931327e6356d765478069b9e66452a5bAshwin            ALOGI("FOUND %d hotlist APs", num);
1082f0d5070a931327e6356d765478069b9e66452a5bAshwin            if (*mHandler.on_hotlist_ap_found)
1083f0d5070a931327e6356d765478069b9e66452a5bAshwin                (*mHandler.on_hotlist_ap_found)(id(), num, mResults);
1084f0d5070a931327e6356d765478069b9e66452a5bAshwin        } else if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_LOST) {
1085f0d5070a931327e6356d765478069b9e66452a5bAshwin            ALOGI("LOST %d hotlist APs", num);
1086f0d5070a931327e6356d765478069b9e66452a5bAshwin            if (*mHandler.on_hotlist_ap_lost)
1087f0d5070a931327e6356d765478069b9e66452a5bAshwin                (*mHandler.on_hotlist_ap_lost)(id(), num, mResults);
1088f0d5070a931327e6356d765478069b9e66452a5bAshwin        }
10891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return NL_SKIP;
10901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
10911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde};
10921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_set_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface,
10941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler)
10951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
10961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_handle handle = getWifiHandle(iface);
10971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    BssidHotlistCommand *cmd = new BssidHotlistCommand(iface, id, params, handler);
10991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_register_cmd(handle, id, cmd);
11001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    return (wifi_error)cmd->start();
11011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
11021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_reset_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface)
11041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
11051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_handle handle = getWifiHandle(iface);
11061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    WifiCommand *cmd = wifi_unregister_cmd(handle, id);
11081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (cmd) {
11091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        cmd->cancel();
111028237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande        cmd->releaseRef();
11111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return WIFI_SUCCESS;
11121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
11131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    return WIFI_ERROR_INVALID_ARGS;
11151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
11161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde/////////////////////////////////////////////////////////////////////////////
11191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass SignificantWifiChangeCommand : public WifiCommand
11211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
1122e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande    typedef struct {
1123e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande        mac_addr bssid;                     // BSSID
1124e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande        wifi_channel channel;               // channel frequency in MHz
1125e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande        int num_rssi;                       // number of rssi samples
1126e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande        wifi_rssi rssi[8];                   // RSSI history in db
1127e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande    } wifi_significant_change_result_internal;
1128e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande
11291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeprivate:
11301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_significant_change_params mParams;
11311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_significant_change_handler mHandler;
11321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    static const int MAX_RESULTS = 64;
1133e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande    wifi_significant_change_result_internal mResultsBuffer[MAX_RESULTS];
1134e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande    wifi_significant_change_result *mResults[MAX_RESULTS];
11351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic:
11361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    SignificantWifiChangeCommand(wifi_interface_handle handle, int id,
11371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            wifi_significant_change_params params, wifi_significant_change_handler handler)
11381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        : WifiCommand(handle, id), mParams(params), mHandler(handler)
11391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    { }
11401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int createSetupRequest(WifiRequest& request) {
11421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG);
11431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
11441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
11451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
11461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
11481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = request.put_u8(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1);
11491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
11501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
11511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
11521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = request.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE, mParams.rssi_sample_size);
11531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
11541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
11551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
11561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = request.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size);
11571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
11581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
11591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
11601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = request.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING, mParams.min_breaching);
11611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
11621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
11631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
11641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS);
11661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
1167e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande        for (int i = 0; i < mParams.num_ap; i++) {
11681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            nlattr *attr2 = request.attr_start(i);
11701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (attr2 == NULL) {
11711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                return WIFI_ERROR_OUT_OF_MEMORY;
11721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
1173e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande            result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid);
11741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (result < 0) {
11751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                return result;
11761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
1177e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande            result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high);
11781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (result < 0) {
11791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                return result;
11801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
1181e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande            result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low);
11821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (result < 0) {
11831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                return result;
11841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
11851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            request.attr_end(attr2);
11861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
11871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        request.attr_end(attr);
11891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        request.attr_end(data);
11901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return result;
11921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
11931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int createTeardownRequest(WifiRequest& request) {
11951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG);
11961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
11971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
11981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
11991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
12011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = request.put_u16(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1);
12021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
12031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
12041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
12051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        request.attr_end(data);
12071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return result;
12081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
12091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int start() {
12111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGI("Set significant wifi change config");
12121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        WifiRequest request(familyId(), ifaceId());
12131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = createSetupRequest(request);
12151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
12161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
12171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
12181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = requestResponse(request);
12201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
12211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGI("failed to set significant wifi change config %d", result);
12221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
12231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
12241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGI("successfully set significant wifi change config");
12261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
12281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
12291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
12301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
12311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
12331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = requestResponse(request);
12351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
12361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
12371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
12381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
12391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGI("successfully restarted the scan");
12411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return result;
12421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
12431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int cancel() {
12451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        /* unregister event handler */
12461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
12471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        /* create set significant change monitor message with empty hotlist */
12491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        WifiRequest request(familyId(), ifaceId());
12501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = createTeardownRequest(request);
12521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
12531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
12541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
12551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = requestResponse(request);
12571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
12581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
12591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
12601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGI("successfully reset significant wifi change config");
12621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return result;
12631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
12641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int handleResponse(WifiEvent& reply) {
12661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        /* Nothing to do on response! */
12671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return NL_SKIP;
12681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
12691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int handleEvent(WifiEvent& event) {
12711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGI("Got a significant wifi change event");
12721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
12741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int len = event.get_vendor_data_len();
12751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (vendor_data == NULL || len == 0) {
12771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGI("No scan results found");
12781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return NL_SKIP;
12791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
12801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        typedef struct {
12821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            uint16_t flags;
12831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            uint16_t channel;
12841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            mac_addr bssid;
12859a23388d5a9f58f106169700bb179de0a4af7840Ashwin            s8 rssi_history[8];
12861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        } ChangeInfo;
12871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int num = min(len / sizeof(ChangeInfo), MAX_RESULTS);
12891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ChangeInfo *ci = (ChangeInfo *)event.get_vendor_data();
12901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
12911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        for (int i = 0; i < num; i++) {
1292e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande            memcpy(mResultsBuffer[i].bssid, ci[i].bssid, sizeof(mac_addr));
1293e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande            mResultsBuffer[i].channel = ci[i].channel;
1294e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande            mResultsBuffer[i].num_rssi = 8;
12959a23388d5a9f58f106169700bb179de0a4af7840Ashwin            for (int j = 0; j < mResultsBuffer[i].num_rssi; j++)
12969a23388d5a9f58f106169700bb179de0a4af7840Ashwin                mResultsBuffer[i].rssi[j] = (int) ci[i].rssi_history[j];
1297e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande            mResults[i] = reinterpret_cast<wifi_significant_change_result *>(&(mResultsBuffer[i]));
12981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
12991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
13001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGI("Retrieved %d scan results", num);
13011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
13021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (num != 0) {
13031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            (*mHandler.on_significant_change)(id(), num, mResults);
13041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        } else {
13051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGW("No significant change reported");
13061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
13071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
13081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return NL_SKIP;
13091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
13101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde};
13111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
13121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_set_significant_change_handler(wifi_request_id id, wifi_interface_handle iface,
13131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        wifi_significant_change_params params, wifi_significant_change_handler handler)
13141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
13151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_handle handle = getWifiHandle(iface);
13161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
13171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    SignificantWifiChangeCommand *cmd = new SignificantWifiChangeCommand(
13181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            iface, id, params, handler);
13191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_register_cmd(handle, id, cmd);
13201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    return (wifi_error)cmd->start();
13211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
13221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
13231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface)
13241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
13251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_handle handle = getWifiHandle(iface);
13261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
13271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    WifiCommand *cmd = wifi_unregister_cmd(handle, id);
13281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (cmd) {
13291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        cmd->cancel();
133028237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande        cmd->releaseRef();
13311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return WIFI_SUCCESS;
13321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
13331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
13341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    return WIFI_ERROR_INVALID_ARGS;
13351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
1336