• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "sync.h"
18 #define LOG_TAG  "WifiHAL"
19 #include <utils/Log.h>
20 #include <time.h>
21 #include <errno.h>
22 #include <stdlib.h>
23 
24 #include "common.h"
25 #include "cpp_bindings.h"
26 #include "gscancommand.h"
27 #include "gscan_event_handler.h"
28 
29 #define GSCAN_EVENT_WAIT_TIME_SECONDS 4
30 
31 /* 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         ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
102     } else {
103         ret = lowiWifiHalApi->get_valid_channels(handle, band, max_channels,
104                           channels, num_channels);
105         ALOGI("%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     ALOGI("%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         ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
199     } else {
200         ret = lowiWifiHalApi->get_gscan_capabilities(handle,
201                                                      capabilities);
202         ALOGI("%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     ALOGI("%s: RequestId:%d", __FUNCTION__, requestId);
212 
213     if (capabilities == NULL) {
214         ALOGE("%s: NULL capabilities pointer provided. Exit.",
215             __FUNCTION__);
216         return WIFI_ERROR_INVALID_ARGS;
217     }
218 
219     gScanCommand = new GScanCommand(
220                             wifiHandle,
221                             requestId,
222                             OUI_QCA,
223                             QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES);
224     if (gScanCommand == NULL) {
225         ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
226         return WIFI_ERROR_UNKNOWN;
227     }
228 
229     /* Create the NL message. */
230     ret = gScanCommand->create();
231     if (ret < 0)
232         goto cleanup;
233 
234     /* Set the interface Id of the message. */
235     ret = gScanCommand->set_iface_id(ifaceInfo->name);
236     if (ret < 0)
237         goto cleanup;
238 
239     /* Add the vendor specific attributes for the NL command. */
240     nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
241     if (!nlData)
242         goto cleanup;
243 
244     ret = gScanCommand->put_u32(
245             QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
246             requestId);
247     if (ret < 0)
248         goto cleanup;
249 
250     gScanCommand->attr_end(nlData);
251     ret = gScanCommand->allocRspParams(eGScanGetCapabilitiesRspParams);
252     if (ret != 0) {
253         ALOGE("%s: Failed to allocate memory fo response struct. Error:%d",
254             __FUNCTION__, ret);
255         goto cleanup;
256     }
257 
258     ret = gScanCommand->requestResponse();
259     if (ret != 0) {
260         ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
261         goto cleanup;
262     }
263 
264     gScanCommand->getGetCapabilitiesRspParams(capabilities);
265 
266 cleanup:
267     gScanCommand->freeRspParams(eGScanGetCapabilitiesRspParams);
268     delete gScanCommand;
269     return (wifi_error)ret;
270 }
271 
wifi_start_gscan(wifi_request_id id,wifi_interface_handle iface,wifi_scan_cmd_params params,wifi_scan_result_handler handler)272 wifi_error wifi_start_gscan(wifi_request_id id,
273                             wifi_interface_handle iface,
274                             wifi_scan_cmd_params params,
275                             wifi_scan_result_handler handler)
276 {
277     int ret = 0;
278     u32 i, j;
279     GScanCommand *gScanCommand;
280     struct nlattr *nlData;
281     interface_info *ifaceInfo = getIfaceInfo(iface);
282     wifi_handle wifiHandle = getWifiHandle(iface);
283     u32 num_scan_buckets, numChannelSpecs;
284     wifi_scan_bucket_spec bucketSpec;
285     struct nlattr *nlBuckectSpecList;
286     bool previousGScanRunning = false;
287     hal_info *info = getHalInfo(wifiHandle);
288     lowi_cb_table_t *lowiWifiHalApi = NULL;
289     gscan_event_handlers* event_handlers;
290     GScanCommandEventHandler *gScanStartCmdEventHandler;
291 
292     event_handlers = (gscan_event_handlers*)info->gscan_handlers;
293     gScanStartCmdEventHandler = event_handlers->gscanStartCmdEventHandler;
294 
295     if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
296         ALOGE("%s: GSCAN is not supported by driver",
297             __FUNCTION__);
298         return WIFI_ERROR_NOT_SUPPORTED;
299     }
300 
301     /* Route GSCAN request through LOWI if supported */
302     lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED);
303     if (lowiWifiHalApi == NULL ||
304         lowiWifiHalApi->start_gscan  == NULL) {
305         ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
306     } else {
307         ret = lowiWifiHalApi->start_gscan(id, iface, params, handler);
308         ALOGI("%s: lowi start_gscan "
309             "returned: %d. Exit.", __FUNCTION__, ret);
310         return (wifi_error)ret;
311     }
312 
313     ALOGI("%s: RequestId:%d ", __FUNCTION__, id);
314     /* Wi-Fi HAL doesn't need to check if a similar request to start gscan was
315      *  made earlier. If start_gscan() is called while another gscan is already
316      *  running, the request will be sent down to driver and firmware. If new
317      * request is successfully honored, then Wi-Fi HAL will use the new request
318      * id for the gScanStartCmdEventHandler object.
319      */
320     gScanCommand = new GScanCommand(
321                                 wifiHandle,
322                                 id,
323                                 OUI_QCA,
324                                 QCA_NL80211_VENDOR_SUBCMD_GSCAN_START);
325     if (gScanCommand == NULL) {
326         ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
327         return WIFI_ERROR_UNKNOWN;
328     }
329 
330     /* Create the NL message. */
331     ret = gScanCommand->create();
332     if (ret < 0)
333         goto cleanup;
334 
335     /* Set the interface Id of the message. */
336     ret = gScanCommand->set_iface_id(ifaceInfo->name);
337     if (ret < 0)
338         goto cleanup;
339 
340     /* Add the vendor specific attributes for the NL command. */
341     nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
342     if (!nlData)
343         goto cleanup;
344 
345     num_scan_buckets = (unsigned int)params.num_buckets > MAX_BUCKETS ?
346                             MAX_BUCKETS : params.num_buckets;
347 
348     ALOGI("%s: Base Period:%d Max_ap_per_scan:%d "
349           "Threshold_percent:%d Threshold_num_scans:%d "
350           "num_buckets:%d", __FUNCTION__, params.base_period,
351           params.max_ap_per_scan, params.report_threshold_percent,
352           params.report_threshold_num_scans, num_scan_buckets);
353     if (gScanCommand->put_u32(
354             QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
355             id) ||
356         gScanCommand->put_u32(
357             QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_BASE_PERIOD,
358             params.base_period) ||
359         gScanCommand->put_u32(
360             QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN,
361             params.max_ap_per_scan) ||
362         gScanCommand->put_u8(
363             QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT,
364             params.report_threshold_percent) ||
365         gScanCommand->put_u8(
366             QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS,
367             params.report_threshold_num_scans) ||
368         gScanCommand->put_u8(
369             QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS,
370             num_scan_buckets))
371     {
372         goto cleanup;
373     }
374 
375     nlBuckectSpecList =
376         gScanCommand->attr_start(QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC);
377     /* Add NL attributes for scan bucket specs . */
378     for (i = 0; i < num_scan_buckets; i++) {
379         bucketSpec = params.buckets[i];
380         numChannelSpecs = (unsigned int)bucketSpec.num_channels > MAX_CHANNELS ?
381                                 MAX_CHANNELS : bucketSpec.num_channels;
382 
383         ALOGI("%s: Index: %d Bucket Id:%d Band:%d Period:%d ReportEvent:%d "
384               "numChannelSpecs:%d max_period:%d exponent:%d step_count:%d",
385               __FUNCTION__, i, bucketSpec.bucket, bucketSpec.band,
386               bucketSpec.period, bucketSpec.report_events,
387               numChannelSpecs, bucketSpec.max_period,
388               bucketSpec.exponent, bucketSpec.step_count);
389 
390         struct nlattr *nlBucketSpec = gScanCommand->attr_start(i);
391         if (gScanCommand->put_u8(
392                 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_INDEX,
393                 bucketSpec.bucket) ||
394             gScanCommand->put_u8(
395                 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_BAND,
396                 bucketSpec.band) ||
397             gScanCommand->put_u32(
398                 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_PERIOD,
399                 bucketSpec.period) ||
400             gScanCommand->put_u8(
401                 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_REPORT_EVENTS,
402                 bucketSpec.report_events) ||
403             gScanCommand->put_u32(
404                 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS,
405                 numChannelSpecs) ||
406             gScanCommand->put_u32(
407                 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_MAX_PERIOD,
408                 bucketSpec.max_period) ||
409             gScanCommand->put_u32(
410                 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_EXPONENT,
411                 bucketSpec.exponent) ||
412             gScanCommand->put_u32(
413                 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_STEP_COUNT,
414                 bucketSpec.step_count))
415         {
416             goto cleanup;
417         }
418 
419         struct nlattr *nl_channelSpecList =
420             gScanCommand->attr_start(QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC);
421 
422         /* Add NL attributes for scan channel specs . */
423         for (j = 0; j < numChannelSpecs; j++) {
424             struct nlattr *nl_channelSpec = gScanCommand->attr_start(j);
425             wifi_scan_channel_spec channel_spec = bucketSpec.channels[j];
426 
427             ALOGI("%s: Channel Spec Index:%d Channel:%d Dwell Time:%d "
428                   "passive:%d", __FUNCTION__, j, channel_spec.channel,
429                   channel_spec.dwellTimeMs, channel_spec.passive);
430 
431             if ( gScanCommand->put_u32(
432                     QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_CHANNEL,
433                     channel_spec.channel) ||
434                 gScanCommand->put_u32(
435                     QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_DWELL_TIME,
436                     channel_spec.dwellTimeMs) ||
437                 gScanCommand->put_u8(
438                     QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_PASSIVE,
439                     channel_spec.passive) )
440             {
441                 goto cleanup;
442             }
443 
444             gScanCommand->attr_end(nl_channelSpec);
445         }
446         gScanCommand->attr_end(nl_channelSpecList);
447         gScanCommand->attr_end(nlBucketSpec);
448     }
449     gScanCommand->attr_end(nlBuckectSpecList);
450 
451     gScanCommand->attr_end(nlData);
452 
453     /* Set the callback handler functions for related events. */
454     GScanCallbackHandler callbackHandler;
455     memset(&callbackHandler, 0, sizeof(callbackHandler));
456     callbackHandler.on_scan_results_available =
457                         handler.on_scan_results_available;
458     callbackHandler.on_full_scan_result = handler.on_full_scan_result;
459     callbackHandler.on_scan_event = handler.on_scan_event;
460 
461     /* Create an object to handle the related events from firmware/driver. */
462     if (gScanStartCmdEventHandler == NULL) {
463         gScanStartCmdEventHandler = new GScanCommandEventHandler(
464                                     wifiHandle,
465                                     id,
466                                     OUI_QCA,
467                                     QCA_NL80211_VENDOR_SUBCMD_GSCAN_START,
468                                     callbackHandler);
469         if (gScanStartCmdEventHandler == NULL) {
470             ALOGE("%s: Error gScanStartCmdEventHandler NULL", __FUNCTION__);
471             ret = WIFI_ERROR_UNKNOWN;
472             goto cleanup;
473         }
474         event_handlers->gscanStartCmdEventHandler = gScanStartCmdEventHandler;
475     } else {
476         gScanStartCmdEventHandler->setCallbackHandler(callbackHandler);
477     }
478 
479     ret = gScanCommand->requestResponse();
480     if (ret != 0) {
481         ALOGE("%s : requestResponse Error:%d", __FUNCTION__, ret);
482         goto cleanup;
483     }
484 
485     if (gScanStartCmdEventHandler != NULL) {
486         gScanStartCmdEventHandler->set_request_id(id);
487         gScanStartCmdEventHandler->enableEventHandling();
488     }
489 
490 cleanup:
491     delete gScanCommand;
492     /* Disable Event Handling if ret != 0 */
493     if (ret && gScanStartCmdEventHandler) {
494         ALOGI("%s: Error ret:%d, disable event handling",
495             __FUNCTION__, ret);
496         gScanStartCmdEventHandler->disableEventHandling();
497     }
498     return (wifi_error)ret;
499 
500 }
501 
wifi_stop_gscan(wifi_request_id id,wifi_interface_handle iface)502 wifi_error wifi_stop_gscan(wifi_request_id id,
503                             wifi_interface_handle iface)
504 {
505     int ret = 0;
506     GScanCommand *gScanCommand;
507     struct nlattr *nlData;
508     lowi_cb_table_t *lowiWifiHalApi = NULL;
509 
510     interface_info *ifaceInfo = getIfaceInfo(iface);
511     wifi_handle wifiHandle = getWifiHandle(iface);
512     hal_info *info = getHalInfo(wifiHandle);
513     gscan_event_handlers* event_handlers;
514     GScanCommandEventHandler *gScanStartCmdEventHandler;
515 
516     event_handlers = (gscan_event_handlers*)info->gscan_handlers;
517     gScanStartCmdEventHandler = event_handlers->gscanStartCmdEventHandler;
518 
519     if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
520         ALOGE("%s: GSCAN is not supported by driver",
521             __FUNCTION__);
522         return WIFI_ERROR_NOT_SUPPORTED;
523     }
524 
525     /* Route GSCAN request through LOWI if supported */
526     lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED);
527     if (lowiWifiHalApi == NULL ||
528         lowiWifiHalApi->stop_gscan == NULL) {
529         ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
530     } else {
531         ret = lowiWifiHalApi->stop_gscan(id, iface);
532         ALOGI("%s: lowi stop_gscan "
533             "returned: %d. Exit.", __FUNCTION__, ret);
534         return (wifi_error)ret;
535     }
536 
537     ALOGI("%s: RequestId:%d", __FUNCTION__, id);
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         ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
625     } else {
626         ret = lowiWifiHalApi->set_bssid_hotlist(id, iface, params,handler);
627         ALOGI("%s: lowi set_bssid_hotlist "
628             "returned: %d. Exit.", __FUNCTION__, ret);
629         return (wifi_error)ret;
630     }
631 
632     ALOGI("%s: RequestId:%d", __FUNCTION__, id);
633 
634     /* Wi-Fi HAL doesn't need to check if a similar request to set bssid
635      * hotlist was made earlier. If set_bssid_hotlist() is called while
636      * another one is running, the request will be sent down to driver and
637      * firmware. If the new request is successfully honored, then Wi-Fi HAL
638      * will use the new request id for the gScanSetBssidHotlistCmdEventHandler
639      * object.
640      */
641 
642     gScanCommand =
643         new GScanCommand(
644                     wifiHandle,
645                     id,
646                     OUI_QCA,
647                     QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_BSSID_HOTLIST);
648     if (gScanCommand == NULL) {
649         ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
650         return WIFI_ERROR_UNKNOWN;
651     }
652 
653     /* Create the NL message. */
654     ret = gScanCommand->create();
655     if (ret < 0)
656         goto cleanup;
657 
658     /* Set the interface Id of the message. */
659     ret = gScanCommand->set_iface_id(ifaceInfo->name);
660     if (ret < 0)
661         goto cleanup;
662 
663     /* Add the vendor specific attributes for the NL command. */
664     nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
665     if (!nlData)
666         goto cleanup;
667 
668     numAp = (unsigned int)params.num_bssid > MAX_HOTLIST_APS ?
669         MAX_HOTLIST_APS : params.num_bssid;
670     if (gScanCommand->put_u32(
671             QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
672             id) ||
673         gScanCommand->put_u32(
674             QCA_WLAN_VENDOR_ATTR_GSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE,
675             params.lost_ap_sample_size) ||
676         gScanCommand->put_u32(
677             QCA_WLAN_VENDOR_ATTR_GSCAN_BSSID_HOTLIST_PARAMS_NUM_AP,
678             numAp))
679     {
680         goto cleanup;
681     }
682 
683     ALOGI("%s: lost_ap_sample_size:%d numAp:%d", __FUNCTION__,
684           params.lost_ap_sample_size, numAp);
685     /* Add the vendor specific attributes for the NL command. */
686     nlApThresholdParamList =
687         gScanCommand->attr_start(
688                                 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM);
689     if (!nlApThresholdParamList)
690         goto cleanup;
691 
692     /* Add nested NL attributes for AP Threshold Param. */
693     for (i = 0; i < numAp; i++) {
694         ap_threshold_param apThreshold = params.ap[i];
695         struct nlattr *nlApThresholdParam = gScanCommand->attr_start(i);
696         if (!nlApThresholdParam)
697             goto cleanup;
698         if (gScanCommand->put_addr(
699                 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_BSSID,
700                 apThreshold.bssid) ||
701             gScanCommand->put_s32(
702                 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_LOW,
703                 apThreshold.low) ||
704             gScanCommand->put_s32(
705                 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH,
706                 apThreshold.high))
707         {
708             goto cleanup;
709         }
710         ALOGI("%s: Index:%d BssId: %hhx:%hhx:%hhx:%hhx:%hhx:%hhx "
711               "Threshold low:%d high:%d", __FUNCTION__, i,
712               apThreshold.bssid[0], apThreshold.bssid[1],
713               apThreshold.bssid[2], apThreshold.bssid[3],
714               apThreshold.bssid[4], apThreshold.bssid[5],
715               apThreshold.low, apThreshold.high);
716         gScanCommand->attr_end(nlApThresholdParam);
717     }
718 
719     gScanCommand->attr_end(nlApThresholdParamList);
720 
721     gScanCommand->attr_end(nlData);
722 
723     GScanCallbackHandler callbackHandler;
724     memset(&callbackHandler, 0, sizeof(callbackHandler));
725     callbackHandler.on_hotlist_ap_found = handler.on_hotlist_ap_found;
726     callbackHandler.on_hotlist_ap_lost = handler.on_hotlist_ap_lost;
727 
728     /* Create an object of the event handler class to take care of the
729       * asychronous events on the north-bound.
730       */
731     if (gScanSetBssidHotlistCmdEventHandler == NULL) {
732         gScanSetBssidHotlistCmdEventHandler = new GScanCommandEventHandler(
733                             wifiHandle,
734                             id,
735                             OUI_QCA,
736                             QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_BSSID_HOTLIST,
737                             callbackHandler);
738         if (gScanSetBssidHotlistCmdEventHandler == NULL) {
739             ALOGE("%s: Error instantiating "
740                 "gScanSetBssidHotlistCmdEventHandler.", __FUNCTION__);
741             ret = WIFI_ERROR_UNKNOWN;
742             goto cleanup;
743         }
744         event_handlers->gScanSetBssidHotlistCmdEventHandler =
745             gScanSetBssidHotlistCmdEventHandler;
746         ALOGD("%s: Handler object was created for HOTLIST_AP_FOUND.", __FUNCTION__);
747     } else {
748         gScanSetBssidHotlistCmdEventHandler->setCallbackHandler(callbackHandler);
749     }
750 
751     ret = gScanCommand->requestResponse();
752     if (ret != 0) {
753         ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
754         goto cleanup;
755     }
756 
757     if (gScanSetBssidHotlistCmdEventHandler != NULL) {
758         gScanSetBssidHotlistCmdEventHandler->set_request_id(id);
759         gScanSetBssidHotlistCmdEventHandler->enableEventHandling();
760     }
761 
762 cleanup:
763     delete gScanCommand;
764     /* Disable Event Handling if ret != 0 */
765     if (ret && gScanSetBssidHotlistCmdEventHandler) {
766         ALOGI("%s: Error ret:%d, disable event handling",
767             __FUNCTION__, ret);
768         gScanSetBssidHotlistCmdEventHandler->disableEventHandling();
769     }
770     return (wifi_error)ret;
771 }
772 
wifi_reset_bssid_hotlist(wifi_request_id id,wifi_interface_handle iface)773 wifi_error wifi_reset_bssid_hotlist(wifi_request_id id,
774                             wifi_interface_handle iface)
775 {
776     int ret = 0;
777     GScanCommand *gScanCommand;
778     struct nlattr *nlData;
779     interface_info *ifaceInfo = getIfaceInfo(iface);
780     wifi_handle wifiHandle = getWifiHandle(iface);
781     hal_info *info = getHalInfo(wifiHandle);
782     lowi_cb_table_t *lowiWifiHalApi = NULL;
783     gscan_event_handlers* event_handlers;
784     GScanCommandEventHandler *gScanSetBssidHotlistCmdEventHandler;
785 
786     event_handlers = (gscan_event_handlers*)info->gscan_handlers;
787     gScanSetBssidHotlistCmdEventHandler =
788         event_handlers->gScanSetBssidHotlistCmdEventHandler;
789 
790     if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
791         ALOGE("%s: GSCAN is not supported by driver",
792             __FUNCTION__);
793         return WIFI_ERROR_NOT_SUPPORTED;
794     }
795 
796     /* Route request through LOWI if supported*/
797     lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED);
798     if (lowiWifiHalApi == NULL ||
799         lowiWifiHalApi->reset_bssid_hotlist == NULL) {
800         ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
801     } else {
802         ret = lowiWifiHalApi->reset_bssid_hotlist(id, iface);
803         ALOGI("%s: lowi reset_bssid_hotlist "
804             "returned: %d. Exit.", __FUNCTION__, ret);
805         return (wifi_error)ret;
806     }
807 
808     ALOGI("%s: RequestId:%d", __FUNCTION__, id);
809 
810     if (gScanSetBssidHotlistCmdEventHandler == NULL ||
811         (gScanSetBssidHotlistCmdEventHandler->isEventHandlingEnabled() ==
812          false)) {
813         ALOGE("wifi_reset_bssid_hotlist: GSCAN bssid_hotlist isn't set. "
814             "Nothing to do. Exit");
815         return WIFI_ERROR_NOT_AVAILABLE;
816     }
817 
818     gScanCommand = new GScanCommand(
819                         wifiHandle,
820                         id,
821                         OUI_QCA,
822                         QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_BSSID_HOTLIST);
823 
824     if (gScanCommand == NULL) {
825         ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
826         return WIFI_ERROR_UNKNOWN;
827     }
828 
829     /* Create the NL message. */
830     ret = gScanCommand->create();
831     if (ret < 0)
832         goto cleanup;
833 
834     /* Set the interface Id of the message. */
835     ret = gScanCommand->set_iface_id(ifaceInfo->name);
836     if (ret < 0)
837         goto cleanup;
838 
839     /* Add the vendor specific attributes for the NL command. */
840     nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
841     if (!nlData)
842         goto cleanup;
843 
844     ret = gScanCommand->put_u32(
845             QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, id);
846     if (ret < 0)
847         goto cleanup;
848 
849     gScanCommand->attr_end(nlData);
850 
851     ret = gScanCommand->requestResponse();
852     if (ret != 0) {
853         ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
854     }
855 
856     /* Disable Event Handling. */
857     if (gScanSetBssidHotlistCmdEventHandler) {
858         gScanSetBssidHotlistCmdEventHandler->disableEventHandling();
859     }
860 
861 cleanup:
862     delete gScanCommand;
863     return (wifi_error)ret;
864 }
865 
866 /* 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)867 wifi_error wifi_set_significant_change_handler(wifi_request_id id,
868                                             wifi_interface_handle iface,
869                                     wifi_significant_change_params params,
870                                     wifi_significant_change_handler handler)
871 {
872     int i, numAp, ret = 0;
873     GScanCommand *gScanCommand;
874     struct nlattr *nlData, *nlApThresholdParamList;
875     interface_info *ifaceInfo = getIfaceInfo(iface);
876     wifi_handle wifiHandle = getWifiHandle(iface);
877     bool previousGScanSetSigChangeRunning = false;
878     hal_info *info = getHalInfo(wifiHandle);
879     lowi_cb_table_t *lowiWifiHalApi = NULL;
880     gscan_event_handlers* event_handlers;
881     GScanCommandEventHandler *gScanSetSignificantChangeCmdEventHandler;
882 
883     event_handlers = (gscan_event_handlers*)info->gscan_handlers;
884     gScanSetSignificantChangeCmdEventHandler =
885         event_handlers->gScanSetSignificantChangeCmdEventHandler;
886 
887     if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
888         ALOGE("%s: GSCAN is not supported by driver",
889             __FUNCTION__);
890         return WIFI_ERROR_NOT_SUPPORTED;
891     }
892 
893     /* Route request through LOWI if supported*/
894     lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED);
895     if (lowiWifiHalApi == NULL ||
896         lowiWifiHalApi->set_significant_change_handler == NULL) {
897         ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
898     } else {
899         ret = lowiWifiHalApi->set_significant_change_handler(id,
900                                                              iface,
901                                                              params,
902                                                              handler);
903         ALOGI("%s: lowi set_significant_change_handler "
904             "returned: %d. Exit.", __FUNCTION__, ret);
905         return (wifi_error)ret;
906     }
907 
908     ALOGI("%s: RequestId:%d", __FUNCTION__, id);
909 
910     /* Wi-Fi HAL doesn't need to check if a similar request to set significant
911      * change list was made earlier. If set_significant_change() is called while
912      * another one is running, the request will be sent down to driver and
913      * firmware. If the new request is successfully honored, then Wi-Fi HAL
914      * will use the new request id for the gScanSetSignificantChangeCmdEventHandler
915      * object.
916      */
917 
918     gScanCommand = new GScanCommand(
919                     wifiHandle,
920                     id,
921                     OUI_QCA,
922                     QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SIGNIFICANT_CHANGE);
923     if (gScanCommand == NULL) {
924         ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
925         return WIFI_ERROR_UNKNOWN;
926     }
927 
928     /* Create the NL message. */
929     ret = gScanCommand->create();
930     if (ret < 0)
931         goto cleanup;
932 
933     /* Set the interface Id of the message. */
934     ret = gScanCommand->set_iface_id(ifaceInfo->name);
935     if (ret < 0)
936         goto cleanup;
937 
938     /* Add the vendor specific attributes for the NL command. */
939     nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
940     if (!nlData)
941         goto cleanup;
942 
943     numAp = (unsigned int)params.num_bssid > MAX_SIGNIFICANT_CHANGE_APS ?
944         MAX_SIGNIFICANT_CHANGE_APS : params.num_bssid;
945 
946     if (gScanCommand->put_u32(
947             QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
948             id) ||
949         gScanCommand->put_u32(
950         QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE,
951             params.rssi_sample_size) ||
952         gScanCommand->put_u32(
953         QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE,
954             params.lost_ap_sample_size) ||
955         gScanCommand->put_u32(
956             QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING,
957             params.min_breaching) ||
958         gScanCommand->put_u32(
959             QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP,
960             numAp))
961     {
962         goto cleanup;
963     }
964 
965     ALOGI("%s: Number of AP params:%d Rssi_sample_size:%d "
966           "lost_ap_sample_size:%d min_breaching:%d", __FUNCTION__,
967           numAp, params.rssi_sample_size, params.lost_ap_sample_size,
968           params.min_breaching);
969 
970     /* Add the vendor specific attributes for the NL command. */
971     nlApThresholdParamList =
972         gScanCommand->attr_start(
973                                 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM);
974     if (!nlApThresholdParamList)
975         goto cleanup;
976 
977     /* Add nested NL attributes for AP Threshold Param list. */
978     for (i = 0; i < numAp; i++) {
979         ap_threshold_param apThreshold = params.ap[i];
980         struct nlattr *nlApThresholdParam = gScanCommand->attr_start(i);
981         if (!nlApThresholdParam)
982             goto cleanup;
983         if ( gScanCommand->put_addr(
984                 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_BSSID,
985                 apThreshold.bssid) ||
986             gScanCommand->put_s32(
987                 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_LOW,
988                 apThreshold.low) ||
989             gScanCommand->put_s32(
990                 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH,
991                 apThreshold.high))
992         {
993             goto cleanup;
994         }
995         ALOGI("%s: ap[%d].bssid:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx "
996               "ap[%d].low:%d  ap[%d].high:%d", __FUNCTION__,
997               i,
998               apThreshold.bssid[0], apThreshold.bssid[1],
999               apThreshold.bssid[2], apThreshold.bssid[3],
1000               apThreshold.bssid[4], apThreshold.bssid[5],
1001               i, apThreshold.low, i, apThreshold.high);
1002         gScanCommand->attr_end(nlApThresholdParam);
1003     }
1004 
1005     gScanCommand->attr_end(nlApThresholdParamList);
1006 
1007     gScanCommand->attr_end(nlData);
1008 
1009     GScanCallbackHandler callbackHandler;
1010     memset(&callbackHandler, 0, sizeof(callbackHandler));
1011     callbackHandler.on_significant_change = handler.on_significant_change;
1012 
1013     /* Create an object of the event handler class to take care of the
1014       * asychronous events on the north-bound.
1015       */
1016     if (gScanSetSignificantChangeCmdEventHandler == NULL) {
1017         gScanSetSignificantChangeCmdEventHandler =
1018             new GScanCommandEventHandler(
1019                      wifiHandle,
1020                      id,
1021                      OUI_QCA,
1022                      QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SIGNIFICANT_CHANGE,
1023                      callbackHandler);
1024         if (gScanSetSignificantChangeCmdEventHandler == NULL) {
1025             ALOGE("%s: Error in instantiating, "
1026                 "gScanSetSignificantChangeCmdEventHandler.",
1027                 __FUNCTION__);
1028             ret = WIFI_ERROR_UNKNOWN;
1029             goto cleanup;
1030         }
1031         event_handlers->gScanSetSignificantChangeCmdEventHandler =
1032             gScanSetSignificantChangeCmdEventHandler;
1033         ALOGD("%s: Event handler object was created for SIGNIFICANT_CHANGE.",
1034             __FUNCTION__);
1035     } else {
1036         gScanSetSignificantChangeCmdEventHandler->setCallbackHandler(callbackHandler);
1037     }
1038 
1039     ret = gScanCommand->requestResponse();
1040     if (ret != 0) {
1041         ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
1042         goto cleanup;
1043     }
1044 
1045     if (gScanSetSignificantChangeCmdEventHandler != NULL) {
1046         gScanSetSignificantChangeCmdEventHandler->set_request_id(id);
1047         gScanSetSignificantChangeCmdEventHandler->enableEventHandling();
1048     }
1049 
1050 cleanup:
1051     /* Disable Event Handling if ret != 0 */
1052     if (ret && gScanSetSignificantChangeCmdEventHandler) {
1053         ALOGI("%s: Error ret:%d, disable event handling",
1054             __FUNCTION__, ret);
1055         gScanSetSignificantChangeCmdEventHandler->disableEventHandling();
1056     }
1057     delete gScanCommand;
1058     return (wifi_error)ret;
1059 }
1060 
1061 /* Clear the GSCAN Significant AP change list. */
wifi_reset_significant_change_handler(wifi_request_id id,wifi_interface_handle iface)1062 wifi_error wifi_reset_significant_change_handler(wifi_request_id id,
1063                                             wifi_interface_handle iface)
1064 {
1065     int ret = 0;
1066     GScanCommand *gScanCommand;
1067     struct nlattr *nlData;
1068     interface_info *ifaceInfo = getIfaceInfo(iface);
1069     wifi_handle wifiHandle = getWifiHandle(iface);
1070     hal_info *info = getHalInfo(wifiHandle);
1071     lowi_cb_table_t *lowiWifiHalApi = NULL;
1072     gscan_event_handlers* event_handlers;
1073     GScanCommandEventHandler *gScanSetSignificantChangeCmdEventHandler;
1074 
1075     event_handlers = (gscan_event_handlers*)info->gscan_handlers;
1076     gScanSetSignificantChangeCmdEventHandler =
1077         event_handlers->gScanSetSignificantChangeCmdEventHandler;
1078 
1079     if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
1080         ALOGE("%s: GSCAN is not supported by driver",
1081             __FUNCTION__);
1082         return WIFI_ERROR_NOT_SUPPORTED;
1083     }
1084 
1085     /* Route request through LOWI if supported*/
1086     lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED);
1087     if (lowiWifiHalApi == NULL ||
1088         lowiWifiHalApi->reset_significant_change_handler == NULL) {
1089         ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
1090     } else {
1091         ret = lowiWifiHalApi->reset_significant_change_handler(id, iface);
1092         ALOGI("%s: lowi reset_significant_change_handler "
1093             "returned: %d. Exit.", __FUNCTION__, ret);
1094         return (wifi_error)ret;
1095     }
1096 
1097     ALOGI("%s: RequestId:%d", __FUNCTION__, id);
1098 
1099     if (gScanSetSignificantChangeCmdEventHandler == NULL ||
1100         (gScanSetSignificantChangeCmdEventHandler->isEventHandlingEnabled() ==
1101         false)) {
1102         ALOGE("wifi_reset_significant_change_handler: GSCAN significant_change"
1103             " isn't set. Nothing to do. Exit");
1104         return WIFI_ERROR_NOT_AVAILABLE;
1105     }
1106 
1107     gScanCommand =
1108         new GScanCommand
1109                     (
1110                     wifiHandle,
1111                     id,
1112                     OUI_QCA,
1113                     QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_SIGNIFICANT_CHANGE);
1114     if (gScanCommand == NULL) {
1115         ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
1116         return WIFI_ERROR_UNKNOWN;
1117     }
1118 
1119     /* Create the NL message. */
1120     ret = gScanCommand->create();
1121     if (ret < 0)
1122         goto cleanup;
1123 
1124     /* Set the interface Id of the message. */
1125     ret = gScanCommand->set_iface_id(ifaceInfo->name);
1126     if (ret < 0)
1127         goto cleanup;
1128 
1129     /* Add the vendor specific attributes for the NL command. */
1130     nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1131     if (!nlData)
1132         goto cleanup;
1133 
1134     ret = gScanCommand->put_u32(
1135                     QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
1136                     id);
1137     if (ret < 0)
1138         goto cleanup;
1139 
1140     gScanCommand->attr_end(nlData);
1141 
1142     ret = gScanCommand->requestResponse();
1143     if (ret != 0) {
1144         ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
1145     }
1146 
1147     /* Disable Event Handling. */
1148     if (gScanSetSignificantChangeCmdEventHandler) {
1149         gScanSetSignificantChangeCmdEventHandler->disableEventHandling();
1150     }
1151 
1152 cleanup:
1153     delete gScanCommand;
1154     return (wifi_error)ret;
1155 }
1156 
1157 /* 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)1158 wifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface,
1159                                             byte flush, int max,
1160                                             wifi_cached_scan_results *results,
1161                                             int *num)
1162 {
1163     int requestId, ret = 0, retRequestRsp = 0;
1164     wifi_cached_scan_results *result = results;
1165     u32 j = 0;
1166     int i = 0;
1167     u8 moreData = 0;
1168     u16 waitTime = GSCAN_EVENT_WAIT_TIME_SECONDS;
1169     GScanCommand *gScanCommand;
1170     struct nlattr *nlData;
1171     wifi_cached_scan_results *cached_results;
1172     lowi_cb_table_t *lowiWifiHalApi = NULL;
1173 
1174     interface_info *ifaceInfo = getIfaceInfo(iface);
1175     wifi_handle wifiHandle = getWifiHandle(iface);
1176     hal_info *info = getHalInfo(wifiHandle);
1177 
1178     if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
1179         ALOGE("%s: GSCAN is not supported by driver",
1180             __FUNCTION__);
1181         return WIFI_ERROR_NOT_SUPPORTED;
1182     }
1183 
1184     /* Route GSCAN request through LOWI if supported */
1185     lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED);
1186     if (lowiWifiHalApi == NULL ||
1187         lowiWifiHalApi->get_cached_gscan_results == NULL) {
1188         ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
1189     } else {
1190         ret = lowiWifiHalApi->get_cached_gscan_results(iface,
1191                                                        flush,
1192                                                        max,
1193                                                        results,
1194                                                        num);
1195         ALOGI("%s: lowi get_cached_gscan_results"
1196             "returned: %d. Exit.", __FUNCTION__, ret);
1197         return (wifi_error)ret;
1198     }
1199 
1200     /* No request id from caller, so generate one and pass it on to the driver. */
1201     /* Generate it randomly */
1202     requestId = get_requestid();
1203     ALOGI("%s: RequestId:%d", __FUNCTION__, requestId);
1204 
1205     if (results == NULL || num == NULL) {
1206         ALOGE("%s: NULL pointer provided. Exit.",
1207             __FUNCTION__);
1208         return WIFI_ERROR_INVALID_ARGS;
1209     }
1210 
1211     gScanCommand = new GScanCommand(
1212                         wifiHandle,
1213                         requestId,
1214                         OUI_QCA,
1215                         QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS);
1216     if (gScanCommand == NULL) {
1217         ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
1218         return WIFI_ERROR_UNKNOWN;
1219     }
1220 
1221     ret = gScanCommand->allocRspParams(eGScanGetCachedResultsRspParams);
1222     if (ret != 0) {
1223         ALOGE("%s: Failed to allocate memory for response struct. Error:%d",
1224             __FUNCTION__, ret);
1225         goto cleanup;
1226     }
1227 
1228     ret = gScanCommand->allocCachedResultsTemp(max, results);
1229     if (ret != 0) {
1230         ALOGE("%s: Failed to allocate memory for temp gscan cached list. "
1231             "Error:%d", __FUNCTION__, ret);
1232         goto cleanup;
1233     }
1234 
1235     /* Clear the destination cached results list before copying results. */
1236     memset(results, 0, max * sizeof(wifi_cached_scan_results));
1237 
1238     /* Create the NL message. */
1239     ret = gScanCommand->create();
1240     if (ret < 0)
1241         goto cleanup;
1242 
1243     /* Set the interface Id of the message. */
1244     ret = gScanCommand->set_iface_id(ifaceInfo->name);
1245     if (ret < 0)
1246         goto cleanup;
1247 
1248     /* Add the vendor specific attributes for the NL command. */
1249     nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1250     if (!nlData)
1251         goto cleanup;
1252 
1253     if (ret < 0)
1254         goto cleanup;
1255 
1256     if (gScanCommand->put_u32(
1257          QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
1258             requestId) ||
1259         gScanCommand->put_u8(
1260          QCA_WLAN_VENDOR_ATTR_GSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH,
1261             flush) ||
1262         gScanCommand->put_u32(
1263          QCA_WLAN_VENDOR_ATTR_GSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX,
1264             max))
1265     {
1266         goto cleanup;
1267     }
1268 
1269     ALOGI("%s: flush:%d max:%d", __FUNCTION__, flush, max);
1270     gScanCommand->attr_end(nlData);
1271 
1272     retRequestRsp = gScanCommand->requestResponse();
1273     if (retRequestRsp != 0) {
1274         ALOGE("%s: requestResponse Error:%d",
1275             __FUNCTION__, retRequestRsp);
1276         if (retRequestRsp != -ETIMEDOUT) {
1277             /* Proceed to cleanup & return no results */
1278             goto cleanup;
1279         }
1280     }
1281 
1282     /* No more data, copy the parsed results into the caller's results array */
1283     ret = gScanCommand->copyCachedScanResults(num, results);
1284     ALOGI("%s: max: %d, num:%d", __FUNCTION__, max, *num);
1285 
1286     if (!ret) {
1287         /* If requestResponse returned a TIMEOUT */
1288         if (retRequestRsp == -ETIMEDOUT) {
1289             if (*num > 0) {
1290                 /* Mark scan results as incomplete for the last scan_id */
1291                 results[(*num)-1].flags = WIFI_SCAN_FLAG_INTERRUPTED;
1292                 ALOGD("%s: Timeout happened. Mark scan results as incomplete "
1293                     "for scan_id:%d", __FUNCTION__, results[(*num)-1].scan_id);
1294                 ret = WIFI_SUCCESS;
1295             } else
1296                 ret = WIFI_ERROR_TIMED_OUT;
1297         }
1298     }
1299 cleanup:
1300     gScanCommand->freeRspParams(eGScanGetCachedResultsRspParams);
1301     delete gScanCommand;
1302     return (wifi_error)ret;
1303 }
1304 
1305 /* Random MAC OUI for PNO */
wifi_set_scanning_mac_oui(wifi_interface_handle handle,oui scan_oui)1306 wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui)
1307 {
1308     int ret = 0;
1309     struct nlattr *nlData;
1310     WifiVendorCommand *vCommand = NULL;
1311     interface_info *iinfo = getIfaceInfo(handle);
1312     wifi_handle wifiHandle = getWifiHandle(handle);
1313 
1314     vCommand = new WifiVendorCommand(wifiHandle, 0,
1315             OUI_QCA,
1316             QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI);
1317     if (vCommand == NULL) {
1318         ALOGE("%s: Error vCommand NULL", __FUNCTION__);
1319         return WIFI_ERROR_OUT_OF_MEMORY;
1320     }
1321 
1322     /* create the message */
1323     ret = vCommand->create();
1324     if (ret < 0)
1325         goto cleanup;
1326 
1327     ret = vCommand->set_iface_id(iinfo->name);
1328     if (ret < 0)
1329         goto cleanup;
1330 
1331     /* Add the vendor specific attributes for the NL command. */
1332     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1333     if (!nlData)
1334         goto cleanup;
1335 
1336     ALOGI("%s: MAC_OUI - %02x:%02x:%02x", __FUNCTION__,
1337           scan_oui[0], scan_oui[1], scan_oui[2]);
1338 
1339     /* Add the fixed part of the mac_oui to the nl command */
1340     ret = vCommand->put_bytes(
1341             QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI,
1342             (char *)scan_oui,
1343             WIFI_SCANNING_MAC_OUI_LENGTH);
1344     if (ret < 0)
1345         goto cleanup;
1346 
1347     vCommand->attr_end(nlData);
1348 
1349     ret = vCommand->requestResponse();
1350     if (ret != 0) {
1351         ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
1352         goto cleanup;
1353     }
1354 
1355 cleanup:
1356     delete vCommand;
1357     return (wifi_error)ret;
1358 }
1359 
1360 
1361 /* Set the GSCAN SSID Hotlist. */
wifi_set_ssid_hotlist(wifi_request_id id,wifi_interface_handle iface,wifi_ssid_hotlist_params params,wifi_hotlist_ssid_handler handler)1362 wifi_error wifi_set_ssid_hotlist(wifi_request_id id,
1363                                     wifi_interface_handle iface,
1364                                     wifi_ssid_hotlist_params params,
1365                                     wifi_hotlist_ssid_handler handler)
1366 {
1367     int i, numSsid, ret = 0;
1368     GScanCommand *gScanCommand;
1369     struct nlattr *nlData, *nlSsidThresholdParamList;
1370     interface_info *ifaceInfo = getIfaceInfo(iface);
1371     wifi_handle wifiHandle = getWifiHandle(iface);
1372     bool previousGScanSetSsidRunning = false;
1373     hal_info *info = getHalInfo(wifiHandle);
1374     lowi_cb_table_t *lowiWifiHalApi = NULL;
1375     gscan_event_handlers* event_handlers;
1376     GScanCommandEventHandler *gScanSetSsidHotlistCmdEventHandler;
1377 
1378     event_handlers = (gscan_event_handlers*)info->gscan_handlers;
1379     gScanSetSsidHotlistCmdEventHandler =
1380         event_handlers->gScanSetSsidHotlistCmdEventHandler;
1381 
1382     if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
1383         ALOGE("%s: GSCAN is not supported by driver",
1384             __FUNCTION__);
1385         return WIFI_ERROR_NOT_SUPPORTED;
1386     }
1387 
1388     /* Route request through LOWI if supported*/
1389     lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED);
1390     if (lowiWifiHalApi == NULL ||
1391         lowiWifiHalApi->set_ssid_hotlist == NULL) {
1392         ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
1393     } else {
1394         ret = lowiWifiHalApi->set_ssid_hotlist(id, iface, params,handler);
1395         ALOGI("%s: lowi set_ssid_hotlist "
1396             "returned: %d. Exit.", __FUNCTION__, ret);
1397         return (wifi_error)ret;
1398     }
1399 
1400     ALOGI("%s: RequestId:%d", __FUNCTION__, id);
1401 
1402     /* Wi-Fi HAL doesn't need to check if a similar request to set ssid
1403      * hotlist was made earlier. If set_ssid_hotlist() is called while
1404      * another one is running, the request will be sent down to driver and
1405      * firmware. If the new request is successfully honored, then Wi-Fi HAL
1406      * will use the new request id for the gScanSetSsidHotlistCmdEventHandler
1407      * object.
1408      */
1409 
1410     gScanCommand =
1411         new GScanCommand(
1412                     wifiHandle,
1413                     id,
1414                     OUI_QCA,
1415                     QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SSID_HOTLIST);
1416     if (gScanCommand == NULL) {
1417         ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
1418         return WIFI_ERROR_UNKNOWN;
1419     }
1420 
1421     /* Create the NL message. */
1422     ret = gScanCommand->create();
1423     if (ret < 0)
1424         goto cleanup;
1425 
1426     /* Set the interface Id of the message. */
1427     ret = gScanCommand->set_iface_id(ifaceInfo->name);
1428     if (ret < 0)
1429         goto cleanup;
1430 
1431     /* Add the vendor specific attributes for the NL command. */
1432     nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1433     if (!nlData)
1434         goto cleanup;
1435 
1436     numSsid = (unsigned int)params.num_ssid > MAX_HOTLIST_SSID ?
1437         MAX_HOTLIST_SSID : params.num_ssid;
1438     if (gScanCommand->put_u32(
1439             QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
1440             id) ||
1441         gScanCommand->put_u32(
1442         QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE,
1443             params.lost_ssid_sample_size) ||
1444         gScanCommand->put_u32(
1445             QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_HOTLIST_PARAMS_NUM_SSID,
1446             numSsid))
1447     {
1448         goto cleanup;
1449     }
1450     ALOGI("%s: numSsid:%d "
1451           "lost_ssid_sameple_size: %d",
1452           __FUNCTION__, numSsid,
1453           params.lost_ssid_sample_size);
1454 
1455     /* Add the vendor specific attributes for the NL command. */
1456     nlSsidThresholdParamList =
1457         gScanCommand->attr_start(
1458                             QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM);
1459     if (!nlSsidThresholdParamList)
1460         goto cleanup;
1461 
1462     /* Add nested NL attributes for SSID Threshold Param. */
1463     for (i = 0; i < numSsid; i++) {
1464         ssid_threshold_param ssidThreshold = params.ssid[i];
1465         struct nlattr *nlSsidThresholdParam = gScanCommand->attr_start(i);
1466         if (!nlSsidThresholdParam)
1467             goto cleanup;
1468         if (gScanCommand->put_string(
1469                 QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_SSID,
1470                 ssidThreshold.ssid) ||
1471             gScanCommand->put_u8(
1472                 QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_BAND,
1473                 ssidThreshold.band) ||
1474             gScanCommand->put_s32(
1475                 QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW,
1476                 ssidThreshold.low) ||
1477             gScanCommand->put_s32(
1478                 QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH,
1479                 ssidThreshold.high))
1480         {
1481             goto cleanup;
1482         }
1483         ALOGI("%s: SSID[%d].ssid:%s "
1484               "SSID[%d].band:%d SSID[%d].low:%d "
1485               "SSID[%d].high:%d", __FUNCTION__,
1486               i, ssidThreshold.ssid,
1487               i, ssidThreshold.band,
1488               i, ssidThreshold.low,
1489               i, ssidThreshold.high);
1490         gScanCommand->attr_end(nlSsidThresholdParam);
1491     }
1492 
1493     gScanCommand->attr_end(nlSsidThresholdParamList);
1494 
1495     gScanCommand->attr_end(nlData);
1496 
1497     GScanCallbackHandler callbackHandler;
1498     memset(&callbackHandler, 0, sizeof(callbackHandler));
1499     callbackHandler.on_hotlist_ssid_found = handler.on_hotlist_ssid_found;
1500     callbackHandler.on_hotlist_ssid_lost = handler.on_hotlist_ssid_lost;
1501 
1502     /* Create an object of the event handler class to take care of the
1503       * asychronous events on the north-bound.
1504       */
1505     if (gScanSetSsidHotlistCmdEventHandler == NULL) {
1506         gScanSetSsidHotlistCmdEventHandler = new GScanCommandEventHandler(
1507                             wifiHandle,
1508                             id,
1509                             OUI_QCA,
1510                             QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SSID_HOTLIST,
1511                             callbackHandler);
1512         if (gScanSetSsidHotlistCmdEventHandler == NULL) {
1513             ALOGE("%s: Error instantiating "
1514                 "gScanSetSsidHotlistCmdEventHandler.", __FUNCTION__);
1515             ret = WIFI_ERROR_UNKNOWN;
1516             goto cleanup;
1517         }
1518         ALOGD("%s: Handler object was created for HOTLIST_AP_FOUND.", __FUNCTION__);
1519         event_handlers->gScanSetSsidHotlistCmdEventHandler =
1520             gScanSetSsidHotlistCmdEventHandler;
1521     } else {
1522         gScanSetSsidHotlistCmdEventHandler->setCallbackHandler(callbackHandler);
1523     }
1524 
1525     ret = gScanCommand->requestResponse();
1526     if (ret != 0) {
1527         ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
1528         goto cleanup;
1529     }
1530 
1531     if (gScanSetSsidHotlistCmdEventHandler != NULL) {
1532         gScanSetSsidHotlistCmdEventHandler->set_request_id(id);
1533         gScanSetSsidHotlistCmdEventHandler->enableEventHandling();
1534     }
1535 
1536 cleanup:
1537     delete gScanCommand;
1538     /* Disable Event Handling if ret != 0 */
1539     if (ret && gScanSetSsidHotlistCmdEventHandler) {
1540         ALOGI("%s: Error ret:%d, disable event handling",
1541             __FUNCTION__, ret);
1542         gScanSetSsidHotlistCmdEventHandler->disableEventHandling();
1543     }
1544     return (wifi_error)ret;
1545 }
1546 
wifi_reset_ssid_hotlist(wifi_request_id id,wifi_interface_handle iface)1547 wifi_error wifi_reset_ssid_hotlist(wifi_request_id id,
1548                             wifi_interface_handle iface)
1549 {
1550     int ret = 0;
1551     GScanCommand *gScanCommand;
1552     struct nlattr *nlData;
1553     interface_info *ifaceInfo = getIfaceInfo(iface);
1554     wifi_handle wifiHandle = getWifiHandle(iface);
1555     hal_info *info = getHalInfo(wifiHandle);
1556     lowi_cb_table_t *lowiWifiHalApi = NULL;
1557     gscan_event_handlers* event_handlers;
1558     GScanCommandEventHandler *gScanSetSsidHotlistCmdEventHandler;
1559 
1560     event_handlers = (gscan_event_handlers*)info->gscan_handlers;
1561     gScanSetSsidHotlistCmdEventHandler =
1562         event_handlers->gScanSetSsidHotlistCmdEventHandler;
1563 
1564     if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
1565         ALOGE("%s: GSCAN is not supported by driver",
1566             __FUNCTION__);
1567         return WIFI_ERROR_NOT_SUPPORTED;
1568     }
1569 
1570     /* Route request through LOWI if supported*/
1571     lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED);
1572     if (lowiWifiHalApi == NULL ||
1573         lowiWifiHalApi->reset_ssid_hotlist == NULL) {
1574         ALOGD("%s: Sending cmd directly to host", __FUNCTION__);
1575     } else {
1576         ret = lowiWifiHalApi->reset_ssid_hotlist(id, iface);
1577         ALOGI("%s: lowi reset_ssid_hotlist "
1578             "returned: %d. Exit.", __FUNCTION__, ret);
1579         return (wifi_error)ret;
1580     }
1581 
1582     ALOGI("%s: RequestId:%d", __FUNCTION__, id);
1583 
1584     if (gScanSetSsidHotlistCmdEventHandler == NULL ||
1585         (gScanSetSsidHotlistCmdEventHandler->isEventHandlingEnabled() ==
1586         false)) {
1587         ALOGE("wifi_reset_ssid_hotlist: GSCAN ssid_hotlist isn't set. "
1588             "Nothing to do. Exit");
1589         return WIFI_ERROR_NOT_AVAILABLE;
1590     }
1591 
1592     gScanCommand = new GScanCommand(
1593                         wifiHandle,
1594                         id,
1595                         OUI_QCA,
1596                         QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_SSID_HOTLIST);
1597 
1598     if (gScanCommand == NULL) {
1599         ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
1600         return WIFI_ERROR_UNKNOWN;
1601     }
1602 
1603     /* Create the NL message. */
1604     ret = gScanCommand->create();
1605     if (ret < 0)
1606         goto cleanup;
1607 
1608     /* Set the interface Id of the message. */
1609     ret = gScanCommand->set_iface_id(ifaceInfo->name);
1610     if (ret < 0)
1611         goto cleanup;
1612 
1613     /* Add the vendor specific attributes for the NL command. */
1614     nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1615     if (!nlData)
1616         goto cleanup;
1617 
1618     ret = gScanCommand->put_u32(
1619             QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, id);
1620     if (ret < 0)
1621         goto cleanup;
1622 
1623     gScanCommand->attr_end(nlData);
1624 
1625     ret = gScanCommand->requestResponse();
1626     if (ret != 0) {
1627         ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
1628     }
1629 
1630     /* Disable Event Handling. */
1631     if (gScanSetSsidHotlistCmdEventHandler) {
1632         gScanSetSsidHotlistCmdEventHandler->disableEventHandling();
1633     }
1634 
1635 cleanup:
1636     delete gScanCommand;
1637     return (wifi_error)ret;
1638 }
1639 
1640 
GScanCommand(wifi_handle handle,int id,u32 vendor_id,u32 subcmd)1641 GScanCommand::GScanCommand(wifi_handle handle, int id, u32 vendor_id,
1642                                   u32 subcmd)
1643         : WifiVendorCommand(handle, id, vendor_id, subcmd)
1644 {
1645 #ifdef QC_HAL_DEBUG
1646     ALOGD("GScanCommand %p constructed", this);
1647 #endif
1648     /* Initialize the member data variables here */
1649     mGetCapabilitiesRspParams = NULL;
1650     mGetCachedResultsRspParams = NULL;
1651     mChannels = NULL;
1652     mMaxChannels = 0;
1653     mNumChannelsPtr = NULL;
1654 
1655     mRequestId = id;
1656     memset(&mHandler, 0,sizeof(mHandler));
1657 }
1658 
~GScanCommand()1659 GScanCommand::~GScanCommand()
1660 {
1661 #ifdef QC_HAL_DEBUG
1662     ALOGD("GScanCommand %p destructor", this);
1663 #endif
1664     unregisterVendorHandler(mVendor_id, mSubcmd);
1665 }
1666 
1667 
1668 /* This function implements creation of Vendor command */
create()1669 int GScanCommand::create() {
1670     int ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
1671     if (ret < 0) {
1672         return ret;
1673     }
1674 
1675     /* Insert the oui in the msg */
1676     ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
1677     if (ret < 0)
1678         goto out;
1679     /* Insert the subcmd in the msg */
1680     ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
1681     if (ret < 0)
1682         goto out;
1683 
1684 #ifdef QC_HAL_DEBUG
1685      ALOGI("%s: mVendor_id = %d, Subcmd = %d.",
1686         __FUNCTION__, mVendor_id, mSubcmd);
1687 #endif
1688 
1689 out:
1690     return ret;
1691 }
1692 
1693 /* Callback handlers registered for nl message send */
error_handler_gscan(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)1694 static int error_handler_gscan(struct sockaddr_nl *nla, struct nlmsgerr *err,
1695                                    void *arg)
1696 {
1697     struct sockaddr_nl *tmp;
1698     int *ret = (int *)arg;
1699     tmp = nla;
1700     *ret = err->error;
1701     ALOGE("%s: Error code:%d (%s)", __FUNCTION__, *ret, strerror(-(*ret)));
1702     return NL_STOP;
1703 }
1704 
1705 /* Callback handlers registered for nl message send */
ack_handler_gscan(struct nl_msg * msg,void * arg)1706 static int ack_handler_gscan(struct nl_msg *msg, void *arg)
1707 {
1708     int *ret = (int *)arg;
1709     struct nl_msg * a;
1710 
1711     ALOGE("%s: called", __FUNCTION__);
1712     a = msg;
1713     *ret = 0;
1714     return NL_STOP;
1715 }
1716 
1717 /* Callback handlers registered for nl message send */
finish_handler_gscan(struct nl_msg * msg,void * arg)1718 static int finish_handler_gscan(struct nl_msg *msg, void *arg)
1719 {
1720   int *ret = (int *)arg;
1721   struct nl_msg * a;
1722 
1723   ALOGE("%s: called", __FUNCTION__);
1724   a = msg;
1725   *ret = 0;
1726   return NL_SKIP;
1727 }
1728 
requestResponse()1729 int GScanCommand::requestResponse()
1730 {
1731     return WifiCommand::requestResponse(mMsg);
1732 }
1733 
handleResponse(WifiEvent & reply)1734 int GScanCommand::handleResponse(WifiEvent &reply) {
1735     u32 status;
1736     int i = 0;
1737     int ret = WIFI_SUCCESS;
1738     u32 val;
1739 
1740     WifiVendorCommand::handleResponse(reply);
1741 
1742     struct nlattr *tbVendor[
1743         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
1744     nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
1745                 (struct nlattr *)mVendorData,mDataLen, NULL);
1746 
1747     switch(mSubcmd)
1748     {
1749         case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_VALID_CHANNELS:
1750         {
1751             if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_CHANNELS]) {
1752                 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_CHANNELS"
1753                     " not found", __FUNCTION__);
1754                 ret = WIFI_ERROR_INVALID_ARGS;
1755                 break;
1756             }
1757             val = nla_get_u32(tbVendor[
1758                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_CHANNELS]);
1759 
1760             val = val > (unsigned int)mMaxChannels ?
1761                     (unsigned int)mMaxChannels : val;
1762             *mNumChannelsPtr = val;
1763 
1764             /* Extract the list of channels. */
1765             if (*mNumChannelsPtr > 0 ) {
1766                 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CHANNELS]) {
1767                     ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CHANNELS"
1768                         " not found", __FUNCTION__);
1769                     ret = WIFI_ERROR_INVALID_ARGS;
1770                     break;
1771                 }
1772                 nla_memcpy(mChannels,
1773                     tbVendor[
1774                     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CHANNELS],
1775                     sizeof(wifi_channel) * (*mNumChannelsPtr));
1776             }
1777 
1778             ALOGD("%s: Get valid channels response received.",
1779                 __FUNCTION__);
1780             ALOGD("%s: Num channels : %d",
1781                 __FUNCTION__, *mNumChannelsPtr);
1782             ALOGD("%s: List of valid channels are: ", __FUNCTION__);
1783             for(i = 0; i < *mNumChannelsPtr; i++)
1784             {
1785                 ALOGD("%u", *(mChannels + i));
1786             }
1787         }
1788         break;
1789         case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES:
1790         {
1791             ret = gscan_parse_capabilities(tbVendor);
1792             if (ret) {
1793                 break;
1794             }
1795 
1796             if (mGetCapabilitiesRspParams) {
1797                 wifi_gscan_capabilities capa =
1798                     mGetCapabilitiesRspParams->capabilities;
1799                 ALOGI("%s: max_ap_cache_per_scan:%d\n"
1800                         "max_bssid_history_entries:%d\n"
1801                         "max_hotlist_bssids:%d\n"
1802                         "max_hotlist_ssids:%d\n"
1803                         "max_rssi_sample_size:%d\n"
1804                         "max_scan_buckets:%d\n"
1805                         "max_scan_cache_size:%d\n"
1806                         "max_scan_reporting_threshold:%d\n"
1807                         "max_significant_wifi_change_aps:%d\n"
1808                         "max_number_epno_networks:%d\n"
1809                         "max_number_epno_networks_by_ssid:%d\n"
1810                         "max_number_of_white_listed_ssid:%d.",
1811                         __FUNCTION__, capa.max_ap_cache_per_scan,
1812                         capa.max_bssid_history_entries,
1813                         capa.max_hotlist_bssids,
1814                         capa.max_hotlist_ssids,
1815                         capa.max_rssi_sample_size,
1816                         capa.max_scan_buckets,
1817                         capa.max_scan_cache_size,
1818                         capa.max_scan_reporting_threshold,
1819                         capa.max_significant_wifi_change_aps,
1820                         capa.max_number_epno_networks,
1821                         capa.max_number_epno_networks_by_ssid,
1822                         capa.max_number_of_white_listed_ssid);
1823             }
1824         }
1825         break;
1826         case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS:
1827         {
1828             wifi_request_id id;
1829             u32 numResults = 0;
1830             u32 startingIndex;
1831             int firstScanIdInPatch = -1;
1832 
1833             if (!tbVendor[
1834                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]) {
1835                 ALOGE("%s: GSCAN_RESULTS_REQUEST_ID not"
1836                     "found", __FUNCTION__);
1837                 ret = WIFI_ERROR_INVALID_ARGS;
1838                 break;
1839             }
1840             id = nla_get_u32(
1841                     tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]
1842                     );
1843             /* If this is not for us, just ignore it. */
1844             if (id != mRequestId) {
1845                 ALOGE("%s: Event has Req. ID:%d <> ours:%d",
1846                     __FUNCTION__, id, mRequestId);
1847                 break;
1848             }
1849             if (!tbVendor[
1850                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]) {
1851                 ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not"
1852                     "found", __FUNCTION__);
1853                 ret = WIFI_ERROR_INVALID_ARGS;
1854                 break;
1855             }
1856             /* Read num of cached scan results in this data chunk. Note that
1857              * this value doesn't represent the number of unique gscan scan Ids
1858              * since the first scan id in this new chunk could be similar to
1859              * the last scan id in the previous chunk.
1860              */
1861             numResults = nla_get_u32(tbVendor[
1862                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]);
1863             ALOGE("%s: num Cached results in this fragment:%d",
1864                        __FUNCTION__, numResults);
1865 
1866             if (!mGetCachedResultsRspParams) {
1867                 ALOGE("%s: mGetCachedResultsRspParams is NULL, exit.",
1868                     __FUNCTION__);
1869                 ret = WIFI_ERROR_INVALID_ARGS;
1870                 break;
1871             }
1872 
1873             /* To support fragmentation from firmware, monitor the
1874              * MORE_DATA flag and cache results until MORE_DATA = 0.
1875              */
1876             if (!tbVendor[
1877                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]) {
1878                 ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_MORE_DATA "
1879                     "not found", __FUNCTION__);
1880                 ret = WIFI_ERROR_INVALID_ARGS;
1881                 break;
1882             } else {
1883                 mGetCachedResultsRspParams->more_data = nla_get_u8(
1884                     tbVendor[
1885                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]);
1886             }
1887 
1888             /* No data in this chunk so skip this chunk */
1889             if (numResults == 0) {
1890                 return NL_SKIP;
1891             }
1892 
1893             if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID]) {
1894                 ALOGE("GSCAN_CACHED_RESULTS_SCAN_ID not found");
1895                 ret = WIFI_ERROR_INVALID_ARGS;
1896                 break;
1897             }
1898 
1899             /* Get the first Scan-Id in this chuck of cached results. */
1900             firstScanIdInPatch = nla_get_u32(tbVendor[
1901                     QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID]);
1902 
1903             ALOGE("More data: %d, firstScanIdInPatch: %d, lastProcessedScanId: %d",
1904                 mGetCachedResultsRspParams->more_data, firstScanIdInPatch,
1905                 mGetCachedResultsRspParams->lastProcessedScanId);
1906 
1907             if (numResults) {
1908                 if (firstScanIdInPatch !=
1909                     mGetCachedResultsRspParams->lastProcessedScanId) {
1910                     /* New result scan Id block, update the starting index. */
1911                     mGetCachedResultsRspParams->cachedResultsStartingIndex++;
1912                 }
1913 
1914                 ret = gscan_get_cached_results(
1915                                     mGetCachedResultsRspParams->cached_results,
1916                                     tbVendor);
1917                 /* If a parsing error occurred, exit and proceed for cleanup. */
1918                 if (ret)
1919                     break;
1920             }
1921         }
1922         break;
1923         default:
1924             /* Error case should not happen print log */
1925             ALOGE("%s: Wrong GScan subcmd response received %d",
1926                 __FUNCTION__, mSubcmd);
1927     }
1928 
1929     /* A parsing error occurred, do the cleanup of gscan result lists. */
1930     if (ret) {
1931         switch(mSubcmd)
1932         {
1933             case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS:
1934             {
1935                 ALOGE("%s: Parsing error, free CachedResultsRspParams",
1936                     __FUNCTION__);
1937                 freeRspParams(eGScanGetCachedResultsRspParams);
1938             }
1939             break;
1940             case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES:
1941             {
1942                 ALOGE("%s: Parsing error, free CapabilitiesRspParams",
1943                     __FUNCTION__);
1944                 freeRspParams(eGScanGetCapabilitiesRspParams);
1945             }
1946             break;
1947             default:
1948                 ALOGE("%s: Wrong GScan subcmd received %d", __FUNCTION__, mSubcmd);
1949         }
1950     }
1951     return NL_SKIP;
1952 }
1953 
1954 /* Parses and extracts gscan capabilities results. */
gscan_parse_capabilities(struct nlattr ** tbVendor)1955 int GScanCommand::gscan_parse_capabilities(struct nlattr **tbVendor)
1956 {
1957     if (!mGetCapabilitiesRspParams){
1958         ALOGE("%s: mGetCapabilitiesRspParams ptr is NULL. Exit.",
1959             __FUNCTION__);
1960         return WIFI_ERROR_INVALID_ARGS;
1961     }
1962 
1963     if (!tbVendor[
1964     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE
1965             ]) {
1966         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_"
1967             "CAPABILITIES_MAX_SCAN_CACHE_SIZE not found", __FUNCTION__);
1968         return WIFI_ERROR_INVALID_ARGS;
1969     }
1970     mGetCapabilitiesRspParams->capabilities.max_scan_cache_size =
1971         nla_get_u32(tbVendor[
1972         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE]);
1973 
1974     if (!tbVendor[
1975     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS
1976             ]) {
1977         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
1978             "_SCAN_BUCKETS not found", __FUNCTION__);
1979         return WIFI_ERROR_INVALID_ARGS;
1980     }
1981     mGetCapabilitiesRspParams->capabilities.max_scan_buckets =
1982         nla_get_u32(tbVendor[
1983         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS]
1984                         );
1985 
1986     if (!tbVendor[
1987     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN
1988             ]) {
1989         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
1990             "_AP_CACHE_PER_SCAN not found", __FUNCTION__);
1991         return WIFI_ERROR_INVALID_ARGS;
1992     }
1993     mGetCapabilitiesRspParams->capabilities.max_ap_cache_per_scan =
1994             nla_get_u32(tbVendor[
1995         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN]);
1996 
1997     if (!tbVendor[
1998     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE
1999             ]) {
2000         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
2001             "_RSSI_SAMPLE_SIZE not found", __FUNCTION__);
2002         return WIFI_ERROR_INVALID_ARGS;
2003     }
2004     mGetCapabilitiesRspParams->capabilities.max_rssi_sample_size =
2005         nla_get_u32(tbVendor[
2006         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE]);
2007 
2008     if (!tbVendor[
2009     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD
2010             ]) {
2011         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_"
2012             "MAX_SCAN_REPORTING_THRESHOLD not found", __FUNCTION__);
2013         return WIFI_ERROR_INVALID_ARGS;
2014     }
2015     mGetCapabilitiesRspParams->capabilities.max_scan_reporting_threshold =
2016             nla_get_u32(tbVendor[
2017     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD
2018     ]);
2019 
2020     if (!tbVendor[
2021     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS
2022             ]) {
2023         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_"
2024             "MAX_HOTLIST_BSSIDS not found", __FUNCTION__);
2025         return WIFI_ERROR_INVALID_ARGS;
2026     }
2027     mGetCapabilitiesRspParams->capabilities.max_hotlist_bssids =
2028             nla_get_u32(tbVendor[
2029             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS]);
2030 
2031     if (!tbVendor[
2032     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS
2033             ]) {
2034         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
2035             "_SIGNIFICANT_WIFI_CHANGE_APS not found", __FUNCTION__);
2036         return WIFI_ERROR_INVALID_ARGS;
2037     }
2038     mGetCapabilitiesRspParams->capabilities.max_significant_wifi_change_aps =
2039             nla_get_u32(tbVendor[
2040     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS]);
2041 
2042     if (!tbVendor[
2043     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES
2044             ]) {
2045         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
2046             "_BSSID_HISTORY_ENTRIES not found", __FUNCTION__);
2047         return WIFI_ERROR_INVALID_ARGS;
2048     }
2049     mGetCapabilitiesRspParams->capabilities.max_bssid_history_entries =
2050             nla_get_u32(tbVendor[
2051     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES
2052     ]);
2053 
2054     if (!tbVendor[
2055     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS
2056             ]) {
2057         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES"
2058             "_MAX_HOTLIST_SSIDS not found. Set to 0.", __FUNCTION__);
2059         mGetCapabilitiesRspParams->capabilities.max_hotlist_ssids = 0;
2060     } else {
2061         mGetCapabilitiesRspParams->capabilities.max_hotlist_ssids =
2062                 nla_get_u32(tbVendor[
2063         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS
2064         ]);
2065     }
2066 
2067     if (!tbVendor[
2068     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS
2069             ]) {
2070         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
2071             "_NUM_EPNO_NETS not found. Set to 0.", __FUNCTION__);
2072         mGetCapabilitiesRspParams->capabilities.\
2073             max_number_epno_networks = 0;
2074     } else {
2075         mGetCapabilitiesRspParams->capabilities.max_number_epno_networks
2076             = nla_get_u32(tbVendor[
2077         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS
2078         ]);
2079     }
2080 
2081     if (!tbVendor[
2082     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID
2083             ]) {
2084         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
2085             "_NUM_EPNO_NETS_BY_SSID not found. Set to 0.", __FUNCTION__);
2086         mGetCapabilitiesRspParams->capabilities.\
2087             max_number_epno_networks_by_ssid = 0;
2088     } else {
2089         mGetCapabilitiesRspParams->capabilities.max_number_epno_networks_by_ssid
2090             = nla_get_u32(tbVendor[
2091         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID
2092         ]);
2093     }
2094 
2095     if (!tbVendor[
2096        QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID
2097             ]) {
2098         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
2099             "_NUM_WHITELISTED_SSID not found. Set to 0.", __FUNCTION__);
2100         mGetCapabilitiesRspParams->capabilities.\
2101             max_number_of_white_listed_ssid = 0;
2102     } else {
2103         mGetCapabilitiesRspParams->capabilities.max_number_of_white_listed_ssid
2104             = nla_get_u32(tbVendor[
2105         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID
2106         ]);
2107     }
2108     return WIFI_SUCCESS;
2109 }
2110 
2111 /* Called to parse and extract cached results. */
gscan_get_cached_results(wifi_cached_scan_results * cached_results,struct nlattr ** tb_vendor)2112 int GScanCommand:: gscan_get_cached_results(
2113                                       wifi_cached_scan_results *cached_results,
2114                                       struct nlattr **tb_vendor)
2115 {
2116     u32 j = 0;
2117     struct nlattr *scanResultsInfo, *wifiScanResultsInfo;
2118     int rem = 0, remResults = 0;
2119     u32 len = 0, numScanResults = 0;
2120     u32 i = mGetCachedResultsRspParams->cachedResultsStartingIndex;
2121     ALOGE("%s: starting counter: %d", __FUNCTION__, i);
2122 
2123     for (scanResultsInfo = (struct nlattr *) nla_data(tb_vendor[
2124                QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_LIST]),
2125                rem = nla_len(tb_vendor[
2126                QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_LIST]);
2127            nla_ok(scanResultsInfo, rem) && i < mGetCachedResultsRspParams->max;
2128            scanResultsInfo = nla_next(scanResultsInfo, &(rem)))
2129        {
2130            struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
2131            nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
2132            (struct nlattr *) nla_data(scanResultsInfo),
2133                    nla_len(scanResultsInfo), NULL);
2134 
2135            if (!
2136                tb2[
2137                    QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID
2138                    ])
2139            {
2140                ALOGE("%s: GSCAN_CACHED_RESULTS_SCAN_ID"
2141                    " not found", __FUNCTION__);
2142                return WIFI_ERROR_INVALID_ARGS;
2143            }
2144            cached_results[i].scan_id =
2145                nla_get_u32(
2146                tb2[
2147                    QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID
2148                    ]);
2149 
2150            if (!
2151                tb2[
2152                    QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_FLAGS
2153                    ])
2154            {
2155                ALOGE("%s: GSCAN_CACHED_RESULTS_FLAGS "
2156                    "not found", __FUNCTION__);
2157                return WIFI_ERROR_INVALID_ARGS;
2158            }
2159            cached_results[i].flags =
2160                nla_get_u32(
2161                tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_FLAGS]);
2162 
2163            if (!
2164                tb2[
2165                    QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE
2166                    ])
2167            {
2168                ALOGE("%s: RESULTS_NUM_RESULTS_AVAILABLE "
2169                    "not found", __FUNCTION__);
2170                return WIFI_ERROR_INVALID_ARGS;
2171            }
2172            numScanResults =
2173                nla_get_u32(
2174                tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]);
2175 
2176            if (mGetCachedResultsRspParams->lastProcessedScanId !=
2177                                         cached_results[i].scan_id) {
2178                j = 0; /* reset wifi_scan_result counter */
2179                cached_results[i].num_results = 0;
2180                ALOGD("parsing: *lastProcessedScanId [%d] !="
2181                      " cached_results[%d].scan_id:%d, j:%d "
2182                      "numScanResults: %d",
2183                      mGetCachedResultsRspParams->lastProcessedScanId, i,
2184                      cached_results[i].scan_id, j, numScanResults);
2185                mGetCachedResultsRspParams->lastProcessedScanId =
2186                    cached_results[i].scan_id;
2187                mGetCachedResultsRspParams->wifiScanResultsStartingIndex = 0;
2188                /* Increment the number of cached scan results received */
2189                mGetCachedResultsRspParams->num_cached_results++;
2190            } else {
2191                j = mGetCachedResultsRspParams->wifiScanResultsStartingIndex;
2192                ALOGD("parsing: *lastProcessedScanId [%d] == "
2193                      "cached_results[%d].scan_id:%d, j:%d "
2194                      "numScanResults:%d",
2195                      mGetCachedResultsRspParams->lastProcessedScanId, i,
2196                      cached_results[i].scan_id, j, numScanResults);
2197            }
2198 
2199            if (!cached_results[i].results) {
2200                ALOGE("%s: NULL cached_results[%d].results"
2201                      ". Abort.", __FUNCTION__, i);
2202                return WIFI_ERROR_OUT_OF_MEMORY;
2203            }
2204 #ifdef QC_HAL_DEBUG
2205            ALOGE("%s: scan_id %d ", __FUNCTION__,
2206             cached_results[i].scan_id);
2207            ALOGE("%s: flags  %u ", __FUNCTION__,
2208             cached_results[i].flags);
2209 #endif
2210 
2211            for (wifiScanResultsInfo = (struct nlattr *) nla_data(tb2[
2212                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]),
2213                 remResults = nla_len(tb2[
2214                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]);
2215                 nla_ok(wifiScanResultsInfo, remResults);
2216                 wifiScanResultsInfo = nla_next(wifiScanResultsInfo, &(remResults)))
2217            {
2218                 struct nlattr *tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
2219                 nla_parse(tb3, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
2220                         (struct nlattr *) nla_data(wifiScanResultsInfo),
2221                         nla_len(wifiScanResultsInfo), NULL);
2222                 if (j < MAX_AP_CACHE_PER_SCAN) {
2223                     if (!
2224                         tb3[
2225                            QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
2226                            ])
2227                     {
2228                         ALOGE("%s: "
2229                             "RESULTS_SCAN_RESULT_TIME_STAMP not found",
2230                             __FUNCTION__);
2231                         return WIFI_ERROR_INVALID_ARGS;
2232                     }
2233                     cached_results[i].results[j].ts =
2234                         nla_get_u64(
2235                         tb3[
2236                             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
2237                             ]);
2238                     if (!
2239                         tb3[
2240                             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID
2241                             ])
2242                     {
2243                         ALOGE("%s: "
2244                             "RESULTS_SCAN_RESULT_SSID not found",
2245                             __FUNCTION__);
2246                         return WIFI_ERROR_INVALID_ARGS;
2247                     }
2248                     len = nla_len(tb3[
2249                             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]);
2250                     len =
2251                         sizeof(cached_results[i].results[j].ssid) <= len ?
2252                         sizeof(cached_results[i].results[j].ssid) : len;
2253                     memcpy((void *)&cached_results[i].results[j].ssid,
2254                         nla_data(
2255                         tb3[
2256                         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]),
2257                         len);
2258                     if (!
2259                         tb3[
2260                             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID
2261                             ])
2262                     {
2263                         ALOGE("%s: "
2264                             "RESULTS_SCAN_RESULT_BSSID not found",
2265                             __FUNCTION__);
2266                         return WIFI_ERROR_INVALID_ARGS;
2267                     }
2268                     len = nla_len(
2269                         tb3[
2270                         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]);
2271                     len =
2272                         sizeof(cached_results[i].results[j].bssid) <= len ?
2273                         sizeof(cached_results[i].results[j].bssid) : len;
2274                     memcpy(&cached_results[i].results[j].bssid,
2275                         nla_data(
2276                         tb3[
2277                         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]),
2278                         len);
2279                     if (!
2280                         tb3[
2281                             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL
2282                             ])
2283                     {
2284                         ALOGE("%s: "
2285                             "RESULTS_SCAN_RESULT_CHANNEL not found",
2286                             __FUNCTION__);
2287                         return WIFI_ERROR_INVALID_ARGS;
2288                     }
2289                     cached_results[i].results[j].channel =
2290                         nla_get_u32(
2291                         tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]);
2292                     if (!
2293                         tb3[
2294                             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI
2295                             ])
2296                     {
2297                         ALOGE("%s: "
2298                             "RESULTS_SCAN_RESULT_RSSI not found",
2299                             __FUNCTION__);
2300                         return WIFI_ERROR_INVALID_ARGS;
2301                     }
2302                     cached_results[i].results[j].rssi =
2303                         get_s32(
2304                         tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI]);
2305                     if (!
2306                         tb3[
2307                             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT
2308                             ])
2309                     {
2310                         ALOGE("%s: "
2311                             "RESULTS_SCAN_RESULT_RTT not found",
2312                             __FUNCTION__);
2313                         return WIFI_ERROR_INVALID_ARGS;
2314                     }
2315                     cached_results[i].results[j].rtt =
2316                         nla_get_u32(
2317                         tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]);
2318                     if (!
2319                         tb3[
2320                             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD
2321                         ])
2322                     {
2323                         ALOGE("%s: "
2324                             "RESULTS_SCAN_RESULT_RTT_SD not found",
2325                             __FUNCTION__);
2326                         return WIFI_ERROR_INVALID_ARGS;
2327                     }
2328                     cached_results[i].results[j].rtt_sd =
2329                         nla_get_u32(
2330                         tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]);
2331 #ifdef QC_HAL_DEBUG
2332                     /* Enable these prints for debugging if needed. */
2333                     ALOGD("%s: ts  %lld ", __FUNCTION__,
2334                         cached_results[i].results[j].ts);
2335                     ALOGD("%s: SSID  %s ", __FUNCTION__,
2336                         cached_results[i].results[j].ssid);
2337                     ALOGD("%s: ", __FUNCTION__,
2338                         "BSSID: %02x:%02x:%02x:%02x:%02x:%02x \n",
2339                         cached_results[i].results[j].bssid[0],
2340                         cached_results[i].results[j].bssid[1],
2341                         cached_results[i].results[j].bssid[2],
2342                         cached_results[i].results[j].bssid[3],
2343                         cached_results[i].results[j].bssid[4],
2344                         cached_results[i].results[j].bssid[5]);
2345                     ALOGD("%s: channel %d ", __FUNCTION__,
2346                         cached_results[i].results[j].channel);
2347                     ALOGD("%s: rssi  %d ", __FUNCTION__,
2348                         cached_results[i].results[j].rssi);
2349                     ALOGD("%s: rtt  %lld ", __FUNCTION__,
2350                         cached_results[i].results[j].rtt);
2351                     ALOGD("%s: rtt_sd  %lld ", __FUNCTION__,
2352                         cached_results[i].results[j].rtt_sd);
2353 #endif
2354                     /* Increment loop index for next record */
2355                     j++;
2356                     /* For this scan id, update the wifiScanResultsStartingIndex
2357                     * and number of cached results parsed so far.
2358                     */
2359                     mGetCachedResultsRspParams->wifiScanResultsStartingIndex = j;
2360                     cached_results[i].num_results++;
2361                 } else {
2362                     /* We already parsed and stored up to max wifi_scan_results
2363                      * specified by the caller. Now, continue to loop over NL
2364                      * entries in order to properly update NL parsing pointer
2365                      * so it points to the next scan_id results.
2366                      */
2367                     ALOGD("%s: loop index:%d > max num"
2368                         " of wifi_scan_results:%d for gscan cached results"
2369                         " bucket:%d. Dummy loop", __FUNCTION__,
2370                         j, MAX_AP_CACHE_PER_SCAN, i);
2371                 }
2372            }
2373            ALOGE("%s: cached_results[%d].num_results: %d ", __FUNCTION__,
2374             i, cached_results[i].num_results);
2375            /* Increment loop index for next cached scan result record */
2376            i++;
2377        }
2378        /* Increment starting index of filling cached results received */
2379        if (mGetCachedResultsRspParams->num_cached_results)
2380            mGetCachedResultsRspParams->cachedResultsStartingIndex =
2381                mGetCachedResultsRspParams->num_cached_results - 1;
2382     return WIFI_SUCCESS;
2383 }
2384 
2385 /* Set the GSCAN BSSID Hotlist. */
wifi_set_epno_list(wifi_request_id id,wifi_interface_handle iface,int num_networks,wifi_epno_network * networks,wifi_epno_handler handler)2386 wifi_error wifi_set_epno_list(wifi_request_id id,
2387                                 wifi_interface_handle iface,
2388                                 int num_networks,
2389                                 wifi_epno_network *networks,
2390                                 wifi_epno_handler handler)
2391 {
2392     int i, ret = 0;
2393     GScanCommand *gScanCommand;
2394     struct nlattr *nlData, *nlPnoParamList;
2395     interface_info *ifaceInfo = getIfaceInfo(iface);
2396     wifi_handle wifiHandle = getWifiHandle(iface);
2397     bool previousGScanSetEpnoListRunning = false;
2398     hal_info *info = getHalInfo(wifiHandle);
2399     gscan_event_handlers* event_handlers;
2400     GScanCommandEventHandler *gScanSetPnoListCmdEventHandler;
2401 
2402     event_handlers = (gscan_event_handlers*)info->gscan_handlers;
2403     gScanSetPnoListCmdEventHandler =
2404         event_handlers->gScanSetPnoListCmdEventHandler;
2405 
2406     if (!(info->supported_feature_set & WIFI_FEATURE_HAL_EPNO)) {
2407         ALOGE("%s: Enhanced PNO is not supported by the driver",
2408             __FUNCTION__);
2409         return WIFI_ERROR_NOT_SUPPORTED;
2410     }
2411 
2412     ALOGI("%s: RequestId:%d", __FUNCTION__, id);
2413 
2414     /* Wi-Fi HAL doesn't need to check if a similar request to set ePNO
2415      * list was made earlier. If wifi_set_epno_list() is called while
2416      * another one is running, the request will be sent down to driver and
2417      * firmware. If the new request is successfully honored, then Wi-Fi HAL
2418      * will use the new request id for the gScanSetPnoListCmdEventHandler
2419      * object.
2420      */
2421 
2422     gScanCommand =
2423         new GScanCommand(
2424                     wifiHandle,
2425                     id,
2426                     OUI_QCA,
2427                     QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST);
2428     if (gScanCommand == NULL) {
2429         ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
2430         return WIFI_ERROR_UNKNOWN;
2431     }
2432 
2433     /* Create the NL message. */
2434     ret = gScanCommand->create();
2435     if (ret < 0) {
2436         ALOGE("%s: Failed to create the NL msg. Error:%d", __FUNCTION__, ret);
2437         goto cleanup;
2438     }
2439 
2440     /* Set the interface Id of the message. */
2441     ret = gScanCommand->set_iface_id(ifaceInfo->name);
2442     if (ret < 0) {
2443         ALOGE("%s: Failed to set iface id. Error:%d", __FUNCTION__, ret);
2444         goto cleanup;
2445     }
2446 
2447     /* Add the vendor specific attributes for the NL command. */
2448     nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2449     if (!nlData) {
2450         ALOGE("%s: Failed to add attribute NL80211_ATTR_VENDOR_DATA. Error:%d",
2451             __FUNCTION__, ret);
2452         goto cleanup;
2453     }
2454 
2455     num_networks = (unsigned int)num_networks > MAX_PNO_SSID ?
2456         MAX_PNO_SSID : num_networks;
2457     if (gScanCommand->put_u32(
2458             QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
2459             id) ||
2460         gScanCommand->put_u32(
2461             QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS,
2462             num_networks))
2463     {
2464         ALOGE("%s: Failed to add vendor atributes. Error:%d", __FUNCTION__, ret);
2465         goto cleanup;
2466     }
2467 
2468     /* Add the vendor specific attributes for the NL command. */
2469     nlPnoParamList =
2470         gScanCommand->attr_start(
2471                 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST);
2472     if (!nlPnoParamList) {
2473         ALOGE("%s: Failed to add attr. PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST. "
2474             "Error:%d", __FUNCTION__, ret);
2475         goto cleanup;
2476     }
2477 
2478     /* Add nested NL attributes for ePno List. */
2479     for (i = 0; i < num_networks; i++) {
2480         wifi_epno_network pnoNetwork = networks[i];
2481         struct nlattr *nlPnoNetwork = gScanCommand->attr_start(i);
2482         if (!nlPnoNetwork) {
2483             ALOGE("%s: Failed attr_start for nlPnoNetwork. Error:%d",
2484                 __FUNCTION__, ret);
2485             goto cleanup;
2486         }
2487         if (gScanCommand->put_string(
2488                 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID,
2489                 pnoNetwork.ssid) ||
2490                 gScanCommand->put_s8(
2491            QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_RSSI_THRESHOLD,
2492                 pnoNetwork.rssi_threshold) ||
2493             gScanCommand->put_u8(
2494                 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS,
2495                 pnoNetwork.flags) ||
2496             gScanCommand->put_u8(
2497                 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT,
2498                 pnoNetwork.auth_bit_field))
2499         {
2500             ALOGE("%s: Failed to add PNO_SET_LIST_PARAM_EPNO_NETWORK_*. "
2501                 "Error:%d", __FUNCTION__, ret);
2502             goto cleanup;
2503         }
2504         gScanCommand->attr_end(nlPnoNetwork);
2505     }
2506 
2507     gScanCommand->attr_end(nlPnoParamList);
2508 
2509     gScanCommand->attr_end(nlData);
2510 
2511     GScanCallbackHandler callbackHandler;
2512     memset(&callbackHandler, 0, sizeof(callbackHandler));
2513     callbackHandler.on_pno_network_found = handler.on_network_found;
2514 
2515     /* Create an object of the event handler class to take care of the
2516       * asychronous events on the north-bound.
2517       */
2518     if (gScanSetPnoListCmdEventHandler == NULL) {
2519         gScanSetPnoListCmdEventHandler = new GScanCommandEventHandler(
2520                             wifiHandle,
2521                             id,
2522                             OUI_QCA,
2523                             QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST,
2524                             callbackHandler);
2525         if (gScanSetPnoListCmdEventHandler == NULL) {
2526             ALOGE("%s: Error instantiating "
2527                 "gScanSetPnoListCmdEventHandler.", __FUNCTION__);
2528             ret = WIFI_ERROR_UNKNOWN;
2529             goto cleanup;
2530         }
2531         event_handlers->gScanSetPnoListCmdEventHandler =
2532             gScanSetPnoListCmdEventHandler;
2533         ALOGD("%s: Handler object was created for PNO_NETWORK_FOUND.",
2534             __FUNCTION__);
2535     } else {
2536         gScanSetPnoListCmdEventHandler->setCallbackHandler(callbackHandler);
2537     }
2538 
2539     ret = gScanCommand->requestResponse();
2540     if (ret != 0) {
2541         ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
2542         goto cleanup;
2543     }
2544 
2545     if (gScanSetPnoListCmdEventHandler != NULL) {
2546         gScanSetPnoListCmdEventHandler->set_request_id(id);
2547         gScanSetPnoListCmdEventHandler->enableEventHandling();
2548     }
2549 
2550 cleanup:
2551     delete gScanCommand;
2552     /* Disable Event Handling if ret != 0 */
2553     if (ret && gScanSetPnoListCmdEventHandler) {
2554         ALOGI("%s: Error ret:%d, disable event handling",
2555             __FUNCTION__, ret);
2556         gScanSetPnoListCmdEventHandler->disableEventHandling();
2557     }
2558     return (wifi_error)ret;
2559 }
2560 
2561 /* 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)2562 wifi_error wifi_set_passpoint_list(wifi_request_id id,
2563                                    wifi_interface_handle iface, int num,
2564                                    wifi_passpoint_network *networks,
2565                                    wifi_passpoint_event_handler handler)
2566 {
2567     int i, numAp, ret = 0;
2568     GScanCommand *gScanCommand;
2569     struct nlattr *nlData, *nlPasspointNetworksParamList;
2570     interface_info *ifaceInfo = getIfaceInfo(iface);
2571     wifi_handle wifiHandle = getWifiHandle(iface);
2572     bool previousGScanPnoSetPasspointListRunning = false;
2573     hal_info *info = getHalInfo(wifiHandle);
2574     gscan_event_handlers* event_handlers;
2575     GScanCommandEventHandler *gScanPnoSetPasspointListCmdEventHandler;
2576 
2577     event_handlers = (gscan_event_handlers*)info->gscan_handlers;
2578     gScanPnoSetPasspointListCmdEventHandler =
2579         event_handlers->gScanPnoSetPasspointListCmdEventHandler;
2580 
2581     if (!(info->supported_feature_set & WIFI_FEATURE_HAL_EPNO)) {
2582         ALOGE("%s: Enhanced PNO is not supported by the driver",
2583             __FUNCTION__);
2584         return WIFI_ERROR_NOT_SUPPORTED;
2585     }
2586 
2587     ALOGI("%s: RequestId:%d", __FUNCTION__, id);
2588 
2589     /* Wi-Fi HAL doesn't need to check if a similar request to set ePNO
2590      * passpoint list was made earlier. If wifi_set_passpoint_list() is called
2591      * while another one is running, the request will be sent down to driver and
2592      * firmware. If the new request is successfully honored, then Wi-Fi HAL
2593      * will use the new request id for the
2594      * gScanPnoSetPasspointListCmdEventHandler object.
2595      */
2596     gScanCommand =
2597         new GScanCommand(
2598                     wifiHandle,
2599                     id,
2600                     OUI_QCA,
2601                     QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST);
2602     if (gScanCommand == NULL) {
2603         ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
2604         return WIFI_ERROR_UNKNOWN;
2605     }
2606 
2607     /* Create the NL message. */
2608     ret = gScanCommand->create();
2609     if (ret < 0) {
2610         ALOGE("%s: Failed to create the NL msg. Error:%d", __FUNCTION__, ret);
2611         goto cleanup;
2612     }
2613 
2614     /* Set the interface Id of the message. */
2615     ret = gScanCommand->set_iface_id(ifaceInfo->name);
2616     if (ret < 0) {
2617         ALOGE("%s: Failed to set iface id. Error:%d", __FUNCTION__, ret);
2618         goto cleanup;
2619     }
2620 
2621     /* Add the vendor specific attributes for the NL command. */
2622     nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2623     if (!nlData) {
2624         ALOGE("%s: Failed to add attribute NL80211_ATTR_VENDOR_DATA. Error:%d",
2625             __FUNCTION__, ret);
2626         goto cleanup;
2627     }
2628 
2629     if (gScanCommand->put_u32(
2630             QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
2631             id) ||
2632         gScanCommand->put_u32(
2633             QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM,
2634             num))
2635     {
2636         ALOGE("%s: Failed to add vendor atributes. Error:%d", __FUNCTION__, ret);
2637         goto cleanup;
2638     }
2639 
2640     /* Add the vendor specific attributes for the NL command. */
2641     nlPasspointNetworksParamList =
2642         gScanCommand->attr_start(
2643             QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY);
2644     if (!nlPasspointNetworksParamList) {
2645         ALOGE("%s: Failed attr_start for PASSPOINT_LIST_PARAM_NETWORK_ARRAY. "
2646             "Error:%d", __FUNCTION__, ret);
2647         goto cleanup;
2648     }
2649 
2650     /* Add nested NL attributes for Passpoint List param. */
2651     for (i = 0; i < num; i++) {
2652         wifi_passpoint_network passpointNetwork = networks[i];
2653         struct nlattr *nlPasspointNetworkParam = gScanCommand->attr_start(i);
2654         if (!nlPasspointNetworkParam) {
2655             ALOGE("%s: Failed attr_start for nlPasspointNetworkParam. "
2656                 "Error:%d", __FUNCTION__, ret);
2657             goto cleanup;
2658         }
2659         if (gScanCommand->put_u32(
2660                 QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID,
2661                 passpointNetwork.id) ||
2662             gScanCommand->put_string(
2663                 QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM,
2664                 passpointNetwork.realm) ||
2665             gScanCommand->put_bytes(
2666          QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID,
2667                 (char*)passpointNetwork.roamingConsortiumIds,
2668                 16 * sizeof(int64_t)) ||
2669             gScanCommand->put_bytes(
2670             QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN,
2671                 (char*)passpointNetwork.plmn, 3 * sizeof(u8)))
2672         {
2673             ALOGE("%s: Failed to add PNO_PASSPOINT_NETWORK_PARAM_ROAM_* attr. "
2674                 "Error:%d", __FUNCTION__, ret);
2675             goto cleanup;
2676         }
2677         gScanCommand->attr_end(nlPasspointNetworkParam);
2678     }
2679 
2680     gScanCommand->attr_end(nlPasspointNetworksParamList);
2681 
2682     gScanCommand->attr_end(nlData);
2683 
2684     GScanCallbackHandler callbackHandler;
2685     memset(&callbackHandler, 0, sizeof(callbackHandler));
2686     callbackHandler.on_passpoint_network_found =
2687                         handler.on_passpoint_network_found;
2688 
2689     /* Create an object of the event handler class to take care of the
2690       * asychronous events on the north-bound.
2691       */
2692     if (gScanPnoSetPasspointListCmdEventHandler == NULL) {
2693         gScanPnoSetPasspointListCmdEventHandler = new GScanCommandEventHandler(
2694                         wifiHandle,
2695                         id,
2696                         OUI_QCA,
2697                         QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST,
2698                         callbackHandler);
2699         if (gScanPnoSetPasspointListCmdEventHandler == NULL) {
2700             ALOGE("%s: Error instantiating "
2701                 "gScanPnoSetPasspointListCmdEventHandler.", __FUNCTION__);
2702             ret = WIFI_ERROR_UNKNOWN;
2703             goto cleanup;
2704         }
2705         event_handlers->gScanPnoSetPasspointListCmdEventHandler =
2706             gScanPnoSetPasspointListCmdEventHandler;
2707         ALOGD("%s: Handler object was created for PNO_PASSPOINT_"
2708             "NETWORK_FOUND.", __FUNCTION__);
2709     } else {
2710         gScanPnoSetPasspointListCmdEventHandler->setCallbackHandler(callbackHandler);
2711     }
2712 
2713     ret = gScanCommand->requestResponse();
2714     if (ret != 0) {
2715         ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
2716         goto cleanup;
2717     }
2718 
2719     if (gScanPnoSetPasspointListCmdEventHandler != NULL) {
2720         gScanPnoSetPasspointListCmdEventHandler->set_request_id(id);
2721         gScanPnoSetPasspointListCmdEventHandler->enableEventHandling();
2722     }
2723 
2724 cleanup:
2725     delete gScanCommand;
2726     /* Disable Event Handling if ret != 0 */
2727     if (ret && gScanPnoSetPasspointListCmdEventHandler) {
2728         ALOGI("%s: Error ret:%d, disable event handling",
2729             __FUNCTION__, ret);
2730         gScanPnoSetPasspointListCmdEventHandler->disableEventHandling();
2731     }
2732     return (wifi_error)ret;
2733 }
2734 
wifi_reset_passpoint_list(wifi_request_id id,wifi_interface_handle iface)2735 wifi_error wifi_reset_passpoint_list(wifi_request_id id,
2736                             wifi_interface_handle iface)
2737 {
2738     int ret = 0;
2739     GScanCommand *gScanCommand;
2740     struct nlattr *nlData;
2741     interface_info *ifaceInfo = getIfaceInfo(iface);
2742     wifi_handle wifiHandle = getWifiHandle(iface);
2743     hal_info *info = getHalInfo(wifiHandle);
2744     gscan_event_handlers* event_handlers;
2745     GScanCommandEventHandler *gScanPnoSetPasspointListCmdEventHandler;
2746 
2747     event_handlers = (gscan_event_handlers*)info->gscan_handlers;
2748     gScanPnoSetPasspointListCmdEventHandler =
2749         event_handlers->gScanPnoSetPasspointListCmdEventHandler;
2750 
2751     if (!(info->supported_feature_set & WIFI_FEATURE_HAL_EPNO)) {
2752         ALOGE("%s: Enhanced PNO is not supported by the driver",
2753             __FUNCTION__);
2754         return WIFI_ERROR_NOT_SUPPORTED;
2755     }
2756 
2757     ALOGI("%s: RequestId:%d", __FUNCTION__, id);
2758 
2759     if (gScanPnoSetPasspointListCmdEventHandler == NULL ||
2760         (gScanPnoSetPasspointListCmdEventHandler->isEventHandlingEnabled() ==
2761          false)) {
2762         ALOGE("wifi_reset_passpoint_list: ePNO passpoint_list isn't set. "
2763             "Nothing to do. Exit.");
2764         return WIFI_ERROR_NOT_AVAILABLE;
2765     }
2766 
2767     gScanCommand = new GScanCommand(
2768                     wifiHandle,
2769                     id,
2770                     OUI_QCA,
2771                     QCA_NL80211_VENDOR_SUBCMD_PNO_RESET_PASSPOINT_LIST);
2772 
2773     if (gScanCommand == NULL) {
2774         ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
2775         return WIFI_ERROR_UNKNOWN;
2776     }
2777 
2778     /* Create the NL message. */
2779     ret = gScanCommand->create();
2780     if (ret < 0) {
2781         ALOGE("%s: Failed to create the NL msg. Error:%d", __FUNCTION__, ret);
2782         goto cleanup;
2783     }
2784 
2785     /* Set the interface Id of the message. */
2786     ret = gScanCommand->set_iface_id(ifaceInfo->name);
2787     if (ret < 0) {
2788         ALOGE("%s: Failed to set iface id. Error:%d", __FUNCTION__, ret);
2789         goto cleanup;
2790     }
2791 
2792     /* Add the vendor specific attributes for the NL command. */
2793     nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2794     if (!nlData) {
2795         ALOGE("%s: Failed to add attribute NL80211_ATTR_VENDOR_DATA. Error:%d",
2796             __FUNCTION__, ret);
2797         goto cleanup;
2798     }
2799 
2800     ret = gScanCommand->put_u32(
2801             QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, id);
2802     if (ret < 0) {
2803         ALOGE("%s: Failed to add vendor data attributes. Error:%d",
2804             __FUNCTION__, ret);
2805         goto cleanup;
2806     }
2807 
2808     gScanCommand->attr_end(nlData);
2809 
2810     ret = gScanCommand->requestResponse();
2811     if (ret != 0) {
2812         ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
2813     }
2814 
2815     /* Disable Event Handling. */
2816     if (gScanPnoSetPasspointListCmdEventHandler) {
2817         gScanPnoSetPasspointListCmdEventHandler->disableEventHandling();
2818     }
2819 
2820 cleanup:
2821     delete gScanCommand;
2822     return (wifi_error)ret;
2823 }
2824 
allocCachedResultsTemp(int max,wifi_cached_scan_results * cached_results)2825 int GScanCommand::allocCachedResultsTemp(int max,
2826                                      wifi_cached_scan_results *cached_results)
2827 {
2828     wifi_cached_scan_results *tempCachedResults = NULL;
2829 
2830     /* Alloc memory for "max" number of cached results. */
2831     mGetCachedResultsRspParams->cached_results =
2832         (wifi_cached_scan_results*)
2833         malloc(max * sizeof(wifi_cached_scan_results));
2834     if (!mGetCachedResultsRspParams->cached_results) {
2835         ALOGE("%s: Failed to allocate memory for "
2836               "mGetCachedResultsRspParams->cached_results.",
2837               __FUNCTION__);
2838         return WIFI_ERROR_OUT_OF_MEMORY;
2839     }
2840     memset(mGetCachedResultsRspParams->cached_results, 0,
2841            max * sizeof(wifi_cached_scan_results));
2842 
2843     mGetCachedResultsRspParams->max = max;
2844 
2845     return WIFI_SUCCESS;
2846 }
2847 
2848 /*
2849  * Allocates memory for the subCmd response struct and initializes status = -1
2850  */
allocRspParams(eGScanRspRarams cmd)2851 int GScanCommand::allocRspParams(eGScanRspRarams cmd)
2852 {
2853     int ret = 0;
2854     switch(cmd)
2855     {
2856         case eGScanGetCapabilitiesRspParams:
2857             mGetCapabilitiesRspParams = (GScanGetCapabilitiesRspParams *)
2858                 malloc(sizeof(GScanGetCapabilitiesRspParams));
2859             if (!mGetCapabilitiesRspParams)
2860                 ret = -1;
2861             else  {
2862                 memset(&mGetCapabilitiesRspParams->capabilities, 0,
2863                     sizeof(wifi_gscan_capabilities));
2864             }
2865         break;
2866         case eGScanGetCachedResultsRspParams:
2867             mGetCachedResultsRspParams = (GScanGetCachedResultsRspParams *)
2868                 malloc(sizeof(GScanGetCachedResultsRspParams));
2869             if (!mGetCachedResultsRspParams)
2870                 ret = -1;
2871             else {
2872                 mGetCachedResultsRspParams->num_cached_results = 0;
2873                 mGetCachedResultsRspParams->more_data = false;
2874                 mGetCachedResultsRspParams->cachedResultsStartingIndex = -1;
2875                 mGetCachedResultsRspParams->lastProcessedScanId = -1;
2876                 mGetCachedResultsRspParams->wifiScanResultsStartingIndex = -1;
2877                 mGetCachedResultsRspParams->max = 0;
2878                 mGetCachedResultsRspParams->cached_results = NULL;
2879             }
2880         break;
2881         default:
2882             ALOGD("%s: Wrong request for alloc.", __FUNCTION__);
2883             ret = -1;
2884     }
2885     return ret;
2886 }
2887 
freeRspParams(eGScanRspRarams cmd)2888 void GScanCommand::freeRspParams(eGScanRspRarams cmd)
2889 {
2890     u32 i = 0;
2891     wifi_cached_scan_results *cached_results = NULL;
2892 
2893     switch(cmd)
2894     {
2895         case eGScanGetCapabilitiesRspParams:
2896             if (mGetCapabilitiesRspParams) {
2897                 free(mGetCapabilitiesRspParams);
2898                 mGetCapabilitiesRspParams = NULL;
2899             }
2900         break;
2901         case eGScanGetCachedResultsRspParams:
2902             if (mGetCachedResultsRspParams) {
2903                 if (mGetCachedResultsRspParams->cached_results) {
2904                     free(mGetCachedResultsRspParams->cached_results);
2905                     mGetCachedResultsRspParams->cached_results = NULL;
2906                 }
2907                 free(mGetCachedResultsRspParams);
2908                 mGetCachedResultsRspParams = NULL;
2909             }
2910         break;
2911         default:
2912             ALOGD("%s: Wrong request for free.", __FUNCTION__);
2913     }
2914 }
2915 
copyCachedScanResults(int * numResults,wifi_cached_scan_results * cached_results)2916 wifi_error GScanCommand::copyCachedScanResults(
2917                                       int *numResults,
2918                                       wifi_cached_scan_results *cached_results)
2919 {
2920     wifi_error ret = WIFI_SUCCESS;
2921     int i;
2922     wifi_cached_scan_results *cachedResultRsp;
2923 
2924     if (mGetCachedResultsRspParams && cached_results)
2925     {
2926         /* Populate the number of parsed cached results. */
2927         *numResults = mGetCachedResultsRspParams->num_cached_results;
2928 
2929         for (i = 0; i < *numResults; i++) {
2930             cachedResultRsp = &mGetCachedResultsRspParams->cached_results[i];
2931             cached_results[i].scan_id = cachedResultRsp->scan_id;
2932             cached_results[i].flags = cachedResultRsp->flags;
2933             cached_results[i].num_results = cachedResultRsp->num_results;
2934 
2935             if (!cached_results[i].num_results) {
2936                 ALOGI("Error: cached_results[%d].num_results=0", i);
2937                 continue;
2938             }
2939 
2940             ALOGI("copyCachedScanResults: "
2941                 "cached_results[%d].num_results : %d",
2942                 i, cached_results[i].num_results);
2943 
2944             memcpy(cached_results[i].results,
2945                 cachedResultRsp->results,
2946                 cached_results[i].num_results * sizeof(wifi_scan_result));
2947         }
2948     } else {
2949         ALOGE("%s: mGetCachedResultsRspParams is NULL", __FUNCTION__);
2950         *numResults = 0;
2951         ret = WIFI_ERROR_INVALID_ARGS;
2952     }
2953     return ret;
2954 }
2955 
getGetCapabilitiesRspParams(wifi_gscan_capabilities * capabilities)2956 void GScanCommand::getGetCapabilitiesRspParams(
2957                                         wifi_gscan_capabilities *capabilities)
2958 {
2959     if (mGetCapabilitiesRspParams && capabilities)
2960     {
2961         memcpy(capabilities,
2962             &mGetCapabilitiesRspParams->capabilities,
2963             sizeof(wifi_gscan_capabilities));
2964     } else {
2965         ALOGD("%s: mGetCapabilitiesRspParams is NULL", __FUNCTION__);
2966     }
2967 }
2968 
setMaxChannels(int max_channels)2969 void GScanCommand::setMaxChannels(int max_channels) {
2970     mMaxChannels = max_channels;
2971 }
2972 
setChannels(int * channels)2973 void GScanCommand::setChannels(int *channels) {
2974     mChannels = channels;
2975 }
2976 
setNumChannelsPtr(int * num_channels)2977 void GScanCommand::setNumChannelsPtr(int *num_channels) {
2978     mNumChannelsPtr = num_channels;
2979 }
2980 
wifi_set_ssid_white_list(wifi_request_id id,wifi_interface_handle iface,int num_networks,wifi_ssid * ssids)2981 wifi_error wifi_set_ssid_white_list(wifi_request_id id,
2982                                     wifi_interface_handle iface,
2983                                     int num_networks,
2984                                     wifi_ssid *ssids)
2985 {
2986     int ret = 0, i;
2987     GScanCommand *roamCommand;
2988     struct nlattr *nlData, *nlSsids;
2989     interface_info *ifaceInfo = getIfaceInfo(iface);
2990     wifi_handle wifiHandle = getWifiHandle(iface);
2991     hal_info *info = getHalInfo(wifiHandle);
2992 
2993     if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
2994         ALOGE("%s: GSCAN is not supported by driver",
2995             __FUNCTION__);
2996         return WIFI_ERROR_NOT_SUPPORTED;
2997     }
2998 
2999     ALOGI("%s: RequestId:%d", __FUNCTION__, id);
3000 
3001     ALOGI("Number of SSIDs : %d", num_networks);
3002     for (i = 0; i < num_networks; i++) {
3003         ALOGI("ssid %d : %s", i, ssids[i].ssid);
3004     }
3005 
3006     roamCommand = new GScanCommand(
3007                                 wifiHandle,
3008                                 id,
3009                                 OUI_QCA,
3010                                 QCA_NL80211_VENDOR_SUBCMD_ROAM);
3011     if (roamCommand == NULL) {
3012         ALOGE("wifi_set_ssid_white_list(): Error roamCommand NULL");
3013         return WIFI_ERROR_UNKNOWN;
3014     }
3015 
3016     /* Create the NL message. */
3017     ret = roamCommand->create();
3018     if (ret < 0)
3019         goto cleanup;
3020 
3021     /* Set the interface Id of the message. */
3022     ret = roamCommand->set_iface_id(ifaceInfo->name);
3023     if (ret < 0)
3024         goto cleanup;
3025 
3026     /* Add the vendor specific attributes for the NL command. */
3027     nlData = roamCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
3028     if (!nlData)
3029         goto cleanup;
3030 
3031     if (roamCommand->put_u32(QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD,
3032             QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST) ||
3033         roamCommand->put_u32(
3034             QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID,
3035             id) ||
3036         roamCommand->put_u32(
3037             QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS,
3038             num_networks)) {
3039         goto cleanup;
3040     }
3041 
3042     nlSsids =
3043       roamCommand->attr_start(
3044             QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST);
3045     for (i = 0; i < num_networks; i++) {
3046         struct nlattr *nl_ssid = roamCommand->attr_start(i);
3047 
3048         if ( roamCommand->put_string(
3049                     QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID,
3050                     ssids[i].ssid)) {
3051             goto cleanup;
3052         }
3053 
3054         roamCommand->attr_end(nl_ssid);
3055     }
3056     roamCommand->attr_end(nlSsids);
3057 
3058     roamCommand->attr_end(nlData);
3059 
3060     ret = roamCommand->requestResponse();
3061     if (ret != 0) {
3062         ALOGE("wifi_set_ssid_white_list(): requestResponse Error:%d", ret);
3063     }
3064 
3065 cleanup:
3066     delete roamCommand;
3067     return (wifi_error)ret;
3068 
3069 }
3070 
wifi_set_gscan_roam_params(wifi_request_id id,wifi_interface_handle iface,wifi_roam_params * params)3071 wifi_error wifi_set_gscan_roam_params(wifi_request_id id,
3072                                       wifi_interface_handle iface,
3073                                       wifi_roam_params * params)
3074 {
3075     int ret = 0;
3076     GScanCommand *roamCommand;
3077     struct nlattr *nlData;
3078     interface_info *ifaceInfo = getIfaceInfo(iface);
3079     wifi_handle wifiHandle = getWifiHandle(iface);
3080     hal_info *info = getHalInfo(wifiHandle);
3081 
3082     if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
3083         ALOGE("%s: GSCAN is not supported by driver",
3084             __FUNCTION__);
3085         return WIFI_ERROR_NOT_SUPPORTED;
3086     }
3087 
3088     ALOGI("%s: RequestId:%d", __FUNCTION__, id);
3089 
3090     if(params) {
3091         ALOGI("A_band_boost_threshold   %d", params->A_band_boost_threshold);
3092         ALOGI("A_band_penalty_threshol  %d", params->A_band_penalty_threshold);
3093         ALOGI("A_band_boost_factor      %u", params->A_band_boost_factor);
3094         ALOGI("A_band_penalty_factor    %u", params->A_band_penalty_factor);
3095         ALOGI("A_band_max_boost         %u", params->A_band_max_boost);
3096         ALOGI("lazy_roam_histeresys     %u", params->lazy_roam_hysteresis);
3097         ALOGI("alert_roam_rssi_trigger  %d", params->alert_roam_rssi_trigger);
3098     } else {
3099         ALOGE("wifi_roam_params is NULL");
3100         return WIFI_ERROR_INVALID_ARGS;
3101     }
3102 
3103     roamCommand = new GScanCommand(wifiHandle,
3104                                    id,
3105                                    OUI_QCA,
3106                                    QCA_NL80211_VENDOR_SUBCMD_ROAM);
3107     if (roamCommand == NULL) {
3108         ALOGE("wifi_set_gscan_roam_params(): Error roamCommand NULL");
3109         return WIFI_ERROR_UNKNOWN;
3110     }
3111 
3112     /* Create the NL message. */
3113     ret = roamCommand->create();
3114     if (ret < 0)
3115         goto cleanup;
3116 
3117     /* Set the interface Id of the message. */
3118     ret = roamCommand->set_iface_id(ifaceInfo->name);
3119     if (ret < 0)
3120         goto cleanup;
3121 
3122     /* Add the vendor specific attributes for the NL command. */
3123     nlData = roamCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
3124     if (!nlData)
3125         goto cleanup;
3126 
3127     if (roamCommand->put_u32(QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD,
3128             QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_GSCAN_ROAM_PARAMS) ||
3129         roamCommand->put_u32(
3130             QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID,
3131             id) ||
3132         roamCommand->put_s32(
3133             QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD,
3134             params->A_band_boost_threshold) ||
3135         roamCommand->put_s32(
3136             QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD,
3137             params->A_band_penalty_threshold) ||
3138         roamCommand->put_u32(
3139             QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR,
3140             params->A_band_boost_factor) ||
3141         roamCommand->put_u32(
3142             QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR,
3143             params->A_band_penalty_factor) ||
3144         roamCommand->put_u32(
3145             QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST,
3146             params->A_band_max_boost) ||
3147         roamCommand->put_u32(
3148             QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS,
3149             params->lazy_roam_hysteresis) ||
3150         roamCommand->put_s32(
3151             QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER,
3152             params->alert_roam_rssi_trigger)) {
3153         goto cleanup;
3154     }
3155 
3156     roamCommand->attr_end(nlData);
3157 
3158     ret = roamCommand->requestResponse();
3159     if (ret != 0) {
3160         ALOGE("wifi_set_gscan_roam_params(): requestResponse Error:%d", ret);
3161     }
3162 
3163 cleanup:
3164     delete roamCommand;
3165     return (wifi_error)ret;
3166 
3167 }
3168 
wifi_enable_lazy_roam(wifi_request_id id,wifi_interface_handle iface,int enable)3169 wifi_error wifi_enable_lazy_roam(wifi_request_id id,
3170                                  wifi_interface_handle iface,
3171                                  int enable)
3172 {
3173     int ret = 0;
3174     GScanCommand *roamCommand;
3175     struct nlattr *nlData;
3176     interface_info *ifaceInfo = getIfaceInfo(iface);
3177     wifi_handle wifiHandle = getWifiHandle(iface);
3178     hal_info *info = getHalInfo(wifiHandle);
3179 
3180     if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
3181         ALOGE("%s: GSCAN is not supported by driver",
3182             __FUNCTION__);
3183         return WIFI_ERROR_NOT_SUPPORTED;
3184     }
3185 
3186     ALOGI("%s: RequestId:%d Setting lazy roam: %s",
3187           __FUNCTION__, id, enable?"ENABLE":"DISABLE");
3188 
3189     roamCommand =
3190          new GScanCommand(wifiHandle,
3191                           id,
3192                           OUI_QCA,
3193                           QCA_NL80211_VENDOR_SUBCMD_ROAM);
3194     if (roamCommand == NULL) {
3195         ALOGE("%s: Error roamCommand NULL", __FUNCTION__);
3196         return WIFI_ERROR_UNKNOWN;
3197     }
3198 
3199     /* Create the NL message. */
3200     ret = roamCommand->create();
3201     if (ret < 0)
3202         goto cleanup;
3203 
3204     /* Set the interface Id of the message. */
3205     ret = roamCommand->set_iface_id(ifaceInfo->name);
3206     if (ret < 0)
3207         goto cleanup;
3208 
3209     /* Add the vendor specific attributes for the NL command. */
3210     nlData = roamCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
3211     if (!nlData)
3212         goto cleanup;
3213 
3214     if (roamCommand->put_u32(QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD,
3215             QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM) ||
3216         roamCommand->put_u32(
3217             QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID,
3218             id) ||
3219         roamCommand->put_u32(
3220             QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE,
3221             enable)) {
3222         goto cleanup;
3223     }
3224 
3225     roamCommand->attr_end(nlData);
3226 
3227     ret = roamCommand->requestResponse();
3228     if (ret != 0) {
3229         ALOGE("wifi_enable_lazy_roam(): requestResponse Error:%d", ret);
3230     }
3231 
3232 cleanup:
3233     delete roamCommand;
3234     return (wifi_error)ret;
3235 
3236 }
3237 
wifi_set_bssid_preference(wifi_request_id id,wifi_interface_handle iface,int num_bssid,wifi_bssid_preference * prefs)3238 wifi_error wifi_set_bssid_preference(wifi_request_id id,
3239                                      wifi_interface_handle iface,
3240                                      int num_bssid,
3241                                      wifi_bssid_preference *prefs)
3242 {
3243     int ret = 0, i;
3244     GScanCommand *roamCommand;
3245     struct nlattr *nlData, *nlBssids;
3246     interface_info *ifaceInfo = getIfaceInfo(iface);
3247     wifi_handle wifiHandle = getWifiHandle(iface);
3248     hal_info *info = getHalInfo(wifiHandle);
3249 
3250     if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
3251         ALOGE("%s: GSCAN is not supported by driver",
3252             __FUNCTION__);
3253         return WIFI_ERROR_NOT_SUPPORTED;
3254     }
3255 
3256     ALOGI("%s: RequestId:%d", __FUNCTION__, id);
3257 
3258     ALOGI("Number of BSSIDs: %d", num_bssid);
3259     if(prefs && num_bssid) {
3260         for (i = 0; i < num_bssid; i++) {
3261             ALOGI("BSSID: %d : %02x:%02x:%02x:%02x:%02x:%02x", i,
3262                     prefs[i].bssid[0], prefs[i].bssid[1],
3263                     prefs[i].bssid[2], prefs[i].bssid[3],
3264                     prefs[i].bssid[4], prefs[i].bssid[5]);
3265             ALOGI("alert_roam_rssi_trigger : %d", prefs[i].rssi_modifier);
3266         }
3267     } else {
3268         ALOGE("wifi_bssid_preference is NULL");
3269         return WIFI_ERROR_INVALID_ARGS;
3270     }
3271 
3272     roamCommand =
3273          new GScanCommand(wifiHandle,
3274                           id,
3275                           OUI_QCA,
3276                           QCA_NL80211_VENDOR_SUBCMD_ROAM);
3277     if (roamCommand == NULL) {
3278         ALOGE("%s: Error roamCommand NULL", __FUNCTION__);
3279         return WIFI_ERROR_UNKNOWN;
3280     }
3281 
3282     /* Create the NL message. */
3283     ret = roamCommand->create();
3284     if (ret < 0)
3285         goto cleanup;
3286 
3287     /* Set the interface Id of the message. */
3288     ret = roamCommand->set_iface_id(ifaceInfo->name);
3289     if (ret < 0)
3290         goto cleanup;
3291 
3292     /* Add the vendor specific attributes for the NL command. */
3293     nlData = roamCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
3294     if (!nlData)
3295         goto cleanup;
3296 
3297     if (roamCommand->put_u32(QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD,
3298             QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS) ||
3299         roamCommand->put_u32(
3300             QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID,
3301             id) ||
3302         roamCommand->put_u32(
3303             QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID,
3304             num_bssid)) {
3305         goto cleanup;
3306     }
3307 
3308     nlBssids = roamCommand->attr_start(
3309             QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS);
3310     for (i = 0; i < num_bssid; i++) {
3311         struct nlattr *nl_ssid = roamCommand->attr_start(i);
3312 
3313         if (roamCommand->put_addr(
3314                 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID,
3315                 (u8 *)prefs[i].bssid) ||
3316             roamCommand->put_s32(
3317                 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER,
3318                 prefs[i].rssi_modifier)) {
3319             goto cleanup;
3320         }
3321 
3322         roamCommand->attr_end(nl_ssid);
3323     }
3324     roamCommand->attr_end(nlBssids);
3325 
3326     roamCommand->attr_end(nlData);
3327 
3328     ret = roamCommand->requestResponse();
3329     if (ret != 0) {
3330         ALOGE("wifi_set_bssid_preference(): requestResponse Error:%d", ret);
3331     }
3332 
3333 cleanup:
3334     delete roamCommand;
3335     return (wifi_error)ret;
3336 
3337 }
3338 
wifi_set_bssid_blacklist(wifi_request_id id,wifi_interface_handle iface,wifi_bssid_params params)3339 wifi_error wifi_set_bssid_blacklist(wifi_request_id id,
3340                                     wifi_interface_handle iface,
3341                                     wifi_bssid_params params)
3342 {
3343     int ret = 0, i;
3344     GScanCommand *roamCommand;
3345     struct nlattr *nlData, *nlBssids;
3346     interface_info *ifaceInfo = getIfaceInfo(iface);
3347     wifi_handle wifiHandle = getWifiHandle(iface);
3348     hal_info *info = getHalInfo(wifiHandle);
3349 
3350     if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
3351         ALOGE("%s: GSCAN is not supported by driver",
3352             __FUNCTION__);
3353         return WIFI_ERROR_NOT_SUPPORTED;
3354     }
3355 
3356     ALOGI("%s: RequestId:%d", __FUNCTION__, id);
3357 
3358     for (i = 0; i < params.num_bssid; i++) {
3359         ALOGI("BSSID: %d : %02x:%02x:%02x:%02x:%02x:%02x", i,
3360                 params.bssids[i][0], params.bssids[i][1],
3361                 params.bssids[i][2], params.bssids[i][3],
3362                 params.bssids[i][4], params.bssids[i][5]);
3363     }
3364 
3365     roamCommand =
3366          new GScanCommand(wifiHandle,
3367                           id,
3368                           OUI_QCA,
3369                           QCA_NL80211_VENDOR_SUBCMD_ROAM);
3370     if (roamCommand == NULL) {
3371         ALOGE("%s: Error roamCommand NULL", __FUNCTION__);
3372         return WIFI_ERROR_UNKNOWN;
3373     }
3374 
3375     /* Create the NL message. */
3376     ret = roamCommand->create();
3377     if (ret < 0)
3378         goto cleanup;
3379 
3380     /* Set the interface Id of the message. */
3381     ret = roamCommand->set_iface_id(ifaceInfo->name);
3382     if (ret < 0)
3383         goto cleanup;
3384 
3385     /* Add the vendor specific attributes for the NL command. */
3386     nlData = roamCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
3387     if (!nlData)
3388         goto cleanup;
3389 
3390     if (roamCommand->put_u32(QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD,
3391             QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID) ||
3392         roamCommand->put_u32(
3393             QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID,
3394             id) ||
3395         roamCommand->put_u32(
3396             QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID,
3397             params.num_bssid)) {
3398         goto cleanup;
3399     }
3400 
3401     nlBssids = roamCommand->attr_start(
3402             QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS);
3403     for (i = 0; i < params.num_bssid; i++) {
3404         struct nlattr *nl_ssid = roamCommand->attr_start(i);
3405 
3406         if (roamCommand->put_addr(
3407                 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID,
3408                 (u8 *)params.bssids[i])) {
3409             goto cleanup;
3410         }
3411 
3412         roamCommand->attr_end(nl_ssid);
3413     }
3414     roamCommand->attr_end(nlBssids);
3415 
3416     roamCommand->attr_end(nlData);
3417 
3418     ret = roamCommand->requestResponse();
3419     if (ret != 0) {
3420         ALOGE("wifi_set_bssid_blacklist(): requestResponse Error:%d", ret);
3421     }
3422 
3423 cleanup:
3424     delete roamCommand;
3425     return (wifi_error)ret;
3426 
3427 }
3428