xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/utils/src/wlan_utility.c (revision 3149adf58a329e17232a4c0e58d460d025edd55a)
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 
29 uint32_t wlan_chan_to_freq(uint8_t chan)
30 {
31 	/* ch 0 - ch 13 */
32 	if (chan < WLAN_24_GHZ_CHANNEL_14)
33 		return WLAN_24_GHZ_BASE_FREQ + chan * WLAN_CHAN_SPACING_5MHZ;
34 	else if (chan == WLAN_24_GHZ_CHANNEL_14)
35 		return WLAN_CHAN_14_FREQ;
36 	else if (chan < WLAN_24_GHZ_CHANNEL_27)
37 		/* ch 15 - ch 26 */
38 		return WLAN_CHAN_15_FREQ +
39 		  (chan - WLAN_24_GHZ_CHANNEL_15) * WLAN_CHAN_SPACING_20MHZ;
40 	else if (chan == WLAN_5_GHZ_CHANNEL_170)
41 		return WLAN_CHAN_170_FREQ;
42 	else
43 		return WLAN_5_GHZ_BASE_FREQ + chan * WLAN_CHAN_SPACING_5MHZ;
44 }
45 
46 bool wlan_is_dsrc_channel(uint16_t center_freq)
47 {
48 	if (center_freq >= 5852 &&
49 	    center_freq <= 5920)
50 		return true;
51 
52 	return false;
53 }
54 
55 uint8_t wlan_freq_to_chan(uint32_t freq)
56 {
57 	uint8_t chan;
58 
59 	if (freq > WLAN_24_GHZ_BASE_FREQ && freq < WLAN_CHAN_14_FREQ)
60 		chan = ((freq - WLAN_24_GHZ_BASE_FREQ) /
61 			WLAN_CHAN_SPACING_5MHZ);
62 	else if (freq == WLAN_CHAN_14_FREQ)
63 		chan = WLAN_24_GHZ_CHANNEL_14;
64 	else if ((freq > WLAN_24_GHZ_BASE_FREQ) &&
65 		(freq < WLAN_5_GHZ_BASE_FREQ))
66 		chan = (((freq - WLAN_CHAN_15_FREQ) /
67 			WLAN_CHAN_SPACING_20MHZ) +
68 			WLAN_24_GHZ_CHANNEL_15);
69 	else
70 		chan = (freq - WLAN_5_GHZ_BASE_FREQ) /
71 			WLAN_CHAN_SPACING_5MHZ;
72 
73 	return chan;
74 }
75 
76 bool wlan_is_ie_valid(const uint8_t *ie, size_t ie_len)
77 {
78 	uint8_t elen;
79 
80 	while (ie_len) {
81 		if (ie_len < 2)
82 			return false;
83 
84 		elen = ie[1];
85 		ie_len -= 2;
86 		ie += 2;
87 		if (elen > ie_len)
88 			return false;
89 
90 		ie_len -= elen;
91 		ie += elen;
92 	}
93 
94 	return true;
95 }
96 
97 static const uint8_t *wlan_get_ie_ptr_from_eid_n_oui(uint8_t eid,
98 						     const uint8_t *oui,
99 						     uint8_t oui_size,
100 						     const uint8_t *ie,
101 						     uint16_t ie_len)
102 {
103 	int32_t left = ie_len;
104 	const uint8_t *ptr = ie;
105 	uint8_t elem_id, elem_len;
106 
107 	while (left >= 2) {
108 		elem_id  = ptr[0];
109 		elem_len = ptr[1];
110 		left -= 2;
111 
112 		if (elem_len > left)
113 			return NULL;
114 
115 		if (eid == elem_id) {
116 			/* if oui is not provide eid match is enough */
117 			if (!oui)
118 				return ptr;
119 
120 			/*
121 			 * if oui is provided and oui_size is more than left
122 			 * bytes, then we cannot have match
123 			 */
124 			if (oui_size > left)
125 				return NULL;
126 
127 			if (qdf_mem_cmp(&ptr[2], oui, oui_size) == 0)
128 				return ptr;
129 		}
130 
131 		left -= elem_len;
132 		ptr += (elem_len + 2);
133 	}
134 
135 	return NULL;
136 }
137 
138 const uint8_t *wlan_get_ie_ptr_from_eid(uint8_t eid,
139 					const uint8_t *ie,
140 					int ie_len)
141 {
142 	return wlan_get_ie_ptr_from_eid_n_oui(eid, NULL, 0, ie, ie_len);
143 }
144 
145 const uint8_t *wlan_get_vendor_ie_ptr_from_oui(const uint8_t *oui,
146 					       uint8_t oui_size,
147 					       const uint8_t *ie,
148 					       uint16_t ie_len)
149 {
150 	return wlan_get_ie_ptr_from_eid_n_oui(WLAN_MAC_EID_VENDOR,
151 					      oui, oui_size, ie, ie_len);
152 }
153 
154 const uint8_t *wlan_get_ext_ie_ptr_from_ext_id(const uint8_t *oui,
155 					       uint8_t oui_size,
156 					       const uint8_t *ie,
157 					       uint16_t ie_len)
158 {
159 	return wlan_get_ie_ptr_from_eid_n_oui(WLAN_MAC_EID_EXT,
160 					      oui, oui_size, ie, ie_len);
161 }
162 
163 bool wlan_is_emulation_platform(uint32_t phy_version)
164 {
165 	if ((phy_version == 0xABC0) || (phy_version == 0xABC1) ||
166 		(phy_version == 0xABC2) || (phy_version == 0xABC3) ||
167 		(phy_version == 0xFFFF) || (phy_version == 0xABCD))
168 		return true;
169 
170 	return false;
171 }
172 
173 uint32_t wlan_get_pdev_id_from_vdev_id(struct wlan_objmgr_psoc *psoc,
174 				      uint8_t vdev_id,
175 				      wlan_objmgr_ref_dbgid dbg_id)
176 {
177 	struct wlan_objmgr_vdev *vdev;
178 	struct wlan_objmgr_pdev *pdev = NULL;
179 	uint32_t pdev_id = WLAN_INVALID_PDEV_ID;
180 
181 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
182 						    vdev_id, dbg_id);
183 
184 	if (vdev) {
185 		pdev = wlan_vdev_get_pdev(vdev);
186 		if (pdev)
187 			pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
188 		wlan_objmgr_vdev_release_ref(vdev, dbg_id);
189 	}
190 
191 	return pdev_id;
192 }
193 EXPORT_SYMBOL(wlan_get_pdev_id_from_vdev_id);
194 
195 static void wlan_util_get_vdev_by_ifname_cb(struct wlan_objmgr_psoc *psoc,
196 					    void *obj, void *arg)
197 {
198 	struct wlan_objmgr_vdev *vdev = obj;
199 	struct wlan_find_vdev_filter *filter = arg;
200 
201 	if (filter->found_vdev)
202 		return;
203 
204 	wlan_vdev_obj_lock(vdev);
205 	if (!qdf_str_cmp(vdev->vdev_nif.osdev->wdev->netdev->name,
206 			 filter->ifname)) {
207 		filter->found_vdev = vdev;
208 	}
209 	wlan_vdev_obj_unlock(vdev);
210 }
211 
212 struct wlan_objmgr_vdev *wlan_util_get_vdev_by_ifname(
213 				struct wlan_objmgr_psoc *psoc, char *ifname,
214 				wlan_objmgr_ref_dbgid ref_id)
215 {
216 	QDF_STATUS status;
217 	struct wlan_find_vdev_filter filter = {0};
218 
219 	filter.ifname = ifname;
220 	wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
221 				     wlan_util_get_vdev_by_ifname_cb,
222 				     &filter, 0, ref_id);
223 
224 	if (!filter.found_vdev)
225 		return NULL;
226 
227 	status = wlan_objmgr_vdev_try_get_ref(filter.found_vdev, ref_id);
228 	if (QDF_IS_STATUS_ERROR(status))
229 		return NULL;
230 
231 	return filter.found_vdev;
232 }
233 
234 /**
235  * wlan_util_vdev_get_if_name() - get vdev's interface name
236  * @vdev: VDEV object
237  *
238  * API to get vdev's interface name
239  *
240  * Return:
241  * @id: vdev's interface name
242  */
243 uint8_t *wlan_util_vdev_get_if_name(struct wlan_objmgr_vdev *vdev)
244 {
245 	uint8_t *name;
246 	struct vdev_osif_priv *osif_priv;
247 
248 	wlan_vdev_obj_lock(vdev);
249 
250 	osif_priv = wlan_vdev_get_ospriv(vdev);
251 	if (!osif_priv) {
252 		wlan_vdev_obj_unlock(vdev);
253 		return NULL;
254 	}
255 
256 	if (!osif_priv->wdev) {
257 		wlan_vdev_obj_unlock(vdev);
258 		return NULL;
259 	}
260 
261 	name = osif_priv->wdev->netdev->name;
262 	wlan_vdev_obj_unlock(vdev);
263 
264 	return name;
265 }
266 EXPORT_SYMBOL(wlan_util_vdev_get_if_name);
267 
268 static void wlan_vap_active(struct wlan_objmgr_pdev *pdev,
269 			void *object,
270 			void *arg)
271 {
272 	struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
273 	uint8_t *flag = (uint8_t *)arg;
274 
275 	wlan_vdev_obj_lock(vdev);
276 	if ((wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_RUN) ||
277 		(wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_DFS_WAIT)) {
278 		*flag = 1;
279 	}
280 	wlan_vdev_obj_unlock(vdev);
281 }
282 
283 QDF_STATUS wlan_util_is_vap_active(struct wlan_objmgr_pdev *pdev)
284 {
285 	uint8_t flag = 0;
286 
287 	if (!pdev)
288 		return QDF_STATUS_E_INVAL;
289 
290 	wlan_objmgr_pdev_iterate_obj_list(pdev,
291 				WLAN_VDEV_OP,
292 				wlan_vap_active,
293 				&flag, 0, WLAN_OBJMGR_ID);
294 
295 	if (flag == 1)
296 		return QDF_STATUS_SUCCESS;
297 
298 	return QDF_STATUS_E_INVAL;
299 }
300