1 #include <stdint.h>
2 #include <fcntl.h>
3 #include <sys/socket.h>
4 #include <netlink/genl/genl.h>
5 #include <netlink/genl/family.h>
6 #include <netlink/genl/ctrl.h>
7 #include <linux/rtnetlink.h>
8 #include <netpacket/packet.h>
9 #include <linux/filter.h>
10 #include <linux/errqueue.h>
11 #include <errno.h>
12
13 #include <linux/pkt_sched.h>
14 #include <netlink/object-api.h>
15 #include <netlink/netlink.h>
16 #include <netlink/socket.h>
17 #include <netlink/attr.h>
18 #include <netlink/handlers.h>
19 #include <netlink/msg.h>
20
21 #include <dirent.h>
22 #include <net/if.h>
23
24 #include "sync.h"
25
26 #define LOG_TAG "WifiHAL"
27
28 #include <utils/Log.h>
29
30 #include "wifi_hal.h"
31 #include "common.h"
32 #include "cpp_bindings.h"
33 #include "rtt.h"
34 /*
35 BUGBUG: normally, libnl allocates ports for all connections it makes; but
36 being a static library, it doesn't really know how many other netlink connections
37 are made by the same process, if connections come from different shared libraries.
38 These port assignments exist to solve that problem - temporarily. We need to fix
39 libnl to try and allocate ports across the entire process.
40 */
41
42 #define WIFI_HAL_CMD_SOCK_PORT 644
43 #define WIFI_HAL_EVENT_SOCK_PORT 645
44
45 #define FEATURE_SET 0
46 #define FEATURE_SET_MATRIX 1
47 #define ATTR_NODFS_VALUE 3
48 #define ATTR_COUNTRY_CODE 4
49
50 static void internal_event_handler(wifi_handle handle, int events);
51 static int internal_no_seq_check(nl_msg *msg, void *arg);
52 static int internal_valid_message_handler(nl_msg *msg, void *arg);
53 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group);
54 static int wifi_add_membership(wifi_handle handle, const char *group);
55 static wifi_error wifi_init_interfaces(wifi_handle handle);
56 static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
57 iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh);
58 static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface);
59
60 typedef enum wifi_attr {
61 ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET,
62 ANDR_WIFI_ATTRIBUTE_FEATURE_SET,
63 ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI
64 } wifi_attr_t;
65
66 enum wifi_rssi_monitor_attr {
67 RSSI_MONITOR_ATTRIBUTE_MAX_RSSI,
68 RSSI_MONITOR_ATTRIBUTE_MIN_RSSI,
69 RSSI_MONITOR_ATTRIBUTE_START,
70 };
71
72 /* Initialize/Cleanup */
73
wifi_socket_set_local_port(struct nl_sock * sock,uint32_t port)74 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
75 {
76 uint32_t pid = getpid() & 0x3FFFFF;
77 nl_socket_set_local_port(sock, pid + (port << 22));
78 }
79
wifi_create_nl_socket(int port)80 static nl_sock * wifi_create_nl_socket(int port)
81 {
82 // ALOGI("Creating socket");
83 struct nl_sock *sock = nl_socket_alloc();
84 if (sock == NULL) {
85 ALOGE("Could not create handle");
86 return NULL;
87 }
88
89 wifi_socket_set_local_port(sock, port);
90
91 struct sockaddr *addr = NULL;
92 // ALOGI("sizeof(sockaddr) = %d, sizeof(sockaddr_nl) = %d", sizeof(*addr), sizeof(*addr_nl));
93
94 // ALOGI("Connecting socket");
95 if (nl_connect(sock, NETLINK_GENERIC)) {
96 ALOGE("Could not connect handle");
97 nl_socket_free(sock);
98 return NULL;
99 }
100
101 // ALOGI("Making socket nonblocking");
102 /*
103 if (nl_socket_set_nonblocking(sock)) {
104 ALOGE("Could make socket non-blocking");
105 nl_socket_free(sock);
106 return NULL;
107 }
108 */
109
110 return sock;
111 }
112
113 /*initialize function pointer table with Broadcom HHAL API*/
init_wifi_vendor_hal_func_table(wifi_hal_fn * fn)114 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn)
115 {
116 if (fn == NULL) {
117 return WIFI_ERROR_UNKNOWN;
118 }
119 fn->wifi_initialize = wifi_initialize;
120 fn->wifi_cleanup = wifi_cleanup;
121 fn->wifi_event_loop = wifi_event_loop;
122 fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
123 fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
124 fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui;
125 fn->wifi_get_ifaces = wifi_get_ifaces;
126 fn->wifi_get_iface_name = wifi_get_iface_name;
127 fn->wifi_start_gscan = wifi_start_gscan;
128 fn->wifi_stop_gscan = wifi_stop_gscan;
129 fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
130 fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
131 fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
132 fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
133 fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
134 fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
135 fn->wifi_get_link_stats = wifi_get_link_stats;
136 fn->wifi_get_valid_channels = wifi_get_valid_channels;
137 fn->wifi_rtt_range_request = wifi_rtt_range_request;
138 fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
139 fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
140 fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
141 fn->wifi_start_logging = wifi_start_logging;
142 fn->wifi_set_epno_list = wifi_set_epno_list;
143 fn->wifi_set_country_code = wifi_set_country_code;
144 fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
145 fn->wifi_set_log_handler = wifi_set_log_handler;
146 fn->wifi_reset_log_handler = wifi_reset_log_handler;
147 fn->wifi_set_alert_handler = wifi_set_alert_handler;
148 fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
149 fn->wifi_get_firmware_version = wifi_get_firmware_version;
150 fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
151 fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;
152 fn->wifi_get_ring_data = wifi_get_ring_data;
153 fn->wifi_get_driver_version = wifi_get_driver_version;
154 fn->wifi_set_ssid_white_list = wifi_set_ssid_white_list;
155 fn->wifi_set_gscan_roam_params = wifi_set_gscan_roam_params;
156 fn->wifi_set_bssid_preference = wifi_set_bssid_preference;
157 fn->wifi_set_bssid_blacklist = wifi_set_bssid_blacklist;
158 fn->wifi_enable_lazy_roam = wifi_enable_lazy_roam;
159 fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
160 fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
161 fn->wifi_start_sending_offloaded_packet = wifi_start_sending_offloaded_packet;
162 fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
163 return WIFI_SUCCESS;
164 }
165
wifi_initialize(wifi_handle * handle)166 wifi_error wifi_initialize(wifi_handle *handle)
167 {
168 srand(getpid());
169
170 ALOGI("Initializing wifi");
171 hal_info *info = (hal_info *)malloc(sizeof(hal_info));
172 if (info == NULL) {
173 ALOGE("Could not allocate hal_info");
174 return WIFI_ERROR_UNKNOWN;
175 }
176
177 memset(info, 0, sizeof(*info));
178
179 ALOGI("Creating socket");
180 if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->cleanup_socks) == -1) {
181 ALOGE("Could not create cleanup sockets");
182 free(info);
183 return WIFI_ERROR_UNKNOWN;
184 }
185
186 struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT);
187 if (cmd_sock == NULL) {
188 ALOGE("Could not create handle");
189 free(info);
190 return WIFI_ERROR_UNKNOWN;
191 }
192
193 struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT);
194 if (event_sock == NULL) {
195 ALOGE("Could not create handle");
196 nl_socket_free(cmd_sock);
197 free(info);
198 return WIFI_ERROR_UNKNOWN;
199 }
200
201 struct nl_cb *cb = nl_socket_get_cb(event_sock);
202 if (cb == NULL) {
203 ALOGE("Could not create handle");
204 nl_socket_free(cmd_sock);
205 nl_socket_free(event_sock);
206 free(info);
207 return WIFI_ERROR_UNKNOWN;
208 }
209
210 // ALOGI("cb->refcnt = %d", cb->cb_refcnt);
211 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, info);
212 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info);
213 nl_cb_put(cb);
214
215 info->cmd_sock = cmd_sock;
216 info->event_sock = event_sock;
217 info->clean_up = false;
218 info->in_event_loop = false;
219
220 info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
221 info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
222 info->num_event_cb = 0;
223
224 info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
225 info->alloc_cmd = DEFAULT_CMD_SIZE;
226 info->num_cmd = 0;
227
228 info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
229 if (info->nl80211_family_id < 0) {
230 ALOGE("Could not resolve nl80211 familty id");
231 nl_socket_free(cmd_sock);
232 nl_socket_free(event_sock);
233 free(info);
234 return WIFI_ERROR_UNKNOWN;
235 }
236
237 pthread_mutex_init(&info->cb_lock, NULL);
238
239 *handle = (wifi_handle) info;
240
241 wifi_add_membership(*handle, "scan");
242 wifi_add_membership(*handle, "mlme");
243 wifi_add_membership(*handle, "regulatory");
244 wifi_add_membership(*handle, "vendor");
245
246 wifi_init_interfaces(*handle);
247 // ALOGI("Found %d interfaces", info->num_interfaces);
248
249
250 ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d", NL80211_CMD_VENDOR);
251 return WIFI_SUCCESS;
252 }
253
wifi_add_membership(wifi_handle handle,const char * group)254 static int wifi_add_membership(wifi_handle handle, const char *group)
255 {
256 hal_info *info = getHalInfo(handle);
257
258 int id = wifi_get_multicast_id(handle, "nl80211", group);
259 if (id < 0) {
260 ALOGE("Could not find group %s", group);
261 return id;
262 }
263
264 int ret = nl_socket_add_membership(info->event_sock, id);
265 if (ret < 0) {
266 ALOGE("Could not add membership to group %s", group);
267 }
268
269 // ALOGI("Successfully added membership for group %s", group);
270 return ret;
271 }
272
internal_cleaned_up_handler(wifi_handle handle)273 static void internal_cleaned_up_handler(wifi_handle handle)
274 {
275 hal_info *info = getHalInfo(handle);
276 wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
277
278 if (info->cmd_sock != 0) {
279 close(info->cleanup_socks[0]);
280 close(info->cleanup_socks[1]);
281 nl_socket_free(info->cmd_sock);
282 nl_socket_free(info->event_sock);
283 info->cmd_sock = NULL;
284 info->event_sock = NULL;
285 }
286
287 (*cleaned_up_handler)(handle);
288 pthread_mutex_destroy(&info->cb_lock);
289 free(info);
290
291 ALOGI("Internal cleanup completed");
292 }
293
wifi_cleanup(wifi_handle handle,wifi_cleaned_up_handler handler)294 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
295 {
296 hal_info *info = getHalInfo(handle);
297 char buf[64];
298
299 info->cleaned_up_handler = handler;
300 if (write(info->cleanup_socks[0], "Exit", 4) < 1) {
301 // As a fallback set the cleanup flag to TRUE
302 ALOGE("could not write to the cleanup socket");
303 } else {
304 // Listen to the response
305 // Hopefully we dont get errors or get hung up
306 // Not much can be done in that case, but assume that
307 // it has rx'ed the Exit message to exit the thread.
308 // As a fallback set the cleanup flag to TRUE
309 memset(buf, 0, sizeof(buf));
310 int result = read(info->cleanup_socks[0], buf, sizeof(buf));
311 ALOGE("%s: Read after POLL returned %d, error no = %d", __FUNCTION__, result, errno);
312 if (strncmp(buf, "Done", 4) == 0) {
313 ALOGE("Event processing terminated");
314 } else {
315 ALOGD("Rx'ed %s", buf);
316 }
317 }
318 info->clean_up = true;
319 pthread_mutex_lock(&info->cb_lock);
320
321 int bad_commands = 0;
322
323 for (int i = 0; i < info->num_event_cb; i++) {
324 cb_info *cbi = &(info->event_cb[i]);
325 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
326 ALOGI("Command left in event_cb %p:%s", cmd, (cmd ? cmd->getType(): ""));
327 }
328
329 while (info->num_cmd > bad_commands) {
330 int num_cmd = info->num_cmd;
331 cmd_info *cmdi = &(info->cmd[bad_commands]);
332 WifiCommand *cmd = cmdi->cmd;
333 if (cmd != NULL) {
334 ALOGI("Cancelling command %p:%s", cmd, cmd->getType());
335 pthread_mutex_unlock(&info->cb_lock);
336 cmd->cancel();
337 pthread_mutex_lock(&info->cb_lock);
338 if (num_cmd == info->num_cmd) {
339 ALOGI("Cancelling command %p:%s did not work", cmd, (cmd ? cmd->getType(): ""));
340 bad_commands++;
341 }
342 /* release reference added when command is saved */
343 cmd->releaseRef();
344 }
345 }
346
347 for (int i = 0; i < info->num_event_cb; i++) {
348 cb_info *cbi = &(info->event_cb[i]);
349 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
350 ALOGE("Leaked command %p", cmd);
351 }
352 pthread_mutex_unlock(&info->cb_lock);
353 internal_cleaned_up_handler(handle);
354 }
355
internal_pollin_handler(wifi_handle handle)356 static int internal_pollin_handler(wifi_handle handle)
357 {
358 hal_info *info = getHalInfo(handle);
359 struct nl_cb *cb = nl_socket_get_cb(info->event_sock);
360 int res = nl_recvmsgs(info->event_sock, cb);
361 // ALOGD("nl_recvmsgs returned %d", res);
362 nl_cb_put(cb);
363 return res;
364 }
365
366 /* Run event handler */
wifi_event_loop(wifi_handle handle)367 void wifi_event_loop(wifi_handle handle)
368 {
369 hal_info *info = getHalInfo(handle);
370 if (info->in_event_loop) {
371 return;
372 } else {
373 info->in_event_loop = true;
374 }
375
376 pollfd pfd[2];
377 memset(&pfd[0], 0, sizeof(pollfd) * 2);
378
379 pfd[0].fd = nl_socket_get_fd(info->event_sock);
380 pfd[0].events = POLLIN;
381 pfd[1].fd = info->cleanup_socks[1];
382 pfd[1].events = POLLIN;
383
384 char buf[2048];
385 /* TODO: Add support for timeouts */
386
387 do {
388 int timeout = -1; /* Infinite timeout */
389 pfd[0].revents = 0;
390 pfd[1].revents = 0;
391 // ALOGI("Polling socket");
392 int result = poll(pfd, 2, timeout);
393 if (result < 0) {
394 // ALOGE("Error polling socket");
395 } else if (pfd[0].revents & POLLERR) {
396 ALOGE("POLL Error; error no = %d", errno);
397 int result2 = read(pfd[0].fd, buf, sizeof(buf));
398 ALOGE("Read after POLL returned %d, error no = %d", result2, errno);
399 } else if (pfd[0].revents & POLLHUP) {
400 ALOGE("Remote side hung up");
401 break;
402 } else if (pfd[0].revents & POLLIN) {
403 // ALOGI("Found some events!!!");
404 internal_pollin_handler(handle);
405 } else if (pfd[1].revents & POLLIN) {
406 memset(buf, 0, sizeof(buf));
407 int result2 = read(pfd[1].fd, buf, sizeof(buf));
408 ALOGE("%s: Read after POLL returned %d, error no = %d", __FUNCTION__, result2, errno);
409 if (strncmp(buf, "Exit", 4) == 0) {
410 ALOGD("Got a signal to exit!!!");
411 if (write(pfd[1].fd, "Done", 4) < 1) {
412 ALOGE("could not write to the cleanup socket");
413 }
414 break;
415 } else {
416 ALOGD("Rx'ed %s on the cleanup socket\n", buf);
417 }
418 } else {
419 ALOGE("Unknown event - %0x, %0x", pfd[0].revents, pfd[1].revents);
420 }
421 } while (!info->clean_up);
422 ALOGI("Exit %s", __FUNCTION__);
423 }
424
425 ///////////////////////////////////////////////////////////////////////////////////////
426
internal_no_seq_check(struct nl_msg * msg,void * arg)427 static int internal_no_seq_check(struct nl_msg *msg, void *arg)
428 {
429 return NL_OK;
430 }
431
internal_valid_message_handler(nl_msg * msg,void * arg)432 static int internal_valid_message_handler(nl_msg *msg, void *arg)
433 {
434 // ALOGI("got an event");
435
436 wifi_handle handle = (wifi_handle)arg;
437 hal_info *info = getHalInfo(handle);
438
439 WifiEvent event(msg);
440 int res = event.parse();
441 if (res < 0) {
442 ALOGE("Failed to parse event: %d", res);
443 return NL_SKIP;
444 }
445
446 int cmd = event.get_cmd();
447 uint32_t vendor_id = 0;
448 int subcmd = 0;
449
450 if (cmd == NL80211_CMD_VENDOR) {
451 vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
452 subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
453 ALOGV("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
454 event.get_cmdString(), vendor_id, subcmd);
455 } else {
456 // ALOGV("event received %s", event.get_cmdString());
457 }
458
459 // ALOGV("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id);
460 // event.log();
461
462 bool dispatched = false;
463
464 pthread_mutex_lock(&info->cb_lock);
465
466 for (int i = 0; i < info->num_event_cb; i++) {
467 if (cmd == info->event_cb[i].nl_cmd) {
468 if (cmd == NL80211_CMD_VENDOR
469 && ((vendor_id != info->event_cb[i].vendor_id)
470 || (subcmd != info->event_cb[i].vendor_subcmd)))
471 {
472 /* event for a different vendor, ignore it */
473 continue;
474 }
475
476 cb_info *cbi = &(info->event_cb[i]);
477 nl_recvmsg_msg_cb_t cb_func = cbi->cb_func;
478 void *cb_arg = cbi->cb_arg;
479 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
480 if (cmd != NULL) {
481 cmd->addRef();
482 }
483 pthread_mutex_unlock(&info->cb_lock);
484 if (cb_func)
485 (*cb_func)(msg, cb_arg);
486 if (cmd != NULL) {
487 cmd->releaseRef();
488 }
489
490 return NL_OK;
491 }
492 }
493
494 pthread_mutex_unlock(&info->cb_lock);
495 return NL_OK;
496 }
497
498 ///////////////////////////////////////////////////////////////////////////////////////
499
500 class GetMulticastIdCommand : public WifiCommand
501 {
502 private:
503 const char *mName;
504 const char *mGroup;
505 int mId;
506 public:
GetMulticastIdCommand(wifi_handle handle,const char * name,const char * group)507 GetMulticastIdCommand(wifi_handle handle, const char *name, const char *group)
508 : WifiCommand("GetMulticastIdCommand", handle, 0)
509 {
510 mName = name;
511 mGroup = group;
512 mId = -1;
513 }
514
getId()515 int getId() {
516 return mId;
517 }
518
create()519 virtual int create() {
520 int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
521 // ALOGI("ctrl family = %d", nlctrlFamily);
522 int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
523 if (ret < 0) {
524 return ret;
525 }
526 ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
527 return ret;
528 }
529
handleResponse(WifiEvent & reply)530 virtual int handleResponse(WifiEvent& reply) {
531
532 // ALOGI("handling reponse in %s", __func__);
533
534 struct nlattr **tb = reply.attributes();
535 struct genlmsghdr *gnlh = reply.header();
536 struct nlattr *mcgrp = NULL;
537 int i;
538
539 if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
540 ALOGI("No multicast groups found");
541 return NL_SKIP;
542 } else {
543 // ALOGI("Multicast groups attr size = %d", nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
544 }
545
546 for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
547
548 // ALOGI("Processing group");
549 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
550 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
551 nla_len(mcgrp), NULL);
552 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID]) {
553 continue;
554 }
555
556 char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
557 int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
558
559 // ALOGI("Found group name %s", grpName);
560
561 if (strncmp(grpName, mGroup, grpNameLen) != 0)
562 continue;
563
564 mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
565 break;
566 }
567
568 return NL_SKIP;
569 }
570
571 };
572
573 class SetPnoMacAddrOuiCommand : public WifiCommand {
574
575 private:
576 byte *mOui;
577 feature_set *fset;
578 feature_set *feature_matrix;
579 int *fm_size;
580 int set_size_max;
581 public:
SetPnoMacAddrOuiCommand(wifi_interface_handle handle,oui scan_oui)582 SetPnoMacAddrOuiCommand(wifi_interface_handle handle, oui scan_oui)
583 : WifiCommand("SetPnoMacAddrOuiCommand", handle, 0)
584 {
585 mOui = scan_oui;
586 }
587
createRequest(WifiRequest & request,int subcmd,byte * scan_oui)588 int createRequest(WifiRequest& request, int subcmd, byte *scan_oui) {
589 int result = request.create(GOOGLE_OUI, subcmd);
590 if (result < 0) {
591 return result;
592 }
593
594 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
595 result = request.put(ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, scan_oui, DOT11_OUI_LEN);
596 if (result < 0) {
597 return result;
598 }
599
600 request.attr_end(data);
601 return WIFI_SUCCESS;
602
603 }
604
start()605 int start() {
606 ALOGD("Sending mac address OUI");
607 WifiRequest request(familyId(), ifaceId());
608 int result = createRequest(request, WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, mOui);
609 if (result != WIFI_SUCCESS) {
610 ALOGE("failed to create request; result = %d", result);
611 return result;
612 }
613
614 result = requestResponse(request);
615 if (result != WIFI_SUCCESS) {
616 ALOGE("failed to set scanning mac OUI; result = %d", result);
617 }
618
619 return result;
620 }
621 protected:
handleResponse(WifiEvent & reply)622 virtual int handleResponse(WifiEvent& reply) {
623 ALOGD("Request complete!");
624 /* Nothing to do on response! */
625 return NL_SKIP;
626 }
627 };
628
629 class SetNodfsCommand : public WifiCommand {
630
631 private:
632 u32 mNoDfs;
633 public:
SetNodfsCommand(wifi_interface_handle handle,u32 nodfs)634 SetNodfsCommand(wifi_interface_handle handle, u32 nodfs)
635 : WifiCommand("SetNodfsCommand", handle, 0) {
636 mNoDfs = nodfs;
637 }
create()638 virtual int create() {
639 int ret;
640
641 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_NODFS_SET);
642 if (ret < 0) {
643 ALOGE("Can't create message to send to driver - %d", ret);
644 return ret;
645 }
646
647 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
648 ret = mMsg.put_u32(ATTR_NODFS_VALUE, mNoDfs);
649 if (ret < 0) {
650 return ret;
651 }
652
653 mMsg.attr_end(data);
654 return WIFI_SUCCESS;
655 }
656 };
657
658 class SetCountryCodeCommand : public WifiCommand {
659 private:
660 const char *mCountryCode;
661 public:
SetCountryCodeCommand(wifi_interface_handle handle,const char * country_code)662 SetCountryCodeCommand(wifi_interface_handle handle, const char *country_code)
663 : WifiCommand("SetCountryCodeCommand", handle, 0) {
664 mCountryCode = country_code;
665 }
create()666 virtual int create() {
667 int ret;
668
669 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_SET_COUNTRY_CODE);
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_string(ATTR_COUNTRY_CODE, mCountryCode);
677 if (ret < 0) {
678 return ret;
679 }
680
681 mMsg.attr_end(data);
682 return WIFI_SUCCESS;
683
684 }
685 };
686
687 class SetRSSIMonitorCommand : public WifiCommand {
688 private:
689 s8 mMax_rssi;
690 s8 mMin_rssi;
691 wifi_rssi_event_handler mHandler;
692 public:
SetRSSIMonitorCommand(wifi_request_id id,wifi_interface_handle handle,s8 max_rssi,s8 min_rssi,wifi_rssi_event_handler eh)693 SetRSSIMonitorCommand(wifi_request_id id, wifi_interface_handle handle,
694 s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
695 : WifiCommand("SetRSSIMonitorCommand", handle, id), mMax_rssi(max_rssi), mMin_rssi
696 (min_rssi), mHandler(eh)
697 {
698 }
createRequest(WifiRequest & request,int enable)699 int createRequest(WifiRequest& request, int enable) {
700 int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_SET_RSSI_MONITOR);
701 if (result < 0) {
702 return result;
703 }
704
705 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
706 result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_MAX_RSSI, (enable ? mMax_rssi: 0));
707 if (result < 0) {
708 return result;
709 }
710 ALOGD("create request");
711 result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_MIN_RSSI, (enable? mMin_rssi: 0));
712 if (result < 0) {
713 return result;
714 }
715 result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_START, enable);
716 if (result < 0) {
717 return result;
718 }
719 request.attr_end(data);
720 return result;
721 }
722
start()723 int start() {
724 WifiRequest request(familyId(), ifaceId());
725 int result = createRequest(request, 1);
726 if (result < 0) {
727 return result;
728 }
729 result = requestResponse(request);
730 if (result < 0) {
731 ALOGI("Failed to set RSSI Monitor, result = %d", result);
732 return result;
733 }
734 ALOGI("Successfully set RSSI monitoring");
735 registerVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
736
737
738 if (result < 0) {
739 unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
740 return result;
741 }
742 ALOGI("Done!");
743 return result;
744 }
745
cancel()746 virtual int cancel() {
747
748 WifiRequest request(familyId(), ifaceId());
749 int result = createRequest(request, 0);
750 if (result != WIFI_SUCCESS) {
751 ALOGE("failed to create request; result = %d", result);
752 } else {
753 result = requestResponse(request);
754 if (result != WIFI_SUCCESS) {
755 ALOGE("failed to stop RSSI monitoring = %d", result);
756 }
757 }
758 unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
759 return WIFI_SUCCESS;
760 }
761
handleResponse(WifiEvent & reply)762 virtual int handleResponse(WifiEvent& reply) {
763 /* Nothing to do on response! */
764 return NL_SKIP;
765 }
766
handleEvent(WifiEvent & event)767 virtual int handleEvent(WifiEvent& event) {
768 ALOGI("Got a RSSI monitor event");
769
770 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
771 int len = event.get_vendor_data_len();
772
773 if (vendor_data == NULL || len == 0) {
774 ALOGI("RSSI monitor: No data");
775 return NL_SKIP;
776 }
777 /* driver<->HAL event structure */
778 #define RSSI_MONITOR_EVT_VERSION 1
779 typedef struct {
780 u8 version;
781 s8 cur_rssi;
782 mac_addr BSSID;
783 } rssi_monitor_evt;
784
785 rssi_monitor_evt *data = (rssi_monitor_evt *)event.get_vendor_data();
786
787 if (data->version != RSSI_MONITOR_EVT_VERSION) {
788 ALOGI("Event version mismatch %d, expected %d", data->version, RSSI_MONITOR_EVT_VERSION);
789 return NL_SKIP;
790 }
791
792 if (*mHandler.on_rssi_threshold_breached) {
793 (*mHandler.on_rssi_threshold_breached)(id(), data->BSSID, data->cur_rssi);
794 } else {
795 ALOGW("No RSSI monitor handler registered");
796 }
797
798 return NL_SKIP;
799 }
800
801 };
802
803 class GetFeatureSetCommand : public WifiCommand {
804
805 private:
806 int feature_type;
807 feature_set *fset;
808 feature_set *feature_matrix;
809 int *fm_size;
810 int set_size_max;
811 public:
GetFeatureSetCommand(wifi_interface_handle handle,int feature,feature_set * set,feature_set set_matrix[],int * size,int max_size)812 GetFeatureSetCommand(wifi_interface_handle handle, int feature, feature_set *set,
813 feature_set set_matrix[], int *size, int max_size)
814 : WifiCommand("GetFeatureSetCommand", handle, 0)
815 {
816 feature_type = feature;
817 fset = set;
818 feature_matrix = set_matrix;
819 fm_size = size;
820 set_size_max = max_size;
821 }
822
create()823 virtual int create() {
824 int ret;
825
826 if(feature_type == FEATURE_SET) {
827 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET);
828 } else if (feature_type == FEATURE_SET_MATRIX) {
829 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET_MATRIX);
830 } else {
831 ALOGE("Unknown feature type %d", feature_type);
832 return -1;
833 }
834
835 if (ret < 0) {
836 ALOGE("Can't create message to send to driver - %d", ret);
837 }
838
839 return ret;
840 }
841
842 protected:
handleResponse(WifiEvent & reply)843 virtual int handleResponse(WifiEvent& reply) {
844
845 ALOGV("In GetFeatureSetCommand::handleResponse");
846
847 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
848 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
849 return NL_SKIP;
850 }
851
852 int id = reply.get_vendor_id();
853 int subcmd = reply.get_vendor_subcmd();
854
855 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
856 int len = reply.get_vendor_data_len();
857
858 ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
859 if (vendor_data == NULL || len == 0) {
860 ALOGE("no vendor data in GetFeatureSetCommand response; ignoring it");
861 return NL_SKIP;
862 }
863 if(feature_type == FEATURE_SET) {
864 void *data = reply.get_vendor_data();
865 if(!fset) {
866 ALOGE("Buffers pointers not set");
867 return NL_SKIP;
868 }
869 memcpy(fset, data, min(len, (int) sizeof(*fset)));
870 } else {
871 int num_features_set = 0;
872 int i = 0;
873
874 if(!feature_matrix || !fm_size) {
875 ALOGE("Buffers pointers not set");
876 return NL_SKIP;
877 }
878
879 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
880 if (it.get_type() == ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET) {
881 num_features_set = it.get_u32();
882 ALOGV("Got feature list with %d concurrent sets", num_features_set);
883 if(set_size_max && (num_features_set > set_size_max))
884 num_features_set = set_size_max;
885 *fm_size = num_features_set;
886 } else if ((it.get_type() == ANDR_WIFI_ATTRIBUTE_FEATURE_SET) &&
887 i < num_features_set) {
888 feature_matrix[i] = it.get_u32();
889 i++;
890 } else {
891 ALOGW("Ignoring invalid attribute type = %d, size = %d",
892 it.get_type(), it.get_len());
893 }
894 }
895
896 }
897 return NL_OK;
898 }
899
900 };
901
wifi_get_multicast_id(wifi_handle handle,const char * name,const char * group)902 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group)
903 {
904 GetMulticastIdCommand cmd(handle, name, group);
905 int res = cmd.requestResponse();
906 if (res < 0)
907 return res;
908 else
909 return cmd.getId();
910 }
911
912 /////////////////////////////////////////////////////////////////////////
913
is_wifi_interface(const char * name)914 static bool is_wifi_interface(const char *name)
915 {
916 if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
917 /* not a wifi interface; ignore it */
918 return false;
919 } else {
920 return true;
921 }
922 }
923
get_interface(const char * name,interface_info * info)924 static int get_interface(const char *name, interface_info *info)
925 {
926 strcpy(info->name, name);
927 info->id = if_nametoindex(name);
928 // ALOGI("found an interface : %s, id = %d", name, info->id);
929 return WIFI_SUCCESS;
930 }
931
wifi_init_interfaces(wifi_handle handle)932 wifi_error wifi_init_interfaces(wifi_handle handle)
933 {
934 hal_info *info = (hal_info *)handle;
935
936 struct dirent *de;
937
938 DIR *d = opendir("/sys/class/net");
939 if (d == 0)
940 return WIFI_ERROR_UNKNOWN;
941
942 int n = 0;
943 while ((de = readdir(d))) {
944 if (de->d_name[0] == '.')
945 continue;
946 if (is_wifi_interface(de->d_name) ) {
947 n++;
948 }
949 }
950
951 closedir(d);
952
953 d = opendir("/sys/class/net");
954 if (d == 0)
955 return WIFI_ERROR_UNKNOWN;
956
957 info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
958
959 int i = 0;
960 while ((de = readdir(d))) {
961 if (de->d_name[0] == '.')
962 continue;
963 if (is_wifi_interface(de->d_name)) {
964 interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info));
965 if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
966 free(ifinfo);
967 continue;
968 }
969 ifinfo->handle = handle;
970 info->interfaces[i] = ifinfo;
971 i++;
972 }
973 }
974
975 closedir(d);
976
977 info->num_interfaces = n;
978 return WIFI_SUCCESS;
979 }
980
wifi_get_ifaces(wifi_handle handle,int * num,wifi_interface_handle ** interfaces)981 wifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle **interfaces)
982 {
983 hal_info *info = (hal_info *)handle;
984
985 *interfaces = (wifi_interface_handle *)info->interfaces;
986 *num = info->num_interfaces;
987
988 return WIFI_SUCCESS;
989 }
990
wifi_get_iface_name(wifi_interface_handle handle,char * name,size_t size)991 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size)
992 {
993 interface_info *info = (interface_info *)handle;
994 strcpy(name, info->name);
995 return WIFI_SUCCESS;
996 }
997
wifi_get_supported_feature_set(wifi_interface_handle handle,feature_set * set)998 wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *set)
999 {
1000 GetFeatureSetCommand command(handle, FEATURE_SET, set, NULL, NULL, 1);
1001 return (wifi_error) command.requestResponse();
1002 }
1003
wifi_get_concurrency_matrix(wifi_interface_handle handle,int set_size_max,feature_set set[],int * set_size)1004 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_size_max,
1005 feature_set set[], int *set_size)
1006 {
1007 GetFeatureSetCommand command(handle, FEATURE_SET_MATRIX, NULL, set, set_size, set_size_max);
1008 return (wifi_error) command.requestResponse();
1009 }
1010
wifi_set_scanning_mac_oui(wifi_interface_handle handle,oui scan_oui)1011 wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui)
1012 {
1013 SetPnoMacAddrOuiCommand command(handle, scan_oui);
1014 return (wifi_error)command.start();
1015
1016 }
1017
wifi_set_nodfs_flag(wifi_interface_handle handle,u32 nodfs)1018 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
1019 {
1020 SetNodfsCommand command(handle, nodfs);
1021 return (wifi_error) command.requestResponse();
1022 }
1023
wifi_set_country_code(wifi_interface_handle handle,const char * country_code)1024 wifi_error wifi_set_country_code(wifi_interface_handle handle, const char *country_code)
1025 {
1026 SetCountryCodeCommand command(handle, country_code);
1027 return (wifi_error) command.requestResponse();
1028 }
1029
wifi_start_rssi_monitoring(wifi_request_id id,wifi_interface_handle iface,s8 max_rssi,s8 min_rssi,wifi_rssi_event_handler eh)1030 static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
1031 iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
1032 {
1033 ALOGD("Start RSSI monitor %d", id);
1034 wifi_handle handle = getWifiHandle(iface);
1035 SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface, max_rssi, min_rssi, eh);
1036 wifi_register_cmd(handle, id, cmd);
1037
1038 wifi_error result = (wifi_error)cmd->start();
1039 if (result != WIFI_SUCCESS) {
1040 wifi_unregister_cmd(handle, id);
1041 }
1042 return result;
1043 }
1044
1045
wifi_stop_rssi_monitoring(wifi_request_id id,wifi_interface_handle iface)1046 static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface)
1047 {
1048 ALOGD("Stopping RSSI monitor");
1049
1050 if(id == -1) {
1051 wifi_rssi_event_handler handler;
1052 s8 max_rssi = 0, min_rssi = 0;
1053 wifi_handle handle = getWifiHandle(iface);
1054 memset(&handler, 0, sizeof(handler));
1055 SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface,
1056 max_rssi, min_rssi, handler);
1057 cmd->cancel();
1058 cmd->releaseRef();
1059 return WIFI_SUCCESS;
1060 }
1061 return wifi_cancel_cmd(id, iface);
1062 }
1063
1064 /////////////////////////////////////////////////////////////////////////////
1065