1 /*
2  * SPDX-FileCopyrightText: 2016 Intel Corporation
3  * SPDX-FileCopyrightText: 2016 Wind River Systems, Inc.
4  * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <errno.h>
10 
11 #include "osi/hash_map.h"
12 #include "osi/alarm.h"
13 #include "osi/hash_functions.h"
14 
15 #include "mesh_common.h"
16 #include "provisioner_prov.h"
17 
18 static hash_map_t *bm_alarm_hash_map;
19 static const size_t BLE_MESH_GENERAL_ALARM_HASH_MAP_SIZE = 20 + CONFIG_BLE_MESH_PBA_SAME_TIME + \
20         CONFIG_BLE_MESH_PBG_SAME_TIME;
21 
22 typedef struct alarm_t {
23     /* timer id point to here */
24     esp_timer_handle_t alarm_hdl;
25     osi_alarm_callback_t cb;
26     void *cb_data;
27     int64_t deadline_us;
28 } osi_alarm_t;
29 
k_uptime_get(void)30 int64_t k_uptime_get(void)
31 {
32     /* k_uptime_get_32 is in in milliseconds,
33      * but esp_timer_get_time is in microseconds
34      */
35     return (esp_timer_get_time() / 1000);
36 }
37 
k_uptime_get_32(void)38 uint32_t k_uptime_get_32(void)
39 {
40     /* k_uptime_get_32 is in in milliseconds,
41      * but esp_timer_get_time is in microseconds
42      */
43     return (uint32_t)(esp_timer_get_time() / 1000);
44 }
45 
bt_mesh_timer_init(void)46 void bt_mesh_timer_init(void)
47 {
48     bm_alarm_hash_map = hash_map_new(BLE_MESH_GENERAL_ALARM_HASH_MAP_SIZE,
49                                      hash_function_pointer, NULL,
50                                      (data_free_fn)osi_alarm_free, NULL);
51     __ASSERT(bm_alarm_hash_map, "Failed to create hash map");
52 }
53 
54 #if CONFIG_BLE_MESH_DEINIT
bt_mesh_timer_deinit(void)55 void bt_mesh_timer_deinit(void)
56 {
57     if (bm_alarm_hash_map) {
58         hash_map_free(bm_alarm_hash_map);
59         bm_alarm_hash_map = NULL;
60     }
61 }
62 #endif /* CONFIG_BLE_MESH_DEINIT */
63 
k_delayed_work_init(struct k_delayed_work * work,k_work_handler_t handler)64 int k_delayed_work_init(struct k_delayed_work *work, k_work_handler_t handler)
65 {
66     osi_alarm_t *alarm = NULL;
67 
68     if (!work || !bm_alarm_hash_map) {
69         BT_ERR("%s, Invalid parameter", __func__);
70         return -EINVAL;
71     }
72 
73     k_work_init(&work->work, handler);
74 
75     bt_mesh_alarm_lock();
76     if (!hash_map_has_key(bm_alarm_hash_map, (void *)work)) {
77         alarm = osi_alarm_new("bt_mesh", (osi_alarm_callback_t)handler, (void *)&work->work, 0);
78         if (alarm == NULL) {
79             BT_ERR("Alarm not created");
80             bt_mesh_alarm_unlock();
81             return -EIO;
82         }
83         if (!hash_map_set(bm_alarm_hash_map, work, (void *)alarm)) {
84             BT_ERR("Alarm not set");
85             bt_mesh_alarm_unlock();
86             return -EIO;
87         }
88     }
89 
90     alarm = hash_map_get(bm_alarm_hash_map, work);
91     if (alarm == NULL) {
92         BT_ERR("Init, alarm not found");
93         bt_mesh_alarm_unlock();
94         return -ENODEV;
95     }
96 
97     // Just init the work timer only, don't start it.
98     osi_alarm_cancel(alarm);
99     bt_mesh_alarm_unlock();
100     return 0;
101 }
102 
k_delayed_work_submit(struct k_delayed_work * work,int32_t delay)103 int k_delayed_work_submit(struct k_delayed_work *work, int32_t delay)
104 {
105     if (!work || !bm_alarm_hash_map) {
106         BT_ERR("%s, Invalid parameter", __func__);
107         return -EINVAL;
108     }
109 
110     bt_mesh_alarm_lock();
111     osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
112     if (alarm == NULL) {
113         BT_WARN("Submit, alarm not found");
114         bt_mesh_alarm_unlock();
115         return -EINVAL;
116     }
117 
118     // Cancel the alarm first, before start the alarm.
119     osi_alarm_cancel(alarm);
120     osi_alarm_set(alarm, delay);
121     bt_mesh_alarm_unlock();
122     return 0;
123 }
124 
k_delayed_work_submit_periodic(struct k_delayed_work * work,int32_t period)125 int k_delayed_work_submit_periodic(struct k_delayed_work *work, int32_t period)
126 {
127     if (!work || !bm_alarm_hash_map) {
128         BT_ERR("%s, Invalid parameter", __func__);
129         return -EINVAL;
130     }
131 
132     bt_mesh_alarm_lock();
133     osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
134     if (alarm == NULL) {
135         BT_WARN("Submit, alarm not found");
136         bt_mesh_alarm_unlock();
137         return -EINVAL;
138     }
139 
140     /* Cancel the alarm first before starting it. */
141     osi_alarm_cancel(alarm);
142     osi_alarm_set_periodic(alarm, period);
143     bt_mesh_alarm_unlock();
144     return 0;
145 }
146 
k_delayed_work_cancel(struct k_delayed_work * work)147 int k_delayed_work_cancel(struct k_delayed_work *work)
148 {
149     if (!work || !bm_alarm_hash_map) {
150         BT_ERR("%s, Invalid parameter", __func__);
151         return -EINVAL;
152     }
153 
154     bt_mesh_alarm_lock();
155     osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
156     if (alarm == NULL) {
157         BT_WARN("Cancel, alarm not found");
158         bt_mesh_alarm_unlock();
159         return -EINVAL;
160     }
161 
162     osi_alarm_cancel(alarm);
163     alarm->deadline_us = 0;
164     bt_mesh_alarm_unlock();
165     return 0;
166 }
167 
k_delayed_work_free(struct k_delayed_work * work)168 int k_delayed_work_free(struct k_delayed_work *work)
169 {
170     if (!work || !bm_alarm_hash_map) {
171         BT_ERR("%s, Invalid parameter", __func__);
172         return -EINVAL;
173     }
174 
175     bt_mesh_alarm_lock();
176     osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, work);
177     if (alarm == NULL) {
178         BT_WARN("Free, alarm not found");
179         bt_mesh_alarm_unlock();
180         return -EINVAL;
181     }
182 
183     osi_alarm_cancel(alarm);
184     hash_map_erase(bm_alarm_hash_map, work);
185     bt_mesh_alarm_unlock();
186     return 0;
187 }
188 
k_delayed_work_remaining_get(struct k_delayed_work * work)189 int32_t k_delayed_work_remaining_get(struct k_delayed_work *work)
190 {
191     int32_t time = 0;
192 
193     if (!work || !bm_alarm_hash_map) {
194         BT_ERR("%s, Invalid parameter", __func__);
195         return 0;
196     }
197 
198     bt_mesh_alarm_lock();
199     osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
200     if (alarm == NULL) {
201         BT_WARN("Get time, alarm not found");
202         bt_mesh_alarm_unlock();
203         return 0;
204     }
205 
206     time = osi_alarm_get_remaining_ms(alarm);
207     bt_mesh_alarm_unlock();
208     return time;
209 }
210