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