1 /*
2  * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stddef.h>
8 #include <string.h>
9 
10 #include "sdkconfig.h"
11 #include "soc/soc_caps.h"
12 #include "esp_private/sleep_event.h"
13 
14 #include "esp_sleep.h"
15 #include "esp_log.h"
16 #include "esp_check.h"
17 
18 #include <zephyr/kernel.h>
19 
20 static __attribute__((unused)) const char *TAG = "sleep_event";
21 
22 #if CONFIG_ESP_SLEEP_EVENT_CALLBACKS
23 esp_sleep_event_cbs_config_t g_sleep_event_cbs_config;
24 static unsigned int s_sleep_event_mutex;
25 
esp_sleep_register_event_callback(esp_sleep_event_cb_index_t event_id,const esp_sleep_event_cb_config_t * event_cb_conf)26 esp_err_t esp_sleep_register_event_callback(esp_sleep_event_cb_index_t event_id, const esp_sleep_event_cb_config_t *event_cb_conf) {
27     if (event_cb_conf == NULL || event_id >= SLEEP_EVENT_CB_INDEX_NUM) {
28         return ESP_ERR_INVALID_ARG;
29     }
30     esp_sleep_event_cb_config_t *new_config = (esp_sleep_event_cb_config_t *)heap_caps_malloc(sizeof(esp_sleep_event_cb_config_t), MALLOC_CAP_INTERNAL);
31     if (new_config == NULL) {
32         return ESP_ERR_NO_MEM; /* Memory allocation failed */
33     }
34 
35     s_sleep_event_mutex = irq_lock();
36     esp_sleep_event_cb_config_t **current_ptr = &(g_sleep_event_cbs_config.sleep_event_cb_config[event_id]);
37     while (*current_ptr != NULL) {
38         if (((*current_ptr)->cb) == (event_cb_conf->cb)) {
39             free(new_config);
40             irq_unlock(s_sleep_event_mutex);
41             return ESP_FAIL;
42         }
43         current_ptr = &((*current_ptr)->next);
44     }
45 
46     *new_config = *event_cb_conf;
47     while (*current_ptr != NULL && (*current_ptr)->prior <= new_config->prior) {
48         current_ptr = &((*current_ptr)->next);
49     }
50     new_config->next = *current_ptr;
51     *current_ptr = new_config;
52     irq_unlock(s_sleep_event_mutex);
53     return ESP_OK;
54 }
55 
esp_sleep_unregister_event_callback(esp_sleep_event_cb_index_t event_id,esp_sleep_event_cb_t cb)56 esp_err_t esp_sleep_unregister_event_callback(esp_sleep_event_cb_index_t event_id, esp_sleep_event_cb_t cb) {
57     if (cb == NULL || event_id >= SLEEP_EVENT_CB_INDEX_NUM) {
58         return ESP_ERR_INVALID_ARG;
59     }
60     s_sleep_event_mutex = irq_lock();
61     esp_sleep_event_cb_config_t **current_ptr = &(g_sleep_event_cbs_config.sleep_event_cb_config[event_id]);
62     while (*current_ptr != NULL) {
63         if (((*current_ptr)->cb) == cb) {
64             esp_sleep_event_cb_config_t *temp = *current_ptr;
65             *current_ptr = (*current_ptr)->next;
66             free(temp);
67             break;
68         }
69         current_ptr = &((*current_ptr)->next);
70     }
71     irq_unlock(s_sleep_event_mutex);
72     return ESP_OK;
73 }
74 #endif
75 
esp_sleep_execute_event_callbacks(esp_sleep_event_cb_index_t event_id,void * ext_arg)76 void IRAM_ATTR esp_sleep_execute_event_callbacks(esp_sleep_event_cb_index_t event_id, void *ext_arg)
77 {
78 #if CONFIG_ESP_SLEEP_EVENT_CALLBACKS
79     if (event_id >= SLEEP_EVENT_CB_INDEX_NUM) {
80         ESP_EARLY_LOGW(TAG, "event_id out of range");
81         return;
82     }
83     esp_sleep_event_cb_config_t *current = g_sleep_event_cbs_config.sleep_event_cb_config[event_id];
84     while (current != NULL) {
85         if (current->cb != NULL) {
86             if (ESP_OK != (*current->cb)(current->user_arg, ext_arg)) {
87                 ESP_EARLY_LOGW(TAG, "esp_sleep_execute_event_callbacks has an err, current->cb = %p", current->cb);
88             }
89         }
90         current = current->next;
91     }
92 #endif
93 }
94