OVMS3-idf/components/bt/esp_ble_mesh/mesh_common/mesh_kernel.c
lly b19671e0d4 ble_mesh: Add ESP BLE Mesh implementation
1. BLE Mesh Core

    * Provisioning: Node Role
        * PB-ADV and PB-GATT
        * Authentication OOB

    * Provisioning: Provisioner Role
        * PB-ADV and PB-GATT
        * 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 BLE Mesh node related information in flash
        * Store BLE Mesh Provisioner related information in flash

2. BLE Mesh Models

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

    * Generic
        * Generic OnOff Server
        * Generic OnOff Client
        * Generic Level Server
        * Generic Level Client
        * Generic Default Transition Time Server
        * Generic Default Transition Time Client
        * Generic Power OnOff Server
        * Generic Power OnOff Setup Server
        * Generic Power OnOff Client
        * Generic Power Level Server
        * Generic Power Level Setup Server
        * Generic Power Level Client
        * Generic Battery Server
        * Generic Battery Client
        * Generic Location Server
        * Generic Location Setup Server
        * Generic Location Client
        * Generic Admin Property Server
        * Generic Manufacturer Property Server
        * Generic User Property Server
        * Generic Client Property Server
        * Generic Property Client

    * Sensor Server Model
        * Sensor Server
        * Sensor Setup Server
        * Sensor Client

    * Time and Scenes
        * Time Server
        * Time Setup Server
        * Time Client
        * Scene Server
        * Scene Setup Server
        * Scene Client
        * Scheduler Server
        * Scheduler Setup Server
        * Scheduler Client

    * Lighting
        * Light Lightness Server
        * Light Lightness Setup Server
        * Light Lightness Client
        * Light CTL Server
        * Light CTL Setup Server
        * Light CTL Client
        * Light CTL Temperature Server
        * Light HSL Server
        * Light HSL Setup Server
        * Light HSL Client
        * Light HSL Hue Server
        * Light HSL Saturation Server
        * Light xyL Server
        * Light xyL Setup Server
        * Light xyL Client
        * Light LC Server
        * Light LC Setup Server
        * Light LC Client

3. BLE Mesh Applications

    * BLE Mesh Node
        * OnOff Client Example
        * OnOff Server Example

    * BLE Mesh Provisioner
        * Example

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

    * Wi-Fi & BLE Mesh Coexistence
        * Example

    * BLE Mesh Console Commands
        * Examples
2020-02-03 12:03:36 +08:00

294 lines
6.9 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 "osi/hash_map.h"
#include "osi/alarm.h"
#include "osi/hash_functions.h"
#include "mesh_common.h"
#include "provisioner_prov.h"
static bt_mesh_mutex_t bm_alarm_lock;
static bt_mesh_mutex_t bm_list_lock;
static bt_mesh_mutex_t bm_buf_lock;
static bt_mesh_mutex_t bm_atomic_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_mutex_new(void)
{
if (!bm_alarm_lock.mutex) {
bt_mesh_mutex_create(&bm_alarm_lock);
}
}
static void bt_mesh_alarm_mutex_free(void)
{
bt_mesh_mutex_free(&bm_alarm_lock);
}
static void bt_mesh_alarm_lock(void)
{
bt_mesh_mutex_lock(&bm_alarm_lock);
}
static void bt_mesh_alarm_unlock(void)
{
bt_mesh_mutex_unlock(&bm_alarm_lock);
}
static void bt_mesh_list_mutex_new(void)
{
if (!bm_list_lock.mutex) {
bt_mesh_mutex_create(&bm_list_lock);
}
}
static void bt_mesh_list_mutex_free(void)
{
bt_mesh_mutex_free(&bm_list_lock);
}
void bt_mesh_list_lock(void)
{
bt_mesh_mutex_lock(&bm_list_lock);
}
void bt_mesh_list_unlock(void)
{
bt_mesh_mutex_unlock(&bm_list_lock);
}
static void bt_mesh_buf_mutex_new(void)
{
if (!bm_buf_lock.mutex) {
bt_mesh_mutex_create(&bm_buf_lock);
}
}
static void bt_mesh_buf_mutex_free(void)
{
bt_mesh_mutex_free(&bm_buf_lock);
}
void bt_mesh_buf_lock(void)
{
bt_mesh_mutex_lock(&bm_buf_lock);
}
void bt_mesh_buf_unlock(void)
{
bt_mesh_mutex_unlock(&bm_buf_lock);
}
static void bt_mesh_atomic_mutex_new(void)
{
if (!bm_atomic_lock.mutex) {
bt_mesh_mutex_create(&bm_atomic_lock);
}
}
static void bt_mesh_atomic_mutex_free(void)
{
bt_mesh_mutex_free(&bm_atomic_lock);
}
void bt_mesh_atomic_lock(void)
{
bt_mesh_mutex_lock(&bm_atomic_lock);
}
void bt_mesh_atomic_unlock(void)
{
bt_mesh_mutex_unlock(&bm_atomic_lock);
}
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)
{
bt_mesh_alarm_mutex_new();
bt_mesh_list_mutex_new();
bt_mesh_buf_mutex_new();
bt_mesh_atomic_mutex_new();
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, "%s, Failed to create hash map", __func__);
}
void bt_mesh_k_deinit(void)
{
bt_mesh_alarm_mutex_free();
bt_mesh_list_mutex_free();
bt_mesh_buf_mutex_free();
bt_mesh_atomic_mutex_free();
if (bm_alarm_hash_map) {
hash_map_free(bm_alarm_hash_map);
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;
if (!work || !bm_alarm_hash_map) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
k_work_init(&work->work, handler);
bt_mesh_alarm_lock();
if (!hash_map_has_key(bm_alarm_hash_map, (void *)work)) {
alarm = osi_alarm_new("bt_mesh", (osi_alarm_callback_t)handler, (void *)&work->work, 0);
if (alarm == NULL) {
BT_ERR("%s, Unable to create alarm", __func__);
bt_mesh_alarm_unlock();
return;
}
if (!hash_map_set(bm_alarm_hash_map, work, (void *)alarm)) {
BT_ERR("%s Unable to add the timer to hash map.", __func__);
}
}
bt_mesh_alarm_unlock();
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)
{
if (!work || !bm_alarm_hash_map) {
BT_ERR("%s, Invalid parameter", __func__);
return -EINVAL;
}
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_submit_periodic(struct k_delayed_work *work, s32_t period)
{
if (!work || !bm_alarm_hash_map) {
BT_ERR("%s, Invalid parameter", __func__);
return -EINVAL;
}
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 starting it. */
osi_alarm_cancel(alarm);
osi_alarm_set_periodic(alarm, period);
return 0;
}
int k_delayed_work_cancel(struct k_delayed_work *work)
{
if (!work || !bm_alarm_hash_map) {
BT_ERR("%s, Invalid parameter", __func__);
return -EINVAL;
}
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)
{
if (!work || !bm_alarm_hash_map) {
BT_ERR("%s, Invalid parameter", __func__);
return -EINVAL;
}
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;
}
osi_alarm_cancel(alarm);
hash_map_erase(bm_alarm_hash_map, work);
return 0;
}
s32_t k_delayed_work_remaining_get(struct k_delayed_work *work)
{
if (!work || !bm_alarm_hash_map) {
BT_ERR("%s, Invalid parameter", __func__);
return 0;
}
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;
}
return osi_alarm_get_remaining_ms(alarm);
}