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