• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <stdint.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <sys/socket.h>
21 #include <netlink/genl/genl.h>
22 #include <netlink/genl/family.h>
23 #include <netlink/genl/ctrl.h>
24 #include <linux/rtnetlink.h>
25 #include <netpacket/packet.h>
26 #include <linux/filter.h>
27 #include <linux/errqueue.h>
28 
29 #include <linux/pkt_sched.h>
30 #include <netlink/object-api.h>
31 #include <netlink/netlink.h>
32 #include <netlink/socket.h>
33 #include <netlink-types.h>
34 
35 #include "nl80211_copy.h"
36 
37 #include <dirent.h>
38 #include <net/if.h>
39 #include <netinet/in.h>
40 
41 #include "sync.h"
42 
43 #define LOG_TAG  "WifiHAL"
44 
45 #include "hardware_legacy/wifi.h"
46 
47 #include "wifi_hal.h"
48 #include "common.h"
49 #include "cpp_bindings.h"
50 #include "ifaceeventhandler.h"
51 #include "wifiloggercmd.h"
52 #include "vendor_definitions.h"
53 
54 /*
55  BUGBUG: normally, libnl allocates ports for all connections it makes; but
56  being a static library, it doesn't really know how many other netlink
57  connections are made by the same process, if connections come from different
58  shared libraries. These port assignments exist to solve that
59  problem - temporarily. We need to fix libnl to try and allocate ports across
60  the entire process.
61  */
62 
63 #define WIFI_HAL_CMD_SOCK_PORT       644
64 #define WIFI_HAL_EVENT_SOCK_PORT     645
65 
66 static void internal_event_handler(wifi_handle handle, int events,
67                                    struct nl_sock *sock);
68 static int internal_valid_message_handler(nl_msg *msg, void *arg);
69 static int user_sock_message_handler(nl_msg *msg, void *arg);
70 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
71         const char *group);
72 static int wifi_add_membership(wifi_handle handle, const char *group);
73 static wifi_error wifi_init_interfaces(wifi_handle handle);
74 
75 /* Initialize/Cleanup */
76 
wifi_get_iface_handle(wifi_handle handle,char * name)77 wifi_interface_handle wifi_get_iface_handle(wifi_handle handle, char *name)
78 {
79     hal_info *info = (hal_info *)handle;
80     for (int i=0;i<info->num_interfaces;i++)
81     {
82         if (!strcmp(info->interfaces[i]->name, name))
83         {
84             return ((wifi_interface_handle )(info->interfaces)[i]);
85         }
86     }
87     return NULL;
88 }
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 
94     if (port == 0) {
95         sock->s_flags &= ~NL_OWN_PORT;
96     } else {
97         sock->s_flags |= NL_OWN_PORT;
98     }
99 
100     sock->s_local.nl_pid = pid + (port << 22);
101 }
102 
wifi_create_nl_socket(int port,int protocol)103 static nl_sock * wifi_create_nl_socket(int port, int protocol)
104 {
105     // ALOGI("Creating socket");
106     struct nl_sock *sock = nl_socket_alloc();
107     if (sock == NULL) {
108         ALOGE("Failed to create NL socket");
109         return NULL;
110     }
111 
112     wifi_socket_set_local_port(sock, port);
113 
114     struct sockaddr_nl *addr_nl = &(sock->s_local);
115     /* ALOGI("socket address is %d:%d:%d:%d",
116        addr_nl->nl_family, addr_nl->nl_pad, addr_nl->nl_pid,
117        addr_nl->nl_groups); */
118 
119     struct sockaddr *addr = NULL;
120     // ALOGI("sizeof(sockaddr) = %d, sizeof(sockaddr_nl) = %d", sizeof(*addr),
121     // sizeof(*addr_nl));
122 
123     // ALOGI("Connecting socket");
124     if (nl_connect(sock, protocol)) {
125         ALOGE("Could not connect handle");
126         nl_socket_free(sock);
127         return NULL;
128     }
129 
130     return sock;
131 }
132 
ack_handler(struct nl_msg * msg,void * arg)133 int ack_handler(struct nl_msg *msg, void *arg)
134 {
135     int *err = (int *)arg;
136     *err = 0;
137     return NL_STOP;
138 }
139 
finish_handler(struct nl_msg * msg,void * arg)140 int finish_handler(struct nl_msg *msg, void *arg)
141 {
142     int *ret = (int *)arg;
143     *ret = 0;
144     return NL_SKIP;
145 }
146 
error_handler(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)147 int error_handler(struct sockaddr_nl *nla,
148                   struct nlmsgerr *err, void *arg)
149 {
150     int *ret = (int *)arg;
151     *ret = err->error;
152 
153     ALOGD("%s invoked with error: %d", __func__, err->error);
154     return NL_SKIP;
155 }
no_seq_check(struct nl_msg * msg,void * arg)156 static int no_seq_check(struct nl_msg *msg, void *arg)
157 {
158     return NL_OK;
159 }
160 
acquire_supported_features(wifi_interface_handle iface,feature_set * set)161 static wifi_error acquire_supported_features(wifi_interface_handle iface,
162         feature_set *set)
163 {
164     int ret = 0;
165     interface_info *iinfo = getIfaceInfo(iface);
166     wifi_handle handle = getWifiHandle(iface);
167     *set = 0;
168 
169     WifihalGeneric supportedFeatures(handle, 0,
170             OUI_QCA,
171             QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES);
172 
173     /* create the message */
174     ret = supportedFeatures.create();
175     if (ret < 0)
176         goto cleanup;
177 
178     ret = supportedFeatures.set_iface_id(iinfo->name);
179     if (ret < 0)
180         goto cleanup;
181 
182     ret = supportedFeatures.requestResponse();
183     if (ret != 0) {
184         ALOGE("%s: requestResponse Error:%d",__func__, ret);
185         goto cleanup;
186     }
187 
188     supportedFeatures.getResponseparams(set);
189 
190 cleanup:
191     return (wifi_error)ret;
192 }
193 
wifi_init_user_sock(hal_info * info)194 static wifi_error wifi_init_user_sock(hal_info *info)
195 {
196     struct nl_sock *user_sock =
197         wifi_create_nl_socket(WIFI_HAL_USER_SOCK_PORT, NETLINK_USERSOCK);
198     if (user_sock == NULL) {
199         ALOGE("Could not create diag sock");
200         return WIFI_ERROR_UNKNOWN;
201     }
202 
203     /* Set the socket buffer size */
204     if (nl_socket_set_buffer_size(user_sock, (256*1024), 0) < 0) {
205         ALOGE("Could not set size for user_sock: %s",
206                    strerror(errno));
207         /* continue anyway with the default (smaller) buffer */
208     }
209     else {
210         ALOGI("nl_socket_set_buffer_size successful for user_sock");
211     }
212 
213     struct nl_cb *cb = nl_socket_get_cb(user_sock);
214     if (cb == NULL) {
215         ALOGE("Could not get cb");
216         return WIFI_ERROR_UNKNOWN;
217     }
218 
219     info->user_sock_arg = 1;
220     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
221     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg);
222     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg);
223     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg);
224 
225     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info);
226     nl_cb_put(cb);
227 
228     int ret = nl_socket_add_membership(user_sock, 1);
229     if (ret < 0) {
230         ALOGE("Could not add membership");
231         return WIFI_ERROR_UNKNOWN;
232     }
233 
234     info->user_sock = user_sock;
235     ALOGI("Initiialized diag sock successfully");
236     return WIFI_SUCCESS;
237 }
238 
239 /*initialize function pointer table with Qualcomm HAL API*/
init_wifi_vendor_hal_func_table(wifi_hal_fn * fn)240 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) {
241     if (fn == NULL) {
242         return WIFI_ERROR_UNKNOWN;
243     }
244 
245     fn->wifi_initialize = wifi_initialize;
246     fn->wifi_cleanup = wifi_cleanup;
247     fn->wifi_event_loop = wifi_event_loop;
248     fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
249     fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
250     fn->wifi_set_scanning_mac_oui =  wifi_set_scanning_mac_oui;
251     fn->wifi_get_ifaces = wifi_get_ifaces;
252     fn->wifi_get_iface_name = wifi_get_iface_name;
253     fn->wifi_set_iface_event_handler = wifi_set_iface_event_handler;
254     fn->wifi_reset_iface_event_handler = wifi_reset_iface_event_handler;
255     fn->wifi_start_gscan = wifi_start_gscan;
256     fn->wifi_stop_gscan = wifi_stop_gscan;
257     fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
258     fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
259     fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
260     fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
261     fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
262     fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
263     fn->wifi_set_link_stats = wifi_set_link_stats;
264     fn->wifi_get_link_stats = wifi_get_link_stats;
265     fn->wifi_clear_link_stats = wifi_clear_link_stats;
266     fn->wifi_get_valid_channels = wifi_get_valid_channels;
267     fn->wifi_rtt_range_request = wifi_rtt_range_request;
268     fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
269     fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
270     fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
271     fn->wifi_start_logging = wifi_start_logging;
272     fn->wifi_set_epno_list = wifi_set_epno_list;
273     fn->wifi_set_country_code = wifi_set_country_code;
274     fn->wifi_enable_tdls = wifi_enable_tdls;
275     fn->wifi_disable_tdls = wifi_disable_tdls;
276     fn->wifi_get_tdls_status = wifi_get_tdls_status;
277     fn->wifi_get_tdls_capabilities = wifi_get_tdls_capabilities;
278     fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
279     fn->wifi_set_log_handler = wifi_set_log_handler;
280     fn->wifi_reset_log_handler = wifi_reset_log_handler;
281     fn->wifi_set_alert_handler = wifi_set_alert_handler;
282     fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
283     fn->wifi_get_firmware_version = wifi_get_firmware_version;
284     fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
285     fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;
286     fn->wifi_get_ring_data = wifi_get_ring_data;
287     fn->wifi_get_driver_version = wifi_get_driver_version;
288     fn->wifi_set_passpoint_list = wifi_set_passpoint_list;
289     fn->wifi_reset_passpoint_list = wifi_reset_passpoint_list;
290     fn->wifi_set_bssid_blacklist = wifi_set_bssid_blacklist;
291     fn->wifi_enable_lazy_roam = wifi_enable_lazy_roam;
292     fn->wifi_set_bssid_preference = wifi_set_bssid_preference;
293     fn->wifi_set_gscan_roam_params = wifi_set_gscan_roam_params;
294     fn->wifi_set_ssid_white_list = wifi_set_ssid_white_list;
295     fn->wifi_set_lci = wifi_set_lci;
296     fn->wifi_set_lcr = wifi_set_lcr;
297     fn->wifi_start_sending_offloaded_packet =
298             wifi_start_sending_offloaded_packet;
299     fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
300     fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
301     fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
302 
303     return WIFI_SUCCESS;
304 }
305 
wifi_initialize(wifi_handle * handle)306 wifi_error wifi_initialize(wifi_handle *handle)
307 {
308     int err = 0;
309     bool driver_loaded = false;
310     wifi_error ret = WIFI_SUCCESS;
311     wifi_interface_handle iface_handle;
312     struct nl_sock *cmd_sock = NULL;
313     struct nl_sock *event_sock = NULL;
314     struct nl_cb *cb = NULL;
315 
316     ALOGI("Initializing wifi");
317     hal_info *info = (hal_info *)malloc(sizeof(hal_info));
318     if (info == NULL) {
319         ALOGE("Could not allocate hal_info");
320         return WIFI_ERROR_OUT_OF_MEMORY;
321     }
322 
323     memset(info, 0, sizeof(*info));
324 
325     cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT,
326                                                      NETLINK_GENERIC);
327     if (cmd_sock == NULL) {
328         ALOGE("Failed to create command socket port");
329         ret = WIFI_ERROR_UNKNOWN;
330         goto unload;
331     }
332 
333     /* Set the socket buffer size */
334     if (nl_socket_set_buffer_size(cmd_sock, (256*1024), 0) < 0) {
335         ALOGE("Could not set nl_socket RX buffer size for cmd_sock: %s",
336                    strerror(errno));
337         /* continue anyway with the default (smaller) buffer */
338     }
339 
340     event_sock =
341         wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT, NETLINK_GENERIC);
342     if (event_sock == NULL) {
343         ALOGE("Failed to create event socket port");
344         ret = WIFI_ERROR_UNKNOWN;
345         goto unload;
346     }
347 
348     /* Set the socket buffer size */
349     if (nl_socket_set_buffer_size(event_sock, (256*1024), 0) < 0) {
350         ALOGE("Could not set nl_socket RX buffer size for event_sock: %s",
351                    strerror(errno));
352         /* continue anyway with the default (smaller) buffer */
353     }
354 
355     cb = nl_socket_get_cb(event_sock);
356     if (cb == NULL) {
357         ALOGE("Failed to get NL control block for event socket port");
358         ret = WIFI_ERROR_UNKNOWN;
359         goto unload;
360     }
361 
362     err = 1;
363     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
364     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
365     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
366     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
367 
368     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler,
369             info);
370     nl_cb_put(cb);
371 
372     info->cmd_sock = cmd_sock;
373     info->event_sock = event_sock;
374     info->clean_up = false;
375     info->in_event_loop = false;
376 
377     info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
378     if (info->event_cb == NULL) {
379         ALOGE("Could not allocate event_cb");
380         ret = WIFI_ERROR_OUT_OF_MEMORY;
381         goto unload;
382     }
383     info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
384     info->num_event_cb = 0;
385 
386     info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
387     if (info->cmd == NULL) {
388         ALOGE("Could not allocate cmd info");
389         ret = WIFI_ERROR_OUT_OF_MEMORY;
390         goto unload;
391     }
392     info->alloc_cmd = DEFAULT_CMD_SIZE;
393     info->num_cmd = 0;
394 
395     info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
396     if (info->nl80211_family_id < 0) {
397         ALOGE("Could not resolve nl80211 familty id");
398         ret = WIFI_ERROR_UNKNOWN;
399         goto unload;
400     }
401 
402     pthread_mutex_init(&info->cb_lock, NULL);
403 
404     *handle = (wifi_handle) info;
405 
406     wifi_add_membership(*handle, "scan");
407     wifi_add_membership(*handle, "mlme");
408     wifi_add_membership(*handle, "regulatory");
409     wifi_add_membership(*handle, "vendor");
410 
411     ret = wifi_init_user_sock(info);
412     if (ret != WIFI_SUCCESS) {
413         ALOGE("Failed to alloc user socket");
414         goto unload;
415     }
416 
417     if (!is_wifi_driver_loaded()) {
418         ret = (wifi_error)wifi_load_driver();
419         if(ret != WIFI_SUCCESS) {
420             ALOGE("%s Failed to load wifi driver : %d\n", __func__, ret);
421             goto unload;
422         }
423         driver_loaded = true;
424     }
425 
426     ret = wifi_init_interfaces(*handle);
427     if (ret != WIFI_SUCCESS) {
428         ALOGI("Failed to init interfaces");
429         goto unload;
430     }
431 
432     if (info->num_interfaces == 0) {
433         ALOGI("No interfaces found");
434         ret = WIFI_ERROR_UNINITIALIZED;
435         goto unload;
436     }
437 
438     iface_handle = wifi_get_iface_handle((info->interfaces[0])->handle,
439             (info->interfaces[0])->name);
440     if (iface_handle == NULL) {
441         int i;
442         for (i = 0; i < info->num_interfaces; i++)
443         {
444             free(info->interfaces[i]);
445         }
446         ALOGE("%s no iface with %s\n", __func__, info->interfaces[0]->name);
447         goto unload;
448     }
449 
450     ret = acquire_supported_features(iface_handle,
451             &info->supported_feature_set);
452     if (ret != WIFI_SUCCESS) {
453         ALOGI("Failed to get supported feature set : %d", ret);
454         //acquire_supported_features failure is acceptable condition as legacy
455         //drivers might not support the required vendor command. So, do not
456         //consider it as failure of wifi_initialize
457         ret = WIFI_SUCCESS;
458     }
459 
460     ret = wifi_logger_ring_buffers_init(info);
461     if (ret != WIFI_SUCCESS) {
462         ALOGE("Wifi Logger Ring Initialization Failed");
463         goto unload;
464     }
465 
466     info->pkt_stats = (struct pkt_stats_s *)malloc(sizeof(struct pkt_stats_s));
467     if (!info->pkt_stats) {
468         ALOGE("%s: malloc Failed for size: %d",
469                 __FUNCTION__, sizeof(struct pkt_stats_s));
470         ret = WIFI_ERROR_OUT_OF_MEMORY;
471         goto unload;
472     }
473 
474     info->rx_buf_size_allocated = MAX_RXMPDUS_PER_AMPDU * MAX_MSDUS_PER_MPDU
475                                   * PKT_STATS_BUF_SIZE;
476 
477     info->rx_aggr_pkts =
478         (wifi_ring_buffer_entry  *)malloc(info->rx_buf_size_allocated);
479     if (!info->rx_aggr_pkts) {
480         ALOGE("%s: malloc Failed for size: %d",
481                 __FUNCTION__, info->rx_buf_size_allocated);
482         ret = WIFI_ERROR_OUT_OF_MEMORY;
483         info->rx_buf_size_allocated = 0;
484         goto unload;
485     }
486     memset(info->rx_aggr_pkts, 0, info->rx_buf_size_allocated);
487 
488     info->exit_sockets[0] = -1;
489     info->exit_sockets[1] = -1;
490 
491     if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->exit_sockets) == -1) {
492         ALOGE("Failed to create exit socket pair");
493         ret = WIFI_ERROR_UNKNOWN;
494         goto unload;
495     }
496 
497     ALOGI("Initializing Gscan Event Handlers");
498     ret = initializeGscanHandlers(info);
499     if (ret != WIFI_SUCCESS) {
500         ALOGE("Initializing Gscan Event Handlers Failed");
501         goto unload;
502     }
503 
504     ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d Supported"
505             " features : %x", NL80211_CMD_VENDOR, info->supported_feature_set);
506 
507 unload:
508     if (ret != WIFI_SUCCESS) {
509         if (cmd_sock)
510             nl_socket_free(cmd_sock);
511         if (event_sock)
512             nl_socket_free(event_sock);
513         if (info) {
514             if (info->cmd) free(info->cmd);
515             if (info->event_cb) free(info->event_cb);
516             if (info->user_sock) nl_socket_free(info->user_sock);
517             if (info->pkt_stats) free(info->pkt_stats);
518             if (info->rx_aggr_pkts) free(info->rx_aggr_pkts);
519             cleanupGscanHandlers(info);
520             free(info);
521         }
522     }
523 
524     if (driver_loaded)
525         wifi_unload_driver();
526     return ret;
527 }
528 
wifi_add_membership(wifi_handle handle,const char * group)529 static int wifi_add_membership(wifi_handle handle, const char *group)
530 {
531     hal_info *info = getHalInfo(handle);
532 
533     int id = wifi_get_multicast_id(handle, "nl80211", group);
534     if (id < 0) {
535         ALOGE("Could not find group %s", group);
536         return id;
537     }
538 
539     int ret = nl_socket_add_membership(info->event_sock, id);
540     if (ret < 0) {
541         ALOGE("Could not add membership to group %s", group);
542     }
543 
544     return ret;
545 }
546 
internal_cleaned_up_handler(wifi_handle handle)547 static void internal_cleaned_up_handler(wifi_handle handle)
548 {
549     hal_info *info = getHalInfo(handle);
550     wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
551 
552     if (info->cmd_sock != 0) {
553         nl_socket_free(info->cmd_sock);
554         nl_socket_free(info->event_sock);
555         info->cmd_sock = NULL;
556         info->event_sock = NULL;
557     }
558 
559     if (info->user_sock != 0) {
560         nl_socket_free(info->user_sock);
561         info->user_sock = NULL;
562     }
563 
564     if (info->pkt_stats)
565         free(info->pkt_stats);
566     if (info->rx_aggr_pkts)
567         free(info->rx_aggr_pkts);
568     wifi_logger_ring_buffers_deinit(info);
569     ALOGI("Cleanup Gscan Event Handlers");
570     cleanupGscanHandlers(info);
571 
572     if (info->exit_sockets[0] >= 0) {
573         close(info->exit_sockets[0]);
574         info->exit_sockets[0] = -1;
575     }
576 
577     if (info->exit_sockets[1] >= 0) {
578         close(info->exit_sockets[1]);
579         info->exit_sockets[1] = -1;
580     }
581 
582     (*cleaned_up_handler)(handle);
583     pthread_mutex_destroy(&info->cb_lock);
584     free(info);
585 
586     ALOGI("Internal cleanup completed");
587 }
588 
wifi_cleanup(wifi_handle handle,wifi_cleaned_up_handler handler)589 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
590 {
591     if (!handle) {
592         ALOGE("Handle is null");
593         return;
594     }
595 
596     hal_info *info = getHalInfo(handle);
597     info->cleaned_up_handler = handler;
598     info->clean_up = true;
599 
600     TEMP_FAILURE_RETRY(write(info->exit_sockets[0], "E", 1));
601     ALOGI("Sent msg on exit sock to unblock poll()");
602 }
603 
internal_pollin_handler(wifi_handle handle,struct nl_sock * sock)604 static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock)
605 {
606     struct nl_cb *cb = nl_socket_get_cb(sock);
607 
608     int res = nl_recvmsgs(sock, cb);
609     if(res)
610         ALOGE("Error :%d while reading nl msg", res);
611     nl_cb_put(cb);
612     return res;
613 }
614 
internal_event_handler(wifi_handle handle,int events,struct nl_sock * sock)615 static void internal_event_handler(wifi_handle handle, int events,
616                                    struct nl_sock *sock)
617 {
618     if (events & POLLERR) {
619         ALOGE("Error reading from socket");
620         internal_pollin_handler(handle, sock);
621     } else if (events & POLLHUP) {
622         ALOGE("Remote side hung up");
623     } else if (events & POLLIN) {
624         //ALOGI("Found some events!!!");
625         internal_pollin_handler(handle, sock);
626     } else {
627         ALOGE("Unknown event - %0x", events);
628     }
629 }
630 
631 /* Run event handler */
wifi_event_loop(wifi_handle handle)632 void wifi_event_loop(wifi_handle handle)
633 {
634     hal_info *info = getHalInfo(handle);
635     if (info->in_event_loop) {
636         return;
637     } else {
638         info->in_event_loop = true;
639     }
640 
641     pollfd pfd[3];
642     memset(&pfd, 0, 3*sizeof(pfd[0]));
643 
644     pfd[0].fd = nl_socket_get_fd(info->event_sock);
645     pfd[0].events = POLLIN;
646 
647     pfd[1].fd = nl_socket_get_fd(info->user_sock);
648     pfd[1].events = POLLIN;
649 
650     pfd[2].fd = info->exit_sockets[1];
651     pfd[2].events = POLLIN;
652 
653     /* TODO: Add support for timeouts */
654 
655     do {
656         int timeout = -1;                   /* Infinite timeout */
657         pfd[0].revents = 0;
658         pfd[1].revents = 0;
659         pfd[2].revents = 0;
660         //ALOGI("Polling sockets");
661         int result = poll(pfd, 3, -1);
662         if (result < 0) {
663             ALOGE("Error polling socket");
664         } else {
665             if (pfd[0].revents & (POLLIN | POLLHUP | POLLERR)) {
666                 internal_event_handler(handle, pfd[0].revents, info->event_sock);
667             }
668             if (pfd[1].revents & (POLLIN | POLLHUP | POLLERR)) {
669                 internal_event_handler(handle, pfd[1].revents, info->user_sock);
670             }
671         }
672         rb_timerhandler(info);
673     } while (!info->clean_up);
674 
675 
676     ALOGI("Cleaning up");
677     internal_cleaned_up_handler(handle);
678 }
679 
user_sock_message_handler(nl_msg * msg,void * arg)680 static int user_sock_message_handler(nl_msg *msg, void *arg)
681 {
682     wifi_handle handle = (wifi_handle)arg;
683     hal_info *info = getHalInfo(handle);
684 
685     diag_message_handler(info, msg);
686 
687     return NL_OK;
688 }
689 
internal_valid_message_handler(nl_msg * msg,void * arg)690 static int internal_valid_message_handler(nl_msg *msg, void *arg)
691 {
692     wifi_handle handle = (wifi_handle)arg;
693     hal_info *info = getHalInfo(handle);
694 
695     WifiEvent event(msg);
696     int res = event.parse();
697     if (res < 0) {
698         ALOGE("Failed to parse event: %d", res);
699         return NL_SKIP;
700     }
701 
702     int cmd = event.get_cmd();
703     uint32_t vendor_id = 0;
704     int subcmd = 0;
705 
706     if (cmd == NL80211_CMD_VENDOR) {
707         vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
708         subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
709         /* Restrict printing GSCAN_FULL_RESULT which is causing lot
710            of logs in bug report */
711         if (subcmd != QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT) {
712             ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
713                   event.get_cmdString(), vendor_id, subcmd);
714         }
715     } else {
716         ALOGV("event received %s", event.get_cmdString());
717     }
718 
719     // event.log();
720 
721     bool dispatched = false;
722 
723     pthread_mutex_lock(&info->cb_lock);
724 
725     for (int i = 0; i < info->num_event_cb; i++) {
726         if (cmd == info->event_cb[i].nl_cmd) {
727             if (cmd == NL80211_CMD_VENDOR
728                 && ((vendor_id != info->event_cb[i].vendor_id)
729                 || (subcmd != info->event_cb[i].vendor_subcmd)))
730             {
731                 /* event for a different vendor, ignore it */
732                 continue;
733             }
734 
735             cb_info *cbi = &(info->event_cb[i]);
736             pthread_mutex_unlock(&info->cb_lock);
737             if (cbi && cbi->cb_func) {
738                 (*(cbi->cb_func))(msg, cbi->cb_arg);
739                 dispatched = true;
740             }
741             return NL_OK;
742         }
743     }
744 
745 #ifdef QC_HAL_DEBUG
746     if (!dispatched) {
747         ALOGI("event ignored!!");
748     }
749 #endif
750 
751     pthread_mutex_unlock(&info->cb_lock);
752     return NL_OK;
753 }
754 
755 ////////////////////////////////////////////////////////////////////////////////
756 
757 class GetMulticastIdCommand : public WifiCommand
758 {
759 private:
760     const char *mName;
761     const char *mGroup;
762     int   mId;
763 public:
GetMulticastIdCommand(wifi_handle handle,const char * name,const char * group)764     GetMulticastIdCommand(wifi_handle handle, const char *name,
765             const char *group) : WifiCommand(handle, 0)
766     {
767         mName = name;
768         mGroup = group;
769         mId = -1;
770     }
771 
getId()772     int getId() {
773         return mId;
774     }
775 
create()776     virtual int create() {
777         int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
778         // ALOGI("ctrl family = %d", nlctrlFamily);
779         int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
780         if (ret < 0) {
781             return ret;
782         }
783         ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
784         return ret;
785     }
786 
handleResponse(WifiEvent & reply)787     virtual int handleResponse(WifiEvent& reply) {
788 
789         // ALOGI("handling reponse in %s", __func__);
790 
791         struct nlattr **tb = reply.attributes();
792         struct genlmsghdr *gnlh = reply.header();
793         struct nlattr *mcgrp = NULL;
794         int i;
795 
796         if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
797             ALOGI("No multicast groups found");
798             return NL_SKIP;
799         } else {
800             // ALOGI("Multicast groups attr size = %d",
801             // nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
802         }
803 
804         for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
805 
806             // ALOGI("Processing group");
807             struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
808             nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
809                 nla_len(mcgrp), NULL);
810             if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID])
811             {
812                 continue;
813             }
814 
815             char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
816             int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
817 
818             // ALOGI("Found group name %s", grpName);
819 
820             if (strncmp(grpName, mGroup, grpNameLen) != 0)
821                 continue;
822 
823             mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
824             break;
825         }
826 
827         return NL_SKIP;
828     }
829 
830 };
831 
wifi_get_multicast_id(wifi_handle handle,const char * name,const char * group)832 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
833         const char *group)
834 {
835     GetMulticastIdCommand cmd(handle, name, group);
836     int res = cmd.requestResponse();
837     if (res < 0)
838         return res;
839     else
840         return cmd.getId();
841 }
842 
843 /////////////////////////////////////////////////////////////////////////
844 
is_wifi_interface(const char * name)845 static bool is_wifi_interface(const char *name)
846 {
847     if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
848         /* not a wifi interface; ignore it */
849         return false;
850     } else {
851         return true;
852     }
853 }
854 
get_interface(const char * name,interface_info * info)855 static int get_interface(const char *name, interface_info *info)
856 {
857     strlcpy(info->name, name, (IFNAMSIZ + 1));
858     info->id = if_nametoindex(name);
859     // ALOGI("found an interface : %s, id = %d", name, info->id);
860     return WIFI_SUCCESS;
861 }
862 
wifi_init_interfaces(wifi_handle handle)863 wifi_error wifi_init_interfaces(wifi_handle handle)
864 {
865     hal_info *info = (hal_info *)handle;
866 
867     struct dirent *de;
868 
869     DIR *d = opendir("/sys/class/net");
870     if (d == 0)
871         return WIFI_ERROR_UNKNOWN;
872 
873     int n = 0;
874     while ((de = readdir(d))) {
875         if (de->d_name[0] == '.')
876             continue;
877         if (is_wifi_interface(de->d_name) ) {
878             n++;
879         }
880     }
881 
882     closedir(d);
883 
884     d = opendir("/sys/class/net");
885     if (d == 0)
886         return WIFI_ERROR_UNKNOWN;
887 
888     info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
889     if (info->interfaces == NULL) {
890         ALOGE("%s: Error info->interfaces NULL", __func__);
891         return WIFI_ERROR_OUT_OF_MEMORY;
892     }
893 
894     int i = 0;
895     while ((de = readdir(d))) {
896         if (de->d_name[0] == '.')
897             continue;
898         if (is_wifi_interface(de->d_name)) {
899             interface_info *ifinfo
900                 = (interface_info *)malloc(sizeof(interface_info));
901             if (ifinfo == NULL) {
902                 ALOGE("%s: Error ifinfo NULL", __func__);
903                 while (i > 0) {
904                     free(info->interfaces[i-1]);
905                     i--;
906                 }
907                 free(info->interfaces);
908                 return WIFI_ERROR_OUT_OF_MEMORY;
909             }
910             if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
911                 free(ifinfo);
912                 continue;
913             }
914             ifinfo->handle = handle;
915             info->interfaces[i] = ifinfo;
916             i++;
917         }
918     }
919 
920     closedir(d);
921 
922     info->num_interfaces = n;
923 
924     return WIFI_SUCCESS;
925 }
926 
wifi_get_ifaces(wifi_handle handle,int * num,wifi_interface_handle ** interfaces)927 wifi_error wifi_get_ifaces(wifi_handle handle, int *num,
928         wifi_interface_handle **interfaces)
929 {
930     hal_info *info = (hal_info *)handle;
931 
932     *interfaces = (wifi_interface_handle *)info->interfaces;
933     *num = info->num_interfaces;
934 
935     return WIFI_SUCCESS;
936 }
937 
wifi_get_iface_name(wifi_interface_handle handle,char * name,size_t size)938 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name,
939         size_t size)
940 {
941     interface_info *info = (interface_info *)handle;
942     strlcpy(name, info->name, size);
943     return WIFI_SUCCESS;
944 }
945 
946 /* Get the supported Feature set */
wifi_get_supported_feature_set(wifi_interface_handle iface,feature_set * set)947 wifi_error wifi_get_supported_feature_set(wifi_interface_handle iface,
948         feature_set *set)
949 {
950     int ret = 0;
951     wifi_handle handle = getWifiHandle(iface);
952     *set = 0;
953     hal_info *info = getHalInfo(handle);
954 
955     ret = acquire_supported_features(iface, set);
956     if (ret != WIFI_SUCCESS) {
957         *set = info->supported_feature_set;
958         ALOGI("Supported feature set acquired at initialization : %x", *set);
959     } else {
960         info->supported_feature_set = *set;
961         ALOGI("Supported feature set acquired : %x", *set);
962     }
963     return WIFI_SUCCESS;
964 }
965 
wifi_get_concurrency_matrix(wifi_interface_handle handle,int set_size_max,feature_set set[],int * set_size)966 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle,
967                                        int set_size_max,
968                                        feature_set set[], int *set_size)
969 {
970     int ret = 0;
971     struct nlattr *nlData;
972     WifihalGeneric *vCommand = NULL;
973     interface_info *ifaceInfo = getIfaceInfo(handle);
974     wifi_handle wifiHandle = getWifiHandle(handle);
975 
976     if (set == NULL) {
977         ALOGE("%s: NULL set pointer provided. Exit.",
978             __func__);
979         return WIFI_ERROR_INVALID_ARGS;
980     }
981 
982     vCommand = new WifihalGeneric(wifiHandle, 0,
983             OUI_QCA,
984             QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX);
985     if (vCommand == NULL) {
986         ALOGE("%s: Error vCommand NULL", __func__);
987         return WIFI_ERROR_OUT_OF_MEMORY;
988     }
989 
990     /* Create the message */
991     ret = vCommand->create();
992     if (ret < 0)
993         goto cleanup;
994 
995     ret = vCommand->set_iface_id(ifaceInfo->name);
996     if (ret < 0)
997         goto cleanup;
998 
999     /* Add the vendor specific attributes for the NL command. */
1000     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1001     if (!nlData)
1002         goto cleanup;
1003 
1004     if (vCommand->put_u32(
1005         QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX,
1006         set_size_max))
1007     {
1008         goto cleanup;
1009     }
1010     vCommand->attr_end(nlData);
1011 
1012     /* Populate the input received from caller/framework. */
1013     vCommand->setMaxSetSize(set_size_max);
1014     vCommand->setSizePtr(set_size);
1015     vCommand->setConcurrencySet(set);
1016 
1017     ret = vCommand->requestResponse();
1018     if (ret) {
1019         ALOGE("%s: requestResponse() error: %d", __func__, ret);
1020     }
1021 
1022 cleanup:
1023     delete vCommand;
1024     if (ret) {
1025         *set_size = 0;
1026     }
1027     return (wifi_error)ret;
1028 }
1029 
1030 
wifi_set_nodfs_flag(wifi_interface_handle handle,u32 nodfs)1031 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
1032 {
1033     int ret = 0;
1034     struct nlattr *nlData;
1035     WifiVendorCommand *vCommand = NULL;
1036     interface_info *ifaceInfo = getIfaceInfo(handle);
1037     wifi_handle wifiHandle = getWifiHandle(handle);
1038 
1039     vCommand = new WifiVendorCommand(wifiHandle, 0,
1040             OUI_QCA,
1041             QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG);
1042     if (vCommand == NULL) {
1043         ALOGE("%s: Error vCommand NULL", __func__);
1044         return WIFI_ERROR_OUT_OF_MEMORY;
1045     }
1046 
1047     /* Create the message */
1048     ret = vCommand->create();
1049     if (ret < 0)
1050         goto cleanup;
1051 
1052     ret = vCommand->set_iface_id(ifaceInfo->name);
1053     if (ret < 0)
1054         goto cleanup;
1055 
1056     /* Add the vendor specific attributes for the NL command. */
1057     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1058     if (!nlData)
1059         goto cleanup;
1060 
1061     /* Add the fixed part of the mac_oui to the nl command */
1062     if (vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG, nodfs)) {
1063         goto cleanup;
1064     }
1065 
1066     vCommand->attr_end(nlData);
1067 
1068     ret = vCommand->requestResponse();
1069     /* Don't check response since we aren't expecting one */
1070 
1071 cleanup:
1072     delete vCommand;
1073     return (wifi_error)ret;
1074 }
1075 
wifi_start_sending_offloaded_packet(wifi_request_id id,wifi_interface_handle iface,u8 * ip_packet,u16 ip_packet_len,u8 * src_mac_addr,u8 * dst_mac_addr,u32 period_msec)1076 wifi_error wifi_start_sending_offloaded_packet(wifi_request_id id,
1077                                                wifi_interface_handle iface,
1078                                                u8 *ip_packet,
1079                                                u16 ip_packet_len,
1080                                                u8 *src_mac_addr,
1081                                                u8 *dst_mac_addr,
1082                                                u32 period_msec)
1083 {
1084     int ret = WIFI_SUCCESS;
1085     struct nlattr *nlData;
1086     WifiVendorCommand *vCommand = NULL;
1087 
1088     ret = initialize_vendor_cmd(iface, id,
1089                                 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
1090                                 &vCommand);
1091     if (ret != WIFI_SUCCESS) {
1092         ALOGE("%s: Initialization failed", __func__);
1093         return (wifi_error)ret;
1094     }
1095 
1096     ALOGI("ip packet length : %u\nIP Packet:", ip_packet_len);
1097     hexdump(ip_packet, ip_packet_len);
1098     ALOGI("Src Mac Address: " MAC_ADDR_STR "\nDst Mac Address: " MAC_ADDR_STR
1099           "\nPeriod in msec : %u", MAC_ADDR_ARRAY(src_mac_addr),
1100           MAC_ADDR_ARRAY(dst_mac_addr), period_msec);
1101 
1102     /* Add the vendor specific attributes for the NL command. */
1103     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1104     if (!nlData)
1105         goto cleanup;
1106 
1107     if (vCommand->put_u32(
1108             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
1109             QCA_WLAN_OFFLOADED_PACKETS_SENDING_START) ||
1110         vCommand->put_u32(
1111             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
1112             id) ||
1113         vCommand->put_bytes(
1114             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET,
1115             (const char *)ip_packet, ip_packet_len) ||
1116         vCommand->put_addr(
1117             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR,
1118             src_mac_addr) ||
1119         vCommand->put_addr(
1120             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR,
1121             dst_mac_addr) ||
1122         vCommand->put_u32(
1123             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD,
1124             period_msec))
1125     {
1126         goto cleanup;
1127     }
1128 
1129     vCommand->attr_end(nlData);
1130 
1131     ret = vCommand->requestResponse();
1132     if (ret < 0)
1133         goto cleanup;
1134 
1135 cleanup:
1136     delete vCommand;
1137     return (wifi_error)ret;
1138 }
1139 
wifi_stop_sending_offloaded_packet(wifi_request_id id,wifi_interface_handle iface)1140 wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id id,
1141                                               wifi_interface_handle iface)
1142 {
1143     int ret = WIFI_SUCCESS;
1144     struct nlattr *nlData;
1145     WifiVendorCommand *vCommand = NULL;
1146 
1147     ret = initialize_vendor_cmd(iface, id,
1148                                 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
1149                                 &vCommand);
1150     if (ret != WIFI_SUCCESS) {
1151         ALOGE("%s: Initialization failed", __func__);
1152         return (wifi_error)ret;
1153     }
1154 
1155     /* Add the vendor specific attributes for the NL command. */
1156     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1157     if (!nlData)
1158         goto cleanup;
1159 
1160     if (vCommand->put_u32(
1161             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
1162             QCA_WLAN_OFFLOADED_PACKETS_SENDING_STOP) ||
1163         vCommand->put_u32(
1164             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
1165             id))
1166     {
1167         goto cleanup;
1168     }
1169 
1170 
1171     vCommand->attr_end(nlData);
1172 
1173     ret = vCommand->requestResponse();
1174     if (ret < 0)
1175         goto cleanup;
1176 
1177 cleanup:
1178     delete vCommand;
1179     return (wifi_error)ret;
1180 }
1181