1 /*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "sync.h"
18 #define LOG_TAG "WifiHAL"
19 #include <utils/Log.h>
20 #include <time.h>
21 #include <errno.h>
22 #include <stdlib.h>
23
24 #include "common.h"
25 #include "cpp_bindings.h"
26 #include "gscancommand.h"
27 #include "gscan_event_handler.h"
28
29 #define GSCAN_EVENT_WAIT_TIME_SECONDS 4
30
31 /* BSSID blacklist */
32 typedef struct {
33 int num_bssid; // number of blacklisted BSSIDs
34 mac_addr bssids[MAX_BLACKLIST_BSSID]; // blacklisted BSSIDs
35 } wifi_bssid_params;
36
37 /* Used to handle gscan command events from driver/firmware.*/
38 typedef struct gscan_event_handlers_s {
39 GScanCommandEventHandler *gscanStartCmdEventHandler;
40 GScanCommandEventHandler *gScanSetBssidHotlistCmdEventHandler;
41 GScanCommandEventHandler *gScanSetSignificantChangeCmdEventHandler;
42 GScanCommandEventHandler *gScanSetSsidHotlistCmdEventHandler;
43 GScanCommandEventHandler *gScanSetPnoListCmdEventHandler;
44 GScanCommandEventHandler *gScanPnoSetPasspointListCmdEventHandler;
45 } gscan_event_handlers;
46
initializeGscanHandlers(hal_info * info)47 wifi_error initializeGscanHandlers(hal_info *info)
48 {
49 info->gscan_handlers = (gscan_event_handlers *)malloc(sizeof(gscan_event_handlers));
50 if (info->gscan_handlers) {
51 memset(info->gscan_handlers, 0, sizeof(gscan_event_handlers));
52 }
53 else {
54 ALOGE("%s: Allocation of gscan event handlers failed",
55 __FUNCTION__);
56 return WIFI_ERROR_OUT_OF_MEMORY;
57 }
58 return WIFI_SUCCESS;
59 }
60
cleanupGscanHandlers(hal_info * info)61 wifi_error cleanupGscanHandlers(hal_info *info)
62 {
63 gscan_event_handlers* event_handlers;
64 if (info && info->gscan_handlers) {
65 event_handlers = (gscan_event_handlers*) info->gscan_handlers;
66 if (event_handlers->gscanStartCmdEventHandler) {
67 delete event_handlers->gscanStartCmdEventHandler;
68 }
69 if (event_handlers->gScanSetBssidHotlistCmdEventHandler) {
70 delete event_handlers->gScanSetBssidHotlistCmdEventHandler;
71 }
72 if (event_handlers->gScanSetSignificantChangeCmdEventHandler) {
73 delete event_handlers->gScanSetSignificantChangeCmdEventHandler;
74 }
75 if (event_handlers->gScanSetSsidHotlistCmdEventHandler) {
76 delete event_handlers->gScanSetSsidHotlistCmdEventHandler;
77 }
78 if (event_handlers->gScanSetPnoListCmdEventHandler) {
79 delete event_handlers->gScanSetPnoListCmdEventHandler;
80 }
81 if (event_handlers->gScanPnoSetPasspointListCmdEventHandler) {
82 delete event_handlers->gScanPnoSetPasspointListCmdEventHandler;
83 }
84 memset(event_handlers, 0, sizeof(gscan_event_handlers));
85 free(info->gscan_handlers);
86 info->gscan_handlers = NULL;
87 return WIFI_SUCCESS;
88 }
89 ALOGE ("%s: info or info->gscan_handlers NULL", __FUNCTION__);
90 return WIFI_ERROR_UNKNOWN;
91 }
92
93 /* Implementation of the API functions exposed in gscan.h */
wifi_get_valid_channels(wifi_interface_handle handle,int band,int max_channels,wifi_channel * channels,int * num_channels)94 wifi_error wifi_get_valid_channels(wifi_interface_handle handle,
95 int band, int max_channels, wifi_channel *channels, int *num_channels)
96 {
97 int requestId;
98 wifi_error ret;
99 GScanCommand *gScanCommand;
100 struct nlattr *nlData;
101 interface_info *ifaceInfo = getIfaceInfo(handle);
102 wifi_handle wifiHandle = getWifiHandle(handle);
103
104 /* No request id from caller, so generate one and pass it on to the driver.
105 * Generate one randomly.
106 */
107 requestId = get_requestid();
108 ALOGV("%s: RequestId:%d band:%d max_channels:%d", __FUNCTION__,
109 requestId, band, max_channels);
110
111 if (channels == NULL) {
112 ALOGE("%s: NULL channels pointer provided. Exit.",
113 __FUNCTION__);
114 return WIFI_ERROR_INVALID_ARGS;
115 }
116
117 gScanCommand = new GScanCommand(
118 wifiHandle,
119 requestId,
120 OUI_QCA,
121 QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_VALID_CHANNELS);
122 if (gScanCommand == NULL) {
123 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
124 return WIFI_ERROR_UNKNOWN;
125 }
126 /* Create the NL message. */
127 ret = gScanCommand->create();
128 if (ret != WIFI_SUCCESS)
129 goto cleanup;
130
131 /* Set the interface Id of the message. */
132 ret = gScanCommand->set_iface_id(ifaceInfo->name);
133 if (ret != WIFI_SUCCESS)
134 goto cleanup;
135
136 /* Add the vendor specific attributes for the NL command. */
137 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
138 if (!nlData)
139 goto cleanup;
140
141 if (gScanCommand->put_u32(
142 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
143 requestId) ||
144 gScanCommand->put_u32(
145 QCA_WLAN_VENDOR_ATTR_GSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND,
146 band) ||
147 gScanCommand->put_u32(
148 QCA_WLAN_VENDOR_ATTR_GSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS,
149 max_channels) )
150 {
151 goto cleanup;
152 }
153 gScanCommand->attr_end(nlData);
154 /* Populate the input received from caller/framework. */
155 gScanCommand->setMaxChannels(max_channels);
156 gScanCommand->setChannels(channels);
157 gScanCommand->setNumChannelsPtr(num_channels);
158
159 /* Send the msg and wait for a response. */
160 ret = gScanCommand->requestResponse();
161 if (ret != WIFI_SUCCESS)
162 ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
163
164 cleanup:
165 delete gScanCommand;
166 return ret;
167 }
168
wifi_get_gscan_capabilities(wifi_interface_handle handle,wifi_gscan_capabilities * capabilities)169 wifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle,
170 wifi_gscan_capabilities *capabilities)
171 {
172 wifi_handle wifiHandle = getWifiHandle(handle);
173 hal_info *info = getHalInfo(wifiHandle);
174
175 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
176 ALOGE("%s: GSCAN is not supported by driver", __FUNCTION__);
177 return WIFI_ERROR_NOT_SUPPORTED;
178 }
179
180 if (capabilities == NULL) {
181 ALOGE("%s: NULL capabilities pointer provided. Exit.", __FUNCTION__);
182 return WIFI_ERROR_INVALID_ARGS;
183 }
184
185 memcpy(capabilities, &info->capa.gscan_capa, sizeof(wifi_gscan_capabilities));
186
187 return WIFI_SUCCESS;
188 }
189
wifi_start_gscan(wifi_request_id id,wifi_interface_handle iface,wifi_scan_cmd_params params,wifi_scan_result_handler handler)190 wifi_error wifi_start_gscan(wifi_request_id id,
191 wifi_interface_handle iface,
192 wifi_scan_cmd_params params,
193 wifi_scan_result_handler handler)
194 {
195 wifi_error ret;
196 u32 i, j;
197 GScanCommand *gScanCommand;
198 struct nlattr *nlData;
199 interface_info *ifaceInfo = getIfaceInfo(iface);
200 wifi_handle wifiHandle = getWifiHandle(iface);
201 u32 num_scan_buckets, numChannelSpecs;
202 wifi_scan_bucket_spec bucketSpec;
203 struct nlattr *nlBuckectSpecList;
204 hal_info *info = getHalInfo(wifiHandle);
205 gscan_event_handlers* event_handlers;
206 GScanCommandEventHandler *gScanStartCmdEventHandler;
207
208 event_handlers = (gscan_event_handlers*)info->gscan_handlers;
209 gScanStartCmdEventHandler = event_handlers->gscanStartCmdEventHandler;
210
211 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
212 ALOGE("%s: GSCAN is not supported by driver",
213 __FUNCTION__);
214 return WIFI_ERROR_NOT_SUPPORTED;
215 }
216
217 ALOGV("%s: RequestId:%d ", __FUNCTION__, id);
218 /* Wi-Fi HAL doesn't need to check if a similar request to start gscan was
219 * made earlier. If start_gscan() is called while another gscan is already
220 * running, the request will be sent down to driver and firmware. If new
221 * request is successfully honored, then Wi-Fi HAL will use the new request
222 * id for the gScanStartCmdEventHandler object.
223 */
224 gScanCommand = new GScanCommand(
225 wifiHandle,
226 id,
227 OUI_QCA,
228 QCA_NL80211_VENDOR_SUBCMD_GSCAN_START);
229 if (gScanCommand == NULL) {
230 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
231 return WIFI_ERROR_UNKNOWN;
232 }
233
234 /* Create the NL message. */
235 ret = gScanCommand->create();
236 if (ret != WIFI_SUCCESS)
237 goto cleanup;
238
239 /* Set the interface Id of the message. */
240 ret = gScanCommand->set_iface_id(ifaceInfo->name);
241 if (ret != WIFI_SUCCESS)
242 goto cleanup;
243
244 /* Add the vendor specific attributes for the NL command. */
245 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
246 if (!nlData)
247 goto cleanup;
248
249 num_scan_buckets = (unsigned int)params.num_buckets > MAX_BUCKETS ?
250 MAX_BUCKETS : params.num_buckets;
251
252 ALOGV("%s: Base Period:%d Max_ap_per_scan:%d "
253 "Threshold_percent:%d Threshold_num_scans:%d "
254 "num_buckets:%d", __FUNCTION__, params.base_period,
255 params.max_ap_per_scan, params.report_threshold_percent,
256 params.report_threshold_num_scans, num_scan_buckets);
257 if (gScanCommand->put_u32(
258 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
259 id) ||
260 gScanCommand->put_u32(
261 QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_BASE_PERIOD,
262 params.base_period) ||
263 gScanCommand->put_u32(
264 QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN,
265 params.max_ap_per_scan) ||
266 gScanCommand->put_u8(
267 QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT,
268 params.report_threshold_percent) ||
269 gScanCommand->put_u8(
270 QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS,
271 params.report_threshold_num_scans) ||
272 gScanCommand->put_u8(
273 QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS,
274 num_scan_buckets))
275 {
276 goto cleanup;
277 }
278
279 nlBuckectSpecList =
280 gScanCommand->attr_start(QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC);
281 /* Add NL attributes for scan bucket specs . */
282 for (i = 0; i < num_scan_buckets; i++) {
283 bucketSpec = params.buckets[i];
284 numChannelSpecs = (unsigned int)bucketSpec.num_channels > MAX_CHANNELS ?
285 MAX_CHANNELS : bucketSpec.num_channels;
286
287 ALOGV("%s: Index: %d Bucket Id:%d Band:%d Period:%d ReportEvent:%d "
288 "numChannelSpecs:%d max_period:%d base:%d step_count:%d",
289 __FUNCTION__, i, bucketSpec.bucket, bucketSpec.band,
290 bucketSpec.period, bucketSpec.report_events,
291 numChannelSpecs, bucketSpec.max_period,
292 bucketSpec.base, bucketSpec.step_count);
293
294 struct nlattr *nlBucketSpec = gScanCommand->attr_start(i);
295 if (gScanCommand->put_u8(
296 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_INDEX,
297 bucketSpec.bucket) ||
298 gScanCommand->put_u8(
299 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_BAND,
300 bucketSpec.band) ||
301 gScanCommand->put_u32(
302 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_PERIOD,
303 bucketSpec.period) ||
304 gScanCommand->put_u8(
305 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_REPORT_EVENTS,
306 bucketSpec.report_events) ||
307 gScanCommand->put_u32(
308 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS,
309 numChannelSpecs) ||
310 gScanCommand->put_u32(
311 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_MAX_PERIOD,
312 bucketSpec.max_period) ||
313 gScanCommand->put_u32(
314 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_BASE,
315 bucketSpec.base) ||
316 gScanCommand->put_u32(
317 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_STEP_COUNT,
318 bucketSpec.step_count))
319 {
320 goto cleanup;
321 }
322
323 struct nlattr *nl_channelSpecList =
324 gScanCommand->attr_start(QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC);
325
326 /* Add NL attributes for scan channel specs . */
327 for (j = 0; j < numChannelSpecs; j++) {
328 struct nlattr *nl_channelSpec = gScanCommand->attr_start(j);
329 wifi_scan_channel_spec channel_spec = bucketSpec.channels[j];
330
331 ALOGV("%s: Channel Spec Index:%d Channel:%d Dwell Time:%d "
332 "passive:%d", __FUNCTION__, j, channel_spec.channel,
333 channel_spec.dwellTimeMs, channel_spec.passive);
334
335 if ( gScanCommand->put_u32(
336 QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_CHANNEL,
337 channel_spec.channel) ||
338 gScanCommand->put_u32(
339 QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_DWELL_TIME,
340 channel_spec.dwellTimeMs) ||
341 gScanCommand->put_u8(
342 QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_PASSIVE,
343 channel_spec.passive) )
344 {
345 goto cleanup;
346 }
347
348 gScanCommand->attr_end(nl_channelSpec);
349 }
350 gScanCommand->attr_end(nl_channelSpecList);
351 gScanCommand->attr_end(nlBucketSpec);
352 }
353 gScanCommand->attr_end(nlBuckectSpecList);
354
355 gScanCommand->attr_end(nlData);
356
357 /* Set the callback handler functions for related events. */
358 GScanCallbackHandler callbackHandler;
359 memset(&callbackHandler, 0, sizeof(callbackHandler));
360 callbackHandler.on_full_scan_result = handler.on_full_scan_result;
361 callbackHandler.on_scan_event = handler.on_scan_event;
362
363 /* Create an object to handle the related events from firmware/driver. */
364 if (gScanStartCmdEventHandler == NULL) {
365 gScanStartCmdEventHandler = new GScanCommandEventHandler(
366 wifiHandle,
367 id,
368 OUI_QCA,
369 QCA_NL80211_VENDOR_SUBCMD_GSCAN_START,
370 callbackHandler);
371 if (gScanStartCmdEventHandler == NULL) {
372 ALOGE("%s: Error gScanStartCmdEventHandler NULL", __FUNCTION__);
373 ret = WIFI_ERROR_UNKNOWN;
374 goto cleanup;
375 }
376 event_handlers->gscanStartCmdEventHandler = gScanStartCmdEventHandler;
377 } else {
378 gScanStartCmdEventHandler->setCallbackHandler(callbackHandler);
379 }
380
381 ret = gScanCommand->requestResponse();
382 if (ret != WIFI_SUCCESS) {
383 ALOGE("%s : requestResponse Error:%d", __FUNCTION__, ret);
384 goto cleanup;
385 }
386
387 if (gScanStartCmdEventHandler != NULL) {
388 gScanStartCmdEventHandler->set_request_id(id);
389 gScanStartCmdEventHandler->enableEventHandling();
390 }
391
392 cleanup:
393 delete gScanCommand;
394 /* Disable Event Handling if ret != 0 */
395 if ((ret != WIFI_SUCCESS) && gScanStartCmdEventHandler) {
396 ALOGI("%s: Error ret:%d, disable event handling",
397 __FUNCTION__, ret);
398 gScanStartCmdEventHandler->disableEventHandling();
399 }
400 return ret;
401
402 }
403
wifi_stop_gscan(wifi_request_id id,wifi_interface_handle iface)404 wifi_error wifi_stop_gscan(wifi_request_id id,
405 wifi_interface_handle iface)
406 {
407 wifi_error ret;
408 GScanCommand *gScanCommand;
409 struct nlattr *nlData;
410
411 interface_info *ifaceInfo = getIfaceInfo(iface);
412 wifi_handle wifiHandle = getWifiHandle(iface);
413 hal_info *info = getHalInfo(wifiHandle);
414 gscan_event_handlers* event_handlers;
415 GScanCommandEventHandler *gScanStartCmdEventHandler;
416
417 event_handlers = (gscan_event_handlers*)info->gscan_handlers;
418 gScanStartCmdEventHandler = event_handlers->gscanStartCmdEventHandler;
419
420 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
421 ALOGE("%s: GSCAN is not supported by driver",
422 __FUNCTION__);
423 return WIFI_ERROR_NOT_SUPPORTED;
424 }
425
426 if (gScanStartCmdEventHandler == NULL ||
427 gScanStartCmdEventHandler->isEventHandlingEnabled() == false) {
428 ALOGE("%s: GSCAN isn't running or already stopped. "
429 "Nothing to do. Exit", __FUNCTION__);
430 return WIFI_ERROR_NOT_AVAILABLE;
431 }
432
433 gScanCommand = new GScanCommand(
434 wifiHandle,
435 id,
436 OUI_QCA,
437 QCA_NL80211_VENDOR_SUBCMD_GSCAN_STOP);
438 if (gScanCommand == NULL) {
439 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
440 return WIFI_ERROR_UNKNOWN;
441 }
442
443 /* Create the NL message. */
444 ret = gScanCommand->create();
445 if (ret != WIFI_SUCCESS)
446 goto cleanup;
447
448 /* Set the interface Id of the message. */
449 ret = gScanCommand->set_iface_id(ifaceInfo->name);
450 if (ret != WIFI_SUCCESS)
451 goto cleanup;
452
453 /* Add the vendor specific attributes for the NL command. */
454 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
455 if (!nlData)
456 goto cleanup;
457
458 ret = gScanCommand->put_u32(
459 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
460 id);
461 if (ret != WIFI_SUCCESS)
462 goto cleanup;
463
464 gScanCommand->attr_end(nlData);
465
466 ret = gScanCommand->requestResponse();
467 if (ret != WIFI_SUCCESS)
468 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
469
470 /* Disable Event Handling. */
471 if (gScanStartCmdEventHandler) {
472 gScanStartCmdEventHandler->disableEventHandling();
473 }
474
475 cleanup:
476 delete gScanCommand;
477 return ret;
478 }
479
480 /* Set the GSCAN BSSID Hotlist. */
wifi_set_bssid_hotlist(wifi_request_id id,wifi_interface_handle iface,wifi_bssid_hotlist_params params,wifi_hotlist_ap_found_handler handler)481 wifi_error wifi_set_bssid_hotlist(wifi_request_id id,
482 wifi_interface_handle iface,
483 wifi_bssid_hotlist_params params,
484 wifi_hotlist_ap_found_handler handler)
485 {
486 int i, numAp;
487 wifi_error ret;
488 GScanCommand *gScanCommand;
489 struct nlattr *nlData, *nlApThresholdParamList;
490 interface_info *ifaceInfo = getIfaceInfo(iface);
491 wifi_handle wifiHandle = getWifiHandle(iface);
492 hal_info *info = getHalInfo(wifiHandle);
493 gscan_event_handlers* event_handlers;
494 GScanCommandEventHandler *gScanSetBssidHotlistCmdEventHandler;
495
496 event_handlers = (gscan_event_handlers*)info->gscan_handlers;
497 gScanSetBssidHotlistCmdEventHandler =
498 event_handlers->gScanSetBssidHotlistCmdEventHandler;
499
500 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
501 ALOGE("%s: GSCAN is not supported by driver",
502 __FUNCTION__);
503 return WIFI_ERROR_NOT_SUPPORTED;
504 }
505
506 /* Wi-Fi HAL doesn't need to check if a similar request to set bssid
507 * hotlist was made earlier. If set_bssid_hotlist() is called while
508 * another one is running, the request will be sent down to driver and
509 * firmware. If the new request is successfully honored, then Wi-Fi HAL
510 * will use the new request id for the gScanSetBssidHotlistCmdEventHandler
511 * object.
512 */
513
514 gScanCommand =
515 new GScanCommand(
516 wifiHandle,
517 id,
518 OUI_QCA,
519 QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_BSSID_HOTLIST);
520 if (gScanCommand == NULL) {
521 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
522 return WIFI_ERROR_UNKNOWN;
523 }
524
525 /* Create the NL message. */
526 ret = gScanCommand->create();
527 if (ret != WIFI_SUCCESS)
528 goto cleanup;
529
530 /* Set the interface Id of the message. */
531 ret = gScanCommand->set_iface_id(ifaceInfo->name);
532 if (ret != WIFI_SUCCESS)
533 goto cleanup;
534
535 /* Add the vendor specific attributes for the NL command. */
536 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
537 if (!nlData)
538 goto cleanup;
539
540 numAp = (unsigned int)params.num_bssid > MAX_HOTLIST_APS ?
541 MAX_HOTLIST_APS : params.num_bssid;
542 if (gScanCommand->put_u32(
543 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
544 id) ||
545 gScanCommand->put_u32(
546 QCA_WLAN_VENDOR_ATTR_GSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE,
547 params.lost_ap_sample_size) ||
548 gScanCommand->put_u32(
549 QCA_WLAN_VENDOR_ATTR_GSCAN_BSSID_HOTLIST_PARAMS_NUM_AP,
550 numAp))
551 {
552 goto cleanup;
553 }
554
555 ALOGV("%s: lost_ap_sample_size:%d numAp:%d", __FUNCTION__,
556 params.lost_ap_sample_size, numAp);
557 /* Add the vendor specific attributes for the NL command. */
558 nlApThresholdParamList =
559 gScanCommand->attr_start(
560 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM);
561 if (!nlApThresholdParamList)
562 goto cleanup;
563
564 /* Add nested NL attributes for AP Threshold Param. */
565 for (i = 0; i < numAp; i++) {
566 ap_threshold_param apThreshold = params.ap[i];
567 struct nlattr *nlApThresholdParam = gScanCommand->attr_start(i);
568 if (!nlApThresholdParam)
569 goto cleanup;
570 if (gScanCommand->put_addr(
571 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_BSSID,
572 apThreshold.bssid) ||
573 gScanCommand->put_s32(
574 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_LOW,
575 apThreshold.low) ||
576 gScanCommand->put_s32(
577 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH,
578 apThreshold.high))
579 {
580 goto cleanup;
581 }
582 ALOGV("%s: Index:%d BssId: %hhx:%hhx:%hhx:%hhx:%hhx:%hhx "
583 "Threshold low:%d high:%d", __FUNCTION__, i,
584 apThreshold.bssid[0], apThreshold.bssid[1],
585 apThreshold.bssid[2], apThreshold.bssid[3],
586 apThreshold.bssid[4], apThreshold.bssid[5],
587 apThreshold.low, apThreshold.high);
588 gScanCommand->attr_end(nlApThresholdParam);
589 }
590
591 gScanCommand->attr_end(nlApThresholdParamList);
592
593 gScanCommand->attr_end(nlData);
594
595 GScanCallbackHandler callbackHandler;
596 memset(&callbackHandler, 0, sizeof(callbackHandler));
597 callbackHandler.on_hotlist_ap_found = handler.on_hotlist_ap_found;
598 callbackHandler.on_hotlist_ap_lost = handler.on_hotlist_ap_lost;
599
600 /* Create an object of the event handler class to take care of the
601 * asychronous events on the north-bound.
602 */
603 if (gScanSetBssidHotlistCmdEventHandler == NULL) {
604 gScanSetBssidHotlistCmdEventHandler = new GScanCommandEventHandler(
605 wifiHandle,
606 id,
607 OUI_QCA,
608 QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_BSSID_HOTLIST,
609 callbackHandler);
610 if (gScanSetBssidHotlistCmdEventHandler == NULL) {
611 ALOGE("%s: Error instantiating "
612 "gScanSetBssidHotlistCmdEventHandler.", __FUNCTION__);
613 ret = WIFI_ERROR_UNKNOWN;
614 goto cleanup;
615 }
616 event_handlers->gScanSetBssidHotlistCmdEventHandler =
617 gScanSetBssidHotlistCmdEventHandler;
618 } else {
619 gScanSetBssidHotlistCmdEventHandler->setCallbackHandler(callbackHandler);
620 }
621
622 ret = gScanCommand->requestResponse();
623 if (ret != WIFI_SUCCESS) {
624 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
625 goto cleanup;
626 }
627
628 if (gScanSetBssidHotlistCmdEventHandler != NULL) {
629 gScanSetBssidHotlistCmdEventHandler->set_request_id(id);
630 gScanSetBssidHotlistCmdEventHandler->enableEventHandling();
631 }
632
633 cleanup:
634 delete gScanCommand;
635 /* Disable Event Handling if ret != 0 */
636 if ((ret != WIFI_SUCCESS) && gScanSetBssidHotlistCmdEventHandler) {
637 ALOGI("%s: Error ret:%d, disable event handling",
638 __FUNCTION__, ret);
639 gScanSetBssidHotlistCmdEventHandler->disableEventHandling();
640 }
641 return ret;
642 }
643
wifi_reset_bssid_hotlist(wifi_request_id id,wifi_interface_handle iface)644 wifi_error wifi_reset_bssid_hotlist(wifi_request_id id,
645 wifi_interface_handle iface)
646 {
647 wifi_error ret;
648 GScanCommand *gScanCommand;
649 struct nlattr *nlData;
650 interface_info *ifaceInfo = getIfaceInfo(iface);
651 wifi_handle wifiHandle = getWifiHandle(iface);
652 hal_info *info = getHalInfo(wifiHandle);
653 gscan_event_handlers* event_handlers;
654 GScanCommandEventHandler *gScanSetBssidHotlistCmdEventHandler;
655
656 event_handlers = (gscan_event_handlers*)info->gscan_handlers;
657 gScanSetBssidHotlistCmdEventHandler =
658 event_handlers->gScanSetBssidHotlistCmdEventHandler;
659
660 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
661 ALOGE("%s: GSCAN is not supported by driver",
662 __FUNCTION__);
663 return WIFI_ERROR_NOT_SUPPORTED;
664 }
665
666 if (gScanSetBssidHotlistCmdEventHandler == NULL ||
667 (gScanSetBssidHotlistCmdEventHandler->isEventHandlingEnabled() ==
668 false)) {
669 ALOGE("wifi_reset_bssid_hotlist: GSCAN bssid_hotlist isn't set. "
670 "Nothing to do. Exit");
671 return WIFI_ERROR_NOT_AVAILABLE;
672 }
673
674 gScanCommand = new GScanCommand(
675 wifiHandle,
676 id,
677 OUI_QCA,
678 QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_BSSID_HOTLIST);
679
680 if (gScanCommand == NULL) {
681 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
682 return WIFI_ERROR_UNKNOWN;
683 }
684
685 /* Create the NL message. */
686 ret = gScanCommand->create();
687 if (ret != WIFI_SUCCESS)
688 goto cleanup;
689
690 /* Set the interface Id of the message. */
691 ret = gScanCommand->set_iface_id(ifaceInfo->name);
692 if (ret != WIFI_SUCCESS)
693 goto cleanup;
694
695 /* Add the vendor specific attributes for the NL command. */
696 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
697 if (!nlData)
698 goto cleanup;
699
700 ret = gScanCommand->put_u32(
701 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, id);
702 if (ret != WIFI_SUCCESS)
703 goto cleanup;
704
705 gScanCommand->attr_end(nlData);
706
707 ret = gScanCommand->requestResponse();
708 if (ret != WIFI_SUCCESS)
709 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
710
711 /* Disable Event Handling. */
712 if (gScanSetBssidHotlistCmdEventHandler) {
713 gScanSetBssidHotlistCmdEventHandler->disableEventHandling();
714 }
715
716 cleanup:
717 delete gScanCommand;
718 return ret;
719 }
720
721 /* Set the GSCAN Significant AP Change list. */
wifi_set_significant_change_handler(wifi_request_id id,wifi_interface_handle iface,wifi_significant_change_params params,wifi_significant_change_handler handler)722 wifi_error wifi_set_significant_change_handler(wifi_request_id id,
723 wifi_interface_handle iface,
724 wifi_significant_change_params params,
725 wifi_significant_change_handler handler)
726 {
727 int i, numAp;
728 wifi_error ret;
729 GScanCommand *gScanCommand;
730 struct nlattr *nlData, *nlApThresholdParamList;
731 interface_info *ifaceInfo = getIfaceInfo(iface);
732 wifi_handle wifiHandle = getWifiHandle(iface);
733 hal_info *info = getHalInfo(wifiHandle);
734 gscan_event_handlers* event_handlers;
735 GScanCommandEventHandler *gScanSetSignificantChangeCmdEventHandler;
736
737 event_handlers = (gscan_event_handlers*)info->gscan_handlers;
738 gScanSetSignificantChangeCmdEventHandler =
739 event_handlers->gScanSetSignificantChangeCmdEventHandler;
740
741 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
742 ALOGE("%s: GSCAN is not supported by driver",
743 __FUNCTION__);
744 return WIFI_ERROR_NOT_SUPPORTED;
745 }
746
747 /* Wi-Fi HAL doesn't need to check if a similar request to set significant
748 * change list was made earlier. If set_significant_change() is called while
749 * another one is running, the request will be sent down to driver and
750 * firmware. If the new request is successfully honored, then Wi-Fi HAL
751 * will use the new request id for the gScanSetSignificantChangeCmdEventHandler
752 * object.
753 */
754
755 gScanCommand = new GScanCommand(
756 wifiHandle,
757 id,
758 OUI_QCA,
759 QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SIGNIFICANT_CHANGE);
760 if (gScanCommand == NULL) {
761 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
762 return WIFI_ERROR_UNKNOWN;
763 }
764
765 /* Create the NL message. */
766 ret = gScanCommand->create();
767 if (ret != WIFI_SUCCESS)
768 goto cleanup;
769
770 /* Set the interface Id of the message. */
771 ret = gScanCommand->set_iface_id(ifaceInfo->name);
772 if (ret != WIFI_SUCCESS)
773 goto cleanup;
774
775 /* Add the vendor specific attributes for the NL command. */
776 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
777 if (!nlData)
778 goto cleanup;
779
780 numAp = (unsigned int)params.num_bssid > MAX_SIGNIFICANT_CHANGE_APS ?
781 MAX_SIGNIFICANT_CHANGE_APS : params.num_bssid;
782
783 if (gScanCommand->put_u32(
784 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
785 id) ||
786 gScanCommand->put_u32(
787 QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE,
788 params.rssi_sample_size) ||
789 gScanCommand->put_u32(
790 QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE,
791 params.lost_ap_sample_size) ||
792 gScanCommand->put_u32(
793 QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING,
794 params.min_breaching) ||
795 gScanCommand->put_u32(
796 QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP,
797 numAp))
798 {
799 goto cleanup;
800 }
801
802 ALOGV("%s: Number of AP params:%d Rssi_sample_size:%d "
803 "lost_ap_sample_size:%d min_breaching:%d", __FUNCTION__,
804 numAp, params.rssi_sample_size, params.lost_ap_sample_size,
805 params.min_breaching);
806
807 /* Add the vendor specific attributes for the NL command. */
808 nlApThresholdParamList =
809 gScanCommand->attr_start(
810 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM);
811 if (!nlApThresholdParamList)
812 goto cleanup;
813
814 /* Add nested NL attributes for AP Threshold Param list. */
815 for (i = 0; i < numAp; i++) {
816 ap_threshold_param apThreshold = params.ap[i];
817 struct nlattr *nlApThresholdParam = gScanCommand->attr_start(i);
818 if (!nlApThresholdParam)
819 goto cleanup;
820 if ( gScanCommand->put_addr(
821 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_BSSID,
822 apThreshold.bssid) ||
823 gScanCommand->put_s32(
824 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_LOW,
825 apThreshold.low) ||
826 gScanCommand->put_s32(
827 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH,
828 apThreshold.high))
829 {
830 goto cleanup;
831 }
832 ALOGV("%s: ap[%d].bssid:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx "
833 "ap[%d].low:%d ap[%d].high:%d", __FUNCTION__,
834 i,
835 apThreshold.bssid[0], apThreshold.bssid[1],
836 apThreshold.bssid[2], apThreshold.bssid[3],
837 apThreshold.bssid[4], apThreshold.bssid[5],
838 i, apThreshold.low, i, apThreshold.high);
839 gScanCommand->attr_end(nlApThresholdParam);
840 }
841
842 gScanCommand->attr_end(nlApThresholdParamList);
843
844 gScanCommand->attr_end(nlData);
845
846 GScanCallbackHandler callbackHandler;
847 memset(&callbackHandler, 0, sizeof(callbackHandler));
848 callbackHandler.on_significant_change = handler.on_significant_change;
849
850 /* Create an object of the event handler class to take care of the
851 * asychronous events on the north-bound.
852 */
853 if (gScanSetSignificantChangeCmdEventHandler == NULL) {
854 gScanSetSignificantChangeCmdEventHandler =
855 new GScanCommandEventHandler(
856 wifiHandle,
857 id,
858 OUI_QCA,
859 QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SIGNIFICANT_CHANGE,
860 callbackHandler);
861 if (gScanSetSignificantChangeCmdEventHandler == NULL) {
862 ALOGE("%s: Error in instantiating, "
863 "gScanSetSignificantChangeCmdEventHandler.",
864 __FUNCTION__);
865 ret = WIFI_ERROR_UNKNOWN;
866 goto cleanup;
867 }
868 event_handlers->gScanSetSignificantChangeCmdEventHandler =
869 gScanSetSignificantChangeCmdEventHandler;
870 } else {
871 gScanSetSignificantChangeCmdEventHandler->setCallbackHandler(callbackHandler);
872 }
873
874 ret = gScanCommand->requestResponse();
875 if (ret != WIFI_SUCCESS) {
876 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
877 goto cleanup;
878 }
879
880 if (gScanSetSignificantChangeCmdEventHandler != NULL) {
881 gScanSetSignificantChangeCmdEventHandler->set_request_id(id);
882 gScanSetSignificantChangeCmdEventHandler->enableEventHandling();
883 }
884
885 cleanup:
886 /* Disable Event Handling if ret != 0 */
887 if ((ret != WIFI_SUCCESS) && gScanSetSignificantChangeCmdEventHandler) {
888 ALOGI("%s: Error ret:%d, disable event handling",
889 __FUNCTION__, ret);
890 gScanSetSignificantChangeCmdEventHandler->disableEventHandling();
891 }
892 delete gScanCommand;
893 return ret;
894 }
895
896 /* Clear the GSCAN Significant AP change list. */
wifi_reset_significant_change_handler(wifi_request_id id,wifi_interface_handle iface)897 wifi_error wifi_reset_significant_change_handler(wifi_request_id id,
898 wifi_interface_handle iface)
899 {
900 wifi_error ret;
901 GScanCommand *gScanCommand;
902 struct nlattr *nlData;
903 interface_info *ifaceInfo = getIfaceInfo(iface);
904 wifi_handle wifiHandle = getWifiHandle(iface);
905 hal_info *info = getHalInfo(wifiHandle);
906 gscan_event_handlers* event_handlers;
907 GScanCommandEventHandler *gScanSetSignificantChangeCmdEventHandler;
908
909 event_handlers = (gscan_event_handlers*)info->gscan_handlers;
910 gScanSetSignificantChangeCmdEventHandler =
911 event_handlers->gScanSetSignificantChangeCmdEventHandler;
912
913 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
914 ALOGE("%s: GSCAN is not supported by driver",
915 __FUNCTION__);
916 return WIFI_ERROR_NOT_SUPPORTED;
917 }
918
919 if (gScanSetSignificantChangeCmdEventHandler == NULL ||
920 (gScanSetSignificantChangeCmdEventHandler->isEventHandlingEnabled() ==
921 false)) {
922 ALOGE("wifi_reset_significant_change_handler: GSCAN significant_change"
923 " isn't set. Nothing to do. Exit");
924 return WIFI_ERROR_NOT_AVAILABLE;
925 }
926
927 gScanCommand =
928 new GScanCommand
929 (
930 wifiHandle,
931 id,
932 OUI_QCA,
933 QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_SIGNIFICANT_CHANGE);
934 if (gScanCommand == NULL) {
935 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
936 return WIFI_ERROR_UNKNOWN;
937 }
938
939 /* Create the NL message. */
940 ret = gScanCommand->create();
941 if (ret != WIFI_SUCCESS)
942 goto cleanup;
943
944 /* Set the interface Id of the message. */
945 ret = gScanCommand->set_iface_id(ifaceInfo->name);
946 if (ret != WIFI_SUCCESS)
947 goto cleanup;
948
949 /* Add the vendor specific attributes for the NL command. */
950 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
951 if (!nlData)
952 goto cleanup;
953
954 ret = gScanCommand->put_u32(
955 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
956 id);
957 if (ret != WIFI_SUCCESS)
958 goto cleanup;
959
960 gScanCommand->attr_end(nlData);
961
962 ret = gScanCommand->requestResponse();
963 if (ret != WIFI_SUCCESS)
964 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
965
966 /* Disable Event Handling. */
967 if (gScanSetSignificantChangeCmdEventHandler) {
968 gScanSetSignificantChangeCmdEventHandler->disableEventHandling();
969 }
970
971 cleanup:
972 delete gScanCommand;
973 return ret;
974 }
975
976 /* Get the GSCAN cached scan results. */
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,
978 byte flush, int max,
979 wifi_cached_scan_results *results,
980 int *num)
981 {
982 int requestId, retRequestRsp = 0;
983 wifi_error ret;
984 GScanCommand *gScanCommand;
985 struct nlattr *nlData;
986
987 interface_info *ifaceInfo = getIfaceInfo(iface);
988 wifi_handle wifiHandle = getWifiHandle(iface);
989 hal_info *info = getHalInfo(wifiHandle);
990
991 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
992 ALOGE("%s: GSCAN is not supported by driver",
993 __FUNCTION__);
994 return WIFI_ERROR_NOT_SUPPORTED;
995 }
996
997 /* No request id from caller, so generate one and pass it on to the driver. */
998 /* Generate it randomly */
999 requestId = get_requestid();
1000
1001 if (results == NULL || num == NULL) {
1002 ALOGE("%s: NULL pointer provided. Exit.",
1003 __FUNCTION__);
1004 return WIFI_ERROR_INVALID_ARGS;
1005 }
1006
1007 gScanCommand = new GScanCommand(
1008 wifiHandle,
1009 requestId,
1010 OUI_QCA,
1011 QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS);
1012 if (gScanCommand == NULL) {
1013 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
1014 return WIFI_ERROR_UNKNOWN;
1015 }
1016
1017 ret = gScanCommand->allocRspParams(eGScanGetCachedResultsRspParams);
1018 if (ret != WIFI_SUCCESS) {
1019 ALOGE("%s: Failed to allocate memory for response struct. Error:%d",
1020 __FUNCTION__, ret);
1021 goto cleanup;
1022 }
1023
1024 ret = gScanCommand->allocCachedResultsTemp(max, results);
1025 if (ret != WIFI_SUCCESS) {
1026 ALOGE("%s: Failed to allocate memory for temp gscan cached list. "
1027 "Error:%d", __FUNCTION__, ret);
1028 goto cleanup;
1029 }
1030
1031 /* Clear the destination cached results list before copying results. */
1032 memset(results, 0, max * sizeof(wifi_cached_scan_results));
1033
1034 /* Create the NL message. */
1035 ret = gScanCommand->create();
1036 if (ret != WIFI_SUCCESS)
1037 goto cleanup;
1038
1039 /* Set the interface Id of the message. */
1040 ret = gScanCommand->set_iface_id(ifaceInfo->name);
1041 if (ret != WIFI_SUCCESS)
1042 goto cleanup;
1043
1044 /* Add the vendor specific attributes for the NL command. */
1045 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1046 if (!nlData)
1047 goto cleanup;
1048
1049 if (gScanCommand->put_u32(
1050 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
1051 requestId) ||
1052 gScanCommand->put_u8(
1053 QCA_WLAN_VENDOR_ATTR_GSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH,
1054 flush) ||
1055 gScanCommand->put_u32(
1056 QCA_WLAN_VENDOR_ATTR_GSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX,
1057 max))
1058 {
1059 goto cleanup;
1060 }
1061
1062 ALOGV("%s: flush:%d max:%d", __FUNCTION__, flush, max);
1063 gScanCommand->attr_end(nlData);
1064
1065 retRequestRsp = gScanCommand->requestResponse();
1066 if (retRequestRsp != 0) {
1067 ALOGE("%s: requestResponse Error:%d",
1068 __FUNCTION__, retRequestRsp);
1069 /* It's possible to get ETIMEDOUT after receiving few results from
1070 * driver. Copy and forward them to framework.
1071 */
1072 if (retRequestRsp != -ETIMEDOUT) {
1073 /* Proceed to cleanup & return no results */
1074 goto cleanup;
1075 }
1076 }
1077
1078 /* No more data, copy the parsed results into the caller's results array */
1079 ret = gScanCommand->copyCachedScanResults(num, results);
1080 ALOGV("%s: max: %d, num:%d", __FUNCTION__, max, *num);
1081
1082 if (!ret) {
1083 /* If requestResponse returned a TIMEOUT */
1084 if (retRequestRsp == -ETIMEDOUT) {
1085 if (*num > 0) {
1086 /* Mark scan results as incomplete for the last scan_id */
1087 results[(*num)-1].flags = WIFI_SCAN_FLAG_INTERRUPTED;
1088 ALOGV("%s: Timeout happened. Mark scan results as incomplete "
1089 "for scan_id:%d", __FUNCTION__, results[(*num)-1].scan_id);
1090 ret = WIFI_SUCCESS;
1091 } else
1092 ret = WIFI_ERROR_TIMED_OUT;
1093 }
1094 }
1095 cleanup:
1096 gScanCommand->freeRspParams(eGScanGetCachedResultsRspParams);
1097 delete gScanCommand;
1098 return ret;
1099 }
1100
1101 /* Random MAC OUI for PNO */
wifi_set_scanning_mac_oui(wifi_interface_handle handle,oui scan_oui)1102 wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui)
1103 {
1104 wifi_error ret;
1105 struct nlattr *nlData;
1106 WifiVendorCommand *vCommand = NULL;
1107 interface_info *iinfo = getIfaceInfo(handle);
1108 wifi_handle wifiHandle = getWifiHandle(handle);
1109
1110 vCommand = new WifiVendorCommand(wifiHandle, 0,
1111 OUI_QCA,
1112 QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI);
1113 if (vCommand == NULL) {
1114 ALOGE("%s: Error vCommand NULL", __FUNCTION__);
1115 return WIFI_ERROR_OUT_OF_MEMORY;
1116 }
1117
1118 /* create the message */
1119 ret = vCommand->create();
1120 if (ret != WIFI_SUCCESS)
1121 goto cleanup;
1122
1123 ret = vCommand->set_iface_id(iinfo->name);
1124 if (ret != WIFI_SUCCESS)
1125 goto cleanup;
1126
1127 /* Add the vendor specific attributes for the NL command. */
1128 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1129 if (!nlData)
1130 goto cleanup;
1131
1132 ALOGV("%s: MAC_OUI - %02x:%02x:%02x", __FUNCTION__,
1133 scan_oui[0], scan_oui[1], scan_oui[2]);
1134
1135 /* Add the fixed part of the mac_oui to the nl command */
1136 ret = vCommand->put_bytes(
1137 QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI,
1138 (char *)scan_oui,
1139 WIFI_SCANNING_MAC_OUI_LENGTH);
1140 if (ret != WIFI_SUCCESS)
1141 goto cleanup;
1142
1143 vCommand->attr_end(nlData);
1144
1145 ret = vCommand->requestResponse();
1146 if (ret != WIFI_SUCCESS) {
1147 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
1148 goto cleanup;
1149 }
1150
1151 cleanup:
1152 delete vCommand;
1153 return ret;
1154 }
1155
1156
GScanCommand(wifi_handle handle,int id,u32 vendor_id,u32 subcmd)1157 GScanCommand::GScanCommand(wifi_handle handle, int id, u32 vendor_id,
1158 u32 subcmd)
1159 : WifiVendorCommand(handle, id, vendor_id, subcmd)
1160 {
1161 /* Initialize the member data variables here */
1162 mGetCachedResultsRspParams = NULL;
1163 mChannels = NULL;
1164 mMaxChannels = 0;
1165 mNumChannelsPtr = NULL;
1166
1167 mRequestId = id;
1168 memset(&mHandler, 0,sizeof(mHandler));
1169 }
1170
~GScanCommand()1171 GScanCommand::~GScanCommand()
1172 {
1173 unregisterVendorHandler(mVendor_id, mSubcmd);
1174 }
1175
1176
1177 /* This function implements creation of Vendor command */
create()1178 wifi_error GScanCommand::create() {
1179 wifi_error ret;
1180
1181 ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
1182 if (ret != WIFI_SUCCESS)
1183 return ret;
1184
1185 /* Insert the oui in the msg */
1186 ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
1187 if (ret != WIFI_SUCCESS)
1188 return ret;
1189
1190 /* Insert the subcmd in the msg */
1191 ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
1192 if (ret != WIFI_SUCCESS)
1193 return ret;
1194
1195 ALOGV("%s: mVendor_id = %d, Subcmd = %d.",
1196 __FUNCTION__, mVendor_id, mSubcmd);
1197
1198 return ret;
1199 }
1200
requestResponse()1201 wifi_error GScanCommand::requestResponse()
1202 {
1203 return WifiCommand::requestResponse(mMsg);
1204 }
1205
handleResponse(WifiEvent & reply)1206 int GScanCommand::handleResponse(WifiEvent &reply)
1207 {
1208 int i = 0;
1209 wifi_error ret = WIFI_SUCCESS;
1210 u32 val;
1211
1212 WifiVendorCommand::handleResponse(reply);
1213
1214 struct nlattr *tbVendor[
1215 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
1216 nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
1217 (struct nlattr *)mVendorData,mDataLen, NULL);
1218
1219 switch(mSubcmd)
1220 {
1221 case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_VALID_CHANNELS:
1222 {
1223 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_CHANNELS]) {
1224 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_CHANNELS"
1225 " not found", __FUNCTION__);
1226 ret = WIFI_ERROR_INVALID_ARGS;
1227 break;
1228 }
1229 val = nla_get_u32(tbVendor[
1230 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_CHANNELS]);
1231
1232 val = val > (unsigned int)mMaxChannels ?
1233 (unsigned int)mMaxChannels : val;
1234 *mNumChannelsPtr = val;
1235
1236 /* Extract the list of channels. */
1237 if (*mNumChannelsPtr > 0 ) {
1238 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CHANNELS]) {
1239 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CHANNELS"
1240 " not found", __FUNCTION__);
1241 ret = WIFI_ERROR_INVALID_ARGS;
1242 break;
1243 }
1244 nla_memcpy(mChannels,
1245 tbVendor[
1246 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CHANNELS],
1247 sizeof(wifi_channel) * (*mNumChannelsPtr));
1248 }
1249 char buf[256];
1250 size_t len = 0;
1251 for (i = 0; i < *mNumChannelsPtr && len < sizeof(buf); i++) {
1252 len += snprintf(buf + len, sizeof(buf) - len, "%u ",
1253 *(mChannels + i));
1254 }
1255 ALOGV("%s: Num Channels %d: List of valid channels are: %s",
1256 __FUNCTION__, *mNumChannelsPtr, buf);
1257
1258 }
1259 break;
1260 case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS:
1261 {
1262 wifi_request_id id;
1263 u32 numResults = 0;
1264 int firstScanIdInPatch = -1;
1265
1266 if (!tbVendor[
1267 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]) {
1268 ALOGE("%s: GSCAN_RESULTS_REQUEST_ID not"
1269 "found", __FUNCTION__);
1270 ret = WIFI_ERROR_INVALID_ARGS;
1271 break;
1272 }
1273 id = nla_get_u32(
1274 tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]
1275 );
1276 /* If this is not for us, just ignore it. */
1277 if (id != mRequestId) {
1278 ALOGV("%s: Event has Req. ID:%d <> ours:%d",
1279 __FUNCTION__, id, mRequestId);
1280 break;
1281 }
1282 if (!tbVendor[
1283 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]) {
1284 ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not"
1285 "found", __FUNCTION__);
1286 ret = WIFI_ERROR_INVALID_ARGS;
1287 break;
1288 }
1289 /* Read num of cached scan results in this data chunk. Note that
1290 * this value doesn't represent the number of unique gscan scan Ids
1291 * since the first scan id in this new chunk could be similar to
1292 * the last scan id in the previous chunk.
1293 */
1294 numResults = nla_get_u32(tbVendor[
1295 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]);
1296 ALOGV("%s: num Cached results in this fragment:%d",
1297 __FUNCTION__, numResults);
1298
1299 if (!mGetCachedResultsRspParams) {
1300 ALOGE("%s: mGetCachedResultsRspParams is NULL, exit.",
1301 __FUNCTION__);
1302 ret = WIFI_ERROR_INVALID_ARGS;
1303 break;
1304 }
1305
1306 /* To support fragmentation from firmware, monitor the
1307 * MORE_DATA flag and cache results until MORE_DATA = 0.
1308 */
1309 if (!tbVendor[
1310 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]) {
1311 ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_MORE_DATA "
1312 "not found", __FUNCTION__);
1313 ret = WIFI_ERROR_INVALID_ARGS;
1314 break;
1315 } else {
1316 mGetCachedResultsRspParams->more_data = nla_get_u8(
1317 tbVendor[
1318 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]);
1319 }
1320
1321 /* No data in this chunk so skip this chunk */
1322 if (numResults == 0) {
1323 return NL_SKIP;
1324 }
1325
1326 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID]) {
1327 ALOGE("GSCAN_CACHED_RESULTS_SCAN_ID not found");
1328 ret = WIFI_ERROR_INVALID_ARGS;
1329 break;
1330 }
1331
1332 /* Get the first Scan-Id in this chuck of cached results. */
1333 firstScanIdInPatch = nla_get_u32(tbVendor[
1334 QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID]);
1335
1336 ALOGV("More data: %d, firstScanIdInPatch: %d, lastProcessedScanId: %d",
1337 mGetCachedResultsRspParams->more_data, firstScanIdInPatch,
1338 mGetCachedResultsRspParams->lastProcessedScanId);
1339
1340 if (numResults) {
1341 if (firstScanIdInPatch !=
1342 mGetCachedResultsRspParams->lastProcessedScanId) {
1343 /* New result scan Id block, update the starting index. */
1344 mGetCachedResultsRspParams->cachedResultsStartingIndex++;
1345 }
1346
1347 ret = gscan_get_cached_results(
1348 mGetCachedResultsRspParams->cached_results,
1349 tbVendor);
1350 /* If a parsing error occurred, exit and proceed for cleanup. */
1351 if (ret)
1352 break;
1353 }
1354 }
1355 break;
1356 default:
1357 /* Error case should not happen print log */
1358 ALOGE("%s: Wrong GScan subcmd response received %d",
1359 __FUNCTION__, mSubcmd);
1360 }
1361
1362 /* A parsing error occurred, do the cleanup of gscan result lists. */
1363 if (ret) {
1364 switch(mSubcmd)
1365 {
1366 case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS:
1367 {
1368 ALOGE("%s: Parsing error, free CachedResultsRspParams",
1369 __FUNCTION__);
1370 freeRspParams(eGScanGetCachedResultsRspParams);
1371 }
1372 break;
1373 default:
1374 ALOGE("%s: Wrong GScan subcmd received %d", __FUNCTION__, mSubcmd);
1375 }
1376 }
1377 return NL_SKIP;
1378 }
1379
1380 /* Called to parse and extract cached results. */
gscan_get_cached_results(wifi_cached_scan_results * cached_results,struct nlattr ** tb_vendor)1381 wifi_error GScanCommand:: gscan_get_cached_results(
1382 wifi_cached_scan_results *cached_results,
1383 struct nlattr **tb_vendor)
1384 {
1385 u32 j = 0;
1386 struct nlattr *scanResultsInfo, *wifiScanResultsInfo;
1387 int rem = 0, remResults = 0;
1388 u32 len = 0, numScanResults = 0;
1389 u32 i = mGetCachedResultsRspParams->cachedResultsStartingIndex;
1390 ALOGV("%s: starting counter: %d", __FUNCTION__, i);
1391
1392 for (scanResultsInfo = (struct nlattr *) nla_data(tb_vendor[
1393 QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_LIST]),
1394 rem = nla_len(tb_vendor[
1395 QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_LIST]);
1396 nla_ok(scanResultsInfo, rem) && i < mGetCachedResultsRspParams->max;
1397 scanResultsInfo = nla_next(scanResultsInfo, &(rem)))
1398 {
1399 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
1400 nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
1401 (struct nlattr *) nla_data(scanResultsInfo),
1402 nla_len(scanResultsInfo), NULL);
1403
1404 if (!
1405 tb2[
1406 QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID
1407 ])
1408 {
1409 ALOGE("%s: GSCAN_CACHED_RESULTS_SCAN_ID"
1410 " not found", __FUNCTION__);
1411 return WIFI_ERROR_INVALID_ARGS;
1412 }
1413 cached_results[i].scan_id =
1414 nla_get_u32(
1415 tb2[
1416 QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID
1417 ]);
1418
1419 if (!
1420 tb2[
1421 QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_FLAGS
1422 ])
1423 {
1424 ALOGE("%s: GSCAN_CACHED_RESULTS_FLAGS "
1425 "not found", __FUNCTION__);
1426 return WIFI_ERROR_INVALID_ARGS;
1427 }
1428 cached_results[i].flags =
1429 nla_get_u32(
1430 tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_FLAGS]);
1431
1432 if (!tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_BUCKETS_SCANNED])
1433 {
1434 ALOGI("%s: GSCAN_RESULTS_BUCKETS_SCANNED"
1435 "not found", __FUNCTION__);
1436 } else {
1437 cached_results[i].buckets_scanned = nla_get_u32(
1438 tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_BUCKETS_SCANNED]);
1439 }
1440
1441 if (!
1442 tb2[
1443 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE
1444 ])
1445 {
1446 ALOGE("%s: RESULTS_NUM_RESULTS_AVAILABLE "
1447 "not found", __FUNCTION__);
1448 return WIFI_ERROR_INVALID_ARGS;
1449 }
1450 numScanResults =
1451 nla_get_u32(
1452 tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]);
1453
1454 if (mGetCachedResultsRspParams->lastProcessedScanId !=
1455 cached_results[i].scan_id) {
1456 j = 0; /* reset wifi_scan_result counter */
1457 cached_results[i].num_results = 0;
1458 ALOGV("parsing: *lastProcessedScanId [%d] !="
1459 " cached_results[%d].scan_id:%d, j:%d "
1460 "numScanResults: %d",
1461 mGetCachedResultsRspParams->lastProcessedScanId, i,
1462 cached_results[i].scan_id, j, numScanResults);
1463 mGetCachedResultsRspParams->lastProcessedScanId =
1464 cached_results[i].scan_id;
1465 mGetCachedResultsRspParams->wifiScanResultsStartingIndex = 0;
1466 /* Increment the number of cached scan results received */
1467 mGetCachedResultsRspParams->num_cached_results++;
1468 } else {
1469 j = mGetCachedResultsRspParams->wifiScanResultsStartingIndex;
1470 ALOGV("parsing: *lastProcessedScanId [%d] == "
1471 "cached_results[%d].scan_id:%d, j:%d "
1472 "numScanResults:%d",
1473 mGetCachedResultsRspParams->lastProcessedScanId, i,
1474 cached_results[i].scan_id, j, numScanResults);
1475 }
1476
1477 ALOGV("%s: scan_id %d ", __FUNCTION__,
1478 cached_results[i].scan_id);
1479 ALOGV("%s: flags %u ", __FUNCTION__,
1480 cached_results[i].flags);
1481
1482 for (wifiScanResultsInfo = (struct nlattr *) nla_data(tb2[
1483 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]),
1484 remResults = nla_len(tb2[
1485 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]);
1486 nla_ok(wifiScanResultsInfo, remResults);
1487 wifiScanResultsInfo = nla_next(wifiScanResultsInfo, &(remResults)))
1488 {
1489 struct nlattr *tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
1490 nla_parse(tb3, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
1491 (struct nlattr *) nla_data(wifiScanResultsInfo),
1492 nla_len(wifiScanResultsInfo), NULL);
1493 if (j < MAX_AP_CACHE_PER_SCAN) {
1494 if (!
1495 tb3[
1496 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
1497 ])
1498 {
1499 ALOGE("%s: "
1500 "RESULTS_SCAN_RESULT_TIME_STAMP not found",
1501 __FUNCTION__);
1502 return WIFI_ERROR_INVALID_ARGS;
1503 }
1504 cached_results[i].results[j].ts =
1505 nla_get_u64(
1506 tb3[
1507 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
1508 ]);
1509 if (!
1510 tb3[
1511 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID
1512 ])
1513 {
1514 ALOGE("%s: "
1515 "RESULTS_SCAN_RESULT_SSID not found",
1516 __FUNCTION__);
1517 return WIFI_ERROR_INVALID_ARGS;
1518 }
1519 len = nla_len(tb3[
1520 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]);
1521 len =
1522 sizeof(cached_results[i].results[j].ssid) <= len ?
1523 sizeof(cached_results[i].results[j].ssid) : len;
1524 memcpy((void *)&cached_results[i].results[j].ssid,
1525 nla_data(
1526 tb3[
1527 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]),
1528 len);
1529 if (!
1530 tb3[
1531 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID
1532 ])
1533 {
1534 ALOGE("%s: "
1535 "RESULTS_SCAN_RESULT_BSSID not found",
1536 __FUNCTION__);
1537 return WIFI_ERROR_INVALID_ARGS;
1538 }
1539 len = nla_len(
1540 tb3[
1541 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]);
1542 len =
1543 sizeof(cached_results[i].results[j].bssid) <= len ?
1544 sizeof(cached_results[i].results[j].bssid) : len;
1545 memcpy(&cached_results[i].results[j].bssid,
1546 nla_data(
1547 tb3[
1548 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]),
1549 len);
1550 if (!
1551 tb3[
1552 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL
1553 ])
1554 {
1555 ALOGE("%s: "
1556 "RESULTS_SCAN_RESULT_CHANNEL not found",
1557 __FUNCTION__);
1558 return WIFI_ERROR_INVALID_ARGS;
1559 }
1560 cached_results[i].results[j].channel =
1561 nla_get_u32(
1562 tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]);
1563 if (!
1564 tb3[
1565 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI
1566 ])
1567 {
1568 ALOGE("%s: "
1569 "RESULTS_SCAN_RESULT_RSSI not found",
1570 __FUNCTION__);
1571 return WIFI_ERROR_INVALID_ARGS;
1572 }
1573 cached_results[i].results[j].rssi =
1574 get_s32(
1575 tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI]);
1576 if (!
1577 tb3[
1578 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT
1579 ])
1580 {
1581 ALOGE("%s: "
1582 "RESULTS_SCAN_RESULT_RTT not found",
1583 __FUNCTION__);
1584 return WIFI_ERROR_INVALID_ARGS;
1585 }
1586 cached_results[i].results[j].rtt =
1587 nla_get_u32(
1588 tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]);
1589 if (!
1590 tb3[
1591 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD
1592 ])
1593 {
1594 ALOGE("%s: "
1595 "RESULTS_SCAN_RESULT_RTT_SD not found",
1596 __FUNCTION__);
1597 return WIFI_ERROR_INVALID_ARGS;
1598 }
1599 cached_results[i].results[j].rtt_sd =
1600 nla_get_u32(
1601 tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]);
1602 #ifdef QC_HAL_DEBUG
1603 /* Enable these prints for debugging if needed. */
1604 ALOGD("%s: ts %" PRId64, __FUNCTION__,
1605 cached_results[i].results[j].ts);
1606 ALOGD("%s: SSID %s ", __FUNCTION__,
1607 cached_results[i].results[j].ssid);
1608 ALOGD("%s: BSSID: %02x:%02x:%02x:%02x:%02x:%02x \n",
1609 __FUNCTION__, cached_results[i].results[j].bssid[0],
1610 cached_results[i].results[j].bssid[1],
1611 cached_results[i].results[j].bssid[2],
1612 cached_results[i].results[j].bssid[3],
1613 cached_results[i].results[j].bssid[4],
1614 cached_results[i].results[j].bssid[5]);
1615 ALOGD("%s: channel %d ", __FUNCTION__,
1616 cached_results[i].results[j].channel);
1617 ALOGD("%s: rssi %d ", __FUNCTION__,
1618 cached_results[i].results[j].rssi);
1619 ALOGD("%s: rtt %" PRId64, __FUNCTION__,
1620 cached_results[i].results[j].rtt);
1621 ALOGD("%s: rtt_sd %" PRId64, __FUNCTION__,
1622 cached_results[i].results[j].rtt_sd);
1623 #endif
1624 /* Increment loop index for next record */
1625 j++;
1626 /* For this scan id, update the wifiScanResultsStartingIndex
1627 * and number of cached results parsed so far.
1628 */
1629 mGetCachedResultsRspParams->wifiScanResultsStartingIndex = j;
1630 cached_results[i].num_results++;
1631 } else {
1632 /* We already parsed and stored up to max wifi_scan_results
1633 * specified by the caller. Now, continue to loop over NL
1634 * entries in order to properly update NL parsing pointer
1635 * so it points to the next scan_id results.
1636 */
1637 ALOGD("%s: loop index:%d > max num"
1638 " of wifi_scan_results:%d for gscan cached results"
1639 " bucket:%d. Dummy loop", __FUNCTION__,
1640 j, MAX_AP_CACHE_PER_SCAN, i);
1641 }
1642 }
1643 ALOGV("%s: cached_results[%d].num_results: %d ", __FUNCTION__,
1644 i, cached_results[i].num_results);
1645 /* Increment loop index for next cached scan result record */
1646 i++;
1647 }
1648 /* Increment starting index of filling cached results received */
1649 if (mGetCachedResultsRspParams->num_cached_results)
1650 mGetCachedResultsRspParams->cachedResultsStartingIndex =
1651 mGetCachedResultsRspParams->num_cached_results - 1;
1652 return WIFI_SUCCESS;
1653 }
1654
1655 /* Set the GSCAN BSSID Hotlist. */
wifi_set_epno_list(wifi_request_id id,wifi_interface_handle iface,const wifi_epno_params * epno_params,wifi_epno_handler handler)1656 wifi_error wifi_set_epno_list(wifi_request_id id,
1657 wifi_interface_handle iface,
1658 const wifi_epno_params *epno_params,
1659 wifi_epno_handler handler)
1660 {
1661 int i, num_networks;
1662 wifi_error ret;
1663 GScanCommand *gScanCommand;
1664 struct nlattr *nlData, *nlPnoParamList;
1665 interface_info *ifaceInfo = getIfaceInfo(iface);
1666 wifi_handle wifiHandle = getWifiHandle(iface);
1667 hal_info *info = getHalInfo(wifiHandle);
1668 gscan_event_handlers* event_handlers;
1669 GScanCommandEventHandler *gScanSetPnoListCmdEventHandler;
1670
1671 event_handlers = (gscan_event_handlers*)info->gscan_handlers;
1672 gScanSetPnoListCmdEventHandler =
1673 event_handlers->gScanSetPnoListCmdEventHandler;
1674
1675 if (!(info->supported_feature_set & WIFI_FEATURE_HAL_EPNO)) {
1676 ALOGE("%s: Enhanced PNO is not supported by the driver",
1677 __FUNCTION__);
1678 return WIFI_ERROR_NOT_SUPPORTED;
1679 }
1680
1681 /* Wi-Fi HAL doesn't need to check if a similar request to set ePNO
1682 * list was made earlier. If wifi_set_epno_list() is called while
1683 * another one is running, the request will be sent down to driver and
1684 * firmware. If the new request is successfully honored, then Wi-Fi HAL
1685 * will use the new request id for the gScanSetPnoListCmdEventHandler
1686 * object.
1687 */
1688
1689 gScanCommand =
1690 new GScanCommand(
1691 wifiHandle,
1692 id,
1693 OUI_QCA,
1694 QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST);
1695 if (gScanCommand == NULL) {
1696 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
1697 return WIFI_ERROR_UNKNOWN;
1698 }
1699
1700 /* Create the NL message. */
1701 ret = gScanCommand->create();
1702 if (ret != WIFI_SUCCESS) {
1703 ALOGE("%s: Failed to create the NL msg. Error:%d", __FUNCTION__, ret);
1704 goto cleanup;
1705 }
1706
1707 /* Set the interface Id of the message. */
1708 ret = gScanCommand->set_iface_id(ifaceInfo->name);
1709 if (ret != WIFI_SUCCESS) {
1710 ALOGE("%s: Failed to set iface id. Error:%d", __FUNCTION__, ret);
1711 goto cleanup;
1712 }
1713
1714 /* Add the vendor specific attributes for the NL command. */
1715 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1716 if (!nlData) {
1717 ALOGE("%s: Failed to add attribute NL80211_ATTR_VENDOR_DATA. Error:%d",
1718 __FUNCTION__, ret);
1719 goto cleanup;
1720 }
1721
1722 num_networks = (unsigned int)epno_params->num_networks > MAX_EPNO_NETWORKS ?
1723 MAX_EPNO_NETWORKS : epno_params->num_networks;
1724 if (gScanCommand->put_u32(
1725 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
1726 id) ||
1727 gScanCommand->put_u32(
1728 QCA_WLAN_VENDOR_ATTR_EPNO_MIN5GHZ_RSSI,
1729 epno_params->min5GHz_rssi) ||
1730 gScanCommand->put_u32(
1731 QCA_WLAN_VENDOR_ATTR_EPNO_MIN24GHZ_RSSI,
1732 epno_params->min24GHz_rssi) ||
1733 gScanCommand->put_u32(
1734 QCA_WLAN_VENDOR_ATTR_EPNO_INITIAL_SCORE_MAX,
1735 epno_params->initial_score_max) ||
1736 gScanCommand->put_u32(
1737 QCA_WLAN_VENDOR_ATTR_EPNO_CURRENT_CONNECTION_BONUS,
1738 epno_params->current_connection_bonus) ||
1739 gScanCommand->put_u32(
1740 QCA_WLAN_VENDOR_ATTR_EPNO_SAME_NETWORK_BONUS,
1741 epno_params->same_network_bonus) ||
1742 gScanCommand->put_u32(
1743 QCA_WLAN_VENDOR_ATTR_EPNO_SECURE_BONUS,
1744 epno_params->secure_bonus) ||
1745 gScanCommand->put_u32(
1746 QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS,
1747 epno_params->band5GHz_bonus) ||
1748 gScanCommand->put_u32(
1749 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS,
1750 num_networks))
1751 {
1752 ALOGE("%s: Failed to add vendor atributes. Error:%d", __FUNCTION__, ret);
1753 goto cleanup;
1754 }
1755
1756 /* Add the vendor specific attributes for the NL command. */
1757 nlPnoParamList =
1758 gScanCommand->attr_start(
1759 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST);
1760 if (!nlPnoParamList) {
1761 ALOGE("%s: Failed to add attr. PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST. "
1762 "Error:%d", __FUNCTION__, ret);
1763 goto cleanup;
1764 }
1765
1766 /* Add nested NL attributes for ePno List. */
1767 for (i = 0; i < num_networks; i++) {
1768 wifi_epno_network pnoNetwork = epno_params->networks[i];
1769 struct nlattr *nlPnoNetwork = gScanCommand->attr_start(i);
1770 if (!nlPnoNetwork) {
1771 ALOGE("%s: Failed attr_start for nlPnoNetwork. Error:%d",
1772 __FUNCTION__, ret);
1773 goto cleanup;
1774 }
1775 if (gScanCommand->put_string(
1776 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID,
1777 pnoNetwork.ssid) ||
1778 gScanCommand->put_u8(
1779 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS,
1780 pnoNetwork.flags) ||
1781 gScanCommand->put_u8(
1782 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT,
1783 pnoNetwork.auth_bit_field))
1784 {
1785 ALOGE("%s: Failed to add PNO_SET_LIST_PARAM_EPNO_NETWORK_*. "
1786 "Error:%d", __FUNCTION__, ret);
1787 goto cleanup;
1788 }
1789 gScanCommand->attr_end(nlPnoNetwork);
1790 }
1791
1792 gScanCommand->attr_end(nlPnoParamList);
1793
1794 gScanCommand->attr_end(nlData);
1795
1796 GScanCallbackHandler callbackHandler;
1797 memset(&callbackHandler, 0, sizeof(callbackHandler));
1798 callbackHandler.on_pno_network_found = handler.on_network_found;
1799
1800 /* Create an object of the event handler class to take care of the
1801 * asychronous events on the north-bound.
1802 */
1803 if (gScanSetPnoListCmdEventHandler == NULL) {
1804 gScanSetPnoListCmdEventHandler = new GScanCommandEventHandler(
1805 wifiHandle,
1806 id,
1807 OUI_QCA,
1808 QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST,
1809 callbackHandler);
1810 if (gScanSetPnoListCmdEventHandler == NULL) {
1811 ALOGE("%s: Error instantiating "
1812 "gScanSetPnoListCmdEventHandler.", __FUNCTION__);
1813 ret = WIFI_ERROR_UNKNOWN;
1814 goto cleanup;
1815 }
1816 event_handlers->gScanSetPnoListCmdEventHandler =
1817 gScanSetPnoListCmdEventHandler;
1818 } else {
1819 gScanSetPnoListCmdEventHandler->setCallbackHandler(callbackHandler);
1820 }
1821
1822 ret = gScanCommand->requestResponse();
1823 if (ret != WIFI_SUCCESS) {
1824 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
1825 goto cleanup;
1826 }
1827
1828 if (gScanSetPnoListCmdEventHandler != NULL) {
1829 gScanSetPnoListCmdEventHandler->set_request_id(id);
1830 gScanSetPnoListCmdEventHandler->enableEventHandling();
1831 }
1832
1833 cleanup:
1834 delete gScanCommand;
1835 /* Disable Event Handling if ret != 0 */
1836 if ((ret != WIFI_SUCCESS) && gScanSetPnoListCmdEventHandler) {
1837 ALOGI("%s: Error ret:%d, disable event handling",
1838 __FUNCTION__, ret);
1839 gScanSetPnoListCmdEventHandler->disableEventHandling();
1840 }
1841 return ret;
1842 }
1843
1844 /* Reset the ePNO list - no ePNO networks should be matched after this */
wifi_reset_epno_list(wifi_request_id id,wifi_interface_handle iface)1845 wifi_error wifi_reset_epno_list(wifi_request_id id, wifi_interface_handle iface)
1846 {
1847 wifi_error ret;
1848 GScanCommand *gScanCommand;
1849 struct nlattr *nlData;
1850 interface_info *ifaceInfo = getIfaceInfo(iface);
1851 wifi_handle wifiHandle = getWifiHandle(iface);
1852 hal_info *info = getHalInfo(wifiHandle);
1853
1854 if (!(info->supported_feature_set & WIFI_FEATURE_HAL_EPNO)) {
1855 ALOGE("%s: Enhanced PNO is not supported by the driver",
1856 __FUNCTION__);
1857 return WIFI_ERROR_NOT_SUPPORTED;
1858 }
1859
1860 gScanCommand = new GScanCommand(wifiHandle,
1861 id,
1862 OUI_QCA,
1863 QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST);
1864 if (gScanCommand == NULL) {
1865 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
1866 return WIFI_ERROR_UNKNOWN;
1867 }
1868
1869 /* Create the NL message. */
1870 ret = gScanCommand->create();
1871 if (ret != WIFI_SUCCESS) {
1872 ALOGE("%s: Failed to create the NL msg. Error:%d", __FUNCTION__, ret);
1873 goto cleanup;
1874 }
1875
1876 /* Set the interface Id of the message. */
1877 ret = gScanCommand->set_iface_id(ifaceInfo->name);
1878 if (ret != WIFI_SUCCESS) {
1879 ALOGE("%s: Failed to set iface id. Error:%d", __FUNCTION__, ret);
1880 goto cleanup;
1881 }
1882
1883 /* Add the vendor specific attributes for the NL command. */
1884 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1885 if (!nlData) {
1886 ALOGE("%s: Failed to add attribute NL80211_ATTR_VENDOR_DATA. Error:%d",
1887 __FUNCTION__, ret);
1888 goto cleanup;
1889 }
1890
1891 if (gScanCommand->put_u32(
1892 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
1893 id) ||
1894 gScanCommand->put_u32(
1895 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS,
1896 EPNO_NO_NETWORKS))
1897 {
1898 ALOGE("%s: Failed to add vendor atributes Error:%d", __FUNCTION__, ret);
1899 goto cleanup;
1900 }
1901
1902 gScanCommand->attr_end(nlData);
1903
1904 ret = gScanCommand->requestResponse();
1905 if (ret != WIFI_SUCCESS)
1906 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
1907
1908 cleanup:
1909 delete gScanCommand;
1910 return ret;
1911 }
1912
1913 /* Set the ePNO Passpoint List. */
wifi_set_passpoint_list(wifi_request_id id,wifi_interface_handle iface,int num,wifi_passpoint_network * networks,wifi_passpoint_event_handler handler)1914 wifi_error wifi_set_passpoint_list(wifi_request_id id,
1915 wifi_interface_handle iface, int num,
1916 wifi_passpoint_network *networks,
1917 wifi_passpoint_event_handler handler)
1918 {
1919 int i;
1920 wifi_error ret;
1921 GScanCommand *gScanCommand;
1922 struct nlattr *nlData, *nlPasspointNetworksParamList;
1923 interface_info *ifaceInfo = getIfaceInfo(iface);
1924 wifi_handle wifiHandle = getWifiHandle(iface);
1925 hal_info *info = getHalInfo(wifiHandle);
1926 gscan_event_handlers* event_handlers;
1927 GScanCommandEventHandler *gScanPnoSetPasspointListCmdEventHandler;
1928
1929 event_handlers = (gscan_event_handlers*)info->gscan_handlers;
1930 gScanPnoSetPasspointListCmdEventHandler =
1931 event_handlers->gScanPnoSetPasspointListCmdEventHandler;
1932
1933 if (!(info->supported_feature_set & WIFI_FEATURE_HAL_EPNO)) {
1934 ALOGE("%s: Enhanced PNO is not supported by the driver",
1935 __FUNCTION__);
1936 return WIFI_ERROR_NOT_SUPPORTED;
1937 }
1938
1939 /* Wi-Fi HAL doesn't need to check if a similar request to set ePNO
1940 * passpoint list was made earlier. If wifi_set_passpoint_list() is called
1941 * while another one is running, the request will be sent down to driver and
1942 * firmware. If the new request is successfully honored, then Wi-Fi HAL
1943 * will use the new request id for the
1944 * gScanPnoSetPasspointListCmdEventHandler object.
1945 */
1946 gScanCommand =
1947 new GScanCommand(
1948 wifiHandle,
1949 id,
1950 OUI_QCA,
1951 QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST);
1952 if (gScanCommand == NULL) {
1953 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
1954 return WIFI_ERROR_UNKNOWN;
1955 }
1956
1957 /* Create the NL message. */
1958 ret = gScanCommand->create();
1959 if (ret != WIFI_SUCCESS) {
1960 ALOGE("%s: Failed to create the NL msg. Error:%d", __FUNCTION__, ret);
1961 goto cleanup;
1962 }
1963
1964 /* Set the interface Id of the message. */
1965 ret = gScanCommand->set_iface_id(ifaceInfo->name);
1966 if (ret != WIFI_SUCCESS) {
1967 ALOGE("%s: Failed to set iface id. Error:%d", __FUNCTION__, ret);
1968 goto cleanup;
1969 }
1970
1971 /* Add the vendor specific attributes for the NL command. */
1972 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1973 if (!nlData) {
1974 ALOGE("%s: Failed to add attribute NL80211_ATTR_VENDOR_DATA. Error:%d",
1975 __FUNCTION__, ret);
1976 goto cleanup;
1977 }
1978
1979 if (gScanCommand->put_u32(
1980 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
1981 id) ||
1982 gScanCommand->put_u32(
1983 QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM,
1984 num))
1985 {
1986 ALOGE("%s: Failed to add vendor atributes. Error:%d", __FUNCTION__, ret);
1987 goto cleanup;
1988 }
1989
1990 /* Add the vendor specific attributes for the NL command. */
1991 nlPasspointNetworksParamList =
1992 gScanCommand->attr_start(
1993 QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY);
1994 if (!nlPasspointNetworksParamList) {
1995 ALOGE("%s: Failed attr_start for PASSPOINT_LIST_PARAM_NETWORK_ARRAY. "
1996 "Error:%d", __FUNCTION__, ret);
1997 goto cleanup;
1998 }
1999
2000 /* Add nested NL attributes for Passpoint List param. */
2001 for (i = 0; i < num; i++) {
2002 wifi_passpoint_network passpointNetwork = networks[i];
2003 struct nlattr *nlPasspointNetworkParam = gScanCommand->attr_start(i);
2004 if (!nlPasspointNetworkParam) {
2005 ALOGE("%s: Failed attr_start for nlPasspointNetworkParam. "
2006 "Error:%d", __FUNCTION__, ret);
2007 goto cleanup;
2008 }
2009 if (gScanCommand->put_u32(
2010 QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID,
2011 passpointNetwork.id) ||
2012 gScanCommand->put_string(
2013 QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM,
2014 passpointNetwork.realm) ||
2015 gScanCommand->put_bytes(
2016 QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID,
2017 (char*)passpointNetwork.roamingConsortiumIds,
2018 16 * sizeof(int64_t)) ||
2019 gScanCommand->put_bytes(
2020 QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN,
2021 (char*)passpointNetwork.plmn, 3 * sizeof(u8)))
2022 {
2023 ALOGE("%s: Failed to add PNO_PASSPOINT_NETWORK_PARAM_ROAM_* attr. "
2024 "Error:%d", __FUNCTION__, ret);
2025 goto cleanup;
2026 }
2027 gScanCommand->attr_end(nlPasspointNetworkParam);
2028 }
2029
2030 gScanCommand->attr_end(nlPasspointNetworksParamList);
2031
2032 gScanCommand->attr_end(nlData);
2033
2034 GScanCallbackHandler callbackHandler;
2035 memset(&callbackHandler, 0, sizeof(callbackHandler));
2036 callbackHandler.on_passpoint_network_found =
2037 handler.on_passpoint_network_found;
2038
2039 /* Create an object of the event handler class to take care of the
2040 * asychronous events on the north-bound.
2041 */
2042 if (gScanPnoSetPasspointListCmdEventHandler == NULL) {
2043 gScanPnoSetPasspointListCmdEventHandler = new GScanCommandEventHandler(
2044 wifiHandle,
2045 id,
2046 OUI_QCA,
2047 QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST,
2048 callbackHandler);
2049 if (gScanPnoSetPasspointListCmdEventHandler == NULL) {
2050 ALOGE("%s: Error instantiating "
2051 "gScanPnoSetPasspointListCmdEventHandler.", __FUNCTION__);
2052 ret = WIFI_ERROR_UNKNOWN;
2053 goto cleanup;
2054 }
2055 event_handlers->gScanPnoSetPasspointListCmdEventHandler =
2056 gScanPnoSetPasspointListCmdEventHandler;
2057 } else {
2058 gScanPnoSetPasspointListCmdEventHandler->setCallbackHandler(callbackHandler);
2059 }
2060
2061 ret = gScanCommand->requestResponse();
2062 if (ret != WIFI_SUCCESS) {
2063 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
2064 goto cleanup;
2065 }
2066
2067 if (gScanPnoSetPasspointListCmdEventHandler != NULL) {
2068 gScanPnoSetPasspointListCmdEventHandler->set_request_id(id);
2069 gScanPnoSetPasspointListCmdEventHandler->enableEventHandling();
2070 }
2071
2072 cleanup:
2073 delete gScanCommand;
2074 /* Disable Event Handling if ret != 0 */
2075 if ((ret != WIFI_SUCCESS) && gScanPnoSetPasspointListCmdEventHandler) {
2076 ALOGI("%s: Error ret:%d, disable event handling",
2077 __FUNCTION__, ret);
2078 gScanPnoSetPasspointListCmdEventHandler->disableEventHandling();
2079 }
2080 return ret;
2081 }
2082
wifi_reset_passpoint_list(wifi_request_id id,wifi_interface_handle iface)2083 wifi_error wifi_reset_passpoint_list(wifi_request_id id,
2084 wifi_interface_handle iface)
2085 {
2086 wifi_error ret;
2087 GScanCommand *gScanCommand;
2088 struct nlattr *nlData;
2089 interface_info *ifaceInfo = getIfaceInfo(iface);
2090 wifi_handle wifiHandle = getWifiHandle(iface);
2091 hal_info *info = getHalInfo(wifiHandle);
2092 gscan_event_handlers* event_handlers;
2093 GScanCommandEventHandler *gScanPnoSetPasspointListCmdEventHandler;
2094
2095 event_handlers = (gscan_event_handlers*)info->gscan_handlers;
2096 gScanPnoSetPasspointListCmdEventHandler =
2097 event_handlers->gScanPnoSetPasspointListCmdEventHandler;
2098
2099 if (!(info->supported_feature_set & WIFI_FEATURE_HAL_EPNO)) {
2100 ALOGE("%s: Enhanced PNO is not supported by the driver",
2101 __FUNCTION__);
2102 return WIFI_ERROR_NOT_SUPPORTED;
2103 }
2104
2105 if (gScanPnoSetPasspointListCmdEventHandler == NULL ||
2106 (gScanPnoSetPasspointListCmdEventHandler->isEventHandlingEnabled() ==
2107 false)) {
2108 ALOGE("wifi_reset_passpoint_list: ePNO passpoint_list isn't set. "
2109 "Nothing to do. Exit.");
2110 return WIFI_ERROR_NOT_AVAILABLE;
2111 }
2112
2113 gScanCommand = new GScanCommand(
2114 wifiHandle,
2115 id,
2116 OUI_QCA,
2117 QCA_NL80211_VENDOR_SUBCMD_PNO_RESET_PASSPOINT_LIST);
2118
2119 if (gScanCommand == NULL) {
2120 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
2121 return WIFI_ERROR_UNKNOWN;
2122 }
2123
2124 /* Create the NL message. */
2125 ret = gScanCommand->create();
2126 if (ret != WIFI_SUCCESS) {
2127 ALOGE("%s: Failed to create the NL msg. Error:%d", __FUNCTION__, ret);
2128 goto cleanup;
2129 }
2130
2131 /* Set the interface Id of the message. */
2132 ret = gScanCommand->set_iface_id(ifaceInfo->name);
2133 if (ret != WIFI_SUCCESS) {
2134 ALOGE("%s: Failed to set iface id. Error:%d", __FUNCTION__, ret);
2135 goto cleanup;
2136 }
2137
2138 /* Add the vendor specific attributes for the NL command. */
2139 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2140 if (!nlData) {
2141 ALOGE("%s: Failed to add attribute NL80211_ATTR_VENDOR_DATA. Error:%d",
2142 __FUNCTION__, ret);
2143 goto cleanup;
2144 }
2145
2146 ret = gScanCommand->put_u32(
2147 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, id);
2148 if (ret != WIFI_SUCCESS) {
2149 ALOGE("%s: Failed to add vendor data attributes. Error:%d",
2150 __FUNCTION__, ret);
2151 goto cleanup;
2152 }
2153
2154 gScanCommand->attr_end(nlData);
2155
2156 ret = gScanCommand->requestResponse();
2157 if (ret != WIFI_SUCCESS)
2158 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
2159
2160 /* Disable Event Handling. */
2161 if (gScanPnoSetPasspointListCmdEventHandler) {
2162 gScanPnoSetPasspointListCmdEventHandler->disableEventHandling();
2163 }
2164
2165 cleanup:
2166 delete gScanCommand;
2167 return ret;
2168 }
2169
allocCachedResultsTemp(int max,wifi_cached_scan_results * cached_results)2170 wifi_error GScanCommand::allocCachedResultsTemp(int max,
2171 wifi_cached_scan_results *cached_results)
2172 {
2173 /* Alloc memory for "max" number of cached results. */
2174 mGetCachedResultsRspParams->cached_results =
2175 (wifi_cached_scan_results*)
2176 malloc(max * sizeof(wifi_cached_scan_results));
2177 if (!mGetCachedResultsRspParams->cached_results) {
2178 ALOGE("%s: Failed to allocate memory for "
2179 "mGetCachedResultsRspParams->cached_results.",
2180 __FUNCTION__);
2181 return WIFI_ERROR_OUT_OF_MEMORY;
2182 }
2183 memset(mGetCachedResultsRspParams->cached_results, 0,
2184 max * sizeof(wifi_cached_scan_results));
2185
2186 mGetCachedResultsRspParams->max = max;
2187
2188 return WIFI_SUCCESS;
2189 }
2190
2191 /*
2192 * Allocates memory for the subCmd response struct and initializes status = -1
2193 */
allocRspParams(eGScanRspRarams cmd)2194 wifi_error GScanCommand::allocRspParams(eGScanRspRarams cmd)
2195 {
2196 switch(cmd)
2197 {
2198 case eGScanGetCachedResultsRspParams:
2199 mGetCachedResultsRspParams = (GScanGetCachedResultsRspParams *)
2200 malloc(sizeof(GScanGetCachedResultsRspParams));
2201 if (!mGetCachedResultsRspParams)
2202 return WIFI_ERROR_OUT_OF_MEMORY;
2203
2204 mGetCachedResultsRspParams->num_cached_results = 0;
2205 mGetCachedResultsRspParams->more_data = false;
2206 mGetCachedResultsRspParams->cachedResultsStartingIndex = -1;
2207 mGetCachedResultsRspParams->lastProcessedScanId = -1;
2208 mGetCachedResultsRspParams->wifiScanResultsStartingIndex = -1;
2209 mGetCachedResultsRspParams->max = 0;
2210 mGetCachedResultsRspParams->cached_results = NULL;
2211 break;
2212 default:
2213 ALOGD("%s: Wrong request for alloc.", __FUNCTION__);
2214 return WIFI_ERROR_NOT_SUPPORTED;
2215 }
2216 return WIFI_SUCCESS;
2217 }
2218
freeRspParams(eGScanRspRarams cmd)2219 void GScanCommand::freeRspParams(eGScanRspRarams cmd)
2220 {
2221 switch(cmd)
2222 {
2223 case eGScanGetCachedResultsRspParams:
2224 if (mGetCachedResultsRspParams) {
2225 if (mGetCachedResultsRspParams->cached_results) {
2226 free(mGetCachedResultsRspParams->cached_results);
2227 mGetCachedResultsRspParams->cached_results = NULL;
2228 }
2229 free(mGetCachedResultsRspParams);
2230 mGetCachedResultsRspParams = NULL;
2231 }
2232 break;
2233 default:
2234 ALOGD("%s: Wrong request for free.", __FUNCTION__);
2235 }
2236 }
2237
copyCachedScanResults(int * numResults,wifi_cached_scan_results * cached_results)2238 wifi_error GScanCommand::copyCachedScanResults(
2239 int *numResults,
2240 wifi_cached_scan_results *cached_results)
2241 {
2242 wifi_error ret = WIFI_SUCCESS;
2243 int i;
2244 wifi_cached_scan_results *cachedResultRsp;
2245
2246 if (mGetCachedResultsRspParams && cached_results)
2247 {
2248 /* Populate the number of parsed cached results. */
2249 *numResults = mGetCachedResultsRspParams->num_cached_results;
2250
2251 for (i = 0; i < *numResults; i++) {
2252 cachedResultRsp = &mGetCachedResultsRspParams->cached_results[i];
2253 cached_results[i].scan_id = cachedResultRsp->scan_id;
2254 cached_results[i].flags = cachedResultRsp->flags;
2255 cached_results[i].num_results = cachedResultRsp->num_results;
2256 cached_results[i].buckets_scanned = cachedResultRsp->buckets_scanned;
2257
2258 if (!cached_results[i].num_results) {
2259 ALOGI("Error: cached_results[%d].num_results=0", i);
2260 continue;
2261 }
2262
2263 ALOGV("copyCachedScanResults: "
2264 "cached_results[%d].num_results : %d",
2265 i, cached_results[i].num_results);
2266
2267 memcpy(cached_results[i].results,
2268 cachedResultRsp->results,
2269 cached_results[i].num_results * sizeof(wifi_scan_result));
2270 }
2271 } else {
2272 ALOGE("%s: mGetCachedResultsRspParams is NULL", __FUNCTION__);
2273 *numResults = 0;
2274 ret = WIFI_ERROR_INVALID_ARGS;
2275 }
2276 return ret;
2277 }
2278
setMaxChannels(int max_channels)2279 void GScanCommand::setMaxChannels(int max_channels) {
2280 mMaxChannels = max_channels;
2281 }
2282
setChannels(int * channels)2283 void GScanCommand::setChannels(int *channels) {
2284 mChannels = channels;
2285 }
2286
setNumChannelsPtr(int * num_channels)2287 void GScanCommand::setNumChannelsPtr(int *num_channels) {
2288 mNumChannelsPtr = num_channels;
2289 }
2290