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