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