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