OVMS3-idf/components/bt/ble_mesh/mesh_core/mesh_kernel.c
Island fc3253163e component/ble_mesh: ESP BLE Mesh release
1. BLE Mesh Core

* Provisioning: Node Role
    * Advertising and GATT bearer
    * Authentication OOB

* Provisioning: Provisioner Role
    * Advertising and GATT bearer
    * Authentication OOB

* Networking
    * Relay
    * Segmentation and Reassembly
    * Key Refresh
    * IV Update

* Proxy Support

* Multiple Client Models Run Simultaneously
    * Support multiple client models send packets to different nodes simultaneously
    * No blocking between client model and server

* NVS Storage
    * Store Provisioning Data of BLE Mesh Nodes in Flash

2. BLE Mesh Applications

* BLE Mesh Node & Provisioner
    * Node Example
    * Provisioner Example
    * Node + Generic OnOff Client Example

* Fast Provisioning
    * Vendor Fast Prov Server Model
    * Vendor Fast Prov Client Model
    * Examples

* Wi-Fi & BLE Mesh Coexistence
    * Example

* BLE Mesh Console Commands
    * Example

3. BLE Mesh Models

* Foundation Models
    * Configuration Server Model
    * Configuration Client Model
    * Health Server Model
    * Health Client Model

* Generic Client Models
    * Generic OnOff Client
    * Generic Level Client
    * Generic Location Client
    * Generic Default Transition Timer Client
    * Generic Power OnOff Client
    * Generic Power Level Client
    * Generic Battery Client
    * Generic Property Client

* Generic Server Models
    * Generic OnOff Server (Example)

* Lighting Client Models
    * Light Lightness Client
    * Light CTL Client
    * Light HSL Client
    * Light xyL Client
    * Light LC Client

* Sensor Client Model
    * Sensor Client

* Time and Scenes Client Models
    * Time Client
    * Scene Client
    * Scheduler Client
2019-06-24 11:31:24 +08:00

206 lines
5.3 KiB
C

/*
* Copyright (c) 2016 Intel Corporation
* Copyright (c) 2016 Wind River Systems, Inc.
* Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <errno.h>
#include "sdkconfig.h"
#include "osi/hash_map.h"
#include "osi/alarm.h"
#include "osi/hash_functions.h"
#include "common/bt_trace.h"
#include "common/bt_defs.h"
#include "esp_timer.h"
#include "mesh_kernel.h"
#include "mesh_trace.h"
#include "provisioner_prov.h"
static osi_mutex_t bm_alarm_lock;
static osi_mutex_t bm_irq_lock;
static hash_map_t *bm_alarm_hash_map;
static const size_t BLE_MESH_GENERAL_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;
static void bt_mesh_alarm_cb(void *data)
{
assert(data != NULL);
struct k_delayed_work *work = (struct k_delayed_work *)data;
work->work.handler(&work->work);
return;
}
unsigned int bt_mesh_irq_lock(void)
{
#if defined(CONFIG_BLE_MESH_IRQ_LOCK) && CONFIG_BLE_MESH_IRQ_LOCK
unsigned int key = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL);
return key;
#else
/* Change by Espressif. In BLE Mesh, in order to improve the real-time
* requirements of bt controller, we use task lock to replace IRQ lock.
*/
osi_mutex_lock(&bm_irq_lock, OSI_MUTEX_MAX_TIMEOUT);
return 0;
#endif
}
void bt_mesh_irq_unlock(unsigned int key)
{
#if defined(CONFIG_BLE_MESH_IRQ_LOCK) && CONFIG_BLE_MESH_IRQ_LOCK
XTOS_RESTORE_INTLEVEL(key);
#else
osi_mutex_unlock(&bm_irq_lock);
#endif
}
s64_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);
}
u32_t k_uptime_get_32(void)
{
/** k_uptime_get_32 is in in milliseconds,
* but esp_timer_get_time is in microseconds
*/
return (u32_t)(esp_timer_get_time() / 1000);
}
void k_sleep(s32_t duration)
{
vTaskDelay(duration / portTICK_PERIOD_MS);
return;
}
void bt_mesh_k_init(void)
{
osi_mutex_new(&bm_alarm_lock);
osi_mutex_new(&bm_irq_lock);
bm_alarm_hash_map = hash_map_new(BLE_MESH_GENERAL_ALARM_HASH_MAP_SIZE,
hash_function_pointer, NULL,
(data_free_fn)osi_alarm_free, NULL);
assert(bm_alarm_hash_map != NULL);
}
void k_delayed_work_init(struct k_delayed_work *work, k_work_handler_t handler)
{
osi_alarm_t *alarm = NULL;
assert(work != NULL && bm_alarm_hash_map != NULL);
k_work_init(&work->work, handler);
osi_mutex_lock(&bm_alarm_lock, OSI_MUTEX_MAX_TIMEOUT);
if (!hash_map_has_key(bm_alarm_hash_map, (void *)work)) {
alarm = osi_alarm_new("bt_mesh", bt_mesh_alarm_cb, (void *)work, 0);
if (alarm == NULL) {
BT_ERR("%s, Unable to create alarm", __func__);
return;
}
if (!hash_map_set(bm_alarm_hash_map, work, (void *)alarm)) {
BT_ERR("%s Unable to add the timer to hash map.", __func__);
}
}
osi_mutex_unlock(&bm_alarm_lock);
alarm = hash_map_get(bm_alarm_hash_map, work);
if (alarm == NULL) {
BT_WARN("%s, Unable to find expected alarm in hash map", __func__);
return;
}
// Just init the work timer only, don't start it.
osi_alarm_cancel(alarm);
return;
}
int k_delayed_work_submit(struct k_delayed_work *work,
s32_t delay)
{
assert(work != NULL && bm_alarm_hash_map != NULL);
osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
if (alarm == NULL) {
BT_WARN("%s, Unable to find expected alarm in hash map", __func__);
return -EINVAL;
}
// Cancel the alarm first, before start the alarm.
osi_alarm_cancel(alarm);
osi_alarm_set(alarm, delay);
return 0;
}
int k_delayed_work_cancel(struct k_delayed_work *work)
{
assert(work != NULL && bm_alarm_hash_map != NULL);
osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
if (alarm == NULL) {
BT_WARN("%s, Unable to find expected alarm in hash map", __func__);
return -EINVAL;
}
osi_alarm_cancel(alarm);
alarm->deadline_us = 0;
return 0;
}
int k_delayed_work_free(struct k_delayed_work *work)
{
assert(work != NULL && bm_alarm_hash_map != NULL);
osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, work);
if (alarm == NULL) {
BT_WARN("%s Unable to find expected alarm in hash map", __func__);
return -EINVAL;
}
hash_map_erase(bm_alarm_hash_map, work);
return 0;
}
s32_t k_delayed_work_remaining_get(struct k_delayed_work *work)
{
assert(work != NULL && bm_alarm_hash_map != NULL);
osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
if (alarm == NULL) {
BT_WARN("%s Unable to find expected alarm in hash map", __func__);
return 0;
}
if (!alarm->deadline_us) {
return 0;
}
s32_t remain_time = 0;
int64_t now = esp_timer_get_time();
if ((alarm->deadline_us - now) < 0x1FFFFFFFFFF) {
remain_time = (alarm->deadline_us - now) / 1000;
} else {
return 0;
}
return remain_time;
}