SSB-8693 slsi hal library code for GSCAN
[GitHub/MotorolaMobilityLLC/hardware-samsung_slsi-scsc_wifibt-wifi_hal.git] / wifi_hal.cpp
1 #include <errno.h>
2 #include <stdint.h>
3 #include <fcntl.h>
4 #include <sys/socket.h>
5 #include <netlink/genl/genl.h>
6 #include <netlink/genl/family.h>
7 #include <netlink/genl/ctrl.h>
8 #include <linux/rtnetlink.h>
9 #include <netpacket/packet.h>
10 #include <linux/filter.h>
11 #include <linux/errqueue.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
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
42 static void internal_event_handler(wifi_handle handle, int events);
43 static int internal_no_seq_check(nl_msg *msg, void *arg);
44 static int internal_valid_message_handler(nl_msg *msg, void *arg);
45 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group);
46 static int wifi_add_membership(wifi_handle handle, const char *group);
47 static wifi_error wifi_init_interfaces(wifi_handle handle);
48
49 typedef enum wifi_attr {
50 ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET,
51 ANDR_WIFI_ATTRIBUTE_FEATURE_SET,
52 ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI
53 } wifi_attr_t;
54
55 /* Initialize/Cleanup */
56
57 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
58 {
59 uint32_t pid = getpid() & 0x3FFFFF;
60 nl_socket_set_local_port(sock, pid + (port << 22));
61 }
62
63 static nl_sock * wifi_create_nl_socket(int port)
64 {
65 ALOGI("Creating socket");
66 struct nl_sock *sock = nl_socket_alloc();
67 if (sock == NULL) {
68 ALOGE("Could not create handle");
69 return NULL;
70 }
71
72 wifi_socket_set_local_port(sock, port);
73
74 struct sockaddr *addr = NULL;
75 // ALOGI("sizeof(sockaddr) = %d, sizeof(sockaddr_nl) = %d", sizeof(*addr), sizeof(*addr_nl));
76
77 ALOGI("Connecting socket");
78 if (nl_connect(sock, NETLINK_GENERIC)) {
79 ALOGE("Could not connect handle");
80 nl_socket_free(sock);
81 return NULL;
82 }
83
84 ALOGI("Making socket nonblocking");
85 /*
86 if (nl_socket_set_nonblocking(sock)) {
87 ALOGE("Could make socket non-blocking");
88 nl_socket_free(sock);
89 return NULL;
90 }
91 */
92
93 return sock;
94 }
95
96 wifi_error wifi_initialize(wifi_handle *handle)
97 {
98 srand(getpid());
99
100 ALOGI("Initializing wifi");
101 hal_info *info = (hal_info *)malloc(sizeof(hal_info));
102 if (info == NULL) {
103 ALOGE("Could not allocate hal_info");
104 return WIFI_ERROR_UNKNOWN;
105 }
106
107 memset(info, 0, sizeof(*info));
108
109 ALOGI("Creating socket");
110 struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT);
111 if (cmd_sock == NULL) {
112 ALOGE("Could not create handle");
113 return WIFI_ERROR_UNKNOWN;
114 }
115
116 struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT);
117 if (event_sock == NULL) {
118 ALOGE("Could not create handle");
119 nl_socket_free(cmd_sock);
120 return WIFI_ERROR_UNKNOWN;
121 }
122
123 struct nl_cb *cb = nl_socket_get_cb(event_sock);
124 if (cb == NULL) {
125 ALOGE("Could not create handle");
126 return WIFI_ERROR_UNKNOWN;
127 }
128
129 // ALOGI("cb->refcnt = %d", cb->cb_refcnt);
130 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, info);
131 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info);
132 nl_cb_put(cb);
133
134 info->cmd_sock = cmd_sock;
135 info->event_sock = event_sock;
136 info->clean_up = false;
137 info->in_event_loop = false;
138
139 info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
140 info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
141 info->num_event_cb = 0;
142
143 info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
144 info->alloc_cmd = DEFAULT_CMD_SIZE;
145 info->num_cmd = 0;
146
147 info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
148 if (info->nl80211_family_id < 0) {
149 ALOGE("Could not resolve nl80211 familty id");
150 nl_socket_free(cmd_sock);
151 nl_socket_free(event_sock);
152 free(info);
153 return WIFI_ERROR_UNKNOWN;
154 }
155
156 pthread_mutex_init(&info->cb_lock, NULL);
157
158 *handle = (wifi_handle) info;
159 ALOGD("wifi_initialize, handle = %p\n", handle);
160 ALOGD("wifi_initialize, *handle = %p\n", *handle);
161 ALOGD("wifi_initialize, info = %p\n", info);
162 ALOGD("wifi_initialize, *info = %pn", *info);
163 wifi_add_membership(*handle, "scan");
164 wifi_add_membership(*handle, "mlme");
165 wifi_add_membership(*handle, "regulatory");
166 wifi_add_membership(*handle, "vendor");
167
168 wifi_init_interfaces(*handle);
169 ALOGD("Found %d interfaces", info->num_interfaces);
170
171
172 ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d", NL80211_CMD_VENDOR);
173 return WIFI_SUCCESS;
174 }
175
176 static int wifi_add_membership(wifi_handle handle, const char *group)
177 {
178 hal_info *info = getHalInfo(handle);
179
180 int id = wifi_get_multicast_id(handle, "nl80211", group);
181 if (id < 0) {
182 ALOGE("Could not find group %s", group);
183 return id;
184 }
185
186 int ret = nl_socket_add_membership(info->event_sock, id);
187 if (ret < 0) {
188 ALOGE("Could not add membership to group %s", group);
189 }
190
191 ALOGI("Successfully added membership for group %s", group);
192 return ret;
193 }
194
195 static void internal_cleaned_up_handler(wifi_handle handle)
196 {
197 hal_info *info = getHalInfo(handle);
198 wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
199
200 if (info->cmd_sock != 0) {
201 nl_socket_free(info->cmd_sock);
202 nl_socket_free(info->event_sock);
203 info->cmd_sock = NULL;
204 info->event_sock = NULL;
205 }
206
207 (*cleaned_up_handler)(handle);
208 pthread_mutex_destroy(&info->cb_lock);
209 free(info);
210
211 ALOGI("Internal cleanup completed");
212 }
213
214 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
215 {
216 hal_info *info = getHalInfo(handle);
217 info->cleaned_up_handler = handler;
218 info->clean_up = true;
219
220 ALOGI("Wifi cleanup completed");
221 }
222
223 static int internal_pollin_handler(wifi_handle handle)
224 {
225 hal_info *info = getHalInfo(handle);
226 ALOGI("even_loop info = %p", info);
227 struct nl_cb *cb = nl_socket_get_cb(info->event_sock);
228 int res = nl_recvmsgs(info->event_sock, cb);
229 ALOGD("nl_recvmsgs returned %d", res);
230 nl_cb_put(cb);
231 return res;
232 }
233
234 /* Run event handler */
235 void wifi_event_loop(wifi_handle handle)
236 {
237 hal_info *info = getHalInfo(handle);
238 ALOGI("even_loop info = %p", info);
239 ALOGI("even_loop info = %p", handle);
240 if (info->in_event_loop) {
241 return;
242 } else {
243 info->in_event_loop = true;
244 }
245
246 pollfd pfd;
247 memset(&pfd, 0, sizeof(pfd));
248
249 pfd.fd = nl_socket_get_fd(info->event_sock);
250 pfd.events = POLLIN;
251
252 /* TODO: Add support for timeouts */
253
254 do {
255 int timeout = -1; /* Infinite timeout */
256 pfd.revents = 0;
257 ALOGI("Polling socket");
258 int result = poll(&pfd, 1, -1);
259 if (result < 0) {
260 ALOGE("Error polling socket");
261 } else if (pfd.revents & POLLERR) {
262 ALOGE("POLL Error; error no = %d", errno);
263 char buf[2048];
264 int result2 = read(pfd.fd, buf, sizeof(buf));
265 ALOGE("Read after POLL returned %d, error no = %d", result2, errno);
266 } else if (pfd.revents & POLLHUP) {
267 ALOGE("Remote side hung up");
268 break;
269 } else if (pfd.revents & POLLIN) {
270 ALOGI("Found some events!!!");
271 internal_pollin_handler(handle);
272 } else {
273 ALOGE("Unknown event - %0x", pfd.revents);
274 }
275 } while (!info->clean_up);
276
277
278 ALOGI("Cleaning up");
279 internal_cleaned_up_handler(handle);
280 }
281
282 ///////////////////////////////////////////////////////////////////////////////////////
283
284 static int internal_no_seq_check(struct nl_msg *msg, void *arg)
285 {
286 return NL_OK;
287 }
288
289 static int internal_valid_message_handler(nl_msg *msg, void *arg)
290 {
291 wifi_handle handle = (wifi_handle)arg;
292 hal_info *info = getHalInfo(handle);
293 ALOGI("even_loop info = %p", handle);
294 ALOGD("internal_valid_message_handler, info = %p", info);
295
296 WifiEvent event(msg);
297 int res = event.parse();
298 if (res < 0) {
299 ALOGE("Failed to parse event: %d", res);
300 return NL_SKIP;
301 }
302
303 int cmd = event.get_cmd();
304 uint32_t vendor_id = 0;
305 int subcmd = 0;
306
307 if (cmd == NL80211_CMD_VENDOR) {
308 vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
309 subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
310 ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
311 event.get_cmdString(), vendor_id, subcmd);
312 } else {
313 ALOGI("event received %s", event.get_cmdString());
314 }
315
316 //ALOGI("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id);
317 //event.log();
318
319 bool dispatched = false;
320
321 pthread_mutex_lock(&info->cb_lock);
322
323 ALOGI("Number of events %d", info->num_event_cb);
324
325 for (int i = 0; i < info->num_event_cb; i++) {
326 if (cmd == info->event_cb[i].nl_cmd) {
327 if (cmd == NL80211_CMD_VENDOR
328 && ((vendor_id != info->event_cb[i].vendor_id)
329 || (subcmd != info->event_cb[i].vendor_subcmd)))
330 {
331 /* event for a different vendor, ignore it */
332 continue;
333 }
334
335 cb_info *cbi = &(info->event_cb[i]);
336 nl_recvmsg_msg_cb_t cb_func = cbi->cb_func;
337 void *cb_arg = cbi->cb_arg;
338 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
339 if (cmd != NULL) {
340 cmd->addRef();
341 }
342
343 pthread_mutex_unlock(&info->cb_lock);
344
345 (*cb_func)(msg, cb_arg);
346 if (cmd != NULL) {
347 cmd->releaseRef();
348 }
349
350 return NL_OK;
351 }
352 }
353
354 pthread_mutex_unlock(&info->cb_lock);
355 return NL_OK;
356 }
357
358 ///////////////////////////////////////////////////////////////////////////////////////
359
360 class GetMulticastIdCommand : public WifiCommand
361 {
362 private:
363 const char *mName;
364 const char *mGroup;
365 int mId;
366 public:
367 GetMulticastIdCommand(wifi_handle handle, const char *name, const char *group)
368 : WifiCommand(handle, 0)
369 {
370 mName = name;
371 mGroup = group;
372 mId = -1;
373 }
374
375 int getId() {
376 return mId;
377 }
378
379 virtual int create() {
380 int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
381 ALOGI("ctrl family = %d", nlctrlFamily);
382 int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
383 if (ret < 0) {
384 return ret;
385 }
386 ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
387 return ret;
388 }
389
390 virtual int handleResponse(WifiEvent& reply) {
391
392 ALOGE("handling reponse in %s", __func__);
393
394 struct nlattr **tb = reply.attributes();
395 struct genlmsghdr *gnlh = reply.header();
396 struct nlattr *mcgrp = NULL;
397 int i;
398
399 if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
400 ALOGE("No multicast groups found");
401 return NL_SKIP;
402 } else {
403 ALOGE("Multicast groups attr size = %d", nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
404 }
405
406 for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
407
408 ALOGE("Processing group");
409 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
410 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
411 nla_len(mcgrp), NULL);
412 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID]) {
413 continue;
414 }
415
416 char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
417 int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
418
419 ALOGE("Found group name %s", grpName);
420
421 if (strncmp(grpName, mGroup, grpNameLen) != 0)
422 continue;
423
424 mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
425 break;
426 }
427
428 return NL_SKIP;
429 }
430
431 };
432
433 class SetPnoMacAddrOuiCommand : public WifiCommand {
434
435 private:
436 byte *mOui;
437 feature_set *fset;
438 feature_set *feature_matrix;
439 int *fm_size;
440 int set_size_max;
441 public:
442 SetPnoMacAddrOuiCommand(wifi_interface_handle handle, oui scan_oui)
443 : WifiCommand(handle, 0)
444 {
445 mOui = scan_oui;
446 }
447
448 int createRequest(WifiRequest& request, int subcmd, byte *scan_oui) {
449 int result = request.create(GOOGLE_OUI, subcmd);
450 if (result < 0) {
451 return result;
452 }
453
454 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
455 result = request.put(ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, scan_oui, DOT11_OUI_LEN);
456 if (result < 0) {
457 return result;
458 }
459
460 request.attr_end(data);
461 return WIFI_SUCCESS;
462
463 }
464
465 int start() {
466 ALOGD("Sending mac address OUI");
467 WifiRequest request(familyId(), ifaceId());
468 int result = createRequest(request, SLSI_NL80211_VENDOR_SUBCMD_SET_GSCAN_OUI, mOui);
469 if (result != WIFI_SUCCESS) {
470 ALOGE("failed to create request; result = %d", result);
471 return result;
472 }
473
474 result = requestResponse(request);
475 if (result != WIFI_SUCCESS) {
476 ALOGE("failed to set scanning mac OUI; result = %d", result);
477 }
478
479 return result;
480 }
481 protected:
482 virtual int handleResponse(WifiEvent& reply) {
483 ALOGD("Request complete!");
484 /* Nothing to do on response! */
485 return NL_SKIP;
486 }
487 };
488
489 class SetNodfsCommand : public WifiCommand {
490
491 private:
492 u32 mNoDfs;
493 public:
494 SetNodfsCommand(wifi_interface_handle handle, u32 nodfs)
495 : WifiCommand(handle, 0) {
496 mNoDfs = nodfs;
497 }
498 virtual int create() {
499 int ret;
500
501 ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_NODFS);
502 if (ret < 0) {
503 ALOGE("Can't create message to send to driver - %d", ret);
504 return ret;
505 }
506
507 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
508 ret = mMsg.put_u32(ATTR_NODFS_VALUE, mNoDfs);
509 if (ret < 0) {
510 return ret;
511 }
512
513 mMsg.attr_end(data);
514 return WIFI_SUCCESS;
515 }
516 };
517
518 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group)
519 {
520 GetMulticastIdCommand cmd(handle, name, group);
521 int res = cmd.requestResponse();
522 if (res < 0)
523 return res;
524 else
525 return cmd.getId();
526 }
527
528 /////////////////////////////////////////////////////////////////////////
529
530 static bool is_wifi_interface(const char *name)
531 {
532 if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
533 /* not a wifi interface; ignore it */
534 return false;
535 } else {
536 return true;
537 }
538 }
539
540 static int get_interface(const char *name, interface_info *info)
541 {
542 strcpy(info->name, name);
543 info->id = if_nametoindex(name);
544 ALOGI("found an interface : %s, id = %d", name, info->id);
545 return WIFI_SUCCESS;
546 }
547
548 wifi_error wifi_init_interfaces(wifi_handle handle)
549 {
550 hal_info *info = (hal_info *)handle;
551 ALOGD("wifi_init_interfaces, info = %p", info);
552
553 struct dirent *de;
554
555 DIR *d = opendir("/sys/class/net");
556 if (d == 0)
557 return WIFI_ERROR_UNKNOWN;
558
559 int n = 0;
560 while ((de = readdir(d))) {
561 if (de->d_name[0] == '.')
562 continue;
563 if (is_wifi_interface(de->d_name) ) {
564 n++;
565 }
566 }
567
568 closedir(d);
569
570 d = opendir("/sys/class/net");
571 if (d == 0)
572 return WIFI_ERROR_UNKNOWN;
573
574 info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
575
576 int i = 0;
577 while ((de = readdir(d))) {
578 if (de->d_name[0] == '.')
579 continue;
580 if (is_wifi_interface(de->d_name)) {
581 interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info));
582 if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
583 free(ifinfo);
584 continue;
585 }
586 ifinfo->handle = handle;
587 info->interfaces[i] = ifinfo;
588 i++;
589 }
590 }
591
592 closedir(d);
593
594 info->num_interfaces = n;
595 return WIFI_SUCCESS;
596 }
597
598 wifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle **interfaces)
599 {
600 hal_info *info = (hal_info *)handle;
601
602 *interfaces = (wifi_interface_handle *)info->interfaces;
603 *num = info->num_interfaces;
604
605 return WIFI_SUCCESS;
606 }
607
608 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size)
609 {
610 interface_info *info = (interface_info *)handle;
611 strcpy(name, info->name);
612 return WIFI_SUCCESS;
613 }
614
615 wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *set)
616 {
617 return WIFI_ERROR_NOT_SUPPORTED;
618 }
619
620 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_size_max,
621 feature_set set[], int *set_size)
622 {
623 return WIFI_ERROR_NOT_SUPPORTED;
624 }
625
626 wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui)
627 {
628 SetPnoMacAddrOuiCommand command(handle, scan_oui);
629 return (wifi_error)command.start();
630
631 }
632
633 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
634 {
635 SetNodfsCommand command(handle, nodfs);
636 return (wifi_error) command.requestResponse();
637 }
638
639 /////////////////////////////////////////////////////////////////////////////