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