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