• 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 #define FEATURE_SET                  0
46 #define FEATURE_SET_MATRIX           1
47 #define ATTR_NODFS_VALUE             3
48 #define ATTR_COUNTRY_CODE            4
49 
50 static void internal_event_handler(wifi_handle handle, int events);
51 static int internal_no_seq_check(nl_msg *msg, void *arg);
52 static int internal_valid_message_handler(nl_msg *msg, void *arg);
53 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group);
54 static int wifi_add_membership(wifi_handle handle, const char *group);
55 static wifi_error wifi_init_interfaces(wifi_handle handle);
56 static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
57                         iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh);
58 static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface);
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 } wifi_attr_t;
65 
66 enum wifi_rssi_monitor_attr {
67     RSSI_MONITOR_ATTRIBUTE_MAX_RSSI,
68     RSSI_MONITOR_ATTRIBUTE_MIN_RSSI,
69     RSSI_MONITOR_ATTRIBUTE_START,
70 };
71 
72 /* Initialize/Cleanup */
73 
wifi_socket_set_local_port(struct nl_sock * sock,uint32_t port)74 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
75 {
76     uint32_t pid = getpid() & 0x3FFFFF;
77     nl_socket_set_local_port(sock, pid + (port << 22));
78 }
79 
wifi_create_nl_socket(int port)80 static nl_sock * wifi_create_nl_socket(int port)
81 {
82     // ALOGI("Creating socket");
83     struct nl_sock *sock = nl_socket_alloc();
84     if (sock == NULL) {
85         ALOGE("Could not create handle");
86         return NULL;
87     }
88 
89     wifi_socket_set_local_port(sock, port);
90 
91     struct sockaddr *addr = NULL;
92     // ALOGI("sizeof(sockaddr) = %d, sizeof(sockaddr_nl) = %d", sizeof(*addr), sizeof(*addr_nl));
93 
94     // ALOGI("Connecting socket");
95     if (nl_connect(sock, NETLINK_GENERIC)) {
96         ALOGE("Could not connect handle");
97         nl_socket_free(sock);
98         return NULL;
99     }
100 
101     // ALOGI("Making socket nonblocking");
102     /*
103     if (nl_socket_set_nonblocking(sock)) {
104         ALOGE("Could make socket non-blocking");
105         nl_socket_free(sock);
106         return NULL;
107     }
108     */
109 
110     return sock;
111 }
112 
113 /*initialize function pointer table with Broadcom HHAL API*/
init_wifi_vendor_hal_func_table(wifi_hal_fn * fn)114 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn)
115 {
116     if (fn == NULL) {
117         return WIFI_ERROR_UNKNOWN;
118     }
119     fn->wifi_initialize = wifi_initialize;
120     fn->wifi_cleanup = wifi_cleanup;
121     fn->wifi_event_loop = wifi_event_loop;
122     fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
123     fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
124     fn->wifi_set_scanning_mac_oui =  wifi_set_scanning_mac_oui;
125     fn->wifi_get_ifaces = wifi_get_ifaces;
126     fn->wifi_get_iface_name = wifi_get_iface_name;
127     fn->wifi_start_gscan = wifi_start_gscan;
128     fn->wifi_stop_gscan = wifi_stop_gscan;
129     fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
130     fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
131     fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
132     fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
133     fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
134     fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
135     fn->wifi_get_link_stats = wifi_get_link_stats;
136     fn->wifi_get_valid_channels = wifi_get_valid_channels;
137     fn->wifi_rtt_range_request = wifi_rtt_range_request;
138     fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
139     fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
140     fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
141     fn->wifi_start_logging = wifi_start_logging;
142     fn->wifi_set_epno_list = wifi_set_epno_list;
143     fn->wifi_set_country_code = wifi_set_country_code;
144     fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
145     fn->wifi_set_log_handler = wifi_set_log_handler;
146     fn->wifi_reset_log_handler = wifi_reset_log_handler;
147     fn->wifi_set_alert_handler = wifi_set_alert_handler;
148     fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
149     fn->wifi_get_firmware_version = wifi_get_firmware_version;
150     fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
151     fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;
152     fn->wifi_get_ring_data = wifi_get_ring_data;
153     fn->wifi_get_driver_version = wifi_get_driver_version;
154     fn->wifi_set_ssid_white_list = wifi_set_ssid_white_list;
155     fn->wifi_set_gscan_roam_params = wifi_set_gscan_roam_params;
156     fn->wifi_set_bssid_preference = wifi_set_bssid_preference;
157     fn->wifi_set_bssid_blacklist = wifi_set_bssid_blacklist;
158     fn->wifi_enable_lazy_roam = wifi_enable_lazy_roam;
159     fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
160     fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
161     fn->wifi_start_sending_offloaded_packet = wifi_start_sending_offloaded_packet;
162     fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
163     return WIFI_SUCCESS;
164 }
165 
wifi_initialize(wifi_handle * handle)166 wifi_error wifi_initialize(wifi_handle *handle)
167 {
168     srand(getpid());
169 
170     ALOGI("Initializing wifi");
171     hal_info *info = (hal_info *)malloc(sizeof(hal_info));
172     if (info == NULL) {
173         ALOGE("Could not allocate hal_info");
174         return WIFI_ERROR_UNKNOWN;
175     }
176 
177     memset(info, 0, sizeof(*info));
178 
179     ALOGI("Creating socket");
180     if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->cleanup_socks) == -1) {
181         ALOGE("Could not create cleanup sockets");
182         free(info);
183         return WIFI_ERROR_UNKNOWN;
184     }
185 
186     struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT);
187     if (cmd_sock == NULL) {
188         ALOGE("Could not create handle");
189         free(info);
190         return WIFI_ERROR_UNKNOWN;
191     }
192 
193     struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT);
194     if (event_sock == NULL) {
195         ALOGE("Could not create handle");
196         nl_socket_free(cmd_sock);
197         free(info);
198         return WIFI_ERROR_UNKNOWN;
199     }
200 
201     struct nl_cb *cb = nl_socket_get_cb(event_sock);
202     if (cb == NULL) {
203         ALOGE("Could not create handle");
204         nl_socket_free(cmd_sock);
205         nl_socket_free(event_sock);
206         free(info);
207         return WIFI_ERROR_UNKNOWN;
208     }
209 
210     // ALOGI("cb->refcnt = %d", cb->cb_refcnt);
211     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, info);
212     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info);
213     nl_cb_put(cb);
214 
215     info->cmd_sock = cmd_sock;
216     info->event_sock = event_sock;
217     info->clean_up = false;
218     info->in_event_loop = false;
219 
220     info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
221     info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
222     info->num_event_cb = 0;
223 
224     info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
225     info->alloc_cmd = DEFAULT_CMD_SIZE;
226     info->num_cmd = 0;
227 
228     info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
229     if (info->nl80211_family_id < 0) {
230         ALOGE("Could not resolve nl80211 familty id");
231         nl_socket_free(cmd_sock);
232         nl_socket_free(event_sock);
233         free(info);
234         return WIFI_ERROR_UNKNOWN;
235     }
236 
237     pthread_mutex_init(&info->cb_lock, NULL);
238 
239     *handle = (wifi_handle) info;
240 
241     wifi_add_membership(*handle, "scan");
242     wifi_add_membership(*handle, "mlme");
243     wifi_add_membership(*handle, "regulatory");
244     wifi_add_membership(*handle, "vendor");
245 
246     wifi_init_interfaces(*handle);
247     // ALOGI("Found %d interfaces", info->num_interfaces);
248 
249 
250     ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d", NL80211_CMD_VENDOR);
251     return WIFI_SUCCESS;
252 }
253 
wifi_add_membership(wifi_handle handle,const char * group)254 static int wifi_add_membership(wifi_handle handle, const char *group)
255 {
256     hal_info *info = getHalInfo(handle);
257 
258     int id = wifi_get_multicast_id(handle, "nl80211", group);
259     if (id < 0) {
260         ALOGE("Could not find group %s", group);
261         return id;
262     }
263 
264     int ret = nl_socket_add_membership(info->event_sock, id);
265     if (ret < 0) {
266         ALOGE("Could not add membership to group %s", group);
267     }
268 
269     // ALOGI("Successfully added membership for group %s", group);
270     return ret;
271 }
272 
internal_cleaned_up_handler(wifi_handle handle)273 static void internal_cleaned_up_handler(wifi_handle handle)
274 {
275     hal_info *info = getHalInfo(handle);
276     wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
277 
278     if (info->cmd_sock != 0) {
279         close(info->cleanup_socks[0]);
280         close(info->cleanup_socks[1]);
281         nl_socket_free(info->cmd_sock);
282         nl_socket_free(info->event_sock);
283         info->cmd_sock = NULL;
284         info->event_sock = NULL;
285     }
286 
287     (*cleaned_up_handler)(handle);
288     pthread_mutex_destroy(&info->cb_lock);
289     free(info);
290 
291     ALOGI("Internal cleanup completed");
292 }
293 
wifi_cleanup(wifi_handle handle,wifi_cleaned_up_handler handler)294 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
295 {
296     hal_info *info = getHalInfo(handle);
297     char buf[64];
298 
299     info->cleaned_up_handler = handler;
300     if (write(info->cleanup_socks[0], "Exit", 4) < 1) {
301         // As a fallback set the cleanup flag to TRUE
302         ALOGE("could not write to the cleanup socket");
303     } else {
304         // Listen to the response
305         // Hopefully we dont get errors or get hung up
306         // Not much can be done in that case, but assume that
307         // it has rx'ed the Exit message to exit the thread.
308         // As a fallback set the cleanup flag to TRUE
309         memset(buf, 0, sizeof(buf));
310         int result = read(info->cleanup_socks[0], buf, sizeof(buf));
311         ALOGE("%s: Read after POLL returned %d, error no = %d", __FUNCTION__, result, errno);
312         if (strncmp(buf, "Done", 4) == 0) {
313             ALOGE("Event processing terminated");
314         } else {
315             ALOGD("Rx'ed %s", buf);
316         }
317     }
318     info->clean_up = true;
319     pthread_mutex_lock(&info->cb_lock);
320 
321     int bad_commands = 0;
322 
323     for (int i = 0; i < info->num_event_cb; i++) {
324         cb_info *cbi = &(info->event_cb[i]);
325         WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
326         ALOGI("Command left in event_cb %p:%s", cmd, (cmd ? cmd->getType(): ""));
327     }
328 
329     while (info->num_cmd > bad_commands) {
330         int num_cmd = info->num_cmd;
331         cmd_info *cmdi = &(info->cmd[bad_commands]);
332         WifiCommand *cmd = cmdi->cmd;
333         if (cmd != NULL) {
334             ALOGI("Cancelling command %p:%s", cmd, cmd->getType());
335             pthread_mutex_unlock(&info->cb_lock);
336             cmd->cancel();
337             pthread_mutex_lock(&info->cb_lock);
338             if (num_cmd == info->num_cmd) {
339                 ALOGI("Cancelling command %p:%s did not work", cmd, (cmd ? cmd->getType(): ""));
340                 bad_commands++;
341             }
342             /* release reference added when command is saved */
343             cmd->releaseRef();
344         }
345     }
346 
347     for (int i = 0; i < info->num_event_cb; i++) {
348         cb_info *cbi = &(info->event_cb[i]);
349         WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
350         ALOGE("Leaked command %p", cmd);
351     }
352     pthread_mutex_unlock(&info->cb_lock);
353     internal_cleaned_up_handler(handle);
354 }
355 
internal_pollin_handler(wifi_handle handle)356 static int internal_pollin_handler(wifi_handle handle)
357 {
358     hal_info *info = getHalInfo(handle);
359     struct nl_cb *cb = nl_socket_get_cb(info->event_sock);
360     int res = nl_recvmsgs(info->event_sock, cb);
361     // ALOGD("nl_recvmsgs returned %d", res);
362     nl_cb_put(cb);
363     return res;
364 }
365 
366 /* Run event handler */
wifi_event_loop(wifi_handle handle)367 void wifi_event_loop(wifi_handle handle)
368 {
369     hal_info *info = getHalInfo(handle);
370     if (info->in_event_loop) {
371         return;
372     } else {
373         info->in_event_loop = true;
374     }
375 
376     pollfd pfd[2];
377     memset(&pfd[0], 0, sizeof(pollfd) * 2);
378 
379     pfd[0].fd = nl_socket_get_fd(info->event_sock);
380     pfd[0].events = POLLIN;
381     pfd[1].fd = info->cleanup_socks[1];
382     pfd[1].events = POLLIN;
383 
384     char buf[2048];
385     /* TODO: Add support for timeouts */
386 
387     do {
388         int timeout = -1;                   /* Infinite timeout */
389         pfd[0].revents = 0;
390         pfd[1].revents = 0;
391         // ALOGI("Polling socket");
392         int result = poll(pfd, 2, timeout);
393         if (result < 0) {
394             // ALOGE("Error polling socket");
395         } else if (pfd[0].revents & POLLERR) {
396             ALOGE("POLL Error; error no = %d", errno);
397             int result2 = read(pfd[0].fd, buf, sizeof(buf));
398             ALOGE("Read after POLL returned %d, error no = %d", result2, errno);
399         } else if (pfd[0].revents & POLLHUP) {
400             ALOGE("Remote side hung up");
401             break;
402         } else if (pfd[0].revents & POLLIN) {
403             // ALOGI("Found some events!!!");
404             internal_pollin_handler(handle);
405         } else if (pfd[1].revents & POLLIN) {
406             memset(buf, 0, sizeof(buf));
407             int result2 = read(pfd[1].fd, buf, sizeof(buf));
408             ALOGE("%s: Read after POLL returned %d, error no = %d", __FUNCTION__, result2, errno);
409             if (strncmp(buf, "Exit", 4) == 0) {
410                 ALOGD("Got a signal to exit!!!");
411                 if (write(pfd[1].fd, "Done", 4) < 1) {
412                     ALOGE("could not write to the cleanup socket");
413                 }
414                 break;
415             } else {
416                 ALOGD("Rx'ed %s on the cleanup socket\n", buf);
417             }
418         } else {
419             ALOGE("Unknown event - %0x, %0x", pfd[0].revents, pfd[1].revents);
420         }
421     } while (!info->clean_up);
422     ALOGI("Exit %s", __FUNCTION__);
423 }
424 
425 ///////////////////////////////////////////////////////////////////////////////////////
426 
internal_no_seq_check(struct nl_msg * msg,void * arg)427 static int internal_no_seq_check(struct nl_msg *msg, void *arg)
428 {
429     return NL_OK;
430 }
431 
internal_valid_message_handler(nl_msg * msg,void * arg)432 static int internal_valid_message_handler(nl_msg *msg, void *arg)
433 {
434     // ALOGI("got an event");
435 
436     wifi_handle handle = (wifi_handle)arg;
437     hal_info *info = getHalInfo(handle);
438 
439     WifiEvent event(msg);
440     int res = event.parse();
441     if (res < 0) {
442         ALOGE("Failed to parse event: %d", res);
443         return NL_SKIP;
444     }
445 
446     int cmd = event.get_cmd();
447     uint32_t vendor_id = 0;
448     int subcmd = 0;
449 
450     if (cmd == NL80211_CMD_VENDOR) {
451         vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
452         subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
453         ALOGV("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
454                 event.get_cmdString(), vendor_id, subcmd);
455     } else {
456         // ALOGV("event received %s", event.get_cmdString());
457     }
458 
459     // ALOGV("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id);
460     // event.log();
461 
462     bool dispatched = false;
463 
464     pthread_mutex_lock(&info->cb_lock);
465 
466     for (int i = 0; i < info->num_event_cb; i++) {
467         if (cmd == info->event_cb[i].nl_cmd) {
468             if (cmd == NL80211_CMD_VENDOR
469                 && ((vendor_id != info->event_cb[i].vendor_id)
470                 || (subcmd != info->event_cb[i].vendor_subcmd)))
471             {
472                 /* event for a different vendor, ignore it */
473                 continue;
474             }
475 
476             cb_info *cbi = &(info->event_cb[i]);
477             nl_recvmsg_msg_cb_t cb_func = cbi->cb_func;
478             void *cb_arg = cbi->cb_arg;
479             WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
480             if (cmd != NULL) {
481                 cmd->addRef();
482             }
483             pthread_mutex_unlock(&info->cb_lock);
484             if (cb_func)
485                 (*cb_func)(msg, cb_arg);
486             if (cmd != NULL) {
487                 cmd->releaseRef();
488             }
489 
490             return NL_OK;
491         }
492     }
493 
494     pthread_mutex_unlock(&info->cb_lock);
495     return NL_OK;
496 }
497 
498 ///////////////////////////////////////////////////////////////////////////////////////
499 
500 class GetMulticastIdCommand : public WifiCommand
501 {
502 private:
503     const char *mName;
504     const char *mGroup;
505     int   mId;
506 public:
GetMulticastIdCommand(wifi_handle handle,const char * name,const char * group)507     GetMulticastIdCommand(wifi_handle handle, const char *name, const char *group)
508         : WifiCommand("GetMulticastIdCommand", handle, 0)
509     {
510         mName = name;
511         mGroup = group;
512         mId = -1;
513     }
514 
getId()515     int getId() {
516         return mId;
517     }
518 
create()519     virtual int create() {
520         int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
521         // ALOGI("ctrl family = %d", nlctrlFamily);
522         int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
523         if (ret < 0) {
524             return ret;
525         }
526         ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
527         return ret;
528     }
529 
handleResponse(WifiEvent & reply)530     virtual int handleResponse(WifiEvent& reply) {
531 
532         // ALOGI("handling reponse in %s", __func__);
533 
534         struct nlattr **tb = reply.attributes();
535         struct genlmsghdr *gnlh = reply.header();
536         struct nlattr *mcgrp = NULL;
537         int i;
538 
539         if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
540             ALOGI("No multicast groups found");
541             return NL_SKIP;
542         } else {
543             // ALOGI("Multicast groups attr size = %d", nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
544         }
545 
546         for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
547 
548             // ALOGI("Processing group");
549             struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
550             nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
551                 nla_len(mcgrp), NULL);
552             if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID]) {
553                 continue;
554             }
555 
556             char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
557             int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
558 
559             // ALOGI("Found group name %s", grpName);
560 
561             if (strncmp(grpName, mGroup, grpNameLen) != 0)
562                 continue;
563 
564             mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
565             break;
566         }
567 
568         return NL_SKIP;
569     }
570 
571 };
572 
573 class SetPnoMacAddrOuiCommand : public WifiCommand {
574 
575 private:
576     byte *mOui;
577     feature_set *fset;
578     feature_set *feature_matrix;
579     int *fm_size;
580     int set_size_max;
581 public:
SetPnoMacAddrOuiCommand(wifi_interface_handle handle,oui scan_oui)582     SetPnoMacAddrOuiCommand(wifi_interface_handle handle, oui scan_oui)
583         : WifiCommand("SetPnoMacAddrOuiCommand", handle, 0)
584     {
585         mOui = scan_oui;
586     }
587 
createRequest(WifiRequest & request,int subcmd,byte * scan_oui)588     int createRequest(WifiRequest& request, int subcmd, byte *scan_oui) {
589         int result = request.create(GOOGLE_OUI, subcmd);
590         if (result < 0) {
591             return result;
592         }
593 
594         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
595         result = request.put(ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, scan_oui, DOT11_OUI_LEN);
596         if (result < 0) {
597             return result;
598         }
599 
600         request.attr_end(data);
601         return WIFI_SUCCESS;
602 
603     }
604 
start()605     int start() {
606         ALOGD("Sending mac address OUI");
607         WifiRequest request(familyId(), ifaceId());
608         int result = createRequest(request, WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, mOui);
609         if (result != WIFI_SUCCESS) {
610             ALOGE("failed to create request; result = %d", result);
611             return result;
612         }
613 
614         result = requestResponse(request);
615         if (result != WIFI_SUCCESS) {
616             ALOGE("failed to set scanning mac OUI; result = %d", result);
617         }
618 
619         return result;
620     }
621 protected:
handleResponse(WifiEvent & reply)622     virtual int handleResponse(WifiEvent& reply) {
623          ALOGD("Request complete!");
624         /* Nothing to do on response! */
625         return NL_SKIP;
626     }
627 };
628 
629 class SetNodfsCommand : public WifiCommand {
630 
631 private:
632     u32 mNoDfs;
633 public:
SetNodfsCommand(wifi_interface_handle handle,u32 nodfs)634     SetNodfsCommand(wifi_interface_handle handle, u32 nodfs)
635         : WifiCommand("SetNodfsCommand", handle, 0) {
636         mNoDfs = nodfs;
637     }
create()638     virtual int create() {
639         int ret;
640 
641         ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_NODFS_SET);
642         if (ret < 0) {
643             ALOGE("Can't create message to send to driver - %d", ret);
644             return ret;
645         }
646 
647         nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
648         ret = mMsg.put_u32(ATTR_NODFS_VALUE, mNoDfs);
649         if (ret < 0) {
650              return ret;
651         }
652 
653         mMsg.attr_end(data);
654         return WIFI_SUCCESS;
655     }
656 };
657 
658 class SetCountryCodeCommand : public WifiCommand {
659 private:
660     const char *mCountryCode;
661 public:
SetCountryCodeCommand(wifi_interface_handle handle,const char * country_code)662     SetCountryCodeCommand(wifi_interface_handle handle, const char *country_code)
663         : WifiCommand("SetCountryCodeCommand", handle, 0) {
664         mCountryCode = country_code;
665         }
create()666     virtual int create() {
667         int ret;
668 
669         ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_SET_COUNTRY_CODE);
670         if (ret < 0) {
671              ALOGE("Can't create message to send to driver - %d", ret);
672              return ret;
673         }
674 
675         nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
676         ret = mMsg.put_string(ATTR_COUNTRY_CODE, mCountryCode);
677         if (ret < 0) {
678             return ret;
679         }
680 
681         mMsg.attr_end(data);
682         return WIFI_SUCCESS;
683 
684     }
685 };
686 
687 class SetRSSIMonitorCommand : public WifiCommand {
688 private:
689     s8 mMax_rssi;
690     s8 mMin_rssi;
691     wifi_rssi_event_handler mHandler;
692 public:
SetRSSIMonitorCommand(wifi_request_id id,wifi_interface_handle handle,s8 max_rssi,s8 min_rssi,wifi_rssi_event_handler eh)693     SetRSSIMonitorCommand(wifi_request_id id, wifi_interface_handle handle,
694                 s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
695         : WifiCommand("SetRSSIMonitorCommand", handle, id), mMax_rssi(max_rssi), mMin_rssi
696         (min_rssi), mHandler(eh)
697         {
698         }
createRequest(WifiRequest & request,int enable)699    int createRequest(WifiRequest& request, int enable) {
700         int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_SET_RSSI_MONITOR);
701         if (result < 0) {
702             return result;
703         }
704 
705         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
706         result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_MAX_RSSI, (enable ? mMax_rssi: 0));
707         if (result < 0) {
708             return result;
709         }
710         ALOGD("create request");
711         result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_MIN_RSSI, (enable? mMin_rssi: 0));
712         if (result < 0) {
713             return result;
714         }
715         result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_START, enable);
716         if (result < 0) {
717             return result;
718         }
719         request.attr_end(data);
720         return result;
721     }
722 
start()723     int start() {
724         WifiRequest request(familyId(), ifaceId());
725         int result = createRequest(request, 1);
726         if (result < 0) {
727             return result;
728         }
729         result = requestResponse(request);
730         if (result < 0) {
731             ALOGI("Failed to set RSSI Monitor, result = %d", result);
732             return result;
733         }
734         ALOGI("Successfully set RSSI monitoring");
735         registerVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
736 
737 
738         if (result < 0) {
739             unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
740             return result;
741         }
742         ALOGI("Done!");
743         return result;
744     }
745 
cancel()746     virtual int cancel() {
747 
748         WifiRequest request(familyId(), ifaceId());
749         int result = createRequest(request, 0);
750         if (result != WIFI_SUCCESS) {
751             ALOGE("failed to create request; result = %d", result);
752         } else {
753             result = requestResponse(request);
754             if (result != WIFI_SUCCESS) {
755                 ALOGE("failed to stop RSSI monitoring = %d", result);
756             }
757         }
758         unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
759         return WIFI_SUCCESS;
760     }
761 
handleResponse(WifiEvent & reply)762     virtual int handleResponse(WifiEvent& reply) {
763         /* Nothing to do on response! */
764         return NL_SKIP;
765     }
766 
handleEvent(WifiEvent & event)767    virtual int handleEvent(WifiEvent& event) {
768         ALOGI("Got a RSSI monitor event");
769 
770         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
771         int len = event.get_vendor_data_len();
772 
773         if (vendor_data == NULL || len == 0) {
774             ALOGI("RSSI monitor: No data");
775             return NL_SKIP;
776         }
777         /* driver<->HAL event structure */
778         #define RSSI_MONITOR_EVT_VERSION   1
779         typedef struct {
780             u8 version;
781             s8 cur_rssi;
782             mac_addr BSSID;
783         } rssi_monitor_evt;
784 
785         rssi_monitor_evt *data = (rssi_monitor_evt *)event.get_vendor_data();
786 
787         if (data->version != RSSI_MONITOR_EVT_VERSION) {
788             ALOGI("Event version mismatch %d, expected %d", data->version, RSSI_MONITOR_EVT_VERSION);
789             return NL_SKIP;
790         }
791 
792         if (*mHandler.on_rssi_threshold_breached) {
793             (*mHandler.on_rssi_threshold_breached)(id(), data->BSSID, data->cur_rssi);
794         } else {
795             ALOGW("No RSSI monitor handler registered");
796         }
797 
798         return NL_SKIP;
799     }
800 
801 };
802 
803 class GetFeatureSetCommand : public WifiCommand {
804 
805 private:
806     int feature_type;
807     feature_set *fset;
808     feature_set *feature_matrix;
809     int *fm_size;
810     int set_size_max;
811 public:
GetFeatureSetCommand(wifi_interface_handle handle,int feature,feature_set * set,feature_set set_matrix[],int * size,int max_size)812     GetFeatureSetCommand(wifi_interface_handle handle, int feature, feature_set *set,
813          feature_set set_matrix[], int *size, int max_size)
814         : WifiCommand("GetFeatureSetCommand", handle, 0)
815     {
816         feature_type = feature;
817         fset = set;
818         feature_matrix = set_matrix;
819         fm_size = size;
820         set_size_max = max_size;
821     }
822 
create()823     virtual int create() {
824         int ret;
825 
826         if(feature_type == FEATURE_SET) {
827             ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET);
828         } else if (feature_type == FEATURE_SET_MATRIX) {
829             ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET_MATRIX);
830         } else {
831             ALOGE("Unknown feature type %d", feature_type);
832             return -1;
833         }
834 
835         if (ret < 0) {
836             ALOGE("Can't create message to send to driver - %d", ret);
837         }
838 
839         return ret;
840     }
841 
842 protected:
handleResponse(WifiEvent & reply)843     virtual int handleResponse(WifiEvent& reply) {
844 
845         ALOGV("In GetFeatureSetCommand::handleResponse");
846 
847         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
848             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
849             return NL_SKIP;
850         }
851 
852         int id = reply.get_vendor_id();
853         int subcmd = reply.get_vendor_subcmd();
854 
855         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
856         int len = reply.get_vendor_data_len();
857 
858         ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
859         if (vendor_data == NULL || len == 0) {
860             ALOGE("no vendor data in GetFeatureSetCommand response; ignoring it");
861             return NL_SKIP;
862         }
863         if(feature_type == FEATURE_SET) {
864             void *data = reply.get_vendor_data();
865             if(!fset) {
866                 ALOGE("Buffers pointers not set");
867                 return NL_SKIP;
868             }
869             memcpy(fset, data, min(len, (int) sizeof(*fset)));
870         } else {
871             int num_features_set = 0;
872             int i = 0;
873 
874             if(!feature_matrix || !fm_size) {
875                 ALOGE("Buffers pointers not set");
876                 return NL_SKIP;
877             }
878 
879             for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
880                 if (it.get_type() == ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET) {
881                     num_features_set = it.get_u32();
882                     ALOGV("Got feature list with %d concurrent sets", num_features_set);
883                     if(set_size_max && (num_features_set > set_size_max))
884                         num_features_set = set_size_max;
885                     *fm_size = num_features_set;
886                 } else if ((it.get_type() == ANDR_WIFI_ATTRIBUTE_FEATURE_SET) &&
887                              i < num_features_set) {
888                     feature_matrix[i] = it.get_u32();
889                     i++;
890                 } else {
891                     ALOGW("Ignoring invalid attribute type = %d, size = %d",
892                             it.get_type(), it.get_len());
893                 }
894             }
895 
896         }
897         return NL_OK;
898     }
899 
900 };
901 
wifi_get_multicast_id(wifi_handle handle,const char * name,const char * group)902 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group)
903 {
904     GetMulticastIdCommand cmd(handle, name, group);
905     int res = cmd.requestResponse();
906     if (res < 0)
907         return res;
908     else
909         return cmd.getId();
910 }
911 
912 /////////////////////////////////////////////////////////////////////////
913 
is_wifi_interface(const char * name)914 static bool is_wifi_interface(const char *name)
915 {
916     if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
917         /* not a wifi interface; ignore it */
918         return false;
919     } else {
920         return true;
921     }
922 }
923 
get_interface(const char * name,interface_info * info)924 static int get_interface(const char *name, interface_info *info)
925 {
926     strcpy(info->name, name);
927     info->id = if_nametoindex(name);
928     // ALOGI("found an interface : %s, id = %d", name, info->id);
929     return WIFI_SUCCESS;
930 }
931 
wifi_init_interfaces(wifi_handle handle)932 wifi_error wifi_init_interfaces(wifi_handle handle)
933 {
934     hal_info *info = (hal_info *)handle;
935 
936     struct dirent *de;
937 
938     DIR *d = opendir("/sys/class/net");
939     if (d == 0)
940         return WIFI_ERROR_UNKNOWN;
941 
942     int n = 0;
943     while ((de = readdir(d))) {
944         if (de->d_name[0] == '.')
945             continue;
946         if (is_wifi_interface(de->d_name) ) {
947             n++;
948         }
949     }
950 
951     closedir(d);
952 
953     d = opendir("/sys/class/net");
954     if (d == 0)
955         return WIFI_ERROR_UNKNOWN;
956 
957     info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
958 
959     int i = 0;
960     while ((de = readdir(d))) {
961         if (de->d_name[0] == '.')
962             continue;
963         if (is_wifi_interface(de->d_name)) {
964             interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info));
965             if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
966                 free(ifinfo);
967                 continue;
968             }
969             ifinfo->handle = handle;
970             info->interfaces[i] = ifinfo;
971             i++;
972         }
973     }
974 
975     closedir(d);
976 
977     info->num_interfaces = n;
978     return WIFI_SUCCESS;
979 }
980 
wifi_get_ifaces(wifi_handle handle,int * num,wifi_interface_handle ** interfaces)981 wifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle **interfaces)
982 {
983     hal_info *info = (hal_info *)handle;
984 
985     *interfaces = (wifi_interface_handle *)info->interfaces;
986     *num = info->num_interfaces;
987 
988     return WIFI_SUCCESS;
989 }
990 
wifi_get_iface_name(wifi_interface_handle handle,char * name,size_t size)991 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size)
992 {
993     interface_info *info = (interface_info *)handle;
994     strcpy(name, info->name);
995     return WIFI_SUCCESS;
996 }
997 
wifi_get_supported_feature_set(wifi_interface_handle handle,feature_set * set)998 wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *set)
999 {
1000     GetFeatureSetCommand command(handle, FEATURE_SET, set, NULL, NULL, 1);
1001     return (wifi_error) command.requestResponse();
1002 }
1003 
wifi_get_concurrency_matrix(wifi_interface_handle handle,int set_size_max,feature_set set[],int * set_size)1004 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_size_max,
1005        feature_set set[], int *set_size)
1006 {
1007     GetFeatureSetCommand command(handle, FEATURE_SET_MATRIX, NULL, set, set_size, set_size_max);
1008     return (wifi_error) command.requestResponse();
1009 }
1010 
wifi_set_scanning_mac_oui(wifi_interface_handle handle,oui scan_oui)1011 wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui)
1012 {
1013     SetPnoMacAddrOuiCommand command(handle, scan_oui);
1014     return (wifi_error)command.start();
1015 
1016 }
1017 
wifi_set_nodfs_flag(wifi_interface_handle handle,u32 nodfs)1018 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
1019 {
1020     SetNodfsCommand command(handle, nodfs);
1021     return (wifi_error) command.requestResponse();
1022 }
1023 
wifi_set_country_code(wifi_interface_handle handle,const char * country_code)1024 wifi_error wifi_set_country_code(wifi_interface_handle handle, const char *country_code)
1025 {
1026     SetCountryCodeCommand command(handle, country_code);
1027     return (wifi_error) command.requestResponse();
1028 }
1029 
wifi_start_rssi_monitoring(wifi_request_id id,wifi_interface_handle iface,s8 max_rssi,s8 min_rssi,wifi_rssi_event_handler eh)1030 static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
1031                         iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
1032 {
1033     ALOGD("Start RSSI monitor %d", id);
1034     wifi_handle handle = getWifiHandle(iface);
1035     SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface, max_rssi, min_rssi, eh);
1036     wifi_register_cmd(handle, id, cmd);
1037 
1038     wifi_error result = (wifi_error)cmd->start();
1039     if (result != WIFI_SUCCESS) {
1040         wifi_unregister_cmd(handle, id);
1041     }
1042     return result;
1043 }
1044 
1045 
wifi_stop_rssi_monitoring(wifi_request_id id,wifi_interface_handle iface)1046 static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface)
1047 {
1048     ALOGD("Stopping RSSI monitor");
1049 
1050     if(id == -1) {
1051         wifi_rssi_event_handler handler;
1052         s8 max_rssi = 0, min_rssi = 0;
1053         wifi_handle handle = getWifiHandle(iface);
1054         memset(&handler, 0, sizeof(handler));
1055         SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface,
1056                                                     max_rssi, min_rssi, handler);
1057         cmd->cancel();
1058         cmd->releaseRef();
1059         return WIFI_SUCCESS;
1060     }
1061     return wifi_cancel_cmd(id, iface);
1062 }
1063 
1064 /////////////////////////////////////////////////////////////////////////////
1065