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. */
30GScanCommandEventHandler *GScanStartCmdEventHandler = NULL;
31GScanCommandEventHandler *GScanSetBssidHotlistCmdEventHandler = NULL;
32GScanCommandEventHandler *GScanSetSignificantChangeCmdEventHandler = NULL;
33
34/* Implementation of the API functions exposed in gscan.h */
35wifi_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
104cleanup:
105    ALOGI("%s: Delete object.", __func__);
106    delete gScanCommand;
107    return (wifi_error)ret;
108}
109
110void 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
126wifi_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
204cleanup:
205    gScanCommand->freeRspParams(eGScanGetCapabilitiesRspParams);
206    ALOGI("%s: Delete object.", __func__);
207    delete gScanCommand;
208    return (wifi_error)ret;
209}
210
211void start_gscan_cb(int status)
212{
213    ALOGD("%s: Status = %d.", __func__, status);
214}
215
216wifi_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
398cleanup:
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
413void stop_gscan_cb(int status)
414{
415    ALOGD("%s: Status = %d.", __func__, status);
416}
417
418wifi_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
510cleanup:
511    gScanCommand->freeRspParams(eGScanStopRspParams);
512    ALOGI("%s: Delete object.", __func__);
513    delete gScanCommand;
514    return (wifi_error)ret;
515}
516
517void set_bssid_hotlist_cb(int status)
518{
519    ALOGD("%s: Status = %d.", __func__, status);
520}
521
522/* Set the GSCAN BSSID Hotlist. */
523wifi_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
671cleanup:
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
683void reset_bssid_hotlist_cb(int status)
684{
685    ALOGD("%s: Status = %d.", __func__, status);
686}
687
688wifi_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
775cleanup:
776    gScanCommand->freeRspParams(eGScanResetBssidHotlistRspParams);
777    ALOGI("%s: Delete object.", __func__);
778    delete gScanCommand;
779    return (wifi_error)ret;
780}
781
782void set_significant_change_cb(int status)
783{
784    ALOGD("%s: Status = %d.", __func__, status);
785}
786
787/* Set the GSCAN Significant AP Change list. */
788wifi_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
948cleanup:
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
960void reset_significant_change_cb(int status)
961{
962    ALOGD("%s: Status = %d.", __func__, status);
963}
964
965/* Clear the GSCAN Significant AP change list. */
966wifi_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
1055cleanup:
1056    gScanCommand->freeRspParams(eGScanResetSignificantChangeRspParams);
1057    ALOGI("%s: Delete object.", __func__);
1058    delete gScanCommand;
1059    return (wifi_error)ret;
1060}
1061
1062void 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. */
1069wifi_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    }
1212cleanup:
1213    gScanCommand->freeRspParams(eGScanGetCachedResultsRspParams);
1214    ALOGI("%s: Delete object.", __func__);
1215    delete gScanCommand;
1216    return (wifi_error)ret;
1217}
1218
1219GScanCommand::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
1243GScanCommand::~GScanCommand()
1244{
1245    ALOGD("GScanCommand %p destructor", this);
1246    unregisterVendorHandler(mVendor_id, mSubcmd);
1247}
1248
1249
1250/* This function implements creation of Vendor command */
1251int 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
1269out:
1270    return ret;
1271}
1272
1273/* Callback handlers registered for nl message send */
1274static 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 */
1286static 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 */
1298static 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 */
1315int 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    }
1359out:
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
1370int GScanCommand::requestResponse()
1371{
1372    ALOGD("%s: request a response", __func__);
1373    return WifiCommand::requestResponse(mMsg);
1374}
1375
1376int 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. */
1433static 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 */
1572int 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
1937int 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 */
1953int 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
2037void 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
2099wifi_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
2122void 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
2137void 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
2147void 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
2157void 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
2167void 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
2177void 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
2187void 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
2197int 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
2206void GScanCommand::waitForRsp(bool wait)
2207{
2208    mWaitforRsp = wait;
2209}
2210
2211void GScanCommand::setMaxChannels(int max_channels) {
2212    mMaxChannels = max_channels;
2213}
2214
2215void GScanCommand::setChannels(int *channels) {
2216    mChannels = channels;
2217}
2218
2219void GScanCommand::setNumChannelsPtr(int *num_channels) {
2220    mNumChannelsPtr = num_channels;
2221}
2222
2223