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 * Changes from Qualcomm Innovation Center are provided under the following license:
17 *
18 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted (subject to the limitations in the
22 * disclaimer below) provided that the following conditions are met:
23 *
24 * * Redistributions of source code must retain the above copyright
25 * notice, this list of conditions and the following disclaimer.
26 *
27 * * Redistributions in binary form must reproduce the above
28 * copyright notice, this list of conditions and the following
29 * disclaimer in the documentation and/or other materials provided
30 * with the distribution.
31 *
32 * * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
33 * contributors may be used to endorse or promote products derived
34 * from this software without specific prior written permission.
35 *
36 * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
37 * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
38 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
39 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
40 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
41 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
42 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
44 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
45 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
46 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
47 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
48 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49 */
50
51 #include <stdint.h>
52 #include <errno.h>
53 #include <fcntl.h>
54 #include <sys/socket.h>
55 #include <netlink/genl/genl.h>
56 #include <netlink/genl/family.h>
57 #include <netlink/genl/ctrl.h>
58 #include <linux/rtnetlink.h>
59 #include <netpacket/packet.h>
60 #include <linux/filter.h>
61 #include <linux/errqueue.h>
62
63 #include <linux/pkt_sched.h>
64 #include <netlink/object-api.h>
65 #include <netlink/netlink.h>
66 #include <netlink/socket.h>
67 #include <netlink-private/object-api.h>
68 #include <netlink-private/types.h>
69
70 #include "nl80211_copy.h"
71
72 #include <dirent.h>
73 #include <net/if.h>
74 #include <netinet/in.h>
75 #include <cld80211_lib.h>
76
77 #include <sys/types.h>
78 #include "list.h"
79 #include <unistd.h>
80
81 #include "sync.h"
82
83 #define LOG_TAG "WifiHAL"
84
85 #include "wifi_hal.h"
86 #include "wifi_hal_ctrl.h"
87 #include "common.h"
88 #include "cpp_bindings.h"
89 #include "ifaceeventhandler.h"
90 #include "wifiloggercmd.h"
91
92 /*
93 BUGBUG: normally, libnl allocates ports for all connections it makes; but
94 being a static library, it doesn't really know how many other netlink
95 connections are made by the same process, if connections come from different
96 shared libraries. These port assignments exist to solve that
97 problem - temporarily. We need to fix libnl to try and allocate ports across
98 the entire process.
99 */
100
101 #define WIFI_HAL_CMD_SOCK_PORT 644
102 #define WIFI_HAL_EVENT_SOCK_PORT 645
103
104 #define MAX_HW_VER_LENGTH 100
105 /*
106 * Defines for wifi_wait_for_driver_ready()
107 * Specify durations between polls and max wait time
108 */
109 #define POLL_DRIVER_DURATION_US (100000)
110 #define POLL_DRIVER_MAX_TIME_MS (10000)
111
112 static int attach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg);
113
114 static int dettach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg);
115
116 static int register_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg, int attach);
117
118 static int send_nl_data(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg);
119
120 static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock);
121
122 static void internal_event_handler_app(wifi_handle handle, int events,
123 struct ctrl_sock *sock);
124
125 static void internal_event_handler(wifi_handle handle, int events,
126 struct nl_sock *sock);
127 static int internal_valid_message_handler(nl_msg *msg, void *arg);
128 static int user_sock_message_handler(nl_msg *msg, void *arg);
129 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
130 const char *group);
131 static int wifi_add_membership(wifi_handle handle, const char *group);
132 static wifi_error wifi_init_interfaces(wifi_handle handle);
133 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
134 const u8 *program, u32 len);
135 static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
136 u32 *version, u32 *max_len);
137 static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
138 u32 src_offset, u8 *host_dst, u32 length);
139 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
140 u8 enable);
141 wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,
142 WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt);
143 static int wifi_is_nan_ext_cmd_supported(wifi_interface_handle handle);
144
145 /* Initialize/Cleanup */
146
wifi_get_iface_handle(wifi_handle handle,char * name)147 wifi_interface_handle wifi_get_iface_handle(wifi_handle handle, char *name)
148 {
149 hal_info *info = (hal_info *)handle;
150 for (int i=0;i<info->num_interfaces;i++)
151 {
152 if (!strcmp(info->interfaces[i]->name, name))
153 {
154 return ((wifi_interface_handle )(info->interfaces)[i]);
155 }
156 }
157 return NULL;
158 }
159
wifi_socket_set_local_port(struct nl_sock * sock,uint32_t port)160 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
161 {
162 /* Release local port pool maintained by libnl and assign a own port
163 * identifier to the socket.
164 */
165 nl_socket_set_local_port(sock, ((uint32_t)getpid() & 0x3FFFFFU) | (port << 22));
166 }
167
wifi_create_nl_socket(int port,int protocol)168 static nl_sock * wifi_create_nl_socket(int port, int protocol)
169 {
170 // ALOGI("Creating socket");
171 struct nl_sock *sock = nl_socket_alloc();
172 if (sock == NULL) {
173 ALOGE("Failed to create NL socket");
174 return NULL;
175 }
176
177 wifi_socket_set_local_port(sock, port);
178
179 if (nl_connect(sock, protocol)) {
180 ALOGE("Could not connect handle");
181 nl_socket_free(sock);
182 return NULL;
183 }
184
185 return sock;
186 }
187
wifi_create_ctrl_socket(hal_info * info)188 void wifi_create_ctrl_socket(hal_info *info)
189 {
190 #ifdef ANDROID
191 struct group *grp_wifi;
192 gid_t gid_wifi;
193 struct passwd *pwd_system;
194 uid_t uid_system;
195 #endif
196
197 int flags;
198
199 info->wifihal_ctrl_sock.s = socket(PF_UNIX, SOCK_DGRAM, 0);
200
201 if (info->wifihal_ctrl_sock.s < 0) {
202 ALOGE("socket(PF_UNIX): %s", strerror(errno));
203 return;
204 }
205 memset(&info->wifihal_ctrl_sock.local, 0, sizeof(info->wifihal_ctrl_sock.local));
206
207 info->wifihal_ctrl_sock.local.sun_family = AF_UNIX;
208
209 snprintf(info->wifihal_ctrl_sock.local.sun_path,
210 sizeof(info->wifihal_ctrl_sock.local.sun_path), "%s", WIFI_HAL_CTRL_IFACE);
211
212 if (bind(info->wifihal_ctrl_sock.s, (struct sockaddr *) &info->wifihal_ctrl_sock.local,
213 sizeof(info->wifihal_ctrl_sock.local)) < 0) {
214 ALOGD("ctrl_iface bind(PF_UNIX) failed: %s",
215 strerror(errno));
216 if (connect(info->wifihal_ctrl_sock.s, (struct sockaddr *) &info->wifihal_ctrl_sock.local,
217 sizeof(info->wifihal_ctrl_sock.local)) < 0) {
218 ALOGD("ctrl_iface exists, but does not"
219 " allow connections - assuming it was left"
220 "over from forced program termination");
221 if (unlink(info->wifihal_ctrl_sock.local.sun_path) < 0) {
222 ALOGE("Could not unlink existing ctrl_iface socket '%s': %s",
223 info->wifihal_ctrl_sock.local.sun_path, strerror(errno));
224 goto out;
225
226 }
227 if (bind(info->wifihal_ctrl_sock.s ,
228 (struct sockaddr *) &info->wifihal_ctrl_sock.local,
229 sizeof(info->wifihal_ctrl_sock.local)) < 0) {
230 ALOGE("wifihal-ctrl-iface-init: bind(PF_UNIX): %s",
231 strerror(errno));
232 goto out;
233 }
234 ALOGD("Successfully replaced leftover "
235 "ctrl_iface socket '%s'", info->wifihal_ctrl_sock.local.sun_path);
236 } else {
237 ALOGI("ctrl_iface exists and seems to "
238 "be in use - cannot override it");
239 ALOGI("Delete '%s' manually if it is "
240 "not used anymore", info->wifihal_ctrl_sock.local.sun_path);
241 goto out;
242 }
243 }
244
245 /*
246 * Make socket non-blocking so that we don't hang forever if
247 * target dies unexpectedly.
248 */
249
250 #ifdef ANDROID
251 if (chmod(info->wifihal_ctrl_sock.local.sun_path, S_IRWXU | S_IRWXG) < 0)
252 {
253 ALOGE("Failed to give permissions: %s", strerror(errno));
254 }
255
256 /* Set group even if we do not have privileges to change owner */
257 grp_wifi = getgrnam("wifi");
258 gid_wifi = grp_wifi ? grp_wifi->gr_gid : 0;
259 pwd_system = getpwnam("system");
260 uid_system = pwd_system ? pwd_system->pw_uid : 0;
261 if (!gid_wifi || !uid_system) {
262 ALOGE("Failed to get grp ids");
263 unlink(info->wifihal_ctrl_sock.local.sun_path);
264 goto out;
265 }
266 chown(info->wifihal_ctrl_sock.local.sun_path, -1, gid_wifi);
267 chown(info->wifihal_ctrl_sock.local.sun_path, uid_system, gid_wifi);
268 #endif
269
270 flags = fcntl(info->wifihal_ctrl_sock.s, F_GETFL);
271 if (flags >= 0) {
272 flags |= O_NONBLOCK;
273 if (fcntl(info->wifihal_ctrl_sock.s, F_SETFL, flags) < 0) {
274 ALOGI("fcntl(ctrl, O_NONBLOCK): %s",
275 strerror(errno));
276 /* Not fatal, continue on.*/
277 }
278 }
279 return;
280
281 out:
282 close(info->wifihal_ctrl_sock.s);
283 info->wifihal_ctrl_sock.s = 0;
284 return;
285 }
286
ack_handler(struct nl_msg * msg,void * arg)287 int ack_handler(struct nl_msg *msg, void *arg)
288 {
289 int *err = (int *)arg;
290 *err = 0;
291 return NL_STOP;
292 }
293
finish_handler(struct nl_msg * msg,void * arg)294 int finish_handler(struct nl_msg *msg, void *arg)
295 {
296 int *ret = (int *)arg;
297 *ret = 0;
298 return NL_SKIP;
299 }
300
error_handler(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)301 int error_handler(struct sockaddr_nl *nla,
302 struct nlmsgerr *err, void *arg)
303 {
304 int *ret = (int *)arg;
305 *ret = err->error;
306
307 ALOGV("%s invoked with error: %d", __func__, err->error);
308 return NL_SKIP;
309 }
no_seq_check(struct nl_msg * msg,void * arg)310 static int no_seq_check(struct nl_msg *msg, void *arg)
311 {
312 return NL_OK;
313 }
314
acquire_supported_features(wifi_interface_handle iface,feature_set * set)315 static wifi_error acquire_supported_features(wifi_interface_handle iface,
316 feature_set *set)
317 {
318 wifi_error ret;
319 interface_info *iinfo = getIfaceInfo(iface);
320 wifi_handle handle = getWifiHandle(iface);
321 *set = 0;
322
323 WifihalGeneric supportedFeatures(handle, 0,
324 OUI_QCA,
325 QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES);
326
327 /* create the message */
328 ret = supportedFeatures.create();
329 if (ret != WIFI_SUCCESS)
330 goto cleanup;
331
332 ret = supportedFeatures.set_iface_id(iinfo->name);
333 if (ret != WIFI_SUCCESS)
334 goto cleanup;
335
336 ret = supportedFeatures.requestResponse();
337 if (ret != WIFI_SUCCESS) {
338 ALOGE("%s: requestResponse Error:%d",__func__, ret);
339 goto cleanup;
340 }
341
342 supportedFeatures.getResponseparams(set);
343
344 cleanup:
345 return ret;
346 }
347
acquire_driver_supported_features(wifi_interface_handle iface,features_info * driver_features)348 static wifi_error acquire_driver_supported_features(wifi_interface_handle iface,
349 features_info *driver_features)
350 {
351 wifi_error ret;
352 interface_info *iinfo = getIfaceInfo(iface);
353 wifi_handle handle = getWifiHandle(iface);
354
355 WifihalGeneric driverFeatures(handle, 0,
356 OUI_QCA,
357 QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES);
358
359 /* create the message */
360 ret = driverFeatures.create();
361 if (ret != WIFI_SUCCESS)
362 goto cleanup;
363
364 ret = driverFeatures.set_iface_id(iinfo->name);
365 if (ret != WIFI_SUCCESS)
366 goto cleanup;
367
368 ret = driverFeatures.requestResponse();
369 if (ret != WIFI_SUCCESS) {
370 ALOGE("%s: requestResponse Error:%d",__func__, ret);
371 goto cleanup;
372 }
373
374 driverFeatures.getDriverFeatures(driver_features);
375
376 cleanup:
377 return mapKernelErrortoWifiHalError(ret);
378 }
379
wifi_get_capabilities(wifi_interface_handle handle)380 static wifi_error wifi_get_capabilities(wifi_interface_handle handle)
381 {
382 wifi_error ret;
383 int requestId;
384 WifihalGeneric *wifihalGeneric;
385 wifi_handle wifiHandle = getWifiHandle(handle);
386 hal_info *info = getHalInfo(wifiHandle);
387
388 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
389 ALOGE("%s: GSCAN is not supported by driver", __FUNCTION__);
390 return WIFI_ERROR_NOT_SUPPORTED;
391 }
392
393 /* No request id from caller, so generate one and pass it on to the driver.
394 * Generate it randomly.
395 */
396 requestId = get_requestid();
397
398 wifihalGeneric = new WifihalGeneric(
399 wifiHandle,
400 requestId,
401 OUI_QCA,
402 QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES);
403 if (!wifihalGeneric) {
404 ALOGE("%s: Failed to create object of WifihalGeneric class", __FUNCTION__);
405 return WIFI_ERROR_OUT_OF_MEMORY;
406 }
407
408 ret = wifihalGeneric->wifiGetCapabilities(handle);
409
410 delete wifihalGeneric;
411 return ret;
412 }
413
get_firmware_bus_max_size_supported(wifi_interface_handle iface)414 static wifi_error get_firmware_bus_max_size_supported(
415 wifi_interface_handle iface)
416 {
417 wifi_error ret;
418 interface_info *iinfo = getIfaceInfo(iface);
419 wifi_handle handle = getWifiHandle(iface);
420 hal_info *info = (hal_info *)handle;
421
422 WifihalGeneric busSizeSupported(handle, 0,
423 OUI_QCA,
424 QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE);
425
426 /* create the message */
427 ret = busSizeSupported.create();
428 if (ret != WIFI_SUCCESS)
429 goto cleanup;
430
431 ret = busSizeSupported.set_iface_id(iinfo->name);
432 if (ret != WIFI_SUCCESS)
433 goto cleanup;
434
435 ret = busSizeSupported.requestResponse();
436 if (ret != WIFI_SUCCESS) {
437 ALOGE("%s: requestResponse Error:%d", __FUNCTION__, ret);
438 goto cleanup;
439 }
440 info->firmware_bus_max_size = busSizeSupported.getBusSize();
441
442 cleanup:
443 return ret;
444 }
445
wifi_init_user_sock(hal_info * info)446 static wifi_error wifi_init_user_sock(hal_info *info)
447 {
448 struct nl_sock *user_sock =
449 wifi_create_nl_socket(WIFI_HAL_USER_SOCK_PORT, NETLINK_USERSOCK);
450 if (user_sock == NULL) {
451 ALOGE("Could not create diag sock");
452 return WIFI_ERROR_UNKNOWN;
453 }
454
455 /* Set the socket buffer size */
456 if (nl_socket_set_buffer_size(user_sock, (256*1024), 0) < 0) {
457 ALOGE("Could not set size for user_sock: %s",
458 strerror(errno));
459 /* continue anyway with the default (smaller) buffer */
460 }
461 else {
462 ALOGV("nl_socket_set_buffer_size successful for user_sock");
463 }
464
465 struct nl_cb *cb = nl_socket_get_cb(user_sock);
466 if (cb == NULL) {
467 ALOGE("Could not get cb");
468 return WIFI_ERROR_UNKNOWN;
469 }
470
471 info->user_sock_arg = 1;
472 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
473 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg);
474 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg);
475 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg);
476
477 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info);
478 nl_cb_put(cb);
479
480 int ret = nl_socket_add_membership(user_sock, 1);
481 if (ret < 0) {
482 ALOGE("Could not add membership");
483 return WIFI_ERROR_UNKNOWN;
484 }
485
486 info->user_sock = user_sock;
487 ALOGV("Initiialized diag sock successfully");
488 return WIFI_SUCCESS;
489 }
490
wifi_init_cld80211_sock_cb(hal_info * info)491 static wifi_error wifi_init_cld80211_sock_cb(hal_info *info)
492 {
493 struct nl_cb *cb = nl_socket_get_cb(info->cldctx->sock);
494 if (cb == NULL) {
495 ALOGE("Could not get cb");
496 return WIFI_ERROR_UNKNOWN;
497 }
498
499 info->user_sock_arg = 1;
500 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
501 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg);
502 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg);
503 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg);
504
505 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info);
506 nl_cb_put(cb);
507
508 return WIFI_SUCCESS;
509 }
510
get_frequency_from_channel(uint32_t channel,wlan_mac_band band)511 static uint32_t get_frequency_from_channel(uint32_t channel, wlan_mac_band band)
512 {
513 uint32_t freq = 0;
514
515 switch (band)
516 {
517 case WLAN_MAC_2_4_BAND:
518 if (!(channel >= 1 && channel <= 14))
519 goto failure;
520 //special handling for channel 14 by filling freq here
521 if (channel == 14)
522 freq = 2484;
523 else
524 freq = 2407 + (channel * 5);
525 break;
526 case WLAN_MAC_5_0_BAND:
527 if (!((channel >= 34 && channel < 65) ||
528 (channel > 99 && channel <= 196)))
529 goto failure;
530 freq = 5000 + (channel * 5);
531 break;
532 case WLAN_MAC_6_0_BAND:
533 if (!(channel >= 1 && channel <= 233))
534 goto failure;
535 freq = 5950 + (channel * 5);
536 break;
537 default:
538 break;
539 }
540
541 failure:
542 return freq;
543 }
544
get_nl_ifmask_from_coex_restriction_mask(u32 in_mask)545 static u32 get_nl_ifmask_from_coex_restriction_mask(u32 in_mask)
546 {
547 u32 op_mask = 0;
548
549 if (!in_mask)
550 return op_mask;
551 if (in_mask & SOFTAP)
552 op_mask |= BIT(NL80211_IFTYPE_AP);
553 if (in_mask & WIFI_DIRECT)
554 op_mask |= BIT(NL80211_IFTYPE_P2P_GO);
555 if (in_mask & WIFI_AWARE)
556 op_mask |= BIT(NL80211_IFTYPE_NAN);
557
558 return op_mask;
559 }
560
wifi_set_coex_unsafe_channels(wifi_handle handle,u32 num_channels,wifi_coex_unsafe_channel * unsafeChannels,u32 restrictions)561 wifi_error wifi_set_coex_unsafe_channels(wifi_handle handle, u32 num_channels,
562 wifi_coex_unsafe_channel *unsafeChannels,
563 u32 restrictions)
564 {
565 wifi_error ret = WIFI_ERROR_UNKNOWN;
566 WifihalGeneric *cmd = NULL;
567 struct nlattr *nl_data = NULL;
568 struct nlattr *nl_attr_unsafe_chan = NULL;
569 struct nlattr *unsafe_channels_attr = NULL;
570 hal_info *info = NULL;
571
572 if (!handle) {
573 ALOGE("%s: Error, wifi_handle NULL", __FUNCTION__);
574 goto cleanup;
575 }
576
577 info = getHalInfo(handle);
578 if (!info || info->num_interfaces < 1) {
579 ALOGE("%s: Error, wifi_handle NULL or base wlan interface not present",
580 __FUNCTION__);
581 goto cleanup;
582 }
583
584 cmd = new WifihalGeneric(handle, get_requestid(), OUI_QCA,
585 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_EXT);
586 if (cmd == NULL) {
587 ALOGE("%s: Error, created command NULL", __FUNCTION__);
588 ret = WIFI_ERROR_OUT_OF_MEMORY;
589 goto cleanup;
590 }
591
592 /* Create the NL message. */
593 ret = cmd->create();
594 if (ret < 0) {
595 ALOGE("%s: failed to create NL msg due to error: (%d)",
596 __FUNCTION__, ret);
597 goto cleanup;
598 }
599
600 /* Add the vendor specific attributes for the NL command. */
601 nl_data = cmd->attr_start(NL80211_ATTR_VENDOR_DATA);
602 if (!nl_data) {
603 ALOGE("%s: failed attr_start for NL80211_ATTR_VENDOR_DATA",
604 __FUNCTION__);
605 ret = WIFI_ERROR_OUT_OF_MEMORY;
606 goto cleanup;
607 }
608
609 nl_attr_unsafe_chan = cmd->attr_start(
610 QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE);
611 if (!nl_attr_unsafe_chan) {
612 ALOGE("%s: failed attr_start for"
613 " QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE", __FUNCTION__);
614 ret = WIFI_ERROR_OUT_OF_MEMORY;
615 goto cleanup;
616 }
617 ALOGD("%s: num_channels:%d, restrictions:%x", __FUNCTION__, num_channels,
618 restrictions);
619 if (num_channels == 0) {
620 unsafe_channels_attr = cmd->attr_start(0);
621 if (!unsafe_channels_attr) {
622 ALOGE("%s: failed attr_start for unsafe_channels_attr when"
623 " trying to clear usafe channels clear", __FUNCTION__);
624 ret = WIFI_ERROR_OUT_OF_MEMORY;
625 goto cleanup;
626 }
627 ret = cmd->put_u32(
628 QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START, 0);
629 if (ret != WIFI_SUCCESS) {
630 ALOGE("%s: Failed to put frequency start, ret:%d",
631 __FUNCTION__, ret);
632 goto cleanup;
633 }
634 ret = cmd->put_u32(
635 QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END, 0);
636 if (ret != WIFI_SUCCESS) {
637 ALOGE("%s: Failed to put frequency end, ret:%d",
638 __FUNCTION__, ret);
639 goto cleanup;
640 }
641 cmd->attr_end(unsafe_channels_attr);
642 }
643 else {
644 if (!unsafeChannels) {
645 ALOGE("%s: unsafe channels buffer should not be NULL when"
646 " there are unsafe channels", __FUNCTION__);
647 ret = WIFI_ERROR_INVALID_ARGS;
648 goto cleanup;
649 }
650 }
651 for (int i = 0; i < num_channels; i++) {
652 unsafe_channels_attr = cmd->attr_start(i);
653 if (!unsafe_channels_attr) {
654 ALOGE("%s: failed attr_start for unsafe_channels_attr of"
655 " index:%d", __FUNCTION__, i);
656 ret = WIFI_ERROR_OUT_OF_MEMORY;
657 goto cleanup;
658 }
659 u32 freq = get_frequency_from_channel(unsafeChannels[i].channel,
660 unsafeChannels[i].band);
661 if (!freq) {
662 ALOGE("%s: Failed to get frequency of band:%d, channel:%d",
663 __FUNCTION__, (int)unsafeChannels[i].band,
664 unsafeChannels[i].channel);
665 ret = WIFI_ERROR_INVALID_ARGS;
666 goto cleanup;
667 }
668 ret = cmd->put_u32(
669 QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START, freq);
670 if (ret != WIFI_SUCCESS) {
671 ALOGE("%s: Failed to put frequency start, ret:%d",
672 __FUNCTION__, ret);
673 goto cleanup;
674 }
675 ret = cmd->put_u32(
676 QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END, freq);
677 if (ret != WIFI_SUCCESS) {
678 ALOGE("%s: Failed to put frequency end, ret:%d",
679 __FUNCTION__, ret);
680 goto cleanup;
681 }
682 /**
683 * WIFI_COEX_NO_POWER_CAP (0x7FFFFFF) is specific to android
684 * framework, this value denotes that framework/wifihal is not
685 * providing any power cap and allow driver/firmware to operate on
686 * current power cap dbm. As driver is supposed to work on with
687 * LA/LE etc, we are skipping to send 0x7FFFFFF down to driver,
688 * hence driver will be operating as per current power cap calculated
689 * based on regulatory or other constraints.
690 */
691 if (unsafeChannels[i].power_cap_dbm != WIFI_COEX_NO_POWER_CAP) {
692 ret = cmd->put_s32(
693 QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM,
694 unsafeChannels[i].power_cap_dbm);
695 if (ret != WIFI_SUCCESS) {
696 ALOGE("%s: Failed to put power_cap_dbm, ret:%d",
697 __FUNCTION__, ret);
698 goto cleanup;
699 }
700 }
701 cmd->attr_end(unsafe_channels_attr);
702 ALOGD("%s: channel:%d, freq:%d, power_cap_dbm:%d, band:%d",
703 __FUNCTION__, unsafeChannels[i].channel, freq,
704 unsafeChannels[i].power_cap_dbm, unsafeChannels[i].band);
705 }
706 cmd->attr_end(nl_attr_unsafe_chan);
707 if (num_channels > 0) {
708 ret = cmd->put_u32(QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK,
709 get_nl_ifmask_from_coex_restriction_mask(restrictions));
710 if (ret != WIFI_SUCCESS) {
711 ALOGE("%s: Failed to put restrictions mask, ret:%d",
712 __FUNCTION__, ret);
713 goto cleanup;
714 }
715 }
716 cmd->attr_end(nl_data);
717
718 /* Send the msg and wait for a response. */
719 ret = cmd->requestResponse();
720 if (ret != WIFI_SUCCESS) {
721 ALOGE("%s: Error %d waiting for response.", __FUNCTION__, ret);
722 goto cleanup;
723 }
724
725 cleanup:
726 if (cmd)
727 delete cmd;
728 return ret;
729 }
730
wifi_set_dtim_config(wifi_interface_handle handle,u32 multiplier)731 wifi_error wifi_set_dtim_config(wifi_interface_handle handle, u32 multiplier)
732 {
733 wifi_error ret = WIFI_ERROR_INVALID_ARGS;
734 WifihalGeneric *cmd = NULL;
735 struct nlattr *nlData = NULL;
736 interface_info *ifaceInfo = NULL;
737 wifi_handle wifiHandle = NULL;
738
739 if (!handle) {
740 ALOGE("%s: Error, wifi_interface_handle NULL", __FUNCTION__);
741 goto cleanup;
742 }
743 ALOGD("%s: multiplier:%d", __FUNCTION__, multiplier);
744 wifiHandle = getWifiHandle(handle);
745 cmd = new WifihalGeneric(wifiHandle, get_requestid(), OUI_QCA,
746 QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
747 if (cmd == NULL) {
748 ALOGE("%s: Error WifihalGeneric NULL", __FUNCTION__);
749 ret = WIFI_ERROR_OUT_OF_MEMORY;
750 goto cleanup;
751 }
752
753 /* Create the NL message. */
754 ret = cmd->create();
755 if (ret != WIFI_SUCCESS) {
756 ALOGE("%s: failed to create NL msg. Error:%d", __FUNCTION__, ret);
757 goto cleanup;
758 }
759 ifaceInfo = getIfaceInfo(handle);
760 if (!ifaceInfo) {
761 ALOGE("%s: getIfaceInfo is NULL", __FUNCTION__);
762 ret = WIFI_ERROR_OUT_OF_MEMORY;
763 goto cleanup;
764 }
765
766 /* Set the interface Id of the message. */
767 ret = cmd->set_iface_id(ifaceInfo->name);
768 if (ret != WIFI_SUCCESS) {
769 ALOGE("%s: failed to set iface id. Error:%d", __FUNCTION__, ret);
770 goto cleanup;
771 }
772
773 /* Add the vendor specific attributes for the NL command. */
774 nlData = cmd->attr_start(NL80211_ATTR_VENDOR_DATA);
775 if (!nlData) {
776 ALOGE("%s: failed attr_start for VENDOR_DATA", __FUNCTION__);
777 ret = WIFI_ERROR_OUT_OF_MEMORY;
778 goto cleanup;
779 }
780
781 ret = cmd->put_u32(QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_DTIM, multiplier);
782 if (ret != WIFI_SUCCESS) {
783 ALOGE("%s: failed to put vendor data. Error:%d", __FUNCTION__, ret);
784 goto cleanup;
785 }
786 cmd->attr_end(nlData);
787
788 /* Send the NL msg. */
789 ret = cmd->requestResponse();
790 if (ret != WIFI_SUCCESS) {
791 ALOGE("%s: requestResponse Error:%d", __FUNCTION__, ret);
792 goto cleanup;
793 }
794
795 cleanup:
796 if (cmd)
797 delete cmd;
798 return ret;
799 }
800
get_nl_band_mask(u32 in_mask)801 static u32 get_nl_band_mask(u32 in_mask)
802 {
803 u32 op_mask = 0;
804
805 if (in_mask & WLAN_MAC_2_4_BAND)
806 op_mask |= BIT(NL80211_BAND_2GHZ);
807 if (in_mask & WLAN_MAC_5_0_BAND)
808 op_mask |= BIT(NL80211_BAND_5GHZ);
809 if (in_mask & WLAN_MAC_6_0_BAND)
810 op_mask |= BIT(NL80211_BAND_6GHZ);
811 if (in_mask & WLAN_MAC_60_0_BAND)
812 op_mask |= BIT(NL80211_BAND_60GHZ);
813
814 return op_mask;
815 }
816
get_nl_iftype_mode_masks(u32 in_mask)817 static u32 get_nl_iftype_mode_masks(u32 in_mask)
818 {
819 u32 op_mask = 0;
820
821 if (in_mask & BIT(WIFI_INTERFACE_STA) ||
822 in_mask & BIT(WIFI_INTERFACE_TDLS))
823 op_mask |= BIT(NL80211_IFTYPE_STATION);
824 if (in_mask & BIT(WIFI_INTERFACE_SOFTAP))
825 op_mask |= BIT(NL80211_IFTYPE_AP);
826 if (in_mask & BIT(WIFI_INTERFACE_P2P_CLIENT))
827 op_mask |= BIT(NL80211_IFTYPE_P2P_CLIENT);
828 if (in_mask & BIT(WIFI_INTERFACE_P2P_GO))
829 op_mask |= BIT(NL80211_IFTYPE_P2P_GO);
830 if (in_mask & BIT(WIFI_INTERFACE_NAN))
831 op_mask |= BIT(NL80211_IFTYPE_NAN);
832
833 return op_mask;
834 }
835
get_vendor_filter_mask(u32 in_mask)836 static u32 get_vendor_filter_mask(u32 in_mask)
837 {
838 u32 op_mask = 0;
839
840 if (in_mask & WIFI_USABLE_CHANNEL_FILTER_CELLULAR_COEXISTENCE)
841 op_mask |= BIT(QCA_WLAN_VENDOR_FILTER_CELLULAR_COEX);
842 if (in_mask & WIFI_USABLE_CHANNEL_FILTER_CONCURRENCY)
843 op_mask |= BIT(QCA_WLAN_VENDOR_FILTER_WLAN_CONCURRENCY);
844
845 return op_mask;
846 }
847
wifi_get_usable_channels(wifi_handle handle,u32 band_mask,u32 iface_mode_mask,u32 filter_mask,u32 max_size,u32 * size,wifi_usable_channel * channels)848 wifi_error wifi_get_usable_channels(wifi_handle handle, u32 band_mask,
849 u32 iface_mode_mask, u32 filter_mask,
850 u32 max_size, u32* size,
851 wifi_usable_channel* channels)
852 {
853 wifi_error ret = WIFI_ERROR_UNKNOWN;
854 WifihalGeneric *cmd = NULL;
855 struct nlattr *nl_data = NULL;
856 hal_info *info = NULL;
857 u32 band = 0, iface_mask = 0, filter = 0;
858
859 if (!handle) {
860 ALOGE("%s: Error, wifi_handle NULL", __FUNCTION__);
861 goto cleanup;
862 }
863
864 info = getHalInfo(handle);
865 if (!info || info->num_interfaces < 1) {
866 ALOGE("%s: Error, wifi_handle NULL or base wlan interface not present",
867 __FUNCTION__);
868 goto cleanup;
869 }
870
871 if (!max_size) {
872 ALOGE("%s: max channel size is zero", __FUNCTION__);
873 ret = WIFI_ERROR_INVALID_ARGS;
874 goto cleanup;
875 }
876
877 if (!channels) {
878 ALOGE("%s: user input channel buffer NULL", __FUNCTION__);
879 ret = WIFI_ERROR_INVALID_ARGS;
880 goto cleanup;
881 }
882
883 cmd = new WifihalGeneric(handle, get_requestid(), OUI_QCA,
884 QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS);
885 if (cmd == NULL) {
886 ALOGE("%s: Error, created command NULL", __FUNCTION__);
887 ret = WIFI_ERROR_OUT_OF_MEMORY;
888 goto cleanup;
889 }
890
891 /* Create the NL message. */
892 ret = cmd->create();
893 if (ret < 0) {
894 ALOGE("%s: failed to create NL msg due to error: (%d)",
895 __FUNCTION__, ret);
896 goto cleanup;
897 }
898
899 /* Add the vendor specific attributes for the NL command. */
900 nl_data = cmd->attr_start(NL80211_ATTR_VENDOR_DATA);
901 if (!nl_data) {
902 ALOGE("%s: failed attr_start for VENDOR_DATA due to error: (%d)",
903 __FUNCTION__, ret);
904 ret = WIFI_ERROR_OUT_OF_MEMORY;
905 goto cleanup;
906 }
907
908 band = get_nl_band_mask(band_mask);
909 ret = cmd->put_u32(QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK,
910 band);
911 if (ret != WIFI_SUCCESS) {
912 ALOGE("%s: failed to put vendor data due to error:%d",
913 __FUNCTION__, ret);
914 goto cleanup;
915 }
916
917 iface_mask = get_nl_iftype_mode_masks(iface_mode_mask);
918 ret = cmd->put_u32(QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK,
919 iface_mask);
920 if (ret != WIFI_SUCCESS) {
921 ALOGE("%s: failed to put vendor data due to error:%d",
922 __FUNCTION__, ret);
923 goto cleanup;
924 }
925
926 filter = get_vendor_filter_mask(filter_mask);
927 ret = cmd->put_u32(QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK,
928 filter);
929 if (ret != WIFI_SUCCESS) {
930 ALOGE("%s: failed to put vendor data due to error:%d",
931 __FUNCTION__, ret);
932 goto cleanup;
933 }
934
935 cmd->attr_end(nl_data);
936
937 /* Populate the input received from caller/framework. */
938 cmd->setMaxSetSize(max_size);
939 cmd->set_channels_buff(channels);
940
941 /* Send the msg and wait for a response. */
942 ret = cmd->requestResponse();
943 if (ret != WIFI_SUCCESS) {
944 ALOGE("%s: Error %d waiting for response.", __FUNCTION__, ret);
945 goto cleanup;
946 }
947
948 *size = cmd->get_results_size();
949
950 cleanup:
951 if (cmd)
952 delete cmd;
953 return ret;
954 }
955
956 /*initialize function pointer table with Qualcomm HAL API*/
init_wifi_vendor_hal_func_table(wifi_hal_fn * fn)957 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) {
958 if (fn == NULL) {
959 return WIFI_ERROR_UNKNOWN;
960 }
961
962 fn->wifi_initialize = wifi_initialize;
963 fn->wifi_wait_for_driver_ready = wifi_wait_for_driver_ready;
964 fn->wifi_cleanup = wifi_cleanup;
965 fn->wifi_event_loop = wifi_event_loop;
966 fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
967 fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
968 fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui;
969 fn->wifi_get_ifaces = wifi_get_ifaces;
970 fn->wifi_get_iface_name = wifi_get_iface_name;
971 fn->wifi_set_iface_event_handler = wifi_set_iface_event_handler;
972 fn->wifi_reset_iface_event_handler = wifi_reset_iface_event_handler;
973 fn->wifi_start_gscan = wifi_start_gscan;
974 fn->wifi_stop_gscan = wifi_stop_gscan;
975 fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
976 fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
977 fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
978 fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
979 fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
980 fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
981 fn->wifi_set_link_stats = wifi_set_link_stats;
982 fn->wifi_get_link_stats = wifi_get_link_stats;
983 fn->wifi_clear_link_stats = wifi_clear_link_stats;
984 fn->wifi_get_valid_channels = wifi_get_valid_channels;
985 fn->wifi_rtt_range_request = wifi_rtt_range_request;
986 fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
987 fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
988 fn->wifi_rtt_get_responder_info = wifi_rtt_get_responder_info;
989 fn->wifi_enable_responder = wifi_enable_responder;
990 fn->wifi_disable_responder = wifi_disable_responder;
991 fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
992 fn->wifi_start_logging = wifi_start_logging;
993 fn->wifi_set_epno_list = wifi_set_epno_list;
994 fn->wifi_reset_epno_list = wifi_reset_epno_list;
995 fn->wifi_set_country_code = wifi_set_country_code;
996 fn->wifi_enable_tdls = wifi_enable_tdls;
997 fn->wifi_disable_tdls = wifi_disable_tdls;
998 fn->wifi_get_tdls_status = wifi_get_tdls_status;
999 fn->wifi_get_tdls_capabilities = wifi_get_tdls_capabilities;
1000 fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
1001 fn->wifi_set_log_handler = wifi_set_log_handler;
1002 fn->wifi_reset_log_handler = wifi_reset_log_handler;
1003 fn->wifi_set_alert_handler = wifi_set_alert_handler;
1004 fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
1005 fn->wifi_get_firmware_version = wifi_get_firmware_version;
1006 fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
1007 fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;
1008 fn->wifi_get_ring_data = wifi_get_ring_data;
1009 fn->wifi_get_driver_version = wifi_get_driver_version;
1010 fn->wifi_set_passpoint_list = wifi_set_passpoint_list;
1011 fn->wifi_reset_passpoint_list = wifi_reset_passpoint_list;
1012 fn->wifi_set_lci = wifi_set_lci;
1013 fn->wifi_set_lcr = wifi_set_lcr;
1014 fn->wifi_start_sending_offloaded_packet =
1015 wifi_start_sending_offloaded_packet;
1016 fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
1017 fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
1018 fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
1019 fn->wifi_nan_enable_request = nan_enable_request;
1020 fn->wifi_nan_disable_request = nan_disable_request;
1021 fn->wifi_nan_publish_request = nan_publish_request;
1022 fn->wifi_nan_publish_cancel_request = nan_publish_cancel_request;
1023 fn->wifi_nan_subscribe_request = nan_subscribe_request;
1024 fn->wifi_nan_subscribe_cancel_request = nan_subscribe_cancel_request;
1025 fn->wifi_nan_transmit_followup_request = nan_transmit_followup_request;
1026 fn->wifi_nan_stats_request = nan_stats_request;
1027 fn->wifi_nan_config_request = nan_config_request;
1028 fn->wifi_nan_tca_request = nan_tca_request;
1029 fn->wifi_nan_beacon_sdf_payload_request = nan_beacon_sdf_payload_request;
1030 fn->wifi_nan_register_handler = nan_register_handler;
1031 fn->wifi_nan_get_version = nan_get_version;
1032 fn->wifi_set_packet_filter = wifi_set_packet_filter;
1033 fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
1034 fn->wifi_read_packet_filter = wifi_read_packet_filter;
1035 fn->wifi_nan_get_capabilities = nan_get_capabilities;
1036 fn->wifi_nan_data_interface_create = nan_data_interface_create;
1037 fn->wifi_nan_data_interface_delete = nan_data_interface_delete;
1038 fn->wifi_nan_data_request_initiator = nan_data_request_initiator;
1039 fn->wifi_nan_data_indication_response = nan_data_indication_response;
1040 fn->wifi_nan_data_end = nan_data_end;
1041 fn->wifi_configure_nd_offload = wifi_configure_nd_offload;
1042 fn->wifi_get_driver_memory_dump = wifi_get_driver_memory_dump;
1043 fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats;
1044 fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring;
1045 fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;
1046 fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;
1047 fn->wifi_get_roaming_capabilities = wifi_get_roaming_capabilities;
1048 fn->wifi_configure_roaming = wifi_configure_roaming;
1049 fn->wifi_enable_firmware_roaming = wifi_enable_firmware_roaming;
1050 fn->wifi_select_tx_power_scenario = wifi_select_tx_power_scenario;
1051 fn->wifi_reset_tx_power_scenario = wifi_reset_tx_power_scenario;
1052 fn->wifi_set_radio_mode_change_handler = wifi_set_radio_mode_change_handler;
1053 fn->wifi_virtual_interface_create = wifi_virtual_interface_create;
1054 fn->wifi_virtual_interface_delete = wifi_virtual_interface_delete;
1055 fn->wifi_set_latency_mode = wifi_set_latency_mode;
1056 fn->wifi_set_thermal_mitigation_mode = wifi_set_thermal_mitigation_mode;
1057 fn->wifi_set_coex_unsafe_channels = wifi_set_coex_unsafe_channels;
1058 fn->wifi_set_dtim_config = wifi_set_dtim_config;
1059 fn->wifi_get_usable_channels = wifi_get_usable_channels;
1060
1061 return WIFI_SUCCESS;
1062 }
1063
cld80211lib_cleanup(hal_info * info)1064 static void cld80211lib_cleanup(hal_info *info)
1065 {
1066 if (!info->cldctx)
1067 return;
1068 cld80211_remove_mcast_group(info->cldctx, "host_logs");
1069 cld80211_remove_mcast_group(info->cldctx, "fw_logs");
1070 cld80211_remove_mcast_group(info->cldctx, "per_pkt_stats");
1071 cld80211_remove_mcast_group(info->cldctx, "diag_events");
1072 cld80211_remove_mcast_group(info->cldctx, "fatal_events");
1073 cld80211_remove_mcast_group(info->cldctx, "oem_msgs");
1074 exit_cld80211_recv(info->cldctx);
1075 cld80211_deinit(info->cldctx);
1076 info->cldctx = NULL;
1077 }
1078
wifi_get_iface_id(hal_info * info,const char * iface)1079 static int wifi_get_iface_id(hal_info *info, const char *iface)
1080 {
1081 int i;
1082 for (i = 0; i < info->num_interfaces; i++)
1083 if (!strcmp(info->interfaces[i]->name, iface))
1084 return i;
1085 return -1;
1086 }
1087
wifi_initialize(wifi_handle * handle)1088 wifi_error wifi_initialize(wifi_handle *handle)
1089 {
1090 wifi_error ret = WIFI_SUCCESS;
1091 wifi_interface_handle iface_handle;
1092 struct nl_sock *cmd_sock = NULL;
1093 struct nl_sock *event_sock = NULL;
1094 struct nl_cb *cb = NULL;
1095 int status = 0;
1096 int index;
1097 char hw_ver_type[MAX_HW_VER_LENGTH];
1098 char *hw_name = NULL;
1099
1100 ALOGI("Initializing wifi");
1101 hal_info *info = (hal_info *)malloc(sizeof(hal_info));
1102 if (info == NULL) {
1103 ALOGE("Could not allocate hal_info");
1104 return WIFI_ERROR_OUT_OF_MEMORY;
1105 }
1106
1107 memset(info, 0, sizeof(*info));
1108
1109 cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT,
1110 NETLINK_GENERIC);
1111 if (cmd_sock == NULL) {
1112 ALOGE("Failed to create command socket port");
1113 ret = WIFI_ERROR_UNKNOWN;
1114 goto unload;
1115 }
1116
1117 /* Set the socket buffer size */
1118 if (nl_socket_set_buffer_size(cmd_sock, (256*1024), 0) < 0) {
1119 ALOGE("Could not set nl_socket RX buffer size for cmd_sock: %s",
1120 strerror(errno));
1121 /* continue anyway with the default (smaller) buffer */
1122 }
1123
1124 event_sock =
1125 wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT, NETLINK_GENERIC);
1126 if (event_sock == NULL) {
1127 ALOGE("Failed to create event socket port");
1128 ret = WIFI_ERROR_UNKNOWN;
1129 goto unload;
1130 }
1131
1132 /* Set the socket buffer size */
1133 if (nl_socket_set_buffer_size(event_sock, (256*1024), 0) < 0) {
1134 ALOGE("Could not set nl_socket RX buffer size for event_sock: %s",
1135 strerror(errno));
1136 /* continue anyway with the default (smaller) buffer */
1137 }
1138
1139 cb = nl_socket_get_cb(event_sock);
1140 if (cb == NULL) {
1141 ALOGE("Failed to get NL control block for event socket port");
1142 ret = WIFI_ERROR_UNKNOWN;
1143 goto unload;
1144 }
1145
1146 info->event_sock_arg = 1;
1147 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
1148 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->event_sock_arg);
1149 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->event_sock_arg);
1150 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->event_sock_arg);
1151
1152 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler,
1153 info);
1154 nl_cb_put(cb);
1155
1156 info->cmd_sock = cmd_sock;
1157 info->event_sock = event_sock;
1158 info->clean_up = false;
1159 info->in_event_loop = false;
1160
1161 info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
1162 if (info->event_cb == NULL) {
1163 ALOGE("Could not allocate event_cb");
1164 ret = WIFI_ERROR_OUT_OF_MEMORY;
1165 goto unload;
1166 }
1167 info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
1168 info->num_event_cb = 0;
1169
1170 info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
1171 if (info->nl80211_family_id < 0) {
1172 ALOGE("Could not resolve nl80211 familty id");
1173 ret = WIFI_ERROR_UNKNOWN;
1174 goto unload;
1175 }
1176
1177 pthread_mutex_init(&info->cb_lock, NULL);
1178 pthread_mutex_init(&info->pkt_fate_stats_lock, NULL);
1179
1180 *handle = (wifi_handle) info;
1181
1182 wifi_add_membership(*handle, "scan");
1183 wifi_add_membership(*handle, "mlme");
1184 wifi_add_membership(*handle, "regulatory");
1185 wifi_add_membership(*handle, "vendor");
1186
1187 info->wifihal_ctrl_sock.s = 0;
1188
1189 wifi_create_ctrl_socket(info);
1190
1191 //! Initailise the monitoring clients list
1192 INITIALISE_LIST(&info->monitor_sockets);
1193
1194 info->cldctx = cld80211_init();
1195 if (info->cldctx != NULL) {
1196 info->user_sock = info->cldctx->sock;
1197 ret = wifi_init_cld80211_sock_cb(info);
1198 if (ret != WIFI_SUCCESS) {
1199 ALOGE("Could not set cb for CLD80211 family");
1200 goto cld80211_cleanup;
1201 }
1202
1203 status = cld80211_add_mcast_group(info->cldctx, "host_logs");
1204 if (status) {
1205 ALOGE("Failed to add mcast group host_logs :%d", status);
1206 goto cld80211_cleanup;
1207 }
1208 status = cld80211_add_mcast_group(info->cldctx, "fw_logs");
1209 if (status) {
1210 ALOGE("Failed to add mcast group fw_logs :%d", status);
1211 goto cld80211_cleanup;
1212 }
1213 status = cld80211_add_mcast_group(info->cldctx, "per_pkt_stats");
1214 if (status) {
1215 ALOGE("Failed to add mcast group per_pkt_stats :%d", status);
1216 goto cld80211_cleanup;
1217 }
1218 status = cld80211_add_mcast_group(info->cldctx, "diag_events");
1219 if (status) {
1220 ALOGE("Failed to add mcast group diag_events :%d", status);
1221 goto cld80211_cleanup;
1222 }
1223 status = cld80211_add_mcast_group(info->cldctx, "fatal_events");
1224 if (status) {
1225 ALOGE("Failed to add mcast group fatal_events :%d", status);
1226 goto cld80211_cleanup;
1227 }
1228
1229 if(info->wifihal_ctrl_sock.s > 0)
1230 {
1231 status = cld80211_add_mcast_group(info->cldctx, "oem_msgs");
1232 if (status) {
1233 ALOGE("Failed to add mcast group oem_msgs :%d", status);
1234 goto cld80211_cleanup;
1235 }
1236 }
1237 } else {
1238 ret = wifi_init_user_sock(info);
1239 if (ret != WIFI_SUCCESS) {
1240 ALOGE("Failed to alloc user socket");
1241 goto unload;
1242 }
1243 }
1244
1245 ret = wifi_init_interfaces(*handle);
1246 if (ret != WIFI_SUCCESS) {
1247 ALOGE("Failed to init interfaces");
1248 goto unload;
1249 }
1250
1251 if (info->num_interfaces == 0) {
1252 ALOGE("No interfaces found");
1253 ret = WIFI_ERROR_UNINITIALIZED;
1254 goto unload;
1255 }
1256
1257 index = wifi_get_iface_id(info, "wlan0");
1258 if (index == -1) {
1259 int i;
1260 for (i = 0; i < info->num_interfaces; i++)
1261 {
1262 free(info->interfaces[i]);
1263 }
1264 ALOGE("%s no iface with wlan0", __func__);
1265 goto unload;
1266 }
1267 iface_handle = (wifi_interface_handle)info->interfaces[index];
1268
1269 ret = acquire_supported_features(iface_handle,
1270 &info->supported_feature_set);
1271 if (ret != WIFI_SUCCESS) {
1272 ALOGI("Failed to get supported feature set : %d", ret);
1273 //acquire_supported_features failure is acceptable condition as legacy
1274 //drivers might not support the required vendor command. So, do not
1275 //consider it as failure of wifi_initialize
1276 ret = WIFI_SUCCESS;
1277 }
1278
1279 ret = acquire_driver_supported_features(iface_handle,
1280 &info->driver_supported_features);
1281 if (ret != WIFI_SUCCESS) {
1282 ALOGI("Failed to get vendor feature set : %d", ret);
1283 ret = WIFI_SUCCESS;
1284 }
1285
1286 ret = wifi_get_logger_supported_feature_set(iface_handle,
1287 &info->supported_logger_feature_set);
1288 if (ret != WIFI_SUCCESS)
1289 ALOGE("Failed to get supported logger feature set: %d", ret);
1290
1291 ret = wifi_get_firmware_version(iface_handle, hw_ver_type,
1292 MAX_HW_VER_LENGTH);
1293 if (ret == WIFI_SUCCESS) {
1294 hw_name = strstr(hw_ver_type, "HW:");
1295 if (hw_name) {
1296 hw_name += strlen("HW:");
1297 if (strncmp(hw_name, "QCA6174", 7) == 0)
1298 info->pkt_log_ver = PKT_LOG_V1;
1299 else
1300 info->pkt_log_ver = PKT_LOG_V2;
1301 } else {
1302 info->pkt_log_ver = PKT_LOG_V0;
1303 }
1304 ALOGV("%s: hardware version type %d", __func__, info->pkt_log_ver);
1305 } else {
1306 ALOGE("Failed to get firmware version: %d", ret);
1307 }
1308
1309 ret = get_firmware_bus_max_size_supported(iface_handle);
1310 if (ret != WIFI_SUCCESS) {
1311 ALOGE("Failed to get supported bus size, error : %d", ret);
1312 info->firmware_bus_max_size = 1520;
1313 }
1314
1315 ret = wifi_logger_ring_buffers_init(info);
1316 if (ret != WIFI_SUCCESS)
1317 ALOGE("Wifi Logger Ring Initialization Failed");
1318
1319 ret = wifi_get_capabilities(iface_handle);
1320 if (ret != WIFI_SUCCESS)
1321 ALOGE("Failed to get wifi Capabilities, error: %d", ret);
1322
1323 info->pkt_stats = (struct pkt_stats_s *)malloc(sizeof(struct pkt_stats_s));
1324 if (!info->pkt_stats) {
1325 ALOGE("%s: malloc Failed for size: %zu",
1326 __FUNCTION__, sizeof(struct pkt_stats_s));
1327 ret = WIFI_ERROR_OUT_OF_MEMORY;
1328 goto unload;
1329 }
1330
1331 info->rx_buf_size_allocated = MAX_RXMPDUS_PER_AMPDU * MAX_MSDUS_PER_MPDU
1332 * PKT_STATS_BUF_SIZE;
1333
1334 info->rx_aggr_pkts =
1335 (wifi_ring_buffer_entry *)malloc(info->rx_buf_size_allocated);
1336 if (!info->rx_aggr_pkts) {
1337 ALOGE("%s: malloc Failed for size: %d",
1338 __FUNCTION__, info->rx_buf_size_allocated);
1339 ret = WIFI_ERROR_OUT_OF_MEMORY;
1340 info->rx_buf_size_allocated = 0;
1341 goto unload;
1342 }
1343 memset(info->rx_aggr_pkts, 0, info->rx_buf_size_allocated);
1344
1345 info->exit_sockets[0] = -1;
1346 info->exit_sockets[1] = -1;
1347
1348 if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->exit_sockets) == -1) {
1349 ALOGE("Failed to create exit socket pair");
1350 ret = WIFI_ERROR_UNKNOWN;
1351 goto unload;
1352 }
1353
1354 ALOGV("Initializing Gscan Event Handlers");
1355 ret = initializeGscanHandlers(info);
1356 if (ret != WIFI_SUCCESS) {
1357 ALOGE("Initializing Gscan Event Handlers Failed");
1358 goto unload;
1359 }
1360
1361 ret = initializeRSSIMonitorHandler(info);
1362 if (ret != WIFI_SUCCESS) {
1363 ALOGE("Initializing RSSI Event Handler Failed");
1364 goto unload;
1365 }
1366
1367 ALOGV("Initialized Wifi HAL Successfully; vendor cmd = %d Supported"
1368 " features : 0x%" PRIx64, NL80211_CMD_VENDOR, info->supported_feature_set);
1369
1370 if (wifi_is_nan_ext_cmd_supported(iface_handle))
1371 info->support_nan_ext_cmd = true;
1372 else
1373 info->support_nan_ext_cmd = false;
1374
1375 ALOGV("support_nan_ext_cmd is %d",
1376 info->support_nan_ext_cmd);
1377
1378 cld80211_cleanup:
1379 if (status != 0 || ret != WIFI_SUCCESS) {
1380 ret = WIFI_ERROR_UNKNOWN;
1381 cld80211lib_cleanup(info);
1382 }
1383 unload:
1384 if (ret != WIFI_SUCCESS) {
1385 if (cmd_sock)
1386 nl_socket_free(cmd_sock);
1387 if (event_sock)
1388 nl_socket_free(event_sock);
1389 if (info) {
1390 if (info->cldctx) {
1391 cld80211lib_cleanup(info);
1392 } else if (info->user_sock) {
1393 nl_socket_free(info->user_sock);
1394 }
1395 if (info->pkt_stats) free(info->pkt_stats);
1396 if (info->rx_aggr_pkts) free(info->rx_aggr_pkts);
1397 wifi_logger_ring_buffers_deinit(info);
1398 cleanupGscanHandlers(info);
1399 cleanupRSSIMonitorHandler(info);
1400 free(info->event_cb);
1401 if (info->driver_supported_features.flags) {
1402 free(info->driver_supported_features.flags);
1403 info->driver_supported_features.flags = NULL;
1404 }
1405 free(info);
1406 }
1407 }
1408
1409 return ret;
1410 }
1411
1412 #ifdef WIFI_DRIVER_STATE_CTRL_PARAM
wifi_update_driver_state(const char * state)1413 static int wifi_update_driver_state(const char *state) {
1414 struct timespec ts;
1415 int len, fd, ret = 0, count = 5;
1416 ts.tv_sec = 0;
1417 ts.tv_nsec = 200 * 1000000L;
1418
1419 do {
1420 if (access(WIFI_DRIVER_STATE_CTRL_PARAM, W_OK) == 0)
1421 break;
1422 nanosleep(&ts, (struct timespec *)NULL);
1423 } while (--count > 0); /* wait at most 1 second for completion. */
1424 if (count == 0) {
1425 ALOGE("Failed to access driver state control param %s, %d at %s",
1426 strerror(errno), errno, WIFI_DRIVER_STATE_CTRL_PARAM);
1427 return -1;
1428 }
1429
1430 fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_STATE_CTRL_PARAM, O_WRONLY));
1431 if (fd < 0) {
1432 ALOGE("Failed to open driver state control param at %s",
1433 WIFI_DRIVER_STATE_CTRL_PARAM);
1434 return -1;
1435 }
1436
1437 len = strlen(state) + 1;
1438 if (TEMP_FAILURE_RETRY(write(fd, state, len)) != len) {
1439 ALOGE("Failed to write driver state control param at %s",
1440 WIFI_DRIVER_STATE_CTRL_PARAM);
1441 ret = -1;
1442 }
1443
1444 close(fd);
1445 return ret;
1446 }
1447 #endif
1448
wifi_wait_for_driver_ready(void)1449 wifi_error wifi_wait_for_driver_ready(void)
1450 {
1451 // This function will wait to make sure basic client netdev is created
1452 // Function times out after 10 seconds
1453 int count = (POLL_DRIVER_MAX_TIME_MS * 1000) / POLL_DRIVER_DURATION_US;
1454 FILE *fd;
1455
1456 #if defined(WIFI_DRIVER_STATE_CTRL_PARAM) && defined(WIFI_DRIVER_STATE_ON)
1457 if (wifi_update_driver_state(WIFI_DRIVER_STATE_ON) < 0) {
1458 return WIFI_ERROR_UNKNOWN;
1459 }
1460 #endif
1461
1462 do {
1463 if ((fd = fopen("/sys/class/net/wlan0", "r")) != NULL) {
1464 fclose(fd);
1465 return WIFI_SUCCESS;
1466 }
1467 usleep(POLL_DRIVER_DURATION_US);
1468 } while(--count > 0);
1469
1470 ALOGE("Timed out wating on Driver ready ... ");
1471 return WIFI_ERROR_TIMED_OUT;
1472 }
1473
wifi_add_membership(wifi_handle handle,const char * group)1474 static int wifi_add_membership(wifi_handle handle, const char *group)
1475 {
1476 hal_info *info = getHalInfo(handle);
1477
1478 int id = wifi_get_multicast_id(handle, "nl80211", group);
1479 if (id < 0) {
1480 ALOGE("Could not find group %s", group);
1481 return id;
1482 }
1483
1484 int ret = nl_socket_add_membership(info->event_sock, id);
1485 if (ret < 0) {
1486 ALOGE("Could not add membership to group %s", group);
1487 }
1488
1489 return ret;
1490 }
1491
internal_cleaned_up_handler(wifi_handle handle)1492 static void internal_cleaned_up_handler(wifi_handle handle)
1493 {
1494 hal_info *info = getHalInfo(handle);
1495 wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
1496 wifihal_mon_sock_t *reg, *tmp;
1497
1498 if (info->cmd_sock != 0) {
1499 nl_socket_free(info->cmd_sock);
1500 nl_socket_free(info->event_sock);
1501 info->cmd_sock = NULL;
1502 info->event_sock = NULL;
1503 }
1504
1505 if (info->wifihal_ctrl_sock.s != 0) {
1506 close(info->wifihal_ctrl_sock.s);
1507 unlink(info->wifihal_ctrl_sock.local.sun_path);
1508 info->wifihal_ctrl_sock.s = 0;
1509 }
1510
1511 list_for_each_entry_safe(reg, tmp, &info->monitor_sockets, list) {
1512 del_from_list(®->list);
1513 if(reg) {
1514 free(reg);
1515 }
1516 }
1517
1518 if (info->interfaces) {
1519 for (int i = 0; i < info->num_interfaces; i++)
1520 free(info->interfaces[i]);
1521 free(info->interfaces);
1522 }
1523
1524 if (info->cldctx != NULL) {
1525 cld80211lib_cleanup(info);
1526 } else if (info->user_sock != 0) {
1527 nl_socket_free(info->user_sock);
1528 info->user_sock = NULL;
1529 }
1530
1531 if (info->pkt_stats)
1532 free(info->pkt_stats);
1533 if (info->rx_aggr_pkts)
1534 free(info->rx_aggr_pkts);
1535 wifi_logger_ring_buffers_deinit(info);
1536 cleanupGscanHandlers(info);
1537 cleanupRSSIMonitorHandler(info);
1538
1539 if (info->num_event_cb)
1540 ALOGE("%d events were leftover without being freed",
1541 info->num_event_cb);
1542 free(info->event_cb);
1543
1544 if (info->exit_sockets[0] >= 0) {
1545 close(info->exit_sockets[0]);
1546 info->exit_sockets[0] = -1;
1547 }
1548
1549 if (info->exit_sockets[1] >= 0) {
1550 close(info->exit_sockets[1]);
1551 info->exit_sockets[1] = -1;
1552 }
1553
1554 if (info->pkt_fate_stats) {
1555 free(info->pkt_fate_stats);
1556 info->pkt_fate_stats = NULL;
1557 }
1558
1559 if (info->driver_supported_features.flags) {
1560 free(info->driver_supported_features.flags);
1561 info->driver_supported_features.flags = NULL;
1562 }
1563
1564 (*cleaned_up_handler)(handle);
1565 pthread_mutex_destroy(&info->cb_lock);
1566 pthread_mutex_destroy(&info->pkt_fate_stats_lock);
1567 free(info);
1568 }
1569
wifi_cleanup(wifi_handle handle,wifi_cleaned_up_handler handler)1570 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
1571 {
1572 if (!handle) {
1573 ALOGE("Handle is null");
1574 return;
1575 }
1576
1577 hal_info *info = getHalInfo(handle);
1578 info->cleaned_up_handler = handler;
1579 info->clean_up = true;
1580 // Remove the dynamically created interface during wifi cleanup.
1581 wifi_cleanup_dynamic_ifaces(handle);
1582
1583
1584 TEMP_FAILURE_RETRY(write(info->exit_sockets[0], "E", 1));
1585 ALOGI("Sent msg on exit sock to unblock poll()");
1586 }
1587
1588
1589
validate_cld80211_msg(nlmsghdr * nlh,int family,int cmd)1590 static int validate_cld80211_msg(nlmsghdr *nlh, int family, int cmd)
1591 {
1592 //! Enhance this API
1593 struct genlmsghdr *hdr;
1594 hdr = (genlmsghdr *)nlmsg_data(nlh);
1595
1596 if (nlh->nlmsg_len > DEFAULT_PAGE_SIZE - sizeof(wifihal_ctrl_req_t))
1597 {
1598 ALOGE("%s: Invalid nlmsg length", __FUNCTION__);
1599 return -1;
1600 }
1601 if(hdr->cmd == WLAN_NL_MSG_OEM)
1602 {
1603 ALOGV("%s: FAMILY ID : %d ,NL CMD : %d received", __FUNCTION__,
1604 nlh->nlmsg_type, hdr->cmd);
1605
1606 //! Update pid with the wifihal pid
1607 nlh->nlmsg_pid = getpid();
1608 return 0;
1609 }
1610 else
1611 {
1612 ALOGE("%s: NL CMD : %d received is not allowed", __FUNCTION__, hdr->cmd);
1613 return -1;
1614 }
1615 }
1616
1617
validate_genl_msg(nlmsghdr * nlh,int family,int cmd)1618 static int validate_genl_msg(nlmsghdr *nlh, int family, int cmd)
1619 {
1620 //! Enhance this API
1621 struct genlmsghdr *hdr;
1622 hdr = (genlmsghdr *)nlmsg_data(nlh);
1623
1624 if (nlh->nlmsg_len > DEFAULT_PAGE_SIZE - sizeof(wifihal_ctrl_req_t))
1625 {
1626 ALOGE("%s: Invalid nlmsg length", __FUNCTION__);
1627 return -1;
1628 }
1629 if(hdr->cmd == NL80211_CMD_FRAME ||
1630 hdr->cmd == NL80211_CMD_REGISTER_ACTION)
1631 {
1632 ALOGV("%s: FAMILY ID : %d ,NL CMD : %d received", __FUNCTION__,
1633 nlh->nlmsg_type, hdr->cmd);
1634 return 0;
1635 }
1636 else
1637 {
1638 ALOGE("%s: NL CMD : %d received is not allowed", __FUNCTION__, hdr->cmd);
1639 return -1;
1640 }
1641 }
1642
send_nl_data(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg)1643 static int send_nl_data(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
1644 {
1645 hal_info *info = getHalInfo(handle);
1646 struct nl_msg *msg = NULL;
1647 int retval = -1;
1648
1649 //! attach monitor socket if it was not it the list
1650 if(ctrl_msg->monsock_len)
1651 {
1652 retval = attach_monitor_sock(handle, ctrl_msg);
1653 if(retval)
1654 goto nl_out;
1655 }
1656
1657 msg = nlmsg_alloc();
1658 if (!msg)
1659 {
1660 ALOGE("%s: Memory allocation failed \n", __FUNCTION__);
1661 goto nl_out;
1662 }
1663
1664 if (ctrl_msg->data_len > nlmsg_get_max_size(msg))
1665 {
1666 ALOGE("%s: Invalid ctrl msg length \n", __FUNCTION__);
1667 retval = -1;
1668 goto nl_out;
1669 }
1670 memcpy((char *)msg->nm_nlh, (char *)ctrl_msg->data, ctrl_msg->data_len);
1671
1672 if(ctrl_msg->family_name == GENERIC_NL_FAMILY)
1673 {
1674 //! Before sending the received gennlmsg to kernel,
1675 //! better to have checks for allowed commands
1676 retval = validate_genl_msg(msg->nm_nlh, ctrl_msg->family_name, ctrl_msg->cmd_id);
1677 if (retval < 0)
1678 goto nl_out;
1679
1680 retval = nl_send_auto_complete(info->event_sock, msg); /* send message */
1681 if (retval < 0)
1682 {
1683 ALOGE("%s: nl_send_auto_complete - failed : %d \n", __FUNCTION__, retval);
1684 goto nl_out;
1685 }
1686
1687 retval = internal_pollin_handler(handle, info->event_sock);
1688 }
1689 else if (ctrl_msg->family_name == CLD80211_FAMILY)
1690 {
1691 if (info->cldctx != NULL)
1692 {
1693 //! Before sending the received cld80211 msg to kernel,
1694 //! better to have checks for allowed commands
1695 retval = validate_cld80211_msg(msg->nm_nlh, ctrl_msg->family_name, ctrl_msg->cmd_id);
1696 if (retval < 0)
1697 goto nl_out;
1698
1699 retval = cld80211_send_msg(info->cldctx, msg);
1700 if (retval != 0)
1701 {
1702 ALOGE("%s: send cld80211 message - failed\n", __FUNCTION__);
1703 goto nl_out;
1704 }
1705 ALOGD("%s: sent cld80211 message for pid %d\n", __FUNCTION__, getpid());
1706 }
1707 else
1708 {
1709 ALOGE("%s: cld80211 ctx not present \n", __FUNCTION__);
1710 }
1711 }
1712 else
1713 {
1714 ALOGE("%s: Unknown family name : %d \n", __FUNCTION__, ctrl_msg->family_name);
1715 retval = -1;
1716 }
1717 nl_out:
1718 if (msg)
1719 {
1720 nlmsg_free(msg);
1721 }
1722 return retval;
1723 }
1724
register_monitor_sock(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg,int attach)1725 static int register_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg, int attach)
1726 {
1727 hal_info *info = getHalInfo(handle);
1728
1729 wifihal_mon_sock_t *reg, *nreg;
1730 char *match = NULL;
1731 unsigned int match_len = 0;
1732 unsigned int type;
1733
1734 //! For Register Action frames, compare the match length and match buffer.
1735 //! For other registrations such as oem messages,
1736 //! diag messages check for respective commands
1737
1738 if((ctrl_msg->family_name == GENERIC_NL_FAMILY) &&
1739 (ctrl_msg->cmd_id == NL80211_CMD_REGISTER_ACTION))
1740 {
1741 struct genlmsghdr *genlh;
1742 struct nlmsghdr *nlh = (struct nlmsghdr *)ctrl_msg->data;
1743 genlh = (struct genlmsghdr *)nlmsg_data(nlh);
1744 struct nlattr *nlattrs[NL80211_ATTR_MAX + 1];
1745
1746 if (nlh->nlmsg_len > DEFAULT_PAGE_SIZE - sizeof(*ctrl_msg))
1747 {
1748 ALOGE("%s: Invalid nlmsg length", __FUNCTION__);
1749 return -1;
1750 }
1751 if (nla_parse(nlattrs, NL80211_ATTR_MAX, genlmsg_attrdata(genlh, 0),
1752 genlmsg_attrlen(genlh, 0), NULL))
1753 {
1754 ALOGE("unable to parse nl attributes");
1755 return -1;
1756 }
1757 if (!nlattrs[NL80211_ATTR_FRAME_TYPE])
1758 {
1759 ALOGD("No Valid frame type");
1760 }
1761 else
1762 {
1763 type = nla_get_u16(nlattrs[NL80211_ATTR_FRAME_TYPE]);
1764 }
1765 if (!nlattrs[NL80211_ATTR_FRAME_MATCH])
1766 {
1767 ALOGE("No Frame Match");
1768 return -1;
1769 }
1770 else
1771 {
1772 match_len = nla_len(nlattrs[NL80211_ATTR_FRAME_MATCH]);
1773 match = (char *)nla_data(nlattrs[NL80211_ATTR_FRAME_MATCH]);
1774
1775 list_for_each_entry(reg, &info->monitor_sockets, list) {
1776
1777 if(reg == NULL)
1778 break;
1779
1780 int mlen = min(match_len, reg->match_len);
1781
1782 if (reg->match_len == 0)
1783 continue;
1784
1785 if (memcmp(reg->match, match, mlen) == 0) {
1786
1787 if((ctrl_msg->monsock_len == reg->monsock_len) &&
1788 (memcmp((char *)®->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len) == 0))
1789 {
1790 if(attach)
1791 {
1792 ALOGE(" %s :Action frame already registered for this client ", __FUNCTION__);
1793 return -2;
1794 }
1795 else
1796 {
1797 del_from_list(®->list);
1798 free(reg);
1799 return 0;
1800 }
1801 }
1802 else
1803 {
1804 //! when action frame registered for other client,
1805 //! you can't attach or dettach for new client
1806 ALOGE(" %s :Action frame registered for other client ", __FUNCTION__);
1807 return -2;
1808 }
1809 }
1810 }
1811 }
1812 }
1813 else
1814 {
1815 list_for_each_entry(reg, &info->monitor_sockets, list) {
1816
1817 //! Checking for monitor sock in the list :
1818
1819 //! For attach request :
1820 //! if sock is not present, then it is a new entry , so add to list.
1821 //! if sock is present, and cmd_id does not match, add another entry to list.
1822 //! if sock is present, and cmd_id matches, return 0.
1823
1824 //! For dettach req :
1825 //! if sock is not present, return error -2.
1826 //! if sock is present, and cmd_id does not match, return error -2.
1827 //! if sock is present, and cmd_id matches, delete entry and return 0.
1828 if(reg == NULL)
1829 break;
1830
1831 if (ctrl_msg->monsock_len != reg->monsock_len)
1832 continue;
1833
1834 if (memcmp((char *)®->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len) == 0) {
1835
1836 if((reg->family_name == ctrl_msg->family_name) && (reg->cmd_id == ctrl_msg->cmd_id))
1837 {
1838 if(!attach)
1839 {
1840 del_from_list(®->list);
1841 free(reg);
1842 }
1843 return 0;
1844 }
1845 }
1846 }
1847 }
1848
1849 if(attach)
1850 {
1851 if (ctrl_msg->monsock_len > sizeof(struct sockaddr_un))
1852 {
1853 ALOGE("%s: Invalid monitor socket length \n", __FUNCTION__);
1854 return -3;
1855 }
1856
1857 nreg = (wifihal_mon_sock_t *)malloc(sizeof(*reg) + match_len);
1858 if (!nreg)
1859 return -1;
1860
1861 memset((char *)nreg, 0, sizeof(*reg) + match_len);
1862 nreg->family_name = ctrl_msg->family_name;
1863 nreg->cmd_id = ctrl_msg->cmd_id;
1864 nreg->monsock_len = ctrl_msg->monsock_len;
1865 memcpy((char *)&nreg->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len);
1866
1867 if(match_len && match)
1868 {
1869 nreg->match_len = match_len;
1870 memcpy(nreg->match, match, match_len);
1871 }
1872 add_to_list(&nreg->list, &info->monitor_sockets);
1873 }
1874 else
1875 {
1876 //! Not attached, so cant be dettached
1877 ALOGE("%s: Dettaching the unregistered socket \n", __FUNCTION__);
1878 return -2;
1879 }
1880
1881 return 0;
1882 }
1883
attach_monitor_sock(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg)1884 static int attach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
1885 {
1886 return register_monitor_sock(handle, ctrl_msg, 1);
1887 }
1888
dettach_monitor_sock(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg)1889 static int dettach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
1890 {
1891 return register_monitor_sock(handle, ctrl_msg, 0);
1892 }
1893
internal_pollin_handler_app(wifi_handle handle,struct ctrl_sock * sock)1894 static int internal_pollin_handler_app(wifi_handle handle, struct ctrl_sock *sock)
1895 {
1896 int retval = -1;
1897 int res;
1898 struct sockaddr_un from;
1899 socklen_t fromlen = sizeof(from);
1900 wifihal_ctrl_req_t *ctrl_msg;
1901 wifihal_ctrl_sync_rsp_t ctrl_reply;
1902
1903 ctrl_msg = (wifihal_ctrl_req_t *)malloc(DEFAULT_PAGE_SIZE);
1904 if(ctrl_msg == NULL)
1905 {
1906 ALOGE ("Memory allocation failure");
1907 return -1;
1908 }
1909
1910 memset((char *)ctrl_msg, 0, DEFAULT_PAGE_SIZE);
1911
1912 res = recvfrom(sock->s, (char *)ctrl_msg, DEFAULT_PAGE_SIZE, 0,
1913 (struct sockaddr *)&from, &fromlen);
1914 if (res < 0) {
1915 ALOGE("recvfrom(ctrl_iface): %s",
1916 strerror(errno));
1917 if(ctrl_msg)
1918 free(ctrl_msg);
1919
1920 return 0;
1921 }
1922 switch(ctrl_msg->ctrl_cmd)
1923 {
1924 case WIFIHAL_CTRL_MONITOR_ATTACH:
1925 retval = attach_monitor_sock(handle, ctrl_msg);
1926 break;
1927 case WIFIHAL_CTRL_MONITOR_DETTACH:
1928 retval = dettach_monitor_sock(handle, ctrl_msg);
1929 break;
1930 case WIFIHAL_CTRL_SEND_NL_DATA:
1931 retval = send_nl_data(handle, ctrl_msg);
1932 break;
1933 default:
1934 break;
1935 }
1936
1937 ctrl_reply.ctrl_cmd = ctrl_msg->ctrl_cmd;
1938 ctrl_reply.family_name = ctrl_msg->family_name;
1939 ctrl_reply.cmd_id = ctrl_msg->cmd_id;
1940 ctrl_reply.status = retval;
1941
1942 if(ctrl_msg)
1943 free(ctrl_msg);
1944
1945 if (sendto(sock->s, (char *)&ctrl_reply, sizeof(ctrl_reply), 0, (struct sockaddr *)&from,
1946 fromlen) < 0) {
1947 int _errno = errno;
1948 ALOGE("socket send failed : %d",_errno);
1949
1950 if (_errno == ENOBUFS || _errno == EAGAIN) {
1951 /*
1952 * The socket send buffer could be full. This
1953 * may happen if client programs are not
1954 * receiving their pending messages. Close and
1955 * reopen the socket as a workaround to avoid
1956 * getting stuck being unable to send any new
1957 * responses.
1958 */
1959 }
1960 }
1961 return res;
1962 }
1963
internal_pollin_handler(wifi_handle handle,struct nl_sock * sock)1964 static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock)
1965 {
1966 struct nl_cb *cb = nl_socket_get_cb(sock);
1967
1968 int res = nl_recvmsgs(sock, cb);
1969 if(res)
1970 ALOGE("Error :%d while reading nl msg", res);
1971 nl_cb_put(cb);
1972 return res;
1973 }
1974
internal_event_handler_app(wifi_handle handle,int events,struct ctrl_sock * sock)1975 static void internal_event_handler_app(wifi_handle handle, int events,
1976 struct ctrl_sock *sock)
1977 {
1978 if (events & POLLERR) {
1979 ALOGE("Error reading from wifi_hal ctrl socket");
1980 internal_pollin_handler_app(handle, sock);
1981 } else if (events & POLLHUP) {
1982 ALOGE("Remote side hung up");
1983 } else if (events & POLLIN) {
1984 //ALOGI("Found some events!!!");
1985 internal_pollin_handler_app(handle, sock);
1986 } else {
1987 ALOGE("Unknown event - %0x", events);
1988 }
1989 }
1990
internal_event_handler(wifi_handle handle,int events,struct nl_sock * sock)1991 static void internal_event_handler(wifi_handle handle, int events,
1992 struct nl_sock *sock)
1993 {
1994 if (events & POLLERR) {
1995 ALOGE("Error reading from socket");
1996 internal_pollin_handler(handle, sock);
1997 } else if (events & POLLHUP) {
1998 ALOGE("Remote side hung up");
1999 } else if (events & POLLIN) {
2000 //ALOGI("Found some events!!!");
2001 internal_pollin_handler(handle, sock);
2002 } else {
2003 ALOGE("Unknown event - %0x", events);
2004 }
2005 }
2006
2007 /* Run event handler */
wifi_event_loop(wifi_handle handle)2008 void wifi_event_loop(wifi_handle handle)
2009 {
2010 hal_info *info = getHalInfo(handle);
2011 if (info->in_event_loop) {
2012 return;
2013 } else {
2014 info->in_event_loop = true;
2015 }
2016
2017 pollfd pfd[4];
2018 memset(&pfd, 0, 4*sizeof(pfd[0]));
2019
2020 pfd[0].fd = nl_socket_get_fd(info->event_sock);
2021 pfd[0].events = POLLIN;
2022
2023 pfd[1].fd = nl_socket_get_fd(info->user_sock);
2024 pfd[1].events = POLLIN;
2025
2026 pfd[2].fd = info->exit_sockets[1];
2027 pfd[2].events = POLLIN;
2028
2029 if(info->wifihal_ctrl_sock.s > 0) {
2030 pfd[3].fd = info->wifihal_ctrl_sock.s ;
2031 pfd[3].events = POLLIN;
2032 }
2033 /* TODO: Add support for timeouts */
2034
2035 do {
2036 pfd[0].revents = 0;
2037 pfd[1].revents = 0;
2038 pfd[2].revents = 0;
2039 pfd[3].revents = 0;
2040 //ALOGI("Polling sockets");
2041 int result = poll(pfd, 4, -1);
2042 if (result < 0) {
2043 ALOGE("Error polling socket");
2044 } else {
2045 if (pfd[0].revents & (POLLIN | POLLHUP | POLLERR)) {
2046 internal_event_handler(handle, pfd[0].revents, info->event_sock);
2047 }
2048 if (pfd[1].revents & (POLLIN | POLLHUP | POLLERR)) {
2049 internal_event_handler(handle, pfd[1].revents, info->user_sock);
2050 }
2051 if ((info->wifihal_ctrl_sock.s > 0) && (pfd[3].revents & (POLLIN | POLLHUP | POLLERR))) {
2052 internal_event_handler_app(handle, pfd[3].revents, &info->wifihal_ctrl_sock);
2053 }
2054 }
2055 rb_timerhandler(info);
2056 } while (!info->clean_up);
2057 internal_cleaned_up_handler(handle);
2058 }
2059
user_sock_message_handler(nl_msg * msg,void * arg)2060 static int user_sock_message_handler(nl_msg *msg, void *arg)
2061 {
2062 wifi_handle handle = (wifi_handle)arg;
2063 hal_info *info = getHalInfo(handle);
2064
2065 diag_message_handler(info, msg);
2066
2067 return NL_OK;
2068 }
2069
internal_valid_message_handler(nl_msg * msg,void * arg)2070 static int internal_valid_message_handler(nl_msg *msg, void *arg)
2071 {
2072 wifi_handle handle = (wifi_handle)arg;
2073 hal_info *info = getHalInfo(handle);
2074
2075 WifiEvent event(msg);
2076 int res = event.parse();
2077 if (res < 0) {
2078 ALOGE("Failed to parse event: %d", res);
2079 return NL_SKIP;
2080 }
2081
2082 int cmd = event.get_cmd();
2083 uint32_t vendor_id = 0;
2084 int subcmd = 0;
2085
2086 if (cmd == NL80211_CMD_VENDOR) {
2087 vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
2088 subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
2089 /* Restrict printing GSCAN_FULL_RESULT which is causing lot
2090 of logs in bug report */
2091 if (subcmd != QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT) {
2092 ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
2093 event.get_cmdString(), vendor_id, subcmd);
2094 }
2095 }
2096 else if((info->wifihal_ctrl_sock.s > 0) && (cmd == NL80211_CMD_FRAME))
2097 {
2098 struct genlmsghdr *genlh;
2099 struct nlmsghdr *nlh = nlmsg_hdr(msg);
2100 genlh = (struct genlmsghdr *)nlmsg_data(nlh);
2101 struct nlattr *nlattrs[NL80211_ATTR_MAX + 1];
2102
2103 wifihal_ctrl_event_t *ctrl_evt;
2104 char *buff;
2105 wifihal_mon_sock_t *reg;
2106
2107 nla_parse(nlattrs, NL80211_ATTR_MAX, genlmsg_attrdata(genlh, 0),
2108 genlmsg_attrlen(genlh, 0), NULL);
2109
2110 if (!nlattrs[NL80211_ATTR_FRAME])
2111 {
2112 ALOGD("No Frame body");
2113 return WIFI_SUCCESS;
2114 }
2115 ctrl_evt = (wifihal_ctrl_event_t *)malloc(sizeof(*ctrl_evt) + nlh->nlmsg_len);
2116 if(ctrl_evt == NULL)
2117 {
2118 ALOGE("Memory allocation failure");
2119 return -1;
2120 }
2121 memset((char *)ctrl_evt, 0, sizeof(*ctrl_evt) + nlh->nlmsg_len);
2122 ctrl_evt->family_name = GENERIC_NL_FAMILY;
2123 ctrl_evt->cmd_id = cmd;
2124 ctrl_evt->data_len = nlh->nlmsg_len;
2125 memcpy(ctrl_evt->data, (char *)nlh, ctrl_evt->data_len);
2126
2127
2128 buff = (char *)nla_data(nlattrs[NL80211_ATTR_FRAME]) + 24; //! Size of Wlan80211FrameHeader
2129
2130 list_for_each_entry(reg, &info->monitor_sockets, list) {
2131
2132 if(reg == NULL)
2133 break;
2134
2135 if (memcmp(reg->match, buff, reg->match_len))
2136 continue;
2137
2138 /* found match! */
2139 /* Indicate the received Action frame to respective client */
2140 if (sendto(info->wifihal_ctrl_sock.s, (char *)ctrl_evt,
2141 sizeof(*ctrl_evt) + ctrl_evt->data_len,
2142 0, (struct sockaddr *)®->monsock, reg->monsock_len) < 0)
2143 {
2144 int _errno = errno;
2145 ALOGE("socket send failed : %d",_errno);
2146
2147 if (_errno == ENOBUFS || _errno == EAGAIN) {
2148 }
2149 }
2150
2151 }
2152 free(ctrl_evt);
2153 }
2154
2155 else {
2156 ALOGV("event received %s", event.get_cmdString());
2157 }
2158
2159 // event.log();
2160
2161 bool dispatched = false;
2162
2163 pthread_mutex_lock(&info->cb_lock);
2164
2165 for (int i = 0; i < info->num_event_cb; i++) {
2166 if (cmd == info->event_cb[i].nl_cmd) {
2167 if (cmd == NL80211_CMD_VENDOR
2168 && ((vendor_id != info->event_cb[i].vendor_id)
2169 || (subcmd != info->event_cb[i].vendor_subcmd)))
2170 {
2171 /* event for a different vendor, ignore it */
2172 continue;
2173 }
2174
2175 cb_info *cbi = &(info->event_cb[i]);
2176 pthread_mutex_unlock(&info->cb_lock);
2177 if (cbi->cb_func) {
2178 (*(cbi->cb_func))(msg, cbi->cb_arg);
2179 dispatched = true;
2180 }
2181 return NL_OK;
2182 }
2183 }
2184
2185 #ifdef QC_HAL_DEBUG
2186 if (!dispatched) {
2187 ALOGI("event ignored!!");
2188 }
2189 #endif
2190
2191 pthread_mutex_unlock(&info->cb_lock);
2192 return NL_OK;
2193 }
2194
2195 ////////////////////////////////////////////////////////////////////////////////
2196
2197 class GetMulticastIdCommand : public WifiCommand
2198 {
2199 private:
2200 const char *mName;
2201 const char *mGroup;
2202 int mId;
2203 public:
GetMulticastIdCommand(wifi_handle handle,const char * name,const char * group)2204 GetMulticastIdCommand(wifi_handle handle, const char *name,
2205 const char *group) : WifiCommand(handle, 0)
2206 {
2207 mName = name;
2208 mGroup = group;
2209 mId = -1;
2210 }
2211
getId()2212 int getId() {
2213 return mId;
2214 }
2215
create()2216 virtual wifi_error create() {
2217 int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
2218 // ALOGI("ctrl family = %d", nlctrlFamily);
2219 wifi_error ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
2220 if (ret != WIFI_SUCCESS)
2221 return ret;
2222
2223 ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
2224 return ret;
2225 }
2226
handleResponse(WifiEvent & reply)2227 virtual int handleResponse(WifiEvent& reply) {
2228
2229 // ALOGI("handling reponse in %s", __func__);
2230
2231 struct nlattr **tb = reply.attributes();
2232 struct nlattr *mcgrp = NULL;
2233 int i;
2234
2235 if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
2236 ALOGI("No multicast groups found");
2237 return NL_SKIP;
2238 } else {
2239 // ALOGI("Multicast groups attr size = %d",
2240 // nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
2241 }
2242
2243 for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
2244
2245 // ALOGI("Processing group");
2246 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
2247 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
2248 nla_len(mcgrp), NULL);
2249 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID])
2250 {
2251 continue;
2252 }
2253
2254 char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
2255 int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
2256
2257 // ALOGI("Found group name %s", grpName);
2258
2259 if (strncmp(grpName, mGroup, grpNameLen) != 0)
2260 continue;
2261
2262 mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
2263 break;
2264 }
2265
2266 return NL_SKIP;
2267 }
2268
2269 };
2270
wifi_get_multicast_id(wifi_handle handle,const char * name,const char * group)2271 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
2272 const char *group)
2273 {
2274 GetMulticastIdCommand cmd(handle, name, group);
2275 int res = cmd.requestResponse();
2276 if (res < 0)
2277 return res;
2278 else
2279 return cmd.getId();
2280 }
2281
2282 /////////////////////////////////////////////////////////////////////////
2283
is_wifi_interface(const char * name)2284 static bool is_wifi_interface(const char *name)
2285 {
2286 if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0
2287 && strncmp(name, "wifi", 4) != 0) {
2288 /* not a wifi interface; ignore it */
2289 return false;
2290 } else {
2291 return true;
2292 }
2293 }
2294
get_interface(const char * name,interface_info * info)2295 static int get_interface(const char *name, interface_info *info)
2296 {
2297 strlcpy(info->name, name, (IFNAMSIZ + 1));
2298 info->id = if_nametoindex(name);
2299 // ALOGI("found an interface : %s, id = %d", name, info->id);
2300 return WIFI_SUCCESS;
2301 }
2302
wifi_init_interfaces(wifi_handle handle)2303 wifi_error wifi_init_interfaces(wifi_handle handle)
2304 {
2305 hal_info *info = (hal_info *)handle;
2306
2307 struct dirent *de;
2308
2309 DIR *d = opendir("/sys/class/net");
2310 if (d == 0)
2311 return WIFI_ERROR_UNKNOWN;
2312
2313 int n = 0;
2314 while ((de = readdir(d))) {
2315 if (de->d_name[0] == '.')
2316 continue;
2317 if (is_wifi_interface(de->d_name) ) {
2318 n++;
2319 }
2320 }
2321
2322 closedir(d);
2323
2324 d = opendir("/sys/class/net");
2325 if (d == 0)
2326 return WIFI_ERROR_UNKNOWN;
2327
2328 info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
2329 if (info->interfaces == NULL) {
2330 ALOGE("%s: Error info->interfaces NULL", __func__);
2331 return WIFI_ERROR_OUT_OF_MEMORY;
2332 }
2333
2334 int i = 0;
2335 while ((de = readdir(d))) {
2336 if (de->d_name[0] == '.')
2337 continue;
2338 if (is_wifi_interface(de->d_name)) {
2339 interface_info *ifinfo
2340 = (interface_info *)malloc(sizeof(interface_info));
2341 if (ifinfo == NULL) {
2342 ALOGE("%s: Error ifinfo NULL", __func__);
2343 while (i > 0) {
2344 free(info->interfaces[i-1]);
2345 i--;
2346 }
2347 free(info->interfaces);
2348 return WIFI_ERROR_OUT_OF_MEMORY;
2349 }
2350 if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
2351 free(ifinfo);
2352 continue;
2353 }
2354 ifinfo->handle = handle;
2355 info->interfaces[i] = ifinfo;
2356 i++;
2357 }
2358 }
2359
2360 closedir(d);
2361
2362 info->num_interfaces = n;
2363
2364 return WIFI_SUCCESS;
2365 }
2366
wifi_get_ifaces(wifi_handle handle,int * num,wifi_interface_handle ** interfaces)2367 wifi_error wifi_get_ifaces(wifi_handle handle, int *num,
2368 wifi_interface_handle **interfaces)
2369 {
2370 hal_info *info = (hal_info *)handle;
2371
2372 /* In case of dynamic interface add/remove, interface handles need to be
2373 * updated so that, interface specific APIs could be instantiated.
2374 * Reload here to get interfaces which are dynamically added. */
2375
2376 if (info->num_interfaces > 0) {
2377 for (int i = 0; i < info->num_interfaces; i++)
2378 free(info->interfaces[i]);
2379 free(info->interfaces);
2380 info->interfaces = NULL;
2381 info->num_interfaces = 0;
2382 }
2383
2384 wifi_error ret = wifi_init_interfaces(handle);
2385 if (ret != WIFI_SUCCESS) {
2386 ALOGE("Failed to init interfaces while wifi_get_ifaces");
2387 return ret;
2388 }
2389
2390 *interfaces = (wifi_interface_handle *)info->interfaces;
2391 *num = info->num_interfaces;
2392
2393 return WIFI_SUCCESS;
2394 }
2395
wifi_get_iface_name(wifi_interface_handle handle,char * name,size_t size)2396 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name,
2397 size_t size)
2398 {
2399 interface_info *info = (interface_info *)handle;
2400 strlcpy(name, info->name, size);
2401 return WIFI_SUCCESS;
2402 }
2403
2404 /* Get the supported Feature set */
wifi_get_supported_feature_set(wifi_interface_handle iface,feature_set * set)2405 wifi_error wifi_get_supported_feature_set(wifi_interface_handle iface,
2406 feature_set *set)
2407 {
2408 int ret = 0;
2409 wifi_handle handle = getWifiHandle(iface);
2410 *set = 0;
2411 hal_info *info = getHalInfo(handle);
2412
2413 ret = acquire_supported_features(iface, set);
2414 if (ret != WIFI_SUCCESS) {
2415 *set = info->supported_feature_set;
2416 ALOGV("Supported feature set acquired at initialization : 0x%" PRIx64, *set);
2417 } else {
2418 info->supported_feature_set = *set;
2419 ALOGV("Supported feature set acquired : 0x%" PRIx64, *set);
2420 }
2421 return WIFI_SUCCESS;
2422 }
2423
wifi_get_concurrency_matrix(wifi_interface_handle handle,int set_size_max,feature_set set[],int * set_size)2424 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle,
2425 int set_size_max,
2426 feature_set set[], int *set_size)
2427 {
2428 wifi_error ret;
2429 struct nlattr *nlData;
2430 WifihalGeneric *vCommand = NULL;
2431 interface_info *ifaceInfo = getIfaceInfo(handle);
2432 wifi_handle wifiHandle = getWifiHandle(handle);
2433
2434 if (set == NULL) {
2435 ALOGE("%s: NULL set pointer provided. Exit.",
2436 __func__);
2437 return WIFI_ERROR_INVALID_ARGS;
2438 }
2439
2440 vCommand = new WifihalGeneric(wifiHandle, 0,
2441 OUI_QCA,
2442 QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX);
2443 if (vCommand == NULL) {
2444 ALOGE("%s: Error vCommand NULL", __func__);
2445 return WIFI_ERROR_OUT_OF_MEMORY;
2446 }
2447
2448 /* Create the message */
2449 ret = vCommand->create();
2450 if (ret != WIFI_SUCCESS)
2451 goto cleanup;
2452
2453 ret = vCommand->set_iface_id(ifaceInfo->name);
2454 if (ret != WIFI_SUCCESS)
2455 goto cleanup;
2456
2457 /* Add the vendor specific attributes for the NL command. */
2458 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2459 if (!nlData)
2460 goto cleanup;
2461
2462 ret = vCommand->put_u32(
2463 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX,
2464 set_size_max);
2465 if (ret != WIFI_SUCCESS)
2466 goto cleanup;
2467
2468 vCommand->attr_end(nlData);
2469
2470 /* Populate the input received from caller/framework. */
2471 vCommand->setMaxSetSize(set_size_max);
2472 vCommand->setSizePtr(set_size);
2473 vCommand->setConcurrencySet(set);
2474
2475 ret = vCommand->requestResponse();
2476 if (ret != WIFI_SUCCESS)
2477 ALOGE("%s: requestResponse() error: %d", __func__, ret);
2478
2479 cleanup:
2480 delete vCommand;
2481 if (ret)
2482 *set_size = 0;
2483 return ret;
2484 }
2485
2486
wifi_set_nodfs_flag(wifi_interface_handle handle,u32 nodfs)2487 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
2488 {
2489 wifi_error ret;
2490 struct nlattr *nlData;
2491 WifiVendorCommand *vCommand = NULL;
2492 interface_info *ifaceInfo = getIfaceInfo(handle);
2493 wifi_handle wifiHandle = getWifiHandle(handle);
2494
2495 vCommand = new WifiVendorCommand(wifiHandle, 0,
2496 OUI_QCA,
2497 QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG);
2498 if (vCommand == NULL) {
2499 ALOGE("%s: Error vCommand NULL", __func__);
2500 return WIFI_ERROR_OUT_OF_MEMORY;
2501 }
2502
2503 /* Create the message */
2504 ret = vCommand->create();
2505 if (ret != WIFI_SUCCESS)
2506 goto cleanup;
2507
2508 ret = vCommand->set_iface_id(ifaceInfo->name);
2509 if (ret != WIFI_SUCCESS)
2510 goto cleanup;
2511
2512 /* Add the vendor specific attributes for the NL command. */
2513 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2514 if (!nlData)
2515 goto cleanup;
2516
2517 /* Add the fixed part of the mac_oui to the nl command */
2518 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG, nodfs);
2519 if (ret != WIFI_SUCCESS)
2520 goto cleanup;
2521
2522 vCommand->attr_end(nlData);
2523
2524 ret = vCommand->requestResponse();
2525 /* Don't check response since we aren't expecting one */
2526
2527 cleanup:
2528 delete vCommand;
2529 return ret;
2530 }
2531
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)2532 wifi_error wifi_start_sending_offloaded_packet(wifi_request_id id,
2533 wifi_interface_handle iface,
2534 u16 ether_type,
2535 u8 *ip_packet,
2536 u16 ip_packet_len,
2537 u8 *src_mac_addr,
2538 u8 *dst_mac_addr,
2539 u32 period_msec)
2540 {
2541 wifi_error ret;
2542 struct nlattr *nlData;
2543 WifiVendorCommand *vCommand = NULL;
2544
2545 ret = initialize_vendor_cmd(iface, id,
2546 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
2547 &vCommand);
2548 if (ret != WIFI_SUCCESS) {
2549 ALOGE("%s: Initialization failed", __func__);
2550 return ret;
2551 }
2552
2553 ALOGV("ether type 0x%04x\n", ether_type);
2554 ALOGV("ip packet length : %u\nIP Packet:", ip_packet_len);
2555 hexdump(ip_packet, ip_packet_len);
2556 ALOGV("Src Mac Address: " MAC_ADDR_STR "\nDst Mac Address: " MAC_ADDR_STR
2557 "\nPeriod in msec : %u", MAC_ADDR_ARRAY(src_mac_addr),
2558 MAC_ADDR_ARRAY(dst_mac_addr), period_msec);
2559
2560 /* Add the vendor specific attributes for the NL command. */
2561 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2562 if (!nlData)
2563 goto cleanup;
2564
2565 ret = vCommand->put_u32(
2566 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
2567 QCA_WLAN_OFFLOADED_PACKETS_SENDING_START);
2568 if (ret != WIFI_SUCCESS)
2569 goto cleanup;
2570
2571 ret = vCommand->put_u32(
2572 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
2573 id);
2574 if (ret != WIFI_SUCCESS)
2575 goto cleanup;
2576
2577 ret = vCommand->put_u16(
2578 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_ETHER_PROTO_TYPE,
2579 ether_type);
2580 if (ret != WIFI_SUCCESS)
2581 goto cleanup;
2582
2583 ret = vCommand->put_bytes(
2584 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA,
2585 (const char *)ip_packet, ip_packet_len);
2586 if (ret != WIFI_SUCCESS)
2587 goto cleanup;
2588
2589 ret = vCommand->put_addr(
2590 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR,
2591 src_mac_addr);
2592 if (ret != WIFI_SUCCESS)
2593 goto cleanup;
2594
2595 ret = vCommand->put_addr(
2596 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR,
2597 dst_mac_addr);
2598 if (ret != WIFI_SUCCESS)
2599 goto cleanup;
2600
2601 ret = vCommand->put_u32(
2602 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD,
2603 period_msec);
2604 if (ret != WIFI_SUCCESS)
2605 goto cleanup;
2606
2607 vCommand->attr_end(nlData);
2608
2609 ret = vCommand->requestResponse();
2610 if (ret != WIFI_SUCCESS)
2611 goto cleanup;
2612
2613 cleanup:
2614 delete vCommand;
2615 return ret;
2616 }
2617
wifi_stop_sending_offloaded_packet(wifi_request_id id,wifi_interface_handle iface)2618 wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id id,
2619 wifi_interface_handle iface)
2620 {
2621 wifi_error ret;
2622 struct nlattr *nlData;
2623 WifiVendorCommand *vCommand = NULL;
2624
2625 ret = initialize_vendor_cmd(iface, id,
2626 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
2627 &vCommand);
2628 if (ret != WIFI_SUCCESS) {
2629 ALOGE("%s: Initialization failed", __func__);
2630 return ret;
2631 }
2632
2633 /* Add the vendor specific attributes for the NL command. */
2634 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2635 if (!nlData)
2636 goto cleanup;
2637
2638 ret = vCommand->put_u32(
2639 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
2640 QCA_WLAN_OFFLOADED_PACKETS_SENDING_STOP);
2641 if (ret != WIFI_SUCCESS)
2642 goto cleanup;
2643
2644 ret = vCommand->put_u32(
2645 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
2646 id);
2647 if (ret != WIFI_SUCCESS)
2648 goto cleanup;
2649
2650 vCommand->attr_end(nlData);
2651
2652 ret = vCommand->requestResponse();
2653 if (ret != WIFI_SUCCESS)
2654 goto cleanup;
2655
2656 cleanup:
2657 delete vCommand;
2658 return ret;
2659 }
2660
2661 #define PACKET_FILTER_ID 0
2662
wifi_set_packet_filter(wifi_interface_handle iface,const u8 * program,u32 len)2663 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
2664 const u8 *program, u32 len)
2665 {
2666 wifi_error ret;
2667 struct nlattr *nlData;
2668 WifiVendorCommand *vCommand = NULL;
2669 u32 current_offset = 0;
2670 wifi_handle wifiHandle = getWifiHandle(iface);
2671 hal_info *info = getHalInfo(wifiHandle);
2672
2673 /* len=0 clears the filters in driver/firmware */
2674 if (len != 0 && program == NULL) {
2675 ALOGE("%s: No valid program provided. Exit.",
2676 __func__);
2677 return WIFI_ERROR_INVALID_ARGS;
2678 }
2679
2680 do {
2681 ret = initialize_vendor_cmd(iface, get_requestid(),
2682 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
2683 &vCommand);
2684 if (ret != WIFI_SUCCESS) {
2685 ALOGE("%s: Initialization failed", __FUNCTION__);
2686 return ret;
2687 }
2688
2689 /* Add the vendor specific attributes for the NL command. */
2690 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2691 if (!nlData)
2692 goto cleanup;
2693
2694 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2695 QCA_WLAN_SET_PACKET_FILTER);
2696 if (ret != WIFI_SUCCESS)
2697 goto cleanup;
2698 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
2699 PACKET_FILTER_ID);
2700 if (ret != WIFI_SUCCESS)
2701 goto cleanup;
2702 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE,
2703 len);
2704 if (ret != WIFI_SUCCESS)
2705 goto cleanup;
2706 ret = vCommand->put_u32(
2707 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
2708 current_offset);
2709 if (ret != WIFI_SUCCESS)
2710 goto cleanup;
2711
2712 if (len) {
2713 ret = vCommand->put_bytes(
2714 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
2715 (char *)&program[current_offset],
2716 min(info->firmware_bus_max_size,
2717 len-current_offset));
2718 if (ret!= WIFI_SUCCESS) {
2719 ALOGE("%s: failed to put program", __FUNCTION__);
2720 goto cleanup;
2721 }
2722 }
2723
2724 vCommand->attr_end(nlData);
2725
2726 ret = vCommand->requestResponse();
2727 if (ret != WIFI_SUCCESS) {
2728 ALOGE("%s: requestResponse Error:%d",__func__, ret);
2729 goto cleanup;
2730 }
2731
2732 /* destroy the object after sending each fragment to driver */
2733 delete vCommand;
2734 vCommand = NULL;
2735
2736 current_offset += min(info->firmware_bus_max_size, len);
2737 } while (current_offset < len);
2738
2739 info->apf_enabled = !!len;
2740
2741 cleanup:
2742 if (vCommand)
2743 delete vCommand;
2744 return ret;
2745 }
2746
wifi_get_packet_filter_capabilities(wifi_interface_handle handle,u32 * version,u32 * max_len)2747 static wifi_error wifi_get_packet_filter_capabilities(
2748 wifi_interface_handle handle, u32 *version, u32 *max_len)
2749 {
2750 wifi_error ret;
2751 struct nlattr *nlData;
2752 WifihalGeneric *vCommand = NULL;
2753 interface_info *ifaceInfo = getIfaceInfo(handle);
2754 wifi_handle wifiHandle = getWifiHandle(handle);
2755
2756 if (version == NULL || max_len == NULL) {
2757 ALOGE("%s: NULL version/max_len pointer provided. Exit.",
2758 __FUNCTION__);
2759 return WIFI_ERROR_INVALID_ARGS;
2760 }
2761
2762 vCommand = new WifihalGeneric(wifiHandle, 0,
2763 OUI_QCA,
2764 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
2765 if (vCommand == NULL) {
2766 ALOGE("%s: Error vCommand NULL", __FUNCTION__);
2767 return WIFI_ERROR_OUT_OF_MEMORY;
2768 }
2769
2770 /* Create the message */
2771 ret = vCommand->create();
2772 if (ret != WIFI_SUCCESS)
2773 goto cleanup;
2774
2775 ret = vCommand->set_iface_id(ifaceInfo->name);
2776 if (ret != WIFI_SUCCESS)
2777 goto cleanup;
2778
2779 /* Add the vendor specific attributes for the NL command. */
2780 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2781 if (!nlData)
2782 goto cleanup;
2783
2784 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2785 QCA_WLAN_GET_PACKET_FILTER);
2786 if (ret != WIFI_SUCCESS)
2787 goto cleanup;
2788
2789 vCommand->attr_end(nlData);
2790
2791 ret = vCommand->requestResponse();
2792 if (ret != WIFI_SUCCESS) {
2793 ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
2794 if (ret == WIFI_ERROR_NOT_SUPPORTED) {
2795 /* Packet filtering is not supported currently, so return version
2796 * and length as 0
2797 */
2798 ALOGI("Packet filtering is not supprted");
2799 *version = 0;
2800 *max_len = 0;
2801 ret = WIFI_SUCCESS;
2802 }
2803 goto cleanup;
2804 }
2805
2806 *version = vCommand->getFilterVersion();
2807 *max_len = vCommand->getFilterLength();
2808 cleanup:
2809 delete vCommand;
2810 return ret;
2811 }
2812
2813
wifi_configure_nd_offload(wifi_interface_handle iface,u8 enable)2814 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
2815 u8 enable)
2816 {
2817 wifi_error ret;
2818 struct nlattr *nlData;
2819 WifiVendorCommand *vCommand = NULL;
2820
2821 ret = initialize_vendor_cmd(iface, get_requestid(),
2822 QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
2823 &vCommand);
2824 if (ret != WIFI_SUCCESS) {
2825 ALOGE("%s: Initialization failed", __func__);
2826 return ret;
2827 }
2828
2829 ALOGV("ND offload : %s", enable?"Enable":"Disable");
2830
2831 /* Add the vendor specific attributes for the NL command. */
2832 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2833 if (!nlData)
2834 goto cleanup;
2835
2836 ret = vCommand->put_u8(QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG, enable);
2837 if (ret != WIFI_SUCCESS)
2838 goto cleanup;
2839
2840 vCommand->attr_end(nlData);
2841
2842 ret = vCommand->requestResponse();
2843
2844 cleanup:
2845 delete vCommand;
2846 return ret;
2847 }
2848
2849 /**
2850 * Copy 'len' bytes of raw data from host memory at source address 'program'
2851 * to APF (Android Packet Filter) working memory starting at offset 'dst_offset'.
2852 * The size of the program lenght passed to the interpreter is set to
2853 * 'progaram_lenght'
2854 *
2855 * The implementation is allowed to tranlate this wrtie into a series of smaller
2856 * writes,but this function is not allowed to return untill all write operations
2857 * have been completed
2858 * additionally visible memory not targeted by this function must remain
2859 * unchanged
2860
2861 * @param dst_offset write offset in bytes relative to the beginning of the APF
2862 * working memory with logical address 0X000. Must be a multiple of 4
2863 *
2864 * @param program host memory to copy bytes from. Must be 4B aligned
2865 *
2866 * @param len the number of bytes to copy from the bost into the APF working
2867 * memory
2868 *
2869 * @param program_length new length of the program instructions in bytes to pass
2870 * to the interpreter
2871 */
2872
wifi_write_packet_filter(wifi_interface_handle iface,u32 dst_offset,const u8 * program,u32 len,u32 program_length)2873 wifi_error wifi_write_packet_filter(wifi_interface_handle iface,
2874 u32 dst_offset, const u8 *program,
2875 u32 len, u32 program_length)
2876 {
2877 wifi_error ret;
2878 struct nlattr *nlData;
2879 WifiVendorCommand *vCommand = NULL;
2880 u32 current_offset = 0;
2881 wifi_handle wifiHandle = getWifiHandle(iface);
2882 hal_info *info = getHalInfo(wifiHandle);
2883
2884 /* len=0 clears the filters in driver/firmware */
2885 if (len != 0 && program == NULL) {
2886 ALOGE("%s: No valid program provided. Exit.",
2887 __func__);
2888 return WIFI_ERROR_INVALID_ARGS;
2889 }
2890
2891 do {
2892 ret = initialize_vendor_cmd(iface, get_requestid(),
2893 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
2894 &vCommand);
2895 if (ret != WIFI_SUCCESS) {
2896 ALOGE("%s: Initialization failed", __FUNCTION__);
2897 return ret;
2898 }
2899
2900 /* Add the vendor specific attributes for the NL command. */
2901 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2902 if (!nlData)
2903 goto cleanup;
2904
2905 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2906 QCA_WLAN_WRITE_PACKET_FILTER);
2907 if (ret != WIFI_SUCCESS)
2908 goto cleanup;
2909 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
2910 PACKET_FILTER_ID);
2911 if (ret != WIFI_SUCCESS)
2912 goto cleanup;
2913 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE,
2914 len);
2915 if (ret != WIFI_SUCCESS)
2916 goto cleanup;
2917 ret = vCommand->put_u32(
2918 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
2919 dst_offset + current_offset);
2920 if (ret != WIFI_SUCCESS)
2921 goto cleanup;
2922 ret = vCommand->put_u32(
2923 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROG_LENGTH,
2924 program_length);
2925 if (ret != WIFI_SUCCESS)
2926 goto cleanup;
2927
2928 ret = vCommand->put_bytes(
2929 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
2930 (char *)&program[current_offset],
2931 min(info->firmware_bus_max_size,
2932 len - current_offset));
2933 if (ret!= WIFI_SUCCESS) {
2934 ALOGE("%s: failed to put program", __FUNCTION__);
2935 goto cleanup;
2936 }
2937
2938 vCommand->attr_end(nlData);
2939
2940 ret = vCommand->requestResponse();
2941 if (ret != WIFI_SUCCESS) {
2942 ALOGE("%s: requestResponse Error:%d",__func__, ret);
2943 goto cleanup;
2944 }
2945
2946 /* destroy the object after sending each fragment to driver */
2947 delete vCommand;
2948 vCommand = NULL;
2949
2950 current_offset += min(info->firmware_bus_max_size,
2951 len - current_offset);
2952 } while (current_offset < len);
2953
2954 cleanup:
2955 if (vCommand)
2956 delete vCommand;
2957 return ret;
2958 }
2959
wifi_enable_packet_filter(wifi_interface_handle handle,u32 enable)2960 wifi_error wifi_enable_packet_filter(wifi_interface_handle handle,
2961 u32 enable)
2962 {
2963 wifi_error ret;
2964 struct nlattr *nlData;
2965 WifiVendorCommand *vCommand = NULL;
2966 u32 subcmd;
2967 wifi_handle wifiHandle = getWifiHandle(handle);
2968 hal_info *info = getHalInfo(wifiHandle);
2969
2970 ret = initialize_vendor_cmd(handle, get_requestid(),
2971 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
2972 &vCommand);
2973
2974 if (ret != WIFI_SUCCESS) {
2975 ALOGE("%s: Initialization failed", __func__);
2976 return ret;
2977 }
2978 /* Add the vendor specific attributes for the NL command. */
2979 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2980 if (!nlData)
2981 goto cleanup;
2982
2983 subcmd = enable ? QCA_WLAN_ENABLE_PACKET_FILTER :
2984 QCA_WLAN_DISABLE_PACKET_FILTER;
2985 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2986 subcmd);
2987 if (ret != WIFI_SUCCESS)
2988 goto cleanup;
2989
2990 vCommand->attr_end(nlData);
2991 ret = vCommand->requestResponse();
2992
2993 if (ret != WIFI_SUCCESS) {
2994 ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
2995 goto cleanup;
2996 }
2997
2998 info->apf_enabled = !!enable;
2999
3000 cleanup:
3001 if (vCommand)
3002 delete vCommand;
3003 return ret;
3004
3005 }
3006
3007 /**
3008 * Copy 'length' bytes of raw data from APF (Android Packet Filter) working
3009 * memory to host memory starting at offset src_offset into host memory
3010 * pointed to by host_dst.
3011 * Memory can be text, data or some combination of the two. The implementiion is
3012 * allowed to translate this read into a series of smaller reads, but this
3013 * function is not allowed to return untill all the reads operations
3014 * into host_dst have been completed.
3015 *
3016 * @param src_offset offset in bytes of destination memory within APF working
3017 * memory
3018 *
3019 * @param host_dst host memory to copy into. Must be 4B aligned.
3020 *
3021 * @param length the number of bytes to copy from the APF working memory to the
3022 * host.
3023 */
3024
wifi_read_packet_filter(wifi_interface_handle handle,u32 src_offset,u8 * host_dst,u32 length)3025 static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
3026 u32 src_offset, u8 *host_dst, u32 length)
3027 {
3028 wifi_error ret = WIFI_SUCCESS;
3029 struct nlattr *nlData;
3030 WifihalGeneric *vCommand = NULL;
3031 interface_info *ifaceInfo = getIfaceInfo(handle);
3032 wifi_handle wifiHandle = getWifiHandle(handle);
3033 hal_info *info = getHalInfo(wifiHandle);
3034
3035 /* Length to be passed to this function should be non-zero
3036 * Return invalid argument if length is passed as zero
3037 */
3038 if (length == 0)
3039 return WIFI_ERROR_INVALID_ARGS;
3040
3041 /*Temporary varibles to support the read complete length in chunks */
3042 u8 *temp_host_dst;
3043 u32 remainingLengthToBeRead, currentLength;
3044 u8 apf_locally_disabled = 0;
3045
3046 /*Initializing the temporary variables*/
3047 temp_host_dst = host_dst;
3048 remainingLengthToBeRead = length;
3049
3050 if (info->apf_enabled) {
3051 /* Disable APF only when not disabled by framework before calling
3052 * wifi_read_packet_filter()
3053 */
3054 ret = wifi_enable_packet_filter(handle, 0);
3055 if (ret != WIFI_SUCCESS) {
3056 ALOGE("%s: Failed to disable APF", __FUNCTION__);
3057 return ret;
3058 }
3059 apf_locally_disabled = 1;
3060 }
3061 /**
3062 * Read the complete length in chunks of size less or equal to firmware bus
3063 * max size
3064 */
3065 while (remainingLengthToBeRead)
3066 {
3067 vCommand = new WifihalGeneric(wifiHandle, 0, OUI_QCA,
3068 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
3069
3070 if (vCommand == NULL) {
3071 ALOGE("%s: Error vCommand NULL", __FUNCTION__);
3072 ret = WIFI_ERROR_OUT_OF_MEMORY;
3073 break;
3074 }
3075
3076 /* Create the message */
3077 ret = vCommand->create();
3078 if (ret != WIFI_SUCCESS)
3079 break;
3080 ret = vCommand->set_iface_id(ifaceInfo->name);
3081 if (ret != WIFI_SUCCESS)
3082 break;
3083 /* Add the vendor specific attributes for the NL command. */
3084 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
3085 if (!nlData)
3086 break;
3087 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
3088 QCA_WLAN_READ_PACKET_FILTER);
3089 if (ret != WIFI_SUCCESS)
3090 break;
3091
3092 currentLength = min(remainingLengthToBeRead, info->firmware_bus_max_size);
3093
3094 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE,
3095 currentLength);
3096 if (ret != WIFI_SUCCESS)
3097 break;
3098 ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
3099 src_offset);
3100 if (ret != WIFI_SUCCESS)
3101 break;
3102
3103 vCommand->setPacketBufferParams(temp_host_dst, currentLength);
3104 vCommand->attr_end(nlData);
3105 ret = vCommand->requestResponse();
3106
3107 if (ret != WIFI_SUCCESS) {
3108 ALOGE("%s: requestResponse() error: %d current_len = %u, src_offset = %u",
3109 __FUNCTION__, ret, currentLength, src_offset);
3110 break;
3111 }
3112
3113 remainingLengthToBeRead -= currentLength;
3114 temp_host_dst += currentLength;
3115 src_offset += currentLength;
3116 delete vCommand;
3117 vCommand = NULL;
3118 }
3119
3120 /* Re enable APF only when disabled above within this API */
3121 if (apf_locally_disabled) {
3122 wifi_error status;
3123 status = wifi_enable_packet_filter(handle, 1);
3124 if (status != WIFI_SUCCESS)
3125 ALOGE("%s: Failed to enable APF", __FUNCTION__);
3126 /* Prefer to return read status if read fails */
3127 if (ret == WIFI_SUCCESS)
3128 ret = status;
3129 }
3130
3131 delete vCommand;
3132 return ret;
3133 }
3134
3135 class GetSupportedVendorCmd : public WifiCommand
3136 {
3137 private:
3138 u32 mVendorCmds[256];
3139 int mNumOfVendorCmds;
3140
3141 public:
GetSupportedVendorCmd(wifi_handle handle)3142 GetSupportedVendorCmd(wifi_handle handle) : WifiCommand(handle, 0)
3143 {
3144 mNumOfVendorCmds = 0;
3145 memset(mVendorCmds, 0, 256);
3146 }
3147
create()3148 virtual wifi_error create() {
3149 int nl80211_id = genl_ctrl_resolve(mInfo->cmd_sock, "nl80211");
3150 wifi_error ret = mMsg.create(nl80211_id, NL80211_CMD_GET_WIPHY, NLM_F_DUMP, 0);
3151 mMsg.put_flag(NL80211_ATTR_SPLIT_WIPHY_DUMP);
3152
3153 return ret;
3154 }
3155
requestResponse()3156 virtual wifi_error requestResponse() {
3157 return WifiCommand::requestResponse(mMsg);
3158 }
set_iface_id(const char * name)3159 virtual wifi_error set_iface_id(const char* name) {
3160 unsigned ifindex = if_nametoindex(name);
3161 return mMsg.set_iface_id(ifindex);
3162 }
3163
handleResponse(WifiEvent & reply)3164 virtual int handleResponse(WifiEvent& reply) {
3165 struct nlattr **tb = reply.attributes();
3166
3167 if (tb[NL80211_ATTR_VENDOR_DATA]) {
3168 struct nlattr *nl;
3169 int rem, i = 0;
3170
3171 for_each_attr(nl, tb[NL80211_ATTR_VENDOR_DATA], rem) {
3172 struct nl80211_vendor_cmd_info *vinfo;
3173 if (nla_len(nl) != sizeof(*vinfo)) {
3174 ALOGE("Unexpected vendor data info found in attribute");
3175 continue;
3176 }
3177 vinfo = (struct nl80211_vendor_cmd_info *)nla_data(nl);
3178 if (vinfo->vendor_id == OUI_QCA) {
3179 mVendorCmds[i] = vinfo->subcmd;
3180 i++;
3181 }
3182 }
3183 mNumOfVendorCmds = i;
3184 }
3185 return NL_SKIP;
3186 }
3187
isVendorCmdSupported(u32 cmdId)3188 int isVendorCmdSupported(u32 cmdId) {
3189 int i, ret;
3190
3191 ret = 0;
3192 for (i = 0; i < mNumOfVendorCmds; i++) {
3193 if (cmdId == mVendorCmds[i]) {
3194 ret = 1;
3195 break;
3196 }
3197 }
3198
3199 return ret;
3200 }
3201 };
3202
wifi_is_nan_ext_cmd_supported(wifi_interface_handle iface_handle)3203 static int wifi_is_nan_ext_cmd_supported(wifi_interface_handle iface_handle)
3204 {
3205 wifi_error ret;
3206 wifi_handle handle = getWifiHandle(iface_handle);
3207 interface_info *info = getIfaceInfo(iface_handle);
3208 GetSupportedVendorCmd cmd(handle);
3209
3210 ret = cmd.create();
3211 if (ret != WIFI_SUCCESS) {
3212 ALOGE("%s: create command failed", __func__);
3213 return 0;
3214 }
3215
3216 ret = cmd.set_iface_id(info->name);
3217 if (ret != WIFI_SUCCESS) {
3218 ALOGE("%s: set iface id failed", __func__);
3219 return 0;
3220 }
3221
3222 ret = cmd.requestResponse();
3223 if (ret != WIFI_SUCCESS) {
3224 ALOGE("Failed to query nan_ext command support, ret=%d", ret);
3225 return 0;
3226 } else {
3227 return cmd.isVendorCmdSupported(QCA_NL80211_VENDOR_SUBCMD_NAN_EXT);
3228 }
3229 }
3230