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