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 "list.h"
45 #include <unistd.h>
46
47 #include "sync.h"
48
49 #define LOG_TAG "WifiHAL"
50
51 #include "wifi_hal.h"
52 #include "wifi_hal_ctrl.h"
53 #include "common.h"
54 #include "cpp_bindings.h"
55 #include "ifaceeventhandler.h"
56 #include "wifiloggercmd.h"
57
58 /*
59 BUGBUG: normally, libnl allocates ports for all connections it makes; but
60 being a static library, it doesn't really know how many other netlink
61 connections are made by the same process, if connections come from different
62 shared libraries. These port assignments exist to solve that
63 problem - temporarily. We need to fix libnl to try and allocate ports across
64 the entire process.
65 */
66
67 #define WIFI_HAL_CMD_SOCK_PORT 644
68 #define WIFI_HAL_EVENT_SOCK_PORT 645
69
70 #define MAX_HW_VER_LENGTH 100
71 /*
72 * Defines for wifi_wait_for_driver_ready()
73 * Specify durations between polls and max wait time
74 */
75 #define POLL_DRIVER_DURATION_US (100000)
76 #define POLL_DRIVER_MAX_TIME_MS (10000)
77
78 static int attach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg);
79
80 static int dettach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg);
81
82 static int register_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg, int attach);
83
84 static int send_nl_data(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg);
85
86 static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock);
87
88 static void internal_event_handler_app(wifi_handle handle, int events,
89 struct ctrl_sock *sock);
90
91 static void internal_event_handler(wifi_handle handle, int events,
92 struct nl_sock *sock);
93 static int internal_valid_message_handler(nl_msg *msg, void *arg);
94 static int user_sock_message_handler(nl_msg *msg, void *arg);
95 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
96 const char *group);
97 static int wifi_add_membership(wifi_handle handle, const char *group);
98 static wifi_error wifi_init_interfaces(wifi_handle handle);
99 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
100 const u8 *program, u32 len);
101 static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
102 u32 *version, u32 *max_len);
103 static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
104 u32 src_offset, u8 *host_dst, u32 length);
105 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
106 u8 enable);
107 wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,
108 WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt);
109
110 /* Initialize/Cleanup */
111
wifi_get_iface_handle(wifi_handle handle,char * name)112 wifi_interface_handle wifi_get_iface_handle(wifi_handle handle, char *name)
113 {
114 hal_info *info = (hal_info *)handle;
115 for (int i=0;i<info->num_interfaces;i++)
116 {
117 if (!strcmp(info->interfaces[i]->name, name))
118 {
119 return ((wifi_interface_handle )(info->interfaces)[i]);
120 }
121 }
122 return NULL;
123 }
124
wifi_socket_set_local_port(struct nl_sock * sock,uint32_t port)125 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
126 {
127 /* Release local port pool maintained by libnl and assign a own port
128 * identifier to the socket.
129 */
130 nl_socket_set_local_port(sock, ((uint32_t)getpid() & 0x3FFFFFU) | (port << 22));
131 }
132
wifi_create_nl_socket(int port,int protocol)133 static nl_sock * wifi_create_nl_socket(int port, int protocol)
134 {
135 // ALOGI("Creating socket");
136 struct nl_sock *sock = nl_socket_alloc();
137 if (sock == NULL) {
138 ALOGE("Failed to create NL socket");
139 return NULL;
140 }
141
142 wifi_socket_set_local_port(sock, port);
143
144 if (nl_connect(sock, protocol)) {
145 ALOGE("Could not connect handle");
146 nl_socket_free(sock);
147 return NULL;
148 }
149
150 return sock;
151 }
152
wifi_create_ctrl_socket(hal_info * info)153 void wifi_create_ctrl_socket(hal_info *info)
154 {
155 #ifdef ANDROID
156 struct group *grp_wifi;
157 gid_t gid_wifi;
158 struct passwd *pwd_system;
159 uid_t uid_system;
160 #endif
161
162 int flags;
163
164 info->wifihal_ctrl_sock.s = socket(PF_UNIX, SOCK_DGRAM, 0);
165
166 if (info->wifihal_ctrl_sock.s < 0) {
167 ALOGE("socket(PF_UNIX): %s", strerror(errno));
168 return;
169 }
170 memset(&info->wifihal_ctrl_sock.local, 0, sizeof(info->wifihal_ctrl_sock.local));
171
172 info->wifihal_ctrl_sock.local.sun_family = AF_UNIX;
173
174 snprintf(info->wifihal_ctrl_sock.local.sun_path,
175 sizeof(info->wifihal_ctrl_sock.local.sun_path), "%s", WIFI_HAL_CTRL_IFACE);
176
177 if (bind(info->wifihal_ctrl_sock.s, (struct sockaddr *) &info->wifihal_ctrl_sock.local,
178 sizeof(info->wifihal_ctrl_sock.local)) < 0) {
179 ALOGD("ctrl_iface bind(PF_UNIX) failed: %s",
180 strerror(errno));
181 if (connect(info->wifihal_ctrl_sock.s, (struct sockaddr *) &info->wifihal_ctrl_sock.local,
182 sizeof(info->wifihal_ctrl_sock.local)) < 0) {
183 ALOGD("ctrl_iface exists, but does not"
184 " allow connections - assuming it was left"
185 "over from forced program termination");
186 if (unlink(info->wifihal_ctrl_sock.local.sun_path) < 0) {
187 ALOGE("Could not unlink existing ctrl_iface socket '%s': %s",
188 info->wifihal_ctrl_sock.local.sun_path, strerror(errno));
189 goto out;
190
191 }
192 if (bind(info->wifihal_ctrl_sock.s ,
193 (struct sockaddr *) &info->wifihal_ctrl_sock.local,
194 sizeof(info->wifihal_ctrl_sock.local)) < 0) {
195 ALOGE("wifihal-ctrl-iface-init: bind(PF_UNIX): %s",
196 strerror(errno));
197 goto out;
198 }
199 ALOGD("Successfully replaced leftover "
200 "ctrl_iface socket '%s'", info->wifihal_ctrl_sock.local.sun_path);
201 } else {
202 ALOGI("ctrl_iface exists and seems to "
203 "be in use - cannot override it");
204 ALOGI("Delete '%s' manually if it is "
205 "not used anymore", info->wifihal_ctrl_sock.local.sun_path);
206 goto out;
207 }
208 }
209
210 /*
211 * Make socket non-blocking so that we don't hang forever if
212 * target dies unexpectedly.
213 */
214
215 #ifdef ANDROID
216 if (chmod(info->wifihal_ctrl_sock.local.sun_path, S_IRWXU | S_IRWXG) < 0)
217 {
218 ALOGE("Failed to give permissions: %s", strerror(errno));
219 }
220
221 /* Set group even if we do not have privileges to change owner */
222 grp_wifi = getgrnam("wifi");
223 gid_wifi = grp_wifi ? grp_wifi->gr_gid : 0;
224 pwd_system = getpwnam("system");
225 uid_system = pwd_system ? pwd_system->pw_uid : 0;
226 if (!gid_wifi || !uid_system) {
227 ALOGE("Failed to get grp ids");
228 unlink(info->wifihal_ctrl_sock.local.sun_path);
229 goto out;
230 }
231 chown(info->wifihal_ctrl_sock.local.sun_path, -1, gid_wifi);
232 chown(info->wifihal_ctrl_sock.local.sun_path, uid_system, gid_wifi);
233 #endif
234
235 flags = fcntl(info->wifihal_ctrl_sock.s, F_GETFL);
236 if (flags >= 0) {
237 flags |= O_NONBLOCK;
238 if (fcntl(info->wifihal_ctrl_sock.s, F_SETFL, flags) < 0) {
239 ALOGI("fcntl(ctrl, O_NONBLOCK): %s",
240 strerror(errno));
241 /* Not fatal, continue on.*/
242 }
243 }
244 return;
245
246 out:
247 close(info->wifihal_ctrl_sock.s);
248 info->wifihal_ctrl_sock.s = 0;
249 return;
250 }
251
ack_handler(struct nl_msg * msg,void * arg)252 int ack_handler(struct nl_msg *msg, void *arg)
253 {
254 int *err = (int *)arg;
255 *err = 0;
256 return NL_STOP;
257 }
258
finish_handler(struct nl_msg * msg,void * arg)259 int finish_handler(struct nl_msg *msg, void *arg)
260 {
261 int *ret = (int *)arg;
262 *ret = 0;
263 return NL_SKIP;
264 }
265
error_handler(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)266 int error_handler(struct sockaddr_nl *nla,
267 struct nlmsgerr *err, void *arg)
268 {
269 int *ret = (int *)arg;
270 *ret = err->error;
271
272 ALOGV("%s invoked with error: %d", __func__, err->error);
273 return NL_SKIP;
274 }
no_seq_check(struct nl_msg * msg,void * arg)275 static int no_seq_check(struct nl_msg *msg, void *arg)
276 {
277 return NL_OK;
278 }
279
acquire_supported_features(wifi_interface_handle iface,feature_set * set)280 static wifi_error acquire_supported_features(wifi_interface_handle iface,
281 feature_set *set)
282 {
283 wifi_error ret;
284 interface_info *iinfo = getIfaceInfo(iface);
285 wifi_handle handle = getWifiHandle(iface);
286 *set = 0;
287
288 WifihalGeneric supportedFeatures(handle, 0,
289 OUI_QCA,
290 QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES);
291
292 /* create the message */
293 ret = supportedFeatures.create();
294 if (ret != WIFI_SUCCESS)
295 goto cleanup;
296
297 ret = supportedFeatures.set_iface_id(iinfo->name);
298 if (ret != WIFI_SUCCESS)
299 goto cleanup;
300
301 ret = supportedFeatures.requestResponse();
302 if (ret != WIFI_SUCCESS) {
303 ALOGE("%s: requestResponse Error:%d",__func__, ret);
304 goto cleanup;
305 }
306
307 supportedFeatures.getResponseparams(set);
308
309 cleanup:
310 return ret;
311 }
312
acquire_driver_supported_features(wifi_interface_handle iface,features_info * driver_features)313 static wifi_error acquire_driver_supported_features(wifi_interface_handle iface,
314 features_info *driver_features)
315 {
316 wifi_error ret;
317 interface_info *iinfo = getIfaceInfo(iface);
318 wifi_handle handle = getWifiHandle(iface);
319
320 WifihalGeneric driverFeatures(handle, 0,
321 OUI_QCA,
322 QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES);
323
324 /* create the message */
325 ret = driverFeatures.create();
326 if (ret != WIFI_SUCCESS)
327 goto cleanup;
328
329 ret = driverFeatures.set_iface_id(iinfo->name);
330 if (ret != WIFI_SUCCESS)
331 goto cleanup;
332
333 ret = driverFeatures.requestResponse();
334 if (ret != WIFI_SUCCESS) {
335 ALOGE("%s: requestResponse Error:%d",__func__, ret);
336 goto cleanup;
337 }
338
339 driverFeatures.getDriverFeatures(driver_features);
340
341 cleanup:
342 return mapKernelErrortoWifiHalError(ret);
343 }
344
wifi_get_capabilities(wifi_interface_handle handle)345 static wifi_error wifi_get_capabilities(wifi_interface_handle handle)
346 {
347 wifi_error ret;
348 int requestId;
349 WifihalGeneric *wifihalGeneric;
350 wifi_handle wifiHandle = getWifiHandle(handle);
351 hal_info *info = getHalInfo(wifiHandle);
352
353 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
354 ALOGE("%s: GSCAN is not supported by driver", __FUNCTION__);
355 return WIFI_ERROR_NOT_SUPPORTED;
356 }
357
358 /* No request id from caller, so generate one and pass it on to the driver.
359 * Generate it randomly.
360 */
361 requestId = get_requestid();
362
363 wifihalGeneric = new WifihalGeneric(
364 wifiHandle,
365 requestId,
366 OUI_QCA,
367 QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES);
368 if (!wifihalGeneric) {
369 ALOGE("%s: Failed to create object of WifihalGeneric class", __FUNCTION__);
370 return WIFI_ERROR_OUT_OF_MEMORY;
371 }
372
373 ret = wifihalGeneric->wifiGetCapabilities(handle);
374
375 delete wifihalGeneric;
376 return ret;
377 }
378
get_firmware_bus_max_size_supported(wifi_interface_handle iface)379 static wifi_error get_firmware_bus_max_size_supported(
380 wifi_interface_handle iface)
381 {
382 wifi_error ret;
383 interface_info *iinfo = getIfaceInfo(iface);
384 wifi_handle handle = getWifiHandle(iface);
385 hal_info *info = (hal_info *)handle;
386
387 WifihalGeneric busSizeSupported(handle, 0,
388 OUI_QCA,
389 QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE);
390
391 /* create the message */
392 ret = busSizeSupported.create();
393 if (ret != WIFI_SUCCESS)
394 goto cleanup;
395
396 ret = busSizeSupported.set_iface_id(iinfo->name);
397 if (ret != WIFI_SUCCESS)
398 goto cleanup;
399
400 ret = busSizeSupported.requestResponse();
401 if (ret != WIFI_SUCCESS) {
402 ALOGE("%s: requestResponse Error:%d", __FUNCTION__, ret);
403 goto cleanup;
404 }
405 info->firmware_bus_max_size = busSizeSupported.getBusSize();
406
407 cleanup:
408 return ret;
409 }
410
wifi_init_user_sock(hal_info * info)411 static wifi_error wifi_init_user_sock(hal_info *info)
412 {
413 struct nl_sock *user_sock =
414 wifi_create_nl_socket(WIFI_HAL_USER_SOCK_PORT, NETLINK_USERSOCK);
415 if (user_sock == NULL) {
416 ALOGE("Could not create diag sock");
417 return WIFI_ERROR_UNKNOWN;
418 }
419
420 /* Set the socket buffer size */
421 if (nl_socket_set_buffer_size(user_sock, (256*1024), 0) < 0) {
422 ALOGE("Could not set size for user_sock: %s",
423 strerror(errno));
424 /* continue anyway with the default (smaller) buffer */
425 }
426 else {
427 ALOGV("nl_socket_set_buffer_size successful for user_sock");
428 }
429
430 struct nl_cb *cb = nl_socket_get_cb(user_sock);
431 if (cb == NULL) {
432 ALOGE("Could not get cb");
433 return WIFI_ERROR_UNKNOWN;
434 }
435
436 info->user_sock_arg = 1;
437 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
438 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg);
439 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg);
440 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg);
441
442 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info);
443 nl_cb_put(cb);
444
445 int ret = nl_socket_add_membership(user_sock, 1);
446 if (ret < 0) {
447 ALOGE("Could not add membership");
448 return WIFI_ERROR_UNKNOWN;
449 }
450
451 info->user_sock = user_sock;
452 ALOGV("Initiialized diag sock successfully");
453 return WIFI_SUCCESS;
454 }
455
wifi_init_cld80211_sock_cb(hal_info * info)456 static wifi_error wifi_init_cld80211_sock_cb(hal_info *info)
457 {
458 struct nl_cb *cb = nl_socket_get_cb(info->cldctx->sock);
459 if (cb == NULL) {
460 ALOGE("Could not get cb");
461 return WIFI_ERROR_UNKNOWN;
462 }
463
464 info->user_sock_arg = 1;
465 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
466 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg);
467 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg);
468 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg);
469
470 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info);
471 nl_cb_put(cb);
472
473 return WIFI_SUCCESS;
474 }
475
476
477 /*initialize function pointer table with Qualcomm HAL API*/
init_wifi_vendor_hal_func_table(wifi_hal_fn * fn)478 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) {
479 if (fn == NULL) {
480 return WIFI_ERROR_UNKNOWN;
481 }
482
483 fn->wifi_initialize = wifi_initialize;
484 fn->wifi_wait_for_driver_ready = wifi_wait_for_driver_ready;
485 fn->wifi_cleanup = wifi_cleanup;
486 fn->wifi_event_loop = wifi_event_loop;
487 fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
488 fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
489 fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui;
490 fn->wifi_get_ifaces = wifi_get_ifaces;
491 fn->wifi_get_iface_name = wifi_get_iface_name;
492 fn->wifi_set_iface_event_handler = wifi_set_iface_event_handler;
493 fn->wifi_reset_iface_event_handler = wifi_reset_iface_event_handler;
494 fn->wifi_start_gscan = wifi_start_gscan;
495 fn->wifi_stop_gscan = wifi_stop_gscan;
496 fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
497 fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
498 fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
499 fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
500 fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
501 fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
502 fn->wifi_set_link_stats = wifi_set_link_stats;
503 fn->wifi_get_link_stats = wifi_get_link_stats;
504 fn->wifi_clear_link_stats = wifi_clear_link_stats;
505 fn->wifi_get_valid_channels = wifi_get_valid_channels;
506 fn->wifi_rtt_range_request = wifi_rtt_range_request;
507 fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
508 fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
509 fn->wifi_rtt_get_responder_info = wifi_rtt_get_responder_info;
510 fn->wifi_enable_responder = wifi_enable_responder;
511 fn->wifi_disable_responder = wifi_disable_responder;
512 fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
513 fn->wifi_start_logging = wifi_start_logging;
514 fn->wifi_set_epno_list = wifi_set_epno_list;
515 fn->wifi_reset_epno_list = wifi_reset_epno_list;
516 fn->wifi_set_country_code = wifi_set_country_code;
517 fn->wifi_enable_tdls = wifi_enable_tdls;
518 fn->wifi_disable_tdls = wifi_disable_tdls;
519 fn->wifi_get_tdls_status = wifi_get_tdls_status;
520 fn->wifi_get_tdls_capabilities = wifi_get_tdls_capabilities;
521 fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
522 fn->wifi_set_log_handler = wifi_set_log_handler;
523 fn->wifi_reset_log_handler = wifi_reset_log_handler;
524 fn->wifi_set_alert_handler = wifi_set_alert_handler;
525 fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
526 fn->wifi_get_firmware_version = wifi_get_firmware_version;
527 fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
528 fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;
529 fn->wifi_get_ring_data = wifi_get_ring_data;
530 fn->wifi_get_driver_version = wifi_get_driver_version;
531 fn->wifi_set_passpoint_list = wifi_set_passpoint_list;
532 fn->wifi_reset_passpoint_list = wifi_reset_passpoint_list;
533 fn->wifi_set_lci = wifi_set_lci;
534 fn->wifi_set_lcr = wifi_set_lcr;
535 fn->wifi_start_sending_offloaded_packet =
536 wifi_start_sending_offloaded_packet;
537 fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
538 fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
539 fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
540 fn->wifi_nan_enable_request = nan_enable_request;
541 fn->wifi_nan_disable_request = nan_disable_request;
542 fn->wifi_nan_publish_request = nan_publish_request;
543 fn->wifi_nan_publish_cancel_request = nan_publish_cancel_request;
544 fn->wifi_nan_subscribe_request = nan_subscribe_request;
545 fn->wifi_nan_subscribe_cancel_request = nan_subscribe_cancel_request;
546 fn->wifi_nan_transmit_followup_request = nan_transmit_followup_request;
547 fn->wifi_nan_stats_request = nan_stats_request;
548 fn->wifi_nan_config_request = nan_config_request;
549 fn->wifi_nan_tca_request = nan_tca_request;
550 fn->wifi_nan_beacon_sdf_payload_request = nan_beacon_sdf_payload_request;
551 fn->wifi_nan_register_handler = nan_register_handler;
552 fn->wifi_nan_get_version = nan_get_version;
553 fn->wifi_set_packet_filter = wifi_set_packet_filter;
554 fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
555 fn->wifi_read_packet_filter = wifi_read_packet_filter;
556 fn->wifi_nan_get_capabilities = nan_get_capabilities;
557 fn->wifi_nan_data_interface_create = nan_data_interface_create;
558 fn->wifi_nan_data_interface_delete = nan_data_interface_delete;
559 fn->wifi_nan_data_request_initiator = nan_data_request_initiator;
560 fn->wifi_nan_data_indication_response = nan_data_indication_response;
561 fn->wifi_nan_data_end = nan_data_end;
562 fn->wifi_configure_nd_offload = wifi_configure_nd_offload;
563 fn->wifi_get_driver_memory_dump = wifi_get_driver_memory_dump;
564 fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats;
565 fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring;
566 fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;
567 fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;
568 fn->wifi_get_roaming_capabilities = wifi_get_roaming_capabilities;
569 fn->wifi_configure_roaming = wifi_configure_roaming;
570 fn->wifi_enable_firmware_roaming = wifi_enable_firmware_roaming;
571 fn->wifi_select_tx_power_scenario = wifi_select_tx_power_scenario;
572 fn->wifi_reset_tx_power_scenario = wifi_reset_tx_power_scenario;
573 fn->wifi_set_radio_mode_change_handler = wifi_set_radio_mode_change_handler;
574 fn->wifi_set_latency_mode = wifi_set_latency_mode;
575
576 return WIFI_SUCCESS;
577 }
578
cld80211lib_cleanup(hal_info * info)579 static void cld80211lib_cleanup(hal_info *info)
580 {
581 if (!info->cldctx)
582 return;
583 cld80211_remove_mcast_group(info->cldctx, "host_logs");
584 cld80211_remove_mcast_group(info->cldctx, "fw_logs");
585 cld80211_remove_mcast_group(info->cldctx, "per_pkt_stats");
586 cld80211_remove_mcast_group(info->cldctx, "diag_events");
587 cld80211_remove_mcast_group(info->cldctx, "fatal_events");
588 cld80211_remove_mcast_group(info->cldctx, "oem_msgs");
589 exit_cld80211_recv(info->cldctx);
590 cld80211_deinit(info->cldctx);
591 info->cldctx = NULL;
592 }
593
wifi_get_iface_id(hal_info * info,const char * iface)594 static int wifi_get_iface_id(hal_info *info, const char *iface)
595 {
596 int i;
597 for (i = 0; i < info->num_interfaces; i++)
598 if (!strcmp(info->interfaces[i]->name, iface))
599 return i;
600 return -1;
601 }
602
wifi_initialize(wifi_handle * handle)603 wifi_error wifi_initialize(wifi_handle *handle)
604 {
605 wifi_error ret = WIFI_SUCCESS;
606 wifi_interface_handle iface_handle;
607 struct nl_sock *cmd_sock = NULL;
608 struct nl_sock *event_sock = NULL;
609 struct nl_cb *cb = NULL;
610 int status = 0;
611 int index;
612 char hw_ver_type[MAX_HW_VER_LENGTH];
613 char *hw_name = NULL;
614
615 ALOGI("Initializing wifi");
616 hal_info *info = (hal_info *)malloc(sizeof(hal_info));
617 if (info == NULL) {
618 ALOGE("Could not allocate hal_info");
619 return WIFI_ERROR_OUT_OF_MEMORY;
620 }
621
622 memset(info, 0, sizeof(*info));
623
624 cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT,
625 NETLINK_GENERIC);
626 if (cmd_sock == NULL) {
627 ALOGE("Failed to create command socket port");
628 ret = WIFI_ERROR_UNKNOWN;
629 goto unload;
630 }
631
632 /* Set the socket buffer size */
633 if (nl_socket_set_buffer_size(cmd_sock, (256*1024), 0) < 0) {
634 ALOGE("Could not set nl_socket RX buffer size for cmd_sock: %s",
635 strerror(errno));
636 /* continue anyway with the default (smaller) buffer */
637 }
638
639 event_sock =
640 wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT, NETLINK_GENERIC);
641 if (event_sock == NULL) {
642 ALOGE("Failed to create event socket port");
643 ret = WIFI_ERROR_UNKNOWN;
644 goto unload;
645 }
646
647 /* Set the socket buffer size */
648 if (nl_socket_set_buffer_size(event_sock, (256*1024), 0) < 0) {
649 ALOGE("Could not set nl_socket RX buffer size for event_sock: %s",
650 strerror(errno));
651 /* continue anyway with the default (smaller) buffer */
652 }
653
654 cb = nl_socket_get_cb(event_sock);
655 if (cb == NULL) {
656 ALOGE("Failed to get NL control block for event socket port");
657 ret = WIFI_ERROR_UNKNOWN;
658 goto unload;
659 }
660
661 info->event_sock_arg = 1;
662 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
663 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->event_sock_arg);
664 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->event_sock_arg);
665 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->event_sock_arg);
666
667 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler,
668 info);
669 nl_cb_put(cb);
670
671 info->cmd_sock = cmd_sock;
672 info->event_sock = event_sock;
673 info->clean_up = false;
674 info->in_event_loop = false;
675
676 info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
677 if (info->event_cb == NULL) {
678 ALOGE("Could not allocate event_cb");
679 ret = WIFI_ERROR_OUT_OF_MEMORY;
680 goto unload;
681 }
682 info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
683 info->num_event_cb = 0;
684
685 info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
686 if (info->nl80211_family_id < 0) {
687 ALOGE("Could not resolve nl80211 familty id");
688 ret = WIFI_ERROR_UNKNOWN;
689 goto unload;
690 }
691
692 pthread_mutex_init(&info->cb_lock, NULL);
693 pthread_mutex_init(&info->pkt_fate_stats_lock, NULL);
694
695 *handle = (wifi_handle) info;
696
697 wifi_add_membership(*handle, "scan");
698 wifi_add_membership(*handle, "mlme");
699 wifi_add_membership(*handle, "regulatory");
700 wifi_add_membership(*handle, "vendor");
701
702 info->wifihal_ctrl_sock.s = 0;
703
704 wifi_create_ctrl_socket(info);
705
706 //! Initailise the monitoring clients list
707 INITIALISE_LIST(&info->monitor_sockets);
708
709 info->cldctx = cld80211_init();
710 if (info->cldctx != NULL) {
711 info->user_sock = info->cldctx->sock;
712 ret = wifi_init_cld80211_sock_cb(info);
713 if (ret != WIFI_SUCCESS) {
714 ALOGE("Could not set cb for CLD80211 family");
715 goto cld80211_cleanup;
716 }
717
718 status = cld80211_add_mcast_group(info->cldctx, "host_logs");
719 if (status) {
720 ALOGE("Failed to add mcast group host_logs :%d", status);
721 goto cld80211_cleanup;
722 }
723 status = cld80211_add_mcast_group(info->cldctx, "fw_logs");
724 if (status) {
725 ALOGE("Failed to add mcast group fw_logs :%d", status);
726 goto cld80211_cleanup;
727 }
728 status = cld80211_add_mcast_group(info->cldctx, "per_pkt_stats");
729 if (status) {
730 ALOGE("Failed to add mcast group per_pkt_stats :%d", status);
731 goto cld80211_cleanup;
732 }
733 status = cld80211_add_mcast_group(info->cldctx, "diag_events");
734 if (status) {
735 ALOGE("Failed to add mcast group diag_events :%d", status);
736 goto cld80211_cleanup;
737 }
738 status = cld80211_add_mcast_group(info->cldctx, "fatal_events");
739 if (status) {
740 ALOGE("Failed to add mcast group fatal_events :%d", status);
741 goto cld80211_cleanup;
742 }
743
744 if(info->wifihal_ctrl_sock.s > 0)
745 {
746 status = cld80211_add_mcast_group(info->cldctx, "oem_msgs");
747 if (status) {
748 ALOGE("Failed to add mcast group oem_msgs :%d", status);
749 goto cld80211_cleanup;
750 }
751 }
752 } else {
753 ret = wifi_init_user_sock(info);
754 if (ret != WIFI_SUCCESS) {
755 ALOGE("Failed to alloc user socket");
756 goto unload;
757 }
758 }
759
760 ret = wifi_init_interfaces(*handle);
761 if (ret != WIFI_SUCCESS) {
762 ALOGE("Failed to init interfaces");
763 goto unload;
764 }
765
766 if (info->num_interfaces == 0) {
767 ALOGE("No interfaces found");
768 ret = WIFI_ERROR_UNINITIALIZED;
769 goto unload;
770 }
771
772 index = wifi_get_iface_id(info, "wlan0");
773 if (index == -1) {
774 int i;
775 for (i = 0; i < info->num_interfaces; i++)
776 {
777 free(info->interfaces[i]);
778 }
779 ALOGE("%s no iface with wlan0", __func__);
780 goto unload;
781 }
782 iface_handle = (wifi_interface_handle)info->interfaces[index];
783
784 ret = acquire_supported_features(iface_handle,
785 &info->supported_feature_set);
786 if (ret != WIFI_SUCCESS) {
787 ALOGI("Failed to get supported feature set : %d", ret);
788 //acquire_supported_features failure is acceptable condition as legacy
789 //drivers might not support the required vendor command. So, do not
790 //consider it as failure of wifi_initialize
791 ret = WIFI_SUCCESS;
792 }
793
794 ret = acquire_driver_supported_features(iface_handle,
795 &info->driver_supported_features);
796 if (ret != WIFI_SUCCESS) {
797 ALOGI("Failed to get vendor feature set : %d", ret);
798 ret = WIFI_SUCCESS;
799 }
800
801 ret = wifi_get_logger_supported_feature_set(iface_handle,
802 &info->supported_logger_feature_set);
803 if (ret != WIFI_SUCCESS)
804 ALOGE("Failed to get supported logger feature set: %d", ret);
805
806 ret = wifi_get_firmware_version(iface_handle, hw_ver_type,
807 MAX_HW_VER_LENGTH);
808 if (ret == WIFI_SUCCESS) {
809 hw_name = strstr(hw_ver_type, "HW:");
810 if (hw_name) {
811 hw_name += strlen("HW:");
812 if (strncmp(hw_name, "QCA6174", 7) == 0)
813 info->pkt_log_ver = PKT_LOG_V1;
814 else
815 info->pkt_log_ver = PKT_LOG_V2;
816 } else {
817 info->pkt_log_ver = PKT_LOG_V0;
818 }
819 ALOGV("%s: hardware version type %d", __func__, info->pkt_log_ver);
820 } else {
821 ALOGE("Failed to get firmware version: %d", ret);
822 }
823
824 ret = get_firmware_bus_max_size_supported(iface_handle);
825 if (ret != WIFI_SUCCESS) {
826 ALOGE("Failed to get supported bus size, error : %d", ret);
827 info->firmware_bus_max_size = 1520;
828 }
829
830 ret = wifi_logger_ring_buffers_init(info);
831 if (ret != WIFI_SUCCESS)
832 ALOGE("Wifi Logger Ring Initialization Failed");
833
834 ret = wifi_get_capabilities(iface_handle);
835 if (ret != WIFI_SUCCESS)
836 ALOGE("Failed to get wifi Capabilities, error: %d", ret);
837
838 info->pkt_stats = (struct pkt_stats_s *)malloc(sizeof(struct pkt_stats_s));
839 if (!info->pkt_stats) {
840 ALOGE("%s: malloc Failed for size: %zu",
841 __FUNCTION__, sizeof(struct pkt_stats_s));
842 ret = WIFI_ERROR_OUT_OF_MEMORY;
843 goto unload;
844 }
845
846 info->rx_buf_size_allocated = MAX_RXMPDUS_PER_AMPDU * MAX_MSDUS_PER_MPDU
847 * PKT_STATS_BUF_SIZE;
848
849 info->rx_aggr_pkts =
850 (wifi_ring_buffer_entry *)malloc(info->rx_buf_size_allocated);
851 if (!info->rx_aggr_pkts) {
852 ALOGE("%s: malloc Failed for size: %d",
853 __FUNCTION__, info->rx_buf_size_allocated);
854 ret = WIFI_ERROR_OUT_OF_MEMORY;
855 info->rx_buf_size_allocated = 0;
856 goto unload;
857 }
858 memset(info->rx_aggr_pkts, 0, info->rx_buf_size_allocated);
859
860 info->exit_sockets[0] = -1;
861 info->exit_sockets[1] = -1;
862
863 if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->exit_sockets) == -1) {
864 ALOGE("Failed to create exit socket pair");
865 ret = WIFI_ERROR_UNKNOWN;
866 goto unload;
867 }
868
869 ALOGV("Initializing Gscan Event Handlers");
870 ret = initializeGscanHandlers(info);
871 if (ret != WIFI_SUCCESS) {
872 ALOGE("Initializing Gscan Event Handlers Failed");
873 goto unload;
874 }
875
876 ret = initializeRSSIMonitorHandler(info);
877 if (ret != WIFI_SUCCESS) {
878 ALOGE("Initializing RSSI Event Handler Failed");
879 goto unload;
880 }
881
882 ALOGV("Initialized Wifi HAL Successfully; vendor cmd = %d Supported"
883 " features : %x", NL80211_CMD_VENDOR, info->supported_feature_set);
884
885 cld80211_cleanup:
886 if (status != 0 || ret != WIFI_SUCCESS) {
887 ret = WIFI_ERROR_UNKNOWN;
888 cld80211lib_cleanup(info);
889 }
890 unload:
891 if (ret != WIFI_SUCCESS) {
892 if (cmd_sock)
893 nl_socket_free(cmd_sock);
894 if (event_sock)
895 nl_socket_free(event_sock);
896 if (info) {
897 if (info->cldctx) {
898 cld80211lib_cleanup(info);
899 } else if (info->user_sock) {
900 nl_socket_free(info->user_sock);
901 }
902 if (info->pkt_stats) free(info->pkt_stats);
903 if (info->rx_aggr_pkts) free(info->rx_aggr_pkts);
904 wifi_logger_ring_buffers_deinit(info);
905 cleanupGscanHandlers(info);
906 cleanupRSSIMonitorHandler(info);
907 free(info->event_cb);
908 if (info->driver_supported_features.flags) {
909 free(info->driver_supported_features.flags);
910 info->driver_supported_features.flags = NULL;
911 }
912 free(info);
913 }
914 }
915
916 return ret;
917 }
918
wifi_wait_for_driver_ready(void)919 wifi_error wifi_wait_for_driver_ready(void)
920 {
921 // This function will wait to make sure basic client netdev is created
922 // Function times out after 10 seconds
923 int count = (POLL_DRIVER_MAX_TIME_MS * 1000) / POLL_DRIVER_DURATION_US;
924 FILE *fd;
925
926 do {
927 if ((fd = fopen("/sys/class/net/wlan0", "r")) != NULL) {
928 fclose(fd);
929 return WIFI_SUCCESS;
930 }
931 usleep(POLL_DRIVER_DURATION_US);
932 } while(--count > 0);
933
934 ALOGE("Timed out wating on Driver ready ... ");
935 return WIFI_ERROR_TIMED_OUT;
936 }
937
wifi_add_membership(wifi_handle handle,const char * group)938 static int wifi_add_membership(wifi_handle handle, const char *group)
939 {
940 hal_info *info = getHalInfo(handle);
941
942 int id = wifi_get_multicast_id(handle, "nl80211", group);
943 if (id < 0) {
944 ALOGE("Could not find group %s", group);
945 return id;
946 }
947
948 int ret = nl_socket_add_membership(info->event_sock, id);
949 if (ret < 0) {
950 ALOGE("Could not add membership to group %s", group);
951 }
952
953 return ret;
954 }
955
internal_cleaned_up_handler(wifi_handle handle)956 static void internal_cleaned_up_handler(wifi_handle handle)
957 {
958 hal_info *info = getHalInfo(handle);
959 wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
960 wifihal_mon_sock_t *reg, *tmp;
961
962 if (info->cmd_sock != 0) {
963 nl_socket_free(info->cmd_sock);
964 nl_socket_free(info->event_sock);
965 info->cmd_sock = NULL;
966 info->event_sock = NULL;
967 }
968
969 if (info->wifihal_ctrl_sock.s != 0) {
970 close(info->wifihal_ctrl_sock.s);
971 unlink(info->wifihal_ctrl_sock.local.sun_path);
972 info->wifihal_ctrl_sock.s = 0;
973 }
974
975 list_for_each_entry_safe(reg, tmp, &info->monitor_sockets, list) {
976 del_from_list(®->list);
977 if(reg) {
978 free(reg);
979 }
980 }
981
982 if (info->interfaces) {
983 for (int i = 0; i < info->num_interfaces; i++)
984 free(info->interfaces[i]);
985 free(info->interfaces);
986 }
987
988 if (info->cldctx != NULL) {
989 cld80211lib_cleanup(info);
990 } else if (info->user_sock != 0) {
991 nl_socket_free(info->user_sock);
992 info->user_sock = NULL;
993 }
994
995 if (info->pkt_stats)
996 free(info->pkt_stats);
997 if (info->rx_aggr_pkts)
998 free(info->rx_aggr_pkts);
999 wifi_logger_ring_buffers_deinit(info);
1000 cleanupGscanHandlers(info);
1001 cleanupRSSIMonitorHandler(info);
1002
1003 if (info->num_event_cb)
1004 ALOGE("%d events were leftover without being freed",
1005 info->num_event_cb);
1006 free(info->event_cb);
1007
1008 if (info->exit_sockets[0] >= 0) {
1009 close(info->exit_sockets[0]);
1010 info->exit_sockets[0] = -1;
1011 }
1012
1013 if (info->exit_sockets[1] >= 0) {
1014 close(info->exit_sockets[1]);
1015 info->exit_sockets[1] = -1;
1016 }
1017
1018 if (info->pkt_fate_stats) {
1019 free(info->pkt_fate_stats);
1020 info->pkt_fate_stats = NULL;
1021 }
1022
1023 if (info->driver_supported_features.flags) {
1024 free(info->driver_supported_features.flags);
1025 info->driver_supported_features.flags = NULL;
1026 }
1027
1028 (*cleaned_up_handler)(handle);
1029 pthread_mutex_destroy(&info->cb_lock);
1030 pthread_mutex_destroy(&info->pkt_fate_stats_lock);
1031 free(info);
1032 }
1033
wifi_cleanup(wifi_handle handle,wifi_cleaned_up_handler handler)1034 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
1035 {
1036 if (!handle) {
1037 ALOGE("Handle is null");
1038 return;
1039 }
1040
1041 hal_info *info = getHalInfo(handle);
1042 info->cleaned_up_handler = handler;
1043 info->clean_up = true;
1044
1045 TEMP_FAILURE_RETRY(write(info->exit_sockets[0], "E", 1));
1046 ALOGI("Sent msg on exit sock to unblock poll()");
1047 }
1048
1049
1050
validate_cld80211_msg(nlmsghdr * nlh,int family,int cmd)1051 static int validate_cld80211_msg(nlmsghdr *nlh, int family, int cmd)
1052 {
1053 //! Enhance this API
1054 struct genlmsghdr *hdr;
1055 hdr = (genlmsghdr *)nlmsg_data(nlh);
1056
1057 if (nlh->nlmsg_len > DEFAULT_PAGE_SIZE - sizeof(wifihal_ctrl_req_t))
1058 {
1059 ALOGE("%s: Invalid nlmsg length", __FUNCTION__);
1060 return -1;
1061 }
1062 if(hdr->cmd == WLAN_NL_MSG_OEM)
1063 {
1064 ALOGV("%s: FAMILY ID : %d ,NL CMD : %d received", __FUNCTION__,
1065 nlh->nlmsg_type, hdr->cmd);
1066
1067 //! Update pid with the wifihal pid
1068 nlh->nlmsg_pid = getpid();
1069 return 0;
1070 }
1071 else
1072 {
1073 ALOGE("%s: NL CMD : %d received is not allowed", __FUNCTION__, hdr->cmd);
1074 return -1;
1075 }
1076 }
1077
1078
validate_genl_msg(nlmsghdr * nlh,int family,int cmd)1079 static int validate_genl_msg(nlmsghdr *nlh, int family, int cmd)
1080 {
1081 //! Enhance this API
1082 struct genlmsghdr *hdr;
1083 hdr = (genlmsghdr *)nlmsg_data(nlh);
1084
1085 if (nlh->nlmsg_len > DEFAULT_PAGE_SIZE - sizeof(wifihal_ctrl_req_t))
1086 {
1087 ALOGE("%s: Invalid nlmsg length", __FUNCTION__);
1088 return -1;
1089 }
1090 if(hdr->cmd == NL80211_CMD_FRAME ||
1091 hdr->cmd == NL80211_CMD_REGISTER_ACTION)
1092 {
1093 ALOGV("%s: FAMILY ID : %d ,NL CMD : %d received", __FUNCTION__,
1094 nlh->nlmsg_type, hdr->cmd);
1095 return 0;
1096 }
1097 else
1098 {
1099 ALOGE("%s: NL CMD : %d received is not allowed", __FUNCTION__, hdr->cmd);
1100 return -1;
1101 }
1102 }
1103
send_nl_data(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg)1104 static int send_nl_data(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
1105 {
1106 hal_info *info = getHalInfo(handle);
1107 struct nl_msg *msg = NULL;
1108 int retval = -1;
1109
1110 //! attach monitor socket if it was not it the list
1111 if(ctrl_msg->monsock_len)
1112 {
1113 retval = attach_monitor_sock(handle, ctrl_msg);
1114 if(retval)
1115 goto nl_out;
1116 }
1117
1118 msg = nlmsg_alloc();
1119 if (!msg)
1120 {
1121 ALOGE("%s: Memory allocation failed \n", __FUNCTION__);
1122 goto nl_out;
1123 }
1124
1125 if (ctrl_msg->data_len > nlmsg_get_max_size(msg))
1126 {
1127 ALOGE("%s: Invalid ctrl msg length \n", __FUNCTION__);
1128 retval = -1;
1129 goto nl_out;
1130 }
1131 memcpy((char *)msg->nm_nlh, (char *)ctrl_msg->data, ctrl_msg->data_len);
1132
1133 if(ctrl_msg->family_name == GENERIC_NL_FAMILY)
1134 {
1135 //! Before sending the received gennlmsg to kernel,
1136 //! better to have checks for allowed commands
1137 retval = validate_genl_msg(msg->nm_nlh, ctrl_msg->family_name, ctrl_msg->cmd_id);
1138 if (retval < 0)
1139 goto nl_out;
1140
1141 retval = nl_send_auto_complete(info->event_sock, msg); /* send message */
1142 if (retval < 0)
1143 {
1144 ALOGE("%s: nl_send_auto_complete - failed : %d \n", __FUNCTION__, retval);
1145 goto nl_out;
1146 }
1147
1148 retval = internal_pollin_handler(handle, info->event_sock);
1149 }
1150 else if (ctrl_msg->family_name == CLD80211_FAMILY)
1151 {
1152 if (info->cldctx != NULL)
1153 {
1154 //! Before sending the received cld80211 msg to kernel,
1155 //! better to have checks for allowed commands
1156 retval = validate_cld80211_msg(msg->nm_nlh, ctrl_msg->family_name, ctrl_msg->cmd_id);
1157 if (retval < 0)
1158 goto nl_out;
1159
1160 retval = cld80211_send_msg(info->cldctx, msg);
1161 if (retval != 0)
1162 {
1163 ALOGE("%s: send cld80211 message - failed\n", __FUNCTION__);
1164 goto nl_out;
1165 }
1166 ALOGD("%s: sent cld80211 message for pid %d\n", __FUNCTION__, getpid());
1167 }
1168 else
1169 {
1170 ALOGE("%s: cld80211 ctx not present \n", __FUNCTION__);
1171 }
1172 }
1173 else
1174 {
1175 ALOGE("%s: Unknown family name : %d \n", __FUNCTION__, ctrl_msg->family_name);
1176 retval = -1;
1177 }
1178 nl_out:
1179 if (msg)
1180 {
1181 nlmsg_free(msg);
1182 }
1183 return retval;
1184 }
1185
register_monitor_sock(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg,int attach)1186 static int register_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg, int attach)
1187 {
1188 hal_info *info = getHalInfo(handle);
1189
1190 wifihal_mon_sock_t *reg, *nreg;
1191 char *match = NULL;
1192 unsigned int match_len = 0;
1193 unsigned int type;
1194
1195 //! For Register Action frames, compare the match length and match buffer.
1196 //! For other registrations such as oem messages,
1197 //! diag messages check for respective commands
1198
1199 if((ctrl_msg->family_name == GENERIC_NL_FAMILY) &&
1200 (ctrl_msg->cmd_id == NL80211_CMD_REGISTER_ACTION))
1201 {
1202 struct genlmsghdr *genlh;
1203 struct nlmsghdr *nlh = (struct nlmsghdr *)ctrl_msg->data;
1204 genlh = (struct genlmsghdr *)nlmsg_data(nlh);
1205 struct nlattr *nlattrs[NL80211_ATTR_MAX + 1];
1206
1207 if (nlh->nlmsg_len > DEFAULT_PAGE_SIZE - sizeof(*ctrl_msg))
1208 {
1209 ALOGE("%s: Invalid nlmsg length", __FUNCTION__);
1210 return -1;
1211 }
1212 if (nla_parse(nlattrs, NL80211_ATTR_MAX, genlmsg_attrdata(genlh, 0),
1213 genlmsg_attrlen(genlh, 0), NULL))
1214 {
1215 ALOGE("unable to parse nl attributes");
1216 return -1;
1217 }
1218 if (!nlattrs[NL80211_ATTR_FRAME_TYPE])
1219 {
1220 ALOGD("No Valid frame type");
1221 }
1222 else
1223 {
1224 type = nla_get_u16(nlattrs[NL80211_ATTR_FRAME_TYPE]);
1225 }
1226 if (!nlattrs[NL80211_ATTR_FRAME_MATCH])
1227 {
1228 ALOGE("No Frame Match");
1229 return -1;
1230 }
1231 else
1232 {
1233 match_len = nla_len(nlattrs[NL80211_ATTR_FRAME_MATCH]);
1234 match = (char *)nla_data(nlattrs[NL80211_ATTR_FRAME_MATCH]);
1235
1236 list_for_each_entry(reg, &info->monitor_sockets, list) {
1237
1238 if(reg == NULL)
1239 break;
1240
1241 int mlen = min(match_len, reg->match_len);
1242
1243 if (reg->match_len == 0)
1244 continue;
1245
1246 if (memcmp(reg->match, match, mlen) == 0) {
1247
1248 if((ctrl_msg->monsock_len == reg->monsock_len) &&
1249 (memcmp((char *)®->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len) == 0))
1250 {
1251 if(attach)
1252 {
1253 ALOGE(" %s :Action frame already registered for this client ", __FUNCTION__);
1254 return -2;
1255 }
1256 else
1257 {
1258 del_from_list(®->list);
1259 free(reg);
1260 return 0;
1261 }
1262 }
1263 else
1264 {
1265 //! when action frame registered for other client,
1266 //! you can't attach or dettach for new client
1267 ALOGE(" %s :Action frame registered for other client ", __FUNCTION__);
1268 return -2;
1269 }
1270 }
1271 }
1272 }
1273 }
1274 else
1275 {
1276 list_for_each_entry(reg, &info->monitor_sockets, list) {
1277
1278 //! Checking for monitor sock in the list :
1279
1280 //! For attach request :
1281 //! if sock is not present, then it is a new entry , so add to list.
1282 //! if sock is present, and cmd_id does not match, add another entry to list.
1283 //! if sock is present, and cmd_id matches, return 0.
1284
1285 //! For dettach req :
1286 //! if sock is not present, return error -2.
1287 //! if sock is present, and cmd_id does not match, return error -2.
1288 //! if sock is present, and cmd_id matches, delete entry and return 0.
1289 if(reg == NULL)
1290 break;
1291
1292 if (ctrl_msg->monsock_len != reg->monsock_len)
1293 continue;
1294
1295 if (memcmp((char *)®->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len) == 0) {
1296
1297 if((reg->family_name == ctrl_msg->family_name) && (reg->cmd_id == ctrl_msg->cmd_id))
1298 {
1299 if(!attach)
1300 {
1301 del_from_list(®->list);
1302 free(reg);
1303 }
1304 return 0;
1305 }
1306 }
1307 }
1308 }
1309
1310 if(attach)
1311 {
1312 if (ctrl_msg->monsock_len > sizeof(struct sockaddr_un))
1313 {
1314 ALOGE("%s: Invalid monitor socket length \n", __FUNCTION__);
1315 return -3;
1316 }
1317
1318 nreg = (wifihal_mon_sock_t *)malloc(sizeof(*reg) + match_len);
1319 if (!nreg)
1320 return -1;
1321
1322 memset((char *)nreg, 0, sizeof(*reg) + match_len);
1323 nreg->family_name = ctrl_msg->family_name;
1324 nreg->cmd_id = ctrl_msg->cmd_id;
1325 nreg->monsock_len = ctrl_msg->monsock_len;
1326 memcpy((char *)&nreg->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len);
1327
1328 if(match_len && match)
1329 {
1330 nreg->match_len = match_len;
1331 memcpy(nreg->match, match, match_len);
1332 }
1333 add_to_list(&nreg->list, &info->monitor_sockets);
1334 }
1335 else
1336 {
1337 //! Not attached, so cant be dettached
1338 ALOGE("%s: Dettaching the unregistered socket \n", __FUNCTION__);
1339 return -2;
1340 }
1341
1342 return 0;
1343 }
1344
attach_monitor_sock(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg)1345 static int attach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
1346 {
1347 return register_monitor_sock(handle, ctrl_msg, 1);
1348 }
1349
dettach_monitor_sock(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg)1350 static int dettach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
1351 {
1352 return register_monitor_sock(handle, ctrl_msg, 0);
1353 }
1354
internal_pollin_handler_app(wifi_handle handle,struct ctrl_sock * sock)1355 static int internal_pollin_handler_app(wifi_handle handle, struct ctrl_sock *sock)
1356 {
1357 int retval = -1;
1358 int res;
1359 struct sockaddr_un from;
1360 socklen_t fromlen = sizeof(from);
1361 wifihal_ctrl_req_t *ctrl_msg;
1362 wifihal_ctrl_sync_rsp_t ctrl_reply;
1363
1364 ctrl_msg = (wifihal_ctrl_req_t *)malloc(DEFAULT_PAGE_SIZE);
1365 if(ctrl_msg == NULL)
1366 {
1367 ALOGE ("Memory allocation failure");
1368 return -1;
1369 }
1370
1371 memset((char *)ctrl_msg, 0, DEFAULT_PAGE_SIZE);
1372
1373 res = recvfrom(sock->s, (char *)ctrl_msg, DEFAULT_PAGE_SIZE, 0,
1374 (struct sockaddr *)&from, &fromlen);
1375 if (res < 0) {
1376 ALOGE("recvfrom(ctrl_iface): %s",
1377 strerror(errno));
1378 if(ctrl_msg)
1379 free(ctrl_msg);
1380
1381 return 0;
1382 }
1383 switch(ctrl_msg->ctrl_cmd)
1384 {
1385 case WIFIHAL_CTRL_MONITOR_ATTACH:
1386 retval = attach_monitor_sock(handle, ctrl_msg);
1387 break;
1388 case WIFIHAL_CTRL_MONITOR_DETTACH:
1389 retval = dettach_monitor_sock(handle, ctrl_msg);
1390 break;
1391 case WIFIHAL_CTRL_SEND_NL_DATA:
1392 retval = send_nl_data(handle, ctrl_msg);
1393 break;
1394 default:
1395 break;
1396 }
1397
1398 ctrl_reply.ctrl_cmd = ctrl_msg->ctrl_cmd;
1399 ctrl_reply.family_name = ctrl_msg->family_name;
1400 ctrl_reply.cmd_id = ctrl_msg->cmd_id;
1401 ctrl_reply.status = retval;
1402
1403 if(ctrl_msg)
1404 free(ctrl_msg);
1405
1406 if (sendto(sock->s, (char *)&ctrl_reply, sizeof(ctrl_reply), 0, (struct sockaddr *)&from,
1407 fromlen) < 0) {
1408 int _errno = errno;
1409 ALOGE("socket send failed : %d",_errno);
1410
1411 if (_errno == ENOBUFS || _errno == EAGAIN) {
1412 /*
1413 * The socket send buffer could be full. This
1414 * may happen if client programs are not
1415 * receiving their pending messages. Close and
1416 * reopen the socket as a workaround to avoid
1417 * getting stuck being unable to send any new
1418 * responses.
1419 */
1420 }
1421 }
1422 return res;
1423 }
1424
internal_pollin_handler(wifi_handle handle,struct nl_sock * sock)1425 static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock)
1426 {
1427 struct nl_cb *cb = nl_socket_get_cb(sock);
1428
1429 int res = nl_recvmsgs(sock, cb);
1430 if(res)
1431 ALOGE("Error :%d while reading nl msg", res);
1432 nl_cb_put(cb);
1433 return res;
1434 }
1435
internal_event_handler_app(wifi_handle handle,int events,struct ctrl_sock * sock)1436 static void internal_event_handler_app(wifi_handle handle, int events,
1437 struct ctrl_sock *sock)
1438 {
1439 if (events & POLLERR) {
1440 ALOGE("Error reading from wifi_hal ctrl socket");
1441 internal_pollin_handler_app(handle, sock);
1442 } else if (events & POLLHUP) {
1443 ALOGE("Remote side hung up");
1444 } else if (events & POLLIN) {
1445 //ALOGI("Found some events!!!");
1446 internal_pollin_handler_app(handle, sock);
1447 } else {
1448 ALOGE("Unknown event - %0x", events);
1449 }
1450 }
1451
internal_event_handler(wifi_handle handle,int events,struct nl_sock * sock)1452 static void internal_event_handler(wifi_handle handle, int events,
1453 struct nl_sock *sock)
1454 {
1455 if (events & POLLERR) {
1456 ALOGE("Error reading from socket");
1457 internal_pollin_handler(handle, sock);
1458 } else if (events & POLLHUP) {
1459 ALOGE("Remote side hung up");
1460 } else if (events & POLLIN) {
1461 //ALOGI("Found some events!!!");
1462 internal_pollin_handler(handle, sock);
1463 } else {
1464 ALOGE("Unknown event - %0x", events);
1465 }
1466 }
1467
1468 /* Run event handler */
wifi_event_loop(wifi_handle handle)1469 void wifi_event_loop(wifi_handle handle)
1470 {
1471 hal_info *info = getHalInfo(handle);
1472 if (info->in_event_loop) {
1473 return;
1474 } else {
1475 info->in_event_loop = true;
1476 }
1477
1478 pollfd pfd[4];
1479 memset(&pfd, 0, 4*sizeof(pfd[0]));
1480
1481 pfd[0].fd = nl_socket_get_fd(info->event_sock);
1482 pfd[0].events = POLLIN;
1483
1484 pfd[1].fd = nl_socket_get_fd(info->user_sock);
1485 pfd[1].events = POLLIN;
1486
1487 pfd[2].fd = info->exit_sockets[1];
1488 pfd[2].events = POLLIN;
1489
1490 if(info->wifihal_ctrl_sock.s > 0) {
1491 pfd[3].fd = info->wifihal_ctrl_sock.s ;
1492 pfd[3].events = POLLIN;
1493 }
1494 /* TODO: Add support for timeouts */
1495
1496 do {
1497 pfd[0].revents = 0;
1498 pfd[1].revents = 0;
1499 pfd[2].revents = 0;
1500 pfd[3].revents = 0;
1501 //ALOGI("Polling sockets");
1502 int result = poll(pfd, 4, -1);
1503 if (result < 0) {
1504 ALOGE("Error polling socket");
1505 } else {
1506 if (pfd[0].revents & (POLLIN | POLLHUP | POLLERR)) {
1507 internal_event_handler(handle, pfd[0].revents, info->event_sock);
1508 }
1509 if (pfd[1].revents & (POLLIN | POLLHUP | POLLERR)) {
1510 internal_event_handler(handle, pfd[1].revents, info->user_sock);
1511 }
1512 if ((info->wifihal_ctrl_sock.s > 0) && (pfd[3].revents & (POLLIN | POLLHUP | POLLERR))) {
1513 internal_event_handler_app(handle, pfd[3].revents, &info->wifihal_ctrl_sock);
1514 }
1515 }
1516 rb_timerhandler(info);
1517 } while (!info->clean_up);
1518 internal_cleaned_up_handler(handle);
1519 }
1520
user_sock_message_handler(nl_msg * msg,void * arg)1521 static int user_sock_message_handler(nl_msg *msg, void *arg)
1522 {
1523 wifi_handle handle = (wifi_handle)arg;
1524 hal_info *info = getHalInfo(handle);
1525
1526 diag_message_handler(info, msg);
1527
1528 return NL_OK;
1529 }
1530
internal_valid_message_handler(nl_msg * msg,void * arg)1531 static int internal_valid_message_handler(nl_msg *msg, void *arg)
1532 {
1533 wifi_handle handle = (wifi_handle)arg;
1534 hal_info *info = getHalInfo(handle);
1535
1536 WifiEvent event(msg);
1537 int res = event.parse();
1538 if (res < 0) {
1539 ALOGE("Failed to parse event: %d", res);
1540 return NL_SKIP;
1541 }
1542
1543 int cmd = event.get_cmd();
1544 uint32_t vendor_id = 0;
1545 int subcmd = 0;
1546
1547 if (cmd == NL80211_CMD_VENDOR) {
1548 vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
1549 subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
1550 /* Restrict printing GSCAN_FULL_RESULT which is causing lot
1551 of logs in bug report */
1552 if (subcmd != QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT) {
1553 ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
1554 event.get_cmdString(), vendor_id, subcmd);
1555 }
1556 }
1557 else if((info->wifihal_ctrl_sock.s > 0) && (cmd == NL80211_CMD_FRAME))
1558 {
1559 struct genlmsghdr *genlh;
1560 struct nlmsghdr *nlh = nlmsg_hdr(msg);
1561 genlh = (struct genlmsghdr *)nlmsg_data(nlh);
1562 struct nlattr *nlattrs[NL80211_ATTR_MAX + 1];
1563
1564 wifihal_ctrl_event_t *ctrl_evt;
1565 char *buff;
1566 wifihal_mon_sock_t *reg;
1567
1568 nla_parse(nlattrs, NL80211_ATTR_MAX, genlmsg_attrdata(genlh, 0),
1569 genlmsg_attrlen(genlh, 0), NULL);
1570
1571 if (!nlattrs[NL80211_ATTR_FRAME])
1572 {
1573 ALOGD("No Frame body");
1574 return WIFI_SUCCESS;
1575 }
1576 ctrl_evt = (wifihal_ctrl_event_t *)malloc(sizeof(*ctrl_evt) + nlh->nlmsg_len);
1577 if(ctrl_evt == NULL)
1578 {
1579 ALOGE("Memory allocation failure");
1580 return -1;
1581 }
1582 memset((char *)ctrl_evt, 0, sizeof(*ctrl_evt) + nlh->nlmsg_len);
1583 ctrl_evt->family_name = GENERIC_NL_FAMILY;
1584 ctrl_evt->cmd_id = cmd;
1585 ctrl_evt->data_len = nlh->nlmsg_len;
1586 memcpy(ctrl_evt->data, (char *)nlh, ctrl_evt->data_len);
1587
1588
1589 buff = (char *)nla_data(nlattrs[NL80211_ATTR_FRAME]) + 24; //! Size of Wlan80211FrameHeader
1590
1591 list_for_each_entry(reg, &info->monitor_sockets, list) {
1592
1593 if(reg == NULL)
1594 break;
1595
1596 if (memcmp(reg->match, buff, reg->match_len))
1597 continue;
1598
1599 /* found match! */
1600 /* Indicate the received Action frame to respective client */
1601 if (sendto(info->wifihal_ctrl_sock.s, (char *)ctrl_evt,
1602 sizeof(*ctrl_evt) + ctrl_evt->data_len,
1603 0, (struct sockaddr *)®->monsock, reg->monsock_len) < 0)
1604 {
1605 int _errno = errno;
1606 ALOGE("socket send failed : %d",_errno);
1607
1608 if (_errno == ENOBUFS || _errno == EAGAIN) {
1609 }
1610 }
1611
1612 }
1613 free(ctrl_evt);
1614 }
1615
1616 else {
1617 ALOGV("event received %s", event.get_cmdString());
1618 }
1619
1620 // event.log();
1621
1622 bool dispatched = false;
1623
1624 pthread_mutex_lock(&info->cb_lock);
1625
1626 for (int i = 0; i < info->num_event_cb; i++) {
1627 if (cmd == info->event_cb[i].nl_cmd) {
1628 if (cmd == NL80211_CMD_VENDOR
1629 && ((vendor_id != info->event_cb[i].vendor_id)
1630 || (subcmd != info->event_cb[i].vendor_subcmd)))
1631 {
1632 /* event for a different vendor, ignore it */
1633 continue;
1634 }
1635
1636 cb_info *cbi = &(info->event_cb[i]);
1637 pthread_mutex_unlock(&info->cb_lock);
1638 if (cbi->cb_func) {
1639 (*(cbi->cb_func))(msg, cbi->cb_arg);
1640 dispatched = true;
1641 }
1642 return NL_OK;
1643 }
1644 }
1645
1646 #ifdef QC_HAL_DEBUG
1647 if (!dispatched) {
1648 ALOGI("event ignored!!");
1649 }
1650 #endif
1651
1652 pthread_mutex_unlock(&info->cb_lock);
1653 return NL_OK;
1654 }
1655
1656 ////////////////////////////////////////////////////////////////////////////////
1657
1658 class GetMulticastIdCommand : public WifiCommand
1659 {
1660 private:
1661 const char *mName;
1662 const char *mGroup;
1663 int mId;
1664 public:
GetMulticastIdCommand(wifi_handle handle,const char * name,const char * group)1665 GetMulticastIdCommand(wifi_handle handle, const char *name,
1666 const char *group) : WifiCommand(handle, 0)
1667 {
1668 mName = name;
1669 mGroup = group;
1670 mId = -1;
1671 }
1672
getId()1673 int getId() {
1674 return mId;
1675 }
1676
create()1677 virtual wifi_error create() {
1678 int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
1679 // ALOGI("ctrl family = %d", nlctrlFamily);
1680 wifi_error ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
1681 if (ret != WIFI_SUCCESS)
1682 return ret;
1683
1684 ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
1685 return ret;
1686 }
1687
handleResponse(WifiEvent & reply)1688 virtual int handleResponse(WifiEvent& reply) {
1689
1690 // ALOGI("handling reponse in %s", __func__);
1691
1692 struct nlattr **tb = reply.attributes();
1693 struct nlattr *mcgrp = NULL;
1694 int i;
1695
1696 if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
1697 ALOGI("No multicast groups found");
1698 return NL_SKIP;
1699 } else {
1700 // ALOGI("Multicast groups attr size = %d",
1701 // nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
1702 }
1703
1704 for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
1705
1706 // ALOGI("Processing group");
1707 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
1708 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
1709 nla_len(mcgrp), NULL);
1710 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID])
1711 {
1712 continue;
1713 }
1714
1715 char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
1716 int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
1717
1718 // ALOGI("Found group name %s", grpName);
1719
1720 if (strncmp(grpName, mGroup, grpNameLen) != 0)
1721 continue;
1722
1723 mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
1724 break;
1725 }
1726
1727 return NL_SKIP;
1728 }
1729
1730 };
1731
wifi_get_multicast_id(wifi_handle handle,const char * name,const char * group)1732 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
1733 const char *group)
1734 {
1735 GetMulticastIdCommand cmd(handle, name, group);
1736 int res = cmd.requestResponse();
1737 if (res < 0)
1738 return res;
1739 else
1740 return cmd.getId();
1741 }
1742
1743 /////////////////////////////////////////////////////////////////////////
1744
is_wifi_interface(const char * name)1745 static bool is_wifi_interface(const char *name)
1746 {
1747 if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
1748 /* not a wifi interface; ignore it */
1749 return false;
1750 } else {
1751 return true;
1752 }
1753 }
1754
get_interface(const char * name,interface_info * info)1755 static int get_interface(const char *name, interface_info *info)
1756 {
1757 strlcpy(info->name, name, (IFNAMSIZ + 1));
1758 info->id = if_nametoindex(name);
1759 // ALOGI("found an interface : %s, id = %d", name, info->id);
1760 return WIFI_SUCCESS;
1761 }
1762
wifi_init_interfaces(wifi_handle handle)1763 wifi_error wifi_init_interfaces(wifi_handle handle)
1764 {
1765 hal_info *info = (hal_info *)handle;
1766
1767 struct dirent *de;
1768
1769 DIR *d = opendir("/sys/class/net");
1770 if (d == 0)
1771 return WIFI_ERROR_UNKNOWN;
1772
1773 int n = 0;
1774 while ((de = readdir(d))) {
1775 if (de->d_name[0] == '.')
1776 continue;
1777 if (is_wifi_interface(de->d_name) ) {
1778 n++;
1779 }
1780 }
1781
1782 closedir(d);
1783
1784 d = opendir("/sys/class/net");
1785 if (d == 0)
1786 return WIFI_ERROR_UNKNOWN;
1787
1788 info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
1789 if (info->interfaces == NULL) {
1790 ALOGE("%s: Error info->interfaces NULL", __func__);
1791 return WIFI_ERROR_OUT_OF_MEMORY;
1792 }
1793
1794 int i = 0;
1795 while ((de = readdir(d))) {
1796 if (de->d_name[0] == '.')
1797 continue;
1798 if (is_wifi_interface(de->d_name)) {
1799 interface_info *ifinfo
1800 = (interface_info *)malloc(sizeof(interface_info));
1801 if (ifinfo == NULL) {
1802 ALOGE("%s: Error ifinfo NULL", __func__);
1803 while (i > 0) {
1804 free(info->interfaces[i-1]);
1805 i--;
1806 }
1807 free(info->interfaces);
1808 return WIFI_ERROR_OUT_OF_MEMORY;
1809 }
1810 if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
1811 free(ifinfo);
1812 continue;
1813 }
1814 ifinfo->handle = handle;
1815 info->interfaces[i] = ifinfo;
1816 i++;
1817 }
1818 }
1819
1820 closedir(d);
1821
1822 info->num_interfaces = n;
1823
1824 return WIFI_SUCCESS;
1825 }
1826
wifi_get_ifaces(wifi_handle handle,int * num,wifi_interface_handle ** interfaces)1827 wifi_error wifi_get_ifaces(wifi_handle handle, int *num,
1828 wifi_interface_handle **interfaces)
1829 {
1830 hal_info *info = (hal_info *)handle;
1831
1832 *interfaces = (wifi_interface_handle *)info->interfaces;
1833 *num = info->num_interfaces;
1834
1835 return WIFI_SUCCESS;
1836 }
1837
wifi_get_iface_name(wifi_interface_handle handle,char * name,size_t size)1838 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name,
1839 size_t size)
1840 {
1841 interface_info *info = (interface_info *)handle;
1842 strlcpy(name, info->name, size);
1843 return WIFI_SUCCESS;
1844 }
1845
1846 /* Get the supported Feature set */
wifi_get_supported_feature_set(wifi_interface_handle iface,feature_set * set)1847 wifi_error wifi_get_supported_feature_set(wifi_interface_handle iface,
1848 feature_set *set)
1849 {
1850 int ret = 0;
1851 wifi_handle handle = getWifiHandle(iface);
1852 *set = 0;
1853 hal_info *info = getHalInfo(handle);
1854
1855 ret = acquire_supported_features(iface, set);
1856 if (ret != WIFI_SUCCESS) {
1857 *set = info->supported_feature_set;
1858 ALOGV("Supported feature set acquired at initialization : %x", *set);
1859 } else {
1860 info->supported_feature_set = *set;
1861 ALOGV("Supported feature set acquired : %x", *set);
1862 }
1863 return WIFI_SUCCESS;
1864 }
1865
wifi_get_concurrency_matrix(wifi_interface_handle handle,int set_size_max,feature_set set[],int * set_size)1866 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle,
1867 int set_size_max,
1868 feature_set set[], int *set_size)
1869 {
1870 wifi_error ret;
1871 struct nlattr *nlData;
1872 WifihalGeneric *vCommand = NULL;
1873 interface_info *ifaceInfo = getIfaceInfo(handle);
1874 wifi_handle wifiHandle = getWifiHandle(handle);
1875
1876 if (set == NULL) {
1877 ALOGE("%s: NULL set pointer provided. Exit.",
1878 __func__);
1879 return WIFI_ERROR_INVALID_ARGS;
1880 }
1881
1882 vCommand = new WifihalGeneric(wifiHandle, 0,
1883 OUI_QCA,
1884 QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX);
1885 if (vCommand == NULL) {
1886 ALOGE("%s: Error vCommand NULL", __func__);
1887 return WIFI_ERROR_OUT_OF_MEMORY;
1888 }
1889
1890 /* Create the message */
1891 ret = vCommand->create();
1892 if (ret != WIFI_SUCCESS)
1893 goto cleanup;
1894
1895 ret = vCommand->set_iface_id(ifaceInfo->name);
1896 if (ret != WIFI_SUCCESS)
1897 goto cleanup;
1898
1899 /* Add the vendor specific attributes for the NL command. */
1900 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1901 if (!nlData)
1902 goto cleanup;
1903
1904 ret = vCommand->put_u32(
1905 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX,
1906 set_size_max);
1907 if (ret != WIFI_SUCCESS)
1908 goto cleanup;
1909
1910 vCommand->attr_end(nlData);
1911
1912 /* Populate the input received from caller/framework. */
1913 vCommand->setMaxSetSize(set_size_max);
1914 vCommand->setSizePtr(set_size);
1915 vCommand->setConcurrencySet(set);
1916
1917 ret = vCommand->requestResponse();
1918 if (ret != WIFI_SUCCESS)
1919 ALOGE("%s: requestResponse() error: %d", __func__, ret);
1920
1921 cleanup:
1922 delete vCommand;
1923 if (ret)
1924 *set_size = 0;
1925 return ret;
1926 }
1927
1928
wifi_set_nodfs_flag(wifi_interface_handle handle,u32 nodfs)1929 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
1930 {
1931 wifi_error ret;
1932 struct nlattr *nlData;
1933 WifiVendorCommand *vCommand = NULL;
1934 interface_info *ifaceInfo = getIfaceInfo(handle);
1935 wifi_handle wifiHandle = getWifiHandle(handle);
1936
1937 vCommand = new WifiVendorCommand(wifiHandle, 0,
1938 OUI_QCA,
1939 QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG);
1940 if (vCommand == NULL) {
1941 ALOGE("%s: Error vCommand NULL", __func__);
1942 return WIFI_ERROR_OUT_OF_MEMORY;
1943 }
1944
1945 /* Create the message */
1946 ret = vCommand->create();
1947 if (ret != WIFI_SUCCESS)
1948 goto cleanup;
1949
1950 ret = vCommand->set_iface_id(ifaceInfo->name);
1951 if (ret != WIFI_SUCCESS)
1952 goto cleanup;
1953
1954 /* Add the vendor specific attributes for the NL command. */
1955 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1956 if (!nlData)
1957 goto cleanup;
1958
1959 /* Add the fixed part of the mac_oui to the nl command */
1960 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG, nodfs);
1961 if (ret != WIFI_SUCCESS)
1962 goto cleanup;
1963
1964 vCommand->attr_end(nlData);
1965
1966 ret = vCommand->requestResponse();
1967 /* Don't check response since we aren't expecting one */
1968
1969 cleanup:
1970 delete vCommand;
1971 return ret;
1972 }
1973
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)1974 wifi_error wifi_start_sending_offloaded_packet(wifi_request_id id,
1975 wifi_interface_handle iface,
1976 u16 ether_type,
1977 u8 *ip_packet,
1978 u16 ip_packet_len,
1979 u8 *src_mac_addr,
1980 u8 *dst_mac_addr,
1981 u32 period_msec)
1982 {
1983 wifi_error ret;
1984 struct nlattr *nlData;
1985 WifiVendorCommand *vCommand = NULL;
1986
1987 ret = initialize_vendor_cmd(iface, id,
1988 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
1989 &vCommand);
1990 if (ret != WIFI_SUCCESS) {
1991 ALOGE("%s: Initialization failed", __func__);
1992 return ret;
1993 }
1994
1995 ALOGV("ether type 0x%04x\n", ether_type);
1996 ALOGV("ip packet length : %u\nIP Packet:", ip_packet_len);
1997 hexdump(ip_packet, ip_packet_len);
1998 ALOGV("Src Mac Address: " MAC_ADDR_STR "\nDst Mac Address: " MAC_ADDR_STR
1999 "\nPeriod in msec : %u", MAC_ADDR_ARRAY(src_mac_addr),
2000 MAC_ADDR_ARRAY(dst_mac_addr), period_msec);
2001
2002 /* Add the vendor specific attributes for the NL command. */
2003 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2004 if (!nlData)
2005 goto cleanup;
2006
2007 ret = vCommand->put_u32(
2008 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
2009 QCA_WLAN_OFFLOADED_PACKETS_SENDING_START);
2010 if (ret != WIFI_SUCCESS)
2011 goto cleanup;
2012
2013 ret = vCommand->put_u32(
2014 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
2015 id);
2016 if (ret != WIFI_SUCCESS)
2017 goto cleanup;
2018
2019 ret = vCommand->put_u16(
2020 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_ETHER_PROTO_TYPE,
2021 ether_type);
2022 if (ret != WIFI_SUCCESS)
2023 goto cleanup;
2024
2025 ret = vCommand->put_bytes(
2026 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA,
2027 (const char *)ip_packet, ip_packet_len);
2028 if (ret != WIFI_SUCCESS)
2029 goto cleanup;
2030
2031 ret = vCommand->put_addr(
2032 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR,
2033 src_mac_addr);
2034 if (ret != WIFI_SUCCESS)
2035 goto cleanup;
2036
2037 ret = vCommand->put_addr(
2038 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR,
2039 dst_mac_addr);
2040 if (ret != WIFI_SUCCESS)
2041 goto cleanup;
2042
2043 ret = vCommand->put_u32(
2044 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD,
2045 period_msec);
2046 if (ret != WIFI_SUCCESS)
2047 goto cleanup;
2048
2049 vCommand->attr_end(nlData);
2050
2051 ret = vCommand->requestResponse();
2052 if (ret != WIFI_SUCCESS)
2053 goto cleanup;
2054
2055 cleanup:
2056 delete vCommand;
2057 return ret;
2058 }
2059
wifi_stop_sending_offloaded_packet(wifi_request_id id,wifi_interface_handle iface)2060 wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id id,
2061 wifi_interface_handle iface)
2062 {
2063 wifi_error ret;
2064 struct nlattr *nlData;
2065 WifiVendorCommand *vCommand = NULL;
2066
2067 ret = initialize_vendor_cmd(iface, id,
2068 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
2069 &vCommand);
2070 if (ret != WIFI_SUCCESS) {
2071 ALOGE("%s: Initialization failed", __func__);
2072 return ret;
2073 }
2074
2075 /* Add the vendor specific attributes for the NL command. */
2076 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2077 if (!nlData)
2078 goto cleanup;
2079
2080 ret = vCommand->put_u32(
2081 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
2082 QCA_WLAN_OFFLOADED_PACKETS_SENDING_STOP);
2083 if (ret != WIFI_SUCCESS)
2084 goto cleanup;
2085
2086 ret = vCommand->put_u32(
2087 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
2088 id);
2089 if (ret != WIFI_SUCCESS)
2090 goto cleanup;
2091
2092 vCommand->attr_end(nlData);
2093
2094 ret = vCommand->requestResponse();
2095 if (ret != WIFI_SUCCESS)
2096 goto cleanup;
2097
2098 cleanup:
2099 delete vCommand;
2100 return ret;
2101 }
2102
2103 #define PACKET_FILTER_ID 0
2104
wifi_set_packet_filter(wifi_interface_handle iface,const u8 * program,u32 len)2105 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
2106 const u8 *program, u32 len)
2107 {
2108 wifi_error ret;
2109 struct nlattr *nlData;
2110 WifiVendorCommand *vCommand = NULL;
2111 u32 current_offset = 0;
2112 wifi_handle wifiHandle = getWifiHandle(iface);
2113 hal_info *info = getHalInfo(wifiHandle);
2114
2115 /* len=0 clears the filters in driver/firmware */
2116 if (len != 0 && program == NULL) {
2117 ALOGE("%s: No valid program provided. Exit.",
2118 __func__);
2119 return WIFI_ERROR_INVALID_ARGS;
2120 }
2121
2122 do {
2123 ret = initialize_vendor_cmd(iface, get_requestid(),
2124 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
2125 &vCommand);
2126 if (ret != WIFI_SUCCESS) {
2127 ALOGE("%s: Initialization failed", __FUNCTION__);
2128 return ret;
2129 }
2130
2131 /* Add the vendor specific attributes for the NL command. */
2132 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2133 if (!nlData)
2134 goto cleanup;
2135
2136 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2137 QCA_WLAN_SET_PACKET_FILTER);
2138 if (ret != WIFI_SUCCESS)
2139 goto cleanup;
2140 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
2141 PACKET_FILTER_ID);
2142 if (ret != WIFI_SUCCESS)
2143 goto cleanup;
2144 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE,
2145 len);
2146 if (ret != WIFI_SUCCESS)
2147 goto cleanup;
2148 ret = vCommand->put_u32(
2149 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
2150 current_offset);
2151 if (ret != WIFI_SUCCESS)
2152 goto cleanup;
2153
2154 if (len) {
2155 ret = vCommand->put_bytes(
2156 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
2157 (char *)&program[current_offset],
2158 min(info->firmware_bus_max_size,
2159 len-current_offset));
2160 if (ret!= WIFI_SUCCESS) {
2161 ALOGE("%s: failed to put program", __FUNCTION__);
2162 goto cleanup;
2163 }
2164 }
2165
2166 vCommand->attr_end(nlData);
2167
2168 ret = vCommand->requestResponse();
2169 if (ret != WIFI_SUCCESS) {
2170 ALOGE("%s: requestResponse Error:%d",__func__, ret);
2171 goto cleanup;
2172 }
2173
2174 /* destroy the object after sending each fragment to driver */
2175 delete vCommand;
2176 vCommand = NULL;
2177
2178 current_offset += min(info->firmware_bus_max_size, len);
2179 } while (current_offset < len);
2180
2181 info->apf_enabled = !!len;
2182
2183 cleanup:
2184 if (vCommand)
2185 delete vCommand;
2186 return ret;
2187 }
2188
wifi_get_packet_filter_capabilities(wifi_interface_handle handle,u32 * version,u32 * max_len)2189 static wifi_error wifi_get_packet_filter_capabilities(
2190 wifi_interface_handle handle, u32 *version, u32 *max_len)
2191 {
2192 wifi_error ret;
2193 struct nlattr *nlData;
2194 WifihalGeneric *vCommand = NULL;
2195 interface_info *ifaceInfo = getIfaceInfo(handle);
2196 wifi_handle wifiHandle = getWifiHandle(handle);
2197
2198 if (version == NULL || max_len == NULL) {
2199 ALOGE("%s: NULL version/max_len pointer provided. Exit.",
2200 __FUNCTION__);
2201 return WIFI_ERROR_INVALID_ARGS;
2202 }
2203
2204 vCommand = new WifihalGeneric(wifiHandle, 0,
2205 OUI_QCA,
2206 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
2207 if (vCommand == NULL) {
2208 ALOGE("%s: Error vCommand NULL", __FUNCTION__);
2209 return WIFI_ERROR_OUT_OF_MEMORY;
2210 }
2211
2212 /* Create the message */
2213 ret = vCommand->create();
2214 if (ret != WIFI_SUCCESS)
2215 goto cleanup;
2216
2217 ret = vCommand->set_iface_id(ifaceInfo->name);
2218 if (ret != WIFI_SUCCESS)
2219 goto cleanup;
2220
2221 /* Add the vendor specific attributes for the NL command. */
2222 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2223 if (!nlData)
2224 goto cleanup;
2225
2226 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2227 QCA_WLAN_GET_PACKET_FILTER);
2228 if (ret != WIFI_SUCCESS)
2229 goto cleanup;
2230
2231 vCommand->attr_end(nlData);
2232
2233 ret = vCommand->requestResponse();
2234 if (ret != WIFI_SUCCESS) {
2235 ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
2236 if (ret == WIFI_ERROR_NOT_SUPPORTED) {
2237 /* Packet filtering is not supported currently, so return version
2238 * and length as 0
2239 */
2240 ALOGI("Packet filtering is not supprted");
2241 *version = 0;
2242 *max_len = 0;
2243 ret = WIFI_SUCCESS;
2244 }
2245 goto cleanup;
2246 }
2247
2248 *version = vCommand->getFilterVersion();
2249 *max_len = vCommand->getFilterLength();
2250 cleanup:
2251 delete vCommand;
2252 return ret;
2253 }
2254
2255
wifi_configure_nd_offload(wifi_interface_handle iface,u8 enable)2256 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
2257 u8 enable)
2258 {
2259 wifi_error ret;
2260 struct nlattr *nlData;
2261 WifiVendorCommand *vCommand = NULL;
2262
2263 ret = initialize_vendor_cmd(iface, get_requestid(),
2264 QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
2265 &vCommand);
2266 if (ret != WIFI_SUCCESS) {
2267 ALOGE("%s: Initialization failed", __func__);
2268 return ret;
2269 }
2270
2271 ALOGV("ND offload : %s", enable?"Enable":"Disable");
2272
2273 /* Add the vendor specific attributes for the NL command. */
2274 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2275 if (!nlData)
2276 goto cleanup;
2277
2278 ret = vCommand->put_u8(QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG, enable);
2279 if (ret != WIFI_SUCCESS)
2280 goto cleanup;
2281
2282 vCommand->attr_end(nlData);
2283
2284 ret = vCommand->requestResponse();
2285
2286 cleanup:
2287 delete vCommand;
2288 return ret;
2289 }
2290
2291 /**
2292 * Copy 'len' bytes of raw data from host memory at source address 'program'
2293 * to APF (Android Packet Filter) working memory starting at offset 'dst_offset'.
2294 * The size of the program lenght passed to the interpreter is set to
2295 * 'progaram_lenght'
2296 *
2297 * The implementation is allowed to tranlate this wrtie into a series of smaller
2298 * writes,but this function is not allowed to return untill all write operations
2299 * have been completed
2300 * additionally visible memory not targeted by this function must remain
2301 * unchanged
2302
2303 * @param dst_offset write offset in bytes relative to the beginning of the APF
2304 * working memory with logical address 0X000. Must be a multiple of 4
2305 *
2306 * @param program host memory to copy bytes from. Must be 4B aligned
2307 *
2308 * @param len the number of bytes to copy from the bost into the APF working
2309 * memory
2310 *
2311 * @param program_length new length of the program instructions in bytes to pass
2312 * to the interpreter
2313 */
2314
wifi_write_packet_filter(wifi_interface_handle iface,u32 dst_offset,const u8 * program,u32 len,u32 program_length)2315 wifi_error wifi_write_packet_filter(wifi_interface_handle iface,
2316 u32 dst_offset, const u8 *program,
2317 u32 len, u32 program_length)
2318 {
2319 wifi_error ret;
2320 struct nlattr *nlData;
2321 WifiVendorCommand *vCommand = NULL;
2322 u32 current_offset = 0;
2323 wifi_handle wifiHandle = getWifiHandle(iface);
2324 hal_info *info = getHalInfo(wifiHandle);
2325
2326 /* len=0 clears the filters in driver/firmware */
2327 if (len != 0 && program == NULL) {
2328 ALOGE("%s: No valid program provided. Exit.",
2329 __func__);
2330 return WIFI_ERROR_INVALID_ARGS;
2331 }
2332
2333 do {
2334 ret = initialize_vendor_cmd(iface, get_requestid(),
2335 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
2336 &vCommand);
2337 if (ret != WIFI_SUCCESS) {
2338 ALOGE("%s: Initialization failed", __FUNCTION__);
2339 return ret;
2340 }
2341
2342 /* Add the vendor specific attributes for the NL command. */
2343 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2344 if (!nlData)
2345 goto cleanup;
2346
2347 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2348 QCA_WLAN_WRITE_PACKET_FILTER);
2349 if (ret != WIFI_SUCCESS)
2350 goto cleanup;
2351 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
2352 PACKET_FILTER_ID);
2353 if (ret != WIFI_SUCCESS)
2354 goto cleanup;
2355 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE,
2356 len);
2357 if (ret != WIFI_SUCCESS)
2358 goto cleanup;
2359 ret = vCommand->put_u32(
2360 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
2361 dst_offset + current_offset);
2362 if (ret != WIFI_SUCCESS)
2363 goto cleanup;
2364 ret = vCommand->put_u32(
2365 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROG_LENGTH,
2366 program_length);
2367 if (ret != WIFI_SUCCESS)
2368 goto cleanup;
2369
2370 ret = vCommand->put_bytes(
2371 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
2372 (char *)&program[current_offset],
2373 min(info->firmware_bus_max_size,
2374 len - current_offset));
2375 if (ret!= WIFI_SUCCESS) {
2376 ALOGE("%s: failed to put program", __FUNCTION__);
2377 goto cleanup;
2378 }
2379
2380 vCommand->attr_end(nlData);
2381
2382 ret = vCommand->requestResponse();
2383 if (ret != WIFI_SUCCESS) {
2384 ALOGE("%s: requestResponse Error:%d",__func__, ret);
2385 goto cleanup;
2386 }
2387
2388 /* destroy the object after sending each fragment to driver */
2389 delete vCommand;
2390 vCommand = NULL;
2391
2392 current_offset += min(info->firmware_bus_max_size,
2393 len - current_offset);
2394 } while (current_offset < len);
2395
2396 cleanup:
2397 if (vCommand)
2398 delete vCommand;
2399 return ret;
2400 }
2401
wifi_enable_packet_filter(wifi_interface_handle handle,u32 enable)2402 wifi_error wifi_enable_packet_filter(wifi_interface_handle handle,
2403 u32 enable)
2404 {
2405 wifi_error ret;
2406 struct nlattr *nlData;
2407 WifiVendorCommand *vCommand = NULL;
2408 u32 subcmd;
2409 wifi_handle wifiHandle = getWifiHandle(handle);
2410 hal_info *info = getHalInfo(wifiHandle);
2411
2412 ret = initialize_vendor_cmd(handle, get_requestid(),
2413 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
2414 &vCommand);
2415
2416 if (ret != WIFI_SUCCESS) {
2417 ALOGE("%s: Initialization failed", __func__);
2418 return ret;
2419 }
2420 /* Add the vendor specific attributes for the NL command. */
2421 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2422 if (!nlData)
2423 goto cleanup;
2424
2425 subcmd = enable ? QCA_WLAN_ENABLE_PACKET_FILTER :
2426 QCA_WLAN_DISABLE_PACKET_FILTER;
2427 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2428 subcmd);
2429 if (ret != WIFI_SUCCESS)
2430 goto cleanup;
2431
2432 vCommand->attr_end(nlData);
2433 ret = vCommand->requestResponse();
2434
2435 if (ret != WIFI_SUCCESS) {
2436 ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
2437 goto cleanup;
2438 }
2439
2440 info->apf_enabled = !!enable;
2441
2442 cleanup:
2443 if (vCommand)
2444 delete vCommand;
2445 return ret;
2446
2447 }
2448
2449 /**
2450 * Copy 'length' bytes of raw data from APF (Android Packet Filter) working
2451 * memory to host memory starting at offset src_offset into host memory
2452 * pointed to by host_dst.
2453 * Memory can be text, data or some combination of the two. The implementiion is
2454 * allowed to translate this read into a series of smaller reads, but this
2455 * function is not allowed to return untill all the reads operations
2456 * into host_dst have been completed.
2457 *
2458 * @param src_offset offset in bytes of destination memory within APF working
2459 * memory
2460 *
2461 * @param host_dst host memory to copy into. Must be 4B aligned.
2462 *
2463 * @param length the number of bytes to copy from the APF working memory to the
2464 * host.
2465 */
2466
wifi_read_packet_filter(wifi_interface_handle handle,u32 src_offset,u8 * host_dst,u32 length)2467 static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
2468 u32 src_offset, u8 *host_dst, u32 length)
2469 {
2470 wifi_error ret = WIFI_SUCCESS;
2471 struct nlattr *nlData;
2472 WifihalGeneric *vCommand = NULL;
2473 interface_info *ifaceInfo = getIfaceInfo(handle);
2474 wifi_handle wifiHandle = getWifiHandle(handle);
2475 hal_info *info = getHalInfo(wifiHandle);
2476
2477 /* Length to be passed to this function should be non-zero
2478 * Return invalid argument if length is passed as zero
2479 */
2480 if (length == 0)
2481 return WIFI_ERROR_INVALID_ARGS;
2482
2483 /*Temporary varibles to support the read complete length in chunks */
2484 u8 *temp_host_dst;
2485 u32 remainingLengthToBeRead, currentLength;
2486 u8 apf_locally_disabled = 0;
2487
2488 /*Initializing the temporary variables*/
2489 temp_host_dst = host_dst;
2490 remainingLengthToBeRead = length;
2491
2492 if (info->apf_enabled) {
2493 /* Disable APF only when not disabled by framework before calling
2494 * wifi_read_packet_filter()
2495 */
2496 ret = wifi_enable_packet_filter(handle, 0);
2497 if (ret != WIFI_SUCCESS) {
2498 ALOGE("%s: Failed to disable APF", __FUNCTION__);
2499 return ret;
2500 }
2501 apf_locally_disabled = 1;
2502 }
2503 /**
2504 * Read the complete length in chunks of size less or equal to firmware bus
2505 * max size
2506 */
2507 while (remainingLengthToBeRead)
2508 {
2509 vCommand = new WifihalGeneric(wifiHandle, 0, OUI_QCA,
2510 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
2511
2512 if (vCommand == NULL) {
2513 ALOGE("%s: Error vCommand NULL", __FUNCTION__);
2514 ret = WIFI_ERROR_OUT_OF_MEMORY;
2515 break;
2516 }
2517
2518 /* Create the message */
2519 ret = vCommand->create();
2520 if (ret != WIFI_SUCCESS)
2521 break;
2522 ret = vCommand->set_iface_id(ifaceInfo->name);
2523 if (ret != WIFI_SUCCESS)
2524 break;
2525 /* Add the vendor specific attributes for the NL command. */
2526 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2527 if (!nlData)
2528 break;
2529 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2530 QCA_WLAN_READ_PACKET_FILTER);
2531 if (ret != WIFI_SUCCESS)
2532 break;
2533
2534 currentLength = min(remainingLengthToBeRead, info->firmware_bus_max_size);
2535
2536 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE,
2537 currentLength);
2538 if (ret != WIFI_SUCCESS)
2539 break;
2540 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
2541 src_offset);
2542 if (ret != WIFI_SUCCESS)
2543 break;
2544
2545 vCommand->setPacketBufferParams(temp_host_dst, currentLength);
2546 vCommand->attr_end(nlData);
2547 ret = vCommand->requestResponse();
2548
2549 if (ret != WIFI_SUCCESS) {
2550 ALOGE("%s: requestResponse() error: %d current_len = %u, src_offset = %u",
2551 __FUNCTION__, ret, currentLength, src_offset);
2552 break;
2553 }
2554
2555 remainingLengthToBeRead -= currentLength;
2556 temp_host_dst += currentLength;
2557 src_offset += currentLength;
2558 delete vCommand;
2559 vCommand = NULL;
2560 }
2561
2562 /* Re enable APF only when disabled above within this API */
2563 if (apf_locally_disabled) {
2564 wifi_error status;
2565 status = wifi_enable_packet_filter(handle, 1);
2566 if (status != WIFI_SUCCESS)
2567 ALOGE("%s: Failed to enable APF", __FUNCTION__);
2568 /* Prefer to return read status if read fails */
2569 if (ret == WIFI_SUCCESS)
2570 ret = status;
2571 }
2572
2573 delete vCommand;
2574 return ret;
2575 }
2576