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 #include <utils/Log.h>
25 #include "cpp_bindings.h"
28 EPNO_ATTRIBUTE_MINIMUM_5G_RSSI
,
29 EPNO_ATTRIBUTE_MINIMUM_2G_RSSI
,
30 EPNO_ATTRIBUTE_INITIAL_SCORE_MAX
,
31 EPNO_ATTRIBUTE_CUR_CONN_BONUS
,
32 EPNO_ATTRIBUTE_SAME_NETWORK_BONUS
,
33 EPNO_ATTRIBUTE_SECURE_BONUS
,
34 EPNO_ATTRIBUTE_5G_BONUS
,
35 EPNO_ATTRIBUTE_SSID_NUM
,
36 EPNO_ATTRIBUTE_SSID_LIST
,
38 EPNO_ATTRIBUTE_SSID_LEN
,
45 EPNO_ATTRIBUTE_HS_PARAM_LIST
,
46 EPNO_ATTRIBUTE_HS_NUM
,
48 EPNO_ATTRIBUTE_HS_REALM
,
49 EPNO_ATTRIBUTE_HS_CONSORTIUM_IDS
,
50 EPNO_ATTRIBUTE_HS_PLMN
,
55 class GetCapabilitiesCommand
: public WifiCommand
57 wifi_gscan_capabilities
*mCapabilities
;
59 GetCapabilitiesCommand(wifi_interface_handle iface
, wifi_gscan_capabilities
*capabitlites
)
60 : WifiCommand(iface
, 0), mCapabilities(capabitlites
)
62 memset(mCapabilities
, 0, sizeof(*mCapabilities
));
65 virtual int create() {
66 int ret
= mMsg
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_GET_CAPABILITIES
);
68 ALOGE("NL message creation failed");
76 virtual int handleResponse(WifiEvent
& reply
) {
78 if (reply
.get_cmd() != NL80211_CMD_VENDOR
) {
79 ALOGE("Ignoring reply with cmd = %d", reply
.get_cmd());
83 void *data
= reply
.get_vendor_data();
84 int len
= reply
.get_vendor_data_len();
86 memcpy(mCapabilities
, data
, min(len
, (int) sizeof(*mCapabilities
)));
93 wifi_error
wifi_get_gscan_capabilities(wifi_interface_handle handle
,
94 wifi_gscan_capabilities
*capabilities
)
96 GetCapabilitiesCommand
command(handle
, capabilities
);
97 return (wifi_error
) command
.requestResponse();
100 class GetChannelListCommand
: public WifiCommand
102 wifi_channel
*channels
;
107 GetChannelListCommand(wifi_interface_handle iface
, wifi_channel
*channel_buf
, int *ch_num
,
108 int num_max_ch
, int band
)
109 : WifiCommand(iface
, 0), channels(channel_buf
), max_channels(num_max_ch
), num_channels(ch_num
),
112 memset(channels
, 0, sizeof(wifi_channel
) * max_channels
);
114 virtual int create() {
115 int ret
= mMsg
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_GET_VALID_CHANNELS
);
120 nlattr
*data
= mMsg
.attr_start(NL80211_ATTR_VENDOR_DATA
);
121 ret
= mMsg
.put_u32(GSCAN_ATTRIBUTE_BAND
, band
);
132 virtual int handleResponse(WifiEvent
& reply
) {
134 if (reply
.get_cmd() != NL80211_CMD_VENDOR
) {
135 ALOGE("Ignoring reply with cmd = %d", reply
.get_cmd());
139 int num_channels_to_copy
= 0;
141 nlattr
*vendor_data
= reply
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
142 int len
= reply
.get_vendor_data_len();
144 if (vendor_data
== NULL
|| len
== 0) {
145 ALOGE("no vendor data in GetChannelList response; ignoring it");
149 for (nl_iterator
it(vendor_data
); it
.has_next(); it
.next()) {
150 if (it
.get_type() == GSCAN_ATTRIBUTE_NUM_CHANNELS
) {
151 num_channels_to_copy
= it
.get_u32();
152 /*ALOGD("Got channel list with %d channels", num_channels_to_copy);*/
153 if(num_channels_to_copy
> max_channels
)
154 num_channels_to_copy
= max_channels
;
155 *num_channels
= num_channels_to_copy
;
156 } else if (it
.get_type() == GSCAN_ATTRIBUTE_CHANNEL_LIST
&& num_channels_to_copy
) {
157 memcpy(channels
, it
.get_data(), sizeof(int) * num_channels_to_copy
);
159 ALOGW("Ignoring invalid attribute type = %d, size = %d",
160 it
.get_type(), it
.get_len());
168 wifi_error
wifi_get_valid_channels(wifi_interface_handle handle
,
169 int band
, int max_channels
, wifi_channel
*channels
, int *num_channels
)
171 GetChannelListCommand
command(handle
, channels
, num_channels
,
173 return (wifi_error
) command
.requestResponse();
175 /////////////////////////////////////////////////////////////////////////////
177 /* helper functions */
180 static int parseScanResults(wifi_scan_result *results, int num, nlattr *attr)
182 memset(results, 0, sizeof(wifi_scan_result) * num);
185 for (nl_iterator it(attr); it.has_next() && i < num; it.next(), i++) {
187 nlattr *sc_data = (nlattr *) it.get_data();
188 wifi_scan_result *result = results + i;
190 for (nl_iterator it2(sc_data); it2.has_next(); it2.next()) {
191 int type = it2.get_type();
192 if (type == GSCAN_ATTRIBUTE_SSID) {
193 strncpy(result->ssid, (char *) it2.get_data(), it2.get_len());
194 result->ssid[it2.get_len()] = 0;
195 } else if (type == GSCAN_ATTRIBUTE_BSSID) {
196 memcpy(result->bssid, (byte *) it2.get_data(), sizeof(mac_addr));
197 } else if (type == GSCAN_ATTRIBUTE_TIMESTAMP) {
198 result->ts = it2.get_u64();
199 } else if (type == GSCAN_ATTRIBUTE_CHANNEL) {
200 result->ts = it2.get_u16();
201 } else if (type == GSCAN_ATTRIBUTE_RSSI) {
202 result->rssi = it2.get_u8();
203 } else if (type == GSCAN_ATTRIBUTE_RTT) {
204 result->rtt = it2.get_u64();
205 } else if (type == GSCAN_ATTRIBUTE_RTTSD) {
206 result->rtt_sd = it2.get_u64();
213 ALOGE("Got too many results; skipping some");
220 int createFeatureRequest(WifiRequest
& request
, int subcmd
) {
222 int result
= request
.create(GOOGLE_OUI
, subcmd
);
230 class ScanCommand
: public WifiCommand
232 wifi_scan_cmd_params
*mParams
;
233 wifi_scan_result_handler mHandler
;
234 static unsigned mGlobalFullScanBuckets
;
236 ScanCommand(wifi_interface_handle iface
, int id
, wifi_scan_cmd_params
*params
,
237 wifi_scan_result_handler handler
)
238 : WifiCommand(iface
, id
), mParams(params
), mHandler(handler
)
241 int createSetupRequest(WifiRequest
& request
) {
242 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN
);
247 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
248 result
= request
.put_u32(GSCAN_ATTRIBUTE_BASE_PERIOD
, mParams
->base_period
);
253 result
= request
.put_u32(GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN
, mParams
->max_ap_per_scan
);
258 result
= request
.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD
, mParams
->report_threshold_percent
);
263 result
= request
.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD_NUM_SCANS
, mParams
->report_threshold_num_scans
);
268 result
= request
.put_u32(GSCAN_ATTRIBUTE_NUM_BUCKETS
, mParams
->num_buckets
);
273 for (int i
= 0; i
< mParams
->num_buckets
; i
++) {
274 nlattr
* bucket
= request
.attr_start(i
); // next bucket
275 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_ID
, mParams
->buckets
[i
].bucket
);
279 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_PERIOD
, mParams
->buckets
[i
].period
);
283 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKETS_BAND
,
284 mParams
->buckets
[i
].band
);
289 if (mParams
->buckets
[i
].report_events
== 0) {
290 mParams
->buckets
[i
].report_events
= REPORT_EVENTS_EACH_SCAN
;
292 result
= request
.put_u32(GSCAN_ATTRIBUTE_REPORT_EVENTS
,
293 mParams
->buckets
[i
].report_events
);
298 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS
,
299 mParams
->buckets
[i
].num_channels
);
304 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_EXPONENT
,
305 mParams
->buckets
[i
].base
);
310 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD
,
311 mParams
->buckets
[i
].max_period
);
316 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT
,
317 mParams
->buckets
[i
].step_count
);
322 if (mParams
->buckets
[i
].num_channels
) {
323 nlattr
*channels
= request
.attr_start(GSCAN_ATTRIBUTE_BUCKET_CHANNELS
);
324 for (int j
= 0; j
< mParams
->buckets
[i
].num_channels
; j
++) {
325 result
= request
.put_u32(j
, mParams
->buckets
[i
].channels
[j
].channel
);
330 request
.attr_end(channels
);
333 request
.attr_end(bucket
);
336 request
.attr_end(data
);
340 int createStartRequest(WifiRequest
& request
) {
341 return createFeatureRequest(request
, SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN
);
344 int createStopRequest(WifiRequest
& request
) {
345 return createFeatureRequest(request
, SLSI_NL80211_VENDOR_SUBCMD_DEL_GSCAN
);
349 ALOGD("starting Gscan");
350 WifiRequest
request(familyId(), ifaceId());
351 int result
= createSetupRequest(request
);
352 if (result
!= WIFI_SUCCESS
) {
353 ALOGE("failed to create setup request; result = %d", result
);
357 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE
);
358 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_COMPLETE_SCAN
);
361 for (int i
= 0; i
< mParams
->num_buckets
; i
++) {
362 if (mParams
->buckets
[i
].report_events
& REPORT_EVENTS_FULL_RESULTS
) {
368 ALOGI("Full scan requested with nBuckets = %d", nBuckets
);
369 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_FULL_SCAN_RESULTS
);
371 result
= requestResponse(request
);
372 if (result
!= WIFI_SUCCESS
) {
373 ALOGE("failed to start scan; result = %d", result
);
374 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_COMPLETE_SCAN
);
375 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE
);
383 virtual int cancel() {
384 ALOGD("Stopping Gscan");
386 WifiRequest
request(familyId(), ifaceId());
387 int result
= createStopRequest(request
);
388 if (result
!= WIFI_SUCCESS
) {
389 ALOGE("failed to create stop request; result = %d", result
);
391 result
= requestResponse(request
);
392 if (result
!= WIFI_SUCCESS
) {
393 ALOGE("failed to stop scan; result = %d", result
);
397 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_COMPLETE_SCAN
);
398 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE
);
399 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_FULL_SCAN_RESULTS
);
404 virtual int handleResponse(WifiEvent
& reply
) {
405 /* Nothing to do on response! */
409 virtual int handleEvent(WifiEvent
& event
) {
412 nlattr
*vendor_data
= event
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
413 unsigned int len
= event
.get_vendor_data_len();
414 int event_id
= event
.get_vendor_subcmd();
416 if(event_id
== GSCAN_EVENT_COMPLETE_SCAN
) {
417 if (vendor_data
== NULL
|| len
!= 4) {
418 ALOGE("Scan complete type not mentioned!");
421 wifi_scan_event evt_type
;
423 evt_type
= (wifi_scan_event
) event
.get_u32(NL80211_ATTR_VENDOR_DATA
);
424 if(*mHandler
.on_scan_event
)
425 (*mHandler
.on_scan_event
)(id(), evt_type
);
426 } else if(event_id
== GSCAN_EVENT_FULL_SCAN_RESULTS
) {
427 uint32_t bucket_scanned
= 0;
428 wifi_scan_result
*scan_result
= NULL
;
429 for (nl_iterator
it(vendor_data
); it
.has_next(); it
.next()) {
430 if (it
.get_type() == GSCAN_ATTRIBUTE_SCAN_BUCKET_BIT
) {
431 bucket_scanned
= it
.get_u32();
432 } else if (it
.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS
) {
433 if (it
.get_len() >= (int)sizeof(*scan_result
))
434 scan_result
= (wifi_scan_result
*)it
.get_data();
438 if(*mHandler
.on_full_scan_result
)
439 (*mHandler
.on_full_scan_result
)(id(), scan_result
, bucket_scanned
);
441 ALOGD("%-32s\t", scan_result->ssid);
442 ALOGD("%02x:%02x:%02x:%02x:%02x:%02x ", scan_result->bssid[0], scan_result->bssid[1],
443 scan_result->bssid[2], scan_result->bssid[3], scan_result->bssid[4], scan_result->bssid[5]);
444 ALOGD("%d\t", scan_result->rssi);
445 ALOGD("%d\t", scan_result->channel);
446 ALOGD("%lld\t", scan_result->ts);
447 ALOGD("%lld\t", scan_result->rtt);
448 ALOGD("%lld\n", scan_result->rtt_sd);
456 unsigned ScanCommand::mGlobalFullScanBuckets
= 0;
458 wifi_error
wifi_start_gscan(
460 wifi_interface_handle iface
,
461 wifi_scan_cmd_params params
,
462 wifi_scan_result_handler handler
)
464 wifi_handle handle
= getWifiHandle(iface
);
466 ScanCommand
*cmd
= new ScanCommand(iface
, id
, ¶ms
, handler
);
467 wifi_register_cmd(handle
, id
, cmd
);
468 return (wifi_error
)cmd
->start();
471 wifi_error
wifi_stop_gscan(wifi_request_id id
, wifi_interface_handle iface
)
473 wifi_handle handle
= getWifiHandle(iface
);
476 wifi_scan_result_handler handler
;
477 wifi_scan_cmd_params dummy_params
;
478 memset(&handler
, 0, sizeof(handler
));
480 ScanCommand
*cmd
= new ScanCommand(iface
, id
, &dummy_params
, handler
);
487 WifiCommand
*cmd
= wifi_unregister_cmd(handle
, id
);
494 return WIFI_ERROR_INVALID_ARGS
;
497 class GetScanResultsCommand
: public WifiCommand
{
498 wifi_cached_scan_results
*mScans
;
504 static const int MAX_RESULTS
= 320;
505 wifi_scan_result mScanResults
[MAX_RESULTS
];
508 GetScanResultsCommand(wifi_interface_handle iface
, byte flush
,
509 wifi_cached_scan_results
*results
, int max
, int *num
)
510 : WifiCommand(iface
, -1), mScans(results
), mMax(max
), mNum(num
),
511 mRetrieved(0), mFlush(flush
), mCompleted(0)
513 memset(mScanResults
,0,sizeof(mScanResults
));
517 int createRequest(WifiRequest
& request
, int num
, byte flush
) {
518 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_GET_SCAN_RESULTS
);
523 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
524 result
= request
.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS
, num
);
529 request
.attr_end(data
);
534 WifiRequest
request(familyId(), ifaceId());
536 for (int i
= 0; i
< 10 && mRetrieved
< mMax
; i
++) {
537 int result
= createRequest(request
, (mMax
- mRetrieved
), mFlush
);
539 ALOGE("failed to create request");
543 int prev_retrieved
= mRetrieved
;
545 result
= requestResponse(request
);
547 if (result
!= WIFI_SUCCESS
) {
548 ALOGE("failed to retrieve scan results; result = %d", result
);
552 if (mRetrieved
== prev_retrieved
|| mCompleted
) {
553 /* no more items left to retrieve */
560 ALOGE("GetScanResults read %d results", mRetrieved
);
565 virtual int handleResponse(WifiEvent
& reply
) {
567 if (reply
.get_cmd() != NL80211_CMD_VENDOR
) {
568 ALOGE("Ignoring reply with cmd = %d", reply
.get_cmd());
572 nlattr
*vendor_data
= reply
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
573 int len
= reply
.get_vendor_data_len();
575 if (vendor_data
== NULL
|| len
== 0) {
576 ALOGE("no vendor data in GetScanResults response; ignoring it");
580 for (nl_iterator
it(vendor_data
); it
.has_next(); it
.next()) {
581 if (it
.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE
) {
582 mCompleted
= it
.get_u8();
583 //ALOGD("retrieved mCompleted flag : %d", mCompleted);
584 } else if (it
.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS
|| it
.get_type() == 0) {
585 int scan_id
= 0, flags
= 0, num
= 0;
586 for (nl_iterator
it2(it
.get()); it2
.has_next(); it2
.next()) {
587 if (it2
.get_type() == GSCAN_ATTRIBUTE_SCAN_ID
) {
588 scan_id
= it2
.get_u32();
589 //ALOGD("retrieved scan_id : 0x%0x", scan_id);
590 } else if (it2
.get_type() == GSCAN_ATTRIBUTE_SCAN_FLAGS
) {
591 flags
= it2
.get_u8();
592 //ALOGD("retrieved scan_flags : 0x%0x", flags);
593 } else if (it2
.get_type() == GSCAN_ATTRIBUTE_NUM_OF_RESULTS
) {
595 //ALOGD("retrieved num_results: %d", num);
596 } else if (it2
.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS
) {
597 if (mRetrieved
>= mMax
) {
598 ALOGW("Stored %d scans, ignoring excess results", mRetrieved
);
601 num
= it2
.get_len() / sizeof(wifi_scan_result
);
602 num
= min(MAX_RESULTS
- mNextScanResult
, num
);
603 num
= min((int)MAX_AP_CACHE_PER_SCAN
, num
);
604 memcpy(mScanResults
+ mNextScanResult
, it2
.get_data(),
605 sizeof(wifi_scan_result
) * num
);
607 wifi_scan_result *results = (wifi_scan_result *)it2.get_data();
608 for (int i = 0; i < num; i++) {
609 wifi_scan_result *result = results + i;
610 ALOGD("%02d %-32s %02x:%02x:%02x:%02x:%02x:%02x %04d", i,
611 result->ssid, result->bssid[0], result->bssid[1], result->bssid[2],
612 result->bssid[3], result->bssid[4], result->bssid[5],
615 mScans
[mRetrieved
].scan_id
= scan_id
;
616 mScans
[mRetrieved
].flags
= flags
;
617 mScans
[mRetrieved
].num_results
= num
;
618 //ALOGD("Setting result of scan_id : 0x%0x", mScans[mRetrieved].scan_id);
619 memcpy(mScans
[mRetrieved
].results
,
620 &(mScanResults
[mNextScanResult
]), num
* sizeof(wifi_scan_result
));
621 mNextScanResult
+= num
;
624 ALOGW("Ignoring invalid attribute type = %d, size = %d",
625 it
.get_type(), it
.get_len());
629 ALOGW("Ignoring invalid attribute type = %d, size = %d",
630 it
.get_type(), it
.get_len());
638 wifi_error
wifi_get_cached_gscan_results(wifi_interface_handle iface
, byte flush
,
639 int max
, wifi_cached_scan_results
*results
, int *num
) {
640 GetScanResultsCommand
*cmd
= new GetScanResultsCommand(iface
, flush
, results
, max
, num
);
641 return (wifi_error
)cmd
->execute();
644 /////////////////////////////////////////////////////////////////////////////
646 class BssidHotlistCommand
: public WifiCommand
649 wifi_bssid_hotlist_params mParams
;
650 wifi_hotlist_ap_found_handler mHandler
;
651 static const int MAX_RESULTS
= 64;
652 wifi_scan_result mResults
[MAX_RESULTS
];
654 BssidHotlistCommand(wifi_interface_handle handle
, int id
,
655 wifi_bssid_hotlist_params params
, wifi_hotlist_ap_found_handler handler
)
656 : WifiCommand(handle
, id
), mParams(params
), mHandler(handler
)
658 memset(mResults
, 0, sizeof(mResults
));
661 int createSetupRequest(WifiRequest
& request
) {
662 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_SET_BSSID_HOTLIST
);
667 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
669 result
= request
.put_u32(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE
, mParams
.lost_ap_sample_size
);
674 struct nlattr
* attr
= request
.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS
);
675 for (int i
= 0; i
< mParams
.num_bssid
; i
++) {
676 nlattr
*attr2
= request
.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM
);
678 return WIFI_ERROR_OUT_OF_MEMORY
;
680 result
= request
.put_addr(GSCAN_ATTRIBUTE_BSSID
, mParams
.ap
[i
].bssid
);
684 result
= request
.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH
, mParams
.ap
[i
].high
);
688 result
= request
.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW
, mParams
.ap
[i
].low
);
692 request
.attr_end(attr2
);
695 request
.attr_end(attr
);
696 request
.attr_end(data
);
700 int createTeardownRequest(WifiRequest
& request
) {
701 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_RESET_BSSID_HOTLIST
);
710 WifiRequest
request(familyId(), ifaceId());
711 int result
= createSetupRequest(request
);
716 result
= requestResponse(request
);
718 ALOGE("Failed to execute hotlist setup request, result = %d", result
);
719 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_FOUND
);
720 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_LOST
);
724 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_FOUND
);
725 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_LOST
);
730 virtual int cancel() {
731 /* unregister event handler */
732 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_FOUND
);
733 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_LOST
);
734 /* create set hotlist message with empty hotlist */
735 WifiRequest
request(familyId(), ifaceId());
736 int result
= createTeardownRequest(request
);
741 result
= requestResponse(request
);
749 virtual int handleResponse(WifiEvent
& reply
) {
750 /* Nothing to do on response! */
754 virtual int handleEvent(WifiEvent
& event
) {
755 int event_id
= event
.get_vendor_subcmd();
758 nlattr
*vendor_data
= event
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
759 int len
= event
.get_vendor_data_len();
761 if (vendor_data
== NULL
|| len
== 0) {
762 ALOGE("No scan results found");
767 int num
= len
/ sizeof(wifi_scan_result
);
768 num
= min(MAX_RESULTS
, num
);
769 memcpy(mResults
, event
.get_vendor_data(), num
* sizeof(wifi_scan_result
));
771 if (event_id
== GSCAN_EVENT_HOTLIST_RESULTS_FOUND
) {
772 ALOGD("FOUND %d hotlist APs", num
);
773 if (*mHandler
.on_hotlist_ap_found
)
774 (*mHandler
.on_hotlist_ap_found
)(id(), num
, mResults
);
775 } else if (event_id
== GSCAN_EVENT_HOTLIST_RESULTS_LOST
) {
776 ALOGD("LOST %d hotlist APs", num
);
777 if (*mHandler
.on_hotlist_ap_lost
)
778 (*mHandler
.on_hotlist_ap_lost
)(id(), num
, mResults
);
784 wifi_error
wifi_set_bssid_hotlist(wifi_request_id id
, wifi_interface_handle iface
,
785 wifi_bssid_hotlist_params params
, wifi_hotlist_ap_found_handler handler
)
787 wifi_handle handle
= getWifiHandle(iface
);
789 BssidHotlistCommand
*cmd
= new BssidHotlistCommand(iface
, id
, params
, handler
);
790 wifi_register_cmd(handle
, id
, cmd
);
791 return (wifi_error
)cmd
->start();
794 wifi_error
wifi_reset_bssid_hotlist(wifi_request_id id
, wifi_interface_handle iface
)
796 wifi_handle handle
= getWifiHandle(iface
);
798 WifiCommand
*cmd
= wifi_unregister_cmd(handle
, id
);
805 return WIFI_ERROR_INVALID_ARGS
;
809 /////////////////////////////////////////////////////////////////////////////
811 class SignificantWifiChangeCommand
: public WifiCommand
814 mac_addr bssid
; // BSSID
815 wifi_channel channel
; // channel frequency in MHz
816 int num_rssi
; // number of rssi samples
817 wifi_rssi rssi
[8]; // RSSI history in db
818 } wifi_significant_change_result_internal
;
821 wifi_significant_change_params mParams
;
822 wifi_significant_change_handler mHandler
;
823 static const int MAX_RESULTS
= 64;
824 wifi_significant_change_result_internal mResultsBuffer
[MAX_RESULTS
];
825 wifi_significant_change_result
*mResults
[MAX_RESULTS
];
827 SignificantWifiChangeCommand(wifi_interface_handle handle
, int id
,
828 wifi_significant_change_params params
, wifi_significant_change_handler handler
)
829 : WifiCommand(handle
, id
), mParams(params
), mHandler(handler
)
831 memset(mResultsBuffer
,0,sizeof(mResultsBuffer
));
832 memset(mResults
,0,sizeof(mResults
));
835 int createSetupRequest(WifiRequest
& request
) {
836 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_SET_SIGNIFICANT_CHANGE
);
841 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
843 result
= request
.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE
, mParams
.rssi_sample_size
);
847 result
= request
.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE
, mParams
.lost_ap_sample_size
);
851 result
= request
.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING
, mParams
.min_breaching
);
856 struct nlattr
* attr
= request
.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS
);
858 for (int i
= 0; i
< mParams
.num_bssid
; i
++) {
860 nlattr
*attr2
= request
.attr_start(i
);
862 return WIFI_ERROR_OUT_OF_MEMORY
;
864 result
= request
.put_addr(GSCAN_ATTRIBUTE_BSSID
, mParams
.ap
[i
].bssid
);
868 result
= request
.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH
, mParams
.ap
[i
].high
);
872 result
= request
.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW
, mParams
.ap
[i
].low
);
876 request
.attr_end(attr2
);
879 request
.attr_end(attr
);
880 request
.attr_end(data
);
885 int createTeardownRequest(WifiRequest
& request
) {
886 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_RESET_SIGNIFICANT_CHANGE
);
895 WifiRequest
request(familyId(), ifaceId());
897 int result
= createSetupRequest(request
);
902 result
= requestResponse(request
);
904 ALOGE("failed to set significant wifi change %d", result
);
907 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS
);
912 virtual int cancel() {
913 /* unregister event handler */
914 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS
);
916 /* create set significant change monitor message with empty hotlist */
917 WifiRequest
request(familyId(), ifaceId());
919 int result
= createTeardownRequest(request
);
924 result
= requestResponse(request
);
932 virtual int handleResponse(WifiEvent
& reply
) {
933 /* Nothing to do on response! */
937 virtual int handleEvent(WifiEvent
& event
) {
938 nlattr
*vendor_data
= event
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
939 int len
= event
.get_vendor_data_len();
941 if (vendor_data
== NULL
|| len
== 0) {
942 ALOGE("No scan results found");
949 int16_t rssi_history
[8];
952 int num
= min(len
/ sizeof(ChangeInfo
), MAX_RESULTS
);
953 ChangeInfo
*ci
= (ChangeInfo
*)event
.get_vendor_data();
955 for (int i
= 0; i
< num
; i
++) {
956 memcpy(mResultsBuffer
[i
].bssid
, ci
[i
].bssid
, sizeof(mac_addr
));
957 mResultsBuffer
[i
].channel
= ci
[i
].channel
;
958 /* Driver sends N samples and the rest 8-N are filled 0x7FFF
959 * N = no of rssi samples to average sent in significant change request. */
961 for (int j
= 0; j
< 8; j
++) {
962 if (ci
[i
].rssi_history
[j
] == 0x7FFF) {
966 mResultsBuffer
[i
].rssi
[j
] = (int) ci
[i
].rssi_history
[j
];
968 mResultsBuffer
[i
].num_rssi
= num_rssi
;
969 mResults
[i
] = reinterpret_cast<wifi_significant_change_result
*>(&(mResultsBuffer
[i
]));
973 (*mHandler
.on_significant_change
)(id(), num
, mResults
);
975 ALOGW("No significant change reported");
982 wifi_error
wifi_set_significant_change_handler(wifi_request_id id
, wifi_interface_handle iface
,
983 wifi_significant_change_params params
, wifi_significant_change_handler handler
)
985 wifi_handle handle
= getWifiHandle(iface
);
987 SignificantWifiChangeCommand
*cmd
= new SignificantWifiChangeCommand(
988 iface
, id
, params
, handler
);
989 wifi_register_cmd(handle
, id
, cmd
);
990 return (wifi_error
)cmd
->start();
993 wifi_error
wifi_reset_significant_change_handler(wifi_request_id id
, wifi_interface_handle iface
)
995 wifi_handle handle
= getWifiHandle(iface
);
997 WifiCommand
*cmd
= wifi_unregister_cmd(handle
, id
);
1001 return WIFI_SUCCESS
;
1004 return WIFI_ERROR_INVALID_ARGS
;
1007 class ePNOCommand
: public WifiCommand
1010 wifi_epno_params
*epno_params
;
1011 wifi_epno_handler mHandler
;
1012 wifi_scan_result mResults
;
1014 ePNOCommand(wifi_interface_handle handle
, int id
,
1015 wifi_epno_params
*params
, wifi_epno_handler handler
)
1016 : WifiCommand(handle
, id
), mHandler(handler
)
1018 epno_params
= params
;
1019 memset(&mResults
,0,sizeof(wifi_scan_result
));
1022 int createSetupRequest(WifiRequest
& request
) {
1023 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_SET_EPNO_LIST
);
1028 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
1029 if (epno_params
== NULL
) {
1030 result
= request
.put_u8(EPNO_ATTRIBUTE_SSID_NUM
, 0);
1034 request
.attr_end(data
);
1037 result
= request
.put_u16(EPNO_ATTRIBUTE_MINIMUM_5G_RSSI
, epno_params
->min5GHz_rssi
);
1041 result
= request
.put_u16(EPNO_ATTRIBUTE_MINIMUM_2G_RSSI
, epno_params
->min24GHz_rssi
);
1045 result
= request
.put_u16(EPNO_ATTRIBUTE_INITIAL_SCORE_MAX
, epno_params
->initial_score_max
);
1049 result
= request
.put_u8(EPNO_ATTRIBUTE_CUR_CONN_BONUS
, epno_params
->current_connection_bonus
);
1053 result
= request
.put_u8(EPNO_ATTRIBUTE_SAME_NETWORK_BONUS
, epno_params
->same_network_bonus
);
1057 result
= request
.put_u8(EPNO_ATTRIBUTE_SECURE_BONUS
, epno_params
->secure_bonus
);
1061 result
= request
.put_u8(EPNO_ATTRIBUTE_5G_BONUS
, epno_params
->band5GHz_bonus
);
1065 result
= request
.put_u8(EPNO_ATTRIBUTE_SSID_NUM
, epno_params
->num_networks
);
1070 ALOGI("ePNO [min5GHz_rssi:%d min24GHz_rssi:%d initial_score_max:%d current_connection_bonus:%d same_network_bonus:%d secure_bonus:%d band5GHz_bonus:%d num_networks:%d]",
1071 epno_params
->min5GHz_rssi
,
1072 epno_params
->min24GHz_rssi
,
1073 epno_params
->initial_score_max
,
1074 epno_params
->current_connection_bonus
,
1075 epno_params
->same_network_bonus
,
1076 epno_params
->secure_bonus
,
1077 epno_params
->band5GHz_bonus
,
1078 epno_params
->num_networks
);
1080 struct nlattr
* attr
= request
.attr_start(EPNO_ATTRIBUTE_SSID_LIST
);
1081 for (int i
= 0; i
< epno_params
->num_networks
; i
++) {
1082 nlattr
*attr2
= request
.attr_start(i
);
1083 if (attr2
== NULL
) {
1084 return WIFI_ERROR_OUT_OF_MEMORY
;
1086 result
= request
.put_u16(EPNO_ATTRIBUTE_FLAGS
, epno_params
->networks
[i
].flags
);
1090 result
= request
.put_u8(EPNO_ATTRIBUTE_AUTH
, epno_params
->networks
[i
].auth_bit_field
);
1094 result
= request
.put_u8(EPNO_ATTRIBUTE_SSID_LEN
, strlen(epno_params
->networks
[i
].ssid
));
1098 result
= request
.put(EPNO_ATTRIBUTE_SSID
, epno_params
->networks
[i
].ssid
, strlen(epno_params
->networks
[i
].ssid
));
1102 request
.attr_end(attr2
);
1105 request
.attr_end(attr
);
1106 request
.attr_end(data
);
1111 ALOGI("ePNO num_network=%d", epno_params
? epno_params
->num_networks
: 0);
1112 WifiRequest
request(familyId(), ifaceId());
1113 int result
= createSetupRequest(request
);
1118 result
= requestResponse(request
);
1120 ALOGI("Failed: ePNO setup request, result = %d", result
);
1121 unregisterVendorHandler(GOOGLE_OUI
, WIFI_EPNO_EVENT
);
1126 registerVendorHandler(GOOGLE_OUI
, WIFI_EPNO_EVENT
);
1131 virtual int cancel() {
1132 /* unregister event handler */
1133 unregisterVendorHandler(GOOGLE_OUI
, WIFI_EPNO_EVENT
);
1137 virtual int handleResponse(WifiEvent
& reply
) {
1138 /* Nothing to do on response! */
1142 virtual int handleEvent(WifiEvent
& event
) {
1145 nlattr
*vendor_data
= event
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
1146 int len
= event
.get_vendor_data_len();
1148 if (vendor_data
== NULL
|| len
== 0) {
1149 ALOGI("No scan results found");
1154 mResults
= *(wifi_scan_result
*) event
.get_vendor_data();
1155 if (*mHandler
.on_network_found
)
1156 (*mHandler
.on_network_found
)(id(), 1, &mResults
);
1161 wifi_error
wifi_set_epno_list(wifi_request_id id
,
1162 wifi_interface_handle iface
,
1163 const wifi_epno_params
*epno_params
,
1164 wifi_epno_handler handler
)
1166 wifi_handle handle
= getWifiHandle(iface
);
1167 ePNOCommand
*cmd
= new ePNOCommand(iface
, id
, (wifi_epno_params
*)epno_params
, handler
);
1168 wifi_register_cmd(handle
, id
, cmd
);
1169 wifi_error result
= (wifi_error
)cmd
->start();
1170 if (result
!= WIFI_SUCCESS
) {
1171 wifi_unregister_cmd(handle
, id
);
1176 wifi_error
wifi_reset_epno_list(wifi_request_id id
, wifi_interface_handle iface
)
1178 wifi_handle handle
= getWifiHandle(iface
);
1179 wifi_epno_handler handler
;
1181 handler
.on_network_found
= NULL
;
1182 ePNOCommand
*cmd
= new ePNOCommand(iface
, id
, NULL
, handler
);
1183 wifi_register_cmd(handle
, id
, cmd
);
1184 wifi_error result
= (wifi_error
)cmd
->start();
1185 if (result
!= WIFI_SUCCESS
) {
1186 wifi_unregister_cmd(handle
, id
);
1191 class HsListCommand
: public WifiCommand
1194 wifi_passpoint_network
*mNetworks
;
1195 wifi_passpoint_event_handler mHandler
;
1197 HsListCommand(wifi_request_id id
, wifi_interface_handle iface
,
1198 int num
, wifi_passpoint_network
*hs_list
, wifi_passpoint_event_handler handler
)
1199 : WifiCommand(iface
, id
), num_hs(num
), mNetworks(hs_list
),
1204 HsListCommand(wifi_request_id id
, wifi_interface_handle iface
,
1206 : WifiCommand(iface
, id
), num_hs(num
), mNetworks(NULL
)
1208 mHandler
.on_passpoint_network_found
= NULL
;
1211 int createRequest(WifiRequest
& request
, int val
) {
1215 result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_SET_HS_LIST
);
1216 result
= request
.put_u32(EPNO_ATTRIBUTE_HS_NUM
, num_hs
);
1220 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
1222 struct nlattr
* attr
= request
.attr_start(EPNO_ATTRIBUTE_HS_PARAM_LIST
);
1223 for (int i
= 0; i
< num_hs
; i
++) {
1224 nlattr
*attr2
= request
.attr_start(i
);
1225 if (attr2
== NULL
) {
1226 return WIFI_ERROR_OUT_OF_MEMORY
;
1228 result
= request
.put_u32(EPNO_ATTRIBUTE_HS_ID
, mNetworks
[i
].id
);
1232 result
= request
.put(EPNO_ATTRIBUTE_HS_REALM
, mNetworks
[i
].realm
, 256);
1236 result
= request
.put(EPNO_ATTRIBUTE_HS_CONSORTIUM_IDS
, mNetworks
[i
].roamingConsortiumIds
, 128);
1240 result
= request
.put(EPNO_ATTRIBUTE_HS_PLMN
, mNetworks
[i
].plmn
, 3);
1244 request
.attr_end(attr2
);
1246 request
.attr_end(attr
);
1247 request
.attr_end(data
);
1249 result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_RESET_HS_LIST
);
1255 return WIFI_SUCCESS
;
1260 WifiRequest
request(familyId(), ifaceId());
1261 int result
= createRequest(request
, num_hs
);
1262 if (result
!= WIFI_SUCCESS
) {
1263 ALOGE("failed to create request; result = %d", result
);
1267 registerVendorHandler(GOOGLE_OUI
, WIFI_HOTSPOT_MATCH
);
1269 result
= requestResponse(request
);
1270 if (result
!= WIFI_SUCCESS
) {
1271 ALOGE("failed to set ANQPO networks; result = %d", result
);
1272 unregisterVendorHandler(GOOGLE_OUI
, WIFI_HOTSPOT_MATCH
);
1279 virtual int cancel() {
1281 WifiRequest
request(familyId(), ifaceId());
1282 int result
= createRequest(request
, 0);
1283 if (result
!= WIFI_SUCCESS
) {
1284 ALOGE("failed to create request; result = %d", result
);
1286 result
= requestResponse(request
);
1287 if (result
!= WIFI_SUCCESS
) {
1288 ALOGE("failed to reset ANQPO networks;result = %d", result
);
1292 unregisterVendorHandler(GOOGLE_OUI
, WIFI_HOTSPOT_MATCH
);
1293 return WIFI_SUCCESS
;
1296 virtual int handleResponse(WifiEvent
& reply
) {
1297 /* Nothing to do on response! */
1301 virtual int handleEvent(WifiEvent
& event
) {
1302 nlattr
*vendor_data
= event
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
1303 unsigned int len
= event
.get_vendor_data_len();
1304 if (vendor_data
== NULL
|| len
< sizeof(wifi_scan_result
)) {
1305 ALOGE("ERROR: No scan results found");
1309 wifi_scan_result
*result
= (wifi_scan_result
*)event
.get_vendor_data();
1310 byte
*anqp
= (byte
*)result
+ offsetof(wifi_scan_result
, ie_data
) + result
->ie_length
;
1311 int networkId
= *(int *)anqp
;
1312 anqp
+= sizeof(int);
1313 int anqp_len
= *(u16
*)anqp
;
1314 anqp
+= sizeof(u16
);
1316 if(*mHandler
.on_passpoint_network_found
)
1317 (*mHandler
.on_passpoint_network_found
)(id(), networkId
, result
, anqp_len
, anqp
);
1323 wifi_error
wifi_set_passpoint_list(wifi_request_id id
, wifi_interface_handle iface
, int num
,
1324 wifi_passpoint_network
*networks
, wifi_passpoint_event_handler handler
)
1326 wifi_handle handle
= getWifiHandle(iface
);
1327 HsListCommand
*cmd
= new HsListCommand(id
, iface
, num
, networks
, handler
);
1329 wifi_register_cmd(handle
, id
, cmd
);
1330 wifi_error result
= (wifi_error
)cmd
->start();
1331 if (result
!= WIFI_SUCCESS
) {
1332 wifi_unregister_cmd(handle
, id
);
1337 wifi_error
wifi_reset_passpoint_list(wifi_request_id id
, wifi_interface_handle iface
)
1339 wifi_handle handle
= getWifiHandle(iface
);
1341 HsListCommand
*cmd
= (HsListCommand
*)(wifi_get_cmd(handle
, id
));
1344 cmd
= new HsListCommand(id
, iface
, 0);
1345 wifi_register_cmd(handle
, id
, cmd
);
1347 result
= (wifi_error
)cmd
->cancel();
1348 wifi_unregister_cmd(handle
, id
);