update wifi packages
[GitHub/mt8127/android_device_alcatel_ttab.git] / wifi_hal / wifi_hal.cpp
CommitLineData
f3fa1980 1#include <stdint.h>
c481cf08
JA
2#include <stdlib.h>
3#include <unistd.h>
f3fa1980
S
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#include <errno.h>
14#include <string.h>
15
16#include <linux/pkt_sched.h>
17#include <netlink/object-api.h>
18#include <netlink/netlink.h>
19#include <netlink/socket.h>
20#include <netlink/attr.h>
21#include <netlink/handlers.h>
22#include <netlink/msg.h>
23
24#include <dirent.h>
25#include <net/if.h>
26
27#include "sync.h"
28
29#define LOG_TAG "WifiHAL"
30
31#include <utils/Log.h>
32
33#include "wifi_hal.h"
34#include "common.h"
35#include "cpp_bindings.h"
36#include "cutils/properties.h"
37
c481cf08
JA
38template<typename>
39struct DummyFunction;
40
41template<typename R, typename... Args>
42struct DummyFunction<R (*)(Args...)> {
43 static constexpr R invoke(Args...) { return WIFI_SUCCESS; }
44};
45
46template<typename... Args>
47struct DummyFunction<void (*)(Args...)> {
48 static constexpr void invoke(Args...) { }
49};
50
51template<typename T>
52void populateDummyFor(T& val) {
53 val = &DummyFunction<T>::invoke;
54}
55
f3fa1980
S
56/*
57 BUGBUG: normally, libnl allocates ports for all connections it makes; but
58 being a static library, it doesn't really know how many other netlink connections
59 are made by the same process, if connections come from different shared libraries.
60 These port assignments exist to solve that problem - temporarily. We need to fix
61 libnl to try and allocate ports across the entire process.
62 */
63
64#define WIFI_HAL_CMD_SOCK_PORT 644
65#define WIFI_HAL_EVENT_SOCK_PORT 645
66
f3fa1980
S
67static int internal_no_seq_check(nl_msg *msg, void *arg);
68static int internal_valid_message_handler(nl_msg *msg, void *arg);
69static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group);
70static int wifi_add_membership(wifi_handle handle, const char *group);
71static wifi_error wifi_init_interfaces(wifi_handle handle);
72static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
73 iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh);
74static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface);
75
f3fa1980
S
76static wifi_error wifi_get_wake_reason_stats_dummy(wifi_interface_handle iface,
77 WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt);
78static wifi_error wifi_get_packet_filter_capabilities_dummy(
79 wifi_interface_handle handle, u32 *version, u32 *max_len);
f3fa1980
S
80static wifi_error wifi_get_ring_buffers_status_dummy(wifi_interface_handle iface,
81 u32 *num_rings, wifi_ring_buffer_status *status);
82static wifi_error wifi_get_logger_supported_feature_set_dummy(wifi_interface_handle iface,
83 unsigned int *support);
f3fa1980
S
84static wifi_error wifi_get_tx_pkt_fates_dummy(wifi_interface_handle handle,
85 wifi_tx_report *tx_report_bufs, size_t n_requested_fates, size_t *n_provided_fates);
86static wifi_error wifi_get_rx_pkt_fates_dummy(wifi_interface_handle handle,
87 wifi_rx_report *rx_report_bufs, size_t n_requested_fates, size_t *n_provided_fates);
f3fa1980
S
88
89/* Initialize/Cleanup */
90
91void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
92{
93 uint32_t pid = getpid() & 0x3FFFFF;
94 nl_socket_set_local_port(sock, pid + (port << 22));
95}
96
97static nl_sock *wifi_create_nl_socket(int port)
98{
99
100 // ALOGD("Creating netlink socket, local port[%d]", port);
101 struct nl_sock *sock = nl_socket_alloc();
102 if (sock == NULL) {
103 ALOGE("Could not create netlink socket: %s(%d)", strerror(errno), errno);
104 return NULL;
105 }
106
107 wifi_socket_set_local_port(sock, port);
108
109 // ALOGD("Connecting to socket");
110 if (nl_connect(sock, NETLINK_GENERIC)) {
111 ALOGE("Could not connect to netlink socket: %s(%d)", strerror(errno), errno);
112 nl_socket_free(sock);
113 return NULL;
114 }
115
116 return sock;
117}
118/* Initialize vendor function pointer table with MTK HAL API */
119wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn)
120{
121 if (fn == NULL) {
122 return WIFI_ERROR_UNKNOWN;
123 }
124 fn->wifi_initialize = wifi_initialize;
125 fn->wifi_cleanup = wifi_cleanup;
126 fn->wifi_event_loop = wifi_event_loop;
127 fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
f3fa1980
S
128 fn->wifi_get_ifaces = wifi_get_ifaces;
129 fn->wifi_get_iface_name = wifi_get_iface_name;
f3fa1980 130 fn->wifi_set_country_code = wifi_set_country_code;
c481cf08
JA
131 fn->wifi_get_firmware_version = wifi_get_firmware_version;
132 fn->wifi_get_driver_version = wifi_get_driver_version;
f3fa1980
S
133 fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
134 fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
f3fa1980
S
135 fn->wifi_start_sending_offloaded_packet = wifi_start_sending_offloaded_packet;
136 fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
c481cf08
JA
137 fn->wifi_get_roaming_capabilities = wifi_get_roaming_capabilities;
138 fn->wifi_configure_roaming = wifi_configure_roaming;
139 fn->wifi_enable_firmware_roaming = wifi_enable_firmware_roaming;
140 fn->wifi_select_tx_power_scenario = wifi_select_tx_power_scenario;
141 fn->wifi_reset_tx_power_scenario = wifi_reset_tx_power_scenario;
142 fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui;
143 fn->wifi_get_valid_channels = wifi_get_valid_channels;
144
145 fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status_dummy;
146 fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set_dummy;
f3fa1980
S
147 fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates_dummy;
148 fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates_dummy;
149 fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities_dummy;
f3fa1980 150 fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats_dummy;
c481cf08
JA
151
152 populateDummyFor(fn->wifi_wait_for_driver_ready);
153 populateDummyFor(fn->wifi_set_nodfs_flag);
154 populateDummyFor(fn->wifi_set_log_handler);
155 populateDummyFor(fn->wifi_reset_log_handler);
156 populateDummyFor(fn->wifi_configure_nd_offload);
157 populateDummyFor(fn->wifi_start_pkt_fate_monitoring);
158 populateDummyFor(fn->wifi_get_driver_memory_dump);
159 populateDummyFor(fn->wifi_get_ring_data);
160 populateDummyFor(fn->wifi_start_logging);
161 populateDummyFor(fn->wifi_get_gscan_capabilities);
f3fa1980
S
162
163 return WIFI_SUCCESS;
164}
165
166wifi_error wifi_initialize(wifi_handle *handle)
167{
168 ALOGI("Wifi HAL initializing");
169
170 hal_info *info = (hal_info *)malloc(sizeof(hal_info));
171 if (info == NULL) {
172 ALOGE("Could not allocate hal_info");
173 return WIFI_ERROR_OUT_OF_MEMORY;
174 }
175
176 memset(info, 0, sizeof(*info));
177
178 ALOGI("Creating socket");
179 if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->cleanup_socks) < 0) {
180 ALOGE("Could not create cleanup sockets");
181 free(info);
182 return WIFI_ERROR_UNKNOWN;
183 }
184
185 struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT);
186 if (cmd_sock == NULL) {
187 ALOGE("Could not create handle");
188 free(info);
189 return WIFI_ERROR_UNKNOWN;
190 }
191
192 struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT);
193 if (event_sock == NULL) {
194 ALOGE("Could not create handle");
195 nl_socket_free(cmd_sock);
196 free(info);
197 return WIFI_ERROR_UNKNOWN;
198 }
199
200 struct nl_cb *cb = nl_socket_get_cb(event_sock);
201 if (cb == NULL) {
202 ALOGE("Could not create handle");
203 nl_socket_free(cmd_sock);
204 nl_socket_free(event_sock);
205 free(info);
206 return WIFI_ERROR_UNKNOWN;
207 }
208
209 // ALOGI("cb->refcnt = %d", cb->cb_refcnt);
210 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, info);
211 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info);
212 nl_cb_put(cb);
213
214 info->cmd_sock = cmd_sock;
215 info->event_sock = event_sock;
216 info->clean_up = false;
217 info->in_event_loop = false;
218
219 info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
220 info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
221 info->num_event_cb = 0;
222 if (info->event_cb == NULL) {
223 ALOGE("Could not allocate cb_info array");
224 nl_socket_free(cmd_sock);
225 nl_socket_free(event_sock);
226 free(info);
227 return WIFI_ERROR_OUT_OF_MEMORY;
228 }
229
230 info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
231 info->alloc_cmd = DEFAULT_CMD_SIZE;
232 info->num_cmd = 0;
233 if (info->cmd == NULL) {
234 ALOGE("Could not allocate cmd_info array");
235 nl_socket_free(cmd_sock);
236 nl_socket_free(event_sock);
237 free(info->event_cb);
238 free(info);
239 return WIFI_ERROR_OUT_OF_MEMORY;
240 }
241
242 ALOGI("Get nl80211_family_id");
243 info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
244 if (info->nl80211_family_id < 0) {
245 ALOGE("Could not resolve nl80211 familty id");
246 nl_socket_free(cmd_sock);
247 nl_socket_free(event_sock);
248 free(info->event_cb);
249 free(info->cmd);
250 free(info);
251 return WIFI_ERROR_UNKNOWN;
252 }
253
254 pthread_mutex_init(&info->cb_lock, NULL);
255
256 if (wifi_init_interfaces((wifi_handle) info) != WIFI_SUCCESS) {
257 ALOGE("No wifi interface found");
258 nl_socket_free(cmd_sock);
259 nl_socket_free(event_sock);
260 free(info->event_cb);
261 free(info->cmd);
262 pthread_mutex_destroy(&info->cb_lock);
263 free(info);
264 return WIFI_ERROR_NOT_AVAILABLE;
265 }
266
267 if ((wifi_add_membership((wifi_handle) info, "scan") < 0) ||
268 (wifi_add_membership((wifi_handle) info, "mlme") < 0) ||
269 (wifi_add_membership((wifi_handle) info, "regulatory") < 0) ||
270 (wifi_add_membership((wifi_handle) info, "vendor") < 0)) {
271 ALOGE("Add membership failed");
272 nl_socket_free(cmd_sock);
273 nl_socket_free(event_sock);
274 free(info->event_cb);
275 free(info->cmd);
276 pthread_mutex_destroy(&info->cb_lock);
277 free(info);
278 return WIFI_ERROR_NOT_AVAILABLE;
279 }
280
281 *handle = (wifi_handle) info;
282
283 ALOGD("Wifi HAL initialized successfully: nl80211_family_id=%d, found %d interfaces",
284 info->nl80211_family_id, info->num_interfaces);
285 return WIFI_SUCCESS;
286}
287
288static int wifi_add_membership(wifi_handle handle, const char *group)
289{
290 hal_info *info = getHalInfo(handle);
291
292 int id = wifi_get_multicast_id(handle, "nl80211", group);
293 if (id < 0) {
294 ALOGE("Could not find group %s", group);
295 return id;
296 }
297
298 int ret = nl_socket_add_membership(info->event_sock, id);
299 if (ret < 0) {
300 ALOGE("Could not add membership to group %s", group);
301 }
302
303 ALOGD("Add membership for group %s successfully", group);
304 return ret;
305}
306
307static void internal_cleaned_up_handler(wifi_handle handle)
308{
309 hal_info *info = getHalInfo(handle);
310 wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
311
312 if (info->cmd_sock != 0) {
313 close(info->cleanup_socks[0]);
314 close(info->cleanup_socks[1]);
315 nl_socket_free(info->cmd_sock);
316 nl_socket_free(info->event_sock);
317 info->cmd_sock = NULL;
318 info->event_sock = NULL;
319 }
320
c481cf08
JA
321 if (info->interfaces) {
322 int i = 0;
323 for (; i < info->num_interfaces; i++)
324 free(info->interfaces[i]);
325 free(info->interfaces);
326 }
327
f3fa1980
S
328 (*cleaned_up_handler)(handle);
329 pthread_mutex_destroy(&info->cb_lock);
330 free(info);
331
332 ALOGI("Internal cleanup completed");
333}
334
335void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
336{
337 hal_info *info = getHalInfo(handle);
338 char buf[64];
339
340 info->cleaned_up_handler = handler;
341 if (TEMP_FAILURE_RETRY(write(info->cleanup_socks[0], "Exit", 4)) < 1) {
342 // As a fallback set the cleanup flag to TRUE
343 ALOGE("could not write to the cleanup socket");
344 } else {
345 // Listen to the response
346 // Hopefully we dont get errors or get hung up
347 // Not much can be done in that case, but assume that
348 // it has rx'ed the Exit message to exit the thread.
349 // As a fallback set the cleanup flag to TRUE
350 memset(buf, 0, sizeof(buf));
351 ssize_t result = TEMP_FAILURE_RETRY(read(info->cleanup_socks[0], buf, sizeof(buf)));
352 ALOGE("%s: Read after POLL returned %zd, error no = %d (%s)", __FUNCTION__,
353 result, errno, strerror(errno));
354 if (strncmp(buf, "Done", 4) == 0) {
355 ALOGE("Event processing terminated");
356 } else {
357 ALOGD("Rx'ed %s", buf);
358 }
359 }
360 info->clean_up = true;
361 pthread_mutex_lock(&info->cb_lock);
362
363 int bad_commands = 0;
364
365 for (int i = 0; i < info->num_event_cb; i++) {
366 cb_info *cbi = &(info->event_cb[i]);
367 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
368 ALOGI("Command left in event_cb %p:%s", cmd, (cmd ? cmd->getType(): ""));
369 }
370
371 while (info->num_cmd > bad_commands) {
372 int num_cmd = info->num_cmd;
373 cmd_info *cmdi = &(info->cmd[bad_commands]);
374 WifiCommand *cmd = cmdi->cmd;
375 if (cmd != NULL) {
376 ALOGI("Cancelling command %p:%s", cmd, cmd->getType());
377 pthread_mutex_unlock(&info->cb_lock);
378 cmd->cancel();
379 pthread_mutex_lock(&info->cb_lock);
380 if (num_cmd == info->num_cmd) {
381 ALOGI("Cancelling command %p:%s did not work", cmd, (cmd ? cmd->getType(): ""));
382 bad_commands++;
383 }
384 /* release reference added when command is saved */
385 cmd->releaseRef();
386 }
387 }
388
389 for (int i = 0; i < info->num_event_cb; i++) {
390 cb_info *cbi = &(info->event_cb[i]);
391 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
392 ALOGE("Leaked command %p", cmd);
393 }
394 pthread_mutex_unlock(&info->cb_lock);
395 internal_cleaned_up_handler(handle);
396}
397
398static int internal_pollin_handler(wifi_handle handle)
399{
400 hal_info *info = getHalInfo(handle);
401 struct nl_cb *cb = nl_socket_get_cb(info->event_sock);
402 int res = nl_recvmsgs(info->event_sock, cb);
403 // ALOGD("nl_recvmsgs returned %d", res);
404 nl_cb_put(cb);
405 return res;
406}
407
408/* Run event handler */
409void wifi_event_loop(wifi_handle handle)
410{
411 hal_info *info = getHalInfo(handle);
412 if (info->in_event_loop) {
413 return;
414 } else {
415 info->in_event_loop = true;
416 }
417
418 pollfd pfd[2];
419 memset(&pfd[0], 0, sizeof(pollfd) * 2);
420
421 pfd[0].fd = nl_socket_get_fd(info->event_sock);
422 pfd[0].events = POLLIN;
423 pfd[1].fd = info->cleanup_socks[1];
424 pfd[1].events = POLLIN;
425
426 char buf[2048];
427 /* TODO: Add support for timeouts */
428
429 do {
430 int timeout = -1; /* Infinite timeout */
431 pfd[0].revents = 0;
432 pfd[1].revents = 0;
433 // ALOGI("Polling socket");
434 int result = TEMP_FAILURE_RETRY(poll(pfd, 2, timeout));
435 if (result < 0) {
436 // ALOGE("Error polling socket");
437 } else if (pfd[0].revents & POLLERR) {
438 ALOGE("POLL Error; error no = %d (%s)", errno, strerror(errno));
439 ssize_t result2 = TEMP_FAILURE_RETRY(read(pfd[0].fd, buf, sizeof(buf)));
440 ALOGE("Read after POLL returned %zd, error no = %d (%s)", result2,
441 errno, strerror(errno));
442 } else if (pfd[0].revents & POLLHUP) {
443 ALOGE("Remote side hung up");
444 break;
445 } else if (pfd[0].revents & POLLIN) {
446 // ALOGI("Found some events!!!");
447 internal_pollin_handler(handle);
448 } else if (pfd[1].revents & POLLIN) {
449 memset(buf, 0, sizeof(buf));
450 ssize_t result2 = TEMP_FAILURE_RETRY(read(pfd[1].fd, buf, sizeof(buf)));
451 ALOGE("%s: Read after POLL returned %zd, error no = %d (%s)", __FUNCTION__,
452 result2, errno, strerror(errno));
453 if (strncmp(buf, "Exit", 4) == 0) {
454 ALOGD("Got a signal to exit!!!");
455 if (TEMP_FAILURE_RETRY(write(pfd[1].fd, "Done", 4)) < 1) {
456 ALOGE("could not write to the cleanup socket");
457 }
458 break;
459 } else {
460 ALOGD("Rx'ed %s on the cleanup socket\n", buf);
461 }
462 } else {
463 ALOGE("Unknown event - %0x, %0x", pfd[0].revents, pfd[1].revents);
464 }
465 } while (!info->clean_up);
466 ALOGI("Exit %s", __FUNCTION__);
467}
468
469///////////////////////////////////////////////////////////////////////////////////////
470static int internal_no_seq_check(struct nl_msg *msg, void *arg)
471{
472 return NL_OK;
473}
474
475static int internal_valid_message_handler(nl_msg *msg, void *arg)
476{
477 wifi_handle handle = (wifi_handle)arg;
478 hal_info *info = getHalInfo(handle);
479
480 WifiEvent event(msg);
481 int res = event.parse();
482 if (res < 0) {
483 ALOGE("Failed to parse event: %d", res);
484 return NL_SKIP;
485 }
486
487 int cmd = event.get_cmd();
488 uint32_t vendor_id = 0;
489 int subcmd = 0;
490
491 if (cmd == NL80211_CMD_VENDOR) {
492 vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
493 subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
494 ALOGV("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
495 event.get_cmdString(), vendor_id, subcmd);
496 } else {
497 ALOGV("event received %s", event.get_cmdString());
498 }
499
f3fa1980
S
500 pthread_mutex_lock(&info->cb_lock);
501
502 for (int i = 0; i < info->num_event_cb; i++) {
503 if (cmd == info->event_cb[i].nl_cmd) {
504 if (cmd == NL80211_CMD_VENDOR
505 && ((vendor_id != info->event_cb[i].vendor_id)
506 || (subcmd != info->event_cb[i].vendor_subcmd)))
507 {
508 /* event for a different vendor, ignore it */
509 continue;
510 }
511
512 cb_info *cbi = &(info->event_cb[i]);
513 nl_recvmsg_msg_cb_t cb_func = cbi->cb_func;
514 void *cb_arg = cbi->cb_arg;
515 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
516 if (cmd != NULL) {
517 cmd->addRef();
518 }
519
520 pthread_mutex_unlock(&info->cb_lock);
521 if (cb_func)
522 (*cb_func)(msg, cb_arg);
523 if (cmd != NULL) {
524 cmd->releaseRef();
525 }
526
527 return NL_OK;
528 }
529 }
530
531 pthread_mutex_unlock(&info->cb_lock);
532 return NL_OK;
533}
534
535///////////////////////////////////////////////////////////////////////////////////
536
537class GetMulticastIdCommand : public WifiCommand
538{
539private:
540 const char *mName;
541 const char *mGroup;
542 int mId;
543
544public:
545 GetMulticastIdCommand(wifi_handle handle, const char *name, const char *group)
546 : WifiCommand("GetMulticastIdCommand", handle, 0)
547 {
548 mName = name;
549 mGroup = group;
550 mId = -1;
551 }
552
553 int getId() {
554 return mId;
555 }
556
557 virtual int create() {
558 int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
559 // ALOGD("ctrl family = %d", nlctrlFamily);
560 int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
561 if (ret < 0) {
562 return ret;
563 }
564 ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
565 return ret;
566 }
567
568 virtual int handleResponse(WifiEvent& reply) {
569
570 // ALOGD("handling reponse in %s", __func__);
571
572 struct nlattr **tb = reply.attributes();
f3fa1980
S
573 struct nlattr *mcgrp = NULL;
574 int i;
575
576 if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
577 ALOGD("No multicast groups found");
578 return NL_SKIP;
579 } else {
580 // ALOGD("Multicast groups attr size = %d", nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
581 }
582
583 for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
584
585 // ALOGD("Processing group");
586 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
587 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
588 nla_len(mcgrp), NULL);
589 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID]) {
590 continue;
591 }
592
593 char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
594 int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
595
596 // ALOGD("Found group name %s", grpName);
597
598 if (strncmp(grpName, mGroup, grpNameLen) != 0)
599 continue;
600
601 mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
602 break;
603 }
604
605 return NL_SKIP;
606 }
607
608};
609
610class SetCountryCodeCommand : public WifiCommand {
611private:
612 const char *mCountryCode;
613public:
614 SetCountryCodeCommand(wifi_interface_handle handle, const char *country_code)
615 : WifiCommand("SetCountryCodeCommand", handle, 0) {
616 mCountryCode = country_code;
617 }
618 virtual int create() {
619 int ret;
620
621 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_SET_COUNTRY_CODE);
622 if (ret < 0) {
623 ALOGE("Can't create message to send to driver - %d", ret);
624 return ret;
625 }
626
627 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
628 ret = mMsg.put_string(WIFI_ATTRIBUTE_COUNTRY_CODE, mCountryCode);
629 if (ret < 0) {
630 return ret;
631 }
632
633 mMsg.attr_end(data);
634 return WIFI_SUCCESS;
635 }
636};
637
638class SetRSSIMonitorCommand : public WifiCommand
639{
640private:
641 s8 mMax_rssi;
642 s8 mMin_rssi;
643 wifi_rssi_event_handler mHandler;
644
645public:
646 SetRSSIMonitorCommand(wifi_request_id id, wifi_interface_handle handle,
647 s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
648 : WifiCommand("SetRSSIMonitorCommand", handle, id), mMax_rssi(max_rssi), mMin_rssi
649 (min_rssi), mHandler(eh)
650 {
651 }
652
653 int createRequest(WifiRequest& request, int enable) {
654 int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_SET_RSSI_MONITOR);
655 if (result < 0) {
656 return result;
657 }
658
659 ALOGI("set RSSI Monitor, mMax_rssi=%d, mMin_rssi=%d, enable=%d", mMax_rssi, mMin_rssi, enable);
660
661 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
662 result = request.put_u32(WIFI_ATTRIBUTE_MAX_RSSI, (enable? mMax_rssi: 0));
663 if (result < 0) {
664 return result;
665 }
666 ALOGD("create request");
667 result = request.put_u32(WIFI_ATTRIBUTE_MIN_RSSI, (enable? mMin_rssi: 0));
668 if (result < 0) {
669 return result;
670 }
671 result = request.put_u32(WIFI_ATTRIBUTE_RSSI_MONITOR_START, enable);
672 if (result < 0) {
673 return result;
674 }
675
676 request.attr_end(data);
677 return result;
678 }
679
680 int start() {
681 WifiRequest request(familyId(), ifaceId());
682 int result = createRequest(request, 1);
683 if (result < 0) {
684 return result;
685 }
686 result = requestResponse(request);
687 if (result < 0) {
688 ALOGE("Failed to set RSSI Monitor, result=%d", result);
689 return result;
690 }
691 ALOGD("Successfully set RSSI monitoring");
692 registerVendorHandler(GOOGLE_OUI, WIFI_EVENT_RSSI_MONITOR);
693
694
695 if (result < 0) {
696 unregisterVendorHandler(GOOGLE_OUI, WIFI_EVENT_RSSI_MONITOR);
697 return result;
698 }
699 ALOGI("Done!");
700 return result;
701 }
702
703 virtual int cancel() {
704 WifiRequest request(familyId(), ifaceId());
705 int result = createRequest(request, 0);
706 if (result != WIFI_SUCCESS) {
707 ALOGE("Failed to create request, result=%d", result);
708 } else {
709 result = requestResponse(request);
710 if (result != WIFI_SUCCESS) {
711 ALOGE("Failed to stop RSSI monitoring, result=%d", result);
712 }
713 }
714 unregisterVendorHandler(GOOGLE_OUI, WIFI_EVENT_RSSI_MONITOR);
715 return WIFI_SUCCESS;
716 }
717
718 virtual int handleResponse(WifiEvent& reply) {
719 /* Nothing to do on response! */
720 return NL_SKIP;
721 }
722
723 virtual int handleEvent(WifiEvent& event) {
724 ALOGD("Got a RSSI monitor event");
725
726 struct nlattr *vendor_data = (struct nlattr *)event.get_vendor_data();
727 int len = event.get_vendor_data_len();
728
729 if (vendor_data == NULL || len == 0) {
730 ALOGE("RSSI monitor: No data");
731 return NL_SKIP;
732 }
733 /* driver<->HAL event structure */
734 #define RSSI_MONITOR_EVT_VERSION 1
735 typedef struct {
736 u8 version;
737 s8 cur_rssi;
738 mac_addr BSSID;
739 } rssi_monitor_evt;
740
741 rssi_monitor_evt *data = NULL;
742 if (vendor_data->nla_type == WIFI_EVENT_RSSI_MONITOR)
743 data = (rssi_monitor_evt *)nla_data(vendor_data);
744 else
745 return NL_SKIP;
746
747 ALOGI("data: version=%d, cur_rssi=%d BSSID=" MACSTR "\r\n",
748 data->version, data->cur_rssi, MAC2STR(data->BSSID));
749
750 if (data->version != RSSI_MONITOR_EVT_VERSION) {
751 ALOGE("Event version mismatch %d, expected %d", data->version, RSSI_MONITOR_EVT_VERSION);
752 return NL_SKIP;
753 }
754
755 if (*mHandler.on_rssi_threshold_breached) {
756 (*mHandler.on_rssi_threshold_breached)(id(), data->BSSID, data->cur_rssi);
757 } else {
758 ALOGW("No RSSI monitor handler registered");
759 }
760
761 return NL_SKIP;
762 }
763};
764
c481cf08
JA
765class ConfigRoamingCommand : public WifiCommand
766{
767private:
768 wifi_roaming_config *mConfig;
769
770public:
771 ConfigRoamingCommand(wifi_interface_handle handle, wifi_roaming_config *config)
772 : WifiCommand("ConfigRoamingCommand", handle, 0)
773 {
774 mConfig = config;
775 }
776
777 int createRequest(WifiRequest& request, int subcmd, wifi_roaming_config *config) {
778 int result = request.create(GOOGLE_OUI, subcmd);
779 if (result < 0) {
780 return result;
781 }
782
783 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
784 result = request.put_u32(WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM, config->num_blacklist_bssid);
785 if (result < 0) {
786 return result;
787 }
788
789 mac_addr *bssid_list = config->blacklist_bssid;
790 for (u32 i = 0; i < config->num_blacklist_bssid; i++) {
791 result = request.put_addr(WIFI_ATTRIBUTE_ROAMING_BLACKLIST_BSSID, bssid_list[i]);
792 ALOGI("Blacklist BSSID[%d] " MACSTR, i, MAC2STR(bssid_list[i]));
793 if (result < 0) {
794 return result;
795 }
796 }
797
798 result = request.put_u32(WIFI_ATTRIBUTE_ROAMING_WHITELIST_NUM, config->num_whitelist_ssid);
799 if (result < 0) {
800 return result;
801 }
802
803 char ssid[MAX_SSID_LENGTH + 1];
804 ssid_t *ssid_list = config->whitelist_ssid;
805 for (u32 i = 0; i < config->num_whitelist_ssid; i++) {
806 memcpy(ssid, ssid_list[i].ssid_str, ssid_list[i].length);
807 ssid[ssid_list[i].length] = '\0';
808 result = request.put(
809 WIFI_ATTRIBUTE_ROAMING_WHITELIST_SSID, ssid, ssid_list[i].length + 1);
810 ALOGI("Whitelist ssid[%d] : %s", i, ssid);
811 if (result < 0) {
812 return result;
813 }
814 }
815
816 request.attr_end(data);
817 return WIFI_SUCCESS;
818 }
819
820 int start() {
821 ALOGD("[WIFI HAL] Configure roaming");
822 WifiRequest request(familyId(), ifaceId());
823 int result = createRequest(request, WIFI_SUBCMD_CONFIG_ROAMING, mConfig);
824 if (result != WIFI_SUCCESS) {
825 ALOGE("Failed to create request, result=%d", result);
826 return result;
827 }
828
829 result = requestResponse(request);
830 if (result != WIFI_SUCCESS) {
831 ALOGE("[WIFI HAL]Failed to configure roaming, result=%d", result);
832 }
833
834 return result;
835 }
836
837protected:
838 virtual int handleResponse(WifiEvent& reply) {
839 ALOGD("ConfigRoamingCommand complete!");
840 /* Nothing to do on response! */
841 return NL_SKIP;
842 }
843};
844
845class EnableRoamingCommand : public WifiCommand {
846private:
847 fw_roaming_state_t mState;
848public:
849 EnableRoamingCommand(wifi_interface_handle handle, fw_roaming_state_t state)
850 : WifiCommand("EnableRoamingCommand", handle, 0) {
851 mState = state;
852 }
853 virtual int create() {
854 int ret;
855
856 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_ENABLE_ROAMING);
857 if (ret < 0) {
858 ALOGE("Can't create message to send to driver - %d", ret);
859 return ret;
860 }
861
862 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
863 ret = mMsg.put_u32(WIFI_ATTRIBUTE_ROAMING_STATE, mState);
864 if (ret < 0) {
865 return ret;
866 }
867
868 mMsg.attr_end(data);
869 return WIFI_SUCCESS;
870 }
871};
872
f3fa1980
S
873class GetFeatureSetCommand : public WifiCommand
874{
875private:
876 int feature_type;
877 feature_set *fset;
878 feature_set *feature_matrix;
879 int *fm_size;
880 int set_size_max;
881
882public:
883 GetFeatureSetCommand(wifi_interface_handle handle, int feature, feature_set *set,
884 feature_set set_matrix[], int *size, int max_size)
885 : WifiCommand("GetFeatureSetCommand", handle, 0)
886 {
887 feature_type = feature;
888 fset = set;
889 feature_matrix = set_matrix;
890 fm_size = size;
891 set_size_max = max_size;
892 }
893
894 virtual int create() {
895 int ret;
896
897 if(feature_type == WIFI_ATTRIBUTE_FEATURE_SET) {
898 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET);
c481cf08
JA
899 } else if (feature_type == WIFI_ATTRIBUTE_ROAMING_CAPABILITIES) {
900 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_ROAMING_CAPABILITIES);
f3fa1980
S
901 } else {
902 ALOGE("Unknown feature type %d", feature_type);
903 return -1;
904 }
905
906 if (ret < 0) {
907 ALOGE("Can't create subcmd message to driver, ret=%d", ret);
908 }
909
910 return ret;
911 }
912
913protected:
914 virtual int handleResponse(WifiEvent& reply) {
915
c481cf08 916 ALOGD("In GetFeatureSetCommand::handleResponse for %d", feature_type);
f3fa1980
S
917
918 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
919 ALOGD("Ignore reply with cmd 0x%x", reply.get_cmd());
920 return NL_SKIP;
921 }
922
923 int vendor_id = reply.get_vendor_id();
924 int subcmd = reply.get_vendor_subcmd();
925 ALOGD("vendor_id = 0x%x, subcmd = 0x%x", vendor_id, subcmd);
926
927 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
928 int len = reply.get_vendor_data_len();
929 if (vendor_data == NULL || len == 0) {
930 ALOGE("No vendor data in GetFeatureSetCommand response, ignore it");
931 return NL_SKIP;
932 }
933
934 if (feature_type == WIFI_ATTRIBUTE_FEATURE_SET) {
935 void *data = reply.get_vendor_data();
936 if (!fset) {
937 ALOGE("feature_set pointer is not set");
938 return NL_SKIP;
939 }
940 memcpy(fset, data, min(len, (int) sizeof(*fset)));
c481cf08
JA
941 ALOGI("feature_set=0x%x", *fset);
942 } else if (feature_type == WIFI_ATTRIBUTE_ROAMING_CAPABILITIES){
f3fa1980
S
943 if(!feature_matrix || !fm_size) {
944 ALOGE("feature_set pointer is not set");
945 return NL_SKIP;
946 }
947
c481cf08
JA
948 *fm_size = set_size_max; // black and white
949 int i = 0;
950 u32 max[2] = {MAX_BLACKLIST_BSSID, MAX_WHITELIST_SSID};
f3fa1980 951 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
c481cf08
JA
952 if (it.get_type() == WIFI_ATTRIBUTE_ROAMING_CAPABILITIES && i < set_size_max) {
953 feature_matrix[i] = it.get_u32() > max[i] ? max[i] : it.get_u32();
954 ALOGI("feature_matrix %d: %d", i, feature_matrix[i]);
f3fa1980
S
955 i++;
956 } else {
c481cf08
JA
957 ALOGW("Ignore invalid attribute type = %d, idx = %d",
958 it.get_type(), i);
f3fa1980
S
959 }
960 }
961 }
962
963 return NL_OK;
964 }
965
966};
967
c481cf08
JA
968class SelectTxPowerCommand : public WifiCommand {
969private:
970 int mScenario;
971public:
972 SelectTxPowerCommand(wifi_interface_handle handle, int scenario)
973 : WifiCommand("SelectTxPowerCommand", handle, 0) {
974 mScenario = scenario;
975 }
976 virtual int create() {
977 int ret;
978
979 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_SELECT_TX_POWER_SCENARIO);
980 if (ret < 0) {
981 ALOGE("Can't create message to send to driver - %d", ret);
982 return ret;
983 }
984
985 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
986 ret = mMsg.put_u32(WIFI_ATTRIBUTE_TX_POWER_SCENARIO, mScenario);
987 if (ret < 0) {
988 return ret;
989 }
990
991 mMsg.attr_end(data);
992 return WIFI_SUCCESS;
993 }
994};
995
996class SetScanMacOuiCommand : public WifiCommand {
997private:
998 const byte *mScanMacOui;
999public:
1000 SetScanMacOuiCommand(wifi_interface_handle handle, const oui scan_oui)
1001 : WifiCommand("SetScanMacOuiCommand", handle, 0), mScanMacOui(scan_oui) {
1002 }
1003 virtual int create() {
1004 ALOGI("Set scan mac oui");
1005 int ret;
1006
1007 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI);
1008 if (ret < 0) {
1009 ALOGE("Can't create message to send to driver - %d", ret);
1010 return ret;
1011 }
1012
1013 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
1014 ret = mMsg.put(WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, (void *)mScanMacOui, sizeof(oui));
1015 if (ret < 0) {
1016 return ret;
1017 }
1018
1019 mMsg.attr_end(data);
1020 return WIFI_SUCCESS;
1021 }
1022};
1023
1024class GetChannelListCommand : public WifiCommand
1025{
1026private:
1027 wifi_channel *mChannels;
1028 int mMaxChannels;
1029 int *mNumOfChannel;
1030 int mBand;
1031
1032public:
1033 GetChannelListCommand(wifi_interface_handle handle, int band, int max_channels,
1034 wifi_channel *channels, int *num_channels)
1035 : WifiCommand("GetChannelListCommand", handle, 0)
1036 {
1037 mBand = band;
1038 mMaxChannels = max_channels;
1039 mChannels = channels;
1040 mNumOfChannel = num_channels;
1041 memset(mChannels, 0, sizeof(wifi_channel) * mMaxChannels);
1042 }
1043
1044 virtual int create() {
1045 ALOGV("Creating message to get channel list; iface = %d", mIfaceInfo->id);
1046
1047 int ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_CHANNEL_LIST);
1048 if (ret < 0) {
1049 return ret;
1050 }
1051
1052 ALOGI("In GetChannelList::mBand=%d", mBand);
1053
1054 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
1055 ret = mMsg.put_u32(WIFI_ATTRIBUTE_BAND, mBand);
1056 if (ret < 0) {
1057 return ret;
1058 }
1059
1060 mMsg.attr_end(data);
1061 return ret;
1062 }
1063
1064protected:
1065 virtual int handleResponse(WifiEvent& reply) {
1066
1067 ALOGV("In GetChannelList::handleResponse");
1068
1069 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1070 ALOGE("Ignore reply with cmd 0x%x", reply.get_cmd());
1071 return NL_SKIP;
1072 }
1073
1074 int vendor_id = reply.get_vendor_id();
1075 int subcmd = reply.get_vendor_subcmd();
1076 ALOGV("vendor_id = 0x%x, subcmd = 0x%x", vendor_id, subcmd);
1077
1078 nlattr *vendor = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1079 int len = reply.get_vendor_data_len();
1080 if (vendor == NULL || len == 0) {
1081 ALOGE("No vendor data in GetChannelList response, ignore it");
1082 return NL_SKIP;
1083 }
1084
1085 int num_channels = 0;
1086 for (nl_iterator it(vendor); it.has_next(); it.next()) {
1087 if (it.get_type() == WIFI_ATTRIBUTE_NUM_CHANNELS) {
1088 num_channels = it.get_u32();
1089 ALOGI("Get channel list with %d channels", num_channels);
1090 if (num_channels > mMaxChannels)
1091 num_channels = mMaxChannels;
1092 *mNumOfChannel = num_channels;
1093 } else if (it.get_type() == WIFI_ATTRIBUTE_CHANNEL_LIST && num_channels) {
1094 memcpy(mChannels, it.get_data(), sizeof(wifi_channel) * num_channels);
1095 } else {
1096 ALOGW("Ignore invalid attribute type = %d, size = %d",
1097 it.get_type(), it.get_len());
1098 }
1099 }
1100
1101 ALOGD("mChannels[0]=%d mChannels[1]=%d", *mChannels, *(mChannels + 1));
1102
1103 return NL_OK;
1104 }
1105};
1106
1107/////////////////////////////////////////////////////////////////////////
1108
f3fa1980
S
1109static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group)
1110{
1111 GetMulticastIdCommand cmd(handle, name, group);
1112 int res = cmd.requestResponse();
1113 if (res < 0)
1114 return res;
1115 else
1116 return cmd.getId();
1117}
1118
f3fa1980
S
1119static bool is_wifi_interface(const char *name)
1120{
c481cf08 1121 if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0 && strncmp(name, "ap", 2) != 0) {
f3fa1980
S
1122 /* Not a wifi interface; ignore it */
1123 return false;
1124 } else {
1125 return true;
1126 }
1127}
1128
1129int get_interface(const char *name, interface_info *info)
1130{
1131 strncpy(info->name, name, sizeof(info->name));
1132 info->name[sizeof(info->name) - 1] = '\0';
1133 info->id = if_nametoindex(name);
1134 ALOGD("found an interface : %s, id = %d", name, info->id);
1135 return WIFI_SUCCESS;
1136}
1137
1138wifi_error wifi_init_interfaces(wifi_handle handle)
1139{
1140 ALOGI("init wifi interfaces");
1141 hal_info *info = (hal_info *)handle;
1142 struct dirent *de;
1143
1144 DIR *d = opendir("/sys/class/net");
1145 if (d == 0)
1146 return WIFI_ERROR_UNKNOWN;
1147
1148 int n = 0;
1149 while ((de = readdir(d))) {
1150 if (de->d_name[0] == '.')
1151 continue;
1152 if (is_wifi_interface(de->d_name) ) {
1153 n++;
1154 }
1155 }
1156
1157 closedir(d);
1158
1159 if (n == 0)
1160 return WIFI_ERROR_NOT_AVAILABLE;
1161
1162 d = opendir("/sys/class/net");
1163 if (d == 0)
1164 return WIFI_ERROR_UNKNOWN;
1165
1166 info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
1167 if (!info->interfaces) {
1168 closedir(d);
1169 return WIFI_ERROR_OUT_OF_MEMORY;
1170 }
c481cf08 1171 memset(info->interfaces, 0, sizeof(interface_info *) * n);
f3fa1980
S
1172
1173 int i = 0;
1174 while ((de = readdir(d))) {
1175 if (de->d_name[0] == '.')
1176 continue;
1177 if (is_wifi_interface(de->d_name)) {
1178 interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info));
1179 if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
1180 free(ifinfo);
1181 continue;
1182 }
1183 ifinfo->handle = handle;
1184 info->interfaces[i] = ifinfo;
1185 i++;
1186 }
1187 }
1188
1189 closedir(d);
1190
1191 info->num_interfaces = n;
1192 return WIFI_SUCCESS;
1193}
1194
1195wifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle **interfaces)
1196{
1197 hal_info *info = (hal_info *)handle;
1198
1199 *interfaces = (wifi_interface_handle *)info->interfaces;
1200 *num = info->num_interfaces;
1201
1202 return WIFI_SUCCESS;
1203}
1204
1205wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size)
1206{
1207 interface_info *info = (interface_info *)handle;
1208 strncpy(name, info->name, size);
1209 return WIFI_SUCCESS;
1210}
1211
1212wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *pset)
1213{
c481cf08 1214 GetFeatureSetCommand command(handle, WIFI_ATTRIBUTE_FEATURE_SET, pset, NULL, NULL, 1);
f3fa1980 1215 return (wifi_error)command.requestResponse();
f3fa1980
S
1216}
1217
f3fa1980
S
1218wifi_error wifi_set_country_code(wifi_interface_handle handle, const char *country_code)
1219{
1220 SetCountryCodeCommand command(handle, country_code);
1221 return (wifi_error) command.requestResponse();
1222}
1223
1224static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
1225 iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
1226{
1227 ALOGI("Start RSSI monitoring %d", id);
1228 wifi_handle handle = getWifiHandle(iface);
1229 SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface, max_rssi, min_rssi, eh);
1230 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1231 wifi_error result = wifi_register_cmd(handle, id, cmd);
1232 if (result != WIFI_SUCCESS) {
1233 cmd->releaseRef();
1234 return result;
1235 }
1236 result = (wifi_error)cmd->start();
1237 if (result != WIFI_SUCCESS) {
1238 wifi_unregister_cmd(handle, id);
1239 cmd->releaseRef();
1240 return result;
1241 }
1242 return result;
1243}
1244
1245static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface)
1246{
1247 ALOGI("Stopping RSSI monitoring %d", id);
1248
1249 if (id == -1) {
1250 wifi_rssi_event_handler handler;
1251 s8 max_rssi = 0, min_rssi = 0;
f3fa1980
S
1252 memset(&handler, 0, sizeof(handler));
1253 SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface, max_rssi, min_rssi, handler);
1254 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1255 cmd->cancel();
1256 cmd->releaseRef();
1257 return WIFI_SUCCESS;
1258 }
1259 return wifi_cancel_cmd(id, iface);
1260}
1261
c481cf08
JA
1262wifi_error wifi_get_roaming_capabilities(wifi_interface_handle handle,
1263 wifi_roaming_capabilities *caps) {
1264 ALOGI("Get roaming capabilities");
1265
1266 wifi_handle wifiHandle = getWifiHandle(handle);
1267 hal_info *info = getHalInfo(wifiHandle);
1268
1269 if (!caps) {
1270 ALOGE("%s: Invalid Buffer provided. Exit", __FUNCTION__);
1271 return WIFI_ERROR_INVALID_ARGS;
1272 }
1273
1274 if (!info) {
1275 ALOGE("%s: hal_info is NULL", __FUNCTION__);
1276 return WIFI_ERROR_INVALID_ARGS;
1277 }
1278
1279 // first time to get roaming cap
1280 if (info->roaming_capa.max_blacklist_size == 0 && info->roaming_capa.max_whitelist_size == 0) {
1281 int size = 0;
1282 GetFeatureSetCommand command(handle, WIFI_ATTRIBUTE_ROAMING_CAPABILITIES, NULL,
1283 (feature_set*) caps, &size, 2);
1284 wifi_error ret = (wifi_error)command.requestResponse();
1285 if (ret == WIFI_SUCCESS) {
1286 info->roaming_capa.max_blacklist_size = caps->max_blacklist_size;
1287 info->roaming_capa.max_whitelist_size = caps->max_whitelist_size;
1288 }
1289 return ret;
1290 } else {
1291 memcpy(caps, &info->roaming_capa, sizeof(wifi_roaming_capabilities));
1292 }
f3fa1980 1293
f3fa1980
S
1294 return WIFI_SUCCESS;
1295}
1296
c481cf08
JA
1297wifi_error wifi_configure_roaming(wifi_interface_handle handle,
1298 wifi_roaming_config *roaming_config) {
1299 ALOGI("Configure roaming");
1300 wifi_handle wifiHandle = getWifiHandle(handle);
1301 hal_info *info = getHalInfo(wifiHandle);
1302 if (!roaming_config) {
1303 ALOGE("%s: Invalid Buffer provided. Exit", __FUNCTION__);
1304 return WIFI_ERROR_INVALID_ARGS;
1305 }
1306
1307 /* Set bssid blacklist */
1308 if (roaming_config->num_blacklist_bssid > info->roaming_capa.max_blacklist_size) {
1309 ALOGE("%s: Number of blacklist bssids(%d) provided is more than maximum blacklist bssids(%d)"
1310 " supported", __FUNCTION__, roaming_config->num_blacklist_bssid,
1311 info->roaming_capa.max_blacklist_size);
1312 return WIFI_ERROR_NOT_SUPPORTED;
1313 }
1314
1315 /* Set ssid whitelist */
1316 if (roaming_config->num_whitelist_ssid > info->roaming_capa.max_whitelist_size) {
1317 ALOGE("%s: Number of whitelist ssid(%d) provided is more than maximum whitelist ssids(%d) "
1318 "supported", __FUNCTION__, roaming_config->num_whitelist_ssid,
1319 info->roaming_capa.max_whitelist_size);
1320 return WIFI_ERROR_NOT_SUPPORTED;
1321 }
1322
1323 ConfigRoamingCommand command(handle, roaming_config);
1324 return (wifi_error)command.start();
1325}
1326
1327wifi_error wifi_enable_firmware_roaming(wifi_interface_handle handle,
1328 fw_roaming_state_t state) {
1329 ALOGI("Enable roaming %d", state);
1330 EnableRoamingCommand command(handle, state);
1331 return (wifi_error) command.requestResponse();
1332}
1333
1334wifi_error wifi_select_tx_power_scenario(wifi_interface_handle handle,
1335 wifi_power_scenario scenario)
f3fa1980 1336{
c481cf08
JA
1337 ALOGI("Select tx power scenario %d", scenario);
1338 SelectTxPowerCommand command(handle, scenario);
1339 return (wifi_error) command.requestResponse();
f3fa1980
S
1340}
1341
c481cf08
JA
1342wifi_error wifi_reset_tx_power_scenario(wifi_interface_handle handle)
1343{
1344 ALOGI("Reset tx power scenario");
1345 SelectTxPowerCommand command(handle, -1);
1346 return (wifi_error) command.requestResponse();
1347}
1348
1349wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui)
1350{
1351 SetScanMacOuiCommand command(handle, scan_oui);
1352 return (wifi_error) command.requestResponse();
1353}
1354
1355wifi_error wifi_get_valid_channels(wifi_interface_handle handle,
1356 int band, int max_channels, wifi_channel *channels, int *num_channels)
1357{
1358 GetChannelListCommand command(handle, band, max_channels, channels, num_channels);
1359 return (wifi_error) command.requestResponse();
1360}
1361
1362/////////////////////////////////////////////////////////////////////////////
1363
f3fa1980
S
1364static wifi_error wifi_get_wake_reason_stats_dummy(wifi_interface_handle iface,
1365 WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
1366{
1367 if (wifi_wake_reason_cnt) {
1368 memset(wifi_wake_reason_cnt, 0, sizeof(*wifi_wake_reason_cnt));
1369 return WIFI_SUCCESS;
1370 }
1371 return WIFI_ERROR_INVALID_ARGS;
1372}
1373
1374static wifi_error wifi_get_packet_filter_capabilities_dummy(wifi_interface_handle handle,
1375 u32 *version, u32 *max_len)
1376{
1377 if (version && max_len) {
1378 *version = 0;
1379 *max_len = 0;
1380 return WIFI_SUCCESS;
1381 }
1382 return WIFI_ERROR_INVALID_ARGS;
1383}
1384
f3fa1980
S
1385static wifi_error wifi_get_tx_pkt_fates_dummy(wifi_interface_handle handle,
1386 wifi_tx_report *tx_report_bufs, size_t n_requested_fates, size_t *n_provided_fates)
1387{
1388 if (n_provided_fates) {
1389 *n_provided_fates = 0;
1390 return WIFI_SUCCESS;
1391 }
1392 return WIFI_ERROR_INVALID_ARGS;
1393}
1394
1395static wifi_error wifi_get_rx_pkt_fates_dummy(wifi_interface_handle handle,
1396 wifi_rx_report *rx_report_bufs, size_t n_requested_fates, size_t *n_provided_fates)
1397{
1398 if (n_provided_fates) {
1399 *n_provided_fates = 0;
1400 return WIFI_SUCCESS;
1401 }
1402 return WIFI_ERROR_INVALID_ARGS;
1403}
1404
f3fa1980
S
1405
1406static wifi_error wifi_get_ring_buffers_status_dummy(wifi_interface_handle iface,
1407 u32 *num_rings, wifi_ring_buffer_status *status)
1408{
1409 if (num_rings && status) {
1410 *num_rings = 1;
1411 memset(status, 0, sizeof(*status));
c481cf08 1412 strncpy((char*)status->name, "dummy", sizeof(status->name));
f3fa1980
S
1413 return WIFI_SUCCESS;
1414 }
1415 return WIFI_ERROR_INVALID_ARGS;
1416}
1417
1418static wifi_error wifi_get_logger_supported_feature_set_dummy(wifi_interface_handle iface,
1419 unsigned int *support)
1420{
1421 if (support) {
1422 *support = 0;
1423 return WIFI_SUCCESS;
1424 }
1425 return WIFI_ERROR_INVALID_ARGS;
1426}