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
convert_to_hal_result(wifi_scan_result * to,wifi_gscan_result_t * from)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:
GetCapabilitiesCommand(wifi_interface_handle iface,wifi_gscan_capabilities * capabitlites)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
create()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:
handleResponse(WifiEvent & reply)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
wifi_get_gscan_capabilities(wifi_interface_handle handle,wifi_gscan_capabilities * capabilities)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:
GetChannelListCommand(wifi_interface_handle iface,wifi_channel * channel_buf,int * ch_num,int num_max_ch,int band)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 }
create()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:
handleResponse(WifiEvent & reply)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
wifi_get_valid_channels(wifi_interface_handle handle,int band,int max_channels,wifi_channel * channels,int * num_channels)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
parseScanResults(wifi_scan_result * results,int num,nlattr * attr)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
createFeatureRequest(WifiRequest & request,int subcmd,int enable)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:
FullScanResultsCommand(wifi_interface_handle iface,int id,int * params,wifi_scan_result_handler handler)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
createRequest(WifiRequest & request,int subcmd,int enable)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
start()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
cancel()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
handleResponse(WifiEvent & reply)438 virtual int handleResponse(WifiEvent& reply) {
439 ALOGD("Request complete!");
440 /* Nothing to do on response! */
441 return NL_SKIP;
442 }
443
handleEvent(WifiEvent & event)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:
ScanCommand(wifi_interface_handle iface,int id,wifi_scan_cmd_params * params,wifi_scan_result_handler handler)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
createSetupRequest(WifiRequest & request)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
createScanConfigRequest(WifiRequest & request)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
createStartRequest(WifiRequest & request)566 int createStartRequest(WifiRequest& request) {
567 return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
568 }
569
createStopRequest(WifiRequest & request)570 int createStopRequest(WifiRequest& request) {
571 return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 0);
572 }
573
start()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
cancel()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
handleResponse(WifiEvent & reply)646 virtual int handleResponse(WifiEvent& reply) {
647 /* Nothing to do on response! */
648 return NL_SKIP;
649 }
650
handleEvent(WifiEvent & event)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
wifi_start_gscan(wifi_request_id id,wifi_interface_handle iface,wifi_scan_cmd_params params,wifi_scan_result_handler handler)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, ¶ms, 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
wifi_stop_gscan(wifi_request_id id,wifi_interface_handle iface)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
wifi_enable_full_scan_results(wifi_request_id id,wifi_interface_handle iface,wifi_scan_result_handler handler)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, ¶ms_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
wifi_handle_full_scan_event(wifi_request_id id,WifiEvent & event,wifi_scan_result_handler handler)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
wifi_disable_full_scan_results(wifi_request_id id,wifi_interface_handle iface)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, ¶ms_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:
GetScanResultsCommand(wifi_interface_handle iface,byte flush,wifi_cached_scan_results * results,int max,int * num)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
createRequest(WifiRequest & request,int num,byte flush)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
execute()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
handleResponse(WifiEvent & reply)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
wifi_get_cached_gscan_results(wifi_interface_handle iface,byte flush,int max,wifi_cached_scan_results * results,int * num)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:
BssidHotlistCommand(wifi_interface_handle handle,int id,wifi_bssid_hotlist_params params,wifi_hotlist_ap_found_handler handler)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
createSetupRequest(WifiRequest & request)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
createTeardownRequest(WifiRequest & request)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
start()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
cancel()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
handleResponse(WifiEvent & reply)1119 virtual int handleResponse(WifiEvent& reply) {
1120 /* Nothing to do on response! */
1121 return NL_SKIP;
1122 }
1123
handleEvent(WifiEvent & event)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:
ePNOCommand(wifi_interface_handle handle,int id,const wifi_epno_params * params,wifi_epno_handler handler)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 }
createSetupRequest(WifiRequest & request)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
createTeardownRequest(WifiRequest & request)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
start()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
cancel()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
handleResponse(WifiEvent & reply)1315 virtual int handleResponse(WifiEvent& reply) {
1316 /* Nothing to do on response! */
1317 return NL_SKIP;
1318 }
1319
handleEvent(WifiEvent & event)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
wifi_set_bssid_hotlist(wifi_request_id id,wifi_interface_handle iface,wifi_bssid_hotlist_params params,wifi_hotlist_ap_found_handler handler)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
wifi_reset_bssid_hotlist(wifi_request_id id,wifi_interface_handle iface)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:
SignificantWifiChangeCommand(wifi_interface_handle handle,int id,wifi_significant_change_params params,wifi_significant_change_handler handler)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
createSetupRequest(WifiRequest & request)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
createTeardownRequest(WifiRequest & request)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
start()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
cancel()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
handleResponse(WifiEvent & reply)1529 virtual int handleResponse(WifiEvent& reply) {
1530 /* Nothing to do on response! */
1531 return NL_SKIP;
1532 }
1533
handleEvent(WifiEvent & event)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
wifi_set_significant_change_handler(wifi_request_id id,wifi_interface_handle iface,wifi_significant_change_params params,wifi_significant_change_handler handler)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
wifi_reset_significant_change_handler(wifi_request_id id,wifi_interface_handle iface)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
wifi_reset_epno_list(wifi_request_id id,wifi_interface_handle iface)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
wifi_set_epno_list(wifi_request_id id,wifi_interface_handle iface,const wifi_epno_params * params,wifi_epno_handler handler)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:
BssidBlacklistCommand(wifi_interface_handle handle,int id,wifi_bssid_params * params)1645 BssidBlacklistCommand(wifi_interface_handle handle, int id,
1646 wifi_bssid_params *params)
1647 : WifiCommand("BssidBlacklistCommand", handle, id), mParams(params)
1648 { }
createRequest(WifiRequest & request)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
start()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
handleResponse(WifiEvent & reply)1698 virtual int handleResponse(WifiEvent& reply) {
1699 /* Nothing to do on response! */
1700 return NL_SKIP;
1701 }
1702 };
1703
wifi_set_bssid_blacklist(wifi_request_id id,wifi_interface_handle iface,wifi_bssid_params params)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, ¶ms);
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:
AnqpoConfigureCommand(wifi_request_id id,wifi_interface_handle iface,int num,wifi_passpoint_network * hs_list,wifi_passpoint_event_handler handler)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
createRequest(WifiRequest & request,int val)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
start()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
cancel()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
handleResponse(WifiEvent & reply)1815 virtual int handleResponse(WifiEvent& reply) {
1816 ALOGD("Request complete!");
1817 /* Nothing to do on response! */
1818 return NL_SKIP;
1819 }
1820
handleEvent(WifiEvent & event)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
wifi_set_passpoint_list(wifi_request_id id,wifi_interface_handle iface,int num,wifi_passpoint_network * networks,wifi_passpoint_event_handler handler)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
wifi_reset_passpoint_list(wifi_request_id id,wifi_interface_handle iface)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