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