1 /*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "sync.h"
18 #define LOG_TAG "WifiHAL"
19 #include <utils/Log.h>
20 #include <time.h>
21 #include <errno.h>
22 #include <stdlib.h>
23
24 #include "common.h"
25 #include "cpp_bindings.h"
26 #include "gscancommand.h"
27 #include "gscan_event_handler.h"
28
29 #define GSCAN_EVENT_WAIT_TIME_SECONDS 4
30
31 /* Used to handle gscan command events from driver/firmware.*/
32 typedef struct gscan_event_handlers_s {
33 GScanCommandEventHandler *gscanStartCmdEventHandler;
34 GScanCommandEventHandler *gScanSetBssidHotlistCmdEventHandler;
35 GScanCommandEventHandler *gScanSetSignificantChangeCmdEventHandler;
36 GScanCommandEventHandler *gScanSetSsidHotlistCmdEventHandler;
37 GScanCommandEventHandler *gScanSetPnoListCmdEventHandler;
38 GScanCommandEventHandler *gScanPnoSetPasspointListCmdEventHandler;
39 } gscan_event_handlers;
40
initializeGscanHandlers(hal_info * info)41 wifi_error initializeGscanHandlers(hal_info *info)
42 {
43 info->gscan_handlers = (gscan_event_handlers *)malloc(sizeof(gscan_event_handlers));
44 if (info->gscan_handlers) {
45 memset(info->gscan_handlers, 0, sizeof(gscan_event_handlers));
46 }
47 else {
48 ALOGE("%s: Allocation of gscan event handlers failed",
49 __FUNCTION__);
50 return WIFI_ERROR_OUT_OF_MEMORY;
51 }
52 return WIFI_SUCCESS;
53 }
54
cleanupGscanHandlers(hal_info * info)55 wifi_error cleanupGscanHandlers(hal_info *info)
56 {
57 gscan_event_handlers* event_handlers;
58 if (info && info->gscan_handlers) {
59 event_handlers = (gscan_event_handlers*) info->gscan_handlers;
60 if (event_handlers->gscanStartCmdEventHandler) {
61 delete event_handlers->gscanStartCmdEventHandler;
62 }
63 if (event_handlers->gScanSetBssidHotlistCmdEventHandler) {
64 delete event_handlers->gScanSetBssidHotlistCmdEventHandler;
65 }
66 if (event_handlers->gScanSetSignificantChangeCmdEventHandler) {
67 delete event_handlers->gScanSetSignificantChangeCmdEventHandler;
68 }
69 if (event_handlers->gScanSetSsidHotlistCmdEventHandler) {
70 delete event_handlers->gScanSetSsidHotlistCmdEventHandler;
71 }
72 if (event_handlers->gScanSetPnoListCmdEventHandler) {
73 delete event_handlers->gScanSetPnoListCmdEventHandler;
74 }
75 if (event_handlers->gScanPnoSetPasspointListCmdEventHandler) {
76 delete event_handlers->gScanPnoSetPasspointListCmdEventHandler;
77 }
78 memset(event_handlers, 0, sizeof(gscan_event_handlers));
79 return WIFI_SUCCESS;
80 }
81 ALOGE ("%s: info or info->gscan_handlers NULL", __FUNCTION__);
82 return WIFI_ERROR_UNKNOWN;
83 }
84
85 /* Implementation of the API functions exposed in gscan.h */
wifi_get_valid_channels(wifi_interface_handle handle,int band,int max_channels,wifi_channel * channels,int * num_channels)86 wifi_error wifi_get_valid_channels(wifi_interface_handle handle,
87 int band, int max_channels, wifi_channel *channels, int *num_channels)
88 {
89 int requestId, ret = 0, i=0;
90 GScanCommand *gScanCommand;
91 struct nlattr *nlData;
92 interface_info *ifaceInfo = getIfaceInfo(handle);
93 wifi_handle wifiHandle = getWifiHandle(handle);
94 hal_info *info = getHalInfo(wifiHandle);
95 lowi_cb_table_t *lowiWifiHalApi = NULL;
96
97 /* Route GSCAN request through LOWI if supported */
98 lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED);
99 if (lowiWifiHalApi == NULL ||
100 lowiWifiHalApi->get_valid_channels == NULL) {
101 ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
102 } else {
103 ret = lowiWifiHalApi->get_valid_channels(handle, band, max_channels,
104 channels, num_channels);
105 ALOGI("%s: lowi get_valid_channels "
106 "returned: %d. Exit.", __FUNCTION__, ret);
107 return (wifi_error)ret;
108 }
109
110 /* No request id from caller, so generate one and pass it on to the driver.
111 * Generate one randomly.
112 */
113 requestId = get_requestid();
114 ALOGI("%s: RequestId:%d band:%d max_channels:%d", __FUNCTION__,
115 requestId, band, max_channels);
116
117 if (channels == NULL) {
118 ALOGE("%s: NULL channels pointer provided. Exit.",
119 __FUNCTION__);
120 return WIFI_ERROR_INVALID_ARGS;
121 }
122
123 gScanCommand = new GScanCommand(
124 wifiHandle,
125 requestId,
126 OUI_QCA,
127 QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_VALID_CHANNELS);
128 if (gScanCommand == NULL) {
129 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
130 return WIFI_ERROR_UNKNOWN;
131 }
132 /* Create the NL message. */
133 ret = gScanCommand->create();
134 if (ret < 0)
135 goto cleanup;
136
137 /* Set the interface Id of the message. */
138 ret = gScanCommand->set_iface_id(ifaceInfo->name);
139 if (ret < 0)
140 goto cleanup;
141
142 /* Add the vendor specific attributes for the NL command. */
143 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
144 if (!nlData)
145 goto cleanup;
146
147 if (gScanCommand->put_u32(
148 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
149 requestId) ||
150 gScanCommand->put_u32(
151 QCA_WLAN_VENDOR_ATTR_GSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND,
152 band) ||
153 gScanCommand->put_u32(
154 QCA_WLAN_VENDOR_ATTR_GSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS,
155 max_channels) )
156 {
157 goto cleanup;
158 }
159 gScanCommand->attr_end(nlData);
160 /* Populate the input received from caller/framework. */
161 gScanCommand->setMaxChannels(max_channels);
162 gScanCommand->setChannels(channels);
163 gScanCommand->setNumChannelsPtr(num_channels);
164
165 /* Send the msg and wait for a response. */
166 ret = gScanCommand->requestResponse();
167 if (ret) {
168 ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
169 }
170
171 cleanup:
172 delete gScanCommand;
173 return (wifi_error)ret;
174 }
175
wifi_get_gscan_capabilities(wifi_interface_handle handle,wifi_gscan_capabilities * capabilities)176 wifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle,
177 wifi_gscan_capabilities *capabilities)
178 {
179 int requestId, ret = 0;
180 GScanCommand *gScanCommand;
181 struct nlattr *nlData;
182 wifi_gscan_capabilities tCapabilities;
183 interface_info *ifaceInfo = getIfaceInfo(handle);
184 wifi_handle wifiHandle = getWifiHandle(handle);
185 hal_info *info = getHalInfo(wifiHandle);
186 lowi_cb_table_t *lowiWifiHalApi = NULL;
187
188 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
189 ALOGE("%s: GSCAN is not supported by driver",
190 __FUNCTION__);
191 return WIFI_ERROR_NOT_SUPPORTED;
192 }
193
194 /* Route GSCAN request through LOWI if supported */
195 lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED);
196 if (lowiWifiHalApi == NULL ||
197 lowiWifiHalApi->get_gscan_capabilities == NULL) {
198 ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
199 } else {
200 ret = lowiWifiHalApi->get_gscan_capabilities(handle,
201 capabilities);
202 ALOGI("%s: lowi get_gscan_capabilities "
203 "returned: %d. Exit.", __FUNCTION__, ret);
204 return (wifi_error)ret;
205 }
206
207 /* No request id from caller, so generate one and pass it on to the driver.
208 * Generate it randomly.
209 */
210 requestId = get_requestid();
211 ALOGI("%s: RequestId:%d", __FUNCTION__, requestId);
212
213 if (capabilities == NULL) {
214 ALOGE("%s: NULL capabilities pointer provided. Exit.",
215 __FUNCTION__);
216 return WIFI_ERROR_INVALID_ARGS;
217 }
218
219 gScanCommand = new GScanCommand(
220 wifiHandle,
221 requestId,
222 OUI_QCA,
223 QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES);
224 if (gScanCommand == NULL) {
225 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
226 return WIFI_ERROR_UNKNOWN;
227 }
228
229 /* Create the NL message. */
230 ret = gScanCommand->create();
231 if (ret < 0)
232 goto cleanup;
233
234 /* Set the interface Id of the message. */
235 ret = gScanCommand->set_iface_id(ifaceInfo->name);
236 if (ret < 0)
237 goto cleanup;
238
239 /* Add the vendor specific attributes for the NL command. */
240 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
241 if (!nlData)
242 goto cleanup;
243
244 ret = gScanCommand->put_u32(
245 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
246 requestId);
247 if (ret < 0)
248 goto cleanup;
249
250 gScanCommand->attr_end(nlData);
251 ret = gScanCommand->allocRspParams(eGScanGetCapabilitiesRspParams);
252 if (ret != 0) {
253 ALOGE("%s: Failed to allocate memory fo response struct. Error:%d",
254 __FUNCTION__, ret);
255 goto cleanup;
256 }
257
258 ret = gScanCommand->requestResponse();
259 if (ret != 0) {
260 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
261 goto cleanup;
262 }
263
264 gScanCommand->getGetCapabilitiesRspParams(capabilities);
265
266 cleanup:
267 gScanCommand->freeRspParams(eGScanGetCapabilitiesRspParams);
268 delete gScanCommand;
269 return (wifi_error)ret;
270 }
271
wifi_start_gscan(wifi_request_id id,wifi_interface_handle iface,wifi_scan_cmd_params params,wifi_scan_result_handler handler)272 wifi_error wifi_start_gscan(wifi_request_id id,
273 wifi_interface_handle iface,
274 wifi_scan_cmd_params params,
275 wifi_scan_result_handler handler)
276 {
277 int ret = 0;
278 u32 i, j;
279 GScanCommand *gScanCommand;
280 struct nlattr *nlData;
281 interface_info *ifaceInfo = getIfaceInfo(iface);
282 wifi_handle wifiHandle = getWifiHandle(iface);
283 u32 num_scan_buckets, numChannelSpecs;
284 wifi_scan_bucket_spec bucketSpec;
285 struct nlattr *nlBuckectSpecList;
286 bool previousGScanRunning = false;
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 ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
306 } else {
307 ret = lowiWifiHalApi->start_gscan(id, iface, params, handler);
308 ALOGI("%s: lowi start_gscan "
309 "returned: %d. Exit.", __FUNCTION__, ret);
310 return (wifi_error)ret;
311 }
312
313 ALOGI("%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 ALOGI("%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 ALOGI("%s: Index: %d Bucket Id:%d Band:%d Period:%d ReportEvent:%d "
384 "numChannelSpecs:%d max_period:%d exponent:%d step_count:%d",
385 __FUNCTION__, i, bucketSpec.bucket, bucketSpec.band,
386 bucketSpec.period, bucketSpec.report_events,
387 numChannelSpecs, bucketSpec.max_period,
388 bucketSpec.exponent, 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_EXPONENT,
411 bucketSpec.exponent) ||
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 ALOGI("%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_scan_results_available =
457 handler.on_scan_results_available;
458 callbackHandler.on_full_scan_result = handler.on_full_scan_result;
459 callbackHandler.on_scan_event = handler.on_scan_event;
460
461 /* Create an object to handle the related events from firmware/driver. */
462 if (gScanStartCmdEventHandler == NULL) {
463 gScanStartCmdEventHandler = new GScanCommandEventHandler(
464 wifiHandle,
465 id,
466 OUI_QCA,
467 QCA_NL80211_VENDOR_SUBCMD_GSCAN_START,
468 callbackHandler);
469 if (gScanStartCmdEventHandler == NULL) {
470 ALOGE("%s: Error gScanStartCmdEventHandler NULL", __FUNCTION__);
471 ret = WIFI_ERROR_UNKNOWN;
472 goto cleanup;
473 }
474 event_handlers->gscanStartCmdEventHandler = gScanStartCmdEventHandler;
475 } else {
476 gScanStartCmdEventHandler->setCallbackHandler(callbackHandler);
477 }
478
479 ret = gScanCommand->requestResponse();
480 if (ret != 0) {
481 ALOGE("%s : requestResponse Error:%d", __FUNCTION__, ret);
482 goto cleanup;
483 }
484
485 if (gScanStartCmdEventHandler != NULL) {
486 gScanStartCmdEventHandler->set_request_id(id);
487 gScanStartCmdEventHandler->enableEventHandling();
488 }
489
490 cleanup:
491 delete gScanCommand;
492 /* Disable Event Handling if ret != 0 */
493 if (ret && gScanStartCmdEventHandler) {
494 ALOGI("%s: Error ret:%d, disable event handling",
495 __FUNCTION__, ret);
496 gScanStartCmdEventHandler->disableEventHandling();
497 }
498 return (wifi_error)ret;
499
500 }
501
wifi_stop_gscan(wifi_request_id id,wifi_interface_handle iface)502 wifi_error wifi_stop_gscan(wifi_request_id id,
503 wifi_interface_handle iface)
504 {
505 int ret = 0;
506 GScanCommand *gScanCommand;
507 struct nlattr *nlData;
508 lowi_cb_table_t *lowiWifiHalApi = NULL;
509
510 interface_info *ifaceInfo = getIfaceInfo(iface);
511 wifi_handle wifiHandle = getWifiHandle(iface);
512 hal_info *info = getHalInfo(wifiHandle);
513 gscan_event_handlers* event_handlers;
514 GScanCommandEventHandler *gScanStartCmdEventHandler;
515
516 event_handlers = (gscan_event_handlers*)info->gscan_handlers;
517 gScanStartCmdEventHandler = event_handlers->gscanStartCmdEventHandler;
518
519 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
520 ALOGE("%s: GSCAN is not supported by driver",
521 __FUNCTION__);
522 return WIFI_ERROR_NOT_SUPPORTED;
523 }
524
525 /* Route GSCAN request through LOWI if supported */
526 lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED);
527 if (lowiWifiHalApi == NULL ||
528 lowiWifiHalApi->stop_gscan == NULL) {
529 ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
530 } else {
531 ret = lowiWifiHalApi->stop_gscan(id, iface);
532 ALOGI("%s: lowi stop_gscan "
533 "returned: %d. Exit.", __FUNCTION__, ret);
534 return (wifi_error)ret;
535 }
536
537 ALOGI("%s: RequestId:%d", __FUNCTION__, id);
538 if (gScanStartCmdEventHandler == NULL ||
539 gScanStartCmdEventHandler->isEventHandlingEnabled() == false) {
540 ALOGE("%s: GSCAN isn't running or already stopped. "
541 "Nothing to do. Exit", __FUNCTION__);
542 return WIFI_ERROR_NOT_AVAILABLE;
543 }
544
545 gScanCommand = new GScanCommand(
546 wifiHandle,
547 id,
548 OUI_QCA,
549 QCA_NL80211_VENDOR_SUBCMD_GSCAN_STOP);
550 if (gScanCommand == NULL) {
551 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
552 return WIFI_ERROR_UNKNOWN;
553 }
554
555 /* Create the NL message. */
556 ret = gScanCommand->create();
557 if (ret < 0)
558 goto cleanup;
559
560 /* Set the interface Id of the message. */
561 ret = gScanCommand->set_iface_id(ifaceInfo->name);
562 if (ret < 0)
563 goto cleanup;
564
565 /* Add the vendor specific attributes for the NL command. */
566 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
567 if (!nlData)
568 goto cleanup;
569
570 ret = gScanCommand->put_u32(
571 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
572 id);
573 if (ret < 0)
574 goto cleanup;
575
576 gScanCommand->attr_end(nlData);
577
578 ret = gScanCommand->requestResponse();
579 if (ret != 0) {
580 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
581 }
582
583 /* Disable Event Handling. */
584 if (gScanStartCmdEventHandler) {
585 gScanStartCmdEventHandler->disableEventHandling();
586 }
587
588 cleanup:
589 delete gScanCommand;
590 return (wifi_error)ret;
591 }
592
593 /* Set the GSCAN BSSID Hotlist. */
wifi_set_bssid_hotlist(wifi_request_id id,wifi_interface_handle iface,wifi_bssid_hotlist_params params,wifi_hotlist_ap_found_handler handler)594 wifi_error wifi_set_bssid_hotlist(wifi_request_id id,
595 wifi_interface_handle iface,
596 wifi_bssid_hotlist_params params,
597 wifi_hotlist_ap_found_handler handler)
598 {
599 int i, numAp, ret = 0;
600 GScanCommand *gScanCommand;
601 struct nlattr *nlData, *nlApThresholdParamList;
602 interface_info *ifaceInfo = getIfaceInfo(iface);
603 wifi_handle wifiHandle = getWifiHandle(iface);
604 bool previousGScanSetBssidRunning = false;
605 hal_info *info = getHalInfo(wifiHandle);
606 lowi_cb_table_t *lowiWifiHalApi = NULL;
607 gscan_event_handlers* event_handlers;
608 GScanCommandEventHandler *gScanSetBssidHotlistCmdEventHandler;
609
610 event_handlers = (gscan_event_handlers*)info->gscan_handlers;
611 gScanSetBssidHotlistCmdEventHandler =
612 event_handlers->gScanSetBssidHotlistCmdEventHandler;
613
614 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
615 ALOGE("%s: GSCAN is not supported by driver",
616 __FUNCTION__);
617 return WIFI_ERROR_NOT_SUPPORTED;
618 }
619
620 /* Route request through LOWI if supported*/
621 lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED);
622 if (lowiWifiHalApi == NULL ||
623 lowiWifiHalApi->set_bssid_hotlist == NULL) {
624 ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
625 } else {
626 ret = lowiWifiHalApi->set_bssid_hotlist(id, iface, params,handler);
627 ALOGI("%s: lowi set_bssid_hotlist "
628 "returned: %d. Exit.", __FUNCTION__, ret);
629 return (wifi_error)ret;
630 }
631
632 ALOGI("%s: RequestId:%d", __FUNCTION__, id);
633
634 /* Wi-Fi HAL doesn't need to check if a similar request to set bssid
635 * hotlist was made earlier. If set_bssid_hotlist() is called while
636 * another one is running, the request will be sent down to driver and
637 * firmware. If the new request is successfully honored, then Wi-Fi HAL
638 * will use the new request id for the gScanSetBssidHotlistCmdEventHandler
639 * object.
640 */
641
642 gScanCommand =
643 new GScanCommand(
644 wifiHandle,
645 id,
646 OUI_QCA,
647 QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_BSSID_HOTLIST);
648 if (gScanCommand == NULL) {
649 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
650 return WIFI_ERROR_UNKNOWN;
651 }
652
653 /* Create the NL message. */
654 ret = gScanCommand->create();
655 if (ret < 0)
656 goto cleanup;
657
658 /* Set the interface Id of the message. */
659 ret = gScanCommand->set_iface_id(ifaceInfo->name);
660 if (ret < 0)
661 goto cleanup;
662
663 /* Add the vendor specific attributes for the NL command. */
664 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
665 if (!nlData)
666 goto cleanup;
667
668 numAp = (unsigned int)params.num_bssid > MAX_HOTLIST_APS ?
669 MAX_HOTLIST_APS : params.num_bssid;
670 if (gScanCommand->put_u32(
671 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
672 id) ||
673 gScanCommand->put_u32(
674 QCA_WLAN_VENDOR_ATTR_GSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE,
675 params.lost_ap_sample_size) ||
676 gScanCommand->put_u32(
677 QCA_WLAN_VENDOR_ATTR_GSCAN_BSSID_HOTLIST_PARAMS_NUM_AP,
678 numAp))
679 {
680 goto cleanup;
681 }
682
683 ALOGI("%s: lost_ap_sample_size:%d numAp:%d", __FUNCTION__,
684 params.lost_ap_sample_size, numAp);
685 /* Add the vendor specific attributes for the NL command. */
686 nlApThresholdParamList =
687 gScanCommand->attr_start(
688 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM);
689 if (!nlApThresholdParamList)
690 goto cleanup;
691
692 /* Add nested NL attributes for AP Threshold Param. */
693 for (i = 0; i < numAp; i++) {
694 ap_threshold_param apThreshold = params.ap[i];
695 struct nlattr *nlApThresholdParam = gScanCommand->attr_start(i);
696 if (!nlApThresholdParam)
697 goto cleanup;
698 if (gScanCommand->put_addr(
699 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_BSSID,
700 apThreshold.bssid) ||
701 gScanCommand->put_s32(
702 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_LOW,
703 apThreshold.low) ||
704 gScanCommand->put_s32(
705 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH,
706 apThreshold.high))
707 {
708 goto cleanup;
709 }
710 ALOGI("%s: Index:%d BssId: %hhx:%hhx:%hhx:%hhx:%hhx:%hhx "
711 "Threshold low:%d high:%d", __FUNCTION__, i,
712 apThreshold.bssid[0], apThreshold.bssid[1],
713 apThreshold.bssid[2], apThreshold.bssid[3],
714 apThreshold.bssid[4], apThreshold.bssid[5],
715 apThreshold.low, apThreshold.high);
716 gScanCommand->attr_end(nlApThresholdParam);
717 }
718
719 gScanCommand->attr_end(nlApThresholdParamList);
720
721 gScanCommand->attr_end(nlData);
722
723 GScanCallbackHandler callbackHandler;
724 memset(&callbackHandler, 0, sizeof(callbackHandler));
725 callbackHandler.on_hotlist_ap_found = handler.on_hotlist_ap_found;
726 callbackHandler.on_hotlist_ap_lost = handler.on_hotlist_ap_lost;
727
728 /* Create an object of the event handler class to take care of the
729 * asychronous events on the north-bound.
730 */
731 if (gScanSetBssidHotlistCmdEventHandler == NULL) {
732 gScanSetBssidHotlistCmdEventHandler = new GScanCommandEventHandler(
733 wifiHandle,
734 id,
735 OUI_QCA,
736 QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_BSSID_HOTLIST,
737 callbackHandler);
738 if (gScanSetBssidHotlistCmdEventHandler == NULL) {
739 ALOGE("%s: Error instantiating "
740 "gScanSetBssidHotlistCmdEventHandler.", __FUNCTION__);
741 ret = WIFI_ERROR_UNKNOWN;
742 goto cleanup;
743 }
744 event_handlers->gScanSetBssidHotlistCmdEventHandler =
745 gScanSetBssidHotlistCmdEventHandler;
746 ALOGD("%s: Handler object was created for HOTLIST_AP_FOUND.", __FUNCTION__);
747 } else {
748 gScanSetBssidHotlistCmdEventHandler->setCallbackHandler(callbackHandler);
749 }
750
751 ret = gScanCommand->requestResponse();
752 if (ret != 0) {
753 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
754 goto cleanup;
755 }
756
757 if (gScanSetBssidHotlistCmdEventHandler != NULL) {
758 gScanSetBssidHotlistCmdEventHandler->set_request_id(id);
759 gScanSetBssidHotlistCmdEventHandler->enableEventHandling();
760 }
761
762 cleanup:
763 delete gScanCommand;
764 /* Disable Event Handling if ret != 0 */
765 if (ret && gScanSetBssidHotlistCmdEventHandler) {
766 ALOGI("%s: Error ret:%d, disable event handling",
767 __FUNCTION__, ret);
768 gScanSetBssidHotlistCmdEventHandler->disableEventHandling();
769 }
770 return (wifi_error)ret;
771 }
772
wifi_reset_bssid_hotlist(wifi_request_id id,wifi_interface_handle iface)773 wifi_error wifi_reset_bssid_hotlist(wifi_request_id id,
774 wifi_interface_handle iface)
775 {
776 int ret = 0;
777 GScanCommand *gScanCommand;
778 struct nlattr *nlData;
779 interface_info *ifaceInfo = getIfaceInfo(iface);
780 wifi_handle wifiHandle = getWifiHandle(iface);
781 hal_info *info = getHalInfo(wifiHandle);
782 lowi_cb_table_t *lowiWifiHalApi = NULL;
783 gscan_event_handlers* event_handlers;
784 GScanCommandEventHandler *gScanSetBssidHotlistCmdEventHandler;
785
786 event_handlers = (gscan_event_handlers*)info->gscan_handlers;
787 gScanSetBssidHotlistCmdEventHandler =
788 event_handlers->gScanSetBssidHotlistCmdEventHandler;
789
790 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
791 ALOGE("%s: GSCAN is not supported by driver",
792 __FUNCTION__);
793 return WIFI_ERROR_NOT_SUPPORTED;
794 }
795
796 /* Route request through LOWI if supported*/
797 lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED);
798 if (lowiWifiHalApi == NULL ||
799 lowiWifiHalApi->reset_bssid_hotlist == NULL) {
800 ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
801 } else {
802 ret = lowiWifiHalApi->reset_bssid_hotlist(id, iface);
803 ALOGI("%s: lowi reset_bssid_hotlist "
804 "returned: %d. Exit.", __FUNCTION__, ret);
805 return (wifi_error)ret;
806 }
807
808 ALOGI("%s: RequestId:%d", __FUNCTION__, id);
809
810 if (gScanSetBssidHotlistCmdEventHandler == NULL ||
811 (gScanSetBssidHotlistCmdEventHandler->isEventHandlingEnabled() ==
812 false)) {
813 ALOGE("wifi_reset_bssid_hotlist: GSCAN bssid_hotlist isn't set. "
814 "Nothing to do. Exit");
815 return WIFI_ERROR_NOT_AVAILABLE;
816 }
817
818 gScanCommand = new GScanCommand(
819 wifiHandle,
820 id,
821 OUI_QCA,
822 QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_BSSID_HOTLIST);
823
824 if (gScanCommand == NULL) {
825 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
826 return WIFI_ERROR_UNKNOWN;
827 }
828
829 /* Create the NL message. */
830 ret = gScanCommand->create();
831 if (ret < 0)
832 goto cleanup;
833
834 /* Set the interface Id of the message. */
835 ret = gScanCommand->set_iface_id(ifaceInfo->name);
836 if (ret < 0)
837 goto cleanup;
838
839 /* Add the vendor specific attributes for the NL command. */
840 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
841 if (!nlData)
842 goto cleanup;
843
844 ret = gScanCommand->put_u32(
845 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, id);
846 if (ret < 0)
847 goto cleanup;
848
849 gScanCommand->attr_end(nlData);
850
851 ret = gScanCommand->requestResponse();
852 if (ret != 0) {
853 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
854 }
855
856 /* Disable Event Handling. */
857 if (gScanSetBssidHotlistCmdEventHandler) {
858 gScanSetBssidHotlistCmdEventHandler->disableEventHandling();
859 }
860
861 cleanup:
862 delete gScanCommand;
863 return (wifi_error)ret;
864 }
865
866 /* 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)867 wifi_error wifi_set_significant_change_handler(wifi_request_id id,
868 wifi_interface_handle iface,
869 wifi_significant_change_params params,
870 wifi_significant_change_handler handler)
871 {
872 int i, numAp, ret = 0;
873 GScanCommand *gScanCommand;
874 struct nlattr *nlData, *nlApThresholdParamList;
875 interface_info *ifaceInfo = getIfaceInfo(iface);
876 wifi_handle wifiHandle = getWifiHandle(iface);
877 bool previousGScanSetSigChangeRunning = false;
878 hal_info *info = getHalInfo(wifiHandle);
879 lowi_cb_table_t *lowiWifiHalApi = NULL;
880 gscan_event_handlers* event_handlers;
881 GScanCommandEventHandler *gScanSetSignificantChangeCmdEventHandler;
882
883 event_handlers = (gscan_event_handlers*)info->gscan_handlers;
884 gScanSetSignificantChangeCmdEventHandler =
885 event_handlers->gScanSetSignificantChangeCmdEventHandler;
886
887 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
888 ALOGE("%s: GSCAN is not supported by driver",
889 __FUNCTION__);
890 return WIFI_ERROR_NOT_SUPPORTED;
891 }
892
893 /* Route request through LOWI if supported*/
894 lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED);
895 if (lowiWifiHalApi == NULL ||
896 lowiWifiHalApi->set_significant_change_handler == NULL) {
897 ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
898 } else {
899 ret = lowiWifiHalApi->set_significant_change_handler(id,
900 iface,
901 params,
902 handler);
903 ALOGI("%s: lowi set_significant_change_handler "
904 "returned: %d. Exit.", __FUNCTION__, ret);
905 return (wifi_error)ret;
906 }
907
908 ALOGI("%s: RequestId:%d", __FUNCTION__, id);
909
910 /* Wi-Fi HAL doesn't need to check if a similar request to set significant
911 * change list was made earlier. If set_significant_change() is called while
912 * another one is running, the request will be sent down to driver and
913 * firmware. If the new request is successfully honored, then Wi-Fi HAL
914 * will use the new request id for the gScanSetSignificantChangeCmdEventHandler
915 * object.
916 */
917
918 gScanCommand = new GScanCommand(
919 wifiHandle,
920 id,
921 OUI_QCA,
922 QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SIGNIFICANT_CHANGE);
923 if (gScanCommand == NULL) {
924 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
925 return WIFI_ERROR_UNKNOWN;
926 }
927
928 /* Create the NL message. */
929 ret = gScanCommand->create();
930 if (ret < 0)
931 goto cleanup;
932
933 /* Set the interface Id of the message. */
934 ret = gScanCommand->set_iface_id(ifaceInfo->name);
935 if (ret < 0)
936 goto cleanup;
937
938 /* Add the vendor specific attributes for the NL command. */
939 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
940 if (!nlData)
941 goto cleanup;
942
943 numAp = (unsigned int)params.num_bssid > MAX_SIGNIFICANT_CHANGE_APS ?
944 MAX_SIGNIFICANT_CHANGE_APS : params.num_bssid;
945
946 if (gScanCommand->put_u32(
947 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
948 id) ||
949 gScanCommand->put_u32(
950 QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE,
951 params.rssi_sample_size) ||
952 gScanCommand->put_u32(
953 QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE,
954 params.lost_ap_sample_size) ||
955 gScanCommand->put_u32(
956 QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING,
957 params.min_breaching) ||
958 gScanCommand->put_u32(
959 QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP,
960 numAp))
961 {
962 goto cleanup;
963 }
964
965 ALOGI("%s: Number of AP params:%d Rssi_sample_size:%d "
966 "lost_ap_sample_size:%d min_breaching:%d", __FUNCTION__,
967 numAp, params.rssi_sample_size, params.lost_ap_sample_size,
968 params.min_breaching);
969
970 /* Add the vendor specific attributes for the NL command. */
971 nlApThresholdParamList =
972 gScanCommand->attr_start(
973 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM);
974 if (!nlApThresholdParamList)
975 goto cleanup;
976
977 /* Add nested NL attributes for AP Threshold Param list. */
978 for (i = 0; i < numAp; i++) {
979 ap_threshold_param apThreshold = params.ap[i];
980 struct nlattr *nlApThresholdParam = gScanCommand->attr_start(i);
981 if (!nlApThresholdParam)
982 goto cleanup;
983 if ( gScanCommand->put_addr(
984 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_BSSID,
985 apThreshold.bssid) ||
986 gScanCommand->put_s32(
987 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_LOW,
988 apThreshold.low) ||
989 gScanCommand->put_s32(
990 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH,
991 apThreshold.high))
992 {
993 goto cleanup;
994 }
995 ALOGI("%s: ap[%d].bssid:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx "
996 "ap[%d].low:%d ap[%d].high:%d", __FUNCTION__,
997 i,
998 apThreshold.bssid[0], apThreshold.bssid[1],
999 apThreshold.bssid[2], apThreshold.bssid[3],
1000 apThreshold.bssid[4], apThreshold.bssid[5],
1001 i, apThreshold.low, i, apThreshold.high);
1002 gScanCommand->attr_end(nlApThresholdParam);
1003 }
1004
1005 gScanCommand->attr_end(nlApThresholdParamList);
1006
1007 gScanCommand->attr_end(nlData);
1008
1009 GScanCallbackHandler callbackHandler;
1010 memset(&callbackHandler, 0, sizeof(callbackHandler));
1011 callbackHandler.on_significant_change = handler.on_significant_change;
1012
1013 /* Create an object of the event handler class to take care of the
1014 * asychronous events on the north-bound.
1015 */
1016 if (gScanSetSignificantChangeCmdEventHandler == NULL) {
1017 gScanSetSignificantChangeCmdEventHandler =
1018 new GScanCommandEventHandler(
1019 wifiHandle,
1020 id,
1021 OUI_QCA,
1022 QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SIGNIFICANT_CHANGE,
1023 callbackHandler);
1024 if (gScanSetSignificantChangeCmdEventHandler == NULL) {
1025 ALOGE("%s: Error in instantiating, "
1026 "gScanSetSignificantChangeCmdEventHandler.",
1027 __FUNCTION__);
1028 ret = WIFI_ERROR_UNKNOWN;
1029 goto cleanup;
1030 }
1031 event_handlers->gScanSetSignificantChangeCmdEventHandler =
1032 gScanSetSignificantChangeCmdEventHandler;
1033 ALOGD("%s: Event handler object was created for SIGNIFICANT_CHANGE.",
1034 __FUNCTION__);
1035 } else {
1036 gScanSetSignificantChangeCmdEventHandler->setCallbackHandler(callbackHandler);
1037 }
1038
1039 ret = gScanCommand->requestResponse();
1040 if (ret != 0) {
1041 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
1042 goto cleanup;
1043 }
1044
1045 if (gScanSetSignificantChangeCmdEventHandler != NULL) {
1046 gScanSetSignificantChangeCmdEventHandler->set_request_id(id);
1047 gScanSetSignificantChangeCmdEventHandler->enableEventHandling();
1048 }
1049
1050 cleanup:
1051 /* Disable Event Handling if ret != 0 */
1052 if (ret && gScanSetSignificantChangeCmdEventHandler) {
1053 ALOGI("%s: Error ret:%d, disable event handling",
1054 __FUNCTION__, ret);
1055 gScanSetSignificantChangeCmdEventHandler->disableEventHandling();
1056 }
1057 delete gScanCommand;
1058 return (wifi_error)ret;
1059 }
1060
1061 /* Clear the GSCAN Significant AP change list. */
wifi_reset_significant_change_handler(wifi_request_id id,wifi_interface_handle iface)1062 wifi_error wifi_reset_significant_change_handler(wifi_request_id id,
1063 wifi_interface_handle iface)
1064 {
1065 int ret = 0;
1066 GScanCommand *gScanCommand;
1067 struct nlattr *nlData;
1068 interface_info *ifaceInfo = getIfaceInfo(iface);
1069 wifi_handle wifiHandle = getWifiHandle(iface);
1070 hal_info *info = getHalInfo(wifiHandle);
1071 lowi_cb_table_t *lowiWifiHalApi = NULL;
1072 gscan_event_handlers* event_handlers;
1073 GScanCommandEventHandler *gScanSetSignificantChangeCmdEventHandler;
1074
1075 event_handlers = (gscan_event_handlers*)info->gscan_handlers;
1076 gScanSetSignificantChangeCmdEventHandler =
1077 event_handlers->gScanSetSignificantChangeCmdEventHandler;
1078
1079 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
1080 ALOGE("%s: GSCAN is not supported by driver",
1081 __FUNCTION__);
1082 return WIFI_ERROR_NOT_SUPPORTED;
1083 }
1084
1085 /* Route request through LOWI if supported*/
1086 lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED);
1087 if (lowiWifiHalApi == NULL ||
1088 lowiWifiHalApi->reset_significant_change_handler == NULL) {
1089 ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
1090 } else {
1091 ret = lowiWifiHalApi->reset_significant_change_handler(id, iface);
1092 ALOGI("%s: lowi reset_significant_change_handler "
1093 "returned: %d. Exit.", __FUNCTION__, ret);
1094 return (wifi_error)ret;
1095 }
1096
1097 ALOGI("%s: RequestId:%d", __FUNCTION__, id);
1098
1099 if (gScanSetSignificantChangeCmdEventHandler == NULL ||
1100 (gScanSetSignificantChangeCmdEventHandler->isEventHandlingEnabled() ==
1101 false)) {
1102 ALOGE("wifi_reset_significant_change_handler: GSCAN significant_change"
1103 " isn't set. Nothing to do. Exit");
1104 return WIFI_ERROR_NOT_AVAILABLE;
1105 }
1106
1107 gScanCommand =
1108 new GScanCommand
1109 (
1110 wifiHandle,
1111 id,
1112 OUI_QCA,
1113 QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_SIGNIFICANT_CHANGE);
1114 if (gScanCommand == NULL) {
1115 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
1116 return WIFI_ERROR_UNKNOWN;
1117 }
1118
1119 /* Create the NL message. */
1120 ret = gScanCommand->create();
1121 if (ret < 0)
1122 goto cleanup;
1123
1124 /* Set the interface Id of the message. */
1125 ret = gScanCommand->set_iface_id(ifaceInfo->name);
1126 if (ret < 0)
1127 goto cleanup;
1128
1129 /* Add the vendor specific attributes for the NL command. */
1130 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1131 if (!nlData)
1132 goto cleanup;
1133
1134 ret = gScanCommand->put_u32(
1135 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
1136 id);
1137 if (ret < 0)
1138 goto cleanup;
1139
1140 gScanCommand->attr_end(nlData);
1141
1142 ret = gScanCommand->requestResponse();
1143 if (ret != 0) {
1144 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
1145 }
1146
1147 /* Disable Event Handling. */
1148 if (gScanSetSignificantChangeCmdEventHandler) {
1149 gScanSetSignificantChangeCmdEventHandler->disableEventHandling();
1150 }
1151
1152 cleanup:
1153 delete gScanCommand;
1154 return (wifi_error)ret;
1155 }
1156
1157 /* 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)1158 wifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface,
1159 byte flush, int max,
1160 wifi_cached_scan_results *results,
1161 int *num)
1162 {
1163 int requestId, ret = 0, retRequestRsp = 0;
1164 wifi_cached_scan_results *result = results;
1165 u32 j = 0;
1166 int i = 0;
1167 u8 moreData = 0;
1168 u16 waitTime = GSCAN_EVENT_WAIT_TIME_SECONDS;
1169 GScanCommand *gScanCommand;
1170 struct nlattr *nlData;
1171 wifi_cached_scan_results *cached_results;
1172 lowi_cb_table_t *lowiWifiHalApi = NULL;
1173
1174 interface_info *ifaceInfo = getIfaceInfo(iface);
1175 wifi_handle wifiHandle = getWifiHandle(iface);
1176 hal_info *info = getHalInfo(wifiHandle);
1177
1178 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
1179 ALOGE("%s: GSCAN is not supported by driver",
1180 __FUNCTION__);
1181 return WIFI_ERROR_NOT_SUPPORTED;
1182 }
1183
1184 /* Route GSCAN request through LOWI if supported */
1185 lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED);
1186 if (lowiWifiHalApi == NULL ||
1187 lowiWifiHalApi->get_cached_gscan_results == NULL) {
1188 ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
1189 } else {
1190 ret = lowiWifiHalApi->get_cached_gscan_results(iface,
1191 flush,
1192 max,
1193 results,
1194 num);
1195 ALOGI("%s: lowi get_cached_gscan_results"
1196 "returned: %d. Exit.", __FUNCTION__, ret);
1197 return (wifi_error)ret;
1198 }
1199
1200 /* No request id from caller, so generate one and pass it on to the driver. */
1201 /* Generate it randomly */
1202 requestId = get_requestid();
1203 ALOGI("%s: RequestId:%d", __FUNCTION__, requestId);
1204
1205 if (results == NULL || num == NULL) {
1206 ALOGE("%s: NULL pointer provided. Exit.",
1207 __FUNCTION__);
1208 return WIFI_ERROR_INVALID_ARGS;
1209 }
1210
1211 gScanCommand = new GScanCommand(
1212 wifiHandle,
1213 requestId,
1214 OUI_QCA,
1215 QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS);
1216 if (gScanCommand == NULL) {
1217 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
1218 return WIFI_ERROR_UNKNOWN;
1219 }
1220
1221 ret = gScanCommand->allocRspParams(eGScanGetCachedResultsRspParams);
1222 if (ret != 0) {
1223 ALOGE("%s: Failed to allocate memory for response struct. Error:%d",
1224 __FUNCTION__, ret);
1225 goto cleanup;
1226 }
1227
1228 ret = gScanCommand->allocCachedResultsTemp(max, results);
1229 if (ret != 0) {
1230 ALOGE("%s: Failed to allocate memory for temp gscan cached list. "
1231 "Error:%d", __FUNCTION__, ret);
1232 goto cleanup;
1233 }
1234
1235 /* Clear the destination cached results list before copying results. */
1236 memset(results, 0, max * sizeof(wifi_cached_scan_results));
1237
1238 /* Create the NL message. */
1239 ret = gScanCommand->create();
1240 if (ret < 0)
1241 goto cleanup;
1242
1243 /* Set the interface Id of the message. */
1244 ret = gScanCommand->set_iface_id(ifaceInfo->name);
1245 if (ret < 0)
1246 goto cleanup;
1247
1248 /* Add the vendor specific attributes for the NL command. */
1249 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1250 if (!nlData)
1251 goto cleanup;
1252
1253 if (ret < 0)
1254 goto cleanup;
1255
1256 if (gScanCommand->put_u32(
1257 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
1258 requestId) ||
1259 gScanCommand->put_u8(
1260 QCA_WLAN_VENDOR_ATTR_GSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH,
1261 flush) ||
1262 gScanCommand->put_u32(
1263 QCA_WLAN_VENDOR_ATTR_GSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX,
1264 max))
1265 {
1266 goto cleanup;
1267 }
1268
1269 ALOGI("%s: flush:%d max:%d", __FUNCTION__, flush, max);
1270 gScanCommand->attr_end(nlData);
1271
1272 retRequestRsp = gScanCommand->requestResponse();
1273 if (retRequestRsp != 0) {
1274 ALOGE("%s: requestResponse Error:%d",
1275 __FUNCTION__, retRequestRsp);
1276 if (retRequestRsp != -ETIMEDOUT) {
1277 /* Proceed to cleanup & return no results */
1278 goto cleanup;
1279 }
1280 }
1281
1282 /* No more data, copy the parsed results into the caller's results array */
1283 ret = gScanCommand->copyCachedScanResults(num, results);
1284 ALOGI("%s: max: %d, num:%d", __FUNCTION__, max, *num);
1285
1286 if (!ret) {
1287 /* If requestResponse returned a TIMEOUT */
1288 if (retRequestRsp == -ETIMEDOUT) {
1289 if (*num > 0) {
1290 /* Mark scan results as incomplete for the last scan_id */
1291 results[(*num)-1].flags = WIFI_SCAN_FLAG_INTERRUPTED;
1292 ALOGD("%s: Timeout happened. Mark scan results as incomplete "
1293 "for scan_id:%d", __FUNCTION__, results[(*num)-1].scan_id);
1294 ret = WIFI_SUCCESS;
1295 } else
1296 ret = WIFI_ERROR_TIMED_OUT;
1297 }
1298 }
1299 cleanup:
1300 gScanCommand->freeRspParams(eGScanGetCachedResultsRspParams);
1301 delete gScanCommand;
1302 return (wifi_error)ret;
1303 }
1304
1305 /* Random MAC OUI for PNO */
wifi_set_scanning_mac_oui(wifi_interface_handle handle,oui scan_oui)1306 wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui)
1307 {
1308 int ret = 0;
1309 struct nlattr *nlData;
1310 WifiVendorCommand *vCommand = NULL;
1311 interface_info *iinfo = getIfaceInfo(handle);
1312 wifi_handle wifiHandle = getWifiHandle(handle);
1313
1314 vCommand = new WifiVendorCommand(wifiHandle, 0,
1315 OUI_QCA,
1316 QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI);
1317 if (vCommand == NULL) {
1318 ALOGE("%s: Error vCommand NULL", __FUNCTION__);
1319 return WIFI_ERROR_OUT_OF_MEMORY;
1320 }
1321
1322 /* create the message */
1323 ret = vCommand->create();
1324 if (ret < 0)
1325 goto cleanup;
1326
1327 ret = vCommand->set_iface_id(iinfo->name);
1328 if (ret < 0)
1329 goto cleanup;
1330
1331 /* Add the vendor specific attributes for the NL command. */
1332 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1333 if (!nlData)
1334 goto cleanup;
1335
1336 ALOGI("%s: MAC_OUI - %02x:%02x:%02x", __FUNCTION__,
1337 scan_oui[0], scan_oui[1], scan_oui[2]);
1338
1339 /* Add the fixed part of the mac_oui to the nl command */
1340 ret = vCommand->put_bytes(
1341 QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI,
1342 (char *)scan_oui,
1343 WIFI_SCANNING_MAC_OUI_LENGTH);
1344 if (ret < 0)
1345 goto cleanup;
1346
1347 vCommand->attr_end(nlData);
1348
1349 ret = vCommand->requestResponse();
1350 if (ret != 0) {
1351 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
1352 goto cleanup;
1353 }
1354
1355 cleanup:
1356 delete vCommand;
1357 return (wifi_error)ret;
1358 }
1359
1360
1361 /* Set the GSCAN SSID Hotlist. */
wifi_set_ssid_hotlist(wifi_request_id id,wifi_interface_handle iface,wifi_ssid_hotlist_params params,wifi_hotlist_ssid_handler handler)1362 wifi_error wifi_set_ssid_hotlist(wifi_request_id id,
1363 wifi_interface_handle iface,
1364 wifi_ssid_hotlist_params params,
1365 wifi_hotlist_ssid_handler handler)
1366 {
1367 int i, numSsid, ret = 0;
1368 GScanCommand *gScanCommand;
1369 struct nlattr *nlData, *nlSsidThresholdParamList;
1370 interface_info *ifaceInfo = getIfaceInfo(iface);
1371 wifi_handle wifiHandle = getWifiHandle(iface);
1372 bool previousGScanSetSsidRunning = false;
1373 hal_info *info = getHalInfo(wifiHandle);
1374 lowi_cb_table_t *lowiWifiHalApi = NULL;
1375 gscan_event_handlers* event_handlers;
1376 GScanCommandEventHandler *gScanSetSsidHotlistCmdEventHandler;
1377
1378 event_handlers = (gscan_event_handlers*)info->gscan_handlers;
1379 gScanSetSsidHotlistCmdEventHandler =
1380 event_handlers->gScanSetSsidHotlistCmdEventHandler;
1381
1382 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
1383 ALOGE("%s: GSCAN is not supported by driver",
1384 __FUNCTION__);
1385 return WIFI_ERROR_NOT_SUPPORTED;
1386 }
1387
1388 /* Route request through LOWI if supported*/
1389 lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED);
1390 if (lowiWifiHalApi == NULL ||
1391 lowiWifiHalApi->set_ssid_hotlist == NULL) {
1392 ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
1393 } else {
1394 ret = lowiWifiHalApi->set_ssid_hotlist(id, iface, params,handler);
1395 ALOGI("%s: lowi set_ssid_hotlist "
1396 "returned: %d. Exit.", __FUNCTION__, ret);
1397 return (wifi_error)ret;
1398 }
1399
1400 ALOGI("%s: RequestId:%d", __FUNCTION__, id);
1401
1402 /* Wi-Fi HAL doesn't need to check if a similar request to set ssid
1403 * hotlist was made earlier. If set_ssid_hotlist() is called while
1404 * another one is running, the request will be sent down to driver and
1405 * firmware. If the new request is successfully honored, then Wi-Fi HAL
1406 * will use the new request id for the gScanSetSsidHotlistCmdEventHandler
1407 * object.
1408 */
1409
1410 gScanCommand =
1411 new GScanCommand(
1412 wifiHandle,
1413 id,
1414 OUI_QCA,
1415 QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SSID_HOTLIST);
1416 if (gScanCommand == NULL) {
1417 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
1418 return WIFI_ERROR_UNKNOWN;
1419 }
1420
1421 /* Create the NL message. */
1422 ret = gScanCommand->create();
1423 if (ret < 0)
1424 goto cleanup;
1425
1426 /* Set the interface Id of the message. */
1427 ret = gScanCommand->set_iface_id(ifaceInfo->name);
1428 if (ret < 0)
1429 goto cleanup;
1430
1431 /* Add the vendor specific attributes for the NL command. */
1432 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1433 if (!nlData)
1434 goto cleanup;
1435
1436 numSsid = (unsigned int)params.num_ssid > MAX_HOTLIST_SSID ?
1437 MAX_HOTLIST_SSID : params.num_ssid;
1438 if (gScanCommand->put_u32(
1439 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
1440 id) ||
1441 gScanCommand->put_u32(
1442 QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE,
1443 params.lost_ssid_sample_size) ||
1444 gScanCommand->put_u32(
1445 QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_HOTLIST_PARAMS_NUM_SSID,
1446 numSsid))
1447 {
1448 goto cleanup;
1449 }
1450 ALOGI("%s: numSsid:%d "
1451 "lost_ssid_sameple_size: %d",
1452 __FUNCTION__, numSsid,
1453 params.lost_ssid_sample_size);
1454
1455 /* Add the vendor specific attributes for the NL command. */
1456 nlSsidThresholdParamList =
1457 gScanCommand->attr_start(
1458 QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM);
1459 if (!nlSsidThresholdParamList)
1460 goto cleanup;
1461
1462 /* Add nested NL attributes for SSID Threshold Param. */
1463 for (i = 0; i < numSsid; i++) {
1464 ssid_threshold_param ssidThreshold = params.ssid[i];
1465 struct nlattr *nlSsidThresholdParam = gScanCommand->attr_start(i);
1466 if (!nlSsidThresholdParam)
1467 goto cleanup;
1468 if (gScanCommand->put_string(
1469 QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_SSID,
1470 ssidThreshold.ssid) ||
1471 gScanCommand->put_u8(
1472 QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_BAND,
1473 ssidThreshold.band) ||
1474 gScanCommand->put_s32(
1475 QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW,
1476 ssidThreshold.low) ||
1477 gScanCommand->put_s32(
1478 QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH,
1479 ssidThreshold.high))
1480 {
1481 goto cleanup;
1482 }
1483 ALOGI("%s: SSID[%d].ssid:%s "
1484 "SSID[%d].band:%d SSID[%d].low:%d "
1485 "SSID[%d].high:%d", __FUNCTION__,
1486 i, ssidThreshold.ssid,
1487 i, ssidThreshold.band,
1488 i, ssidThreshold.low,
1489 i, ssidThreshold.high);
1490 gScanCommand->attr_end(nlSsidThresholdParam);
1491 }
1492
1493 gScanCommand->attr_end(nlSsidThresholdParamList);
1494
1495 gScanCommand->attr_end(nlData);
1496
1497 GScanCallbackHandler callbackHandler;
1498 memset(&callbackHandler, 0, sizeof(callbackHandler));
1499 callbackHandler.on_hotlist_ssid_found = handler.on_hotlist_ssid_found;
1500 callbackHandler.on_hotlist_ssid_lost = handler.on_hotlist_ssid_lost;
1501
1502 /* Create an object of the event handler class to take care of the
1503 * asychronous events on the north-bound.
1504 */
1505 if (gScanSetSsidHotlistCmdEventHandler == NULL) {
1506 gScanSetSsidHotlistCmdEventHandler = new GScanCommandEventHandler(
1507 wifiHandle,
1508 id,
1509 OUI_QCA,
1510 QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SSID_HOTLIST,
1511 callbackHandler);
1512 if (gScanSetSsidHotlistCmdEventHandler == NULL) {
1513 ALOGE("%s: Error instantiating "
1514 "gScanSetSsidHotlistCmdEventHandler.", __FUNCTION__);
1515 ret = WIFI_ERROR_UNKNOWN;
1516 goto cleanup;
1517 }
1518 ALOGD("%s: Handler object was created for HOTLIST_AP_FOUND.", __FUNCTION__);
1519 event_handlers->gScanSetSsidHotlistCmdEventHandler =
1520 gScanSetSsidHotlistCmdEventHandler;
1521 } else {
1522 gScanSetSsidHotlistCmdEventHandler->setCallbackHandler(callbackHandler);
1523 }
1524
1525 ret = gScanCommand->requestResponse();
1526 if (ret != 0) {
1527 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
1528 goto cleanup;
1529 }
1530
1531 if (gScanSetSsidHotlistCmdEventHandler != NULL) {
1532 gScanSetSsidHotlistCmdEventHandler->set_request_id(id);
1533 gScanSetSsidHotlistCmdEventHandler->enableEventHandling();
1534 }
1535
1536 cleanup:
1537 delete gScanCommand;
1538 /* Disable Event Handling if ret != 0 */
1539 if (ret && gScanSetSsidHotlistCmdEventHandler) {
1540 ALOGI("%s: Error ret:%d, disable event handling",
1541 __FUNCTION__, ret);
1542 gScanSetSsidHotlistCmdEventHandler->disableEventHandling();
1543 }
1544 return (wifi_error)ret;
1545 }
1546
wifi_reset_ssid_hotlist(wifi_request_id id,wifi_interface_handle iface)1547 wifi_error wifi_reset_ssid_hotlist(wifi_request_id id,
1548 wifi_interface_handle iface)
1549 {
1550 int ret = 0;
1551 GScanCommand *gScanCommand;
1552 struct nlattr *nlData;
1553 interface_info *ifaceInfo = getIfaceInfo(iface);
1554 wifi_handle wifiHandle = getWifiHandle(iface);
1555 hal_info *info = getHalInfo(wifiHandle);
1556 lowi_cb_table_t *lowiWifiHalApi = NULL;
1557 gscan_event_handlers* event_handlers;
1558 GScanCommandEventHandler *gScanSetSsidHotlistCmdEventHandler;
1559
1560 event_handlers = (gscan_event_handlers*)info->gscan_handlers;
1561 gScanSetSsidHotlistCmdEventHandler =
1562 event_handlers->gScanSetSsidHotlistCmdEventHandler;
1563
1564 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
1565 ALOGE("%s: GSCAN is not supported by driver",
1566 __FUNCTION__);
1567 return WIFI_ERROR_NOT_SUPPORTED;
1568 }
1569
1570 /* Route request through LOWI if supported*/
1571 lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED);
1572 if (lowiWifiHalApi == NULL ||
1573 lowiWifiHalApi->reset_ssid_hotlist == NULL) {
1574 ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
1575 } else {
1576 ret = lowiWifiHalApi->reset_ssid_hotlist(id, iface);
1577 ALOGI("%s: lowi reset_ssid_hotlist "
1578 "returned: %d. Exit.", __FUNCTION__, ret);
1579 return (wifi_error)ret;
1580 }
1581
1582 ALOGI("%s: RequestId:%d", __FUNCTION__, id);
1583
1584 if (gScanSetSsidHotlistCmdEventHandler == NULL ||
1585 (gScanSetSsidHotlistCmdEventHandler->isEventHandlingEnabled() ==
1586 false)) {
1587 ALOGE("wifi_reset_ssid_hotlist: GSCAN ssid_hotlist isn't set. "
1588 "Nothing to do. Exit");
1589 return WIFI_ERROR_NOT_AVAILABLE;
1590 }
1591
1592 gScanCommand = new GScanCommand(
1593 wifiHandle,
1594 id,
1595 OUI_QCA,
1596 QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_SSID_HOTLIST);
1597
1598 if (gScanCommand == NULL) {
1599 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
1600 return WIFI_ERROR_UNKNOWN;
1601 }
1602
1603 /* Create the NL message. */
1604 ret = gScanCommand->create();
1605 if (ret < 0)
1606 goto cleanup;
1607
1608 /* Set the interface Id of the message. */
1609 ret = gScanCommand->set_iface_id(ifaceInfo->name);
1610 if (ret < 0)
1611 goto cleanup;
1612
1613 /* Add the vendor specific attributes for the NL command. */
1614 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1615 if (!nlData)
1616 goto cleanup;
1617
1618 ret = gScanCommand->put_u32(
1619 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, id);
1620 if (ret < 0)
1621 goto cleanup;
1622
1623 gScanCommand->attr_end(nlData);
1624
1625 ret = gScanCommand->requestResponse();
1626 if (ret != 0) {
1627 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
1628 }
1629
1630 /* Disable Event Handling. */
1631 if (gScanSetSsidHotlistCmdEventHandler) {
1632 gScanSetSsidHotlistCmdEventHandler->disableEventHandling();
1633 }
1634
1635 cleanup:
1636 delete gScanCommand;
1637 return (wifi_error)ret;
1638 }
1639
1640
GScanCommand(wifi_handle handle,int id,u32 vendor_id,u32 subcmd)1641 GScanCommand::GScanCommand(wifi_handle handle, int id, u32 vendor_id,
1642 u32 subcmd)
1643 : WifiVendorCommand(handle, id, vendor_id, subcmd)
1644 {
1645 #ifdef QC_HAL_DEBUG
1646 ALOGD("GScanCommand %p constructed", this);
1647 #endif
1648 /* Initialize the member data variables here */
1649 mGetCapabilitiesRspParams = NULL;
1650 mGetCachedResultsRspParams = NULL;
1651 mChannels = NULL;
1652 mMaxChannels = 0;
1653 mNumChannelsPtr = NULL;
1654
1655 mRequestId = id;
1656 memset(&mHandler, 0,sizeof(mHandler));
1657 }
1658
~GScanCommand()1659 GScanCommand::~GScanCommand()
1660 {
1661 #ifdef QC_HAL_DEBUG
1662 ALOGD("GScanCommand %p destructor", this);
1663 #endif
1664 unregisterVendorHandler(mVendor_id, mSubcmd);
1665 }
1666
1667
1668 /* This function implements creation of Vendor command */
create()1669 int GScanCommand::create() {
1670 int ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
1671 if (ret < 0) {
1672 return ret;
1673 }
1674
1675 /* Insert the oui in the msg */
1676 ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
1677 if (ret < 0)
1678 goto out;
1679 /* Insert the subcmd in the msg */
1680 ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
1681 if (ret < 0)
1682 goto out;
1683
1684 #ifdef QC_HAL_DEBUG
1685 ALOGI("%s: mVendor_id = %d, Subcmd = %d.",
1686 __FUNCTION__, mVendor_id, mSubcmd);
1687 #endif
1688
1689 out:
1690 return ret;
1691 }
1692
1693 /* Callback handlers registered for nl message send */
error_handler_gscan(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)1694 static int error_handler_gscan(struct sockaddr_nl *nla, struct nlmsgerr *err,
1695 void *arg)
1696 {
1697 struct sockaddr_nl *tmp;
1698 int *ret = (int *)arg;
1699 tmp = nla;
1700 *ret = err->error;
1701 ALOGE("%s: Error code:%d (%s)", __FUNCTION__, *ret, strerror(-(*ret)));
1702 return NL_STOP;
1703 }
1704
1705 /* Callback handlers registered for nl message send */
ack_handler_gscan(struct nl_msg * msg,void * arg)1706 static int ack_handler_gscan(struct nl_msg *msg, void *arg)
1707 {
1708 int *ret = (int *)arg;
1709 struct nl_msg * a;
1710
1711 ALOGE("%s: called", __FUNCTION__);
1712 a = msg;
1713 *ret = 0;
1714 return NL_STOP;
1715 }
1716
1717 /* Callback handlers registered for nl message send */
finish_handler_gscan(struct nl_msg * msg,void * arg)1718 static int finish_handler_gscan(struct nl_msg *msg, void *arg)
1719 {
1720 int *ret = (int *)arg;
1721 struct nl_msg * a;
1722
1723 ALOGE("%s: called", __FUNCTION__);
1724 a = msg;
1725 *ret = 0;
1726 return NL_SKIP;
1727 }
1728
requestResponse()1729 int GScanCommand::requestResponse()
1730 {
1731 return WifiCommand::requestResponse(mMsg);
1732 }
1733
handleResponse(WifiEvent & reply)1734 int GScanCommand::handleResponse(WifiEvent &reply) {
1735 u32 status;
1736 int i = 0;
1737 int ret = WIFI_SUCCESS;
1738 u32 val;
1739
1740 WifiVendorCommand::handleResponse(reply);
1741
1742 struct nlattr *tbVendor[
1743 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
1744 nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
1745 (struct nlattr *)mVendorData,mDataLen, NULL);
1746
1747 switch(mSubcmd)
1748 {
1749 case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_VALID_CHANNELS:
1750 {
1751 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_CHANNELS]) {
1752 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_CHANNELS"
1753 " not found", __FUNCTION__);
1754 ret = WIFI_ERROR_INVALID_ARGS;
1755 break;
1756 }
1757 val = nla_get_u32(tbVendor[
1758 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_CHANNELS]);
1759
1760 val = val > (unsigned int)mMaxChannels ?
1761 (unsigned int)mMaxChannels : val;
1762 *mNumChannelsPtr = val;
1763
1764 /* Extract the list of channels. */
1765 if (*mNumChannelsPtr > 0 ) {
1766 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CHANNELS]) {
1767 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CHANNELS"
1768 " not found", __FUNCTION__);
1769 ret = WIFI_ERROR_INVALID_ARGS;
1770 break;
1771 }
1772 nla_memcpy(mChannels,
1773 tbVendor[
1774 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CHANNELS],
1775 sizeof(wifi_channel) * (*mNumChannelsPtr));
1776 }
1777
1778 ALOGD("%s: Get valid channels response received.",
1779 __FUNCTION__);
1780 ALOGD("%s: Num channels : %d",
1781 __FUNCTION__, *mNumChannelsPtr);
1782 ALOGD("%s: List of valid channels are: ", __FUNCTION__);
1783 for(i = 0; i < *mNumChannelsPtr; i++)
1784 {
1785 ALOGD("%u", *(mChannels + i));
1786 }
1787 }
1788 break;
1789 case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES:
1790 {
1791 ret = gscan_parse_capabilities(tbVendor);
1792 if (ret) {
1793 break;
1794 }
1795
1796 if (mGetCapabilitiesRspParams) {
1797 wifi_gscan_capabilities capa =
1798 mGetCapabilitiesRspParams->capabilities;
1799 ALOGI("%s: max_ap_cache_per_scan:%d\n"
1800 "max_bssid_history_entries:%d\n"
1801 "max_hotlist_bssids:%d\n"
1802 "max_hotlist_ssids:%d\n"
1803 "max_rssi_sample_size:%d\n"
1804 "max_scan_buckets:%d\n"
1805 "max_scan_cache_size:%d\n"
1806 "max_scan_reporting_threshold:%d\n"
1807 "max_significant_wifi_change_aps:%d\n"
1808 "max_number_epno_networks:%d\n"
1809 "max_number_epno_networks_by_ssid:%d\n"
1810 "max_number_of_white_listed_ssid:%d.",
1811 __FUNCTION__, capa.max_ap_cache_per_scan,
1812 capa.max_bssid_history_entries,
1813 capa.max_hotlist_bssids,
1814 capa.max_hotlist_ssids,
1815 capa.max_rssi_sample_size,
1816 capa.max_scan_buckets,
1817 capa.max_scan_cache_size,
1818 capa.max_scan_reporting_threshold,
1819 capa.max_significant_wifi_change_aps,
1820 capa.max_number_epno_networks,
1821 capa.max_number_epno_networks_by_ssid,
1822 capa.max_number_of_white_listed_ssid);
1823 }
1824 }
1825 break;
1826 case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS:
1827 {
1828 wifi_request_id id;
1829 u32 numResults = 0;
1830 u32 startingIndex;
1831 int firstScanIdInPatch = -1;
1832
1833 if (!tbVendor[
1834 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]) {
1835 ALOGE("%s: GSCAN_RESULTS_REQUEST_ID not"
1836 "found", __FUNCTION__);
1837 ret = WIFI_ERROR_INVALID_ARGS;
1838 break;
1839 }
1840 id = nla_get_u32(
1841 tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]
1842 );
1843 /* If this is not for us, just ignore it. */
1844 if (id != mRequestId) {
1845 ALOGE("%s: Event has Req. ID:%d <> ours:%d",
1846 __FUNCTION__, id, mRequestId);
1847 break;
1848 }
1849 if (!tbVendor[
1850 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]) {
1851 ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not"
1852 "found", __FUNCTION__);
1853 ret = WIFI_ERROR_INVALID_ARGS;
1854 break;
1855 }
1856 /* Read num of cached scan results in this data chunk. Note that
1857 * this value doesn't represent the number of unique gscan scan Ids
1858 * since the first scan id in this new chunk could be similar to
1859 * the last scan id in the previous chunk.
1860 */
1861 numResults = nla_get_u32(tbVendor[
1862 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]);
1863 ALOGE("%s: num Cached results in this fragment:%d",
1864 __FUNCTION__, numResults);
1865
1866 if (!mGetCachedResultsRspParams) {
1867 ALOGE("%s: mGetCachedResultsRspParams is NULL, exit.",
1868 __FUNCTION__);
1869 ret = WIFI_ERROR_INVALID_ARGS;
1870 break;
1871 }
1872
1873 /* To support fragmentation from firmware, monitor the
1874 * MORE_DATA flag and cache results until MORE_DATA = 0.
1875 */
1876 if (!tbVendor[
1877 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]) {
1878 ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_MORE_DATA "
1879 "not found", __FUNCTION__);
1880 ret = WIFI_ERROR_INVALID_ARGS;
1881 break;
1882 } else {
1883 mGetCachedResultsRspParams->more_data = nla_get_u8(
1884 tbVendor[
1885 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]);
1886 }
1887
1888 /* No data in this chunk so skip this chunk */
1889 if (numResults == 0) {
1890 return NL_SKIP;
1891 }
1892
1893 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID]) {
1894 ALOGE("GSCAN_CACHED_RESULTS_SCAN_ID not found");
1895 ret = WIFI_ERROR_INVALID_ARGS;
1896 break;
1897 }
1898
1899 /* Get the first Scan-Id in this chuck of cached results. */
1900 firstScanIdInPatch = nla_get_u32(tbVendor[
1901 QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID]);
1902
1903 ALOGE("More data: %d, firstScanIdInPatch: %d, lastProcessedScanId: %d",
1904 mGetCachedResultsRspParams->more_data, firstScanIdInPatch,
1905 mGetCachedResultsRspParams->lastProcessedScanId);
1906
1907 if (numResults) {
1908 if (firstScanIdInPatch !=
1909 mGetCachedResultsRspParams->lastProcessedScanId) {
1910 /* New result scan Id block, update the starting index. */
1911 mGetCachedResultsRspParams->cachedResultsStartingIndex++;
1912 }
1913
1914 ret = gscan_get_cached_results(
1915 mGetCachedResultsRspParams->cached_results,
1916 tbVendor);
1917 /* If a parsing error occurred, exit and proceed for cleanup. */
1918 if (ret)
1919 break;
1920 }
1921 }
1922 break;
1923 default:
1924 /* Error case should not happen print log */
1925 ALOGE("%s: Wrong GScan subcmd response received %d",
1926 __FUNCTION__, mSubcmd);
1927 }
1928
1929 /* A parsing error occurred, do the cleanup of gscan result lists. */
1930 if (ret) {
1931 switch(mSubcmd)
1932 {
1933 case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS:
1934 {
1935 ALOGE("%s: Parsing error, free CachedResultsRspParams",
1936 __FUNCTION__);
1937 freeRspParams(eGScanGetCachedResultsRspParams);
1938 }
1939 break;
1940 case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES:
1941 {
1942 ALOGE("%s: Parsing error, free CapabilitiesRspParams",
1943 __FUNCTION__);
1944 freeRspParams(eGScanGetCapabilitiesRspParams);
1945 }
1946 break;
1947 default:
1948 ALOGE("%s: Wrong GScan subcmd received %d", __FUNCTION__, mSubcmd);
1949 }
1950 }
1951 return NL_SKIP;
1952 }
1953
1954 /* Parses and extracts gscan capabilities results. */
gscan_parse_capabilities(struct nlattr ** tbVendor)1955 int GScanCommand::gscan_parse_capabilities(struct nlattr **tbVendor)
1956 {
1957 if (!mGetCapabilitiesRspParams){
1958 ALOGE("%s: mGetCapabilitiesRspParams ptr is NULL. Exit.",
1959 __FUNCTION__);
1960 return WIFI_ERROR_INVALID_ARGS;
1961 }
1962
1963 if (!tbVendor[
1964 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE
1965 ]) {
1966 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_"
1967 "CAPABILITIES_MAX_SCAN_CACHE_SIZE not found", __FUNCTION__);
1968 return WIFI_ERROR_INVALID_ARGS;
1969 }
1970 mGetCapabilitiesRspParams->capabilities.max_scan_cache_size =
1971 nla_get_u32(tbVendor[
1972 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE]);
1973
1974 if (!tbVendor[
1975 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS
1976 ]) {
1977 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
1978 "_SCAN_BUCKETS not found", __FUNCTION__);
1979 return WIFI_ERROR_INVALID_ARGS;
1980 }
1981 mGetCapabilitiesRspParams->capabilities.max_scan_buckets =
1982 nla_get_u32(tbVendor[
1983 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS]
1984 );
1985
1986 if (!tbVendor[
1987 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN
1988 ]) {
1989 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
1990 "_AP_CACHE_PER_SCAN not found", __FUNCTION__);
1991 return WIFI_ERROR_INVALID_ARGS;
1992 }
1993 mGetCapabilitiesRspParams->capabilities.max_ap_cache_per_scan =
1994 nla_get_u32(tbVendor[
1995 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN]);
1996
1997 if (!tbVendor[
1998 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE
1999 ]) {
2000 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
2001 "_RSSI_SAMPLE_SIZE not found", __FUNCTION__);
2002 return WIFI_ERROR_INVALID_ARGS;
2003 }
2004 mGetCapabilitiesRspParams->capabilities.max_rssi_sample_size =
2005 nla_get_u32(tbVendor[
2006 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE]);
2007
2008 if (!tbVendor[
2009 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD
2010 ]) {
2011 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_"
2012 "MAX_SCAN_REPORTING_THRESHOLD not found", __FUNCTION__);
2013 return WIFI_ERROR_INVALID_ARGS;
2014 }
2015 mGetCapabilitiesRspParams->capabilities.max_scan_reporting_threshold =
2016 nla_get_u32(tbVendor[
2017 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD
2018 ]);
2019
2020 if (!tbVendor[
2021 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS
2022 ]) {
2023 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_"
2024 "MAX_HOTLIST_BSSIDS not found", __FUNCTION__);
2025 return WIFI_ERROR_INVALID_ARGS;
2026 }
2027 mGetCapabilitiesRspParams->capabilities.max_hotlist_bssids =
2028 nla_get_u32(tbVendor[
2029 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS]);
2030
2031 if (!tbVendor[
2032 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS
2033 ]) {
2034 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
2035 "_SIGNIFICANT_WIFI_CHANGE_APS not found", __FUNCTION__);
2036 return WIFI_ERROR_INVALID_ARGS;
2037 }
2038 mGetCapabilitiesRspParams->capabilities.max_significant_wifi_change_aps =
2039 nla_get_u32(tbVendor[
2040 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS]);
2041
2042 if (!tbVendor[
2043 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES
2044 ]) {
2045 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
2046 "_BSSID_HISTORY_ENTRIES not found", __FUNCTION__);
2047 return WIFI_ERROR_INVALID_ARGS;
2048 }
2049 mGetCapabilitiesRspParams->capabilities.max_bssid_history_entries =
2050 nla_get_u32(tbVendor[
2051 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES
2052 ]);
2053
2054 if (!tbVendor[
2055 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS
2056 ]) {
2057 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES"
2058 "_MAX_HOTLIST_SSIDS not found. Set to 0.", __FUNCTION__);
2059 mGetCapabilitiesRspParams->capabilities.max_hotlist_ssids = 0;
2060 } else {
2061 mGetCapabilitiesRspParams->capabilities.max_hotlist_ssids =
2062 nla_get_u32(tbVendor[
2063 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS
2064 ]);
2065 }
2066
2067 if (!tbVendor[
2068 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS
2069 ]) {
2070 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
2071 "_NUM_EPNO_NETS not found. Set to 0.", __FUNCTION__);
2072 mGetCapabilitiesRspParams->capabilities.\
2073 max_number_epno_networks = 0;
2074 } else {
2075 mGetCapabilitiesRspParams->capabilities.max_number_epno_networks
2076 = nla_get_u32(tbVendor[
2077 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS
2078 ]);
2079 }
2080
2081 if (!tbVendor[
2082 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID
2083 ]) {
2084 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
2085 "_NUM_EPNO_NETS_BY_SSID not found. Set to 0.", __FUNCTION__);
2086 mGetCapabilitiesRspParams->capabilities.\
2087 max_number_epno_networks_by_ssid = 0;
2088 } else {
2089 mGetCapabilitiesRspParams->capabilities.max_number_epno_networks_by_ssid
2090 = nla_get_u32(tbVendor[
2091 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID
2092 ]);
2093 }
2094
2095 if (!tbVendor[
2096 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID
2097 ]) {
2098 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
2099 "_NUM_WHITELISTED_SSID not found. Set to 0.", __FUNCTION__);
2100 mGetCapabilitiesRspParams->capabilities.\
2101 max_number_of_white_listed_ssid = 0;
2102 } else {
2103 mGetCapabilitiesRspParams->capabilities.max_number_of_white_listed_ssid
2104 = nla_get_u32(tbVendor[
2105 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID
2106 ]);
2107 }
2108 return WIFI_SUCCESS;
2109 }
2110
2111 /* Called to parse and extract cached results. */
gscan_get_cached_results(wifi_cached_scan_results * cached_results,struct nlattr ** tb_vendor)2112 int GScanCommand:: gscan_get_cached_results(
2113 wifi_cached_scan_results *cached_results,
2114 struct nlattr **tb_vendor)
2115 {
2116 u32 j = 0;
2117 struct nlattr *scanResultsInfo, *wifiScanResultsInfo;
2118 int rem = 0, remResults = 0;
2119 u32 len = 0, numScanResults = 0;
2120 u32 i = mGetCachedResultsRspParams->cachedResultsStartingIndex;
2121 ALOGE("%s: starting counter: %d", __FUNCTION__, i);
2122
2123 for (scanResultsInfo = (struct nlattr *) nla_data(tb_vendor[
2124 QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_LIST]),
2125 rem = nla_len(tb_vendor[
2126 QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_LIST]);
2127 nla_ok(scanResultsInfo, rem) && i < mGetCachedResultsRspParams->max;
2128 scanResultsInfo = nla_next(scanResultsInfo, &(rem)))
2129 {
2130 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
2131 nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
2132 (struct nlattr *) nla_data(scanResultsInfo),
2133 nla_len(scanResultsInfo), NULL);
2134
2135 if (!
2136 tb2[
2137 QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID
2138 ])
2139 {
2140 ALOGE("%s: GSCAN_CACHED_RESULTS_SCAN_ID"
2141 " not found", __FUNCTION__);
2142 return WIFI_ERROR_INVALID_ARGS;
2143 }
2144 cached_results[i].scan_id =
2145 nla_get_u32(
2146 tb2[
2147 QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID
2148 ]);
2149
2150 if (!
2151 tb2[
2152 QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_FLAGS
2153 ])
2154 {
2155 ALOGE("%s: GSCAN_CACHED_RESULTS_FLAGS "
2156 "not found", __FUNCTION__);
2157 return WIFI_ERROR_INVALID_ARGS;
2158 }
2159 cached_results[i].flags =
2160 nla_get_u32(
2161 tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_FLAGS]);
2162
2163 if (!
2164 tb2[
2165 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE
2166 ])
2167 {
2168 ALOGE("%s: RESULTS_NUM_RESULTS_AVAILABLE "
2169 "not found", __FUNCTION__);
2170 return WIFI_ERROR_INVALID_ARGS;
2171 }
2172 numScanResults =
2173 nla_get_u32(
2174 tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]);
2175
2176 if (mGetCachedResultsRspParams->lastProcessedScanId !=
2177 cached_results[i].scan_id) {
2178 j = 0; /* reset wifi_scan_result counter */
2179 cached_results[i].num_results = 0;
2180 ALOGD("parsing: *lastProcessedScanId [%d] !="
2181 " cached_results[%d].scan_id:%d, j:%d "
2182 "numScanResults: %d",
2183 mGetCachedResultsRspParams->lastProcessedScanId, i,
2184 cached_results[i].scan_id, j, numScanResults);
2185 mGetCachedResultsRspParams->lastProcessedScanId =
2186 cached_results[i].scan_id;
2187 mGetCachedResultsRspParams->wifiScanResultsStartingIndex = 0;
2188 /* Increment the number of cached scan results received */
2189 mGetCachedResultsRspParams->num_cached_results++;
2190 } else {
2191 j = mGetCachedResultsRspParams->wifiScanResultsStartingIndex;
2192 ALOGD("parsing: *lastProcessedScanId [%d] == "
2193 "cached_results[%d].scan_id:%d, j:%d "
2194 "numScanResults:%d",
2195 mGetCachedResultsRspParams->lastProcessedScanId, i,
2196 cached_results[i].scan_id, j, numScanResults);
2197 }
2198
2199 if (!cached_results[i].results) {
2200 ALOGE("%s: NULL cached_results[%d].results"
2201 ". Abort.", __FUNCTION__, i);
2202 return WIFI_ERROR_OUT_OF_MEMORY;
2203 }
2204 #ifdef QC_HAL_DEBUG
2205 ALOGE("%s: scan_id %d ", __FUNCTION__,
2206 cached_results[i].scan_id);
2207 ALOGE("%s: flags %u ", __FUNCTION__,
2208 cached_results[i].flags);
2209 #endif
2210
2211 for (wifiScanResultsInfo = (struct nlattr *) nla_data(tb2[
2212 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]),
2213 remResults = nla_len(tb2[
2214 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]);
2215 nla_ok(wifiScanResultsInfo, remResults);
2216 wifiScanResultsInfo = nla_next(wifiScanResultsInfo, &(remResults)))
2217 {
2218 struct nlattr *tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
2219 nla_parse(tb3, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
2220 (struct nlattr *) nla_data(wifiScanResultsInfo),
2221 nla_len(wifiScanResultsInfo), NULL);
2222 if (j < MAX_AP_CACHE_PER_SCAN) {
2223 if (!
2224 tb3[
2225 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
2226 ])
2227 {
2228 ALOGE("%s: "
2229 "RESULTS_SCAN_RESULT_TIME_STAMP not found",
2230 __FUNCTION__);
2231 return WIFI_ERROR_INVALID_ARGS;
2232 }
2233 cached_results[i].results[j].ts =
2234 nla_get_u64(
2235 tb3[
2236 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
2237 ]);
2238 if (!
2239 tb3[
2240 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID
2241 ])
2242 {
2243 ALOGE("%s: "
2244 "RESULTS_SCAN_RESULT_SSID not found",
2245 __FUNCTION__);
2246 return WIFI_ERROR_INVALID_ARGS;
2247 }
2248 len = nla_len(tb3[
2249 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]);
2250 len =
2251 sizeof(cached_results[i].results[j].ssid) <= len ?
2252 sizeof(cached_results[i].results[j].ssid) : len;
2253 memcpy((void *)&cached_results[i].results[j].ssid,
2254 nla_data(
2255 tb3[
2256 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]),
2257 len);
2258 if (!
2259 tb3[
2260 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID
2261 ])
2262 {
2263 ALOGE("%s: "
2264 "RESULTS_SCAN_RESULT_BSSID not found",
2265 __FUNCTION__);
2266 return WIFI_ERROR_INVALID_ARGS;
2267 }
2268 len = nla_len(
2269 tb3[
2270 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]);
2271 len =
2272 sizeof(cached_results[i].results[j].bssid) <= len ?
2273 sizeof(cached_results[i].results[j].bssid) : len;
2274 memcpy(&cached_results[i].results[j].bssid,
2275 nla_data(
2276 tb3[
2277 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]),
2278 len);
2279 if (!
2280 tb3[
2281 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL
2282 ])
2283 {
2284 ALOGE("%s: "
2285 "RESULTS_SCAN_RESULT_CHANNEL not found",
2286 __FUNCTION__);
2287 return WIFI_ERROR_INVALID_ARGS;
2288 }
2289 cached_results[i].results[j].channel =
2290 nla_get_u32(
2291 tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]);
2292 if (!
2293 tb3[
2294 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI
2295 ])
2296 {
2297 ALOGE("%s: "
2298 "RESULTS_SCAN_RESULT_RSSI not found",
2299 __FUNCTION__);
2300 return WIFI_ERROR_INVALID_ARGS;
2301 }
2302 cached_results[i].results[j].rssi =
2303 get_s32(
2304 tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI]);
2305 if (!
2306 tb3[
2307 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT
2308 ])
2309 {
2310 ALOGE("%s: "
2311 "RESULTS_SCAN_RESULT_RTT not found",
2312 __FUNCTION__);
2313 return WIFI_ERROR_INVALID_ARGS;
2314 }
2315 cached_results[i].results[j].rtt =
2316 nla_get_u32(
2317 tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]);
2318 if (!
2319 tb3[
2320 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD
2321 ])
2322 {
2323 ALOGE("%s: "
2324 "RESULTS_SCAN_RESULT_RTT_SD not found",
2325 __FUNCTION__);
2326 return WIFI_ERROR_INVALID_ARGS;
2327 }
2328 cached_results[i].results[j].rtt_sd =
2329 nla_get_u32(
2330 tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]);
2331 #ifdef QC_HAL_DEBUG
2332 /* Enable these prints for debugging if needed. */
2333 ALOGD("%s: ts %lld ", __FUNCTION__,
2334 cached_results[i].results[j].ts);
2335 ALOGD("%s: SSID %s ", __FUNCTION__,
2336 cached_results[i].results[j].ssid);
2337 ALOGD("%s: ", __FUNCTION__,
2338 "BSSID: %02x:%02x:%02x:%02x:%02x:%02x \n",
2339 cached_results[i].results[j].bssid[0],
2340 cached_results[i].results[j].bssid[1],
2341 cached_results[i].results[j].bssid[2],
2342 cached_results[i].results[j].bssid[3],
2343 cached_results[i].results[j].bssid[4],
2344 cached_results[i].results[j].bssid[5]);
2345 ALOGD("%s: channel %d ", __FUNCTION__,
2346 cached_results[i].results[j].channel);
2347 ALOGD("%s: rssi %d ", __FUNCTION__,
2348 cached_results[i].results[j].rssi);
2349 ALOGD("%s: rtt %lld ", __FUNCTION__,
2350 cached_results[i].results[j].rtt);
2351 ALOGD("%s: rtt_sd %lld ", __FUNCTION__,
2352 cached_results[i].results[j].rtt_sd);
2353 #endif
2354 /* Increment loop index for next record */
2355 j++;
2356 /* For this scan id, update the wifiScanResultsStartingIndex
2357 * and number of cached results parsed so far.
2358 */
2359 mGetCachedResultsRspParams->wifiScanResultsStartingIndex = j;
2360 cached_results[i].num_results++;
2361 } else {
2362 /* We already parsed and stored up to max wifi_scan_results
2363 * specified by the caller. Now, continue to loop over NL
2364 * entries in order to properly update NL parsing pointer
2365 * so it points to the next scan_id results.
2366 */
2367 ALOGD("%s: loop index:%d > max num"
2368 " of wifi_scan_results:%d for gscan cached results"
2369 " bucket:%d. Dummy loop", __FUNCTION__,
2370 j, MAX_AP_CACHE_PER_SCAN, i);
2371 }
2372 }
2373 ALOGE("%s: cached_results[%d].num_results: %d ", __FUNCTION__,
2374 i, cached_results[i].num_results);
2375 /* Increment loop index for next cached scan result record */
2376 i++;
2377 }
2378 /* Increment starting index of filling cached results received */
2379 if (mGetCachedResultsRspParams->num_cached_results)
2380 mGetCachedResultsRspParams->cachedResultsStartingIndex =
2381 mGetCachedResultsRspParams->num_cached_results - 1;
2382 return WIFI_SUCCESS;
2383 }
2384
2385 /* Set the GSCAN BSSID Hotlist. */
wifi_set_epno_list(wifi_request_id id,wifi_interface_handle iface,int num_networks,wifi_epno_network * networks,wifi_epno_handler handler)2386 wifi_error wifi_set_epno_list(wifi_request_id id,
2387 wifi_interface_handle iface,
2388 int num_networks,
2389 wifi_epno_network *networks,
2390 wifi_epno_handler handler)
2391 {
2392 int i, ret = 0;
2393 GScanCommand *gScanCommand;
2394 struct nlattr *nlData, *nlPnoParamList;
2395 interface_info *ifaceInfo = getIfaceInfo(iface);
2396 wifi_handle wifiHandle = getWifiHandle(iface);
2397 bool previousGScanSetEpnoListRunning = false;
2398 hal_info *info = getHalInfo(wifiHandle);
2399 gscan_event_handlers* event_handlers;
2400 GScanCommandEventHandler *gScanSetPnoListCmdEventHandler;
2401
2402 event_handlers = (gscan_event_handlers*)info->gscan_handlers;
2403 gScanSetPnoListCmdEventHandler =
2404 event_handlers->gScanSetPnoListCmdEventHandler;
2405
2406 if (!(info->supported_feature_set & WIFI_FEATURE_HAL_EPNO)) {
2407 ALOGE("%s: Enhanced PNO is not supported by the driver",
2408 __FUNCTION__);
2409 return WIFI_ERROR_NOT_SUPPORTED;
2410 }
2411
2412 ALOGI("%s: RequestId:%d", __FUNCTION__, id);
2413
2414 /* Wi-Fi HAL doesn't need to check if a similar request to set ePNO
2415 * list was made earlier. If wifi_set_epno_list() is called while
2416 * another one is running, the request will be sent down to driver and
2417 * firmware. If the new request is successfully honored, then Wi-Fi HAL
2418 * will use the new request id for the gScanSetPnoListCmdEventHandler
2419 * object.
2420 */
2421
2422 gScanCommand =
2423 new GScanCommand(
2424 wifiHandle,
2425 id,
2426 OUI_QCA,
2427 QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST);
2428 if (gScanCommand == NULL) {
2429 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
2430 return WIFI_ERROR_UNKNOWN;
2431 }
2432
2433 /* Create the NL message. */
2434 ret = gScanCommand->create();
2435 if (ret < 0) {
2436 ALOGE("%s: Failed to create the NL msg. Error:%d", __FUNCTION__, ret);
2437 goto cleanup;
2438 }
2439
2440 /* Set the interface Id of the message. */
2441 ret = gScanCommand->set_iface_id(ifaceInfo->name);
2442 if (ret < 0) {
2443 ALOGE("%s: Failed to set iface id. Error:%d", __FUNCTION__, ret);
2444 goto cleanup;
2445 }
2446
2447 /* Add the vendor specific attributes for the NL command. */
2448 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2449 if (!nlData) {
2450 ALOGE("%s: Failed to add attribute NL80211_ATTR_VENDOR_DATA. Error:%d",
2451 __FUNCTION__, ret);
2452 goto cleanup;
2453 }
2454
2455 num_networks = (unsigned int)num_networks > MAX_PNO_SSID ?
2456 MAX_PNO_SSID : num_networks;
2457 if (gScanCommand->put_u32(
2458 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
2459 id) ||
2460 gScanCommand->put_u32(
2461 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS,
2462 num_networks))
2463 {
2464 ALOGE("%s: Failed to add vendor atributes. Error:%d", __FUNCTION__, ret);
2465 goto cleanup;
2466 }
2467
2468 /* Add the vendor specific attributes for the NL command. */
2469 nlPnoParamList =
2470 gScanCommand->attr_start(
2471 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST);
2472 if (!nlPnoParamList) {
2473 ALOGE("%s: Failed to add attr. PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST. "
2474 "Error:%d", __FUNCTION__, ret);
2475 goto cleanup;
2476 }
2477
2478 /* Add nested NL attributes for ePno List. */
2479 for (i = 0; i < num_networks; i++) {
2480 wifi_epno_network pnoNetwork = networks[i];
2481 struct nlattr *nlPnoNetwork = gScanCommand->attr_start(i);
2482 if (!nlPnoNetwork) {
2483 ALOGE("%s: Failed attr_start for nlPnoNetwork. Error:%d",
2484 __FUNCTION__, ret);
2485 goto cleanup;
2486 }
2487 if (gScanCommand->put_string(
2488 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID,
2489 pnoNetwork.ssid) ||
2490 gScanCommand->put_s8(
2491 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_RSSI_THRESHOLD,
2492 pnoNetwork.rssi_threshold) ||
2493 gScanCommand->put_u8(
2494 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS,
2495 pnoNetwork.flags) ||
2496 gScanCommand->put_u8(
2497 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT,
2498 pnoNetwork.auth_bit_field))
2499 {
2500 ALOGE("%s: Failed to add PNO_SET_LIST_PARAM_EPNO_NETWORK_*. "
2501 "Error:%d", __FUNCTION__, ret);
2502 goto cleanup;
2503 }
2504 gScanCommand->attr_end(nlPnoNetwork);
2505 }
2506
2507 gScanCommand->attr_end(nlPnoParamList);
2508
2509 gScanCommand->attr_end(nlData);
2510
2511 GScanCallbackHandler callbackHandler;
2512 memset(&callbackHandler, 0, sizeof(callbackHandler));
2513 callbackHandler.on_pno_network_found = handler.on_network_found;
2514
2515 /* Create an object of the event handler class to take care of the
2516 * asychronous events on the north-bound.
2517 */
2518 if (gScanSetPnoListCmdEventHandler == NULL) {
2519 gScanSetPnoListCmdEventHandler = new GScanCommandEventHandler(
2520 wifiHandle,
2521 id,
2522 OUI_QCA,
2523 QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST,
2524 callbackHandler);
2525 if (gScanSetPnoListCmdEventHandler == NULL) {
2526 ALOGE("%s: Error instantiating "
2527 "gScanSetPnoListCmdEventHandler.", __FUNCTION__);
2528 ret = WIFI_ERROR_UNKNOWN;
2529 goto cleanup;
2530 }
2531 event_handlers->gScanSetPnoListCmdEventHandler =
2532 gScanSetPnoListCmdEventHandler;
2533 ALOGD("%s: Handler object was created for PNO_NETWORK_FOUND.",
2534 __FUNCTION__);
2535 } else {
2536 gScanSetPnoListCmdEventHandler->setCallbackHandler(callbackHandler);
2537 }
2538
2539 ret = gScanCommand->requestResponse();
2540 if (ret != 0) {
2541 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
2542 goto cleanup;
2543 }
2544
2545 if (gScanSetPnoListCmdEventHandler != NULL) {
2546 gScanSetPnoListCmdEventHandler->set_request_id(id);
2547 gScanSetPnoListCmdEventHandler->enableEventHandling();
2548 }
2549
2550 cleanup:
2551 delete gScanCommand;
2552 /* Disable Event Handling if ret != 0 */
2553 if (ret && gScanSetPnoListCmdEventHandler) {
2554 ALOGI("%s: Error ret:%d, disable event handling",
2555 __FUNCTION__, ret);
2556 gScanSetPnoListCmdEventHandler->disableEventHandling();
2557 }
2558 return (wifi_error)ret;
2559 }
2560
2561 /* 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)2562 wifi_error wifi_set_passpoint_list(wifi_request_id id,
2563 wifi_interface_handle iface, int num,
2564 wifi_passpoint_network *networks,
2565 wifi_passpoint_event_handler handler)
2566 {
2567 int i, numAp, ret = 0;
2568 GScanCommand *gScanCommand;
2569 struct nlattr *nlData, *nlPasspointNetworksParamList;
2570 interface_info *ifaceInfo = getIfaceInfo(iface);
2571 wifi_handle wifiHandle = getWifiHandle(iface);
2572 bool previousGScanPnoSetPasspointListRunning = false;
2573 hal_info *info = getHalInfo(wifiHandle);
2574 gscan_event_handlers* event_handlers;
2575 GScanCommandEventHandler *gScanPnoSetPasspointListCmdEventHandler;
2576
2577 event_handlers = (gscan_event_handlers*)info->gscan_handlers;
2578 gScanPnoSetPasspointListCmdEventHandler =
2579 event_handlers->gScanPnoSetPasspointListCmdEventHandler;
2580
2581 if (!(info->supported_feature_set & WIFI_FEATURE_HAL_EPNO)) {
2582 ALOGE("%s: Enhanced PNO is not supported by the driver",
2583 __FUNCTION__);
2584 return WIFI_ERROR_NOT_SUPPORTED;
2585 }
2586
2587 ALOGI("%s: RequestId:%d", __FUNCTION__, id);
2588
2589 /* Wi-Fi HAL doesn't need to check if a similar request to set ePNO
2590 * passpoint list was made earlier. If wifi_set_passpoint_list() is called
2591 * while another one is running, the request will be sent down to driver and
2592 * firmware. If the new request is successfully honored, then Wi-Fi HAL
2593 * will use the new request id for the
2594 * gScanPnoSetPasspointListCmdEventHandler object.
2595 */
2596 gScanCommand =
2597 new GScanCommand(
2598 wifiHandle,
2599 id,
2600 OUI_QCA,
2601 QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST);
2602 if (gScanCommand == NULL) {
2603 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
2604 return WIFI_ERROR_UNKNOWN;
2605 }
2606
2607 /* Create the NL message. */
2608 ret = gScanCommand->create();
2609 if (ret < 0) {
2610 ALOGE("%s: Failed to create the NL msg. Error:%d", __FUNCTION__, ret);
2611 goto cleanup;
2612 }
2613
2614 /* Set the interface Id of the message. */
2615 ret = gScanCommand->set_iface_id(ifaceInfo->name);
2616 if (ret < 0) {
2617 ALOGE("%s: Failed to set iface id. Error:%d", __FUNCTION__, ret);
2618 goto cleanup;
2619 }
2620
2621 /* Add the vendor specific attributes for the NL command. */
2622 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2623 if (!nlData) {
2624 ALOGE("%s: Failed to add attribute NL80211_ATTR_VENDOR_DATA. Error:%d",
2625 __FUNCTION__, ret);
2626 goto cleanup;
2627 }
2628
2629 if (gScanCommand->put_u32(
2630 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
2631 id) ||
2632 gScanCommand->put_u32(
2633 QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM,
2634 num))
2635 {
2636 ALOGE("%s: Failed to add vendor atributes. Error:%d", __FUNCTION__, ret);
2637 goto cleanup;
2638 }
2639
2640 /* Add the vendor specific attributes for the NL command. */
2641 nlPasspointNetworksParamList =
2642 gScanCommand->attr_start(
2643 QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY);
2644 if (!nlPasspointNetworksParamList) {
2645 ALOGE("%s: Failed attr_start for PASSPOINT_LIST_PARAM_NETWORK_ARRAY. "
2646 "Error:%d", __FUNCTION__, ret);
2647 goto cleanup;
2648 }
2649
2650 /* Add nested NL attributes for Passpoint List param. */
2651 for (i = 0; i < num; i++) {
2652 wifi_passpoint_network passpointNetwork = networks[i];
2653 struct nlattr *nlPasspointNetworkParam = gScanCommand->attr_start(i);
2654 if (!nlPasspointNetworkParam) {
2655 ALOGE("%s: Failed attr_start for nlPasspointNetworkParam. "
2656 "Error:%d", __FUNCTION__, ret);
2657 goto cleanup;
2658 }
2659 if (gScanCommand->put_u32(
2660 QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID,
2661 passpointNetwork.id) ||
2662 gScanCommand->put_string(
2663 QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM,
2664 passpointNetwork.realm) ||
2665 gScanCommand->put_bytes(
2666 QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID,
2667 (char*)passpointNetwork.roamingConsortiumIds,
2668 16 * sizeof(int64_t)) ||
2669 gScanCommand->put_bytes(
2670 QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN,
2671 (char*)passpointNetwork.plmn, 3 * sizeof(u8)))
2672 {
2673 ALOGE("%s: Failed to add PNO_PASSPOINT_NETWORK_PARAM_ROAM_* attr. "
2674 "Error:%d", __FUNCTION__, ret);
2675 goto cleanup;
2676 }
2677 gScanCommand->attr_end(nlPasspointNetworkParam);
2678 }
2679
2680 gScanCommand->attr_end(nlPasspointNetworksParamList);
2681
2682 gScanCommand->attr_end(nlData);
2683
2684 GScanCallbackHandler callbackHandler;
2685 memset(&callbackHandler, 0, sizeof(callbackHandler));
2686 callbackHandler.on_passpoint_network_found =
2687 handler.on_passpoint_network_found;
2688
2689 /* Create an object of the event handler class to take care of the
2690 * asychronous events on the north-bound.
2691 */
2692 if (gScanPnoSetPasspointListCmdEventHandler == NULL) {
2693 gScanPnoSetPasspointListCmdEventHandler = new GScanCommandEventHandler(
2694 wifiHandle,
2695 id,
2696 OUI_QCA,
2697 QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST,
2698 callbackHandler);
2699 if (gScanPnoSetPasspointListCmdEventHandler == NULL) {
2700 ALOGE("%s: Error instantiating "
2701 "gScanPnoSetPasspointListCmdEventHandler.", __FUNCTION__);
2702 ret = WIFI_ERROR_UNKNOWN;
2703 goto cleanup;
2704 }
2705 event_handlers->gScanPnoSetPasspointListCmdEventHandler =
2706 gScanPnoSetPasspointListCmdEventHandler;
2707 ALOGD("%s: Handler object was created for PNO_PASSPOINT_"
2708 "NETWORK_FOUND.", __FUNCTION__);
2709 } else {
2710 gScanPnoSetPasspointListCmdEventHandler->setCallbackHandler(callbackHandler);
2711 }
2712
2713 ret = gScanCommand->requestResponse();
2714 if (ret != 0) {
2715 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
2716 goto cleanup;
2717 }
2718
2719 if (gScanPnoSetPasspointListCmdEventHandler != NULL) {
2720 gScanPnoSetPasspointListCmdEventHandler->set_request_id(id);
2721 gScanPnoSetPasspointListCmdEventHandler->enableEventHandling();
2722 }
2723
2724 cleanup:
2725 delete gScanCommand;
2726 /* Disable Event Handling if ret != 0 */
2727 if (ret && gScanPnoSetPasspointListCmdEventHandler) {
2728 ALOGI("%s: Error ret:%d, disable event handling",
2729 __FUNCTION__, ret);
2730 gScanPnoSetPasspointListCmdEventHandler->disableEventHandling();
2731 }
2732 return (wifi_error)ret;
2733 }
2734
wifi_reset_passpoint_list(wifi_request_id id,wifi_interface_handle iface)2735 wifi_error wifi_reset_passpoint_list(wifi_request_id id,
2736 wifi_interface_handle iface)
2737 {
2738 int ret = 0;
2739 GScanCommand *gScanCommand;
2740 struct nlattr *nlData;
2741 interface_info *ifaceInfo = getIfaceInfo(iface);
2742 wifi_handle wifiHandle = getWifiHandle(iface);
2743 hal_info *info = getHalInfo(wifiHandle);
2744 gscan_event_handlers* event_handlers;
2745 GScanCommandEventHandler *gScanPnoSetPasspointListCmdEventHandler;
2746
2747 event_handlers = (gscan_event_handlers*)info->gscan_handlers;
2748 gScanPnoSetPasspointListCmdEventHandler =
2749 event_handlers->gScanPnoSetPasspointListCmdEventHandler;
2750
2751 if (!(info->supported_feature_set & WIFI_FEATURE_HAL_EPNO)) {
2752 ALOGE("%s: Enhanced PNO is not supported by the driver",
2753 __FUNCTION__);
2754 return WIFI_ERROR_NOT_SUPPORTED;
2755 }
2756
2757 ALOGI("%s: RequestId:%d", __FUNCTION__, id);
2758
2759 if (gScanPnoSetPasspointListCmdEventHandler == NULL ||
2760 (gScanPnoSetPasspointListCmdEventHandler->isEventHandlingEnabled() ==
2761 false)) {
2762 ALOGE("wifi_reset_passpoint_list: ePNO passpoint_list isn't set. "
2763 "Nothing to do. Exit.");
2764 return WIFI_ERROR_NOT_AVAILABLE;
2765 }
2766
2767 gScanCommand = new GScanCommand(
2768 wifiHandle,
2769 id,
2770 OUI_QCA,
2771 QCA_NL80211_VENDOR_SUBCMD_PNO_RESET_PASSPOINT_LIST);
2772
2773 if (gScanCommand == NULL) {
2774 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
2775 return WIFI_ERROR_UNKNOWN;
2776 }
2777
2778 /* Create the NL message. */
2779 ret = gScanCommand->create();
2780 if (ret < 0) {
2781 ALOGE("%s: Failed to create the NL msg. Error:%d", __FUNCTION__, ret);
2782 goto cleanup;
2783 }
2784
2785 /* Set the interface Id of the message. */
2786 ret = gScanCommand->set_iface_id(ifaceInfo->name);
2787 if (ret < 0) {
2788 ALOGE("%s: Failed to set iface id. Error:%d", __FUNCTION__, ret);
2789 goto cleanup;
2790 }
2791
2792 /* Add the vendor specific attributes for the NL command. */
2793 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2794 if (!nlData) {
2795 ALOGE("%s: Failed to add attribute NL80211_ATTR_VENDOR_DATA. Error:%d",
2796 __FUNCTION__, ret);
2797 goto cleanup;
2798 }
2799
2800 ret = gScanCommand->put_u32(
2801 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, id);
2802 if (ret < 0) {
2803 ALOGE("%s: Failed to add vendor data attributes. Error:%d",
2804 __FUNCTION__, ret);
2805 goto cleanup;
2806 }
2807
2808 gScanCommand->attr_end(nlData);
2809
2810 ret = gScanCommand->requestResponse();
2811 if (ret != 0) {
2812 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
2813 }
2814
2815 /* Disable Event Handling. */
2816 if (gScanPnoSetPasspointListCmdEventHandler) {
2817 gScanPnoSetPasspointListCmdEventHandler->disableEventHandling();
2818 }
2819
2820 cleanup:
2821 delete gScanCommand;
2822 return (wifi_error)ret;
2823 }
2824
allocCachedResultsTemp(int max,wifi_cached_scan_results * cached_results)2825 int GScanCommand::allocCachedResultsTemp(int max,
2826 wifi_cached_scan_results *cached_results)
2827 {
2828 wifi_cached_scan_results *tempCachedResults = NULL;
2829
2830 /* Alloc memory for "max" number of cached results. */
2831 mGetCachedResultsRspParams->cached_results =
2832 (wifi_cached_scan_results*)
2833 malloc(max * sizeof(wifi_cached_scan_results));
2834 if (!mGetCachedResultsRspParams->cached_results) {
2835 ALOGE("%s: Failed to allocate memory for "
2836 "mGetCachedResultsRspParams->cached_results.",
2837 __FUNCTION__);
2838 return WIFI_ERROR_OUT_OF_MEMORY;
2839 }
2840 memset(mGetCachedResultsRspParams->cached_results, 0,
2841 max * sizeof(wifi_cached_scan_results));
2842
2843 mGetCachedResultsRspParams->max = max;
2844
2845 return WIFI_SUCCESS;
2846 }
2847
2848 /*
2849 * Allocates memory for the subCmd response struct and initializes status = -1
2850 */
allocRspParams(eGScanRspRarams cmd)2851 int GScanCommand::allocRspParams(eGScanRspRarams cmd)
2852 {
2853 int ret = 0;
2854 switch(cmd)
2855 {
2856 case eGScanGetCapabilitiesRspParams:
2857 mGetCapabilitiesRspParams = (GScanGetCapabilitiesRspParams *)
2858 malloc(sizeof(GScanGetCapabilitiesRspParams));
2859 if (!mGetCapabilitiesRspParams)
2860 ret = -1;
2861 else {
2862 memset(&mGetCapabilitiesRspParams->capabilities, 0,
2863 sizeof(wifi_gscan_capabilities));
2864 }
2865 break;
2866 case eGScanGetCachedResultsRspParams:
2867 mGetCachedResultsRspParams = (GScanGetCachedResultsRspParams *)
2868 malloc(sizeof(GScanGetCachedResultsRspParams));
2869 if (!mGetCachedResultsRspParams)
2870 ret = -1;
2871 else {
2872 mGetCachedResultsRspParams->num_cached_results = 0;
2873 mGetCachedResultsRspParams->more_data = false;
2874 mGetCachedResultsRspParams->cachedResultsStartingIndex = -1;
2875 mGetCachedResultsRspParams->lastProcessedScanId = -1;
2876 mGetCachedResultsRspParams->wifiScanResultsStartingIndex = -1;
2877 mGetCachedResultsRspParams->max = 0;
2878 mGetCachedResultsRspParams->cached_results = NULL;
2879 }
2880 break;
2881 default:
2882 ALOGD("%s: Wrong request for alloc.", __FUNCTION__);
2883 ret = -1;
2884 }
2885 return ret;
2886 }
2887
freeRspParams(eGScanRspRarams cmd)2888 void GScanCommand::freeRspParams(eGScanRspRarams cmd)
2889 {
2890 u32 i = 0;
2891 wifi_cached_scan_results *cached_results = NULL;
2892
2893 switch(cmd)
2894 {
2895 case eGScanGetCapabilitiesRspParams:
2896 if (mGetCapabilitiesRspParams) {
2897 free(mGetCapabilitiesRspParams);
2898 mGetCapabilitiesRspParams = NULL;
2899 }
2900 break;
2901 case eGScanGetCachedResultsRspParams:
2902 if (mGetCachedResultsRspParams) {
2903 if (mGetCachedResultsRspParams->cached_results) {
2904 free(mGetCachedResultsRspParams->cached_results);
2905 mGetCachedResultsRspParams->cached_results = NULL;
2906 }
2907 free(mGetCachedResultsRspParams);
2908 mGetCachedResultsRspParams = NULL;
2909 }
2910 break;
2911 default:
2912 ALOGD("%s: Wrong request for free.", __FUNCTION__);
2913 }
2914 }
2915
copyCachedScanResults(int * numResults,wifi_cached_scan_results * cached_results)2916 wifi_error GScanCommand::copyCachedScanResults(
2917 int *numResults,
2918 wifi_cached_scan_results *cached_results)
2919 {
2920 wifi_error ret = WIFI_SUCCESS;
2921 int i;
2922 wifi_cached_scan_results *cachedResultRsp;
2923
2924 if (mGetCachedResultsRspParams && cached_results)
2925 {
2926 /* Populate the number of parsed cached results. */
2927 *numResults = mGetCachedResultsRspParams->num_cached_results;
2928
2929 for (i = 0; i < *numResults; i++) {
2930 cachedResultRsp = &mGetCachedResultsRspParams->cached_results[i];
2931 cached_results[i].scan_id = cachedResultRsp->scan_id;
2932 cached_results[i].flags = cachedResultRsp->flags;
2933 cached_results[i].num_results = cachedResultRsp->num_results;
2934
2935 if (!cached_results[i].num_results) {
2936 ALOGI("Error: cached_results[%d].num_results=0", i);
2937 continue;
2938 }
2939
2940 ALOGI("copyCachedScanResults: "
2941 "cached_results[%d].num_results : %d",
2942 i, cached_results[i].num_results);
2943
2944 memcpy(cached_results[i].results,
2945 cachedResultRsp->results,
2946 cached_results[i].num_results * sizeof(wifi_scan_result));
2947 }
2948 } else {
2949 ALOGE("%s: mGetCachedResultsRspParams is NULL", __FUNCTION__);
2950 *numResults = 0;
2951 ret = WIFI_ERROR_INVALID_ARGS;
2952 }
2953 return ret;
2954 }
2955
getGetCapabilitiesRspParams(wifi_gscan_capabilities * capabilities)2956 void GScanCommand::getGetCapabilitiesRspParams(
2957 wifi_gscan_capabilities *capabilities)
2958 {
2959 if (mGetCapabilitiesRspParams && capabilities)
2960 {
2961 memcpy(capabilities,
2962 &mGetCapabilitiesRspParams->capabilities,
2963 sizeof(wifi_gscan_capabilities));
2964 } else {
2965 ALOGD("%s: mGetCapabilitiesRspParams is NULL", __FUNCTION__);
2966 }
2967 }
2968
setMaxChannels(int max_channels)2969 void GScanCommand::setMaxChannels(int max_channels) {
2970 mMaxChannels = max_channels;
2971 }
2972
setChannels(int * channels)2973 void GScanCommand::setChannels(int *channels) {
2974 mChannels = channels;
2975 }
2976
setNumChannelsPtr(int * num_channels)2977 void GScanCommand::setNumChannelsPtr(int *num_channels) {
2978 mNumChannelsPtr = num_channels;
2979 }
2980
wifi_set_ssid_white_list(wifi_request_id id,wifi_interface_handle iface,int num_networks,wifi_ssid * ssids)2981 wifi_error wifi_set_ssid_white_list(wifi_request_id id,
2982 wifi_interface_handle iface,
2983 int num_networks,
2984 wifi_ssid *ssids)
2985 {
2986 int ret = 0, i;
2987 GScanCommand *roamCommand;
2988 struct nlattr *nlData, *nlSsids;
2989 interface_info *ifaceInfo = getIfaceInfo(iface);
2990 wifi_handle wifiHandle = getWifiHandle(iface);
2991 hal_info *info = getHalInfo(wifiHandle);
2992
2993 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
2994 ALOGE("%s: GSCAN is not supported by driver",
2995 __FUNCTION__);
2996 return WIFI_ERROR_NOT_SUPPORTED;
2997 }
2998
2999 ALOGI("%s: RequestId:%d", __FUNCTION__, id);
3000
3001 ALOGI("Number of SSIDs : %d", num_networks);
3002 for (i = 0; i < num_networks; i++) {
3003 ALOGI("ssid %d : %s", i, ssids[i].ssid);
3004 }
3005
3006 roamCommand = new GScanCommand(
3007 wifiHandle,
3008 id,
3009 OUI_QCA,
3010 QCA_NL80211_VENDOR_SUBCMD_ROAM);
3011 if (roamCommand == NULL) {
3012 ALOGE("wifi_set_ssid_white_list(): Error roamCommand NULL");
3013 return WIFI_ERROR_UNKNOWN;
3014 }
3015
3016 /* Create the NL message. */
3017 ret = roamCommand->create();
3018 if (ret < 0)
3019 goto cleanup;
3020
3021 /* Set the interface Id of the message. */
3022 ret = roamCommand->set_iface_id(ifaceInfo->name);
3023 if (ret < 0)
3024 goto cleanup;
3025
3026 /* Add the vendor specific attributes for the NL command. */
3027 nlData = roamCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
3028 if (!nlData)
3029 goto cleanup;
3030
3031 if (roamCommand->put_u32(QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD,
3032 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST) ||
3033 roamCommand->put_u32(
3034 QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID,
3035 id) ||
3036 roamCommand->put_u32(
3037 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS,
3038 num_networks)) {
3039 goto cleanup;
3040 }
3041
3042 nlSsids =
3043 roamCommand->attr_start(
3044 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST);
3045 for (i = 0; i < num_networks; i++) {
3046 struct nlattr *nl_ssid = roamCommand->attr_start(i);
3047
3048 if ( roamCommand->put_string(
3049 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID,
3050 ssids[i].ssid)) {
3051 goto cleanup;
3052 }
3053
3054 roamCommand->attr_end(nl_ssid);
3055 }
3056 roamCommand->attr_end(nlSsids);
3057
3058 roamCommand->attr_end(nlData);
3059
3060 ret = roamCommand->requestResponse();
3061 if (ret != 0) {
3062 ALOGE("wifi_set_ssid_white_list(): requestResponse Error:%d", ret);
3063 }
3064
3065 cleanup:
3066 delete roamCommand;
3067 return (wifi_error)ret;
3068
3069 }
3070
wifi_set_gscan_roam_params(wifi_request_id id,wifi_interface_handle iface,wifi_roam_params * params)3071 wifi_error wifi_set_gscan_roam_params(wifi_request_id id,
3072 wifi_interface_handle iface,
3073 wifi_roam_params * params)
3074 {
3075 int ret = 0;
3076 GScanCommand *roamCommand;
3077 struct nlattr *nlData;
3078 interface_info *ifaceInfo = getIfaceInfo(iface);
3079 wifi_handle wifiHandle = getWifiHandle(iface);
3080 hal_info *info = getHalInfo(wifiHandle);
3081
3082 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
3083 ALOGE("%s: GSCAN is not supported by driver",
3084 __FUNCTION__);
3085 return WIFI_ERROR_NOT_SUPPORTED;
3086 }
3087
3088 ALOGI("%s: RequestId:%d", __FUNCTION__, id);
3089
3090 if(params) {
3091 ALOGI("A_band_boost_threshold %d", params->A_band_boost_threshold);
3092 ALOGI("A_band_penalty_threshol %d", params->A_band_penalty_threshold);
3093 ALOGI("A_band_boost_factor %u", params->A_band_boost_factor);
3094 ALOGI("A_band_penalty_factor %u", params->A_band_penalty_factor);
3095 ALOGI("A_band_max_boost %u", params->A_band_max_boost);
3096 ALOGI("lazy_roam_histeresys %u", params->lazy_roam_hysteresis);
3097 ALOGI("alert_roam_rssi_trigger %d", params->alert_roam_rssi_trigger);
3098 } else {
3099 ALOGE("wifi_roam_params is NULL");
3100 return WIFI_ERROR_INVALID_ARGS;
3101 }
3102
3103 roamCommand = new GScanCommand(wifiHandle,
3104 id,
3105 OUI_QCA,
3106 QCA_NL80211_VENDOR_SUBCMD_ROAM);
3107 if (roamCommand == NULL) {
3108 ALOGE("wifi_set_gscan_roam_params(): Error roamCommand NULL");
3109 return WIFI_ERROR_UNKNOWN;
3110 }
3111
3112 /* Create the NL message. */
3113 ret = roamCommand->create();
3114 if (ret < 0)
3115 goto cleanup;
3116
3117 /* Set the interface Id of the message. */
3118 ret = roamCommand->set_iface_id(ifaceInfo->name);
3119 if (ret < 0)
3120 goto cleanup;
3121
3122 /* Add the vendor specific attributes for the NL command. */
3123 nlData = roamCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
3124 if (!nlData)
3125 goto cleanup;
3126
3127 if (roamCommand->put_u32(QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD,
3128 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_GSCAN_ROAM_PARAMS) ||
3129 roamCommand->put_u32(
3130 QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID,
3131 id) ||
3132 roamCommand->put_s32(
3133 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD,
3134 params->A_band_boost_threshold) ||
3135 roamCommand->put_s32(
3136 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD,
3137 params->A_band_penalty_threshold) ||
3138 roamCommand->put_u32(
3139 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR,
3140 params->A_band_boost_factor) ||
3141 roamCommand->put_u32(
3142 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR,
3143 params->A_band_penalty_factor) ||
3144 roamCommand->put_u32(
3145 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST,
3146 params->A_band_max_boost) ||
3147 roamCommand->put_u32(
3148 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS,
3149 params->lazy_roam_hysteresis) ||
3150 roamCommand->put_s32(
3151 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER,
3152 params->alert_roam_rssi_trigger)) {
3153 goto cleanup;
3154 }
3155
3156 roamCommand->attr_end(nlData);
3157
3158 ret = roamCommand->requestResponse();
3159 if (ret != 0) {
3160 ALOGE("wifi_set_gscan_roam_params(): requestResponse Error:%d", ret);
3161 }
3162
3163 cleanup:
3164 delete roamCommand;
3165 return (wifi_error)ret;
3166
3167 }
3168
wifi_enable_lazy_roam(wifi_request_id id,wifi_interface_handle iface,int enable)3169 wifi_error wifi_enable_lazy_roam(wifi_request_id id,
3170 wifi_interface_handle iface,
3171 int enable)
3172 {
3173 int ret = 0;
3174 GScanCommand *roamCommand;
3175 struct nlattr *nlData;
3176 interface_info *ifaceInfo = getIfaceInfo(iface);
3177 wifi_handle wifiHandle = getWifiHandle(iface);
3178 hal_info *info = getHalInfo(wifiHandle);
3179
3180 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
3181 ALOGE("%s: GSCAN is not supported by driver",
3182 __FUNCTION__);
3183 return WIFI_ERROR_NOT_SUPPORTED;
3184 }
3185
3186 ALOGI("%s: RequestId:%d Setting lazy roam: %s",
3187 __FUNCTION__, id, enable?"ENABLE":"DISABLE");
3188
3189 roamCommand =
3190 new GScanCommand(wifiHandle,
3191 id,
3192 OUI_QCA,
3193 QCA_NL80211_VENDOR_SUBCMD_ROAM);
3194 if (roamCommand == NULL) {
3195 ALOGE("%s: Error roamCommand NULL", __FUNCTION__);
3196 return WIFI_ERROR_UNKNOWN;
3197 }
3198
3199 /* Create the NL message. */
3200 ret = roamCommand->create();
3201 if (ret < 0)
3202 goto cleanup;
3203
3204 /* Set the interface Id of the message. */
3205 ret = roamCommand->set_iface_id(ifaceInfo->name);
3206 if (ret < 0)
3207 goto cleanup;
3208
3209 /* Add the vendor specific attributes for the NL command. */
3210 nlData = roamCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
3211 if (!nlData)
3212 goto cleanup;
3213
3214 if (roamCommand->put_u32(QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD,
3215 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM) ||
3216 roamCommand->put_u32(
3217 QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID,
3218 id) ||
3219 roamCommand->put_u32(
3220 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE,
3221 enable)) {
3222 goto cleanup;
3223 }
3224
3225 roamCommand->attr_end(nlData);
3226
3227 ret = roamCommand->requestResponse();
3228 if (ret != 0) {
3229 ALOGE("wifi_enable_lazy_roam(): requestResponse Error:%d", ret);
3230 }
3231
3232 cleanup:
3233 delete roamCommand;
3234 return (wifi_error)ret;
3235
3236 }
3237
wifi_set_bssid_preference(wifi_request_id id,wifi_interface_handle iface,int num_bssid,wifi_bssid_preference * prefs)3238 wifi_error wifi_set_bssid_preference(wifi_request_id id,
3239 wifi_interface_handle iface,
3240 int num_bssid,
3241 wifi_bssid_preference *prefs)
3242 {
3243 int ret = 0, i;
3244 GScanCommand *roamCommand;
3245 struct nlattr *nlData, *nlBssids;
3246 interface_info *ifaceInfo = getIfaceInfo(iface);
3247 wifi_handle wifiHandle = getWifiHandle(iface);
3248 hal_info *info = getHalInfo(wifiHandle);
3249
3250 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
3251 ALOGE("%s: GSCAN is not supported by driver",
3252 __FUNCTION__);
3253 return WIFI_ERROR_NOT_SUPPORTED;
3254 }
3255
3256 ALOGI("%s: RequestId:%d", __FUNCTION__, id);
3257
3258 ALOGI("Number of BSSIDs: %d", num_bssid);
3259 if(prefs && num_bssid) {
3260 for (i = 0; i < num_bssid; i++) {
3261 ALOGI("BSSID: %d : %02x:%02x:%02x:%02x:%02x:%02x", i,
3262 prefs[i].bssid[0], prefs[i].bssid[1],
3263 prefs[i].bssid[2], prefs[i].bssid[3],
3264 prefs[i].bssid[4], prefs[i].bssid[5]);
3265 ALOGI("alert_roam_rssi_trigger : %d", prefs[i].rssi_modifier);
3266 }
3267 } else {
3268 ALOGE("wifi_bssid_preference is NULL");
3269 return WIFI_ERROR_INVALID_ARGS;
3270 }
3271
3272 roamCommand =
3273 new GScanCommand(wifiHandle,
3274 id,
3275 OUI_QCA,
3276 QCA_NL80211_VENDOR_SUBCMD_ROAM);
3277 if (roamCommand == NULL) {
3278 ALOGE("%s: Error roamCommand NULL", __FUNCTION__);
3279 return WIFI_ERROR_UNKNOWN;
3280 }
3281
3282 /* Create the NL message. */
3283 ret = roamCommand->create();
3284 if (ret < 0)
3285 goto cleanup;
3286
3287 /* Set the interface Id of the message. */
3288 ret = roamCommand->set_iface_id(ifaceInfo->name);
3289 if (ret < 0)
3290 goto cleanup;
3291
3292 /* Add the vendor specific attributes for the NL command. */
3293 nlData = roamCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
3294 if (!nlData)
3295 goto cleanup;
3296
3297 if (roamCommand->put_u32(QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD,
3298 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS) ||
3299 roamCommand->put_u32(
3300 QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID,
3301 id) ||
3302 roamCommand->put_u32(
3303 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID,
3304 num_bssid)) {
3305 goto cleanup;
3306 }
3307
3308 nlBssids = roamCommand->attr_start(
3309 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS);
3310 for (i = 0; i < num_bssid; i++) {
3311 struct nlattr *nl_ssid = roamCommand->attr_start(i);
3312
3313 if (roamCommand->put_addr(
3314 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID,
3315 (u8 *)prefs[i].bssid) ||
3316 roamCommand->put_s32(
3317 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER,
3318 prefs[i].rssi_modifier)) {
3319 goto cleanup;
3320 }
3321
3322 roamCommand->attr_end(nl_ssid);
3323 }
3324 roamCommand->attr_end(nlBssids);
3325
3326 roamCommand->attr_end(nlData);
3327
3328 ret = roamCommand->requestResponse();
3329 if (ret != 0) {
3330 ALOGE("wifi_set_bssid_preference(): requestResponse Error:%d", ret);
3331 }
3332
3333 cleanup:
3334 delete roamCommand;
3335 return (wifi_error)ret;
3336
3337 }
3338
wifi_set_bssid_blacklist(wifi_request_id id,wifi_interface_handle iface,wifi_bssid_params params)3339 wifi_error wifi_set_bssid_blacklist(wifi_request_id id,
3340 wifi_interface_handle iface,
3341 wifi_bssid_params params)
3342 {
3343 int ret = 0, i;
3344 GScanCommand *roamCommand;
3345 struct nlattr *nlData, *nlBssids;
3346 interface_info *ifaceInfo = getIfaceInfo(iface);
3347 wifi_handle wifiHandle = getWifiHandle(iface);
3348 hal_info *info = getHalInfo(wifiHandle);
3349
3350 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
3351 ALOGE("%s: GSCAN is not supported by driver",
3352 __FUNCTION__);
3353 return WIFI_ERROR_NOT_SUPPORTED;
3354 }
3355
3356 ALOGI("%s: RequestId:%d", __FUNCTION__, id);
3357
3358 for (i = 0; i < params.num_bssid; i++) {
3359 ALOGI("BSSID: %d : %02x:%02x:%02x:%02x:%02x:%02x", i,
3360 params.bssids[i][0], params.bssids[i][1],
3361 params.bssids[i][2], params.bssids[i][3],
3362 params.bssids[i][4], params.bssids[i][5]);
3363 }
3364
3365 roamCommand =
3366 new GScanCommand(wifiHandle,
3367 id,
3368 OUI_QCA,
3369 QCA_NL80211_VENDOR_SUBCMD_ROAM);
3370 if (roamCommand == NULL) {
3371 ALOGE("%s: Error roamCommand NULL", __FUNCTION__);
3372 return WIFI_ERROR_UNKNOWN;
3373 }
3374
3375 /* Create the NL message. */
3376 ret = roamCommand->create();
3377 if (ret < 0)
3378 goto cleanup;
3379
3380 /* Set the interface Id of the message. */
3381 ret = roamCommand->set_iface_id(ifaceInfo->name);
3382 if (ret < 0)
3383 goto cleanup;
3384
3385 /* Add the vendor specific attributes for the NL command. */
3386 nlData = roamCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
3387 if (!nlData)
3388 goto cleanup;
3389
3390 if (roamCommand->put_u32(QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD,
3391 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID) ||
3392 roamCommand->put_u32(
3393 QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID,
3394 id) ||
3395 roamCommand->put_u32(
3396 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID,
3397 params.num_bssid)) {
3398 goto cleanup;
3399 }
3400
3401 nlBssids = roamCommand->attr_start(
3402 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS);
3403 for (i = 0; i < params.num_bssid; i++) {
3404 struct nlattr *nl_ssid = roamCommand->attr_start(i);
3405
3406 if (roamCommand->put_addr(
3407 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID,
3408 (u8 *)params.bssids[i])) {
3409 goto cleanup;
3410 }
3411
3412 roamCommand->attr_end(nl_ssid);
3413 }
3414 roamCommand->attr_end(nlBssids);
3415
3416 roamCommand->attr_end(nlData);
3417
3418 ret = roamCommand->requestResponse();
3419 if (ret != 0) {
3420 ALOGE("wifi_set_bssid_blacklist(): requestResponse Error:%d", ret);
3421 }
3422
3423 cleanup:
3424 delete roamCommand;
3425 return (wifi_error)ret;
3426
3427 }
3428