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