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