mesh_timer.c
1 /* 2 * Copyright (c) 2016 Intel Corporation 3 * Copyright (c) 2016 Wind River Systems, Inc. 4 * Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE 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 30 s64_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 38 u32_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 (u32_t)(esp_timer_get_time() / 1000); 44 } 45 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 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 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 103 int k_delayed_work_submit(struct k_delayed_work *work, s32_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 125 int k_delayed_work_submit_periodic(struct k_delayed_work *work, s32_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 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 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 189 s32_t k_delayed_work_remaining_get(struct k_delayed_work *work) 190 { 191 s32_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 }