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