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-private/object-api.h>
34 #include <netlink-private/types.h>
35
36 #include "nl80211_copy.h"
37
38 #include <dirent.h>
39 #include <net/if.h>
40 #include <netinet/in.h>
41 #include <cld80211_lib.h>
42
43 #include <sys/types.h>
44 #include <unistd.h>
45
46 #include "sync.h"
47
48 #define LOG_TAG "WifiHAL"
49
50 #include "wifi_hal.h"
51 #include "common.h"
52 #include "cpp_bindings.h"
53 #include "ifaceeventhandler.h"
54 #include "wifiloggercmd.h"
55 #include "vendor_definitions.h"
56
57 /*
58 BUGBUG: normally, libnl allocates ports for all connections it makes; but
59 being a static library, it doesn't really know how many other netlink
60 connections are made by the same process, if connections come from different
61 shared libraries. These port assignments exist to solve that
62 problem - temporarily. We need to fix libnl to try and allocate ports across
63 the entire process.
64 */
65
66 #define WIFI_HAL_CMD_SOCK_PORT 644
67 #define WIFI_HAL_EVENT_SOCK_PORT 645
68
69 /*
70 * Defines for wifi_wait_for_driver_ready()
71 * Specify durations between polls and max wait time
72 */
73 #define POLL_DRIVER_DURATION_US (100000)
74 #define POLL_DRIVER_MAX_TIME_MS (10000)
75
76 static void internal_event_handler(wifi_handle handle, int events,
77 struct nl_sock *sock);
78 static int internal_valid_message_handler(nl_msg *msg, void *arg);
79 static int user_sock_message_handler(nl_msg *msg, void *arg);
80 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
81 const char *group);
82 static int wifi_add_membership(wifi_handle handle, const char *group);
83 static wifi_error wifi_init_interfaces(wifi_handle handle);
84 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
85 const u8 *program, u32 len);
86 static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
87 u32 *version, u32 *max_len);
88 static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
89 u32 src_offset, u8 *host_dst, u32 length);
90 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
91 u8 enable);
92 wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,
93 WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt);
94
95 /* Initialize/Cleanup */
96
wifi_get_iface_handle(wifi_handle handle,char * name)97 wifi_interface_handle wifi_get_iface_handle(wifi_handle handle, char *name)
98 {
99 hal_info *info = (hal_info *)handle;
100 for (int i=0;i<info->num_interfaces;i++)
101 {
102 if (!strcmp(info->interfaces[i]->name, name))
103 {
104 return ((wifi_interface_handle )(info->interfaces)[i]);
105 }
106 }
107 return NULL;
108 }
109
wifi_socket_set_local_port(struct nl_sock * sock,uint32_t port)110 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
111 {
112 /* Release local port pool maintained by libnl and assign a own port
113 * identifier to the socket.
114 */
115 nl_socket_set_local_port(sock, ((uint32_t)getpid() & 0x3FFFFFU) | (port << 22));
116 }
117
wifi_create_nl_socket(int port,int protocol)118 static nl_sock * wifi_create_nl_socket(int port, int protocol)
119 {
120 // ALOGI("Creating socket");
121 struct nl_sock *sock = nl_socket_alloc();
122 if (sock == NULL) {
123 ALOGE("Failed to create NL socket");
124 return NULL;
125 }
126
127 wifi_socket_set_local_port(sock, port);
128
129 if (nl_connect(sock, protocol)) {
130 ALOGE("Could not connect handle");
131 nl_socket_free(sock);
132 return NULL;
133 }
134
135 return sock;
136 }
137
ack_handler(struct nl_msg * msg,void * arg)138 int ack_handler(struct nl_msg *msg, void *arg)
139 {
140 int *err = (int *)arg;
141 *err = 0;
142 return NL_STOP;
143 }
144
finish_handler(struct nl_msg * msg,void * arg)145 int finish_handler(struct nl_msg *msg, void *arg)
146 {
147 int *ret = (int *)arg;
148 *ret = 0;
149 return NL_SKIP;
150 }
151
error_handler(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)152 int error_handler(struct sockaddr_nl *nla,
153 struct nlmsgerr *err, void *arg)
154 {
155 int *ret = (int *)arg;
156 *ret = err->error;
157
158 ALOGV("%s invoked with error: %d", __func__, err->error);
159 return NL_SKIP;
160 }
no_seq_check(struct nl_msg * msg,void * arg)161 static int no_seq_check(struct nl_msg *msg, void *arg)
162 {
163 return NL_OK;
164 }
165
acquire_supported_features(wifi_interface_handle iface,feature_set * set)166 static wifi_error acquire_supported_features(wifi_interface_handle iface,
167 feature_set *set)
168 {
169 wifi_error ret;
170 interface_info *iinfo = getIfaceInfo(iface);
171 wifi_handle handle = getWifiHandle(iface);
172 *set = 0;
173
174 WifihalGeneric supportedFeatures(handle, 0,
175 OUI_QCA,
176 QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES);
177
178 /* create the message */
179 ret = supportedFeatures.create();
180 if (ret != WIFI_SUCCESS)
181 goto cleanup;
182
183 ret = supportedFeatures.set_iface_id(iinfo->name);
184 if (ret != WIFI_SUCCESS)
185 goto cleanup;
186
187 ret = supportedFeatures.requestResponse();
188 if (ret != WIFI_SUCCESS) {
189 ALOGE("%s: requestResponse Error:%d",__func__, ret);
190 goto cleanup;
191 }
192
193 supportedFeatures.getResponseparams(set);
194
195 cleanup:
196 return ret;
197 }
198
wifi_get_capabilities(wifi_interface_handle handle)199 static wifi_error wifi_get_capabilities(wifi_interface_handle handle)
200 {
201 wifi_error ret;
202 int requestId;
203 WifihalGeneric *wifihalGeneric;
204 wifi_handle wifiHandle = getWifiHandle(handle);
205 hal_info *info = getHalInfo(wifiHandle);
206
207 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
208 ALOGE("%s: GSCAN is not supported by driver", __FUNCTION__);
209 return WIFI_ERROR_NOT_SUPPORTED;
210 }
211
212 /* No request id from caller, so generate one and pass it on to the driver.
213 * Generate it randomly.
214 */
215 requestId = get_requestid();
216
217 wifihalGeneric = new WifihalGeneric(
218 wifiHandle,
219 requestId,
220 OUI_QCA,
221 QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES);
222 if (!wifihalGeneric) {
223 ALOGE("%s: Failed to create object of WifihalGeneric class", __FUNCTION__);
224 return WIFI_ERROR_OUT_OF_MEMORY;
225 }
226
227 ret = wifihalGeneric->wifiGetCapabilities(handle);
228
229 delete wifihalGeneric;
230 return ret;
231 }
232
get_firmware_bus_max_size_supported(wifi_interface_handle iface)233 static wifi_error get_firmware_bus_max_size_supported(
234 wifi_interface_handle iface)
235 {
236 wifi_error ret;
237 interface_info *iinfo = getIfaceInfo(iface);
238 wifi_handle handle = getWifiHandle(iface);
239 hal_info *info = (hal_info *)handle;
240
241 WifihalGeneric busSizeSupported(handle, 0,
242 OUI_QCA,
243 QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE);
244
245 /* create the message */
246 ret = busSizeSupported.create();
247 if (ret != WIFI_SUCCESS)
248 goto cleanup;
249
250 ret = busSizeSupported.set_iface_id(iinfo->name);
251 if (ret != WIFI_SUCCESS)
252 goto cleanup;
253
254 ret = busSizeSupported.requestResponse();
255 if (ret != WIFI_SUCCESS) {
256 ALOGE("%s: requestResponse Error:%d", __FUNCTION__, ret);
257 goto cleanup;
258 }
259 info->firmware_bus_max_size = busSizeSupported.getBusSize();
260
261 cleanup:
262 return ret;
263 }
264
wifi_init_user_sock(hal_info * info)265 static wifi_error wifi_init_user_sock(hal_info *info)
266 {
267 struct nl_sock *user_sock =
268 wifi_create_nl_socket(WIFI_HAL_USER_SOCK_PORT, NETLINK_USERSOCK);
269 if (user_sock == NULL) {
270 ALOGE("Could not create diag sock");
271 return WIFI_ERROR_UNKNOWN;
272 }
273
274 /* Set the socket buffer size */
275 if (nl_socket_set_buffer_size(user_sock, (256*1024), 0) < 0) {
276 ALOGE("Could not set size for user_sock: %s",
277 strerror(errno));
278 /* continue anyway with the default (smaller) buffer */
279 }
280 else {
281 ALOGV("nl_socket_set_buffer_size successful for user_sock");
282 }
283
284 struct nl_cb *cb = nl_socket_get_cb(user_sock);
285 if (cb == NULL) {
286 ALOGE("Could not get cb");
287 return WIFI_ERROR_UNKNOWN;
288 }
289
290 info->user_sock_arg = 1;
291 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
292 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg);
293 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg);
294 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg);
295
296 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info);
297 nl_cb_put(cb);
298
299 int ret = nl_socket_add_membership(user_sock, 1);
300 if (ret < 0) {
301 ALOGE("Could not add membership");
302 return WIFI_ERROR_UNKNOWN;
303 }
304
305 info->user_sock = user_sock;
306 ALOGV("Initiialized diag sock successfully");
307 return WIFI_SUCCESS;
308 }
309
wifi_init_cld80211_sock_cb(hal_info * info)310 static wifi_error wifi_init_cld80211_sock_cb(hal_info *info)
311 {
312 struct nl_cb *cb = nl_socket_get_cb(info->cldctx->sock);
313 if (cb == NULL) {
314 ALOGE("Could not get cb");
315 return WIFI_ERROR_UNKNOWN;
316 }
317
318 info->user_sock_arg = 1;
319 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
320 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg);
321 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg);
322 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg);
323
324 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info);
325 nl_cb_put(cb);
326
327 return WIFI_SUCCESS;
328 }
329
330
331 /*initialize function pointer table with Qualcomm HAL API*/
init_wifi_vendor_hal_func_table(wifi_hal_fn * fn)332 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) {
333 if (fn == NULL) {
334 return WIFI_ERROR_UNKNOWN;
335 }
336
337 fn->wifi_initialize = wifi_initialize;
338 fn->wifi_wait_for_driver_ready = wifi_wait_for_driver_ready;
339 fn->wifi_cleanup = wifi_cleanup;
340 fn->wifi_event_loop = wifi_event_loop;
341 fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
342 fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
343 fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui;
344 fn->wifi_get_ifaces = wifi_get_ifaces;
345 fn->wifi_get_iface_name = wifi_get_iface_name;
346 fn->wifi_set_iface_event_handler = wifi_set_iface_event_handler;
347 fn->wifi_reset_iface_event_handler = wifi_reset_iface_event_handler;
348 fn->wifi_start_gscan = wifi_start_gscan;
349 fn->wifi_stop_gscan = wifi_stop_gscan;
350 fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
351 fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
352 fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
353 fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
354 fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
355 fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
356 fn->wifi_set_link_stats = wifi_set_link_stats;
357 fn->wifi_get_link_stats = wifi_get_link_stats;
358 fn->wifi_clear_link_stats = wifi_clear_link_stats;
359 fn->wifi_get_valid_channels = wifi_get_valid_channels;
360 fn->wifi_rtt_range_request = wifi_rtt_range_request;
361 fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
362 fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
363 fn->wifi_rtt_get_responder_info = wifi_rtt_get_responder_info;
364 fn->wifi_enable_responder = wifi_enable_responder;
365 fn->wifi_disable_responder = wifi_disable_responder;
366 fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
367 fn->wifi_start_logging = wifi_start_logging;
368 fn->wifi_set_epno_list = wifi_set_epno_list;
369 fn->wifi_reset_epno_list = wifi_reset_epno_list;
370 fn->wifi_set_country_code = wifi_set_country_code;
371 fn->wifi_enable_tdls = wifi_enable_tdls;
372 fn->wifi_disable_tdls = wifi_disable_tdls;
373 fn->wifi_get_tdls_status = wifi_get_tdls_status;
374 fn->wifi_get_tdls_capabilities = wifi_get_tdls_capabilities;
375 fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
376 fn->wifi_set_log_handler = wifi_set_log_handler;
377 fn->wifi_reset_log_handler = wifi_reset_log_handler;
378 fn->wifi_set_alert_handler = wifi_set_alert_handler;
379 fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
380 fn->wifi_get_firmware_version = wifi_get_firmware_version;
381 fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
382 fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;
383 fn->wifi_get_ring_data = wifi_get_ring_data;
384 fn->wifi_get_driver_version = wifi_get_driver_version;
385 fn->wifi_set_passpoint_list = wifi_set_passpoint_list;
386 fn->wifi_reset_passpoint_list = wifi_reset_passpoint_list;
387 fn->wifi_set_lci = wifi_set_lci;
388 fn->wifi_set_lcr = wifi_set_lcr;
389 fn->wifi_start_sending_offloaded_packet =
390 wifi_start_sending_offloaded_packet;
391 fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
392 fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
393 fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
394 fn->wifi_nan_enable_request = nan_enable_request;
395 fn->wifi_nan_disable_request = nan_disable_request;
396 fn->wifi_nan_publish_request = nan_publish_request;
397 fn->wifi_nan_publish_cancel_request = nan_publish_cancel_request;
398 fn->wifi_nan_subscribe_request = nan_subscribe_request;
399 fn->wifi_nan_subscribe_cancel_request = nan_subscribe_cancel_request;
400 fn->wifi_nan_transmit_followup_request = nan_transmit_followup_request;
401 fn->wifi_nan_stats_request = nan_stats_request;
402 fn->wifi_nan_config_request = nan_config_request;
403 fn->wifi_nan_tca_request = nan_tca_request;
404 fn->wifi_nan_beacon_sdf_payload_request = nan_beacon_sdf_payload_request;
405 fn->wifi_nan_register_handler = nan_register_handler;
406 fn->wifi_nan_get_version = nan_get_version;
407 fn->wifi_set_packet_filter = wifi_set_packet_filter;
408 fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
409 fn->wifi_read_packet_filter = wifi_read_packet_filter;
410 fn->wifi_nan_get_capabilities = nan_get_capabilities;
411 fn->wifi_nan_data_interface_create = nan_data_interface_create;
412 fn->wifi_nan_data_interface_delete = nan_data_interface_delete;
413 fn->wifi_nan_data_request_initiator = nan_data_request_initiator;
414 fn->wifi_nan_data_indication_response = nan_data_indication_response;
415 fn->wifi_nan_data_end = nan_data_end;
416 fn->wifi_configure_nd_offload = wifi_configure_nd_offload;
417 fn->wifi_get_driver_memory_dump = wifi_get_driver_memory_dump;
418 fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats;
419 fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring;
420 fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;
421 fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;
422 fn->wifi_get_roaming_capabilities = wifi_get_roaming_capabilities;
423 fn->wifi_configure_roaming = wifi_configure_roaming;
424 fn->wifi_enable_firmware_roaming = wifi_enable_firmware_roaming;
425 fn->wifi_select_tx_power_scenario = wifi_select_tx_power_scenario;
426 fn->wifi_reset_tx_power_scenario = wifi_reset_tx_power_scenario;
427 fn->wifi_set_radio_mode_change_handler = wifi_set_radio_mode_change_handler;
428
429 return WIFI_SUCCESS;
430 }
431
cld80211lib_cleanup(hal_info * info)432 static void cld80211lib_cleanup(hal_info *info)
433 {
434 if (!info->cldctx)
435 return;
436 cld80211_remove_mcast_group(info->cldctx, "host_logs");
437 cld80211_remove_mcast_group(info->cldctx, "fw_logs");
438 cld80211_remove_mcast_group(info->cldctx, "per_pkt_stats");
439 cld80211_remove_mcast_group(info->cldctx, "diag_events");
440 cld80211_remove_mcast_group(info->cldctx, "fatal_events");
441 exit_cld80211_recv(info->cldctx);
442 cld80211_deinit(info->cldctx);
443 info->cldctx = NULL;
444 }
445
wifi_get_iface_id(hal_info * info,const char * iface)446 static int wifi_get_iface_id(hal_info *info, const char *iface)
447 {
448 int i;
449 for (i = 0; i < info->num_interfaces; i++)
450 if (!strcmp(info->interfaces[i]->name, iface))
451 return i;
452 return -1;
453 }
454
wifi_initialize(wifi_handle * handle)455 wifi_error wifi_initialize(wifi_handle *handle)
456 {
457 int err = 0;
458 wifi_error ret = WIFI_SUCCESS;
459 wifi_interface_handle iface_handle;
460 struct nl_sock *cmd_sock = NULL;
461 struct nl_sock *event_sock = NULL;
462 struct nl_cb *cb = NULL;
463 int status = 0;
464 int index;
465
466 ALOGI("Initializing wifi");
467 hal_info *info = (hal_info *)malloc(sizeof(hal_info));
468 if (info == NULL) {
469 ALOGE("Could not allocate hal_info");
470 return WIFI_ERROR_OUT_OF_MEMORY;
471 }
472
473 memset(info, 0, sizeof(*info));
474
475 cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT,
476 NETLINK_GENERIC);
477 if (cmd_sock == NULL) {
478 ALOGE("Failed to create command socket port");
479 ret = WIFI_ERROR_UNKNOWN;
480 goto unload;
481 }
482
483 /* Set the socket buffer size */
484 if (nl_socket_set_buffer_size(cmd_sock, (256*1024), 0) < 0) {
485 ALOGE("Could not set nl_socket RX buffer size for cmd_sock: %s",
486 strerror(errno));
487 /* continue anyway with the default (smaller) buffer */
488 }
489
490 event_sock =
491 wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT, NETLINK_GENERIC);
492 if (event_sock == NULL) {
493 ALOGE("Failed to create event socket port");
494 ret = WIFI_ERROR_UNKNOWN;
495 goto unload;
496 }
497
498 /* Set the socket buffer size */
499 if (nl_socket_set_buffer_size(event_sock, (256*1024), 0) < 0) {
500 ALOGE("Could not set nl_socket RX buffer size for event_sock: %s",
501 strerror(errno));
502 /* continue anyway with the default (smaller) buffer */
503 }
504
505 cb = nl_socket_get_cb(event_sock);
506 if (cb == NULL) {
507 ALOGE("Failed to get NL control block for event socket port");
508 ret = WIFI_ERROR_UNKNOWN;
509 goto unload;
510 }
511
512 err = 1;
513 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
514 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
515 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
516 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
517
518 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler,
519 info);
520 nl_cb_put(cb);
521
522 info->cmd_sock = cmd_sock;
523 info->event_sock = event_sock;
524 info->clean_up = false;
525 info->in_event_loop = false;
526
527 info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
528 if (info->event_cb == NULL) {
529 ALOGE("Could not allocate event_cb");
530 ret = WIFI_ERROR_OUT_OF_MEMORY;
531 goto unload;
532 }
533 info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
534 info->num_event_cb = 0;
535
536 info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
537 if (info->nl80211_family_id < 0) {
538 ALOGE("Could not resolve nl80211 familty id");
539 ret = WIFI_ERROR_UNKNOWN;
540 goto unload;
541 }
542
543 pthread_mutex_init(&info->cb_lock, NULL);
544 pthread_mutex_init(&info->pkt_fate_stats_lock, NULL);
545
546 *handle = (wifi_handle) info;
547
548 wifi_add_membership(*handle, "scan");
549 wifi_add_membership(*handle, "mlme");
550 wifi_add_membership(*handle, "regulatory");
551 wifi_add_membership(*handle, "vendor");
552
553 info->cldctx = cld80211_init();
554 if (info->cldctx != NULL) {
555 info->user_sock = info->cldctx->sock;
556 ret = wifi_init_cld80211_sock_cb(info);
557 if (ret != WIFI_SUCCESS) {
558 ALOGE("Could not set cb for CLD80211 family");
559 goto cld80211_cleanup;
560 }
561
562 status = cld80211_add_mcast_group(info->cldctx, "host_logs");
563 if (status) {
564 ALOGE("Failed to add mcast group host_logs :%d", status);
565 goto cld80211_cleanup;
566 }
567 status = cld80211_add_mcast_group(info->cldctx, "fw_logs");
568 if (status) {
569 ALOGE("Failed to add mcast group fw_logs :%d", status);
570 goto cld80211_cleanup;
571 }
572 status = cld80211_add_mcast_group(info->cldctx, "per_pkt_stats");
573 if (status) {
574 ALOGE("Failed to add mcast group per_pkt_stats :%d", status);
575 goto cld80211_cleanup;
576 }
577 status = cld80211_add_mcast_group(info->cldctx, "diag_events");
578 if (status) {
579 ALOGE("Failed to add mcast group diag_events :%d", status);
580 goto cld80211_cleanup;
581 }
582 status = cld80211_add_mcast_group(info->cldctx, "fatal_events");
583 if (status) {
584 ALOGE("Failed to add mcast group fatal_events :%d", status);
585 goto cld80211_cleanup;
586 }
587 } else {
588 ret = wifi_init_user_sock(info);
589 if (ret != WIFI_SUCCESS) {
590 ALOGE("Failed to alloc user socket");
591 goto unload;
592 }
593 }
594
595 ret = wifi_init_interfaces(*handle);
596 if (ret != WIFI_SUCCESS) {
597 ALOGE("Failed to init interfaces");
598 goto unload;
599 }
600
601 if (info->num_interfaces == 0) {
602 ALOGE("No interfaces found");
603 ret = WIFI_ERROR_UNINITIALIZED;
604 goto unload;
605 }
606
607 index = wifi_get_iface_id(info, "wlan0");
608 if (index == -1) {
609 int i;
610 for (i = 0; i < info->num_interfaces; i++)
611 {
612 free(info->interfaces[i]);
613 }
614 ALOGE("%s no iface with wlan0", __func__);
615 goto unload;
616 }
617 iface_handle = (wifi_interface_handle)info->interfaces[index];
618
619 ret = acquire_supported_features(iface_handle,
620 &info->supported_feature_set);
621 if (ret != WIFI_SUCCESS) {
622 ALOGI("Failed to get supported feature set : %d", ret);
623 //acquire_supported_features failure is acceptable condition as legacy
624 //drivers might not support the required vendor command. So, do not
625 //consider it as failure of wifi_initialize
626 ret = WIFI_SUCCESS;
627 }
628
629 ret = wifi_get_logger_supported_feature_set(iface_handle,
630 &info->supported_logger_feature_set);
631 if (ret != WIFI_SUCCESS)
632 ALOGE("Failed to get supported logger feature set: %d", ret);
633
634 ret = get_firmware_bus_max_size_supported(iface_handle);
635 if (ret != WIFI_SUCCESS) {
636 ALOGE("Failed to get supported bus size, error : %d", ret);
637 info->firmware_bus_max_size = 1520;
638 }
639
640 ret = wifi_logger_ring_buffers_init(info);
641 if (ret != WIFI_SUCCESS)
642 ALOGE("Wifi Logger Ring Initialization Failed");
643
644 ret = wifi_get_capabilities(iface_handle);
645 if (ret != WIFI_SUCCESS)
646 ALOGE("Failed to get wifi Capabilities, error: %d", ret);
647
648 info->pkt_stats = (struct pkt_stats_s *)malloc(sizeof(struct pkt_stats_s));
649 if (!info->pkt_stats) {
650 ALOGE("%s: malloc Failed for size: %zu",
651 __FUNCTION__, sizeof(struct pkt_stats_s));
652 ret = WIFI_ERROR_OUT_OF_MEMORY;
653 goto unload;
654 }
655
656 info->rx_buf_size_allocated = MAX_RXMPDUS_PER_AMPDU * MAX_MSDUS_PER_MPDU
657 * PKT_STATS_BUF_SIZE;
658
659 info->rx_aggr_pkts =
660 (wifi_ring_buffer_entry *)malloc(info->rx_buf_size_allocated);
661 if (!info->rx_aggr_pkts) {
662 ALOGE("%s: malloc Failed for size: %d",
663 __FUNCTION__, info->rx_buf_size_allocated);
664 ret = WIFI_ERROR_OUT_OF_MEMORY;
665 info->rx_buf_size_allocated = 0;
666 goto unload;
667 }
668 memset(info->rx_aggr_pkts, 0, info->rx_buf_size_allocated);
669
670 info->exit_sockets[0] = -1;
671 info->exit_sockets[1] = -1;
672
673 if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->exit_sockets) == -1) {
674 ALOGE("Failed to create exit socket pair");
675 ret = WIFI_ERROR_UNKNOWN;
676 goto unload;
677 }
678
679 ALOGV("Initializing Gscan Event Handlers");
680 ret = initializeGscanHandlers(info);
681 if (ret != WIFI_SUCCESS) {
682 ALOGE("Initializing Gscan Event Handlers Failed");
683 goto unload;
684 }
685
686 ret = initializeRSSIMonitorHandler(info);
687 if (ret != WIFI_SUCCESS) {
688 ALOGE("Initializing RSSI Event Handler Failed");
689 goto unload;
690 }
691
692 ALOGV("Initialized Wifi HAL Successfully; vendor cmd = %d Supported"
693 " features : %x", NL80211_CMD_VENDOR, info->supported_feature_set);
694
695 cld80211_cleanup:
696 if (status != 0 || ret != WIFI_SUCCESS) {
697 ret = WIFI_ERROR_UNKNOWN;
698 cld80211lib_cleanup(info);
699 }
700 unload:
701 if (ret != WIFI_SUCCESS) {
702 if (cmd_sock)
703 nl_socket_free(cmd_sock);
704 if (event_sock)
705 nl_socket_free(event_sock);
706 if (info) {
707 if (info->cldctx) {
708 cld80211lib_cleanup(info);
709 } else if (info->user_sock) {
710 nl_socket_free(info->user_sock);
711 }
712 if (info->pkt_stats) free(info->pkt_stats);
713 if (info->rx_aggr_pkts) free(info->rx_aggr_pkts);
714 wifi_logger_ring_buffers_deinit(info);
715 cleanupGscanHandlers(info);
716 cleanupRSSIMonitorHandler(info);
717 free(info->event_cb);
718 free(info);
719 }
720 }
721
722 return ret;
723 }
724
wifi_wait_for_driver_ready(void)725 wifi_error wifi_wait_for_driver_ready(void)
726 {
727 // This function will wait to make sure basic client netdev is created
728 // Function times out after 10 seconds
729 int count = (POLL_DRIVER_MAX_TIME_MS * 1000) / POLL_DRIVER_DURATION_US;
730 FILE *fd;
731
732 do {
733 if ((fd = fopen("/sys/class/net/wlan0", "r")) != NULL) {
734 fclose(fd);
735 return WIFI_SUCCESS;
736 }
737 usleep(POLL_DRIVER_DURATION_US);
738 } while(--count > 0);
739
740 ALOGE("Timed out wating on Driver ready ... ");
741 return WIFI_ERROR_TIMED_OUT;
742 }
743
wifi_add_membership(wifi_handle handle,const char * group)744 static int wifi_add_membership(wifi_handle handle, const char *group)
745 {
746 hal_info *info = getHalInfo(handle);
747
748 int id = wifi_get_multicast_id(handle, "nl80211", group);
749 if (id < 0) {
750 ALOGE("Could not find group %s", group);
751 return id;
752 }
753
754 int ret = nl_socket_add_membership(info->event_sock, id);
755 if (ret < 0) {
756 ALOGE("Could not add membership to group %s", group);
757 }
758
759 return ret;
760 }
761
internal_cleaned_up_handler(wifi_handle handle)762 static void internal_cleaned_up_handler(wifi_handle handle)
763 {
764 hal_info *info = getHalInfo(handle);
765 wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
766
767 if (info->cmd_sock != 0) {
768 nl_socket_free(info->cmd_sock);
769 nl_socket_free(info->event_sock);
770 info->cmd_sock = NULL;
771 info->event_sock = NULL;
772 }
773
774 if (info->interfaces) {
775 for (int i = 0; i < info->num_interfaces; i++)
776 free(info->interfaces[i]);
777 free(info->interfaces);
778 }
779
780 if (info->cldctx != NULL) {
781 cld80211lib_cleanup(info);
782 } else if (info->user_sock != 0) {
783 nl_socket_free(info->user_sock);
784 info->user_sock = NULL;
785 }
786
787 if (info->pkt_stats)
788 free(info->pkt_stats);
789 if (info->rx_aggr_pkts)
790 free(info->rx_aggr_pkts);
791 wifi_logger_ring_buffers_deinit(info);
792 cleanupGscanHandlers(info);
793 cleanupRSSIMonitorHandler(info);
794
795 if (info->num_event_cb)
796 ALOGE("%d events were leftover without being freed",
797 info->num_event_cb);
798 free(info->event_cb);
799
800 if (info->exit_sockets[0] >= 0) {
801 close(info->exit_sockets[0]);
802 info->exit_sockets[0] = -1;
803 }
804
805 if (info->exit_sockets[1] >= 0) {
806 close(info->exit_sockets[1]);
807 info->exit_sockets[1] = -1;
808 }
809
810 if (info->pkt_fate_stats) {
811 free(info->pkt_fate_stats);
812 info->pkt_fate_stats = NULL;
813 }
814
815 (*cleaned_up_handler)(handle);
816 pthread_mutex_destroy(&info->cb_lock);
817 pthread_mutex_destroy(&info->pkt_fate_stats_lock);
818 free(info);
819 }
820
wifi_cleanup(wifi_handle handle,wifi_cleaned_up_handler handler)821 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
822 {
823 if (!handle) {
824 ALOGE("Handle is null");
825 return;
826 }
827
828 hal_info *info = getHalInfo(handle);
829 info->cleaned_up_handler = handler;
830 info->clean_up = true;
831
832 TEMP_FAILURE_RETRY(write(info->exit_sockets[0], "E", 1));
833 ALOGI("Sent msg on exit sock to unblock poll()");
834 }
835
internal_pollin_handler(wifi_handle handle,struct nl_sock * sock)836 static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock)
837 {
838 struct nl_cb *cb = nl_socket_get_cb(sock);
839
840 int res = nl_recvmsgs(sock, cb);
841 if(res)
842 ALOGE("Error :%d while reading nl msg", res);
843 nl_cb_put(cb);
844 return res;
845 }
846
internal_event_handler(wifi_handle handle,int events,struct nl_sock * sock)847 static void internal_event_handler(wifi_handle handle, int events,
848 struct nl_sock *sock)
849 {
850 if (events & POLLERR) {
851 ALOGE("Error reading from socket");
852 internal_pollin_handler(handle, sock);
853 } else if (events & POLLHUP) {
854 ALOGE("Remote side hung up");
855 } else if (events & POLLIN) {
856 //ALOGI("Found some events!!!");
857 internal_pollin_handler(handle, sock);
858 } else {
859 ALOGE("Unknown event - %0x", events);
860 }
861 }
862
863 /* Run event handler */
wifi_event_loop(wifi_handle handle)864 void wifi_event_loop(wifi_handle handle)
865 {
866 hal_info *info = getHalInfo(handle);
867 if (info->in_event_loop) {
868 return;
869 } else {
870 info->in_event_loop = true;
871 }
872
873 pollfd pfd[3];
874 memset(&pfd, 0, 3*sizeof(pfd[0]));
875
876 pfd[0].fd = nl_socket_get_fd(info->event_sock);
877 pfd[0].events = POLLIN;
878
879 pfd[1].fd = nl_socket_get_fd(info->user_sock);
880 pfd[1].events = POLLIN;
881
882 pfd[2].fd = info->exit_sockets[1];
883 pfd[2].events = POLLIN;
884
885 /* TODO: Add support for timeouts */
886
887 do {
888 pfd[0].revents = 0;
889 pfd[1].revents = 0;
890 pfd[2].revents = 0;
891 //ALOGI("Polling sockets");
892 int result = poll(pfd, 3, -1);
893 if (result < 0) {
894 ALOGE("Error polling socket");
895 } else {
896 if (pfd[0].revents & (POLLIN | POLLHUP | POLLERR)) {
897 internal_event_handler(handle, pfd[0].revents, info->event_sock);
898 }
899 if (pfd[1].revents & (POLLIN | POLLHUP | POLLERR)) {
900 internal_event_handler(handle, pfd[1].revents, info->user_sock);
901 }
902 }
903 rb_timerhandler(info);
904 } while (!info->clean_up);
905 internal_cleaned_up_handler(handle);
906 }
907
user_sock_message_handler(nl_msg * msg,void * arg)908 static int user_sock_message_handler(nl_msg *msg, void *arg)
909 {
910 wifi_handle handle = (wifi_handle)arg;
911 hal_info *info = getHalInfo(handle);
912
913 diag_message_handler(info, msg);
914
915 return NL_OK;
916 }
917
internal_valid_message_handler(nl_msg * msg,void * arg)918 static int internal_valid_message_handler(nl_msg *msg, void *arg)
919 {
920 wifi_handle handle = (wifi_handle)arg;
921 hal_info *info = getHalInfo(handle);
922
923 WifiEvent event(msg);
924 int res = event.parse();
925 if (res < 0) {
926 ALOGE("Failed to parse event: %d", res);
927 return NL_SKIP;
928 }
929
930 int cmd = event.get_cmd();
931 uint32_t vendor_id = 0;
932 int subcmd = 0;
933
934 if (cmd == NL80211_CMD_VENDOR) {
935 vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
936 subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
937 /* Restrict printing GSCAN_FULL_RESULT which is causing lot
938 of logs in bug report */
939 if (subcmd != QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT) {
940 ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
941 event.get_cmdString(), vendor_id, subcmd);
942 }
943 } else {
944 ALOGV("event received %s", event.get_cmdString());
945 }
946
947 // event.log();
948
949 bool dispatched = false;
950
951 pthread_mutex_lock(&info->cb_lock);
952
953 for (int i = 0; i < info->num_event_cb; i++) {
954 if (cmd == info->event_cb[i].nl_cmd) {
955 if (cmd == NL80211_CMD_VENDOR
956 && ((vendor_id != info->event_cb[i].vendor_id)
957 || (subcmd != info->event_cb[i].vendor_subcmd)))
958 {
959 /* event for a different vendor, ignore it */
960 continue;
961 }
962
963 cb_info *cbi = &(info->event_cb[i]);
964 pthread_mutex_unlock(&info->cb_lock);
965 if (cbi->cb_func) {
966 (*(cbi->cb_func))(msg, cbi->cb_arg);
967 dispatched = true;
968 }
969 return NL_OK;
970 }
971 }
972
973 #ifdef QC_HAL_DEBUG
974 if (!dispatched) {
975 ALOGI("event ignored!!");
976 }
977 #endif
978
979 pthread_mutex_unlock(&info->cb_lock);
980 return NL_OK;
981 }
982
983 ////////////////////////////////////////////////////////////////////////////////
984
985 class GetMulticastIdCommand : public WifiCommand
986 {
987 private:
988 const char *mName;
989 const char *mGroup;
990 int mId;
991 public:
GetMulticastIdCommand(wifi_handle handle,const char * name,const char * group)992 GetMulticastIdCommand(wifi_handle handle, const char *name,
993 const char *group) : WifiCommand(handle, 0)
994 {
995 mName = name;
996 mGroup = group;
997 mId = -1;
998 }
999
getId()1000 int getId() {
1001 return mId;
1002 }
1003
create()1004 virtual wifi_error create() {
1005 int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
1006 // ALOGI("ctrl family = %d", nlctrlFamily);
1007 wifi_error ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
1008 if (ret != WIFI_SUCCESS)
1009 return ret;
1010
1011 ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
1012 return ret;
1013 }
1014
handleResponse(WifiEvent & reply)1015 virtual int handleResponse(WifiEvent& reply) {
1016
1017 // ALOGI("handling reponse in %s", __func__);
1018
1019 struct nlattr **tb = reply.attributes();
1020 struct nlattr *mcgrp = NULL;
1021 int i;
1022
1023 if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
1024 ALOGI("No multicast groups found");
1025 return NL_SKIP;
1026 } else {
1027 // ALOGI("Multicast groups attr size = %d",
1028 // nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
1029 }
1030
1031 for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
1032
1033 // ALOGI("Processing group");
1034 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
1035 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
1036 nla_len(mcgrp), NULL);
1037 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID])
1038 {
1039 continue;
1040 }
1041
1042 char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
1043 int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
1044
1045 // ALOGI("Found group name %s", grpName);
1046
1047 if (strncmp(grpName, mGroup, grpNameLen) != 0)
1048 continue;
1049
1050 mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
1051 break;
1052 }
1053
1054 return NL_SKIP;
1055 }
1056
1057 };
1058
wifi_get_multicast_id(wifi_handle handle,const char * name,const char * group)1059 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
1060 const char *group)
1061 {
1062 GetMulticastIdCommand cmd(handle, name, group);
1063 int res = cmd.requestResponse();
1064 if (res < 0)
1065 return res;
1066 else
1067 return cmd.getId();
1068 }
1069
1070 /////////////////////////////////////////////////////////////////////////
1071
is_wifi_interface(const char * name)1072 static bool is_wifi_interface(const char *name)
1073 {
1074 if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
1075 /* not a wifi interface; ignore it */
1076 return false;
1077 } else {
1078 return true;
1079 }
1080 }
1081
get_interface(const char * name,interface_info * info)1082 static int get_interface(const char *name, interface_info *info)
1083 {
1084 strlcpy(info->name, name, (IFNAMSIZ + 1));
1085 info->id = if_nametoindex(name);
1086 // ALOGI("found an interface : %s, id = %d", name, info->id);
1087 return WIFI_SUCCESS;
1088 }
1089
wifi_init_interfaces(wifi_handle handle)1090 wifi_error wifi_init_interfaces(wifi_handle handle)
1091 {
1092 hal_info *info = (hal_info *)handle;
1093
1094 struct dirent *de;
1095
1096 DIR *d = opendir("/sys/class/net");
1097 if (d == 0)
1098 return WIFI_ERROR_UNKNOWN;
1099
1100 int n = 0;
1101 while ((de = readdir(d))) {
1102 if (de->d_name[0] == '.')
1103 continue;
1104 if (is_wifi_interface(de->d_name) ) {
1105 n++;
1106 }
1107 }
1108
1109 closedir(d);
1110
1111 d = opendir("/sys/class/net");
1112 if (d == 0)
1113 return WIFI_ERROR_UNKNOWN;
1114
1115 info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
1116 if (info->interfaces == NULL) {
1117 ALOGE("%s: Error info->interfaces NULL", __func__);
1118 return WIFI_ERROR_OUT_OF_MEMORY;
1119 }
1120
1121 int i = 0;
1122 while ((de = readdir(d))) {
1123 if (de->d_name[0] == '.')
1124 continue;
1125 if (is_wifi_interface(de->d_name)) {
1126 interface_info *ifinfo
1127 = (interface_info *)malloc(sizeof(interface_info));
1128 if (ifinfo == NULL) {
1129 ALOGE("%s: Error ifinfo NULL", __func__);
1130 while (i > 0) {
1131 free(info->interfaces[i-1]);
1132 i--;
1133 }
1134 free(info->interfaces);
1135 return WIFI_ERROR_OUT_OF_MEMORY;
1136 }
1137 if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
1138 free(ifinfo);
1139 continue;
1140 }
1141 ifinfo->handle = handle;
1142 info->interfaces[i] = ifinfo;
1143 i++;
1144 }
1145 }
1146
1147 closedir(d);
1148
1149 info->num_interfaces = n;
1150
1151 return WIFI_SUCCESS;
1152 }
1153
wifi_get_ifaces(wifi_handle handle,int * num,wifi_interface_handle ** interfaces)1154 wifi_error wifi_get_ifaces(wifi_handle handle, int *num,
1155 wifi_interface_handle **interfaces)
1156 {
1157 hal_info *info = (hal_info *)handle;
1158
1159 *interfaces = (wifi_interface_handle *)info->interfaces;
1160 *num = info->num_interfaces;
1161
1162 return WIFI_SUCCESS;
1163 }
1164
wifi_get_iface_name(wifi_interface_handle handle,char * name,size_t size)1165 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name,
1166 size_t size)
1167 {
1168 interface_info *info = (interface_info *)handle;
1169 strlcpy(name, info->name, size);
1170 return WIFI_SUCCESS;
1171 }
1172
1173 /* Get the supported Feature set */
wifi_get_supported_feature_set(wifi_interface_handle iface,feature_set * set)1174 wifi_error wifi_get_supported_feature_set(wifi_interface_handle iface,
1175 feature_set *set)
1176 {
1177 int ret = 0;
1178 wifi_handle handle = getWifiHandle(iface);
1179 *set = 0;
1180 hal_info *info = getHalInfo(handle);
1181
1182 ret = acquire_supported_features(iface, set);
1183 if (ret != WIFI_SUCCESS) {
1184 *set = info->supported_feature_set;
1185 ALOGV("Supported feature set acquired at initialization : %x", *set);
1186 } else {
1187 info->supported_feature_set = *set;
1188 ALOGV("Supported feature set acquired : %x", *set);
1189 }
1190 return WIFI_SUCCESS;
1191 }
1192
wifi_get_concurrency_matrix(wifi_interface_handle handle,int set_size_max,feature_set set[],int * set_size)1193 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle,
1194 int set_size_max,
1195 feature_set set[], int *set_size)
1196 {
1197 wifi_error ret;
1198 struct nlattr *nlData;
1199 WifihalGeneric *vCommand = NULL;
1200 interface_info *ifaceInfo = getIfaceInfo(handle);
1201 wifi_handle wifiHandle = getWifiHandle(handle);
1202
1203 if (set == NULL) {
1204 ALOGE("%s: NULL set pointer provided. Exit.",
1205 __func__);
1206 return WIFI_ERROR_INVALID_ARGS;
1207 }
1208
1209 vCommand = new WifihalGeneric(wifiHandle, 0,
1210 OUI_QCA,
1211 QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX);
1212 if (vCommand == NULL) {
1213 ALOGE("%s: Error vCommand NULL", __func__);
1214 return WIFI_ERROR_OUT_OF_MEMORY;
1215 }
1216
1217 /* Create the message */
1218 ret = vCommand->create();
1219 if (ret != WIFI_SUCCESS)
1220 goto cleanup;
1221
1222 ret = vCommand->set_iface_id(ifaceInfo->name);
1223 if (ret != WIFI_SUCCESS)
1224 goto cleanup;
1225
1226 /* Add the vendor specific attributes for the NL command. */
1227 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1228 if (!nlData)
1229 goto cleanup;
1230
1231 ret = vCommand->put_u32(
1232 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX,
1233 set_size_max);
1234 if (ret != WIFI_SUCCESS)
1235 goto cleanup;
1236
1237 vCommand->attr_end(nlData);
1238
1239 /* Populate the input received from caller/framework. */
1240 vCommand->setMaxSetSize(set_size_max);
1241 vCommand->setSizePtr(set_size);
1242 vCommand->setConcurrencySet(set);
1243
1244 ret = vCommand->requestResponse();
1245 if (ret != WIFI_SUCCESS)
1246 ALOGE("%s: requestResponse() error: %d", __func__, ret);
1247
1248 cleanup:
1249 delete vCommand;
1250 if (ret)
1251 *set_size = 0;
1252 return ret;
1253 }
1254
1255
wifi_set_nodfs_flag(wifi_interface_handle handle,u32 nodfs)1256 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
1257 {
1258 wifi_error ret;
1259 struct nlattr *nlData;
1260 WifiVendorCommand *vCommand = NULL;
1261 interface_info *ifaceInfo = getIfaceInfo(handle);
1262 wifi_handle wifiHandle = getWifiHandle(handle);
1263
1264 vCommand = new WifiVendorCommand(wifiHandle, 0,
1265 OUI_QCA,
1266 QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG);
1267 if (vCommand == NULL) {
1268 ALOGE("%s: Error vCommand NULL", __func__);
1269 return WIFI_ERROR_OUT_OF_MEMORY;
1270 }
1271
1272 /* Create the message */
1273 ret = vCommand->create();
1274 if (ret != WIFI_SUCCESS)
1275 goto cleanup;
1276
1277 ret = vCommand->set_iface_id(ifaceInfo->name);
1278 if (ret != WIFI_SUCCESS)
1279 goto cleanup;
1280
1281 /* Add the vendor specific attributes for the NL command. */
1282 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1283 if (!nlData)
1284 goto cleanup;
1285
1286 /* Add the fixed part of the mac_oui to the nl command */
1287 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG, nodfs);
1288 if (ret != WIFI_SUCCESS)
1289 goto cleanup;
1290
1291 vCommand->attr_end(nlData);
1292
1293 ret = vCommand->requestResponse();
1294 /* Don't check response since we aren't expecting one */
1295
1296 cleanup:
1297 delete vCommand;
1298 return ret;
1299 }
1300
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)1301 wifi_error wifi_start_sending_offloaded_packet(wifi_request_id id,
1302 wifi_interface_handle iface,
1303 u8 *ip_packet,
1304 u16 ip_packet_len,
1305 u8 *src_mac_addr,
1306 u8 *dst_mac_addr,
1307 u32 period_msec)
1308 {
1309 wifi_error ret;
1310 struct nlattr *nlData;
1311 WifiVendorCommand *vCommand = NULL;
1312
1313 ret = initialize_vendor_cmd(iface, id,
1314 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
1315 &vCommand);
1316 if (ret != WIFI_SUCCESS) {
1317 ALOGE("%s: Initialization failed", __func__);
1318 return ret;
1319 }
1320
1321 ALOGV("ip packet length : %u\nIP Packet:", ip_packet_len);
1322 hexdump(ip_packet, ip_packet_len);
1323 ALOGV("Src Mac Address: " MAC_ADDR_STR "\nDst Mac Address: " MAC_ADDR_STR
1324 "\nPeriod in msec : %u", MAC_ADDR_ARRAY(src_mac_addr),
1325 MAC_ADDR_ARRAY(dst_mac_addr), period_msec);
1326
1327 /* Add the vendor specific attributes for the NL command. */
1328 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1329 if (!nlData)
1330 goto cleanup;
1331
1332 ret = vCommand->put_u32(
1333 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
1334 QCA_WLAN_OFFLOADED_PACKETS_SENDING_START);
1335 if (ret != WIFI_SUCCESS)
1336 goto cleanup;
1337
1338 ret = vCommand->put_u32(
1339 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
1340 id);
1341 if (ret != WIFI_SUCCESS)
1342 goto cleanup;
1343
1344 ret = vCommand->put_bytes(
1345 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET,
1346 (const char *)ip_packet, ip_packet_len);
1347 if (ret != WIFI_SUCCESS)
1348 goto cleanup;
1349
1350 ret = vCommand->put_addr(
1351 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR,
1352 src_mac_addr);
1353 if (ret != WIFI_SUCCESS)
1354 goto cleanup;
1355
1356 ret = vCommand->put_addr(
1357 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR,
1358 dst_mac_addr);
1359 if (ret != WIFI_SUCCESS)
1360 goto cleanup;
1361
1362 ret = vCommand->put_u32(
1363 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD,
1364 period_msec);
1365 if (ret != WIFI_SUCCESS)
1366 goto cleanup;
1367
1368 vCommand->attr_end(nlData);
1369
1370 ret = vCommand->requestResponse();
1371 if (ret != WIFI_SUCCESS)
1372 goto cleanup;
1373
1374 cleanup:
1375 delete vCommand;
1376 return ret;
1377 }
1378
wifi_stop_sending_offloaded_packet(wifi_request_id id,wifi_interface_handle iface)1379 wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id id,
1380 wifi_interface_handle iface)
1381 {
1382 wifi_error ret;
1383 struct nlattr *nlData;
1384 WifiVendorCommand *vCommand = NULL;
1385
1386 ret = initialize_vendor_cmd(iface, id,
1387 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
1388 &vCommand);
1389 if (ret != WIFI_SUCCESS) {
1390 ALOGE("%s: Initialization failed", __func__);
1391 return ret;
1392 }
1393
1394 /* Add the vendor specific attributes for the NL command. */
1395 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1396 if (!nlData)
1397 goto cleanup;
1398
1399 ret = vCommand->put_u32(
1400 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
1401 QCA_WLAN_OFFLOADED_PACKETS_SENDING_STOP);
1402 if (ret != WIFI_SUCCESS)
1403 goto cleanup;
1404
1405 ret = vCommand->put_u32(
1406 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
1407 id);
1408 if (ret != WIFI_SUCCESS)
1409 goto cleanup;
1410
1411 vCommand->attr_end(nlData);
1412
1413 ret = vCommand->requestResponse();
1414 if (ret != WIFI_SUCCESS)
1415 goto cleanup;
1416
1417 cleanup:
1418 delete vCommand;
1419 return ret;
1420 }
1421
wifi_set_packet_filter(wifi_interface_handle iface,const u8 * program,u32 len)1422 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
1423 const u8 *program, u32 len)
1424 {
1425 wifi_error ret;
1426 struct nlattr *nlData;
1427 WifiVendorCommand *vCommand = NULL;
1428 u32 current_offset = 0;
1429 wifi_handle wifiHandle = getWifiHandle(iface);
1430 hal_info *info = getHalInfo(wifiHandle);
1431
1432 /* len=0 clears the filters in driver/firmware */
1433 if (len != 0 && program == NULL) {
1434 ALOGE("%s: No valid program provided. Exit.",
1435 __func__);
1436 return WIFI_ERROR_INVALID_ARGS;
1437 }
1438
1439 do {
1440 ret = initialize_vendor_cmd(iface, get_requestid(),
1441 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
1442 &vCommand);
1443 if (ret != WIFI_SUCCESS) {
1444 ALOGE("%s: Initialization failed", __FUNCTION__);
1445 return ret;
1446 }
1447
1448 /* Add the vendor specific attributes for the NL command. */
1449 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1450 if (!nlData)
1451 goto cleanup;
1452
1453 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
1454 QCA_WLAN_SET_PACKET_FILTER);
1455 if (ret != WIFI_SUCCESS)
1456 goto cleanup;
1457 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
1458 PACKET_FILTER_ID);
1459 if (ret != WIFI_SUCCESS)
1460 goto cleanup;
1461 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH,
1462 len);
1463 if (ret != WIFI_SUCCESS)
1464 goto cleanup;
1465 ret = vCommand->put_u32(
1466 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
1467 current_offset);
1468 if (ret != WIFI_SUCCESS)
1469 goto cleanup;
1470
1471 if (len) {
1472 ret = vCommand->put_bytes(
1473 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
1474 (char *)&program[current_offset],
1475 min(info->firmware_bus_max_size,
1476 len-current_offset));
1477 if (ret!= WIFI_SUCCESS) {
1478 ALOGE("%s: failed to put program", __FUNCTION__);
1479 goto cleanup;
1480 }
1481 }
1482
1483 vCommand->attr_end(nlData);
1484
1485 ret = vCommand->requestResponse();
1486 if (ret != WIFI_SUCCESS) {
1487 ALOGE("%s: requestResponse Error:%d",__func__, ret);
1488 goto cleanup;
1489 }
1490
1491 /* destroy the object after sending each fragment to driver */
1492 delete vCommand;
1493 vCommand = NULL;
1494
1495 current_offset += min(info->firmware_bus_max_size, len);
1496 } while (current_offset < len);
1497
1498 info->apf_enabled = !!len;
1499
1500 cleanup:
1501 if (vCommand)
1502 delete vCommand;
1503 return ret;
1504 }
1505
wifi_get_packet_filter_capabilities(wifi_interface_handle handle,u32 * version,u32 * max_len)1506 static wifi_error wifi_get_packet_filter_capabilities(
1507 wifi_interface_handle handle, u32 *version, u32 *max_len)
1508 {
1509 wifi_error ret;
1510 struct nlattr *nlData;
1511 WifihalGeneric *vCommand = NULL;
1512 interface_info *ifaceInfo = getIfaceInfo(handle);
1513 wifi_handle wifiHandle = getWifiHandle(handle);
1514
1515 if (version == NULL || max_len == NULL) {
1516 ALOGE("%s: NULL version/max_len pointer provided. Exit.",
1517 __FUNCTION__);
1518 return WIFI_ERROR_INVALID_ARGS;
1519 }
1520
1521 vCommand = new WifihalGeneric(wifiHandle, 0,
1522 OUI_QCA,
1523 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
1524 if (vCommand == NULL) {
1525 ALOGE("%s: Error vCommand NULL", __FUNCTION__);
1526 return WIFI_ERROR_OUT_OF_MEMORY;
1527 }
1528
1529 /* Create the message */
1530 ret = vCommand->create();
1531 if (ret != WIFI_SUCCESS)
1532 goto cleanup;
1533
1534 ret = vCommand->set_iface_id(ifaceInfo->name);
1535 if (ret != WIFI_SUCCESS)
1536 goto cleanup;
1537
1538 /* Add the vendor specific attributes for the NL command. */
1539 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1540 if (!nlData)
1541 goto cleanup;
1542
1543 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
1544 QCA_WLAN_GET_PACKET_FILTER_SIZE);
1545 if (ret != WIFI_SUCCESS)
1546 goto cleanup;
1547
1548 vCommand->attr_end(nlData);
1549
1550 ret = vCommand->requestResponse();
1551 if (ret != WIFI_SUCCESS) {
1552 ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
1553 if (ret == WIFI_ERROR_NOT_SUPPORTED) {
1554 /* Packet filtering is not supported currently, so return version
1555 * and length as 0
1556 */
1557 ALOGI("Packet filtering is not supprted");
1558 *version = 0;
1559 *max_len = 0;
1560 ret = WIFI_SUCCESS;
1561 }
1562 goto cleanup;
1563 }
1564
1565 *version = vCommand->getFilterVersion();
1566 *max_len = vCommand->getFilterLength();
1567 cleanup:
1568 delete vCommand;
1569 return ret;
1570 }
1571
1572
wifi_configure_nd_offload(wifi_interface_handle iface,u8 enable)1573 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
1574 u8 enable)
1575 {
1576 wifi_error ret;
1577 struct nlattr *nlData;
1578 WifiVendorCommand *vCommand = NULL;
1579
1580 ret = initialize_vendor_cmd(iface, get_requestid(),
1581 QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
1582 &vCommand);
1583 if (ret != WIFI_SUCCESS) {
1584 ALOGE("%s: Initialization failed", __func__);
1585 return ret;
1586 }
1587
1588 ALOGV("ND offload : %s", enable?"Enable":"Disable");
1589
1590 /* Add the vendor specific attributes for the NL command. */
1591 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1592 if (!nlData)
1593 goto cleanup;
1594
1595 ret = vCommand->put_u8(QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG, enable);
1596 if (ret != WIFI_SUCCESS)
1597 goto cleanup;
1598
1599 vCommand->attr_end(nlData);
1600
1601 ret = vCommand->requestResponse();
1602
1603 cleanup:
1604 delete vCommand;
1605 return ret;
1606 }
1607
1608 /**
1609 * Copy 'len' bytes of raw data from host memory at source address 'program'
1610 * to APF (Android Packet Filter) working memory starting at offset 'dst_offset'.
1611 * The size of the program lenght passed to the interpreter is set to
1612 * 'progaram_lenght'
1613 *
1614 * The implementation is allowed to tranlate this wrtie into a series of smaller
1615 * writes,but this function is not allowed to return untill all write operations
1616 * have been completed
1617 * additionally visible memory not targeted by this function must remain
1618 * unchanged
1619
1620 * @param dst_offset write offset in bytes relative to the beginning of the APF
1621 * working memory with logical address 0X000. Must be a multiple of 4
1622 *
1623 * @param program host memory to copy bytes from. Must be 4B aligned
1624 *
1625 * @param len the number of bytes to copy from the bost into the APF working
1626 * memory
1627 *
1628 * @param program_length new length of the program instructions in bytes to pass
1629 * to the interpreter
1630 */
1631
wifi_write_packet_filter(wifi_interface_handle iface,u32 dst_offset,const u8 * program,u32 len,u32 program_length)1632 wifi_error wifi_write_packet_filter(wifi_interface_handle iface,
1633 u32 dst_offset, const u8 *program,
1634 u32 len, u32 program_length)
1635 {
1636 wifi_error ret;
1637 struct nlattr *nlData;
1638 WifiVendorCommand *vCommand = NULL;
1639 u32 current_offset = 0;
1640 wifi_handle wifiHandle = getWifiHandle(iface);
1641 hal_info *info = getHalInfo(wifiHandle);
1642
1643 /* len=0 clears the filters in driver/firmware */
1644 if (len != 0 && program == NULL) {
1645 ALOGE("%s: No valid program provided. Exit.",
1646 __func__);
1647 return WIFI_ERROR_INVALID_ARGS;
1648 }
1649
1650 do {
1651 ret = initialize_vendor_cmd(iface, get_requestid(),
1652 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
1653 &vCommand);
1654 if (ret != WIFI_SUCCESS) {
1655 ALOGE("%s: Initialization failed", __FUNCTION__);
1656 return ret;
1657 }
1658
1659 /* Add the vendor specific attributes for the NL command. */
1660 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1661 if (!nlData)
1662 goto cleanup;
1663
1664 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
1665 QCA_WLAN_WRITE_PACKET_FILTER);
1666 if (ret != WIFI_SUCCESS)
1667 goto cleanup;
1668 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
1669 PACKET_FILTER_ID);
1670 if (ret != WIFI_SUCCESS)
1671 goto cleanup;
1672 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH,
1673 len);
1674 if (ret != WIFI_SUCCESS)
1675 goto cleanup;
1676 ret = vCommand->put_u32(
1677 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
1678 dst_offset + current_offset);
1679 if (ret != WIFI_SUCCESS)
1680 goto cleanup;
1681 ret = vCommand->put_u32(
1682 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROG_LENGTH,
1683 program_length);
1684 if (ret != WIFI_SUCCESS)
1685 goto cleanup;
1686
1687 ret = vCommand->put_bytes(
1688 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
1689 (char *)&program[current_offset],
1690 min(info->firmware_bus_max_size,
1691 len - current_offset));
1692 if (ret!= WIFI_SUCCESS) {
1693 ALOGE("%s: failed to put program", __FUNCTION__);
1694 goto cleanup;
1695 }
1696
1697 vCommand->attr_end(nlData);
1698
1699 ret = vCommand->requestResponse();
1700 if (ret != WIFI_SUCCESS) {
1701 ALOGE("%s: requestResponse Error:%d",__func__, ret);
1702 goto cleanup;
1703 }
1704
1705 /* destroy the object after sending each fragment to driver */
1706 delete vCommand;
1707 vCommand = NULL;
1708
1709 current_offset += min(info->firmware_bus_max_size,
1710 len - current_offset);
1711 } while (current_offset < len);
1712
1713 cleanup:
1714 if (vCommand)
1715 delete vCommand;
1716 return ret;
1717 }
1718
wifi_enable_packet_filter(wifi_interface_handle handle,u32 enable)1719 wifi_error wifi_enable_packet_filter(wifi_interface_handle handle,
1720 u32 enable)
1721 {
1722 wifi_error ret;
1723 struct nlattr *nlData;
1724 WifiVendorCommand *vCommand = NULL;
1725 u32 subcmd;
1726 wifi_handle wifiHandle = getWifiHandle(handle);
1727 hal_info *info = getHalInfo(wifiHandle);
1728
1729 ret = initialize_vendor_cmd(handle, get_requestid(),
1730 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
1731 &vCommand);
1732
1733 if (ret != WIFI_SUCCESS) {
1734 ALOGE("%s: Initialization failed", __func__);
1735 return ret;
1736 }
1737 /* Add the vendor specific attributes for the NL command. */
1738 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1739 if (!nlData)
1740 goto cleanup;
1741
1742 subcmd = enable ? QCA_WLAN_ENABLE_PACKET_FILTER :
1743 QCA_WLAN_DISABLE_PACKET_FILTER;
1744 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
1745 subcmd);
1746 if (ret != WIFI_SUCCESS)
1747 goto cleanup;
1748
1749 vCommand->attr_end(nlData);
1750 ret = vCommand->requestResponse();
1751
1752 if (ret != WIFI_SUCCESS) {
1753 ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
1754 goto cleanup;
1755 }
1756
1757 info->apf_enabled = !!enable;
1758
1759 cleanup:
1760 if (vCommand)
1761 delete vCommand;
1762 return ret;
1763
1764 }
1765
1766 /**
1767 * Copy 'length' bytes of raw data from APF (Android Packet Filter) working
1768 * memory to host memory starting at offset src_offset into host memory
1769 * pointed to by host_dst.
1770 * Memory can be text, data or some combination of the two. The implementiion is
1771 * allowed to translate this read into a series of smaller reads, but this
1772 * function is not allowed to return untill all the reads operations
1773 * into host_dst have been completed.
1774 *
1775 * @param src_offset offset in bytes of destination memory within APF working
1776 * memory
1777 *
1778 * @param host_dst host memory to copy into. Must be 4B aligned.
1779 *
1780 * @param length the number of bytes to copy from the APF working memory to the
1781 * host.
1782 */
1783
wifi_read_packet_filter(wifi_interface_handle handle,u32 src_offset,u8 * host_dst,u32 length)1784 static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
1785 u32 src_offset, u8 *host_dst, u32 length)
1786 {
1787 wifi_error ret;
1788 struct nlattr *nlData;
1789 WifihalGeneric *vCommand = NULL;
1790 interface_info *ifaceInfo = getIfaceInfo(handle);
1791 wifi_handle wifiHandle = getWifiHandle(handle);
1792 hal_info *info = getHalInfo(wifiHandle);
1793
1794 /*Temporary varibles to support the read complete length in chunks */
1795 u8 *temp_host_dst;
1796 u32 remainingLengthToBeRead, currentLength;
1797 u8 apf_locally_disabled = 0;
1798
1799 /*Initializing the temporary variables*/
1800 temp_host_dst = host_dst;
1801 remainingLengthToBeRead = length;
1802
1803 if (info->apf_enabled) {
1804 /* Disable APF only when not disabled by framework before calling
1805 * wifi_read_packet_filter()
1806 */
1807 ret = wifi_enable_packet_filter(handle, 0);
1808 if (ret != WIFI_SUCCESS) {
1809 ALOGE("%s: Failed to disable APF", __FUNCTION__);
1810 return ret;
1811 }
1812 apf_locally_disabled = 1;
1813 }
1814 /**
1815 * Read the complete length in chunks of size less or equal to firmware bus
1816 * max size
1817 */
1818 while (remainingLengthToBeRead)
1819 {
1820 vCommand = new WifihalGeneric(wifiHandle, 0, OUI_QCA,
1821 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
1822
1823 if (vCommand == NULL) {
1824 ALOGE("%s: Error vCommand NULL", __FUNCTION__);
1825 ret = WIFI_ERROR_OUT_OF_MEMORY;
1826 break;
1827 }
1828
1829 /* Create the message */
1830 ret = vCommand->create();
1831 if (ret != WIFI_SUCCESS)
1832 break;
1833 ret = vCommand->set_iface_id(ifaceInfo->name);
1834 if (ret != WIFI_SUCCESS)
1835 break;
1836 /* Add the vendor specific attributes for the NL command. */
1837 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1838 if (!nlData)
1839 break;
1840 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
1841 QCA_WLAN_READ_PACKET_FILTER);
1842 if (ret != WIFI_SUCCESS)
1843 break;
1844
1845 currentLength = min(remainingLengthToBeRead, info->firmware_bus_max_size);
1846
1847 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH,
1848 currentLength);
1849 if (ret != WIFI_SUCCESS)
1850 break;
1851 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
1852 src_offset);
1853 if (ret != WIFI_SUCCESS)
1854 break;
1855
1856 vCommand->setPacketBufferParams(temp_host_dst, currentLength);
1857 vCommand->attr_end(nlData);
1858 ret = vCommand->requestResponse();
1859
1860 if (ret != WIFI_SUCCESS) {
1861 ALOGE("%s: requestResponse() error: %d current_len = %u, src_offset = %u",
1862 __FUNCTION__, ret, currentLength, src_offset);
1863 break;
1864 }
1865
1866 remainingLengthToBeRead -= currentLength;
1867 temp_host_dst += currentLength;
1868 src_offset += currentLength;
1869 delete vCommand;
1870 vCommand = NULL;
1871 }
1872
1873 /* Re enable APF only when disabled above within this API */
1874 if (apf_locally_disabled) {
1875 wifi_error status;
1876 status = wifi_enable_packet_filter(handle, 1);
1877 if (status != WIFI_SUCCESS)
1878 ALOGE("%s: Failed to enable APF", __FUNCTION__);
1879 /* Prefer to return read status if read fails */
1880 if (ret == WIFI_SUCCESS)
1881 ret = status;
1882 }
1883
1884 delete vCommand;
1885 return ret;
1886 }
1887