1 /* Copyright (c) 2016, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Changes from Qualcomm Innovation Center are provided under the following license:
29 *
30 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted (subject to the limitations in the
34 * disclaimer below) provided that the following conditions are met:
35 *
36 * * Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 *
39 * * Redistributions in binary form must reproduce the above
40 * copyright notice, this list of conditions and the following
41 * disclaimer in the documentation and/or other materials provided
42 * with the distribution.
43 *
44 * * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
45 * contributors may be used to endorse or promote products derived
46 * from this software without specific prior written permission.
47 *
48 * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
49 * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
50 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
51 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
52 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
53 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
54 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
56 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
57 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
58 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
59 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
60 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 */
62
63 #include <netlink/object-api.h>
64 #include <linux/pkt_sched.h>
65 #include <dlfcn.h>
66 #include <dirent.h>
67 #include <string.h>
68 #include "common.h"
69 #include "driver_cmd_nl80211_extn.h"
70
71 #define QCA_NL80211_VENDOR_SUBCMD_DIAG_DATA 201
72 #define MAX_OEM_LIBS 5
73 #define MAX_LIB_NAME_SIZE 30
74 #define CB_SUFFIX "_cb"
75 static wpa_driver_oem_cb_table_t oem_cb_array[MAX_OEM_LIBS + 1];
76
wpa_msg_handler(struct wpa_driver_nl80211_data * drv,char * msg,u32 subcmd)77 void wpa_msg_handler(struct wpa_driver_nl80211_data *drv, char *msg, u32 subcmd) {
78 if (subcmd == QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT) {
79 wpa_msg(drv->ctx, MSG_INFO, "%s", msg);
80 }
81 }
82
wpa_driver_oem_initialize(wpa_driver_oem_cb_table_t ** oem_cb_table)83 int wpa_driver_oem_initialize(wpa_driver_oem_cb_table_t **oem_cb_table)
84 {
85 wpa_driver_oem_get_cb_table_t *get_oem_table;
86 wpa_driver_oem_cb_table_t *oem_cb_table_local;
87 struct dirent *entry;
88 void *oem_handle_n;
89 char cb_sym_name[MAX_LIB_NAME_SIZE], *tmp;
90 DIR *oem_lib_dir;
91 unsigned int lib_n;
92 #ifdef ANDROID
93 #if __WORDSIZE == 64
94 char *oem_lib_path = "/vendor/lib64/";
95 #else
96 char *oem_lib_path = "/vendor/lib/";
97 #endif
98 #else
99 char *oem_lib_path = "/usr/lib/";
100 #endif
101 /* Return the callback table if it is already initialized*/
102 if (*oem_cb_table)
103 return WPA_DRIVER_OEM_STATUS_SUCCESS;
104
105 for (lib_n = 0; lib_n < MAX_OEM_LIBS; lib_n++) {
106 oem_cb_array[lib_n].wpa_driver_driver_cmd_oem_cb = NULL;
107 oem_cb_array[lib_n].wpa_driver_nl80211_driver_oem_event = NULL;
108 oem_cb_array[lib_n].wpa_driver_oem_feature_check_cb = NULL;
109 }
110
111 oem_lib_dir = opendir(oem_lib_path);
112 if (!oem_lib_dir) {
113 wpa_printf(MSG_ERROR, "%s: Unable to open %s", __FUNCTION__, oem_lib_path);
114 return WPA_DRIVER_OEM_STATUS_FAILURE;
115 }
116
117 lib_n = 0;
118 while((entry = readdir(oem_lib_dir)) != NULL) {
119 if (strncmp(entry->d_name, "libwpa_drv_oem", 14))
120 continue;
121
122 wpa_printf(MSG_DEBUG, "%s: Opening lib %s", __FUNCTION__, entry->d_name);
123 oem_handle_n = dlopen(entry->d_name, RTLD_NOW);
124
125 if (!oem_handle_n) {
126 wpa_printf(MSG_ERROR, "%s: Could not load %s", __FUNCTION__, entry->d_name);
127 /* let's not worry much, continue with others */
128 continue;
129 }
130
131 if (strlen(entry->d_name) >= (sizeof(cb_sym_name) - sizeof(CB_SUFFIX))) {
132 wpa_printf(MSG_ERROR, "%s: libname (%s) too lengthy", __FUNCTION__, entry->d_name);
133 continue;
134 }
135
136 os_strlcpy(cb_sym_name, entry->d_name, sizeof(cb_sym_name));
137 tmp = strchr(cb_sym_name, '.');
138 if (!tmp) {
139 wpa_printf(MSG_ERROR, "%s: libname (%s) incorrect?", __FUNCTION__, entry->d_name);
140 continue;
141 }
142
143 os_strlcpy(tmp, CB_SUFFIX, sizeof(CB_SUFFIX));
144 wpa_printf(MSG_DEBUG, "%s: Loading sym %s", __FUNCTION__, cb_sym_name);
145
146 /* Get the lib's function table callback */
147 get_oem_table = (wpa_driver_oem_get_cb_table_t *)dlsym(oem_handle_n,
148 cb_sym_name);
149
150 if (!get_oem_table) {
151 wpa_printf(MSG_ERROR, "%s: Could not get sym table", __FUNCTION__);
152 continue;
153 }
154
155 oem_cb_table_local = get_oem_table();
156
157 oem_cb_array[lib_n].wpa_driver_driver_cmd_oem_cb =
158 oem_cb_table_local->wpa_driver_driver_cmd_oem_cb;
159 oem_cb_array[lib_n].wpa_driver_nl80211_driver_oem_event =
160 oem_cb_table_local->wpa_driver_nl80211_driver_oem_event;
161 oem_cb_array[lib_n].wpa_driver_driver_wpa_msg_oem_cb =
162 oem_cb_table_local->wpa_driver_driver_wpa_msg_oem_cb;
163 oem_cb_array[lib_n].wpa_driver_oem_feature_check_cb =
164 oem_cb_table_local->wpa_driver_oem_feature_check_cb;
165
166 /* Register wpa message callback with the oem library */
167 if(oem_cb_array[lib_n].wpa_driver_driver_wpa_msg_oem_cb) {
168 oem_cb_array[lib_n].wpa_driver_driver_wpa_msg_oem_cb(wpa_msg_handler);
169 }
170
171 lib_n++;
172
173 if (lib_n == MAX_OEM_LIBS) {
174 wpa_printf(MSG_DEBUG, "%s: Exceeded max libs %d", __FUNCTION__, lib_n);
175 break;
176 }
177 }
178
179 oem_cb_array[lib_n].wpa_driver_driver_cmd_oem_cb = NULL;
180 *oem_cb_table = oem_cb_array;
181 wpa_printf(MSG_DEBUG, "%s: OEM lib initialized\n", __func__);
182 closedir(oem_lib_dir);
183
184 return WPA_DRIVER_OEM_STATUS_SUCCESS;
185 }
186