1 /*
2 * Copyright (c) 2020 Espressif Systems (Shanghai) Co., Ltd.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT espressif_esp32_wifi
8
9 #include <zephyr/logging/log.h>
10 LOG_MODULE_REGISTER(esp32_wifi, CONFIG_WIFI_LOG_LEVEL);
11
12 #include <zephyr/net/ethernet.h>
13 #include <zephyr/net/net_pkt.h>
14 #include <zephyr/net/net_if.h>
15 #include <zephyr/net/wifi_mgmt.h>
16 #if defined(CONFIG_ESP32_WIFI_AP_STA_MODE)
17 #include <zephyr/net/wifi_nm.h>
18 #include <zephyr/net/conn_mgr/connectivity_wifi_mgmt.h>
19 #endif
20 #include <zephyr/device.h>
21 #include <soc.h>
22 #include "esp_private/wifi.h"
23 #include "esp_event.h"
24 #include "esp_timer.h"
25 #include "esp_system.h"
26 #include "esp_wpa.h"
27 #include <esp_mac.h>
28 #include "wifi/wifi_event.h"
29
30 #if CONFIG_SOC_SERIES_ESP32S2 || CONFIG_SOC_SERIES_ESP32C3
31 #include <esp_private/adc_share_hw_ctrl.h>
32 #endif /* CONFIG_SOC_SERIES_ESP32S2 || CONFIG_SOC_SERIES_ESP32C3 */
33
34 #define DHCPV4_MASK (NET_EVENT_IPV4_DHCP_BOUND | NET_EVENT_IPV4_DHCP_STOP)
35
36 /* use global iface pointer to support any ethernet driver */
37 /* necessary for wifi callback functions */
38 static struct net_if *esp32_wifi_iface;
39 static struct esp32_wifi_runtime esp32_data;
40
41 #if defined(CONFIG_ESP32_WIFI_AP_STA_MODE)
42 static struct net_if *esp32_wifi_iface_ap;
43 static struct esp32_wifi_runtime esp32_ap_sta_data;
44 #endif
45
46 enum esp32_state_flag {
47 ESP32_STA_STOPPED,
48 ESP32_STA_STARTED,
49 ESP32_STA_CONNECTING,
50 ESP32_STA_CONNECTED,
51 ESP32_AP_STARTED,
52 ESP32_AP_CONNECTED,
53 ESP32_AP_DISCONNECTED,
54 ESP32_AP_STOPPED,
55 };
56
57 struct esp32_wifi_status {
58 char ssid[WIFI_SSID_MAX_LEN + 1];
59 char pass[WIFI_PSK_MAX_LEN + 1];
60 wifi_auth_mode_t security;
61 bool connected;
62 uint8_t channel;
63 int rssi;
64 };
65
66 struct esp32_wifi_runtime {
67 uint8_t mac_addr[6];
68 uint8_t frame_buf[NET_ETH_MAX_FRAME_SIZE];
69 #if defined(CONFIG_NET_STATISTICS_WIFI)
70 struct net_stats_wifi stats;
71 #endif
72 struct esp32_wifi_status status;
73 scan_result_cb_t scan_cb;
74 uint8_t state;
75 uint8_t ap_connection_cnt;
76 };
77
78 static struct net_mgmt_event_callback esp32_dhcp_cb;
79
wifi_event_handler(struct net_mgmt_event_callback * cb,uint32_t mgmt_event,struct net_if * iface)80 static void wifi_event_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event,
81 struct net_if *iface)
82 {
83 switch (mgmt_event) {
84 case NET_EVENT_IPV4_DHCP_BOUND:
85 wifi_mgmt_raise_connect_result_event(iface, 0);
86 break;
87 default:
88 break;
89 }
90 }
91
esp32_wifi_send(const struct device * dev,struct net_pkt * pkt)92 static int esp32_wifi_send(const struct device *dev, struct net_pkt *pkt)
93 {
94 struct esp32_wifi_runtime *data = dev->data;
95 const int pkt_len = net_pkt_get_len(pkt);
96 esp_interface_t ifx = data->state == ESP32_AP_CONNECTED ? ESP_IF_WIFI_AP : ESP_IF_WIFI_STA;
97
98 /* Read the packet payload */
99 if (net_pkt_read(pkt, data->frame_buf, pkt_len) < 0) {
100 goto out;
101 }
102
103 /* Enqueue packet for transmission */
104 if (esp_wifi_internal_tx(ifx, (void *)data->frame_buf, pkt_len) != ESP_OK) {
105 goto out;
106 }
107
108 #if defined(CONFIG_NET_STATISTICS_WIFI)
109 data->stats.bytes.sent += pkt_len;
110 data->stats.pkts.tx++;
111 #endif
112
113 LOG_DBG("pkt sent %p len %d", pkt, pkt_len);
114 return 0;
115
116 out:
117
118 LOG_ERR("Failed to send packet");
119 #if defined(CONFIG_NET_STATISTICS_WIFI)
120 data->stats.errors.tx++;
121 #endif
122 return -EIO;
123 }
124
eth_esp32_rx(void * buffer,uint16_t len,void * eb)125 static esp_err_t eth_esp32_rx(void *buffer, uint16_t len, void *eb)
126 {
127 struct net_pkt *pkt;
128
129 if (esp32_wifi_iface == NULL) {
130 esp_wifi_internal_free_rx_buffer(eb);
131 LOG_ERR("network interface unavailable");
132 return -EIO;
133 }
134
135 pkt = net_pkt_rx_alloc_with_buffer(esp32_wifi_iface, len, AF_UNSPEC, 0, K_MSEC(100));
136 if (!pkt) {
137 LOG_ERR("Failed to allocate net buffer");
138 esp_wifi_internal_free_rx_buffer(eb);
139 return -EIO;
140 }
141
142 if (net_pkt_write(pkt, buffer, len) < 0) {
143 LOG_ERR("Failed to write to net buffer");
144 goto pkt_unref;
145 }
146
147 if (net_recv_data(esp32_wifi_iface, pkt) < 0) {
148 LOG_ERR("Failed to push received data");
149 goto pkt_unref;
150 }
151
152 #if defined(CONFIG_NET_STATISTICS_WIFI)
153 esp32_data.stats.bytes.received += len;
154 esp32_data.stats.pkts.rx++;
155 #endif
156
157 esp_wifi_internal_free_rx_buffer(eb);
158 return 0;
159
160 pkt_unref:
161 esp_wifi_internal_free_rx_buffer(eb);
162 net_pkt_unref(pkt);
163
164 #if defined(CONFIG_NET_STATISTICS_WIFI)
165 esp32_data.stats.errors.rx++;
166 #endif
167
168 return -EIO;
169 }
170
171 #if defined(CONFIG_ESP32_WIFI_AP_STA_MODE)
wifi_esp32_ap_iface_rx(void * buffer,uint16_t len,void * eb)172 static esp_err_t wifi_esp32_ap_iface_rx(void *buffer, uint16_t len, void *eb)
173 {
174 struct net_pkt *pkt;
175
176 if (esp32_wifi_iface_ap == NULL) {
177 esp_wifi_internal_free_rx_buffer(eb);
178 LOG_ERR("network interface unavailable");
179 return -EIO;
180 }
181
182 pkt = net_pkt_rx_alloc_with_buffer(esp32_wifi_iface_ap, len, AF_UNSPEC, 0, K_MSEC(100));
183 if (!pkt) {
184 esp_wifi_internal_free_rx_buffer(eb);
185 LOG_ERR("Failed to get net buffer");
186 return -EIO;
187 }
188
189 if (net_pkt_write(pkt, buffer, len) < 0) {
190 LOG_ERR("Failed to write pkt");
191 goto pkt_unref;
192 }
193
194 if (net_recv_data(esp32_wifi_iface_ap, pkt) < 0) {
195 LOG_ERR("Failed to push received data");
196 goto pkt_unref;
197 }
198
199 #if defined(CONFIG_NET_STATISTICS_WIFI)
200 esp32_ap_sta_data.stats.bytes.received += len;
201 esp32_ap_sta_data.stats.pkts.rx++;
202 #endif
203
204 esp_wifi_internal_free_rx_buffer(eb);
205 return 0;
206
207 pkt_unref:
208 esp_wifi_internal_free_rx_buffer(eb);
209 net_pkt_unref(pkt);
210
211 #if defined(CONFIG_NET_STATISTICS_WIFI)
212 esp32_ap_sta_data.stats.errors.rx++;
213 #endif
214 return -EIO;
215 }
216 #endif
217
scan_done_handler(void)218 static void scan_done_handler(void)
219 {
220 uint16_t aps = 0;
221 wifi_ap_record_t *ap_list_buffer;
222 struct wifi_scan_result res = { 0 };
223
224 esp_wifi_scan_get_ap_num(&aps);
225 if (!aps) {
226 LOG_INF("No Wi-Fi AP found");
227 goto out;
228 }
229
230 ap_list_buffer = k_malloc(aps * sizeof(wifi_ap_record_t));
231 if (ap_list_buffer == NULL) {
232 LOG_INF("Failed to malloc buffer to print scan results");
233 goto out;
234 }
235
236 if (esp_wifi_scan_get_ap_records(&aps, (wifi_ap_record_t *)ap_list_buffer) == ESP_OK) {
237 for (int k = 0; k < aps; k++) {
238 memset(&res, 0, sizeof(struct wifi_scan_result));
239 int ssid_len = strnlen(ap_list_buffer[k].ssid, WIFI_SSID_MAX_LEN);
240
241 res.ssid_length = ssid_len;
242 strncpy(res.ssid, ap_list_buffer[k].ssid, ssid_len);
243 res.rssi = ap_list_buffer[k].rssi;
244 res.channel = ap_list_buffer[k].primary;
245
246 memcpy(res.mac, ap_list_buffer[k].bssid, WIFI_MAC_ADDR_LEN);
247 res.mac_length = WIFI_MAC_ADDR_LEN;
248
249 switch (ap_list_buffer[k].authmode) {
250 case WIFI_AUTH_OPEN:
251 res.security = WIFI_SECURITY_TYPE_NONE;
252 break;
253 case WIFI_AUTH_WPA2_PSK:
254 res.security = WIFI_SECURITY_TYPE_PSK;
255 break;
256 case WIFI_AUTH_WPA3_PSK:
257 res.security = WIFI_SECURITY_TYPE_SAE;
258 break;
259 case WIFI_AUTH_WAPI_PSK:
260 res.security = WIFI_SECURITY_TYPE_WAPI;
261 break;
262 case WIFI_AUTH_WPA2_ENTERPRISE:
263 res.security = WIFI_SECURITY_TYPE_EAP;
264 break;
265 case WIFI_AUTH_WEP:
266 res.security = WIFI_SECURITY_TYPE_WEP;
267 break;
268 case WIFI_AUTH_WPA_PSK:
269 res.security = WIFI_SECURITY_TYPE_WPA_PSK;
270 break;
271 default:
272 res.security = WIFI_SECURITY_TYPE_UNKNOWN;
273 break;
274 }
275
276 if (esp32_data.scan_cb) {
277 esp32_data.scan_cb(esp32_wifi_iface, 0, &res);
278
279 /* ensure notifications get delivered */
280 k_yield();
281 }
282 }
283 } else {
284 LOG_INF("Unable to retrieve AP records");
285 }
286
287 k_free(ap_list_buffer);
288
289 out:
290 /* report end of scan event */
291 esp32_data.scan_cb(esp32_wifi_iface, 0, NULL);
292 esp32_data.scan_cb = NULL;
293 }
294
esp_wifi_handle_sta_connect_event(void * event_data)295 static void esp_wifi_handle_sta_connect_event(void *event_data)
296 {
297 ARG_UNUSED(event_data);
298 esp32_data.state = ESP32_STA_CONNECTED;
299 #if defined(CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4)
300 net_dhcpv4_start(esp32_wifi_iface);
301 #else
302 wifi_mgmt_raise_connect_result_event(esp32_wifi_iface, 0);
303 #endif
304 }
305
esp_wifi_handle_sta_disconnect_event(void * event_data)306 static void esp_wifi_handle_sta_disconnect_event(void *event_data)
307 {
308 wifi_event_sta_disconnected_t *event = (wifi_event_sta_disconnected_t *)event_data;
309
310 if (esp32_data.state == ESP32_STA_CONNECTED) {
311 #if defined(CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4)
312 net_dhcpv4_stop(esp32_wifi_iface);
313 #endif
314 wifi_mgmt_raise_disconnect_result_event(esp32_wifi_iface, 0);
315 } else {
316 wifi_mgmt_raise_disconnect_result_event(esp32_wifi_iface, -1);
317 }
318
319 LOG_DBG("Disconnect reason: %d", event->reason);
320 switch (event->reason) {
321 case WIFI_REASON_AUTH_EXPIRE:
322 case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT:
323 case WIFI_REASON_AUTH_FAIL:
324 case WIFI_REASON_HANDSHAKE_TIMEOUT:
325 case WIFI_REASON_MIC_FAILURE:
326 LOG_DBG("STA Auth Error");
327 break;
328 case WIFI_REASON_NO_AP_FOUND:
329 LOG_DBG("AP Not found");
330 break;
331 default:
332 break;
333 }
334
335 if (IS_ENABLED(CONFIG_ESP32_WIFI_STA_RECONNECT) &&
336 (event->reason != WIFI_REASON_ASSOC_LEAVE)) {
337 esp32_data.state = ESP32_STA_CONNECTING;
338 esp_wifi_connect();
339 } else {
340 esp32_data.state = ESP32_STA_STARTED;
341 }
342 }
343
esp_wifi_handle_ap_connect_event(void * event_data)344 static void esp_wifi_handle_ap_connect_event(void *event_data)
345 {
346 #if defined(CONFIG_ESP32_WIFI_AP_STA_MODE)
347 struct net_if *iface = esp32_wifi_iface_ap;
348 wifi_rxcb_t esp32_rx = wifi_esp32_ap_iface_rx;
349 #else
350 struct net_if *iface = esp32_wifi_iface;
351 wifi_rxcb_t esp32_rx = eth_esp32_rx;
352 #endif
353 wifi_event_ap_staconnected_t *event = (wifi_event_ap_staconnected_t *)event_data;
354
355 LOG_DBG("Station " MACSTR " join, AID=%d", MAC2STR(event->mac), event->aid);
356
357 wifi_sta_list_t sta_list;
358 struct wifi_ap_sta_info sta_info;
359
360 sta_info.link_mode = WIFI_LINK_MODE_UNKNOWN;
361 sta_info.twt_capable = false; /* Only support in 802.11ax */
362 sta_info.mac_length = WIFI_MAC_ADDR_LEN;
363 memcpy(sta_info.mac, event->mac, WIFI_MAC_ADDR_LEN);
364
365 /* Expect the return value to always be ESP_OK,
366 * since it is called in esp_wifi_event_handler()
367 */
368 (void)esp_wifi_ap_get_sta_list(&sta_list);
369 for (int i = 0; i < sta_list.num; i++) {
370 wifi_sta_info_t *sta = &sta_list.sta[i];
371
372 if (memcmp(event->mac, sta->mac, 6) == 0) {
373 if (sta->phy_11n) {
374 sta_info.link_mode = WIFI_4;
375 } else if (sta->phy_11g) {
376 sta_info.link_mode = WIFI_3;
377 } else if (sta->phy_11b) {
378 sta_info.link_mode = WIFI_1;
379 } else {
380 sta_info.link_mode = WIFI_LINK_MODE_UNKNOWN;
381 }
382 break;
383 }
384 }
385
386 wifi_mgmt_raise_ap_sta_connected_event(iface, &sta_info);
387
388 if (!(esp32_data.ap_connection_cnt++)) {
389 esp_wifi_internal_reg_rxcb(WIFI_IF_AP, esp32_rx);
390 }
391 }
392
esp_wifi_handle_ap_disconnect_event(void * event_data)393 static void esp_wifi_handle_ap_disconnect_event(void *event_data)
394 {
395 #if defined(CONFIG_ESP32_WIFI_AP_STA_MODE)
396 struct net_if *iface = esp32_wifi_iface_ap;
397 #else
398 struct net_if *iface = esp32_wifi_iface;
399 #endif
400 wifi_event_ap_stadisconnected_t *event = (wifi_event_ap_stadisconnected_t *)event_data;
401
402 LOG_DBG("station " MACSTR " leave, AID=%d", MAC2STR(event->mac), event->aid);
403 struct wifi_ap_sta_info sta_info;
404
405 sta_info.link_mode = WIFI_LINK_MODE_UNKNOWN;
406 sta_info.twt_capable = false; /* Only support in 802.11ax */
407 sta_info.mac_length = WIFI_MAC_ADDR_LEN;
408 memcpy(sta_info.mac, event->mac, WIFI_MAC_ADDR_LEN);
409 wifi_mgmt_raise_ap_sta_disconnected_event(iface, &sta_info);
410
411 if (!(--esp32_data.ap_connection_cnt)) {
412 esp_wifi_internal_reg_rxcb(WIFI_IF_AP, NULL);
413 }
414 }
415
esp_wifi_event_handler(const char * event_base,int32_t event_id,void * event_data,size_t event_data_size,uint32_t ticks_to_wait)416 void esp_wifi_event_handler(const char *event_base, int32_t event_id, void *event_data,
417 size_t event_data_size, uint32_t ticks_to_wait)
418 {
419 #if defined(CONFIG_ESP32_WIFI_AP_STA_MODE)
420 struct net_if *iface_ap = esp32_wifi_iface_ap;
421 struct esp32_wifi_runtime *ap_data = &esp32_ap_sta_data;
422 #else
423 struct net_if *iface_ap = esp32_wifi_iface;
424 struct esp32_wifi_runtime *ap_data = &esp32_data;
425 #endif
426
427 LOG_DBG("Wi-Fi event: %d", event_id);
428 switch (event_id) {
429 case WIFI_EVENT_STA_START:
430 esp32_data.state = ESP32_STA_STARTED;
431 net_eth_carrier_on(esp32_wifi_iface);
432 break;
433 case WIFI_EVENT_STA_STOP:
434 esp32_data.state = ESP32_STA_STOPPED;
435 net_eth_carrier_off(esp32_wifi_iface);
436 break;
437 case WIFI_EVENT_STA_CONNECTED:
438 esp_wifi_handle_sta_connect_event(event_data);
439 break;
440 case WIFI_EVENT_STA_DISCONNECTED:
441 esp_wifi_handle_sta_disconnect_event(event_data);
442 break;
443 case WIFI_EVENT_SCAN_DONE:
444 scan_done_handler();
445 break;
446 case WIFI_EVENT_AP_START:
447 ap_data->state = ESP32_AP_STARTED;
448 net_eth_carrier_on(iface_ap);
449 wifi_mgmt_raise_ap_enable_result_event(iface_ap, 0);
450 break;
451 case WIFI_EVENT_AP_STOP:
452 ap_data->state = ESP32_AP_STOPPED;
453 net_eth_carrier_off(iface_ap);
454 wifi_mgmt_raise_ap_disable_result_event(iface_ap, 0);
455 break;
456 case WIFI_EVENT_AP_STACONNECTED:
457 ap_data->state = ESP32_AP_CONNECTED;
458 esp_wifi_handle_ap_connect_event(event_data);
459 break;
460 case WIFI_EVENT_AP_STADISCONNECTED:
461 ap_data->state = ESP32_AP_DISCONNECTED;
462 esp_wifi_handle_ap_disconnect_event(event_data);
463 break;
464 default:
465 break;
466 }
467 }
468
esp32_wifi_disconnect(const struct device * dev)469 static int esp32_wifi_disconnect(const struct device *dev)
470 {
471 int ret = esp_wifi_disconnect();
472
473 if (ret != ESP_OK) {
474 LOG_INF("Failed to disconnect from hotspot");
475 return -EAGAIN;
476 }
477
478 return 0;
479 }
480
esp32_wifi_connect(const struct device * dev,struct wifi_connect_req_params * params)481 static int esp32_wifi_connect(const struct device *dev,
482 struct wifi_connect_req_params *params)
483 {
484 struct esp32_wifi_runtime *data = dev->data;
485 struct net_if *iface = net_if_lookup_by_dev(dev);
486 wifi_mode_t mode;
487 int ret;
488
489 if (data->state == ESP32_STA_CONNECTING || data->state == ESP32_STA_CONNECTED) {
490 wifi_mgmt_raise_connect_result_event(iface, -1);
491 return -EALREADY;
492 }
493
494 ret = esp_wifi_get_mode(&mode);
495 if (ret) {
496 LOG_ERR("Failed to get Wi-Fi mode (%d)", ret);
497 return -EAGAIN;
498 }
499
500 if (IS_ENABLED(CONFIG_ESP32_WIFI_AP_STA_MODE) &&
501 (mode == ESP32_WIFI_MODE_AP || mode == ESP32_WIFI_MODE_APSTA)) {
502 ret = esp_wifi_set_mode(ESP32_WIFI_MODE_APSTA);
503 } else {
504 ret = esp_wifi_set_mode(ESP32_WIFI_MODE_STA);
505 }
506
507 if (ret) {
508 LOG_ERR("Failed to set Wi-Fi mode (%d)", ret);
509 return -EAGAIN;
510 }
511 ret = esp_wifi_start();
512 if (ret) {
513 LOG_ERR("Failed to start Wi-Fi driver (%d)", ret);
514 return -EAGAIN;
515 }
516
517 if (data->state != ESP32_STA_STARTED) {
518 LOG_ERR("Wi-Fi not in station mode");
519 wifi_mgmt_raise_connect_result_event(iface, -1);
520 return -EIO;
521 }
522
523 data->state = ESP32_STA_CONNECTING;
524
525 memcpy(data->status.ssid, params->ssid, params->ssid_length);
526 data->status.ssid[params->ssid_length] = '\0';
527
528 wifi_config_t wifi_config;
529
530 memset(&wifi_config, 0, sizeof(wifi_config_t));
531
532 memcpy(wifi_config.sta.ssid, params->ssid, params->ssid_length);
533 wifi_config.sta.ssid[params->ssid_length] = '\0';
534 switch (params->security) {
535 case WIFI_SECURITY_TYPE_NONE:
536 wifi_config.sta.threshold.authmode = WIFI_AUTH_OPEN;
537 data->status.security = WIFI_AUTH_OPEN;
538 wifi_config.sta.pmf_cfg.required = false;
539 break;
540 case WIFI_SECURITY_TYPE_PSK:
541 memcpy(wifi_config.sta.password, params->psk, params->psk_length);
542 wifi_config.sta.password[params->psk_length] = '\0';
543 wifi_config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK;
544 wifi_config.sta.pmf_cfg.required = false;
545 data->status.security = WIFI_AUTH_WPA2_PSK;
546 break;
547 case WIFI_SECURITY_TYPE_SAE:
548 #if defined(CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE)
549 if (params->sae_password) {
550 memcpy(wifi_config.sta.password, params->sae_password,
551 params->sae_password_length);
552 wifi_config.sta.password[params->sae_password_length] = '\0';
553 } else {
554 memcpy(wifi_config.sta.password, params->psk, params->psk_length);
555 wifi_config.sta.password[params->psk_length] = '\0';
556 }
557 data->status.security = WIFI_AUTH_WPA3_PSK;
558 wifi_config.sta.threshold.authmode = WIFI_AUTH_WPA3_PSK;
559 wifi_config.sta.sae_pwe_h2e = WPA3_SAE_PWE_BOTH;
560 break;
561 #else
562 LOG_ERR("WPA3 not supported for STA mode. Enable "
563 "CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE");
564 return -EINVAL;
565 #endif /* CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE */
566 default:
567 LOG_ERR("Authentication method not supported");
568 return -EIO;
569 }
570
571 if (params->channel == WIFI_CHANNEL_ANY) {
572 wifi_config.sta.channel = 0U;
573 data->status.channel = 0U;
574 } else {
575 wifi_config.sta.channel = params->channel;
576 data->status.channel = params->channel;
577 }
578
579 ret = esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
580 if (ret) {
581 LOG_ERR("Failed to set Wi-Fi configuration (%d)", ret);
582 return -EINVAL;
583 }
584
585 ret = esp_wifi_connect();
586 if (ret) {
587 LOG_ERR("Failed to connect to Wi-Fi access point (%d)", ret);
588 return -EAGAIN;
589 }
590
591 return 0;
592 }
593
esp32_wifi_scan(const struct device * dev,struct wifi_scan_params * params,scan_result_cb_t cb)594 static int esp32_wifi_scan(const struct device *dev, struct wifi_scan_params *params,
595 scan_result_cb_t cb)
596 {
597 struct esp32_wifi_runtime *data = dev->data;
598 int ret = 0;
599
600 if (data->scan_cb != NULL) {
601 LOG_INF("Scan callback in progress");
602 return -EINPROGRESS;
603 }
604
605 data->scan_cb = cb;
606
607 wifi_scan_config_t scan_config = { 0 };
608
609 if (params) {
610 /* The enum values are same, so, no conversion needed */
611 scan_config.scan_type = params->scan_type;
612 }
613
614 #if defined(CONFIG_ESP32_WIFI_AP_STA_MODE)
615 wifi_mode_t mode;
616
617 esp_wifi_get_mode(&mode);
618 if (mode == ESP32_WIFI_MODE_AP || mode == ESP32_WIFI_MODE_APSTA) {
619 ret = esp_wifi_set_mode(ESP32_WIFI_MODE_APSTA);
620 } else {
621 ret = esp_wifi_set_mode(ESP32_WIFI_MODE_STA);
622 }
623 #else
624 ret = esp_wifi_set_mode(ESP32_WIFI_MODE_STA);
625 #endif
626
627 if (ret) {
628 LOG_ERR("Failed to set Wi-Fi mode (%d)", ret);
629 return -EINVAL;
630 }
631
632 ret = esp_wifi_start();
633 if (ret) {
634 LOG_ERR("Failed to start Wi-Fi driver (%d)", ret);
635 return -EAGAIN;
636 }
637
638 ret = esp_wifi_scan_start(&scan_config, false);
639 if (ret != ESP_OK) {
640 LOG_ERR("Failed to start Wi-Fi scanning");
641 return -EAGAIN;
642 }
643
644 return 0;
645 };
646
esp32_wifi_ap_enable(const struct device * dev,struct wifi_connect_req_params * params)647 static int esp32_wifi_ap_enable(const struct device *dev,
648 struct wifi_connect_req_params *params)
649 {
650 struct esp32_wifi_runtime *data = dev->data;
651 esp_err_t err = 0;
652
653 /* Build Wi-Fi configuration for AP mode */
654 wifi_config_t wifi_config = {
655 .ap = {
656 .max_connection = 5,
657 .channel = params->channel == WIFI_CHANNEL_ANY ?
658 0 : params->channel,
659 },
660 };
661
662 memcpy(data->status.ssid, params->ssid, params->ssid_length);
663 data->status.ssid[params->ssid_length] = '\0';
664
665 strncpy((char *) wifi_config.ap.ssid, params->ssid, params->ssid_length);
666 wifi_config.ap.ssid_len = params->ssid_length;
667
668 switch (params->security) {
669 case WIFI_SECURITY_TYPE_NONE:
670 memset(wifi_config.ap.password, 0, sizeof(wifi_config.ap.password));
671 wifi_config.ap.authmode = WIFI_AUTH_OPEN;
672 data->status.security = WIFI_AUTH_OPEN;
673 wifi_config.ap.pmf_cfg.required = false;
674 break;
675 case WIFI_SECURITY_TYPE_PSK:
676 strncpy((char *) wifi_config.ap.password, params->psk, params->psk_length);
677 wifi_config.ap.authmode = WIFI_AUTH_WPA2_PSK;
678 data->status.security = WIFI_AUTH_WPA2_PSK;
679 wifi_config.ap.pmf_cfg.required = false;
680 break;
681 default:
682 LOG_ERR("Authentication method not supported");
683 return -EINVAL;
684 }
685
686 /* Start Wi-Fi in AP mode with configuration built above */
687 wifi_mode_t mode;
688
689 err = esp_wifi_get_mode(&mode);
690 if (IS_ENABLED(CONFIG_ESP32_WIFI_AP_STA_MODE) &&
691 (mode == ESP32_WIFI_MODE_STA || mode == ESP32_WIFI_MODE_APSTA)) {
692 err |= esp_wifi_set_mode(ESP32_WIFI_MODE_APSTA);
693 } else {
694 err |= esp_wifi_set_mode(ESP32_WIFI_MODE_AP);
695 }
696 if (err) {
697 LOG_ERR("Failed to set Wi-Fi mode (%d)", err);
698 return -EINVAL;
699 }
700
701 err = esp_wifi_set_config(WIFI_IF_AP, &wifi_config);
702 if (err) {
703 LOG_ERR("Failed to set Wi-Fi configuration (%d)", err);
704 return -EINVAL;
705 }
706
707 err = esp_wifi_start();
708 if (err) {
709 LOG_ERR("Failed to enable Wi-Fi AP mode");
710 return -EAGAIN;
711 }
712
713 return 0;
714 };
715
esp32_wifi_ap_disable(const struct device * dev)716 static int esp32_wifi_ap_disable(const struct device *dev)
717 {
718 int err = 0;
719 wifi_mode_t mode;
720
721 esp_wifi_get_mode(&mode);
722 if (mode == ESP32_WIFI_MODE_APSTA) {
723 err = esp_wifi_set_mode(ESP32_WIFI_MODE_STA);
724 err |= esp_wifi_start();
725 } else {
726 err = esp_wifi_stop();
727 }
728 if (err) {
729 LOG_ERR("Failed to disable Wi-Fi AP mode: (%d)", err);
730 return -EAGAIN;
731 }
732
733 return 0;
734 };
735
esp32_wifi_status(const struct device * dev,struct wifi_iface_status * status)736 static int esp32_wifi_status(const struct device *dev, struct wifi_iface_status *status)
737 {
738 struct esp32_wifi_runtime *data = dev->data;
739 wifi_mode_t mode;
740 wifi_config_t conf;
741 wifi_ap_record_t ap_info;
742
743 switch (data->state) {
744 case ESP32_STA_STOPPED:
745 case ESP32_AP_STOPPED:
746 status->state = WIFI_STATE_INACTIVE;
747 break;
748 case ESP32_STA_STARTED:
749 case ESP32_AP_DISCONNECTED:
750 status->state = WIFI_STATE_DISCONNECTED;
751 break;
752 case ESP32_STA_CONNECTING:
753 status->state = WIFI_STATE_SCANNING;
754 break;
755 case ESP32_STA_CONNECTED:
756 case ESP32_AP_CONNECTED:
757 status->state = WIFI_STATE_COMPLETED;
758 break;
759 default:
760 break;
761 }
762
763 strncpy(status->ssid, data->status.ssid, WIFI_SSID_MAX_LEN);
764 status->ssid_len = strnlen(data->status.ssid, WIFI_SSID_MAX_LEN);
765 status->ssid[status->ssid_len] = '\0';
766 status->band = WIFI_FREQ_BAND_2_4_GHZ;
767 status->link_mode = WIFI_LINK_MODE_UNKNOWN;
768 status->mfp = WIFI_MFP_DISABLE;
769
770 if (esp_wifi_get_mode(&mode) == ESP_OK) {
771 if (mode == ESP32_WIFI_MODE_STA) {
772 wifi_phy_mode_t phy_mode;
773 esp_err_t err;
774
775 esp_wifi_get_config(ESP_IF_WIFI_STA, &conf);
776 esp_wifi_sta_get_ap_info(&ap_info);
777
778 status->iface_mode = WIFI_MODE_INFRA;
779 status->channel = ap_info.primary;
780 status->rssi = ap_info.rssi;
781 memcpy(status->bssid, ap_info.bssid, WIFI_MAC_ADDR_LEN);
782
783 err = esp_wifi_sta_get_negotiated_phymode(&phy_mode);
784 if (err == ESP_OK) {
785 if (phy_mode == WIFI_PHY_MODE_11B) {
786 status->link_mode = WIFI_1;
787 } else if (phy_mode == WIFI_PHY_MODE_11G) {
788 status->link_mode = WIFI_3;
789 } else if ((phy_mode == WIFI_PHY_MODE_HT20) ||
790 (phy_mode == WIFI_PHY_MODE_HT40)) {
791 status->link_mode = WIFI_4;
792 } else if (phy_mode == WIFI_PHY_MODE_HE20) {
793 status->link_mode = WIFI_6;
794 }
795 }
796
797 status->beacon_interval = conf.sta.listen_interval;
798 } else if (mode == ESP32_WIFI_MODE_AP) {
799 esp_wifi_get_config(ESP_IF_WIFI_AP, &conf);
800 status->iface_mode = WIFI_MODE_AP;
801 status->link_mode = WIFI_LINK_MODE_UNKNOWN;
802 status->channel = conf.ap.channel;
803 status->beacon_interval = conf.ap.beacon_interval;
804
805 } else {
806 status->iface_mode = WIFI_MODE_UNKNOWN;
807 status->link_mode = WIFI_LINK_MODE_UNKNOWN;
808 status->channel = 0;
809 }
810 }
811
812 switch (data->status.security) {
813 case WIFI_AUTH_OPEN:
814 status->security = WIFI_SECURITY_TYPE_NONE;
815 break;
816 case WIFI_AUTH_WPA2_PSK:
817 status->security = WIFI_SECURITY_TYPE_PSK;
818 break;
819 case WIFI_AUTH_WPA3_PSK:
820 status->security = WIFI_SECURITY_TYPE_SAE;
821 break;
822 default:
823 status->security = WIFI_SECURITY_TYPE_UNKNOWN;
824 }
825
826 return 0;
827 }
828
esp32_wifi_init(struct net_if * iface)829 static void esp32_wifi_init(struct net_if *iface)
830 {
831 const struct device *dev = net_if_get_device(iface);
832 struct esp32_wifi_runtime *dev_data = dev->data;
833 struct ethernet_context *eth_ctx = net_if_l2_data(iface);
834
835 eth_ctx->eth_if_type = L2_ETH_IF_TYPE_WIFI;
836
837 #if defined(CONFIG_ESP32_WIFI_AP_STA_MODE)
838 struct wifi_nm_instance *nm = wifi_nm_get_instance("esp32_wifi_nm");
839
840 if (!esp32_wifi_iface_ap) {
841 esp32_wifi_iface_ap = iface;
842 dev_data->state = ESP32_AP_STOPPED;
843
844 esp_read_mac(dev_data->mac_addr, ESP_MAC_WIFI_SOFTAP);
845 wifi_nm_register_mgd_type_iface(nm, WIFI_TYPE_SAP, esp32_wifi_iface_ap);
846 } else {
847 esp32_wifi_iface = iface;
848 dev_data->state = ESP32_STA_STOPPED;
849
850 /* Start interface when we are actually connected with Wi-Fi network */
851 esp_read_mac(dev_data->mac_addr, ESP_MAC_WIFI_STA);
852 esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, eth_esp32_rx);
853 wifi_nm_register_mgd_type_iface(nm, WIFI_TYPE_STA, esp32_wifi_iface);
854 }
855 #else
856
857 esp32_wifi_iface = iface;
858 dev_data->state = ESP32_STA_STOPPED;
859
860 /* Start interface when we are actually connected with Wi-Fi network */
861 esp_read_mac(dev_data->mac_addr, ESP_MAC_WIFI_STA);
862 esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, eth_esp32_rx);
863
864 #endif
865
866 /* Assign link local address. */
867 net_if_set_link_addr(iface, dev_data->mac_addr, 6, NET_LINK_ETHERNET);
868
869 ethernet_init(iface);
870 net_if_carrier_off(iface);
871 }
872
873 #if defined(CONFIG_NET_STATISTICS_WIFI)
esp32_wifi_stats(const struct device * dev,struct net_stats_wifi * stats)874 static int esp32_wifi_stats(const struct device *dev, struct net_stats_wifi *stats)
875 {
876 struct esp32_wifi_runtime *data = dev->data;
877
878 stats->bytes.received = data->stats.bytes.received;
879 stats->bytes.sent = data->stats.bytes.sent;
880 stats->pkts.rx = data->stats.pkts.rx;
881 stats->pkts.tx = data->stats.pkts.tx;
882 stats->errors.rx = data->stats.errors.rx;
883 stats->errors.tx = data->stats.errors.tx;
884 stats->broadcast.rx = data->stats.broadcast.rx;
885 stats->broadcast.tx = data->stats.broadcast.tx;
886 stats->multicast.rx = data->stats.multicast.rx;
887 stats->multicast.tx = data->stats.multicast.tx;
888 stats->sta_mgmt.beacons_rx = data->stats.sta_mgmt.beacons_rx;
889 stats->sta_mgmt.beacons_miss = data->stats.sta_mgmt.beacons_miss;
890
891 return 0;
892 }
893 #endif
894
esp32_wifi_dev_init(const struct device * dev)895 static int esp32_wifi_dev_init(const struct device *dev)
896 {
897 #if CONFIG_SOC_SERIES_ESP32S2 || CONFIG_SOC_SERIES_ESP32C3
898 adc2_init_code_calibration();
899 #endif /* CONFIG_SOC_SERIES_ESP32S2 || CONFIG_SOC_SERIES_ESP32C3 */
900
901 wifi_init_config_t config = WIFI_INIT_CONFIG_DEFAULT();
902 esp_err_t ret = esp_wifi_init(&config);
903
904 if (ret == ESP_ERR_NO_MEM) {
905 LOG_ERR("Not enough memory to initialize Wi-Fi.");
906 LOG_ERR("Consider increasing CONFIG_HEAP_MEM_POOL_SIZE value.");
907 return -ENOMEM;
908 } else if (ret != ESP_OK) {
909 LOG_ERR("Unable to initialize the Wi-Fi: %d", ret);
910 return -EIO;
911 }
912 if (IS_ENABLED(CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4)) {
913 net_mgmt_init_event_callback(&esp32_dhcp_cb, wifi_event_handler, DHCPV4_MASK);
914 net_mgmt_add_event_callback(&esp32_dhcp_cb);
915 }
916
917 return 0;
918 }
919
920 static const struct wifi_mgmt_ops esp32_wifi_mgmt = {
921 .scan = esp32_wifi_scan,
922 .connect = esp32_wifi_connect,
923 .disconnect = esp32_wifi_disconnect,
924 .ap_enable = esp32_wifi_ap_enable,
925 .ap_disable = esp32_wifi_ap_disable,
926 .iface_status = esp32_wifi_status,
927 #if defined(CONFIG_NET_STATISTICS_WIFI)
928 .get_stats = esp32_wifi_stats,
929 #endif
930 };
931
932 static const struct net_wifi_mgmt_offload esp32_api = {
933 .wifi_iface.iface_api.init = esp32_wifi_init,
934 .wifi_iface.send = esp32_wifi_send,
935 .wifi_mgmt_api = &esp32_wifi_mgmt,
936 };
937
938 NET_DEVICE_DT_INST_DEFINE(0,
939 esp32_wifi_dev_init, NULL,
940 &esp32_data, NULL, CONFIG_WIFI_INIT_PRIORITY,
941 &esp32_api, ETHERNET_L2,
942 NET_L2_GET_CTX_TYPE(ETHERNET_L2), NET_ETH_MTU);
943
944 #if defined(CONFIG_ESP32_WIFI_AP_STA_MODE)
945 NET_DEVICE_DT_INST_DEFINE(1,
946 NULL, NULL,
947 &esp32_ap_sta_data, NULL, CONFIG_WIFI_INIT_PRIORITY,
948 &esp32_api, ETHERNET_L2,
949 NET_L2_GET_CTX_TYPE(ETHERNET_L2), NET_ETH_MTU);
950
951 DEFINE_WIFI_NM_INSTANCE(esp32_wifi_nm, &esp32_wifi_mgmt);
952
953 CONNECTIVITY_WIFI_MGMT_BIND(Z_DEVICE_DT_DEV_ID(DT_DRV_INST(0)));
954 #endif
955