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