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