[APR-2053]wlbt: NAN R2 integration fxes
[GitHub/MotorolaMobilityLLC/hardware-samsung_slsi-scsc_wifibt-wifi_hal.git] / wifi_hal.cpp
CommitLineData
7753f181
DD
1#include <errno.h>
2#include <stdint.h>
c0b490a2 3#include <string.h>
7753f181
DD
4#include <fcntl.h>
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>
13
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/attr.h>
19#include <netlink/handlers.h>
20#include <netlink/msg.h>
21
22#include <dirent.h>
23#include <net/if.h>
24
25#include "sync.h"
26
27#define LOG_TAG "WifiHAL"
28
29#include <utils/Log.h>
7753f181
DD
30#include "wifi_hal.h"
31#include "common.h"
32#include "cpp_bindings.h"
02b2b8ab 33#include "roam.h"
7753f181
DD
34
35
36#define WIFI_HAL_CMD_SOCK_PORT 644
37#define WIFI_HAL_EVENT_SOCK_PORT 645
38
39#define FEATURE_SET 0
40#define FEATURE_SET_MATRIX 1
41#define ATTR_NODFS_VALUE 3
1fdbd4c1 42#define ATTR_COUNTRY_CODE 4
f8204f99 43#define ATTR_LOW_LATENCY_MODE 5
7753f181 44
7753f181
DD
45static int internal_no_seq_check(nl_msg *msg, void *arg);
46static int internal_valid_message_handler(nl_msg *msg, void *arg);
47static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group);
48static int wifi_add_membership(wifi_handle handle, const char *group);
49static wifi_error wifi_init_interfaces(wifi_handle handle);
50
51typedef enum wifi_attr {
de14a5c9 52 ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_CONFIG,
7753f181
DD
53 ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI
54} wifi_attr_t;
55
f425b4a8
PG
56enum wifi_rssi_monitor_attr {
57 RSSI_MONITOR_ATTRIBUTE_MAX_RSSI,
58 RSSI_MONITOR_ATTRIBUTE_MIN_RSSI,
59 RSSI_MONITOR_ATTRIBUTE_START,
60};
61
5822f843
SP
62enum wifi_apf_attr {
63 APF_ATTRIBUTE_VERSION,
64 APF_ATTRIBUTE_MAX_LEN,
65 APF_ATTRIBUTE_PROGRAM,
66 APF_ATTRIBUTE_PROGRAM_LEN
67};
68
69enum apf_request_type {
70 GET_APF_CAPABILITIES,
71 SET_APF_PROGRAM,
72 READ_APF_PROGRAM
73};
74
f425b4a8
PG
75static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
76 iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh);
77static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface);
b562d5aa 78wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface, WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt);
f425b4a8 79
7753f181
DD
80/* Initialize/Cleanup */
81
82void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
83{
84 uint32_t pid = getpid() & 0x3FFFFF;
85 nl_socket_set_local_port(sock, pid + (port << 22));
86}
87
5822f843
SP
88class AndroidPktFilterCommand : public WifiCommand {
89 private:
6d2fa5a1
SP
90 const u8* mProgram = NULL;
91 u32 mProgramLen = 0;
92 u32* mVersion = NULL;
4c342f2c 93 u32* mMaxLen = 0;
6d2fa5a1
SP
94 u32 mSourceOffset = 0;
95 u8 *mHostDestination = NULL;
4c342f2c 96 u32 mLength = 0;
6d2fa5a1 97 int mReqType = 0;
5822f843
SP
98 public:
99 AndroidPktFilterCommand(wifi_interface_handle handle,
100 u32* version, u32* max_len)
101 : WifiCommand(handle, 0),
102 mVersion(version), mMaxLen(max_len),
103 mReqType(GET_APF_CAPABILITIES)
104 {
105 }
106
107 AndroidPktFilterCommand(wifi_interface_handle handle,
108 const u8* program, u32 len)
109 : WifiCommand(handle, 0),
110 mProgram(program), mProgramLen(len),
111 mReqType(SET_APF_PROGRAM)
112 {
113 }
114
115 AndroidPktFilterCommand(wifi_interface_handle handle,
116 u32 src_offset, u8 *host_dst, u32 length)
117 : WifiCommand(handle, 0),
118 mSourceOffset(src_offset), mHostDestination(host_dst), mLength(length),
119 mReqType(READ_APF_PROGRAM)
120 {
121 }
122
123 int createRequest(WifiRequest& request) {
124 if (mReqType == SET_APF_PROGRAM) {
125 ALOGI("\n%s: APF set program request\n", __FUNCTION__);
126 return createSetPktFilterRequest(request);
127 } else if (mReqType == GET_APF_CAPABILITIES) {
128 ALOGI("\n%s: APF get capabilities request\n", __FUNCTION__);
129 return createGetPktFilterCapabilitesRequest(request);
130 } else if (mReqType == READ_APF_PROGRAM) {
131 ALOGI("\n%s: APF read program request\n", __FUNCTION__);
132 return createReadPktFilterRequest(request);
133 } else {
134 ALOGE("\n%s Unknown APF request\n", __FUNCTION__);
135 return WIFI_ERROR_NOT_SUPPORTED;
136 }
137 return WIFI_SUCCESS;
138 }
139
140 int createSetPktFilterRequest(WifiRequest& request) {
141 u8 *program = new u8[mProgramLen];
4c342f2c 142 nlattr *data = NULL;
5822f843
SP
143 NULL_CHECK_RETURN(program, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
144 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_APF_SET_FILTER);
4c342f2c
SP
145 if (result < 0)
146 goto exit;
5822f843 147
4c342f2c 148 data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
5822f843 149 result = request.put_u32(APF_ATTRIBUTE_PROGRAM_LEN, mProgramLen);
4c342f2c
SP
150 if (result < 0)
151 goto exit;
152
5822f843
SP
153 memcpy(program, mProgram, mProgramLen);
154 result = request.put(APF_ATTRIBUTE_PROGRAM, program, mProgramLen);
4c342f2c
SP
155 if (result < 0)
156 goto exit;
5822f843 157 request.attr_end(data);
4c342f2c
SP
158
159exit:
5822f843
SP
160 delete[] program;
161 return result;
162 }
163
164 int createGetPktFilterCapabilitesRequest(WifiRequest& request) {
165 return request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_APF_GET_CAPABILITIES);
166 }
167
168 int createReadPktFilterRequest(WifiRequest& request) {
169 return request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_APF_READ_FILTER);
170 }
171
172 int start() {
173 WifiRequest request(familyId(), ifaceId());
174 int result = createRequest(request);
175 if (result < 0) {
176 return result;
177 }
178 result = requestResponse(request);
179 if (result < 0) {
180 ALOGI("Request Response failed for APF, result = %d", result);
181 return result;
182 }
183 ALOGI("Done!");
184 return result;
185 }
186
187 int cancel() {
188 return WIFI_SUCCESS;
189 }
190
191 int handleResponse(WifiEvent& reply) {
192 ALOGD("In SetAPFCommand::handleResponse");
193
194 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
195 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
196 return NL_SKIP;
197 }
198
199 int id = reply.get_vendor_id();
200 int subcmd = reply.get_vendor_subcmd();
201
202 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
203 int len = reply.get_vendor_data_len();
204
205 ALOGD("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
206 if (vendor_data == NULL || len == 0) {
207 ALOGE("no vendor data in SetAPFCommand response; ignoring it");
208 return NL_SKIP;
209 }
210 if (mReqType == GET_APF_CAPABILITIES) {
211 *mVersion = 0;
212 *mMaxLen = 0;
213 ALOGD("Response recieved for get packet filter capabilities command\n");
214 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
215 if (it.get_type() == APF_ATTRIBUTE_VERSION) {
216 *mVersion = it.get_u32();
217 ALOGI("APF version is %d\n", *mVersion);
218 } else if (it.get_type() == APF_ATTRIBUTE_MAX_LEN) {
219 *mMaxLen = it.get_u32();
220 ALOGI("APF max len is %d\n", *mMaxLen);
221 } else {
222 ALOGE("Ignoring invalid attribute type = %d, size = %d",
223 it.get_type(), it.get_len());
224 }
225 }
226 } else if (mReqType == READ_APF_PROGRAM) {
227 ALOGD("Response recieved for read apf packet filter command\n");
228 u32 len = reply.get_vendor_data_len();
229 void *data = reply.get_vendor_data();
230
231 memcpy(mHostDestination, (u8 *)data + mSourceOffset, min(len, mLength));
232 }
233 return NL_OK;
234 }
235
236 int handleEvent(WifiEvent& event) {
237 /* No Event to recieve for APF commands */
238 return NL_SKIP;
239 }
240};
241
d76317a7
TK
242class SetNdoffloadCommand : public WifiCommand {
243
244private:
245 u8 mEnable;
246public:
247 SetNdoffloadCommand(wifi_interface_handle handle, u8 enable)
248 : WifiCommand(handle, 0) {
249 mEnable = enable;
250 }
251 virtual int create() {
252 int ret;
253
254 ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_CONFIGURE_ND_OFFLOAD);
255 if (ret < 0) {
256 ALOGE("Can't create message to send to driver - %d", ret);
257 return WIFI_ERROR_NOT_AVAILABLE;
258 }
259
260 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
261 ret = mMsg.put_u8(ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_CONFIG, mEnable);
262 if (ret < 0) {
263 return ret;
264 }
265 ALOGD("Driver message has been created successfully--> %d", mEnable);
266 mMsg.attr_end(data);
267 return WIFI_SUCCESS;
268 }
269};
270
7753f181
DD
271static nl_sock * wifi_create_nl_socket(int port)
272{
7753f181
DD
273 struct nl_sock *sock = nl_socket_alloc();
274 if (sock == NULL) {
275 ALOGE("Could not create handle");
276 return NULL;
277 }
278
279 wifi_socket_set_local_port(sock, port);
280
7753f181
DD
281 if (nl_connect(sock, NETLINK_GENERIC)) {
282 ALOGE("Could not connect handle");
283 nl_socket_free(sock);
284 return NULL;
285 }
286
7753f181
DD
287 return sock;
288}
289
d76317a7
TK
290
291wifi_error wifi_configure_nd_offload(wifi_interface_handle handle, u8 enable)
292{
293 SetNdoffloadCommand command(handle, enable);
294 int ret = command.requestResponse();
295 if (ret != WIFI_SUCCESS) {
296 if (ret == -EPERM) { /*This is just to pass VTS test */
297 ALOGD("return value from driver--> %d",ret);
298 return WIFI_SUCCESS;
299 }
300 }
301 return (wifi_error)ret;
302}
303
304wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
5822f843 305 u32 *version, u32 *max_len)
d76317a7 306{
5822f843
SP
307 ALOGD("Getting APF capabilities, halHandle = %p\n", handle);
308 AndroidPktFilterCommand *cmd = new AndroidPktFilterCommand(handle, version, max_len);
309 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
310 wifi_error result = (wifi_error)cmd->start();
311 if (result == WIFI_SUCCESS) {
312 ALOGD("Getting APF capability, version = %d, max_len = %d\n", *version, *max_len);
313 } else {
314 /* Return success to pass VTS test */
315 *version = 0;
316 *max_len = 0;
317 ALOGD("Packet Filter not supported");
318 result = WIFI_SUCCESS;
319 }
320 cmd->releaseRef();
321 return result;
322}
d76317a7 323
5822f843
SP
324wifi_error wifi_set_packet_filter(wifi_interface_handle handle,
325 const u8 *program, u32 len)
326{
327 ALOGD("Setting APF program, halHandle = %p\n", handle);
328 AndroidPktFilterCommand *cmd = new AndroidPktFilterCommand(handle, program, len);
329 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
330 wifi_error result = (wifi_error)cmd->start();
331 cmd->releaseRef();
332 return result;
333}
d76317a7 334
5822f843
SP
335wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
336 u32 src_offset, u8 *host_dst, u32 length)
337{
338 ALOGD("Reading APF filter, halHandle = %p\n", handle);
339 AndroidPktFilterCommand *cmd = new AndroidPktFilterCommand(handle, src_offset, host_dst, length);
340 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
341 wifi_error result = (wifi_error)cmd->start();
342 cmd->releaseRef();
343 return result;
d76317a7
TK
344}
345
d59e4b54 346/* Initialize HAL function pointer table */
7753f181
DD
347wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn)
348{
349 if (fn == NULL) {
350 return WIFI_ERROR_UNKNOWN;
351 }
352 fn->wifi_initialize = wifi_initialize;
353 fn->wifi_cleanup = wifi_cleanup;
354 fn->wifi_event_loop = wifi_event_loop;
355 fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
356 fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
357 fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui;
358 fn->wifi_get_ifaces = wifi_get_ifaces;
359 fn->wifi_get_iface_name = wifi_get_iface_name;
360 fn->wifi_start_gscan = wifi_start_gscan;
361 fn->wifi_stop_gscan = wifi_stop_gscan;
362 fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
7753f181 363 fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
7753f181
DD
364 fn->wifi_get_valid_channels = wifi_get_valid_channels;
365 fn->wifi_rtt_range_request = wifi_rtt_range_request;
366 fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
367 fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
368 fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
f0567d5c 369 fn->wifi_start_sending_offloaded_packet = wifi_start_sending_offloaded_packet;
3c0c6ab1 370 fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
6ff2d683 371 fn->wifi_set_epno_list = wifi_set_epno_list;
c15187c1 372 fn->wifi_reset_epno_list = wifi_reset_epno_list;
6ff2d683
JPS
373 fn->wifi_set_passpoint_list = wifi_set_passpoint_list;
374 fn->wifi_reset_passpoint_list = wifi_reset_passpoint_list;
f425b4a8
PG
375 fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
376 fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
d583845d 377 fn->wifi_set_link_stats = wifi_set_link_stats;
058cae5f 378 fn->wifi_get_link_stats = wifi_get_link_stats;
d583845d 379 fn->wifi_clear_link_stats = wifi_clear_link_stats;
1fdbd4c1 380 fn->wifi_set_country_code = wifi_set_country_code;
02b2b8ab 381 fn->wifi_configure_roaming = wifi_configure_roaming;
de14a5c9 382 fn->wifi_configure_nd_offload = wifi_configure_nd_offload;
cdc775c7
HG
383 fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring;
384 fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;
385 fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;
386 fn->wifi_start_logging = wifi_start_logging;
387 fn->wifi_set_log_handler = wifi_set_log_handler;
388 fn->wifi_set_alert_handler= wifi_set_alert_handler;
389 fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
390 fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;
391 fn->wifi_get_ring_data = wifi_get_ring_data;
392 fn->wifi_get_driver_version = wifi_get_driver_version;
393 fn->wifi_get_firmware_version = wifi_get_firmware_version;
394 fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
395 fn->wifi_get_driver_memory_dump = wifi_get_driver_memory_dump;
396 fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats;
d3a587e8
JPS
397 fn->wifi_nan_enable_request = nan_enable_request;
398 fn->wifi_nan_disable_request = nan_disable_request;
399 fn->wifi_nan_publish_request = nan_publish_request;
400 fn->wifi_nan_publish_cancel_request = nan_publish_cancel_request;
401 fn->wifi_nan_subscribe_request = nan_subscribe_request;
402 fn->wifi_nan_subscribe_cancel_request = nan_subscribe_cancel_request;
403 fn->wifi_nan_transmit_followup_request = nan_transmit_followup_request;
404 fn->wifi_nan_config_request = nan_config_request;
405 fn->wifi_nan_register_handler = nan_register_handler;
406 fn->wifi_nan_get_version = nan_get_version;
407 fn->wifi_nan_get_capabilities = nan_get_capabilities;
082f0000
JPS
408 fn->wifi_nan_data_interface_create = nan_data_interface_create;
409 fn->wifi_nan_data_interface_delete = nan_data_interface_delete;
410 fn->wifi_nan_data_request_initiator = nan_data_request_initiator;
411 fn->wifi_nan_data_indication_response = nan_data_indication_response;
412 fn->wifi_nan_data_end = nan_data_end;
47e18f37
JPS
413 fn->wifi_get_roaming_capabilities = wifi_get_roaming_capabilities;
414 fn->wifi_enable_firmware_roaming = wifi_enable_firmware_roaming;
5822f843
SP
415 fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
416 fn->wifi_set_packet_filter = wifi_set_packet_filter;
417 fn->wifi_read_packet_filter = wifi_read_packet_filter;
f8204f99 418 fn->wifi_set_latency_mode = wifi_set_latency_mode;
d1c19a13 419
7753f181
DD
420 return WIFI_SUCCESS;
421}
422
423wifi_error wifi_initialize(wifi_handle *handle)
424{
425 srand(getpid());
426
427 ALOGI("Initializing wifi");
428 hal_info *info = (hal_info *)malloc(sizeof(hal_info));
429 if (info == NULL) {
430 ALOGE("Could not allocate hal_info");
431 return WIFI_ERROR_UNKNOWN;
432 }
433
434 memset(info, 0, sizeof(*info));
435
7753f181
DD
436 if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->cleanup_socks) == -1) {
437 ALOGE("Could not create cleanup sockets");
438 free(info);
439 return WIFI_ERROR_UNKNOWN;
440 }
441
442 struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT);
443 if (cmd_sock == NULL) {
444 ALOGE("Could not create handle");
445 free(info);
446 return WIFI_ERROR_UNKNOWN;
447 }
448
449 struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT);
450 if (event_sock == NULL) {
451 ALOGE("Could not create handle");
452 nl_socket_free(cmd_sock);
453 free(info);
454 return WIFI_ERROR_UNKNOWN;
455 }
456
457 struct nl_cb *cb = nl_socket_get_cb(event_sock);
458 if (cb == NULL) {
459 ALOGE("Could not create handle");
460 nl_socket_free(cmd_sock);
461 nl_socket_free(event_sock);
462 free(info);
463 return WIFI_ERROR_UNKNOWN;
464 }
465
466// ALOGI("cb->refcnt = %d", cb->cb_refcnt);
467 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, info);
468 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info);
469 nl_cb_put(cb);
470
471 info->cmd_sock = cmd_sock;
472 info->event_sock = event_sock;
473 info->clean_up = false;
474 info->in_event_loop = false;
475
476 info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
477 info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
478 info->num_event_cb = 0;
479
480 info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
481 info->alloc_cmd = DEFAULT_CMD_SIZE;
482 info->num_cmd = 0;
483
484 info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
485 if (info->nl80211_family_id < 0) {
486 ALOGE("Could not resolve nl80211 familty id");
487 nl_socket_free(cmd_sock);
488 nl_socket_free(event_sock);
489 free(info);
490 return WIFI_ERROR_UNKNOWN;
491 }
492
493 pthread_mutex_init(&info->cb_lock, NULL);
494
495 *handle = (wifi_handle) info;
7753f181
DD
496 wifi_add_membership(*handle, "scan");
497 wifi_add_membership(*handle, "mlme");
498 wifi_add_membership(*handle, "regulatory");
499 wifi_add_membership(*handle, "vendor");
500
501 wifi_init_interfaces(*handle);
c0b490a2
JPS
502 char intf_name_buff[10 * 10 + 4]; /* Randomly choosen max interface 10. each interface name max 9 + 1(for space) */
503 char *pos = intf_name_buff;
504 for (int i = 0; i < (info->num_interfaces < 10 ? info->num_interfaces : 10); i++) {
505 strncpy(pos, info->interfaces[i]->name, sizeof(intf_name_buff) - (pos - intf_name_buff));
506 pos += strlen(pos);
507 }
508 if (info->num_interfaces > 10) {
509 strncpy(pos, "...", 3);
510 }
7753f181 511
c0b490a2 512 ALOGD("Found %d interfaces[%s]. Initialized Wifi HAL Successfully", info->num_interfaces, intf_name_buff);
7753f181 513
7753f181
DD
514 return WIFI_SUCCESS;
515}
516
517static int wifi_add_membership(wifi_handle handle, const char *group)
518{
519 hal_info *info = getHalInfo(handle);
520
521 int id = wifi_get_multicast_id(handle, "nl80211", group);
522 if (id < 0) {
523 ALOGE("Could not find group %s", group);
524 return id;
525 }
526
527 int ret = nl_socket_add_membership(info->event_sock, id);
528 if (ret < 0) {
529 ALOGE("Could not add membership to group %s", group);
530 }
7753f181
DD
531 return ret;
532}
533
534static void internal_cleaned_up_handler(wifi_handle handle)
535{
536 hal_info *info = getHalInfo(handle);
537 wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
538
539 if (info->cmd_sock != 0) {
540 close(info->cleanup_socks[0]);
541 close(info->cleanup_socks[1]);
542 nl_socket_free(info->cmd_sock);
543 nl_socket_free(info->event_sock);
544 info->cmd_sock = NULL;
545 info->event_sock = NULL;
546 }
547
548 (*cleaned_up_handler)(handle);
549 pthread_mutex_destroy(&info->cb_lock);
550 free(info);
7753f181
DD
551}
552
553void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
554{
555 hal_info *info = getHalInfo(handle);
556 char buf[64];
557
558 info->cleaned_up_handler = handler;
559 if (write(info->cleanup_socks[0], "Exit", 4) < 1) {
560 ALOGE("could not write to the cleanup socket");
561 } else {
562 // Listen to the response
563 // Hopefully we dont get errors or get hung up
564 // Not much can be done in that case, but assume that
565 // it has rx'ed the Exit message to exit the thread.
566 // As a fallback set the cleanup flag to TRUE
567 memset(buf, 0, sizeof(buf));
568 int result = read(info->cleanup_socks[0], buf, sizeof(buf));
569 ALOGE("%s: Read after POLL returned %d, error no = %d", __FUNCTION__, result, errno);
c0b490a2 570 if (strncmp(buf, "Done", 4) != 0) {
7753f181
DD
571 ALOGD("Rx'ed %s", buf);
572 }
573 }
574 info->clean_up = true;
575 pthread_mutex_lock(&info->cb_lock);
576
577 int bad_commands = 0;
578
7753f181
DD
579 while (info->num_cmd > bad_commands) {
580 int num_cmd = info->num_cmd;
581 cmd_info *cmdi = &(info->cmd[bad_commands]);
582 WifiCommand *cmd = cmdi->cmd;
583 if (cmd != NULL) {
584 pthread_mutex_unlock(&info->cb_lock);
585 cmd->cancel();
586 pthread_mutex_lock(&info->cb_lock);
587 /* release reference added when command is saved */
588 cmd->releaseRef();
589 if (num_cmd == info->num_cmd) {
590 bad_commands++;
591 }
592 }
593 }
594
595 for (int i = 0; i < info->num_event_cb; i++) {
596 cb_info *cbi = &(info->event_cb[i]);
597 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
598 ALOGE("Leaked command %p", cmd);
599 }
600 pthread_mutex_unlock(&info->cb_lock);
601 internal_cleaned_up_handler(handle);
602}
603
604static int internal_pollin_handler(wifi_handle handle)
605{
606 hal_info *info = getHalInfo(handle);
7753f181
DD
607 struct nl_cb *cb = nl_socket_get_cb(info->event_sock);
608 int res = nl_recvmsgs(info->event_sock, cb);
7753f181
DD
609 nl_cb_put(cb);
610 return res;
611}
612
613/* Run event handler */
614void wifi_event_loop(wifi_handle handle)
615{
616 hal_info *info = getHalInfo(handle);
7753f181
DD
617 if (info->in_event_loop) {
618 return;
619 } else {
620 info->in_event_loop = true;
621 }
622
623 pollfd pfd[2];
624 memset(&pfd[0], 0, sizeof(pollfd) * 2);
625
626 pfd[0].fd = nl_socket_get_fd(info->event_sock);
627 pfd[0].events = POLLIN;
628 pfd[1].fd = info->cleanup_socks[1];
629 pfd[1].events = POLLIN;
630
631 char buf[2048];
632
633 do {
634 int timeout = -1; /* Infinite timeout */
635 pfd[0].revents = 0;
636 pfd[1].revents = 0;
637 int result = poll(pfd, 2, timeout);
638 if (result < 0) {
639 } else if (pfd[0].revents & POLLERR) {
c0b490a2 640 int prev_err = (int)errno;
7753f181 641 int result2 = read(pfd[0].fd, buf, sizeof(buf));
c0b490a2 642 ALOGE("Poll err:%d | Read after POLL returned %d, error no = %d", prev_err, result2, errno);
7753f181
DD
643 } else if (pfd[0].revents & POLLHUP) {
644 ALOGE("Remote side hung up");
645 break;
646 } else if (pfd[0].revents & POLLIN) {
647 internal_pollin_handler(handle);
648 } else if (pfd[1].revents & POLLIN) {
649 memset(buf, 0, sizeof(buf));
650 int result2 = read(pfd[1].fd, buf, sizeof(buf));
651 ALOGE("%s: Read after POLL returned %d, error no = %d", __FUNCTION__, result2, errno);
652 if (strncmp(buf, "Exit", 4) == 0) {
653 ALOGD("Got a signal to exit!!!");
654 if (write(pfd[1].fd, "Done", 4) < 1) {
655 ALOGE("could not write to the cleanup socket");
656 }
657 break;
658 } else {
659 ALOGD("Rx'ed %s on the cleanup socket\n", buf);
660 }
661 } else {
662 ALOGE("Unknown event - %0x, %0x", pfd[0].revents, pfd[1].revents);
663 }
664 } while (!info->clean_up);
7753f181
DD
665}
666
667///////////////////////////////////////////////////////////////////////////////////////
668
669static int internal_no_seq_check(struct nl_msg *msg, void *arg)
670{
671 return NL_OK;
672}
673
674static int internal_valid_message_handler(nl_msg *msg, void *arg)
675{
676 wifi_handle handle = (wifi_handle)arg;
677 hal_info *info = getHalInfo(handle);
7753f181
DD
678
679 WifiEvent event(msg);
680 int res = event.parse();
681 if (res < 0) {
682 ALOGE("Failed to parse event: %d", res);
683 return NL_SKIP;
684 }
685
686 int cmd = event.get_cmd();
687 uint32_t vendor_id = 0;
688 int subcmd = 0;
689
690 if (cmd == NL80211_CMD_VENDOR) {
691 vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
692 subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
d20effd2 693 /*
7753f181 694 ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
d20effd2 695 event.get_cmdString(), vendor_id, subcmd);*/
7753f181
DD
696 }
697
698 //ALOGI("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id);
699 //event.log();
700
7753f181 701 pthread_mutex_lock(&info->cb_lock);
3c0c6ab1 702
7753f181
DD
703 for (int i = 0; i < info->num_event_cb; i++) {
704 if (cmd == info->event_cb[i].nl_cmd) {
705 if (cmd == NL80211_CMD_VENDOR
706 && ((vendor_id != info->event_cb[i].vendor_id)
707 || (subcmd != info->event_cb[i].vendor_subcmd)))
708 {
709 /* event for a different vendor, ignore it */
710 continue;
711 }
712
713 cb_info *cbi = &(info->event_cb[i]);
714 nl_recvmsg_msg_cb_t cb_func = cbi->cb_func;
715 void *cb_arg = cbi->cb_arg;
716 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
717 if (cmd != NULL) {
718 cmd->addRef();
719 }
720
721 pthread_mutex_unlock(&info->cb_lock);
722 if (cb_func)
723 (*cb_func)(msg, cb_arg);
724 if (cmd != NULL) {
725 cmd->releaseRef();
726 }
727
728 return NL_OK;
729 }
730 }
731
732 pthread_mutex_unlock(&info->cb_lock);
733 return NL_OK;
734}
735
736///////////////////////////////////////////////////////////////////////////////////////
737
738class GetMulticastIdCommand : public WifiCommand
739{
740private:
741 const char *mName;
742 const char *mGroup;
743 int mId;
744public:
745 GetMulticastIdCommand(wifi_handle handle, const char *name, const char *group)
746 : WifiCommand(handle, 0)
747 {
748 mName = name;
749 mGroup = group;
750 mId = -1;
751 }
752
753 int getId() {
754 return mId;
755 }
756
757 virtual int create() {
758 int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
7753f181
DD
759 int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
760 if (ret < 0) {
761 return ret;
762 }
763 ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
764 return ret;
765 }
766
767 virtual int handleResponse(WifiEvent& reply) {
7753f181 768 struct nlattr **tb = reply.attributes();
7753f181
DD
769 struct nlattr *mcgrp = NULL;
770 int i;
771
772 if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
773 ALOGE("No multicast groups found");
774 return NL_SKIP;
7753f181
DD
775 }
776
777 for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
778
7753f181
DD
779 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
780 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
781 nla_len(mcgrp), NULL);
782 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID]) {
783 continue;
784 }
785
786 char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
787 int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
788
7753f181
DD
789 if (strncmp(grpName, mGroup, grpNameLen) != 0)
790 continue;
791
792 mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
793 break;
794 }
795
796 return NL_SKIP;
797 }
798
799};
800
801class SetPnoMacAddrOuiCommand : public WifiCommand {
802
803private:
804 byte *mOui;
805 feature_set *fset;
806 feature_set *feature_matrix;
807 int *fm_size;
808 int set_size_max;
809public:
810 SetPnoMacAddrOuiCommand(wifi_interface_handle handle, oui scan_oui)
811 : WifiCommand(handle, 0)
812 {
813 mOui = scan_oui;
ec386ae4
HG
814 fset = NULL;
815 feature_matrix = NULL;
816 fm_size = NULL;
817 set_size_max = 0;
7753f181
DD
818 }
819
820 int createRequest(WifiRequest& request, int subcmd, byte *scan_oui) {
821 int result = request.create(GOOGLE_OUI, subcmd);
822 if (result < 0) {
823 return result;
824 }
825
826 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
827 result = request.put(ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, scan_oui, DOT11_OUI_LEN);
828 if (result < 0) {
829 return result;
830 }
831
832 request.attr_end(data);
833 return WIFI_SUCCESS;
834
835 }
836
837 int start() {
7753f181
DD
838 WifiRequest request(familyId(), ifaceId());
839 int result = createRequest(request, SLSI_NL80211_VENDOR_SUBCMD_SET_GSCAN_OUI, mOui);
840 if (result != WIFI_SUCCESS) {
841 ALOGE("failed to create request; result = %d", result);
842 return result;
843 }
844
845 result = requestResponse(request);
846 if (result != WIFI_SUCCESS) {
847 ALOGE("failed to set scanning mac OUI; result = %d", result);
848 }
849
850 return result;
851 }
852protected:
853 virtual int handleResponse(WifiEvent& reply) {
7753f181
DD
854 /* Nothing to do on response! */
855 return NL_SKIP;
856 }
857};
858
859class SetNodfsCommand : public WifiCommand {
860
861private:
862 u32 mNoDfs;
863public:
864 SetNodfsCommand(wifi_interface_handle handle, u32 nodfs)
865 : WifiCommand(handle, 0) {
866 mNoDfs = nodfs;
867 }
868 virtual int create() {
869 int ret;
870
871 ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_NODFS);
872 if (ret < 0) {
873 ALOGE("Can't create message to send to driver - %d", ret);
874 return ret;
875 }
876
877 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
878 ret = mMsg.put_u32(ATTR_NODFS_VALUE, mNoDfs);
879 if (ret < 0) {
880 return ret;
881 }
882
883 mMsg.attr_end(data);
884 return WIFI_SUCCESS;
885 }
886};
887
f425b4a8
PG
888class SetRSSIMonitorCommand : public WifiCommand {
889private:
890 s8 mMax_rssi;
891 s8 mMin_rssi;
892 wifi_rssi_event_handler mHandler;
893public:
894 SetRSSIMonitorCommand(wifi_request_id id, wifi_interface_handle handle,
895 s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
896 : WifiCommand(handle, id), mMax_rssi(max_rssi), mMin_rssi
897 (min_rssi), mHandler(eh)
898 {
899 }
900 int createRequest(WifiRequest& request, int enable) {
901 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_RSSI_MONITOR);
902 if (result < 0) {
903 return result;
904 }
905
906 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
907 result = request.put_u8(RSSI_MONITOR_ATTRIBUTE_MAX_RSSI, (enable ? mMax_rssi: 0));
908 if (result < 0) {
909 return result;
910 }
c0b490a2 911
f425b4a8
PG
912 result = request.put_u8(RSSI_MONITOR_ATTRIBUTE_MIN_RSSI, (enable? mMin_rssi: 0));
913 if (result < 0) {
914 return result;
915 }
916 result = request.put_u8(RSSI_MONITOR_ATTRIBUTE_START, enable);
917 if (result < 0) {
918 return result;
919 }
920 request.attr_end(data);
921 return result;
922 }
923
924 int start() {
925 WifiRequest request(familyId(), ifaceId());
926 int result = createRequest(request, 1);
927 if (result < 0) {
928 return result;
929 }
930 result = requestResponse(request);
931 if (result < 0) {
932 ALOGI("Failed to set RSSI Monitor, result = %d", result);
933 return result;
934 }
935 ALOGI("Successfully set RSSI monitoring");
936 registerVendorHandler(GOOGLE_OUI, WIFI_RSSI_REPORT_EVENT);
937
f425b4a8
PG
938 return result;
939 }
940
941 virtual int cancel() {
942
943 WifiRequest request(familyId(), ifaceId());
944 int result = createRequest(request, 0);
945 if (result != WIFI_SUCCESS) {
946 ALOGE("failed to create request; result = %d", result);
947 } else {
948 result = requestResponse(request);
949 if (result != WIFI_SUCCESS) {
950 ALOGE("failed to stop RSSI monitoring = %d", result);
951 }
952 }
953 unregisterVendorHandler(GOOGLE_OUI, WIFI_RSSI_REPORT_EVENT);
954 return WIFI_SUCCESS;
955 }
956
957 virtual int handleResponse(WifiEvent& reply) {
958 /* Nothing to do on response! */
959 return NL_SKIP;
960 }
961
962 virtual int handleEvent(WifiEvent& event) {
f425b4a8
PG
963
964 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
965 int len = event.get_vendor_data_len();
966
967 if (vendor_data == NULL || len == 0) {
968 ALOGI("RSSI monitor: No data");
969 return NL_SKIP;
970 }
971
972 typedef struct {
973 s8 cur_rssi;
974 mac_addr BSSID;
975 } rssi_monitor_evt;
976
977 rssi_monitor_evt *data = (rssi_monitor_evt *)event.get_vendor_data();
978
979 if (*mHandler.on_rssi_threshold_breached) {
980 (*mHandler.on_rssi_threshold_breached)(id(), data->BSSID, data->cur_rssi);
981 } else {
982 ALOGW("No RSSI monitor handler registered");
983 }
984
985 return NL_SKIP;
986 }
987
988};
989
1fdbd4c1
MG
990class SetCountryCodeCommand : public WifiCommand {
991private:
992 const char *mCountryCode;
993public:
994 SetCountryCodeCommand(wifi_interface_handle handle, const char *country_code)
995 : WifiCommand(handle, 0) {
996 mCountryCode = country_code;
997 }
998 virtual int create() {
999 int ret;
1000
1001 ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_COUNTRY_CODE);
1002 if (ret < 0) {
1003 ALOGE("Can't create message to send to driver - %d", ret);
1004 return ret;
1005 }
1006
1007 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
1008 ret = mMsg.put_string(ATTR_COUNTRY_CODE, mCountryCode);
1009 if (ret < 0) {
1010 return ret;
1011 }
1012
1013 mMsg.attr_end(data);
1014 return WIFI_SUCCESS;
1015
1016 }
1017};
1018
0318783f 1019class GetFeatureSetCommand : public WifiCommand {
f425b4a8 1020
0318783f 1021private:
0fe9bfaf 1022
0318783f 1023 feature_set *fset;
0fe9bfaf 1024
0318783f
JPS
1025public:
1026 GetFeatureSetCommand(wifi_interface_handle handle, feature_set *set)
1027 : WifiCommand(handle, 0)
1028 {
1029 fset = set;
1030 }
1031
1032 virtual int create() {
1033 int ret;
1034
1035 ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_GET_FEATURE_SET);
1036 if (ret < 0) {
1037 ALOGE("create failed - %d", ret);
1038 }
1039
1040 return ret;
1041 }
1042
1043protected:
1044 virtual int handleResponse(WifiEvent& reply) {
1045
0318783f
JPS
1046 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1047 ALOGD("Ignore reply; cmd = %d", reply.get_cmd());
1048 return NL_SKIP;
1049 }
1050
1051 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1052 int len = reply.get_vendor_data_len();
1053
1054 if (vendor_data == NULL || len == 0) {
1055 ALOGE("vendor data in GetFeatureSetCommand missing!!");
1056 return NL_SKIP;
1057 }
1058
1059 void *data = reply.get_vendor_data();
1060 if(!fset) {
1061 ALOGE("feature_set Pointer not set");
1062 return NL_SKIP;
1063 }
1064 memcpy(fset, data, min(len, (int) sizeof(*fset)));
1065 return NL_OK;
1066 }
1067
1068};
f425b4a8 1069
f8204f99
AC
1070class SetLatencyLockCommand : public WifiCommand {
1071private:
1072 wifi_latency_mode mMode;
1073public:
1074 SetLatencyLockCommand(wifi_interface_handle handle, wifi_latency_mode mode)
1075 : WifiCommand(handle, 0) {
1076 mMode = mode;
1077 }
1078 virtual int create() {
1079 int ret;
1080
1081 ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_LATENCY_MODE);
1082 if (ret < 0) {
1083 ALOGE("Can't create message to send to driver - %d", ret);
1084 return ret;
1085 }
de14a5c9 1086
f8204f99
AC
1087 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
1088 ret = mMsg.put_u8(ATTR_LOW_LATENCY_MODE, mMode);
1089 if (ret < 0) {
1090 return ret;
1091 }
1092
1093 mMsg.attr_end(data);
1094 return WIFI_SUCCESS;
1095 }
1096};
de14a5c9 1097
7753f181
DD
1098static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group)
1099{
1100 GetMulticastIdCommand cmd(handle, name, group);
1101 int res = cmd.requestResponse();
1102 if (res < 0)
1103 return res;
1104 else
1105 return cmd.getId();
1106}
1107
1108/////////////////////////////////////////////////////////////////////////
1109
1110static bool is_wifi_interface(const char *name)
1111{
1112 if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
1113 /* not a wifi interface; ignore it */
1114 return false;
1115 } else {
1116 return true;
1117 }
1118}
1119
1120static int get_interface(const char *name, interface_info *info)
1121{
1122 strcpy(info->name, name);
1123 info->id = if_nametoindex(name);
7753f181
DD
1124 return WIFI_SUCCESS;
1125}
1126
1127wifi_error wifi_init_interfaces(wifi_handle handle)
1128{
1129 hal_info *info = (hal_info *)handle;
7753f181
DD
1130 struct dirent *de;
1131
1132 DIR *d = opendir("/sys/class/net");
1133 if (d == 0)
1134 return WIFI_ERROR_UNKNOWN;
1135
1136 int n = 0;
1137 while ((de = readdir(d))) {
1138 if (de->d_name[0] == '.')
1139 continue;
1140 if (is_wifi_interface(de->d_name) ) {
1141 n++;
1142 }
1143 }
1144
1145 closedir(d);
1146
1147 d = opendir("/sys/class/net");
1148 if (d == 0)
1149 return WIFI_ERROR_UNKNOWN;
1150
1151 info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
1152
1153 int i = 0;
1154 while ((de = readdir(d))) {
1155 if (de->d_name[0] == '.')
1156 continue;
1157 if (is_wifi_interface(de->d_name)) {
1158 interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info));
1159 if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
1160 free(ifinfo);
1161 continue;
1162 }
1163 ifinfo->handle = handle;
1164 info->interfaces[i] = ifinfo;
1165 i++;
1166 }
1167 }
1168
1169 closedir(d);
1170
1171 info->num_interfaces = n;
1172 return WIFI_SUCCESS;
1173}
1174
1175wifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle **interfaces)
1176{
1177 hal_info *info = (hal_info *)handle;
1178
1179 *interfaces = (wifi_interface_handle *)info->interfaces;
1180 *num = info->num_interfaces;
1181
1182 return WIFI_SUCCESS;
1183}
1184
1185wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size)
1186{
1187 interface_info *info = (interface_info *)handle;
1188 strcpy(name, info->name);
1189 return WIFI_SUCCESS;
1190}
1191
7753f181
DD
1192wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_size_max,
1193 feature_set set[], int *set_size)
1194{
1195 return WIFI_ERROR_NOT_SUPPORTED;
1196}
1197
1198wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui)
1199{
046aeb41
HG
1200 SetPnoMacAddrOuiCommand command(handle, scan_oui);
1201 return (wifi_error)command.start();
1202
7753f181
DD
1203}
1204
1205wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
1206{
1207 SetNodfsCommand command(handle, nodfs);
1208 return (wifi_error) command.requestResponse();
1209}
1210
f425b4a8
PG
1211static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
1212 iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
1213{
1214 ALOGD("Start RSSI monitor %d", id);
1215 wifi_handle handle = getWifiHandle(iface);
1216 SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface, max_rssi, min_rssi, eh);
1217 wifi_register_cmd(handle, id, cmd);
1218
1219 wifi_error result = (wifi_error)cmd->start();
1220 if (result != WIFI_SUCCESS) {
1221 wifi_unregister_cmd(handle, id);
1222 }
1223 return result;
1224}
1225
1226
1227static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface)
1228{
1229 ALOGD("Stopping RSSI monitor");
1230
1231 if(id == -1) {
1232 wifi_rssi_event_handler handler;
f425b4a8
PG
1233 memset(&handler, 0, sizeof(handler));
1234 SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface,
1235 0, 0, handler);
1236 cmd->cancel();
1237 cmd->releaseRef();
1238 return WIFI_SUCCESS;
1239 }
1240 return wifi_cancel_cmd(id, iface);
1241}
1242
0318783f
JPS
1243wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *set)
1244{
1245 GetFeatureSetCommand command(handle, set);
1246 return (wifi_error) command.requestResponse();
1247}
1248
1fdbd4c1
MG
1249wifi_error wifi_set_country_code(wifi_interface_handle handle, const char *country_code)
1250{
1251 SetCountryCodeCommand command(handle, country_code);
1252 return (wifi_error) command.requestResponse();
1253}
1254
f8204f99
AC
1255wifi_error wifi_set_latency_mode(wifi_interface_handle handle, wifi_latency_mode mode) {
1256 SetLatencyLockCommand cmd(handle, mode);
1257 return (wifi_error) cmd.requestResponse();
1258}
114ef2d7
HG
1259/////////////////////////////////////////////////////////////////////////////
1260