5 #include <sys/socket.h>
6 #include <netlink/genl/genl.h>
7 #include <netlink/genl/family.h>
8 #include <netlink/genl/ctrl.h>
9 #include <linux/rtnetlink.h>
10 #include <netpacket/packet.h>
11 #include <linux/filter.h>
12 #include <linux/errqueue.h>
14 #include <linux/pkt_sched.h>
15 #include <netlink/object-api.h>
16 #include <netlink/netlink.h>
17 #include <netlink/socket.h>
18 #include <netlink/handlers.h>
22 #define LOG_TAG "WifiHAL"
24 #include <utils/Log.h>
28 #include "cpp_bindings.h"
31 EPNO_ATTRIBUTE_MINIMUM_5G_RSSI
,
32 EPNO_ATTRIBUTE_MINIMUM_2G_RSSI
,
33 EPNO_ATTRIBUTE_INITIAL_SCORE_MAX
,
34 EPNO_ATTRIBUTE_CUR_CONN_BONUS
,
35 EPNO_ATTRIBUTE_SAME_NETWORK_BONUS
,
36 EPNO_ATTRIBUTE_SECURE_BONUS
,
37 EPNO_ATTRIBUTE_5G_BONUS
,
38 EPNO_ATTRIBUTE_SSID_NUM
,
39 EPNO_ATTRIBUTE_SSID_LIST
,
41 EPNO_ATTRIBUTE_SSID_LEN
,
48 EPNO_ATTRIBUTE_HS_PARAM_LIST
,
49 EPNO_ATTRIBUTE_HS_NUM
,
51 EPNO_ATTRIBUTE_HS_REALM
,
52 EPNO_ATTRIBUTE_HS_CONSORTIUM_IDS
,
53 EPNO_ATTRIBUTE_HS_PLMN
,
58 class GetCapabilitiesCommand
: public WifiCommand
60 wifi_gscan_capabilities
*mCapabilities
;
62 GetCapabilitiesCommand(wifi_interface_handle iface
, wifi_gscan_capabilities
*capabitlites
)
63 : WifiCommand(iface
, 0), mCapabilities(capabitlites
)
65 memset(mCapabilities
, 0, sizeof(*mCapabilities
));
68 virtual int create() {
69 int ret
= mMsg
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_GET_CAPABILITIES
);
71 ALOGE("NL message creation failed");
79 virtual int handleResponse(WifiEvent
& reply
) {
81 if (reply
.get_cmd() != NL80211_CMD_VENDOR
) {
82 ALOGE("Ignoring reply with cmd = %d", reply
.get_cmd());
86 int id
= reply
.get_vendor_id();
87 int subcmd
= reply
.get_vendor_subcmd();
89 void *data
= reply
.get_vendor_data();
90 int len
= reply
.get_vendor_data_len();
92 memcpy(mCapabilities
, data
, min(len
, (int) sizeof(*mCapabilities
)));
99 wifi_error
wifi_get_gscan_capabilities(wifi_interface_handle handle
,
100 wifi_gscan_capabilities
*capabilities
)
102 GetCapabilitiesCommand
command(handle
, capabilities
);
103 return (wifi_error
) command
.requestResponse();
106 class GetChannelListCommand
: public WifiCommand
108 wifi_channel
*channels
;
113 GetChannelListCommand(wifi_interface_handle iface
, wifi_channel
*channel_buf
, int *ch_num
,
114 int num_max_ch
, int band
)
115 : WifiCommand(iface
, 0), channels(channel_buf
), max_channels(num_max_ch
), num_channels(ch_num
),
118 memset(channels
, 0, sizeof(wifi_channel
) * max_channels
);
120 virtual int create() {
121 int ret
= mMsg
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_GET_VALID_CHANNELS
);
126 nlattr
*data
= mMsg
.attr_start(NL80211_ATTR_VENDOR_DATA
);
127 ret
= mMsg
.put_u32(GSCAN_ATTRIBUTE_BAND
, band
);
138 virtual int handleResponse(WifiEvent
& reply
) {
140 if (reply
.get_cmd() != NL80211_CMD_VENDOR
) {
141 ALOGE("Ignoring reply with cmd = %d", reply
.get_cmd());
145 int id
= reply
.get_vendor_id();
146 int subcmd
= reply
.get_vendor_subcmd();
147 int num_channels_to_copy
= 0;
149 nlattr
*vendor_data
= reply
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
150 int len
= reply
.get_vendor_data_len();
152 if (vendor_data
== NULL
|| len
== 0) {
153 ALOGE("no vendor data in GetChannelList response; ignoring it");
157 for (nl_iterator
it(vendor_data
); it
.has_next(); it
.next()) {
158 if (it
.get_type() == GSCAN_ATTRIBUTE_NUM_CHANNELS
) {
159 num_channels_to_copy
= it
.get_u32();
160 /*ALOGD("Got channel list with %d channels", num_channels_to_copy);*/
161 if(num_channels_to_copy
> max_channels
)
162 num_channels_to_copy
= max_channels
;
163 *num_channels
= num_channels_to_copy
;
164 } else if (it
.get_type() == GSCAN_ATTRIBUTE_CHANNEL_LIST
&& num_channels_to_copy
) {
165 memcpy(channels
, it
.get_data(), sizeof(int) * num_channels_to_copy
);
167 ALOGW("Ignoring invalid attribute type = %d, size = %d",
168 it
.get_type(), it
.get_len());
176 wifi_error
wifi_get_valid_channels(wifi_interface_handle handle
,
177 int band
, int max_channels
, wifi_channel
*channels
, int *num_channels
)
179 GetChannelListCommand
command(handle
, channels
, num_channels
,
181 return (wifi_error
) command
.requestResponse();
183 /////////////////////////////////////////////////////////////////////////////
185 /* helper functions */
187 static int parseScanResults(wifi_scan_result
*results
, int num
, nlattr
*attr
)
189 memset(results
, 0, sizeof(wifi_scan_result
) * num
);
192 for (nl_iterator
it(attr
); it
.has_next() && i
< num
; it
.next(), i
++) {
194 int index
= it
.get_type();
195 nlattr
*sc_data
= (nlattr
*) it
.get_data();
196 wifi_scan_result
*result
= results
+ i
;
198 for (nl_iterator
it2(sc_data
); it2
.has_next(); it2
.next()) {
199 int type
= it2
.get_type();
200 if (type
== GSCAN_ATTRIBUTE_SSID
) {
201 strncpy(result
->ssid
, (char *) it2
.get_data(), it2
.get_len());
202 result
->ssid
[it2
.get_len()] = 0;
203 } else if (type
== GSCAN_ATTRIBUTE_BSSID
) {
204 memcpy(result
->bssid
, (byte
*) it2
.get_data(), sizeof(mac_addr
));
205 } else if (type
== GSCAN_ATTRIBUTE_TIMESTAMP
) {
206 result
->ts
= it2
.get_u64();
207 } else if (type
== GSCAN_ATTRIBUTE_CHANNEL
) {
208 result
->ts
= it2
.get_u16();
209 } else if (type
== GSCAN_ATTRIBUTE_RSSI
) {
210 result
->rssi
= it2
.get_u8();
211 } else if (type
== GSCAN_ATTRIBUTE_RTT
) {
212 result
->rtt
= it2
.get_u64();
213 } else if (type
== GSCAN_ATTRIBUTE_RTTSD
) {
214 result
->rtt_sd
= it2
.get_u64();
221 ALOGE("Got too many results; skipping some");
227 int createFeatureRequest(WifiRequest
& request
, int subcmd
) {
229 int result
= request
.create(GOOGLE_OUI
, subcmd
);
237 class ScanCommand
: public WifiCommand
239 wifi_scan_cmd_params
*mParams
;
240 wifi_scan_result_handler mHandler
;
241 static unsigned mGlobalFullScanBuckets
;
242 bool mLocalFullScanBuckets
;
244 ScanCommand(wifi_interface_handle iface
, int id
, wifi_scan_cmd_params
*params
,
245 wifi_scan_result_handler handler
)
246 : WifiCommand(iface
, id
), mParams(params
), mHandler(handler
),
247 mLocalFullScanBuckets(0)
250 int createSetupRequest(WifiRequest
& request
) {
251 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN
);
256 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
257 result
= request
.put_u32(GSCAN_ATTRIBUTE_BASE_PERIOD
, mParams
->base_period
);
262 result
= request
.put_u32(GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN
, mParams
->max_ap_per_scan
);
267 result
= request
.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD
, mParams
->report_threshold_percent
);
272 result
= request
.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD_NUM_SCANS
, mParams
->report_threshold_num_scans
);
277 result
= request
.put_u32(GSCAN_ATTRIBUTE_NUM_BUCKETS
, mParams
->num_buckets
);
282 for (int i
= 0; i
< mParams
->num_buckets
; i
++) {
283 nlattr
* bucket
= request
.attr_start(i
); // next bucket
284 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_ID
, mParams
->buckets
[i
].bucket
);
288 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_PERIOD
, mParams
->buckets
[i
].period
);
292 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKETS_BAND
,
293 mParams
->buckets
[i
].band
);
298 result
= request
.put_u32(GSCAN_ATTRIBUTE_REPORT_EVENTS
,
299 mParams
->buckets
[i
].report_events
);
304 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS
,
305 mParams
->buckets
[i
].num_channels
);
310 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_EXPONENT
,
311 mParams
->buckets
[i
].base
);
316 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD
,
317 mParams
->buckets
[i
].max_period
);
322 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT
,
323 mParams
->buckets
[i
].step_count
);
328 if (mParams
->buckets
[i
].num_channels
) {
329 nlattr
*channels
= request
.attr_start(GSCAN_ATTRIBUTE_BUCKET_CHANNELS
);
330 for (int j
= 0; j
< mParams
->buckets
[i
].num_channels
; j
++) {
331 result
= request
.put_u32(j
, mParams
->buckets
[i
].channels
[j
].channel
);
336 request
.attr_end(channels
);
339 request
.attr_end(bucket
);
342 request
.attr_end(data
);
346 int createStartRequest(WifiRequest
& request
) {
347 return createFeatureRequest(request
, SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN
);
350 int createStopRequest(WifiRequest
& request
) {
351 return createFeatureRequest(request
, SLSI_NL80211_VENDOR_SUBCMD_DEL_GSCAN
);
355 ALOGD("starting Gscan");
356 WifiRequest
request(familyId(), ifaceId());
357 int result
= createSetupRequest(request
);
358 if (result
!= WIFI_SUCCESS
) {
359 ALOGE("failed to create setup request; result = %d", result
);
363 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE
);
364 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_COMPLETE_SCAN
);
367 for (int i
= 0; i
< mParams
->num_buckets
; i
++) {
368 if (mParams
->buckets
[i
].report_events
== 2) {
374 ALOGI("Full scan requested with nBuckets = %d", nBuckets
);
375 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_FULL_SCAN_RESULTS
);
377 result
= requestResponse(request
);
378 if (result
!= WIFI_SUCCESS
) {
379 ALOGE("failed to start scan; result = %d", result
);
380 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_COMPLETE_SCAN
);
381 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE
);
389 virtual int cancel() {
390 ALOGD("Stopping Gscan");
392 WifiRequest
request(familyId(), ifaceId());
393 int result
= createStopRequest(request
);
394 if (result
!= WIFI_SUCCESS
) {
395 ALOGE("failed to create stop request; result = %d", result
);
397 result
= requestResponse(request
);
398 if (result
!= WIFI_SUCCESS
) {
399 ALOGE("failed to stop scan; result = %d", result
);
403 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_COMPLETE_SCAN
);
404 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE
);
405 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_FULL_SCAN_RESULTS
);
410 virtual int handleResponse(WifiEvent
& reply
) {
411 /* Nothing to do on response! */
415 virtual int handleEvent(WifiEvent
& event
) {
418 nlattr
*vendor_data
= event
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
419 unsigned int len
= event
.get_vendor_data_len();
420 int event_id
= event
.get_vendor_subcmd();
422 if(event_id
== GSCAN_EVENT_COMPLETE_SCAN
) {
423 if (vendor_data
== NULL
|| len
!= 4) {
424 ALOGE("Scan complete type not mentioned!");
427 wifi_scan_event evt_type
;
429 evt_type
= (wifi_scan_event
) event
.get_u32(NL80211_ATTR_VENDOR_DATA
);
430 if(*mHandler
.on_scan_event
)
431 (*mHandler
.on_scan_event
)(evt_type
, evt_type
);
432 } else if(event_id
== GSCAN_EVENT_FULL_SCAN_RESULTS
) {
433 uint32_t bucket_scanned
= 0;
434 wifi_scan_result
*scan_result
= NULL
;
435 for (nl_iterator
it(vendor_data
); it
.has_next(); it
.next()) {
436 if (it
.get_type() == GSCAN_ATTRIBUTE_SCAN_BUCKET_BIT
) {
437 bucket_scanned
= it
.get_u32();
438 } else if (it
.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS
) {
439 if (it
.get_len() >= (int)sizeof(*scan_result
))
440 scan_result
= (wifi_scan_result
*)it
.get_data();
444 if(*mHandler
.on_full_scan_result
)
445 (*mHandler
.on_full_scan_result
)(id(), scan_result
, bucket_scanned
);
447 ALOGD("%-32s\t", scan_result->ssid);
448 ALOGD("%02x:%02x:%02x:%02x:%02x:%02x ", scan_result->bssid[0], scan_result->bssid[1],
449 scan_result->bssid[2], scan_result->bssid[3], scan_result->bssid[4], scan_result->bssid[5]);
450 ALOGD("%d\t", scan_result->rssi);
451 ALOGD("%d\t", scan_result->channel);
452 ALOGD("%lld\t", scan_result->ts);
453 ALOGD("%lld\t", scan_result->rtt);
454 ALOGD("%lld\n", scan_result->rtt_sd);
462 unsigned ScanCommand::mGlobalFullScanBuckets
= 0;
464 wifi_error
wifi_start_gscan(
466 wifi_interface_handle iface
,
467 wifi_scan_cmd_params params
,
468 wifi_scan_result_handler handler
)
470 wifi_handle handle
= getWifiHandle(iface
);
472 ScanCommand
*cmd
= new ScanCommand(iface
, id
, ¶ms
, handler
);
473 wifi_register_cmd(handle
, id
, cmd
);
474 return (wifi_error
)cmd
->start();
477 wifi_error
wifi_stop_gscan(wifi_request_id id
, wifi_interface_handle iface
)
479 wifi_handle handle
= getWifiHandle(iface
);
482 wifi_scan_result_handler handler
;
483 wifi_scan_cmd_params dummy_params
;
484 wifi_handle handle
= getWifiHandle(iface
);
485 memset(&handler
, 0, sizeof(handler
));
487 ScanCommand
*cmd
= new ScanCommand(iface
, id
, &dummy_params
, handler
);
494 WifiCommand
*cmd
= wifi_unregister_cmd(handle
, id
);
501 return WIFI_ERROR_INVALID_ARGS
;
504 class GetScanResultsCommand
: public WifiCommand
{
505 wifi_cached_scan_results
*mScans
;
511 static const int MAX_RESULTS
= 320;
512 wifi_scan_result mScanResults
[MAX_RESULTS
];
515 GetScanResultsCommand(wifi_interface_handle iface
, byte flush
,
516 wifi_cached_scan_results
*results
, int max
, int *num
)
517 : WifiCommand(iface
, -1), mScans(results
), mMax(max
), mNum(num
),
518 mRetrieved(0), mFlush(flush
), mCompleted(0)
520 memset(mScanResults
,0,sizeof(mScanResults
));
524 int createRequest(WifiRequest
& request
, int num
, byte flush
) {
525 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_GET_SCAN_RESULTS
);
530 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
531 result
= request
.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS
, num
);
536 request
.attr_end(data
);
541 WifiRequest
request(familyId(), ifaceId());
543 for (int i
= 0; i
< 10 && mRetrieved
< mMax
; i
++) {
544 int result
= createRequest(request
, (mMax
- mRetrieved
), mFlush
);
546 ALOGE("failed to create request");
550 int prev_retrieved
= mRetrieved
;
552 result
= requestResponse(request
);
554 if (result
!= WIFI_SUCCESS
) {
555 ALOGE("failed to retrieve scan results; result = %d", result
);
559 if (mRetrieved
== prev_retrieved
|| mCompleted
) {
560 /* no more items left to retrieve */
567 ALOGE("GetScanResults read %d results", mRetrieved
);
572 virtual int handleResponse(WifiEvent
& reply
) {
574 if (reply
.get_cmd() != NL80211_CMD_VENDOR
) {
575 ALOGE("Ignoring reply with cmd = %d", reply
.get_cmd());
579 int id
= reply
.get_vendor_id();
580 int subcmd
= reply
.get_vendor_subcmd();
582 nlattr
*vendor_data
= reply
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
583 int len
= reply
.get_vendor_data_len();
585 if (vendor_data
== NULL
|| len
== 0) {
586 ALOGE("no vendor data in GetScanResults response; ignoring it");
590 for (nl_iterator
it(vendor_data
); it
.has_next(); it
.next()) {
591 if (it
.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE
) {
592 mCompleted
= it
.get_u8();
593 //ALOGD("retrieved mCompleted flag : %d", mCompleted);
594 } else if (it
.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS
|| it
.get_type() == 0) {
595 int scan_id
= 0, flags
= 0, num
= 0;
596 for (nl_iterator
it2(it
.get()); it2
.has_next(); it2
.next()) {
597 if (it2
.get_type() == GSCAN_ATTRIBUTE_SCAN_ID
) {
598 scan_id
= it2
.get_u32();
599 //ALOGD("retrieved scan_id : 0x%0x", scan_id);
600 } else if (it2
.get_type() == GSCAN_ATTRIBUTE_SCAN_FLAGS
) {
601 flags
= it2
.get_u8();
602 //ALOGD("retrieved scan_flags : 0x%0x", flags);
603 } else if (it2
.get_type() == GSCAN_ATTRIBUTE_NUM_OF_RESULTS
) {
605 //ALOGD("retrieved num_results: %d", num);
606 } else if (it2
.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS
) {
607 if (mRetrieved
>= mMax
) {
608 ALOGW("Stored %d scans, ignoring excess results", mRetrieved
);
611 num
= it2
.get_len() / sizeof(wifi_scan_result
);
612 num
= min(MAX_RESULTS
- mNextScanResult
, num
);
613 num
= min((int)MAX_AP_CACHE_PER_SCAN
, num
);
614 memcpy(mScanResults
+ mNextScanResult
, it2
.get_data(),
615 sizeof(wifi_scan_result
) * num
);
616 wifi_scan_result
*results
= (wifi_scan_result
*)it2
.get_data();
618 for (int i = 0; i < num; i++) {
619 wifi_scan_result *result = results + i;
620 ALOGD("%02d %-32s %02x:%02x:%02x:%02x:%02x:%02x %04d", i,
621 result->ssid, result->bssid[0], result->bssid[1], result->bssid[2],
622 result->bssid[3], result->bssid[4], result->bssid[5],
625 mScans
[mRetrieved
].scan_id
= scan_id
;
626 mScans
[mRetrieved
].flags
= flags
;
627 mScans
[mRetrieved
].num_results
= num
;
628 //ALOGD("Setting result of scan_id : 0x%0x", mScans[mRetrieved].scan_id);
629 memcpy(mScans
[mRetrieved
].results
,
630 &(mScanResults
[mNextScanResult
]), num
* sizeof(wifi_scan_result
));
631 mNextScanResult
+= num
;
634 ALOGW("Ignoring invalid attribute type = %d, size = %d",
635 it
.get_type(), it
.get_len());
639 ALOGW("Ignoring invalid attribute type = %d, size = %d",
640 it
.get_type(), it
.get_len());
648 wifi_error
wifi_get_cached_gscan_results(wifi_interface_handle iface
, byte flush
,
649 int max
, wifi_cached_scan_results
*results
, int *num
) {
650 GetScanResultsCommand
*cmd
= new GetScanResultsCommand(iface
, flush
, results
, max
, num
);
651 return (wifi_error
)cmd
->execute();
654 /////////////////////////////////////////////////////////////////////////////
656 class BssidHotlistCommand
: public WifiCommand
659 wifi_bssid_hotlist_params mParams
;
660 wifi_hotlist_ap_found_handler mHandler
;
661 static const int MAX_RESULTS
= 64;
662 wifi_scan_result mResults
[MAX_RESULTS
];
664 BssidHotlistCommand(wifi_interface_handle handle
, int id
,
665 wifi_bssid_hotlist_params params
, wifi_hotlist_ap_found_handler handler
)
666 : WifiCommand(handle
, id
), mParams(params
), mHandler(handler
)
668 memset(mResults
, 0, sizeof(mResults
));
671 int createSetupRequest(WifiRequest
& request
) {
672 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_SET_BSSID_HOTLIST
);
677 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
679 result
= request
.put_u32(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE
, mParams
.lost_ap_sample_size
);
684 struct nlattr
* attr
= request
.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS
);
685 for (int i
= 0; i
< mParams
.num_bssid
; i
++) {
686 nlattr
*attr2
= request
.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM
);
688 return WIFI_ERROR_OUT_OF_MEMORY
;
690 result
= request
.put_addr(GSCAN_ATTRIBUTE_BSSID
, mParams
.ap
[i
].bssid
);
694 result
= request
.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH
, mParams
.ap
[i
].high
);
698 result
= request
.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW
, mParams
.ap
[i
].low
);
702 request
.attr_end(attr2
);
705 request
.attr_end(attr
);
706 request
.attr_end(data
);
710 int createTeardownRequest(WifiRequest
& request
) {
711 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_RESET_BSSID_HOTLIST
);
720 WifiRequest
request(familyId(), ifaceId());
721 int result
= createSetupRequest(request
);
726 result
= requestResponse(request
);
728 ALOGE("Failed to execute hotlist setup request, result = %d", result
);
729 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_FOUND
);
730 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_LOST
);
734 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_FOUND
);
735 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_LOST
);
740 virtual int cancel() {
741 /* unregister event handler */
742 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_FOUND
);
743 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_LOST
);
744 /* create set hotlist message with empty hotlist */
745 WifiRequest
request(familyId(), ifaceId());
746 int result
= createTeardownRequest(request
);
751 result
= requestResponse(request
);
759 virtual int handleResponse(WifiEvent
& reply
) {
760 /* Nothing to do on response! */
764 virtual int handleEvent(WifiEvent
& event
) {
765 int event_id
= event
.get_vendor_subcmd();
768 nlattr
*vendor_data
= event
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
769 int len
= event
.get_vendor_data_len();
771 if (vendor_data
== NULL
|| len
== 0) {
772 ALOGE("No scan results found");
777 int num
= len
/ sizeof(wifi_scan_result
);
778 num
= min(MAX_RESULTS
, num
);
779 memcpy(mResults
, event
.get_vendor_data(), num
* sizeof(wifi_scan_result
));
781 if (event_id
== GSCAN_EVENT_HOTLIST_RESULTS_FOUND
) {
782 ALOGD("FOUND %d hotlist APs", num
);
783 if (*mHandler
.on_hotlist_ap_found
)
784 (*mHandler
.on_hotlist_ap_found
)(id(), num
, mResults
);
785 } else if (event_id
== GSCAN_EVENT_HOTLIST_RESULTS_LOST
) {
786 ALOGD("LOST %d hotlist APs", num
);
787 if (*mHandler
.on_hotlist_ap_lost
)
788 (*mHandler
.on_hotlist_ap_lost
)(id(), num
, mResults
);
794 wifi_error
wifi_set_bssid_hotlist(wifi_request_id id
, wifi_interface_handle iface
,
795 wifi_bssid_hotlist_params params
, wifi_hotlist_ap_found_handler handler
)
797 wifi_handle handle
= getWifiHandle(iface
);
799 BssidHotlistCommand
*cmd
= new BssidHotlistCommand(iface
, id
, params
, handler
);
800 wifi_register_cmd(handle
, id
, cmd
);
801 return (wifi_error
)cmd
->start();
804 wifi_error
wifi_reset_bssid_hotlist(wifi_request_id id
, wifi_interface_handle iface
)
806 wifi_handle handle
= getWifiHandle(iface
);
808 WifiCommand
*cmd
= wifi_unregister_cmd(handle
, id
);
815 return WIFI_ERROR_INVALID_ARGS
;
819 /////////////////////////////////////////////////////////////////////////////
821 class SignificantWifiChangeCommand
: public WifiCommand
824 mac_addr bssid
; // BSSID
825 wifi_channel channel
; // channel frequency in MHz
826 int num_rssi
; // number of rssi samples
827 wifi_rssi rssi
[8]; // RSSI history in db
828 } wifi_significant_change_result_internal
;
831 wifi_significant_change_params mParams
;
832 wifi_significant_change_handler mHandler
;
833 static const int MAX_RESULTS
= 64;
834 wifi_significant_change_result_internal mResultsBuffer
[MAX_RESULTS
];
835 wifi_significant_change_result
*mResults
[MAX_RESULTS
];
837 SignificantWifiChangeCommand(wifi_interface_handle handle
, int id
,
838 wifi_significant_change_params params
, wifi_significant_change_handler handler
)
839 : WifiCommand(handle
, id
), mParams(params
), mHandler(handler
)
841 memset(mResultsBuffer
,0,sizeof(mResultsBuffer
));
842 memset(mResults
,0,sizeof(mResults
));
845 int createSetupRequest(WifiRequest
& request
) {
846 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_SET_SIGNIFICANT_CHANGE
);
851 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
853 result
= request
.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE
, mParams
.rssi_sample_size
);
857 result
= request
.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE
, mParams
.lost_ap_sample_size
);
861 result
= request
.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING
, mParams
.min_breaching
);
866 struct nlattr
* attr
= request
.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS
);
868 for (int i
= 0; i
< mParams
.num_bssid
; i
++) {
870 nlattr
*attr2
= request
.attr_start(i
);
872 return WIFI_ERROR_OUT_OF_MEMORY
;
874 result
= request
.put_addr(GSCAN_ATTRIBUTE_BSSID
, mParams
.ap
[i
].bssid
);
878 result
= request
.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH
, mParams
.ap
[i
].high
);
882 result
= request
.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW
, mParams
.ap
[i
].low
);
886 request
.attr_end(attr2
);
889 request
.attr_end(attr
);
890 request
.attr_end(data
);
895 int createTeardownRequest(WifiRequest
& request
) {
896 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_RESET_SIGNIFICANT_CHANGE
);
905 WifiRequest
request(familyId(), ifaceId());
907 int result
= createSetupRequest(request
);
912 result
= requestResponse(request
);
914 ALOGE("failed to set significant wifi change %d", result
);
917 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS
);
922 virtual int cancel() {
923 /* unregister event handler */
924 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS
);
926 /* create set significant change monitor message with empty hotlist */
927 WifiRequest
request(familyId(), ifaceId());
929 int result
= createTeardownRequest(request
);
934 result
= requestResponse(request
);
942 virtual int handleResponse(WifiEvent
& reply
) {
943 /* Nothing to do on response! */
947 virtual int handleEvent(WifiEvent
& event
) {
948 nlattr
*vendor_data
= event
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
949 int len
= event
.get_vendor_data_len();
951 if (vendor_data
== NULL
|| len
== 0) {
952 ALOGE("No scan results found");
959 int16_t rssi_history
[8];
962 int num
= min(len
/ sizeof(ChangeInfo
), MAX_RESULTS
);
963 ChangeInfo
*ci
= (ChangeInfo
*)event
.get_vendor_data();
965 for (int i
= 0; i
< num
; i
++) {
966 memcpy(mResultsBuffer
[i
].bssid
, ci
[i
].bssid
, sizeof(mac_addr
));
967 mResultsBuffer
[i
].channel
= ci
[i
].channel
;
968 /* Driver sends N samples and the rest 8-N are filled 0x7FFF
969 * N = no of rssi samples to average sent in significant change request. */
971 for (int j
= 0; j
< 8; j
++) {
972 if (ci
[i
].rssi_history
[j
] == 0x7FFF) {
976 mResultsBuffer
[i
].rssi
[j
] = (int) ci
[i
].rssi_history
[j
];
978 mResultsBuffer
[i
].num_rssi
= num_rssi
;
979 mResults
[i
] = reinterpret_cast<wifi_significant_change_result
*>(&(mResultsBuffer
[i
]));
983 (*mHandler
.on_significant_change
)(id(), num
, mResults
);
985 ALOGW("No significant change reported");
992 wifi_error
wifi_set_significant_change_handler(wifi_request_id id
, wifi_interface_handle iface
,
993 wifi_significant_change_params params
, wifi_significant_change_handler handler
)
995 wifi_handle handle
= getWifiHandle(iface
);
997 SignificantWifiChangeCommand
*cmd
= new SignificantWifiChangeCommand(
998 iface
, id
, params
, handler
);
999 wifi_register_cmd(handle
, id
, cmd
);
1000 return (wifi_error
)cmd
->start();
1003 wifi_error
wifi_reset_significant_change_handler(wifi_request_id id
, wifi_interface_handle iface
)
1005 wifi_handle handle
= getWifiHandle(iface
);
1007 WifiCommand
*cmd
= wifi_unregister_cmd(handle
, id
);
1011 return WIFI_SUCCESS
;
1014 return WIFI_ERROR_INVALID_ARGS
;
1017 class ePNOCommand
: public WifiCommand
1020 wifi_epno_params
*epno_params
;
1021 wifi_epno_handler mHandler
;
1022 wifi_scan_result mResults
;
1024 ePNOCommand(wifi_interface_handle handle
, int id
,
1025 wifi_epno_params
*params
, wifi_epno_handler handler
)
1026 : WifiCommand(handle
, id
), mHandler(handler
)
1028 epno_params
= params
;
1029 memset(&mResults
,0,sizeof(wifi_scan_result
));
1032 int createSetupRequest(WifiRequest
& request
) {
1033 int result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_SET_EPNO_LIST
);
1038 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
1039 if (epno_params
== NULL
) {
1040 result
= request
.put_u8(EPNO_ATTRIBUTE_SSID_NUM
, 0);
1044 request
.attr_end(data
);
1047 result
= request
.put_u16(EPNO_ATTRIBUTE_MINIMUM_5G_RSSI
, epno_params
->min5GHz_rssi
);
1051 result
= request
.put_u16(EPNO_ATTRIBUTE_MINIMUM_2G_RSSI
, epno_params
->min24GHz_rssi
);
1055 result
= request
.put_u16(EPNO_ATTRIBUTE_INITIAL_SCORE_MAX
, epno_params
->initial_score_max
);
1059 result
= request
.put_u8(EPNO_ATTRIBUTE_CUR_CONN_BONUS
, epno_params
->current_connection_bonus
);
1063 result
= request
.put_u8(EPNO_ATTRIBUTE_SAME_NETWORK_BONUS
, epno_params
->same_network_bonus
);
1067 result
= request
.put_u8(EPNO_ATTRIBUTE_SECURE_BONUS
, epno_params
->secure_bonus
);
1071 result
= request
.put_u8(EPNO_ATTRIBUTE_5G_BONUS
, epno_params
->band5GHz_bonus
);
1075 result
= request
.put_u8(EPNO_ATTRIBUTE_SSID_NUM
, epno_params
->num_networks
);
1080 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]",
1081 epno_params
->min5GHz_rssi
,
1082 epno_params
->min24GHz_rssi
,
1083 epno_params
->initial_score_max
,
1084 epno_params
->current_connection_bonus
,
1085 epno_params
->same_network_bonus
,
1086 epno_params
->secure_bonus
,
1087 epno_params
->band5GHz_bonus
,
1088 epno_params
->num_networks
);
1090 struct nlattr
* attr
= request
.attr_start(EPNO_ATTRIBUTE_SSID_LIST
);
1091 for (int i
= 0; i
< epno_params
->num_networks
; i
++) {
1092 nlattr
*attr2
= request
.attr_start(i
);
1093 if (attr2
== NULL
) {
1094 return WIFI_ERROR_OUT_OF_MEMORY
;
1096 result
= request
.put_u16(EPNO_ATTRIBUTE_FLAGS
, epno_params
->networks
[i
].flags
);
1100 result
= request
.put_u8(EPNO_ATTRIBUTE_AUTH
, epno_params
->networks
[i
].auth_bit_field
);
1104 result
= request
.put_u8(EPNO_ATTRIBUTE_SSID_LEN
, strlen(epno_params
->networks
[i
].ssid
));
1108 result
= request
.put(EPNO_ATTRIBUTE_SSID
, epno_params
->networks
[i
].ssid
, strlen(epno_params
->networks
[i
].ssid
));
1112 request
.attr_end(attr2
);
1115 request
.attr_end(attr
);
1116 request
.attr_end(data
);
1121 ALOGI("ePNO num_network=%d", epno_params
? epno_params
->num_networks
: 0);
1122 WifiRequest
request(familyId(), ifaceId());
1123 int result
= createSetupRequest(request
);
1128 result
= requestResponse(request
);
1130 ALOGI("Failed: ePNO setup request, result = %d", result
);
1131 unregisterVendorHandler(GOOGLE_OUI
, WIFI_EPNO_EVENT
);
1136 registerVendorHandler(GOOGLE_OUI
, WIFI_EPNO_EVENT
);
1141 virtual int cancel() {
1142 /* unregister event handler */
1143 unregisterVendorHandler(GOOGLE_OUI
, WIFI_EPNO_EVENT
);
1147 virtual int handleResponse(WifiEvent
& reply
) {
1148 /* Nothing to do on response! */
1152 virtual int handleEvent(WifiEvent
& event
) {
1153 int event_id
= event
.get_vendor_subcmd();
1156 nlattr
*vendor_data
= event
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
1157 int len
= event
.get_vendor_data_len();
1159 if (vendor_data
== NULL
|| len
== 0) {
1160 ALOGI("No scan results found");
1165 mResults
= *(wifi_scan_result
*) event
.get_vendor_data();
1166 if (*mHandler
.on_network_found
)
1167 (*mHandler
.on_network_found
)(id(), 1, &mResults
);
1172 wifi_error
wifi_set_epno_list(wifi_request_id id
,
1173 wifi_interface_handle iface
,
1174 const wifi_epno_params
*epno_params
,
1175 wifi_epno_handler handler
)
1177 wifi_handle handle
= getWifiHandle(iface
);
1178 ePNOCommand
*cmd
= new ePNOCommand(iface
, id
, (wifi_epno_params
*)epno_params
, handler
);
1179 wifi_register_cmd(handle
, id
, cmd
);
1180 wifi_error result
= (wifi_error
)cmd
->start();
1181 if (result
!= WIFI_SUCCESS
) {
1182 wifi_unregister_cmd(handle
, id
);
1187 wifi_error
wifi_reset_epno_list(wifi_request_id id
, wifi_interface_handle iface
)
1189 wifi_handle handle
= getWifiHandle(iface
);
1190 wifi_epno_handler handler
;
1192 handler
.on_network_found
= NULL
;
1193 ePNOCommand
*cmd
= new ePNOCommand(iface
, id
, NULL
, handler
);
1194 wifi_register_cmd(handle
, id
, cmd
);
1195 wifi_error result
= (wifi_error
)cmd
->start();
1196 if (result
!= WIFI_SUCCESS
) {
1197 wifi_unregister_cmd(handle
, id
);
1202 class HsListCommand
: public WifiCommand
1205 wifi_passpoint_network
*mNetworks
;
1206 wifi_passpoint_event_handler mHandler
;
1208 HsListCommand(wifi_request_id id
, wifi_interface_handle iface
,
1209 int num
, wifi_passpoint_network
*hs_list
, wifi_passpoint_event_handler handler
)
1210 : WifiCommand(iface
, id
), num_hs(num
), mNetworks(hs_list
),
1215 HsListCommand(wifi_request_id id
, wifi_interface_handle iface
,
1217 : WifiCommand(iface
, id
), num_hs(num
), mNetworks(NULL
)
1219 mHandler
.on_passpoint_network_found
= NULL
;
1222 int createRequest(WifiRequest
& request
, int val
) {
1226 result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_SET_HS_LIST
);
1227 result
= request
.put_u32(EPNO_ATTRIBUTE_HS_NUM
, num_hs
);
1231 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
1233 struct nlattr
* attr
= request
.attr_start(EPNO_ATTRIBUTE_HS_PARAM_LIST
);
1234 for (int i
= 0; i
< num_hs
; i
++) {
1235 nlattr
*attr2
= request
.attr_start(i
);
1236 if (attr2
== NULL
) {
1237 return WIFI_ERROR_OUT_OF_MEMORY
;
1239 result
= request
.put_u32(EPNO_ATTRIBUTE_HS_ID
, mNetworks
[i
].id
);
1243 result
= request
.put(EPNO_ATTRIBUTE_HS_REALM
, mNetworks
[i
].realm
, 256);
1247 result
= request
.put(EPNO_ATTRIBUTE_HS_CONSORTIUM_IDS
, mNetworks
[i
].roamingConsortiumIds
, 128);
1251 result
= request
.put(EPNO_ATTRIBUTE_HS_PLMN
, mNetworks
[i
].plmn
, 3);
1255 request
.attr_end(attr2
);
1257 request
.attr_end(attr
);
1258 request
.attr_end(data
);
1260 result
= request
.create(GOOGLE_OUI
, SLSI_NL80211_VENDOR_SUBCMD_RESET_HS_LIST
);
1266 return WIFI_SUCCESS
;
1271 WifiRequest
request(familyId(), ifaceId());
1272 int result
= createRequest(request
, num_hs
);
1273 if (result
!= WIFI_SUCCESS
) {
1274 ALOGE("failed to create request; result = %d", result
);
1278 registerVendorHandler(GOOGLE_OUI
, WIFI_HOTSPOT_MATCH
);
1280 result
= requestResponse(request
);
1281 if (result
!= WIFI_SUCCESS
) {
1282 ALOGE("failed to set ANQPO networks; result = %d", result
);
1283 unregisterVendorHandler(GOOGLE_OUI
, WIFI_HOTSPOT_MATCH
);
1290 virtual int cancel() {
1292 WifiRequest
request(familyId(), ifaceId());
1293 int result
= createRequest(request
, 0);
1294 if (result
!= WIFI_SUCCESS
) {
1295 ALOGE("failed to create request; result = %d", result
);
1297 result
= requestResponse(request
);
1298 if (result
!= WIFI_SUCCESS
) {
1299 ALOGE("failed to reset ANQPO networks;result = %d", result
);
1303 unregisterVendorHandler(GOOGLE_OUI
, WIFI_HOTSPOT_MATCH
);
1304 return WIFI_SUCCESS
;
1307 virtual int handleResponse(WifiEvent
& reply
) {
1308 /* Nothing to do on response! */
1312 virtual int handleEvent(WifiEvent
& event
) {
1313 nlattr
*vendor_data
= event
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
1314 unsigned int len
= event
.get_vendor_data_len();
1315 if (vendor_data
== NULL
|| len
< sizeof(wifi_scan_result
)) {
1316 ALOGE("ERROR: No scan results found");
1320 wifi_scan_result
*result
= (wifi_scan_result
*)event
.get_vendor_data();
1321 byte
*anqp
= (byte
*)result
+ offsetof(wifi_scan_result
, ie_data
) + result
->ie_length
;
1322 int networkId
= *(int *)anqp
;
1323 anqp
+= sizeof(int);
1324 int anqp_len
= *(u16
*)anqp
;
1325 anqp
+= sizeof(u16
);
1327 if(*mHandler
.on_passpoint_network_found
)
1328 (*mHandler
.on_passpoint_network_found
)(id(), networkId
, result
, anqp_len
, anqp
);
1334 wifi_error
wifi_set_passpoint_list(wifi_request_id id
, wifi_interface_handle iface
, int num
,
1335 wifi_passpoint_network
*networks
, wifi_passpoint_event_handler handler
)
1337 wifi_handle handle
= getWifiHandle(iface
);
1338 HsListCommand
*cmd
= new HsListCommand(id
, iface
, num
, networks
, handler
);
1340 wifi_register_cmd(handle
, id
, cmd
);
1341 wifi_error result
= (wifi_error
)cmd
->start();
1342 if (result
!= WIFI_SUCCESS
) {
1343 wifi_unregister_cmd(handle
, id
);
1348 wifi_error
wifi_reset_passpoint_list(wifi_request_id id
, wifi_interface_handle iface
)
1350 wifi_handle handle
= getWifiHandle(iface
);
1352 HsListCommand
*cmd
= (HsListCommand
*)(wifi_get_cmd(handle
, id
));
1355 cmd
= new HsListCommand(id
, iface
, 0);
1356 wifi_register_cmd(handle
, id
, cmd
);
1358 result
= (wifi_error
)cmd
->cancel();
1359 wifi_unregister_cmd(handle
, id
);