1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Portions copyright (C) 2017 Broadcom Limited
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include <stdint.h>
20 #include <fcntl.h>
21 #include <sys/socket.h>
22 #include <netlink/genl/genl.h>
23 #include <netlink/genl/family.h>
24 #include <netlink/genl/ctrl.h>
25 #include <linux/rtnetlink.h>
26 #include <netpacket/packet.h>
27 #include <linux/filter.h>
28 #include <linux/errqueue.h>
29 #include <errno.h>
30
31 #include <linux/pkt_sched.h>
32 #include <netlink/object-api.h>
33 #include <netlink/netlink.h>
34 #include <netlink/socket.h>
35 #include <netlink/attr.h>
36 #include <netlink/handlers.h>
37 #include <netlink/msg.h>
38
39 #include <dirent.h>
40 #include <net/if.h>
41
42 #include "sync.h"
43
44 #define LOG_TAG "WifiHAL"
45
46 #include <log/log.h>
47
48 #include "wifi_hal.h"
49 #include "common.h"
50 #include "cpp_bindings.h"
51 #include "rtt.h"
52 /*
53 BUGBUG: normally, libnl allocates ports for all connections it makes; but
54 being a static library, it doesn't really know how many other netlink connections
55 are made by the same process, if connections come from different shared libraries.
56 These port assignments exist to solve that problem - temporarily. We need to fix
57 libnl to try and allocate ports across the entire process.
58 */
59
60 #define WIFI_HAL_CMD_SOCK_PORT 644
61 #define WIFI_HAL_EVENT_SOCK_PORT 645
62
63 /*
64 * Defines for wifi_wait_for_driver_ready()
65 * Specify durations between polls and max wait time
66 */
67 #define POLL_DRIVER_DURATION_US (100000)
68 #define POLL_DRIVER_MAX_TIME_MS (10000)
69
70 static void internal_event_handler(wifi_handle handle, int events);
71 static int internal_no_seq_check(nl_msg *msg, void *arg);
72 static int internal_valid_message_handler(nl_msg *msg, void *arg);
73 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group);
74 static int wifi_add_membership(wifi_handle handle, const char *group);
75 static wifi_error wifi_init_interfaces(wifi_handle handle);
76 static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
77 iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh);
78 static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface);
79 static wifi_error wifi_set_packet_filter(wifi_interface_handle handle,
80 const u8 *program, u32 len);
81 static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
82 u32 *version, u32 *max_len);
83 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface, u8 enable);
84
85 typedef enum wifi_attr {
86 ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET,
87 ANDR_WIFI_ATTRIBUTE_FEATURE_SET,
88 ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI,
89 ANDR_WIFI_ATTRIBUTE_NODFS_SET,
90 ANDR_WIFI_ATTRIBUTE_COUNTRY,
91 ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE
92 // Add more attribute here
93 } wifi_attr_t;
94
95 enum wifi_rssi_monitor_attr {
96 RSSI_MONITOR_ATTRIBUTE_MAX_RSSI,
97 RSSI_MONITOR_ATTRIBUTE_MIN_RSSI,
98 RSSI_MONITOR_ATTRIBUTE_START,
99 };
100
101 enum wifi_apf_attr {
102 APF_ATTRIBUTE_VERSION,
103 APF_ATTRIBUTE_MAX_LEN,
104 APF_ATTRIBUTE_PROGRAM,
105 APF_ATTRIBUTE_PROGRAM_LEN
106 };
107
108 enum apf_request_type {
109 GET_APF_CAPABILITIES,
110 SET_APF_PROGRAM
111 };
112
113 /* Initialize/Cleanup */
114
wifi_socket_set_local_port(struct nl_sock * sock,uint32_t port)115 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
116 {
117 uint32_t pid = getpid() & 0x3FFFFF;
118 nl_socket_set_local_port(sock, pid + (port << 22));
119 }
120
wifi_create_nl_socket(int port)121 static nl_sock * wifi_create_nl_socket(int port)
122 {
123 // ALOGI("Creating socket");
124 struct nl_sock *sock = nl_socket_alloc();
125 if (sock == NULL) {
126 ALOGE("Could not create handle");
127 return NULL;
128 }
129
130 wifi_socket_set_local_port(sock, port);
131
132 struct sockaddr *addr = NULL;
133 // ALOGI("sizeof(sockaddr) = %d, sizeof(sockaddr_nl) = %d", sizeof(*addr), sizeof(*addr_nl));
134
135 // ALOGI("Connecting socket");
136 if (nl_connect(sock, NETLINK_GENERIC)) {
137 ALOGE("Could not connect handle");
138 nl_socket_free(sock);
139 return NULL;
140 }
141
142 // ALOGI("Making socket nonblocking");
143 /*
144 if (nl_socket_set_nonblocking(sock)) {
145 ALOGE("Could make socket non-blocking");
146 nl_socket_free(sock);
147 return NULL;
148 }
149 */
150
151 return sock;
152 }
153
154 /*initialize function pointer table with Broadcom HHAL API*/
init_wifi_vendor_hal_func_table(wifi_hal_fn * fn)155 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn)
156 {
157 if (fn == NULL) {
158 return WIFI_ERROR_UNKNOWN;
159 }
160 fn->wifi_initialize = wifi_initialize;
161 fn->wifi_wait_for_driver_ready = wifi_wait_for_driver_ready;
162 fn->wifi_cleanup = wifi_cleanup;
163 fn->wifi_event_loop = wifi_event_loop;
164 fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
165 fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
166 fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui;
167 fn->wifi_get_ifaces = wifi_get_ifaces;
168 fn->wifi_get_iface_name = wifi_get_iface_name;
169 fn->wifi_start_gscan = wifi_start_gscan;
170 fn->wifi_stop_gscan = wifi_stop_gscan;
171 fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
172 fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
173 fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
174 fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
175 fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
176 fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
177 fn->wifi_get_link_stats = wifi_get_link_stats;
178 fn->wifi_set_link_stats = wifi_set_link_stats;
179 fn->wifi_clear_link_stats = wifi_clear_link_stats;
180 fn->wifi_get_valid_channels = wifi_get_valid_channels;
181 fn->wifi_rtt_range_request = wifi_rtt_range_request;
182 fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
183 fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
184 fn->wifi_rtt_get_responder_info = wifi_rtt_get_responder_info;
185 fn->wifi_enable_responder = wifi_enable_responder;
186 fn->wifi_disable_responder = wifi_disable_responder;
187 fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
188 fn->wifi_start_logging = wifi_start_logging;
189 fn->wifi_set_epno_list = wifi_set_epno_list;
190 fn->wifi_reset_epno_list = wifi_reset_epno_list;
191 fn->wifi_set_country_code = wifi_set_country_code;
192 fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
193 fn->wifi_set_log_handler = wifi_set_log_handler;
194 fn->wifi_reset_log_handler = wifi_reset_log_handler;
195 fn->wifi_set_alert_handler = wifi_set_alert_handler;
196 fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
197 fn->wifi_get_firmware_version = wifi_get_firmware_version;
198 fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
199 fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;
200 fn->wifi_get_ring_data = wifi_get_ring_data;
201 fn->wifi_get_driver_version = wifi_get_driver_version;
202 fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
203 fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
204 fn->wifi_configure_nd_offload = wifi_configure_nd_offload;
205 fn->wifi_start_sending_offloaded_packet = wifi_start_sending_offloaded_packet;
206 fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
207 fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring;
208 fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;
209 fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;
210 fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
211 fn->wifi_set_packet_filter = wifi_set_packet_filter;
212 return WIFI_SUCCESS;
213 }
214
wifi_initialize(wifi_handle * handle)215 wifi_error wifi_initialize(wifi_handle *handle)
216 {
217 srand(getpid());
218
219 ALOGI("Initializing wifi");
220 hal_info *info = (hal_info *)malloc(sizeof(hal_info));
221 if (info == NULL) {
222 ALOGE("Could not allocate hal_info");
223 return WIFI_ERROR_UNKNOWN;
224 }
225
226 memset(info, 0, sizeof(*info));
227
228 ALOGI("Creating socket");
229 if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->cleanup_socks) == -1) {
230 ALOGE("Could not create cleanup sockets");
231 free(info);
232 return WIFI_ERROR_UNKNOWN;
233 }
234
235 struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT);
236 if (cmd_sock == NULL) {
237 ALOGE("Could not create handle");
238 free(info);
239 return WIFI_ERROR_UNKNOWN;
240 }
241
242 struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT);
243 if (event_sock == NULL) {
244 ALOGE("Could not create handle");
245 nl_socket_free(cmd_sock);
246 free(info);
247 return WIFI_ERROR_UNKNOWN;
248 }
249
250 struct nl_cb *cb = nl_socket_get_cb(event_sock);
251 if (cb == NULL) {
252 ALOGE("Could not create handle");
253 nl_socket_free(cmd_sock);
254 nl_socket_free(event_sock);
255 free(info);
256 return WIFI_ERROR_UNKNOWN;
257 }
258
259 // ALOGI("cb->refcnt = %d", cb->cb_refcnt);
260 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, info);
261 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info);
262 nl_cb_put(cb);
263
264 info->cmd_sock = cmd_sock;
265 info->event_sock = event_sock;
266 info->clean_up = false;
267 info->in_event_loop = false;
268
269 info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
270 info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
271 info->num_event_cb = 0;
272
273 info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
274 info->alloc_cmd = DEFAULT_CMD_SIZE;
275 info->num_cmd = 0;
276
277 info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
278 if (info->nl80211_family_id < 0) {
279 ALOGE("Could not resolve nl80211 familty id");
280 nl_socket_free(cmd_sock);
281 nl_socket_free(event_sock);
282 free(info);
283 return WIFI_ERROR_UNKNOWN;
284 }
285
286 pthread_mutex_init(&info->cb_lock, NULL);
287
288 *handle = (wifi_handle) info;
289
290 if (wifi_init_interfaces(*handle) != WIFI_SUCCESS) {
291 ALOGE("No wifi interface found");
292 nl_socket_free(cmd_sock);
293 nl_socket_free(event_sock);
294 pthread_mutex_destroy(&info->cb_lock);
295 free(info);
296 return WIFI_ERROR_NOT_AVAILABLE;
297 }
298
299 if ((wifi_add_membership(*handle, "scan") < 0) ||
300 (wifi_add_membership(*handle, "mlme") < 0) ||
301 (wifi_add_membership(*handle, "regulatory") < 0) ||
302 (wifi_add_membership(*handle, "vendor") < 0)) {
303 ALOGE("Add membership failed");
304 nl_socket_free(cmd_sock);
305 nl_socket_free(event_sock);
306 pthread_mutex_destroy(&info->cb_lock);
307 free(info);
308 return WIFI_ERROR_NOT_AVAILABLE;
309 }
310
311 // ALOGI("Found %d interfaces", info->num_interfaces);
312
313 ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d", NL80211_CMD_VENDOR);
314 return WIFI_SUCCESS;
315 }
316
wifi_wait_for_driver_ready(void)317 wifi_error wifi_wait_for_driver_ready(void)
318 {
319 // This function will wait to make sure basic client netdev is created
320 // Function times out after 10 seconds
321 int count = (POLL_DRIVER_MAX_TIME_MS * 1000) / POLL_DRIVER_DURATION_US;
322 FILE *fd;
323
324 do {
325 if ((fd = fopen("/sys/class/net/wlan0", "r")) != NULL) {
326 fclose(fd);
327 return WIFI_SUCCESS;
328 }
329 usleep(POLL_DRIVER_DURATION_US);
330 } while(--count > 0);
331
332 ALOGE("Timed out waiting on Driver ready ... ");
333 return WIFI_ERROR_TIMED_OUT;
334 }
335
wifi_add_membership(wifi_handle handle,const char * group)336 static int wifi_add_membership(wifi_handle handle, const char *group)
337 {
338 hal_info *info = getHalInfo(handle);
339
340 int id = wifi_get_multicast_id(handle, "nl80211", group);
341 if (id < 0) {
342 ALOGE("Could not find group %s", group);
343 return id;
344 }
345
346 int ret = nl_socket_add_membership(info->event_sock, id);
347 if (ret < 0) {
348 ALOGE("Could not add membership to group %s", group);
349 }
350
351 // ALOGI("Successfully added membership for group %s", group);
352 return ret;
353 }
354
internal_cleaned_up_handler(wifi_handle handle)355 static void internal_cleaned_up_handler(wifi_handle handle)
356 {
357 hal_info *info = getHalInfo(handle);
358 wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
359
360 if (info->cmd_sock != 0) {
361 close(info->cleanup_socks[0]);
362 close(info->cleanup_socks[1]);
363 nl_socket_free(info->cmd_sock);
364 nl_socket_free(info->event_sock);
365 info->cmd_sock = NULL;
366 info->event_sock = NULL;
367 }
368
369 (*cleaned_up_handler)(handle);
370 pthread_mutex_destroy(&info->cb_lock);
371 free(info);
372
373 ALOGI("Internal cleanup completed");
374 }
375
wifi_cleanup(wifi_handle handle,wifi_cleaned_up_handler handler)376 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
377 {
378 hal_info *info = getHalInfo(handle);
379 char buf[64];
380
381 info->cleaned_up_handler = handler;
382 if (TEMP_FAILURE_RETRY(write(info->cleanup_socks[0], "Exit", 4)) < 1) {
383 // As a fallback set the cleanup flag to TRUE
384 ALOGE("could not write to the cleanup socket");
385 } else {
386 // Listen to the response
387 // Hopefully we dont get errors or get hung up
388 // Not much can be done in that case, but assume that
389 // it has rx'ed the Exit message to exit the thread.
390 // As a fallback set the cleanup flag to TRUE
391 memset(buf, 0, sizeof(buf));
392 ssize_t result = TEMP_FAILURE_RETRY(read(info->cleanup_socks[0], buf, sizeof(buf)));
393 ALOGE("%s: Read after POLL returned %zd, error no = %d (%s)", __FUNCTION__,
394 result, errno, strerror(errno));
395 if (strncmp(buf, "Done", 4) == 0) {
396 ALOGE("Event processing terminated");
397 } else {
398 ALOGD("Rx'ed %s", buf);
399 }
400 }
401 info->clean_up = true;
402 pthread_mutex_lock(&info->cb_lock);
403
404 int bad_commands = 0;
405
406 for (int i = 0; i < info->num_event_cb; i++) {
407 cb_info *cbi = &(info->event_cb[i]);
408 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
409 ALOGI("Command left in event_cb %p:%s", cmd, (cmd ? cmd->getType(): ""));
410 }
411
412 while (info->num_cmd > bad_commands) {
413 int num_cmd = info->num_cmd;
414 cmd_info *cmdi = &(info->cmd[bad_commands]);
415 WifiCommand *cmd = cmdi->cmd;
416 if (cmd != NULL) {
417 ALOGI("Cancelling command %p:%s", cmd, cmd->getType());
418 pthread_mutex_unlock(&info->cb_lock);
419 cmd->cancel();
420 pthread_mutex_lock(&info->cb_lock);
421 if (num_cmd == info->num_cmd) {
422 ALOGI("Cancelling command %p:%s did not work", cmd, (cmd ? cmd->getType(): ""));
423 bad_commands++;
424 }
425 /* release reference added when command is saved */
426 cmd->releaseRef();
427 }
428 }
429
430 for (int i = 0; i < info->num_event_cb; i++) {
431 cb_info *cbi = &(info->event_cb[i]);
432 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
433 ALOGE("Leaked command %p", cmd);
434 }
435 pthread_mutex_unlock(&info->cb_lock);
436 internal_cleaned_up_handler(handle);
437 }
438
internal_pollin_handler(wifi_handle handle)439 static int internal_pollin_handler(wifi_handle handle)
440 {
441 hal_info *info = getHalInfo(handle);
442 struct nl_cb *cb = nl_socket_get_cb(info->event_sock);
443 int res = nl_recvmsgs(info->event_sock, cb);
444 // ALOGD("nl_recvmsgs returned %d", res);
445 nl_cb_put(cb);
446 return res;
447 }
448
449 /* Run event handler */
wifi_event_loop(wifi_handle handle)450 void wifi_event_loop(wifi_handle handle)
451 {
452 hal_info *info = getHalInfo(handle);
453 if (info->in_event_loop) {
454 return;
455 } else {
456 info->in_event_loop = true;
457 }
458
459 pollfd pfd[2];
460 memset(&pfd[0], 0, sizeof(pollfd) * 2);
461
462 pfd[0].fd = nl_socket_get_fd(info->event_sock);
463 pfd[0].events = POLLIN;
464 pfd[1].fd = info->cleanup_socks[1];
465 pfd[1].events = POLLIN;
466
467 char buf[2048];
468 /* TODO: Add support for timeouts */
469
470 do {
471 int timeout = -1; /* Infinite timeout */
472 pfd[0].revents = 0;
473 pfd[1].revents = 0;
474 // ALOGI("Polling socket");
475 int result = TEMP_FAILURE_RETRY(poll(pfd, 2, timeout));
476 if (result < 0) {
477 // ALOGE("Error polling socket");
478 } else if (pfd[0].revents & POLLERR) {
479 ALOGE("POLL Error; error no = %d (%s)", errno, strerror(errno));
480 ssize_t result2 = TEMP_FAILURE_RETRY(read(pfd[0].fd, buf, sizeof(buf)));
481 ALOGE("Read after POLL returned %zd, error no = %d (%s)", result2,
482 errno, strerror(errno));
483 } else if (pfd[0].revents & POLLHUP) {
484 ALOGE("Remote side hung up");
485 break;
486 } else if (pfd[0].revents & POLLIN) {
487 // ALOGI("Found some events!!!");
488 internal_pollin_handler(handle);
489 } else if (pfd[1].revents & POLLIN) {
490 memset(buf, 0, sizeof(buf));
491 ssize_t result2 = TEMP_FAILURE_RETRY(read(pfd[1].fd, buf, sizeof(buf)));
492 ALOGE("%s: Read after POLL returned %zd, error no = %d (%s)", __FUNCTION__,
493 result2, errno, strerror(errno));
494 if (strncmp(buf, "Exit", 4) == 0) {
495 ALOGD("Got a signal to exit!!!");
496 if (TEMP_FAILURE_RETRY(write(pfd[1].fd, "Done", 4)) < 1) {
497 ALOGE("could not write to the cleanup socket");
498 }
499 break;
500 } else {
501 ALOGD("Rx'ed %s on the cleanup socket\n", buf);
502 }
503 } else {
504 ALOGE("Unknown event - %0x, %0x", pfd[0].revents, pfd[1].revents);
505 }
506 } while (!info->clean_up);
507 ALOGI("Exit %s", __FUNCTION__);
508 }
509
510 ///////////////////////////////////////////////////////////////////////////////////////
511
internal_no_seq_check(struct nl_msg * msg,void * arg)512 static int internal_no_seq_check(struct nl_msg *msg, void *arg)
513 {
514 return NL_OK;
515 }
516
internal_valid_message_handler(nl_msg * msg,void * arg)517 static int internal_valid_message_handler(nl_msg *msg, void *arg)
518 {
519 // ALOGI("got an event");
520
521 wifi_handle handle = (wifi_handle)arg;
522 hal_info *info = getHalInfo(handle);
523
524 WifiEvent event(msg);
525 int res = event.parse();
526 if (res < 0) {
527 ALOGE("Failed to parse event: %d", res);
528 return NL_SKIP;
529 }
530
531 int cmd = event.get_cmd();
532 uint32_t vendor_id = 0;
533 int subcmd = 0;
534
535 if (cmd == NL80211_CMD_VENDOR) {
536 vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
537 subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
538 ALOGV("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
539 event.get_cmdString(), vendor_id, subcmd);
540 } else {
541 // ALOGV("event received %s", event.get_cmdString());
542 }
543
544 // ALOGV("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id);
545 // event.log();
546
547 bool dispatched = false;
548
549 pthread_mutex_lock(&info->cb_lock);
550
551 for (int i = 0; i < info->num_event_cb; i++) {
552 if (cmd == info->event_cb[i].nl_cmd) {
553 if (cmd == NL80211_CMD_VENDOR
554 && ((vendor_id != info->event_cb[i].vendor_id)
555 || (subcmd != info->event_cb[i].vendor_subcmd)))
556 {
557 /* event for a different vendor, ignore it */
558 continue;
559 }
560
561 cb_info *cbi = &(info->event_cb[i]);
562 nl_recvmsg_msg_cb_t cb_func = cbi->cb_func;
563 void *cb_arg = cbi->cb_arg;
564 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
565 if (cmd != NULL) {
566 cmd->addRef();
567 }
568 pthread_mutex_unlock(&info->cb_lock);
569 if (cb_func)
570 (*cb_func)(msg, cb_arg);
571 if (cmd != NULL) {
572 cmd->releaseRef();
573 }
574
575 return NL_OK;
576 }
577 }
578
579 pthread_mutex_unlock(&info->cb_lock);
580 return NL_OK;
581 }
582
583 ///////////////////////////////////////////////////////////////////////////////////////
584
585 class GetMulticastIdCommand : public WifiCommand
586 {
587 private:
588 const char *mName;
589 const char *mGroup;
590 int mId;
591 public:
GetMulticastIdCommand(wifi_handle handle,const char * name,const char * group)592 GetMulticastIdCommand(wifi_handle handle, const char *name, const char *group)
593 : WifiCommand("GetMulticastIdCommand", handle, 0)
594 {
595 mName = name;
596 mGroup = group;
597 mId = -1;
598 }
599
getId()600 int getId() {
601 return mId;
602 }
603
create()604 virtual int create() {
605 int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
606 // ALOGI("ctrl family = %d", nlctrlFamily);
607 int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
608 if (ret < 0) {
609 return ret;
610 }
611 ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
612 return ret;
613 }
614
handleResponse(WifiEvent & reply)615 virtual int handleResponse(WifiEvent& reply) {
616
617 // ALOGI("handling reponse in %s", __func__);
618
619 struct nlattr **tb = reply.attributes();
620 struct genlmsghdr *gnlh = reply.header();
621 struct nlattr *mcgrp = NULL;
622 int i;
623
624 if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
625 ALOGI("No multicast groups found");
626 return NL_SKIP;
627 } else {
628 // ALOGI("Multicast groups attr size = %d", nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
629 }
630
631 for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
632
633 // ALOGI("Processing group");
634 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
635 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
636 nla_len(mcgrp), NULL);
637 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID]) {
638 continue;
639 }
640
641 char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
642 int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
643
644 // ALOGI("Found group name %s", grpName);
645
646 if (strncmp(grpName, mGroup, grpNameLen) != 0)
647 continue;
648
649 mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
650 break;
651 }
652
653 return NL_SKIP;
654 }
655
656 };
657
658 class SetPnoMacAddrOuiCommand : public WifiCommand {
659
660 private:
661 byte *mOui;
662 feature_set *fset;
663 feature_set *feature_matrix;
664 int *fm_size;
665 int set_size_max;
666 public:
SetPnoMacAddrOuiCommand(wifi_interface_handle handle,oui scan_oui)667 SetPnoMacAddrOuiCommand(wifi_interface_handle handle, oui scan_oui)
668 : WifiCommand("SetPnoMacAddrOuiCommand", handle, 0)
669 {
670 mOui = scan_oui;
671 }
672
createRequest(WifiRequest & request,int subcmd,byte * scan_oui)673 int createRequest(WifiRequest& request, int subcmd, byte *scan_oui) {
674 int result = request.create(GOOGLE_OUI, subcmd);
675 if (result < 0) {
676 return result;
677 }
678
679 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
680 result = request.put(ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, scan_oui, DOT11_OUI_LEN);
681 if (result < 0) {
682 return result;
683 }
684
685 request.attr_end(data);
686 return WIFI_SUCCESS;
687
688 }
689
start()690 int start() {
691 ALOGD("Sending mac address OUI");
692 WifiRequest request(familyId(), ifaceId());
693 int result = createRequest(request, WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, mOui);
694 if (result != WIFI_SUCCESS) {
695 ALOGE("failed to create request; result = %d", result);
696 return result;
697 }
698
699 result = requestResponse(request);
700 if (result != WIFI_SUCCESS) {
701 ALOGE("failed to set scanning mac OUI; result = %d", result);
702 }
703
704 return result;
705 }
706 protected:
handleResponse(WifiEvent & reply)707 virtual int handleResponse(WifiEvent& reply) {
708 ALOGD("Request complete!");
709 /* Nothing to do on response! */
710 return NL_SKIP;
711 }
712 };
713
714 class SetNodfsCommand : public WifiCommand {
715
716 private:
717 u32 mNoDfs;
718 public:
SetNodfsCommand(wifi_interface_handle handle,u32 nodfs)719 SetNodfsCommand(wifi_interface_handle handle, u32 nodfs)
720 : WifiCommand("SetNodfsCommand", handle, 0) {
721 mNoDfs = nodfs;
722 }
create()723 virtual int create() {
724 int ret;
725
726 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_NODFS_SET);
727 if (ret < 0) {
728 ALOGE("Can't create message to send to driver - %d", ret);
729 return ret;
730 }
731
732 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
733 ret = mMsg.put_u32(ANDR_WIFI_ATTRIBUTE_NODFS_SET, mNoDfs);
734 if (ret < 0) {
735 return ret;
736 }
737
738 mMsg.attr_end(data);
739 return WIFI_SUCCESS;
740 }
741 };
742
743 class SetCountryCodeCommand : public WifiCommand {
744 private:
745 const char *mCountryCode;
746 public:
SetCountryCodeCommand(wifi_interface_handle handle,const char * country_code)747 SetCountryCodeCommand(wifi_interface_handle handle, const char *country_code)
748 : WifiCommand("SetCountryCodeCommand", handle, 0) {
749 mCountryCode = country_code;
750 }
create()751 virtual int create() {
752 int ret;
753
754 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_SET_COUNTRY_CODE);
755 if (ret < 0) {
756 ALOGE("Can't create message to send to driver - %d", ret);
757 return ret;
758 }
759
760 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
761 ret = mMsg.put_string(ANDR_WIFI_ATTRIBUTE_COUNTRY, mCountryCode);
762 if (ret < 0) {
763 return ret;
764 }
765
766 mMsg.attr_end(data);
767 return WIFI_SUCCESS;
768
769 }
770 };
771
772 class SetRSSIMonitorCommand : public WifiCommand {
773 private:
774 s8 mMax_rssi;
775 s8 mMin_rssi;
776 wifi_rssi_event_handler mHandler;
777 public:
SetRSSIMonitorCommand(wifi_request_id id,wifi_interface_handle handle,s8 max_rssi,s8 min_rssi,wifi_rssi_event_handler eh)778 SetRSSIMonitorCommand(wifi_request_id id, wifi_interface_handle handle,
779 s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
780 : WifiCommand("SetRSSIMonitorCommand", handle, id), mMax_rssi(max_rssi), mMin_rssi
781 (min_rssi), mHandler(eh)
782 {
783 }
createRequest(WifiRequest & request,int enable)784 int createRequest(WifiRequest& request, int enable) {
785 int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_SET_RSSI_MONITOR);
786 if (result < 0) {
787 return result;
788 }
789
790 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
791 result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_MAX_RSSI, (enable ? mMax_rssi: 0));
792 if (result < 0) {
793 return result;
794 }
795 ALOGD("create request");
796 result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_MIN_RSSI, (enable? mMin_rssi: 0));
797 if (result < 0) {
798 return result;
799 }
800 result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_START, enable);
801 if (result < 0) {
802 return result;
803 }
804 request.attr_end(data);
805 return result;
806 }
807
start()808 int start() {
809 WifiRequest request(familyId(), ifaceId());
810 int result = createRequest(request, 1);
811 if (result < 0) {
812 return result;
813 }
814 result = requestResponse(request);
815 if (result < 0) {
816 ALOGI("Failed to set RSSI Monitor, result = %d", result);
817 return result;
818 }
819 ALOGI("Successfully set RSSI monitoring");
820 registerVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
821
822
823 if (result < 0) {
824 unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
825 return result;
826 }
827 ALOGI("Done!");
828 return result;
829 }
830
cancel()831 virtual int cancel() {
832
833 WifiRequest request(familyId(), ifaceId());
834 int result = createRequest(request, 0);
835 if (result != WIFI_SUCCESS) {
836 ALOGE("failed to create request; result = %d", result);
837 } else {
838 result = requestResponse(request);
839 if (result != WIFI_SUCCESS) {
840 ALOGE("failed to stop RSSI monitoring = %d", result);
841 }
842 }
843 unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
844 return WIFI_SUCCESS;
845 }
846
handleResponse(WifiEvent & reply)847 virtual int handleResponse(WifiEvent& reply) {
848 /* Nothing to do on response! */
849 return NL_SKIP;
850 }
851
handleEvent(WifiEvent & event)852 virtual int handleEvent(WifiEvent& event) {
853 ALOGI("Got a RSSI monitor event");
854
855 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
856 int len = event.get_vendor_data_len();
857
858 if (vendor_data == NULL || len == 0) {
859 ALOGI("RSSI monitor: No data");
860 return NL_SKIP;
861 }
862 /* driver<->HAL event structure */
863 #define RSSI_MONITOR_EVT_VERSION 1
864 typedef struct {
865 u8 version;
866 s8 cur_rssi;
867 mac_addr BSSID;
868 } rssi_monitor_evt;
869
870 rssi_monitor_evt *data = (rssi_monitor_evt *)event.get_vendor_data();
871
872 if (data->version != RSSI_MONITOR_EVT_VERSION) {
873 ALOGI("Event version mismatch %d, expected %d", data->version, RSSI_MONITOR_EVT_VERSION);
874 return NL_SKIP;
875 }
876
877 if (*mHandler.on_rssi_threshold_breached) {
878 (*mHandler.on_rssi_threshold_breached)(id(), data->BSSID, data->cur_rssi);
879 } else {
880 ALOGW("No RSSI monitor handler registered");
881 }
882
883 return NL_SKIP;
884 }
885
886 };
887
888 class AndroidPktFilterCommand : public WifiCommand {
889 private:
890 const u8* mProgram;
891 u32 mProgramLen;
892 u32* mVersion;
893 u32* mMaxLen;
894 int mReqType;
895 public:
AndroidPktFilterCommand(wifi_interface_handle handle,u32 * version,u32 * max_len)896 AndroidPktFilterCommand(wifi_interface_handle handle,
897 u32* version, u32* max_len)
898 : WifiCommand("AndroidPktFilterCommand", handle, 0),
899 mVersion(version), mMaxLen(max_len),
900 mReqType(GET_APF_CAPABILITIES)
901 {
902 }
903
AndroidPktFilterCommand(wifi_interface_handle handle,const u8 * program,u32 len)904 AndroidPktFilterCommand(wifi_interface_handle handle,
905 const u8* program, u32 len)
906 : WifiCommand("AndroidPktFilterCommand", handle, 0),
907 mProgram(program), mProgramLen(len),
908 mReqType(SET_APF_PROGRAM)
909 {
910 }
911
createRequest(WifiRequest & request)912 int createRequest(WifiRequest& request) {
913 if (mReqType == SET_APF_PROGRAM) {
914 ALOGI("\n%s: APF set program request\n", __FUNCTION__);
915 return createSetPktFilterRequest(request);
916 } else if (mReqType == GET_APF_CAPABILITIES) {
917 ALOGI("\n%s: APF get capabilities request\n", __FUNCTION__);
918 return createGetPktFilterCapabilitesRequest(request);
919 } else {
920 ALOGE("\n%s Unknown APF request\n", __FUNCTION__);
921 return WIFI_ERROR_NOT_SUPPORTED;
922 }
923 return WIFI_SUCCESS;
924 }
925
createSetPktFilterRequest(WifiRequest & request)926 int createSetPktFilterRequest(WifiRequest& request) {
927 u8 *program = new u8[mProgramLen];
928 NULL_CHECK_RETURN(program, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
929 int result = request.create(GOOGLE_OUI, APF_SUBCMD_SET_FILTER);
930 if (result < 0) {
931 return result;
932 }
933
934 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
935 result = request.put_u32(APF_ATTRIBUTE_PROGRAM_LEN, mProgramLen);
936 if (result < 0) {
937 return result;
938 }
939 memcpy(program, mProgram, mProgramLen);
940 result = request.put(APF_ATTRIBUTE_PROGRAM, program, mProgramLen);
941 if (result < 0) {
942 return result;
943 }
944 request.attr_end(data);
945 delete[] program;
946 return result;
947 }
948
createGetPktFilterCapabilitesRequest(WifiRequest & request)949 int createGetPktFilterCapabilitesRequest(WifiRequest& request) {
950 int result = request.create(GOOGLE_OUI, APF_SUBCMD_GET_CAPABILITIES);
951 if (result < 0) {
952 return result;
953 }
954
955 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
956 request.attr_end(data);
957 return result;
958 }
959
start()960 int start() {
961 WifiRequest request(familyId(), ifaceId());
962 int result = createRequest(request);
963 if (result < 0) {
964 return result;
965 }
966 result = requestResponse(request);
967 if (result < 0) {
968 ALOGI("Request Response failed for APF, result = %d", result);
969 return result;
970 }
971 ALOGI("Done!");
972 return result;
973 }
974
cancel()975 int cancel() {
976 return WIFI_SUCCESS;
977 }
978
handleResponse(WifiEvent & reply)979 int handleResponse(WifiEvent& reply) {
980 ALOGD("In SetAPFCommand::handleResponse");
981
982 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
983 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
984 return NL_SKIP;
985 }
986
987 int id = reply.get_vendor_id();
988 int subcmd = reply.get_vendor_subcmd();
989
990 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
991 int len = reply.get_vendor_data_len();
992
993 ALOGD("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
994 if (vendor_data == NULL || len == 0) {
995 ALOGE("no vendor data in SetAPFCommand response; ignoring it");
996 return NL_SKIP;
997 }
998 if( mReqType == SET_APF_PROGRAM) {
999 ALOGD("Response recieved for set packet filter command\n");
1000 } else if (mReqType == GET_APF_CAPABILITIES) {
1001 *mVersion = 0;
1002 *mMaxLen = 0;
1003 ALOGD("Response recieved for get packet filter capabilities command\n");
1004 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1005 if (it.get_type() == APF_ATTRIBUTE_VERSION) {
1006 *mVersion = it.get_u32();
1007 ALOGI("APF version is %d\n", *mVersion);
1008 } else if (it.get_type() == APF_ATTRIBUTE_MAX_LEN) {
1009 *mMaxLen = it.get_u32();
1010 ALOGI("APF max len is %d\n", *mMaxLen);
1011 } else {
1012 ALOGE("Ignoring invalid attribute type = %d, size = %d",
1013 it.get_type(), it.get_len());
1014 }
1015 }
1016 }
1017 return NL_OK;
1018 }
1019
handleEvent(WifiEvent & event)1020 int handleEvent(WifiEvent& event) {
1021 /* No Event to recieve for APF commands */
1022 return NL_SKIP;
1023 }
1024 };
1025
1026 class SetNdoffloadCommand : public WifiCommand {
1027
1028 private:
1029 u8 mEnable;
1030 public:
SetNdoffloadCommand(wifi_interface_handle handle,u8 enable)1031 SetNdoffloadCommand(wifi_interface_handle handle, u8 enable)
1032 : WifiCommand("SetNdoffloadCommand", handle, 0) {
1033 mEnable = enable;
1034 }
create()1035 virtual int create() {
1036 int ret;
1037
1038 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_CONFIG_ND_OFFLOAD);
1039 if (ret < 0) {
1040 ALOGE("Can't create message to send to driver - %d", ret);
1041 return ret;
1042 }
1043
1044 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
1045 ret = mMsg.put_u8(ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE, mEnable);
1046 if (ret < 0) {
1047 return ret;
1048 }
1049
1050 mMsg.attr_end(data);
1051 return WIFI_SUCCESS;
1052 }
1053 };
1054
1055 class GetFeatureSetCommand : public WifiCommand {
1056
1057 private:
1058 int feature_type;
1059 feature_set *fset;
1060 feature_set *feature_matrix;
1061 int *fm_size;
1062 int set_size_max;
1063 public:
GetFeatureSetCommand(wifi_interface_handle handle,int feature,feature_set * set,feature_set set_matrix[],int * size,int max_size)1064 GetFeatureSetCommand(wifi_interface_handle handle, int feature, feature_set *set,
1065 feature_set set_matrix[], int *size, int max_size)
1066 : WifiCommand("GetFeatureSetCommand", handle, 0)
1067 {
1068 feature_type = feature;
1069 fset = set;
1070 feature_matrix = set_matrix;
1071 fm_size = size;
1072 set_size_max = max_size;
1073 }
1074
create()1075 virtual int create() {
1076 int ret;
1077
1078 if(feature_type == ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET) {
1079 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET);
1080 } else if (feature_type == ANDR_WIFI_ATTRIBUTE_FEATURE_SET) {
1081 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET_MATRIX);
1082 } else {
1083 ALOGE("Unknown feature type %d", feature_type);
1084 return -1;
1085 }
1086
1087 if (ret < 0) {
1088 ALOGE("Can't create message to send to driver - %d", ret);
1089 }
1090
1091 return ret;
1092 }
1093
1094 protected:
handleResponse(WifiEvent & reply)1095 virtual int handleResponse(WifiEvent& reply) {
1096
1097 ALOGV("In GetFeatureSetCommand::handleResponse");
1098
1099 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1100 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
1101 return NL_SKIP;
1102 }
1103
1104 int id = reply.get_vendor_id();
1105 int subcmd = reply.get_vendor_subcmd();
1106
1107 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1108 int len = reply.get_vendor_data_len();
1109
1110 ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
1111 if (vendor_data == NULL || len == 0) {
1112 ALOGE("no vendor data in GetFeatureSetCommand response; ignoring it");
1113 return NL_SKIP;
1114 }
1115 if(feature_type == ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET) {
1116 void *data = reply.get_vendor_data();
1117 if(!fset) {
1118 ALOGE("Buffers pointers not set");
1119 return NL_SKIP;
1120 }
1121 memcpy(fset, data, min(len, (int) sizeof(*fset)));
1122 } else {
1123 int num_features_set = 0;
1124 int i = 0;
1125
1126 if(!feature_matrix || !fm_size) {
1127 ALOGE("Buffers pointers not set");
1128 return NL_SKIP;
1129 }
1130
1131 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1132 if (it.get_type() == ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET) {
1133 num_features_set = it.get_u32();
1134 ALOGV("Got feature list with %d concurrent sets", num_features_set);
1135 if(set_size_max && (num_features_set > set_size_max))
1136 num_features_set = set_size_max;
1137 *fm_size = num_features_set;
1138 } else if ((it.get_type() == ANDR_WIFI_ATTRIBUTE_FEATURE_SET) &&
1139 i < num_features_set) {
1140 feature_matrix[i] = it.get_u32();
1141 i++;
1142 } else {
1143 ALOGW("Ignoring invalid attribute type = %d, size = %d",
1144 it.get_type(), it.get_len());
1145 }
1146 }
1147
1148 }
1149 return NL_OK;
1150 }
1151
1152 };
1153
wifi_get_multicast_id(wifi_handle handle,const char * name,const char * group)1154 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group)
1155 {
1156 GetMulticastIdCommand cmd(handle, name, group);
1157 int res = cmd.requestResponse();
1158 if (res < 0)
1159 return res;
1160 else
1161 return cmd.getId();
1162 }
1163
1164 /////////////////////////////////////////////////////////////////////////
1165
is_wifi_interface(const char * name)1166 static bool is_wifi_interface(const char *name)
1167 {
1168 if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
1169 /* not a wifi interface; ignore it */
1170 return false;
1171 } else {
1172 return true;
1173 }
1174 }
1175
get_interface(const char * name,interface_info * info)1176 static int get_interface(const char *name, interface_info *info)
1177 {
1178 strcpy(info->name, name);
1179 info->id = if_nametoindex(name);
1180 // ALOGI("found an interface : %s, id = %d", name, info->id);
1181 return WIFI_SUCCESS;
1182 }
1183
wifi_init_interfaces(wifi_handle handle)1184 wifi_error wifi_init_interfaces(wifi_handle handle)
1185 {
1186 hal_info *info = (hal_info *)handle;
1187
1188 struct dirent *de;
1189
1190 DIR *d = opendir("/sys/class/net");
1191 if (d == 0)
1192 return WIFI_ERROR_UNKNOWN;
1193
1194 int n = 0;
1195 while ((de = readdir(d))) {
1196 if (de->d_name[0] == '.')
1197 continue;
1198 if (is_wifi_interface(de->d_name) ) {
1199 n++;
1200 }
1201 }
1202
1203 closedir(d);
1204
1205 if (n == 0)
1206 return WIFI_ERROR_NOT_AVAILABLE;
1207
1208 d = opendir("/sys/class/net");
1209 if (d == 0)
1210 return WIFI_ERROR_UNKNOWN;
1211
1212 info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
1213
1214 int i = 0;
1215 while ((de = readdir(d))) {
1216 if (de->d_name[0] == '.')
1217 continue;
1218 if (is_wifi_interface(de->d_name)) {
1219 interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info));
1220 if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
1221 free(ifinfo);
1222 continue;
1223 }
1224 ifinfo->handle = handle;
1225 info->interfaces[i] = ifinfo;
1226 i++;
1227 }
1228 }
1229
1230 closedir(d);
1231
1232 info->num_interfaces = n;
1233 return WIFI_SUCCESS;
1234 }
1235
wifi_get_ifaces(wifi_handle handle,int * num,wifi_interface_handle ** interfaces)1236 wifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle **interfaces)
1237 {
1238 hal_info *info = (hal_info *)handle;
1239
1240 *interfaces = (wifi_interface_handle *)info->interfaces;
1241 *num = info->num_interfaces;
1242
1243 return WIFI_SUCCESS;
1244 }
1245
wifi_get_iface_name(wifi_interface_handle handle,char * name,size_t size)1246 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size)
1247 {
1248 interface_info *info = (interface_info *)handle;
1249 strcpy(name, info->name);
1250 return WIFI_SUCCESS;
1251 }
1252
wifi_get_supported_feature_set(wifi_interface_handle handle,feature_set * set)1253 wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *set)
1254 {
1255 GetFeatureSetCommand command(handle, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, set, NULL, NULL, 1);
1256 return (wifi_error) command.requestResponse();
1257 }
1258
wifi_get_concurrency_matrix(wifi_interface_handle handle,int set_size_max,feature_set set[],int * set_size)1259 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_size_max,
1260 feature_set set[], int *set_size)
1261 {
1262 GetFeatureSetCommand command(handle, ANDR_WIFI_ATTRIBUTE_FEATURE_SET, NULL,
1263 set, set_size, set_size_max);
1264 return (wifi_error) command.requestResponse();
1265 }
1266
wifi_set_scanning_mac_oui(wifi_interface_handle handle,oui scan_oui)1267 wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui)
1268 {
1269 SetPnoMacAddrOuiCommand command(handle, scan_oui);
1270 return (wifi_error)command.start();
1271
1272 }
1273
wifi_set_nodfs_flag(wifi_interface_handle handle,u32 nodfs)1274 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
1275 {
1276 SetNodfsCommand command(handle, nodfs);
1277 return (wifi_error) command.requestResponse();
1278 }
1279
wifi_set_country_code(wifi_interface_handle handle,const char * country_code)1280 wifi_error wifi_set_country_code(wifi_interface_handle handle, const char *country_code)
1281 {
1282 SetCountryCodeCommand command(handle, country_code);
1283 return (wifi_error) command.requestResponse();
1284 }
1285
wifi_start_rssi_monitoring(wifi_request_id id,wifi_interface_handle iface,s8 max_rssi,s8 min_rssi,wifi_rssi_event_handler eh)1286 static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
1287 iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
1288 {
1289 ALOGD("Start RSSI monitor %d", id);
1290 wifi_handle handle = getWifiHandle(iface);
1291 SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface, max_rssi, min_rssi, eh);
1292 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1293 wifi_error result = wifi_register_cmd(handle, id, cmd);
1294 if (result != WIFI_SUCCESS) {
1295 cmd->releaseRef();
1296 return result;
1297 }
1298 result = (wifi_error)cmd->start();
1299 if (result != WIFI_SUCCESS) {
1300 wifi_unregister_cmd(handle, id);
1301 cmd->releaseRef();
1302 return result;
1303 }
1304 return result;
1305 }
1306
wifi_stop_rssi_monitoring(wifi_request_id id,wifi_interface_handle iface)1307 static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface)
1308 {
1309 ALOGD("Stopping RSSI monitor");
1310
1311 if(id == -1) {
1312 wifi_rssi_event_handler handler;
1313 s8 max_rssi = 0, min_rssi = 0;
1314 wifi_handle handle = getWifiHandle(iface);
1315 memset(&handler, 0, sizeof(handler));
1316 SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface,
1317 max_rssi, min_rssi, handler);
1318 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1319 cmd->cancel();
1320 cmd->releaseRef();
1321 return WIFI_SUCCESS;
1322 }
1323 return wifi_cancel_cmd(id, iface);
1324 }
1325
wifi_get_packet_filter_capabilities(wifi_interface_handle handle,u32 * version,u32 * max_len)1326 static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
1327 u32 *version, u32 *max_len)
1328 {
1329 ALOGD("Getting APF capabilities, halHandle = %p\n", handle);
1330 AndroidPktFilterCommand *cmd = new AndroidPktFilterCommand(handle, version, max_len);
1331 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1332 wifi_error result = (wifi_error)cmd->start();
1333 if (result == WIFI_SUCCESS) {
1334 ALOGD("Getting APF capability, version = %d, max_len = %d\n", *version, *max_len);
1335 }
1336 cmd->releaseRef();
1337 return result;
1338 }
1339
wifi_set_packet_filter(wifi_interface_handle handle,const u8 * program,u32 len)1340 static wifi_error wifi_set_packet_filter(wifi_interface_handle handle,
1341 const u8 *program, u32 len)
1342 {
1343 ALOGD("Setting APF program, halHandle = %p\n", handle);
1344 AndroidPktFilterCommand *cmd = new AndroidPktFilterCommand(handle, program, len);
1345 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1346 wifi_error result = (wifi_error)cmd->start();
1347 cmd->releaseRef();
1348 return result;
1349 }
1350
wifi_configure_nd_offload(wifi_interface_handle handle,u8 enable)1351 static wifi_error wifi_configure_nd_offload(wifi_interface_handle handle, u8 enable)
1352 {
1353 SetNdoffloadCommand command(handle, enable);
1354 return (wifi_error) command.requestResponse();
1355 }
1356
1357 /////////////////////////////////////////////////////////////////////////////
1358