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