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 "gscan_event_handler.h"
18#include "vendor_definitions.h"
19
20/* This function implements creation of Vendor command event handler. */
21int GScanCommandEventHandler::create() {
22    int ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
23    if (ret < 0) {
24        return ret;
25    }
26
27    /* Insert the oui in the msg */
28    ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
29    if (ret < 0)
30        goto out;
31
32    /* Insert the subcmd in the msg */
33    ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
34    if (ret < 0)
35        goto out;
36out:
37    return ret;
38}
39
40int GScanCommandEventHandler::get_request_id()
41{
42    return mRequestId;
43}
44
45GScanCommandEventHandler::GScanCommandEventHandler(wifi_handle handle, int id,
46                                                u32 vendor_id,
47                                                u32 subcmd,
48                                                GScanCallbackHandler handler)
49        : WifiVendorCommand(handle, id, vendor_id, subcmd)
50{
51    int ret = 0;
52    ALOGD("GScanCommandEventHandler %p constructed", this);
53    mRequestId = id;
54    mHandler = handler;
55    mSubCommandId = subcmd;
56    mHotlistApFoundResults = NULL;
57    mHotlistApFoundNumResults = 0;
58    mHotlistApFoundMoreData = false;
59    mSignificantChangeResults = NULL;
60    mSignificantChangeNumResults = 0;
61    mSignificantChangeMoreData = false;
62
63    switch(mSubCommandId)
64    {
65        case QCA_NL80211_VENDOR_SUBCMD_GSCAN_START:
66        {
67            /* Register handlers for northbound asychronous scan events. */
68            ALOGD("%s: wait for GSCAN_RESULTS_AVAILABLE, "
69                "FULL_SCAN_RESULT, and SCAN EVENT events. \n", __func__);
70            ret = registerVendorHandler(mVendor_id,
71                    QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE) ||
72                  registerVendorHandler(mVendor_id,
73                    QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT) ||
74                  registerVendorHandler(mVendor_id,
75                    QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT);
76            if (ret < 0)
77                ALOGD("%s: Error in registering handler for "
78                    "GSCAN_START. \n", __func__);
79        }
80        break;
81
82        case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SIGNIFICANT_CHANGE:
83        {
84            ret = registerVendorHandler(mVendor_id,
85                    QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE);
86            if (ret < 0)
87                ALOGD("%s: Error in registering handler for "
88                    "GSCAN_SIGNIFICANT_CHANGE. \n", __func__);
89        }
90        break;
91
92        case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_BSSID_HOTLIST:
93        {
94            ret = registerVendorHandler(mVendor_id,
95                    QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND);
96            if (ret < 0)
97                ALOGD("%s: Error in registering handler for"
98                    " GSCAN_HOTLIST_AP_FOUND. \n", __func__);
99        }
100        break;
101    }
102}
103
104GScanCommandEventHandler::~GScanCommandEventHandler()
105{
106    ALOGD("GScanCommandEventHandler %p destructor", this);
107    switch(mSubCommandId)
108    {
109        case QCA_NL80211_VENDOR_SUBCMD_GSCAN_START:
110        {
111            /* Unregister event handlers. */
112            ALOGD("%s: Unregister handlers for GSCAN_RESULTS_AVAILABLE, "
113            "FULL_SCAN_RESULT, and SCAN EVENT events. \n", __func__);
114            unregisterVendorHandler(mVendor_id,
115                    QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE);
116            unregisterVendorHandler(mVendor_id,
117                    QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT);
118            unregisterVendorHandler(mVendor_id,
119                    QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT);
120        }
121        break;
122
123        case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SIGNIFICANT_CHANGE:
124        {
125            unregisterVendorHandler(mVendor_id,
126                    QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE);
127        }
128        break;
129
130        case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_BSSID_HOTLIST:
131        {
132            unregisterVendorHandler(mVendor_id,
133                    QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND);
134        }
135        break;
136    }
137}
138
139static wifi_error gscan_get_hotlist_ap_found_results(u32 num_results,
140                                            wifi_scan_result *results,
141                                            u32 starting_index,
142                                            struct nlattr **tb_vendor)
143{
144    u32 i = starting_index;
145    struct nlattr *scanResultsInfo;
146    int rem = 0;
147    u32 len = 0;
148    ALOGE("gscan_get_hotlist_ap_found_results: starting counter: %d", i);
149
150    for (scanResultsInfo = (struct nlattr *) nla_data(tb_vendor[
151            QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]),
152            rem = nla_len(tb_vendor[
153            QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST
154            ]);
155                nla_ok(scanResultsInfo, rem);
156                scanResultsInfo = nla_next(scanResultsInfo, &(rem)))
157    {
158        struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
159        nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
160        (struct nlattr *) nla_data(scanResultsInfo),
161                nla_len(scanResultsInfo), NULL);
162
163        if (!
164            tb2[
165                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
166                ])
167        {
168            ALOGE("gscan_get_hotlist_ap_found_results: "
169                "RESULTS_SCAN_RESULT_TIME_STAMP not found");
170            return WIFI_ERROR_INVALID_ARGS;
171        }
172        results[i].ts =
173            nla_get_u64(
174            tb2[
175                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
176                ]);
177        if (!
178            tb2[
179                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID
180                ])
181        {
182            ALOGE("gscan_get_hotlist_ap_found_results: "
183                "RESULTS_SCAN_RESULT_SSID not found");
184            return WIFI_ERROR_INVALID_ARGS;
185        }
186        len = nla_len(tb2[
187                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]);
188        len =
189            sizeof(results->ssid) <= len ? sizeof(results->ssid) : len;
190        memcpy((void *)&results[i].ssid,
191            nla_data(
192            tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]), len);
193        if (!
194            tb2[
195                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID
196                ])
197        {
198            ALOGE("gscan_get_hotlist_ap_found_results: "
199                "RESULTS_SCAN_RESULT_BSSID not found");
200            return WIFI_ERROR_INVALID_ARGS;
201        }
202        len = nla_len(
203            tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]);
204        len =
205            sizeof(results->bssid) <= len ? sizeof(results->bssid) : len;
206        memcpy(&results[i].bssid,
207            nla_data(
208            tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]), len);
209        if (!
210            tb2[
211                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL
212                ])
213        {
214            ALOGE("gscan_get_hotlist_ap_found_results: "
215                "RESULTS_SCAN_RESULT_CHANNEL not found");
216            return WIFI_ERROR_INVALID_ARGS;
217        }
218        results[i].channel =
219            nla_get_u32(
220            tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]);
221        if (!
222            tb2[
223                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI
224                ])
225        {
226            ALOGE("gscan_get_hotlist_ap_found_results: "
227                "RESULTS_SCAN_RESULT_RSSI not found");
228            return WIFI_ERROR_INVALID_ARGS;
229        }
230        results[i].rssi =
231            nla_get_u32(
232            tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI]);
233        if (!
234            tb2[
235                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT
236                ])
237        {
238            ALOGE("gscan_get_hotlist_ap_found_results: "
239                "RESULTS_SCAN_RESULT_RTT not found");
240            return WIFI_ERROR_INVALID_ARGS;
241        }
242        results[i].rtt =
243            nla_get_u32(
244            tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]);
245        if (!
246            tb2[
247                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD
248            ])
249        {
250            ALOGE("gscan_get_hotlist_ap_found_results: "
251                "RESULTS_SCAN_RESULT_RTT_SD not found");
252            return WIFI_ERROR_INVALID_ARGS;
253        }
254        results[i].rtt_sd =
255            nla_get_u32(
256            tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]);
257
258        ALOGE("gscan_get_hotlist_ap_found_results: ts  %lld ", results[i].ts);
259        ALOGE("gscan_get_hotlist_ap_found_results: SSID  %s ",
260            results[i].ssid) ;
261        ALOGE("gscan_get_hotlist_ap_found_results: "
262            "BSSID: %02x:%02x:%02x:%02x:%02x:%02x \n",
263            results[i].bssid[0], results[i].bssid[1], results[i].bssid[2],
264            results[i].bssid[3], results[i].bssid[4], results[i].bssid[5]);
265        ALOGE("gscan_get_hotlist_ap_found_results: channel %d ",
266            results[i].channel);
267        ALOGE("gscan_get_hotlist_ap_found_results: rssi %d ", results[i].rssi);
268        ALOGE("gscan_get_hotlist_ap_found_results: rtt %lld ", results[i].rtt);
269        ALOGE("gscan_get_hotlist_ap_found_results: rtt_sd %lld ",
270            results[i].rtt_sd);
271        /* Increment loop index for next record */
272        i++;
273    }
274    return WIFI_SUCCESS;
275}
276
277static wifi_error gscan_get_significant_change_results(u32 num_results,
278                                    wifi_significant_change_result **results,
279                                    u32 starting_index,
280                                    struct nlattr **tb_vendor)
281{
282    u32 i = starting_index;
283    int j;
284    int rem = 0;
285    u32 len = 0;
286    struct nlattr *scanResultsInfo;
287
288    ALOGE("gscan_get_significant_change_results: starting counter: %d", i);
289
290    for (scanResultsInfo = (struct nlattr *) nla_data(tb_vendor[
291            QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]),
292            rem = nla_len(tb_vendor[
293            QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]);
294        nla_ok(scanResultsInfo, rem);
295        scanResultsInfo = nla_next(scanResultsInfo, &(rem)))
296    {
297        struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
298        nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
299            (struct nlattr *) nla_data(scanResultsInfo),
300                nla_len(scanResultsInfo), NULL);
301        if (!
302            tb2[
303            QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID
304            ])
305        {
306            ALOGE("gscan_get_significant_change_results: "
307                "SIGNIFICANT_CHANGE_RESULT_BSSID not found");
308            return WIFI_ERROR_INVALID_ARGS;
309        }
310        len = nla_len(
311            tb2[
312            QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID]
313            );
314        len =
315            sizeof(results[i]->bssid) <= len ? sizeof(results[i]->bssid) : len;
316        memcpy(&results[i]->bssid[0],
317            nla_data(
318            tb2[
319        QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID]),
320            len);
321        ALOGI("\nsignificant_change_result:%d, BSSID:"
322            "%02x:%02x:%02x:%02x:%02x:%02x \n", i, results[i]->bssid[0],
323            results[i]->bssid[1], results[i]->bssid[2], results[i]->bssid[3],
324            results[i]->bssid[4], results[i]->bssid[5]);
325
326        if (!
327            tb2[
328        QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL
329                ])
330        {
331            ALOGE("gscan_get_significant_change_results: "
332                "SIGNIFICANT_CHANGE_RESULT_CHANNEL not found");
333            return WIFI_ERROR_INVALID_ARGS;
334        }
335        results[i]->channel =
336            nla_get_u32(
337            tb2[
338        QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL]);
339        ALOGI("significant_change_result:%d, channel:%d.\n",
340            i, results[i]->channel);
341
342        if (!
343            tb2[
344        QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI
345            ])
346        {
347            ALOGE("gscan_get_significant_change_results: "
348                "SIGNIFICANT_CHANGE_RESULT_NUM_RSSI not found");
349            return WIFI_ERROR_INVALID_ARGS;
350        }
351        results[i]->num_rssi =
352            nla_get_u32(
353            tb2[
354        QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI]);
355        ALOGI("gscan_get_significant_change_results: "
356            "significant_change_result:%d, num_rssi:%d.\n",
357            i, results[i]->num_rssi);
358
359        if (!
360            tb2[
361        QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST
362            ])
363        {
364            ALOGE("gscan_get_significant_change_results: "
365                "SIGNIFICANT_CHANGE_RESULT_RSSI_LIST not found");
366            return WIFI_ERROR_INVALID_ARGS;
367        }
368        ALOGI("gscan_get_significant_change_results: before reading the RSSI "
369            "list: num_rssi:%d, size_of_rssi:%d, total size:%d, ",
370            results[i]->num_rssi,
371            sizeof(wifi_rssi), results[i]->num_rssi * sizeof(wifi_rssi));
372
373        memcpy(&(results[i]->rssi[0]),
374            nla_data(
375            tb2[
376        QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST]
377            ), results[i]->num_rssi * sizeof(wifi_rssi));
378
379        for (j = 0; j < results[i]->num_rssi; j++)
380            ALOGI("     significant_change_result: %d, rssi[%d]:%d, ",
381            i, j, results[i]->rssi[j]);
382
383        /* Increment loop index to prase next record. */
384        i++;
385    }
386    return WIFI_SUCCESS;
387}
388
389/* This function will be the main handler for incoming (from driver)  GSscan_SUBCMD.
390 *  Calls the appropriate callback handler after parsing the vendor data.
391 */
392int GScanCommandEventHandler::handleEvent(WifiEvent &event)
393{
394    ALOGI("GScanCommandEventHandler::handleEvent: Got a GSCAN Event"
395        " message from the Driver.");
396    unsigned i=0;
397    int ret = WIFI_SUCCESS;
398    u32 status;
399    wifi_scan_result *result;
400    struct nlattr *tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
401
402    WifiVendorCommand::handleEvent(event);
403
404    nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
405                        (struct nlattr *)mVendorData,
406                        mDataLen, NULL);
407
408    switch(mSubcmd)
409    {
410        case QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT:
411        {
412            wifi_request_id reqId;
413            u32 len = 0;
414            u32 resultsBufSize = 0;
415            u32 lengthOfInfoElements = 0;
416
417            ALOGD("Event QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT "
418                "received.");
419
420            if (!tbVendor[
421                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID])
422            {
423                ALOGE("%s: ATTR_GSCAN_RESULTS_REQUEST_ID not found. Exit.",
424                    __func__);
425                ret = WIFI_ERROR_INVALID_ARGS;
426                break;
427            }
428            reqId = nla_get_u32(
429                    tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]
430                    );
431            /* If this is not for us, just ignore it. */
432            if (reqId != mRequestId) {
433                ALOGE("%s: Event has Req. ID:%d <> Ours:%d, ignore it.",
434                    __func__, reqId, mRequestId);
435                break;
436            }
437
438            /* Parse and extract the results. */
439            if (!
440                tbVendor[
441                    QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_LENGTH
442                ])
443            {
444                ALOGE("%s:RESULTS_SCAN_RESULT_IE_LENGTH not found", __func__);
445                ret = WIFI_ERROR_INVALID_ARGS;
446                break;
447            }
448            lengthOfInfoElements =
449                nla_get_u32(
450                tbVendor[
451                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_LENGTH]);
452            ALOGI("%s: RESULTS_SCAN_RESULT_IE_LENGTH =%d",
453                __func__, lengthOfInfoElements);
454            resultsBufSize =
455                lengthOfInfoElements + sizeof(wifi_scan_result);
456            result = (wifi_scan_result *) malloc (resultsBufSize);
457            if (!result) {
458                ALOGE("%s: Failed to alloc memory for result struct. Exit.\n",
459                    __func__);
460                ret = WIFI_ERROR_OUT_OF_MEMORY;
461                break;
462            }
463            memset(result, 0, resultsBufSize);
464
465            result->ie_length = lengthOfInfoElements;
466
467            /* Extract and fill out the wifi_scan_result struct. */
468            if (!
469            tbVendor[
470                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
471                ])
472            {
473                ALOGE("%s: RESULTS_SCAN_RESULT_TIME_STAMP not found",
474                    __func__);
475                ret = WIFI_ERROR_INVALID_ARGS;
476                break;
477            }
478            result->ts =
479                nla_get_u64(
480                tbVendor[
481                    QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
482                    ]);
483
484            if (!
485                tbVendor[
486                    QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID
487                    ])
488            {
489                ALOGE("%s: RESULTS_SCAN_RESULT_SSID not found", __func__);
490                ret = WIFI_ERROR_INVALID_ARGS;
491                break;
492            }
493            len = nla_len(tbVendor[
494                    QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]);
495            len =
496                sizeof(result->ssid) <= len ? sizeof(result->ssid) : len;
497            memcpy((void *)&result->ssid,
498                nla_data(
499                tbVendor[
500                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]), len);
501
502            if (!
503                tbVendor[
504                    QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID
505                    ])
506            {
507                ALOGE("%s: RESULTS_SCAN_RESULT_BSSID not found", __func__);
508                ret = WIFI_ERROR_INVALID_ARGS;
509                break;
510            }
511            len = nla_len(
512                tbVendor[
513                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]);
514            len =
515                sizeof(result->bssid) <= len ? sizeof(result->bssid) : len;
516            memcpy(&result->bssid,
517                nla_data(
518                tbVendor[
519                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]), len);
520
521            if (!
522                tbVendor[
523                    QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL
524                    ])
525            {
526                ALOGE("%s: RESULTS_SCAN_RESULT_CHANNEL not found", __func__);
527                ret = WIFI_ERROR_INVALID_ARGS;
528                break;
529            }
530            result->channel =
531                nla_get_u32(
532                tbVendor[
533                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]);
534
535            if (!
536                tbVendor[
537                    QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI
538                    ])
539            {
540                ALOGE("%s: RESULTS_SCAN_RESULT_RSSI not found", __func__);
541                ret = WIFI_ERROR_INVALID_ARGS;
542                break;
543            }
544            result->rssi =
545                nla_get_u32(
546                tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI]
547                );
548
549            if (!
550                tbVendor[
551                    QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT
552                    ])
553            {
554                ALOGE("%s: RESULTS_SCAN_RESULT_RTT not found", __func__);
555                ret = WIFI_ERROR_INVALID_ARGS;
556                break;
557            }
558            result->rtt =
559                nla_get_u32(
560                tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]);
561
562            if (!
563                tbVendor[
564                    QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD
565                ])
566            {
567                ALOGE("%s: RESULTS_SCAN_RESULT_RTT_SD not found", __func__);
568                ret = WIFI_ERROR_INVALID_ARGS;
569                break;
570            }
571            result->rtt_sd =
572                nla_get_u32(
573                tbVendor[
574                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]);
575
576            if (!
577                tbVendor[
578                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD])
579            {
580                ALOGE("%s: RESULTS_SCAN_RESULT_BEACON_PERIOD not found",
581                    __func__);
582                ret = WIFI_ERROR_INVALID_ARGS;
583                break;
584            }
585            result->beacon_period =
586                nla_get_u16(
587                tbVendor[
588                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD]);
589
590            if (!
591                tbVendor[
592                    QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CAPABILITY
593                    ])
594            {
595                ALOGE("%s: RESULTS_SCAN_RESULT_CAPABILITY not found", __func__);
596                ret = WIFI_ERROR_INVALID_ARGS;
597                break;
598            }
599            result->capability =
600                nla_get_u16(
601                tbVendor[
602                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CAPABILITY]);
603
604            if (!
605                tbVendor[
606                    QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_DATA
607                ])
608            {
609                ALOGE("%s: RESULTS_SCAN_RESULT_IE_DATA not found", __func__);
610                ret = WIFI_ERROR_INVALID_ARGS;
611                break;
612            }
613            memcpy(&(result->ie_data[0]),
614                nla_data(tbVendor[
615                    QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_DATA]),
616                lengthOfInfoElements);
617
618            ALOGE("handleEvent:FULL_SCAN_RESULTS: ts  %lld ", result->ts);
619            ALOGE("handleEvent:FULL_SCAN_RESULTS: SSID  %s ", result->ssid) ;
620            ALOGE("handleEvent:FULL_SCAN_RESULTS: "
621                "BSSID: %02x:%02x:%02x:%02x:%02x:%02x \n",
622                result->bssid[0], result->bssid[1], result->bssid[2],
623                result->bssid[3], result->bssid[4], result->bssid[5]);
624            ALOGE("handleEvent:FULL_SCAN_RESULTS: channel %d ",
625                result->channel);
626            ALOGE("handleEvent:FULL_SCAN_RESULTS: rssi  %d ", result->rssi);
627            ALOGE("handleEvent:FULL_SCAN_RESULTS: rtt  %lld ", result->rtt);
628            ALOGE("handleEvent:FULL_SCAN_RESULTS: rtt_sd  %lld ",
629                result->rtt_sd);
630            ALOGE("handleEvent:FULL_SCAN_RESULTS: beacon period  %d ",
631                result->beacon_period);
632            ALOGE("handleEvent:FULL_SCAN_RESULTS: capability  %d ",
633                result->capability);
634            ALOGE("handleEvent:FULL_SCAN_RESULTS: IE length  %d ",
635                result->ie_length);
636
637            ALOGE("%s: Invoking the callback. \n", __func__);
638            if (mHandler.on_full_scan_result) {
639                (*mHandler.on_full_scan_result)(reqId, result);
640                /* Reset flag and num counter. */
641                free(result);
642                result = NULL;
643            }
644        }
645        break;
646
647        case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE:
648        {
649            wifi_request_id id;
650            u32 numResults = 0;
651
652            ALOGD("Event "
653                "QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE "
654                "received.");
655
656            if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]) {
657                ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID"
658                    "not found. Exit", __func__);
659                ret = WIFI_ERROR_INVALID_ARGS;
660                break;
661            }
662            id = nla_get_u32(
663                    tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]
664                    );
665            /* If this is not for us, then ignore it. */
666            if (id != mRequestId) {
667                ALOGE("%s: Event has Req. ID:%d <> ours:%d",
668                    __func__, id, mRequestId);
669                break;
670            }
671            if (!tbVendor[
672                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]) {
673                ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not found",
674                    __func__);
675                ret = WIFI_ERROR_INVALID_ARGS;
676                break;
677            }
678            numResults = nla_get_u32(tbVendor[
679                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]);
680            ALOGE("%s: number of results:%d", __func__, numResults);
681
682            /* Invoke the callback func to report the number of results. */
683            ALOGE("%s: Calling on_scan_results_available handler",
684                __func__);
685            if (!mHandler.on_scan_results_available) {
686                break;
687            }
688            (*mHandler.on_scan_results_available)(id, numResults);
689        }
690        break;
691
692        case QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND:
693        {
694            wifi_request_id id;
695            u32 resultsBufSize = 0;
696            u32 numResults = 0;
697            u32 startingIndex, sizeOfObtainedResults;
698
699            ALOGD("Event QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND "
700                "received.");
701
702            id = nla_get_u32(
703                    tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]
704                    );
705            /* If this is not for us, just ignore it. */
706            if (id != mRequestId) {
707                ALOGE("%s: Event has Req. ID:%d <> ours:%d",
708                    __func__, id, mRequestId);
709                break;
710            }
711            if (!tbVendor[
712                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]) {
713                ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not found",
714                    __func__);
715                ret = WIFI_ERROR_INVALID_ARGS;
716                break;
717            }
718            numResults = nla_get_u32(tbVendor[
719                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]);
720            ALOGE("%s: number of results:%d", __func__, numResults);
721
722            /* Get the memory size of previous fragments, if any. */
723            sizeOfObtainedResults = mHotlistApFoundNumResults *
724                          sizeof(wifi_scan_result);
725
726            mHotlistApFoundNumResults += numResults;
727            resultsBufSize += mHotlistApFoundNumResults *
728                                            sizeof(wifi_scan_result);
729
730            /* Check if this chunck of scan results is a continuation of
731             * a previous one.
732             */
733            if (mHotlistApFoundMoreData) {
734                mHotlistApFoundResults = (wifi_scan_result *)
735                            realloc (mHotlistApFoundResults, resultsBufSize);
736            } else {
737                mHotlistApFoundResults = (wifi_scan_result *)
738                            malloc (resultsBufSize);
739            }
740
741            if (!mHotlistApFoundResults) {
742                ALOGE("%s: Failed to alloc memory for results array. Exit.\n",
743                    __func__);
744                ret = WIFI_ERROR_OUT_OF_MEMORY;
745                break;
746            }
747            /* Initialize the newly allocated memory area with 0. */
748            memset((u8 *)mHotlistApFoundResults + sizeOfObtainedResults, 0,
749                    resultsBufSize - sizeOfObtainedResults);
750
751            ALOGE("%s: Num of AP FOUND results = %d. \n", __func__,
752                                            mHotlistApFoundNumResults);
753
754            /* To support fragmentation from firmware, monitor the
755             * MORE_DTATA flag and cache results until MORE_DATA = 0.
756             * Only then we can pass on the results to framework through
757             * the callback function.
758             */
759            if (!tbVendor[
760                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]) {
761                ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_MORE_DATA not"
762                    " found", __func__);
763                ret = WIFI_ERROR_INVALID_ARGS;
764                break;
765            } else {
766                mHotlistApFoundMoreData = nla_get_u8(
767                    tbVendor[
768                    QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]);
769                ALOGE("%s: More data = %d. \n",
770                    __func__, mHotlistApFoundMoreData);
771            }
772
773            ALOGE("%s: Extract hotlist_ap_found results.\n", __func__);
774            startingIndex = mHotlistApFoundNumResults - numResults;
775            ALOGE("%s: starting_index:%d",
776                __func__, startingIndex);
777            ret = gscan_get_hotlist_ap_found_results(numResults,
778                                                mHotlistApFoundResults,
779                                                startingIndex,
780                                                tbVendor);
781            /* If a parsing error occurred, exit and proceed for cleanup. */
782            if (ret)
783                break;
784            /* Send the results if no more result data fragments are expected. */
785            if (!mHotlistApFoundMoreData) {
786                (*mHandler.on_hotlist_ap_found)(id,
787                                                mHotlistApFoundNumResults,
788                                                mHotlistApFoundResults);
789                /* Reset flag and num counter. */
790                free(mHotlistApFoundResults);
791                mHotlistApFoundResults = NULL;
792                mHotlistApFoundMoreData = false;
793                mHotlistApFoundNumResults = 0;
794            }
795        }
796        break;
797
798        case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE:
799        {
800            wifi_request_id reqId;
801            u32 numResults = 0, sizeOfObtainedResults;
802            u32 startingIndex, index = 0;
803            struct nlattr *scanResultsInfo;
804            int rem = 0;
805
806            ALOGD("Event QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE "
807                "received.");
808
809            if (!tbVendor[
810                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID])
811            {
812                ALOGE("%s: ATTR_GSCAN_RESULTS_REQUEST_ID not found. Exit.",
813                    __func__);
814                ret = WIFI_ERROR_INVALID_ARGS;
815                break;
816            }
817            reqId = nla_get_u32(
818                    tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]
819                    );
820            /* If this is not for us, just ignore it. */
821            if (reqId != mRequestId) {
822                ALOGE("%s: Event has Req. ID:%d <> ours:%d",
823                    __func__, reqId, mRequestId);
824                break;
825            }
826            if (!tbVendor[
827                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE])
828            {
829                ALOGE("%s: ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not found."
830                    "Exit.", __func__);
831                ret = WIFI_ERROR_INVALID_ARGS;
832                break;
833            }
834            numResults = nla_get_u32(tbVendor[
835                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]);
836            /* Get the memory size of previous fragments, if any. */
837            sizeOfObtainedResults = sizeof(wifi_significant_change_result *) *
838                                mSignificantChangeNumResults;
839
840            index = mSignificantChangeNumResults;
841            mSignificantChangeNumResults += numResults;
842            /*
843             * Check if this chunck of wifi_significant_change results is a
844             * continuation of a previous one.
845             */
846            if (mSignificantChangeMoreData) {
847                mSignificantChangeResults =
848                    (wifi_significant_change_result **)
849                        realloc (mSignificantChangeResults,
850                        sizeof(wifi_significant_change_result *) *
851                                mSignificantChangeNumResults);
852            } else {
853                mSignificantChangeResults =
854                    (wifi_significant_change_result **)
855                        malloc (sizeof(wifi_significant_change_result *) *
856                                mSignificantChangeNumResults);
857            }
858
859            if (!mSignificantChangeResults) {
860                ALOGE("%s: Failed to alloc memory for results array. Exit.\n",
861                    __func__);
862                ret = WIFI_ERROR_OUT_OF_MEMORY;
863                break;
864            }
865            /* Initialize the newly allocated memory area with 0. */
866            memset((u8 *)mSignificantChangeResults + sizeOfObtainedResults, 0,
867                    sizeof(wifi_significant_change_result *) *
868                                numResults);
869            ALOGD("%s: mSignificantChangeMoreData = %d",
870                    __func__, mSignificantChangeMoreData);
871
872            for (scanResultsInfo = (struct nlattr *) nla_data(tbVendor[
873                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]),
874                rem = nla_len(tbVendor[
875                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]);
876                nla_ok(scanResultsInfo, rem);
877                scanResultsInfo = nla_next(scanResultsInfo, &(rem)))
878            {
879                u32 num_rssi = 0;
880                u32 resultsBufSize = 0;
881                struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
882                nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
883                    (struct nlattr *) nla_data(scanResultsInfo),
884                    nla_len(scanResultsInfo), NULL);
885                if (!tb2[
886                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI
887                    ])
888                {
889                    ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_"
890                        "SIGNIFICANT_CHANGE_RESULT_NUM_RSSI not found. "
891                        "Exit.", __func__);
892                    ret = WIFI_ERROR_INVALID_ARGS;
893                    break;
894                }
895                num_rssi = nla_get_u32(tb2[
896                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI
897                        ]);
898                resultsBufSize = sizeof(wifi_significant_change_result) +
899                            num_rssi * sizeof(wifi_rssi);
900                mSignificantChangeResults[index] =
901                    (wifi_significant_change_result *) malloc (resultsBufSize);
902
903                if (!mSignificantChangeResults[index]) {
904                    ALOGE("%s: Failed to alloc memory for results array. Exit.\n",
905                        __func__);
906                    ret = WIFI_ERROR_OUT_OF_MEMORY;
907                    break;
908                }
909                /* Initialize the newly allocated memory area with 0. */
910                memset((u8 *)mSignificantChangeResults[index],
911                        0, resultsBufSize);
912
913                ALOGE("%s: For Significant Change results[%d], num_rssi:%d\n",
914                    __func__, index, num_rssi);
915                index++;
916            }
917
918            ALOGE("%s: Extract significant change results.\n", __func__);
919            startingIndex =
920                mSignificantChangeNumResults - numResults;
921            ret = gscan_get_significant_change_results(numResults,
922                                                mSignificantChangeResults,
923                                                startingIndex,
924                                                tbVendor);
925            /* If a parsing error occurred, exit and proceed for cleanup. */
926            if (ret)
927                break;
928            /* To support fragmentation from firmware, monitor the
929             * MORE_DTATA flag and cache results until MORE_DATA = 0.
930             * Only then we can pass on the results to framework through
931             * the callback function.
932             */
933            if (!tbVendor[
934                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]) {
935                ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_MORE_DATA not"
936                    " found. Stop parsing and exit.", __func__);
937                break;
938            }
939            mSignificantChangeMoreData = nla_get_u8(
940                tbVendor[
941                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]);
942            ALOGE("%s: More data = %d. \n",
943                __func__, mSignificantChangeMoreData);
944
945            /* Send the results if no more result fragments are expected */
946            if (!mSignificantChangeMoreData) {
947                ALOGE("%s: Invoking the callback. \n", __func__);
948                (*mHandler.on_significant_change)(reqId,
949                                              mSignificantChangeNumResults,
950                                              mSignificantChangeResults);
951                /* Reset flag and num counter. */
952                for (index = 0; index  < mSignificantChangeNumResults; index++)
953                {
954                    free(mSignificantChangeResults[index]);
955                    mSignificantChangeResults[index] = NULL;
956                }
957                free(mSignificantChangeResults);
958                mSignificantChangeResults = NULL;
959                mSignificantChangeNumResults = 0;
960                mSignificantChangeMoreData = false;
961            }
962        }
963        break;
964
965        case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT:
966        {
967            wifi_scan_event scanEvent;
968            u32 scanEventStatus = 0;
969            wifi_request_id reqId;
970
971            ALOGD("Event QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT "
972                "received.");
973
974            if (!tbVendor[
975                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID])
976            {
977                ALOGE("%s: ATTR_GSCAN_RESULTS_REQUEST_ID not found. Exit.",
978                    __func__);
979                ret = WIFI_ERROR_INVALID_ARGS;
980                break;
981            }
982            reqId = nla_get_u32(
983                    tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]
984                    );
985            /* If this is not for us, just ignore it. */
986            if (reqId != mRequestId) {
987                ALOGE("%s: Event has Req. ID:%d <> ours:%d",
988                    __func__, reqId, mRequestId);
989                break;
990            }
991
992            if (!tbVendor[
993                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_TYPE]) {
994                ALOGE("%s: GSCAN_RESULTS_SCAN_EVENT_TYPE not"
995                    " found. Stop parsing and exit.", __func__);
996                break;
997            }
998            scanEvent = (wifi_scan_event) nla_get_u8(tbVendor[
999                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_TYPE]);
1000
1001            if (!tbVendor[
1002                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_STATUS]) {
1003                ALOGE("%s: GSCAN_RESULTS_SCAN_EVENT_STATUS not"
1004                    " found. Stop parsing and exit.", __func__);
1005                break;
1006            }
1007            scanEventStatus = nla_get_u32(tbVendor[
1008                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_STATUS]);
1009
1010            ALOGE("%s: Scan event type: %d, status = %d. \n", __func__,
1011                                    scanEvent, scanEventStatus);
1012            /* Send the results if no more result fragments are expected. */
1013            (*mHandler.on_scan_event)(scanEvent, scanEventStatus);
1014        }
1015        break;
1016
1017        default:
1018            /* Error case should not happen print log */
1019            ALOGE("%s: Wrong GScan subcmd received %d", __func__, mSubcmd);
1020    }
1021
1022    /* A parsing error occurred, do the cleanup of gscan result lists. */
1023    if (ret) {
1024        switch(mSubcmd)
1025        {
1026            case QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT:
1027            {
1028                free(result);
1029                result = NULL;
1030            }
1031            break;
1032
1033            case QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND:
1034            {
1035                /* Reset flag and num counter. */
1036                free(mHotlistApFoundResults);
1037                mHotlistApFoundResults = NULL;
1038                mHotlistApFoundMoreData = false;
1039                mHotlistApFoundNumResults = 0;
1040            }
1041            break;
1042
1043            case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE:
1044            {
1045                for (i = 0; i < mSignificantChangeNumResults; i++)
1046                {
1047                    if (mSignificantChangeResults[i]) {
1048                        free(mSignificantChangeResults[i]);
1049                        mSignificantChangeResults[i] = NULL;
1050                    }
1051                }
1052                free(mSignificantChangeResults);
1053                mSignificantChangeResults = NULL;
1054                mSignificantChangeNumResults = 0;
1055                mSignificantChangeMoreData = false;
1056            }
1057            break;
1058
1059            case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE:
1060            break;
1061
1062            case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT:
1063            break;
1064
1065            default:
1066                ALOGE("%s: Parsing err handler: wrong GScan subcmd "
1067                    "received %d", __func__, mSubcmd);
1068        }
1069    }
1070    return NL_SKIP;
1071}
1072