723d0d3e4991860eab5ab96e715dbe3c0b2220d7
[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 ALOGI("Connecting socket");
75 if (nl_connect(sock, NETLINK_GENERIC)) {
76 ALOGE("Could not connect handle");
77 nl_socket_free(sock);
78 return NULL;
79 }
80
81 return sock;
82 }
83
84 /* Initialize HAL function pointer table */
85 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn)
86 {
87 if (fn == NULL) {
88 return WIFI_ERROR_UNKNOWN;
89 }
90 fn->wifi_initialize = wifi_initialize;
91 fn->wifi_cleanup = wifi_cleanup;
92 fn->wifi_event_loop = wifi_event_loop;
93 fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
94 fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
95 fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui;
96 fn->wifi_get_ifaces = wifi_get_ifaces;
97 fn->wifi_get_iface_name = wifi_get_iface_name;
98 fn->wifi_start_gscan = wifi_start_gscan;
99 fn->wifi_stop_gscan = wifi_stop_gscan;
100 fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
101 fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
102 fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
103 fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
104 fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
105 fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
106 fn->wifi_get_link_stats = wifi_get_link_stats;
107 fn->wifi_get_valid_channels = wifi_get_valid_channels;
108 fn->wifi_rtt_range_request = wifi_rtt_range_request;
109 fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
110 fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
111 fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
112 fn->wifi_start_sending_offloaded_packet = wifi_start_sending_offloaded_packet;
113 fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
114 fn->wifi_set_bssid_blacklist = wifi_set_bssid_blacklist;
115 return WIFI_SUCCESS;
116 }
117
118 wifi_error wifi_initialize(wifi_handle *handle)
119 {
120 srand(getpid());
121
122 ALOGI("Initializing wifi");
123 hal_info *info = (hal_info *)malloc(sizeof(hal_info));
124 if (info == NULL) {
125 ALOGE("Could not allocate hal_info");
126 return WIFI_ERROR_UNKNOWN;
127 }
128
129 memset(info, 0, sizeof(*info));
130
131 ALOGI("Creating socket");
132 if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->cleanup_socks) == -1) {
133 ALOGE("Could not create cleanup sockets");
134 free(info);
135 return WIFI_ERROR_UNKNOWN;
136 }
137
138 struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT);
139 if (cmd_sock == NULL) {
140 ALOGE("Could not create handle");
141 free(info);
142 return WIFI_ERROR_UNKNOWN;
143 }
144
145 struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT);
146 if (event_sock == NULL) {
147 ALOGE("Could not create handle");
148 nl_socket_free(cmd_sock);
149 free(info);
150 return WIFI_ERROR_UNKNOWN;
151 }
152
153 struct nl_cb *cb = nl_socket_get_cb(event_sock);
154 if (cb == NULL) {
155 ALOGE("Could not create handle");
156 nl_socket_free(cmd_sock);
157 nl_socket_free(event_sock);
158 free(info);
159 return WIFI_ERROR_UNKNOWN;
160 }
161
162 // ALOGI("cb->refcnt = %d", cb->cb_refcnt);
163 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, info);
164 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info);
165 nl_cb_put(cb);
166
167 info->cmd_sock = cmd_sock;
168 info->event_sock = event_sock;
169 info->clean_up = false;
170 info->in_event_loop = false;
171
172 info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
173 info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
174 info->num_event_cb = 0;
175
176 info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
177 info->alloc_cmd = DEFAULT_CMD_SIZE;
178 info->num_cmd = 0;
179
180 info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
181 if (info->nl80211_family_id < 0) {
182 ALOGE("Could not resolve nl80211 familty id");
183 nl_socket_free(cmd_sock);
184 nl_socket_free(event_sock);
185 free(info);
186 return WIFI_ERROR_UNKNOWN;
187 }
188
189 pthread_mutex_init(&info->cb_lock, NULL);
190
191 *handle = (wifi_handle) info;
192 ALOGD("wifi_initialize, handle = %p\n", handle);
193 ALOGD("wifi_initialize, *handle = %p\n", *handle);
194 ALOGD("wifi_initialize, info = %p\n", info);
195 ALOGD("wifi_initialize, *info = %pn", *info);
196 wifi_add_membership(*handle, "scan");
197 wifi_add_membership(*handle, "mlme");
198 wifi_add_membership(*handle, "regulatory");
199 wifi_add_membership(*handle, "vendor");
200
201 wifi_init_interfaces(*handle);
202 ALOGD("Found %d interfaces", info->num_interfaces);
203
204
205 ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d", NL80211_CMD_VENDOR);
206 return WIFI_SUCCESS;
207 }
208
209 static int wifi_add_membership(wifi_handle handle, const char *group)
210 {
211 hal_info *info = getHalInfo(handle);
212
213 int id = wifi_get_multicast_id(handle, "nl80211", group);
214 if (id < 0) {
215 ALOGE("Could not find group %s", group);
216 return id;
217 }
218
219 int ret = nl_socket_add_membership(info->event_sock, id);
220 if (ret < 0) {
221 ALOGE("Could not add membership to group %s", group);
222 }
223
224 ALOGI("Successfully added membership for group %s", group);
225 return ret;
226 }
227
228 static void internal_cleaned_up_handler(wifi_handle handle)
229 {
230 hal_info *info = getHalInfo(handle);
231 wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
232
233 if (info->cmd_sock != 0) {
234 close(info->cleanup_socks[0]);
235 close(info->cleanup_socks[1]);
236 nl_socket_free(info->cmd_sock);
237 nl_socket_free(info->event_sock);
238 info->cmd_sock = NULL;
239 info->event_sock = NULL;
240 }
241
242 (*cleaned_up_handler)(handle);
243 pthread_mutex_destroy(&info->cb_lock);
244 free(info);
245
246 ALOGI("Internal cleanup completed");
247 }
248
249 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
250 {
251 hal_info *info = getHalInfo(handle);
252 char buf[64];
253
254 info->cleaned_up_handler = handler;
255 if (write(info->cleanup_socks[0], "Exit", 4) < 1) {
256 ALOGE("could not write to the cleanup socket");
257 } else {
258 // Listen to the response
259 // Hopefully we dont get errors or get hung up
260 // Not much can be done in that case, but assume that
261 // it has rx'ed the Exit message to exit the thread.
262 // As a fallback set the cleanup flag to TRUE
263 memset(buf, 0, sizeof(buf));
264 int result = read(info->cleanup_socks[0], buf, sizeof(buf));
265 ALOGE("%s: Read after POLL returned %d, error no = %d", __FUNCTION__, result, errno);
266 if (strncmp(buf, "Done", 4) == 0) {
267 ALOGE("Event processing terminated");
268 } else {
269 ALOGD("Rx'ed %s", buf);
270 }
271 }
272 info->clean_up = true;
273 pthread_mutex_lock(&info->cb_lock);
274
275 int bad_commands = 0;
276
277 while (info->num_cmd > bad_commands) {
278 int num_cmd = info->num_cmd;
279 cmd_info *cmdi = &(info->cmd[bad_commands]);
280 WifiCommand *cmd = cmdi->cmd;
281 if (cmd != NULL) {
282 pthread_mutex_unlock(&info->cb_lock);
283 cmd->cancel();
284 pthread_mutex_lock(&info->cb_lock);
285 /* release reference added when command is saved */
286 cmd->releaseRef();
287 if (num_cmd == info->num_cmd) {
288 bad_commands++;
289 }
290 }
291 }
292
293 for (int i = 0; i < info->num_event_cb; i++) {
294 cb_info *cbi = &(info->event_cb[i]);
295 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
296 ALOGE("Leaked command %p", cmd);
297 }
298 pthread_mutex_unlock(&info->cb_lock);
299 internal_cleaned_up_handler(handle);
300 }
301
302 static int internal_pollin_handler(wifi_handle handle)
303 {
304 hal_info *info = getHalInfo(handle);
305 ALOGI("even_loop info = %p", info);
306 struct nl_cb *cb = nl_socket_get_cb(info->event_sock);
307 int res = nl_recvmsgs(info->event_sock, cb);
308 ALOGD("nl_recvmsgs returned %d", res);
309 nl_cb_put(cb);
310 return res;
311 }
312
313 /* Run event handler */
314 void wifi_event_loop(wifi_handle handle)
315 {
316 hal_info *info = getHalInfo(handle);
317 ALOGI("even_loop info = %p", info);
318 ALOGI("even_loop info = %p", handle);
319 if (info->in_event_loop) {
320 return;
321 } else {
322 info->in_event_loop = true;
323 }
324
325 pollfd pfd[2];
326 memset(&pfd[0], 0, sizeof(pollfd) * 2);
327
328 pfd[0].fd = nl_socket_get_fd(info->event_sock);
329 pfd[0].events = POLLIN;
330 pfd[1].fd = info->cleanup_socks[1];
331 pfd[1].events = POLLIN;
332
333 char buf[2048];
334
335 do {
336 int timeout = -1; /* Infinite timeout */
337 pfd[0].revents = 0;
338 pfd[1].revents = 0;
339 int result = poll(pfd, 2, timeout);
340 if (result < 0) {
341 } else if (pfd[0].revents & POLLERR) {
342 ALOGE("POLL Error; error no = %d", errno);
343 int result2 = read(pfd[0].fd, buf, sizeof(buf));
344 ALOGE("Read after POLL returned %d, error no = %d", result2, errno);
345 } else if (pfd[0].revents & POLLHUP) {
346 ALOGE("Remote side hung up");
347 break;
348 } else if (pfd[0].revents & POLLIN) {
349 internal_pollin_handler(handle);
350 } else if (pfd[1].revents & POLLIN) {
351 memset(buf, 0, sizeof(buf));
352 int result2 = read(pfd[1].fd, buf, sizeof(buf));
353 ALOGE("%s: Read after POLL returned %d, error no = %d", __FUNCTION__, result2, errno);
354 if (strncmp(buf, "Exit", 4) == 0) {
355 ALOGD("Got a signal to exit!!!");
356 if (write(pfd[1].fd, "Done", 4) < 1) {
357 ALOGE("could not write to the cleanup socket");
358 }
359 break;
360 } else {
361 ALOGD("Rx'ed %s on the cleanup socket\n", buf);
362 }
363 } else {
364 ALOGE("Unknown event - %0x, %0x", pfd[0].revents, pfd[1].revents);
365 }
366 } while (!info->clean_up);
367 ALOGI("Exit %s", __FUNCTION__);
368 }
369
370 ///////////////////////////////////////////////////////////////////////////////////////
371
372 static int internal_no_seq_check(struct nl_msg *msg, void *arg)
373 {
374 return NL_OK;
375 }
376
377 static int internal_valid_message_handler(nl_msg *msg, void *arg)
378 {
379 wifi_handle handle = (wifi_handle)arg;
380 hal_info *info = getHalInfo(handle);
381 ALOGI("even_loop info = %p", handle);
382 ALOGD("internal_valid_message_handler, info = %p", info);
383
384 WifiEvent event(msg);
385 int res = event.parse();
386 if (res < 0) {
387 ALOGE("Failed to parse event: %d", res);
388 return NL_SKIP;
389 }
390
391 int cmd = event.get_cmd();
392 uint32_t vendor_id = 0;
393 int subcmd = 0;
394
395 if (cmd == NL80211_CMD_VENDOR) {
396 vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
397 subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
398 ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
399 event.get_cmdString(), vendor_id, subcmd);
400 } else {
401 ALOGI("event received %s", event.get_cmdString());
402 }
403
404 //ALOGI("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id);
405 //event.log();
406
407 pthread_mutex_lock(&info->cb_lock);
408
409 ALOGI("Number of events %d", info->num_event_cb);
410
411 for (int i = 0; i < info->num_event_cb; i++) {
412 if (cmd == info->event_cb[i].nl_cmd) {
413 if (cmd == NL80211_CMD_VENDOR
414 && ((vendor_id != info->event_cb[i].vendor_id)
415 || (subcmd != info->event_cb[i].vendor_subcmd)))
416 {
417 /* event for a different vendor, ignore it */
418 continue;
419 }
420
421 cb_info *cbi = &(info->event_cb[i]);
422 nl_recvmsg_msg_cb_t cb_func = cbi->cb_func;
423 void *cb_arg = cbi->cb_arg;
424 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
425 if (cmd != NULL) {
426 cmd->addRef();
427 }
428
429 pthread_mutex_unlock(&info->cb_lock);
430 if (cb_func)
431 (*cb_func)(msg, cb_arg);
432 if (cmd != NULL) {
433 cmd->releaseRef();
434 }
435
436 return NL_OK;
437 }
438 }
439
440 pthread_mutex_unlock(&info->cb_lock);
441 return NL_OK;
442 }
443
444 ///////////////////////////////////////////////////////////////////////////////////////
445
446 class GetMulticastIdCommand : public WifiCommand
447 {
448 private:
449 const char *mName;
450 const char *mGroup;
451 int mId;
452 public:
453 GetMulticastIdCommand(wifi_handle handle, const char *name, const char *group)
454 : WifiCommand(handle, 0)
455 {
456 mName = name;
457 mGroup = group;
458 mId = -1;
459 }
460
461 int getId() {
462 return mId;
463 }
464
465 virtual int create() {
466 int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
467 ALOGI("ctrl family = %d", nlctrlFamily);
468 int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
469 if (ret < 0) {
470 return ret;
471 }
472 ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
473 return ret;
474 }
475
476 virtual int handleResponse(WifiEvent& reply) {
477
478 ALOGE("handling reponse in %s", __func__);
479
480 struct nlattr **tb = reply.attributes();
481 struct nlattr *mcgrp = NULL;
482 int i;
483
484 if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
485 ALOGE("No multicast groups found");
486 return NL_SKIP;
487 } else {
488 ALOGE("Multicast groups attr size = %d", nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
489 }
490
491 for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
492
493 ALOGE("Processing group");
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 ALOGE("Found group name %s", grpName);
505
506 if (strncmp(grpName, mGroup, grpNameLen) != 0)
507 continue;
508
509 mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
510 break;
511 }
512
513 return NL_SKIP;
514 }
515
516 };
517
518 class SetPnoMacAddrOuiCommand : public WifiCommand {
519
520 private:
521 byte *mOui;
522 feature_set *fset;
523 feature_set *feature_matrix;
524 int *fm_size;
525 int set_size_max;
526 public:
527 SetPnoMacAddrOuiCommand(wifi_interface_handle handle, oui scan_oui)
528 : WifiCommand(handle, 0)
529 {
530 mOui = scan_oui;
531 }
532
533 int createRequest(WifiRequest& request, int subcmd, byte *scan_oui) {
534 int result = request.create(GOOGLE_OUI, subcmd);
535 if (result < 0) {
536 return result;
537 }
538
539 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
540 result = request.put(ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, scan_oui, DOT11_OUI_LEN);
541 if (result < 0) {
542 return result;
543 }
544
545 request.attr_end(data);
546 return WIFI_SUCCESS;
547
548 }
549
550 int start() {
551 ALOGD("Sending mac address OUI");
552 WifiRequest request(familyId(), ifaceId());
553 int result = createRequest(request, SLSI_NL80211_VENDOR_SUBCMD_SET_GSCAN_OUI, mOui);
554 if (result != WIFI_SUCCESS) {
555 ALOGE("failed to create request; result = %d", result);
556 return result;
557 }
558
559 result = requestResponse(request);
560 if (result != WIFI_SUCCESS) {
561 ALOGE("failed to set scanning mac OUI; result = %d", result);
562 }
563
564 return result;
565 }
566 protected:
567 virtual int handleResponse(WifiEvent& reply) {
568 ALOGD("Request complete!");
569 /* Nothing to do on response! */
570 return NL_SKIP;
571 }
572 };
573
574 class SetNodfsCommand : public WifiCommand {
575
576 private:
577 u32 mNoDfs;
578 public:
579 SetNodfsCommand(wifi_interface_handle handle, u32 nodfs)
580 : WifiCommand(handle, 0) {
581 mNoDfs = nodfs;
582 }
583 virtual int create() {
584 int ret;
585
586 ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_NODFS);
587 if (ret < 0) {
588 ALOGE("Can't create message to send to driver - %d", ret);
589 return ret;
590 }
591
592 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
593 ret = mMsg.put_u32(ATTR_NODFS_VALUE, mNoDfs);
594 if (ret < 0) {
595 return ret;
596 }
597
598 mMsg.attr_end(data);
599 return WIFI_SUCCESS;
600 }
601 };
602
603 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group)
604 {
605 GetMulticastIdCommand cmd(handle, name, group);
606 int res = cmd.requestResponse();
607 if (res < 0)
608 return res;
609 else
610 return cmd.getId();
611 }
612
613 /////////////////////////////////////////////////////////////////////////
614
615 static bool is_wifi_interface(const char *name)
616 {
617 if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
618 /* not a wifi interface; ignore it */
619 return false;
620 } else {
621 return true;
622 }
623 }
624
625 static int get_interface(const char *name, interface_info *info)
626 {
627 strcpy(info->name, name);
628 info->id = if_nametoindex(name);
629 ALOGI("found an interface : %s, id = %d", name, info->id);
630 return WIFI_SUCCESS;
631 }
632
633 wifi_error wifi_init_interfaces(wifi_handle handle)
634 {
635 hal_info *info = (hal_info *)handle;
636 ALOGD("wifi_init_interfaces, info = %p", info);
637
638 struct dirent *de;
639
640 DIR *d = opendir("/sys/class/net");
641 if (d == 0)
642 return WIFI_ERROR_UNKNOWN;
643
644 int n = 0;
645 while ((de = readdir(d))) {
646 if (de->d_name[0] == '.')
647 continue;
648 if (is_wifi_interface(de->d_name) ) {
649 n++;
650 }
651 }
652
653 closedir(d);
654
655 d = opendir("/sys/class/net");
656 if (d == 0)
657 return WIFI_ERROR_UNKNOWN;
658
659 info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
660
661 int i = 0;
662 while ((de = readdir(d))) {
663 if (de->d_name[0] == '.')
664 continue;
665 if (is_wifi_interface(de->d_name)) {
666 interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info));
667 if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
668 free(ifinfo);
669 continue;
670 }
671 ifinfo->handle = handle;
672 info->interfaces[i] = ifinfo;
673 i++;
674 }
675 }
676
677 closedir(d);
678
679 info->num_interfaces = n;
680 return WIFI_SUCCESS;
681 }
682
683 wifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle **interfaces)
684 {
685 hal_info *info = (hal_info *)handle;
686
687 *interfaces = (wifi_interface_handle *)info->interfaces;
688 *num = info->num_interfaces;
689
690 return WIFI_SUCCESS;
691 }
692
693 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size)
694 {
695 interface_info *info = (interface_info *)handle;
696 strcpy(name, info->name);
697 return WIFI_SUCCESS;
698 }
699
700 wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *set)
701 {
702 return WIFI_ERROR_NOT_SUPPORTED;
703 }
704
705 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_size_max,
706 feature_set set[], int *set_size)
707 {
708 return WIFI_ERROR_NOT_SUPPORTED;
709 }
710
711 wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui)
712 {
713 SetPnoMacAddrOuiCommand command(handle, scan_oui);
714 return (wifi_error)command.start();
715
716 }
717
718 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
719 {
720 SetNodfsCommand command(handle, nodfs);
721 return (wifi_error) command.requestResponse();
722 }
723
724 /////////////////////////////////////////////////////////////////////////////