1 /*
2  * Copyright (c) 2016 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(net_wifi_mgmt, CONFIG_NET_L2_WIFI_MGMT_LOG_LEVEL);
9 
10 #include <errno.h>
11 #include <string.h>
12 
13 #include <zephyr/net/net_core.h>
14 #include <zephyr/net/net_if.h>
15 #include <zephyr/net/wifi_mgmt.h>
16 #ifdef CONFIG_WIFI_NM
17 #include <zephyr/net/wifi_nm.h>
18 #endif /* CONFIG_WIFI_NM */
19 
wifi_security_txt(enum wifi_security_type security)20 const char *wifi_security_txt(enum wifi_security_type security)
21 {
22 	switch (security) {
23 	case WIFI_SECURITY_TYPE_NONE:
24 		return "OPEN";
25 	case WIFI_SECURITY_TYPE_WEP:
26 		return "WEP";
27 	case WIFI_SECURITY_TYPE_WPA_PSK:
28 		return "WPA-PSK";
29 	case WIFI_SECURITY_TYPE_PSK:
30 		return "WPA2-PSK";
31 	case WIFI_SECURITY_TYPE_PSK_SHA256:
32 		return "WPA2-PSK-SHA256";
33 	case WIFI_SECURITY_TYPE_SAE:
34 		return "WPA3-SAE";
35 	case WIFI_SECURITY_TYPE_WAPI:
36 		return "WAPI";
37 	case WIFI_SECURITY_TYPE_EAP:
38 		return "EAP";
39 	case WIFI_SECURITY_TYPE_UNKNOWN:
40 	default:
41 		return "UNKNOWN";
42 	}
43 }
44 
wifi_mfp_txt(enum wifi_mfp_options mfp)45 const char *wifi_mfp_txt(enum wifi_mfp_options mfp)
46 {
47 	switch (mfp) {
48 	case WIFI_MFP_DISABLE:
49 		return "Disable";
50 	case WIFI_MFP_OPTIONAL:
51 		return "Optional";
52 	case WIFI_MFP_REQUIRED:
53 		return "Required";
54 	case WIFI_MFP_UNKNOWN:
55 	default:
56 		return "UNKNOWN";
57 	}
58 }
59 
wifi_band_txt(enum wifi_frequency_bands band)60 const char *wifi_band_txt(enum wifi_frequency_bands band)
61 {
62 	switch (band) {
63 	case WIFI_FREQ_BAND_2_4_GHZ:
64 		return "2.4GHz";
65 	case WIFI_FREQ_BAND_5_GHZ:
66 		return "5GHz";
67 	case WIFI_FREQ_BAND_6_GHZ:
68 		return "6GHz";
69 	case WIFI_FREQ_BAND_UNKNOWN:
70 	default:
71 		return "UNKNOWN";
72 	}
73 }
74 
wifi_state_txt(enum wifi_iface_state state)75 const char *wifi_state_txt(enum wifi_iface_state state)
76 {
77 	switch (state) {
78 	case WIFI_STATE_DISCONNECTED:
79 		return "DISCONNECTED";
80 	case WIFI_STATE_INACTIVE:
81 		return "INACTIVE";
82 	case WIFI_STATE_INTERFACE_DISABLED:
83 		return "INTERFACE_DISABLED";
84 	case WIFI_STATE_SCANNING:
85 		return "SCANNING";
86 	case WIFI_STATE_AUTHENTICATING:
87 		return "AUTHENTICATING";
88 	case WIFI_STATE_ASSOCIATING:
89 		return "ASSOCIATING";
90 	case WIFI_STATE_ASSOCIATED:
91 		return "ASSOCIATED";
92 	case WIFI_STATE_4WAY_HANDSHAKE:
93 		return "4WAY_HANDSHAKE";
94 	case WIFI_STATE_GROUP_HANDSHAKE:
95 		return "GROUP_HANDSHAKE";
96 	case WIFI_STATE_COMPLETED:
97 		return "COMPLETED";
98 	case WIFI_STATE_UNKNOWN:
99 	default:
100 		return "UNKNOWN";
101 	}
102 }
103 
wifi_mode_txt(enum wifi_iface_mode mode)104 const char *wifi_mode_txt(enum wifi_iface_mode mode)
105 {
106 	switch (mode) {
107 	case WIFI_MODE_INFRA:
108 		return "STATION";
109 	case WIFI_MODE_IBSS:
110 		return "ADHOC";
111 	case WIFI_MODE_AP:
112 		return "ACCESS POINT";
113 	case WIFI_MODE_P2P_GO:
114 		return "P2P GROUP OWNER";
115 	case WIFI_MODE_P2P_GROUP_FORMATION:
116 		return "P2P GROUP FORMATION";
117 	case WIFI_MODE_MESH:
118 		return "MESH";
119 	case WIFI_MODE_UNKNOWN:
120 	default:
121 		return "UNKNOWN";
122 	}
123 }
124 
wifi_link_mode_txt(enum wifi_link_mode link_mode)125 const char *wifi_link_mode_txt(enum wifi_link_mode link_mode)
126 {
127 	switch (link_mode) {
128 	case WIFI_0:
129 		return "WIFI 0 (802.11)";
130 	case WIFI_1:
131 		return "WIFI 1 (802.11b)";
132 	case WIFI_2:
133 		return "WIFI 2 (802.11a)";
134 	case WIFI_3:
135 		return "WIFI 3 (802.11g)";
136 	case WIFI_4:
137 		return "WIFI 4 (802.11n/HT)";
138 	case WIFI_5:
139 		return "WIFI 5 (802.11ac/VHT)";
140 	case WIFI_6:
141 		return "WIFI 6 (802.11ax/HE)";
142 	case WIFI_6E:
143 		return "WIFI 6E (802.11ax 6GHz/HE)";
144 	case WIFI_7:
145 		return "WIFI 7 (802.11be/EHT)";
146 	case WIFI_LINK_MODE_UNKNOWN:
147 	default:
148 		return "UNKNOWN";
149 	}
150 }
151 
wifi_ps_txt(enum wifi_ps ps_name)152 const char *wifi_ps_txt(enum wifi_ps ps_name)
153 {
154 	switch (ps_name) {
155 	case WIFI_PS_DISABLED:
156 		return "Power save disabled";
157 	case WIFI_PS_ENABLED:
158 		return "Power save enabled";
159 	default:
160 		return "UNKNOWN";
161 	}
162 }
163 
wifi_ps_mode_txt(enum wifi_ps_mode ps_mode)164 const char *wifi_ps_mode_txt(enum wifi_ps_mode ps_mode)
165 {
166 	switch (ps_mode) {
167 	case WIFI_PS_MODE_LEGACY:
168 		return "Legacy power save";
169 	case WIFI_PS_MODE_WMM:
170 		return "WMM power save";
171 	default:
172 		return "UNKNOWN";
173 	}
174 }
175 
wifi_twt_operation_txt(enum wifi_twt_operation twt_operation)176 const char *wifi_twt_operation_txt(enum wifi_twt_operation twt_operation)
177 {
178 	switch (twt_operation) {
179 	case WIFI_TWT_SETUP:
180 		return "TWT setup";
181 	case WIFI_TWT_TEARDOWN:
182 		return "TWT teardown";
183 	default:
184 		return "UNKNOWN";
185 	}
186 }
187 
wifi_twt_negotiation_type_txt(enum wifi_twt_negotiation_type twt_negotiation)188 const char *wifi_twt_negotiation_type_txt(enum wifi_twt_negotiation_type twt_negotiation)
189 {
190 	switch (twt_negotiation) {
191 	case WIFI_TWT_INDIVIDUAL:
192 		return "TWT individual negotiation";
193 	case WIFI_TWT_BROADCAST:
194 		return "TWT broadcast negotiation";
195 	case WIFI_TWT_WAKE_TBTT:
196 		return "TWT wake TBTT negotiation";
197 	default:
198 		return "UNKNOWN";
199 	}
200 }
201 
wifi_twt_setup_cmd_txt(enum wifi_twt_setup_cmd twt_setup)202 const char *wifi_twt_setup_cmd_txt(enum wifi_twt_setup_cmd twt_setup)
203 {
204 	switch (twt_setup) {
205 	case WIFI_TWT_SETUP_CMD_REQUEST:
206 		return "TWT request";
207 	case WIFI_TWT_SETUP_CMD_SUGGEST:
208 		return "TWT suggest";
209 	case WIFI_TWT_SETUP_CMD_DEMAND:
210 		return "TWT demand";
211 	case WIFI_TWT_SETUP_CMD_GROUPING:
212 		return "TWT grouping";
213 	case WIFI_TWT_SETUP_CMD_ACCEPT:
214 		return "TWT accept";
215 	case WIFI_TWT_SETUP_CMD_ALTERNATE:
216 		return "TWT alternate";
217 	case WIFI_TWT_SETUP_CMD_DICTATE:
218 		return "TWT dictate";
219 	case WIFI_TWT_SETUP_CMD_REJECT:
220 		return "TWT reject";
221 	default:
222 		return "UNKNOWN";
223 	}
224 }
225 
wifi_ps_wakeup_mode_txt(enum wifi_ps_wakeup_mode ps_wakeup_mode)226 const char *wifi_ps_wakeup_mode_txt(enum wifi_ps_wakeup_mode ps_wakeup_mode)
227 {
228 	switch (ps_wakeup_mode) {
229 	case WIFI_PS_WAKEUP_MODE_DTIM:
230 		return "PS wakeup mode DTIM";
231 	case WIFI_PS_WAKEUP_MODE_LISTEN_INTERVAL:
232 		return "PS wakeup mode listen interval";
233 	default:
234 		return "UNKNOWN";
235 	}
236 }
237 
get_wifi_api(struct net_if * iface)238 static const struct wifi_mgmt_ops *const get_wifi_api(struct net_if *iface)
239 {
240 	const struct device *dev = net_if_get_device(iface);
241 	struct net_wifi_mgmt_offload *off_api =
242 			(struct net_wifi_mgmt_offload *) dev->api;
243 #ifdef CONFIG_WIFI_NM
244 	struct wifi_nm_instance *nm = wifi_nm_get_instance_iface(iface);
245 
246 	if (nm) {
247 		return nm->ops;
248 	}
249 #endif /* CONFIG_WIFI_NM */
250 	return off_api ? off_api->wifi_mgmt_api : NULL;
251 }
252 
wifi_connect(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)253 static int wifi_connect(uint32_t mgmt_request, struct net_if *iface,
254 			void *data, size_t len)
255 {
256 	struct wifi_connect_req_params *params =
257 		(struct wifi_connect_req_params *)data;
258 	const struct device *dev = net_if_get_device(iface);
259 
260 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
261 
262 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->connect == NULL) {
263 		return -ENOTSUP;
264 	}
265 
266 	LOG_HEXDUMP_DBG(params->ssid, params->ssid_length, "ssid");
267 	LOG_HEXDUMP_DBG(params->psk, params->psk_length, "psk");
268 	if (params->sae_password) {
269 		LOG_HEXDUMP_DBG(params->sae_password, params->sae_password_length, "sae");
270 	}
271 	NET_DBG("ch %u sec %u", params->channel, params->security);
272 
273 	if ((params->security > WIFI_SECURITY_TYPE_MAX) ||
274 	    (params->ssid_length > WIFI_SSID_MAX_LEN) ||
275 	    (params->ssid_length == 0U) ||
276 	    ((params->security == WIFI_SECURITY_TYPE_PSK ||
277 		  params->security == WIFI_SECURITY_TYPE_WPA_PSK ||
278 		  params->security == WIFI_SECURITY_TYPE_PSK_SHA256 ||
279 		  params->security == WIFI_SECURITY_TYPE_WPA_AUTO_PERSONAL) &&
280 	     ((params->psk_length < 8) || (params->psk_length > 64) ||
281 	      (params->psk_length == 0U) || !params->psk)) ||
282 	    ((params->security == WIFI_SECURITY_TYPE_SAE) &&
283 	      ((params->psk_length == 0U) || !params->psk) &&
284 		  ((params->sae_password_length == 0U) || !params->sae_password)) ||
285 	    ((params->channel != WIFI_CHANNEL_ANY) &&
286 	     (params->channel > WIFI_CHANNEL_MAX)) ||
287 	    !params->ssid) {
288 		return -EINVAL;
289 	}
290 
291 	return wifi_mgmt_api->connect(dev, params);
292 }
293 
294 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_CONNECT, wifi_connect);
295 
scan_result_cb(struct net_if * iface,int status,struct wifi_scan_result * entry)296 static void scan_result_cb(struct net_if *iface, int status,
297 			    struct wifi_scan_result *entry)
298 {
299 	if (!iface) {
300 		return;
301 	}
302 
303 	if (!entry) {
304 		struct wifi_status scan_status = {
305 			.status = status,
306 		};
307 
308 		net_mgmt_event_notify_with_info(NET_EVENT_WIFI_SCAN_DONE,
309 						iface, &scan_status,
310 						sizeof(struct wifi_status));
311 		return;
312 	}
313 
314 #ifndef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS_ONLY
315 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_SCAN_RESULT, iface,
316 					entry, sizeof(struct wifi_scan_result));
317 #endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS_ONLY */
318 }
319 
wifi_scan(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)320 static int wifi_scan(uint32_t mgmt_request, struct net_if *iface,
321 		     void *data, size_t len)
322 {
323 	const struct device *dev = net_if_get_device(iface);
324 	struct wifi_scan_params *params = data;
325 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
326 
327 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->scan == NULL) {
328 		return -ENOTSUP;
329 	}
330 
331 #ifdef CONFIG_WIFI_MGMT_FORCED_PASSIVE_SCAN
332 	struct wifi_scan_params default_params = {0};
333 
334 	if (params == NULL) {
335 		params = &default_params;
336 	}
337 	params->scan_type = WIFI_SCAN_TYPE_PASSIVE;
338 #endif /* CONFIG_WIFI_MGMT_FORCED_PASSIVE_SCAN */
339 
340 	return wifi_mgmt_api->scan(dev, params, scan_result_cb);
341 }
342 
343 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_SCAN, wifi_scan);
344 
wifi_disconnect(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)345 static int wifi_disconnect(uint32_t mgmt_request, struct net_if *iface,
346 			   void *data, size_t len)
347 {
348 	const struct device *dev = net_if_get_device(iface);
349 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
350 
351 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->disconnect == NULL) {
352 		return -ENOTSUP;
353 	}
354 
355 	return wifi_mgmt_api->disconnect(dev);
356 }
357 
358 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_DISCONNECT, wifi_disconnect);
359 
wifi_mgmt_raise_connect_result_event(struct net_if * iface,int status)360 void wifi_mgmt_raise_connect_result_event(struct net_if *iface, int status)
361 {
362 	struct wifi_status cnx_status = {
363 		.status = status,
364 	};
365 
366 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_CONNECT_RESULT,
367 					iface, &cnx_status,
368 					sizeof(struct wifi_status));
369 }
370 
wifi_mgmt_raise_disconnect_result_event(struct net_if * iface,int status)371 void wifi_mgmt_raise_disconnect_result_event(struct net_if *iface, int status)
372 {
373 	struct wifi_status cnx_status = {
374 		.status = status,
375 	};
376 
377 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_DISCONNECT_RESULT,
378 					iface, &cnx_status,
379 					sizeof(struct wifi_status));
380 }
381 
wifi_ap_enable(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)382 static int wifi_ap_enable(uint32_t mgmt_request, struct net_if *iface,
383 			  void *data, size_t len)
384 {
385 	struct wifi_connect_req_params *params =
386 		(struct wifi_connect_req_params *)data;
387 	const struct device *dev = net_if_get_device(iface);
388 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
389 
390 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_enable == NULL) {
391 		return -ENOTSUP;
392 	}
393 
394 	return wifi_mgmt_api->ap_enable(dev, params);
395 }
396 
397 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_ENABLE, wifi_ap_enable);
398 
wifi_ap_disable(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)399 static int wifi_ap_disable(uint32_t mgmt_request, struct net_if *iface,
400 			  void *data, size_t len)
401 {
402 	const struct device *dev = net_if_get_device(iface);
403 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
404 
405 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_enable == NULL) {
406 		return -ENOTSUP;
407 	}
408 
409 	return wifi_mgmt_api->ap_disable(dev);
410 }
411 
412 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_DISABLE, wifi_ap_disable);
413 
wifi_ap_sta_disconnect(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)414 static int wifi_ap_sta_disconnect(uint32_t mgmt_request, struct net_if *iface,
415 				  void *data, size_t len)
416 {
417 	const struct device *dev = net_if_get_device(iface);
418 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
419 	uint8_t *mac = data;
420 
421 	if (dev == NULL) {
422 		return -ENODEV;
423 	}
424 
425 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_sta_disconnect == NULL) {
426 		return -ENOTSUP;
427 	}
428 
429 	if (!data || len != sizeof(uint8_t) * WIFI_MAC_ADDR_LEN) {
430 		return -EINVAL;
431 	}
432 
433 	return wifi_mgmt_api->ap_sta_disconnect(dev, mac);
434 }
435 
436 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_STA_DISCONNECT, wifi_ap_sta_disconnect);
437 
wifi_ap_config_params(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)438 static int wifi_ap_config_params(uint32_t mgmt_request, struct net_if *iface,
439 				 void *data, size_t len)
440 {
441 	const struct device *dev = net_if_get_device(iface);
442 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
443 	struct wifi_ap_config_params *params = data;
444 
445 	if (dev == NULL) {
446 		return -ENODEV;
447 	}
448 
449 	if (wifi_mgmt_api == NULL ||
450 	    wifi_mgmt_api->ap_config_params == NULL) {
451 		return -ENOTSUP;
452 	}
453 
454 	if (!data || len != sizeof(*params)) {
455 		return -EINVAL;
456 	}
457 
458 	if (params->type & WIFI_AP_CONFIG_PARAM_MAX_NUM_STA) {
459 		if (params->max_num_sta > CONFIG_WIFI_MGMT_AP_MAX_NUM_STA) {
460 			LOG_INF("Maximum number of stations(%d) "
461 				"exceeded default configured value = %d.",
462 				params->max_num_sta, CONFIG_WIFI_MGMT_AP_MAX_NUM_STA);
463 			return -EINVAL;
464 		}
465 	}
466 
467 	return wifi_mgmt_api->ap_config_params(dev, params);
468 }
469 
470 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_CONFIG_PARAM, wifi_ap_config_params);
471 
wifi_iface_status(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)472 static int wifi_iface_status(uint32_t mgmt_request, struct net_if *iface,
473 			  void *data, size_t len)
474 {
475 	const struct device *dev = net_if_get_device(iface);
476 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
477 	struct wifi_iface_status *status = data;
478 
479 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->iface_status == NULL) {
480 		return -ENOTSUP;
481 	}
482 
483 	if (!data || len != sizeof(*status)) {
484 		return -EINVAL;
485 	}
486 
487 	return wifi_mgmt_api->iface_status(dev, status);
488 }
489 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_IFACE_STATUS, wifi_iface_status);
490 
wifi_mgmt_raise_iface_status_event(struct net_if * iface,struct wifi_iface_status * iface_status)491 void wifi_mgmt_raise_iface_status_event(struct net_if *iface,
492 		struct wifi_iface_status *iface_status)
493 {
494 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_IFACE_STATUS,
495 					iface, iface_status,
496 					sizeof(struct wifi_iface_status));
497 }
498 
499 #ifdef CONFIG_NET_STATISTICS_WIFI
wifi_iface_stats(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)500 static int wifi_iface_stats(uint32_t mgmt_request, struct net_if *iface,
501 			  void *data, size_t len)
502 {
503 	const struct device *dev = net_if_get_device(iface);
504 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
505 	struct net_stats_wifi *stats = data;
506 
507 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->get_stats == NULL) {
508 		return -ENOTSUP;
509 	}
510 
511 	if (!data || len != sizeof(*stats)) {
512 		return -EINVAL;
513 	}
514 
515 	return wifi_mgmt_api->get_stats(dev, stats);
516 }
517 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_WIFI, wifi_iface_stats);
518 #endif /* CONFIG_NET_STATISTICS_WIFI */
519 
wifi_set_power_save(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)520 static int wifi_set_power_save(uint32_t mgmt_request, struct net_if *iface,
521 			  void *data, size_t len)
522 {
523 	const struct device *dev = net_if_get_device(iface);
524 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
525 	struct wifi_ps_params *ps_params = data;
526 	struct wifi_iface_status info = { 0 };
527 
528 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->set_power_save == NULL) {
529 		return -ENOTSUP;
530 	}
531 
532 	switch (ps_params->type) {
533 	case WIFI_PS_PARAM_LISTEN_INTERVAL:
534 	case WIFI_PS_PARAM_MODE:
535 		if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, iface, &info,
536 			     sizeof(struct wifi_iface_status))) {
537 			ps_params->fail_reason =
538 				WIFI_PS_PARAM_FAIL_UNABLE_TO_GET_IFACE_STATUS;
539 			return -EIO;
540 		}
541 
542 		if (info.state >= WIFI_STATE_ASSOCIATED) {
543 			ps_params->fail_reason =
544 				WIFI_PS_PARAM_FAIL_DEVICE_CONNECTED;
545 			return -ENOTSUP;
546 		}
547 		break;
548 	case WIFI_PS_PARAM_STATE:
549 	case WIFI_PS_PARAM_WAKEUP_MODE:
550 	case WIFI_PS_PARAM_TIMEOUT:
551 		break;
552 	default:
553 		ps_params->fail_reason =
554 			WIFI_PS_PARAM_FAIL_OPERATION_NOT_SUPPORTED;
555 		return -ENOTSUP;
556 	}
557 
558 	return wifi_mgmt_api->set_power_save(dev, ps_params);
559 }
560 
561 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_PS, wifi_set_power_save);
562 
wifi_get_power_save_config(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)563 static int wifi_get_power_save_config(uint32_t mgmt_request, struct net_if *iface,
564 			  void *data, size_t len)
565 {
566 	const struct device *dev = net_if_get_device(iface);
567 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
568 	struct wifi_ps_config *ps_config = data;
569 
570 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->get_power_save_config == NULL) {
571 		return -ENOTSUP;
572 	}
573 
574 	if (!data || len != sizeof(*ps_config)) {
575 		return -EINVAL;
576 	}
577 
578 	return wifi_mgmt_api->get_power_save_config(dev, ps_config);
579 }
580 
581 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_PS_CONFIG, wifi_get_power_save_config);
582 
wifi_set_twt(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)583 static int wifi_set_twt(uint32_t mgmt_request, struct net_if *iface,
584 			  void *data, size_t len)
585 {
586 	const struct device *dev = net_if_get_device(iface);
587 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
588 	struct wifi_twt_params *twt_params = data;
589 	struct wifi_iface_status info = { 0 };
590 
591 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->set_twt == NULL) {
592 		twt_params->fail_reason =
593 			WIFI_TWT_FAIL_OPERATION_NOT_SUPPORTED;
594 		return -ENOTSUP;
595 	}
596 
597 	if (twt_params->operation == WIFI_TWT_TEARDOWN) {
598 		return wifi_mgmt_api->set_twt(dev, twt_params);
599 	}
600 
601 	if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, iface, &info,
602 			sizeof(struct wifi_iface_status))) {
603 		twt_params->fail_reason =
604 			WIFI_TWT_FAIL_UNABLE_TO_GET_IFACE_STATUS;
605 		goto fail;
606 	}
607 
608 	if (info.state != WIFI_STATE_COMPLETED) {
609 		twt_params->fail_reason =
610 			WIFI_TWT_FAIL_DEVICE_NOT_CONNECTED;
611 		goto fail;
612 	}
613 
614 #ifdef CONFIG_WIFI_MGMT_TWT_CHECK_IP
615 	if ((!net_if_ipv4_get_global_addr(iface, NET_ADDR_PREFERRED)) &&
616 	    (!net_if_ipv6_get_global_addr(NET_ADDR_PREFERRED, &iface))) {
617 		twt_params->fail_reason =
618 			WIFI_TWT_FAIL_IP_NOT_ASSIGNED;
619 		goto fail;
620 	}
621 #else
622 	NET_WARN("Check for valid IP address been disabled. "
623 		 "Device might be unreachable or might not receive traffic.\n");
624 #endif /* CONFIG_WIFI_MGMT_TWT_CHECK_IP */
625 
626 	if (info.link_mode < WIFI_6) {
627 		twt_params->fail_reason =
628 			WIFI_TWT_FAIL_PEER_NOT_HE_CAPAB;
629 		goto fail;
630 	}
631 
632 	if (!info.twt_capable) {
633 		twt_params->fail_reason =
634 			WIFI_TWT_FAIL_PEER_NOT_TWT_CAPAB;
635 		goto fail;
636 	}
637 
638 	return wifi_mgmt_api->set_twt(dev, twt_params);
639 fail:
640 	return -ENOEXEC;
641 
642 }
643 
644 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_TWT, wifi_set_twt);
645 
wifi_mgmt_raise_twt_event(struct net_if * iface,struct wifi_twt_params * twt_params)646 void wifi_mgmt_raise_twt_event(struct net_if *iface, struct wifi_twt_params *twt_params)
647 {
648 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_TWT,
649 					iface, twt_params,
650 					sizeof(struct wifi_twt_params));
651 }
652 
wifi_reg_domain(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)653 static int wifi_reg_domain(uint32_t mgmt_request, struct net_if *iface,
654 			   void *data, size_t len)
655 {
656 	const struct device *dev = net_if_get_device(iface);
657 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
658 	struct wifi_reg_domain *reg_domain = data;
659 
660 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->reg_domain == NULL) {
661 		return -ENOTSUP;
662 	}
663 
664 	if (!data || len != sizeof(*reg_domain)) {
665 		return -EINVAL;
666 	}
667 
668 	return wifi_mgmt_api->reg_domain(dev, reg_domain);
669 }
670 
671 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_REG_DOMAIN, wifi_reg_domain);
672 
wifi_mgmt_raise_twt_sleep_state(struct net_if * iface,int twt_sleep_state)673 void wifi_mgmt_raise_twt_sleep_state(struct net_if *iface,
674 				     int twt_sleep_state)
675 {
676 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_TWT_SLEEP_STATE,
677 					iface, &twt_sleep_state,
678 					sizeof(twt_sleep_state));
679 }
680 
wifi_mode(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)681 static int wifi_mode(uint32_t mgmt_request, struct net_if *iface,
682 				void *data, size_t len)
683 {
684 	const struct device *dev = net_if_get_device(iface);
685 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
686 	struct wifi_mode_info *mode_info = data;
687 
688 	if (dev == NULL) {
689 		return -ENODEV;
690 	}
691 
692 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->mode == NULL) {
693 		return -ENOTSUP;
694 	}
695 
696 	return wifi_mgmt_api->mode(dev, mode_info);
697 }
698 
699 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_MODE, wifi_mode);
700 
wifi_packet_filter(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)701 static int wifi_packet_filter(uint32_t mgmt_request, struct net_if *iface,
702 				void *data, size_t len)
703 {
704 	const struct device *dev = net_if_get_device(iface);
705 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
706 	struct wifi_filter_info *filter_info = data;
707 
708 	if (dev == NULL) {
709 		return -ENODEV;
710 	}
711 
712 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->filter == NULL) {
713 		return -ENOTSUP;
714 	}
715 
716 	return wifi_mgmt_api->filter(dev, filter_info);
717 }
718 
719 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_PACKET_FILTER, wifi_packet_filter);
720 
wifi_channel(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)721 static int wifi_channel(uint32_t mgmt_request, struct net_if *iface,
722 				void *data, size_t len)
723 {
724 	const struct device *dev = net_if_get_device(iface);
725 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
726 	struct wifi_channel_info *channel_info = data;
727 
728 	if (dev == NULL) {
729 		return -ENODEV;
730 	}
731 
732 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->channel == NULL) {
733 		return -ENOTSUP;
734 	}
735 
736 	return wifi_mgmt_api->channel(dev, channel_info);
737 }
738 
739 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_CHANNEL, wifi_channel);
740 
wifi_get_version(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)741 static int wifi_get_version(uint32_t mgmt_request, struct net_if *iface,
742 			   void *data, size_t len)
743 {
744 	const struct device *dev = net_if_get_device(iface);
745 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
746 	struct wifi_version *ver_params = data;
747 
748 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->get_version == NULL) {
749 		return -ENOTSUP;
750 	}
751 
752 	return wifi_mgmt_api->get_version(dev, ver_params);
753 }
754 
755 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_VERSION, wifi_get_version);
756 
wifi_set_rts_threshold(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)757 static int wifi_set_rts_threshold(uint32_t mgmt_request, struct net_if *iface,
758 				  void *data, size_t len)
759 {
760 	const struct device *dev = net_if_get_device(iface);
761 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
762 	unsigned int *rts_threshold = data;
763 
764 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->set_rts_threshold == NULL) {
765 		return -ENOTSUP;
766 	}
767 
768 	if (!data || len != sizeof(*rts_threshold)) {
769 		return -EINVAL;
770 	}
771 
772 	return wifi_mgmt_api->set_rts_threshold(dev, *rts_threshold);
773 }
774 
775 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_RTS_THRESHOLD, wifi_set_rts_threshold);
776 
777 #ifdef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS
wifi_mgmt_raise_raw_scan_result_event(struct net_if * iface,struct wifi_raw_scan_result * raw_scan_result)778 void wifi_mgmt_raise_raw_scan_result_event(struct net_if *iface,
779 					   struct wifi_raw_scan_result *raw_scan_result)
780 {
781 	if (raw_scan_result->frame_length > CONFIG_WIFI_MGMT_RAW_SCAN_RESULT_LENGTH) {
782 		LOG_INF("raw scan result frame length = %d too big,"
783 			 "saving upto max raw scan length = %d",
784 			 raw_scan_result->frame_length,
785 			 CONFIG_WIFI_MGMT_RAW_SCAN_RESULT_LENGTH);
786 	}
787 
788 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_RAW_SCAN_RESULT,
789 					iface, raw_scan_result,
790 					sizeof(*raw_scan_result));
791 }
792 #endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS */
793 
wifi_mgmt_raise_disconnect_complete_event(struct net_if * iface,int status)794 void wifi_mgmt_raise_disconnect_complete_event(struct net_if *iface,
795 					       int status)
796 {
797 	struct wifi_status cnx_status = {
798 		.status = status,
799 	};
800 
801 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_DISCONNECT_COMPLETE,
802 					iface, &cnx_status,
803 					sizeof(struct wifi_status));
804 }
805 
wifi_mgmt_raise_ap_enable_result_event(struct net_if * iface,enum wifi_ap_status status)806 void wifi_mgmt_raise_ap_enable_result_event(struct net_if *iface,
807 					    enum wifi_ap_status status)
808 {
809 	struct wifi_status cnx_status = {
810 		.status = status,
811 	};
812 
813 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_AP_ENABLE_RESULT,
814 					iface, &cnx_status,
815 					sizeof(enum wifi_ap_status));
816 }
817 
wifi_mgmt_raise_ap_disable_result_event(struct net_if * iface,enum wifi_ap_status status)818 void wifi_mgmt_raise_ap_disable_result_event(struct net_if *iface,
819 					     enum wifi_ap_status status)
820 {
821 	struct wifi_status cnx_status = {
822 		.status = status,
823 	};
824 
825 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_AP_DISABLE_RESULT,
826 					iface, &cnx_status,
827 					sizeof(enum wifi_ap_status));
828 }
829 
wifi_mgmt_raise_ap_sta_connected_event(struct net_if * iface,struct wifi_ap_sta_info * sta_info)830 void wifi_mgmt_raise_ap_sta_connected_event(struct net_if *iface,
831 					    struct wifi_ap_sta_info *sta_info)
832 {
833 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_AP_STA_CONNECTED,
834 					iface, sta_info,
835 					sizeof(struct wifi_ap_sta_info));
836 }
837 
wifi_mgmt_raise_ap_sta_disconnected_event(struct net_if * iface,struct wifi_ap_sta_info * sta_info)838 void wifi_mgmt_raise_ap_sta_disconnected_event(struct net_if *iface,
839 					       struct wifi_ap_sta_info *sta_info)
840 {
841 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_AP_STA_DISCONNECTED,
842 					iface, sta_info,
843 					sizeof(struct wifi_ap_sta_info));
844 }
845