1cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song/*
2cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * Copyright (C) 2017 The Android Open Source Project
3cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song *
4cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * Portions copyright (C) 2017 Broadcom Limited
5cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song *
6cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * Licensed under the Apache License, Version 2.0 (the "License");
7cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * you may not use this file except in compliance with the License.
8cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * You may obtain a copy of the License at
9cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song *
10cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song *     http://www.apache.org/licenses/LICENSE-2.0
11cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song *
12cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * Unless required by applicable law or agreed to in writing, software
13cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * distributed under the License is distributed on an "AS IS" BASIS,
14cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * See the License for the specific language governing permissions and
16cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * limitations under the License.
17cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song */
181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <stdint.h>
201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <fcntl.h>
211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <sys/socket.h>
221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netlink/genl/genl.h>
231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netlink/genl/family.h>
241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netlink/genl/ctrl.h>
251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <linux/rtnetlink.h>
261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netpacket/packet.h>
271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <linux/filter.h>
281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <linux/errqueue.h>
291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <linux/pkt_sched.h>
311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netlink/object-api.h>
321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netlink/netlink.h>
331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netlink/socket.h>
34642bfbe829f5438db3d99ce4678bcb770359a632Vinit Deshpande#include <netlink/handlers.h>
351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include "sync.h"
371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#define LOG_TAG  "WifiHAL"
39de1c9aa3d3ac645f09507d1ff500fc4dc018624dKevin Cernekee//#define LOG_NDEBUG 0         //uncomment to enable verbose logging
401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
41f05bfb019590f8e25471c0fae23db519dfcfb790Pierre Couillaud#include <log/log.h>
421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include "wifi_hal.h"
441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include "common.h"
451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include "cpp_bindings.h"
461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndetypedef enum {
481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_NUM_BUCKETS = 10,
501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_BASE_PERIOD,
51922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    GSCAN_ATTRIBUTE_BUCKETS_BAND,
521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_BUCKET_ID,
531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_BUCKET_PERIOD,
541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS,
551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_BUCKET_CHANNELS,
561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN,
571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_REPORT_THRESHOLD,
581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE,
5927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin    GSCAN_ATTRIBUTE_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND,
601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20,
621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE,              /* indicates no more results */
631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_FLUSH_FEATURE,                      /* Flush all the configs */
64922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    GSCAN_ENABLE_FULL_SCAN_RESULTS,
65922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    GSCAN_ATTRIBUTE_REPORT_EVENTS,
661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    /* remaining reserved for additional attributes */
681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30,
691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_FLUSH_RESULTS,
701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_SCAN_RESULTS,                       /* flat array of wifi_scan_result */
711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_SCAN_ID,                            /* indicates scan number */
721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_SCAN_FLAGS,                         /* indicates if scan was aborted */
731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_AP_FLAGS,                           /* flags on significant change event */
7427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin    GSCAN_ATTRIBUTE_NUM_CHANNELS,
7527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin    GSCAN_ATTRIBUTE_CHANNEL_LIST,
762b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK,
771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    /* remaining reserved for additional attributes */
781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_SSID = 40,
801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_BSSID,
811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_CHANNEL,
821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_RSSI,
831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_TIMESTAMP,
841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_RTT,
851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_RTTSD,
861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    /* remaining reserved for additional attributes */
881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50,
901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_RSSI_LOW,
911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_RSSI_HIGH,
921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_HOTLIST_ELEM,
931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_HOTLIST_FLUSH,
9466d82546960bb2408e1aa31856a3f9a6a400681fInsun Song    GSCAN_ATTRIBUTE_HOTLIST_BSSID_COUNT,
951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    /* remaining reserved for additional attributes */
971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60,
981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE,
991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_MIN_BREACHING,
1001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS,
1011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH,
1021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10389a9a4cffbcee6af504c61ff575a008194070c82Ashwin    /* EPNO */
10489a9a4cffbcee6af504c61ff575a008194070c82Ashwin    GSCAN_ATTRIBUTE_EPNO_SSID_LIST = 70,
10589a9a4cffbcee6af504c61ff575a008194070c82Ashwin    GSCAN_ATTRIBUTE_EPNO_SSID,
10689a9a4cffbcee6af504c61ff575a008194070c82Ashwin    GSCAN_ATTRIBUTE_EPNO_SSID_LEN,
10789a9a4cffbcee6af504c61ff575a008194070c82Ashwin    GSCAN_ATTRIBUTE_EPNO_RSSI,
10889a9a4cffbcee6af504c61ff575a008194070c82Ashwin    GSCAN_ATTRIBUTE_EPNO_FLAGS,
10989a9a4cffbcee6af504c61ff575a008194070c82Ashwin    GSCAN_ATTRIBUTE_EPNO_AUTH,
11089a9a4cffbcee6af504c61ff575a008194070c82Ashwin    GSCAN_ATTRIBUTE_EPNO_SSID_NUM,
11189a9a4cffbcee6af504c61ff575a008194070c82Ashwin    GSCAN_ATTRIBUTE_EPNO_FLUSH,
11289a9a4cffbcee6af504c61ff575a008194070c82Ashwin
113810c949db9c60baa02684a50d71026727c357cd2Ashwin    /* remaining reserved for additional attributes */
114810c949db9c60baa02684a50d71026727c357cd2Ashwin
115810c949db9c60baa02684a50d71026727c357cd2Ashwin    GSCAN_ATTRIBUTE_WHITELIST_SSID = 80,
116810c949db9c60baa02684a50d71026727c357cd2Ashwin    GSCAN_ATTRIBUTE_NUM_WL_SSID,
117810c949db9c60baa02684a50d71026727c357cd2Ashwin    GSCAN_ATTRIBUTE_WL_SSID_LEN,
118810c949db9c60baa02684a50d71026727c357cd2Ashwin    GSCAN_ATTRIBUTE_WL_SSID_FLUSH,
119810c949db9c60baa02684a50d71026727c357cd2Ashwin    GSCAN_ATTRIBUTE_WHITELIST_SSID_ELEM,
120810c949db9c60baa02684a50d71026727c357cd2Ashwin    GSCAN_ATTRIBUTE_NUM_BSSID,
121810c949db9c60baa02684a50d71026727c357cd2Ashwin    GSCAN_ATTRIBUTE_BSSID_PREF_LIST,
122810c949db9c60baa02684a50d71026727c357cd2Ashwin    GSCAN_ATTRIBUTE_BSSID_PREF_FLUSH,
123810c949db9c60baa02684a50d71026727c357cd2Ashwin    GSCAN_ATTRIBUTE_BSSID_PREF,
124810c949db9c60baa02684a50d71026727c357cd2Ashwin    GSCAN_ATTRIBUTE_RSSI_MODIFIER,
125810c949db9c60baa02684a50d71026727c357cd2Ashwin
126810c949db9c60baa02684a50d71026727c357cd2Ashwin    /* remaining reserved for additional attributes */
127810c949db9c60baa02684a50d71026727c357cd2Ashwin
128810c949db9c60baa02684a50d71026727c357cd2Ashwin    GSCAN_ATTRIBUTE_A_BAND_BOOST_THRESHOLD = 90,
129810c949db9c60baa02684a50d71026727c357cd2Ashwin    GSCAN_ATTRIBUTE_A_BAND_PENALTY_THRESHOLD,
130810c949db9c60baa02684a50d71026727c357cd2Ashwin    GSCAN_ATTRIBUTE_A_BAND_BOOST_FACTOR,
131810c949db9c60baa02684a50d71026727c357cd2Ashwin    GSCAN_ATTRIBUTE_A_BAND_PENALTY_FACTOR,
132810c949db9c60baa02684a50d71026727c357cd2Ashwin    GSCAN_ATTRIBUTE_A_BAND_MAX_BOOST,
133810c949db9c60baa02684a50d71026727c357cd2Ashwin    GSCAN_ATTRIBUTE_LAZY_ROAM_HYSTERESIS,
134810c949db9c60baa02684a50d71026727c357cd2Ashwin    GSCAN_ATTRIBUTE_ALERT_ROAM_RSSI_TRIGGER,
135810c949db9c60baa02684a50d71026727c357cd2Ashwin    GSCAN_ATTRIBUTE_LAZY_ROAM_ENABLE,
136810c949db9c60baa02684a50d71026727c357cd2Ashwin
137810c949db9c60baa02684a50d71026727c357cd2Ashwin    /* BSSID blacklist */
138810c949db9c60baa02684a50d71026727c357cd2Ashwin    GSCAN_ATTRIBUTE_BSSID_BLACKLIST_FLUSH = 100,
139810c949db9c60baa02684a50d71026727c357cd2Ashwin    GSCAN_ATTRIBUTE_BLACKLIST_BSSID,
140810c949db9c60baa02684a50d71026727c357cd2Ashwin
141f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    /* ANQPO */
142f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    GSCAN_ATTRIBUTE_ANQPO_HS_LIST = 110,
143f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE,
144f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID,
145f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM,
146f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID,
147f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    GSCAN_ATTRIBUTE_ANQPO_HS_PLMN,
148f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
14925a0fb843d8b6d9141ccb435f1f9ee9a29d3afc6Ashwin    /* Adaptive scan attributes */
15025a0fb843d8b6d9141ccb435f1f9ee9a29d3afc6Ashwin    GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT = 120,
15125a0fb843d8b6d9141ccb435f1f9ee9a29d3afc6Ashwin    GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD,
15225a0fb843d8b6d9141ccb435f1f9ee9a29d3afc6Ashwin
1532b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    /* ePNO cfg */
1542b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR = 130,
1552b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR,
1562b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX,
1572b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS,
1582b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS,
1592b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS,
1602b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    GSCAN_ATTRIBUTE_EPNO_5G_BONUS,
1612b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin
1621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GSCAN_ATTRIBUTE_MAX
1631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
1641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} GSCAN_ATTRIBUTE;
1651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
166922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
167922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde// helper methods
168922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndewifi_error wifi_enable_full_scan_results(wifi_request_id id, wifi_interface_handle iface,
169922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde         wifi_scan_result_handler handler);
170922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndewifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface);
17177e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwinint wifi_handle_full_scan_event(wifi_request_id id, WifiEvent& event,
17277e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin         wifi_scan_result_handler handler);
1732b31c56930bc154d639da4ff2f56c34ef61688e5Ashwinvoid convert_to_hal_result(wifi_scan_result *to, wifi_gscan_result_t *from);
1742b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin
1752b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin
1762b31c56930bc154d639da4ff2f56c34ef61688e5Ashwinvoid convert_to_hal_result(wifi_scan_result *to, wifi_gscan_result_t *from)
1772b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin{
1782b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    to->ts = from->ts;
1792b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    to->channel = from->channel;
1802b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    to->rssi = from->rssi;
1812b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    to->rtt = from->rtt;
1822b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    to->rtt_sd = from->rtt_sd;
1832b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    to->beacon_period = from->beacon_period;
1842b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    to->capability = from->capability;
1852b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    memcpy(to->ssid, from->ssid, (DOT11_MAX_SSID_LEN+1));
1862b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    memcpy(&to->bssid, &from->bssid, sizeof(mac_addr));
1872b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin}
188922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
1891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde/////////////////////////////////////////////////////////////////////////////
1901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
1911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass GetCapabilitiesCommand : public WifiCommand
1921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
1931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_gscan_capabilities *mCapabilities;
1941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic:
1951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GetCapabilitiesCommand(wifi_interface_handle iface, wifi_gscan_capabilities *capabitlites)
196d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("GetGscanCapabilitiesCommand", iface, 0), mCapabilities(capabitlites)
1971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    {
1981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        memset(mCapabilities, 0, sizeof(*mCapabilities));
1991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
2001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int create() {
202a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        ALOGV("Creating message to get scan capablities; iface = %d", mIfaceInfo->id);
2031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int ret = mMsg.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_CAPABILITIES);
2051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (ret < 0) {
2061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return ret;
2071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
2081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return ret;
2101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
2111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeprotected:
2131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int handleResponse(WifiEvent& reply) {
2141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
215a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        ALOGV("In GetCapabilities::handleResponse");
2161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
2181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
2191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return NL_SKIP;
2201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
2211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int id = reply.get_vendor_id();
2231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int subcmd = reply.get_vendor_subcmd();
2241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        void *data = reply.get_vendor_data();
2261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int len = reply.get_vendor_data_len();
2271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
228a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        ALOGV("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len,
229e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande                    sizeof(*mCapabilities));
230e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande
231e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande        memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities)));
2321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return NL_OK;
2341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
2351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde};
2361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle,
2391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        wifi_gscan_capabilities *capabilities)
2401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
2411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GetCapabilitiesCommand command(handle, capabilities);
2421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    return (wifi_error) command.requestResponse();
2431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
2441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
24527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwinclass GetChannelListCommand : public WifiCommand
24627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin{
24727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin    wifi_channel *channels;
24827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin    int max_channels;
24927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin    int *num_channels;
25027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin    int band;
25127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwinpublic:
25227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin    GetChannelListCommand(wifi_interface_handle iface, wifi_channel *channel_buf, int *ch_num,
25327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        int num_max_ch, int band)
254d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("GetChannelListCommand", iface, 0), channels(channel_buf),
255d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande            max_channels(num_max_ch), num_channels(ch_num), band(band)
25627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin    {
25727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        memset(channels, 0, sizeof(wifi_channel) * max_channels);
25827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin    }
25927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin    virtual int create() {
260a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        ALOGV("Creating message to get channel list; iface = %d", mIfaceInfo->id);
26127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin
26227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        int ret = mMsg.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_CHANNEL_LIST);
26327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        if (ret < 0) {
26427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin            return ret;
26527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        }
26627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin
26727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
26827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        ret = mMsg.put_u32(GSCAN_ATTRIBUTE_BAND, band);
26927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        if (ret < 0) {
27027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin            return ret;
27127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        }
27227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin
27327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        mMsg.attr_end(data);
27427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin
27527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        return ret;
27627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin    }
27727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin
27827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwinprotected:
27927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin    virtual int handleResponse(WifiEvent& reply) {
28027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin
281a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        ALOGV("In GetChannelList::handleResponse");
28227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin
28327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
28427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin            ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
28527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin            return NL_SKIP;
28627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        }
28727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin
28827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        int id = reply.get_vendor_id();
28927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        int subcmd = reply.get_vendor_subcmd();
29027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        int num_channels_to_copy = 0;
29127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin
29227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
29327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        int len = reply.get_vendor_data_len();
29427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin
295a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
29627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        if (vendor_data == NULL || len == 0) {
29727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin            ALOGE("no vendor data in GetChannelList response; ignoring it");
29827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin            return NL_SKIP;
29927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        }
30027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin
30127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
30227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin            if (it.get_type() == GSCAN_ATTRIBUTE_NUM_CHANNELS) {
30327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin                num_channels_to_copy = it.get_u32();
30427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin                ALOGI("Got channel list with %d channels", num_channels_to_copy);
30527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin                if(num_channels_to_copy > max_channels)
30627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin                    num_channels_to_copy = max_channels;
30727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin                *num_channels = num_channels_to_copy;
30827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin            } else if (it.get_type() == GSCAN_ATTRIBUTE_CHANNEL_LIST && num_channels_to_copy) {
30927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin                memcpy(channels, it.get_data(), sizeof(int) * num_channels_to_copy);
31027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin            } else {
31127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin                ALOGW("Ignoring invalid attribute type = %d, size = %d",
31227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin                        it.get_type(), it.get_len());
31327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin            }
31427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        }
31527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin
31627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        return NL_OK;
31727a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin    }
31827a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin};
31927a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin
32027a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwinwifi_error wifi_get_valid_channels(wifi_interface_handle handle,
32127a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin        int band, int max_channels, wifi_channel *channels, int *num_channels)
32227a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin{
32327a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin    GetChannelListCommand command(handle, channels, num_channels,
32427a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin                                        max_channels, band);
32527a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin    return (wifi_error) command.requestResponse();
32627a89dc4e3256ded710cf7bea77aed3b8cd168e2Ashwin}
3271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde/////////////////////////////////////////////////////////////////////////////
3281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
3291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde/* helper functions */
3301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
3311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndestatic int parseScanResults(wifi_scan_result *results, int num, nlattr *attr)
3321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
3331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    memset(results, 0, sizeof(wifi_scan_result) * num);
3341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
3351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int i = 0;
3361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    for (nl_iterator it(attr); it.has_next() && i < num; it.next(), i++) {
3371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
3381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int index = it.get_type();
3391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGI("retrieved scan result %d", index);
3401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nlattr *sc_data = (nlattr *) it.get_data();
3411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        wifi_scan_result *result = results + i;
3421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
3431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        for (nl_iterator it2(sc_data); it2.has_next(); it2.next()) {
3441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            int type = it2.get_type();
3451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (type == GSCAN_ATTRIBUTE_SSID) {
3461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                strncpy(result->ssid, (char *) it2.get_data(), it2.get_len());
3471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                result->ssid[it2.get_len()] = 0;
3481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            } else if (type == GSCAN_ATTRIBUTE_BSSID) {
3491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                memcpy(result->bssid, (byte *) it2.get_data(), sizeof(mac_addr));
3501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            } else if (type == GSCAN_ATTRIBUTE_TIMESTAMP) {
3511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                result->ts = it2.get_u64();
3521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            } else if (type == GSCAN_ATTRIBUTE_CHANNEL) {
3531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                result->ts = it2.get_u16();
3541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            } else if (type == GSCAN_ATTRIBUTE_RSSI) {
3551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                result->rssi = it2.get_u8();
3561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            } else if (type == GSCAN_ATTRIBUTE_RTT) {
3571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                result->rtt = it2.get_u64();
3581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            } else if (type == GSCAN_ATTRIBUTE_RTTSD) {
3591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                result->rtt_sd = it2.get_u64();
3601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
3611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
3621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
3631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
3641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
3651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (i >= num) {
3661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGE("Got too many results; skipping some");
3671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
3681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
3691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    return i;
3701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
3711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
3721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeint createFeatureRequest(WifiRequest& request, int subcmd, int enable) {
3731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
3741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int result = request.create(GOOGLE_OUI, subcmd);
3751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (result < 0) {
3761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return result;
3771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
3781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
3791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
3801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    result = request.put_u32(GSCAN_ATTRIBUTE_ENABLE_FEATURE, enable);
3811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (result < 0) {
3821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return result;
3831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
3841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
3851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    request.attr_end(data);
3861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    return WIFI_SUCCESS;
3871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
3881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
3891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde/////////////////////////////////////////////////////////////////////////////
390922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndeclass FullScanResultsCommand : public WifiCommand
391922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde{
392922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    int *mParams;
393922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    wifi_scan_result_handler mHandler;
394922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndepublic:
395922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    FullScanResultsCommand(wifi_interface_handle iface, int id, int *params,
396922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde                wifi_scan_result_handler handler)
397d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("FullScanResultsCommand", iface, id), mParams(params), mHandler(handler)
398922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    { }
399922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
400922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    int createRequest(WifiRequest& request, int subcmd, int enable) {
401922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        int result = request.create(GOOGLE_OUI, subcmd);
402922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        if (result < 0) {
403922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde            return result;
404922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        }
405922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
406922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
407922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        result = request.put_u32(GSCAN_ENABLE_FULL_SCAN_RESULTS, enable);
408922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        if (result < 0) {
409922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde            return result;
410922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        }
411922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
412922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        request.attr_end(data);
413922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        return WIFI_SUCCESS;
414922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
415922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    }
416922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
417922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    int start() {
418a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        ALOGV("Enabling Full scan results");
419922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        WifiRequest request(familyId(), ifaceId());
420922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 1);
421922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        if (result != WIFI_SUCCESS) {
422922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde            ALOGE("failed to create request; result = %d", result);
423922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde            return result;
424922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        }
425922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
426922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
427922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
428922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        result = requestResponse(request);
429922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        if (result != WIFI_SUCCESS) {
430922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde            ALOGE("failed to enable full scan results; result = %d", result);
431922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
432922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde            return result;
433922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        }
434922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
435922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        return result;
436922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    }
437922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
438922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    virtual int cancel() {
439a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        ALOGV("Disabling Full scan results");
440922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
441922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        WifiRequest request(familyId(), ifaceId());
442922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 0);
443922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        if (result != WIFI_SUCCESS) {
444922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde            ALOGE("failed to create request; result = %d", result);
445922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        } else {
446922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde            result = requestResponse(request);
447922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde            if (result != WIFI_SUCCESS) {
448922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde                ALOGE("failed to disable full scan results;result = %d", result);
449922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde            }
450922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        }
451922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
452922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
453922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        return WIFI_SUCCESS;
454922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    }
455922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
456922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    virtual int handleResponse(WifiEvent& reply) {
457922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde         ALOGD("Request complete!");
458922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        /* Nothing to do on response! */
459922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        return NL_SKIP;
460922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    }
461922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
462922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    virtual int handleEvent(WifiEvent& event) {
463a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        ALOGV("Full scan results:  Got an event");
46477e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin        return wifi_handle_full_scan_event(id(), event, mHandler);
465922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    }
466922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
467922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde};
468922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde/////////////////////////////////////////////////////////////////////////////
4691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
4701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass ScanCommand : public WifiCommand
4711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
4721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_scan_cmd_params *mParams;
4731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_scan_result_handler mHandler;
4741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic:
4751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    ScanCommand(wifi_interface_handle iface, int id, wifi_scan_cmd_params *params,
4761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                wifi_scan_result_handler handler)
47777e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin        : WifiCommand("ScanCommand", iface, id), mParams(params), mHandler(handler)
4781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    { }
4791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
4801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int createSetupRequest(WifiRequest& request) {
4811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_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_BASE_PERIOD, mParams->base_period);
4881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
4891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
4901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
4911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
4921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = request.put_u32(GSCAN_ATTRIBUTE_NUM_BUCKETS, mParams->num_buckets);
4931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
4941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
4951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
4961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
4971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        for (int i = 0; i < mParams->num_buckets; i++) {
4981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            nlattr * bucket = request.attr_start(i);    // next bucket
4991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_ID, mParams->buckets[i].bucket);
5001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (result < 0) {
5011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                return result;
5021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
5031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_PERIOD, mParams->buckets[i].period);
5041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (result < 0) {
5051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                return result;
5061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
507922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde            result = request.put_u32(GSCAN_ATTRIBUTE_BUCKETS_BAND,
508922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde                    mParams->buckets[i].band);
509922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde            if (result < 0) {
510922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde                return result;
511922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde            }
51225a0fb843d8b6d9141ccb435f1f9ee9a29d3afc6Ashwin            result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT,
51325a0fb843d8b6d9141ccb435f1f9ee9a29d3afc6Ashwin                    mParams->buckets[i].step_count);
51425a0fb843d8b6d9141ccb435f1f9ee9a29d3afc6Ashwin            if (result < 0) {
51525a0fb843d8b6d9141ccb435f1f9ee9a29d3afc6Ashwin                return result;
51625a0fb843d8b6d9141ccb435f1f9ee9a29d3afc6Ashwin            }
51725a0fb843d8b6d9141ccb435f1f9ee9a29d3afc6Ashwin            result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD,
51825a0fb843d8b6d9141ccb435f1f9ee9a29d3afc6Ashwin                    mParams->buckets[i].max_period);
51925a0fb843d8b6d9141ccb435f1f9ee9a29d3afc6Ashwin            if (result < 0) {
52025a0fb843d8b6d9141ccb435f1f9ee9a29d3afc6Ashwin                return result;
52125a0fb843d8b6d9141ccb435f1f9ee9a29d3afc6Ashwin            }
522922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde            result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_EVENTS,
523922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde                    mParams->buckets[i].report_events);
524922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde            if (result < 0) {
525922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde                return result;
526922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde            }
527922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
5281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS,
5291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                    mParams->buckets[i].num_channels);
5301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (result < 0) {
5311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                return result;
5321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
5331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
534922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde            if (mParams->buckets[i].num_channels) {
535922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde                nlattr *channels = request.attr_start(GSCAN_ATTRIBUTE_BUCKET_CHANNELS);
536ec74fa4fcb49a35e6af54e086e63692b37d21b02Vinit Deshpande                ALOGV(" channels: ");
537922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde                for (int j = 0; j < mParams->buckets[i].num_channels; j++) {
538922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde                    result = request.put_u32(j, mParams->buckets[i].channels[j].channel);
539ec74fa4fcb49a35e6af54e086e63692b37d21b02Vinit Deshpande                    ALOGV(" %u", mParams->buckets[i].channels[j].channel);
540659515a05a813cf672aa8d50161f76425afa781fPierre Vandwalle
541922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde                    if (result < 0) {
542922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde                        return result;
543922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde                    }
5441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                }
545922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde                request.attr_end(channels);
5461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
5471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            request.attr_end(bucket);
5491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
5501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        request.attr_end(data);
5521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return WIFI_SUCCESS;
5531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
5541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int createScanConfigRequest(WifiRequest& request) {
5561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SCAN_CONFIG);
5571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
5581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
5591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
5601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
5621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = request.put_u32(GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, mParams->max_ap_per_scan);
5631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
5641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
5651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
5661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
567bcd42ae7e431d321090080aa00865b6fe4ab95e0Vinit Deshpande        result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD,
568bcd42ae7e431d321090080aa00865b6fe4ab95e0Vinit Deshpande                mParams->report_threshold_percent);
5691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
5701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
5711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
5721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
573bcd42ae7e431d321090080aa00865b6fe4ab95e0Vinit Deshpande        int num_scans = mParams->report_threshold_num_scans;
57409f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde
57509f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde        result = request.put_u32(GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, num_scans);
5761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
5771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
5781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
5791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        request.attr_end(data);
5811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return WIFI_SUCCESS;
5821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
5831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int createStartRequest(WifiRequest& request) {
5851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
5861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
5871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int createStopRequest(WifiRequest& request) {
5891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 0);
5901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
5911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int start() {
593a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        ALOGV("GSCAN start");
5941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        WifiRequest request(familyId(), ifaceId());
5951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = createSetupRequest(request);
5961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result != WIFI_SUCCESS) {
5971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGE("failed to create setup request; result = %d", result);
5981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
5991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
6001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
6011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = requestResponse(request);
6021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result != WIFI_SUCCESS) {
6031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGE("failed to configure setup; result = %d", result);
6041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
6051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
6061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
6071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        request.destroy();
6081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
6091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = createScanConfigRequest(request);
6101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result != WIFI_SUCCESS) {
6111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGE("failed to create scan config request; result = %d", result);
6121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
6131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
6141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
6151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = requestResponse(request);
6161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result != WIFI_SUCCESS) {
6171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGE("failed to configure scan; result = %d", result);
6181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
6191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
6201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
621a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        ALOGV(" ....starting scan");
6221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
6231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = createStartRequest(request);
6241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result != WIFI_SUCCESS) {
6251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGE("failed to create start request; result = %d", result);
6261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
6271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
6281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
6291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
6309a23388d5a9f58f106169700bb179de0a4af7840Ashwin        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
63177e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
6329a23388d5a9f58f106169700bb179de0a4af7840Ashwin
6331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = requestResponse(request);
6341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result != WIFI_SUCCESS) {
6351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGE("failed to start scan; result = %d", result);
636de37675b218f0c685512417d914dff60f3b4b115Ashwin            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
6371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
63877e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
6391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
6401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
6411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return result;
6421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
6431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
6441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int cancel() {
645a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        ALOGV("Stopping scan");
6461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
6471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        WifiRequest request(familyId(), ifaceId());
6481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = createStopRequest(request);
6491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result != WIFI_SUCCESS) {
6501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGE("failed to create stop request; result = %d", result);
6511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        } else {
6521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            result = requestResponse(request);
6531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (result != WIFI_SUCCESS) {
6541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                ALOGE("failed to stop scan; result = %d", result);
6551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
6561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
6571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
658082cb621b1dd1ad150a747d5010fed0888ae416cVinit Deshpande        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
6591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
66077e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
6611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return WIFI_SUCCESS;
6621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
6631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
6641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int handleResponse(WifiEvent& reply) {
6651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        /* Nothing to do on response! */
6661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return NL_SKIP;
6671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
6681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
6691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int handleEvent(WifiEvent& event) {
670a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        ALOGV("Got a scan results event");
671eaf59b2182588ab2e921741c772070281840e89bNavtej Singh Mann        //event.log();
6721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
6731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
6741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int len = event.get_vendor_data_len();
6759a23388d5a9f58f106169700bb179de0a4af7840Ashwin        int event_id = event.get_vendor_subcmd();
6761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
6772b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        if ((event_id == GSCAN_EVENT_COMPLETE_SCAN) ||
6782b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin            (event_id == GSCAN_EVENT_SCAN_RESULTS_AVAILABLE)) {
6799a23388d5a9f58f106169700bb179de0a4af7840Ashwin            if (vendor_data == NULL || len != 4) {
6802b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                ALOGI("Bad event data!");
6819a23388d5a9f58f106169700bb179de0a4af7840Ashwin                return NL_SKIP;
6829a23388d5a9f58f106169700bb179de0a4af7840Ashwin            }
6839a23388d5a9f58f106169700bb179de0a4af7840Ashwin            wifi_scan_event evt_type;
6849a23388d5a9f58f106169700bb179de0a4af7840Ashwin            evt_type = (wifi_scan_event) event.get_u32(NL80211_ATTR_VENDOR_DATA);
6852b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin            ALOGV("Received event type %d", evt_type);
68689296a7fc953e68649cdb1366d22376c034ace05Mitchell Wills            if(*mHandler.on_scan_event)
6872b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                (*mHandler.on_scan_event)(id(), evt_type);
68877e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin        } else if (event_id == GSCAN_EVENT_FULL_SCAN_RESULTS) {
68977e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin            wifi_handle_full_scan_event(id(), event, mHandler);
6909a23388d5a9f58f106169700bb179de0a4af7840Ashwin        }
6911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return NL_SKIP;
6921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
6931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde};
6941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
6951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_start_gscan(
6961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        wifi_request_id id,
6971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        wifi_interface_handle iface,
6981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        wifi_scan_cmd_params params,
6991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        wifi_scan_result_handler handler)
7001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
7011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_handle handle = getWifiHandle(iface);
7021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
703a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann    ALOGV("Starting GScan, halHandle = %p", handle);
7041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
7051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    ScanCommand *cmd = new ScanCommand(iface, id, &params, handler);
7066af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
7076af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    wifi_error result = wifi_register_cmd(handle, id, cmd);
7086af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    if (result != WIFI_SUCCESS) {
7096af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
7106af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
7116af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    }
7126af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    result = (wifi_error)cmd->start();
713a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann    if (result != WIFI_SUCCESS) {
714a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        wifi_unregister_cmd(handle, id);
7156af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
7166af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
717a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann    }
718a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann    return result;
7191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
7201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
7211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_stop_gscan(wifi_request_id id, wifi_interface_handle iface)
7221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
7231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_handle handle = getWifiHandle(iface);
724a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann    ALOGV("Stopping GScan, wifi_request_id = %d, halHandle = %p", id, handle);
7251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
726d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande    if (id == -1) {
727922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        wifi_scan_result_handler handler;
728922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        wifi_scan_cmd_params dummy_params;
729922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        wifi_handle handle = getWifiHandle(iface);
730922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        memset(&handler, 0, sizeof(handler));
731922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
732922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        ScanCommand *cmd = new ScanCommand(iface, id, &dummy_params, handler);
7336af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
734922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        cmd->cancel();
73528237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande        cmd->releaseRef();
736922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        return WIFI_SUCCESS;
737922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    }
738922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
739fef13c11034313585be68c32322b9a53c43a37b2Ashwin    return wifi_cancel_cmd(id, iface);
7401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
7411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
742922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndewifi_error wifi_enable_full_scan_results(
743922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        wifi_request_id id,
744922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        wifi_interface_handle iface,
745922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        wifi_scan_result_handler handler)
746922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde{
747922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    wifi_handle handle = getWifiHandle(iface);
748922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    int params_dummy;
749a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann
750a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann    ALOGV("Enabling full scan results, halHandle = %p", handle);
751922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
752922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, id, &params_dummy, handler);
7536af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
7546af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    wifi_error result = wifi_register_cmd(handle, id, cmd);
7556af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    if (result != WIFI_SUCCESS) {
7566af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
7576af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
7586af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    }
7596af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    result = (wifi_error)cmd->start();
760a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann    if (result != WIFI_SUCCESS) {
761a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        wifi_unregister_cmd(handle, id);
7626af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
7636af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
764a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann    }
765a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann    return result;
766922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde}
767922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
76877e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwinint wifi_handle_full_scan_event(
76977e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin        wifi_request_id id,
77077e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin        WifiEvent& event,
77177e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin        wifi_scan_result_handler handler)
77277e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin{
77377e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin    nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
77477e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin    unsigned int len = event.get_vendor_data_len();
77577e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin
7762b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    if (vendor_data == NULL || len < sizeof(wifi_gscan_full_result_t)) {
77777e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin        ALOGI("Full scan results: No scan results found");
77877e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin        return NL_SKIP;
77977e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin    }
78077e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin
7812b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    wifi_gscan_full_result_t *drv_res = (wifi_gscan_full_result_t *)event.get_vendor_data();
7822b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    /* To protect against corrupted data, put a ceiling */
7832b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    int ie_len = min(MAX_PROBE_RESP_IE_LEN, drv_res->ie_length);
7842b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    wifi_scan_result *full_scan_result;
7852b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    wifi_gscan_result_t *fixed = &drv_res->fixed;
78677e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin
787dc30cd78fad72d108d327285a2ba899b331c7992Ashwin    if ((ie_len + offsetof(wifi_gscan_full_result_t, ie_data)) > len) {
788dc30cd78fad72d108d327285a2ba899b331c7992Ashwin        ALOGE("BAD event data, len %d ie_len %d fixed length %d!\n", len,
789dc30cd78fad72d108d327285a2ba899b331c7992Ashwin            ie_len, offsetof(wifi_gscan_full_result_t, ie_data));
790dc30cd78fad72d108d327285a2ba899b331c7992Ashwin        return NL_SKIP;
791dc30cd78fad72d108d327285a2ba899b331c7992Ashwin    }
7922b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    full_scan_result = (wifi_scan_result *) malloc((ie_len + offsetof(wifi_scan_result, ie_data)));
7932b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    if (!full_scan_result) {
7942b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        ALOGE("Full scan results: Can't malloc!\n");
7952b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        return NL_SKIP;
7962b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    }
7972b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    convert_to_hal_result(full_scan_result, fixed);
7982b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    full_scan_result->ie_length = ie_len;
7992b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    memcpy(full_scan_result->ie_data, drv_res->ie_data, ie_len);
8002b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    if(handler.on_full_scan_result)
8012b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        handler.on_full_scan_result(id, full_scan_result, drv_res->scan_ch_bucket);
8022b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin
8031c8586503c74fd8bebb5e8b83beed989c33613eeSreenath Sharma    ALOGV("Full scan result: %-32s %02x:%02x:%02x:%02x:%02x:%02x %d %d %lld %lld %lld %x %d\n",
8042b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        fixed->ssid, fixed->bssid[0], fixed->bssid[1], fixed->bssid[2], fixed->bssid[3],
8052b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        fixed->bssid[4], fixed->bssid[5], fixed->rssi, fixed->channel, fixed->ts,
8062b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        fixed->rtt, fixed->rtt_sd, drv_res->scan_ch_bucket, drv_res->ie_length);
8072b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    free(full_scan_result);
80877e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin    return NL_SKIP;
80977e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin}
81077e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin
81177e3df794cfaf6f280b0230cc2a0eaa818606e6aAshwin
812922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapndewifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface)
813922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde{
814a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann    ALOGV("Disabling full scan results");
815922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    wifi_handle handle = getWifiHandle(iface);
816922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
817922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    if(id == -1) {
818922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        wifi_scan_result_handler handler;
819922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        wifi_handle handle = getWifiHandle(iface);
820922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        int params_dummy;
821922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
822922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        memset(&handler, 0, sizeof(handler));
823922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, 0, &params_dummy, handler);
8246af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
825922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        cmd->cancel();
82628237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande        cmd->releaseRef();
827922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde        return WIFI_SUCCESS;
828922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde    }
829922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
830fef13c11034313585be68c32322b9a53c43a37b2Ashwin    return wifi_cancel_cmd(id, iface);
831922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde}
832922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
833922bc148ebc612b6ecf7233b028099aab78feae4Vinit Deshapnde
8341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde/////////////////////////////////////////////////////////////////////////////
8351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass GetScanResultsCommand : public WifiCommand {
837bcd42ae7e431d321090080aa00865b6fe4ab95e0Vinit Deshpande    wifi_cached_scan_results *mScans;
838e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande    int mMax;
8391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int *mNum;
8401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int mRetrieved;
8411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    byte mFlush;
8421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int mCompleted;
8431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic:
8441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GetScanResultsCommand(wifi_interface_handle iface, byte flush,
845bcd42ae7e431d321090080aa00865b6fe4ab95e0Vinit Deshpande            wifi_cached_scan_results *results, int max, int *num)
846d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("GetScanResultsCommand", iface, -1), mScans(results), mMax(max), mNum(num),
8472b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                mRetrieved(0), mFlush(flush), mCompleted(0)
8481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    { }
8491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int createRequest(WifiRequest& request, int num, byte flush) {
8511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_SCAN_RESULTS);
8521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
8531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
8541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
8551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
8571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = request.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num);
8581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
8591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
8601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
8611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = request.put_u8(GSCAN_ATTRIBUTE_FLUSH_RESULTS, flush);
8631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
8641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
8651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
8661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        request.attr_end(data);
8681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return WIFI_SUCCESS;
8691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
8701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int execute() {
8721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        WifiRequest request(familyId(), ifaceId());
873a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        ALOGV("retrieving %d scan results", mMax);
8741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
875e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande        for (int i = 0; i < 10 && mRetrieved < mMax; i++) {
876bcd42ae7e431d321090080aa00865b6fe4ab95e0Vinit Deshpande            int num_to_retrieve = mMax - mRetrieved;
87779c41bc9ff10a322cf6cacc51b80707d5ba5a4eeVinit Deshpande            // ALOGI("retrieving %d scan results in one shot", num_to_retrieve);
878bcd42ae7e431d321090080aa00865b6fe4ab95e0Vinit Deshpande            int result = createRequest(request, num_to_retrieve, mFlush);
8791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (result < 0) {
8801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                ALOGE("failed to create request");
8811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                return result;
8821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
8831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            int prev_retrieved = mRetrieved;
8851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            result = requestResponse(request);
8871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (result != WIFI_SUCCESS) {
8891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                ALOGE("failed to retrieve scan results; result = %d", result);
8901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                return result;
8911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
8921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (mRetrieved == prev_retrieved || mCompleted) {
8941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                /* no more items left to retrieve */
8951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                break;
8961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
8971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
8981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            request.destroy();
8991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
9001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
901aab2ce80bab0221da737f64d15bae68caae21badNavtej Singh Mann        ALOGV("GetScanResults read %d results", mRetrieved);
9021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        *mNum = mRetrieved;
9031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return WIFI_SUCCESS;
9041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
9051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
9061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int handleResponse(WifiEvent& reply) {
907a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        ALOGV("In GetScanResultsCommand::handleResponse");
9081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
9091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
9101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
9111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return NL_SKIP;
9121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
9131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
9141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int id = reply.get_vendor_id();
9151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int subcmd = reply.get_vendor_subcmd();
9161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
917a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        ALOGV("Id = %0x, subcmd = %d", id, subcmd);
9181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
9191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        /*
9201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (subcmd != GSCAN_SUBCMD_SCAN_RESULTS) {
9211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGE("Invalid response to GetScanResultsCommand; ignoring it");
9221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return NL_SKIP;
9231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
9241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        */
9251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
9261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
9271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int len = reply.get_vendor_data_len();
9281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
9291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (vendor_data == NULL || len == 0) {
9301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGE("no vendor data in GetScanResults response; ignoring it");
9311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return NL_SKIP;
9321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
9331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
9341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
9351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE) {
9361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                mCompleted = it.get_u8();
937ec74fa4fcb49a35e6af54e086e63692b37d21b02Vinit Deshpande                ALOGV("retrieved mCompleted flag : %d", mCompleted);
9381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            } else if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS || it.get_type() == 0) {
9392b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                int scan_id = 0, flags = 0, num = 0, scan_ch_bucket_mask = 0;
9401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) {
9411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                    if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_ID) {
942bcd42ae7e431d321090080aa00865b6fe4ab95e0Vinit Deshpande                        scan_id = it2.get_u32();
943ec74fa4fcb49a35e6af54e086e63692b37d21b02Vinit Deshpande                        ALOGV("retrieved scan_id : 0x%0x", scan_id);
9441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                    } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_FLAGS) {
945bcd42ae7e431d321090080aa00865b6fe4ab95e0Vinit Deshpande                        flags = it2.get_u8();
946ec74fa4fcb49a35e6af54e086e63692b37d21b02Vinit Deshpande                        ALOGV("retrieved scan_flags : 0x%0x", flags);
9471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                    } else if (it2.get_type() == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) {
9481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                        num = it2.get_u32();
949ec74fa4fcb49a35e6af54e086e63692b37d21b02Vinit Deshpande                        ALOGV("retrieved num_results: %d", num);
9502b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                    } else if (it2.get_type() == GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK) {
9512b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                        scan_ch_bucket_mask = it2.get_u32();
9522b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                        ALOGD("retrieved scan_ch_bucket_mask: %x", scan_ch_bucket_mask);
9532b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                    } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS && num) {
954e900b04a91fd87e4d706be7ae3499d5fb9995188Kevin Cernekee                        if (mRetrieved >= mMax) {
955e900b04a91fd87e4d706be7ae3499d5fb9995188Kevin Cernekee                            ALOGW("Stored %d scans, ignoring excess results", mRetrieved);
956e900b04a91fd87e4d706be7ae3499d5fb9995188Kevin Cernekee                            break;
957e900b04a91fd87e4d706be7ae3499d5fb9995188Kevin Cernekee                        }
958a1797bbd4753d67ff6a48028710467d3fc68a4d9Sreenath Sharma                        num = min(num, (int)(it2.get_len()/sizeof(wifi_gscan_result)));
9592b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                        num = min(num, (int)MAX_AP_CACHE_PER_SCAN);
9602b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                        ALOGV("Copying %d scan results", num);
9612b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                        wifi_gscan_result_t *results = (wifi_gscan_result_t *)it2.get_data();
9622b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                        wifi_scan_result *mScanResults = mScans[mRetrieved].results;
9632b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin
9641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                        for (int i = 0; i < num; i++) {
9652b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                            wifi_gscan_result_t *result = &results[i];
9662b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                            convert_to_hal_result(&mScanResults[i], result);
9672b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                            mScanResults[i].ie_length = 0;
968ec74fa4fcb49a35e6af54e086e63692b37d21b02Vinit Deshpande                            ALOGV("%02d  %-32s  %02x:%02x:%02x:%02x:%02x:%02x  %04d", i,
9691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                                result->ssid, result->bssid[0], result->bssid[1], result->bssid[2],
97009f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde                                result->bssid[3], result->bssid[4], result->bssid[5],
97109f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde                                result->rssi);
9721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                        }
973bcd42ae7e431d321090080aa00865b6fe4ab95e0Vinit Deshpande                        mScans[mRetrieved].scan_id = scan_id;
974bcd42ae7e431d321090080aa00865b6fe4ab95e0Vinit Deshpande                        mScans[mRetrieved].flags = flags;
975bcd42ae7e431d321090080aa00865b6fe4ab95e0Vinit Deshpande                        mScans[mRetrieved].num_results = num;
9762b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                        mScans[mRetrieved].buckets_scanned = scan_ch_bucket_mask;
9771b166fb091b262273e129c6019c4d07a5ded665dNavtej Singh Mann                        ALOGV("Setting result of scan_id : 0x%0x", mScans[mRetrieved].scan_id);
978bcd42ae7e431d321090080aa00865b6fe4ab95e0Vinit Deshpande                        mRetrieved++;
9791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                    } else {
9801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                        ALOGW("Ignoring invalid attribute type = %d, size = %d",
9811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                                it.get_type(), it.get_len());
9821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                    }
9831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                }
9841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            } else {
9851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                ALOGW("Ignoring invalid attribute type = %d, size = %d",
9861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                        it.get_type(), it.get_len());
9871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
9881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
989aab2ce80bab0221da737f64d15bae68caae21badNavtej Singh Mann        ALOGV("GetScanResults read %d results", mRetrieved);
9901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return NL_OK;
9911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
9921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde};
9931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
9941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface, byte flush,
995bcd42ae7e431d321090080aa00865b6fe4ab95e0Vinit Deshpande        int max, wifi_cached_scan_results *results, int *num) {
996a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann    ALOGV("Getting cached scan results, iface handle = %p, num = %d", iface, *num);
9971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
998e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande    GetScanResultsCommand *cmd = new GetScanResultsCommand(iface, flush, results, max, num);
9996af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
10006af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    wifi_error err = (wifi_error)cmd->execute();
10016af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    cmd->releaseRef();
100242b1646c415b1d3cff220eb3491dc6960d610fafVinit Deshpande    return err;
10031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
10041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde/////////////////////////////////////////////////////////////////////////////
10061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass BssidHotlistCommand : public WifiCommand
10081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
10091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeprivate:
10101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_bssid_hotlist_params mParams;
10111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_hotlist_ap_found_handler mHandler;
10121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    static const int MAX_RESULTS = 64;
10131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_scan_result mResults[MAX_RESULTS];
10141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic:
10151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    BssidHotlistCommand(wifi_interface_handle handle, int id,
10161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler)
1017d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("BssidHotlistCommand", handle, id), mParams(params), mHandler(handler)
10181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    { }
10191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int createSetupRequest(WifiRequest& request) {
10211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST);
10221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
10231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
10241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
10251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
10271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1);
10281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
10291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
10301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
10311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
1032f0d5070a931327e6356d765478069b9e66452a5bAshwin        result = request.put_u32(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size);
1033f0d5070a931327e6356d765478069b9e66452a5bAshwin        if (result < 0) {
1034f0d5070a931327e6356d765478069b9e66452a5bAshwin            return result;
1035f0d5070a931327e6356d765478069b9e66452a5bAshwin        }
1036f0d5070a931327e6356d765478069b9e66452a5bAshwin
103766d82546960bb2408e1aa31856a3f9a6a400681fInsun Song        result = request.put_u32(GSCAN_ATTRIBUTE_HOTLIST_BSSID_COUNT, mParams.num_bssid);
103866d82546960bb2408e1aa31856a3f9a6a400681fInsun Song        if (result < 0) {
103966d82546960bb2408e1aa31856a3f9a6a400681fInsun Song            return result;
104066d82546960bb2408e1aa31856a3f9a6a400681fInsun Song        }
104166d82546960bb2408e1aa31856a3f9a6a400681fInsun Song
10421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS);
1043886a7c99f8664295fe233034cac84d6253324641Pierre Vandwalle        for (int i = 0; i < mParams.num_bssid; i++) {
10441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            nlattr *attr2 = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM);
10451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (attr2 == NULL) {
10461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                return WIFI_ERROR_OUT_OF_MEMORY;
10471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
1048e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande            result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid);
10491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (result < 0) {
10501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                return result;
10511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
1052e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande            result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high);
10531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (result < 0) {
10541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                return result;
10551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
1056e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande            result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low);
10571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (result < 0) {
10581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                return result;
10591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
10601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            request.attr_end(attr2);
10611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
10621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        request.attr_end(attr);
10641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        request.attr_end(data);
10651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return result;
10661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
10671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int createTeardownRequest(WifiRequest& request) {
10691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST);
10701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
10711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
10721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
10731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
10751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1);
10761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
10771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
10781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
10791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS);
10811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        request.attr_end(attr);
10821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        request.attr_end(data);
10831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return result;
10841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
10851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int start() {
1087886a7c99f8664295fe233034cac84d6253324641Pierre Vandwalle        ALOGI("Executing hotlist setup request, num = %d", mParams.num_bssid);
10881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        WifiRequest request(familyId(), ifaceId());
10891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = createSetupRequest(request);
10901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
10911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
10921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
10931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
10941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = requestResponse(request);
10951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
10961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGI("Failed to execute hotlist setup request, result = %d", result);
1097f0d5070a931327e6356d765478069b9e66452a5bAshwin            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
1098f0d5070a931327e6356d765478069b9e66452a5bAshwin            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
10991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
11001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
11011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
1102886a7c99f8664295fe233034cac84d6253324641Pierre Vandwalle        ALOGI("Successfully set %d APs in the hotlist ", mParams.num_bssid);
11031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
11041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
11051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
11061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
11071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
1108f0d5070a931327e6356d765478069b9e66452a5bAshwin        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
1109f0d5070a931327e6356d765478069b9e66452a5bAshwin        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
11101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = requestResponse(request);
11121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
1113f0d5070a931327e6356d765478069b9e66452a5bAshwin            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
1114f0d5070a931327e6356d765478069b9e66452a5bAshwin            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
11151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
11161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
11171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGI("successfully restarted the scan");
11191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return result;
11201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
11211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int cancel() {
11231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        /* unregister event handler */
1124f0d5070a931327e6356d765478069b9e66452a5bAshwin        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
1125f0d5070a931327e6356d765478069b9e66452a5bAshwin        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
11261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        /* create set hotlist message with empty hotlist */
11271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        WifiRequest request(familyId(), ifaceId());
11281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = createTeardownRequest(request);
11291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
11301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
11311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
11321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = requestResponse(request);
11341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
11351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
11361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
11371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGI("Successfully reset APs in current hotlist");
11391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return result;
11401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
11411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int handleResponse(WifiEvent& reply) {
11431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        /* Nothing to do on response! */
11441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return NL_SKIP;
11451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
11461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int handleEvent(WifiEvent& event) {
1148f0d5070a931327e6356d765478069b9e66452a5bAshwin        ALOGI("Hotlist AP event");
1149f0d5070a931327e6356d765478069b9e66452a5bAshwin        int event_id = event.get_vendor_subcmd();
115009f45268753c6021b621e0be82a6808cebbaa37dVinit Deshapnde        // event.log();
11511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
11531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int len = event.get_vendor_data_len();
11541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (vendor_data == NULL || len == 0) {
11561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGI("No scan results found");
11571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return NL_SKIP;
11581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
11591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        memset(mResults, 0, sizeof(wifi_scan_result) * MAX_RESULTS);
11611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11622b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        int num = len / sizeof(wifi_gscan_result_t);
11632b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        wifi_gscan_result_t *inp = (wifi_gscan_result_t *)event.get_vendor_data();
11641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        num = min(MAX_RESULTS, num);
11652b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        for (int i = 0; i < num; i++, inp++) {
11662b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin            convert_to_hal_result(&(mResults[i]), inp);
11672b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        }
11681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
1169f0d5070a931327e6356d765478069b9e66452a5bAshwin        if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_FOUND) {
1170f0d5070a931327e6356d765478069b9e66452a5bAshwin            ALOGI("FOUND %d hotlist APs", num);
1171f0d5070a931327e6356d765478069b9e66452a5bAshwin            if (*mHandler.on_hotlist_ap_found)
1172f0d5070a931327e6356d765478069b9e66452a5bAshwin                (*mHandler.on_hotlist_ap_found)(id(), num, mResults);
1173f0d5070a931327e6356d765478069b9e66452a5bAshwin        } else if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_LOST) {
1174f0d5070a931327e6356d765478069b9e66452a5bAshwin            ALOGI("LOST %d hotlist APs", num);
1175f0d5070a931327e6356d765478069b9e66452a5bAshwin            if (*mHandler.on_hotlist_ap_lost)
1176f0d5070a931327e6356d765478069b9e66452a5bAshwin                (*mHandler.on_hotlist_ap_lost)(id(), num, mResults);
1177f0d5070a931327e6356d765478069b9e66452a5bAshwin        }
11781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return NL_SKIP;
11791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
11801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde};
11811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
118289a9a4cffbcee6af504c61ff575a008194070c82Ashwinclass ePNOCommand : public WifiCommand
118389a9a4cffbcee6af504c61ff575a008194070c82Ashwin{
118489a9a4cffbcee6af504c61ff575a008194070c82Ashwinprivate:
11852b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    wifi_epno_params epno_params;
118689a9a4cffbcee6af504c61ff575a008194070c82Ashwin    wifi_epno_handler mHandler;
11872b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    wifi_scan_result mResults[MAX_EPNO_NETWORKS];
118889a9a4cffbcee6af504c61ff575a008194070c82Ashwinpublic:
118989a9a4cffbcee6af504c61ff575a008194070c82Ashwin    ePNOCommand(wifi_interface_handle handle, int id,
11902b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin            const wifi_epno_params *params, wifi_epno_handler handler)
1191d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("ePNOCommand", handle, id), mHandler(handler)
119289a9a4cffbcee6af504c61ff575a008194070c82Ashwin    {
11932b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        if (params != NULL) {
11942b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin            memcpy(&epno_params, params, sizeof(wifi_epno_params));
11952b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        } else {
11962b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin            memset(&epno_params, 0, sizeof(wifi_epno_params));
11972b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        }
119889a9a4cffbcee6af504c61ff575a008194070c82Ashwin    }
119989a9a4cffbcee6af504c61ff575a008194070c82Ashwin    int createSetupRequest(WifiRequest& request) {
12005a434343e3515e2c1e29b879ed67898206016f3fInsun Song        if (epno_params.num_networks > MAX_EPNO_NETWORKS) {
12015a434343e3515e2c1e29b879ed67898206016f3fInsun Song            ALOGE("wrong epno num_networks:%d", epno_params.num_networks);
12025a434343e3515e2c1e29b879ed67898206016f3fInsun Song            return WIFI_ERROR_INVALID_ARGS;
12035a434343e3515e2c1e29b879ed67898206016f3fInsun Song        }
120489a9a4cffbcee6af504c61ff575a008194070c82Ashwin        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_EPNO_SSID);
120589a9a4cffbcee6af504c61ff575a008194070c82Ashwin        if (result < 0) {
120689a9a4cffbcee6af504c61ff575a008194070c82Ashwin            return result;
120789a9a4cffbcee6af504c61ff575a008194070c82Ashwin        }
120889a9a4cffbcee6af504c61ff575a008194070c82Ashwin        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
120989a9a4cffbcee6af504c61ff575a008194070c82Ashwin        result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_FLUSH, 1);
121089a9a4cffbcee6af504c61ff575a008194070c82Ashwin        if (result < 0) {
121189a9a4cffbcee6af504c61ff575a008194070c82Ashwin            return result;
121289a9a4cffbcee6af504c61ff575a008194070c82Ashwin        }
121389a9a4cffbcee6af504c61ff575a008194070c82Ashwin
12142b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR,
12152b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                            (u8)epno_params.min5GHz_rssi);
12162b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        if (result < 0) {
12172b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin            return result;
12182b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        }
12192b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR,
12202b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                            (u8)epno_params.min24GHz_rssi);
12212b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        if (result < 0) {
12222b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin            return result;
12232b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        }
12242b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX,
12252b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                            epno_params.initial_score_max);
12262b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        if (result < 0) {
12272b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin            return result;
12282b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        }
12292b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS,
12302b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                            epno_params.current_connection_bonus);
12312b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        if (result < 0) {
12322b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin            return result;
12332b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        }
12342b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS,
12352b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                            epno_params.same_network_bonus);
12362b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        if (result < 0) {
12372b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin            return result;
12382b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        }
12392b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS,
12402b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                            epno_params.secure_bonus);
12412b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        if (result < 0) {
12422b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin            return result;
12432b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        }
12442b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_5G_BONUS,
12452b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                            epno_params.band5GHz_bonus);
12462b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        if (result < 0) {
12472b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin            return result;
12482b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        }
12492b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_SSID_NUM,
12502b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                        epno_params.num_networks);
125189a9a4cffbcee6af504c61ff575a008194070c82Ashwin        if (result < 0) {
125289a9a4cffbcee6af504c61ff575a008194070c82Ashwin            return result;
125389a9a4cffbcee6af504c61ff575a008194070c82Ashwin        }
125489a9a4cffbcee6af504c61ff575a008194070c82Ashwin        struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_EPNO_SSID_LIST);
12552b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        wifi_epno_network *ssid_list = epno_params.networks;
12562b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        for (int i = 0; i < epno_params.num_networks; i++) {
125789a9a4cffbcee6af504c61ff575a008194070c82Ashwin            nlattr *attr2 = request.attr_start(i);
125889a9a4cffbcee6af504c61ff575a008194070c82Ashwin            if (attr2 == NULL) {
125989a9a4cffbcee6af504c61ff575a008194070c82Ashwin                return WIFI_ERROR_OUT_OF_MEMORY;
126089a9a4cffbcee6af504c61ff575a008194070c82Ashwin            }
12612b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin            result = request.put(GSCAN_ATTRIBUTE_EPNO_SSID, ssid_list[i].ssid, DOT11_MAX_SSID_LEN);
12622b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin            ALOGI("PNO network: SSID %s flags %x auth %x", ssid_list[i].ssid,
12632b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                ssid_list[i].flags,
12642b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                ssid_list[i].auth_bit_field);
126589a9a4cffbcee6af504c61ff575a008194070c82Ashwin            if (result < 0) {
126689a9a4cffbcee6af504c61ff575a008194070c82Ashwin                return result;
126789a9a4cffbcee6af504c61ff575a008194070c82Ashwin            }
12682b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin            result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_SSID_LEN, strlen(ssid_list[i].ssid));
126989a9a4cffbcee6af504c61ff575a008194070c82Ashwin            if (result < 0) {
127089a9a4cffbcee6af504c61ff575a008194070c82Ashwin                return result;
127189a9a4cffbcee6af504c61ff575a008194070c82Ashwin            }
12722b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin            result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_FLAGS, ssid_list[i].flags);
127389a9a4cffbcee6af504c61ff575a008194070c82Ashwin            if (result < 0) {
127489a9a4cffbcee6af504c61ff575a008194070c82Ashwin                return result;
127589a9a4cffbcee6af504c61ff575a008194070c82Ashwin            }
12762b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin            result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_AUTH, ssid_list[i].auth_bit_field);
127789a9a4cffbcee6af504c61ff575a008194070c82Ashwin            if (result < 0) {
127889a9a4cffbcee6af504c61ff575a008194070c82Ashwin                return result;
127989a9a4cffbcee6af504c61ff575a008194070c82Ashwin            }
128089a9a4cffbcee6af504c61ff575a008194070c82Ashwin            request.attr_end(attr2);
128189a9a4cffbcee6af504c61ff575a008194070c82Ashwin        }
128289a9a4cffbcee6af504c61ff575a008194070c82Ashwin        request.attr_end(attr);
128389a9a4cffbcee6af504c61ff575a008194070c82Ashwin        request.attr_end(data);
128489a9a4cffbcee6af504c61ff575a008194070c82Ashwin        return result;
128589a9a4cffbcee6af504c61ff575a008194070c82Ashwin    }
128689a9a4cffbcee6af504c61ff575a008194070c82Ashwin
128789a9a4cffbcee6af504c61ff575a008194070c82Ashwin    int createTeardownRequest(WifiRequest& request) {
128889a9a4cffbcee6af504c61ff575a008194070c82Ashwin        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_EPNO_SSID);
128989a9a4cffbcee6af504c61ff575a008194070c82Ashwin        if (result < 0) {
129089a9a4cffbcee6af504c61ff575a008194070c82Ashwin            return result;
129189a9a4cffbcee6af504c61ff575a008194070c82Ashwin        }
129289a9a4cffbcee6af504c61ff575a008194070c82Ashwin
129389a9a4cffbcee6af504c61ff575a008194070c82Ashwin        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
129489a9a4cffbcee6af504c61ff575a008194070c82Ashwin        result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_FLUSH, 1);
129589a9a4cffbcee6af504c61ff575a008194070c82Ashwin        if (result < 0) {
129689a9a4cffbcee6af504c61ff575a008194070c82Ashwin            return result;
129789a9a4cffbcee6af504c61ff575a008194070c82Ashwin        }
129889a9a4cffbcee6af504c61ff575a008194070c82Ashwin        request.attr_end(data);
129989a9a4cffbcee6af504c61ff575a008194070c82Ashwin        return result;
130089a9a4cffbcee6af504c61ff575a008194070c82Ashwin    }
130189a9a4cffbcee6af504c61ff575a008194070c82Ashwin
130289a9a4cffbcee6af504c61ff575a008194070c82Ashwin    int start() {
13032b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        ALOGI("Executing ePNO setup request, num = %d", epno_params.num_networks);
130489a9a4cffbcee6af504c61ff575a008194070c82Ashwin        WifiRequest request(familyId(), ifaceId());
130589a9a4cffbcee6af504c61ff575a008194070c82Ashwin        int result = createSetupRequest(request);
130689a9a4cffbcee6af504c61ff575a008194070c82Ashwin        if (result < 0) {
130789a9a4cffbcee6af504c61ff575a008194070c82Ashwin            return result;
130889a9a4cffbcee6af504c61ff575a008194070c82Ashwin        }
130989a9a4cffbcee6af504c61ff575a008194070c82Ashwin
131089a9a4cffbcee6af504c61ff575a008194070c82Ashwin        result = requestResponse(request);
131189a9a4cffbcee6af504c61ff575a008194070c82Ashwin        if (result < 0) {
131289a9a4cffbcee6af504c61ff575a008194070c82Ashwin            ALOGI("Failed to execute ePNO setup request, result = %d", result);
131389a9a4cffbcee6af504c61ff575a008194070c82Ashwin            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT);
131489a9a4cffbcee6af504c61ff575a008194070c82Ashwin            return result;
131589a9a4cffbcee6af504c61ff575a008194070c82Ashwin        }
131689a9a4cffbcee6af504c61ff575a008194070c82Ashwin
13172b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        ALOGI("Successfully set %d SSIDs for ePNO", epno_params.num_networks);
131889a9a4cffbcee6af504c61ff575a008194070c82Ashwin        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT);
131989a9a4cffbcee6af504c61ff575a008194070c82Ashwin        ALOGI("successfully restarted the scan");
132089a9a4cffbcee6af504c61ff575a008194070c82Ashwin        return result;
132189a9a4cffbcee6af504c61ff575a008194070c82Ashwin    }
132289a9a4cffbcee6af504c61ff575a008194070c82Ashwin
132389a9a4cffbcee6af504c61ff575a008194070c82Ashwin    virtual int cancel() {
132489a9a4cffbcee6af504c61ff575a008194070c82Ashwin        /* unregister event handler */
132589a9a4cffbcee6af504c61ff575a008194070c82Ashwin        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT);
132689a9a4cffbcee6af504c61ff575a008194070c82Ashwin        /* create set hotlist message with empty hotlist */
132789a9a4cffbcee6af504c61ff575a008194070c82Ashwin        WifiRequest request(familyId(), ifaceId());
132889a9a4cffbcee6af504c61ff575a008194070c82Ashwin        int result = createTeardownRequest(request);
132989a9a4cffbcee6af504c61ff575a008194070c82Ashwin        if (result < 0) {
133089a9a4cffbcee6af504c61ff575a008194070c82Ashwin            return result;
133189a9a4cffbcee6af504c61ff575a008194070c82Ashwin        }
133289a9a4cffbcee6af504c61ff575a008194070c82Ashwin
133389a9a4cffbcee6af504c61ff575a008194070c82Ashwin        result = requestResponse(request);
133489a9a4cffbcee6af504c61ff575a008194070c82Ashwin        if (result < 0) {
133589a9a4cffbcee6af504c61ff575a008194070c82Ashwin            return result;
133689a9a4cffbcee6af504c61ff575a008194070c82Ashwin        }
133789a9a4cffbcee6af504c61ff575a008194070c82Ashwin
133889a9a4cffbcee6af504c61ff575a008194070c82Ashwin        ALOGI("Successfully reset APs in current hotlist");
133989a9a4cffbcee6af504c61ff575a008194070c82Ashwin        return result;
134089a9a4cffbcee6af504c61ff575a008194070c82Ashwin    }
134189a9a4cffbcee6af504c61ff575a008194070c82Ashwin
134289a9a4cffbcee6af504c61ff575a008194070c82Ashwin    virtual int handleResponse(WifiEvent& reply) {
134389a9a4cffbcee6af504c61ff575a008194070c82Ashwin        /* Nothing to do on response! */
134489a9a4cffbcee6af504c61ff575a008194070c82Ashwin        return NL_SKIP;
134589a9a4cffbcee6af504c61ff575a008194070c82Ashwin    }
134689a9a4cffbcee6af504c61ff575a008194070c82Ashwin
134789a9a4cffbcee6af504c61ff575a008194070c82Ashwin    virtual int handleEvent(WifiEvent& event) {
134889a9a4cffbcee6af504c61ff575a008194070c82Ashwin        ALOGI("ePNO event");
134989a9a4cffbcee6af504c61ff575a008194070c82Ashwin        int event_id = event.get_vendor_subcmd();
135089a9a4cffbcee6af504c61ff575a008194070c82Ashwin        // event.log();
135189a9a4cffbcee6af504c61ff575a008194070c82Ashwin
135289a9a4cffbcee6af504c61ff575a008194070c82Ashwin        nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
135389a9a4cffbcee6af504c61ff575a008194070c82Ashwin        int len = event.get_vendor_data_len();
135489a9a4cffbcee6af504c61ff575a008194070c82Ashwin
135589a9a4cffbcee6af504c61ff575a008194070c82Ashwin        if (vendor_data == NULL || len == 0) {
135689a9a4cffbcee6af504c61ff575a008194070c82Ashwin            ALOGI("No scan results found");
135789a9a4cffbcee6af504c61ff575a008194070c82Ashwin            return NL_SKIP;
135889a9a4cffbcee6af504c61ff575a008194070c82Ashwin        }
135989a9a4cffbcee6af504c61ff575a008194070c82Ashwin
13602b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        memset(mResults, 0, sizeof(wifi_scan_result) * MAX_EPNO_NETWORKS);
136189a9a4cffbcee6af504c61ff575a008194070c82Ashwin
13622b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        unsigned int num = len / sizeof(wifi_pno_result_t);
13632b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        unsigned int i;
13642b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        num = min(MAX_EPNO_NETWORKS, num);
136589a9a4cffbcee6af504c61ff575a008194070c82Ashwin        wifi_pno_result_t *res = (wifi_pno_result_t *) event.get_vendor_data();
136689a9a4cffbcee6af504c61ff575a008194070c82Ashwin        for (i = 0; i < num; i++) {
136789a9a4cffbcee6af504c61ff575a008194070c82Ashwin            if (res[i].flags == PNO_SSID_FOUND) {
136889a9a4cffbcee6af504c61ff575a008194070c82Ashwin                memcpy(mResults[i].ssid, res[i].ssid, res[i].ssid_len);
136925a0fb843d8b6d9141ccb435f1f9ee9a29d3afc6Ashwin                memcpy(mResults[i].bssid, res[i].bssid, sizeof(mac_addr));
137025a0fb843d8b6d9141ccb435f1f9ee9a29d3afc6Ashwin
137189a9a4cffbcee6af504c61ff575a008194070c82Ashwin                mResults[i].ssid[res[i].ssid_len] = '\0';
137289a9a4cffbcee6af504c61ff575a008194070c82Ashwin                mResults[i].channel = res[i].channel;
137389a9a4cffbcee6af504c61ff575a008194070c82Ashwin                mResults[i].rssi = res[i].rssi;
137489a9a4cffbcee6af504c61ff575a008194070c82Ashwin            }
137589a9a4cffbcee6af504c61ff575a008194070c82Ashwin        }
137689a9a4cffbcee6af504c61ff575a008194070c82Ashwin        if (*mHandler.on_network_found)
137789a9a4cffbcee6af504c61ff575a008194070c82Ashwin            (*mHandler.on_network_found)(id(), num, mResults);
137889a9a4cffbcee6af504c61ff575a008194070c82Ashwin        return NL_SKIP;
137989a9a4cffbcee6af504c61ff575a008194070c82Ashwin    }
138089a9a4cffbcee6af504c61ff575a008194070c82Ashwin};
138189a9a4cffbcee6af504c61ff575a008194070c82Ashwin
13821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_set_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface,
13831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler)
13841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
13851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_handle handle = getWifiHandle(iface);
13861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
13871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    BssidHotlistCommand *cmd = new BssidHotlistCommand(iface, id, params, handler);
13886af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
13896af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    wifi_error result = wifi_register_cmd(handle, id, cmd);
13906af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    if (result != WIFI_SUCCESS) {
13916af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
13926af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
13936af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    }
13946af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    result = (wifi_error)cmd->start();
1395a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann    if (result != WIFI_SUCCESS) {
1396a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        wifi_unregister_cmd(handle, id);
13976af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
13986af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
1399a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann    }
1400a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann    return result;
14011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
14021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
14031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_reset_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface)
14041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
1405fef13c11034313585be68c32322b9a53c43a37b2Ashwin    return wifi_cancel_cmd(id, iface);
14061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
14071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
14081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
14091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde/////////////////////////////////////////////////////////////////////////////
14101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
14111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass SignificantWifiChangeCommand : public WifiCommand
14121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
1413e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande    typedef struct {
1414e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande        mac_addr bssid;                     // BSSID
1415e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande        wifi_channel channel;               // channel frequency in MHz
1416e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande        int num_rssi;                       // number of rssi samples
1417e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande        wifi_rssi rssi[8];                   // RSSI history in db
1418e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande    } wifi_significant_change_result_internal;
1419e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande
14201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeprivate:
14211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_significant_change_params mParams;
14221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_significant_change_handler mHandler;
14231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    static const int MAX_RESULTS = 64;
1424e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande    wifi_significant_change_result_internal mResultsBuffer[MAX_RESULTS];
1425e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande    wifi_significant_change_result *mResults[MAX_RESULTS];
14261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic:
14271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    SignificantWifiChangeCommand(wifi_interface_handle handle, int id,
14281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            wifi_significant_change_params params, wifi_significant_change_handler handler)
1429d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("SignificantWifiChangeCommand", handle, id), mParams(params),
1430d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande            mHandler(handler)
14311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    { }
14321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
14331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int createSetupRequest(WifiRequest& request) {
14341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG);
14351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
14361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
14371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
14381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
14391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
14401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = request.put_u8(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1);
14411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
14421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
14431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
14441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = request.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE, mParams.rssi_sample_size);
14451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
14461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
14471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
14481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = request.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size);
14491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
14501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
14511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
14521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = request.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING, mParams.min_breaching);
14531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
14541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
14551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
1456f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song        result = request.put_u16(GSCAN_ATTRIBUTE_NUM_BSSID, mParams.num_bssid);
1457f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song        if (result < 0) {
1458f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song            return result;
1459f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song        }
1460f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song        if (mParams.num_bssid != 0) {
1461f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song            nlattr* attr = request.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS);
1462f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song            if (attr == NULL) {
14631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                return WIFI_ERROR_OUT_OF_MEMORY;
14641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
1465f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song
1466f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song            for (int i = 0; i < mParams.num_bssid; i++) {
1467f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song                nlattr* attr2 = request.attr_start(i);
1468f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song                if (attr2 == NULL) {
1469f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song                    return WIFI_ERROR_OUT_OF_MEMORY;
1470f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song                }
1471f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song                result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid);
1472f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song                if (result < 0) {
1473f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song                    return result;
1474f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song                }
1475f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song                result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high);
1476f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song                if (result < 0) {
1477f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song                    return result;
1478f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song                }
1479f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song                result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low);
1480f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song                if (result < 0) {
1481f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song                    return result;
1482f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song                }
1483f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song                request.attr_end(attr2);
14841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
14851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
1486f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song            request.attr_end(attr);
1487f57fbe161190c2910c349b2b3af0b9b27c6a1c91Insun Song        }
14881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        request.attr_end(data);
14891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
14901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return result;
14911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
14921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
14931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int createTeardownRequest(WifiRequest& request) {
14941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG);
14951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
14961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
14971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
14981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
14991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
15001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = request.put_u16(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1);
15011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
15021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
15031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
15041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        request.attr_end(data);
15061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return result;
15071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
15081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int start() {
15101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGI("Set significant wifi change config");
15111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        WifiRequest request(familyId(), ifaceId());
15121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = createSetupRequest(request);
15141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
15151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
15161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
15171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = requestResponse(request);
15191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
15201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGI("failed to set significant wifi change config %d", result);
15211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
15221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
15231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGI("successfully set significant wifi change config");
15251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
15271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
15281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
15291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
15301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
15321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = requestResponse(request);
15341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
15351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
15361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
15371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
15381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGI("successfully restarted the scan");
15401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return result;
15411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
15421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int cancel() {
15441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        /* unregister event handler */
15451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
15461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        /* create set significant change monitor message with empty hotlist */
15481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        WifiRequest request(familyId(), ifaceId());
15491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int result = createTeardownRequest(request);
15511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
15521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
15531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
15541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        result = requestResponse(request);
15561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
15571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return result;
15581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
15591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGI("successfully reset significant wifi change config");
15611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return result;
15621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
15631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int handleResponse(WifiEvent& reply) {
15651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        /* Nothing to do on response! */
15661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return NL_SKIP;
15671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
15681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int handleEvent(WifiEvent& event) {
1570a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        ALOGV("Got a significant wifi change event");
15711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
15731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int len = event.get_vendor_data_len();
15741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (vendor_data == NULL || len == 0) {
15761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGI("No scan results found");
15771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return NL_SKIP;
15781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
15791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        typedef struct {
15811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            uint16_t flags;
15821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            uint16_t channel;
15831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            mac_addr bssid;
15849a23388d5a9f58f106169700bb179de0a4af7840Ashwin            s8 rssi_history[8];
15851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        } ChangeInfo;
15861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int num = min(len / sizeof(ChangeInfo), MAX_RESULTS);
15881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ChangeInfo *ci = (ChangeInfo *)event.get_vendor_data();
15891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
15901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        for (int i = 0; i < num; i++) {
1591e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande            memcpy(mResultsBuffer[i].bssid, ci[i].bssid, sizeof(mac_addr));
1592e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande            mResultsBuffer[i].channel = ci[i].channel;
1593e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande            mResultsBuffer[i].num_rssi = 8;
15949a23388d5a9f58f106169700bb179de0a4af7840Ashwin            for (int j = 0; j < mResultsBuffer[i].num_rssi; j++)
15959a23388d5a9f58f106169700bb179de0a4af7840Ashwin                mResultsBuffer[i].rssi[j] = (int) ci[i].rssi_history[j];
1596e165f3a9d7d77eed0ae55bebf885d9a879a9349cVinit Deshpande            mResults[i] = reinterpret_cast<wifi_significant_change_result *>(&(mResultsBuffer[i]));
15971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
15981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
1599a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        ALOGV("Retrieved %d scan results", num);
16001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
16011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (num != 0) {
16021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            (*mHandler.on_significant_change)(id(), num, mResults);
16031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        } else {
16041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGW("No significant change reported");
16051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
16061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
16071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return NL_SKIP;
16081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
16091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde};
16101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
16111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_set_significant_change_handler(wifi_request_id id, wifi_interface_handle iface,
16121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        wifi_significant_change_params params, wifi_significant_change_handler handler)
16131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
16141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_handle handle = getWifiHandle(iface);
16151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
16161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    SignificantWifiChangeCommand *cmd = new SignificantWifiChangeCommand(
16171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            iface, id, params, handler);
16186af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
16196af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    wifi_error result = wifi_register_cmd(handle, id, cmd);
16206af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    if (result != WIFI_SUCCESS) {
16216af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
16226af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
16236af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    }
16246af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    result = (wifi_error)cmd->start();
1625a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann    if (result != WIFI_SUCCESS) {
1626a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        wifi_unregister_cmd(handle, id);
16276af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
16286af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
1629a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann    }
1630a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann    return result;
16311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
16321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
16331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface)
16341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
1635fef13c11034313585be68c32322b9a53c43a37b2Ashwin    return wifi_cancel_cmd(id, iface);
16361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
163789a9a4cffbcee6af504c61ff575a008194070c82Ashwin
163889a9a4cffbcee6af504c61ff575a008194070c82Ashwinwifi_error wifi_reset_epno_list(wifi_request_id id, wifi_interface_handle iface)
163989a9a4cffbcee6af504c61ff575a008194070c82Ashwin{
16402b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    if (id == -1) {
16412b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        wifi_epno_handler handler;
16422b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        wifi_handle handle = getWifiHandle(iface);
16432b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin
16442b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        memset(&handler, 0, sizeof(handler));
16452b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        ePNOCommand *cmd = new ePNOCommand(iface, id, NULL, handler);
16466af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
16472b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        cmd->cancel();
16482b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        cmd->releaseRef();
16492b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        return WIFI_SUCCESS;
16502b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    }
1651fef13c11034313585be68c32322b9a53c43a37b2Ashwin    return wifi_cancel_cmd(id, iface);
165289a9a4cffbcee6af504c61ff575a008194070c82Ashwin}
16532672aa697b5dea852e9c3cc210ff2ee3a075d97cPierre Vandwalle
16542672aa697b5dea852e9c3cc210ff2ee3a075d97cPierre Vandwallewifi_error wifi_set_epno_list(wifi_request_id id, wifi_interface_handle iface,
165589296a7fc953e68649cdb1366d22376c034ace05Mitchell Wills        const wifi_epno_params *params, wifi_epno_handler handler)
16562672aa697b5dea852e9c3cc210ff2ee3a075d97cPierre Vandwalle{
16576af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    wifi_handle handle = getWifiHandle(iface);
16586af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma
16596af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    ePNOCommand *cmd = new ePNOCommand(iface, id, params, handler);
16606af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
16616af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    wifi_error result = wifi_register_cmd(handle, id, cmd);
16626af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    if (result != WIFI_SUCCESS) {
16636af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
16646af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
16656af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    }
16666af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    result = (wifi_error)cmd->start();
16676af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    if (result != WIFI_SUCCESS) {
16686af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        wifi_unregister_cmd(handle, id);
16696af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
16706af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
16716af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    }
16726af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    return result;
16732672aa697b5dea852e9c3cc210ff2ee3a075d97cPierre Vandwalle}
16742672aa697b5dea852e9c3cc210ff2ee3a075d97cPierre Vandwalle
1675810c949db9c60baa02684a50d71026727c357cd2Ashwin
1676f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng////////////////////////////////////////////////////////////////////////////////
1677f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1678f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ngclass AnqpoConfigureCommand : public WifiCommand
1679f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng{
1680f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    int num_hs;
1681f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    wifi_passpoint_network *mNetworks;
1682f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    wifi_passpoint_event_handler mHandler;
16832b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin    wifi_scan_result *mResult;
1684f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ngpublic:
1685f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    AnqpoConfigureCommand(wifi_request_id id, wifi_interface_handle iface,
1686f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        int num, wifi_passpoint_network *hs_list, wifi_passpoint_event_handler handler)
1687d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("AnqpoConfigureCommand", iface, id), num_hs(num), mNetworks(hs_list),
1688d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande            mHandler(handler)
1689f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    {
16902b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        mResult = NULL;
1691f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    }
1692f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1693f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    int createRequest(WifiRequest& request, int val) {
1694f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1695f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_ANQPO_CONFIG);
1696f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        result = request.put_u32(GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE, num_hs);
1697f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        if (result < 0) {
1698f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            return result;
1699f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        }
1700f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1701f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1702f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1703f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_ANQPO_HS_LIST);
1704f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        for (int i = 0; i < num_hs; i++) {
1705f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            nlattr *attr2 = request.attr_start(i);
1706f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            if (attr2 == NULL) {
1707f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng                return WIFI_ERROR_OUT_OF_MEMORY;
1708f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            }
1709f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            result = request.put_u32(GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID, mNetworks[i].id);
1710f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            if (result < 0) {
1711f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng                return result;
1712f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            }
1713f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM, mNetworks[i].realm, 256);
1714f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            if (result < 0) {
1715f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng                return result;
1716f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            }
1717f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID,
1718f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng                         mNetworks[i].roamingConsortiumIds, 128);
1719f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            if (result < 0) {
1720f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng                return result;
1721f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            }
1722f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_PLMN, mNetworks[i].plmn, 3);
1723f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            if (result < 0) {
1724f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng                return result;
1725f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            }
1726f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1727f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            request.attr_end(attr2);
1728f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        }
1729f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1730f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        request.attr_end(attr);
1731f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        request.attr_end(data);
1732f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1733f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        return WIFI_SUCCESS;
1734f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    }
1735f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1736f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    int start() {
1737f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1738f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        WifiRequest request(familyId(), ifaceId());
1739f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        int result = createRequest(request, num_hs);
1740f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        if (result != WIFI_SUCCESS) {
1741f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            ALOGE("failed to create request; result = %d", result);
1742f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            return result;
1743f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        }
1744f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1745f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH);
1746f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1747f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        result = requestResponse(request);
1748f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        if (result != WIFI_SUCCESS) {
1749f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            ALOGE("failed to set ANQPO networks; result = %d", result);
1750f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH);
1751f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            return result;
1752f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        }
1753f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1754f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        return result;
1755f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    }
1756f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1757f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    virtual int cancel() {
1758f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1759f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        WifiRequest request(familyId(), ifaceId());
1760f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        int result = createRequest(request, 0);
1761f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        if (result != WIFI_SUCCESS) {
1762f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            ALOGE("failed to create request; result = %d", result);
1763f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        } else {
1764f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            result = requestResponse(request);
1765f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            if (result != WIFI_SUCCESS) {
1766f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng                ALOGE("failed to reset ANQPO networks;result = %d", result);
1767f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            }
1768f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        }
1769f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1770f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH);
1771f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        return WIFI_SUCCESS;
1772f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    }
1773f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1774f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    virtual int handleResponse(WifiEvent& reply) {
1775f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng         ALOGD("Request complete!");
1776f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        /* Nothing to do on response! */
1777f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        return NL_SKIP;
1778f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    }
1779f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1780f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    virtual int handleEvent(WifiEvent& event) {
1781f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        typedef struct {
1782f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            u16 channel;        /* channel of GAS protocol */
1783f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            u8  dialog_token;   /* GAS dialog token */
1784f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            u8  fragment_id;    /* fragment id */
1785f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            u16 status_code;    /* status code on GAS completion */
1786f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            u16 data_len;       /* length of data to follow */
1787f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            u8  data[1];        /* variable length specified by data_len */
1788f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        } wifi_anqp_gas_resp;
1789f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1790f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        ALOGI("ANQPO hotspot matched event!");
1791f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1792f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
1793f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        unsigned int len = event.get_vendor_data_len();
1794f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1795f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        if (vendor_data == NULL || len < sizeof(wifi_scan_result)) {
1796f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            ALOGI("No scan results found");
1797f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng            return NL_SKIP;
1798f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        }
17992b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        mResult = (wifi_scan_result *)malloc(sizeof(wifi_scan_result));
18002b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        if (!mResult) {
18012b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin            return NL_SKIP;
18022b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        }
18032b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        wifi_gscan_full_result_t *drv_res = (wifi_gscan_full_result_t *)event.get_vendor_data();
18042b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        wifi_gscan_result_t *fixed = &drv_res->fixed;
18052b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        convert_to_hal_result(mResult, fixed);
1806f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
18072b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        byte *anqp = (byte *)drv_res + offsetof(wifi_gscan_full_result_t, ie_data) + drv_res->ie_length;
1808f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        wifi_anqp_gas_resp *gas = (wifi_anqp_gas_resp *)anqp;
1809f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        int anqp_len = offsetof(wifi_anqp_gas_resp, data) + gas->data_len;
1810f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        int networkId = *(int *)((byte *)anqp + anqp_len);
1811f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
18122b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        ALOGI("%-32s\t", mResult->ssid);
1813f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
18142b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        ALOGI("%02x:%02x:%02x:%02x:%02x:%02x ", mResult->bssid[0], mResult->bssid[1],
18152b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin                mResult->bssid[2], mResult->bssid[3], mResult->bssid[4], mResult->bssid[5]);
1816f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
18172b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        ALOGI("%d\t", mResult->rssi);
18182b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        ALOGI("%d\t", mResult->channel);
18192b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        ALOGI("%lld\t", mResult->ts);
18202b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        ALOGI("%lld\t", mResult->rtt);
18212b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        ALOGI("%lld\n", mResult->rtt_sd);
1822f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1823f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        if(*mHandler.on_passpoint_network_found)
18242b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin            (*mHandler.on_passpoint_network_found)(id(), networkId, mResult, anqp_len, anqp);
18252b31c56930bc154d639da4ff2f56c34ef61688e5Ashwin        free(mResult);
1826f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        return NL_SKIP;
1827f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    }
1828f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng};
1829f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1830f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ngwifi_error wifi_set_passpoint_list(wifi_request_id id, wifi_interface_handle iface, int num,
1831f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng        wifi_passpoint_network *networks, wifi_passpoint_event_handler handler)
1832f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng{
1833f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    wifi_handle handle = getWifiHandle(iface);
1834f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1835f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng    AnqpoConfigureCommand *cmd = new AnqpoConfigureCommand(id, iface, num, networks, handler);
18366af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
18376af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    wifi_error result = wifi_register_cmd(handle, id, cmd);
18386af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    if (result != WIFI_SUCCESS) {
18396af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
18406af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
18416af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    }
18426af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    result = (wifi_error)cmd->start();
1843a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann    if (result != WIFI_SUCCESS) {
1844a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann        wifi_unregister_cmd(handle, id);
18456af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
18466af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
1847a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann    }
1848a0a6b2113b44aa39f25635f291fba929c98070bdNavtej Singh Mann    return result;
1849f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng}
1850f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng
1851f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ngwifi_error wifi_reset_passpoint_list(wifi_request_id id, wifi_interface_handle iface)
1852f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng{
1853fef13c11034313585be68c32322b9a53c43a37b2Ashwin    return wifi_cancel_cmd(id, iface);
1854f02e958d58bc49a8f228927dfb261fe57d080560Chilam Ng}
1855