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