xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/utils/src/wlan_utility.c (revision 6ecd284e5a94a1c96e26d571dd47419ac305990d)
1 /*
2  * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  * DOC: This file contains definition for mandatory legacy API
21  */
22 
23 #include "qdf_str.h"
24 #include "wlan_utility.h"
25 #include <wlan_cmn.h>
26 #include "wlan_osif_priv.h"
27 #include <net/cfg80211.h>
28 #include <qdf_module.h>
29 
30 uint32_t wlan_chan_to_freq(uint8_t chan)
31 {
32 	/* ch 0 - ch 13 */
33 	if (chan < WLAN_24_GHZ_CHANNEL_14)
34 		return WLAN_24_GHZ_BASE_FREQ + chan * WLAN_CHAN_SPACING_5MHZ;
35 	else if (chan == WLAN_24_GHZ_CHANNEL_14)
36 		return WLAN_CHAN_14_FREQ;
37 	else if (chan < WLAN_24_GHZ_CHANNEL_27)
38 		/* ch 15 - ch 26 */
39 		return WLAN_CHAN_15_FREQ +
40 		  (chan - WLAN_24_GHZ_CHANNEL_15) * WLAN_CHAN_SPACING_20MHZ;
41 	else if (chan == WLAN_5_GHZ_CHANNEL_170)
42 		return WLAN_CHAN_170_FREQ;
43 	else
44 		return WLAN_5_GHZ_BASE_FREQ + chan * WLAN_CHAN_SPACING_5MHZ;
45 }
46 
47 bool wlan_is_dsrc_channel(uint16_t center_freq)
48 {
49 	if (center_freq >= 5852 &&
50 	    center_freq <= 5920)
51 		return true;
52 
53 	return false;
54 }
55 
56 uint8_t wlan_freq_to_chan(uint32_t freq)
57 {
58 	uint8_t chan;
59 
60 	if (freq > WLAN_24_GHZ_BASE_FREQ && freq < WLAN_CHAN_14_FREQ)
61 		chan = ((freq - WLAN_24_GHZ_BASE_FREQ) /
62 			WLAN_CHAN_SPACING_5MHZ);
63 	else if (freq == WLAN_CHAN_14_FREQ)
64 		chan = WLAN_24_GHZ_CHANNEL_14;
65 	else if ((freq > WLAN_24_GHZ_BASE_FREQ) &&
66 		(freq < WLAN_5_GHZ_BASE_FREQ))
67 		chan = (((freq - WLAN_CHAN_15_FREQ) /
68 			WLAN_CHAN_SPACING_20MHZ) +
69 			WLAN_24_GHZ_CHANNEL_15);
70 	else
71 		chan = (freq - WLAN_5_GHZ_BASE_FREQ) /
72 			WLAN_CHAN_SPACING_5MHZ;
73 
74 	return chan;
75 }
76 
77 bool wlan_is_ie_valid(const uint8_t *ie, size_t ie_len)
78 {
79 	uint8_t elen;
80 
81 	while (ie_len) {
82 		if (ie_len < 2)
83 			return false;
84 
85 		elen = ie[1];
86 		ie_len -= 2;
87 		ie += 2;
88 		if (elen > ie_len)
89 			return false;
90 
91 		ie_len -= elen;
92 		ie += elen;
93 	}
94 
95 	return true;
96 }
97 
98 static const uint8_t *wlan_get_ie_ptr_from_eid_n_oui(uint8_t eid,
99 						     const uint8_t *oui,
100 						     uint8_t oui_size,
101 						     const uint8_t *ie,
102 						     uint16_t ie_len)
103 {
104 	int32_t left = ie_len;
105 	const uint8_t *ptr = ie;
106 	uint8_t elem_id, elem_len;
107 
108 	while (left >= 2) {
109 		elem_id  = ptr[0];
110 		elem_len = ptr[1];
111 		left -= 2;
112 
113 		if (elem_len > left)
114 			return NULL;
115 
116 		if (eid == elem_id) {
117 			/* if oui is not provide eid match is enough */
118 			if (!oui)
119 				return ptr;
120 
121 			/*
122 			 * if oui is provided and oui_size is more than left
123 			 * bytes, then we cannot have match
124 			 */
125 			if (oui_size > left)
126 				return NULL;
127 
128 			if (qdf_mem_cmp(&ptr[2], oui, oui_size) == 0)
129 				return ptr;
130 		}
131 
132 		left -= elem_len;
133 		ptr += (elem_len + 2);
134 	}
135 
136 	return NULL;
137 }
138 
139 const uint8_t *wlan_get_ie_ptr_from_eid(uint8_t eid,
140 					const uint8_t *ie,
141 					int ie_len)
142 {
143 	return wlan_get_ie_ptr_from_eid_n_oui(eid, NULL, 0, ie, ie_len);
144 }
145 
146 const uint8_t *wlan_get_vendor_ie_ptr_from_oui(const uint8_t *oui,
147 					       uint8_t oui_size,
148 					       const uint8_t *ie,
149 					       uint16_t ie_len)
150 {
151 	return wlan_get_ie_ptr_from_eid_n_oui(WLAN_MAC_EID_VENDOR,
152 					      oui, oui_size, ie, ie_len);
153 }
154 
155 const uint8_t *wlan_get_ext_ie_ptr_from_ext_id(const uint8_t *oui,
156 					       uint8_t oui_size,
157 					       const uint8_t *ie,
158 					       uint16_t ie_len)
159 {
160 	return wlan_get_ie_ptr_from_eid_n_oui(WLAN_MAC_EID_EXT,
161 					      oui, oui_size, ie, ie_len);
162 }
163 
164 bool wlan_is_emulation_platform(uint32_t phy_version)
165 {
166 	if ((phy_version == 0xABC0) || (phy_version == 0xABC1) ||
167 		(phy_version == 0xABC2) || (phy_version == 0xABC3) ||
168 		(phy_version == 0xFFFF) || (phy_version == 0xABCD))
169 		return true;
170 
171 	return false;
172 }
173 
174 uint32_t wlan_get_pdev_id_from_vdev_id(struct wlan_objmgr_psoc *psoc,
175 				      uint8_t vdev_id,
176 				      wlan_objmgr_ref_dbgid dbg_id)
177 {
178 	struct wlan_objmgr_vdev *vdev;
179 	struct wlan_objmgr_pdev *pdev = NULL;
180 	uint32_t pdev_id = WLAN_INVALID_PDEV_ID;
181 
182 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
183 						    vdev_id, dbg_id);
184 
185 	if (vdev) {
186 		pdev = wlan_vdev_get_pdev(vdev);
187 		if (pdev)
188 			pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
189 		wlan_objmgr_vdev_release_ref(vdev, dbg_id);
190 	}
191 
192 	return pdev_id;
193 }
194 qdf_export_symbol(wlan_get_pdev_id_from_vdev_id);
195 
196 static void wlan_util_get_vdev_by_ifname_cb(struct wlan_objmgr_psoc *psoc,
197 					    void *obj, void *arg)
198 {
199 	struct wlan_objmgr_vdev *vdev = obj;
200 	struct wlan_find_vdev_filter *filter = arg;
201 
202 	if (filter->found_vdev)
203 		return;
204 
205 	wlan_vdev_obj_lock(vdev);
206 	if (!qdf_str_cmp(vdev->vdev_nif.osdev->wdev->netdev->name,
207 			 filter->ifname)) {
208 		filter->found_vdev = vdev;
209 	}
210 	wlan_vdev_obj_unlock(vdev);
211 }
212 
213 struct wlan_objmgr_vdev *wlan_util_get_vdev_by_ifname(
214 				struct wlan_objmgr_psoc *psoc, char *ifname,
215 				wlan_objmgr_ref_dbgid ref_id)
216 {
217 	QDF_STATUS status;
218 	struct wlan_find_vdev_filter filter = {0};
219 
220 	filter.ifname = ifname;
221 	wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
222 				     wlan_util_get_vdev_by_ifname_cb,
223 				     &filter, 0, ref_id);
224 
225 	if (!filter.found_vdev)
226 		return NULL;
227 
228 	status = wlan_objmgr_vdev_try_get_ref(filter.found_vdev, ref_id);
229 	if (QDF_IS_STATUS_ERROR(status))
230 		return NULL;
231 
232 	return filter.found_vdev;
233 }
234 
235 /**
236  * wlan_util_vdev_get_if_name() - get vdev's interface name
237  * @vdev: VDEV object
238  *
239  * API to get vdev's interface name
240  *
241  * Return:
242  * @id: vdev's interface name
243  */
244 uint8_t *wlan_util_vdev_get_if_name(struct wlan_objmgr_vdev *vdev)
245 {
246 	uint8_t *name;
247 	struct vdev_osif_priv *osif_priv;
248 
249 	wlan_vdev_obj_lock(vdev);
250 
251 	osif_priv = wlan_vdev_get_ospriv(vdev);
252 	if (!osif_priv) {
253 		wlan_vdev_obj_unlock(vdev);
254 		return NULL;
255 	}
256 
257 	if (!osif_priv->wdev) {
258 		wlan_vdev_obj_unlock(vdev);
259 		return NULL;
260 	}
261 
262 	name = osif_priv->wdev->netdev->name;
263 	wlan_vdev_obj_unlock(vdev);
264 
265 	return name;
266 }
267 qdf_export_symbol(wlan_util_vdev_get_if_name);
268 
269 static void wlan_vap_active(struct wlan_objmgr_pdev *pdev,
270 			void *object,
271 			void *arg)
272 {
273 	struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
274 	uint8_t *flag = (uint8_t *)arg;
275 
276 	wlan_vdev_obj_lock(vdev);
277 	if ((wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_RUN) ||
278 		(wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_DFS_WAIT)) {
279 		*flag = 1;
280 	}
281 	wlan_vdev_obj_unlock(vdev);
282 }
283 
284 QDF_STATUS wlan_util_is_vap_active(struct wlan_objmgr_pdev *pdev)
285 {
286 	uint8_t flag = 0;
287 
288 	if (!pdev)
289 		return QDF_STATUS_E_INVAL;
290 
291 	wlan_objmgr_pdev_iterate_obj_list(pdev,
292 				WLAN_VDEV_OP,
293 				wlan_vap_active,
294 				&flag, 0, WLAN_OBJMGR_ID);
295 
296 	if (flag == 1)
297 		return QDF_STATUS_SUCCESS;
298 
299 	return QDF_STATUS_E_INVAL;
300 }
301