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