1 /*
2  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <esp_event.h>
8 #include <esp_wifi.h>
9 #include "esp_log.h"
10 #include "esp_private/wifi.h"
11 #include "esp_pm.h"
12 #include "esp_sleep.h"
13 #include "esp_private/pm_impl.h"
14 #include "soc/rtc.h"
15 #include "esp_wpa.h"
16 #include "esp_netif.h"
17 #include "tcpip_adapter_compatible/tcpip_adapter_compat.h"
18 #include "driver/adc2_wifi_private.h"
19 #include "esp_coexist_internal.h"
20 #include "esp_phy_init.h"
21 #include "phy.h"
22 
23 #if (CONFIG_ESP32_WIFI_RX_BA_WIN > CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM)
24 #error "WiFi configuration check: WARNING, WIFI_RX_BA_WIN should not be larger than WIFI_DYNAMIC_RX_BUFFER_NUM!"
25 #endif
26 
27 #if (CONFIG_ESP32_WIFI_RX_BA_WIN > (CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM << 1))
28 #error "WiFi configuration check: WARNING, WIFI_RX_BA_WIN should not be larger than double of the WIFI_STATIC_RX_BUFFER_NUM!"
29 #endif
30 
31 ESP_EVENT_DEFINE_BASE(WIFI_EVENT);
32 
33 extern uint8_t esp_wifi_get_user_init_flag_internal(void);
34 #ifdef CONFIG_PM_ENABLE
35 static esp_pm_lock_handle_t s_wifi_modem_sleep_lock;
36 #endif
37 
38 /* Set additional WiFi features and capabilities */
39 uint64_t g_wifi_feature_caps =
40 #if CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE
41     CONFIG_FEATURE_WPA3_SAE_BIT |
42 #endif
43 #if (CONFIG_ESP32_SPIRAM_SUPPORT || CONFIG_ESP32S2_SPIRAM_SUPPORT || CONFIG_ESP32S3_SPIRAM_SUPPORT)
44     CONFIG_FEATURE_CACHE_TX_BUF_BIT |
45 #endif
46 #if CONFIG_ESP_WIFI_FTM_INITIATOR_SUPPORT
47     CONFIG_FEATURE_FTM_INITIATOR_BIT |
48 #endif
49 #if CONFIG_ESP_WIFI_FTM_RESPONDER_SUPPORT
50     CONFIG_FEATURE_FTM_RESPONDER_BIT |
51 #endif
52 0;
53 
54 
55 static const char* TAG = "wifi_init";
56 
s_set_default_wifi_log_level(void)57 static void __attribute__((constructor)) s_set_default_wifi_log_level(void)
58 {
59     /* WiFi libraries aren't compiled to know CONFIG_LOG_DEFAULT_LEVEL,
60        so set it at runtime startup. Done here not in esp_wifi_init() to allow
61        the user to set the level again before esp_wifi_init() is called.
62     */
63     esp_log_level_set("wifi", CONFIG_LOG_DEFAULT_LEVEL);
64     esp_log_level_set("mesh", CONFIG_LOG_DEFAULT_LEVEL);
65     esp_log_level_set("smartconfig", CONFIG_LOG_DEFAULT_LEVEL);
66     esp_log_level_set("ESPNOW", CONFIG_LOG_DEFAULT_LEVEL);
67 }
68 
esp_wifi_set_log_level(void)69 static void esp_wifi_set_log_level(void)
70 {
71     wifi_log_level_t wifi_log_level = WIFI_LOG_INFO;
72     /* set WiFi log level */
73 #if CONFIG_LOG_MAXIMUM_LEVEL == 0
74     wifi_log_level = WIFI_LOG_NONE;
75 #elif CONFIG_LOG_MAXIMUM_LEVEL == 1
76     wifi_log_level = WIFI_LOG_ERROR;
77 #elif CONFIG_LOG_MAXIMUM_LEVEL == 2
78     wifi_log_level = WIFI_LOG_WARNING;
79 #elif CONFIG_LOG_MAXIMUM_LEVEL == 3
80     wifi_log_level = WIFI_LOG_INFO;
81 #elif CONFIG_LOG_MAXIMUM_LEVEL == 4
82     wifi_log_level = WIFI_LOG_DEBUG;
83 #elif CONFIG_LOG_MAXIMUM_LEVEL == 5
84     wifi_log_level = WIFI_LOG_VERBOSE;
85 #endif
86     esp_wifi_internal_set_log_level(wifi_log_level);
87 }
88 
esp_wifi_deinit(void)89 esp_err_t esp_wifi_deinit(void)
90 {
91     esp_err_t err = ESP_OK;
92 
93     if (esp_wifi_get_user_init_flag_internal()) {
94         ESP_LOGE(TAG, "Wi-Fi not stop");
95         return ESP_ERR_WIFI_NOT_STOPPED;
96     }
97 
98     if (esp_wifi_internal_reg_rxcb(WIFI_IF_STA,  NULL) != ESP_OK ||
99         esp_wifi_internal_reg_rxcb(WIFI_IF_AP,  NULL) != ESP_OK) {
100         ESP_LOGW(TAG, "Failed to unregister Rx callbacks");
101     }
102 
103     esp_supplicant_deinit();
104     err = esp_wifi_deinit_internal();
105     if (err != ESP_OK) {
106         ESP_LOGE(TAG, "Failed to deinit Wi-Fi driver (0x%x)", err);
107         return err;
108     }
109 
110 #if CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER
111     tcpip_adapter_clear_default_wifi_handlers();
112 #endif
113 #if CONFIG_ESP_WIFI_SLP_IRAM_OPT
114     esp_pm_unregister_light_sleep_default_params_config_callback();
115 #endif
116 #if CONFIG_FREERTOS_USE_TICKLESS_IDLE
117 #if SOC_WIFI_HW_TSF
118     esp_pm_unregister_skip_light_sleep_callback(esp_wifi_internal_is_tsf_active);
119     esp_pm_unregister_inform_out_light_sleep_overhead_callback(esp_wifi_internal_update_light_sleep_wake_ahead_time);
120     esp_sleep_disable_wifi_wakeup();
121 #endif
122 #endif
123 #if CONFIG_MAC_BB_PD
124     esp_unregister_mac_bb_pd_callback(pm_mac_sleep);
125     esp_unregister_mac_bb_pu_callback(pm_mac_wakeup);
126 #endif
127 #if CONFIG_IDF_TARGET_ESP32C3
128     phy_init_flag();
129 #endif
130     esp_wifi_power_domain_off();
131     return err;
132 }
133 
esp_wifi_config_info(void)134 static void esp_wifi_config_info(void)
135 {
136 #ifdef CONFIG_ESP32_WIFI_RX_BA_WIN
137     ESP_LOGI(TAG, "rx ba win: %d", CONFIG_ESP32_WIFI_RX_BA_WIN);
138 #endif
139 
140 #ifdef CONFIG_ESP_NETIF_TCPIP_LWIP
141     ESP_LOGI(TAG, "tcpip mbox: %d", CONFIG_LWIP_TCPIP_RECVMBOX_SIZE);
142     ESP_LOGI(TAG, "udp mbox: %d", CONFIG_LWIP_UDP_RECVMBOX_SIZE);
143     ESP_LOGI(TAG, "tcp mbox: %d", CONFIG_LWIP_TCP_RECVMBOX_SIZE);
144     ESP_LOGI(TAG, "tcp tx win: %d", CONFIG_LWIP_TCP_SND_BUF_DEFAULT);
145     ESP_LOGI(TAG, "tcp rx win: %d", CONFIG_LWIP_TCP_WND_DEFAULT);
146     ESP_LOGI(TAG, "tcp mss: %d", CONFIG_LWIP_TCP_MSS);
147 
148 #ifdef CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP
149     ESP_LOGI(TAG, "WiFi/LWIP prefer SPIRAM");
150 #endif
151 
152 #ifdef CONFIG_ESP32_WIFI_IRAM_OPT
153     ESP_LOGI(TAG, "WiFi IRAM OP enabled");
154 #endif
155 
156 #ifdef CONFIG_ESP32_WIFI_RX_IRAM_OPT
157     ESP_LOGI(TAG, "WiFi RX IRAM OP enabled");
158 #endif
159 
160 #ifdef CONFIG_ESP_WIFI_SLP_IRAM_OPT
161     ESP_LOGI(TAG, "WiFi SLP IRAM OP enabled");
162 #endif
163 
164 #ifdef CONFIG_LWIP_IRAM_OPTIMIZATION
165     ESP_LOGI(TAG, "LWIP IRAM OP enabled");
166 #endif
167 
168 #else
169     ESP_LOGI(TAG, "LWIP disabled");
170 #endif
171 }
172 
esp_wifi_init(const wifi_init_config_t * config)173 esp_err_t esp_wifi_init(const wifi_init_config_t *config)
174 {
175     esp_wifi_power_domain_on();
176 #ifdef CONFIG_PM_ENABLE
177     if (s_wifi_modem_sleep_lock == NULL) {
178         esp_err_t err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "wifi",
179                 &s_wifi_modem_sleep_lock);
180         if (err != ESP_OK) {
181             return err;
182         }
183     }
184 #endif
185 
186 #if CONFIG_ESP_WIFI_SLP_IRAM_OPT
187     esp_pm_register_light_sleep_default_params_config_callback(esp_wifi_internal_update_light_sleep_default_params);
188 
189     int min_freq_mhz = esp_pm_impl_get_cpu_freq(PM_MODE_LIGHT_SLEEP);
190     int max_freq_mhz = esp_pm_impl_get_cpu_freq(PM_MODE_CPU_MAX);
191     esp_wifi_internal_update_light_sleep_default_params(min_freq_mhz, max_freq_mhz);
192 
193     uint32_t sleep_delay_us = CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME * 1000;
194     esp_wifi_set_sleep_delay_time(sleep_delay_us);
195 
196     uint32_t keep_alive_time_us = CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME * 1000 * 1000;
197     esp_wifi_set_keep_alive_time(keep_alive_time_us);
198 #endif
199 
200 #if CONFIG_FREERTOS_USE_TICKLESS_IDLE
201 #if CONFIG_MAC_BB_PD
202     if (esp_register_mac_bb_pd_callback(pm_mac_sleep) != ESP_OK
203         || esp_register_mac_bb_pu_callback(pm_mac_wakeup) != ESP_OK) {
204 
205         esp_unregister_mac_bb_pd_callback(pm_mac_sleep);
206         esp_unregister_mac_bb_pu_callback(pm_mac_wakeup);
207         return ESP_ERR_INVALID_ARG;
208     }
209 #endif
210 
211 #if SOC_WIFI_HW_TSF
212     esp_err_t ret = esp_pm_register_skip_light_sleep_callback(esp_wifi_internal_is_tsf_active);
213     if (ret != ESP_OK) {
214         ESP_LOGE(TAG, "Failed to register skip light sleep callback (0x%x)", ret);
215 #if CONFIG_MAC_BB_PD
216         esp_unregister_mac_bb_pd_callback(pm_mac_sleep);
217         esp_unregister_mac_bb_pu_callback(pm_mac_wakeup);
218 #endif
219         return ret;
220     }
221     ret = esp_pm_register_inform_out_light_sleep_overhead_callback(esp_wifi_internal_update_light_sleep_wake_ahead_time);
222     if (ret != ESP_OK) {
223         ESP_LOGE(TAG, "Failed to register inform light sleep overhead callback (0x%x)", ret);
224         return ret;
225     }
226     esp_sleep_enable_wifi_wakeup();
227 #endif
228 #endif
229 
230 #if CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER
231     esp_err_t err = tcpip_adapter_set_default_wifi_handlers();
232     if (err != ESP_OK) {
233         ESP_LOGW(TAG, "Failed to set default Wi-Fi event handlers (0x%x)", err);
234     }
235 #endif
236 #if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
237     coex_init();
238 #endif
239     esp_wifi_set_log_level();
240     esp_err_t result = esp_wifi_init_internal(config);
241     if (result == ESP_OK) {
242 #if CONFIG_MAC_BB_PD
243         esp_mac_bb_pd_mem_init();
244         esp_wifi_internal_set_mac_sleep(true);
245 #endif
246 #if CONFIG_IDF_TARGET_ESP32
247         s_wifi_mac_time_update_cb = esp_wifi_internal_update_mac_time;
248 #endif
249 
250         result = esp_supplicant_init();
251         if (result != ESP_OK) {
252             ESP_LOGE(TAG, "Failed to init supplicant (0x%x)", result);
253             esp_err_t deinit_ret = esp_wifi_deinit();
254             if (deinit_ret != ESP_OK) {
255                 ESP_LOGE(TAG, "Failed to deinit Wi-Fi (0x%x)", deinit_ret);
256             }
257 
258             return result;
259         }
260     }
261     adc2_cal_include(); //This enables the ADC2 calibration constructor at start up.
262 
263     esp_wifi_config_info();
264     return result;
265 }
266 
267 #ifdef CONFIG_PM_ENABLE
wifi_apb80m_request(void)268 void wifi_apb80m_request(void)
269 {
270     assert(s_wifi_modem_sleep_lock);
271     esp_pm_lock_acquire(s_wifi_modem_sleep_lock);
272     if (rtc_clk_apb_freq_get() != APB_CLK_FREQ) {
273         ESP_LOGE(__func__, "WiFi needs 80MHz APB frequency to work, but got %dHz", rtc_clk_apb_freq_get());
274     }
275 }
276 
wifi_apb80m_release(void)277 void wifi_apb80m_release(void)
278 {
279     assert(s_wifi_modem_sleep_lock);
280     esp_pm_lock_release(s_wifi_modem_sleep_lock);
281 }
282 #endif //CONFIG_PM_ENABLE
283 
284 #ifndef CONFIG_ESP_WIFI_FTM_ENABLE
ieee80211_ftm_attach(void)285 void ieee80211_ftm_attach(void)
286 {
287     /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
288 }
289 #endif
290 
291 #ifndef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
net80211_softap_funcs_init(void)292 void net80211_softap_funcs_init(void)
293 {
294 }
295 #endif
296