Home | History | Annotate | Download | only in wifi_hal
      1 
      2 #include <stdint.h>
      3 #include <fcntl.h>
      4 #include <sys/socket.h>
      5 #include <netlink/genl/genl.h>
      6 #include <netlink/genl/family.h>
      7 #include <netlink/genl/ctrl.h>
      8 #include <linux/rtnetlink.h>
      9 #include <netpacket/packet.h>
     10 #include <linux/filter.h>
     11 #include <linux/errqueue.h>
     12 
     13 #include <linux/pkt_sched.h>
     14 #include <netlink/object-api.h>
     15 #include <netlink/netlink.h>
     16 #include <netlink/socket.h>
     17 #include <netlink/handlers.h>
     18 
     19 #include "sync.h"
     20 
     21 #define LOG_TAG  "WifiHAL"
     22 //#define LOG_NDEBUG 0         //uncomment to enable verbose logging
     23 
     24 #include <utils/Log.h>
     25 
     26 #include "wifi_hal.h"
     27 #include "common.h"
     28 #include "cpp_bindings.h"
     29 
     30 typedef enum {
     31 
     32     GSCAN_ATTRIBUTE_NUM_BUCKETS = 10,
     33     GSCAN_ATTRIBUTE_BASE_PERIOD,
     34     GSCAN_ATTRIBUTE_BUCKETS_BAND,
     35     GSCAN_ATTRIBUTE_BUCKET_ID,
     36     GSCAN_ATTRIBUTE_BUCKET_PERIOD,
     37     GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS,
     38     GSCAN_ATTRIBUTE_BUCKET_CHANNELS,
     39     GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN,
     40     GSCAN_ATTRIBUTE_REPORT_THRESHOLD,
     41     GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE,
     42     GSCAN_ATTRIBUTE_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND,
     43 
     44     GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20,
     45     GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE,              /* indicates no more results */
     46     GSCAN_ATTRIBUTE_FLUSH_FEATURE,                      /* Flush all the configs */
     47     GSCAN_ENABLE_FULL_SCAN_RESULTS,
     48     GSCAN_ATTRIBUTE_REPORT_EVENTS,
     49 
     50     /* remaining reserved for additional attributes */
     51     GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30,
     52     GSCAN_ATTRIBUTE_FLUSH_RESULTS,
     53     GSCAN_ATTRIBUTE_SCAN_RESULTS,                       /* flat array of wifi_scan_result */
     54     GSCAN_ATTRIBUTE_SCAN_ID,                            /* indicates scan number */
     55     GSCAN_ATTRIBUTE_SCAN_FLAGS,                         /* indicates if scan was aborted */
     56     GSCAN_ATTRIBUTE_AP_FLAGS,                           /* flags on significant change event */
     57     GSCAN_ATTRIBUTE_NUM_CHANNELS,
     58     GSCAN_ATTRIBUTE_CHANNEL_LIST,
     59     GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK,
     60     /* remaining reserved for additional attributes */
     61 
     62     GSCAN_ATTRIBUTE_SSID = 40,
     63     GSCAN_ATTRIBUTE_BSSID,
     64     GSCAN_ATTRIBUTE_CHANNEL,
     65     GSCAN_ATTRIBUTE_RSSI,
     66     GSCAN_ATTRIBUTE_TIMESTAMP,
     67     GSCAN_ATTRIBUTE_RTT,
     68     GSCAN_ATTRIBUTE_RTTSD,
     69 
     70     /* remaining reserved for additional attributes */
     71 
     72     GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50,
     73     GSCAN_ATTRIBUTE_RSSI_LOW,
     74     GSCAN_ATTRIBUTE_RSSI_HIGH,
     75     GSCAN_ATTRIBUTE_HOTLIST_ELEM,
     76     GSCAN_ATTRIBUTE_HOTLIST_FLUSH,
     77     GSCAN_ATTRIBUTE_HOTLIST_BSSID_COUNT,
     78 
     79     /* remaining reserved for additional attributes */
     80     GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60,
     81     GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE,
     82     GSCAN_ATTRIBUTE_MIN_BREACHING,
     83     GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS,
     84     GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH,
     85 
     86     /* EPNO */
     87     GSCAN_ATTRIBUTE_EPNO_SSID_LIST = 70,
     88     GSCAN_ATTRIBUTE_EPNO_SSID,
     89     GSCAN_ATTRIBUTE_EPNO_SSID_LEN,
     90     GSCAN_ATTRIBUTE_EPNO_RSSI,
     91     GSCAN_ATTRIBUTE_EPNO_FLAGS,
     92     GSCAN_ATTRIBUTE_EPNO_AUTH,
     93     GSCAN_ATTRIBUTE_EPNO_SSID_NUM,
     94     GSCAN_ATTRIBUTE_EPNO_FLUSH,
     95 
     96     /* remaining reserved for additional attributes */
     97 
     98     GSCAN_ATTRIBUTE_WHITELIST_SSID = 80,
     99     GSCAN_ATTRIBUTE_NUM_WL_SSID,
    100     GSCAN_ATTRIBUTE_WL_SSID_LEN,
    101     GSCAN_ATTRIBUTE_WL_SSID_FLUSH,
    102     GSCAN_ATTRIBUTE_WHITELIST_SSID_ELEM,
    103     GSCAN_ATTRIBUTE_NUM_BSSID,
    104     GSCAN_ATTRIBUTE_BSSID_PREF_LIST,
    105     GSCAN_ATTRIBUTE_BSSID_PREF_FLUSH,
    106     GSCAN_ATTRIBUTE_BSSID_PREF,
    107     GSCAN_ATTRIBUTE_RSSI_MODIFIER,
    108 
    109     /* remaining reserved for additional attributes */
    110 
    111     GSCAN_ATTRIBUTE_A_BAND_BOOST_THRESHOLD = 90,
    112     GSCAN_ATTRIBUTE_A_BAND_PENALTY_THRESHOLD,
    113     GSCAN_ATTRIBUTE_A_BAND_BOOST_FACTOR,
    114     GSCAN_ATTRIBUTE_A_BAND_PENALTY_FACTOR,
    115     GSCAN_ATTRIBUTE_A_BAND_MAX_BOOST,
    116     GSCAN_ATTRIBUTE_LAZY_ROAM_HYSTERESIS,
    117     GSCAN_ATTRIBUTE_ALERT_ROAM_RSSI_TRIGGER,
    118     GSCAN_ATTRIBUTE_LAZY_ROAM_ENABLE,
    119 
    120     /* BSSID blacklist */
    121     GSCAN_ATTRIBUTE_BSSID_BLACKLIST_FLUSH = 100,
    122     GSCAN_ATTRIBUTE_BLACKLIST_BSSID,
    123 
    124     /* ANQPO */
    125     GSCAN_ATTRIBUTE_ANQPO_HS_LIST = 110,
    126     GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE,
    127     GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID,
    128     GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM,
    129     GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID,
    130     GSCAN_ATTRIBUTE_ANQPO_HS_PLMN,
    131 
    132     /* Adaptive scan attributes */
    133     GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT = 120,
    134     GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD,
    135 
    136     /* ePNO cfg */
    137     GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR = 130,
    138     GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR,
    139     GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX,
    140     GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS,
    141     GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS,
    142     GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS,
    143     GSCAN_ATTRIBUTE_EPNO_5G_BONUS,
    144 
    145     GSCAN_ATTRIBUTE_MAX
    146 
    147 } GSCAN_ATTRIBUTE;
    148 
    149 
    150 // helper methods
    151 wifi_error wifi_enable_full_scan_results(wifi_request_id id, wifi_interface_handle iface,
    152          wifi_scan_result_handler handler);
    153 wifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface);
    154 int wifi_handle_full_scan_event(wifi_request_id id, WifiEvent& event,
    155          wifi_scan_result_handler handler);
    156 void convert_to_hal_result(wifi_scan_result *to, wifi_gscan_result_t *from);
    157 
    158 
    159 void convert_to_hal_result(wifi_scan_result *to, wifi_gscan_result_t *from)
    160 {
    161     to->ts = from->ts;
    162     to->channel = from->channel;
    163     to->rssi = from->rssi;
    164     to->rtt = from->rtt;
    165     to->rtt_sd = from->rtt_sd;
    166     to->beacon_period = from->beacon_period;
    167     to->capability = from->capability;
    168     memcpy(to->ssid, from->ssid, (DOT11_MAX_SSID_LEN+1));
    169     memcpy(&to->bssid, &from->bssid, sizeof(mac_addr));
    170 }
    171 
    172 /////////////////////////////////////////////////////////////////////////////
    173 
    174 class GetCapabilitiesCommand : public WifiCommand
    175 {
    176     wifi_gscan_capabilities *mCapabilities;
    177 public:
    178     GetCapabilitiesCommand(wifi_interface_handle iface, wifi_gscan_capabilities *capabitlites)
    179         : WifiCommand("GetGscanCapabilitiesCommand", iface, 0), mCapabilities(capabitlites)
    180     {
    181         memset(mCapabilities, 0, sizeof(*mCapabilities));
    182     }
    183 
    184     virtual int create() {
    185         ALOGV("Creating message to get scan capablities; iface = %d", mIfaceInfo->id);
    186 
    187         int ret = mMsg.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_CAPABILITIES);
    188         if (ret < 0) {
    189             return ret;
    190         }
    191 
    192         return ret;
    193     }
    194 
    195 protected:
    196     virtual int handleResponse(WifiEvent& reply) {
    197 
    198         ALOGV("In GetCapabilities::handleResponse");
    199 
    200         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
    201             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
    202             return NL_SKIP;
    203         }
    204 
    205         int id = reply.get_vendor_id();
    206         int subcmd = reply.get_vendor_subcmd();
    207 
    208         void *data = reply.get_vendor_data();
    209         int len = reply.get_vendor_data_len();
    210 
    211         ALOGV("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len,
    212                     sizeof(*mCapabilities));
    213 
    214         memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities)));
    215 
    216         return NL_OK;
    217     }
    218 };
    219 
    220 
    221 wifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle,
    222         wifi_gscan_capabilities *capabilities)
    223 {
    224     GetCapabilitiesCommand command(handle, capabilities);
    225     return (wifi_error) command.requestResponse();
    226 }
    227 
    228 class GetChannelListCommand : public WifiCommand
    229 {
    230     wifi_channel *channels;
    231     int max_channels;
    232     int *num_channels;
    233     int band;
    234 public:
    235     GetChannelListCommand(wifi_interface_handle iface, wifi_channel *channel_buf, int *ch_num,
    236         int num_max_ch, int band)
    237         : WifiCommand("GetChannelListCommand", iface, 0), channels(channel_buf),
    238             max_channels(num_max_ch), num_channels(ch_num), band(band)
    239     {
    240         memset(channels, 0, sizeof(wifi_channel) * max_channels);
    241     }
    242     virtual int create() {
    243         ALOGV("Creating message to get channel list; iface = %d", mIfaceInfo->id);
    244 
    245         int ret = mMsg.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_CHANNEL_LIST);
    246         if (ret < 0) {
    247             return ret;
    248         }
    249 
    250         nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
    251         ret = mMsg.put_u32(GSCAN_ATTRIBUTE_BAND, band);
    252         if (ret < 0) {
    253             return ret;
    254         }
    255 
    256         mMsg.attr_end(data);
    257 
    258         return ret;
    259     }
    260 
    261 protected:
    262     virtual int handleResponse(WifiEvent& reply) {
    263 
    264         ALOGV("In GetChannelList::handleResponse");
    265 
    266         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
    267             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
    268             return NL_SKIP;
    269         }
    270 
    271         int id = reply.get_vendor_id();
    272         int subcmd = reply.get_vendor_subcmd();
    273         int num_channels_to_copy = 0;
    274 
    275         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
    276         int len = reply.get_vendor_data_len();
    277 
    278         ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
    279         if (vendor_data == NULL || len == 0) {
    280             ALOGE("no vendor data in GetChannelList response; ignoring it");
    281             return NL_SKIP;
    282         }
    283 
    284         for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
    285             if (it.get_type() == GSCAN_ATTRIBUTE_NUM_CHANNELS) {
    286                 num_channels_to_copy = it.get_u32();
    287                 ALOGI("Got channel list with %d channels", num_channels_to_copy);
    288                 if(num_channels_to_copy > max_channels)
    289                     num_channels_to_copy = max_channels;
    290                 *num_channels = num_channels_to_copy;
    291             } else if (it.get_type() == GSCAN_ATTRIBUTE_CHANNEL_LIST && num_channels_to_copy) {
    292                 memcpy(channels, it.get_data(), sizeof(int) * num_channels_to_copy);
    293             } else {
    294                 ALOGW("Ignoring invalid attribute type = %d, size = %d",
    295                         it.get_type(), it.get_len());
    296             }
    297         }
    298 
    299         return NL_OK;
    300     }
    301 };
    302 
    303 wifi_error wifi_get_valid_channels(wifi_interface_handle handle,
    304         int band, int max_channels, wifi_channel *channels, int *num_channels)
    305 {
    306     GetChannelListCommand command(handle, channels, num_channels,
    307                                         max_channels, band);
    308     return (wifi_error) command.requestResponse();
    309 }
    310 /////////////////////////////////////////////////////////////////////////////
    311 
    312 /* helper functions */
    313 
    314 static int parseScanResults(wifi_scan_result *results, int num, nlattr *attr)
    315 {
    316     memset(results, 0, sizeof(wifi_scan_result) * num);
    317 
    318     int i = 0;
    319     for (nl_iterator it(attr); it.has_next() && i < num; it.next(), i++) {
    320 
    321         int index = it.get_type();
    322         ALOGI("retrieved scan result %d", index);
    323         nlattr *sc_data = (nlattr *) it.get_data();
    324         wifi_scan_result *result = results + i;
    325 
    326         for (nl_iterator it2(sc_data); it2.has_next(); it2.next()) {
    327             int type = it2.get_type();
    328             if (type == GSCAN_ATTRIBUTE_SSID) {
    329                 strncpy(result->ssid, (char *) it2.get_data(), it2.get_len());
    330                 result->ssid[it2.get_len()] = 0;
    331             } else if (type == GSCAN_ATTRIBUTE_BSSID) {
    332                 memcpy(result->bssid, (byte *) it2.get_data(), sizeof(mac_addr));
    333             } else if (type == GSCAN_ATTRIBUTE_TIMESTAMP) {
    334                 result->ts = it2.get_u64();
    335             } else if (type == GSCAN_ATTRIBUTE_CHANNEL) {
    336                 result->ts = it2.get_u16();
    337             } else if (type == GSCAN_ATTRIBUTE_RSSI) {
    338                 result->rssi = it2.get_u8();
    339             } else if (type == GSCAN_ATTRIBUTE_RTT) {
    340                 result->rtt = it2.get_u64();
    341             } else if (type == GSCAN_ATTRIBUTE_RTTSD) {
    342                 result->rtt_sd = it2.get_u64();
    343             }
    344         }
    345 
    346     }
    347 
    348     if (i >= num) {
    349         ALOGE("Got too many results; skipping some");
    350     }
    351 
    352     return i;
    353 }
    354 
    355 int createFeatureRequest(WifiRequest& request, int subcmd, int enable) {
    356 
    357     int result = request.create(GOOGLE_OUI, subcmd);
    358     if (result < 0) {
    359         return result;
    360     }
    361 
    362     nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
    363     result = request.put_u32(GSCAN_ATTRIBUTE_ENABLE_FEATURE, enable);
    364     if (result < 0) {
    365         return result;
    366     }
    367 
    368     request.attr_end(data);
    369     return WIFI_SUCCESS;
    370 }
    371 
    372 /////////////////////////////////////////////////////////////////////////////
    373 class FullScanResultsCommand : public WifiCommand
    374 {
    375     int *mParams;
    376     wifi_scan_result_handler mHandler;
    377 public:
    378     FullScanResultsCommand(wifi_interface_handle iface, int id, int *params,
    379                 wifi_scan_result_handler handler)
    380         : WifiCommand("FullScanResultsCommand", iface, id), mParams(params), mHandler(handler)
    381     { }
    382 
    383     int createRequest(WifiRequest& request, int subcmd, int enable) {
    384         int result = request.create(GOOGLE_OUI, subcmd);
    385         if (result < 0) {
    386             return result;
    387         }
    388 
    389         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
    390         result = request.put_u32(GSCAN_ENABLE_FULL_SCAN_RESULTS, enable);
    391         if (result < 0) {
    392             return result;
    393         }
    394 
    395         request.attr_end(data);
    396         return WIFI_SUCCESS;
    397 
    398     }
    399 
    400     int start() {
    401         ALOGV("Enabling Full scan results");
    402         WifiRequest request(familyId(), ifaceId());
    403         int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 1);
    404         if (result != WIFI_SUCCESS) {
    405             ALOGE("failed to create request; result = %d", result);
    406             return result;
    407         }
    408 
    409         registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
    410 
    411         result = requestResponse(request);
    412         if (result != WIFI_SUCCESS) {
    413             ALOGE("failed to enable full scan results; result = %d", result);
    414             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
    415             return result;
    416         }
    417 
    418         return result;
    419     }
    420 
    421     virtual int cancel() {
    422         ALOGV("Disabling Full scan results");
    423 
    424         WifiRequest request(familyId(), ifaceId());
    425         int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 0);
    426         if (result != WIFI_SUCCESS) {
    427             ALOGE("failed to create request; result = %d", result);
    428         } else {
    429             result = requestResponse(request);
    430             if (result != WIFI_SUCCESS) {
    431                 ALOGE("failed to disable full scan results;result = %d", result);
    432             }
    433         }
    434 
    435         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
    436         return WIFI_SUCCESS;
    437     }
    438 
    439     virtual int handleResponse(WifiEvent& reply) {
    440          ALOGD("Request complete!");
    441         /* Nothing to do on response! */
    442         return NL_SKIP;
    443     }
    444 
    445     virtual int handleEvent(WifiEvent& event) {
    446         ALOGV("Full scan results:  Got an event");
    447         return wifi_handle_full_scan_event(id(), event, mHandler);
    448     }
    449 
    450 };
    451 /////////////////////////////////////////////////////////////////////////////
    452 
    453 class ScanCommand : public WifiCommand
    454 {
    455     wifi_scan_cmd_params *mParams;
    456     wifi_scan_result_handler mHandler;
    457 public:
    458     ScanCommand(wifi_interface_handle iface, int id, wifi_scan_cmd_params *params,
    459                 wifi_scan_result_handler handler)
    460         : WifiCommand("ScanCommand", iface, id), mParams(params), mHandler(handler)
    461     { }
    462 
    463     int createSetupRequest(WifiRequest& request) {
    464         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_CONFIG);
    465         if (result < 0) {
    466             return result;
    467         }
    468 
    469         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
    470         result = request.put_u32(GSCAN_ATTRIBUTE_BASE_PERIOD, mParams->base_period);
    471         if (result < 0) {
    472             return result;
    473         }
    474 
    475         result = request.put_u32(GSCAN_ATTRIBUTE_NUM_BUCKETS, mParams->num_buckets);
    476         if (result < 0) {
    477             return result;
    478         }
    479 
    480         for (int i = 0; i < mParams->num_buckets; i++) {
    481             nlattr * bucket = request.attr_start(i);    // next bucket
    482             result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_ID, mParams->buckets[i].bucket);
    483             if (result < 0) {
    484                 return result;
    485             }
    486             result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_PERIOD, mParams->buckets[i].period);
    487             if (result < 0) {
    488                 return result;
    489             }
    490             result = request.put_u32(GSCAN_ATTRIBUTE_BUCKETS_BAND,
    491                     mParams->buckets[i].band);
    492             if (result < 0) {
    493                 return result;
    494             }
    495             result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT,
    496                     mParams->buckets[i].step_count);
    497             if (result < 0) {
    498                 return result;
    499             }
    500             result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD,
    501                     mParams->buckets[i].max_period);
    502             if (result < 0) {
    503                 return result;
    504             }
    505             result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_EVENTS,
    506                     mParams->buckets[i].report_events);
    507             if (result < 0) {
    508                 return result;
    509             }
    510 
    511             result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS,
    512                     mParams->buckets[i].num_channels);
    513             if (result < 0) {
    514                 return result;
    515             }
    516 
    517             if (mParams->buckets[i].num_channels) {
    518                 nlattr *channels = request.attr_start(GSCAN_ATTRIBUTE_BUCKET_CHANNELS);
    519                 ALOGV(" channels: ");
    520                 for (int j = 0; j < mParams->buckets[i].num_channels; j++) {
    521                     result = request.put_u32(j, mParams->buckets[i].channels[j].channel);
    522                     ALOGV(" %u", mParams->buckets[i].channels[j].channel);
    523 
    524                     if (result < 0) {
    525                         return result;
    526                     }
    527                 }
    528                 request.attr_end(channels);
    529             }
    530 
    531             request.attr_end(bucket);
    532         }
    533 
    534         request.attr_end(data);
    535         return WIFI_SUCCESS;
    536     }
    537 
    538     int createScanConfigRequest(WifiRequest& request) {
    539         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SCAN_CONFIG);
    540         if (result < 0) {
    541             return result;
    542         }
    543 
    544         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
    545         result = request.put_u32(GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, mParams->max_ap_per_scan);
    546         if (result < 0) {
    547             return result;
    548         }
    549 
    550         result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD,
    551                 mParams->report_threshold_percent);
    552         if (result < 0) {
    553             return result;
    554         }
    555 
    556         int num_scans = mParams->report_threshold_num_scans;
    557 
    558         result = request.put_u32(GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, num_scans);
    559         if (result < 0) {
    560             return result;
    561         }
    562 
    563         request.attr_end(data);
    564         return WIFI_SUCCESS;
    565     }
    566 
    567     int createStartRequest(WifiRequest& request) {
    568         return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
    569     }
    570 
    571     int createStopRequest(WifiRequest& request) {
    572         return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 0);
    573     }
    574 
    575     int start() {
    576         ALOGV("GSCAN start");
    577         WifiRequest request(familyId(), ifaceId());
    578         int result = createSetupRequest(request);
    579         if (result != WIFI_SUCCESS) {
    580             ALOGE("failed to create setup request; result = %d", result);
    581             return result;
    582         }
    583 
    584         result = requestResponse(request);
    585         if (result != WIFI_SUCCESS) {
    586             ALOGE("failed to configure setup; result = %d", result);
    587             return result;
    588         }
    589 
    590         request.destroy();
    591 
    592         result = createScanConfigRequest(request);
    593         if (result != WIFI_SUCCESS) {
    594             ALOGE("failed to create scan config request; result = %d", result);
    595             return result;
    596         }
    597 
    598         result = requestResponse(request);
    599         if (result != WIFI_SUCCESS) {
    600             ALOGE("failed to configure scan; result = %d", result);
    601             return result;
    602         }
    603 
    604         ALOGV(" ....starting scan");
    605 
    606         result = createStartRequest(request);
    607         if (result != WIFI_SUCCESS) {
    608             ALOGE("failed to create start request; result = %d", result);
    609             return result;
    610         }
    611 
    612         registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
    613         registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
    614         registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
    615 
    616         result = requestResponse(request);
    617         if (result != WIFI_SUCCESS) {
    618             ALOGE("failed to start scan; result = %d", result);
    619             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
    620             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
    621             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
    622             return result;
    623         }
    624         return result;
    625     }
    626 
    627     virtual int cancel() {
    628         ALOGV("Stopping scan");
    629 
    630         WifiRequest request(familyId(), ifaceId());
    631         int result = createStopRequest(request);
    632         if (result != WIFI_SUCCESS) {
    633             ALOGE("failed to create stop request; result = %d", result);
    634         } else {
    635             result = requestResponse(request);
    636             if (result != WIFI_SUCCESS) {
    637                 ALOGE("failed to stop scan; result = %d", result);
    638             }
    639         }
    640 
    641         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
    642         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
    643         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
    644         return WIFI_SUCCESS;
    645     }
    646 
    647     virtual int handleResponse(WifiEvent& reply) {
    648         /* Nothing to do on response! */
    649         return NL_SKIP;
    650     }
    651 
    652     virtual int handleEvent(WifiEvent& event) {
    653         ALOGV("Got a scan results event");
    654         //event.log();
    655 
    656         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
    657         int len = event.get_vendor_data_len();
    658         int event_id = event.get_vendor_subcmd();
    659 
    660         if ((event_id == GSCAN_EVENT_COMPLETE_SCAN) ||
    661             (event_id == GSCAN_EVENT_SCAN_RESULTS_AVAILABLE)) {
    662             if (vendor_data == NULL || len != 4) {
    663                 ALOGI("Bad event data!");
    664                 return NL_SKIP;
    665             }
    666             wifi_scan_event evt_type;
    667             evt_type = (wifi_scan_event) event.get_u32(NL80211_ATTR_VENDOR_DATA);
    668             ALOGV("Received event type %d", evt_type);
    669             if(*mHandler.on_scan_event)
    670                 (*mHandler.on_scan_event)(id(), evt_type);
    671         } else if (event_id == GSCAN_EVENT_FULL_SCAN_RESULTS) {
    672             wifi_handle_full_scan_event(id(), event, mHandler);
    673         }
    674         return NL_SKIP;
    675     }
    676 };
    677 
    678 wifi_error wifi_start_gscan(
    679         wifi_request_id id,
    680         wifi_interface_handle iface,
    681         wifi_scan_cmd_params params,
    682         wifi_scan_result_handler handler)
    683 {
    684     wifi_handle handle = getWifiHandle(iface);
    685 
    686     ALOGV("Starting GScan, halHandle = %p", handle);
    687 
    688     ScanCommand *cmd = new ScanCommand(iface, id, &params, handler);
    689     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
    690     wifi_error result = wifi_register_cmd(handle, id, cmd);
    691     if (result != WIFI_SUCCESS) {
    692         cmd->releaseRef();
    693         return result;
    694     }
    695     result = (wifi_error)cmd->start();
    696     if (result != WIFI_SUCCESS) {
    697         wifi_unregister_cmd(handle, id);
    698         cmd->releaseRef();
    699         return result;
    700     }
    701     return result;
    702 }
    703 
    704 wifi_error wifi_stop_gscan(wifi_request_id id, wifi_interface_handle iface)
    705 {
    706     wifi_handle handle = getWifiHandle(iface);
    707     ALOGV("Stopping GScan, wifi_request_id = %d, halHandle = %p", id, handle);
    708 
    709     if (id == -1) {
    710         wifi_scan_result_handler handler;
    711         wifi_scan_cmd_params dummy_params;
    712         wifi_handle handle = getWifiHandle(iface);
    713         memset(&handler, 0, sizeof(handler));
    714 
    715         ScanCommand *cmd = new ScanCommand(iface, id, &dummy_params, handler);
    716         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
    717         cmd->cancel();
    718         cmd->releaseRef();
    719         return WIFI_SUCCESS;
    720     }
    721 
    722     return wifi_cancel_cmd(id, iface);
    723 }
    724 
    725 wifi_error wifi_enable_full_scan_results(
    726         wifi_request_id id,
    727         wifi_interface_handle iface,
    728         wifi_scan_result_handler handler)
    729 {
    730     wifi_handle handle = getWifiHandle(iface);
    731     int params_dummy;
    732 
    733     ALOGV("Enabling full scan results, halHandle = %p", handle);
    734 
    735     FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, id, &params_dummy, handler);
    736     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
    737     wifi_error result = wifi_register_cmd(handle, id, cmd);
    738     if (result != WIFI_SUCCESS) {
    739         cmd->releaseRef();
    740         return result;
    741     }
    742     result = (wifi_error)cmd->start();
    743     if (result != WIFI_SUCCESS) {
    744         wifi_unregister_cmd(handle, id);
    745         cmd->releaseRef();
    746         return result;
    747     }
    748     return result;
    749 }
    750 
    751 int wifi_handle_full_scan_event(
    752         wifi_request_id id,
    753         WifiEvent& event,
    754         wifi_scan_result_handler handler)
    755 {
    756     nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
    757     unsigned int len = event.get_vendor_data_len();
    758 
    759     if (vendor_data == NULL || len < sizeof(wifi_gscan_full_result_t)) {
    760         ALOGI("Full scan results: No scan results found");
    761         return NL_SKIP;
    762     }
    763 
    764     wifi_gscan_full_result_t *drv_res = (wifi_gscan_full_result_t *)event.get_vendor_data();
    765     /* To protect against corrupted data, put a ceiling */
    766     int ie_len = min(MAX_PROBE_RESP_IE_LEN, drv_res->ie_length);
    767     wifi_scan_result *full_scan_result;
    768     wifi_gscan_result_t *fixed = &drv_res->fixed;
    769 
    770     if ((ie_len + offsetof(wifi_gscan_full_result_t, ie_data)) > len) {
    771         ALOGE("BAD event data, len %d ie_len %d fixed length %d!\n", len,
    772             ie_len, offsetof(wifi_gscan_full_result_t, ie_data));
    773         return NL_SKIP;
    774     }
    775     full_scan_result = (wifi_scan_result *) malloc((ie_len + offsetof(wifi_scan_result, ie_data)));
    776     if (!full_scan_result) {
    777         ALOGE("Full scan results: Can't malloc!\n");
    778         return NL_SKIP;
    779     }
    780     convert_to_hal_result(full_scan_result, fixed);
    781     full_scan_result->ie_length = ie_len;
    782     memcpy(full_scan_result->ie_data, drv_res->ie_data, ie_len);
    783     if(handler.on_full_scan_result)
    784         handler.on_full_scan_result(id, full_scan_result, drv_res->scan_ch_bucket);
    785 
    786     ALOGV("Full scan result: %-32s %02x:%02x:%02x:%02x:%02x:%02x %d %d %lld %lld %lld %x %d\n",
    787         fixed->ssid, fixed->bssid[0], fixed->bssid[1], fixed->bssid[2], fixed->bssid[3],
    788         fixed->bssid[4], fixed->bssid[5], fixed->rssi, fixed->channel, fixed->ts,
    789         fixed->rtt, fixed->rtt_sd, drv_res->scan_ch_bucket, drv_res->ie_length);
    790     free(full_scan_result);
    791     return NL_SKIP;
    792 }
    793 
    794 
    795 wifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface)
    796 {
    797     ALOGV("Disabling full scan results");
    798     wifi_handle handle = getWifiHandle(iface);
    799 
    800     if(id == -1) {
    801         wifi_scan_result_handler handler;
    802         wifi_handle handle = getWifiHandle(iface);
    803         int params_dummy;
    804 
    805         memset(&handler, 0, sizeof(handler));
    806         FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, 0, &params_dummy, handler);
    807         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
    808         cmd->cancel();
    809         cmd->releaseRef();
    810         return WIFI_SUCCESS;
    811     }
    812 
    813     return wifi_cancel_cmd(id, iface);
    814 }
    815 
    816 
    817 /////////////////////////////////////////////////////////////////////////////
    818 
    819 class GetScanResultsCommand : public WifiCommand {
    820     wifi_cached_scan_results *mScans;
    821     int mMax;
    822     int *mNum;
    823     int mRetrieved;
    824     byte mFlush;
    825     int mCompleted;
    826 public:
    827     GetScanResultsCommand(wifi_interface_handle iface, byte flush,
    828             wifi_cached_scan_results *results, int max, int *num)
    829         : WifiCommand("GetScanResultsCommand", iface, -1), mScans(results), mMax(max), mNum(num),
    830                 mRetrieved(0), mFlush(flush), mCompleted(0)
    831     { }
    832 
    833     int createRequest(WifiRequest& request, int num, byte flush) {
    834         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_SCAN_RESULTS);
    835         if (result < 0) {
    836             return result;
    837         }
    838 
    839         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
    840         result = request.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num);
    841         if (result < 0) {
    842             return result;
    843         }
    844 
    845         result = request.put_u8(GSCAN_ATTRIBUTE_FLUSH_RESULTS, flush);
    846         if (result < 0) {
    847             return result;
    848         }
    849 
    850         request.attr_end(data);
    851         return WIFI_SUCCESS;
    852     }
    853 
    854     int execute() {
    855         WifiRequest request(familyId(), ifaceId());
    856         ALOGV("retrieving %d scan results", mMax);
    857 
    858         for (int i = 0; i < 10 && mRetrieved < mMax; i++) {
    859             int num_to_retrieve = mMax - mRetrieved;
    860             // ALOGI("retrieving %d scan results in one shot", num_to_retrieve);
    861             int result = createRequest(request, num_to_retrieve, mFlush);
    862             if (result < 0) {
    863                 ALOGE("failed to create request");
    864                 return result;
    865             }
    866 
    867             int prev_retrieved = mRetrieved;
    868 
    869             result = requestResponse(request);
    870 
    871             if (result != WIFI_SUCCESS) {
    872                 ALOGE("failed to retrieve scan results; result = %d", result);
    873                 return result;
    874             }
    875 
    876             if (mRetrieved == prev_retrieved || mCompleted) {
    877                 /* no more items left to retrieve */
    878                 break;
    879             }
    880 
    881             request.destroy();
    882         }
    883 
    884         ALOGV("GetScanResults read %d results", mRetrieved);
    885         *mNum = mRetrieved;
    886         return WIFI_SUCCESS;
    887     }
    888 
    889     virtual int handleResponse(WifiEvent& reply) {
    890         ALOGV("In GetScanResultsCommand::handleResponse");
    891 
    892         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
    893             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
    894             return NL_SKIP;
    895         }
    896 
    897         int id = reply.get_vendor_id();
    898         int subcmd = reply.get_vendor_subcmd();
    899 
    900         ALOGV("Id = %0x, subcmd = %d", id, subcmd);
    901 
    902         /*
    903         if (subcmd != GSCAN_SUBCMD_SCAN_RESULTS) {
    904             ALOGE("Invalid response to GetScanResultsCommand; ignoring it");
    905             return NL_SKIP;
    906         }
    907         */
    908 
    909         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
    910         int len = reply.get_vendor_data_len();
    911 
    912         if (vendor_data == NULL || len == 0) {
    913             ALOGE("no vendor data in GetScanResults response; ignoring it");
    914             return NL_SKIP;
    915         }
    916 
    917         for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
    918             if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE) {
    919                 mCompleted = it.get_u8();
    920                 ALOGV("retrieved mCompleted flag : %d", mCompleted);
    921             } else if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS || it.get_type() == 0) {
    922                 int scan_id = 0, flags = 0, num = 0, scan_ch_bucket_mask = 0;
    923                 for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) {
    924                     if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_ID) {
    925                         scan_id = it2.get_u32();
    926                         ALOGV("retrieved scan_id : 0x%0x", scan_id);
    927                     } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_FLAGS) {
    928                         flags = it2.get_u8();
    929                         ALOGV("retrieved scan_flags : 0x%0x", flags);
    930                     } else if (it2.get_type() == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) {
    931                         num = it2.get_u32();
    932                         ALOGV("retrieved num_results: %d", num);
    933                     } else if (it2.get_type() == GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK) {
    934                         scan_ch_bucket_mask = it2.get_u32();
    935                         ALOGD("retrieved scan_ch_bucket_mask: %x", scan_ch_bucket_mask);
    936                     } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS && num) {
    937                         if (mRetrieved >= mMax) {
    938                             ALOGW("Stored %d scans, ignoring excess results", mRetrieved);
    939                             break;
    940                         }
    941                         num = min(num, (int)(it2.get_len()/sizeof(wifi_gscan_result)));
    942                         num = min(num, (int)MAX_AP_CACHE_PER_SCAN);
    943                         ALOGV("Copying %d scan results", num);
    944                         wifi_gscan_result_t *results = (wifi_gscan_result_t *)it2.get_data();
    945                         wifi_scan_result *mScanResults = mScans[mRetrieved].results;
    946 
    947                         for (int i = 0; i < num; i++) {
    948                             wifi_gscan_result_t *result = &results[i];
    949                             convert_to_hal_result(&mScanResults[i], result);
    950                             mScanResults[i].ie_length = 0;
    951                             ALOGV("%02d  %-32s  %02x:%02x:%02x:%02x:%02x:%02x  %04d", i,
    952                                 result->ssid, result->bssid[0], result->bssid[1], result->bssid[2],
    953                                 result->bssid[3], result->bssid[4], result->bssid[5],
    954                                 result->rssi);
    955                         }
    956                         mScans[mRetrieved].scan_id = scan_id;
    957                         mScans[mRetrieved].flags = flags;
    958                         mScans[mRetrieved].num_results = num;
    959                         mScans[mRetrieved].buckets_scanned = scan_ch_bucket_mask;
    960                         ALOGV("Setting result of scan_id : 0x%0x", mScans[mRetrieved].scan_id);
    961                         mRetrieved++;
    962                     } else {
    963                         ALOGW("Ignoring invalid attribute type = %d, size = %d",
    964                                 it.get_type(), it.get_len());
    965                     }
    966                 }
    967             } else {
    968                 ALOGW("Ignoring invalid attribute type = %d, size = %d",
    969                         it.get_type(), it.get_len());
    970             }
    971         }
    972         ALOGV("GetScanResults read %d results", mRetrieved);
    973         return NL_OK;
    974     }
    975 };
    976 
    977 wifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface, byte flush,
    978         int max, wifi_cached_scan_results *results, int *num) {
    979     ALOGV("Getting cached scan results, iface handle = %p, num = %d", iface, *num);
    980 
    981     GetScanResultsCommand *cmd = new GetScanResultsCommand(iface, flush, results, max, num);
    982     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
    983     wifi_error err = (wifi_error)cmd->execute();
    984     cmd->releaseRef();
    985     return err;
    986 }
    987 
    988 /////////////////////////////////////////////////////////////////////////////
    989 
    990 class BssidHotlistCommand : public WifiCommand
    991 {
    992 private:
    993     wifi_bssid_hotlist_params mParams;
    994     wifi_hotlist_ap_found_handler mHandler;
    995     static const int MAX_RESULTS = 64;
    996     wifi_scan_result mResults[MAX_RESULTS];
    997 public:
    998     BssidHotlistCommand(wifi_interface_handle handle, int id,
    999             wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler)
   1000         : WifiCommand("BssidHotlistCommand", handle, id), mParams(params), mHandler(handler)
   1001     { }
   1002 
   1003     int createSetupRequest(WifiRequest& request) {
   1004         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST);
   1005         if (result < 0) {
   1006             return result;
   1007         }
   1008 
   1009         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
   1010         result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1);
   1011         if (result < 0) {
   1012             return result;
   1013         }
   1014 
   1015         result = request.put_u32(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size);
   1016         if (result < 0) {
   1017             return result;
   1018         }
   1019 
   1020         result = request.put_u32(GSCAN_ATTRIBUTE_HOTLIST_BSSID_COUNT, mParams.num_bssid);
   1021         if (result < 0) {
   1022             return result;
   1023         }
   1024 
   1025         struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS);
   1026         for (int i = 0; i < mParams.num_bssid; i++) {
   1027             nlattr *attr2 = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM);
   1028             if (attr2 == NULL) {
   1029                 return WIFI_ERROR_OUT_OF_MEMORY;
   1030             }
   1031             result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid);
   1032             if (result < 0) {
   1033                 return result;
   1034             }
   1035             result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high);
   1036             if (result < 0) {
   1037                 return result;
   1038             }
   1039             result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low);
   1040             if (result < 0) {
   1041                 return result;
   1042             }
   1043             request.attr_end(attr2);
   1044         }
   1045 
   1046         request.attr_end(attr);
   1047         request.attr_end(data);
   1048         return result;
   1049     }
   1050 
   1051     int createTeardownRequest(WifiRequest& request) {
   1052         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST);
   1053         if (result < 0) {
   1054             return result;
   1055         }
   1056 
   1057         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
   1058         result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1);
   1059         if (result < 0) {
   1060             return result;
   1061         }
   1062 
   1063         struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS);
   1064         request.attr_end(attr);
   1065         request.attr_end(data);
   1066         return result;
   1067     }
   1068 
   1069     int start() {
   1070         ALOGI("Executing hotlist setup request, num = %d", mParams.num_bssid);
   1071         WifiRequest request(familyId(), ifaceId());
   1072         int result = createSetupRequest(request);
   1073         if (result < 0) {
   1074             return result;
   1075         }
   1076 
   1077         result = requestResponse(request);
   1078         if (result < 0) {
   1079             ALOGI("Failed to execute hotlist setup request, result = %d", result);
   1080             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
   1081             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
   1082             return result;
   1083         }
   1084 
   1085         ALOGI("Successfully set %d APs in the hotlist ", mParams.num_bssid);
   1086         result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
   1087         if (result < 0) {
   1088             return result;
   1089         }
   1090 
   1091         registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
   1092         registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
   1093 
   1094         result = requestResponse(request);
   1095         if (result < 0) {
   1096             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
   1097             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
   1098             return result;
   1099         }
   1100 
   1101         ALOGI("successfully restarted the scan");
   1102         return result;
   1103     }
   1104 
   1105     virtual int cancel() {
   1106         /* unregister event handler */
   1107         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
   1108         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
   1109         /* create set hotlist message with empty hotlist */
   1110         WifiRequest request(familyId(), ifaceId());
   1111         int result = createTeardownRequest(request);
   1112         if (result < 0) {
   1113             return result;
   1114         }
   1115 
   1116         result = requestResponse(request);
   1117         if (result < 0) {
   1118             return result;
   1119         }
   1120 
   1121         ALOGI("Successfully reset APs in current hotlist");
   1122         return result;
   1123     }
   1124 
   1125     virtual int handleResponse(WifiEvent& reply) {
   1126         /* Nothing to do on response! */
   1127         return NL_SKIP;
   1128     }
   1129 
   1130     virtual int handleEvent(WifiEvent& event) {
   1131         ALOGI("Hotlist AP event");
   1132         int event_id = event.get_vendor_subcmd();
   1133         // event.log();
   1134 
   1135         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
   1136         int len = event.get_vendor_data_len();
   1137 
   1138         if (vendor_data == NULL || len == 0) {
   1139             ALOGI("No scan results found");
   1140             return NL_SKIP;
   1141         }
   1142 
   1143         memset(mResults, 0, sizeof(wifi_scan_result) * MAX_RESULTS);
   1144 
   1145         int num = len / sizeof(wifi_gscan_result_t);
   1146         wifi_gscan_result_t *inp = (wifi_gscan_result_t *)event.get_vendor_data();
   1147         num = min(MAX_RESULTS, num);
   1148         for (int i = 0; i < num; i++, inp++) {
   1149             convert_to_hal_result(&(mResults[i]), inp);
   1150         }
   1151 
   1152         if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_FOUND) {
   1153             ALOGI("FOUND %d hotlist APs", num);
   1154             if (*mHandler.on_hotlist_ap_found)
   1155                 (*mHandler.on_hotlist_ap_found)(id(), num, mResults);
   1156         } else if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_LOST) {
   1157             ALOGI("LOST %d hotlist APs", num);
   1158             if (*mHandler.on_hotlist_ap_lost)
   1159                 (*mHandler.on_hotlist_ap_lost)(id(), num, mResults);
   1160         }
   1161         return NL_SKIP;
   1162     }
   1163 };
   1164 
   1165 class ePNOCommand : public WifiCommand
   1166 {
   1167 private:
   1168     wifi_epno_params epno_params;
   1169     wifi_epno_handler mHandler;
   1170     wifi_scan_result mResults[MAX_EPNO_NETWORKS];
   1171 public:
   1172     ePNOCommand(wifi_interface_handle handle, int id,
   1173             const wifi_epno_params *params, wifi_epno_handler handler)
   1174         : WifiCommand("ePNOCommand", handle, id), mHandler(handler)
   1175     {
   1176         if (params != NULL) {
   1177             memcpy(&epno_params, params, sizeof(wifi_epno_params));
   1178         } else {
   1179             memset(&epno_params, 0, sizeof(wifi_epno_params));
   1180         }
   1181     }
   1182     int createSetupRequest(WifiRequest& request) {
   1183         if (epno_params.num_networks > MAX_EPNO_NETWORKS) {
   1184             ALOGE("wrong epno num_networks:%d", epno_params.num_networks);
   1185             return WIFI_ERROR_INVALID_ARGS;
   1186         }
   1187         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_EPNO_SSID);
   1188         if (result < 0) {
   1189             return result;
   1190         }
   1191         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
   1192         result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_FLUSH, 1);
   1193         if (result < 0) {
   1194             return result;
   1195         }
   1196 
   1197         result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR,
   1198                             (u8)epno_params.min5GHz_rssi);
   1199         if (result < 0) {
   1200             return result;
   1201         }
   1202         result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR,
   1203                             (u8)epno_params.min24GHz_rssi);
   1204         if (result < 0) {
   1205             return result;
   1206         }
   1207         result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX,
   1208                             epno_params.initial_score_max);
   1209         if (result < 0) {
   1210             return result;
   1211         }
   1212         result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS,
   1213                             epno_params.current_connection_bonus);
   1214         if (result < 0) {
   1215             return result;
   1216         }
   1217         result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS,
   1218                             epno_params.same_network_bonus);
   1219         if (result < 0) {
   1220             return result;
   1221         }
   1222         result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS,
   1223                             epno_params.secure_bonus);
   1224         if (result < 0) {
   1225             return result;
   1226         }
   1227         result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_5G_BONUS,
   1228                             epno_params.band5GHz_bonus);
   1229         if (result < 0) {
   1230             return result;
   1231         }
   1232         result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_SSID_NUM,
   1233                         epno_params.num_networks);
   1234         if (result < 0) {
   1235             return result;
   1236         }
   1237         struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_EPNO_SSID_LIST);
   1238         wifi_epno_network *ssid_list = epno_params.networks;
   1239         for (int i = 0; i < epno_params.num_networks; i++) {
   1240             nlattr *attr2 = request.attr_start(i);
   1241             if (attr2 == NULL) {
   1242                 return WIFI_ERROR_OUT_OF_MEMORY;
   1243             }
   1244             result = request.put(GSCAN_ATTRIBUTE_EPNO_SSID, ssid_list[i].ssid, DOT11_MAX_SSID_LEN);
   1245             ALOGI("PNO network: SSID %s flags %x auth %x", ssid_list[i].ssid,
   1246                 ssid_list[i].flags,
   1247                 ssid_list[i].auth_bit_field);
   1248             if (result < 0) {
   1249                 return result;
   1250             }
   1251             result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_SSID_LEN, strlen(ssid_list[i].ssid));
   1252             if (result < 0) {
   1253                 return result;
   1254             }
   1255             result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_FLAGS, ssid_list[i].flags);
   1256             if (result < 0) {
   1257                 return result;
   1258             }
   1259             result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_AUTH, ssid_list[i].auth_bit_field);
   1260             if (result < 0) {
   1261                 return result;
   1262             }
   1263             request.attr_end(attr2);
   1264         }
   1265         request.attr_end(attr);
   1266         request.attr_end(data);
   1267         return result;
   1268     }
   1269 
   1270     int createTeardownRequest(WifiRequest& request) {
   1271         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_EPNO_SSID);
   1272         if (result < 0) {
   1273             return result;
   1274         }
   1275 
   1276         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
   1277         result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_FLUSH, 1);
   1278         if (result < 0) {
   1279             return result;
   1280         }
   1281         request.attr_end(data);
   1282         return result;
   1283     }
   1284 
   1285     int start() {
   1286         ALOGI("Executing ePNO setup request, num = %d", epno_params.num_networks);
   1287         WifiRequest request(familyId(), ifaceId());
   1288         int result = createSetupRequest(request);
   1289         if (result < 0) {
   1290             return result;
   1291         }
   1292 
   1293         result = requestResponse(request);
   1294         if (result < 0) {
   1295             ALOGI("Failed to execute ePNO setup request, result = %d", result);
   1296             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT);
   1297             return result;
   1298         }
   1299 
   1300         ALOGI("Successfully set %d SSIDs for ePNO", epno_params.num_networks);
   1301         registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT);
   1302         ALOGI("successfully restarted the scan");
   1303         return result;
   1304     }
   1305 
   1306     virtual int cancel() {
   1307         /* unregister event handler */
   1308         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT);
   1309         /* create set hotlist message with empty hotlist */
   1310         WifiRequest request(familyId(), ifaceId());
   1311         int result = createTeardownRequest(request);
   1312         if (result < 0) {
   1313             return result;
   1314         }
   1315 
   1316         result = requestResponse(request);
   1317         if (result < 0) {
   1318             return result;
   1319         }
   1320 
   1321         ALOGI("Successfully reset APs in current hotlist");
   1322         return result;
   1323     }
   1324 
   1325     virtual int handleResponse(WifiEvent& reply) {
   1326         /* Nothing to do on response! */
   1327         return NL_SKIP;
   1328     }
   1329 
   1330     virtual int handleEvent(WifiEvent& event) {
   1331         ALOGI("ePNO event");
   1332         int event_id = event.get_vendor_subcmd();
   1333         // event.log();
   1334 
   1335         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
   1336         int len = event.get_vendor_data_len();
   1337 
   1338         if (vendor_data == NULL || len == 0) {
   1339             ALOGI("No scan results found");
   1340             return NL_SKIP;
   1341         }
   1342 
   1343         memset(mResults, 0, sizeof(wifi_scan_result) * MAX_EPNO_NETWORKS);
   1344 
   1345         unsigned int num = len / sizeof(wifi_pno_result_t);
   1346         unsigned int i;
   1347         num = min(MAX_EPNO_NETWORKS, num);
   1348         wifi_pno_result_t *res = (wifi_pno_result_t *) event.get_vendor_data();
   1349         for (i = 0; i < num; i++) {
   1350             if (res[i].flags == PNO_SSID_FOUND) {
   1351                 memcpy(mResults[i].ssid, res[i].ssid, res[i].ssid_len);
   1352                 memcpy(mResults[i].bssid, res[i].bssid, sizeof(mac_addr));
   1353 
   1354                 mResults[i].ssid[res[i].ssid_len] = '\0';
   1355                 mResults[i].channel = res[i].channel;
   1356                 mResults[i].rssi = res[i].rssi;
   1357             }
   1358         }
   1359         if (*mHandler.on_network_found)
   1360             (*mHandler.on_network_found)(id(), num, mResults);
   1361         return NL_SKIP;
   1362     }
   1363 };
   1364 
   1365 wifi_error wifi_set_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface,
   1366         wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler)
   1367 {
   1368     wifi_handle handle = getWifiHandle(iface);
   1369 
   1370     BssidHotlistCommand *cmd = new BssidHotlistCommand(iface, id, params, handler);
   1371     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
   1372     wifi_error result = wifi_register_cmd(handle, id, cmd);
   1373     if (result != WIFI_SUCCESS) {
   1374         cmd->releaseRef();
   1375         return result;
   1376     }
   1377     result = (wifi_error)cmd->start();
   1378     if (result != WIFI_SUCCESS) {
   1379         wifi_unregister_cmd(handle, id);
   1380         cmd->releaseRef();
   1381         return result;
   1382     }
   1383     return result;
   1384 }
   1385 
   1386 wifi_error wifi_reset_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface)
   1387 {
   1388     return wifi_cancel_cmd(id, iface);
   1389 }
   1390 
   1391 
   1392 /////////////////////////////////////////////////////////////////////////////
   1393 
   1394 class SignificantWifiChangeCommand : public WifiCommand
   1395 {
   1396     typedef struct {
   1397         mac_addr bssid;                     // BSSID
   1398         wifi_channel channel;               // channel frequency in MHz
   1399         int num_rssi;                       // number of rssi samples
   1400         wifi_rssi rssi[8];                   // RSSI history in db
   1401     } wifi_significant_change_result_internal;
   1402 
   1403 private:
   1404     wifi_significant_change_params mParams;
   1405     wifi_significant_change_handler mHandler;
   1406     static const int MAX_RESULTS = 64;
   1407     wifi_significant_change_result_internal mResultsBuffer[MAX_RESULTS];
   1408     wifi_significant_change_result *mResults[MAX_RESULTS];
   1409 public:
   1410     SignificantWifiChangeCommand(wifi_interface_handle handle, int id,
   1411             wifi_significant_change_params params, wifi_significant_change_handler handler)
   1412         : WifiCommand("SignificantWifiChangeCommand", handle, id), mParams(params),
   1413             mHandler(handler)
   1414     { }
   1415 
   1416     int createSetupRequest(WifiRequest& request) {
   1417         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG);
   1418         if (result < 0) {
   1419             return result;
   1420         }
   1421 
   1422         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
   1423         result = request.put_u8(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1);
   1424         if (result < 0) {
   1425             return result;
   1426         }
   1427         result = request.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE, mParams.rssi_sample_size);
   1428         if (result < 0) {
   1429             return result;
   1430         }
   1431         result = request.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size);
   1432         if (result < 0) {
   1433             return result;
   1434         }
   1435         result = request.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING, mParams.min_breaching);
   1436         if (result < 0) {
   1437             return result;
   1438         }
   1439         result = request.put_u16(GSCAN_ATTRIBUTE_NUM_BSSID, mParams.num_bssid);
   1440         if (result < 0) {
   1441             return result;
   1442         }
   1443         if (mParams.num_bssid != 0) {
   1444             nlattr* attr = request.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS);
   1445             if (attr == NULL) {
   1446                 return WIFI_ERROR_OUT_OF_MEMORY;
   1447             }
   1448 
   1449             for (int i = 0; i < mParams.num_bssid; i++) {
   1450                 nlattr* attr2 = request.attr_start(i);
   1451                 if (attr2 == NULL) {
   1452                     return WIFI_ERROR_OUT_OF_MEMORY;
   1453                 }
   1454                 result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid);
   1455                 if (result < 0) {
   1456                     return result;
   1457                 }
   1458                 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high);
   1459                 if (result < 0) {
   1460                     return result;
   1461                 }
   1462                 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low);
   1463                 if (result < 0) {
   1464                     return result;
   1465                 }
   1466                 request.attr_end(attr2);
   1467             }
   1468 
   1469             request.attr_end(attr);
   1470         }
   1471         request.attr_end(data);
   1472 
   1473         return result;
   1474     }
   1475 
   1476     int createTeardownRequest(WifiRequest& request) {
   1477         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG);
   1478         if (result < 0) {
   1479             return result;
   1480         }
   1481 
   1482         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
   1483         result = request.put_u16(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1);
   1484         if (result < 0) {
   1485             return result;
   1486         }
   1487 
   1488         request.attr_end(data);
   1489         return result;
   1490     }
   1491 
   1492     int start() {
   1493         ALOGI("Set significant wifi change config");
   1494         WifiRequest request(familyId(), ifaceId());
   1495 
   1496         int result = createSetupRequest(request);
   1497         if (result < 0) {
   1498             return result;
   1499         }
   1500 
   1501         result = requestResponse(request);
   1502         if (result < 0) {
   1503             ALOGI("failed to set significant wifi change config %d", result);
   1504             return result;
   1505         }
   1506 
   1507         ALOGI("successfully set significant wifi change config");
   1508 
   1509         result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
   1510         if (result < 0) {
   1511             return result;
   1512         }
   1513 
   1514         registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
   1515 
   1516         result = requestResponse(request);
   1517         if (result < 0) {
   1518             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
   1519             return result;
   1520         }
   1521 
   1522         ALOGI("successfully restarted the scan");
   1523         return result;
   1524     }
   1525 
   1526     virtual int cancel() {
   1527         /* unregister event handler */
   1528         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
   1529 
   1530         /* create set significant change monitor message with empty hotlist */
   1531         WifiRequest request(familyId(), ifaceId());
   1532 
   1533         int result = createTeardownRequest(request);
   1534         if (result < 0) {
   1535             return result;
   1536         }
   1537 
   1538         result = requestResponse(request);
   1539         if (result < 0) {
   1540             return result;
   1541         }
   1542 
   1543         ALOGI("successfully reset significant wifi change config");
   1544         return result;
   1545     }
   1546 
   1547     virtual int handleResponse(WifiEvent& reply) {
   1548         /* Nothing to do on response! */
   1549         return NL_SKIP;
   1550     }
   1551 
   1552     virtual int handleEvent(WifiEvent& event) {
   1553         ALOGV("Got a significant wifi change event");
   1554 
   1555         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
   1556         int len = event.get_vendor_data_len();
   1557 
   1558         if (vendor_data == NULL || len == 0) {
   1559             ALOGI("No scan results found");
   1560             return NL_SKIP;
   1561         }
   1562 
   1563         typedef struct {
   1564             uint16_t flags;
   1565             uint16_t channel;
   1566             mac_addr bssid;
   1567             s8 rssi_history[8];
   1568         } ChangeInfo;
   1569 
   1570         int num = min(len / sizeof(ChangeInfo), MAX_RESULTS);
   1571         ChangeInfo *ci = (ChangeInfo *)event.get_vendor_data();
   1572 
   1573         for (int i = 0; i < num; i++) {
   1574             memcpy(mResultsBuffer[i].bssid, ci[i].bssid, sizeof(mac_addr));
   1575             mResultsBuffer[i].channel = ci[i].channel;
   1576             mResultsBuffer[i].num_rssi = 8;
   1577             for (int j = 0; j < mResultsBuffer[i].num_rssi; j++)
   1578                 mResultsBuffer[i].rssi[j] = (int) ci[i].rssi_history[j];
   1579             mResults[i] = reinterpret_cast<wifi_significant_change_result *>(&(mResultsBuffer[i]));
   1580         }
   1581 
   1582         ALOGV("Retrieved %d scan results", num);
   1583 
   1584         if (num != 0) {
   1585             (*mHandler.on_significant_change)(id(), num, mResults);
   1586         } else {
   1587             ALOGW("No significant change reported");
   1588         }
   1589 
   1590         return NL_SKIP;
   1591     }
   1592 };
   1593 
   1594 wifi_error wifi_set_significant_change_handler(wifi_request_id id, wifi_interface_handle iface,
   1595         wifi_significant_change_params params, wifi_significant_change_handler handler)
   1596 {
   1597     wifi_handle handle = getWifiHandle(iface);
   1598 
   1599     SignificantWifiChangeCommand *cmd = new SignificantWifiChangeCommand(
   1600             iface, id, params, handler);
   1601     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
   1602     wifi_error result = wifi_register_cmd(handle, id, cmd);
   1603     if (result != WIFI_SUCCESS) {
   1604         cmd->releaseRef();
   1605         return result;
   1606     }
   1607     result = (wifi_error)cmd->start();
   1608     if (result != WIFI_SUCCESS) {
   1609         wifi_unregister_cmd(handle, id);
   1610         cmd->releaseRef();
   1611         return result;
   1612     }
   1613     return result;
   1614 }
   1615 
   1616 wifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface)
   1617 {
   1618     return wifi_cancel_cmd(id, iface);
   1619 }
   1620 
   1621 wifi_error wifi_reset_epno_list(wifi_request_id id, wifi_interface_handle iface)
   1622 {
   1623     if (id == -1) {
   1624         wifi_epno_handler handler;
   1625         wifi_handle handle = getWifiHandle(iface);
   1626 
   1627         memset(&handler, 0, sizeof(handler));
   1628         ePNOCommand *cmd = new ePNOCommand(iface, id, NULL, handler);
   1629         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
   1630         cmd->cancel();
   1631         cmd->releaseRef();
   1632         return WIFI_SUCCESS;
   1633     }
   1634     return wifi_cancel_cmd(id, iface);
   1635 }
   1636 
   1637 wifi_error wifi_set_epno_list(wifi_request_id id, wifi_interface_handle iface,
   1638         const wifi_epno_params *params, wifi_epno_handler handler)
   1639 {
   1640     wifi_handle handle = getWifiHandle(iface);
   1641 
   1642     ePNOCommand *cmd = new ePNOCommand(iface, id, params, handler);
   1643     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
   1644     wifi_error result = wifi_register_cmd(handle, id, cmd);
   1645     if (result != WIFI_SUCCESS) {
   1646         cmd->releaseRef();
   1647         return result;
   1648     }
   1649     result = (wifi_error)cmd->start();
   1650     if (result != WIFI_SUCCESS) {
   1651         wifi_unregister_cmd(handle, id);
   1652         cmd->releaseRef();
   1653         return result;
   1654     }
   1655     return result;
   1656 }
   1657 
   1658 
   1659 ////////////////////////////////////////////////////////////////////////////////
   1660 
   1661 class AnqpoConfigureCommand : public WifiCommand
   1662 {
   1663     int num_hs;
   1664     wifi_passpoint_network *mNetworks;
   1665     wifi_passpoint_event_handler mHandler;
   1666     wifi_scan_result *mResult;
   1667 public:
   1668     AnqpoConfigureCommand(wifi_request_id id, wifi_interface_handle iface,
   1669         int num, wifi_passpoint_network *hs_list, wifi_passpoint_event_handler handler)
   1670         : WifiCommand("AnqpoConfigureCommand", iface, id), num_hs(num), mNetworks(hs_list),
   1671             mHandler(handler)
   1672     {
   1673         mResult = NULL;
   1674     }
   1675 
   1676     int createRequest(WifiRequest& request, int val) {
   1677 
   1678         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_ANQPO_CONFIG);
   1679         result = request.put_u32(GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE, num_hs);
   1680         if (result < 0) {
   1681             return result;
   1682         }
   1683 
   1684         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
   1685 
   1686         struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_ANQPO_HS_LIST);
   1687         for (int i = 0; i < num_hs; i++) {
   1688             nlattr *attr2 = request.attr_start(i);
   1689             if (attr2 == NULL) {
   1690                 return WIFI_ERROR_OUT_OF_MEMORY;
   1691             }
   1692             result = request.put_u32(GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID, mNetworks[i].id);
   1693             if (result < 0) {
   1694                 return result;
   1695             }
   1696             result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM, mNetworks[i].realm, 256);
   1697             if (result < 0) {
   1698                 return result;
   1699             }
   1700             result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID,
   1701                          mNetworks[i].roamingConsortiumIds, 128);
   1702             if (result < 0) {
   1703                 return result;
   1704             }
   1705             result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_PLMN, mNetworks[i].plmn, 3);
   1706             if (result < 0) {
   1707                 return result;
   1708             }
   1709 
   1710             request.attr_end(attr2);
   1711         }
   1712 
   1713         request.attr_end(attr);
   1714         request.attr_end(data);
   1715 
   1716         return WIFI_SUCCESS;
   1717     }
   1718 
   1719     int start() {
   1720 
   1721         WifiRequest request(familyId(), ifaceId());
   1722         int result = createRequest(request, num_hs);
   1723         if (result != WIFI_SUCCESS) {
   1724             ALOGE("failed to create request; result = %d", result);
   1725             return result;
   1726         }
   1727 
   1728         registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH);
   1729 
   1730         result = requestResponse(request);
   1731         if (result != WIFI_SUCCESS) {
   1732             ALOGE("failed to set ANQPO networks; result = %d", result);
   1733             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH);
   1734             return result;
   1735         }
   1736 
   1737         return result;
   1738     }
   1739 
   1740     virtual int cancel() {
   1741 
   1742         WifiRequest request(familyId(), ifaceId());
   1743         int result = createRequest(request, 0);
   1744         if (result != WIFI_SUCCESS) {
   1745             ALOGE("failed to create request; result = %d", result);
   1746         } else {
   1747             result = requestResponse(request);
   1748             if (result != WIFI_SUCCESS) {
   1749                 ALOGE("failed to reset ANQPO networks;result = %d", result);
   1750             }
   1751         }
   1752 
   1753         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH);
   1754         return WIFI_SUCCESS;
   1755     }
   1756 
   1757     virtual int handleResponse(WifiEvent& reply) {
   1758          ALOGD("Request complete!");
   1759         /* Nothing to do on response! */
   1760         return NL_SKIP;
   1761     }
   1762 
   1763     virtual int handleEvent(WifiEvent& event) {
   1764         typedef struct {
   1765             u16 channel;        /* channel of GAS protocol */
   1766             u8  dialog_token;   /* GAS dialog token */
   1767             u8  fragment_id;    /* fragment id */
   1768             u16 status_code;    /* status code on GAS completion */
   1769             u16 data_len;       /* length of data to follow */
   1770             u8  data[1];        /* variable length specified by data_len */
   1771         } wifi_anqp_gas_resp;
   1772 
   1773         ALOGI("ANQPO hotspot matched event!");
   1774 
   1775         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
   1776         unsigned int len = event.get_vendor_data_len();
   1777 
   1778         if (vendor_data == NULL || len < sizeof(wifi_scan_result)) {
   1779             ALOGI("No scan results found");
   1780             return NL_SKIP;
   1781         }
   1782         mResult = (wifi_scan_result *)malloc(sizeof(wifi_scan_result));
   1783         if (!mResult) {
   1784             return NL_SKIP;
   1785         }
   1786         wifi_gscan_full_result_t *drv_res = (wifi_gscan_full_result_t *)event.get_vendor_data();
   1787         wifi_gscan_result_t *fixed = &drv_res->fixed;
   1788         convert_to_hal_result(mResult, fixed);
   1789 
   1790         byte *anqp = (byte *)drv_res + offsetof(wifi_gscan_full_result_t, ie_data) + drv_res->ie_length;
   1791         wifi_anqp_gas_resp *gas = (wifi_anqp_gas_resp *)anqp;
   1792         int anqp_len = offsetof(wifi_anqp_gas_resp, data) + gas->data_len;
   1793         int networkId = *(int *)((byte *)anqp + anqp_len);
   1794 
   1795         ALOGI("%-32s\t", mResult->ssid);
   1796 
   1797         ALOGI("%02x:%02x:%02x:%02x:%02x:%02x ", mResult->bssid[0], mResult->bssid[1],
   1798                 mResult->bssid[2], mResult->bssid[3], mResult->bssid[4], mResult->bssid[5]);
   1799 
   1800         ALOGI("%d\t", mResult->rssi);
   1801         ALOGI("%d\t", mResult->channel);
   1802         ALOGI("%lld\t", mResult->ts);
   1803         ALOGI("%lld\t", mResult->rtt);
   1804         ALOGI("%lld\n", mResult->rtt_sd);
   1805 
   1806         if(*mHandler.on_passpoint_network_found)
   1807             (*mHandler.on_passpoint_network_found)(id(), networkId, mResult, anqp_len, anqp);
   1808         free(mResult);
   1809         return NL_SKIP;
   1810     }
   1811 };
   1812 
   1813 wifi_error wifi_set_passpoint_list(wifi_request_id id, wifi_interface_handle iface, int num,
   1814         wifi_passpoint_network *networks, wifi_passpoint_event_handler handler)
   1815 {
   1816     wifi_handle handle = getWifiHandle(iface);
   1817 
   1818     AnqpoConfigureCommand *cmd = new AnqpoConfigureCommand(id, iface, num, networks, handler);
   1819     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
   1820     wifi_error result = wifi_register_cmd(handle, id, cmd);
   1821     if (result != WIFI_SUCCESS) {
   1822         cmd->releaseRef();
   1823         return result;
   1824     }
   1825     result = (wifi_error)cmd->start();
   1826     if (result != WIFI_SUCCESS) {
   1827         wifi_unregister_cmd(handle, id);
   1828         cmd->releaseRef();
   1829         return result;
   1830     }
   1831     return result;
   1832 }
   1833 
   1834 wifi_error wifi_reset_passpoint_list(wifi_request_id id, wifi_interface_handle iface)
   1835 {
   1836     return wifi_cancel_cmd(id, iface);
   1837 }
   1838