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