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