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