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