/ components / bt / esp_ble_mesh / mesh_common / mesh_timer.c
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  }