1 /* 2 * Copyright (c) 2012-2015, 2020-2021, The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /** 18 * DOC: wlan_cm_api.c 19 * 20 * This file maintains definitaions public apis. 21 */ 22 23 #include <wlan_cm_api.h> 24 #include "connection_mgr/core/src/wlan_cm_main_api.h" 25 #include "connection_mgr/core/src/wlan_cm_roam.h" 26 27 QDF_STATUS wlan_cm_start_connect(struct wlan_objmgr_vdev *vdev, 28 struct wlan_cm_connect_req *req) 29 { 30 return cm_connect_start_req(vdev, req); 31 } 32 33 QDF_STATUS wlan_cm_disconnect(struct wlan_objmgr_vdev *vdev, 34 enum wlan_cm_source source, 35 enum wlan_reason_code reason_code, 36 struct qdf_mac_addr *bssid) 37 { 38 struct wlan_cm_disconnect_req req = {0}; 39 40 req.vdev_id = wlan_vdev_get_id(vdev); 41 req.source = source; 42 req.reason_code = reason_code; 43 if (bssid) 44 qdf_copy_macaddr(&req.bssid, bssid); 45 46 return cm_disconnect_start_req(vdev, &req); 47 } 48 49 QDF_STATUS wlan_cm_disconnect_sync(struct wlan_objmgr_vdev *vdev, 50 enum wlan_cm_source source, 51 enum wlan_reason_code reason_code) 52 { 53 struct wlan_cm_disconnect_req req = {0}; 54 55 req.vdev_id = wlan_vdev_get_id(vdev); 56 req.source = source; 57 req.reason_code = reason_code; 58 59 return cm_disconnect_start_req_sync(vdev, &req); 60 } 61 62 QDF_STATUS wlan_cm_bss_select_ind_rsp(struct wlan_objmgr_vdev *vdev, 63 QDF_STATUS status) 64 { 65 return cm_bss_select_ind_rsp(vdev, status); 66 } 67 68 QDF_STATUS wlan_cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev, 69 QDF_STATUS status, 70 struct qdf_mac_addr *peer_mac) 71 { 72 uint32_t prefix; 73 struct cnx_mgr *cm_ctx = cm_get_cm_ctx(vdev); 74 75 if (!cm_ctx) 76 return QDF_STATUS_E_INVAL; 77 78 prefix = CM_ID_GET_PREFIX(cm_ctx->active_cm_id); 79 if (prefix == ROAM_REQ_PREFIX) 80 return cm_roam_bss_peer_create_rsp(vdev, status, peer_mac); 81 else 82 return cm_bss_peer_create_rsp(vdev, status, peer_mac); 83 } 84 85 QDF_STATUS wlan_cm_connect_rsp(struct wlan_objmgr_vdev *vdev, 86 struct wlan_cm_connect_resp *resp) 87 { 88 return cm_connect_rsp(vdev, resp); 89 } 90 91 QDF_STATUS wlan_cm_bss_peer_delete_ind(struct wlan_objmgr_vdev *vdev, 92 struct qdf_mac_addr *peer_mac) 93 { 94 return cm_bss_peer_delete_req(vdev, peer_mac); 95 } 96 97 QDF_STATUS wlan_cm_bss_peer_delete_rsp(struct wlan_objmgr_vdev *vdev, 98 uint32_t status) 99 { 100 return cm_vdev_down_req(vdev, status); 101 } 102 103 QDF_STATUS wlan_cm_disconnect_rsp(struct wlan_objmgr_vdev *vdev, 104 struct wlan_cm_discon_rsp *resp) 105 { 106 uint32_t prefix; 107 struct cnx_mgr *cm_ctx = cm_get_cm_ctx(vdev); 108 109 if (!cm_ctx) 110 return QDF_STATUS_E_INVAL; 111 112 prefix = CM_ID_GET_PREFIX(cm_ctx->active_cm_id); 113 if (prefix == ROAM_REQ_PREFIX) 114 return cm_roam_disconnect_rsp(vdev, resp); 115 else 116 return cm_disconnect_rsp(vdev, resp); 117 } 118 119 #ifdef WLAN_FEATURE_HOST_ROAM 120 QDF_STATUS wlan_cm_reassoc_rsp(struct wlan_objmgr_vdev *vdev, 121 struct wlan_cm_connect_resp *resp) 122 { 123 return cm_reassoc_rsp(vdev, resp); 124 } 125 #endif 126 127 void wlan_cm_set_max_connect_attempts(struct wlan_objmgr_vdev *vdev, 128 uint8_t max_connect_attempts) 129 { 130 cm_set_max_connect_attempts(vdev, max_connect_attempts); 131 } 132 133 void wlan_cm_set_max_connect_timeout(struct wlan_objmgr_vdev *vdev, 134 uint32_t max_connect_timeout) 135 { 136 cm_set_max_connect_timeout(vdev, max_connect_timeout); 137 } 138 139 bool wlan_cm_is_vdev_connecting(struct wlan_objmgr_vdev *vdev) 140 { 141 return cm_is_vdev_connecting(vdev); 142 } 143 144 bool wlan_cm_is_vdev_connected(struct wlan_objmgr_vdev *vdev) 145 { 146 return cm_is_vdev_connected(vdev); 147 } 148 149 bool wlan_cm_is_vdev_active(struct wlan_objmgr_vdev *vdev) 150 { 151 return cm_is_vdev_active(vdev); 152 } 153 154 bool wlan_cm_is_vdev_disconnecting(struct wlan_objmgr_vdev *vdev) 155 { 156 return cm_is_vdev_disconnecting(vdev); 157 } 158 159 bool wlan_cm_is_vdev_disconnected(struct wlan_objmgr_vdev *vdev) 160 { 161 return cm_is_vdev_disconnected(vdev); 162 } 163 164 bool wlan_cm_is_vdev_roaming(struct wlan_objmgr_vdev *vdev) 165 { 166 return cm_is_vdev_roaming(vdev); 167 } 168 169 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 170 bool wlan_cm_is_vdev_roam_started(struct wlan_objmgr_vdev *vdev) 171 { 172 return cm_is_vdev_roam_started(vdev); 173 } 174 175 bool wlan_cm_is_vdev_roam_sync_inprogress(struct wlan_objmgr_vdev *vdev) 176 { 177 return cm_is_vdev_roam_sync_inprogress(vdev); 178 } 179 #endif 180 181 #ifdef WLAN_FEATURE_HOST_ROAM 182 bool wlan_cm_is_vdev_roam_preauth_state(struct wlan_objmgr_vdev *vdev) 183 { 184 return cm_is_vdev_roam_preauth_state(vdev); 185 } 186 187 bool wlan_cm_is_vdev_roam_reassoc_state(struct wlan_objmgr_vdev *vdev) 188 { 189 return cm_is_vdev_roam_reassoc_state(vdev); 190 } 191 #endif 192 193 enum wlan_cm_active_request_type 194 wlan_cm_get_active_req_type(struct wlan_objmgr_vdev *vdev) 195 { 196 return cm_get_active_req_type(vdev); 197 } 198 199 bool wlan_cm_get_active_connect_req(struct wlan_objmgr_vdev *vdev, 200 struct wlan_cm_vdev_connect_req *req) 201 { 202 return cm_get_active_connect_req(vdev, req); 203 } 204 205 cm_ext_t *wlan_cm_get_ext_hdl(struct wlan_objmgr_vdev *vdev) 206 { 207 return cm_get_ext_hdl(vdev); 208 } 209 210 #ifdef WLAN_FEATURE_HOST_ROAM 211 bool wlan_cm_get_active_reassoc_req(struct wlan_objmgr_vdev *vdev, 212 struct wlan_cm_vdev_reassoc_req *req) 213 { 214 return cm_get_active_reassoc_req(vdev, req); 215 } 216 #endif 217 218 bool wlan_cm_get_active_disconnect_req(struct wlan_objmgr_vdev *vdev, 219 struct wlan_cm_vdev_discon_req *req) 220 { 221 return cm_get_active_disconnect_req(vdev, req); 222 } 223 224 const char *wlan_cm_reason_code_to_str(enum wlan_reason_code reason) 225 { 226 if (reason > REASON_PROP_START) 227 return ""; 228 229 switch (reason) { 230 CASE_RETURN_STRING(REASON_UNSPEC_FAILURE); 231 CASE_RETURN_STRING(REASON_PREV_AUTH_NOT_VALID); 232 CASE_RETURN_STRING(REASON_DEAUTH_NETWORK_LEAVING); 233 CASE_RETURN_STRING(REASON_DISASSOC_DUE_TO_INACTIVITY); 234 CASE_RETURN_STRING(REASON_DISASSOC_AP_BUSY); 235 CASE_RETURN_STRING(REASON_CLASS2_FRAME_FROM_NON_AUTH_STA); 236 CASE_RETURN_STRING(REASON_CLASS3_FRAME_FROM_NON_ASSOC_STA); 237 CASE_RETURN_STRING(REASON_DISASSOC_NETWORK_LEAVING); 238 CASE_RETURN_STRING(REASON_STA_NOT_AUTHENTICATED); 239 CASE_RETURN_STRING(REASON_BAD_PWR_CAPABILITY); 240 CASE_RETURN_STRING(REASON_BAD_SUPPORTED_CHANNELS); 241 CASE_RETURN_STRING(REASON_DISASSOC_BSS_TRANSITION); 242 CASE_RETURN_STRING(REASON_INVALID_IE); 243 CASE_RETURN_STRING(REASON_MIC_FAILURE); 244 CASE_RETURN_STRING(REASON_4WAY_HANDSHAKE_TIMEOUT); 245 CASE_RETURN_STRING(REASON_GROUP_KEY_UPDATE_TIMEOUT); 246 CASE_RETURN_STRING(REASON_IN_4WAY_DIFFERS); 247 CASE_RETURN_STRING(REASON_INVALID_GROUP_CIPHER); 248 CASE_RETURN_STRING(REASON_INVALID_PAIRWISE_CIPHER); 249 CASE_RETURN_STRING(REASON_INVALID_AKMP); 250 CASE_RETURN_STRING(REASON_UNSUPPORTED_RSNE_VER); 251 CASE_RETURN_STRING(REASON_INVALID_RSNE_CAPABILITIES); 252 CASE_RETURN_STRING(REASON_1X_AUTH_FAILURE); 253 CASE_RETURN_STRING(REASON_CIPHER_SUITE_REJECTED); 254 CASE_RETURN_STRING(REASON_TDLS_PEER_UNREACHABLE); 255 CASE_RETURN_STRING(REASON_TDLS_UNSPEC); 256 CASE_RETURN_STRING(REASON_DISASSOC_SSP_REQUESTED); 257 CASE_RETURN_STRING(REASON_NO_SSP_ROAMING_AGREEMENT); 258 CASE_RETURN_STRING(REASON_BAD_CIPHER_OR_AKM); 259 CASE_RETURN_STRING(REASON_LOCATION_NOT_AUTHORIZED); 260 CASE_RETURN_STRING(REASON_SERVICE_CHANGE_PRECLUDES_TS); 261 CASE_RETURN_STRING(REASON_QOS_UNSPECIFIED); 262 CASE_RETURN_STRING(REASON_NO_BANDWIDTH); 263 CASE_RETURN_STRING(REASON_XS_UNACKED_FRAMES); 264 CASE_RETURN_STRING(REASON_EXCEEDED_TXOP); 265 CASE_RETURN_STRING(REASON_STA_LEAVING); 266 CASE_RETURN_STRING(REASON_END_TS_BA_DLS); 267 CASE_RETURN_STRING(REASON_UNKNOWN_TS_BA); 268 CASE_RETURN_STRING(REASON_TIMEDOUT); 269 CASE_RETURN_STRING(REASON_PEERKEY_MISMATCH); 270 CASE_RETURN_STRING(REASON_AUTHORIZED_ACCESS_LIMIT_REACHED); 271 CASE_RETURN_STRING(REASON_EXTERNAL_SERVICE_REQUIREMENTS); 272 CASE_RETURN_STRING(REASON_INVALID_FT_ACTION_FRAME_COUNT); 273 CASE_RETURN_STRING(REASON_INVALID_PMKID); 274 CASE_RETURN_STRING(REASON_INVALID_MDE); 275 CASE_RETURN_STRING(REASON_INVALID_FTE); 276 CASE_RETURN_STRING(REASON_MESH_PEERING_CANCELLED); 277 CASE_RETURN_STRING(REASON_MESH_MAX_PEERS); 278 CASE_RETURN_STRING(REASON_MESH_CONFIG_POLICY_VIOLATION); 279 CASE_RETURN_STRING(REASON_MESH_CLOSE_RCVD); 280 CASE_RETURN_STRING(REASON_MESH_MAX_RETRIES); 281 CASE_RETURN_STRING(REASON_MESH_CONFIRM_TIMEOUT); 282 CASE_RETURN_STRING(REASON_MESH_INVALID_GTK); 283 CASE_RETURN_STRING(REASON_MESH_INCONSISTENT_PARAMS); 284 CASE_RETURN_STRING(REASON_MESH_INVALID_SECURITY_CAP); 285 CASE_RETURN_STRING(REASON_MESH_PATH_ERROR_NO_PROXY_INFO); 286 CASE_RETURN_STRING(REASON_MESH_PATH_ERROR_NO_FORWARDING_INFO); 287 CASE_RETURN_STRING(REASON_MESH_PATH_ERROR_DEST_UNREACHABLE); 288 CASE_RETURN_STRING(REASON_MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS); 289 CASE_RETURN_STRING(REASON_MESH_CHANNEL_SWITCH_REGULATORY_REQ); 290 CASE_RETURN_STRING(REASON_MESH_CHANNEL_SWITCH_UNSPECIFIED); 291 CASE_RETURN_STRING(REASON_POOR_RSSI_CONDITIONS); 292 default: 293 return "Unknown"; 294 } 295 } 296 297 #ifdef WLAN_POLICY_MGR_ENABLE 298 void wlan_cm_hw_mode_change_resp(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, 299 wlan_cm_id cm_id, QDF_STATUS status) 300 { 301 uint32_t prefix; 302 303 prefix = CM_ID_GET_PREFIX(cm_id); 304 if (prefix == ROAM_REQ_PREFIX) 305 cm_reassoc_hw_mode_change_resp(pdev, vdev_id, cm_id, status); 306 else 307 cm_hw_mode_change_resp(pdev, vdev_id, cm_id, status); 308 } 309 #endif /* ifdef POLICY_MGR_ENABLE */ 310 311 #ifdef SM_ENG_HIST_ENABLE 312 void wlan_cm_sm_history_print(struct wlan_objmgr_vdev *vdev) 313 { 314 return cm_sm_history_print(vdev); 315 } 316 317 void wlan_cm_req_history_print(struct wlan_objmgr_vdev *vdev) 318 { 319 struct cnx_mgr *cm_ctx = cm_get_cm_ctx(vdev); 320 321 if (!cm_ctx) 322 return; 323 324 cm_req_history_print(cm_ctx); 325 } 326 #endif /* SM_ENG_HIST_ENABLE */ 327 328 #ifndef CONN_MGR_ADV_FEATURE 329 void wlan_cm_set_candidate_advance_filter_cb( 330 struct wlan_objmgr_vdev *vdev, 331 void (*filter_fun)(struct wlan_objmgr_vdev *vdev, 332 struct scan_filter *filter)) 333 { 334 cm_set_candidate_advance_filter_cb(vdev, filter_fun); 335 } 336 337 void wlan_cm_set_candidate_custom_sort_cb( 338 struct wlan_objmgr_vdev *vdev, 339 void (*sort_fun)(struct wlan_objmgr_vdev *vdev, 340 qdf_list_t *list)) 341 { 342 cm_set_candidate_custom_sort_cb(vdev, sort_fun); 343 } 344 345 #endif 346 347 struct reduced_neighbor_report *wlan_cm_get_rnr(struct wlan_objmgr_vdev *vdev, 348 wlan_cm_id cm_id) 349 { 350 enum QDF_OPMODE op_mode = wlan_vdev_mlme_get_opmode(vdev); 351 struct cm_req *cm_req; 352 struct cnx_mgr *cm_ctx; 353 354 if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE) { 355 mlme_err("vdev %d Invalid mode %d", 356 wlan_vdev_get_id(vdev), op_mode); 357 return NULL; 358 } 359 360 cm_ctx = cm_get_cm_ctx(vdev); 361 if (!cm_ctx) 362 return NULL; 363 cm_req = cm_get_req_by_cm_id(cm_ctx, cm_id); 364 if (!cm_req) 365 return NULL; 366 367 if (cm_req->connect_req.cur_candidate && 368 cm_req->connect_req.cur_candidate->entry) 369 return &cm_req->connect_req.cur_candidate->entry->rnr; 370 371 return NULL; 372 } 373