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_virtual_interface_create = wifi_virtual_interface_create;
575 fn->wifi_virtual_interface_delete = wifi_virtual_interface_delete;
576 fn->wifi_set_latency_mode = wifi_set_latency_mode;
577 fn->wifi_set_thermal_mitigation_mode = wifi_set_thermal_mitigation_mode;
578
579 return WIFI_SUCCESS;
580 }
581
cld80211lib_cleanup(hal_info * info)582 static void cld80211lib_cleanup(hal_info *info)
583 {
584 if (!info->cldctx)
585 return;
586 cld80211_remove_mcast_group(info->cldctx, "host_logs");
587 cld80211_remove_mcast_group(info->cldctx, "fw_logs");
588 cld80211_remove_mcast_group(info->cldctx, "per_pkt_stats");
589 cld80211_remove_mcast_group(info->cldctx, "diag_events");
590 cld80211_remove_mcast_group(info->cldctx, "fatal_events");
591 cld80211_remove_mcast_group(info->cldctx, "oem_msgs");
592 exit_cld80211_recv(info->cldctx);
593 cld80211_deinit(info->cldctx);
594 info->cldctx = NULL;
595 }
596
wifi_get_iface_id(hal_info * info,const char * iface)597 static int wifi_get_iface_id(hal_info *info, const char *iface)
598 {
599 int i;
600 for (i = 0; i < info->num_interfaces; i++)
601 if (!strcmp(info->interfaces[i]->name, iface))
602 return i;
603 return -1;
604 }
605
wifi_initialize(wifi_handle * handle)606 wifi_error wifi_initialize(wifi_handle *handle)
607 {
608 wifi_error ret = WIFI_SUCCESS;
609 wifi_interface_handle iface_handle;
610 struct nl_sock *cmd_sock = NULL;
611 struct nl_sock *event_sock = NULL;
612 struct nl_cb *cb = NULL;
613 int status = 0;
614 int index;
615 char hw_ver_type[MAX_HW_VER_LENGTH];
616 char *hw_name = NULL;
617
618 ALOGI("Initializing wifi");
619 hal_info *info = (hal_info *)malloc(sizeof(hal_info));
620 if (info == NULL) {
621 ALOGE("Could not allocate hal_info");
622 return WIFI_ERROR_OUT_OF_MEMORY;
623 }
624
625 memset(info, 0, sizeof(*info));
626
627 cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT,
628 NETLINK_GENERIC);
629 if (cmd_sock == NULL) {
630 ALOGE("Failed to create command socket port");
631 ret = WIFI_ERROR_UNKNOWN;
632 goto unload;
633 }
634
635 /* Set the socket buffer size */
636 if (nl_socket_set_buffer_size(cmd_sock, (256*1024), 0) < 0) {
637 ALOGE("Could not set nl_socket RX buffer size for cmd_sock: %s",
638 strerror(errno));
639 /* continue anyway with the default (smaller) buffer */
640 }
641
642 event_sock =
643 wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT, NETLINK_GENERIC);
644 if (event_sock == NULL) {
645 ALOGE("Failed to create event socket port");
646 ret = WIFI_ERROR_UNKNOWN;
647 goto unload;
648 }
649
650 /* Set the socket buffer size */
651 if (nl_socket_set_buffer_size(event_sock, (256*1024), 0) < 0) {
652 ALOGE("Could not set nl_socket RX buffer size for event_sock: %s",
653 strerror(errno));
654 /* continue anyway with the default (smaller) buffer */
655 }
656
657 cb = nl_socket_get_cb(event_sock);
658 if (cb == NULL) {
659 ALOGE("Failed to get NL control block for event socket port");
660 ret = WIFI_ERROR_UNKNOWN;
661 goto unload;
662 }
663
664 info->event_sock_arg = 1;
665 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
666 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->event_sock_arg);
667 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->event_sock_arg);
668 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->event_sock_arg);
669
670 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler,
671 info);
672 nl_cb_put(cb);
673
674 info->cmd_sock = cmd_sock;
675 info->event_sock = event_sock;
676 info->clean_up = false;
677 info->in_event_loop = false;
678
679 info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
680 if (info->event_cb == NULL) {
681 ALOGE("Could not allocate event_cb");
682 ret = WIFI_ERROR_OUT_OF_MEMORY;
683 goto unload;
684 }
685 info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
686 info->num_event_cb = 0;
687
688 info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
689 if (info->nl80211_family_id < 0) {
690 ALOGE("Could not resolve nl80211 familty id");
691 ret = WIFI_ERROR_UNKNOWN;
692 goto unload;
693 }
694
695 pthread_mutex_init(&info->cb_lock, NULL);
696 pthread_mutex_init(&info->pkt_fate_stats_lock, NULL);
697
698 *handle = (wifi_handle) info;
699
700 wifi_add_membership(*handle, "scan");
701 wifi_add_membership(*handle, "mlme");
702 wifi_add_membership(*handle, "regulatory");
703 wifi_add_membership(*handle, "vendor");
704
705 info->wifihal_ctrl_sock.s = 0;
706
707 wifi_create_ctrl_socket(info);
708
709 //! Initailise the monitoring clients list
710 INITIALISE_LIST(&info->monitor_sockets);
711
712 info->cldctx = cld80211_init();
713 if (info->cldctx != NULL) {
714 info->user_sock = info->cldctx->sock;
715 ret = wifi_init_cld80211_sock_cb(info);
716 if (ret != WIFI_SUCCESS) {
717 ALOGE("Could not set cb for CLD80211 family");
718 goto cld80211_cleanup;
719 }
720
721 status = cld80211_add_mcast_group(info->cldctx, "host_logs");
722 if (status) {
723 ALOGE("Failed to add mcast group host_logs :%d", status);
724 goto cld80211_cleanup;
725 }
726 status = cld80211_add_mcast_group(info->cldctx, "fw_logs");
727 if (status) {
728 ALOGE("Failed to add mcast group fw_logs :%d", status);
729 goto cld80211_cleanup;
730 }
731 status = cld80211_add_mcast_group(info->cldctx, "per_pkt_stats");
732 if (status) {
733 ALOGE("Failed to add mcast group per_pkt_stats :%d", status);
734 goto cld80211_cleanup;
735 }
736 status = cld80211_add_mcast_group(info->cldctx, "diag_events");
737 if (status) {
738 ALOGE("Failed to add mcast group diag_events :%d", status);
739 goto cld80211_cleanup;
740 }
741 status = cld80211_add_mcast_group(info->cldctx, "fatal_events");
742 if (status) {
743 ALOGE("Failed to add mcast group fatal_events :%d", status);
744 goto cld80211_cleanup;
745 }
746
747 if(info->wifihal_ctrl_sock.s > 0)
748 {
749 status = cld80211_add_mcast_group(info->cldctx, "oem_msgs");
750 if (status) {
751 ALOGE("Failed to add mcast group oem_msgs :%d", status);
752 goto cld80211_cleanup;
753 }
754 }
755 } else {
756 ret = wifi_init_user_sock(info);
757 if (ret != WIFI_SUCCESS) {
758 ALOGE("Failed to alloc user socket");
759 goto unload;
760 }
761 }
762
763 ret = wifi_init_interfaces(*handle);
764 if (ret != WIFI_SUCCESS) {
765 ALOGE("Failed to init interfaces");
766 goto unload;
767 }
768
769 if (info->num_interfaces == 0) {
770 ALOGE("No interfaces found");
771 ret = WIFI_ERROR_UNINITIALIZED;
772 goto unload;
773 }
774
775 index = wifi_get_iface_id(info, "wlan0");
776 if (index == -1) {
777 int i;
778 for (i = 0; i < info->num_interfaces; i++)
779 {
780 free(info->interfaces[i]);
781 }
782 ALOGE("%s no iface with wlan0", __func__);
783 goto unload;
784 }
785 iface_handle = (wifi_interface_handle)info->interfaces[index];
786
787 ret = acquire_supported_features(iface_handle,
788 &info->supported_feature_set);
789 if (ret != WIFI_SUCCESS) {
790 ALOGI("Failed to get supported feature set : %d", ret);
791 //acquire_supported_features failure is acceptable condition as legacy
792 //drivers might not support the required vendor command. So, do not
793 //consider it as failure of wifi_initialize
794 ret = WIFI_SUCCESS;
795 }
796
797 ret = acquire_driver_supported_features(iface_handle,
798 &info->driver_supported_features);
799 if (ret != WIFI_SUCCESS) {
800 ALOGI("Failed to get vendor feature set : %d", ret);
801 ret = WIFI_SUCCESS;
802 }
803
804 ret = wifi_get_logger_supported_feature_set(iface_handle,
805 &info->supported_logger_feature_set);
806 if (ret != WIFI_SUCCESS)
807 ALOGE("Failed to get supported logger feature set: %d", ret);
808
809 ret = wifi_get_firmware_version(iface_handle, hw_ver_type,
810 MAX_HW_VER_LENGTH);
811 if (ret == WIFI_SUCCESS) {
812 hw_name = strstr(hw_ver_type, "HW:");
813 if (hw_name) {
814 hw_name += strlen("HW:");
815 if (strncmp(hw_name, "QCA6174", 7) == 0)
816 info->pkt_log_ver = PKT_LOG_V1;
817 else
818 info->pkt_log_ver = PKT_LOG_V2;
819 } else {
820 info->pkt_log_ver = PKT_LOG_V0;
821 }
822 ALOGV("%s: hardware version type %d", __func__, info->pkt_log_ver);
823 } else {
824 ALOGE("Failed to get firmware version: %d", ret);
825 }
826
827 ret = get_firmware_bus_max_size_supported(iface_handle);
828 if (ret != WIFI_SUCCESS) {
829 ALOGE("Failed to get supported bus size, error : %d", ret);
830 info->firmware_bus_max_size = 1520;
831 }
832
833 ret = wifi_logger_ring_buffers_init(info);
834 if (ret != WIFI_SUCCESS)
835 ALOGE("Wifi Logger Ring Initialization Failed");
836
837 ret = wifi_get_capabilities(iface_handle);
838 if (ret != WIFI_SUCCESS)
839 ALOGE("Failed to get wifi Capabilities, error: %d", ret);
840
841 info->pkt_stats = (struct pkt_stats_s *)malloc(sizeof(struct pkt_stats_s));
842 if (!info->pkt_stats) {
843 ALOGE("%s: malloc Failed for size: %zu",
844 __FUNCTION__, sizeof(struct pkt_stats_s));
845 ret = WIFI_ERROR_OUT_OF_MEMORY;
846 goto unload;
847 }
848
849 info->rx_buf_size_allocated = MAX_RXMPDUS_PER_AMPDU * MAX_MSDUS_PER_MPDU
850 * PKT_STATS_BUF_SIZE;
851
852 info->rx_aggr_pkts =
853 (wifi_ring_buffer_entry *)malloc(info->rx_buf_size_allocated);
854 if (!info->rx_aggr_pkts) {
855 ALOGE("%s: malloc Failed for size: %d",
856 __FUNCTION__, info->rx_buf_size_allocated);
857 ret = WIFI_ERROR_OUT_OF_MEMORY;
858 info->rx_buf_size_allocated = 0;
859 goto unload;
860 }
861 memset(info->rx_aggr_pkts, 0, info->rx_buf_size_allocated);
862
863 info->exit_sockets[0] = -1;
864 info->exit_sockets[1] = -1;
865
866 if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->exit_sockets) == -1) {
867 ALOGE("Failed to create exit socket pair");
868 ret = WIFI_ERROR_UNKNOWN;
869 goto unload;
870 }
871
872 ALOGV("Initializing Gscan Event Handlers");
873 ret = initializeGscanHandlers(info);
874 if (ret != WIFI_SUCCESS) {
875 ALOGE("Initializing Gscan Event Handlers Failed");
876 goto unload;
877 }
878
879 ret = initializeRSSIMonitorHandler(info);
880 if (ret != WIFI_SUCCESS) {
881 ALOGE("Initializing RSSI Event Handler Failed");
882 goto unload;
883 }
884
885 ALOGV("Initialized Wifi HAL Successfully; vendor cmd = %d Supported"
886 " features : 0x%" PRIx64, NL80211_CMD_VENDOR, info->supported_feature_set);
887
888 cld80211_cleanup:
889 if (status != 0 || ret != WIFI_SUCCESS) {
890 ret = WIFI_ERROR_UNKNOWN;
891 cld80211lib_cleanup(info);
892 }
893 unload:
894 if (ret != WIFI_SUCCESS) {
895 if (cmd_sock)
896 nl_socket_free(cmd_sock);
897 if (event_sock)
898 nl_socket_free(event_sock);
899 if (info) {
900 if (info->cldctx) {
901 cld80211lib_cleanup(info);
902 } else if (info->user_sock) {
903 nl_socket_free(info->user_sock);
904 }
905 if (info->pkt_stats) free(info->pkt_stats);
906 if (info->rx_aggr_pkts) free(info->rx_aggr_pkts);
907 wifi_logger_ring_buffers_deinit(info);
908 cleanupGscanHandlers(info);
909 cleanupRSSIMonitorHandler(info);
910 free(info->event_cb);
911 if (info->driver_supported_features.flags) {
912 free(info->driver_supported_features.flags);
913 info->driver_supported_features.flags = NULL;
914 }
915 free(info);
916 }
917 }
918
919 return ret;
920 }
921
922 #ifdef WIFI_DRIVER_STATE_CTRL_PARAM
wifi_update_driver_state(const char * state)923 static int wifi_update_driver_state(const char *state) {
924 struct timespec ts;
925 int len, fd, ret = 0, count = 5;
926 ts.tv_sec = 0;
927 ts.tv_nsec = 200 * 1000000L;
928
929 do {
930 if (access(WIFI_DRIVER_STATE_CTRL_PARAM, W_OK) == 0)
931 break;
932 nanosleep(&ts, (struct timespec *)NULL);
933 } while (--count > 0); /* wait at most 1 second for completion. */
934 if (count == 0) {
935 ALOGE("Failed to access driver state control param %s, %d at %s",
936 strerror(errno), errno, WIFI_DRIVER_STATE_CTRL_PARAM);
937 return -1;
938 }
939
940 fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_STATE_CTRL_PARAM, O_WRONLY));
941 if (fd < 0) {
942 ALOGE("Failed to open driver state control param at %s",
943 WIFI_DRIVER_STATE_CTRL_PARAM);
944 return -1;
945 }
946
947 len = strlen(state) + 1;
948 if (TEMP_FAILURE_RETRY(write(fd, state, len)) != len) {
949 ALOGE("Failed to write driver state control param at %s",
950 WIFI_DRIVER_STATE_CTRL_PARAM);
951 ret = -1;
952 }
953
954 close(fd);
955 return ret;
956 }
957 #endif
958
wifi_wait_for_driver_ready(void)959 wifi_error wifi_wait_for_driver_ready(void)
960 {
961 // This function will wait to make sure basic client netdev is created
962 // Function times out after 10 seconds
963 int count = (POLL_DRIVER_MAX_TIME_MS * 1000) / POLL_DRIVER_DURATION_US;
964 FILE *fd;
965
966 #if defined(WIFI_DRIVER_STATE_CTRL_PARAM) && defined(WIFI_DRIVER_STATE_ON)
967 if (wifi_update_driver_state(WIFI_DRIVER_STATE_ON) < 0) {
968 return WIFI_ERROR_UNKNOWN;
969 }
970 #endif
971
972 do {
973 if ((fd = fopen("/sys/class/net/wlan0", "r")) != NULL) {
974 fclose(fd);
975 return WIFI_SUCCESS;
976 }
977 usleep(POLL_DRIVER_DURATION_US);
978 } while(--count > 0);
979
980 ALOGE("Timed out wating on Driver ready ... ");
981 return WIFI_ERROR_TIMED_OUT;
982 }
983
wifi_add_membership(wifi_handle handle,const char * group)984 static int wifi_add_membership(wifi_handle handle, const char *group)
985 {
986 hal_info *info = getHalInfo(handle);
987
988 int id = wifi_get_multicast_id(handle, "nl80211", group);
989 if (id < 0) {
990 ALOGE("Could not find group %s", group);
991 return id;
992 }
993
994 int ret = nl_socket_add_membership(info->event_sock, id);
995 if (ret < 0) {
996 ALOGE("Could not add membership to group %s", group);
997 }
998
999 return ret;
1000 }
1001
internal_cleaned_up_handler(wifi_handle handle)1002 static void internal_cleaned_up_handler(wifi_handle handle)
1003 {
1004 hal_info *info = getHalInfo(handle);
1005 wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
1006 wifihal_mon_sock_t *reg, *tmp;
1007
1008 if (info->cmd_sock != 0) {
1009 nl_socket_free(info->cmd_sock);
1010 nl_socket_free(info->event_sock);
1011 info->cmd_sock = NULL;
1012 info->event_sock = NULL;
1013 }
1014
1015 if (info->wifihal_ctrl_sock.s != 0) {
1016 close(info->wifihal_ctrl_sock.s);
1017 unlink(info->wifihal_ctrl_sock.local.sun_path);
1018 info->wifihal_ctrl_sock.s = 0;
1019 }
1020
1021 list_for_each_entry_safe(reg, tmp, &info->monitor_sockets, list) {
1022 del_from_list(®->list);
1023 if(reg) {
1024 free(reg);
1025 }
1026 }
1027
1028 if (info->interfaces) {
1029 for (int i = 0; i < info->num_interfaces; i++)
1030 free(info->interfaces[i]);
1031 free(info->interfaces);
1032 }
1033
1034 if (info->cldctx != NULL) {
1035 cld80211lib_cleanup(info);
1036 } else if (info->user_sock != 0) {
1037 nl_socket_free(info->user_sock);
1038 info->user_sock = NULL;
1039 }
1040
1041 if (info->pkt_stats)
1042 free(info->pkt_stats);
1043 if (info->rx_aggr_pkts)
1044 free(info->rx_aggr_pkts);
1045 wifi_logger_ring_buffers_deinit(info);
1046 cleanupGscanHandlers(info);
1047 cleanupRSSIMonitorHandler(info);
1048
1049 if (info->num_event_cb)
1050 ALOGE("%d events were leftover without being freed",
1051 info->num_event_cb);
1052 free(info->event_cb);
1053
1054 if (info->exit_sockets[0] >= 0) {
1055 close(info->exit_sockets[0]);
1056 info->exit_sockets[0] = -1;
1057 }
1058
1059 if (info->exit_sockets[1] >= 0) {
1060 close(info->exit_sockets[1]);
1061 info->exit_sockets[1] = -1;
1062 }
1063
1064 if (info->pkt_fate_stats) {
1065 free(info->pkt_fate_stats);
1066 info->pkt_fate_stats = NULL;
1067 }
1068
1069 if (info->driver_supported_features.flags) {
1070 free(info->driver_supported_features.flags);
1071 info->driver_supported_features.flags = NULL;
1072 }
1073
1074 (*cleaned_up_handler)(handle);
1075 pthread_mutex_destroy(&info->cb_lock);
1076 pthread_mutex_destroy(&info->pkt_fate_stats_lock);
1077 free(info);
1078 }
1079
wifi_cleanup(wifi_handle handle,wifi_cleaned_up_handler handler)1080 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
1081 {
1082 if (!handle) {
1083 ALOGE("Handle is null");
1084 return;
1085 }
1086
1087 hal_info *info = getHalInfo(handle);
1088 info->cleaned_up_handler = handler;
1089 info->clean_up = true;
1090 // Remove the dynamically created interface during wifi cleanup.
1091 wifi_cleanup_dynamic_ifaces(handle);
1092
1093
1094 TEMP_FAILURE_RETRY(write(info->exit_sockets[0], "E", 1));
1095 ALOGI("Sent msg on exit sock to unblock poll()");
1096 }
1097
1098
1099
validate_cld80211_msg(nlmsghdr * nlh,int family,int cmd)1100 static int validate_cld80211_msg(nlmsghdr *nlh, int family, int cmd)
1101 {
1102 //! Enhance this API
1103 struct genlmsghdr *hdr;
1104 hdr = (genlmsghdr *)nlmsg_data(nlh);
1105
1106 if (nlh->nlmsg_len > DEFAULT_PAGE_SIZE - sizeof(wifihal_ctrl_req_t))
1107 {
1108 ALOGE("%s: Invalid nlmsg length", __FUNCTION__);
1109 return -1;
1110 }
1111 if(hdr->cmd == WLAN_NL_MSG_OEM)
1112 {
1113 ALOGV("%s: FAMILY ID : %d ,NL CMD : %d received", __FUNCTION__,
1114 nlh->nlmsg_type, hdr->cmd);
1115
1116 //! Update pid with the wifihal pid
1117 nlh->nlmsg_pid = getpid();
1118 return 0;
1119 }
1120 else
1121 {
1122 ALOGE("%s: NL CMD : %d received is not allowed", __FUNCTION__, hdr->cmd);
1123 return -1;
1124 }
1125 }
1126
1127
validate_genl_msg(nlmsghdr * nlh,int family,int cmd)1128 static int validate_genl_msg(nlmsghdr *nlh, int family, int cmd)
1129 {
1130 //! Enhance this API
1131 struct genlmsghdr *hdr;
1132 hdr = (genlmsghdr *)nlmsg_data(nlh);
1133
1134 if (nlh->nlmsg_len > DEFAULT_PAGE_SIZE - sizeof(wifihal_ctrl_req_t))
1135 {
1136 ALOGE("%s: Invalid nlmsg length", __FUNCTION__);
1137 return -1;
1138 }
1139 if(hdr->cmd == NL80211_CMD_FRAME ||
1140 hdr->cmd == NL80211_CMD_REGISTER_ACTION)
1141 {
1142 ALOGV("%s: FAMILY ID : %d ,NL CMD : %d received", __FUNCTION__,
1143 nlh->nlmsg_type, hdr->cmd);
1144 return 0;
1145 }
1146 else
1147 {
1148 ALOGE("%s: NL CMD : %d received is not allowed", __FUNCTION__, hdr->cmd);
1149 return -1;
1150 }
1151 }
1152
send_nl_data(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg)1153 static int send_nl_data(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
1154 {
1155 hal_info *info = getHalInfo(handle);
1156 struct nl_msg *msg = NULL;
1157 int retval = -1;
1158
1159 //! attach monitor socket if it was not it the list
1160 if(ctrl_msg->monsock_len)
1161 {
1162 retval = attach_monitor_sock(handle, ctrl_msg);
1163 if(retval)
1164 goto nl_out;
1165 }
1166
1167 msg = nlmsg_alloc();
1168 if (!msg)
1169 {
1170 ALOGE("%s: Memory allocation failed \n", __FUNCTION__);
1171 goto nl_out;
1172 }
1173
1174 if (ctrl_msg->data_len > nlmsg_get_max_size(msg))
1175 {
1176 ALOGE("%s: Invalid ctrl msg length \n", __FUNCTION__);
1177 retval = -1;
1178 goto nl_out;
1179 }
1180 memcpy((char *)msg->nm_nlh, (char *)ctrl_msg->data, ctrl_msg->data_len);
1181
1182 if(ctrl_msg->family_name == GENERIC_NL_FAMILY)
1183 {
1184 //! Before sending the received gennlmsg to kernel,
1185 //! better to have checks for allowed commands
1186 retval = validate_genl_msg(msg->nm_nlh, ctrl_msg->family_name, ctrl_msg->cmd_id);
1187 if (retval < 0)
1188 goto nl_out;
1189
1190 retval = nl_send_auto_complete(info->event_sock, msg); /* send message */
1191 if (retval < 0)
1192 {
1193 ALOGE("%s: nl_send_auto_complete - failed : %d \n", __FUNCTION__, retval);
1194 goto nl_out;
1195 }
1196
1197 retval = internal_pollin_handler(handle, info->event_sock);
1198 }
1199 else if (ctrl_msg->family_name == CLD80211_FAMILY)
1200 {
1201 if (info->cldctx != NULL)
1202 {
1203 //! Before sending the received cld80211 msg to kernel,
1204 //! better to have checks for allowed commands
1205 retval = validate_cld80211_msg(msg->nm_nlh, ctrl_msg->family_name, ctrl_msg->cmd_id);
1206 if (retval < 0)
1207 goto nl_out;
1208
1209 retval = cld80211_send_msg(info->cldctx, msg);
1210 if (retval != 0)
1211 {
1212 ALOGE("%s: send cld80211 message - failed\n", __FUNCTION__);
1213 goto nl_out;
1214 }
1215 ALOGD("%s: sent cld80211 message for pid %d\n", __FUNCTION__, getpid());
1216 }
1217 else
1218 {
1219 ALOGE("%s: cld80211 ctx not present \n", __FUNCTION__);
1220 }
1221 }
1222 else
1223 {
1224 ALOGE("%s: Unknown family name : %d \n", __FUNCTION__, ctrl_msg->family_name);
1225 retval = -1;
1226 }
1227 nl_out:
1228 if (msg)
1229 {
1230 nlmsg_free(msg);
1231 }
1232 return retval;
1233 }
1234
register_monitor_sock(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg,int attach)1235 static int register_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg, int attach)
1236 {
1237 hal_info *info = getHalInfo(handle);
1238
1239 wifihal_mon_sock_t *reg, *nreg;
1240 char *match = NULL;
1241 unsigned int match_len = 0;
1242 unsigned int type;
1243
1244 //! For Register Action frames, compare the match length and match buffer.
1245 //! For other registrations such as oem messages,
1246 //! diag messages check for respective commands
1247
1248 if((ctrl_msg->family_name == GENERIC_NL_FAMILY) &&
1249 (ctrl_msg->cmd_id == NL80211_CMD_REGISTER_ACTION))
1250 {
1251 struct genlmsghdr *genlh;
1252 struct nlmsghdr *nlh = (struct nlmsghdr *)ctrl_msg->data;
1253 genlh = (struct genlmsghdr *)nlmsg_data(nlh);
1254 struct nlattr *nlattrs[NL80211_ATTR_MAX + 1];
1255
1256 if (nlh->nlmsg_len > DEFAULT_PAGE_SIZE - sizeof(*ctrl_msg))
1257 {
1258 ALOGE("%s: Invalid nlmsg length", __FUNCTION__);
1259 return -1;
1260 }
1261 if (nla_parse(nlattrs, NL80211_ATTR_MAX, genlmsg_attrdata(genlh, 0),
1262 genlmsg_attrlen(genlh, 0), NULL))
1263 {
1264 ALOGE("unable to parse nl attributes");
1265 return -1;
1266 }
1267 if (!nlattrs[NL80211_ATTR_FRAME_TYPE])
1268 {
1269 ALOGD("No Valid frame type");
1270 }
1271 else
1272 {
1273 type = nla_get_u16(nlattrs[NL80211_ATTR_FRAME_TYPE]);
1274 }
1275 if (!nlattrs[NL80211_ATTR_FRAME_MATCH])
1276 {
1277 ALOGE("No Frame Match");
1278 return -1;
1279 }
1280 else
1281 {
1282 match_len = nla_len(nlattrs[NL80211_ATTR_FRAME_MATCH]);
1283 match = (char *)nla_data(nlattrs[NL80211_ATTR_FRAME_MATCH]);
1284
1285 list_for_each_entry(reg, &info->monitor_sockets, list) {
1286
1287 if(reg == NULL)
1288 break;
1289
1290 int mlen = min(match_len, reg->match_len);
1291
1292 if (reg->match_len == 0)
1293 continue;
1294
1295 if (memcmp(reg->match, match, mlen) == 0) {
1296
1297 if((ctrl_msg->monsock_len == reg->monsock_len) &&
1298 (memcmp((char *)®->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len) == 0))
1299 {
1300 if(attach)
1301 {
1302 ALOGE(" %s :Action frame already registered for this client ", __FUNCTION__);
1303 return -2;
1304 }
1305 else
1306 {
1307 del_from_list(®->list);
1308 free(reg);
1309 return 0;
1310 }
1311 }
1312 else
1313 {
1314 //! when action frame registered for other client,
1315 //! you can't attach or dettach for new client
1316 ALOGE(" %s :Action frame registered for other client ", __FUNCTION__);
1317 return -2;
1318 }
1319 }
1320 }
1321 }
1322 }
1323 else
1324 {
1325 list_for_each_entry(reg, &info->monitor_sockets, list) {
1326
1327 //! Checking for monitor sock in the list :
1328
1329 //! For attach request :
1330 //! if sock is not present, then it is a new entry , so add to list.
1331 //! if sock is present, and cmd_id does not match, add another entry to list.
1332 //! if sock is present, and cmd_id matches, return 0.
1333
1334 //! For dettach req :
1335 //! if sock is not present, return error -2.
1336 //! if sock is present, and cmd_id does not match, return error -2.
1337 //! if sock is present, and cmd_id matches, delete entry and return 0.
1338 if(reg == NULL)
1339 break;
1340
1341 if (ctrl_msg->monsock_len != reg->monsock_len)
1342 continue;
1343
1344 if (memcmp((char *)®->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len) == 0) {
1345
1346 if((reg->family_name == ctrl_msg->family_name) && (reg->cmd_id == ctrl_msg->cmd_id))
1347 {
1348 if(!attach)
1349 {
1350 del_from_list(®->list);
1351 free(reg);
1352 }
1353 return 0;
1354 }
1355 }
1356 }
1357 }
1358
1359 if(attach)
1360 {
1361 if (ctrl_msg->monsock_len > sizeof(struct sockaddr_un))
1362 {
1363 ALOGE("%s: Invalid monitor socket length \n", __FUNCTION__);
1364 return -3;
1365 }
1366
1367 nreg = (wifihal_mon_sock_t *)malloc(sizeof(*reg) + match_len);
1368 if (!nreg)
1369 return -1;
1370
1371 memset((char *)nreg, 0, sizeof(*reg) + match_len);
1372 nreg->family_name = ctrl_msg->family_name;
1373 nreg->cmd_id = ctrl_msg->cmd_id;
1374 nreg->monsock_len = ctrl_msg->monsock_len;
1375 memcpy((char *)&nreg->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len);
1376
1377 if(match_len && match)
1378 {
1379 nreg->match_len = match_len;
1380 memcpy(nreg->match, match, match_len);
1381 }
1382 add_to_list(&nreg->list, &info->monitor_sockets);
1383 }
1384 else
1385 {
1386 //! Not attached, so cant be dettached
1387 ALOGE("%s: Dettaching the unregistered socket \n", __FUNCTION__);
1388 return -2;
1389 }
1390
1391 return 0;
1392 }
1393
attach_monitor_sock(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg)1394 static int attach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
1395 {
1396 return register_monitor_sock(handle, ctrl_msg, 1);
1397 }
1398
dettach_monitor_sock(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg)1399 static int dettach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
1400 {
1401 return register_monitor_sock(handle, ctrl_msg, 0);
1402 }
1403
internal_pollin_handler_app(wifi_handle handle,struct ctrl_sock * sock)1404 static int internal_pollin_handler_app(wifi_handle handle, struct ctrl_sock *sock)
1405 {
1406 int retval = -1;
1407 int res;
1408 struct sockaddr_un from;
1409 socklen_t fromlen = sizeof(from);
1410 wifihal_ctrl_req_t *ctrl_msg;
1411 wifihal_ctrl_sync_rsp_t ctrl_reply;
1412
1413 ctrl_msg = (wifihal_ctrl_req_t *)malloc(DEFAULT_PAGE_SIZE);
1414 if(ctrl_msg == NULL)
1415 {
1416 ALOGE ("Memory allocation failure");
1417 return -1;
1418 }
1419
1420 memset((char *)ctrl_msg, 0, DEFAULT_PAGE_SIZE);
1421
1422 res = recvfrom(sock->s, (char *)ctrl_msg, DEFAULT_PAGE_SIZE, 0,
1423 (struct sockaddr *)&from, &fromlen);
1424 if (res < 0) {
1425 ALOGE("recvfrom(ctrl_iface): %s",
1426 strerror(errno));
1427 if(ctrl_msg)
1428 free(ctrl_msg);
1429
1430 return 0;
1431 }
1432 switch(ctrl_msg->ctrl_cmd)
1433 {
1434 case WIFIHAL_CTRL_MONITOR_ATTACH:
1435 retval = attach_monitor_sock(handle, ctrl_msg);
1436 break;
1437 case WIFIHAL_CTRL_MONITOR_DETTACH:
1438 retval = dettach_monitor_sock(handle, ctrl_msg);
1439 break;
1440 case WIFIHAL_CTRL_SEND_NL_DATA:
1441 retval = send_nl_data(handle, ctrl_msg);
1442 break;
1443 default:
1444 break;
1445 }
1446
1447 ctrl_reply.ctrl_cmd = ctrl_msg->ctrl_cmd;
1448 ctrl_reply.family_name = ctrl_msg->family_name;
1449 ctrl_reply.cmd_id = ctrl_msg->cmd_id;
1450 ctrl_reply.status = retval;
1451
1452 if(ctrl_msg)
1453 free(ctrl_msg);
1454
1455 if (sendto(sock->s, (char *)&ctrl_reply, sizeof(ctrl_reply), 0, (struct sockaddr *)&from,
1456 fromlen) < 0) {
1457 int _errno = errno;
1458 ALOGE("socket send failed : %d",_errno);
1459
1460 if (_errno == ENOBUFS || _errno == EAGAIN) {
1461 /*
1462 * The socket send buffer could be full. This
1463 * may happen if client programs are not
1464 * receiving their pending messages. Close and
1465 * reopen the socket as a workaround to avoid
1466 * getting stuck being unable to send any new
1467 * responses.
1468 */
1469 }
1470 }
1471 return res;
1472 }
1473
internal_pollin_handler(wifi_handle handle,struct nl_sock * sock)1474 static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock)
1475 {
1476 struct nl_cb *cb = nl_socket_get_cb(sock);
1477
1478 int res = nl_recvmsgs(sock, cb);
1479 if(res)
1480 ALOGE("Error :%d while reading nl msg", res);
1481 nl_cb_put(cb);
1482 return res;
1483 }
1484
internal_event_handler_app(wifi_handle handle,int events,struct ctrl_sock * sock)1485 static void internal_event_handler_app(wifi_handle handle, int events,
1486 struct ctrl_sock *sock)
1487 {
1488 if (events & POLLERR) {
1489 ALOGE("Error reading from wifi_hal ctrl socket");
1490 internal_pollin_handler_app(handle, sock);
1491 } else if (events & POLLHUP) {
1492 ALOGE("Remote side hung up");
1493 } else if (events & POLLIN) {
1494 //ALOGI("Found some events!!!");
1495 internal_pollin_handler_app(handle, sock);
1496 } else {
1497 ALOGE("Unknown event - %0x", events);
1498 }
1499 }
1500
internal_event_handler(wifi_handle handle,int events,struct nl_sock * sock)1501 static void internal_event_handler(wifi_handle handle, int events,
1502 struct nl_sock *sock)
1503 {
1504 if (events & POLLERR) {
1505 ALOGE("Error reading from socket");
1506 internal_pollin_handler(handle, sock);
1507 } else if (events & POLLHUP) {
1508 ALOGE("Remote side hung up");
1509 } else if (events & POLLIN) {
1510 //ALOGI("Found some events!!!");
1511 internal_pollin_handler(handle, sock);
1512 } else {
1513 ALOGE("Unknown event - %0x", events);
1514 }
1515 }
1516
1517 /* Run event handler */
wifi_event_loop(wifi_handle handle)1518 void wifi_event_loop(wifi_handle handle)
1519 {
1520 hal_info *info = getHalInfo(handle);
1521 if (info->in_event_loop) {
1522 return;
1523 } else {
1524 info->in_event_loop = true;
1525 }
1526
1527 pollfd pfd[4];
1528 memset(&pfd, 0, 4*sizeof(pfd[0]));
1529
1530 pfd[0].fd = nl_socket_get_fd(info->event_sock);
1531 pfd[0].events = POLLIN;
1532
1533 pfd[1].fd = nl_socket_get_fd(info->user_sock);
1534 pfd[1].events = POLLIN;
1535
1536 pfd[2].fd = info->exit_sockets[1];
1537 pfd[2].events = POLLIN;
1538
1539 if(info->wifihal_ctrl_sock.s > 0) {
1540 pfd[3].fd = info->wifihal_ctrl_sock.s ;
1541 pfd[3].events = POLLIN;
1542 }
1543 /* TODO: Add support for timeouts */
1544
1545 do {
1546 pfd[0].revents = 0;
1547 pfd[1].revents = 0;
1548 pfd[2].revents = 0;
1549 pfd[3].revents = 0;
1550 //ALOGI("Polling sockets");
1551 int result = poll(pfd, 4, -1);
1552 if (result < 0) {
1553 ALOGE("Error polling socket");
1554 } else {
1555 if (pfd[0].revents & (POLLIN | POLLHUP | POLLERR)) {
1556 internal_event_handler(handle, pfd[0].revents, info->event_sock);
1557 }
1558 if (pfd[1].revents & (POLLIN | POLLHUP | POLLERR)) {
1559 internal_event_handler(handle, pfd[1].revents, info->user_sock);
1560 }
1561 if ((info->wifihal_ctrl_sock.s > 0) && (pfd[3].revents & (POLLIN | POLLHUP | POLLERR))) {
1562 internal_event_handler_app(handle, pfd[3].revents, &info->wifihal_ctrl_sock);
1563 }
1564 }
1565 rb_timerhandler(info);
1566 } while (!info->clean_up);
1567 internal_cleaned_up_handler(handle);
1568 }
1569
user_sock_message_handler(nl_msg * msg,void * arg)1570 static int user_sock_message_handler(nl_msg *msg, void *arg)
1571 {
1572 wifi_handle handle = (wifi_handle)arg;
1573 hal_info *info = getHalInfo(handle);
1574
1575 diag_message_handler(info, msg);
1576
1577 return NL_OK;
1578 }
1579
internal_valid_message_handler(nl_msg * msg,void * arg)1580 static int internal_valid_message_handler(nl_msg *msg, void *arg)
1581 {
1582 wifi_handle handle = (wifi_handle)arg;
1583 hal_info *info = getHalInfo(handle);
1584
1585 WifiEvent event(msg);
1586 int res = event.parse();
1587 if (res < 0) {
1588 ALOGE("Failed to parse event: %d", res);
1589 return NL_SKIP;
1590 }
1591
1592 int cmd = event.get_cmd();
1593 uint32_t vendor_id = 0;
1594 int subcmd = 0;
1595
1596 if (cmd == NL80211_CMD_VENDOR) {
1597 vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
1598 subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
1599 /* Restrict printing GSCAN_FULL_RESULT which is causing lot
1600 of logs in bug report */
1601 if (subcmd != QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT) {
1602 ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
1603 event.get_cmdString(), vendor_id, subcmd);
1604 }
1605 }
1606 else if((info->wifihal_ctrl_sock.s > 0) && (cmd == NL80211_CMD_FRAME))
1607 {
1608 struct genlmsghdr *genlh;
1609 struct nlmsghdr *nlh = nlmsg_hdr(msg);
1610 genlh = (struct genlmsghdr *)nlmsg_data(nlh);
1611 struct nlattr *nlattrs[NL80211_ATTR_MAX + 1];
1612
1613 wifihal_ctrl_event_t *ctrl_evt;
1614 char *buff;
1615 wifihal_mon_sock_t *reg;
1616
1617 nla_parse(nlattrs, NL80211_ATTR_MAX, genlmsg_attrdata(genlh, 0),
1618 genlmsg_attrlen(genlh, 0), NULL);
1619
1620 if (!nlattrs[NL80211_ATTR_FRAME])
1621 {
1622 ALOGD("No Frame body");
1623 return WIFI_SUCCESS;
1624 }
1625 ctrl_evt = (wifihal_ctrl_event_t *)malloc(sizeof(*ctrl_evt) + nlh->nlmsg_len);
1626 if(ctrl_evt == NULL)
1627 {
1628 ALOGE("Memory allocation failure");
1629 return -1;
1630 }
1631 memset((char *)ctrl_evt, 0, sizeof(*ctrl_evt) + nlh->nlmsg_len);
1632 ctrl_evt->family_name = GENERIC_NL_FAMILY;
1633 ctrl_evt->cmd_id = cmd;
1634 ctrl_evt->data_len = nlh->nlmsg_len;
1635 memcpy(ctrl_evt->data, (char *)nlh, ctrl_evt->data_len);
1636
1637
1638 buff = (char *)nla_data(nlattrs[NL80211_ATTR_FRAME]) + 24; //! Size of Wlan80211FrameHeader
1639
1640 list_for_each_entry(reg, &info->monitor_sockets, list) {
1641
1642 if(reg == NULL)
1643 break;
1644
1645 if (memcmp(reg->match, buff, reg->match_len))
1646 continue;
1647
1648 /* found match! */
1649 /* Indicate the received Action frame to respective client */
1650 if (sendto(info->wifihal_ctrl_sock.s, (char *)ctrl_evt,
1651 sizeof(*ctrl_evt) + ctrl_evt->data_len,
1652 0, (struct sockaddr *)®->monsock, reg->monsock_len) < 0)
1653 {
1654 int _errno = errno;
1655 ALOGE("socket send failed : %d",_errno);
1656
1657 if (_errno == ENOBUFS || _errno == EAGAIN) {
1658 }
1659 }
1660
1661 }
1662 free(ctrl_evt);
1663 }
1664
1665 else {
1666 ALOGV("event received %s", event.get_cmdString());
1667 }
1668
1669 // event.log();
1670
1671 bool dispatched = false;
1672
1673 pthread_mutex_lock(&info->cb_lock);
1674
1675 for (int i = 0; i < info->num_event_cb; i++) {
1676 if (cmd == info->event_cb[i].nl_cmd) {
1677 if (cmd == NL80211_CMD_VENDOR
1678 && ((vendor_id != info->event_cb[i].vendor_id)
1679 || (subcmd != info->event_cb[i].vendor_subcmd)))
1680 {
1681 /* event for a different vendor, ignore it */
1682 continue;
1683 }
1684
1685 cb_info *cbi = &(info->event_cb[i]);
1686 pthread_mutex_unlock(&info->cb_lock);
1687 if (cbi->cb_func) {
1688 (*(cbi->cb_func))(msg, cbi->cb_arg);
1689 dispatched = true;
1690 }
1691 return NL_OK;
1692 }
1693 }
1694
1695 #ifdef QC_HAL_DEBUG
1696 if (!dispatched) {
1697 ALOGI("event ignored!!");
1698 }
1699 #endif
1700
1701 pthread_mutex_unlock(&info->cb_lock);
1702 return NL_OK;
1703 }
1704
1705 ////////////////////////////////////////////////////////////////////////////////
1706
1707 class GetMulticastIdCommand : public WifiCommand
1708 {
1709 private:
1710 const char *mName;
1711 const char *mGroup;
1712 int mId;
1713 public:
GetMulticastIdCommand(wifi_handle handle,const char * name,const char * group)1714 GetMulticastIdCommand(wifi_handle handle, const char *name,
1715 const char *group) : WifiCommand(handle, 0)
1716 {
1717 mName = name;
1718 mGroup = group;
1719 mId = -1;
1720 }
1721
getId()1722 int getId() {
1723 return mId;
1724 }
1725
create()1726 virtual wifi_error create() {
1727 int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
1728 // ALOGI("ctrl family = %d", nlctrlFamily);
1729 wifi_error ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
1730 if (ret != WIFI_SUCCESS)
1731 return ret;
1732
1733 ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
1734 return ret;
1735 }
1736
handleResponse(WifiEvent & reply)1737 virtual int handleResponse(WifiEvent& reply) {
1738
1739 // ALOGI("handling reponse in %s", __func__);
1740
1741 struct nlattr **tb = reply.attributes();
1742 struct nlattr *mcgrp = NULL;
1743 int i;
1744
1745 if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
1746 ALOGI("No multicast groups found");
1747 return NL_SKIP;
1748 } else {
1749 // ALOGI("Multicast groups attr size = %d",
1750 // nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
1751 }
1752
1753 for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
1754
1755 // ALOGI("Processing group");
1756 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
1757 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
1758 nla_len(mcgrp), NULL);
1759 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID])
1760 {
1761 continue;
1762 }
1763
1764 char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
1765 int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
1766
1767 // ALOGI("Found group name %s", grpName);
1768
1769 if (strncmp(grpName, mGroup, grpNameLen) != 0)
1770 continue;
1771
1772 mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
1773 break;
1774 }
1775
1776 return NL_SKIP;
1777 }
1778
1779 };
1780
wifi_get_multicast_id(wifi_handle handle,const char * name,const char * group)1781 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
1782 const char *group)
1783 {
1784 GetMulticastIdCommand cmd(handle, name, group);
1785 int res = cmd.requestResponse();
1786 if (res < 0)
1787 return res;
1788 else
1789 return cmd.getId();
1790 }
1791
1792 /////////////////////////////////////////////////////////////////////////
1793
is_wifi_interface(const char * name)1794 static bool is_wifi_interface(const char *name)
1795 {
1796 if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0
1797 && strncmp(name, "wifi", 4) != 0) {
1798 /* not a wifi interface; ignore it */
1799 return false;
1800 } else {
1801 return true;
1802 }
1803 }
1804
get_interface(const char * name,interface_info * info)1805 static int get_interface(const char *name, interface_info *info)
1806 {
1807 strlcpy(info->name, name, (IFNAMSIZ + 1));
1808 info->id = if_nametoindex(name);
1809 // ALOGI("found an interface : %s, id = %d", name, info->id);
1810 return WIFI_SUCCESS;
1811 }
1812
wifi_init_interfaces(wifi_handle handle)1813 wifi_error wifi_init_interfaces(wifi_handle handle)
1814 {
1815 hal_info *info = (hal_info *)handle;
1816
1817 struct dirent *de;
1818
1819 DIR *d = opendir("/sys/class/net");
1820 if (d == 0)
1821 return WIFI_ERROR_UNKNOWN;
1822
1823 int n = 0;
1824 while ((de = readdir(d))) {
1825 if (de->d_name[0] == '.')
1826 continue;
1827 if (is_wifi_interface(de->d_name) ) {
1828 n++;
1829 }
1830 }
1831
1832 closedir(d);
1833
1834 d = opendir("/sys/class/net");
1835 if (d == 0)
1836 return WIFI_ERROR_UNKNOWN;
1837
1838 info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
1839 if (info->interfaces == NULL) {
1840 ALOGE("%s: Error info->interfaces NULL", __func__);
1841 return WIFI_ERROR_OUT_OF_MEMORY;
1842 }
1843
1844 int i = 0;
1845 while ((de = readdir(d))) {
1846 if (de->d_name[0] == '.')
1847 continue;
1848 if (is_wifi_interface(de->d_name)) {
1849 interface_info *ifinfo
1850 = (interface_info *)malloc(sizeof(interface_info));
1851 if (ifinfo == NULL) {
1852 ALOGE("%s: Error ifinfo NULL", __func__);
1853 while (i > 0) {
1854 free(info->interfaces[i-1]);
1855 i--;
1856 }
1857 free(info->interfaces);
1858 return WIFI_ERROR_OUT_OF_MEMORY;
1859 }
1860 if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
1861 free(ifinfo);
1862 continue;
1863 }
1864 ifinfo->handle = handle;
1865 info->interfaces[i] = ifinfo;
1866 i++;
1867 }
1868 }
1869
1870 closedir(d);
1871
1872 info->num_interfaces = n;
1873
1874 return WIFI_SUCCESS;
1875 }
1876
wifi_get_ifaces(wifi_handle handle,int * num,wifi_interface_handle ** interfaces)1877 wifi_error wifi_get_ifaces(wifi_handle handle, int *num,
1878 wifi_interface_handle **interfaces)
1879 {
1880 hal_info *info = (hal_info *)handle;
1881
1882 /* In case of dynamic interface add/remove, interface handles need to be
1883 * updated so that, interface specific APIs could be instantiated.
1884 * Reload here to get interfaces which are dynamically added. */
1885
1886 if (info->num_interfaces > 0) {
1887 for (int i = 0; i < info->num_interfaces; i++)
1888 free(info->interfaces[i]);
1889 free(info->interfaces);
1890 info->interfaces = NULL;
1891 info->num_interfaces = 0;
1892 }
1893
1894 wifi_error ret = wifi_init_interfaces(handle);
1895 if (ret != WIFI_SUCCESS) {
1896 ALOGE("Failed to init interfaces while wifi_get_ifaces");
1897 return ret;
1898 }
1899
1900 *interfaces = (wifi_interface_handle *)info->interfaces;
1901 *num = info->num_interfaces;
1902
1903 return WIFI_SUCCESS;
1904 }
1905
wifi_get_iface_name(wifi_interface_handle handle,char * name,size_t size)1906 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name,
1907 size_t size)
1908 {
1909 interface_info *info = (interface_info *)handle;
1910 strlcpy(name, info->name, size);
1911 return WIFI_SUCCESS;
1912 }
1913
1914 /* Get the supported Feature set */
wifi_get_supported_feature_set(wifi_interface_handle iface,feature_set * set)1915 wifi_error wifi_get_supported_feature_set(wifi_interface_handle iface,
1916 feature_set *set)
1917 {
1918 int ret = 0;
1919 wifi_handle handle = getWifiHandle(iface);
1920 *set = 0;
1921 hal_info *info = getHalInfo(handle);
1922
1923 ret = acquire_supported_features(iface, set);
1924 if (ret != WIFI_SUCCESS) {
1925 *set = info->supported_feature_set;
1926 ALOGV("Supported feature set acquired at initialization : 0x%" PRIx64, *set);
1927 } else {
1928 info->supported_feature_set = *set;
1929 ALOGV("Supported feature set acquired : 0x%" PRIx64, *set);
1930 }
1931 return WIFI_SUCCESS;
1932 }
1933
wifi_get_concurrency_matrix(wifi_interface_handle handle,int set_size_max,feature_set set[],int * set_size)1934 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle,
1935 int set_size_max,
1936 feature_set set[], int *set_size)
1937 {
1938 wifi_error ret;
1939 struct nlattr *nlData;
1940 WifihalGeneric *vCommand = NULL;
1941 interface_info *ifaceInfo = getIfaceInfo(handle);
1942 wifi_handle wifiHandle = getWifiHandle(handle);
1943
1944 if (set == NULL) {
1945 ALOGE("%s: NULL set pointer provided. Exit.",
1946 __func__);
1947 return WIFI_ERROR_INVALID_ARGS;
1948 }
1949
1950 vCommand = new WifihalGeneric(wifiHandle, 0,
1951 OUI_QCA,
1952 QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX);
1953 if (vCommand == NULL) {
1954 ALOGE("%s: Error vCommand NULL", __func__);
1955 return WIFI_ERROR_OUT_OF_MEMORY;
1956 }
1957
1958 /* Create the message */
1959 ret = vCommand->create();
1960 if (ret != WIFI_SUCCESS)
1961 goto cleanup;
1962
1963 ret = vCommand->set_iface_id(ifaceInfo->name);
1964 if (ret != WIFI_SUCCESS)
1965 goto cleanup;
1966
1967 /* Add the vendor specific attributes for the NL command. */
1968 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1969 if (!nlData)
1970 goto cleanup;
1971
1972 ret = vCommand->put_u32(
1973 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX,
1974 set_size_max);
1975 if (ret != WIFI_SUCCESS)
1976 goto cleanup;
1977
1978 vCommand->attr_end(nlData);
1979
1980 /* Populate the input received from caller/framework. */
1981 vCommand->setMaxSetSize(set_size_max);
1982 vCommand->setSizePtr(set_size);
1983 vCommand->setConcurrencySet(set);
1984
1985 ret = vCommand->requestResponse();
1986 if (ret != WIFI_SUCCESS)
1987 ALOGE("%s: requestResponse() error: %d", __func__, ret);
1988
1989 cleanup:
1990 delete vCommand;
1991 if (ret)
1992 *set_size = 0;
1993 return ret;
1994 }
1995
1996
wifi_set_nodfs_flag(wifi_interface_handle handle,u32 nodfs)1997 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
1998 {
1999 wifi_error ret;
2000 struct nlattr *nlData;
2001 WifiVendorCommand *vCommand = NULL;
2002 interface_info *ifaceInfo = getIfaceInfo(handle);
2003 wifi_handle wifiHandle = getWifiHandle(handle);
2004
2005 vCommand = new WifiVendorCommand(wifiHandle, 0,
2006 OUI_QCA,
2007 QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG);
2008 if (vCommand == NULL) {
2009 ALOGE("%s: Error vCommand NULL", __func__);
2010 return WIFI_ERROR_OUT_OF_MEMORY;
2011 }
2012
2013 /* Create the message */
2014 ret = vCommand->create();
2015 if (ret != WIFI_SUCCESS)
2016 goto cleanup;
2017
2018 ret = vCommand->set_iface_id(ifaceInfo->name);
2019 if (ret != WIFI_SUCCESS)
2020 goto cleanup;
2021
2022 /* Add the vendor specific attributes for the NL command. */
2023 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2024 if (!nlData)
2025 goto cleanup;
2026
2027 /* Add the fixed part of the mac_oui to the nl command */
2028 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG, nodfs);
2029 if (ret != WIFI_SUCCESS)
2030 goto cleanup;
2031
2032 vCommand->attr_end(nlData);
2033
2034 ret = vCommand->requestResponse();
2035 /* Don't check response since we aren't expecting one */
2036
2037 cleanup:
2038 delete vCommand;
2039 return ret;
2040 }
2041
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)2042 wifi_error wifi_start_sending_offloaded_packet(wifi_request_id id,
2043 wifi_interface_handle iface,
2044 u16 ether_type,
2045 u8 *ip_packet,
2046 u16 ip_packet_len,
2047 u8 *src_mac_addr,
2048 u8 *dst_mac_addr,
2049 u32 period_msec)
2050 {
2051 wifi_error ret;
2052 struct nlattr *nlData;
2053 WifiVendorCommand *vCommand = NULL;
2054
2055 ret = initialize_vendor_cmd(iface, id,
2056 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
2057 &vCommand);
2058 if (ret != WIFI_SUCCESS) {
2059 ALOGE("%s: Initialization failed", __func__);
2060 return ret;
2061 }
2062
2063 ALOGV("ether type 0x%04x\n", ether_type);
2064 ALOGV("ip packet length : %u\nIP Packet:", ip_packet_len);
2065 hexdump(ip_packet, ip_packet_len);
2066 ALOGV("Src Mac Address: " MAC_ADDR_STR "\nDst Mac Address: " MAC_ADDR_STR
2067 "\nPeriod in msec : %u", MAC_ADDR_ARRAY(src_mac_addr),
2068 MAC_ADDR_ARRAY(dst_mac_addr), period_msec);
2069
2070 /* Add the vendor specific attributes for the NL command. */
2071 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2072 if (!nlData)
2073 goto cleanup;
2074
2075 ret = vCommand->put_u32(
2076 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
2077 QCA_WLAN_OFFLOADED_PACKETS_SENDING_START);
2078 if (ret != WIFI_SUCCESS)
2079 goto cleanup;
2080
2081 ret = vCommand->put_u32(
2082 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
2083 id);
2084 if (ret != WIFI_SUCCESS)
2085 goto cleanup;
2086
2087 ret = vCommand->put_u16(
2088 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_ETHER_PROTO_TYPE,
2089 ether_type);
2090 if (ret != WIFI_SUCCESS)
2091 goto cleanup;
2092
2093 ret = vCommand->put_bytes(
2094 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA,
2095 (const char *)ip_packet, ip_packet_len);
2096 if (ret != WIFI_SUCCESS)
2097 goto cleanup;
2098
2099 ret = vCommand->put_addr(
2100 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR,
2101 src_mac_addr);
2102 if (ret != WIFI_SUCCESS)
2103 goto cleanup;
2104
2105 ret = vCommand->put_addr(
2106 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR,
2107 dst_mac_addr);
2108 if (ret != WIFI_SUCCESS)
2109 goto cleanup;
2110
2111 ret = vCommand->put_u32(
2112 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD,
2113 period_msec);
2114 if (ret != WIFI_SUCCESS)
2115 goto cleanup;
2116
2117 vCommand->attr_end(nlData);
2118
2119 ret = vCommand->requestResponse();
2120 if (ret != WIFI_SUCCESS)
2121 goto cleanup;
2122
2123 cleanup:
2124 delete vCommand;
2125 return ret;
2126 }
2127
wifi_stop_sending_offloaded_packet(wifi_request_id id,wifi_interface_handle iface)2128 wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id id,
2129 wifi_interface_handle iface)
2130 {
2131 wifi_error ret;
2132 struct nlattr *nlData;
2133 WifiVendorCommand *vCommand = NULL;
2134
2135 ret = initialize_vendor_cmd(iface, id,
2136 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
2137 &vCommand);
2138 if (ret != WIFI_SUCCESS) {
2139 ALOGE("%s: Initialization failed", __func__);
2140 return ret;
2141 }
2142
2143 /* Add the vendor specific attributes for the NL command. */
2144 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2145 if (!nlData)
2146 goto cleanup;
2147
2148 ret = vCommand->put_u32(
2149 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
2150 QCA_WLAN_OFFLOADED_PACKETS_SENDING_STOP);
2151 if (ret != WIFI_SUCCESS)
2152 goto cleanup;
2153
2154 ret = vCommand->put_u32(
2155 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
2156 id);
2157 if (ret != WIFI_SUCCESS)
2158 goto cleanup;
2159
2160 vCommand->attr_end(nlData);
2161
2162 ret = vCommand->requestResponse();
2163 if (ret != WIFI_SUCCESS)
2164 goto cleanup;
2165
2166 cleanup:
2167 delete vCommand;
2168 return ret;
2169 }
2170
2171 #define PACKET_FILTER_ID 0
2172
wifi_set_packet_filter(wifi_interface_handle iface,const u8 * program,u32 len)2173 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
2174 const u8 *program, u32 len)
2175 {
2176 wifi_error ret;
2177 struct nlattr *nlData;
2178 WifiVendorCommand *vCommand = NULL;
2179 u32 current_offset = 0;
2180 wifi_handle wifiHandle = getWifiHandle(iface);
2181 hal_info *info = getHalInfo(wifiHandle);
2182
2183 /* len=0 clears the filters in driver/firmware */
2184 if (len != 0 && program == NULL) {
2185 ALOGE("%s: No valid program provided. Exit.",
2186 __func__);
2187 return WIFI_ERROR_INVALID_ARGS;
2188 }
2189
2190 do {
2191 ret = initialize_vendor_cmd(iface, get_requestid(),
2192 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
2193 &vCommand);
2194 if (ret != WIFI_SUCCESS) {
2195 ALOGE("%s: Initialization failed", __FUNCTION__);
2196 return ret;
2197 }
2198
2199 /* Add the vendor specific attributes for the NL command. */
2200 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2201 if (!nlData)
2202 goto cleanup;
2203
2204 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2205 QCA_WLAN_SET_PACKET_FILTER);
2206 if (ret != WIFI_SUCCESS)
2207 goto cleanup;
2208 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
2209 PACKET_FILTER_ID);
2210 if (ret != WIFI_SUCCESS)
2211 goto cleanup;
2212 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE,
2213 len);
2214 if (ret != WIFI_SUCCESS)
2215 goto cleanup;
2216 ret = vCommand->put_u32(
2217 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
2218 current_offset);
2219 if (ret != WIFI_SUCCESS)
2220 goto cleanup;
2221
2222 if (len) {
2223 ret = vCommand->put_bytes(
2224 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
2225 (char *)&program[current_offset],
2226 min(info->firmware_bus_max_size,
2227 len-current_offset));
2228 if (ret!= WIFI_SUCCESS) {
2229 ALOGE("%s: failed to put program", __FUNCTION__);
2230 goto cleanup;
2231 }
2232 }
2233
2234 vCommand->attr_end(nlData);
2235
2236 ret = vCommand->requestResponse();
2237 if (ret != WIFI_SUCCESS) {
2238 ALOGE("%s: requestResponse Error:%d",__func__, ret);
2239 goto cleanup;
2240 }
2241
2242 /* destroy the object after sending each fragment to driver */
2243 delete vCommand;
2244 vCommand = NULL;
2245
2246 current_offset += min(info->firmware_bus_max_size, len);
2247 } while (current_offset < len);
2248
2249 info->apf_enabled = !!len;
2250
2251 cleanup:
2252 if (vCommand)
2253 delete vCommand;
2254 return ret;
2255 }
2256
wifi_get_packet_filter_capabilities(wifi_interface_handle handle,u32 * version,u32 * max_len)2257 static wifi_error wifi_get_packet_filter_capabilities(
2258 wifi_interface_handle handle, u32 *version, u32 *max_len)
2259 {
2260 wifi_error ret;
2261 struct nlattr *nlData;
2262 WifihalGeneric *vCommand = NULL;
2263 interface_info *ifaceInfo = getIfaceInfo(handle);
2264 wifi_handle wifiHandle = getWifiHandle(handle);
2265
2266 if (version == NULL || max_len == NULL) {
2267 ALOGE("%s: NULL version/max_len pointer provided. Exit.",
2268 __FUNCTION__);
2269 return WIFI_ERROR_INVALID_ARGS;
2270 }
2271
2272 vCommand = new WifihalGeneric(wifiHandle, 0,
2273 OUI_QCA,
2274 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
2275 if (vCommand == NULL) {
2276 ALOGE("%s: Error vCommand NULL", __FUNCTION__);
2277 return WIFI_ERROR_OUT_OF_MEMORY;
2278 }
2279
2280 /* Create the message */
2281 ret = vCommand->create();
2282 if (ret != WIFI_SUCCESS)
2283 goto cleanup;
2284
2285 ret = vCommand->set_iface_id(ifaceInfo->name);
2286 if (ret != WIFI_SUCCESS)
2287 goto cleanup;
2288
2289 /* Add the vendor specific attributes for the NL command. */
2290 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2291 if (!nlData)
2292 goto cleanup;
2293
2294 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2295 QCA_WLAN_GET_PACKET_FILTER);
2296 if (ret != WIFI_SUCCESS)
2297 goto cleanup;
2298
2299 vCommand->attr_end(nlData);
2300
2301 ret = vCommand->requestResponse();
2302 if (ret != WIFI_SUCCESS) {
2303 ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
2304 if (ret == WIFI_ERROR_NOT_SUPPORTED) {
2305 /* Packet filtering is not supported currently, so return version
2306 * and length as 0
2307 */
2308 ALOGI("Packet filtering is not supprted");
2309 *version = 0;
2310 *max_len = 0;
2311 ret = WIFI_SUCCESS;
2312 }
2313 goto cleanup;
2314 }
2315
2316 *version = vCommand->getFilterVersion();
2317 *max_len = vCommand->getFilterLength();
2318 cleanup:
2319 delete vCommand;
2320 return ret;
2321 }
2322
2323
wifi_configure_nd_offload(wifi_interface_handle iface,u8 enable)2324 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
2325 u8 enable)
2326 {
2327 wifi_error ret;
2328 struct nlattr *nlData;
2329 WifiVendorCommand *vCommand = NULL;
2330
2331 ret = initialize_vendor_cmd(iface, get_requestid(),
2332 QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
2333 &vCommand);
2334 if (ret != WIFI_SUCCESS) {
2335 ALOGE("%s: Initialization failed", __func__);
2336 return ret;
2337 }
2338
2339 ALOGV("ND offload : %s", enable?"Enable":"Disable");
2340
2341 /* Add the vendor specific attributes for the NL command. */
2342 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2343 if (!nlData)
2344 goto cleanup;
2345
2346 ret = vCommand->put_u8(QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG, enable);
2347 if (ret != WIFI_SUCCESS)
2348 goto cleanup;
2349
2350 vCommand->attr_end(nlData);
2351
2352 ret = vCommand->requestResponse();
2353
2354 cleanup:
2355 delete vCommand;
2356 return ret;
2357 }
2358
2359 /**
2360 * Copy 'len' bytes of raw data from host memory at source address 'program'
2361 * to APF (Android Packet Filter) working memory starting at offset 'dst_offset'.
2362 * The size of the program lenght passed to the interpreter is set to
2363 * 'progaram_lenght'
2364 *
2365 * The implementation is allowed to tranlate this wrtie into a series of smaller
2366 * writes,but this function is not allowed to return untill all write operations
2367 * have been completed
2368 * additionally visible memory not targeted by this function must remain
2369 * unchanged
2370
2371 * @param dst_offset write offset in bytes relative to the beginning of the APF
2372 * working memory with logical address 0X000. Must be a multiple of 4
2373 *
2374 * @param program host memory to copy bytes from. Must be 4B aligned
2375 *
2376 * @param len the number of bytes to copy from the bost into the APF working
2377 * memory
2378 *
2379 * @param program_length new length of the program instructions in bytes to pass
2380 * to the interpreter
2381 */
2382
wifi_write_packet_filter(wifi_interface_handle iface,u32 dst_offset,const u8 * program,u32 len,u32 program_length)2383 wifi_error wifi_write_packet_filter(wifi_interface_handle iface,
2384 u32 dst_offset, const u8 *program,
2385 u32 len, u32 program_length)
2386 {
2387 wifi_error ret;
2388 struct nlattr *nlData;
2389 WifiVendorCommand *vCommand = NULL;
2390 u32 current_offset = 0;
2391 wifi_handle wifiHandle = getWifiHandle(iface);
2392 hal_info *info = getHalInfo(wifiHandle);
2393
2394 /* len=0 clears the filters in driver/firmware */
2395 if (len != 0 && program == NULL) {
2396 ALOGE("%s: No valid program provided. Exit.",
2397 __func__);
2398 return WIFI_ERROR_INVALID_ARGS;
2399 }
2400
2401 do {
2402 ret = initialize_vendor_cmd(iface, get_requestid(),
2403 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
2404 &vCommand);
2405 if (ret != WIFI_SUCCESS) {
2406 ALOGE("%s: Initialization failed", __FUNCTION__);
2407 return ret;
2408 }
2409
2410 /* Add the vendor specific attributes for the NL command. */
2411 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2412 if (!nlData)
2413 goto cleanup;
2414
2415 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2416 QCA_WLAN_WRITE_PACKET_FILTER);
2417 if (ret != WIFI_SUCCESS)
2418 goto cleanup;
2419 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
2420 PACKET_FILTER_ID);
2421 if (ret != WIFI_SUCCESS)
2422 goto cleanup;
2423 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE,
2424 len);
2425 if (ret != WIFI_SUCCESS)
2426 goto cleanup;
2427 ret = vCommand->put_u32(
2428 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
2429 dst_offset + current_offset);
2430 if (ret != WIFI_SUCCESS)
2431 goto cleanup;
2432 ret = vCommand->put_u32(
2433 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROG_LENGTH,
2434 program_length);
2435 if (ret != WIFI_SUCCESS)
2436 goto cleanup;
2437
2438 ret = vCommand->put_bytes(
2439 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
2440 (char *)&program[current_offset],
2441 min(info->firmware_bus_max_size,
2442 len - current_offset));
2443 if (ret!= WIFI_SUCCESS) {
2444 ALOGE("%s: failed to put program", __FUNCTION__);
2445 goto cleanup;
2446 }
2447
2448 vCommand->attr_end(nlData);
2449
2450 ret = vCommand->requestResponse();
2451 if (ret != WIFI_SUCCESS) {
2452 ALOGE("%s: requestResponse Error:%d",__func__, ret);
2453 goto cleanup;
2454 }
2455
2456 /* destroy the object after sending each fragment to driver */
2457 delete vCommand;
2458 vCommand = NULL;
2459
2460 current_offset += min(info->firmware_bus_max_size,
2461 len - current_offset);
2462 } while (current_offset < len);
2463
2464 cleanup:
2465 if (vCommand)
2466 delete vCommand;
2467 return ret;
2468 }
2469
wifi_enable_packet_filter(wifi_interface_handle handle,u32 enable)2470 wifi_error wifi_enable_packet_filter(wifi_interface_handle handle,
2471 u32 enable)
2472 {
2473 wifi_error ret;
2474 struct nlattr *nlData;
2475 WifiVendorCommand *vCommand = NULL;
2476 u32 subcmd;
2477 wifi_handle wifiHandle = getWifiHandle(handle);
2478 hal_info *info = getHalInfo(wifiHandle);
2479
2480 ret = initialize_vendor_cmd(handle, get_requestid(),
2481 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
2482 &vCommand);
2483
2484 if (ret != WIFI_SUCCESS) {
2485 ALOGE("%s: Initialization failed", __func__);
2486 return ret;
2487 }
2488 /* Add the vendor specific attributes for the NL command. */
2489 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2490 if (!nlData)
2491 goto cleanup;
2492
2493 subcmd = enable ? QCA_WLAN_ENABLE_PACKET_FILTER :
2494 QCA_WLAN_DISABLE_PACKET_FILTER;
2495 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2496 subcmd);
2497 if (ret != WIFI_SUCCESS)
2498 goto cleanup;
2499
2500 vCommand->attr_end(nlData);
2501 ret = vCommand->requestResponse();
2502
2503 if (ret != WIFI_SUCCESS) {
2504 ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
2505 goto cleanup;
2506 }
2507
2508 info->apf_enabled = !!enable;
2509
2510 cleanup:
2511 if (vCommand)
2512 delete vCommand;
2513 return ret;
2514
2515 }
2516
2517 /**
2518 * Copy 'length' bytes of raw data from APF (Android Packet Filter) working
2519 * memory to host memory starting at offset src_offset into host memory
2520 * pointed to by host_dst.
2521 * Memory can be text, data or some combination of the two. The implementiion is
2522 * allowed to translate this read into a series of smaller reads, but this
2523 * function is not allowed to return untill all the reads operations
2524 * into host_dst have been completed.
2525 *
2526 * @param src_offset offset in bytes of destination memory within APF working
2527 * memory
2528 *
2529 * @param host_dst host memory to copy into. Must be 4B aligned.
2530 *
2531 * @param length the number of bytes to copy from the APF working memory to the
2532 * host.
2533 */
2534
wifi_read_packet_filter(wifi_interface_handle handle,u32 src_offset,u8 * host_dst,u32 length)2535 static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
2536 u32 src_offset, u8 *host_dst, u32 length)
2537 {
2538 wifi_error ret = WIFI_SUCCESS;
2539 struct nlattr *nlData;
2540 WifihalGeneric *vCommand = NULL;
2541 interface_info *ifaceInfo = getIfaceInfo(handle);
2542 wifi_handle wifiHandle = getWifiHandle(handle);
2543 hal_info *info = getHalInfo(wifiHandle);
2544
2545 /* Length to be passed to this function should be non-zero
2546 * Return invalid argument if length is passed as zero
2547 */
2548 if (length == 0)
2549 return WIFI_ERROR_INVALID_ARGS;
2550
2551 /*Temporary varibles to support the read complete length in chunks */
2552 u8 *temp_host_dst;
2553 u32 remainingLengthToBeRead, currentLength;
2554 u8 apf_locally_disabled = 0;
2555
2556 /*Initializing the temporary variables*/
2557 temp_host_dst = host_dst;
2558 remainingLengthToBeRead = length;
2559
2560 if (info->apf_enabled) {
2561 /* Disable APF only when not disabled by framework before calling
2562 * wifi_read_packet_filter()
2563 */
2564 ret = wifi_enable_packet_filter(handle, 0);
2565 if (ret != WIFI_SUCCESS) {
2566 ALOGE("%s: Failed to disable APF", __FUNCTION__);
2567 return ret;
2568 }
2569 apf_locally_disabled = 1;
2570 }
2571 /**
2572 * Read the complete length in chunks of size less or equal to firmware bus
2573 * max size
2574 */
2575 while (remainingLengthToBeRead)
2576 {
2577 vCommand = new WifihalGeneric(wifiHandle, 0, OUI_QCA,
2578 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
2579
2580 if (vCommand == NULL) {
2581 ALOGE("%s: Error vCommand NULL", __FUNCTION__);
2582 ret = WIFI_ERROR_OUT_OF_MEMORY;
2583 break;
2584 }
2585
2586 /* Create the message */
2587 ret = vCommand->create();
2588 if (ret != WIFI_SUCCESS)
2589 break;
2590 ret = vCommand->set_iface_id(ifaceInfo->name);
2591 if (ret != WIFI_SUCCESS)
2592 break;
2593 /* Add the vendor specific attributes for the NL command. */
2594 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2595 if (!nlData)
2596 break;
2597 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2598 QCA_WLAN_READ_PACKET_FILTER);
2599 if (ret != WIFI_SUCCESS)
2600 break;
2601
2602 currentLength = min(remainingLengthToBeRead, info->firmware_bus_max_size);
2603
2604 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE,
2605 currentLength);
2606 if (ret != WIFI_SUCCESS)
2607 break;
2608 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
2609 src_offset);
2610 if (ret != WIFI_SUCCESS)
2611 break;
2612
2613 vCommand->setPacketBufferParams(temp_host_dst, currentLength);
2614 vCommand->attr_end(nlData);
2615 ret = vCommand->requestResponse();
2616
2617 if (ret != WIFI_SUCCESS) {
2618 ALOGE("%s: requestResponse() error: %d current_len = %u, src_offset = %u",
2619 __FUNCTION__, ret, currentLength, src_offset);
2620 break;
2621 }
2622
2623 remainingLengthToBeRead -= currentLength;
2624 temp_host_dst += currentLength;
2625 src_offset += currentLength;
2626 delete vCommand;
2627 vCommand = NULL;
2628 }
2629
2630 /* Re enable APF only when disabled above within this API */
2631 if (apf_locally_disabled) {
2632 wifi_error status;
2633 status = wifi_enable_packet_filter(handle, 1);
2634 if (status != WIFI_SUCCESS)
2635 ALOGE("%s: Failed to enable APF", __FUNCTION__);
2636 /* Prefer to return read status if read fails */
2637 if (ret == WIFI_SUCCESS)
2638 ret = status;
2639 }
2640
2641 delete vCommand;
2642 return ret;
2643 }
2644