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