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