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