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