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. */
create()21 int 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;
36 out:
37 return ret;
38 }
39
get_request_id()40 int GScanCommandEventHandler::get_request_id()
41 {
42 return mRequestId;
43 }
44
GScanCommandEventHandler(wifi_handle handle,int id,u32 vendor_id,u32 subcmd,GScanCallbackHandler handler)45 GScanCommandEventHandler::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
~GScanCommandEventHandler()104 GScanCommandEventHandler::~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
gscan_get_hotlist_ap_found_results(u32 num_results,wifi_scan_result * results,u32 starting_index,struct nlattr ** tb_vendor)139 static 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
gscan_get_significant_change_results(u32 num_results,wifi_significant_change_result ** results,u32 starting_index,struct nlattr ** tb_vendor)277 static 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 */
handleEvent(WifiEvent & event)392 int 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