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