[APR-1645] wlbt: Initialize variables in APF code
[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;
47e18f37
JPS
408 fn->wifi_get_roaming_capabilities = wifi_get_roaming_capabilities;
409 fn->wifi_enable_firmware_roaming = wifi_enable_firmware_roaming;
5822f843
SP
410 fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
411 fn->wifi_set_packet_filter = wifi_set_packet_filter;
412 fn->wifi_read_packet_filter = wifi_read_packet_filter;
f8204f99 413 fn->wifi_set_latency_mode = wifi_set_latency_mode;
d1c19a13 414
7753f181
DD
415 return WIFI_SUCCESS;
416}
417
418wifi_error wifi_initialize(wifi_handle *handle)
419{
420 srand(getpid());
421
422 ALOGI("Initializing wifi");
423 hal_info *info = (hal_info *)malloc(sizeof(hal_info));
424 if (info == NULL) {
425 ALOGE("Could not allocate hal_info");
426 return WIFI_ERROR_UNKNOWN;
427 }
428
429 memset(info, 0, sizeof(*info));
430
7753f181
DD
431 if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->cleanup_socks) == -1) {
432 ALOGE("Could not create cleanup sockets");
433 free(info);
434 return WIFI_ERROR_UNKNOWN;
435 }
436
437 struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT);
438 if (cmd_sock == NULL) {
439 ALOGE("Could not create handle");
440 free(info);
441 return WIFI_ERROR_UNKNOWN;
442 }
443
444 struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT);
445 if (event_sock == NULL) {
446 ALOGE("Could not create handle");
447 nl_socket_free(cmd_sock);
448 free(info);
449 return WIFI_ERROR_UNKNOWN;
450 }
451
452 struct nl_cb *cb = nl_socket_get_cb(event_sock);
453 if (cb == NULL) {
454 ALOGE("Could not create handle");
455 nl_socket_free(cmd_sock);
456 nl_socket_free(event_sock);
457 free(info);
458 return WIFI_ERROR_UNKNOWN;
459 }
460
461// ALOGI("cb->refcnt = %d", cb->cb_refcnt);
462 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, info);
463 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info);
464 nl_cb_put(cb);
465
466 info->cmd_sock = cmd_sock;
467 info->event_sock = event_sock;
468 info->clean_up = false;
469 info->in_event_loop = false;
470
471 info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
472 info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
473 info->num_event_cb = 0;
474
475 info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
476 info->alloc_cmd = DEFAULT_CMD_SIZE;
477 info->num_cmd = 0;
478
479 info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
480 if (info->nl80211_family_id < 0) {
481 ALOGE("Could not resolve nl80211 familty id");
482 nl_socket_free(cmd_sock);
483 nl_socket_free(event_sock);
484 free(info);
485 return WIFI_ERROR_UNKNOWN;
486 }
487
488 pthread_mutex_init(&info->cb_lock, NULL);
489
490 *handle = (wifi_handle) info;
7753f181
DD
491 wifi_add_membership(*handle, "scan");
492 wifi_add_membership(*handle, "mlme");
493 wifi_add_membership(*handle, "regulatory");
494 wifi_add_membership(*handle, "vendor");
495
496 wifi_init_interfaces(*handle);
c0b490a2
JPS
497 char intf_name_buff[10 * 10 + 4]; /* Randomly choosen max interface 10. each interface name max 9 + 1(for space) */
498 char *pos = intf_name_buff;
499 for (int i = 0; i < (info->num_interfaces < 10 ? info->num_interfaces : 10); i++) {
500 strncpy(pos, info->interfaces[i]->name, sizeof(intf_name_buff) - (pos - intf_name_buff));
501 pos += strlen(pos);
502 }
503 if (info->num_interfaces > 10) {
504 strncpy(pos, "...", 3);
505 }
7753f181 506
c0b490a2 507 ALOGD("Found %d interfaces[%s]. Initialized Wifi HAL Successfully", info->num_interfaces, intf_name_buff);
7753f181 508
7753f181
DD
509 return WIFI_SUCCESS;
510}
511
512static int wifi_add_membership(wifi_handle handle, const char *group)
513{
514 hal_info *info = getHalInfo(handle);
515
516 int id = wifi_get_multicast_id(handle, "nl80211", group);
517 if (id < 0) {
518 ALOGE("Could not find group %s", group);
519 return id;
520 }
521
522 int ret = nl_socket_add_membership(info->event_sock, id);
523 if (ret < 0) {
524 ALOGE("Could not add membership to group %s", group);
525 }
7753f181
DD
526 return ret;
527}
528
529static void internal_cleaned_up_handler(wifi_handle handle)
530{
531 hal_info *info = getHalInfo(handle);
532 wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
533
534 if (info->cmd_sock != 0) {
535 close(info->cleanup_socks[0]);
536 close(info->cleanup_socks[1]);
537 nl_socket_free(info->cmd_sock);
538 nl_socket_free(info->event_sock);
539 info->cmd_sock = NULL;
540 info->event_sock = NULL;
541 }
542
543 (*cleaned_up_handler)(handle);
544 pthread_mutex_destroy(&info->cb_lock);
545 free(info);
7753f181
DD
546}
547
548void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
549{
550 hal_info *info = getHalInfo(handle);
551 char buf[64];
552
553 info->cleaned_up_handler = handler;
554 if (write(info->cleanup_socks[0], "Exit", 4) < 1) {
555 ALOGE("could not write to the cleanup socket");
556 } else {
557 // Listen to the response
558 // Hopefully we dont get errors or get hung up
559 // Not much can be done in that case, but assume that
560 // it has rx'ed the Exit message to exit the thread.
561 // As a fallback set the cleanup flag to TRUE
562 memset(buf, 0, sizeof(buf));
563 int result = read(info->cleanup_socks[0], buf, sizeof(buf));
564 ALOGE("%s: Read after POLL returned %d, error no = %d", __FUNCTION__, result, errno);
c0b490a2 565 if (strncmp(buf, "Done", 4) != 0) {
7753f181
DD
566 ALOGD("Rx'ed %s", buf);
567 }
568 }
569 info->clean_up = true;
570 pthread_mutex_lock(&info->cb_lock);
571
572 int bad_commands = 0;
573
7753f181
DD
574 while (info->num_cmd > bad_commands) {
575 int num_cmd = info->num_cmd;
576 cmd_info *cmdi = &(info->cmd[bad_commands]);
577 WifiCommand *cmd = cmdi->cmd;
578 if (cmd != NULL) {
579 pthread_mutex_unlock(&info->cb_lock);
580 cmd->cancel();
581 pthread_mutex_lock(&info->cb_lock);
582 /* release reference added when command is saved */
583 cmd->releaseRef();
584 if (num_cmd == info->num_cmd) {
585 bad_commands++;
586 }
587 }
588 }
589
590 for (int i = 0; i < info->num_event_cb; i++) {
591 cb_info *cbi = &(info->event_cb[i]);
592 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
593 ALOGE("Leaked command %p", cmd);
594 }
595 pthread_mutex_unlock(&info->cb_lock);
596 internal_cleaned_up_handler(handle);
597}
598
599static int internal_pollin_handler(wifi_handle handle)
600{
601 hal_info *info = getHalInfo(handle);
7753f181
DD
602 struct nl_cb *cb = nl_socket_get_cb(info->event_sock);
603 int res = nl_recvmsgs(info->event_sock, cb);
7753f181
DD
604 nl_cb_put(cb);
605 return res;
606}
607
608/* Run event handler */
609void wifi_event_loop(wifi_handle handle)
610{
611 hal_info *info = getHalInfo(handle);
7753f181
DD
612 if (info->in_event_loop) {
613 return;
614 } else {
615 info->in_event_loop = true;
616 }
617
618 pollfd pfd[2];
619 memset(&pfd[0], 0, sizeof(pollfd) * 2);
620
621 pfd[0].fd = nl_socket_get_fd(info->event_sock);
622 pfd[0].events = POLLIN;
623 pfd[1].fd = info->cleanup_socks[1];
624 pfd[1].events = POLLIN;
625
626 char buf[2048];
627
628 do {
629 int timeout = -1; /* Infinite timeout */
630 pfd[0].revents = 0;
631 pfd[1].revents = 0;
632 int result = poll(pfd, 2, timeout);
633 if (result < 0) {
634 } else if (pfd[0].revents & POLLERR) {
c0b490a2 635 int prev_err = (int)errno;
7753f181 636 int result2 = read(pfd[0].fd, buf, sizeof(buf));
c0b490a2 637 ALOGE("Poll err:%d | Read after POLL returned %d, error no = %d", prev_err, result2, errno);
7753f181
DD
638 } else if (pfd[0].revents & POLLHUP) {
639 ALOGE("Remote side hung up");
640 break;
641 } else if (pfd[0].revents & POLLIN) {
642 internal_pollin_handler(handle);
643 } else if (pfd[1].revents & POLLIN) {
644 memset(buf, 0, sizeof(buf));
645 int result2 = read(pfd[1].fd, buf, sizeof(buf));
646 ALOGE("%s: Read after POLL returned %d, error no = %d", __FUNCTION__, result2, errno);
647 if (strncmp(buf, "Exit", 4) == 0) {
648 ALOGD("Got a signal to exit!!!");
649 if (write(pfd[1].fd, "Done", 4) < 1) {
650 ALOGE("could not write to the cleanup socket");
651 }
652 break;
653 } else {
654 ALOGD("Rx'ed %s on the cleanup socket\n", buf);
655 }
656 } else {
657 ALOGE("Unknown event - %0x, %0x", pfd[0].revents, pfd[1].revents);
658 }
659 } while (!info->clean_up);
7753f181
DD
660}
661
662///////////////////////////////////////////////////////////////////////////////////////
663
664static int internal_no_seq_check(struct nl_msg *msg, void *arg)
665{
666 return NL_OK;
667}
668
669static int internal_valid_message_handler(nl_msg *msg, void *arg)
670{
671 wifi_handle handle = (wifi_handle)arg;
672 hal_info *info = getHalInfo(handle);
7753f181
DD
673
674 WifiEvent event(msg);
675 int res = event.parse();
676 if (res < 0) {
677 ALOGE("Failed to parse event: %d", res);
678 return NL_SKIP;
679 }
680
681 int cmd = event.get_cmd();
682 uint32_t vendor_id = 0;
683 int subcmd = 0;
684
685 if (cmd == NL80211_CMD_VENDOR) {
686 vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
687 subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
d20effd2 688 /*
7753f181 689 ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
d20effd2 690 event.get_cmdString(), vendor_id, subcmd);*/
7753f181
DD
691 }
692
693 //ALOGI("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id);
694 //event.log();
695
7753f181 696 pthread_mutex_lock(&info->cb_lock);
3c0c6ab1 697
7753f181
DD
698 for (int i = 0; i < info->num_event_cb; i++) {
699 if (cmd == info->event_cb[i].nl_cmd) {
700 if (cmd == NL80211_CMD_VENDOR
701 && ((vendor_id != info->event_cb[i].vendor_id)
702 || (subcmd != info->event_cb[i].vendor_subcmd)))
703 {
704 /* event for a different vendor, ignore it */
705 continue;
706 }
707
708 cb_info *cbi = &(info->event_cb[i]);
709 nl_recvmsg_msg_cb_t cb_func = cbi->cb_func;
710 void *cb_arg = cbi->cb_arg;
711 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
712 if (cmd != NULL) {
713 cmd->addRef();
714 }
715
716 pthread_mutex_unlock(&info->cb_lock);
717 if (cb_func)
718 (*cb_func)(msg, cb_arg);
719 if (cmd != NULL) {
720 cmd->releaseRef();
721 }
722
723 return NL_OK;
724 }
725 }
726
727 pthread_mutex_unlock(&info->cb_lock);
728 return NL_OK;
729}
730
731///////////////////////////////////////////////////////////////////////////////////////
732
733class GetMulticastIdCommand : public WifiCommand
734{
735private:
736 const char *mName;
737 const char *mGroup;
738 int mId;
739public:
740 GetMulticastIdCommand(wifi_handle handle, const char *name, const char *group)
741 : WifiCommand(handle, 0)
742 {
743 mName = name;
744 mGroup = group;
745 mId = -1;
746 }
747
748 int getId() {
749 return mId;
750 }
751
752 virtual int create() {
753 int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
7753f181
DD
754 int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
755 if (ret < 0) {
756 return ret;
757 }
758 ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
759 return ret;
760 }
761
762 virtual int handleResponse(WifiEvent& reply) {
7753f181 763 struct nlattr **tb = reply.attributes();
7753f181
DD
764 struct nlattr *mcgrp = NULL;
765 int i;
766
767 if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
768 ALOGE("No multicast groups found");
769 return NL_SKIP;
7753f181
DD
770 }
771
772 for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
773
7753f181
DD
774 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
775 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
776 nla_len(mcgrp), NULL);
777 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID]) {
778 continue;
779 }
780
781 char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
782 int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
783
7753f181
DD
784 if (strncmp(grpName, mGroup, grpNameLen) != 0)
785 continue;
786
787 mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
788 break;
789 }
790
791 return NL_SKIP;
792 }
793
794};
795
796class SetPnoMacAddrOuiCommand : public WifiCommand {
797
798private:
799 byte *mOui;
800 feature_set *fset;
801 feature_set *feature_matrix;
802 int *fm_size;
803 int set_size_max;
804public:
805 SetPnoMacAddrOuiCommand(wifi_interface_handle handle, oui scan_oui)
806 : WifiCommand(handle, 0)
807 {
808 mOui = scan_oui;
ec386ae4
HG
809 fset = NULL;
810 feature_matrix = NULL;
811 fm_size = NULL;
812 set_size_max = 0;
7753f181
DD
813 }
814
815 int createRequest(WifiRequest& request, int subcmd, byte *scan_oui) {
816 int result = request.create(GOOGLE_OUI, subcmd);
817 if (result < 0) {
818 return result;
819 }
820
821 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
822 result = request.put(ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, scan_oui, DOT11_OUI_LEN);
823 if (result < 0) {
824 return result;
825 }
826
827 request.attr_end(data);
828 return WIFI_SUCCESS;
829
830 }
831
832 int start() {
7753f181
DD
833 WifiRequest request(familyId(), ifaceId());
834 int result = createRequest(request, SLSI_NL80211_VENDOR_SUBCMD_SET_GSCAN_OUI, mOui);
835 if (result != WIFI_SUCCESS) {
836 ALOGE("failed to create request; result = %d", result);
837 return result;
838 }
839
840 result = requestResponse(request);
841 if (result != WIFI_SUCCESS) {
842 ALOGE("failed to set scanning mac OUI; result = %d", result);
843 }
844
845 return result;
846 }
847protected:
848 virtual int handleResponse(WifiEvent& reply) {
7753f181
DD
849 /* Nothing to do on response! */
850 return NL_SKIP;
851 }
852};
853
854class SetNodfsCommand : public WifiCommand {
855
856private:
857 u32 mNoDfs;
858public:
859 SetNodfsCommand(wifi_interface_handle handle, u32 nodfs)
860 : WifiCommand(handle, 0) {
861 mNoDfs = nodfs;
862 }
863 virtual int create() {
864 int ret;
865
866 ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_NODFS);
867 if (ret < 0) {
868 ALOGE("Can't create message to send to driver - %d", ret);
869 return ret;
870 }
871
872 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
873 ret = mMsg.put_u32(ATTR_NODFS_VALUE, mNoDfs);
874 if (ret < 0) {
875 return ret;
876 }
877
878 mMsg.attr_end(data);
879 return WIFI_SUCCESS;
880 }
881};
882
f425b4a8
PG
883class SetRSSIMonitorCommand : public WifiCommand {
884private:
885 s8 mMax_rssi;
886 s8 mMin_rssi;
887 wifi_rssi_event_handler mHandler;
888public:
889 SetRSSIMonitorCommand(wifi_request_id id, wifi_interface_handle handle,
890 s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
891 : WifiCommand(handle, id), mMax_rssi(max_rssi), mMin_rssi
892 (min_rssi), mHandler(eh)
893 {
894 }
895 int createRequest(WifiRequest& request, int enable) {
896 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_RSSI_MONITOR);
897 if (result < 0) {
898 return result;
899 }
900
901 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
902 result = request.put_u8(RSSI_MONITOR_ATTRIBUTE_MAX_RSSI, (enable ? mMax_rssi: 0));
903 if (result < 0) {
904 return result;
905 }
c0b490a2 906
f425b4a8
PG
907 result = request.put_u8(RSSI_MONITOR_ATTRIBUTE_MIN_RSSI, (enable? mMin_rssi: 0));
908 if (result < 0) {
909 return result;
910 }
911 result = request.put_u8(RSSI_MONITOR_ATTRIBUTE_START, enable);
912 if (result < 0) {
913 return result;
914 }
915 request.attr_end(data);
916 return result;
917 }
918
919 int start() {
920 WifiRequest request(familyId(), ifaceId());
921 int result = createRequest(request, 1);
922 if (result < 0) {
923 return result;
924 }
925 result = requestResponse(request);
926 if (result < 0) {
927 ALOGI("Failed to set RSSI Monitor, result = %d", result);
928 return result;
929 }
930 ALOGI("Successfully set RSSI monitoring");
931 registerVendorHandler(GOOGLE_OUI, WIFI_RSSI_REPORT_EVENT);
932
f425b4a8
PG
933 return result;
934 }
935
936 virtual int cancel() {
937
938 WifiRequest request(familyId(), ifaceId());
939 int result = createRequest(request, 0);
940 if (result != WIFI_SUCCESS) {
941 ALOGE("failed to create request; result = %d", result);
942 } else {
943 result = requestResponse(request);
944 if (result != WIFI_SUCCESS) {
945 ALOGE("failed to stop RSSI monitoring = %d", result);
946 }
947 }
948 unregisterVendorHandler(GOOGLE_OUI, WIFI_RSSI_REPORT_EVENT);
949 return WIFI_SUCCESS;
950 }
951
952 virtual int handleResponse(WifiEvent& reply) {
953 /* Nothing to do on response! */
954 return NL_SKIP;
955 }
956
957 virtual int handleEvent(WifiEvent& event) {
f425b4a8
PG
958
959 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
960 int len = event.get_vendor_data_len();
961
962 if (vendor_data == NULL || len == 0) {
963 ALOGI("RSSI monitor: No data");
964 return NL_SKIP;
965 }
966
967 typedef struct {
968 s8 cur_rssi;
969 mac_addr BSSID;
970 } rssi_monitor_evt;
971
972 rssi_monitor_evt *data = (rssi_monitor_evt *)event.get_vendor_data();
973
974 if (*mHandler.on_rssi_threshold_breached) {
975 (*mHandler.on_rssi_threshold_breached)(id(), data->BSSID, data->cur_rssi);
976 } else {
977 ALOGW("No RSSI monitor handler registered");
978 }
979
980 return NL_SKIP;
981 }
982
983};
984
1fdbd4c1
MG
985class SetCountryCodeCommand : public WifiCommand {
986private:
987 const char *mCountryCode;
988public:
989 SetCountryCodeCommand(wifi_interface_handle handle, const char *country_code)
990 : WifiCommand(handle, 0) {
991 mCountryCode = country_code;
992 }
993 virtual int create() {
994 int ret;
995
996 ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_COUNTRY_CODE);
997 if (ret < 0) {
998 ALOGE("Can't create message to send to driver - %d", ret);
999 return ret;
1000 }
1001
1002 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
1003 ret = mMsg.put_string(ATTR_COUNTRY_CODE, mCountryCode);
1004 if (ret < 0) {
1005 return ret;
1006 }
1007
1008 mMsg.attr_end(data);
1009 return WIFI_SUCCESS;
1010
1011 }
1012};
1013
0318783f 1014class GetFeatureSetCommand : public WifiCommand {
f425b4a8 1015
0318783f 1016private:
0fe9bfaf 1017
0318783f 1018 feature_set *fset;
0fe9bfaf 1019
0318783f
JPS
1020public:
1021 GetFeatureSetCommand(wifi_interface_handle handle, feature_set *set)
1022 : WifiCommand(handle, 0)
1023 {
1024 fset = set;
1025 }
1026
1027 virtual int create() {
1028 int ret;
1029
1030 ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_GET_FEATURE_SET);
1031 if (ret < 0) {
1032 ALOGE("create failed - %d", ret);
1033 }
1034
1035 return ret;
1036 }
1037
1038protected:
1039 virtual int handleResponse(WifiEvent& reply) {
1040
0318783f
JPS
1041 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1042 ALOGD("Ignore reply; cmd = %d", reply.get_cmd());
1043 return NL_SKIP;
1044 }
1045
1046 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1047 int len = reply.get_vendor_data_len();
1048
1049 if (vendor_data == NULL || len == 0) {
1050 ALOGE("vendor data in GetFeatureSetCommand missing!!");
1051 return NL_SKIP;
1052 }
1053
1054 void *data = reply.get_vendor_data();
1055 if(!fset) {
1056 ALOGE("feature_set Pointer not set");
1057 return NL_SKIP;
1058 }
1059 memcpy(fset, data, min(len, (int) sizeof(*fset)));
1060 return NL_OK;
1061 }
1062
1063};
f425b4a8 1064
f8204f99
AC
1065class SetLatencyLockCommand : public WifiCommand {
1066private:
1067 wifi_latency_mode mMode;
1068public:
1069 SetLatencyLockCommand(wifi_interface_handle handle, wifi_latency_mode mode)
1070 : WifiCommand(handle, 0) {
1071 mMode = mode;
1072 }
1073 virtual int create() {
1074 int ret;
1075
1076 ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_LATENCY_MODE);
1077 if (ret < 0) {
1078 ALOGE("Can't create message to send to driver - %d", ret);
1079 return ret;
1080 }
de14a5c9 1081
f8204f99
AC
1082 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
1083 ret = mMsg.put_u8(ATTR_LOW_LATENCY_MODE, mMode);
1084 if (ret < 0) {
1085 return ret;
1086 }
1087
1088 mMsg.attr_end(data);
1089 return WIFI_SUCCESS;
1090 }
1091};
de14a5c9 1092
7753f181
DD
1093static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group)
1094{
1095 GetMulticastIdCommand cmd(handle, name, group);
1096 int res = cmd.requestResponse();
1097 if (res < 0)
1098 return res;
1099 else
1100 return cmd.getId();
1101}
1102
1103/////////////////////////////////////////////////////////////////////////
1104
1105static bool is_wifi_interface(const char *name)
1106{
1107 if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
1108 /* not a wifi interface; ignore it */
1109 return false;
1110 } else {
1111 return true;
1112 }
1113}
1114
1115static int get_interface(const char *name, interface_info *info)
1116{
1117 strcpy(info->name, name);
1118 info->id = if_nametoindex(name);
7753f181
DD
1119 return WIFI_SUCCESS;
1120}
1121
1122wifi_error wifi_init_interfaces(wifi_handle handle)
1123{
1124 hal_info *info = (hal_info *)handle;
7753f181
DD
1125 struct dirent *de;
1126
1127 DIR *d = opendir("/sys/class/net");
1128 if (d == 0)
1129 return WIFI_ERROR_UNKNOWN;
1130
1131 int n = 0;
1132 while ((de = readdir(d))) {
1133 if (de->d_name[0] == '.')
1134 continue;
1135 if (is_wifi_interface(de->d_name) ) {
1136 n++;
1137 }
1138 }
1139
1140 closedir(d);
1141
1142 d = opendir("/sys/class/net");
1143 if (d == 0)
1144 return WIFI_ERROR_UNKNOWN;
1145
1146 info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
1147
1148 int i = 0;
1149 while ((de = readdir(d))) {
1150 if (de->d_name[0] == '.')
1151 continue;
1152 if (is_wifi_interface(de->d_name)) {
1153 interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info));
1154 if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
1155 free(ifinfo);
1156 continue;
1157 }
1158 ifinfo->handle = handle;
1159 info->interfaces[i] = ifinfo;
1160 i++;
1161 }
1162 }
1163
1164 closedir(d);
1165
1166 info->num_interfaces = n;
1167 return WIFI_SUCCESS;
1168}
1169
1170wifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle **interfaces)
1171{
1172 hal_info *info = (hal_info *)handle;
1173
1174 *interfaces = (wifi_interface_handle *)info->interfaces;
1175 *num = info->num_interfaces;
1176
1177 return WIFI_SUCCESS;
1178}
1179
1180wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size)
1181{
1182 interface_info *info = (interface_info *)handle;
1183 strcpy(name, info->name);
1184 return WIFI_SUCCESS;
1185}
1186
7753f181
DD
1187wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_size_max,
1188 feature_set set[], int *set_size)
1189{
1190 return WIFI_ERROR_NOT_SUPPORTED;
1191}
1192
1193wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui)
1194{
046aeb41
HG
1195 SetPnoMacAddrOuiCommand command(handle, scan_oui);
1196 return (wifi_error)command.start();
1197
7753f181
DD
1198}
1199
1200wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
1201{
1202 SetNodfsCommand command(handle, nodfs);
1203 return (wifi_error) command.requestResponse();
1204}
1205
f425b4a8
PG
1206static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
1207 iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
1208{
1209 ALOGD("Start RSSI monitor %d", id);
1210 wifi_handle handle = getWifiHandle(iface);
1211 SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface, max_rssi, min_rssi, eh);
1212 wifi_register_cmd(handle, id, cmd);
1213
1214 wifi_error result = (wifi_error)cmd->start();
1215 if (result != WIFI_SUCCESS) {
1216 wifi_unregister_cmd(handle, id);
1217 }
1218 return result;
1219}
1220
1221
1222static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface)
1223{
1224 ALOGD("Stopping RSSI monitor");
1225
1226 if(id == -1) {
1227 wifi_rssi_event_handler handler;
f425b4a8
PG
1228 memset(&handler, 0, sizeof(handler));
1229 SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface,
1230 0, 0, handler);
1231 cmd->cancel();
1232 cmd->releaseRef();
1233 return WIFI_SUCCESS;
1234 }
1235 return wifi_cancel_cmd(id, iface);
1236}
1237
0318783f
JPS
1238wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *set)
1239{
1240 GetFeatureSetCommand command(handle, set);
1241 return (wifi_error) command.requestResponse();
1242}
1243
1fdbd4c1
MG
1244wifi_error wifi_set_country_code(wifi_interface_handle handle, const char *country_code)
1245{
1246 SetCountryCodeCommand command(handle, country_code);
1247 return (wifi_error) command.requestResponse();
1248}
1249
f8204f99
AC
1250wifi_error wifi_set_latency_mode(wifi_interface_handle handle, wifi_latency_mode mode) {
1251 SetLatencyLockCommand cmd(handle, mode);
1252 return (wifi_error) cmd.requestResponse();
1253}
114ef2d7
HG
1254/////////////////////////////////////////////////////////////////////////////
1255