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