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