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