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