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