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_REPORT_THRESHOLD_NUM_SCANS
,
42 GSCAN_ATTRIBUTE_BAND
= GSCAN_ATTRIBUTE_BUCKETS_BAND
,
44 GSCAN_ATTRIBUTE_ENABLE_FEATURE
= 20,
45 GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE
, /* indicates no more results */
46 GSCAN_ATTRIBUTE_REPORT_EVENTS
,
48 /* remaining reserved for additional attributes */
49 GSCAN_ATTRIBUTE_NUM_OF_RESULTS
= 30,
50 GSCAN_ATTRIBUTE_SCAN_RESULTS
, /* flat array of wifi_scan_result */
51 GSCAN_ATTRIBUTE_NUM_CHANNELS
,
52 GSCAN_ATTRIBUTE_CHANNEL_LIST
,
53 GSCAN_ATTRIBUTE_SCAN_ID
,
54 GSCAN_ATTRIBUTE_SCAN_FLAGS
,
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
,
81 GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT
= 70,
82 GSCAN_ATTRIBUTE_BUCKET_EXPONENT
,
83 GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD
,
85 GSCAN_ATTRIBUTE_NUM_BSSID
,
86 GSCAN_ATTRIBUTE_BLACKLIST_BSSID
,
93 class GetCapabilitiesCommand
: public WifiCommand
95 wifi_gscan_capabilities
*mCapabilities
;
97 GetCapabilitiesCommand(wifi_interface_handle iface
, wifi_gscan_capabilities
*capabitlites
)
98 : WifiCommand(iface
, 0), mCapabilities(capabitlites
)
100 memset(mCapabilities
, 0, sizeof(*mCapabilities
));
103 virtual int create() {
104 ALOGD("Creating message to get scan capablities; iface = %d", mIfaceInfo
->id
);
106 int ret
= mMsg
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_GET_CAPABILITIES
);
108 ALOGD("NL message creation failed");
116 virtual int handleResponse(WifiEvent
& reply
) {
118 ALOGD("In GetCapabilities::handleResponse");
120 if (reply
.get_cmd() != NL80211_CMD_VENDOR
) {
121 ALOGD("Ignoring reply with cmd = %d", reply
.get_cmd());
125 int id
= reply
.get_vendor_id();
126 int subcmd
= reply
.get_vendor_subcmd();
128 void *data
= reply
.get_vendor_data();
129 int len
= reply
.get_vendor_data_len();
131 ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id
, subcmd
, len
,
132 sizeof(*mCapabilities
));
134 memcpy(mCapabilities
, data
, min(len
, (int) sizeof(*mCapabilities
)));
141 wifi_error
wifi_get_gscan_capabilities(wifi_interface_handle handle
,
142 wifi_gscan_capabilities
*capabilities
)
144 GetCapabilitiesCommand
command(handle
, capabilities
);
145 return (wifi_error
) command
.requestResponse();
148 class GetChannelListCommand
: public WifiCommand
150 wifi_channel
*channels
;
155 GetChannelListCommand(wifi_interface_handle iface
, wifi_channel
*channel_buf
, int *ch_num
,
156 int num_max_ch
, int band
)
157 : WifiCommand(iface
, 0), channels(channel_buf
), max_channels(num_max_ch
), num_channels(ch_num
),
160 memset(channels
, 0, sizeof(wifi_channel
) * max_channels
);
162 virtual int create() {
163 ALOGD("Creating message to get channel list; iface = %d", mIfaceInfo
->id
);
165 int ret
= mMsg
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_GET_VALID_CHANNELS
);
170 nlattr
*data
= mMsg
.attr_start(NL80211_ATTR_VENDOR_DATA
);
171 ret
= mMsg
.put_u32(GSCAN_ATTRIBUTE_BAND
, band
);
182 virtual int handleResponse(WifiEvent
& reply
) {
184 ALOGD("In GetChannelList::handleResponse");
186 if (reply
.get_cmd() != NL80211_CMD_VENDOR
) {
187 ALOGD("Ignoring reply with cmd = %d", reply
.get_cmd());
191 int id
= reply
.get_vendor_id();
192 int subcmd
= reply
.get_vendor_subcmd();
193 int num_channels_to_copy
= 0;
195 nlattr
*vendor_data
= reply
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
196 int len
= reply
.get_vendor_data_len();
198 ALOGD("Id = %0x, subcmd = %d, len = %d", id
, subcmd
, len
);
199 if (vendor_data
== NULL
|| len
== 0) {
200 ALOGE("no vendor data in GetChannelList response; ignoring it");
204 for (nl_iterator
it(vendor_data
); it
.has_next(); it
.next()) {
205 if (it
.get_type() == GSCAN_ATTRIBUTE_NUM_CHANNELS
) {
206 num_channels_to_copy
= it
.get_u32();
207 ALOGD("Got channel list with %d channels", num_channels_to_copy
);
208 if(num_channels_to_copy
> max_channels
)
209 num_channels_to_copy
= max_channels
;
210 *num_channels
= num_channels_to_copy
;
211 } else if (it
.get_type() == GSCAN_ATTRIBUTE_CHANNEL_LIST
&& num_channels_to_copy
) {
212 memcpy(channels
, it
.get_data(), sizeof(int) * num_channels_to_copy
);
214 ALOGW("Ignoring invalid attribute type = %d, size = %d",
215 it
.get_type(), it
.get_len());
223 wifi_error
wifi_get_valid_channels(wifi_interface_handle handle
,
224 int band
, int max_channels
, wifi_channel
*channels
, int *num_channels
)
226 GetChannelListCommand
command(handle
, channels
, num_channels
,
228 return (wifi_error
) command
.requestResponse();
230 /////////////////////////////////////////////////////////////////////////////
232 /* helper functions */
234 static int parseScanResults(wifi_scan_result
*results
, int num
, nlattr
*attr
)
236 memset(results
, 0, sizeof(wifi_scan_result
) * num
);
239 for (nl_iterator
it(attr
); it
.has_next() && i
< num
; it
.next(), i
++) {
241 int index
= it
.get_type();
242 ALOGD("retrieved scan result %d", index
);
243 nlattr
*sc_data
= (nlattr
*) it
.get_data();
244 wifi_scan_result
*result
= results
+ i
;
246 for (nl_iterator
it2(sc_data
); it2
.has_next(); it2
.next()) {
247 int type
= it2
.get_type();
248 if (type
== GSCAN_ATTRIBUTE_SSID
) {
249 strncpy(result
->ssid
, (char *) it2
.get_data(), it2
.get_len());
250 result
->ssid
[it2
.get_len()] = 0;
251 } else if (type
== GSCAN_ATTRIBUTE_BSSID
) {
252 memcpy(result
->bssid
, (byte
*) it2
.get_data(), sizeof(mac_addr
));
253 } else if (type
== GSCAN_ATTRIBUTE_TIMESTAMP
) {
254 result
->ts
= it2
.get_u64();
255 } else if (type
== GSCAN_ATTRIBUTE_CHANNEL
) {
256 result
->ts
= it2
.get_u16();
257 } else if (type
== GSCAN_ATTRIBUTE_RSSI
) {
258 result
->rssi
= it2
.get_u8();
259 } else if (type
== GSCAN_ATTRIBUTE_RTT
) {
260 result
->rtt
= it2
.get_u64();
261 } else if (type
== GSCAN_ATTRIBUTE_RTTSD
) {
262 result
->rtt_sd
= it2
.get_u64();
269 ALOGE("Got too many results; skipping some");
275 int createFeatureRequest(WifiRequest
& request
, int subcmd
) {
277 int result
= request
.create(GOOGLE_OUI
, subcmd
);
285 class ScanCommand
: public WifiCommand
287 wifi_scan_cmd_params
*mParams
;
288 wifi_scan_result_handler mHandler
;
289 static unsigned mGlobalFullScanBuckets
;
290 bool mLocalFullScanBuckets
;
292 ScanCommand(wifi_interface_handle iface
, int id
, wifi_scan_cmd_params
*params
,
293 wifi_scan_result_handler handler
)
294 : WifiCommand(iface
, id
), mParams(params
), mHandler(handler
),
295 mLocalFullScanBuckets(0)
298 int createSetupRequest(WifiRequest
& request
) {
299 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN
);
304 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
305 result
= request
.put_u32(GSCAN_ATTRIBUTE_BASE_PERIOD
, mParams
->base_period
);
310 result
= request
.put_u32(GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN
, mParams
->max_ap_per_scan
);
315 result
= request
.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD
, mParams
->report_threshold_percent
);
320 result
= request
.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD_NUM_SCANS
, mParams
->report_threshold_num_scans
);
325 result
= request
.put_u32(GSCAN_ATTRIBUTE_NUM_BUCKETS
, mParams
->num_buckets
);
330 for (int i
= 0; i
< mParams
->num_buckets
; i
++) {
331 nlattr
* bucket
= request
.attr_start(i
); // next bucket
332 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_ID
, mParams
->buckets
[i
].bucket
);
336 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_PERIOD
, mParams
->buckets
[i
].period
);
340 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKETS_BAND
,
341 mParams
->buckets
[i
].band
);
346 result
= request
.put_u32(GSCAN_ATTRIBUTE_REPORT_EVENTS
,
347 mParams
->buckets
[i
].report_events
);
352 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS
,
353 mParams
->buckets
[i
].num_channels
);
358 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_EXPONENT
,
359 mParams
->buckets
[i
].exponent
);
364 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD
,
365 mParams
->buckets
[i
].max_period
);
370 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT
,
371 mParams
->buckets
[i
].step_count
);
376 if (mParams
->buckets
[i
].num_channels
) {
377 nlattr
*channels
= request
.attr_start(GSCAN_ATTRIBUTE_BUCKET_CHANNELS
);
378 for (int j
= 0; j
< mParams
->buckets
[i
].num_channels
; j
++) {
379 result
= request
.put_u32(j
, mParams
->buckets
[i
].channels
[j
].channel
);
384 request
.attr_end(channels
);
387 request
.attr_end(bucket
);
390 request
.attr_end(data
);
394 int createStartRequest(WifiRequest
& request
) {
395 return createFeatureRequest(request
, SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN
);
398 int createStopRequest(WifiRequest
& request
) {
399 return createFeatureRequest(request
, SLSI_NL80211_VENDOR_SUBCMD_DEL_GSCAN
);
403 ALOGD(" sending scan req to driver");
404 WifiRequest
request(familyId(), ifaceId());
405 int result
= createSetupRequest(request
);
406 if (result
!= WIFI_SUCCESS
) {
407 ALOGE("failed to create setup request; result = %d", result
);
410 ALOGD("Starting scan");
412 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE
);
413 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_COMPLETE_SCAN
);
416 for (int i
= 0; i
< mParams
->num_buckets
; i
++) {
417 if (mParams
->buckets
[i
].report_events
== 2) {
423 ALOGI("Full scan requested with nBuckets = %d", nBuckets
);
424 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_FULL_SCAN_RESULTS
);
426 result
= requestResponse(request
);
427 if (result
!= WIFI_SUCCESS
) {
428 ALOGE("failed to start scan; result = %d", result
);
429 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_COMPLETE_SCAN
);
430 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE
);
438 virtual int cancel() {
439 ALOGD("Stopping scan");
441 WifiRequest
request(familyId(), ifaceId());
442 int result
= createStopRequest(request
);
443 if (result
!= WIFI_SUCCESS
) {
444 ALOGE("failed to create stop request; result = %d", result
);
446 result
= requestResponse(request
);
447 if (result
!= WIFI_SUCCESS
) {
448 ALOGE("failed to stop scan; result = %d", result
);
452 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_COMPLETE_SCAN
);
453 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE
);
454 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_FULL_SCAN_RESULTS
);
459 virtual int handleResponse(WifiEvent
& reply
) {
460 /* Nothing to do on response! */
464 virtual int handleEvent(WifiEvent
& event
) {
465 ALOGD("Got a scan results event");
469 nlattr
*vendor_data
= event
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
470 unsigned int len
= event
.get_vendor_data_len();
471 int event_id
= event
.get_vendor_subcmd();
472 ALOGD("handleEvent, event_id = %d", event_id
);
474 if(event_id
== GSCAN_EVENT_COMPLETE_SCAN
) {
475 if (vendor_data
== NULL
|| len
!= 4) {
476 ALOGD("Scan complete type not mentioned!");
479 wifi_scan_event evt_type
;
481 evt_type
= (wifi_scan_event
) event
.get_u32(NL80211_ATTR_VENDOR_DATA
);
482 ALOGD("Scan complete: Received event type %d", evt_type
);
483 if(*mHandler
.on_scan_event
)
484 (*mHandler
.on_scan_event
)(evt_type
, evt_type
);
485 } else if(event_id
== GSCAN_EVENT_FULL_SCAN_RESULTS
) {
486 if (vendor_data
== NULL
|| len
< sizeof(wifi_scan_result
)) {
487 ALOGD("No scan results found");
490 wifi_scan_result
*result
= (wifi_scan_result
*)event
.get_vendor_data();
492 if(*mHandler
.on_full_scan_result
)
493 (*mHandler
.on_full_scan_result
)(id(), result
);
495 ALOGD("%-32s\t", result
->ssid
);
497 ALOGD("%02x:%02x:%02x:%02x:%02x:%02x ", result
->bssid
[0], result
->bssid
[1],
498 result
->bssid
[2], result
->bssid
[3], result
->bssid
[4], result
->bssid
[5]);
500 ALOGD("%d\t", result
->rssi
);
501 ALOGD("%d\t", result
->channel
);
502 ALOGD("%lld\t", result
->ts
);
503 ALOGD("%lld\t", result
->rtt
);
504 ALOGD("%lld\n", result
->rtt_sd
);
507 if (vendor_data
== NULL
|| len
!= 4) {
508 ALOGD("No scan results found");
512 int num
= event
.get_u32(NL80211_ATTR_VENDOR_DATA
);
513 ALOGD("Found %d scan results", num
);
514 if(*mHandler
.on_scan_results_available
)
515 (*mHandler
.on_scan_results_available
)(id(), num
);
521 unsigned ScanCommand::mGlobalFullScanBuckets
= 0;
523 wifi_error
wifi_start_gscan(
525 wifi_interface_handle iface
,
526 wifi_scan_cmd_params params
,
527 wifi_scan_result_handler handler
)
529 wifi_handle handle
= getWifiHandle(iface
);
531 ALOGD("Starting GScan, halHandle = %p", handle
);
533 ScanCommand
*cmd
= new ScanCommand(iface
, id
, ¶ms
, handler
);
534 wifi_register_cmd(handle
, id
, cmd
);
535 return (wifi_error
)cmd
->start();
538 wifi_error
wifi_stop_gscan(wifi_request_id id
, wifi_interface_handle iface
)
540 ALOGD("Stopping GScan");
541 wifi_handle handle
= getWifiHandle(iface
);
544 wifi_scan_result_handler handler
;
545 wifi_scan_cmd_params dummy_params
;
546 wifi_handle handle
= getWifiHandle(iface
);
547 memset(&handler
, 0, sizeof(handler
));
549 ScanCommand
*cmd
= new ScanCommand(iface
, id
, &dummy_params
, handler
);
556 WifiCommand
*cmd
= wifi_unregister_cmd(handle
, id
);
563 return WIFI_ERROR_INVALID_ARGS
;
566 class GetScanResultsCommand
: public WifiCommand
{
567 wifi_cached_scan_results
*mScans
;
573 static const int MAX_RESULTS
= 320;
574 wifi_scan_result mScanResults
[MAX_RESULTS
];
577 GetScanResultsCommand(wifi_interface_handle iface
, byte flush
,
578 wifi_cached_scan_results
*results
, int max
, int *num
)
579 : WifiCommand(iface
, -1), mScans(results
), mMax(max
), mNum(num
),
580 mRetrieved(0), mFlush(flush
), mCompleted(0)
583 int createRequest(WifiRequest
& request
, int num
, byte flush
) {
584 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_GET_SCAN_RESULTS
);
589 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
590 result
= request
.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS
, num
);
595 request
.attr_end(data
);
600 WifiRequest
request(familyId(), ifaceId());
601 ALOGD("retrieving %d scan results", mMax
);
603 for (int i
= 0; i
< 10 && mRetrieved
< mMax
; i
++) {
604 int result
= createRequest(request
, (mMax
- mRetrieved
), mFlush
);
606 ALOGE("failed to create request");
610 int prev_retrieved
= mRetrieved
;
612 result
= requestResponse(request
);
614 if (result
!= WIFI_SUCCESS
) {
615 ALOGE("failed to retrieve scan results; result = %d", result
);
619 if (mRetrieved
== prev_retrieved
|| mCompleted
) {
620 /* no more items left to retrieve */
627 ALOGE("GetScanResults read %d results", mRetrieved
);
632 virtual int handleResponse(WifiEvent
& reply
) {
633 ALOGD("In GetScanResultsCommand::handleResponse");
635 if (reply
.get_cmd() != NL80211_CMD_VENDOR
) {
636 ALOGD("Ignoring reply with cmd = %d", reply
.get_cmd());
640 int id
= reply
.get_vendor_id();
641 int subcmd
= reply
.get_vendor_subcmd();
643 ALOGD("Id = %0x, subcmd = %d", id
, subcmd
);
645 nlattr
*vendor_data
= reply
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
646 int len
= reply
.get_vendor_data_len();
648 if (vendor_data
== NULL
|| len
== 0) {
649 ALOGE("no vendor data in GetScanResults response; ignoring it");
653 for (nl_iterator
it(vendor_data
); it
.has_next(); it
.next()) {
654 if (it
.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE
) {
655 mCompleted
= it
.get_u8();
656 ALOGD("retrieved mCompleted flag : %d", mCompleted
);
657 } else if (it
.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS
|| it
.get_type() == 0) {
658 int scan_id
= 0, flags
= 0, num
= 0;
659 for (nl_iterator
it2(it
.get()); it2
.has_next(); it2
.next()) {
660 if (it2
.get_type() == GSCAN_ATTRIBUTE_SCAN_ID
) {
661 scan_id
= it2
.get_u32();
662 ALOGD("retrieved scan_id : 0x%0x", scan_id
);
663 } else if (it2
.get_type() == GSCAN_ATTRIBUTE_SCAN_FLAGS
) {
664 flags
= it2
.get_u8();
665 ALOGD("retrieved scan_flags : 0x%0x", flags
);
666 } else if (it2
.get_type() == GSCAN_ATTRIBUTE_NUM_OF_RESULTS
) {
668 ALOGD("retrieved num_results: %d", num
);
669 } else if (it2
.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS
) {
670 if (mRetrieved
>= mMax
) {
671 ALOGW("Stored %d scans, ignoring excess results", mRetrieved
);
674 num
= it2
.get_len() / sizeof(wifi_scan_result
);
675 num
= min(MAX_RESULTS
- mNextScanResult
, num
);
676 num
= min((int)MAX_AP_CACHE_PER_SCAN
, num
);
677 memcpy(mScanResults
+ mNextScanResult
, it2
.get_data(),
678 sizeof(wifi_scan_result
) * num
);
679 ALOGD("Retrieved %d scan results", num
);
680 wifi_scan_result
*results
= (wifi_scan_result
*)it2
.get_data();
681 for (int i
= 0; i
< num
; i
++) {
682 wifi_scan_result
*result
= results
+ i
;
683 ALOGD("%02d %-32s %02x:%02x:%02x:%02x:%02x:%02x %04d", i
,
684 result
->ssid
, result
->bssid
[0], result
->bssid
[1], result
->bssid
[2],
685 result
->bssid
[3], result
->bssid
[4], result
->bssid
[5],
688 mScans
[mRetrieved
].scan_id
= scan_id
;
689 mScans
[mRetrieved
].flags
= flags
;
690 mScans
[mRetrieved
].num_results
= num
;
691 ALOGD("Setting result of scan_id : 0x%0x", mScans
[mRetrieved
].scan_id
);
692 memcpy(mScans
[mRetrieved
].results
,
693 &(mScanResults
[mNextScanResult
]), num
* sizeof(wifi_scan_result
));
694 mNextScanResult
+= num
;
697 ALOGW("Ignoring invalid attribute type = %d, size = %d",
698 it
.get_type(), it
.get_len());
702 ALOGW("Ignoring invalid attribute type = %d, size = %d",
703 it
.get_type(), it
.get_len());
711 wifi_error
wifi_get_cached_gscan_results(wifi_interface_handle iface
, byte flush
,
712 int max
, wifi_cached_scan_results
*results
, int *num
) {
713 ALOGD("Getting cached scan results, iface handle = %p, num = %d", iface
, *num
);
715 GetScanResultsCommand
*cmd
= new GetScanResultsCommand(iface
, flush
, results
, max
, num
);
716 return (wifi_error
)cmd
->execute();
719 /////////////////////////////////////////////////////////////////////////////
721 class BssidHotlistCommand
: public WifiCommand
724 wifi_bssid_hotlist_params mParams
;
725 wifi_hotlist_ap_found_handler mHandler
;
726 static const int MAX_RESULTS
= 64;
727 wifi_scan_result mResults
[MAX_RESULTS
];
729 BssidHotlistCommand(wifi_interface_handle handle
, int id
,
730 wifi_bssid_hotlist_params params
, wifi_hotlist_ap_found_handler handler
)
731 : WifiCommand(handle
, id
), mParams(params
), mHandler(handler
)
734 int createSetupRequest(WifiRequest
& request
) {
735 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_SET_BSSID_HOTLIST
);
740 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
742 result
= request
.put_u32(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE
, mParams
.lost_ap_sample_size
);
747 struct nlattr
* attr
= request
.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS
);
748 for (int i
= 0; i
< mParams
.num_bssid
; i
++) {
749 nlattr
*attr2
= request
.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM
);
751 return WIFI_ERROR_OUT_OF_MEMORY
;
753 result
= request
.put_addr(GSCAN_ATTRIBUTE_BSSID
, mParams
.ap
[i
].bssid
);
757 result
= request
.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH
, mParams
.ap
[i
].high
);
761 result
= request
.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW
, mParams
.ap
[i
].low
);
765 request
.attr_end(attr2
);
768 request
.attr_end(attr
);
769 request
.attr_end(data
);
773 int createTeardownRequest(WifiRequest
& request
) {
774 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_RESET_BSSID_HOTLIST
);
783 ALOGD("Executing hotlist setup request, num = %d", mParams
.num_bssid
);
784 WifiRequest
request(familyId(), ifaceId());
785 int result
= createSetupRequest(request
);
790 result
= requestResponse(request
);
792 ALOGD("Failed to execute hotlist setup request, result = %d", result
);
793 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_FOUND
);
794 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_LOST
);
798 ALOGD("Successfully set %d APs in the hotlist", mParams
.num_bssid
);
800 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_FOUND
);
801 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_LOST
);
806 virtual int cancel() {
807 /* unregister event handler */
808 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_FOUND
);
809 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_LOST
);
810 /* create set hotlist message with empty hotlist */
811 WifiRequest
request(familyId(), ifaceId());
812 int result
= createTeardownRequest(request
);
817 result
= requestResponse(request
);
822 ALOGD("Successfully reset APs in current hotlist");
826 virtual int handleResponse(WifiEvent
& reply
) {
827 /* Nothing to do on response! */
831 virtual int handleEvent(WifiEvent
& event
) {
832 ALOGD("Hotlist AP event");
833 int event_id
= event
.get_vendor_subcmd();
836 nlattr
*vendor_data
= event
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
837 int len
= event
.get_vendor_data_len();
839 if (vendor_data
== NULL
|| len
== 0) {
840 ALOGD("No scan results found");
844 memset(mResults
, 0, sizeof(wifi_scan_result
) * MAX_RESULTS
);
846 int num
= len
/ sizeof(wifi_scan_result
);
847 num
= min(MAX_RESULTS
, num
);
848 memcpy(mResults
, event
.get_vendor_data(), num
* sizeof(wifi_scan_result
));
850 if (event_id
== GSCAN_EVENT_HOTLIST_RESULTS_FOUND
) {
851 ALOGD("FOUND %d hotlist APs", num
);
852 if (*mHandler
.on_hotlist_ap_found
)
853 (*mHandler
.on_hotlist_ap_found
)(id(), num
, mResults
);
854 } else if (event_id
== GSCAN_EVENT_HOTLIST_RESULTS_LOST
) {
855 ALOGD("LOST %d hotlist APs", num
);
856 if (*mHandler
.on_hotlist_ap_lost
)
857 (*mHandler
.on_hotlist_ap_lost
)(id(), num
, mResults
);
863 wifi_error
wifi_set_bssid_hotlist(wifi_request_id id
, wifi_interface_handle iface
,
864 wifi_bssid_hotlist_params params
, wifi_hotlist_ap_found_handler handler
)
866 wifi_handle handle
= getWifiHandle(iface
);
868 BssidHotlistCommand
*cmd
= new BssidHotlistCommand(iface
, id
, params
, handler
);
869 wifi_register_cmd(handle
, id
, cmd
);
870 return (wifi_error
)cmd
->start();
873 wifi_error
wifi_reset_bssid_hotlist(wifi_request_id id
, wifi_interface_handle iface
)
875 wifi_handle handle
= getWifiHandle(iface
);
877 WifiCommand
*cmd
= wifi_unregister_cmd(handle
, id
);
884 return WIFI_ERROR_INVALID_ARGS
;
888 /////////////////////////////////////////////////////////////////////////////
890 class SignificantWifiChangeCommand
: public WifiCommand
893 mac_addr bssid
; // BSSID
894 wifi_channel channel
; // channel frequency in MHz
895 int num_rssi
; // number of rssi samples
896 wifi_rssi rssi
[8]; // RSSI history in db
897 } wifi_significant_change_result_internal
;
900 wifi_significant_change_params mParams
;
901 wifi_significant_change_handler mHandler
;
902 static const int MAX_RESULTS
= 64;
903 wifi_significant_change_result_internal mResultsBuffer
[MAX_RESULTS
];
904 wifi_significant_change_result
*mResults
[MAX_RESULTS
];
906 SignificantWifiChangeCommand(wifi_interface_handle handle
, int id
,
907 wifi_significant_change_params params
, wifi_significant_change_handler handler
)
908 : WifiCommand(handle
, id
), mParams(params
), mHandler(handler
)
911 int createSetupRequest(WifiRequest
& request
) {
912 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_SET_SIGNIFICANT_CHANGE
);
917 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
919 result
= request
.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE
, mParams
.rssi_sample_size
);
923 result
= request
.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE
, mParams
.lost_ap_sample_size
);
927 result
= request
.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING
, mParams
.min_breaching
);
932 struct nlattr
* attr
= request
.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS
);
934 for (int i
= 0; i
< mParams
.num_bssid
; i
++) {
936 nlattr
*attr2
= request
.attr_start(i
);
938 return WIFI_ERROR_OUT_OF_MEMORY
;
940 result
= request
.put_addr(GSCAN_ATTRIBUTE_BSSID
, mParams
.ap
[i
].bssid
);
944 result
= request
.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH
, mParams
.ap
[i
].high
);
948 result
= request
.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW
, mParams
.ap
[i
].low
);
952 request
.attr_end(attr2
);
955 request
.attr_end(attr
);
956 request
.attr_end(data
);
961 int createTeardownRequest(WifiRequest
& request
) {
962 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_RESET_SIGNIFICANT_CHANGE
);
971 ALOGD("Set significant wifi change");
972 WifiRequest
request(familyId(), ifaceId());
974 int result
= createSetupRequest(request
);
979 result
= requestResponse(request
);
981 ALOGD("failed to set significant wifi change %d", result
);
984 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS
);
989 virtual int cancel() {
990 /* unregister event handler */
991 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS
);
993 /* create set significant change monitor message with empty hotlist */
994 WifiRequest
request(familyId(), ifaceId());
996 int result
= createTeardownRequest(request
);
1001 result
= requestResponse(request
);
1006 ALOGD("successfully reset significant wifi change");
1010 virtual int handleResponse(WifiEvent
& reply
) {
1011 /* Nothing to do on response! */
1015 virtual int handleEvent(WifiEvent
& event
) {
1016 ALOGD("Got a significant wifi change event");
1018 nlattr
*vendor_data
= event
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
1019 int len
= event
.get_vendor_data_len();
1021 if (vendor_data
== NULL
|| len
== 0) {
1022 ALOGD("No scan results found");
1029 int16_t rssi_history
[8];
1032 int num
= min(len
/ sizeof(ChangeInfo
), MAX_RESULTS
);
1033 ChangeInfo
*ci
= (ChangeInfo
*)event
.get_vendor_data();
1035 for (int i
= 0; i
< num
; i
++) {
1036 memcpy(mResultsBuffer
[i
].bssid
, ci
[i
].bssid
, sizeof(mac_addr
));
1037 mResultsBuffer
[i
].channel
= ci
[i
].channel
;
1038 /* Driver sends N samples and the rest 8-N are filled 0x7FFF
1039 * N = no of rssi samples to average sent in significant change request. */
1041 for (int j
= 0; j
< 8; j
++) {
1042 if (ci
[i
].rssi_history
[j
] == 0x7FFF) {
1046 mResultsBuffer
[i
].rssi
[j
] = (int) ci
[i
].rssi_history
[j
];
1048 mResultsBuffer
[i
].num_rssi
= num_rssi
;
1049 mResults
[i
] = reinterpret_cast<wifi_significant_change_result
*>(&(mResultsBuffer
[i
]));
1052 ALOGD("Retrieved %d scan results", num
);
1055 (*mHandler
.on_significant_change
)(id(), num
, mResults
);
1057 ALOGW("No significant change reported");
1064 wifi_error
wifi_set_significant_change_handler(wifi_request_id id
, wifi_interface_handle iface
,
1065 wifi_significant_change_params params
, wifi_significant_change_handler handler
)
1067 wifi_handle handle
= getWifiHandle(iface
);
1069 SignificantWifiChangeCommand
*cmd
= new SignificantWifiChangeCommand(
1070 iface
, id
, params
, handler
);
1071 wifi_register_cmd(handle
, id
, cmd
);
1072 return (wifi_error
)cmd
->start();
1075 wifi_error
wifi_reset_significant_change_handler(wifi_request_id id
, wifi_interface_handle iface
)
1077 wifi_handle handle
= getWifiHandle(iface
);
1079 WifiCommand
*cmd
= wifi_unregister_cmd(handle
, id
);
1083 return WIFI_SUCCESS
;
1086 return WIFI_ERROR_INVALID_ARGS
;
1089 class BssidBlacklistCommand
: public WifiCommand
1092 wifi_bssid_params
*mParams
;
1094 BssidBlacklistCommand(wifi_interface_handle handle
, int id
,
1095 wifi_bssid_params
*params
)
1096 : WifiCommand(handle
, id
), mParams(params
)
1098 int createRequest(WifiRequest
& request
) {
1099 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_SET_BSSID_BLACKLIST
);
1104 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
1105 result
= request
.put_u32(GSCAN_ATTRIBUTE_NUM_BSSID
, mParams
->num_bssid
);
1110 for (int i
= 0; i
< mParams
->num_bssid
; i
++) {
1111 result
= request
.put_addr(GSCAN_ATTRIBUTE_BLACKLIST_BSSID
, mParams
->bssids
[i
]);
1116 request
.attr_end(data
);
1121 ALOGD("Executing bssid blacklist request, num = %d", mParams
->num_bssid
);
1122 WifiRequest
request(familyId(), ifaceId());
1123 int result
= createRequest(request
);
1128 result
= requestResponse(request
);
1130 ALOGE("Failed to execute bssid blacklist request, result = %d", result
);
1134 ALOGI("Successfully added %d blacklist bssids", mParams
->num_bssid
);
1139 virtual int handleResponse(WifiEvent
& reply
) {
1140 /* Nothing to do on response! */
1145 wifi_error
wifi_set_bssid_blacklist(wifi_request_id id
, wifi_interface_handle iface
,
1146 wifi_bssid_params params
)
1148 wifi_handle handle
= getWifiHandle(iface
);
1150 BssidBlacklistCommand
*cmd
= new BssidBlacklistCommand(iface
, id
, ¶ms
);
1151 wifi_error result
= (wifi_error
)cmd
->start();
1152 //release the reference of command as well