• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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