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 #define LOG_TAG  "WifiHAL"
18 
19 #include <utils/Log.h>
20 #include "gscan_event_handler.h"
21 
22 /* This function implements creation of Vendor command event handler. */
create()23 wifi_error GScanCommandEventHandler::create() {
24     wifi_error ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
25     if (ret != WIFI_SUCCESS)
26         return ret;
27 
28     /* Insert the oui in the msg */
29     ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
30     if (ret != WIFI_SUCCESS)
31         return ret;
32 
33     /* Insert the subcmd in the msg */
34     ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
35 
36     return ret;
37 }
38 
get_request_id()39 int GScanCommandEventHandler::get_request_id()
40 {
41     return mRequestId;
42 }
43 
set_request_id(int request_id)44 void GScanCommandEventHandler::set_request_id(int request_id)
45 {
46     mRequestId = request_id;
47 }
48 
enableEventHandling()49 void GScanCommandEventHandler::enableEventHandling()
50 {
51     mEventHandlingEnabled = true;
52 }
53 
disableEventHandling()54 void GScanCommandEventHandler::disableEventHandling()
55 {
56     mEventHandlingEnabled = false;
57 }
58 
isEventHandlingEnabled()59 bool GScanCommandEventHandler::isEventHandlingEnabled()
60 {
61     return mEventHandlingEnabled;
62 }
63 
setCallbackHandler(GScanCallbackHandler handler)64 void GScanCommandEventHandler::setCallbackHandler(GScanCallbackHandler handler)
65 {
66     mHandler = handler;
67 }
68 
GScanCommandEventHandler(wifi_handle handle,int id,u32 vendor_id,u32 subcmd,GScanCallbackHandler handler)69 GScanCommandEventHandler::GScanCommandEventHandler(wifi_handle handle, int id,
70                                                 u32 vendor_id,
71                                                 u32 subcmd,
72                                                 GScanCallbackHandler handler)
73         : WifiVendorCommand(handle, id, vendor_id, subcmd)
74 {
75     int ret = 0;
76     mRequestId = id;
77     mHandler = handler;
78     mSubCommandId = subcmd;
79     mHotlistApFoundResults = NULL;
80     mHotlistApFoundNumResults = 0;
81     mHotlistApFoundMoreData = false;
82     mHotlistApLostResults = NULL;
83     mHotlistApLostNumResults = 0;
84     mHotlistApLostMoreData = false;
85     mSignificantChangeResults = NULL;
86     mSignificantChangeNumResults = 0;
87     mSignificantChangeMoreData = false;
88     mHotlistSsidFoundNumResults = 0;
89     mHotlistSsidFoundMoreData = false;
90     mHotlistSsidLostNumResults = 0;
91     mHotlistSsidLostMoreData = false;
92     mHotlistSsidFoundResults = NULL;
93     mHotlistSsidLostResults = NULL;
94     mPnoNetworkFoundResults = NULL;
95     mPnoNetworkFoundNumResults = 0;
96     mPnoNetworkFoundMoreData = false;
97     mPasspointNetworkFoundResult = NULL;
98     mPasspointAnqp = NULL;
99     mPasspointAnqpLen = 0;
100     mPasspointNetId = -1;
101     mEventHandlingEnabled = false;
102 
103     switch(mSubCommandId)
104     {
105         case QCA_NL80211_VENDOR_SUBCMD_GSCAN_START:
106         {
107             /* Register handlers for northbound asychronous scan events. */
108             ret = registerVendorHandler(mVendor_id,
109                     QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE) ||
110                   registerVendorHandler(mVendor_id,
111                     QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT) ||
112                   registerVendorHandler(mVendor_id,
113                     QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT);
114             if (ret)
115                 ALOGE("%s: Error in registering handler for "
116                     "GSCAN_START. \n", __FUNCTION__);
117         }
118         break;
119 
120         case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SIGNIFICANT_CHANGE:
121         {
122             ret = registerVendorHandler(mVendor_id,
123                     QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE);
124             if (ret)
125                 ALOGE("%s: Error in registering handler for "
126                     "GSCAN_SIGNIFICANT_CHANGE. \n", __FUNCTION__);
127         }
128         break;
129 
130         case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_BSSID_HOTLIST:
131         {
132             ret = registerVendorHandler(mVendor_id,
133                     QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND);
134             if (ret)
135                 ALOGE("%s: Error in registering handler for"
136                     " GSCAN_HOTLIST_AP_FOUND. \n", __FUNCTION__);
137 
138             ret = registerVendorHandler(mVendor_id,
139                     QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_LOST);
140             if (ret)
141                 ALOGE("%s: Error in registering handler for"
142                     " GSCAN_HOTLIST_AP_LOST. \n", __FUNCTION__);
143         }
144         break;
145 
146         case QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST:
147         {
148             ret = registerVendorHandler(mVendor_id,
149                     QCA_NL80211_VENDOR_SUBCMD_PNO_NETWORK_FOUND);
150             if (ret)
151                 ALOGE("%s: Error in registering handler for"
152                     " PNO_NETWORK_FOUND. \n", __FUNCTION__);
153         }
154         break;
155 
156         case QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST:
157         {
158             ret = registerVendorHandler(mVendor_id,
159                 QCA_NL80211_VENDOR_SUBCMD_PNO_PASSPOINT_NETWORK_FOUND);
160             if (ret)
161                 ALOGE("%s: Error in registering handler for"
162                     " PNO_PASSPOINT_NETWORK_FOUND. \n", __FUNCTION__);
163         }
164         break;
165     }
166 }
167 
~GScanCommandEventHandler()168 GScanCommandEventHandler::~GScanCommandEventHandler()
169 {
170     switch(mSubCommandId)
171     {
172         case QCA_NL80211_VENDOR_SUBCMD_GSCAN_START:
173         {
174             /* Unregister event handlers. */
175             unregisterVendorHandler(mVendor_id,
176                     QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE);
177             unregisterVendorHandler(mVendor_id,
178                     QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT);
179             unregisterVendorHandler(mVendor_id,
180                     QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT);
181         }
182         break;
183 
184         case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SIGNIFICANT_CHANGE:
185         {
186             unregisterVendorHandler(mVendor_id,
187                     QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE);
188         }
189         break;
190 
191         case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_BSSID_HOTLIST:
192         {
193             unregisterVendorHandler(mVendor_id,
194                     QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND);
195             unregisterVendorHandler(mVendor_id,
196                     QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_LOST);
197         }
198         break;
199 
200         case QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST:
201         {
202             unregisterVendorHandler(mVendor_id,
203                 QCA_NL80211_VENDOR_SUBCMD_PNO_NETWORK_FOUND);
204         }
205         break;
206 
207         case QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST:
208         {
209             unregisterVendorHandler(mVendor_id,
210                 QCA_NL80211_VENDOR_SUBCMD_PNO_PASSPOINT_NETWORK_FOUND);
211         }
212         break;
213     }
214 }
215 
gscan_parse_hotlist_ap_results(u32 num_results,wifi_scan_result * results,u32 starting_index,struct nlattr ** tb_vendor)216 wifi_error GScanCommandEventHandler::gscan_parse_hotlist_ap_results(
217                                             u32 num_results,
218                                             wifi_scan_result *results,
219                                             u32 starting_index,
220                                             struct nlattr **tb_vendor)
221 {
222     u32 i = starting_index;
223     struct nlattr *scanResultsInfo;
224     int rem = 0;
225     u32 len = 0;
226     ALOGV("gscan_parse_hotlist_ap_results: starting counter: %d", i);
227 
228     for (scanResultsInfo = (struct nlattr *) nla_data(tb_vendor[
229             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]),
230             rem = nla_len(tb_vendor[
231             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST
232             ]);
233                 nla_ok(scanResultsInfo, rem);
234                 scanResultsInfo = nla_next(scanResultsInfo, &(rem)))
235     {
236         struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
237         nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
238         (struct nlattr *) nla_data(scanResultsInfo),
239                 nla_len(scanResultsInfo), NULL);
240 
241         if (!
242             tb2[
243                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
244                 ])
245         {
246             ALOGE("gscan_parse_hotlist_ap_results: "
247                 "RESULTS_SCAN_RESULT_TIME_STAMP not found");
248             return WIFI_ERROR_INVALID_ARGS;
249         }
250         results[i].ts =
251             nla_get_u64(
252             tb2[
253                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
254                 ]);
255         if (!
256             tb2[
257                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID
258                 ])
259         {
260             ALOGE("gscan_parse_hotlist_ap_results: "
261                 "RESULTS_SCAN_RESULT_SSID not found");
262             return WIFI_ERROR_INVALID_ARGS;
263         }
264         len = nla_len(tb2[
265                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]);
266         len =
267             sizeof(results->ssid) <= len ? sizeof(results->ssid) : len;
268         memcpy((void *)&results[i].ssid,
269             nla_data(
270             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]), len);
271         if (!
272             tb2[
273                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID
274                 ])
275         {
276             ALOGE("gscan_parse_hotlist_ap_results: "
277                 "RESULTS_SCAN_RESULT_BSSID not found");
278             return WIFI_ERROR_INVALID_ARGS;
279         }
280         len = nla_len(
281             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]);
282         len =
283             sizeof(results->bssid) <= len ? sizeof(results->bssid) : len;
284         memcpy(&results[i].bssid,
285             nla_data(
286             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]), len);
287         if (!
288             tb2[
289                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL
290                 ])
291         {
292             ALOGE("gscan_parse_hotlist_ap_results: "
293                 "RESULTS_SCAN_RESULT_CHANNEL not found");
294             return WIFI_ERROR_INVALID_ARGS;
295         }
296         results[i].channel =
297             nla_get_u32(
298             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]);
299         if (!
300             tb2[
301                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI
302                 ])
303         {
304             ALOGE("gscan_parse_hotlist_ap_results: "
305                 "RESULTS_SCAN_RESULT_RSSI not found");
306             return WIFI_ERROR_INVALID_ARGS;
307         }
308         results[i].rssi =
309             get_s32(
310             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI]);
311         if (!
312             tb2[
313                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT
314                 ])
315         {
316             ALOGE("gscan_parse_hotlist_ap_results: "
317                 "RESULTS_SCAN_RESULT_RTT not found");
318             return WIFI_ERROR_INVALID_ARGS;
319         }
320         results[i].rtt =
321             nla_get_u32(
322             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]);
323         if (!
324             tb2[
325                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD
326             ])
327         {
328             ALOGE("gscan_parse_hotlist_ap_results: "
329                 "RESULTS_SCAN_RESULT_RTT_SD not found");
330             return WIFI_ERROR_INVALID_ARGS;
331         }
332         results[i].rtt_sd =
333             nla_get_u32(
334             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]);
335 
336         ALOGV("gscan_parse_hotlist_ap_results: ts %" PRId64 " SSID  %s "
337               "BSSID: %02x:%02x:%02x:%02x:%02x:%02x channel %d rssi %d "
338               "rtt %" PRId64" rtt_sd %" PRId64,
339               results[i].ts, results[i].ssid,
340               results[i].bssid[0], results[i].bssid[1], results[i].bssid[2],
341               results[i].bssid[3], results[i].bssid[4], results[i].bssid[5],
342               results[i].channel, results[i].rssi, results[i].rtt,
343               results[i].rtt_sd);
344         /* Increment loop index for next record */
345         i++;
346     }
347     return WIFI_SUCCESS;
348 }
349 
gscan_get_significant_change_results(u32 num_results,wifi_significant_change_result ** results,u32 starting_index,struct nlattr ** tb_vendor)350 static wifi_error gscan_get_significant_change_results(u32 num_results,
351                                     wifi_significant_change_result **results,
352                                     u32 starting_index,
353                                     struct nlattr **tb_vendor)
354 {
355     u32 i = starting_index;
356     int j;
357     int rem = 0;
358     u32 len = 0;
359     char rssi_buf[1024]; //TODO: sizeof buf
360     int rem_size;
361     struct nlattr *scanResultsInfo;
362 
363     for (scanResultsInfo = (struct nlattr *) nla_data(tb_vendor[
364             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]),
365             rem = nla_len(tb_vendor[
366             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]);
367         nla_ok(scanResultsInfo, rem);
368         scanResultsInfo = nla_next(scanResultsInfo, &(rem)))
369     {
370         struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
371         nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
372             (struct nlattr *) nla_data(scanResultsInfo),
373                 nla_len(scanResultsInfo), NULL);
374         if (!
375             tb2[
376             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID
377             ])
378         {
379             ALOGE("gscan_get_significant_change_results: "
380                 "SIGNIFICANT_CHANGE_RESULT_BSSID not found");
381             return WIFI_ERROR_INVALID_ARGS;
382         }
383         len = nla_len(
384             tb2[
385             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID]
386             );
387         len =
388             sizeof(results[i]->bssid) <= len ? sizeof(results[i]->bssid) : len;
389         memcpy(&results[i]->bssid[0],
390             nla_data(
391             tb2[
392         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID]),
393             len);
394 
395         if (!
396             tb2[
397         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL
398                 ])
399         {
400             ALOGE("gscan_get_significant_change_results: "
401                 "SIGNIFICANT_CHANGE_RESULT_CHANNEL not found");
402             return WIFI_ERROR_INVALID_ARGS;
403         }
404         results[i]->channel =
405             nla_get_u32(
406             tb2[
407         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL]);
408 
409         if (!
410             tb2[
411         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI
412             ])
413         {
414             ALOGE("gscan_get_significant_change_results: "
415                 "SIGNIFICANT_CHANGE_RESULT_NUM_RSSI not found");
416             return WIFI_ERROR_INVALID_ARGS;
417         }
418         results[i]->num_rssi =
419             nla_get_u32(
420             tb2[
421         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI]);
422 
423         if (!
424             tb2[
425         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST
426             ])
427         {
428             ALOGE("gscan_get_significant_change_results: "
429                 "SIGNIFICANT_CHANGE_RESULT_RSSI_LIST not found");
430             return WIFI_ERROR_INVALID_ARGS;
431         }
432 
433         memcpy(&(results[i]->rssi[0]),
434             nla_data(
435             tb2[
436         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST]
437             ), results[i]->num_rssi * sizeof(wifi_rssi));
438 
439         ALOGV("significant_change_result:%d, BSSID:"
440             "%02x:%02x:%02x:%02x:%02x:%02x channel:%d  num_rssi:%d ",
441             i, results[i]->bssid[0], results[i]->bssid[1], results[i]->bssid[2],
442             results[i]->bssid[3], results[i]->bssid[4], results[i]->bssid[5],
443             results[i]->channel, results[i]->num_rssi);
444 
445         rem_size = sizeof(rssi_buf);
446         char *dst = rssi_buf;
447         for (j = 0; j < results[i]->num_rssi && rem_size > 0; j++) {
448             len = snprintf(dst, rem_size, "rssi[%d]:%d, ", j, results[i]->rssi[j]);
449             dst += len;
450             rem_size -= len;
451         }
452         ALOGV("RSSI LIST: %s", rssi_buf);
453 
454         /* Increment loop index to prase next record. */
455         i++;
456     }
457     return WIFI_SUCCESS;
458 }
459 
gscan_parse_hotlist_ssid_results(u32 num_results,wifi_scan_result * results,u32 starting_index,struct nlattr ** tb_vendor)460 wifi_error GScanCommandEventHandler::gscan_parse_hotlist_ssid_results(
461                                             u32 num_results,
462                                             wifi_scan_result *results,
463                                             u32 starting_index,
464                                             struct nlattr **tb_vendor)
465 {
466     u32 i = starting_index;
467     struct nlattr *scanResultsInfo;
468     int rem = 0;
469     u32 len = 0;
470 
471     for (scanResultsInfo = (struct nlattr *) nla_data(tb_vendor[
472             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]),
473             rem = nla_len(tb_vendor[
474             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST
475             ]);
476                 nla_ok(scanResultsInfo, rem);
477                 scanResultsInfo = nla_next(scanResultsInfo, &(rem)))
478     {
479         struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
480         nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
481         (struct nlattr *) nla_data(scanResultsInfo),
482                 nla_len(scanResultsInfo), NULL);
483 
484         if (!
485             tb2[
486                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
487                 ])
488         {
489             ALOGE("gscan_parse_hotlist_ssid_results: "
490                 "RESULTS_SCAN_RESULT_TIME_STAMP not found");
491             return WIFI_ERROR_INVALID_ARGS;
492         }
493         results[i].ts =
494             nla_get_u64(
495             tb2[
496                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
497                 ]);
498         if (!
499             tb2[
500                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID
501                 ])
502         {
503             ALOGE("gscan_parse_hotlist_ssid_results: "
504                 "RESULTS_SCAN_RESULT_SSID not found");
505             return WIFI_ERROR_INVALID_ARGS;
506         }
507         len = nla_len(tb2[
508                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]);
509         len =
510             sizeof(results->ssid) <= len ? sizeof(results->ssid) : len;
511         memcpy((void *)&results[i].ssid,
512             nla_data(
513             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]), len);
514         if (!
515             tb2[
516                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID
517                 ])
518         {
519             ALOGE("gscan_parse_hotlist_ssid_results: "
520                 "RESULTS_SCAN_RESULT_BSSID not found");
521             return WIFI_ERROR_INVALID_ARGS;
522         }
523         len = nla_len(
524             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]);
525         len =
526             sizeof(results->bssid) <= len ? sizeof(results->bssid) : len;
527         memcpy(&results[i].bssid,
528             nla_data(
529             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]), len);
530         if (!
531             tb2[
532                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL
533                 ])
534         {
535             ALOGE("gscan_parse_hotlist_ssid_results: "
536                 "RESULTS_SCAN_RESULT_CHANNEL not found");
537             return WIFI_ERROR_INVALID_ARGS;
538         }
539         results[i].channel =
540             nla_get_u32(
541             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]);
542         if (!
543             tb2[
544                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI
545                 ])
546         {
547             ALOGE("gscan_parse_hotlist_ssid_results: "
548                 "RESULTS_SCAN_RESULT_RSSI not found");
549             return WIFI_ERROR_INVALID_ARGS;
550         }
551         results[i].rssi =
552             get_s32(
553             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI]);
554         if (!
555             tb2[
556                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT
557                 ])
558         {
559             ALOGE("gscan_parse_hotlist_ssid_results: "
560                 "RESULTS_SCAN_RESULT_RTT not found");
561             return WIFI_ERROR_INVALID_ARGS;
562         }
563         results[i].rtt =
564             nla_get_u32(
565             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]);
566         if (!
567             tb2[
568                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD
569             ])
570         {
571             ALOGE("gscan_parse_hotlist_ssid_results: "
572                 "RESULTS_SCAN_RESULT_RTT_SD not found");
573             return WIFI_ERROR_INVALID_ARGS;
574         }
575         results[i].rtt_sd =
576             nla_get_u32(
577             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]);
578 
579         ALOGV("gscan_parse_hotlist_ssid_results: ts %" PRId64 " SSID  %s "
580               "BSSID: %02x:%02x:%02x:%02x:%02x:%02x channel %d rssi %d "
581               "rtt %" PRId64 " rtt_sd %" PRId64,
582               results[i].ts, results[i].ssid,
583               results[i].bssid[0], results[i].bssid[1], results[i].bssid[2],
584               results[i].bssid[3], results[i].bssid[4], results[i].bssid[5],
585               results[i].channel, results[i].rssi, results[i].rtt,
586               results[i].rtt_sd);
587         /* Increment loop index for next record */
588         i++;
589     }
590     return WIFI_SUCCESS;
591 }
592 
gscan_parse_passpoint_network_result(struct nlattr ** tb_vendor)593 wifi_error GScanCommandEventHandler::gscan_parse_passpoint_network_result(
594             struct nlattr **tb_vendor)
595 {
596     struct nlattr *scanResultsInfo, *wifiScanResultsInfo;
597     u32 resultsBufSize = 0;
598     u32 len = 0;
599     int rem = 0;
600 
601     scanResultsInfo = (struct nlattr *)nla_data(
602         tb_vendor
603             [QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_RESULT_LIST]);
604 
605     rem = nla_len(
606         tb_vendor
607             [QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_RESULT_LIST]);
608 
609     if (!nla_ok(scanResultsInfo, rem)) {
610         return WIFI_SUCCESS;
611     }
612 
613     struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
614     nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
615               (struct nlattr *)nla_data(scanResultsInfo),
616               nla_len(scanResultsInfo), NULL);
617 
618     if (!tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ID]) {
619       ALOGE("%s: GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ID not found", __FUNCTION__);
620       return WIFI_ERROR_INVALID_ARGS;
621     }
622     mPasspointNetId = nla_get_u32(
623         tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ID]);
624 
625     for (wifiScanResultsInfo = (struct nlattr *)nla_data(
626              tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]),
627         rem = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]);
628          nla_ok(wifiScanResultsInfo, rem);
629          wifiScanResultsInfo = nla_next(wifiScanResultsInfo, &(rem))) {
630       struct nlattr *tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
631       nla_parse(tb3, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
632                 (struct nlattr *)nla_data(wifiScanResultsInfo),
633                 nla_len(wifiScanResultsInfo), NULL);
634 
635       resultsBufSize = sizeof(wifi_scan_result);
636       if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_LENGTH]) {
637         ALOGE("%s: RESULTS_SCAN_RESULT_IE_LENGTH not found", __FUNCTION__);
638         return WIFI_ERROR_INVALID_ARGS;
639       }
640       resultsBufSize += nla_get_u32(
641           tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_LENGTH]);
642 
643       /* Allocate the appropriate memory for mPasspointNetworkFoundResult */
644       mPasspointNetworkFoundResult = (wifi_scan_result *)malloc(resultsBufSize);
645 
646       if (!mPasspointNetworkFoundResult) {
647         ALOGE("%s: Failed to alloc memory for result struct. Exit.\n",
648               __FUNCTION__);
649         return WIFI_ERROR_OUT_OF_MEMORY;
650       }
651       memset(mPasspointNetworkFoundResult, 0, resultsBufSize);
652 
653       mPasspointNetworkFoundResult->ie_length = nla_get_u32(
654           tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_LENGTH]);
655 
656       if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP]) {
657         ALOGE("%s: RESULTS_SCAN_RESULT_TIME_STAMP not found", __FUNCTION__);
658         return WIFI_ERROR_INVALID_ARGS;
659       }
660       mPasspointNetworkFoundResult->ts = nla_get_u64(
661           tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP]);
662       if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]) {
663         ALOGE("%s: RESULTS_SCAN_RESULT_SSID not found", __FUNCTION__);
664         return WIFI_ERROR_INVALID_ARGS;
665       }
666       len = nla_len(tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]);
667       len = sizeof(mPasspointNetworkFoundResult->ssid) <= len
668                 ? sizeof(mPasspointNetworkFoundResult->ssid)
669                 : len;
670       memcpy((void *)&(mPasspointNetworkFoundResult->ssid[0]),
671              nla_data(tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]),
672              len);
673       if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]) {
674         ALOGE("%s: RESULTS_SCAN_RESULT_BSSID not found", __FUNCTION__);
675         return WIFI_ERROR_INVALID_ARGS;
676       }
677       len = nla_len(tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]);
678       len = sizeof(mPasspointNetworkFoundResult->bssid) <= len
679                 ? sizeof(mPasspointNetworkFoundResult->bssid)
680                 : len;
681       memcpy(
682           &(mPasspointNetworkFoundResult->bssid[0]),
683           nla_data(tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]),
684           len);
685       if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]) {
686         ALOGE("%s: RESULTS_SCAN_RESULT_CHANNEL not found", __FUNCTION__);
687         return WIFI_ERROR_INVALID_ARGS;
688       }
689       mPasspointNetworkFoundResult->channel = nla_get_u32(
690           tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]);
691       if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI]) {
692         ALOGE("%s: RESULTS_SCAN_RESULT_RSSI not found", __FUNCTION__);
693         return WIFI_ERROR_INVALID_ARGS;
694       }
695       mPasspointNetworkFoundResult->rssi =
696           get_s32(tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI]);
697       if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]) {
698         ALOGE("%s: RESULTS_SCAN_RESULT_RTT not found", __FUNCTION__);
699         return WIFI_ERROR_INVALID_ARGS;
700       }
701       mPasspointNetworkFoundResult->rtt =
702           nla_get_u32(tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]);
703       if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]) {
704         ALOGE("%s: RESULTS_SCAN_RESULT_RTT_SD not found", __FUNCTION__);
705         return WIFI_ERROR_INVALID_ARGS;
706       }
707       mPasspointNetworkFoundResult->rtt_sd = nla_get_u32(
708           tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]);
709 
710       if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD]) {
711         ALOGE("%s: RESULTS_SCAN_RESULT_BEACON_PERIOD not found", __FUNCTION__);
712         return WIFI_ERROR_INVALID_ARGS;
713       }
714       mPasspointNetworkFoundResult->beacon_period = nla_get_u16(
715           tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD]);
716 
717       if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CAPABILITY]) {
718         ALOGE("%s: RESULTS_SCAN_RESULT_CAPABILITY not found", __FUNCTION__);
719         return WIFI_ERROR_INVALID_ARGS;
720       }
721       mPasspointNetworkFoundResult->capability = nla_get_u16(
722           tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CAPABILITY]);
723 
724       if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_DATA]) {
725         ALOGE("%s: RESULTS_SCAN_RESULT_IE_DATA not found", __FUNCTION__);
726         return WIFI_ERROR_INVALID_ARGS;
727       }
728       memcpy(
729           &(mPasspointNetworkFoundResult->ie_data[0]),
730           nla_data(tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_DATA]),
731           mPasspointNetworkFoundResult->ie_length);
732 
733       ALOGV("%s: ts: %" PRId64 " SSID: %s "
734             "BSSID: %02x:%02x:%02x:%02x:%02x:%02x  channel: %d  rssi: %d"
735             " rtt: % " PRId64 " rtt_sd  %" PRId64 " ie_length  %u ",
736             __FUNCTION__, mPasspointNetworkFoundResult->ts,
737             mPasspointNetworkFoundResult->ssid,
738             mPasspointNetworkFoundResult->bssid[0],
739             mPasspointNetworkFoundResult->bssid[1],
740             mPasspointNetworkFoundResult->bssid[2],
741             mPasspointNetworkFoundResult->bssid[3],
742             mPasspointNetworkFoundResult->bssid[4],
743             mPasspointNetworkFoundResult->bssid[5],
744             mPasspointNetworkFoundResult->channel,
745             mPasspointNetworkFoundResult->rssi,
746             mPasspointNetworkFoundResult->rtt,
747             mPasspointNetworkFoundResult->rtt_sd,
748             mPasspointNetworkFoundResult->ie_length);
749       ALOGV("%s: ie_data: ", __FUNCTION__);
750       hexdump(mPasspointNetworkFoundResult->ie_data,
751               mPasspointNetworkFoundResult->ie_length);
752     }
753 
754     if (!tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN]) {
755       ALOGE("%s:PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN not found", __FUNCTION__);
756       return WIFI_ERROR_INVALID_ARGS;
757     }
758     mPasspointAnqpLen = nla_get_u32(
759         tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN]);
760 
761     if (!mPasspointAnqpLen) {
762       return WIFI_SUCCESS;
763     }
764     mPasspointAnqp = (u8 *)malloc(mPasspointAnqpLen);
765     if (!mPasspointAnqp) {
766       ALOGE("%s: Failed to alloc memory for result struct. Exit.\n",
767             __FUNCTION__);
768       return WIFI_ERROR_OUT_OF_MEMORY;
769     }
770 
771     memset(mPasspointAnqp, 0, mPasspointAnqpLen);
772     if (!tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP]) {
773       ALOGE("%s: RESULTS_PASSPOINT_MATCH_ANQP not found", __FUNCTION__);
774       return WIFI_ERROR_INVALID_ARGS;
775     }
776     memcpy(
777         &(mPasspointAnqp[0]),
778         nla_data(
779             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP]),
780         mPasspointAnqpLen);
781 
782     ALOGV("%s: ANQP LEN:%d, ANQP IE:", __FUNCTION__, mPasspointAnqpLen);
783     hexdump((char *)mPasspointAnqp, mPasspointAnqpLen);
784     return WIFI_SUCCESS;
785 }
786 
gscan_parse_pno_network_results(u32 num_results,wifi_scan_result * results,u32 starting_index,struct nlattr ** tb_vendor)787 wifi_error GScanCommandEventHandler::gscan_parse_pno_network_results(
788                                             u32 num_results,
789                                             wifi_scan_result *results,
790                                             u32 starting_index,
791                                             struct nlattr **tb_vendor)
792 {
793     u32 i = starting_index;
794     struct nlattr *scanResultsInfo;
795     int rem = 0;
796     u32 len = 0;
797 
798     for (scanResultsInfo = (struct nlattr *) nla_data(tb_vendor[
799             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]),
800             rem = nla_len(tb_vendor[
801             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST
802             ]);
803                 nla_ok(scanResultsInfo, rem);
804                 scanResultsInfo = nla_next(scanResultsInfo, &(rem)))
805     {
806         struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
807         nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
808         (struct nlattr *) nla_data(scanResultsInfo),
809                 nla_len(scanResultsInfo), NULL);
810 
811         if (!
812             tb2[
813                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
814                 ])
815         {
816             ALOGE("gscan_parse_pno_network_results: "
817                 "RESULTS_SCAN_RESULT_TIME_STAMP not found");
818             return WIFI_ERROR_INVALID_ARGS;
819         }
820         results[i].ts =
821             nla_get_u64(
822             tb2[
823                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
824                 ]);
825         if (!
826             tb2[
827                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID
828                 ])
829         {
830             ALOGE("gscan_parse_pno_network_results: "
831                 "RESULTS_SCAN_RESULT_SSID not found");
832             return WIFI_ERROR_INVALID_ARGS;
833         }
834         len = nla_len(tb2[
835                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]);
836         len =
837             sizeof(results->ssid) <= len ? sizeof(results->ssid) : len;
838         memcpy((void *)&results[i].ssid,
839             nla_data(
840             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]), len);
841         if (!
842             tb2[
843                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID
844                 ])
845         {
846             ALOGE("gscan_parse_pno_network_results: "
847                 "RESULTS_SCAN_RESULT_BSSID not found");
848             return WIFI_ERROR_INVALID_ARGS;
849         }
850         len = nla_len(
851             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]);
852         len =
853             sizeof(results->bssid) <= len ? sizeof(results->bssid) : len;
854         memcpy(&results[i].bssid,
855             nla_data(
856             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]), len);
857         if (!
858             tb2[
859                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL
860                 ])
861         {
862             ALOGE("gscan_parse_pno_network_results: "
863                 "RESULTS_SCAN_RESULT_CHANNEL not found");
864             return WIFI_ERROR_INVALID_ARGS;
865         }
866         results[i].channel =
867             nla_get_u32(
868             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]);
869         if (!
870             tb2[
871                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI
872                 ])
873         {
874             ALOGE("gscan_parse_pno_network_results: "
875                 "RESULTS_SCAN_RESULT_RSSI not found");
876             return WIFI_ERROR_INVALID_ARGS;
877         }
878         results[i].rssi =
879             get_s32(
880             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI]);
881         if (!
882             tb2[
883                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT
884                 ])
885         {
886             ALOGE("gscan_parse_pno_network_results: "
887                 "RESULTS_SCAN_RESULT_RTT not found");
888             return WIFI_ERROR_INVALID_ARGS;
889         }
890         results[i].rtt =
891             nla_get_u32(
892             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]);
893         if (!
894             tb2[
895                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD
896             ])
897         {
898             ALOGE("gscan_parse_pno_network_results: "
899                 "RESULTS_SCAN_RESULT_RTT_SD not found");
900             return WIFI_ERROR_INVALID_ARGS;
901         }
902         results[i].rtt_sd =
903             nla_get_u32(
904             tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]);
905 
906         if (!
907             tb2[
908             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD])
909         {
910             ALOGE("gscan_parse_pno_network_results: "
911                 "RESULTS_SCAN_RESULT_BEACON_PERIOD not found");
912             return WIFI_ERROR_INVALID_ARGS;
913         }
914         results[i].beacon_period =
915             nla_get_u16(
916             tb2[
917             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD]);
918 
919         if (!
920             tb2[
921                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CAPABILITY
922                 ])
923         {
924             ALOGE("gscan_parse_pno_network_results: "
925                 "RESULTS_SCAN_RESULT_CAPABILITY not found");
926             return WIFI_ERROR_INVALID_ARGS;
927         }
928         results[i].capability =
929             nla_get_u16(
930             tb2[
931             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CAPABILITY]);
932 
933         ALOGV("gscan_parse_pno_network_results: ts %" PRId64 " SSID  %s "
934               "BSSID: %02x:%02x:%02x:%02x:%02x:%02x channel %d rssi %d "
935               "rtt %" PRId64 " rtt_sd %" PRId64,
936               results[i].ts, results[i].ssid,
937               results[i].bssid[0], results[i].bssid[1], results[i].bssid[2],
938               results[i].bssid[3], results[i].bssid[4], results[i].bssid[5],
939               results[i].channel, results[i].rssi, results[i].rtt,
940               results[i].rtt_sd);
941         /* Increment loop index for next record */
942         i++;
943     }
944     return WIFI_SUCCESS;
945 }
946 
947 /* This function will be the main handler for incoming (from driver)
948  * GScan_SUBCMD. Calls the appropriate callback handler after parsing
949  * the vendor data.
950  */
handleEvent(WifiEvent & event)951 int GScanCommandEventHandler::handleEvent(WifiEvent &event)
952 {
953     unsigned i=0;
954     int ret = WIFI_SUCCESS;
955     wifi_scan_result *result = NULL;
956     struct nlattr *tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
957 
958     if (mEventHandlingEnabled == false)
959     {
960         ALOGV("%s:Discarding event: %d",
961               __FUNCTION__, mSubcmd);
962         return NL_SKIP;
963     }
964 
965     WifiVendorCommand::handleEvent(event);
966 
967     nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
968                         (struct nlattr *)mVendorData,
969                         mDataLen, NULL);
970 
971     switch(mSubcmd)
972     {
973         case QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT:
974         {
975             wifi_request_id reqId;
976             u32 len = 0;
977             u32 resultsBufSize = 0;
978             u32 lengthOfInfoElements = 0;
979             u32 buckets_scanned = 0;
980 
981             ALOGV("Event QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT "
982                 "received.");
983             if (!tbVendor[
984                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID])
985             {
986                 ALOGE("%s: ATTR_GSCAN_RESULTS_REQUEST_ID not found. Exit.",
987                     __FUNCTION__);
988                 ret = WIFI_ERROR_INVALID_ARGS;
989                 break;
990             }
991             reqId = nla_get_u32(
992                     tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]
993                     );
994             /* If event has a different request_id, ignore that and use the
995              *  request_id value which we're maintaining.
996              */
997             if (reqId != mRequestId) {
998 #ifdef QC_HAL_DEBUG
999                 ALOGE("%s: Event has Req. ID:%d <> Ours:%d, continue...",
1000                     __FUNCTION__, reqId, mRequestId);
1001 #endif
1002                 reqId = mRequestId;
1003             }
1004 
1005             /* Parse and extract the results. */
1006             if (!
1007                 tbVendor[
1008                     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_LENGTH
1009                 ])
1010             {
1011                 ALOGE("%s:RESULTS_SCAN_RESULT_IE_LENGTH not found", __FUNCTION__);
1012                 ret = WIFI_ERROR_INVALID_ARGS;
1013                 break;
1014             }
1015             lengthOfInfoElements =
1016                 nla_get_u32(
1017                 tbVendor[
1018                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_LENGTH]);
1019 
1020             ALOGV("%s: RESULTS_SCAN_RESULT_IE_LENGTH =%d",
1021                 __FUNCTION__, lengthOfInfoElements);
1022 
1023             resultsBufSize =
1024                 lengthOfInfoElements + sizeof(wifi_scan_result);
1025             result = (wifi_scan_result *) malloc (resultsBufSize);
1026             if (!result) {
1027                 ALOGE("%s: Failed to alloc memory for result struct. Exit.\n",
1028                     __FUNCTION__);
1029                 ret = WIFI_ERROR_OUT_OF_MEMORY;
1030                 break;
1031             }
1032             memset(result, 0, resultsBufSize);
1033 
1034             result->ie_length = lengthOfInfoElements;
1035 
1036             /* Extract and fill out the wifi_scan_result struct. */
1037             if (!
1038             tbVendor[
1039                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
1040                 ])
1041             {
1042                 ALOGE("%s: RESULTS_SCAN_RESULT_TIME_STAMP not found",
1043                     __FUNCTION__);
1044                 ret = WIFI_ERROR_INVALID_ARGS;
1045                 break;
1046             }
1047             result->ts =
1048                 nla_get_u64(
1049                 tbVendor[
1050                     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
1051                     ]);
1052 
1053             if (!
1054                 tbVendor[
1055                     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID
1056                     ])
1057             {
1058                 ALOGE("%s: RESULTS_SCAN_RESULT_SSID not found", __FUNCTION__);
1059                 ret = WIFI_ERROR_INVALID_ARGS;
1060                 break;
1061             }
1062             len = nla_len(tbVendor[
1063                     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]);
1064             len =
1065                 sizeof(result->ssid) <= len ? sizeof(result->ssid) : len;
1066             memcpy((void *)&result->ssid,
1067                 nla_data(
1068                 tbVendor[
1069                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]), len);
1070 
1071             if (!
1072                 tbVendor[
1073                     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID
1074                     ])
1075             {
1076                 ALOGE("%s: RESULTS_SCAN_RESULT_BSSID not found", __FUNCTION__);
1077                 ret = WIFI_ERROR_INVALID_ARGS;
1078                 break;
1079             }
1080             len = nla_len(
1081                 tbVendor[
1082                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]);
1083             len =
1084                 sizeof(result->bssid) <= len ? sizeof(result->bssid) : len;
1085             memcpy(&result->bssid,
1086                 nla_data(
1087                 tbVendor[
1088                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]), len);
1089 
1090             if (!
1091                 tbVendor[
1092                     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL
1093                     ])
1094             {
1095                 ALOGE("%s: RESULTS_SCAN_RESULT_CHANNEL not found", __FUNCTION__);
1096                 ret = WIFI_ERROR_INVALID_ARGS;
1097                 break;
1098             }
1099             result->channel =
1100                 nla_get_u32(
1101                 tbVendor[
1102                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]);
1103 
1104             if (!
1105                 tbVendor[
1106                     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI
1107                     ])
1108             {
1109                 ALOGE("%s: RESULTS_SCAN_RESULT_RSSI not found", __FUNCTION__);
1110                 ret = WIFI_ERROR_INVALID_ARGS;
1111                 break;
1112             }
1113             result->rssi =
1114                 get_s32(
1115                 tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI]
1116                 );
1117 
1118             if (!
1119                 tbVendor[
1120                     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT
1121                     ])
1122             {
1123                 ALOGE("%s: RESULTS_SCAN_RESULT_RTT not found", __FUNCTION__);
1124                 ret = WIFI_ERROR_INVALID_ARGS;
1125                 break;
1126             }
1127             result->rtt =
1128                 nla_get_u32(
1129                 tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]);
1130 
1131             if (!
1132                 tbVendor[
1133                     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD
1134                 ])
1135             {
1136                 ALOGE("%s: RESULTS_SCAN_RESULT_RTT_SD not found", __FUNCTION__);
1137                 ret = WIFI_ERROR_INVALID_ARGS;
1138                 break;
1139             }
1140             result->rtt_sd =
1141                 nla_get_u32(
1142                 tbVendor[
1143                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]);
1144 
1145             if (!
1146                 tbVendor[
1147                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD])
1148             {
1149                 ALOGE("%s: RESULTS_SCAN_RESULT_BEACON_PERIOD not found",
1150                     __FUNCTION__);
1151                 ret = WIFI_ERROR_INVALID_ARGS;
1152                 break;
1153             }
1154             result->beacon_period =
1155                 nla_get_u16(
1156                 tbVendor[
1157                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD]);
1158 
1159             if (!
1160                 tbVendor[
1161                     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CAPABILITY
1162                     ])
1163             {
1164                 ALOGE("%s: RESULTS_SCAN_RESULT_CAPABILITY not found", __FUNCTION__);
1165                 ret = WIFI_ERROR_INVALID_ARGS;
1166                 break;
1167             }
1168             result->capability =
1169                 nla_get_u16(
1170                 tbVendor[
1171                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CAPABILITY]);
1172 
1173             if (!
1174                 tbVendor[
1175                     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_DATA
1176                 ])
1177             {
1178                 ALOGE("%s: RESULTS_SCAN_RESULT_IE_DATA not found", __FUNCTION__);
1179                 ret = WIFI_ERROR_INVALID_ARGS;
1180                 break;
1181             }
1182             memcpy(&(result->ie_data[0]),
1183                 nla_data(tbVendor[
1184                     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_DATA]),
1185                 lengthOfInfoElements);
1186             if (!
1187                 tbVendor[
1188                     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_BUCKETS_SCANNED
1189                     ])
1190             {
1191                 ALOGD("%s: RESULTS_BUCKETS_SCANNED not found", __FUNCTION__);
1192             } else {
1193                 buckets_scanned = get_u32(tbVendor[
1194                            QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_BUCKETS_SCANNED]);
1195             }
1196 #ifdef QC_HAL_DEBUG
1197             ALOGD("handleEvent:FULL_SCAN_RESULTS: ts  %" PRId64, result->ts);
1198             ALOGD("handleEvent:FULL_SCAN_RESULTS: SSID  %s ", result->ssid) ;
1199             ALOGD("handleEvent:FULL_SCAN_RESULTS: "
1200                 "BSSID: %02x:%02x:%02x:%02x:%02x:%02x \n",
1201                 result->bssid[0], result->bssid[1], result->bssid[2],
1202                 result->bssid[3], result->bssid[4], result->bssid[5]);
1203             ALOGD("handleEvent:FULL_SCAN_RESULTS: channel %d ",
1204                 result->channel);
1205             ALOGD("handleEvent:FULL_SCAN_RESULTS: rssi  %d ", result->rssi);
1206             ALOGD("handleEvent:FULL_SCAN_RESULTS: rtt  %" PRId64, result->rtt);
1207             ALOGD("handleEvent:FULL_SCAN_RESULTS: rtt_sd  %" PRId64,
1208                 result->rtt_sd);
1209             ALOGD("handleEvent:FULL_SCAN_RESULTS: beacon period  %d ",
1210                 result->beacon_period);
1211             ALOGD("handleEvent:FULL_SCAN_RESULTS: capability  %d ",
1212                 result->capability);
1213             ALOGD("handleEvent:FULL_SCAN_RESULTS: IE length  %d ",
1214                 result->ie_length);
1215 
1216             ALOGD("%s: Invoking the callback. \n", __FUNCTION__);
1217 #endif
1218             if (mHandler.on_full_scan_result) {
1219                 (*mHandler.on_full_scan_result)(reqId, result, buckets_scanned);
1220                 /* Reset flag and num counter. */
1221                 free(result);
1222                 result = NULL;
1223             }
1224         }
1225         break;
1226 
1227         case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE:
1228         {
1229             wifi_request_id id;
1230 
1231 #ifdef QC_HAL_DEBUG
1232             ALOGV("Event "
1233                     "QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE "
1234                     "received.");
1235 #endif
1236 
1237             if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]) {
1238                 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID"
1239                         "not found. Exit", __FUNCTION__);
1240                 ret = WIFI_ERROR_INVALID_ARGS;
1241                 break;
1242             }
1243             id = nla_get_u32(
1244                     tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]
1245                              );
1246             /* If this is not for us, then ignore it. */
1247             if (id != mRequestId) {
1248                 ALOGE("%s: Event has Req. ID:%d <> ours:%d",
1249                         __FUNCTION__, id, mRequestId);
1250                 break;
1251             }
1252 
1253             /* Invoke the callback func to report the number of results. */
1254             ALOGV("%s: Calling on_scan_event handler", __FUNCTION__);
1255             (*mHandler.on_scan_event)(id, WIFI_SCAN_THRESHOLD_NUM_SCANS);
1256         }
1257         break;
1258 
1259         case QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND:
1260         {
1261             wifi_request_id id;
1262             u32 resultsBufSize = 0;
1263             u32 numResults = 0;
1264             u32 startingIndex, sizeOfObtainedResults;
1265 
1266             id = nla_get_u32(
1267                     tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]
1268                     );
1269             /* If this is not for us, just ignore it. */
1270             if (id != mRequestId) {
1271                 ALOGE("%s: Event has Req. ID:%d <> ours:%d",
1272                     __FUNCTION__, id, mRequestId);
1273                 break;
1274             }
1275             if (!tbVendor[
1276                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]) {
1277                 ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not found",
1278                     __FUNCTION__);
1279                 ret = WIFI_ERROR_INVALID_ARGS;
1280                 break;
1281             }
1282             numResults = nla_get_u32(tbVendor[
1283                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]);
1284             ALOGV("%s: number of results:%d", __FUNCTION__, numResults);
1285 
1286             /* Get the memory size of previous fragments, if any. */
1287             sizeOfObtainedResults = mHotlistApFoundNumResults *
1288                           sizeof(wifi_scan_result);
1289 
1290             mHotlistApFoundNumResults += numResults;
1291             resultsBufSize += mHotlistApFoundNumResults *
1292                                             sizeof(wifi_scan_result);
1293 
1294             /* Check if this chunck of scan results is a continuation of
1295              * a previous one.
1296              */
1297             if (mHotlistApFoundMoreData) {
1298                 mHotlistApFoundResults = (wifi_scan_result *)
1299                             realloc (mHotlistApFoundResults, resultsBufSize);
1300             } else {
1301                 mHotlistApFoundResults = (wifi_scan_result *)
1302                             malloc (resultsBufSize);
1303             }
1304 
1305             if (!mHotlistApFoundResults) {
1306                 ALOGE("%s: Failed to alloc memory for results array. Exit.\n",
1307                     __FUNCTION__);
1308                 ret = WIFI_ERROR_OUT_OF_MEMORY;
1309                 break;
1310             }
1311             /* Initialize the newly allocated memory area with 0. */
1312             memset((u8 *)mHotlistApFoundResults + sizeOfObtainedResults, 0,
1313                     resultsBufSize - sizeOfObtainedResults);
1314 
1315             ALOGV("%s: Num of AP FOUND results = %d. \n", __FUNCTION__,
1316                                             mHotlistApFoundNumResults);
1317 
1318             /* To support fragmentation from firmware, monitor the
1319              * MORE_DATA flag and cache results until MORE_DATA = 0.
1320              * Only then we can pass on the results to framework through
1321              * the callback function.
1322              */
1323             if (!tbVendor[
1324                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]) {
1325                 ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_MORE_DATA not"
1326                     " found", __FUNCTION__);
1327                 ret = WIFI_ERROR_INVALID_ARGS;
1328                 break;
1329             } else {
1330                 mHotlistApFoundMoreData = nla_get_u8(
1331                     tbVendor[
1332                     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]);
1333                 ALOGE("%s: More data = %d. \n",
1334                     __FUNCTION__, mHotlistApFoundMoreData);
1335             }
1336 
1337             ALOGV("%s: Extract hotlist_ap_found results.\n", __FUNCTION__);
1338             startingIndex = mHotlistApFoundNumResults - numResults;
1339             ALOGV("%s: starting_index:%d",
1340                 __FUNCTION__, startingIndex);
1341             ret = gscan_parse_hotlist_ap_results(numResults,
1342                                                 mHotlistApFoundResults,
1343                                                 startingIndex,
1344                                                 tbVendor);
1345             /* If a parsing error occurred, exit and proceed for cleanup. */
1346             if (ret)
1347                 break;
1348             /* Send the results if no more result data fragments are expected */
1349             if (!mHotlistApFoundMoreData) {
1350                 (*mHandler.on_hotlist_ap_found)(id,
1351                                                 mHotlistApFoundNumResults,
1352                                                 mHotlistApFoundResults);
1353                 /* Reset flag and num counter. */
1354                 free(mHotlistApFoundResults);
1355                 mHotlistApFoundResults = NULL;
1356                 mHotlistApFoundMoreData = false;
1357                 mHotlistApFoundNumResults = 0;
1358             }
1359         }
1360         break;
1361 
1362         case QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_LOST:
1363         {
1364             wifi_request_id id;
1365             u32 resultsBufSize = 0;
1366             u32 numResults = 0;
1367             u32 startingIndex, sizeOfObtainedResults;
1368 
1369             id = nla_get_u32(
1370                     tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]
1371                     );
1372             /* If this is not for us, just ignore it. */
1373             if (id != mRequestId) {
1374                 ALOGE("%s: Event has Req. ID:%d <> ours:%d",
1375                     __FUNCTION__, id, mRequestId);
1376                 break;
1377             }
1378             if (!tbVendor[
1379                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]) {
1380                 ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not found",
1381                     __FUNCTION__);
1382                 ret = WIFI_ERROR_INVALID_ARGS;
1383                 break;
1384             }
1385             numResults = nla_get_u32(tbVendor[
1386                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]);
1387             ALOGV("%s: number of results:%d", __FUNCTION__, numResults);
1388 
1389             /* Get the memory size of previous fragments, if any. */
1390             sizeOfObtainedResults = mHotlistApLostNumResults *
1391                           sizeof(wifi_scan_result);
1392 
1393             mHotlistApLostNumResults += numResults;
1394             resultsBufSize += mHotlistApLostNumResults *
1395                                             sizeof(wifi_scan_result);
1396 
1397             /* Check if this chunck of scan results is a continuation of
1398              * a previous one.
1399              */
1400             if (mHotlistApLostMoreData) {
1401                 mHotlistApLostResults = (wifi_scan_result *)
1402                             realloc (mHotlistApLostResults, resultsBufSize);
1403             } else {
1404                 mHotlistApLostResults = (wifi_scan_result *)
1405                             malloc (resultsBufSize);
1406             }
1407 
1408             if (!mHotlistApLostResults) {
1409                 ALOGE("%s: Failed to alloc memory for results array. Exit.\n",
1410                     __FUNCTION__);
1411                 ret = WIFI_ERROR_OUT_OF_MEMORY;
1412                 break;
1413             }
1414             /* Initialize the newly allocated memory area with 0. */
1415             memset((u8 *)mHotlistApLostResults + sizeOfObtainedResults, 0,
1416                     resultsBufSize - sizeOfObtainedResults);
1417 
1418             ALOGV("%s: Num of AP Lost results = %d. \n", __FUNCTION__,
1419                                             mHotlistApLostNumResults);
1420 
1421             /* To support fragmentation from firmware, monitor the
1422              * MORE_DATA flag and cache results until MORE_DATA = 0.
1423              * Only then we can pass on the results to framework through
1424              * the callback function.
1425              */
1426             if (!tbVendor[
1427                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]) {
1428                 ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_MORE_DATA not"
1429                     " found", __FUNCTION__);
1430                 ret = WIFI_ERROR_INVALID_ARGS;
1431                 break;
1432             } else {
1433                 mHotlistApLostMoreData = nla_get_u8(
1434                     tbVendor[
1435                     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]);
1436                 ALOGV("%s: More data = %d. \n",
1437                     __FUNCTION__, mHotlistApLostMoreData);
1438             }
1439 
1440             ALOGV("%s: Extract hotlist_ap_Lost results.\n", __FUNCTION__);
1441             startingIndex = mHotlistApLostNumResults - numResults;
1442             ALOGV("%s: starting_index:%d",
1443                 __FUNCTION__, startingIndex);
1444             ret = gscan_parse_hotlist_ap_results(numResults,
1445                                                 mHotlistApLostResults,
1446                                                 startingIndex,
1447                                                 tbVendor);
1448             /* If a parsing error occurred, exit and proceed for cleanup. */
1449             if (ret)
1450                 break;
1451             /* Send the results if no more result data fragments are expected */
1452             if (!mHotlistApLostMoreData) {
1453                 (*mHandler.on_hotlist_ap_lost)(id,
1454                                                mHotlistApLostNumResults,
1455                                                mHotlistApLostResults);
1456                 /* Reset flag and num counter. */
1457                 free(mHotlistApLostResults);
1458                 mHotlistApLostResults = NULL;
1459                 mHotlistApLostMoreData = false;
1460                 mHotlistApLostNumResults = 0;
1461             }
1462         }
1463         break;
1464 
1465         case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE:
1466         {
1467             wifi_request_id reqId;
1468             u32 numResults = 0, sizeOfObtainedResults;
1469             u32 startingIndex, index = 0;
1470             struct nlattr *scanResultsInfo;
1471             int rem = 0;
1472 
1473             if (!tbVendor[
1474                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID])
1475             {
1476                 ALOGE("%s: ATTR_GSCAN_RESULTS_REQUEST_ID not found. Exit.",
1477                     __FUNCTION__);
1478                 ret = WIFI_ERROR_INVALID_ARGS;
1479                 break;
1480             }
1481             reqId = nla_get_u32(
1482                     tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]
1483                     );
1484             /* If this is not for us, just ignore it. */
1485             if (reqId != mRequestId) {
1486                 ALOGE("%s: Event has Req. ID:%d <> ours:%d",
1487                     __FUNCTION__, reqId, mRequestId);
1488                 break;
1489             }
1490             if (!tbVendor[
1491                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE])
1492             {
1493                 ALOGE("%s: ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not found."
1494                     "Exit.", __FUNCTION__);
1495                 ret = WIFI_ERROR_INVALID_ARGS;
1496                 break;
1497             }
1498             numResults = nla_get_u32(tbVendor[
1499                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]);
1500             /* Get the memory size of previous fragments, if any. */
1501             sizeOfObtainedResults = sizeof(wifi_significant_change_result *) *
1502                                 mSignificantChangeNumResults;
1503 
1504             index = mSignificantChangeNumResults;
1505             mSignificantChangeNumResults += numResults;
1506             /*
1507              * Check if this chunck of wifi_significant_change results is a
1508              * continuation of a previous one.
1509              */
1510             if (mSignificantChangeMoreData) {
1511                 mSignificantChangeResults =
1512                     (wifi_significant_change_result **)
1513                         realloc (mSignificantChangeResults,
1514                         sizeof(wifi_significant_change_result *) *
1515                                 mSignificantChangeNumResults);
1516             } else {
1517                 mSignificantChangeResults =
1518                     (wifi_significant_change_result **)
1519                         malloc (sizeof(wifi_significant_change_result *) *
1520                                 mSignificantChangeNumResults);
1521             }
1522 
1523             if (!mSignificantChangeResults) {
1524                 ALOGE("%s: Failed to alloc memory for results array. Exit.\n",
1525                     __FUNCTION__);
1526                 ret = WIFI_ERROR_OUT_OF_MEMORY;
1527                 break;
1528             }
1529             /* Initialize the newly allocated memory area with 0. */
1530             memset((u8 *)mSignificantChangeResults + sizeOfObtainedResults, 0,
1531                     sizeof(wifi_significant_change_result *) *
1532                                 numResults);
1533             ALOGV("%s: mSignificantChangeMoreData = %d",
1534                     __FUNCTION__, mSignificantChangeMoreData);
1535 
1536             for (scanResultsInfo = (struct nlattr *) nla_data(tbVendor[
1537                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]),
1538                 rem = nla_len(tbVendor[
1539                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]);
1540                 nla_ok(scanResultsInfo, rem);
1541                 scanResultsInfo = nla_next(scanResultsInfo, &(rem)))
1542             {
1543                 u32 num_rssi = 0;
1544                 u32 resultsBufSize = 0;
1545                 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
1546                 nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
1547                     (struct nlattr *) nla_data(scanResultsInfo),
1548                     nla_len(scanResultsInfo), NULL);
1549                 if (!tb2[
1550                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI
1551                     ])
1552                 {
1553                     ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_"
1554                         "SIGNIFICANT_CHANGE_RESULT_NUM_RSSI not found. "
1555                         "Exit.", __FUNCTION__);
1556                     ret = WIFI_ERROR_INVALID_ARGS;
1557                     break;
1558                 }
1559                 num_rssi = nla_get_u32(tb2[
1560                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI
1561                         ]);
1562                 resultsBufSize = sizeof(wifi_significant_change_result) +
1563                             num_rssi * sizeof(wifi_rssi);
1564                 mSignificantChangeResults[index] =
1565                     (wifi_significant_change_result *) malloc (resultsBufSize);
1566 
1567                 if (!mSignificantChangeResults[index]) {
1568                     ALOGE("%s: Failed to alloc memory for results array Exit",
1569                         __FUNCTION__);
1570                     ret = WIFI_ERROR_OUT_OF_MEMORY;
1571                     break;
1572                 }
1573                 /* Initialize the newly allocated memory area with 0. */
1574                 memset((u8 *)mSignificantChangeResults[index],
1575                         0, resultsBufSize);
1576 
1577                 ALOGV("%s: For Significant Change results[%d], num_rssi:%d\n",
1578                     __FUNCTION__, index, num_rssi);
1579                 index++;
1580             }
1581 
1582             ALOGV("%s: Extract significant change results.\n", __FUNCTION__);
1583             startingIndex =
1584                 mSignificantChangeNumResults - numResults;
1585             ret = gscan_get_significant_change_results(numResults,
1586                                                 mSignificantChangeResults,
1587                                                 startingIndex,
1588                                                 tbVendor);
1589             /* If a parsing error occurred, exit and proceed for cleanup. */
1590             if (ret)
1591                 break;
1592             /* To support fragmentation from firmware, monitor the
1593              * MORE_DATA flag and cache results until MORE_DATA = 0.
1594              * Only then we can pass on the results to framework through
1595              * the callback function.
1596              */
1597             if (!tbVendor[
1598                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]) {
1599                 ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_MORE_DATA not"
1600                     " found. Stop parsing and exit.", __FUNCTION__);
1601                 break;
1602             }
1603             mSignificantChangeMoreData = nla_get_u8(
1604                 tbVendor[
1605                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]);
1606             ALOGV("%s: More data = %d. \n",
1607                 __FUNCTION__, mSignificantChangeMoreData);
1608 
1609             /* Send the results if no more result fragments are expected */
1610             if (!mSignificantChangeMoreData) {
1611                 ALOGV("%s: Invoking the callback. \n", __FUNCTION__);
1612                 (*mHandler.on_significant_change)(reqId,
1613                                               mSignificantChangeNumResults,
1614                                               mSignificantChangeResults);
1615                 if (mSignificantChangeResults) {
1616                     /* Reset flag and num counter. */
1617                     for (index = 0; index < mSignificantChangeNumResults;
1618                          index++)
1619                     {
1620                         free(mSignificantChangeResults[index]);
1621                         mSignificantChangeResults[index] = NULL;
1622                     }
1623                     free(mSignificantChangeResults);
1624                     mSignificantChangeResults = NULL;
1625                 }
1626                 mSignificantChangeNumResults = 0;
1627                 mSignificantChangeMoreData = false;
1628             }
1629         }
1630         break;
1631 
1632         case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT:
1633         {
1634             wifi_scan_event scanEvent;
1635             wifi_request_id reqId;
1636 
1637             if (!tbVendor[
1638                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID])
1639             {
1640                 ALOGE("%s: ATTR_GSCAN_RESULTS_REQUEST_ID not found. Exit.",
1641                     __FUNCTION__);
1642                 ret = WIFI_ERROR_INVALID_ARGS;
1643                 break;
1644             }
1645             reqId = nla_get_u32(
1646                     tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]
1647                     );
1648             /* If this is not for us, just ignore it. */
1649             if (reqId != mRequestId) {
1650                 ALOGE("%s: Event has Req. ID:%d <> ours:%d",
1651                     __FUNCTION__, reqId, mRequestId);
1652                 break;
1653             }
1654 
1655             if (!tbVendor[
1656                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_TYPE]) {
1657                 ALOGE("%s: GSCAN_RESULTS_SCAN_EVENT_TYPE not"
1658                     " found. Stop parsing and exit.", __FUNCTION__);
1659                 break;
1660             }
1661             scanEvent = (wifi_scan_event) nla_get_u8(tbVendor[
1662                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_TYPE]);
1663 
1664             ALOGV("%s: Scan event type: %d\n", __FUNCTION__, scanEvent);
1665             /* Send the results if no more result fragments are expected. */
1666             (*mHandler.on_scan_event)(reqId, scanEvent);
1667         }
1668         break;
1669 
1670         case QCA_NL80211_VENDOR_SUBCMD_PNO_NETWORK_FOUND:
1671         {
1672             wifi_request_id id;
1673             u32 resultsBufSize = 0;
1674             u32 numResults = 0;
1675             u32 startingIndex, sizeOfObtainedResults;
1676 
1677             if (!tbVendor[
1678                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID])
1679             {
1680                 /* RequestId is not provided by FW/Driver for this event */
1681                 ALOGE("%s: ATTR_GSCAN_RESULTS_REQUEST_ID not found. Continue.",
1682                     __FUNCTION__);
1683                 id = mRequestId; /* Use the saved mRequestId instead. */
1684             } else {
1685                 id = nla_get_u32(
1686                         tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]
1687                         );
1688                 /* If this is not for us, use the saved requestId */
1689                 if (id != mRequestId) {
1690                     ALOGE("%s: Event has Req. ID:%d <> ours:%d",
1691                         __FUNCTION__, id, mRequestId);
1692                     id = mRequestId;
1693                 }
1694             }
1695 
1696             if (!tbVendor[
1697                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]) {
1698                 ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not found",
1699                     __FUNCTION__);
1700                 ret = WIFI_ERROR_INVALID_ARGS;
1701                 break;
1702             }
1703             numResults = nla_get_u32(tbVendor[
1704                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]);
1705             ALOGV("%s: number of results:%d", __FUNCTION__, numResults);
1706 
1707             /* Get the memory size of previous fragments, if any. */
1708             sizeOfObtainedResults = mPnoNetworkFoundNumResults *
1709                           sizeof(wifi_scan_result);
1710 
1711             mPnoNetworkFoundNumResults += numResults;
1712             resultsBufSize += mPnoNetworkFoundNumResults *
1713                                             sizeof(wifi_scan_result);
1714 
1715             /* Check if this chunck of scan results is a continuation of
1716              * a previous one.
1717              */
1718             if (mPnoNetworkFoundMoreData) {
1719                 mPnoNetworkFoundResults = (wifi_scan_result *)
1720                             realloc (mPnoNetworkFoundResults, resultsBufSize);
1721             } else {
1722                 mPnoNetworkFoundResults = (wifi_scan_result *)
1723                             malloc (resultsBufSize);
1724             }
1725 
1726             if (!mPnoNetworkFoundResults) {
1727                 ALOGE("%s: Failed to alloc memory for results array. Exit.\n",
1728                     __FUNCTION__);
1729                 ret = WIFI_ERROR_OUT_OF_MEMORY;
1730                 break;
1731             }
1732             /* Initialize the newly allocated memory area with 0. */
1733             memset((u8 *)mPnoNetworkFoundResults + sizeOfObtainedResults, 0,
1734                     resultsBufSize - sizeOfObtainedResults);
1735 
1736             ALOGV("%s: Num of AP FOUND results = %d. \n", __FUNCTION__,
1737                                             mPnoNetworkFoundNumResults);
1738 
1739             /* To support fragmentation from firmware, monitor the
1740              * MORE_DATA flag and cache results until MORE_DATA = 0.
1741              * Only then we can pass on the results to framework through
1742              * the callback function.
1743              */
1744             if (!tbVendor[
1745                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]) {
1746                 ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_MORE_DATA not"
1747                     " found", __FUNCTION__);
1748                 ret = WIFI_ERROR_INVALID_ARGS;
1749                 break;
1750             } else {
1751                 mPnoNetworkFoundMoreData = nla_get_u8(
1752                     tbVendor[
1753                     QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]);
1754                 ALOGV("%s: More data = %d. \n",
1755                     __FUNCTION__, mPnoNetworkFoundMoreData);
1756             }
1757 
1758             ALOGV("%s: Extract PNO_NETWORK_FOUND results.\n", __FUNCTION__);
1759             startingIndex = mPnoNetworkFoundNumResults - numResults;
1760             ALOGV("%s: starting_index:%d",
1761                 __FUNCTION__, startingIndex);
1762             ret = gscan_parse_pno_network_results(numResults,
1763                                                 mPnoNetworkFoundResults,
1764                                                 startingIndex,
1765                                                 tbVendor);
1766             /* If a parsing error occurred, exit and proceed for cleanup. */
1767             if (ret)
1768                 break;
1769             /* Send the results if no more result data fragments are expected */
1770             if (!mPnoNetworkFoundMoreData) {
1771                 (*mHandler.on_pno_network_found)(id,
1772                                                 mPnoNetworkFoundNumResults,
1773                                                 mPnoNetworkFoundResults);
1774                 /* Reset flag and num counter. */
1775                 if (mPnoNetworkFoundResults) {
1776                     free(mPnoNetworkFoundResults);
1777                     mPnoNetworkFoundResults = NULL;
1778                 }
1779                 mPnoNetworkFoundMoreData = false;
1780                 mPnoNetworkFoundNumResults = 0;
1781             }
1782         }
1783         break;
1784         case QCA_NL80211_VENDOR_SUBCMD_PNO_PASSPOINT_NETWORK_FOUND:
1785         {
1786             wifi_request_id id;
1787 
1788             if (!tbVendor[
1789                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID])
1790             {
1791                 /* RequestId is not provided by FW/Driver for this event */
1792                 ALOGE("%s: ATTR_GSCAN_RESULTS_REQUEST_ID not found. Continue.",
1793                     __FUNCTION__);
1794                 id = mRequestId; /* Use the saved mRequestId instead. */
1795             } else {
1796                 id = nla_get_u32(
1797                         tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]
1798                         );
1799                 /* If this is not for us, use the saved requestId */
1800                 if (id != mRequestId) {
1801                     ALOGE("%s: Event has Req. ID:%d <> ours:%d",
1802                         __FUNCTION__, id, mRequestId);
1803                     id = mRequestId;
1804                 }
1805             }
1806 
1807             ret = gscan_parse_passpoint_network_result(tbVendor);
1808             /* If a parsing error occurred, exit and proceed for cleanup. */
1809             if (ret)
1810             {
1811                 ALOGE("%s: gscan_parse_passpoint_network_result"
1812                       "returned error: %d.\n", __FUNCTION__, ret);
1813                 break;
1814             }
1815             (*mHandler.on_passpoint_network_found)(id,
1816                                                    mPasspointNetId,
1817                                                    mPasspointNetworkFoundResult,
1818                                                    mPasspointAnqpLen,
1819                                                    mPasspointAnqp);
1820             if (mPasspointNetworkFoundResult)
1821             {
1822                 free(mPasspointNetworkFoundResult);
1823                 mPasspointNetworkFoundResult = NULL;
1824             }
1825             if (mPasspointAnqp)
1826             {
1827                 free(mPasspointAnqp);
1828                 mPasspointAnqp = NULL;
1829             }
1830             mPasspointNetId = -1;
1831             mPasspointAnqpLen = 0;
1832         }
1833         break;
1834         default:
1835             /* Error case should not happen print log */
1836             ALOGE("%s: Wrong GScan subcmd received %d", __FUNCTION__, mSubcmd);
1837     }
1838 
1839     /* A parsing error occurred, do the cleanup of gscan result lists. */
1840     if (ret) {
1841         switch(mSubcmd)
1842         {
1843             case QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT:
1844             {
1845                 free(result);
1846                 result = NULL;
1847             }
1848             break;
1849 
1850             case QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND:
1851             {
1852                 /* Reset flag and num counter. */
1853                 free(mHotlistApFoundResults);
1854                 mHotlistApFoundResults = NULL;
1855                 mHotlistApFoundMoreData = false;
1856                 mHotlistApFoundNumResults = 0;
1857             }
1858             break;
1859 
1860             case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE:
1861             {
1862                 if (mSignificantChangeResults) {
1863                     for (i = 0; i < mSignificantChangeNumResults; i++)
1864                     {
1865                         if (mSignificantChangeResults[i]) {
1866                             free(mSignificantChangeResults[i]);
1867                             mSignificantChangeResults[i] = NULL;
1868                         }
1869                     }
1870                     free(mSignificantChangeResults);
1871                     mSignificantChangeResults = NULL;
1872                 }
1873                 mSignificantChangeNumResults = 0;
1874                 mSignificantChangeMoreData = false;
1875             }
1876             break;
1877 
1878             case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE:
1879             break;
1880 
1881             case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT:
1882             break;
1883 
1884             case QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_LOST:
1885             {
1886                 /* Reset flag and num counter. */
1887                 free(mHotlistApLostResults);
1888                 mHotlistApLostResults = NULL;
1889                 mHotlistApLostMoreData = false;
1890                 mHotlistApLostNumResults = 0;
1891             }
1892             break;
1893 
1894             case QCA_NL80211_VENDOR_SUBCMD_PNO_NETWORK_FOUND:
1895             {
1896                 /* Reset flag and num counter. */
1897                 if (mPnoNetworkFoundResults) {
1898                     free(mPnoNetworkFoundResults);
1899                     mPnoNetworkFoundResults = NULL;
1900                 }
1901                 mPnoNetworkFoundMoreData = false;
1902                 mPnoNetworkFoundNumResults = 0;
1903             }
1904             break;
1905 
1906             case QCA_NL80211_VENDOR_SUBCMD_PNO_PASSPOINT_NETWORK_FOUND:
1907             {
1908                 if (mPasspointNetworkFoundResult)
1909                 {
1910                     free(mPasspointNetworkFoundResult);
1911                     mPasspointNetworkFoundResult = NULL;
1912                 }
1913                 if (mPasspointAnqp)
1914                 {
1915                     free(mPasspointAnqp);
1916                     mPasspointAnqp = NULL;
1917                 }
1918                 mPasspointNetId = -1;
1919                 mPasspointAnqpLen = 0;
1920             }
1921             break;
1922 
1923             default:
1924                 ALOGE("%s: Parsing err handler: wrong GScan subcmd "
1925                     "received %d", __FUNCTION__, mSubcmd);
1926         }
1927     }
1928     return NL_SKIP;
1929 }
1930