4 #include <sys/socket.h>
5 #include <netlink/genl/genl.h>
6 #include <netlink/genl/family.h>
7 #include <netlink/genl/ctrl.h>
8 #include <linux/rtnetlink.h>
9 #include <netpacket/packet.h>
10 #include <linux/filter.h>
11 #include <linux/errqueue.h>
13 #include <linux/pkt_sched.h>
14 #include <netlink/object-api.h>
15 #include <netlink/netlink.h>
16 #include <netlink/socket.h>
17 #include <netlink/handlers.h>
21 #define LOG_TAG "WifiHAL"
23 #include <utils/Log.h>
27 #include "cpp_bindings.h"
31 GSCAN_ATTRIBUTE_NUM_BUCKETS
= 10,
32 GSCAN_ATTRIBUTE_BASE_PERIOD
,
33 GSCAN_ATTRIBUTE_BUCKETS_BAND
,
34 GSCAN_ATTRIBUTE_BUCKET_ID
,
35 GSCAN_ATTRIBUTE_BUCKET_PERIOD
,
36 GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS
,
37 GSCAN_ATTRIBUTE_BUCKET_CHANNELS
,
38 GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN
,
39 GSCAN_ATTRIBUTE_REPORT_THRESHOLD
,
40 GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE
,
41 GSCAN_ATTRIBUTE_DWELL_TIME
,
42 GSCAN_ATTRIBUTE_SCAN_TYPE
,
43 GSCAN_ATTRIBUTE_BAND
= GSCAN_ATTRIBUTE_BUCKETS_BAND
,
45 GSCAN_ATTRIBUTE_ENABLE_FEATURE
= 20,
46 GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE
, /* indicates no more results */
47 GSCAN_ENABLE_FULL_SCAN_RESULTS
,
48 GSCAN_ATTRIBUTE_REPORT_EVENTS
,
50 /* remaining reserved for additional attributes */
51 GSCAN_ATTRIBUTE_NUM_OF_RESULTS
= 30,
52 GSCAN_ATTRIBUTE_SCAN_RESULTS
, /* flat array of wifi_scan_result */
53 GSCAN_ATTRIBUTE_NUM_CHANNELS
,
54 GSCAN_ATTRIBUTE_CHANNEL_LIST
,
56 /* remaining reserved for additional attributes */
58 GSCAN_ATTRIBUTE_SSID
= 40,
59 GSCAN_ATTRIBUTE_BSSID
,
60 GSCAN_ATTRIBUTE_CHANNEL
,
62 GSCAN_ATTRIBUTE_TIMESTAMP
,
64 GSCAN_ATTRIBUTE_RTTSD
,
66 /* remaining reserved for additional attributes */
68 GSCAN_ATTRIBUTE_HOTLIST_BSSIDS
= 50,
69 GSCAN_ATTRIBUTE_RSSI_LOW
,
70 GSCAN_ATTRIBUTE_RSSI_HIGH
,
71 GSCAN_ATTRIBUTE_HOTLIST_ELEM
,
72 GSCAN_ATTRIBUTE_HOTLIST_FLUSH
,
73 GSCAN_ATTRIBUTE_CHANNEL_NUMBER
,
75 /* remaining reserved for additional attributes */
76 GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE
= 60,
77 GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE
,
78 GSCAN_ATTRIBUTE_MIN_BREACHING
,
79 GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS
,
86 class GetCapabilitiesCommand
: public WifiCommand
88 wifi_gscan_capabilities
*mCapabilities
;
90 GetCapabilitiesCommand(wifi_interface_handle iface
, wifi_gscan_capabilities
*capabitlites
)
91 : WifiCommand(iface
, 0), mCapabilities(capabitlites
)
93 memset(mCapabilities
, 0, sizeof(*mCapabilities
));
96 virtual int create() {
97 ALOGD("Creating message to get scan capablities; iface = %d", mIfaceInfo
->id
);
99 int ret
= mMsg
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_GET_CAPABILITIES
);
101 ALOGD("NL message creation failed");
109 virtual int handleResponse(WifiEvent
& reply
) {
111 ALOGD("In GetCapabilities::handleResponse");
113 if (reply
.get_cmd() != NL80211_CMD_VENDOR
) {
114 ALOGD("Ignoring reply with cmd = %d", reply
.get_cmd());
118 int id
= reply
.get_vendor_id();
119 int subcmd
= reply
.get_vendor_subcmd();
121 void *data
= reply
.get_vendor_data();
122 int len
= reply
.get_vendor_data_len();
124 ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id
, subcmd
, len
,
125 sizeof(*mCapabilities
));
127 memcpy(mCapabilities
, data
, min(len
, (int) sizeof(*mCapabilities
)));
134 wifi_error
wifi_get_gscan_capabilities(wifi_interface_handle handle
,
135 wifi_gscan_capabilities
*capabilities
)
137 GetCapabilitiesCommand
command(handle
, capabilities
);
138 return (wifi_error
) command
.requestResponse();
141 class GetChannelListCommand
: public WifiCommand
143 wifi_channel
*channels
;
148 GetChannelListCommand(wifi_interface_handle iface
, wifi_channel
*channel_buf
, int *ch_num
,
149 int num_max_ch
, int band
)
150 : WifiCommand(iface
, 0), channels(channel_buf
), max_channels(num_max_ch
), num_channels(ch_num
),
153 memset(channels
, 0, sizeof(wifi_channel
) * max_channels
);
155 virtual int create() {
156 ALOGD("Creating message to get channel list; iface = %d", mIfaceInfo
->id
);
158 int ret
= mMsg
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_GET_VALID_CHANNELS
);
163 nlattr
*data
= mMsg
.attr_start(NL80211_ATTR_VENDOR_DATA
);
164 ret
= mMsg
.put_u32(GSCAN_ATTRIBUTE_BAND
, band
);
175 virtual int handleResponse(WifiEvent
& reply
) {
177 ALOGD("In GetChannelList::handleResponse");
179 if (reply
.get_cmd() != NL80211_CMD_VENDOR
) {
180 ALOGD("Ignoring reply with cmd = %d", reply
.get_cmd());
184 int id
= reply
.get_vendor_id();
185 int subcmd
= reply
.get_vendor_subcmd();
186 int num_channels_to_copy
= 0;
188 nlattr
*vendor_data
= reply
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
189 int len
= reply
.get_vendor_data_len();
191 ALOGD("Id = %0x, subcmd = %d, len = %d", id
, subcmd
, len
);
192 if (vendor_data
== NULL
|| len
== 0) {
193 ALOGE("no vendor data in GetChannelList response; ignoring it");
197 for (nl_iterator
it(vendor_data
); it
.has_next(); it
.next()) {
198 if (it
.get_type() == GSCAN_ATTRIBUTE_NUM_CHANNELS
) {
199 num_channels_to_copy
= it
.get_u32();
200 ALOGD("Got channel list with %d channels", num_channels_to_copy
);
201 if(num_channels_to_copy
> max_channels
)
202 num_channels_to_copy
= max_channels
;
203 *num_channels
= num_channels_to_copy
;
204 } else if (it
.get_type() == GSCAN_ATTRIBUTE_CHANNEL_LIST
&& num_channels_to_copy
) {
205 memcpy(channels
, it
.get_data(), sizeof(int) * num_channels_to_copy
);
207 ALOGW("Ignoring invalid attribute type = %d, size = %d",
208 it
.get_type(), it
.get_len());
216 wifi_error
wifi_get_valid_channels(wifi_interface_handle handle
,
217 int band
, int max_channels
, wifi_channel
*channels
, int *num_channels
)
219 GetChannelListCommand
command(handle
, channels
, num_channels
,
221 return (wifi_error
) command
.requestResponse();
223 /////////////////////////////////////////////////////////////////////////////
225 /* helper functions */
227 static int parseScanResults(wifi_scan_result
*results
, int num
, nlattr
*attr
)
229 memset(results
, 0, sizeof(wifi_scan_result
) * num
);
232 for (nl_iterator
it(attr
); it
.has_next() && i
< num
; it
.next(), i
++) {
234 int index
= it
.get_type();
235 ALOGD("retrieved scan result %d", index
);
236 nlattr
*sc_data
= (nlattr
*) it
.get_data();
237 wifi_scan_result
*result
= results
+ i
;
239 for (nl_iterator
it2(sc_data
); it2
.has_next(); it2
.next()) {
240 int type
= it2
.get_type();
241 if (type
== GSCAN_ATTRIBUTE_SSID
) {
242 strncpy(result
->ssid
, (char *) it2
.get_data(), it2
.get_len());
243 result
->ssid
[it2
.get_len()] = 0;
244 } else if (type
== GSCAN_ATTRIBUTE_BSSID
) {
245 memcpy(result
->bssid
, (byte
*) it2
.get_data(), sizeof(mac_addr
));
246 } else if (type
== GSCAN_ATTRIBUTE_TIMESTAMP
) {
247 result
->ts
= it2
.get_u64();
248 } else if (type
== GSCAN_ATTRIBUTE_CHANNEL
) {
249 result
->ts
= it2
.get_u16();
250 } else if (type
== GSCAN_ATTRIBUTE_RSSI
) {
251 result
->rssi
= it2
.get_u8();
252 } else if (type
== GSCAN_ATTRIBUTE_RTT
) {
253 result
->rtt
= it2
.get_u64();
254 } else if (type
== GSCAN_ATTRIBUTE_RTTSD
) {
255 result
->rtt_sd
= it2
.get_u64();
262 ALOGE("Got too many results; skipping some");
268 int createFeatureRequest(WifiRequest
& request
, int subcmd
) {
270 int result
= request
.create(GOOGLE_OUI
, subcmd
);
278 class ScanCommand
: public WifiCommand
280 wifi_scan_cmd_params
*mParams
;
281 wifi_scan_result_handler mHandler
;
282 static unsigned mGlobalFullScanBuckets
;
283 bool mLocalFullScanBuckets
;
285 ScanCommand(wifi_interface_handle iface
, int id
, wifi_scan_cmd_params
*params
,
286 wifi_scan_result_handler handler
)
287 : WifiCommand(iface
, id
), mParams(params
), mHandler(handler
),
288 mLocalFullScanBuckets(0)
291 int createSetupRequest(WifiRequest
& request
) {
292 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN
);
297 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
298 result
= request
.put_u32(GSCAN_ATTRIBUTE_BASE_PERIOD
, mParams
->base_period
);
303 result
= request
.put_u32(GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN
, mParams
->max_ap_per_scan
);
308 result
= request
.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD
, mParams
->report_threshold
);
313 result
= request
.put_u32(GSCAN_ATTRIBUTE_NUM_BUCKETS
, mParams
->num_buckets
);
318 for (int i
= 0; i
< mParams
->num_buckets
; i
++) {
319 nlattr
* bucket
= request
.attr_start(i
); // next bucket
320 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_ID
, mParams
->buckets
[i
].bucket
);
324 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_PERIOD
, mParams
->buckets
[i
].period
);
328 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKETS_BAND
,
329 mParams
->buckets
[i
].band
);
334 result
= request
.put_u32(GSCAN_ATTRIBUTE_REPORT_EVENTS
,
335 mParams
->buckets
[i
].report_events
);
340 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS
,
341 mParams
->buckets
[i
].num_channels
);
346 if (mParams
->buckets
[i
].num_channels
) {
347 nlattr
*channels
= request
.attr_start(GSCAN_ATTRIBUTE_BUCKET_CHANNELS
);
348 for (int j
= 0; j
< mParams
->buckets
[i
].num_channels
; j
++) {
349 result
= request
.put_u32(j
, mParams
->buckets
[i
].channels
[j
].channel
);
354 request
.attr_end(channels
);
357 request
.attr_end(bucket
);
360 request
.attr_end(data
);
364 int createStartRequest(WifiRequest
& request
) {
365 return createFeatureRequest(request
, SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN
);
368 int createStopRequest(WifiRequest
& request
) {
369 return createFeatureRequest(request
, SLSI_NL80211_VENDOR_SUBCMD_DEL_GSCAN
);
372 int enableFullScanResultsIfRequired() {
373 /* temporary workaround till we have full support for per bucket scans */
375 ALOGI("enabling full scan results if needed");
377 for (int i
= 0; i
< mParams
->num_buckets
; i
++) {
378 if (mParams
->buckets
[i
].report_events
== 2) {
383 if (mGlobalFullScanBuckets
== 0 && nBuckets
!= 0) {
385 ALOGI("full scan results were requested ");
386 ALOGI("mGlobalFullScanBuckets = %d, nBuckets = %d", mGlobalFullScanBuckets
, nBuckets
);
387 mLocalFullScanBuckets
= nBuckets
;
388 mGlobalFullScanBuckets
+= nBuckets
;
389 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_FULL_SCAN_RESULTS
);
392 ALOGI("mGlobalFullScanBuckets = %d, nBuckets = %d", mGlobalFullScanBuckets
, nBuckets
);
398 int disableFullScanResultsIfRequired() {
399 /* temporary workaround till we have full support for per bucket scans */
401 if (mLocalFullScanBuckets
== 0) {
405 mGlobalFullScanBuckets
-= mLocalFullScanBuckets
;
406 if (mGlobalFullScanBuckets
== 0) {
408 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_FULL_SCAN_RESULTS
);
414 ALOGD(" sending scan req to driver");
415 WifiRequest
request(familyId(), ifaceId());
416 int result
= createSetupRequest(request
);
417 if (result
!= WIFI_SUCCESS
) {
418 ALOGE("failed to create setup request; result = %d", result
);
421 ALOGD("Starting scan");
423 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE
);
424 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_COMPLETE_SCAN
);
425 result
= enableFullScanResultsIfRequired();
426 if ( result
== WIFI_SUCCESS
)
431 result
= requestResponse(request
);
432 if (result
!= WIFI_SUCCESS
) {
433 ALOGE("failed to start scan; result = %d", result
);
434 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_COMPLETE_SCAN
);
435 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE
);
443 virtual int cancel() {
444 ALOGD("Stopping scan");
446 WifiRequest
request(familyId(), ifaceId());
447 int result
= createStopRequest(request
);
448 if (result
!= WIFI_SUCCESS
) {
449 ALOGE("failed to create stop request; result = %d", result
);
451 result
= requestResponse(request
);
452 if (result
!= WIFI_SUCCESS
) {
453 ALOGE("failed to stop scan; result = %d", result
);
457 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_COMPLETE_SCAN
);
458 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE
);
459 disableFullScanResultsIfRequired();
464 virtual int handleResponse(WifiEvent
& reply
) {
465 /* Nothing to do on response! */
469 virtual int handleEvent(WifiEvent
& event
) {
470 ALOGD("Got a scan results event");
474 nlattr
*vendor_data
= event
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
475 int len
= event
.get_vendor_data_len();
476 int event_id
= event
.get_vendor_subcmd();
478 if(event_id
== GSCAN_EVENT_COMPLETE_SCAN
) {
479 if (vendor_data
== NULL
|| len
!= 4) {
480 ALOGD("Scan complete type not mentioned!");
483 wifi_scan_event evt_type
;
485 evt_type
= (wifi_scan_event
) event
.get_u32(NL80211_ATTR_VENDOR_DATA
);
486 ALOGD("Scan complete: Received event type %d", evt_type
);
487 if(*mHandler
.on_scan_event
)
488 (*mHandler
.on_scan_event
)(evt_type
, evt_type
);
489 } else if(event_id
== GSCAN_EVENT_FULL_SCAN_RESULTS
) {
490 if (vendor_data
== NULL
|| len
< sizeof(wifi_scan_result
)) {
491 ALOGD("No scan results found");
494 wifi_scan_result
*result
= (wifi_scan_result
*)event
.get_vendor_data();
496 if(*mHandler
.on_full_scan_result
)
497 (*mHandler
.on_full_scan_result
)(id(), result
);
499 ALOGD("%-32s\t", result
->ssid
);
501 ALOGD("%02x:%02x:%02x:%02x:%02x:%02x ", result
->bssid
[0], result
->bssid
[1],
502 result
->bssid
[2], result
->bssid
[3], result
->bssid
[4], result
->bssid
[5]);
504 ALOGD("%d\t", result
->rssi
);
505 ALOGD("%d\t", result
->channel
);
506 ALOGD("%lld\t", result
->ts
);
507 ALOGD("%lld\t", result
->rtt
);
508 ALOGD("%lld\n", result
->rtt_sd
);
511 if (vendor_data
== NULL
|| len
!= 4) {
512 ALOGD("No scan results found");
516 int num
= event
.get_u32(NL80211_ATTR_VENDOR_DATA
);
517 ALOGD("Found %d scan results", num
);
518 if(*mHandler
.on_scan_results_available
)
519 (*mHandler
.on_scan_results_available
)(id(), num
);
525 unsigned ScanCommand::mGlobalFullScanBuckets
= 0;
527 wifi_error
wifi_start_gscan(
529 wifi_interface_handle iface
,
530 wifi_scan_cmd_params params
,
531 wifi_scan_result_handler handler
)
533 wifi_handle handle
= getWifiHandle(iface
);
535 ALOGD("Starting GScan, halHandle = %p", handle
);
537 ScanCommand
*cmd
= new ScanCommand(iface
, id
, ¶ms
, handler
);
538 wifi_register_cmd(handle
, id
, cmd
);
539 return (wifi_error
)cmd
->start();
542 wifi_error
wifi_stop_gscan(wifi_request_id id
, wifi_interface_handle iface
)
544 ALOGD("Stopping GScan");
545 wifi_handle handle
= getWifiHandle(iface
);
548 wifi_scan_result_handler handler
;
549 wifi_scan_cmd_params dummy_params
;
550 wifi_handle handle
= getWifiHandle(iface
);
551 memset(&handler
, 0, sizeof(handler
));
553 ScanCommand
*cmd
= new ScanCommand(iface
, id
, &dummy_params
, handler
);
560 WifiCommand
*cmd
= wifi_unregister_cmd(handle
, id
);
567 return WIFI_ERROR_INVALID_ARGS
;
570 class GetScanResultsCommand
: public WifiCommand
{
571 wifi_scan_result
*mResults
;
578 GetScanResultsCommand(wifi_interface_handle iface
, byte flush
,
579 wifi_scan_result
*results
, int max
, int *num
)
580 : WifiCommand(iface
, -1), mResults(results
), mMax(max
), mNum(num
),
581 mRetrieved(0), mFlush(flush
), mCompleted(0)
584 int createRequest(WifiRequest
& request
, int num
, byte flush
) {
585 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_GET_SCAN_RESULTS
);
590 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
591 result
= request
.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS
, num
);
596 request
.attr_end(data
);
601 WifiRequest
request(familyId(), ifaceId());
602 ALOGD("retrieving %d scan results", mMax
);
604 for (int i
= 0; i
< 10 && mRetrieved
< mMax
; i
++) {
605 int result
= createRequest(request
, (mMax
- mRetrieved
), mFlush
);
607 ALOGE("failed to create request");
611 int prev_retrieved
= mRetrieved
;
613 result
= requestResponse(request
);
615 if (result
!= WIFI_SUCCESS
) {
616 ALOGE("failed to retrieve scan results; result = %d", result
);
620 if (mRetrieved
== prev_retrieved
|| mCompleted
) {
621 /* no more items left to retrieve */
628 ALOGE("GetScanResults read %d results", mRetrieved
);
633 virtual int handleResponse(WifiEvent
& reply
) {
634 ALOGD("In GetScanResultsCommand::handleResponse");
636 if (reply
.get_cmd() != NL80211_CMD_VENDOR
) {
637 ALOGD("Ignoring reply with cmd = %d", reply
.get_cmd());
641 int id
= reply
.get_vendor_id();
642 int subcmd
= reply
.get_vendor_subcmd();
644 ALOGD("Id = %0x, subcmd = %d", id
, subcmd
);
647 if (subcmd != GSCAN_SUBCMD_SCAN_RESULTS) {
648 ALOGE("Invalid response to GetScanResultsCommand; ignoring it");
653 nlattr
*vendor_data
= reply
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
654 int len
= reply
.get_vendor_data_len();
656 if (vendor_data
== NULL
|| len
== 0) {
657 ALOGE("no vendor data in GetScanResults response; ignoring it");
661 for (nl_iterator
it(vendor_data
); it
.has_next(); it
.next()) {
662 if (it
.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE
) {
663 mCompleted
= it
.get_u8();
664 ALOGD("retrieved mCompleted flag : %d", mCompleted
);
665 } else if (it
.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS
|| it
.get_type() == 0) {
666 for (nl_iterator
it2(it
.get()); it2
.has_next(); it2
.next()) {
668 if (it2
.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS
) {
669 num
= it2
.get_len() / sizeof(wifi_scan_result
);
670 num
= min(*mNum
- mRetrieved
, num
);
671 memcpy(mResults
+ mRetrieved
, it2
.get_data(),
672 sizeof(wifi_scan_result
) * num
);
673 ALOGD("Retrieved %d scan results", num
);
674 wifi_scan_result
*results
= (wifi_scan_result
*)it2
.get_data();
675 for (int i
= 0; i
< num
; i
++) {
676 wifi_scan_result
*result
= results
+ i
;
677 ALOGD("%02d %-32s %02x:%02x:%02x:%02x:%02x:%02x %04d", i
,
678 result
->ssid
, result
->bssid
[0], result
->bssid
[1], result
->bssid
[2],
679 result
->bssid
[3], result
->bssid
[4], result
->bssid
[5],
684 ALOGW("Ignoring invalid attribute type = %d, size = %d",
685 it
.get_type(), it
.get_len());
689 ALOGW("Ignoring invalid attribute type = %d, size = %d",
690 it
.get_type(), it
.get_len());
698 wifi_error
wifi_get_cached_gscan_results(wifi_interface_handle iface
, byte flush
,
699 int max
, wifi_scan_result
*results
, int *num
) {
701 ALOGD("Getting cached scan results, iface handle = %p, num = %d", iface
, *num
);
703 GetScanResultsCommand
*cmd
= new GetScanResultsCommand(iface
, flush
, results
, max
, num
);
704 return (wifi_error
)cmd
->execute();
707 /////////////////////////////////////////////////////////////////////////////
709 class BssidHotlistCommand
: public WifiCommand
712 wifi_bssid_hotlist_params mParams
;
713 wifi_hotlist_ap_found_handler mHandler
;
714 static const int MAX_RESULTS
= 64;
715 wifi_scan_result mResults
[MAX_RESULTS
];
717 BssidHotlistCommand(wifi_interface_handle handle
, int id
,
718 wifi_bssid_hotlist_params params
, wifi_hotlist_ap_found_handler handler
)
719 : WifiCommand(handle
, id
), mParams(params
), mHandler(handler
)
722 int createSetupRequest(WifiRequest
& request
) {
723 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_SET_BSSID_HOTLIST
);
728 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
730 result
= request
.put_u32(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE
, mParams
.lost_ap_sample_size
);
735 struct nlattr
* attr
= request
.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS
);
736 for (int i
= 0; i
< mParams
.num_ap
; i
++) {
737 nlattr
*attr2
= request
.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM
);
739 return WIFI_ERROR_OUT_OF_MEMORY
;
741 result
= request
.put_addr(GSCAN_ATTRIBUTE_BSSID
, mParams
.ap
[i
].bssid
);
745 result
= request
.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH
, mParams
.ap
[i
].high
);
749 result
= request
.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW
, mParams
.ap
[i
].low
);
753 result
= request
.put_u8(GSCAN_ATTRIBUTE_CHANNEL_NUMBER
, mParams
.ap
[i
].channel
);
757 request
.attr_end(attr2
);
760 request
.attr_end(attr
);
761 request
.attr_end(data
);
765 int createTeardownRequest(WifiRequest
& request
) {
766 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_RESET_BSSID_HOTLIST
);
775 ALOGD("Executing hotlist setup request, num = %d", mParams
.num_ap
);
776 WifiRequest
request(familyId(), ifaceId());
777 int result
= createSetupRequest(request
);
782 result
= requestResponse(request
);
784 ALOGD("Failed to execute hotlist setup request, result = %d", result
);
785 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_FOUND
);
786 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_LOST
);
790 ALOGD("Successfully set %d APs in the hotlist", mParams
.num_ap
);
791 result
= createFeatureRequest(request
, SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN
);
796 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_FOUND
);
797 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_LOST
);
799 result
= requestResponse(request
);
801 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_FOUND
);
802 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_LOST
);
806 ALOGD("successfully restarted the scan");
810 virtual int cancel() {
811 /* unregister event handler */
812 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_FOUND
);
813 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_LOST
);
814 /* create set hotlist message with empty hotlist */
815 WifiRequest
request(familyId(), ifaceId());
816 int result
= createTeardownRequest(request
);
821 result
= requestResponse(request
);
826 ALOGD("Successfully reset APs in current hotlist");
830 virtual int handleResponse(WifiEvent
& reply
) {
831 /* Nothing to do on response! */
835 virtual int handleEvent(WifiEvent
& event
) {
836 ALOGD("Hotlist AP event");
837 int event_id
= event
.get_vendor_subcmd();
840 nlattr
*vendor_data
= event
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
841 int len
= event
.get_vendor_data_len();
843 if (vendor_data
== NULL
|| len
== 0) {
844 ALOGD("No scan results found");
848 memset(mResults
, 0, sizeof(wifi_scan_result
) * MAX_RESULTS
);
850 int num
= len
/ sizeof(wifi_scan_result
);
851 num
= min(MAX_RESULTS
, num
);
852 memcpy(mResults
, event
.get_vendor_data(), num
* sizeof(wifi_scan_result
));
854 if (event_id
== GSCAN_EVENT_HOTLIST_RESULTS_FOUND
) {
855 ALOGD("FOUND %d hotlist APs", num
);
856 if (*mHandler
.on_hotlist_ap_found
)
857 (*mHandler
.on_hotlist_ap_found
)(id(), num
, mResults
);
858 } else if (event_id
== GSCAN_EVENT_HOTLIST_RESULTS_LOST
) {
859 ALOGD("LOST %d hotlist APs", num
);
860 if (*mHandler
.on_hotlist_ap_lost
)
861 (*mHandler
.on_hotlist_ap_lost
)(id(), num
, mResults
);
867 wifi_error
wifi_set_bssid_hotlist(wifi_request_id id
, wifi_interface_handle iface
,
868 wifi_bssid_hotlist_params params
, wifi_hotlist_ap_found_handler handler
)
870 wifi_handle handle
= getWifiHandle(iface
);
872 BssidHotlistCommand
*cmd
= new BssidHotlistCommand(iface
, id
, params
, handler
);
873 wifi_register_cmd(handle
, id
, cmd
);
874 return (wifi_error
)cmd
->start();
877 wifi_error
wifi_reset_bssid_hotlist(wifi_request_id id
, wifi_interface_handle iface
)
879 wifi_handle handle
= getWifiHandle(iface
);
881 WifiCommand
*cmd
= wifi_unregister_cmd(handle
, id
);
888 return WIFI_ERROR_INVALID_ARGS
;
892 /////////////////////////////////////////////////////////////////////////////
894 class SignificantWifiChangeCommand
: public WifiCommand
897 mac_addr bssid
; // BSSID
898 wifi_channel channel
; // channel frequency in MHz
899 int num_rssi
; // number of rssi samples
900 wifi_rssi rssi
[8]; // RSSI history in db
901 } wifi_significant_change_result_internal
;
904 wifi_significant_change_params mParams
;
905 wifi_significant_change_handler mHandler
;
906 static const int MAX_RESULTS
= 64;
907 wifi_significant_change_result_internal mResultsBuffer
[MAX_RESULTS
];
908 wifi_significant_change_result
*mResults
[MAX_RESULTS
];
910 SignificantWifiChangeCommand(wifi_interface_handle handle
, int id
,
911 wifi_significant_change_params params
, wifi_significant_change_handler handler
)
912 : WifiCommand(handle
, id
), mParams(params
), mHandler(handler
)
915 int createSetupRequest(WifiRequest
& request
) {
916 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_SET_SIGNIFICANT_CHANGE
);
921 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
923 result
= request
.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE
, mParams
.rssi_sample_size
);
927 result
= request
.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE
, mParams
.lost_ap_sample_size
);
931 result
= request
.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING
, mParams
.min_breaching
);
936 struct nlattr
* attr
= request
.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS
);
938 for (int i
= 0; i
< mParams
.num_ap
; i
++) {
940 nlattr
*attr2
= request
.attr_start(i
);
942 return WIFI_ERROR_OUT_OF_MEMORY
;
944 result
= request
.put_addr(GSCAN_ATTRIBUTE_BSSID
, mParams
.ap
[i
].bssid
);
948 result
= request
.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH
, mParams
.ap
[i
].high
);
952 result
= request
.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW
, mParams
.ap
[i
].low
);
956 request
.attr_end(attr2
);
959 request
.attr_end(attr
);
960 request
.attr_end(data
);
965 int createTeardownRequest(WifiRequest
& request
) {
966 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_RESET_SIGNIFICANT_CHANGE
);
975 ALOGD("Set significant wifi change");
976 WifiRequest
request(familyId(), ifaceId());
978 int result
= createSetupRequest(request
);
983 result
= requestResponse(request
);
985 ALOGD("failed to set significant wifi change %d", result
);
989 result
= createFeatureRequest(request
, SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN
);
994 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS
);
996 result
= requestResponse(request
);
998 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS
);
1002 ALOGD("successfully restarted the scan");
1006 virtual int cancel() {
1007 /* unregister event handler */
1008 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS
);
1010 /* create set significant change monitor message with empty hotlist */
1011 WifiRequest
request(familyId(), ifaceId());
1013 int result
= createTeardownRequest(request
);
1018 result
= requestResponse(request
);
1023 ALOGD("successfully reset significant wifi change");
1027 virtual int handleResponse(WifiEvent
& reply
) {
1028 /* Nothing to do on response! */
1032 virtual int handleEvent(WifiEvent
& event
) {
1033 ALOGD("Got a significant wifi change event");
1035 nlattr
*vendor_data
= event
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
1036 int len
= event
.get_vendor_data_len();
1038 if (vendor_data
== NULL
|| len
== 0) {
1039 ALOGD("No scan results found");
1046 s16 rssi_history
[8];
1049 int num
= min(len
/ sizeof(ChangeInfo
), MAX_RESULTS
);
1050 ChangeInfo
*ci
= (ChangeInfo
*)event
.get_vendor_data();
1052 for (int i
= 0; i
< num
; i
++) {
1053 memcpy(mResultsBuffer
[i
].bssid
, ci
[i
].bssid
, sizeof(mac_addr
));
1054 mResultsBuffer
[i
].channel
= ci
[i
].channel
;
1055 mResultsBuffer
[i
].num_rssi
= 8;
1056 for (int j
= 0; j
< mResultsBuffer
[i
].num_rssi
; j
++)
1057 mResultsBuffer
[i
].rssi
[j
] = (int) ci
[i
].rssi_history
[j
];
1058 mResults
[i
] = reinterpret_cast<wifi_significant_change_result
*>(&(mResultsBuffer
[i
]));
1061 ALOGD("Retrieved %d scan results", num
);
1064 (*mHandler
.on_significant_change
)(id(), num
, mResults
);
1066 ALOGW("No significant change reported");
1073 wifi_error
wifi_set_significant_change_handler(wifi_request_id id
, wifi_interface_handle iface
,
1074 wifi_significant_change_params params
, wifi_significant_change_handler handler
)
1076 wifi_handle handle
= getWifiHandle(iface
);
1078 SignificantWifiChangeCommand
*cmd
= new SignificantWifiChangeCommand(
1079 iface
, id
, params
, handler
);
1080 wifi_register_cmd(handle
, id
, cmd
);
1081 return (wifi_error
)cmd
->start();
1084 wifi_error
wifi_reset_significant_change_handler(wifi_request_id id
, wifi_interface_handle iface
)
1086 wifi_handle handle
= getWifiHandle(iface
);
1088 WifiCommand
*cmd
= wifi_unregister_cmd(handle
, id
);
1092 return WIFI_SUCCESS
;
1095 return WIFI_ERROR_INVALID_ARGS
;