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