summaryrefslogtreecommitdiff
path: root/lib/bt/esp_ble_mesh/common/timer.c
diff options
context:
space:
mode:
authorailurux <ailuruxx@gmail.com>2024-03-28 16:17:39 +1100
committerailurux <ailuruxx@gmail.com>2024-03-28 16:17:39 +1100
commitc8e67cbd80b53a4e889ce0485546042d5490918c (patch)
treef06314fef2bb9afaf04b924355b34f5277d69241 /lib/bt/esp_ble_mesh/common/timer.c
parentf1c8866b815a92aeda3133fd27051ce7c873cc57 (diff)
parent35a822fe602cdc9e3a3482df3913ea33af6fc8c2 (diff)
downloadtangara-fw-c8e67cbd80b53a4e889ce0485546042d5490918c.tar.gz
Merge branch 'main' into themes
Diffstat (limited to 'lib/bt/esp_ble_mesh/common/timer.c')
-rw-r--r--lib/bt/esp_ble_mesh/common/timer.c247
1 files changed, 247 insertions, 0 deletions
diff --git a/lib/bt/esp_ble_mesh/common/timer.c b/lib/bt/esp_ble_mesh/common/timer.c
new file mode 100644
index 00000000..0d65bd3a
--- /dev/null
+++ b/lib/bt/esp_ble_mesh/common/timer.c
@@ -0,0 +1,247 @@
+/*
+ * SPDX-FileCopyrightText: 2016 Intel Corporation
+ * SPDX-FileCopyrightText: 2016 Wind River Systems, Inc.
+ * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <errno.h>
+
+#include "osi/hash_map.h"
+#include "osi/alarm.h"
+#include "osi/hash_functions.h"
+
+#include "mesh/config.h"
+#include "mesh/common.h"
+
+static hash_map_t *bm_alarm_hash_map;
+static const size_t BLE_MESH_ALARM_HASH_MAP_SIZE = 20 + CONFIG_BLE_MESH_PBA_SAME_TIME +
+ CONFIG_BLE_MESH_PBG_SAME_TIME;
+
+typedef struct alarm_t {
+ /* timer id point to here */
+ esp_timer_handle_t alarm_hdl;
+ osi_alarm_callback_t cb;
+ void *cb_data;
+ int64_t deadline_us;
+} osi_alarm_t;
+
+int64_t k_uptime_get(void)
+{
+ /* k_uptime_get_32 is in in milliseconds,
+ * but esp_timer_get_time is in microseconds
+ */
+ return (esp_timer_get_time() / 1000);
+}
+
+uint32_t k_uptime_get_32(void)
+{
+ /* k_uptime_get_32 is in in milliseconds,
+ * but esp_timer_get_time is in microseconds
+ */
+ return (uint32_t)(esp_timer_get_time() / 1000);
+}
+
+void bt_mesh_timer_init(void)
+{
+ bm_alarm_hash_map = hash_map_new(BLE_MESH_ALARM_HASH_MAP_SIZE,
+ hash_function_pointer, NULL,
+ (data_free_fn)osi_alarm_free, NULL);
+ __ASSERT(bm_alarm_hash_map, "Failed to create hash map");
+}
+
+#if CONFIG_BLE_MESH_DEINIT
+void bt_mesh_timer_deinit(void)
+{
+ if (bm_alarm_hash_map) {
+ hash_map_free(bm_alarm_hash_map);
+ bm_alarm_hash_map = NULL;
+ }
+}
+#endif /* CONFIG_BLE_MESH_DEINIT */
+
+int k_delayed_work_init(struct k_delayed_work *work, k_work_handler_t handler)
+{
+ osi_alarm_t *alarm = NULL;
+
+ if (!work || !bm_alarm_hash_map) {
+ BT_ERR("%s, Invalid parameter", __func__);
+ return -EINVAL;
+ }
+
+ k_work_init(&work->work, handler);
+
+ bt_mesh_alarm_lock();
+
+ alarm = hash_map_get(bm_alarm_hash_map, work);
+ if (alarm) {
+ BT_ERR("Init, alarm already exists");
+ bt_mesh_alarm_unlock();
+ return -EEXIST;
+ }
+
+ alarm = osi_alarm_new("bt_mesh", (osi_alarm_callback_t)handler, (void *)&work->work, 0);
+ if (alarm == NULL) {
+ BT_ERR("Init, alarm not created");
+ bt_mesh_alarm_unlock();
+ return -EIO;
+ }
+
+ if (!hash_map_set(bm_alarm_hash_map, work, (void *)alarm)) {
+ BT_ERR("Init, alarm not set");
+ bt_mesh_alarm_unlock();
+ return -EIO;
+ }
+
+ // Just init the work timer only, don't start it.
+ osi_alarm_cancel(alarm);
+
+ bt_mesh_alarm_unlock();
+
+ return 0;
+}
+
+int k_delayed_work_submit(struct k_delayed_work *work, int32_t delay)
+{
+ osi_alarm_t *alarm = NULL;
+
+ if (!work || !bm_alarm_hash_map) {
+ BT_ERR("%s, Invalid parameter", __func__);
+ return -EINVAL;
+ }
+
+ /* If delay is 0, call the corresponding timeout handler. */
+ if (delay == 0) {
+ k_work_submit(&work->work);
+ return 0;
+ }
+
+ bt_mesh_alarm_lock();
+
+ alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
+ if (alarm == NULL) {
+ BT_WARN("Submit, alarm not found");
+ bt_mesh_alarm_unlock();
+ return -EINVAL;
+ }
+
+ // Cancel the alarm first, before start the alarm.
+ osi_alarm_cancel(alarm);
+ osi_alarm_set(alarm, delay);
+
+ bt_mesh_alarm_unlock();
+
+ return 0;
+}
+
+int k_delayed_work_submit_periodic(struct k_delayed_work *work, int32_t period)
+{
+ osi_alarm_t *alarm = NULL;
+
+ if (!work || !bm_alarm_hash_map) {
+ BT_ERR("%s, Invalid parameter", __func__);
+ return -EINVAL;
+ }
+
+ /* If period is 0, call the corresponding timeout handler. */
+ if (period == 0) {
+ k_work_submit(&work->work);
+ return 0;
+ }
+
+ bt_mesh_alarm_lock();
+
+ alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
+ if (alarm == NULL) {
+ BT_WARN("Submit, alarm not found");
+ bt_mesh_alarm_unlock();
+ return -EINVAL;
+ }
+
+ /* Cancel the alarm first before starting it. */
+ osi_alarm_cancel(alarm);
+ osi_alarm_set_periodic(alarm, period);
+
+ bt_mesh_alarm_unlock();
+
+ return 0;
+}
+
+int k_delayed_work_cancel(struct k_delayed_work *work)
+{
+ osi_alarm_t *alarm = NULL;
+
+ if (!work || !bm_alarm_hash_map) {
+ BT_ERR("%s, Invalid parameter", __func__);
+ return -EINVAL;
+ }
+
+ bt_mesh_alarm_lock();
+
+ alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
+ if (alarm == NULL) {
+ BT_WARN("Cancel, alarm not found");
+ bt_mesh_alarm_unlock();
+ return -EINVAL;
+ }
+
+ osi_alarm_cancel(alarm);
+ alarm->deadline_us = 0;
+
+ bt_mesh_alarm_unlock();
+
+ return 0;
+}
+
+int k_delayed_work_free(struct k_delayed_work *work)
+{
+ osi_alarm_t *alarm = NULL;
+
+ if (!work || !bm_alarm_hash_map) {
+ BT_ERR("%s, Invalid parameter", __func__);
+ return -EINVAL;
+ }
+
+ bt_mesh_alarm_lock();
+
+ alarm = hash_map_get(bm_alarm_hash_map, work);
+ if (alarm == NULL) {
+ BT_DBG("Free, alarm not found");
+ bt_mesh_alarm_unlock();
+ return -EINVAL;
+ }
+
+ osi_alarm_cancel(alarm);
+ hash_map_erase(bm_alarm_hash_map, work);
+
+ bt_mesh_alarm_unlock();
+
+ return 0;
+}
+
+int32_t k_delayed_work_remaining_get(struct k_delayed_work *work)
+{
+ osi_alarm_t *alarm = NULL;
+ int32_t time = 0;
+
+ if (!work || !bm_alarm_hash_map) {
+ BT_ERR("%s, Invalid parameter", __func__);
+ return 0;
+ }
+
+ bt_mesh_alarm_lock();
+
+ alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
+ if (alarm == NULL) {
+ BT_WARN("Get time, alarm not found");
+ bt_mesh_alarm_unlock();
+ return 0;
+ }
+
+ time = osi_alarm_get_remaining_ms(alarm);
+
+ bt_mesh_alarm_unlock();
+
+ return time;
+}