xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c (revision 2f4b444fb7e689b83a4ab0e7b3b38f0bf4def8e0)
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