blob: a99b1566b73c970b1291ba489f17ee2a0ad649cd [file] [log] [blame]
Vinit Deshapnde1a526432014-04-08 15:36:03 -07001
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>
Vinit Deshpande642bfbe2014-05-22 15:46:29 -070017#include <netlink/attr.h>
18#include <netlink/handlers.h>
19#include <netlink/msg.h>
Vinit Deshapnde1a526432014-04-08 15:36:03 -070020
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
Ashwin9a233882014-06-25 16:33:35 -070045#define FEATURE_SET 0
46#define FEATURE_SET_MATRIX 1
Dmitry Shmidtb4ac10a2014-08-25 10:35:35 -070047#define ATTR_NODFS_VALUE 3
Ashwin9a233882014-06-25 16:33:35 -070048
Vinit Deshapnde1a526432014-04-08 15:36:03 -070049static void internal_event_handler(wifi_handle handle, int events);
Vinit Deshpande642bfbe2014-05-22 15:46:29 -070050static int internal_no_seq_check(nl_msg *msg, void *arg);
Vinit Deshapnde1a526432014-04-08 15:36:03 -070051static int internal_valid_message_handler(nl_msg *msg, void *arg);
52static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group);
53static int wifi_add_membership(wifi_handle handle, const char *group);
54static wifi_error wifi_init_interfaces(wifi_handle handle);
55
Ashwinf0d50702014-08-04 16:52:29 -070056typedef enum wifi_attr {
Ashwin9a233882014-06-25 16:33:35 -070057 ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET,
Ashwinf0d50702014-08-04 16:52:29 -070058 ANDR_WIFI_ATTRIBUTE_FEATURE_SET,
59 ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI
60} wifi_attr_t;
Ashwin9a233882014-06-25 16:33:35 -070061
Vinit Deshapnde1a526432014-04-08 15:36:03 -070062/* Initialize/Cleanup */
63
64void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
65{
Vinit Deshpande642bfbe2014-05-22 15:46:29 -070066 uint32_t pid = getpid() & 0x3FFFFF;
67 nl_socket_set_local_port(sock, pid + (port << 22));
Vinit Deshapnde1a526432014-04-08 15:36:03 -070068}
69
70static 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
Vinit Deshapnde1a526432014-04-08 15:36:03 -070081 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
103wifi_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");
Ashwin9a233882014-06-25 16:33:35 -0700111 return WIFI_ERROR_UNKNOWN;
Vinit Deshapnde1a526432014-04-08 15:36:03 -0700112 }
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);
Vinit Deshpande642bfbe2014-05-22 15:46:29 -0700137 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, info);
Vinit Deshapnde1a526432014-04-08 15:36:03 -0700138 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);
Ashwin9a233882014-06-25 16:33:35 -0700160 return WIFI_ERROR_UNKNOWN;
Vinit Deshapnde1a526432014-04-08 15:36:03 -0700161 }
162
Vinit Deshpandebb8a4d52014-06-02 09:44:35 -0700163 pthread_mutex_init(&info->cb_lock, NULL);
164
Vinit Deshapnde1a526432014-04-08 15:36:03 -0700165 *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
Vinit Deshpandebb8a4d52014-06-02 09:44:35 -0700175
Vinit Deshapnde1a526432014-04-08 15:36:03 -0700176 ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d", NL80211_CMD_VENDOR);
177 return WIFI_SUCCESS;
178}
179
180static 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
199static 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);
Vinit Deshpandebb8a4d52014-06-02 09:44:35 -0700212 pthread_mutex_destroy(&info->cb_lock);
Vinit Deshapnde1a526432014-04-08 15:36:03 -0700213 free(info);
214
215 ALOGI("Internal cleanup completed");
216}
217
218void 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
227static 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);
Vinit Deshpande642bfbe2014-05-22 15:46:29 -0700232 // ALOGD("nl_recvmsgs returned %d", res);
Vinit Deshapnde1a526432014-04-08 15:36:03 -0700233 nl_cb_put(cb);
234 return res;
235}
236
Vinit Deshapnde1a526432014-04-08 15:36:03 -0700237/* Run event handler */
238void 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;
Vinit Deshpande642bfbe2014-05-22 15:46:29 -0700258 // ALOGI("Polling socket");
Vinit Deshapnde1a526432014-04-08 15:36:03 -0700259 int result = poll(&pfd, 1, -1);
260 if (result < 0) {
261 ALOGE("Error polling socket");
Vinit Deshpandecc370432014-08-27 15:18:46 -0700262 } 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);
Vinit Deshapnde1a526432014-04-08 15:36:03 -0700275 }
276 } while (!info->clean_up);
277
278
279 ALOGI("Cleaning up");
280 internal_cleaned_up_handler(handle);
281}
282
283///////////////////////////////////////////////////////////////////////////////////////
284
Vinit Deshpande642bfbe2014-05-22 15:46:29 -0700285static int internal_no_seq_check(struct nl_msg *msg, void *arg)
286{
287 return NL_OK;
288}
289
Vinit Deshapnde1a526432014-04-08 15:36:03 -0700290static 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 {
Vinit Deshapnde922bc142014-05-13 15:38:05 -0700312 // ALOGI("event received %s", event.get_cmdString());
Vinit Deshapnde1a526432014-04-08 15:36:03 -0700313 }
314
Vinit Deshapnde922bc142014-05-13 15:38:05 -0700315 // ALOGI("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id);
Vinit Deshapnde1a526432014-04-08 15:36:03 -0700316 // event.log();
317
318 bool dispatched = false;
Vinit Deshpandebb8a4d52014-06-02 09:44:35 -0700319
320 pthread_mutex_lock(&info->cb_lock);
321
Vinit Deshapnde1a526432014-04-08 15:36:03 -0700322 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]);
Vinit Deshpande28237f92014-07-31 11:05:14 -0700333 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 }
Vinit Deshapnde1a526432014-04-08 15:36:03 -0700339
Vinit Deshpande28237f92014-07-31 11:05:14 -0700340 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 }
Vinit Deshapnde1a526432014-04-08 15:36:03 -0700349 }
350
Vinit Deshpandebb8a4d52014-06-02 09:44:35 -0700351 pthread_mutex_unlock(&info->cb_lock);
Vinit Deshapnde1a526432014-04-08 15:36:03 -0700352 return NL_OK;
353}
354
355///////////////////////////////////////////////////////////////////////////////////////
356
357class GetMulticastIdCommand : public WifiCommand
358{
359private:
360 const char *mName;
361 const char *mGroup;
362 int mId;
363public:
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
372 int getId() {
373 return mId;
374 }
375
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
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
Ashwinf0d50702014-08-04 16:52:29 -0700430class SetPnoMacAddrOuiCommand : public WifiCommand {
431
432private:
433 byte *mOui;
434 feature_set *fset;
435 feature_set *feature_matrix;
436 int *fm_size;
437 int set_size_max;
438public:
439 SetPnoMacAddrOuiCommand(wifi_interface_handle handle, oui scan_oui)
440 : WifiCommand(handle, 0)
441 {
442 mOui = scan_oui;
443 }
444
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
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 }
478protected:
479 virtual int handleResponse(WifiEvent& reply) {
480 ALOGD("Request complete!");
481 /* Nothing to do on response! */
482 return NL_SKIP;
483 }
Ashwinf0d50702014-08-04 16:52:29 -0700484};
485
Dmitry Shmidtb4ac10a2014-08-25 10:35:35 -0700486class SetNodfsCommand : public WifiCommand {
Ashwinf0d50702014-08-04 16:52:29 -0700487
Dmitry Shmidtb4ac10a2014-08-25 10:35:35 -0700488private:
489 u32 mNoDfs;
490public:
491 SetNodfsCommand(wifi_interface_handle handle, u32 nodfs)
492 : WifiCommand(handle, 0) {
493 mNoDfs = nodfs;
494 }
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};
Ashwinf0d50702014-08-04 16:52:29 -0700514
Ashwin9a233882014-06-25 16:33:35 -0700515class GetFeatureSetCommand : public WifiCommand {
516
517private:
518 int feature_type;
519 feature_set *fset;
520 feature_set *feature_matrix;
521 int *fm_size;
522 int set_size_max;
523public:
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
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);
Dmitry Shmidtb4ac10a2014-08-25 10:35:35 -0700540 } else if (feature_type == FEATURE_SET_MATRIX) {
Ashwin9a233882014-06-25 16:33:35 -0700541 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
554protected:
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
Vinit Deshapnde1a526432014-04-08 15:36:03 -0700614static 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
626static 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
636static 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
644wifi_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
693wifi_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
703wifi_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
Ashwin9a233882014-06-25 16:33:35 -0700710wifi_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
716wifi_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
Ashwinf0d50702014-08-04 16:52:29 -0700723wifi_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
Dmitry Shmidtb4ac10a2014-08-25 10:35:35 -0700730wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
731{
732 SetNodfsCommand command(handle, nodfs);
733 return (wifi_error) command.requestResponse();
734}
Vinit Deshapnde1a526432014-04-08 15:36:03 -0700735
Dmitry Shmidtb4ac10a2014-08-25 10:35:35 -0700736/////////////////////////////////////////////////////////////////////////////