1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Portions copyright (C) 2017 Broadcom Limited
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include <stdint.h>
20 #include <fcntl.h>
21 #include <sys/socket.h>
22 #include <netlink/genl/genl.h>
23 #include <netlink/genl/family.h>
24 #include <netlink/genl/ctrl.h>
25 #include <linux/rtnetlink.h>
26 #include <netpacket/packet.h>
27 #include <linux/filter.h>
28 #include <linux/errqueue.h>
29
30 #include <linux/pkt_sched.h>
31 #include <netlink/object-api.h>
32 #include <netlink/netlink.h>
33 #include <netlink/socket.h>
34 #include <netlink/handlers.h>
35
36 #include "sync.h"
37
38 #define LOG_TAG "WifiHAL"
39 //#define LOG_NDEBUG 0 //uncomment to enable verbose logging
40
41 #include <log/log.h>
42
43 #include "wifi_hal.h"
44 #include "common.h"
45 #include "cpp_bindings.h"
46
47 typedef enum {
48
49 GSCAN_ATTRIBUTE_NUM_BUCKETS = 10,
50 GSCAN_ATTRIBUTE_BASE_PERIOD,
51 GSCAN_ATTRIBUTE_BUCKETS_BAND,
52 GSCAN_ATTRIBUTE_BUCKET_ID,
53 GSCAN_ATTRIBUTE_BUCKET_PERIOD,
54 GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS,
55 GSCAN_ATTRIBUTE_BUCKET_CHANNELS,
56 GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN,
57 GSCAN_ATTRIBUTE_REPORT_THRESHOLD,
58 GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE,
59 GSCAN_ATTRIBUTE_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND,
60
61 GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20,
62 GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, /* indicates no more results */
63 GSCAN_ATTRIBUTE_FLUSH_FEATURE, /* Flush all the configs */
64 GSCAN_ENABLE_FULL_SCAN_RESULTS,
65 GSCAN_ATTRIBUTE_REPORT_EVENTS,
66
67 /* remaining reserved for additional attributes */
68 GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30,
69 GSCAN_ATTRIBUTE_FLUSH_RESULTS,
70 GSCAN_ATTRIBUTE_SCAN_RESULTS, /* flat array of wifi_scan_result */
71 GSCAN_ATTRIBUTE_SCAN_ID, /* indicates scan number */
72 GSCAN_ATTRIBUTE_SCAN_FLAGS, /* indicates if scan was aborted */
73 GSCAN_ATTRIBUTE_AP_FLAGS, /* flags on significant change event */
74 GSCAN_ATTRIBUTE_NUM_CHANNELS,
75 GSCAN_ATTRIBUTE_CHANNEL_LIST,
76 GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK,
77 /* remaining reserved for additional attributes */
78
79 GSCAN_ATTRIBUTE_SSID = 40,
80 GSCAN_ATTRIBUTE_BSSID,
81 GSCAN_ATTRIBUTE_CHANNEL,
82 GSCAN_ATTRIBUTE_RSSI,
83 GSCAN_ATTRIBUTE_TIMESTAMP,
84 GSCAN_ATTRIBUTE_RTT,
85 GSCAN_ATTRIBUTE_RTTSD,
86
87 /* remaining reserved for additional attributes */
88
89 GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50,
90 GSCAN_ATTRIBUTE_RSSI_LOW,
91 GSCAN_ATTRIBUTE_RSSI_HIGH,
92 GSCAN_ATTRIBUTE_HOTLIST_ELEM,
93 GSCAN_ATTRIBUTE_HOTLIST_FLUSH,
94 GSCAN_ATTRIBUTE_HOTLIST_BSSID_COUNT,
95
96 /* remaining reserved for additional attributes */
97 GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60,
98 GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE,
99 GSCAN_ATTRIBUTE_MIN_BREACHING,
100 GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS,
101 GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH,
102
103 /* EPNO */
104 GSCAN_ATTRIBUTE_EPNO_SSID_LIST = 70,
105 GSCAN_ATTRIBUTE_EPNO_SSID,
106 GSCAN_ATTRIBUTE_EPNO_SSID_LEN,
107 GSCAN_ATTRIBUTE_EPNO_RSSI,
108 GSCAN_ATTRIBUTE_EPNO_FLAGS,
109 GSCAN_ATTRIBUTE_EPNO_AUTH,
110 GSCAN_ATTRIBUTE_EPNO_SSID_NUM,
111 GSCAN_ATTRIBUTE_EPNO_FLUSH,
112
113 /* remaining reserved for additional attributes */
114
115 GSCAN_ATTRIBUTE_WHITELIST_SSID = 80,
116 GSCAN_ATTRIBUTE_NUM_WL_SSID,
117 GSCAN_ATTRIBUTE_WL_SSID_LEN,
118 GSCAN_ATTRIBUTE_WL_SSID_FLUSH,
119 GSCAN_ATTRIBUTE_WHITELIST_SSID_ELEM,
120 GSCAN_ATTRIBUTE_NUM_BSSID,
121 GSCAN_ATTRIBUTE_BSSID_PREF_LIST,
122 GSCAN_ATTRIBUTE_BSSID_PREF_FLUSH,
123 GSCAN_ATTRIBUTE_BSSID_PREF,
124 GSCAN_ATTRIBUTE_RSSI_MODIFIER,
125
126 /* remaining reserved for additional attributes */
127
128 GSCAN_ATTRIBUTE_A_BAND_BOOST_THRESHOLD = 90,
129 GSCAN_ATTRIBUTE_A_BAND_PENALTY_THRESHOLD,
130 GSCAN_ATTRIBUTE_A_BAND_BOOST_FACTOR,
131 GSCAN_ATTRIBUTE_A_BAND_PENALTY_FACTOR,
132 GSCAN_ATTRIBUTE_A_BAND_MAX_BOOST,
133 GSCAN_ATTRIBUTE_LAZY_ROAM_HYSTERESIS,
134 GSCAN_ATTRIBUTE_ALERT_ROAM_RSSI_TRIGGER,
135 GSCAN_ATTRIBUTE_LAZY_ROAM_ENABLE,
136
137 /* BSSID blacklist */
138 GSCAN_ATTRIBUTE_BSSID_BLACKLIST_FLUSH = 100,
139 GSCAN_ATTRIBUTE_BLACKLIST_BSSID,
140
141 /* ANQPO */
142 GSCAN_ATTRIBUTE_ANQPO_HS_LIST = 110,
143 GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE,
144 GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID,
145 GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM,
146 GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID,
147 GSCAN_ATTRIBUTE_ANQPO_HS_PLMN,
148
149 /* Adaptive scan attributes */
150 GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT = 120,
151 GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD,
152
153 /* ePNO cfg */
154 GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR = 130,
155 GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR,
156 GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX,
157 GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS,
158 GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS,
159 GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS,
160 GSCAN_ATTRIBUTE_EPNO_5G_BONUS,
161
162 /* Roaming features */
163 GSCAN_ATTRIBUTE_ROAM_STATE_SET = 140,
164 GSCAN_ATTRIBUTE_MAX
165
166 } GSCAN_ATTRIBUTE;
167
168 typedef struct {
169 int num_bssid; // number of blacklisted BSSIDs
170 mac_addr bssids[MAX_BLACKLIST_BSSID]; // blacklisted BSSIDs
171 } wifi_bssid_params;
172
173 // helper methods
174 wifi_error wifi_enable_full_scan_results(wifi_request_id id, wifi_interface_handle iface,
175 wifi_scan_result_handler handler);
176 wifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface);
177 int wifi_handle_full_scan_event(wifi_request_id id, WifiEvent& event,
178 wifi_scan_result_handler handler);
179 void convert_to_hal_result(wifi_scan_result *to, wifi_gscan_result_t *from);
180
181
convert_to_hal_result(wifi_scan_result * to,wifi_gscan_result_t * from)182 void convert_to_hal_result(wifi_scan_result *to, wifi_gscan_result_t *from)
183 {
184 to->ts = from->ts;
185 to->channel = from->channel;
186 to->rssi = from->rssi;
187 to->rtt = from->rtt;
188 to->rtt_sd = from->rtt_sd;
189 to->beacon_period = from->beacon_period;
190 to->capability = from->capability;
191 memcpy(to->ssid, from->ssid, (DOT11_MAX_SSID_LEN+1));
192 memcpy(&to->bssid, &from->bssid, sizeof(mac_addr));
193 }
194
195 /////////////////////////////////////////////////////////////////////////////
196
197 class GetCapabilitiesCommand : public WifiCommand
198 {
199 void *mCapabilities;
200 uint16_t mRequesttype;
201 int mRequestsize;
202 public:
GetCapabilitiesCommand(wifi_interface_handle iface,void * capabitlites,uint16_t request_type,int request_size)203 GetCapabilitiesCommand(wifi_interface_handle iface, void *capabitlites, uint16_t request_type,
204 int request_size)
205 : WifiCommand("GetGscanCapabilitiesCommand", iface, 0), mCapabilities(capabitlites), mRequesttype(request_type),
206 mRequestsize(request_size)
207 {
208 memset(mCapabilities, 0, mRequestsize);
209 }
210
create()211 virtual int create() {
212 ALOGV("Creating message to get scan capablities; iface = %d", mIfaceInfo->id);
213
214 int ret = mMsg.create(GOOGLE_OUI, mRequesttype);
215 if (ret < 0) {
216 return ret;
217 }
218
219 return ret;
220 }
221
222 protected:
handleResponse(WifiEvent & reply)223 virtual int handleResponse(WifiEvent& reply) {
224
225 ALOGV("In GetCapabilities::handleResponse");
226
227 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
228 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
229 return NL_SKIP;
230 }
231
232 int id = reply.get_vendor_id();
233 int subcmd = reply.get_vendor_subcmd();
234
235 void *data = reply.get_vendor_data();
236 int len = reply.get_vendor_data_len();
237
238 ALOGV("Id = %0x, subcmd = 0x%x, len = %d, expected len = %d", id, subcmd, len,
239 mRequestsize);
240
241 memcpy(mCapabilities, data, min(len, mRequestsize));
242
243 return NL_OK;
244 }
245 };
246
wifi_get_gscan_capabilities(wifi_interface_handle handle,wifi_gscan_capabilities * capabilities)247 wifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle,
248 wifi_gscan_capabilities *capabilities)
249 {
250 GetCapabilitiesCommand command(handle, capabilities, GSCAN_SUBCMD_GET_CAPABILITIES,
251 (int)sizeof(wifi_gscan_capabilities));
252 return (wifi_error) command.requestResponse();
253 }
254
255 /* Function to get chipset supported roaming capabilities */
wifi_get_roaming_capabilities(wifi_interface_handle handle,wifi_roaming_capabilities * capabilities)256 wifi_error wifi_get_roaming_capabilities(wifi_interface_handle handle,
257 wifi_roaming_capabilities *capabilities)
258 {
259 GetCapabilitiesCommand command(handle, capabilities, WIFI_SUBCMD_ROAM_CAPABILITY,
260 (int)sizeof(wifi_roaming_capabilities));
261 return (wifi_error) command.requestResponse();
262 }
263
264 class GetChannelListCommand : public WifiCommand
265 {
266 wifi_channel *channels;
267 int max_channels;
268 int *num_channels;
269 int band;
270 public:
GetChannelListCommand(wifi_interface_handle iface,wifi_channel * channel_buf,int * ch_num,int num_max_ch,int band)271 GetChannelListCommand(wifi_interface_handle iface, wifi_channel *channel_buf, int *ch_num,
272 int num_max_ch, int band)
273 : WifiCommand("GetChannelListCommand", iface, 0), channels(channel_buf),
274 max_channels(num_max_ch), num_channels(ch_num), band(band)
275 {
276 memset(channels, 0, sizeof(wifi_channel) * max_channels);
277 }
create()278 virtual int create() {
279 ALOGV("Creating message to get channel list; iface = %d", mIfaceInfo->id);
280
281 int ret = mMsg.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_CHANNEL_LIST);
282 if (ret < 0) {
283 return ret;
284 }
285
286 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
287 ret = mMsg.put_u32(GSCAN_ATTRIBUTE_BAND, band);
288 if (ret < 0) {
289 return ret;
290 }
291
292 mMsg.attr_end(data);
293
294 return ret;
295 }
296
297 protected:
handleResponse(WifiEvent & reply)298 virtual int handleResponse(WifiEvent& reply) {
299
300 ALOGV("In GetChannelList::handleResponse");
301
302 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
303 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
304 return NL_SKIP;
305 }
306
307 int id = reply.get_vendor_id();
308 int subcmd = reply.get_vendor_subcmd();
309 int num_channels_to_copy = 0;
310
311 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
312 int len = reply.get_vendor_data_len();
313
314 ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
315 if (vendor_data == NULL || len == 0) {
316 ALOGE("no vendor data in GetChannelList response; ignoring it");
317 return NL_SKIP;
318 }
319
320 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
321 if (it.get_type() == GSCAN_ATTRIBUTE_NUM_CHANNELS) {
322 num_channels_to_copy = it.get_u32();
323 ALOGI("Got channel list with %d channels", num_channels_to_copy);
324 if(num_channels_to_copy > max_channels)
325 num_channels_to_copy = max_channels;
326 *num_channels = num_channels_to_copy;
327 } else if (it.get_type() == GSCAN_ATTRIBUTE_CHANNEL_LIST && num_channels_to_copy) {
328 memcpy(channels, it.get_data(), sizeof(int) * num_channels_to_copy);
329 } else {
330 ALOGW("Ignoring invalid attribute type = %d, size = %d",
331 it.get_type(), it.get_len());
332 }
333 }
334
335 return NL_OK;
336 }
337 };
338
wifi_get_valid_channels(wifi_interface_handle handle,int band,int max_channels,wifi_channel * channels,int * num_channels)339 wifi_error wifi_get_valid_channels(wifi_interface_handle handle,
340 int band, int max_channels, wifi_channel *channels, int *num_channels)
341 {
342 GetChannelListCommand command(handle, channels, num_channels,
343 max_channels, band);
344 return (wifi_error) command.requestResponse();
345 }
346 /////////////////////////////////////////////////////////////////////////////
347
348 /* helper functions */
createFeatureRequest(WifiRequest & request,int subcmd,int enable)349 int createFeatureRequest(WifiRequest& request, int subcmd, int enable) {
350
351 int result = request.create(GOOGLE_OUI, subcmd);
352 if (result < 0) {
353 return result;
354 }
355
356 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
357 result = request.put_u32(GSCAN_ATTRIBUTE_ENABLE_FEATURE, enable);
358 if (result < 0) {
359 return result;
360 }
361
362 request.attr_end(data);
363 return WIFI_SUCCESS;
364 }
365
366 /////////////////////////////////////////////////////////////////////////////
367 class FullScanResultsCommand : public WifiCommand
368 {
369 int *mParams;
370 wifi_scan_result_handler mHandler;
371 public:
FullScanResultsCommand(wifi_interface_handle iface,int id,int * params,wifi_scan_result_handler handler)372 FullScanResultsCommand(wifi_interface_handle iface, int id, int *params,
373 wifi_scan_result_handler handler)
374 : WifiCommand("FullScanResultsCommand", iface, id), mParams(params), mHandler(handler)
375 {*mParams = 0;}
376
createRequest(WifiRequest & request,int subcmd,int enable)377 int createRequest(WifiRequest& request, int subcmd, int enable) {
378 int result = request.create(GOOGLE_OUI, subcmd);
379 if (result < 0) {
380 return result;
381 }
382
383 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
384 result = request.put_u32(GSCAN_ENABLE_FULL_SCAN_RESULTS, enable);
385 if (result < 0) {
386 return result;
387 }
388
389 request.attr_end(data);
390 return WIFI_SUCCESS;
391
392 }
393
start()394 int start() {
395 ALOGV("Enabling Full scan results");
396 WifiRequest request(familyId(), ifaceId());
397 int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 1);
398 if (result != WIFI_SUCCESS) {
399 ALOGE("failed to create request; result = %d", result);
400 return result;
401 }
402
403 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
404
405 result = requestResponse(request);
406 if (result != WIFI_SUCCESS) {
407 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
408 ALOGE("failed to enable full scan results; result = %d", result);
409 return result;
410 }
411
412 return result;
413 }
414
cancel()415 virtual int cancel() {
416 ALOGV("Disabling Full scan results");
417
418 WifiRequest request(familyId(), ifaceId());
419 int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 0);
420 if (result != WIFI_SUCCESS) {
421 ALOGE("failed to create request; result = %d", result);
422 } else {
423 result = requestResponse(request);
424 if (result != WIFI_SUCCESS) {
425 ALOGE("failed to disable full scan results;result = %d", result);
426 }
427 }
428
429 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
430 return WIFI_SUCCESS;
431 }
432
handleResponse(WifiEvent & reply)433 virtual int handleResponse(WifiEvent& reply) {
434 ALOGD("Request complete!");
435 /* Nothing to do on response! */
436 return NL_SKIP;
437 }
438
handleEvent(WifiEvent & event)439 virtual int handleEvent(WifiEvent& event) {
440 ALOGV("Full scan results: Got an event");
441 return wifi_handle_full_scan_event(id(), event, mHandler);
442 }
443
444 };
445 /////////////////////////////////////////////////////////////////////////////
446
447 class ScanCommand : public WifiCommand
448 {
449 wifi_scan_cmd_params *mParams;
450 wifi_scan_result_handler mHandler;
451 public:
ScanCommand(wifi_interface_handle iface,int id,wifi_scan_cmd_params * params,wifi_scan_result_handler handler)452 ScanCommand(wifi_interface_handle iface, int id, wifi_scan_cmd_params *params,
453 wifi_scan_result_handler handler)
454 : WifiCommand("ScanCommand", iface, id), mParams(params), mHandler(handler)
455 { }
456
createSetupRequest(WifiRequest & request)457 int createSetupRequest(WifiRequest& request) {
458 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_CONFIG);
459 if (result < 0) {
460 return result;
461 }
462
463 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
464 result = request.put_u32(GSCAN_ATTRIBUTE_BASE_PERIOD, mParams->base_period);
465 if (result < 0) {
466 return result;
467 }
468
469 result = request.put_u32(GSCAN_ATTRIBUTE_NUM_BUCKETS, mParams->num_buckets);
470 if (result < 0) {
471 return result;
472 }
473
474 for (int i = 0; i < mParams->num_buckets; i++) {
475 nlattr * bucket = request.attr_start(i); // next bucket
476 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_ID, mParams->buckets[i].bucket);
477 if (result < 0) {
478 return result;
479 }
480 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_PERIOD, mParams->buckets[i].period);
481 if (result < 0) {
482 return result;
483 }
484 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKETS_BAND,
485 mParams->buckets[i].band);
486 if (result < 0) {
487 return result;
488 }
489 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT,
490 mParams->buckets[i].step_count);
491 if (result < 0) {
492 return result;
493 }
494 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD,
495 mParams->buckets[i].max_period);
496 if (result < 0) {
497 return result;
498 }
499 result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_EVENTS,
500 mParams->buckets[i].report_events);
501 if (result < 0) {
502 return result;
503 }
504
505 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS,
506 mParams->buckets[i].num_channels);
507 if (result < 0) {
508 return result;
509 }
510
511 if (mParams->buckets[i].num_channels) {
512 nlattr *channels = request.attr_start(GSCAN_ATTRIBUTE_BUCKET_CHANNELS);
513 ALOGV(" channels: ");
514 for (int j = 0; j < mParams->buckets[i].num_channels; j++) {
515 result = request.put_u32(j, mParams->buckets[i].channels[j].channel);
516 ALOGV(" %u", mParams->buckets[i].channels[j].channel);
517
518 if (result < 0) {
519 return result;
520 }
521 }
522 request.attr_end(channels);
523 }
524
525 request.attr_end(bucket);
526 }
527
528 request.attr_end(data);
529 return WIFI_SUCCESS;
530 }
531
createScanConfigRequest(WifiRequest & request)532 int createScanConfigRequest(WifiRequest& request) {
533 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SCAN_CONFIG);
534 if (result < 0) {
535 return result;
536 }
537
538 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
539 result = request.put_u32(GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, mParams->max_ap_per_scan);
540 if (result < 0) {
541 return result;
542 }
543
544 result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD,
545 mParams->report_threshold_percent);
546 if (result < 0) {
547 return result;
548 }
549
550 int num_scans = mParams->report_threshold_num_scans;
551
552 result = request.put_u32(GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, num_scans);
553 if (result < 0) {
554 return result;
555 }
556
557 request.attr_end(data);
558 return WIFI_SUCCESS;
559 }
560
createStartRequest(WifiRequest & request)561 int createStartRequest(WifiRequest& request) {
562 return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
563 }
564
createStopRequest(WifiRequest & request)565 int createStopRequest(WifiRequest& request) {
566 return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 0);
567 }
568
unregisterVendorHandlerAll()569 void unregisterVendorHandlerAll() {
570 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
571 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
572 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
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 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
585 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
586 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
587
588 result = requestResponse(request);
589 if (result != WIFI_SUCCESS) {
590 unregisterVendorHandlerAll();
591 ALOGE("failed to configure setup; result = %d", result);
592 return result;
593 }
594
595 request.destroy();
596
597 result = createScanConfigRequest(request);
598 if (result != WIFI_SUCCESS) {
599 unregisterVendorHandlerAll();
600 ALOGE("failed to create scan config request; result = %d", result);
601 return result;
602 }
603
604 result = requestResponse(request);
605 if (result != WIFI_SUCCESS) {
606 unregisterVendorHandlerAll();
607 ALOGE("failed to configure scan; result = %d", result);
608 return result;
609 }
610
611 ALOGV(" ....starting scan");
612
613 result = createStartRequest(request);
614 if (result != WIFI_SUCCESS) {
615 unregisterVendorHandlerAll();
616 ALOGE("failed to create start request; result = %d", result);
617 return result;
618 }
619
620 result = requestResponse(request);
621 if (result != WIFI_SUCCESS) {
622 unregisterVendorHandlerAll();
623 ALOGE("failed to start scan; result = %d", result);
624 return result;
625 }
626 return result;
627 }
628
cancel()629 virtual int cancel() {
630 ALOGV("Stopping scan");
631
632 WifiRequest request(familyId(), ifaceId());
633 int result = createStopRequest(request);
634 if (result != WIFI_SUCCESS) {
635 ALOGE("failed to create stop request; result = %d", result);
636 } else {
637 result = requestResponse(request);
638 if (result != WIFI_SUCCESS) {
639 ALOGE("failed to stop scan; result = %d", result);
640 }
641 }
642
643 unregisterVendorHandlerAll();
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 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 %lu!\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 %ld %lx %lx %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
798 if(id == -1) {
799 wifi_scan_result_handler handler;
800 int params_dummy;
801
802 memset(&handler, 0, sizeof(handler));
803 FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, 0, ¶ms_dummy, handler);
804 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
805 cmd->cancel();
806 cmd->releaseRef();
807 return WIFI_SUCCESS;
808 }
809
810 return wifi_cancel_cmd(id, iface);
811 }
812
813
814 /////////////////////////////////////////////////////////////////////////////
815
816 class GetScanResultsCommand : public WifiCommand {
817 wifi_cached_scan_results *mScans;
818 int mMax;
819 int *mNum;
820 int mRetrieved;
821 byte mFlush;
822 int mCompleted;
823 public:
GetScanResultsCommand(wifi_interface_handle iface,byte flush,wifi_cached_scan_results * results,int max,int * num)824 GetScanResultsCommand(wifi_interface_handle iface, byte flush,
825 wifi_cached_scan_results *results, int max, int *num)
826 : WifiCommand("GetScanResultsCommand", iface, -1), mScans(results), mMax(max), mNum(num),
827 mRetrieved(0), mFlush(flush), mCompleted(0)
828 { }
829
createRequest(WifiRequest & request,int num,byte flush)830 int createRequest(WifiRequest& request, int num, byte flush) {
831 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_SCAN_RESULTS);
832 if (result < 0) {
833 return result;
834 }
835
836 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
837 result = request.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num);
838 if (result < 0) {
839 return result;
840 }
841
842 result = request.put_u8(GSCAN_ATTRIBUTE_FLUSH_RESULTS, flush);
843 if (result < 0) {
844 return result;
845 }
846
847 request.attr_end(data);
848 return WIFI_SUCCESS;
849 }
850
execute()851 int execute() {
852 WifiRequest request(familyId(), ifaceId());
853 ALOGV("retrieving %d scan results", mMax);
854
855 for (int i = 0; i < 10 && mRetrieved < mMax; i++) {
856 int num_to_retrieve = mMax - mRetrieved;
857 // ALOGI("retrieving %d scan results in one shot", num_to_retrieve);
858 int result = createRequest(request, num_to_retrieve, mFlush);
859 if (result < 0) {
860 ALOGE("failed to create request");
861 return result;
862 }
863
864 int prev_retrieved = mRetrieved;
865
866 result = requestResponse(request);
867
868 if (result != WIFI_SUCCESS) {
869 ALOGE("failed to retrieve scan results; result = %d", result);
870 return result;
871 }
872
873 if (mRetrieved == prev_retrieved || mCompleted) {
874 /* no more items left to retrieve */
875 break;
876 }
877
878 request.destroy();
879 }
880
881 ALOGV("GetScanResults read %d results", mRetrieved);
882 *mNum = mRetrieved;
883 return WIFI_SUCCESS;
884 }
885
handleResponse(WifiEvent & reply)886 virtual int handleResponse(WifiEvent& reply) {
887 ALOGV("In GetScanResultsCommand::handleResponse");
888
889 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
890 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
891 return NL_SKIP;
892 }
893
894 int id = reply.get_vendor_id();
895 int subcmd = reply.get_vendor_subcmd();
896
897 ALOGV("Id = %0x, subcmd = %d", id, subcmd);
898
899 /*
900 if (subcmd != GSCAN_SUBCMD_SCAN_RESULTS) {
901 ALOGE("Invalid response to GetScanResultsCommand; ignoring it");
902 return NL_SKIP;
903 }
904 */
905
906 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
907 int len = reply.get_vendor_data_len();
908
909 if (vendor_data == NULL || len == 0) {
910 ALOGE("no vendor data in GetScanResults response; ignoring it");
911 return NL_SKIP;
912 }
913
914 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
915 if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE) {
916 mCompleted = it.get_u8();
917 ALOGV("retrieved mCompleted flag : %d", mCompleted);
918 } else if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS || it.get_type() == 0) {
919 int scan_id = 0, flags = 0, num = 0, scan_ch_bucket_mask = 0;
920 for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) {
921 if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_ID) {
922 scan_id = it2.get_u32();
923 ALOGV("retrieved scan_id : 0x%0x", scan_id);
924 } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_FLAGS) {
925 flags = it2.get_u8();
926 ALOGV("retrieved scan_flags : 0x%0x", flags);
927 } else if (it2.get_type() == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) {
928 num = it2.get_u32();
929 ALOGV("retrieved num_results: %d", num);
930 } else if (it2.get_type() == GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK) {
931 scan_ch_bucket_mask = it2.get_u32();
932 ALOGD("retrieved scan_ch_bucket_mask: %x", scan_ch_bucket_mask);
933 } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS && num) {
934 if (mRetrieved >= mMax) {
935 ALOGW("Stored %d scans, ignoring excess results", mRetrieved);
936 break;
937 }
938 num = min(num, (int)(it2.get_len()/sizeof(wifi_gscan_result)));
939 num = min(num, (int)MAX_AP_CACHE_PER_SCAN);
940 ALOGV("Copying %d scan results", num);
941 wifi_gscan_result_t *results = (wifi_gscan_result_t *)it2.get_data();
942 wifi_scan_result *mScanResults = mScans[mRetrieved].results;
943
944 for (int i = 0; i < num; i++) {
945 wifi_gscan_result_t *result = &results[i];
946 convert_to_hal_result(&mScanResults[i], result);
947 mScanResults[i].ie_length = 0;
948 ALOGV("%02d %-32s %02x:%02x:%02x:%02x:%02x:%02x %04d", i,
949 result->ssid, result->bssid[0], result->bssid[1], result->bssid[2],
950 result->bssid[3], result->bssid[4], result->bssid[5],
951 result->rssi);
952 }
953 mScans[mRetrieved].scan_id = scan_id;
954 mScans[mRetrieved].flags = flags;
955 mScans[mRetrieved].num_results = num;
956 mScans[mRetrieved].buckets_scanned = scan_ch_bucket_mask;
957 ALOGV("Setting result of scan_id : 0x%0x", mScans[mRetrieved].scan_id);
958 mRetrieved++;
959 } else {
960 ALOGW("Ignoring invalid attribute type = %d, size = %d",
961 it.get_type(), it.get_len());
962 }
963 }
964 } else {
965 ALOGW("Ignoring invalid attribute type = %d, size = %d",
966 it.get_type(), it.get_len());
967 }
968 }
969 ALOGV("GetScanResults read %d results", mRetrieved);
970 return NL_OK;
971 }
972 };
973
wifi_get_cached_gscan_results(wifi_interface_handle iface,byte flush,int max,wifi_cached_scan_results * results,int * num)974 wifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface, byte flush,
975 int max, wifi_cached_scan_results *results, int *num) {
976 ALOGV("Getting cached scan results, iface handle = %p, num = %d", iface, *num);
977
978 GetScanResultsCommand *cmd = new GetScanResultsCommand(iface, flush, results, max, num);
979 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
980 wifi_error err = (wifi_error)cmd->execute();
981 cmd->releaseRef();
982 return err;
983 }
984
985 /////////////////////////////////////////////////////////////////////////////
986
987 class BssidHotlistCommand : public WifiCommand
988 {
989 private:
990 wifi_bssid_hotlist_params mParams;
991 wifi_hotlist_ap_found_handler mHandler;
992 static const int MAX_RESULTS = 64;
993 wifi_scan_result mResults[MAX_RESULTS];
994 public:
BssidHotlistCommand(wifi_interface_handle handle,int id,wifi_bssid_hotlist_params params,wifi_hotlist_ap_found_handler handler)995 BssidHotlistCommand(wifi_interface_handle handle, int id,
996 wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler)
997 : WifiCommand("BssidHotlistCommand", handle, id), mParams(params), mHandler(handler)
998 { }
999
createSetupRequest(WifiRequest & request)1000 int createSetupRequest(WifiRequest& request) {
1001 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST);
1002 if (result < 0) {
1003 return result;
1004 }
1005
1006 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1007 result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1);
1008 if (result < 0) {
1009 return result;
1010 }
1011
1012 result = request.put_u32(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size);
1013 if (result < 0) {
1014 return result;
1015 }
1016
1017 result = request.put_u32(GSCAN_ATTRIBUTE_HOTLIST_BSSID_COUNT, mParams.num_bssid);
1018 if (result < 0) {
1019 return result;
1020 }
1021
1022 struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS);
1023 for (int i = 0; i < mParams.num_bssid; i++) {
1024 nlattr *attr2 = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM);
1025 if (attr2 == NULL) {
1026 return WIFI_ERROR_OUT_OF_MEMORY;
1027 }
1028 result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid);
1029 if (result < 0) {
1030 return result;
1031 }
1032 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high);
1033 if (result < 0) {
1034 return result;
1035 }
1036 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low);
1037 if (result < 0) {
1038 return result;
1039 }
1040 request.attr_end(attr2);
1041 }
1042
1043 request.attr_end(attr);
1044 request.attr_end(data);
1045 return result;
1046 }
1047
createTeardownRequest(WifiRequest & request)1048 int createTeardownRequest(WifiRequest& request) {
1049 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST);
1050 if (result < 0) {
1051 return result;
1052 }
1053
1054 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1055 result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1);
1056 if (result < 0) {
1057 return result;
1058 }
1059
1060 struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS);
1061 request.attr_end(attr);
1062 request.attr_end(data);
1063 return result;
1064 }
1065
unregisterVendorHandlerAll()1066 void unregisterVendorHandlerAll() {
1067 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
1068 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
1069 }
1070
start()1071 int start() {
1072 ALOGI("Executing hotlist setup request, num = %d", mParams.num_bssid);
1073 WifiRequest request(familyId(), ifaceId());
1074 int result = createSetupRequest(request);
1075 if (result < 0) {
1076 return result;
1077 }
1078
1079 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
1080 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
1081
1082 result = requestResponse(request);
1083 if (result < 0) {
1084 unregisterVendorHandlerAll();
1085 ALOGI("Failed to execute hotlist setup request, result = %d", result);
1086 return result;
1087 }
1088
1089 ALOGI("Successfully set %d APs in the hotlist ", mParams.num_bssid);
1090 result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
1091 if (result < 0) {
1092 unregisterVendorHandlerAll();
1093 return result;
1094 }
1095
1096 result = requestResponse(request);
1097 if (result < 0) {
1098 unregisterVendorHandlerAll();
1099 return result;
1100 }
1101
1102 ALOGI("successfully restarted the scan");
1103 return result;
1104 }
1105
cancel()1106 virtual int cancel() {
1107 /* unregister event handler */
1108 unregisterVendorHandlerAll();
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 char tmp_buf[DOT11_MAX_SSID_LEN + 1];
1184 if (epno_params.num_networks > MAX_EPNO_NETWORKS) {
1185 ALOGE("wrong epno num_networks:%d", epno_params.num_networks);
1186 return WIFI_ERROR_INVALID_ARGS;
1187 }
1188 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_EPNO_SSID);
1189 if (result < 0) {
1190 return result;
1191 }
1192 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1193 result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_FLUSH, 1);
1194 if (result < 0) {
1195 return result;
1196 }
1197
1198 result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR,
1199 (u8)epno_params.min5GHz_rssi);
1200 if (result < 0) {
1201 return result;
1202 }
1203 result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR,
1204 (u8)epno_params.min24GHz_rssi);
1205 if (result < 0) {
1206 return result;
1207 }
1208 result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX,
1209 epno_params.initial_score_max);
1210 if (result < 0) {
1211 return result;
1212 }
1213 result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS,
1214 epno_params.current_connection_bonus);
1215 if (result < 0) {
1216 return result;
1217 }
1218 result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS,
1219 epno_params.same_network_bonus);
1220 if (result < 0) {
1221 return result;
1222 }
1223 result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS,
1224 epno_params.secure_bonus);
1225 if (result < 0) {
1226 return result;
1227 }
1228 result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_5G_BONUS,
1229 epno_params.band5GHz_bonus);
1230 if (result < 0) {
1231 return result;
1232 }
1233 result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_SSID_NUM,
1234 epno_params.num_networks);
1235 if (result < 0) {
1236 return result;
1237 }
1238 struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_EPNO_SSID_LIST);
1239 wifi_epno_network *ssid_list = epno_params.networks;
1240 for (int i = 0; i < epno_params.num_networks; i++) {
1241 nlattr *attr2 = request.attr_start(i);
1242 if (attr2 == NULL) {
1243 return WIFI_ERROR_OUT_OF_MEMORY;
1244 }
1245 strlcpy(tmp_buf, ssid_list[i].ssid, sizeof(tmp_buf));
1246 result = request.put(GSCAN_ATTRIBUTE_EPNO_SSID, tmp_buf,
1247 strlen(tmp_buf));
1248 ALOGI("PNO network: SSID %s flags %x auth %x", tmp_buf,
1249 ssid_list[i].flags,
1250 ssid_list[i].auth_bit_field);
1251 if (result < 0) {
1252 return result;
1253 }
1254 result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_SSID_LEN,
1255 strlen(tmp_buf));
1256 if (result < 0) {
1257 return result;
1258 }
1259 result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_FLAGS, ssid_list[i].flags);
1260 if (result < 0) {
1261 return result;
1262 }
1263 result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_AUTH, ssid_list[i].auth_bit_field);
1264 if (result < 0) {
1265 return result;
1266 }
1267 request.attr_end(attr2);
1268 }
1269 request.attr_end(attr);
1270 request.attr_end(data);
1271 return result;
1272 }
1273
createTeardownRequest(WifiRequest & request)1274 int createTeardownRequest(WifiRequest& request) {
1275 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_EPNO_SSID);
1276 if (result < 0) {
1277 return result;
1278 }
1279
1280 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1281 result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_FLUSH, 1);
1282 if (result < 0) {
1283 return result;
1284 }
1285 request.attr_end(data);
1286 return result;
1287 }
1288
start()1289 int start() {
1290 ALOGI("Executing ePNO setup request, num = %d", epno_params.num_networks);
1291 WifiRequest request(familyId(), ifaceId());
1292 int result = createSetupRequest(request);
1293 if (result < 0) {
1294 return result;
1295 }
1296
1297 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT);
1298 result = requestResponse(request);
1299 if (result < 0) {
1300 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT);
1301 ALOGI("Failed to execute ePNO setup request, result = %d", result);
1302 return result;
1303 }
1304
1305 ALOGI("Successfully set %d SSIDs for ePNO", epno_params.num_networks);
1306 ALOGI("successfully restarted the scan");
1307 return result;
1308 }
1309
cancel()1310 virtual int cancel() {
1311 /* unregister event handler */
1312 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT);
1313 /* create set hotlist message with empty hotlist */
1314 WifiRequest request(familyId(), ifaceId());
1315 int result = createTeardownRequest(request);
1316 if (result < 0) {
1317 return result;
1318 }
1319
1320 result = requestResponse(request);
1321 if (result < 0) {
1322 return result;
1323 }
1324
1325 ALOGI("Successfully reset APs in current hotlist");
1326 return result;
1327 }
1328
handleResponse(WifiEvent & reply)1329 virtual int handleResponse(WifiEvent& reply) {
1330 /* Nothing to do on response! */
1331 return NL_SKIP;
1332 }
1333
handleEvent(WifiEvent & event)1334 virtual int handleEvent(WifiEvent& event) {
1335 ALOGI("ePNO event");
1336 // event.log();
1337
1338 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
1339 int len = event.get_vendor_data_len();
1340
1341 if (vendor_data == NULL || len == 0) {
1342 ALOGI("No scan results found");
1343 return NL_SKIP;
1344 }
1345
1346 memset(mResults, 0, sizeof(wifi_scan_result) * MAX_EPNO_NETWORKS);
1347
1348 unsigned int num = len / sizeof(wifi_pno_result_t);
1349 unsigned int i;
1350 num = min(MAX_EPNO_NETWORKS, num);
1351 wifi_pno_result_t *res = (wifi_pno_result_t *) event.get_vendor_data();
1352 for (i = 0; i < num; i++) {
1353 if (res[i].flags == PNO_SSID_FOUND) {
1354 memcpy(mResults[i].ssid, res[i].ssid, res[i].ssid_len);
1355 memcpy(mResults[i].bssid, res[i].bssid, sizeof(mac_addr));
1356
1357 mResults[i].ssid[res[i].ssid_len] = '\0';
1358 mResults[i].channel = res[i].channel;
1359 mResults[i].rssi = res[i].rssi;
1360 }
1361 }
1362 if (*mHandler.on_network_found)
1363 (*mHandler.on_network_found)(id(), num, mResults);
1364 return NL_SKIP;
1365 }
1366 };
1367
wifi_set_bssid_hotlist(wifi_request_id id,wifi_interface_handle iface,wifi_bssid_hotlist_params params,wifi_hotlist_ap_found_handler handler)1368 wifi_error wifi_set_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface,
1369 wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler)
1370 {
1371 wifi_handle handle = getWifiHandle(iface);
1372
1373 BssidHotlistCommand *cmd = new BssidHotlistCommand(iface, id, params, handler);
1374 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1375 wifi_error result = wifi_register_cmd(handle, id, cmd);
1376 if (result != WIFI_SUCCESS) {
1377 cmd->releaseRef();
1378 return result;
1379 }
1380 result = (wifi_error)cmd->start();
1381 if (result != WIFI_SUCCESS) {
1382 wifi_unregister_cmd(handle, id);
1383 cmd->releaseRef();
1384 return result;
1385 }
1386 return result;
1387 }
1388
wifi_reset_bssid_hotlist(wifi_request_id id,wifi_interface_handle iface)1389 wifi_error wifi_reset_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface)
1390 {
1391 return wifi_cancel_cmd(id, iface);
1392 }
1393
1394
1395 /////////////////////////////////////////////////////////////////////////////
1396
1397 class SignificantWifiChangeCommand : public WifiCommand
1398 {
1399 typedef struct {
1400 mac_addr bssid; // BSSID
1401 wifi_channel channel; // channel frequency in MHz
1402 int num_rssi; // number of rssi samples
1403 wifi_rssi rssi[8]; // RSSI history in db
1404 } wifi_significant_change_result_internal;
1405
1406 private:
1407 wifi_significant_change_params mParams;
1408 wifi_significant_change_handler mHandler;
1409 static const int MAX_RESULTS = 64;
1410 wifi_significant_change_result_internal mResultsBuffer[MAX_RESULTS];
1411 wifi_significant_change_result *mResults[MAX_RESULTS];
1412 public:
SignificantWifiChangeCommand(wifi_interface_handle handle,int id,wifi_significant_change_params params,wifi_significant_change_handler handler)1413 SignificantWifiChangeCommand(wifi_interface_handle handle, int id,
1414 wifi_significant_change_params params, wifi_significant_change_handler handler)
1415 : WifiCommand("SignificantWifiChangeCommand", handle, id), mParams(params),
1416 mHandler(handler)
1417 { }
1418
createSetupRequest(WifiRequest & request)1419 int createSetupRequest(WifiRequest& request) {
1420 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG);
1421 if (result < 0) {
1422 return result;
1423 }
1424
1425 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1426 result = request.put_u8(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1);
1427 if (result < 0) {
1428 return result;
1429 }
1430 result = request.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE, mParams.rssi_sample_size);
1431 if (result < 0) {
1432 return result;
1433 }
1434 result = request.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size);
1435 if (result < 0) {
1436 return result;
1437 }
1438 result = request.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING, mParams.min_breaching);
1439 if (result < 0) {
1440 return result;
1441 }
1442 result = request.put_u16(GSCAN_ATTRIBUTE_NUM_BSSID, mParams.num_bssid);
1443 if (result < 0) {
1444 return result;
1445 }
1446 if (mParams.num_bssid != 0) {
1447 nlattr* attr = request.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS);
1448 if (attr == NULL) {
1449 return WIFI_ERROR_OUT_OF_MEMORY;
1450 }
1451
1452 for (int i = 0; i < mParams.num_bssid; i++) {
1453 nlattr* attr2 = request.attr_start(i);
1454 if (attr2 == NULL) {
1455 return WIFI_ERROR_OUT_OF_MEMORY;
1456 }
1457 result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid);
1458 if (result < 0) {
1459 return result;
1460 }
1461 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high);
1462 if (result < 0) {
1463 return result;
1464 }
1465 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low);
1466 if (result < 0) {
1467 return result;
1468 }
1469 request.attr_end(attr2);
1470 }
1471
1472 request.attr_end(attr);
1473 }
1474 request.attr_end(data);
1475
1476 return result;
1477 }
1478
createTeardownRequest(WifiRequest & request)1479 int createTeardownRequest(WifiRequest& request) {
1480 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG);
1481 if (result < 0) {
1482 return result;
1483 }
1484
1485 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1486 result = request.put_u16(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1);
1487 if (result < 0) {
1488 return result;
1489 }
1490
1491 request.attr_end(data);
1492 return result;
1493 }
1494
start()1495 int start() {
1496 ALOGI("Set significant wifi change config");
1497 WifiRequest request(familyId(), ifaceId());
1498
1499 int result = createSetupRequest(request);
1500 if (result < 0) {
1501 return result;
1502 }
1503
1504 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
1505
1506 result = requestResponse(request);
1507 if (result < 0) {
1508 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
1509 ALOGI("failed to set significant wifi change config %d", result);
1510 return result;
1511 }
1512
1513 ALOGI("successfully set significant wifi change config");
1514
1515 result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
1516 if (result < 0) {
1517 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
1518 return result;
1519 }
1520
1521 result = requestResponse(request);
1522 if (result < 0) {
1523 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
1524 return result;
1525 }
1526
1527 ALOGI("successfully restarted the scan");
1528 return result;
1529 }
1530
cancel()1531 virtual int cancel() {
1532 /* unregister event handler */
1533 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
1534
1535 /* create set significant change monitor message with empty hotlist */
1536 WifiRequest request(familyId(), ifaceId());
1537
1538 int result = createTeardownRequest(request);
1539 if (result < 0) {
1540 return result;
1541 }
1542
1543 result = requestResponse(request);
1544 if (result < 0) {
1545 return result;
1546 }
1547
1548 ALOGI("successfully reset significant wifi change config");
1549 return result;
1550 }
1551
handleResponse(WifiEvent & reply)1552 virtual int handleResponse(WifiEvent& reply) {
1553 /* Nothing to do on response! */
1554 return NL_SKIP;
1555 }
1556
handleEvent(WifiEvent & event)1557 virtual int handleEvent(WifiEvent& event) {
1558 ALOGV("Got a significant wifi change event");
1559
1560 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
1561 int len = event.get_vendor_data_len();
1562
1563 if (vendor_data == NULL || len == 0) {
1564 ALOGI("No scan results found");
1565 return NL_SKIP;
1566 }
1567
1568 typedef struct {
1569 uint16_t flags;
1570 uint16_t channel;
1571 mac_addr bssid;
1572 s8 rssi_history[8];
1573 } ChangeInfo;
1574
1575 int num = min(len / sizeof(ChangeInfo), MAX_RESULTS);
1576 ChangeInfo *ci = (ChangeInfo *)event.get_vendor_data();
1577
1578 for (int i = 0; i < num; i++) {
1579 memcpy(mResultsBuffer[i].bssid, ci[i].bssid, sizeof(mac_addr));
1580 mResultsBuffer[i].channel = ci[i].channel;
1581 mResultsBuffer[i].num_rssi = 8;
1582 for (int j = 0; j < mResultsBuffer[i].num_rssi; j++)
1583 mResultsBuffer[i].rssi[j] = (int) ci[i].rssi_history[j];
1584 mResults[i] = reinterpret_cast<wifi_significant_change_result *>(&(mResultsBuffer[i]));
1585 }
1586
1587 ALOGV("Retrieved %d scan results", num);
1588
1589 if (num != 0) {
1590 (*mHandler.on_significant_change)(id(), num, mResults);
1591 } else {
1592 ALOGW("No significant change reported");
1593 }
1594
1595 return NL_SKIP;
1596 }
1597 };
1598
wifi_set_significant_change_handler(wifi_request_id id,wifi_interface_handle iface,wifi_significant_change_params params,wifi_significant_change_handler handler)1599 wifi_error wifi_set_significant_change_handler(wifi_request_id id, wifi_interface_handle iface,
1600 wifi_significant_change_params params, wifi_significant_change_handler handler)
1601 {
1602 wifi_handle handle = getWifiHandle(iface);
1603
1604 SignificantWifiChangeCommand *cmd = new SignificantWifiChangeCommand(
1605 iface, id, params, handler);
1606 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1607 wifi_error result = wifi_register_cmd(handle, id, cmd);
1608 if (result != WIFI_SUCCESS) {
1609 cmd->releaseRef();
1610 return result;
1611 }
1612 result = (wifi_error)cmd->start();
1613 if (result != WIFI_SUCCESS) {
1614 wifi_unregister_cmd(handle, id);
1615 cmd->releaseRef();
1616 return result;
1617 }
1618 return result;
1619 }
1620
wifi_reset_significant_change_handler(wifi_request_id id,wifi_interface_handle iface)1621 wifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface)
1622 {
1623 return wifi_cancel_cmd(id, iface);
1624 }
1625
wifi_reset_epno_list(wifi_request_id id,wifi_interface_handle iface)1626 wifi_error wifi_reset_epno_list(wifi_request_id id, wifi_interface_handle iface)
1627 {
1628 if (id == -1) {
1629 wifi_epno_handler handler;
1630
1631 memset(&handler, 0, sizeof(handler));
1632 ePNOCommand *cmd = new ePNOCommand(iface, id, NULL, handler);
1633 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1634 cmd->cancel();
1635 cmd->releaseRef();
1636 return WIFI_SUCCESS;
1637 }
1638 return wifi_cancel_cmd(id, iface);
1639 }
1640
wifi_set_epno_list(wifi_request_id id,wifi_interface_handle iface,const wifi_epno_params * params,wifi_epno_handler handler)1641 wifi_error wifi_set_epno_list(wifi_request_id id, wifi_interface_handle iface,
1642 const wifi_epno_params *params, wifi_epno_handler handler)
1643 {
1644 wifi_handle handle = getWifiHandle(iface);
1645 if (handler.on_network_found == NULL) {
1646 return WIFI_ERROR_INVALID_ARGS;
1647 }
1648
1649 ePNOCommand *cmd = new ePNOCommand(iface, id, params, handler);
1650 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1651 wifi_error result = wifi_register_cmd(handle, id, cmd);
1652 if (result != WIFI_SUCCESS) {
1653 cmd->releaseRef();
1654 return result;
1655 }
1656 result = (wifi_error)cmd->start();
1657 if (result != WIFI_SUCCESS) {
1658 wifi_unregister_cmd(handle, id);
1659 cmd->releaseRef();
1660 return result;
1661 }
1662 return result;
1663 }
1664
1665 class BssidBlacklistCommand : public WifiCommand
1666 {
1667 private:
1668 wifi_bssid_params *mParams;
1669 public:
BssidBlacklistCommand(wifi_interface_handle handle,int id,wifi_bssid_params * params)1670 BssidBlacklistCommand(wifi_interface_handle handle, int id,
1671 wifi_bssid_params *params)
1672 : WifiCommand("BssidBlacklistCommand", handle, id), mParams(params)
1673 { }
createRequest(WifiRequest & request)1674 int createRequest(WifiRequest& request) {
1675 if ((mParams->num_bssid < 0) || (mParams->num_bssid > MAX_BLACKLIST_BSSID)) {
1676 return WIFI_ERROR_INVALID_ARGS;
1677 }
1678 int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_SET_BSSID_BLACKLIST);
1679 if (result < 0) {
1680 return result;
1681 }
1682
1683 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1684 if (!mParams->num_bssid) {
1685 result = request.put_u32(GSCAN_ATTRIBUTE_BSSID_BLACKLIST_FLUSH, 1);
1686 if (result < 0) {
1687 return result;
1688 }
1689 } else {
1690 result = request.put_u32(GSCAN_ATTRIBUTE_NUM_BSSID, mParams->num_bssid);
1691 if (result < 0) {
1692 return result;
1693 }
1694 for (int i = 0; i < mParams->num_bssid; i++) {
1695 result = request.put_addr(GSCAN_ATTRIBUTE_BLACKLIST_BSSID, mParams->bssids[i]);
1696 if (result < 0) {
1697 return result;
1698 }
1699 }
1700 }
1701 request.attr_end(data);
1702 return result;
1703 }
1704
start()1705 int start() {
1706 ALOGV("Executing bssid blacklist request, num = %d", mParams->num_bssid);
1707 WifiRequest request(familyId(), ifaceId());
1708 int result = createRequest(request);
1709 if (result < 0) {
1710 return result;
1711 }
1712
1713 result = requestResponse(request);
1714 if (result < 0) {
1715 ALOGE("Failed to execute bssid blacklist request, result = %d", result);
1716 return result;
1717 }
1718
1719 ALOGI("Successfully added %d blacklist bssids", mParams->num_bssid);
1720 return result;
1721 }
1722
handleResponse(WifiEvent & reply)1723 virtual int handleResponse(WifiEvent& reply) {
1724 /* Nothing to do on response! */
1725 return NL_SKIP;
1726 }
1727 };
1728
wifi_set_bssid_blacklist(wifi_request_id id,wifi_interface_handle iface,wifi_bssid_params params)1729 wifi_error wifi_set_bssid_blacklist(wifi_request_id id, wifi_interface_handle iface,
1730 wifi_bssid_params params)
1731 {
1732 BssidBlacklistCommand *cmd = new BssidBlacklistCommand(iface, id, ¶ms);
1733 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1734 wifi_error result = (wifi_error)cmd->start();
1735 //release the reference of command as well
1736 cmd->releaseRef();
1737 return result;
1738 }
1739
wifi_configure_roaming(wifi_interface_handle iface,wifi_roaming_config * roam_config)1740 wifi_error wifi_configure_roaming(wifi_interface_handle iface,
1741 wifi_roaming_config *roam_config)
1742 {
1743 wifi_error ret;
1744 wifi_bssid_params bssid_params;
1745 unsigned int i;
1746 wifi_request_id id = 0;
1747
1748 /* Set bssid blacklist */
1749 if (roam_config->num_blacklist_bssid == 0) {
1750 /* Flush request */
1751 ALOGI("%s: num_blacklist_bssid == 0 (flush)", __FUNCTION__);
1752 }
1753
1754 bssid_params.num_bssid = roam_config->num_blacklist_bssid;
1755
1756 for (i = 0; i < roam_config->num_blacklist_bssid; i++) {
1757 mac_addr &addr1 = roam_config->blacklist_bssid[i];
1758 memcpy(&bssid_params.bssids[i], &roam_config->blacklist_bssid[i],
1759 sizeof(mac_addr));
1760 ALOGI("%02x:%02x:%02x:%02x:%02x:%02x\n", addr1[0],
1761 addr1[1], addr1[2], addr1[3], addr1[4], addr1[5]);
1762 }
1763 ret = wifi_set_bssid_blacklist(id, iface, bssid_params);
1764 if (ret != WIFI_SUCCESS) {
1765 ALOGE("%s: Failed to configure blacklist bssids", __FUNCTION__);
1766 return ret;
1767 }
1768
1769 return ret;
1770 }
1771
1772 class FirmwareRoamingStateCommand : public WifiCommand
1773 {
1774 private:
1775 fw_roaming_state_t roam_state;
1776 public:
FirmwareRoamingStateCommand(wifi_interface_handle handle,fw_roaming_state_t state)1777 FirmwareRoamingStateCommand(wifi_interface_handle handle,
1778 fw_roaming_state_t state)
1779 : WifiCommand("FirmwareRoamingStateCommand", handle, -1), roam_state(state)
1780 { }
createRequest(WifiRequest & request)1781 int createRequest(WifiRequest& request) {
1782 int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_FW_ROAM_POLICY);
1783 if (result < 0) {
1784 return result;
1785 }
1786
1787 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1788 result = request.put_u32(GSCAN_ATTRIBUTE_ROAM_STATE_SET, roam_state);
1789 if (result < 0) {
1790 return result;
1791 }
1792 request.attr_end(data);
1793 return result;
1794 }
1795
start()1796 int start() {
1797 ALOGV("Executing firmware roam state set, state = %d", roam_state);
1798 WifiRequest request(familyId(), ifaceId());
1799 int result = createRequest(request);
1800 if (result < 0) {
1801 return result;
1802 }
1803
1804 result = requestResponse(request);
1805 if (result < 0) {
1806 ALOGE("Failed to execute firmware roam state set, result = %d", result);
1807 return result;
1808 }
1809
1810 ALOGI("Successfully set firmware roam state - %d", roam_state);
1811 return result;
1812 }
1813
handleResponse(WifiEvent & reply)1814 virtual int handleResponse(WifiEvent& reply) {
1815 /* Nothing to do on response! */
1816 return NL_SKIP;
1817 }
1818 };
1819
wifi_enable_firmware_roaming(wifi_interface_handle iface,fw_roaming_state_t state)1820 wifi_error wifi_enable_firmware_roaming(wifi_interface_handle iface,
1821 fw_roaming_state_t state)
1822 {
1823 /* Set firmware roaming state */
1824 FirmwareRoamingStateCommand *cmd = new FirmwareRoamingStateCommand(iface, state);
1825 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1826 wifi_error result = (wifi_error)cmd->start();
1827 //release the reference of command as well
1828 cmd->releaseRef();
1829 return result;
1830 }
1831
1832 ////////////////////////////////////////////////////////////////////////////////
1833
1834 class AnqpoConfigureCommand : public WifiCommand
1835 {
1836 int num_hs;
1837 wifi_passpoint_network *mNetworks;
1838 wifi_passpoint_event_handler mHandler;
1839 wifi_scan_result *mResult;
1840 public:
AnqpoConfigureCommand(wifi_request_id id,wifi_interface_handle iface,int num,wifi_passpoint_network * hs_list,wifi_passpoint_event_handler handler)1841 AnqpoConfigureCommand(wifi_request_id id, wifi_interface_handle iface,
1842 int num, wifi_passpoint_network *hs_list, wifi_passpoint_event_handler handler)
1843 : WifiCommand("AnqpoConfigureCommand", iface, id), num_hs(num), mNetworks(hs_list),
1844 mHandler(handler)
1845 {
1846 mResult = NULL;
1847 }
1848
createRequest(WifiRequest & request,int val)1849 int createRequest(WifiRequest& request, int val) {
1850
1851 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_ANQPO_CONFIG);
1852 result = request.put_u32(GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE, num_hs);
1853 if (result < 0) {
1854 return result;
1855 }
1856
1857 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1858
1859 struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_ANQPO_HS_LIST);
1860 for (int i = 0; i < num_hs; i++) {
1861 nlattr *attr2 = request.attr_start(i);
1862 if (attr2 == NULL) {
1863 return WIFI_ERROR_OUT_OF_MEMORY;
1864 }
1865 result = request.put_u32(GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID, mNetworks[i].id);
1866 if (result < 0) {
1867 return result;
1868 }
1869 result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM, mNetworks[i].realm, 256);
1870 if (result < 0) {
1871 return result;
1872 }
1873 result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID,
1874 mNetworks[i].roamingConsortiumIds, 128);
1875 if (result < 0) {
1876 return result;
1877 }
1878 result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_PLMN, mNetworks[i].plmn, 3);
1879 if (result < 0) {
1880 return result;
1881 }
1882
1883 request.attr_end(attr2);
1884 }
1885
1886 request.attr_end(attr);
1887 request.attr_end(data);
1888
1889 return WIFI_SUCCESS;
1890 }
1891
start()1892 int start() {
1893
1894 WifiRequest request(familyId(), ifaceId());
1895 int result = createRequest(request, num_hs);
1896 if (result != WIFI_SUCCESS) {
1897 ALOGE("failed to create request; result = %d", result);
1898 return result;
1899 }
1900
1901 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH);
1902
1903 result = requestResponse(request);
1904 if (result != WIFI_SUCCESS) {
1905 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH);
1906 ALOGE("failed to set ANQPO networks; result = %d", result);
1907 return result;
1908 }
1909
1910 return result;
1911 }
1912
cancel()1913 virtual int cancel() {
1914
1915 WifiRequest request(familyId(), ifaceId());
1916 int result = createRequest(request, 0);
1917 if (result != WIFI_SUCCESS) {
1918 ALOGE("failed to create request; result = %d", result);
1919 } else {
1920 result = requestResponse(request);
1921 if (result != WIFI_SUCCESS) {
1922 ALOGE("failed to reset ANQPO networks;result = %d", result);
1923 }
1924 }
1925
1926 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH);
1927 return WIFI_SUCCESS;
1928 }
1929
handleResponse(WifiEvent & reply)1930 virtual int handleResponse(WifiEvent& reply) {
1931 ALOGD("Request complete!");
1932 /* Nothing to do on response! */
1933 return NL_SKIP;
1934 }
1935
handleEvent(WifiEvent & event)1936 virtual int handleEvent(WifiEvent& event) {
1937 typedef struct {
1938 u16 channel; /* channel of GAS protocol */
1939 u8 dialog_token; /* GAS dialog token */
1940 u8 fragment_id; /* fragment id */
1941 u16 status_code; /* status code on GAS completion */
1942 u16 data_len; /* length of data to follow */
1943 u8 data[1]; /* variable length specified by data_len */
1944 } wifi_anqp_gas_resp;
1945
1946 ALOGI("ANQPO hotspot matched event!");
1947
1948 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
1949 unsigned int len = event.get_vendor_data_len();
1950
1951 if (vendor_data == NULL || len < sizeof(wifi_scan_result)) {
1952 ALOGI("No scan results found");
1953 return NL_SKIP;
1954 }
1955 mResult = (wifi_scan_result *)malloc(sizeof(wifi_scan_result));
1956 if (!mResult) {
1957 return NL_SKIP;
1958 }
1959 wifi_gscan_full_result_t *drv_res = (wifi_gscan_full_result_t *)event.get_vendor_data();
1960 wifi_gscan_result_t *fixed = &drv_res->fixed;
1961 convert_to_hal_result(mResult, fixed);
1962
1963 byte *anqp = (byte *)drv_res + offsetof(wifi_gscan_full_result_t, ie_data) + drv_res->ie_length;
1964 wifi_anqp_gas_resp *gas = (wifi_anqp_gas_resp *)anqp;
1965 int anqp_len = offsetof(wifi_anqp_gas_resp, data) + gas->data_len;
1966 int networkId = *(int *)((byte *)anqp + anqp_len);
1967
1968 ALOGI("%-32s\t", mResult->ssid);
1969
1970 ALOGI("%02x:%02x:%02x:%02x:%02x:%02x ", mResult->bssid[0], mResult->bssid[1],
1971 mResult->bssid[2], mResult->bssid[3], mResult->bssid[4], mResult->bssid[5]);
1972
1973 ALOGI("rssi:%d\t", mResult->rssi);
1974 ALOGI("channel:%d\t", mResult->channel);
1975 ALOGI("ts:0x%jx\t", mResult->ts);
1976 ALOGI("rtt:0x%jx\t", mResult->rtt);
1977 ALOGI("rtt_sd:0x%jx\n", mResult->rtt_sd);
1978
1979 if(*mHandler.on_passpoint_network_found)
1980 (*mHandler.on_passpoint_network_found)(id(), networkId, mResult, anqp_len, anqp);
1981 free(mResult);
1982 return NL_SKIP;
1983 }
1984 };
1985
wifi_set_passpoint_list(wifi_request_id id,wifi_interface_handle iface,int num,wifi_passpoint_network * networks,wifi_passpoint_event_handler handler)1986 wifi_error wifi_set_passpoint_list(wifi_request_id id, wifi_interface_handle iface, int num,
1987 wifi_passpoint_network *networks, wifi_passpoint_event_handler handler)
1988 {
1989 wifi_handle handle = getWifiHandle(iface);
1990
1991 AnqpoConfigureCommand *cmd = new AnqpoConfigureCommand(id, iface, num, networks, handler);
1992 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1993 wifi_error result = wifi_register_cmd(handle, id, cmd);
1994 if (result != WIFI_SUCCESS) {
1995 cmd->releaseRef();
1996 return result;
1997 }
1998 result = (wifi_error)cmd->start();
1999 if (result != WIFI_SUCCESS) {
2000 wifi_unregister_cmd(handle, id);
2001 cmd->releaseRef();
2002 return result;
2003 }
2004 return result;
2005 }
2006
wifi_reset_passpoint_list(wifi_request_id id,wifi_interface_handle iface)2007 wifi_error wifi_reset_passpoint_list(wifi_request_id id, wifi_interface_handle iface)
2008 {
2009 return wifi_cancel_cmd(id, iface);
2010 }
2011