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 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
75 const u8 *program, u32 len);
76 static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
77 u32 *version, u32 *max_len);
78 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
79 u8 enable);
80 wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,
81 WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt);
82
83 /* Initialize/Cleanup */
84
wifi_get_iface_handle(wifi_handle handle,char * name)85 wifi_interface_handle wifi_get_iface_handle(wifi_handle handle, char *name)
86 {
87 hal_info *info = (hal_info *)handle;
88 for (int i=0;i<info->num_interfaces;i++)
89 {
90 if (!strcmp(info->interfaces[i]->name, name))
91 {
92 return ((wifi_interface_handle )(info->interfaces)[i]);
93 }
94 }
95 return NULL;
96 }
97
wifi_socket_set_local_port(struct nl_sock * sock,uint32_t port)98 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
99 {
100 uint32_t pid = getpid() & 0x3FFFFF;
101
102 if (port == 0) {
103 sock->s_flags &= ~NL_OWN_PORT;
104 } else {
105 sock->s_flags |= NL_OWN_PORT;
106 }
107
108 sock->s_local.nl_pid = pid + (port << 22);
109 }
110
wifi_create_nl_socket(int port,int protocol)111 static nl_sock * wifi_create_nl_socket(int port, int protocol)
112 {
113 // ALOGI("Creating socket");
114 struct nl_sock *sock = nl_socket_alloc();
115 if (sock == NULL) {
116 ALOGE("Failed to create NL socket");
117 return NULL;
118 }
119
120 wifi_socket_set_local_port(sock, port);
121
122 struct sockaddr_nl *addr_nl = &(sock->s_local);
123 /* ALOGI("socket address is %d:%d:%d:%d",
124 addr_nl->nl_family, addr_nl->nl_pad, addr_nl->nl_pid,
125 addr_nl->nl_groups); */
126
127 struct sockaddr *addr = NULL;
128 // ALOGI("sizeof(sockaddr) = %d, sizeof(sockaddr_nl) = %d", sizeof(*addr),
129 // sizeof(*addr_nl));
130
131 // ALOGI("Connecting socket");
132 if (nl_connect(sock, protocol)) {
133 ALOGE("Could not connect handle");
134 nl_socket_free(sock);
135 return NULL;
136 }
137
138 return sock;
139 }
140
ack_handler(struct nl_msg * msg,void * arg)141 int ack_handler(struct nl_msg *msg, void *arg)
142 {
143 int *err = (int *)arg;
144 *err = 0;
145 return NL_STOP;
146 }
147
finish_handler(struct nl_msg * msg,void * arg)148 int finish_handler(struct nl_msg *msg, void *arg)
149 {
150 int *ret = (int *)arg;
151 *ret = 0;
152 return NL_SKIP;
153 }
154
error_handler(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)155 int error_handler(struct sockaddr_nl *nla,
156 struct nlmsgerr *err, void *arg)
157 {
158 int *ret = (int *)arg;
159 *ret = err->error;
160
161 ALOGV("%s invoked with error: %d", __func__, err->error);
162 return NL_SKIP;
163 }
no_seq_check(struct nl_msg * msg,void * arg)164 static int no_seq_check(struct nl_msg *msg, void *arg)
165 {
166 return NL_OK;
167 }
168
acquire_supported_features(wifi_interface_handle iface,feature_set * set)169 static wifi_error acquire_supported_features(wifi_interface_handle iface,
170 feature_set *set)
171 {
172 int ret = 0;
173 interface_info *iinfo = getIfaceInfo(iface);
174 wifi_handle handle = getWifiHandle(iface);
175 *set = 0;
176
177 WifihalGeneric supportedFeatures(handle, 0,
178 OUI_QCA,
179 QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES);
180
181 /* create the message */
182 ret = supportedFeatures.create();
183 if (ret < 0)
184 goto cleanup;
185
186 ret = supportedFeatures.set_iface_id(iinfo->name);
187 if (ret < 0)
188 goto cleanup;
189
190 ret = supportedFeatures.requestResponse();
191 if (ret != 0) {
192 ALOGE("%s: requestResponse Error:%d",__func__, ret);
193 goto cleanup;
194 }
195
196 supportedFeatures.getResponseparams(set);
197
198 cleanup:
199 return (wifi_error)ret;
200 }
201
get_firmware_bus_max_size_supported(wifi_interface_handle iface)202 static wifi_error get_firmware_bus_max_size_supported(
203 wifi_interface_handle iface)
204 {
205 int ret = 0;
206 interface_info *iinfo = getIfaceInfo(iface);
207 wifi_handle handle = getWifiHandle(iface);
208 hal_info *info = (hal_info *)handle;
209
210 WifihalGeneric busSizeSupported(handle, 0,
211 OUI_QCA,
212 QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE);
213
214 /* create the message */
215 ret = busSizeSupported.create();
216 if (ret < 0)
217 goto cleanup;
218
219 ret = busSizeSupported.set_iface_id(iinfo->name);
220 if (ret < 0)
221 goto cleanup;
222
223 ret = busSizeSupported.requestResponse();
224 if (ret != 0) {
225 ALOGE("%s: requestResponse Error:%d", __FUNCTION__, ret);
226 goto cleanup;
227 }
228 info->firmware_bus_max_size = busSizeSupported.getBusSize();
229
230 cleanup:
231 return (wifi_error)ret;
232 }
233
wifi_init_user_sock(hal_info * info)234 static wifi_error wifi_init_user_sock(hal_info *info)
235 {
236 struct nl_sock *user_sock =
237 wifi_create_nl_socket(WIFI_HAL_USER_SOCK_PORT, NETLINK_USERSOCK);
238 if (user_sock == NULL) {
239 ALOGE("Could not create diag sock");
240 return WIFI_ERROR_UNKNOWN;
241 }
242
243 /* Set the socket buffer size */
244 if (nl_socket_set_buffer_size(user_sock, (256*1024), 0) < 0) {
245 ALOGE("Could not set size for user_sock: %s",
246 strerror(errno));
247 /* continue anyway with the default (smaller) buffer */
248 }
249 else {
250 ALOGV("nl_socket_set_buffer_size successful for user_sock");
251 }
252
253 struct nl_cb *cb = nl_socket_get_cb(user_sock);
254 if (cb == NULL) {
255 ALOGE("Could not get cb");
256 return WIFI_ERROR_UNKNOWN;
257 }
258
259 info->user_sock_arg = 1;
260 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
261 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg);
262 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg);
263 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg);
264
265 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info);
266 nl_cb_put(cb);
267
268 int ret = nl_socket_add_membership(user_sock, 1);
269 if (ret < 0) {
270 ALOGE("Could not add membership");
271 return WIFI_ERROR_UNKNOWN;
272 }
273
274 info->user_sock = user_sock;
275 ALOGV("Initiialized diag sock successfully");
276 return WIFI_SUCCESS;
277 }
278
279 /*initialize function pointer table with Qualcomm HAL API*/
init_wifi_vendor_hal_func_table(wifi_hal_fn * fn)280 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) {
281 if (fn == NULL) {
282 return WIFI_ERROR_UNKNOWN;
283 }
284
285 fn->wifi_initialize = wifi_initialize;
286 fn->wifi_cleanup = wifi_cleanup;
287 fn->wifi_event_loop = wifi_event_loop;
288 fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
289 fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
290 fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui;
291 fn->wifi_get_ifaces = wifi_get_ifaces;
292 fn->wifi_get_iface_name = wifi_get_iface_name;
293 fn->wifi_set_iface_event_handler = wifi_set_iface_event_handler;
294 fn->wifi_reset_iface_event_handler = wifi_reset_iface_event_handler;
295 fn->wifi_start_gscan = wifi_start_gscan;
296 fn->wifi_stop_gscan = wifi_stop_gscan;
297 fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
298 fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
299 fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
300 fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
301 fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
302 fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
303 fn->wifi_set_link_stats = wifi_set_link_stats;
304 fn->wifi_get_link_stats = wifi_get_link_stats;
305 fn->wifi_clear_link_stats = wifi_clear_link_stats;
306 fn->wifi_get_valid_channels = wifi_get_valid_channels;
307 fn->wifi_rtt_range_request = wifi_rtt_range_request;
308 fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
309 fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
310 fn->wifi_rtt_get_responder_info = wifi_rtt_get_responder_info;
311 fn->wifi_enable_responder = wifi_enable_responder;
312 fn->wifi_disable_responder = wifi_disable_responder;
313 fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
314 fn->wifi_start_logging = wifi_start_logging;
315 fn->wifi_set_epno_list = wifi_set_epno_list;
316 fn->wifi_reset_epno_list = wifi_reset_epno_list;
317 fn->wifi_set_country_code = wifi_set_country_code;
318 fn->wifi_enable_tdls = wifi_enable_tdls;
319 fn->wifi_disable_tdls = wifi_disable_tdls;
320 fn->wifi_get_tdls_status = wifi_get_tdls_status;
321 fn->wifi_get_tdls_capabilities = wifi_get_tdls_capabilities;
322 fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
323 fn->wifi_set_log_handler = wifi_set_log_handler;
324 fn->wifi_reset_log_handler = wifi_reset_log_handler;
325 fn->wifi_set_alert_handler = wifi_set_alert_handler;
326 fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
327 fn->wifi_get_firmware_version = wifi_get_firmware_version;
328 fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
329 fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;
330 fn->wifi_get_ring_data = wifi_get_ring_data;
331 fn->wifi_get_driver_version = wifi_get_driver_version;
332 fn->wifi_set_passpoint_list = wifi_set_passpoint_list;
333 fn->wifi_reset_passpoint_list = wifi_reset_passpoint_list;
334 fn->wifi_set_bssid_blacklist = wifi_set_bssid_blacklist;
335 fn->wifi_set_lci = wifi_set_lci;
336 fn->wifi_set_lcr = wifi_set_lcr;
337 fn->wifi_start_sending_offloaded_packet =
338 wifi_start_sending_offloaded_packet;
339 fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
340 fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
341 fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
342 fn->wifi_nan_enable_request = nan_enable_request;
343 fn->wifi_nan_disable_request = nan_disable_request;
344 fn->wifi_nan_publish_request = nan_publish_request;
345 fn->wifi_nan_publish_cancel_request = nan_publish_cancel_request;
346 fn->wifi_nan_subscribe_request = nan_subscribe_request;
347 fn->wifi_nan_subscribe_cancel_request = nan_subscribe_cancel_request;
348 fn->wifi_nan_transmit_followup_request = nan_transmit_followup_request;
349 fn->wifi_nan_stats_request = nan_stats_request;
350 fn->wifi_nan_config_request = nan_config_request;
351 fn->wifi_nan_tca_request = nan_tca_request;
352 fn->wifi_nan_beacon_sdf_payload_request = nan_beacon_sdf_payload_request;
353 fn->wifi_nan_register_handler = nan_register_handler;
354 fn->wifi_nan_get_version = nan_get_version;
355 fn->wifi_set_packet_filter = wifi_set_packet_filter;
356 fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
357 fn->wifi_nan_get_capabilities = nan_get_capabilities;
358 fn->wifi_configure_nd_offload = wifi_configure_nd_offload;
359 fn->wifi_get_driver_memory_dump = wifi_get_driver_memory_dump;
360 fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats;
361 fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring;
362 fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;
363 fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;
364
365 return WIFI_SUCCESS;
366 }
367
wifi_initialize(wifi_handle * handle)368 wifi_error wifi_initialize(wifi_handle *handle)
369 {
370 int err = 0;
371 bool driver_loaded = false;
372 wifi_error ret = WIFI_SUCCESS;
373 wifi_interface_handle iface_handle;
374 struct nl_sock *cmd_sock = NULL;
375 struct nl_sock *event_sock = NULL;
376 struct nl_cb *cb = NULL;
377
378 ALOGI("Initializing wifi");
379 hal_info *info = (hal_info *)malloc(sizeof(hal_info));
380 if (info == NULL) {
381 ALOGE("Could not allocate hal_info");
382 return WIFI_ERROR_OUT_OF_MEMORY;
383 }
384
385 memset(info, 0, sizeof(*info));
386
387 cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT,
388 NETLINK_GENERIC);
389 if (cmd_sock == NULL) {
390 ALOGE("Failed to create command socket port");
391 ret = WIFI_ERROR_UNKNOWN;
392 goto unload;
393 }
394
395 /* Set the socket buffer size */
396 if (nl_socket_set_buffer_size(cmd_sock, (256*1024), 0) < 0) {
397 ALOGE("Could not set nl_socket RX buffer size for cmd_sock: %s",
398 strerror(errno));
399 /* continue anyway with the default (smaller) buffer */
400 }
401
402 event_sock =
403 wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT, NETLINK_GENERIC);
404 if (event_sock == NULL) {
405 ALOGE("Failed to create event socket port");
406 ret = WIFI_ERROR_UNKNOWN;
407 goto unload;
408 }
409
410 /* Set the socket buffer size */
411 if (nl_socket_set_buffer_size(event_sock, (256*1024), 0) < 0) {
412 ALOGE("Could not set nl_socket RX buffer size for event_sock: %s",
413 strerror(errno));
414 /* continue anyway with the default (smaller) buffer */
415 }
416
417 cb = nl_socket_get_cb(event_sock);
418 if (cb == NULL) {
419 ALOGE("Failed to get NL control block for event socket port");
420 ret = WIFI_ERROR_UNKNOWN;
421 goto unload;
422 }
423
424 err = 1;
425 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
426 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
427 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
428 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
429
430 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler,
431 info);
432 nl_cb_put(cb);
433
434 info->cmd_sock = cmd_sock;
435 info->event_sock = event_sock;
436 info->clean_up = false;
437 info->in_event_loop = false;
438
439 info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
440 if (info->event_cb == NULL) {
441 ALOGE("Could not allocate event_cb");
442 ret = WIFI_ERROR_OUT_OF_MEMORY;
443 goto unload;
444 }
445 info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
446 info->num_event_cb = 0;
447
448 info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
449 if (info->cmd == NULL) {
450 ALOGE("Could not allocate cmd info");
451 ret = WIFI_ERROR_OUT_OF_MEMORY;
452 goto unload;
453 }
454 info->alloc_cmd = DEFAULT_CMD_SIZE;
455 info->num_cmd = 0;
456
457 info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
458 if (info->nl80211_family_id < 0) {
459 ALOGE("Could not resolve nl80211 familty id");
460 ret = WIFI_ERROR_UNKNOWN;
461 goto unload;
462 }
463
464 pthread_mutex_init(&info->cb_lock, NULL);
465 pthread_mutex_init(&info->pkt_fate_stats_lock, NULL);
466
467 *handle = (wifi_handle) info;
468
469 wifi_add_membership(*handle, "scan");
470 wifi_add_membership(*handle, "mlme");
471 wifi_add_membership(*handle, "regulatory");
472 wifi_add_membership(*handle, "vendor");
473
474 ret = wifi_init_user_sock(info);
475 if (ret != WIFI_SUCCESS) {
476 ALOGE("Failed to alloc user socket");
477 goto unload;
478 }
479
480 if (!is_wifi_driver_loaded()) {
481 ret = (wifi_error)wifi_load_driver();
482 if(ret != WIFI_SUCCESS) {
483 ALOGE("%s Failed to load wifi driver : %d\n", __func__, ret);
484 goto unload;
485 }
486 driver_loaded = true;
487 }
488
489 ret = wifi_init_interfaces(*handle);
490 if (ret != WIFI_SUCCESS) {
491 ALOGE("Failed to init interfaces");
492 goto unload;
493 }
494
495 if (info->num_interfaces == 0) {
496 ALOGE("No interfaces found");
497 ret = WIFI_ERROR_UNINITIALIZED;
498 goto unload;
499 }
500
501 iface_handle = wifi_get_iface_handle((info->interfaces[0])->handle,
502 (info->interfaces[0])->name);
503 if (iface_handle == NULL) {
504 int i;
505 for (i = 0; i < info->num_interfaces; i++)
506 {
507 free(info->interfaces[i]);
508 }
509 ALOGE("%s no iface with %s\n", __func__, info->interfaces[0]->name);
510 goto unload;
511 }
512
513 ret = acquire_supported_features(iface_handle,
514 &info->supported_feature_set);
515 if (ret != WIFI_SUCCESS) {
516 ALOGI("Failed to get supported feature set : %d", ret);
517 //acquire_supported_features failure is acceptable condition as legacy
518 //drivers might not support the required vendor command. So, do not
519 //consider it as failure of wifi_initialize
520 ret = WIFI_SUCCESS;
521 }
522
523 ret = get_firmware_bus_max_size_supported(iface_handle);
524 if (ret != WIFI_SUCCESS) {
525 ALOGE("Failed to get supported bus size, error : %d", ret);
526 info->firmware_bus_max_size = 1520;
527 }
528
529 ret = wifi_logger_ring_buffers_init(info);
530 if (ret != WIFI_SUCCESS) {
531 ALOGE("Wifi Logger Ring Initialization Failed");
532 goto unload;
533 }
534
535 info->pkt_stats = (struct pkt_stats_s *)malloc(sizeof(struct pkt_stats_s));
536 if (!info->pkt_stats) {
537 ALOGE("%s: malloc Failed for size: %zu",
538 __FUNCTION__, sizeof(struct pkt_stats_s));
539 ret = WIFI_ERROR_OUT_OF_MEMORY;
540 goto unload;
541 }
542
543 info->rx_buf_size_allocated = MAX_RXMPDUS_PER_AMPDU * MAX_MSDUS_PER_MPDU
544 * PKT_STATS_BUF_SIZE;
545
546 info->rx_aggr_pkts =
547 (wifi_ring_buffer_entry *)malloc(info->rx_buf_size_allocated);
548 if (!info->rx_aggr_pkts) {
549 ALOGE("%s: malloc Failed for size: %d",
550 __FUNCTION__, info->rx_buf_size_allocated);
551 ret = WIFI_ERROR_OUT_OF_MEMORY;
552 info->rx_buf_size_allocated = 0;
553 goto unload;
554 }
555 memset(info->rx_aggr_pkts, 0, info->rx_buf_size_allocated);
556
557 info->exit_sockets[0] = -1;
558 info->exit_sockets[1] = -1;
559
560 if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->exit_sockets) == -1) {
561 ALOGE("Failed to create exit socket pair");
562 ret = WIFI_ERROR_UNKNOWN;
563 goto unload;
564 }
565
566 ALOGV("Initializing Gscan Event Handlers");
567 ret = initializeGscanHandlers(info);
568 if (ret != WIFI_SUCCESS) {
569 ALOGE("Initializing Gscan Event Handlers Failed");
570 goto unload;
571 }
572
573 ALOGV("Initialized Wifi HAL Successfully; vendor cmd = %d Supported"
574 " features : %x", NL80211_CMD_VENDOR, info->supported_feature_set);
575
576 unload:
577 if (ret != WIFI_SUCCESS) {
578 if (cmd_sock)
579 nl_socket_free(cmd_sock);
580 if (event_sock)
581 nl_socket_free(event_sock);
582 if (info) {
583 if (info->cmd) free(info->cmd);
584 if (info->event_cb) free(info->event_cb);
585 if (info->user_sock) nl_socket_free(info->user_sock);
586 if (info->pkt_stats) free(info->pkt_stats);
587 if (info->rx_aggr_pkts) free(info->rx_aggr_pkts);
588 cleanupGscanHandlers(info);
589 free(info);
590 }
591 }
592
593 if (driver_loaded)
594 wifi_unload_driver();
595 return ret;
596 }
597
wifi_add_membership(wifi_handle handle,const char * group)598 static int wifi_add_membership(wifi_handle handle, const char *group)
599 {
600 hal_info *info = getHalInfo(handle);
601
602 int id = wifi_get_multicast_id(handle, "nl80211", group);
603 if (id < 0) {
604 ALOGE("Could not find group %s", group);
605 return id;
606 }
607
608 int ret = nl_socket_add_membership(info->event_sock, id);
609 if (ret < 0) {
610 ALOGE("Could not add membership to group %s", group);
611 }
612
613 return ret;
614 }
615
internal_cleaned_up_handler(wifi_handle handle)616 static void internal_cleaned_up_handler(wifi_handle handle)
617 {
618 hal_info *info = getHalInfo(handle);
619 wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
620
621 if (info->cmd_sock != 0) {
622 nl_socket_free(info->cmd_sock);
623 nl_socket_free(info->event_sock);
624 info->cmd_sock = NULL;
625 info->event_sock = NULL;
626 }
627
628 if (info->user_sock != 0) {
629 nl_socket_free(info->user_sock);
630 info->user_sock = NULL;
631 }
632
633 if (info->pkt_stats)
634 free(info->pkt_stats);
635 if (info->rx_aggr_pkts)
636 free(info->rx_aggr_pkts);
637 wifi_logger_ring_buffers_deinit(info);
638 cleanupGscanHandlers(info);
639
640 if (info->exit_sockets[0] >= 0) {
641 close(info->exit_sockets[0]);
642 info->exit_sockets[0] = -1;
643 }
644
645 if (info->exit_sockets[1] >= 0) {
646 close(info->exit_sockets[1]);
647 info->exit_sockets[1] = -1;
648 }
649
650 if (info->pkt_fate_stats) {
651 free(info->pkt_fate_stats);
652 info->pkt_fate_stats = NULL;
653 }
654
655 (*cleaned_up_handler)(handle);
656 pthread_mutex_destroy(&info->cb_lock);
657 pthread_mutex_destroy(&info->pkt_fate_stats_lock);
658 free(info);
659 }
660
wifi_cleanup(wifi_handle handle,wifi_cleaned_up_handler handler)661 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
662 {
663 if (!handle) {
664 ALOGE("Handle is null");
665 return;
666 }
667
668 hal_info *info = getHalInfo(handle);
669 info->cleaned_up_handler = handler;
670 info->clean_up = true;
671
672 TEMP_FAILURE_RETRY(write(info->exit_sockets[0], "E", 1));
673 ALOGI("Sent msg on exit sock to unblock poll()");
674 }
675
internal_pollin_handler(wifi_handle handle,struct nl_sock * sock)676 static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock)
677 {
678 struct nl_cb *cb = nl_socket_get_cb(sock);
679
680 int res = nl_recvmsgs(sock, cb);
681 if(res)
682 ALOGE("Error :%d while reading nl msg", res);
683 nl_cb_put(cb);
684 return res;
685 }
686
internal_event_handler(wifi_handle handle,int events,struct nl_sock * sock)687 static void internal_event_handler(wifi_handle handle, int events,
688 struct nl_sock *sock)
689 {
690 if (events & POLLERR) {
691 ALOGE("Error reading from socket");
692 internal_pollin_handler(handle, sock);
693 } else if (events & POLLHUP) {
694 ALOGE("Remote side hung up");
695 } else if (events & POLLIN) {
696 //ALOGI("Found some events!!!");
697 internal_pollin_handler(handle, sock);
698 } else {
699 ALOGE("Unknown event - %0x", events);
700 }
701 }
702
703 /* Run event handler */
wifi_event_loop(wifi_handle handle)704 void wifi_event_loop(wifi_handle handle)
705 {
706 hal_info *info = getHalInfo(handle);
707 if (info->in_event_loop) {
708 return;
709 } else {
710 info->in_event_loop = true;
711 }
712
713 pollfd pfd[3];
714 memset(&pfd, 0, 3*sizeof(pfd[0]));
715
716 pfd[0].fd = nl_socket_get_fd(info->event_sock);
717 pfd[0].events = POLLIN;
718
719 pfd[1].fd = nl_socket_get_fd(info->user_sock);
720 pfd[1].events = POLLIN;
721
722 pfd[2].fd = info->exit_sockets[1];
723 pfd[2].events = POLLIN;
724
725 /* TODO: Add support for timeouts */
726
727 do {
728 int timeout = -1; /* Infinite timeout */
729 pfd[0].revents = 0;
730 pfd[1].revents = 0;
731 pfd[2].revents = 0;
732 //ALOGI("Polling sockets");
733 int result = poll(pfd, 3, -1);
734 if (result < 0) {
735 ALOGE("Error polling socket");
736 } else {
737 if (pfd[0].revents & (POLLIN | POLLHUP | POLLERR)) {
738 internal_event_handler(handle, pfd[0].revents, info->event_sock);
739 }
740 if (pfd[1].revents & (POLLIN | POLLHUP | POLLERR)) {
741 internal_event_handler(handle, pfd[1].revents, info->user_sock);
742 }
743 }
744 rb_timerhandler(info);
745 } while (!info->clean_up);
746 internal_cleaned_up_handler(handle);
747 }
748
user_sock_message_handler(nl_msg * msg,void * arg)749 static int user_sock_message_handler(nl_msg *msg, void *arg)
750 {
751 wifi_handle handle = (wifi_handle)arg;
752 hal_info *info = getHalInfo(handle);
753
754 diag_message_handler(info, msg);
755
756 return NL_OK;
757 }
758
internal_valid_message_handler(nl_msg * msg,void * arg)759 static int internal_valid_message_handler(nl_msg *msg, void *arg)
760 {
761 wifi_handle handle = (wifi_handle)arg;
762 hal_info *info = getHalInfo(handle);
763
764 WifiEvent event(msg);
765 int res = event.parse();
766 if (res < 0) {
767 ALOGE("Failed to parse event: %d", res);
768 return NL_SKIP;
769 }
770
771 int cmd = event.get_cmd();
772 uint32_t vendor_id = 0;
773 int subcmd = 0;
774
775 if (cmd == NL80211_CMD_VENDOR) {
776 vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
777 subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
778 /* Restrict printing GSCAN_FULL_RESULT which is causing lot
779 of logs in bug report */
780 if (subcmd != QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT) {
781 ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
782 event.get_cmdString(), vendor_id, subcmd);
783 }
784 } else {
785 ALOGV("event received %s", event.get_cmdString());
786 }
787
788 // event.log();
789
790 bool dispatched = false;
791
792 pthread_mutex_lock(&info->cb_lock);
793
794 for (int i = 0; i < info->num_event_cb; i++) {
795 if (cmd == info->event_cb[i].nl_cmd) {
796 if (cmd == NL80211_CMD_VENDOR
797 && ((vendor_id != info->event_cb[i].vendor_id)
798 || (subcmd != info->event_cb[i].vendor_subcmd)))
799 {
800 /* event for a different vendor, ignore it */
801 continue;
802 }
803
804 cb_info *cbi = &(info->event_cb[i]);
805 pthread_mutex_unlock(&info->cb_lock);
806 if (cbi->cb_func) {
807 (*(cbi->cb_func))(msg, cbi->cb_arg);
808 dispatched = true;
809 }
810 return NL_OK;
811 }
812 }
813
814 #ifdef QC_HAL_DEBUG
815 if (!dispatched) {
816 ALOGI("event ignored!!");
817 }
818 #endif
819
820 pthread_mutex_unlock(&info->cb_lock);
821 return NL_OK;
822 }
823
824 ////////////////////////////////////////////////////////////////////////////////
825
826 class GetMulticastIdCommand : public WifiCommand
827 {
828 private:
829 const char *mName;
830 const char *mGroup;
831 int mId;
832 public:
GetMulticastIdCommand(wifi_handle handle,const char * name,const char * group)833 GetMulticastIdCommand(wifi_handle handle, const char *name,
834 const char *group) : WifiCommand(handle, 0)
835 {
836 mName = name;
837 mGroup = group;
838 mId = -1;
839 }
840
getId()841 int getId() {
842 return mId;
843 }
844
create()845 virtual int create() {
846 int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
847 // ALOGI("ctrl family = %d", nlctrlFamily);
848 int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
849 if (ret < 0) {
850 return ret;
851 }
852 ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
853 return ret;
854 }
855
handleResponse(WifiEvent & reply)856 virtual int handleResponse(WifiEvent& reply) {
857
858 // ALOGI("handling reponse in %s", __func__);
859
860 struct nlattr **tb = reply.attributes();
861 struct genlmsghdr *gnlh = reply.header();
862 struct nlattr *mcgrp = NULL;
863 int i;
864
865 if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
866 ALOGI("No multicast groups found");
867 return NL_SKIP;
868 } else {
869 // ALOGI("Multicast groups attr size = %d",
870 // nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
871 }
872
873 for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
874
875 // ALOGI("Processing group");
876 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
877 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
878 nla_len(mcgrp), NULL);
879 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID])
880 {
881 continue;
882 }
883
884 char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
885 int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
886
887 // ALOGI("Found group name %s", grpName);
888
889 if (strncmp(grpName, mGroup, grpNameLen) != 0)
890 continue;
891
892 mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
893 break;
894 }
895
896 return NL_SKIP;
897 }
898
899 };
900
wifi_get_multicast_id(wifi_handle handle,const char * name,const char * group)901 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
902 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 strlcpy(info->name, name, (IFNAMSIZ + 1));
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 if (info->interfaces == NULL) {
959 ALOGE("%s: Error info->interfaces NULL", __func__);
960 return WIFI_ERROR_OUT_OF_MEMORY;
961 }
962
963 int i = 0;
964 while ((de = readdir(d))) {
965 if (de->d_name[0] == '.')
966 continue;
967 if (is_wifi_interface(de->d_name)) {
968 interface_info *ifinfo
969 = (interface_info *)malloc(sizeof(interface_info));
970 if (ifinfo == NULL) {
971 ALOGE("%s: Error ifinfo NULL", __func__);
972 while (i > 0) {
973 free(info->interfaces[i-1]);
974 i--;
975 }
976 free(info->interfaces);
977 return WIFI_ERROR_OUT_OF_MEMORY;
978 }
979 if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
980 free(ifinfo);
981 continue;
982 }
983 ifinfo->handle = handle;
984 info->interfaces[i] = ifinfo;
985 i++;
986 }
987 }
988
989 closedir(d);
990
991 info->num_interfaces = n;
992
993 return WIFI_SUCCESS;
994 }
995
wifi_get_ifaces(wifi_handle handle,int * num,wifi_interface_handle ** interfaces)996 wifi_error wifi_get_ifaces(wifi_handle handle, int *num,
997 wifi_interface_handle **interfaces)
998 {
999 hal_info *info = (hal_info *)handle;
1000
1001 *interfaces = (wifi_interface_handle *)info->interfaces;
1002 *num = info->num_interfaces;
1003
1004 return WIFI_SUCCESS;
1005 }
1006
wifi_get_iface_name(wifi_interface_handle handle,char * name,size_t size)1007 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name,
1008 size_t size)
1009 {
1010 interface_info *info = (interface_info *)handle;
1011 strlcpy(name, info->name, size);
1012 return WIFI_SUCCESS;
1013 }
1014
1015 /* Get the supported Feature set */
wifi_get_supported_feature_set(wifi_interface_handle iface,feature_set * set)1016 wifi_error wifi_get_supported_feature_set(wifi_interface_handle iface,
1017 feature_set *set)
1018 {
1019 int ret = 0;
1020 wifi_handle handle = getWifiHandle(iface);
1021 *set = 0;
1022 hal_info *info = getHalInfo(handle);
1023
1024 ret = acquire_supported_features(iface, set);
1025 if (ret != WIFI_SUCCESS) {
1026 *set = info->supported_feature_set;
1027 ALOGV("Supported feature set acquired at initialization : %x", *set);
1028 } else {
1029 info->supported_feature_set = *set;
1030 ALOGV("Supported feature set acquired : %x", *set);
1031 }
1032 return WIFI_SUCCESS;
1033 }
1034
wifi_get_concurrency_matrix(wifi_interface_handle handle,int set_size_max,feature_set set[],int * set_size)1035 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle,
1036 int set_size_max,
1037 feature_set set[], int *set_size)
1038 {
1039 int ret = 0;
1040 struct nlattr *nlData;
1041 WifihalGeneric *vCommand = NULL;
1042 interface_info *ifaceInfo = getIfaceInfo(handle);
1043 wifi_handle wifiHandle = getWifiHandle(handle);
1044
1045 if (set == NULL) {
1046 ALOGE("%s: NULL set pointer provided. Exit.",
1047 __func__);
1048 return WIFI_ERROR_INVALID_ARGS;
1049 }
1050
1051 vCommand = new WifihalGeneric(wifiHandle, 0,
1052 OUI_QCA,
1053 QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX);
1054 if (vCommand == NULL) {
1055 ALOGE("%s: Error vCommand NULL", __func__);
1056 return WIFI_ERROR_OUT_OF_MEMORY;
1057 }
1058
1059 /* Create the message */
1060 ret = vCommand->create();
1061 if (ret < 0)
1062 goto cleanup;
1063
1064 ret = vCommand->set_iface_id(ifaceInfo->name);
1065 if (ret < 0)
1066 goto cleanup;
1067
1068 /* Add the vendor specific attributes for the NL command. */
1069 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1070 if (!nlData)
1071 goto cleanup;
1072
1073 if (vCommand->put_u32(
1074 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX,
1075 set_size_max))
1076 {
1077 goto cleanup;
1078 }
1079 vCommand->attr_end(nlData);
1080
1081 /* Populate the input received from caller/framework. */
1082 vCommand->setMaxSetSize(set_size_max);
1083 vCommand->setSizePtr(set_size);
1084 vCommand->setConcurrencySet(set);
1085
1086 ret = vCommand->requestResponse();
1087 if (ret) {
1088 ALOGE("%s: requestResponse() error: %d", __func__, ret);
1089 }
1090
1091 cleanup:
1092 delete vCommand;
1093 if (ret) {
1094 *set_size = 0;
1095 }
1096 return (wifi_error)ret;
1097 }
1098
1099
wifi_set_nodfs_flag(wifi_interface_handle handle,u32 nodfs)1100 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
1101 {
1102 int ret = 0;
1103 struct nlattr *nlData;
1104 WifiVendorCommand *vCommand = NULL;
1105 interface_info *ifaceInfo = getIfaceInfo(handle);
1106 wifi_handle wifiHandle = getWifiHandle(handle);
1107
1108 vCommand = new WifiVendorCommand(wifiHandle, 0,
1109 OUI_QCA,
1110 QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG);
1111 if (vCommand == NULL) {
1112 ALOGE("%s: Error vCommand NULL", __func__);
1113 return WIFI_ERROR_OUT_OF_MEMORY;
1114 }
1115
1116 /* Create the message */
1117 ret = vCommand->create();
1118 if (ret < 0)
1119 goto cleanup;
1120
1121 ret = vCommand->set_iface_id(ifaceInfo->name);
1122 if (ret < 0)
1123 goto cleanup;
1124
1125 /* Add the vendor specific attributes for the NL command. */
1126 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1127 if (!nlData)
1128 goto cleanup;
1129
1130 /* Add the fixed part of the mac_oui to the nl command */
1131 if (vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG, nodfs)) {
1132 goto cleanup;
1133 }
1134
1135 vCommand->attr_end(nlData);
1136
1137 ret = vCommand->requestResponse();
1138 /* Don't check response since we aren't expecting one */
1139
1140 cleanup:
1141 delete vCommand;
1142 return (wifi_error)ret;
1143 }
1144
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)1145 wifi_error wifi_start_sending_offloaded_packet(wifi_request_id id,
1146 wifi_interface_handle iface,
1147 u8 *ip_packet,
1148 u16 ip_packet_len,
1149 u8 *src_mac_addr,
1150 u8 *dst_mac_addr,
1151 u32 period_msec)
1152 {
1153 int ret = WIFI_SUCCESS;
1154 struct nlattr *nlData;
1155 WifiVendorCommand *vCommand = NULL;
1156
1157 ret = initialize_vendor_cmd(iface, id,
1158 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
1159 &vCommand);
1160 if (ret != WIFI_SUCCESS) {
1161 ALOGE("%s: Initialization failed", __func__);
1162 return (wifi_error)ret;
1163 }
1164
1165 ALOGV("ip packet length : %u\nIP Packet:", ip_packet_len);
1166 hexdump(ip_packet, ip_packet_len);
1167 ALOGV("Src Mac Address: " MAC_ADDR_STR "\nDst Mac Address: " MAC_ADDR_STR
1168 "\nPeriod in msec : %u", MAC_ADDR_ARRAY(src_mac_addr),
1169 MAC_ADDR_ARRAY(dst_mac_addr), period_msec);
1170
1171 /* Add the vendor specific attributes for the NL command. */
1172 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1173 if (!nlData)
1174 goto cleanup;
1175
1176 if (vCommand->put_u32(
1177 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
1178 QCA_WLAN_OFFLOADED_PACKETS_SENDING_START) ||
1179 vCommand->put_u32(
1180 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
1181 id) ||
1182 vCommand->put_bytes(
1183 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET,
1184 (const char *)ip_packet, ip_packet_len) ||
1185 vCommand->put_addr(
1186 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR,
1187 src_mac_addr) ||
1188 vCommand->put_addr(
1189 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR,
1190 dst_mac_addr) ||
1191 vCommand->put_u32(
1192 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD,
1193 period_msec))
1194 {
1195 goto cleanup;
1196 }
1197
1198 vCommand->attr_end(nlData);
1199
1200 ret = vCommand->requestResponse();
1201 if (ret < 0)
1202 goto cleanup;
1203
1204 cleanup:
1205 delete vCommand;
1206 return (wifi_error)ret;
1207 }
1208
wifi_stop_sending_offloaded_packet(wifi_request_id id,wifi_interface_handle iface)1209 wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id id,
1210 wifi_interface_handle iface)
1211 {
1212 int ret = WIFI_SUCCESS;
1213 struct nlattr *nlData;
1214 WifiVendorCommand *vCommand = NULL;
1215
1216 ret = initialize_vendor_cmd(iface, id,
1217 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
1218 &vCommand);
1219 if (ret != WIFI_SUCCESS) {
1220 ALOGE("%s: Initialization failed", __func__);
1221 return (wifi_error)ret;
1222 }
1223
1224 /* Add the vendor specific attributes for the NL command. */
1225 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1226 if (!nlData)
1227 goto cleanup;
1228
1229 if (vCommand->put_u32(
1230 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
1231 QCA_WLAN_OFFLOADED_PACKETS_SENDING_STOP) ||
1232 vCommand->put_u32(
1233 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
1234 id))
1235 {
1236 goto cleanup;
1237 }
1238
1239
1240 vCommand->attr_end(nlData);
1241
1242 ret = vCommand->requestResponse();
1243 if (ret < 0)
1244 goto cleanup;
1245
1246 cleanup:
1247 delete vCommand;
1248 return (wifi_error)ret;
1249 }
1250
wifi_set_packet_filter(wifi_interface_handle iface,const u8 * program,u32 len)1251 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
1252 const u8 *program, u32 len)
1253 {
1254 int ret = WIFI_SUCCESS;
1255 struct nlattr *nlData;
1256 WifiVendorCommand *vCommand = NULL;
1257 u32 current_offset = 0;
1258 wifi_handle wifiHandle = getWifiHandle(iface);
1259 hal_info *info = getHalInfo(wifiHandle);
1260
1261 /* len=0 clears the filters in driver/firmware */
1262 if (len != 0 && program == NULL) {
1263 ALOGE("%s: No valid program provided. Exit.",
1264 __func__);
1265 return WIFI_ERROR_INVALID_ARGS;
1266 }
1267
1268 do {
1269 ret = initialize_vendor_cmd(iface, get_requestid(),
1270 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
1271 &vCommand);
1272 if (ret != WIFI_SUCCESS) {
1273 ALOGE("%s: Initialization failed", __FUNCTION__);
1274 return (wifi_error)ret;
1275 }
1276
1277 /* Add the vendor specific attributes for the NL command. */
1278 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1279 if (!nlData)
1280 goto cleanup;
1281
1282 if (vCommand->put_u32(
1283 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
1284 QCA_WLAN_SET_PACKET_FILTER) ||
1285 vCommand->put_u32(
1286 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
1287 PACKET_FILTER_ID) ||
1288 vCommand->put_u32(
1289 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH,
1290 len) ||
1291 vCommand->put_u32(
1292 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
1293 current_offset)) {
1294 ALOGE("%s: failed to put subcmd/program", __FUNCTION__);
1295 goto cleanup;
1296 }
1297
1298 if (len) {
1299 if(vCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
1300 (char *)&program[current_offset],
1301 min(info->firmware_bus_max_size,
1302 len-current_offset))) {
1303 ALOGE("%s: failed to put subcmd", __FUNCTION__);
1304 goto cleanup;
1305 }
1306 }
1307
1308 vCommand->attr_end(nlData);
1309
1310 ret = vCommand->requestResponse();
1311 if (ret < 0) {
1312 ALOGE("%s: requestResponse Error:%d",__func__, ret);
1313 goto cleanup;
1314 }
1315
1316 /* destroy the object after sending each fragment to driver */
1317 delete vCommand;
1318 vCommand = NULL;
1319
1320 current_offset += min(info->firmware_bus_max_size, len);
1321 } while (current_offset < len);
1322
1323 cleanup:
1324 if (vCommand)
1325 delete vCommand;
1326 return (wifi_error)ret;
1327 }
1328
wifi_get_packet_filter_capabilities(wifi_interface_handle handle,u32 * version,u32 * max_len)1329 static wifi_error wifi_get_packet_filter_capabilities(
1330 wifi_interface_handle handle, u32 *version, u32 *max_len)
1331 {
1332 int ret = 0;
1333 struct nlattr *nlData;
1334 WifihalGeneric *vCommand = NULL;
1335 interface_info *ifaceInfo = getIfaceInfo(handle);
1336 wifi_handle wifiHandle = getWifiHandle(handle);
1337
1338 if (version == NULL || max_len == NULL) {
1339 ALOGE("%s: NULL version/max_len pointer provided. Exit.",
1340 __FUNCTION__);
1341 return WIFI_ERROR_INVALID_ARGS;
1342 }
1343
1344 vCommand = new WifihalGeneric(wifiHandle, 0,
1345 OUI_QCA,
1346 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
1347 if (vCommand == NULL) {
1348 ALOGE("%s: Error vCommand NULL", __FUNCTION__);
1349 return WIFI_ERROR_OUT_OF_MEMORY;
1350 }
1351
1352 /* Create the message */
1353 ret = vCommand->create();
1354 if (ret < 0)
1355 goto cleanup;
1356
1357 ret = vCommand->set_iface_id(ifaceInfo->name);
1358 if (ret < 0)
1359 goto cleanup;
1360
1361 /* Add the vendor specific attributes for the NL command. */
1362 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1363 if (!nlData)
1364 goto cleanup;
1365
1366 if (vCommand->put_u32(
1367 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
1368 QCA_WLAN_GET_PACKET_FILTER_SIZE))
1369 {
1370 goto cleanup;
1371 }
1372 vCommand->attr_end(nlData);
1373
1374 ret = vCommand->requestResponse();
1375 if (ret) {
1376 ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
1377 if (ret == -ENOTSUP) {
1378 /* Packet filtering is not supported currently, so return version
1379 * and length as 0
1380 */
1381 ALOGI("Packet filtering is not supprted");
1382 *version = 0;
1383 *max_len = 0;
1384 ret = WIFI_SUCCESS;
1385 }
1386 goto cleanup;
1387 }
1388
1389 *version = vCommand->getFilterVersion();
1390 *max_len = vCommand->getFilterLength();
1391 cleanup:
1392 delete vCommand;
1393 return (wifi_error)ret;
1394 }
1395
1396
wifi_configure_nd_offload(wifi_interface_handle iface,u8 enable)1397 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
1398 u8 enable)
1399 {
1400 int ret = WIFI_SUCCESS;
1401 struct nlattr *nlData;
1402 WifiVendorCommand *vCommand = NULL;
1403
1404 ret = initialize_vendor_cmd(iface, get_requestid(),
1405 QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
1406 &vCommand);
1407 if (ret != WIFI_SUCCESS) {
1408 ALOGE("%s: Initialization failed", __func__);
1409 return (wifi_error)ret;
1410 }
1411
1412 ALOGV("ND offload : %s", enable?"Enable":"Disable");
1413
1414 /* Add the vendor specific attributes for the NL command. */
1415 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1416 if (!nlData)
1417 goto cleanup;
1418
1419 if (vCommand->put_u8(
1420 QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG,
1421 enable))
1422 {
1423 goto cleanup;
1424 }
1425
1426 vCommand->attr_end(nlData);
1427
1428 ret = vCommand->requestResponse();
1429
1430 cleanup:
1431 delete vCommand;
1432 return (wifi_error)ret;
1433 }
1434