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