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