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"
30 GSCAN_ATTRIBUTE_CAPABILITIES
= 1,
32 GSCAN_ATTRIBUTE_NUM_BUCKETS
= 10,
33 GSCAN_ATTRIBUTE_BASE_PERIOD
,
34 GSCAN_ATTRIBUTE_BUCKETS_BAND
,
35 GSCAN_ATTRIBUTE_BUCKET_ID
,
36 GSCAN_ATTRIBUTE_BUCKET_PERIOD
,
37 GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS
,
38 GSCAN_ATTRIBUTE_BUCKET_CHANNELS
,
39 GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN
,
40 GSCAN_ATTRIBUTE_REPORT_THRESHOLD
,
41 GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE
,
43 GSCAN_ATTRIBUTE_ENABLE_FEATURE
= 20,
44 GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE
, /* indicates no more results */
45 GSCAN_ATTRIBUTE_FLUSH_FEATURE
, /* Flush all the configs */
46 GSCAN_ENABLE_FULL_SCAN_RESULTS
,
47 GSCAN_ATTRIBUTE_REPORT_EVENTS
,
48 /* Adaptive scan attributes */
49 GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT
,
50 GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD
,
52 GSCAN_ATTRIBUTE_NUM_OF_RESULTS
= 30,
53 GSCAN_ATTRIBUTE_FLUSH_RESULTS
,
54 GSCAN_ATTRIBUTE_SCAN_RESULTS
, /* flat array of wifi_scan_result */
55 GSCAN_ATTRIBUTE_SCAN_ID
, /* indicates scan number */
56 GSCAN_ATTRIBUTE_SCAN_FLAGS
, /* indicates if scan was aborted */
57 GSCAN_ATTRIBUTE_AP_FLAGS
, /* flags on significant change event */
58 GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK
,
60 GSCAN_ATTRIBUTE_SSID
= 40,
61 GSCAN_ATTRIBUTE_BSSID
,
62 GSCAN_ATTRIBUTE_CHANNEL
,
64 GSCAN_ATTRIBUTE_TIMESTAMP
,
66 GSCAN_ATTRIBUTE_RTTSD
,
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
,
74 GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE
= 60,
75 GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE
,
76 GSCAN_ATTRIBUTE_MIN_BREACHING
,
77 GSCAN_ATTRIBUTE_NUM_AP
, /* TBD */
78 GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS
,
79 GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH
,
82 GSCAN_ATTRIBUTE_EPNO_SSID_LIST
= 70,
83 GSCAN_ATTRIBUTE_EPNO_SSID
,
84 GSCAN_ATTRIBUTE_EPNO_SSID_LEN
,
85 GSCAN_ATTRIBUTE_EPNO_RSSI
,
86 GSCAN_ATTRIBUTE_EPNO_FLAGS
,
87 GSCAN_ATTRIBUTE_EPNO_AUTH
,
88 GSCAN_ATTRIBUTE_EPNO_SSID_NUM
,
89 GSCAN_ATTRIBUTE_EPNO_FLUSH
,
91 GSCAN_ATTRIBUTE_WHITELIST_SSID
= 80,
92 GSCAN_ATTRIBUTE_NUM_WL_SSID
,
93 GSCAN_ATTRIBUTE_WL_SSID_LEN
,
94 GSCAN_ATTRIBUTE_WL_SSID_FLUSH
,
95 GSCAN_ATTRIBUTE_WHITELIST_SSID_ELEM
,
96 GSCAN_ATTRIBUTE_NUM_BSSID
,
97 GSCAN_ATTRIBUTE_BSSID_PREF_LIST
,
98 GSCAN_ATTRIBUTE_BSSID_PREF_FLUSH
,
99 GSCAN_ATTRIBUTE_BSSID_PREF
,
100 GSCAN_ATTRIBUTE_RSSI_MODIFIER
,
102 GSCAN_ATTRIBUTE_A_BAND_BOOST_THRESHOLD
= 90,
103 GSCAN_ATTRIBUTE_A_BAND_PENALTY_THRESHOLD
,
104 GSCAN_ATTRIBUTE_A_BAND_BOOST_FACTOR
,
105 GSCAN_ATTRIBUTE_A_BAND_PENALTY_FACTOR
,
106 GSCAN_ATTRIBUTE_A_BAND_MAX_BOOST
,
107 GSCAN_ATTRIBUTE_LAZY_ROAM_HYSTERESIS
,
108 GSCAN_ATTRIBUTE_ALERT_ROAM_RSSI_TRIGGER
,
109 GSCAN_ATTRIBUTE_LAZY_ROAM_ENABLE
,
111 /* BSSID blacklist */
112 GSCAN_ATTRIBUTE_BSSID_BLACKLIST_FLUSH
= 100,
113 GSCAN_ATTRIBUTE_BLACKLIST_BSSID
,
116 GSCAN_ATTRIBUTE_ANQPO_HS_LIST
= 110,
117 GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE
,
118 GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID
,
119 GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM
,
120 GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID
,
121 GSCAN_ATTRIBUTE_ANQPO_HS_PLMN
,
124 GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR
= 130,
125 GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR
,
126 GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX
,
127 GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS
,
128 GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS
,
129 GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS
,
130 GSCAN_ATTRIBUTE_EPNO_5G_BONUS
,
137 wifi_error
wifi_enable_full_scan_results(wifi_request_id id
, wifi_interface_handle iface
,
138 wifi_scan_result_handler handler
);
139 wifi_error
wifi_disable_full_scan_results(wifi_request_id id
, wifi_interface_handle iface
);
140 int wifi_handle_full_scan_event(wifi_request_id id
, WifiEvent
& event
,
141 wifi_scan_result_handler handler
);
142 void convert_to_hal_result(wifi_scan_result
*to
, wifi_gscan_result_t
*from
);
145 void convert_to_hal_result(wifi_scan_result
*to
, wifi_gscan_result_t
*from
)
148 to
->channel
= from
->channel
;
149 to
->rssi
= from
->rssi
;
151 to
->rtt_sd
= from
->rtt_sd
;
152 to
->beacon_period
= from
->beacon_period
;
153 to
->capability
= from
->capability
;
154 memcpy(to
->ssid
, from
->ssid
, (DOT11_MAX_SSID_LEN
+1));
155 memcpy(&to
->bssid
, &from
->bssid
, sizeof(mac_addr
));
158 /////////////////////////////////////////////////////////////////////////////
160 class GetCapabilitiesCommand
: public WifiCommand
162 wifi_gscan_capabilities
*mCapabilities
;
164 GetCapabilitiesCommand(wifi_interface_handle iface
, wifi_gscan_capabilities
*capabitlites
)
165 : WifiCommand("GetCapabilitiesCommand", iface
, 0), mCapabilities(capabitlites
)
167 memset(mCapabilities
, 0, sizeof(*mCapabilities
));
170 virtual int create() {
171 ALOGD("[WIFI HAL]Creating message to get gscan capablities; handle=%p, iface=%d, ifname=%s",
172 mIfaceInfo
->handle
, mIfaceInfo
->id
, mIfaceInfo
->name
);
174 int ret
= mMsg
.create(GOOGLE_OUI
, GSCAN_SUBCMD_GET_CAPABILITIES
);
183 virtual int handleResponse(WifiEvent
& reply
) {
185 ALOGV("In GetCapabilities::handleResponse");
187 if (reply
.get_cmd() != NL80211_CMD_VENDOR
) {
188 ALOGE("Ignoring reply with cmd = %d", reply
.get_cmd());
192 int id
= reply
.get_vendor_id();
193 int subcmd
= reply
.get_vendor_subcmd();
194 int wiphy_id
= reply
.get_u32(NL80211_ATTR_WIPHY
);
195 int if_id
= reply
.get_u32(NL80211_ATTR_IFINDEX
);
197 struct nlattr
*vendor_data
= (struct nlattr
*)reply
.get_vendor_data();
198 int len
= reply
.get_vendor_data_len();
199 void *payload
= NULL
;
200 if (vendor_data
->nla_type
== GSCAN_ATTRIBUTE_CAPABILITIES
) {
201 payload
= nla_data(vendor_data
);
205 ALOGD("wiphy_id=%d, if_id=%d, Id=%0x, subcmd=%d, len=%d, expected len=%d",
206 wiphy_id
, if_id
, id
, subcmd
, len
, sizeof(*mCapabilities
));
208 memcpy(mCapabilities
, payload
, min(len
, (int) sizeof(*mCapabilities
)));
210 ALOGI("max_scan_cache_size=%d, %d, %d, %d, %d, %d, %d, %d, max_bssid_history_entries=%d",
211 mCapabilities
->max_scan_cache_size
, mCapabilities
->max_scan_buckets
,
212 mCapabilities
->max_ap_cache_per_scan
,
213 mCapabilities
->max_rssi_sample_size
,
214 mCapabilities
->max_scan_reporting_threshold
,
215 mCapabilities
->max_hotlist_bssids
,
216 mCapabilities
->max_hotlist_ssids
,
217 mCapabilities
->max_significant_wifi_change_aps
,
218 mCapabilities
->max_bssid_history_entries
);
220 /* this case wifi driver don't support GScan */
221 if (!(mCapabilities
->max_scan_cache_size
|| mCapabilities
->max_scan_buckets
222 || mCapabilities
->max_ap_cache_per_scan
))
229 wifi_error
wifi_get_gscan_capabilities(wifi_interface_handle handle
,
230 wifi_gscan_capabilities
*capabilities
)
232 GetCapabilitiesCommand
command(handle
, capabilities
);
233 return (wifi_error
) command
.requestResponse();
236 class GetChannelListCommand
: public WifiCommand
239 wifi_channel
*mChannels
;
245 GetChannelListCommand(wifi_interface_handle handle
, int band
, int max_channels
,
246 wifi_channel
*channels
, int *num_channels
)
247 : WifiCommand("GetChannelListCommand", handle
, 0)
250 mMaxChannels
= max_channels
;
251 mChannels
= channels
;
252 mNumOfChannel
= num_channels
;
253 memset(mChannels
, 0, sizeof(wifi_channel
) * mMaxChannels
);
256 virtual int create() {
257 ALOGV("Creating message to get channel list; iface = %d", mIfaceInfo
->id
);
259 int ret
= mMsg
.create(GOOGLE_OUI
, WIFI_SUBCMD_GET_CHANNEL_LIST
);
264 ALOGI("In GetChannelList::mBand=%d", mBand
);
266 nlattr
*data
= mMsg
.attr_start(NL80211_ATTR_VENDOR_DATA
);
267 ret
= mMsg
.put_u32(WIFI_ATTRIBUTE_BAND
, mBand
);
277 virtual int handleResponse(WifiEvent
& reply
) {
279 ALOGV("In GetChannelList::handleResponse");
281 if (reply
.get_cmd() != NL80211_CMD_VENDOR
) {
282 ALOGE("Ignore reply with cmd 0x%x", reply
.get_cmd());
286 int vendor_id
= reply
.get_vendor_id();
287 int subcmd
= reply
.get_vendor_subcmd();
288 ALOGV("vendor_id = 0x%x, subcmd = 0x%x", vendor_id
, subcmd
);
290 nlattr
*vendor
= reply
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
291 int len
= reply
.get_vendor_data_len();
292 if (vendor
== NULL
|| len
== 0) {
293 ALOGE("No vendor data in GetChannelList response, ignore it");
297 int num_channels
= 0;
298 for (nl_iterator
it(vendor
); it
.has_next(); it
.next()) {
299 if (it
.get_type() == WIFI_ATTRIBUTE_NUM_CHANNELS
) {
300 num_channels
= it
.get_u32();
301 ALOGI("Get channel list with %d channels", num_channels
);
302 if (num_channels
> mMaxChannels
)
303 num_channels
= mMaxChannels
;
304 *mNumOfChannel
= num_channels
;
305 } else if (it
.get_type() == WIFI_ATTRIBUTE_CHANNEL_LIST
&& num_channels
) {
306 memcpy(mChannels
, it
.get_data(), sizeof(wifi_channel
) * num_channels
);
308 ALOGW("Ignore invalid attribute type = %d, size = %d",
309 it
.get_type(), it
.get_len());
313 ALOGD("mChannels[0]=%d mChannels[1]=%d", *mChannels
, *(mChannels
+ 1));
319 wifi_error
wifi_get_valid_channels(wifi_interface_handle handle
,
320 int band
, int max_channels
, wifi_channel
*channels
, int *num_channels
)
322 GetChannelListCommand
command(handle
, band
, max_channels
, channels
, num_channels
);
323 return (wifi_error
) command
.requestResponse();
326 /////////////////////////////////////////////////////////////////////////////
328 /* helper functions */
330 static int parseScanResults(wifi_scan_result
*results
, int num
, nlattr
*attr
)
332 memset(results
, 0, sizeof(wifi_scan_result
) * num
);
335 for (nl_iterator
it(attr
); it
.has_next() && i
< num
; it
.next(), i
++) {
337 int index
= it
.get_type();
338 ALOGI("retrieved scan result %d", index
);
339 nlattr
*sc_data
= (nlattr
*) it
.get_data();
340 wifi_scan_result
*result
= results
+ i
;
342 for (nl_iterator
it2(sc_data
); it2
.has_next(); it2
.next()) {
343 int type
= it2
.get_type();
344 if (type
== GSCAN_ATTRIBUTE_SSID
) {
345 strncpy(result
->ssid
, (char *) it2
.get_data(), it2
.get_len());
346 result
->ssid
[it2
.get_len()] = 0;
347 } else if (type
== GSCAN_ATTRIBUTE_BSSID
) {
348 memcpy(result
->bssid
, (byte
*) it2
.get_data(), sizeof(mac_addr
));
349 } else if (type
== GSCAN_ATTRIBUTE_TIMESTAMP
) {
350 result
->ts
= it2
.get_u64();
351 } else if (type
== GSCAN_ATTRIBUTE_CHANNEL
) {
352 result
->ts
= it2
.get_u16();
353 } else if (type
== GSCAN_ATTRIBUTE_RSSI
) {
354 result
->rssi
= it2
.get_u8();
355 } else if (type
== GSCAN_ATTRIBUTE_RTT
) {
356 result
->rtt
= it2
.get_u64();
357 } else if (type
== GSCAN_ATTRIBUTE_RTTSD
) {
358 result
->rtt_sd
= it2
.get_u64();
365 ALOGE("Got too many results; skipping some");
371 int createFeatureRequest(WifiRequest
& request
, int subcmd
, int enable
) {
373 int result
= request
.create(GOOGLE_OUI
, subcmd
);
378 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
379 result
= request
.put_u32(GSCAN_ATTRIBUTE_ENABLE_FEATURE
, enable
);
384 request
.attr_end(data
);
388 /////////////////////////////////////////////////////////////////////////////
389 class FullScanResultsCommand
: public WifiCommand
392 wifi_scan_result_handler mHandler
;
394 FullScanResultsCommand(wifi_interface_handle iface
, int id
, int *params
,
395 wifi_scan_result_handler handler
)
396 : WifiCommand("FullScanResultsCommand", iface
, id
), mParams(params
), mHandler(handler
)
399 int createRequest(WifiRequest
& request
, int subcmd
, int enable
) {
400 int result
= request
.create(GOOGLE_OUI
, subcmd
);
405 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
406 result
= request
.put_u32(GSCAN_ENABLE_FULL_SCAN_RESULTS
, enable
);
411 request
.attr_end(data
);
417 ALOGD("Enabling Full scan results");
418 WifiRequest
request(familyId(), ifaceId());
419 int result
= createRequest(request
, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS
, 1);
420 if (result
!= WIFI_SUCCESS
) {
421 ALOGE("failed to create request; result = %d", result
);
425 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_FULL_SCAN_RESULTS
);
427 result
= requestResponse(request
);
428 if (result
!= WIFI_SUCCESS
) {
429 ALOGE("failed to enable full scan results; result = %d", result
);
430 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_FULL_SCAN_RESULTS
);
437 virtual int cancel() {
438 ALOGD("Disabling Full scan results");
440 WifiRequest
request(familyId(), ifaceId());
441 int result
= createRequest(request
, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS
, 0);
442 if (result
!= WIFI_SUCCESS
) {
443 ALOGE("failed to create request; result = %d", result
);
445 result
= requestResponse(request
);
446 if (result
!= WIFI_SUCCESS
) {
447 ALOGE("failed to disable full scan results;result = %d", result
);
451 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_FULL_SCAN_RESULTS
);
455 virtual int handleResponse(WifiEvent
& reply
) {
456 ALOGD("Request complete!");
457 /* Nothing to do on response! */
461 virtual int handleEvent(WifiEvent
& event
) {
462 ALOGV("Full scan results: Got an event");
463 return wifi_handle_full_scan_event(id(), event
, mHandler
);
467 /////////////////////////////////////////////////////////////////////////////
469 class ScanCommand
: public WifiCommand
471 wifi_scan_cmd_params
*mParams
;
472 wifi_scan_result_handler mHandler
;
474 ScanCommand(wifi_interface_handle iface
, int id
, wifi_scan_cmd_params
*params
,
475 wifi_scan_result_handler handler
)
476 : WifiCommand("ScanCommand", iface
, id
), mParams(params
), mHandler(handler
)
479 int createSetupRequest(WifiRequest
& request
) {
480 int result
= request
.create(GOOGLE_OUI
, GSCAN_SUBCMD_SET_CONFIG
);
485 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
486 result
= request
.put_u32(GSCAN_ATTRIBUTE_BASE_PERIOD
, mParams
->base_period
);
491 result
= request
.put_u32(GSCAN_ATTRIBUTE_NUM_BUCKETS
, mParams
->num_buckets
);
496 for (int i
= 0; i
< mParams
->num_buckets
; i
++) {
497 nlattr
* bucket
= request
.attr_start(i
); // next bucket
498 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_ID
, mParams
->buckets
[i
].bucket
);
502 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_PERIOD
, mParams
->buckets
[i
].period
);
507 /* parameter validity check */
508 if (mParams
->buckets
[i
].band
< WIFI_BAND_UNSPECIFIED
509 || mParams
->buckets
[i
].band
> WIFI_BAND_ABG_WITH_DFS
)
510 mParams
->buckets
[i
].band
= WIFI_BAND_ABG
; /* default 2.4G + 5G */
511 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKETS_BAND
,
512 mParams
->buckets
[i
].band
);
516 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT
,
517 mParams
->buckets
[i
].step_count
);
521 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD
,
522 mParams
->buckets
[i
].max_period
);
526 result
= request
.put_u32(GSCAN_ATTRIBUTE_REPORT_EVENTS
,
527 mParams
->buckets
[i
].report_events
);
532 result
= request
.put_u32(GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS
,
533 mParams
->buckets
[i
].num_channels
);
538 if (mParams
->buckets
[i
].num_channels
) {
539 nlattr
*channels
= request
.attr_start(GSCAN_ATTRIBUTE_BUCKET_CHANNELS
);
540 ALOGV(" channels: ");
541 for (int j
= 0; j
< mParams
->buckets
[i
].num_channels
; j
++) {
542 result
= request
.put_u32(j
, mParams
->buckets
[i
].channels
[j
].channel
);
543 ALOGV(" %u", mParams
->buckets
[i
].channels
[j
].channel
);
549 request
.attr_end(channels
);
552 request
.attr_end(bucket
);
555 request
.attr_end(data
);
559 int createScanConfigRequest(WifiRequest
& request
) {
560 int result
= request
.create(GOOGLE_OUI
, GSCAN_SUBCMD_SET_SCAN_CONFIG
);
565 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
566 result
= request
.put_u32(GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN
, mParams
->max_ap_per_scan
);
571 /* parameter validity check */
572 if (mParams
->report_threshold_percent
< 0 || mParams
->report_threshold_percent
> 100)
573 mParams
->report_threshold_percent
= 100;
574 result
= request
.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD
,
575 mParams
->report_threshold_percent
);
580 int num_scans
= mParams
->report_threshold_num_scans
;
582 result
= request
.put_u32(GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE
, num_scans
);
587 request
.attr_end(data
);
591 int createStartRequest(WifiRequest
& request
) {
592 return createFeatureRequest(request
, GSCAN_SUBCMD_ENABLE_GSCAN
, 1);
595 int createStopRequest(WifiRequest
& request
) {
596 return createFeatureRequest(request
, GSCAN_SUBCMD_ENABLE_GSCAN
, 0);
600 ALOGI("1) GScan Setting configuration: ");
601 WifiRequest
request(familyId(), ifaceId());
602 int result
= createSetupRequest(request
);
603 if (result
!= WIFI_SUCCESS
) {
604 ALOGE("failed to create setup request; result = %d", result
);
608 result
= requestResponse(request
);
609 if (result
!= WIFI_SUCCESS
) {
610 ALOGE("failed to configure setup; result = %d", result
);
616 result
= createScanConfigRequest(request
);
617 if (result
!= WIFI_SUCCESS
) {
618 ALOGE("failed to create scan config request; result = %d", result
);
622 result
= requestResponse(request
);
623 if (result
!= WIFI_SUCCESS
) {
624 ALOGE("failed to configure scan; result = %d", result
);
628 ALOGI("2) Enable GScan: ");
630 result
= createStartRequest(request
);
631 if (result
!= WIFI_SUCCESS
) {
632 ALOGE("failed to create start request; result = %d", result
);
636 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE
);
637 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_COMPLETE_SCAN
);
638 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_FULL_SCAN_RESULTS
);
640 result
= requestResponse(request
);
641 if (result
!= WIFI_SUCCESS
) {
642 ALOGE("failed to start scan; result = %d", result
);
643 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_COMPLETE_SCAN
);
644 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE
);
645 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_FULL_SCAN_RESULTS
);
651 virtual int cancel() {
652 ALOGI("Stopping GScan");
654 WifiRequest
request(familyId(), ifaceId());
655 int result
= createStopRequest(request
);
656 if (result
!= WIFI_SUCCESS
) {
657 ALOGE("failed to create stop request; result = %d", result
);
659 result
= requestResponse(request
);
660 if (result
!= WIFI_SUCCESS
) {
661 ALOGE("failed to stop scan; result = %d", result
);
665 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_COMPLETE_SCAN
);
666 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE
);
667 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_FULL_SCAN_RESULTS
);
671 virtual int handleResponse(WifiEvent
& reply
) {
672 /* Nothing to do on response! */
676 virtual int handleEvent(WifiEvent
& event
) {
677 ALOGV("[WIFI HAL]Got a GScan results event");
681 struct nlattr
*vendor_data
= (struct nlattr
*)event
.get_vendor_data();
682 int len
= event
.get_vendor_data_len();
683 int event_id
= event
.get_vendor_subcmd();
686 ALOGV("vendor_data->nla_type=%d nla_len=%d, len=%d, event_id=%d",
687 vendor_data
->nla_type
, vendor_data
->nla_len
, len
, event_id
);
689 if ((event_id
== GSCAN_EVENT_COMPLETE_SCAN
) ||
690 (event_id
== GSCAN_EVENT_SCAN_RESULTS_AVAILABLE
)) {
691 if (vendor_data
== NULL
|| vendor_data
->nla_len
!= 8) {
692 ALOGE("Bad event data!");
695 wifi_scan_event evt_type
;
696 evt_type
= (wifi_scan_event
) nla_get_u32(vendor_data
);
697 ALOGI("Received event_id=%d, event type=%d", event_id
, evt_type
);
698 if (*mHandler
.on_scan_event
)
699 (*mHandler
.on_scan_event
)(id(), evt_type
);
700 } else if (event_id
== GSCAN_EVENT_FULL_SCAN_RESULTS
) {
701 wifi_handle_full_scan_event(id(), event
, mHandler
);
707 wifi_error
wifi_start_gscan(
709 wifi_interface_handle iface
,
710 wifi_scan_cmd_params params
,
711 wifi_scan_result_handler handler
)
713 wifi_handle handle
= getWifiHandle(iface
);
715 ALOGD("[WIFI HAL]Starting GScan, halHandle = %p", handle
);
717 ScanCommand
*cmd
= new ScanCommand(iface
, id
, ¶ms
, handler
);
718 NULL_CHECK_RETURN(cmd
, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY
);
719 wifi_error result
= wifi_register_cmd(handle
, id
, cmd
);
720 if (result
!= WIFI_SUCCESS
) {
724 result
= (wifi_error
)cmd
->start();
725 if (result
!= WIFI_SUCCESS
) {
726 wifi_unregister_cmd(handle
, id
);
733 wifi_error
wifi_stop_gscan(wifi_request_id id
, wifi_interface_handle iface
)
735 ALOGD("[WIFI HAL]Stopping GScan");
736 wifi_handle handle
= getWifiHandle(iface
);
739 wifi_scan_result_handler handler
;
740 wifi_scan_cmd_params dummy_params
;
741 memset(&handler
, 0, sizeof(handler
));
743 ScanCommand
*cmd
= new ScanCommand(iface
, id
, &dummy_params
, handler
);
744 NULL_CHECK_RETURN(cmd
, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY
);
750 return wifi_cancel_cmd(id
, iface
);
754 wifi_error
wifi_enable_full_scan_results(
756 wifi_interface_handle iface
,
757 wifi_scan_result_handler handler
)
759 wifi_handle handle
= getWifiHandle(iface
);
761 ALOGD("[WIFI HAL]Enabling full scan results, halHandle = %p", handle
);
763 FullScanResultsCommand
*cmd
= new FullScanResultsCommand(iface
, id
, ¶ms_dummy
, handler
);
764 NULL_CHECK_RETURN(cmd
, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY
);
765 wifi_error result
= wifi_register_cmd(handle
, id
, cmd
);
766 if (result
!= WIFI_SUCCESS
) {
770 result
= (wifi_error
)cmd
->start();
771 if (result
!= WIFI_SUCCESS
) {
772 wifi_unregister_cmd(handle
, id
);
779 int wifi_handle_full_scan_event(
782 wifi_scan_result_handler handler
)
784 //nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
785 struct nlattr
*vendor_data
= (struct nlattr
*)event
.get_vendor_data();
786 unsigned int len
= event
.get_vendor_data_len();
787 int event_id
= event
.get_vendor_subcmd();
789 if (vendor_data
== NULL
|| len
< sizeof(wifi_gscan_full_result_t
)) {
790 ALOGE("Full scan results: No scan results found");
794 wifi_gscan_full_result_t
*drv_res
= NULL
;
795 if (event_id
== GSCAN_EVENT_FULL_SCAN_RESULTS
)
796 drv_res
= (wifi_gscan_full_result_t
*)nla_data(vendor_data
);
798 ALOGE("cannot get vendor_data of GSCAN_EVENT_FULL_SCAN_RESULTS\n");
801 /* To protect against corrupted data, put a ceiling */
802 int ie_len
= min(MAX_PROBE_RESP_IE_LEN
, drv_res
->ie_length
);
803 wifi_scan_result
*full_scan_result
;
804 wifi_gscan_result_t
*fixed
= &drv_res
->fixed
;
806 if ((ie_len
+ offsetof(wifi_gscan_full_result_t
, ie_data
)) > len
) {
807 ALOGE("BAD event data, len %d ie_len %d fixed length %lu!\n", len
,
808 ie_len
, offsetof(wifi_gscan_full_result_t
, ie_data
));
811 full_scan_result
= (wifi_scan_result
*) malloc((ie_len
+ offsetof(wifi_scan_result
, ie_data
)));
812 if (!full_scan_result
) {
813 ALOGE("Full scan results: Can't malloc!\n");
816 convert_to_hal_result(full_scan_result
, fixed
);
817 full_scan_result
->ie_length
= ie_len
;
818 memcpy(full_scan_result
->ie_data
, drv_res
->ie_data
, ie_len
);
819 if(handler
.on_full_scan_result
)
820 handler
.on_full_scan_result(id
, full_scan_result
, drv_res
->scan_ch_bucket
);
822 ALOGI("Full scan result: %-32s %02x:%02x:%02x:%02x:%02x:%02x %d %d %llu %llu %llu 0x%x %x %d\n",
823 fixed
->ssid
, fixed
->bssid
[0], fixed
->bssid
[1], fixed
->bssid
[2], fixed
->bssid
[3],
824 fixed
->bssid
[4], fixed
->bssid
[5], fixed
->rssi
, fixed
->channel
, fixed
->ts
,
825 fixed
->rtt
, fixed
->rtt_sd
, fixed
->capability
, drv_res
->scan_ch_bucket
, drv_res
->ie_length
);
826 free(full_scan_result
);
830 wifi_error
wifi_disable_full_scan_results(wifi_request_id id
, wifi_interface_handle iface
)
832 ALOGD("[WIFI HAL]Disabling full scan results");
833 wifi_handle handle
= getWifiHandle(iface
);
836 wifi_scan_result_handler handler
;
837 wifi_handle handle
= getWifiHandle(iface
);
840 memset(&handler
, 0, sizeof(handler
));
841 FullScanResultsCommand
*cmd
= new FullScanResultsCommand(iface
, 0, ¶ms_dummy
, handler
);
842 NULL_CHECK_RETURN(cmd
, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY
);
848 return wifi_cancel_cmd(id
, iface
);
852 /////////////////////////////////////////////////////////////////////////////
854 class GetScanResultsCommand
: public WifiCommand
{
855 wifi_cached_scan_results
*mScans
;
862 GetScanResultsCommand(wifi_interface_handle iface
, byte flush
,
863 wifi_cached_scan_results
*results
, int max
, int *num
)
864 : WifiCommand("GetScanResultsCommand", iface
, -1), mScans(results
), mMax(max
), mNum(num
),
865 mRetrieved(0), mFlush(flush
), mCompleted(0)
868 int createRequest(WifiRequest
& request
, int num
, byte flush
) {
869 int result
= request
.create(GOOGLE_OUI
, GSCAN_SUBCMD_GET_SCAN_RESULTS
);
874 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
875 result
= request
.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS
, num
);
880 result
= request
.put_u8(GSCAN_ATTRIBUTE_FLUSH_RESULTS
, flush
);
885 request
.attr_end(data
);
890 WifiRequest
request(familyId(), ifaceId());
891 ALOGD("retrieving mMax=%d scan results", mMax
);
893 for (int i
= 0; i
< 10 && mRetrieved
< mMax
; i
++) {
894 int num_to_retrieve
= mMax
- mRetrieved
;
895 ALOGI("retrieving %d:%d cached gscan results in one shot", mRetrieved
, num_to_retrieve
);
896 int result
= createRequest(request
, num_to_retrieve
, mFlush
);
898 ALOGE("failed to create request");
902 int prev_retrieved
= mRetrieved
;
904 result
= requestResponse(request
);
906 if (result
!= WIFI_SUCCESS
) {
907 ALOGE("failed to retrieve scan results; result = %d", result
);
911 ALOGD("mRetrieved=%d, prev_retrieved=%d, mCompleted=%d", mRetrieved
, prev_retrieved
, mCompleted
);
913 if (mRetrieved
== prev_retrieved
|| mCompleted
) {
914 /* no more items left to retrieve */
921 ALOGI("GetScanResults total read %d results", mRetrieved
);
926 virtual int handleResponse(WifiEvent
& reply
) {
927 ALOGV("In GetScanResultsCommand::handleResponse");
929 if (reply
.get_cmd() != NL80211_CMD_VENDOR
) {
930 ALOGE("Ignoring reply with cmd = %d", reply
.get_cmd());
934 int id
= reply
.get_vendor_id();
935 int subcmd
= reply
.get_vendor_subcmd();
938 if (subcmd != GSCAN_SUBCMD_SCAN_RESULTS) {
939 ALOGE("Invalid response to GetScanResultsCommand; ignoring it");
944 //nlattr *vendor = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
945 struct nlattr
*vendor_data
= (struct nlattr
*)reply
.get_vendor_data();
946 int len
= reply
.get_vendor_data_len();
947 if (vendor_data
== NULL
|| len
== 0) {
948 ALOGE("no vendor data in GetScanResults response; ignoring it");
951 ALOGD("Id = %0x, subcmd = %d, vendor=%p, get_vendor_data()=%p vendor->nla_type=%d len=%d",
952 id
, subcmd
, vendor_data
, reply
.get_vendor_data(), vendor_data
->nla_type
, len
);
954 for (nl_iterator
it(vendor_data
); it
.has_next(); it
.next()) {
955 if (it
.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE
) {
956 mCompleted
= it
.get_u8();
957 ALOGI("retrieved mCompleted flag : %d", mCompleted
);
958 } else if (it
.get_type() >= GSCAN_ATTRIBUTE_NUM_OF_RESULTS
959 && it
.get_type() <= GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK
) {
960 int scan_id
= 0, flags
= 0, num
= 0, scan_ch_bucket_mask
= 0;
961 for (nl_iterator
it2(it
.get()); it2
.has_next(); it2
.next()) {
962 if (it2
.get_type() == GSCAN_ATTRIBUTE_SCAN_ID
) {
963 scan_id
= it2
.get_u32();
964 ALOGD("retrieved scan_id : %d", scan_id
);
965 } else if (it2
.get_type() == GSCAN_ATTRIBUTE_SCAN_FLAGS
) {
966 flags
= it2
.get_u8();
967 ALOGD("retrieved scan_flags : 0x%0x", flags
);
968 } else if (it2
.get_type() == GSCAN_ATTRIBUTE_NUM_OF_RESULTS
) {
970 ALOGD("retrieved num_results: %d", num
);
971 } else if (it2
.get_type() == GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK
) {
972 scan_ch_bucket_mask
= it2
.get_u32();
973 ALOGD("retrieved scan_ch_bucket_mask: 0x%0x", scan_ch_bucket_mask
);
974 } else if (it2
.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS
&& num
) {
975 if (mRetrieved
>= mMax
) {
976 ALOGW("Stored %d scans, ignoring excess results", mRetrieved
);
979 num
= min(num
, (int)(it2
.get_len()/sizeof(wifi_scan_result
)));
980 num
= min(num
, (int)MAX_AP_CACHE_PER_SCAN
);
981 ALOGI("Copying %d scan results, mRetrieved=%d, scan_id=%d, flag=0x%x, bktMask=0x%04x",
982 num
, mRetrieved
, scan_id
, flags
, scan_ch_bucket_mask
);
983 wifi_gscan_result_t
*results
= (wifi_gscan_result_t
*)it2
.get_data();
984 wifi_scan_result
*mScanResults
= mScans
[mRetrieved
].results
;
986 for (int i
= 0; i
< num
; i
++) {
987 wifi_gscan_result_t
*result
= &results
[i
];
988 convert_to_hal_result(&mScanResults
[i
], result
);
989 mScanResults
[i
].ie_length
= result
->ie_length
;
990 //mScanResults[i].ie_data = result->ie_data;
991 ALOGD("%02d %-32s " MACSTR
" %ddB channel=%d, capa=0x%04x, ie_len=%d", i
,
992 result
->ssid
, MAC2STR(result
->bssid
),
993 result
->rssi
, result
->channel
, mScanResults
[i
].capability
, mScanResults
[i
].ie_length
);
995 mScans
[mRetrieved
].scan_id
= scan_id
;
996 mScans
[mRetrieved
].flags
= flags
;
997 mScans
[mRetrieved
].num_results
= num
;
998 mScans
[mRetrieved
].buckets_scanned
= scan_ch_bucket_mask
;
999 ALOGV("Setting result of scan_id : 0x%0x", mScans
[mRetrieved
].scan_id
);
1002 ALOGW("Ignoring invalid attribute type = %d, size = %d",
1003 it
.get_type(), it
.get_len());
1007 ALOGW("Ignoring invalid attribute type = %d, size = %d",
1008 it
.get_type(), it
.get_len());
1011 ALOGD("GetScanResults read %dth results", mRetrieved
);
1016 wifi_error
wifi_get_cached_gscan_results(wifi_interface_handle iface
, byte flush
,
1017 int max
, wifi_cached_scan_results
*results
, int *num
) {
1019 ALOGI("[WIFI HAL]Getting cached gscan results, flush=%d, max=%d, num=%d", flush
, max
, *num
);
1021 GetScanResultsCommand
*cmd
= new GetScanResultsCommand(iface
, flush
, results
, max
, num
);
1022 NULL_CHECK_RETURN(cmd
, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY
);
1023 wifi_error err
= (wifi_error
) cmd
->execute();
1028 /////////////////////////////////////////////////////////////////////////////
1030 class BssidHotlistCommand
: public WifiCommand
1033 wifi_bssid_hotlist_params mParams
;
1034 wifi_hotlist_ap_found_handler mHandler
;
1035 static const int MAX_RESULTS
= 64;
1036 wifi_scan_result mResults
[MAX_RESULTS
];
1038 BssidHotlistCommand(wifi_interface_handle handle
, int id
,
1039 wifi_bssid_hotlist_params params
, wifi_hotlist_ap_found_handler handler
)
1040 : WifiCommand("BssidHotlistCommand", handle
, id
), mParams(params
), mHandler(handler
)
1043 int createSetupRequest(WifiRequest
& request
) {
1044 int result
= request
.create(GOOGLE_OUI
, GSCAN_SUBCMD_SET_HOTLIST
);
1049 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
1050 result
= request
.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH
, 1);
1055 result
= request
.put_u32(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE
, mParams
.lost_ap_sample_size
);
1059 result
= request
.put_u16(GSCAN_ATTRIBUTE_NUM_AP
, mParams
.num_bssid
);
1064 struct nlattr
* attr
= request
.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS
);
1065 for (int i
= 0; i
< mParams
.num_bssid
; i
++) {
1066 nlattr
*attr2
= request
.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM
);
1067 if (attr2
== NULL
) {
1068 return WIFI_ERROR_OUT_OF_MEMORY
;
1070 result
= request
.put_addr(GSCAN_ATTRIBUTE_BSSID
, mParams
.ap
[i
].bssid
);
1074 result
= request
.put_u32(GSCAN_ATTRIBUTE_RSSI_HIGH
, mParams
.ap
[i
].high
);
1078 result
= request
.put_u32(GSCAN_ATTRIBUTE_RSSI_LOW
, mParams
.ap
[i
].low
);
1082 request
.attr_end(attr2
);
1085 request
.attr_end(attr
);
1086 request
.attr_end(data
);
1090 int createTeardownRequest(WifiRequest
& request
) {
1091 int result
= request
.create(GOOGLE_OUI
, GSCAN_SUBCMD_SET_HOTLIST
);
1096 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
1097 result
= request
.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH
, 1);
1102 struct nlattr
* attr
= request
.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS
);
1103 request
.attr_end(attr
);
1104 request
.attr_end(data
);
1109 ALOGD("[WIFI HAL]Executing hotlist setup request, num = %d", mParams
.num_bssid
);
1110 WifiRequest
request(familyId(), ifaceId());
1111 int result
= createSetupRequest(request
);
1116 result
= requestResponse(request
);
1118 ALOGI("Failed to execute hotlist setup request, result = %d", result
);
1119 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_FOUND
);
1120 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_LOST
);
1124 ALOGI("Successfully set %d APs in the hotlist", mParams
.num_bssid
);
1125 result
= createFeatureRequest(request
, GSCAN_SUBCMD_ENABLE_GSCAN
, 1);
1130 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_FOUND
);
1131 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_LOST
);
1133 result
= requestResponse(request
);
1135 ALOGE("failed to start scan; result = %d", result
);
1136 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_FOUND
);
1137 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_LOST
);
1141 ALOGI("successfully restarted the scan");
1145 virtual int cancel() {
1146 /* unregister event handler */
1147 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_FOUND
);
1148 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_HOTLIST_RESULTS_LOST
);
1149 /* create set hotlist message with empty hotlist */
1150 WifiRequest
request(familyId(), ifaceId());
1151 int result
= createTeardownRequest(request
);
1156 result
= requestResponse(request
);
1161 ALOGI("Successfully reset APs in current hotlist");
1165 virtual int handleResponse(WifiEvent
& reply
) {
1166 /* Nothing to do on response! */
1170 virtual int handleEvent(WifiEvent
& event
) {
1171 ALOGD("[WIFI HAL]Hotlist AP event");
1172 int event_id
= event
.get_vendor_subcmd();
1175 struct nlattr
*vendor_data
= (struct nlattr
*)event
.get_vendor_data();
1176 int len
= event
.get_vendor_data_len();
1178 if (vendor_data
== NULL
|| len
== 0) {
1179 ALOGI("No scan results found");
1183 memset(mResults
, 0, sizeof(wifi_scan_result
) * MAX_RESULTS
);
1185 int num
= len
/ sizeof(wifi_scan_result
);
1186 num
= min(MAX_RESULTS
, num
);
1187 ALOGD("hotlist APs num=%d, vendor len=%d, nla_len=%d nla_type=%d",
1188 num
, len
, vendor_data
->nla_len
, vendor_data
->nla_type
);
1189 if(vendor_data
->nla_type
== GSCAN_EVENT_HOTLIST_RESULTS_LOST
1190 || vendor_data
->nla_type
== GSCAN_EVENT_HOTLIST_RESULTS_FOUND
)
1191 memcpy(mResults
, nla_data(vendor_data
), num
* sizeof(wifi_scan_result
));
1193 if (event_id
== GSCAN_EVENT_HOTLIST_RESULTS_FOUND
) {
1194 ALOGI("FOUND %d hotlist APs", num
);
1195 if (*mHandler
.on_hotlist_ap_found
)
1196 (*mHandler
.on_hotlist_ap_found
)(id(), num
, mResults
);
1197 } else if (event_id
== GSCAN_EVENT_HOTLIST_RESULTS_LOST
) {
1198 ALOGI("LOST %d hotlist APs", num
);
1199 if (*mHandler
.on_hotlist_ap_lost
)
1200 (*mHandler
.on_hotlist_ap_lost
)(id(), num
, mResults
);
1206 class ePNOCommand
: public WifiCommand
1209 wifi_epno_params epno_params
;
1210 wifi_epno_handler mHandler
;
1211 wifi_scan_result mResults
[MAX_EPNO_NETWORKS
];
1213 ePNOCommand(wifi_interface_handle handle
, int id
,
1214 const wifi_epno_params
*params
, wifi_epno_handler handler
)
1215 : WifiCommand("ePNOCommand", handle
, id
), mHandler(handler
)
1217 if (params
!= NULL
) {
1218 memcpy(&epno_params
, params
, sizeof(wifi_epno_params
));
1220 memset(&epno_params
, 0, sizeof(wifi_epno_params
));
1224 int createSetupRequest(WifiRequest
& request
) {
1225 if (epno_params
.num_networks
> MAX_EPNO_NETWORKS
) {
1226 ALOGE("wrong epno num_networks:%d", epno_params
.num_networks
);
1227 return WIFI_ERROR_INVALID_ARGS
;
1229 int result
= request
.create(GOOGLE_OUI
, GSCAN_SUBCMD_SET_EPNO_SSID
);
1233 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
1234 result
= request
.put_u8(GSCAN_ATTRIBUTE_EPNO_FLUSH
, 1);
1239 result
= request
.put_u8(GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR
,
1240 (u8
)epno_params
.min5GHz_rssi
);
1244 result
= request
.put_u8(GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR
,
1245 (u8
)epno_params
.min24GHz_rssi
);
1249 result
= request
.put_u16(GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX
,
1250 epno_params
.initial_score_max
);
1254 result
= request
.put_u16(GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS
,
1255 epno_params
.current_connection_bonus
);
1259 result
= request
.put_u16(GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS
,
1260 epno_params
.same_network_bonus
);
1264 result
= request
.put_u16(GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS
,
1265 epno_params
.secure_bonus
);
1269 result
= request
.put_u16(GSCAN_ATTRIBUTE_EPNO_5G_BONUS
,
1270 epno_params
.band5GHz_bonus
);
1274 result
= request
.put_u8(GSCAN_ATTRIBUTE_EPNO_SSID_NUM
,
1275 epno_params
.num_networks
);
1279 struct nlattr
* attr
= request
.attr_start(GSCAN_ATTRIBUTE_EPNO_SSID_LIST
);
1280 wifi_epno_network
*ssid_list
= epno_params
.networks
;
1281 for (int i
= 0; i
< epno_params
.num_networks
; i
++) {
1282 nlattr
*attr2
= request
.attr_start(i
);
1283 if (attr2
== NULL
) {
1284 return WIFI_ERROR_OUT_OF_MEMORY
;
1286 result
= request
.put(GSCAN_ATTRIBUTE_EPNO_SSID
, ssid_list
[i
].ssid
, DOT11_MAX_SSID_LEN
);
1287 ALOGI("PNO network: SSID %s flags %x auth %x", ssid_list
[i
].ssid
,
1289 ssid_list
[i
].auth_bit_field
);
1293 result
= request
.put_u32(GSCAN_ATTRIBUTE_EPNO_SSID_LEN
, strlen(ssid_list
[i
].ssid
));
1297 result
= request
.put_u32(GSCAN_ATTRIBUTE_EPNO_FLAGS
, ssid_list
[i
].flags
);
1301 result
= request
.put_u32(GSCAN_ATTRIBUTE_EPNO_AUTH
, ssid_list
[i
].auth_bit_field
);
1305 request
.attr_end(attr2
);
1307 request
.attr_end(attr
);
1308 request
.attr_end(data
);
1312 int createTeardownRequest(WifiRequest
& request
) {
1313 int result
= request
.create(GOOGLE_OUI
, GSCAN_SUBCMD_SET_EPNO_SSID
);
1318 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
1319 result
= request
.put_u8(GSCAN_ATTRIBUTE_EPNO_FLUSH
, 1);
1323 request
.attr_end(data
);
1328 ALOGI("Executing ePNO setup request, num = %d", epno_params
.num_networks
);
1329 WifiRequest
request(familyId(), ifaceId());
1330 int result
= createSetupRequest(request
);
1335 result
= requestResponse(request
);
1337 ALOGI("Failed to execute ePNO setup request, result = %d", result
);
1338 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_EPNO_EVENT
);
1342 ALOGI("Successfully set %d SSIDs for ePNO", epno_params
.num_networks
);
1343 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_EPNO_EVENT
);
1344 ALOGI("successfully restarted the scan");
1348 virtual int cancel() {
1349 /* unregister event handler */
1350 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_EPNO_EVENT
);
1351 /* create set hotlist message with empty hotlist */
1352 WifiRequest
request(familyId(), ifaceId());
1353 int result
= createTeardownRequest(request
);
1358 result
= requestResponse(request
);
1363 ALOGI("Successfully reset APs in current hotlist");
1367 virtual int handleResponse(WifiEvent
& reply
) {
1368 /* Nothing to do on response! */
1372 virtual int handleEvent(WifiEvent
& event
) {
1373 ALOGI("ePNO event");
1374 int event_id
= event
.get_vendor_subcmd();
1377 nlattr
*vendor_data
= event
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
1378 int len
= event
.get_vendor_data_len();
1380 if (vendor_data
== NULL
|| len
== 0) {
1381 ALOGI("No scan results found");
1385 memset(mResults
, 0, sizeof(wifi_scan_result
) * MAX_EPNO_NETWORKS
);
1387 unsigned int num
= len
/ sizeof(wifi_pno_result_t
);
1389 num
= min(MAX_EPNO_NETWORKS
, num
);
1390 wifi_pno_result_t
*res
= (wifi_pno_result_t
*) event
.get_vendor_data();
1391 for (i
= 0; i
< num
; i
++) {
1392 if (res
[i
].flags
== PNO_SSID_FOUND
) {
1393 memcpy(mResults
[i
].ssid
, res
[i
].ssid
, res
[i
].ssid_len
);
1394 memcpy(mResults
[i
].bssid
, res
[i
].bssid
, sizeof(mac_addr
));
1396 mResults
[i
].ssid
[res
[i
].ssid_len
] = '\0';
1397 mResults
[i
].channel
= res
[i
].channel
;
1398 mResults
[i
].rssi
= res
[i
].rssi
;
1401 if (*mHandler
.on_network_found
)
1402 (*mHandler
.on_network_found
)(id(), num
, mResults
);
1407 wifi_error
wifi_set_bssid_hotlist(wifi_request_id id
, wifi_interface_handle iface
,
1408 wifi_bssid_hotlist_params params
, wifi_hotlist_ap_found_handler handler
)
1410 wifi_handle handle
= getWifiHandle(iface
);
1412 BssidHotlistCommand
*cmd
= new BssidHotlistCommand(iface
, id
, params
, handler
);
1413 NULL_CHECK_RETURN(cmd
, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY
);
1414 wifi_error result
= wifi_register_cmd(handle
, id
, cmd
);
1415 if (result
!= WIFI_SUCCESS
) {
1419 result
= (wifi_error
)cmd
->start();
1420 if (result
!= WIFI_SUCCESS
) {
1421 wifi_unregister_cmd(handle
, id
);
1428 wifi_error
wifi_reset_bssid_hotlist(wifi_request_id id
, wifi_interface_handle iface
)
1430 return wifi_cancel_cmd(id
, iface
);
1434 /////////////////////////////////////////////////////////////////////////////
1436 class SignificantWifiChangeCommand
: public WifiCommand
1439 mac_addr bssid
; // BSSID
1440 wifi_channel channel
; // channel frequency in MHz
1441 int num_rssi
; // number of rssi samples
1442 wifi_rssi rssi
[8]; // RSSI history in db
1443 } wifi_significant_change_result_internal
;
1446 wifi_significant_change_params mParams
;
1447 wifi_significant_change_handler mHandler
;
1448 static const int MAX_RESULTS
= 64;
1449 wifi_significant_change_result_internal mResultsBuffer
[MAX_RESULTS
];
1450 wifi_significant_change_result
*mResults
[MAX_RESULTS
];
1452 SignificantWifiChangeCommand(wifi_interface_handle handle
, int id
,
1453 wifi_significant_change_params params
, wifi_significant_change_handler handler
)
1454 : WifiCommand("SignificantWifiChangeCommand", handle
, id
), mParams(params
),
1458 int createSetupRequest(WifiRequest
& request
) {
1459 int result
= request
.create(GOOGLE_OUI
, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG
);
1464 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
1465 result
= request
.put_u8(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH
, 1);
1469 result
= request
.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE
, mParams
.rssi_sample_size
);
1473 result
= request
.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE
, mParams
.lost_ap_sample_size
);
1477 result
= request
.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING
, mParams
.min_breaching
);
1481 result
= request
.put_u16(GSCAN_ATTRIBUTE_NUM_AP
, mParams
.num_bssid
);
1486 struct nlattr
* attr
= request
.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS
);
1488 for (int i
= 0; i
< mParams
.num_bssid
; i
++) {
1489 nlattr
*attr2
= request
.attr_start(i
);
1490 if (attr2
== NULL
) {
1491 return WIFI_ERROR_OUT_OF_MEMORY
;
1493 result
= request
.put_addr(GSCAN_ATTRIBUTE_BSSID
, mParams
.ap
[i
].bssid
);
1497 result
= request
.put_u32(GSCAN_ATTRIBUTE_RSSI_HIGH
, mParams
.ap
[i
].high
);
1501 result
= request
.put_u32(GSCAN_ATTRIBUTE_RSSI_LOW
, mParams
.ap
[i
].low
);
1505 request
.attr_end(attr2
);
1508 request
.attr_end(attr
);
1509 request
.attr_end(data
);
1514 int createTeardownRequest(WifiRequest
& request
) {
1515 int result
= request
.create(GOOGLE_OUI
, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG
);
1520 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
1521 result
= request
.put_u16(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH
, 1);
1526 request
.attr_end(data
);
1531 ALOGD("[WIFI HAL]Set significant wifi change config");
1532 WifiRequest
request(familyId(), ifaceId());
1534 int result
= createSetupRequest(request
);
1539 result
= requestResponse(request
);
1541 ALOGE("failed to set significant wifi change config %d", result
);
1545 ALOGI("successfully set significant wifi change config");
1547 result
= createFeatureRequest(request
, GSCAN_SUBCMD_ENABLE_GSCAN
, 1);
1552 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS
);
1554 result
= requestResponse(request
);
1556 ALOGE("failed to start scan; result = %d", result
);
1557 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS
);
1561 ALOGI("successfully restarted the scan");
1565 virtual int cancel() {
1566 /* unregister event handler */
1567 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS
);
1569 /* create set significant change monitor message with empty hotlist */
1570 WifiRequest
request(familyId(), ifaceId());
1572 int result
= createTeardownRequest(request
);
1577 result
= requestResponse(request
);
1582 ALOGI("successfully reset significant wifi change config");
1586 virtual int handleResponse(WifiEvent
& reply
) {
1587 /* Nothing to do on response! */
1591 virtual int handleEvent(WifiEvent
& event
) {
1592 ALOGD("[WIFI HAL]Got a significant wifi change event");
1594 struct nlattr
*vendor_data
= (struct nlattr
*)event
.get_vendor_data();
1595 int len
= event
.get_vendor_data_len();
1597 if (vendor_data
== NULL
|| len
== 0) {
1598 ALOGI("No scan results found");
1609 int num
= min(len
/ sizeof(ChangeInfo
), MAX_RESULTS
);
1611 if (vendor_data
->nla_type
== GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS
)
1612 ci
= (ChangeInfo
*)nla_data(vendor_data
);
1616 for (int i
= 0; i
< num
; i
++) {
1617 memcpy(mResultsBuffer
[i
].bssid
, ci
[i
].bssid
, sizeof(mac_addr
));
1618 mResultsBuffer
[i
].channel
= ci
[i
].channel
;
1619 mResultsBuffer
[i
].num_rssi
= 8;
1620 for (int j
= 0; j
< mResultsBuffer
[i
].num_rssi
; j
++)
1621 mResultsBuffer
[i
].rssi
[j
] = (int) ci
[i
].rssi_history
[j
];
1622 mResults
[i
] = reinterpret_cast<wifi_significant_change_result
*>(&(mResultsBuffer
[i
]));
1625 ALOGI("Retrieved %d scan results, vendor len=%d nla_type=%d", num
, len
, vendor_data
->nla_type
);
1628 (*mHandler
.on_significant_change
)(id(), num
, mResults
);
1630 ALOGW("No significant change reported");
1637 wifi_error
wifi_set_significant_change_handler(wifi_request_id id
, wifi_interface_handle iface
,
1638 wifi_significant_change_params params
, wifi_significant_change_handler handler
)
1640 wifi_handle handle
= getWifiHandle(iface
);
1642 SignificantWifiChangeCommand
*cmd
= new SignificantWifiChangeCommand(
1643 iface
, id
, params
, handler
);
1644 NULL_CHECK_RETURN(cmd
, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY
);
1645 wifi_error result
= wifi_register_cmd(handle
, id
, cmd
);
1646 if (result
!= WIFI_SUCCESS
) {
1650 result
= (wifi_error
)cmd
->start();
1651 if (result
!= WIFI_SUCCESS
) {
1652 wifi_unregister_cmd(handle
, id
);
1659 wifi_error
wifi_reset_significant_change_handler(wifi_request_id id
, wifi_interface_handle iface
)
1661 return wifi_cancel_cmd(id
, iface
);
1664 wifi_error
wifi_reset_epno_list(wifi_request_id id
, wifi_interface_handle iface
)
1667 wifi_epno_handler handler
;
1668 wifi_handle handle
= getWifiHandle(iface
);
1670 memset(&handler
, 0, sizeof(handler
));
1671 ePNOCommand
*cmd
= new ePNOCommand(iface
, id
, NULL
, handler
);
1672 NULL_CHECK_RETURN(cmd
, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY
);
1675 return WIFI_SUCCESS
;
1677 return wifi_cancel_cmd(id
, iface
);
1680 wifi_error
wifi_set_epno_list(wifi_request_id id
, wifi_interface_handle iface
,
1681 const wifi_epno_params
*params
, wifi_epno_handler handler
)
1683 wifi_handle handle
= getWifiHandle(iface
);
1685 ePNOCommand
*cmd
= new ePNOCommand(iface
, id
, params
, handler
);
1686 NULL_CHECK_RETURN(cmd
, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY
);
1687 wifi_error result
= wifi_register_cmd(handle
, id
, cmd
);
1688 if (result
!= WIFI_SUCCESS
) {
1692 result
= (wifi_error
)cmd
->start();
1693 if (result
!= WIFI_SUCCESS
) {
1694 wifi_unregister_cmd(handle
, id
);
1702 ////////////////////////////////////////////////////////////////////////////////
1704 class AnqpoConfigureCommand
: public WifiCommand
1707 wifi_passpoint_network
*mNetworks
;
1708 wifi_passpoint_event_handler mHandler
;
1709 wifi_scan_result
*mResult
;
1711 AnqpoConfigureCommand(wifi_request_id id
, wifi_interface_handle iface
,
1712 int num
, wifi_passpoint_network
*hs_list
, wifi_passpoint_event_handler handler
)
1713 : WifiCommand("AnqpoConfigureCommand", iface
, id
), num_hs(num
), mNetworks(hs_list
),
1719 int createRequest(WifiRequest
& request
, int val
) {
1721 int result
= request
.create(GOOGLE_OUI
, GSCAN_SUBCMD_ANQPO_CONFIG
);
1722 result
= request
.put_u32(GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE
, num_hs
);
1727 nlattr
*data
= request
.attr_start(NL80211_ATTR_VENDOR_DATA
);
1729 struct nlattr
* attr
= request
.attr_start(GSCAN_ATTRIBUTE_ANQPO_HS_LIST
);
1730 for (int i
= 0; i
< num_hs
; i
++) {
1731 nlattr
*attr2
= request
.attr_start(i
);
1732 if (attr2
== NULL
) {
1733 return WIFI_ERROR_OUT_OF_MEMORY
;
1735 result
= request
.put_u32(GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID
, mNetworks
[i
].id
);
1739 result
= request
.put(GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM
, mNetworks
[i
].realm
, 256);
1743 result
= request
.put(GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID
,
1744 mNetworks
[i
].roamingConsortiumIds
, 128);
1748 result
= request
.put(GSCAN_ATTRIBUTE_ANQPO_HS_PLMN
, mNetworks
[i
].plmn
, 3);
1753 request
.attr_end(attr2
);
1756 request
.attr_end(attr
);
1757 request
.attr_end(data
);
1759 return WIFI_SUCCESS
;
1764 WifiRequest
request(familyId(), ifaceId());
1765 int result
= createRequest(request
, num_hs
);
1766 if (result
!= WIFI_SUCCESS
) {
1767 ALOGE("failed to create request; result = %d", result
);
1771 registerVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH
);
1773 result
= requestResponse(request
);
1774 if (result
!= WIFI_SUCCESS
) {
1775 ALOGE("failed to set ANQPO networks; result = %d", result
);
1776 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH
);
1783 virtual int cancel() {
1785 WifiRequest
request(familyId(), ifaceId());
1786 int result
= createRequest(request
, 0);
1787 if (result
!= WIFI_SUCCESS
) {
1788 ALOGE("failed to create request; result = %d", result
);
1790 result
= requestResponse(request
);
1791 if (result
!= WIFI_SUCCESS
) {
1792 ALOGE("failed to reset ANQPO networks;result = %d", result
);
1796 unregisterVendorHandler(GOOGLE_OUI
, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH
);
1797 return WIFI_SUCCESS
;
1800 virtual int handleResponse(WifiEvent
& reply
) {
1801 ALOGD("Request complete!");
1802 /* Nothing to do on response! */
1806 virtual int handleEvent(WifiEvent
& event
) {
1808 u16 channel
; /* channel of GAS protocol */
1809 u8 dialog_token
; /* GAS dialog token */
1810 u8 fragment_id
; /* fragment id */
1811 u16 status_code
; /* status code on GAS completion */
1812 u16 data_len
; /* length of data to follow */
1813 u8 data
[1]; /* variable length specified by data_len */
1814 } wifi_anqp_gas_resp
;
1816 ALOGI("ANQPO hotspot matched event!");
1818 nlattr
*vendor_data
= event
.get_attribute(NL80211_ATTR_VENDOR_DATA
);
1819 unsigned int len
= event
.get_vendor_data_len();
1821 if (vendor_data
== NULL
|| len
< sizeof(wifi_scan_result
)) {
1822 ALOGI("No scan results found");
1825 mResult
= (wifi_scan_result
*)malloc(sizeof(wifi_scan_result
));
1829 wifi_gscan_full_result_t
*drv_res
= (wifi_gscan_full_result_t
*)event
.get_vendor_data();
1830 wifi_gscan_result_t
*fixed
= &drv_res
->fixed
;
1831 convert_to_hal_result(mResult
, fixed
);
1833 byte
*anqp
= (byte
*)drv_res
+ offsetof(wifi_gscan_full_result_t
, ie_data
) + drv_res
->ie_length
;
1834 wifi_anqp_gas_resp
*gas
= (wifi_anqp_gas_resp
*)anqp
;
1835 int anqp_len
= offsetof(wifi_anqp_gas_resp
, data
) + gas
->data_len
;
1836 int networkId
= *(int *)((byte
*)anqp
+ anqp_len
);
1838 ALOGI("%-32s\t", mResult
->ssid
);
1840 ALOGI("%02x:%02x:%02x:%02x:%02x:%02x ", mResult
->bssid
[0], mResult
->bssid
[1],
1841 mResult
->bssid
[2], mResult
->bssid
[3], mResult
->bssid
[4], mResult
->bssid
[5]);
1843 ALOGI("%d\t", mResult
->rssi
);
1844 ALOGI("%d\t", mResult
->channel
);
1845 ALOGI("%lld\t", mResult
->ts
);
1846 ALOGI("%lld\t", mResult
->rtt
);
1847 ALOGI("%lld\n", mResult
->rtt_sd
);
1849 if(*mHandler
.on_passpoint_network_found
)
1850 (*mHandler
.on_passpoint_network_found
)(id(), networkId
, mResult
, anqp_len
, anqp
);
1856 wifi_error
wifi_set_passpoint_list(wifi_request_id id
, wifi_interface_handle iface
, int num
,
1857 wifi_passpoint_network
*networks
, wifi_passpoint_event_handler handler
)
1859 wifi_handle handle
= getWifiHandle(iface
);
1861 AnqpoConfigureCommand
*cmd
= new AnqpoConfigureCommand(id
, iface
, num
, networks
, handler
);
1862 NULL_CHECK_RETURN(cmd
, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY
);
1863 wifi_error result
= wifi_register_cmd(handle
, id
, cmd
);
1864 if (result
!= WIFI_SUCCESS
) {
1868 result
= (wifi_error
)cmd
->start();
1869 if (result
!= WIFI_SUCCESS
) {
1870 wifi_unregister_cmd(handle
, id
);
1877 wifi_error
wifi_reset_passpoint_list(wifi_request_id id
, wifi_interface_handle iface
)
1879 return wifi_cancel_cmd(id
, iface
);