// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include "btc_ble_mesh_sensor_model.h" #include "model_opcode.h" #include "sensor_client.h" /** The following are the macro definitions of sensor client * model messages length, and a message is composed of three * parts: Opcode + msg_value + MIC */ /* Sensor client messages length */ #define BLE_MESH_SENSOR_DESCRIPTOR_GET_MSG_LEN (2 + 2 + 4) #define BLE_MESH_SENSOR_CADENCE_GET_MSG_LEN (2 + 2 + 4) #define BLE_MESH_SENSOR_CADENCE_SET_MSG_LEN /* variable */ #define BLE_MESH_SENSOR_SETTINGS_GET_MSG_LEN (2 + 2 + 4) #define BLE_MESH_SENSOR_SETTING_GET_MSG_LEN (2 + 4 + 4) #define BLE_MESH_SENSOR_SETTING_SET_MSG_LEN /* variable */ #define BLE_MESH_SENSOR_GET_MSG_LEN (2 + 2 + 4) #define BLE_MESH_SENSOR_COLUMN_GET_MSG_LEN /* variable */ #define BLE_MESH_SENSOR_SERIES_GET_MSG_LEN /* variable */ static const bt_mesh_client_op_pair_t sensor_op_pair[] = { { BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_GET, BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_STATUS }, { BLE_MESH_MODEL_OP_SENSOR_CADENCE_GET, BLE_MESH_MODEL_OP_SENSOR_CADENCE_STATUS }, { BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET, BLE_MESH_MODEL_OP_SENSOR_CADENCE_STATUS }, { BLE_MESH_MODEL_OP_SENSOR_SETTINGS_GET, BLE_MESH_MODEL_OP_SENSOR_SETTINGS_STATUS }, { BLE_MESH_MODEL_OP_SENSOR_SETTING_GET, BLE_MESH_MODEL_OP_SENSOR_SETTING_STATUS }, { BLE_MESH_MODEL_OP_SENSOR_SETTING_SET, BLE_MESH_MODEL_OP_SENSOR_SETTING_STATUS }, { BLE_MESH_MODEL_OP_SENSOR_GET, BLE_MESH_MODEL_OP_SENSOR_STATUS }, { BLE_MESH_MODEL_OP_SENSOR_COLUMN_GET, BLE_MESH_MODEL_OP_SENSOR_COLUMN_STATUS }, { BLE_MESH_MODEL_OP_SENSOR_SERIES_GET, BLE_MESH_MODEL_OP_SENSOR_SERIES_STATUS }, }; static bt_mesh_mutex_t sensor_client_lock; static void bt_mesh_sensor_client_mutex_new(void) { if (!sensor_client_lock.mutex) { bt_mesh_mutex_create(&sensor_client_lock); } } static void bt_mesh_sensor_client_mutex_free(void) { bt_mesh_mutex_free(&sensor_client_lock); } static void bt_mesh_sensor_client_lock(void) { bt_mesh_mutex_lock(&sensor_client_lock); } static void bt_mesh_sensor_client_unlock(void) { bt_mesh_mutex_unlock(&sensor_client_lock); } static void timeout_handler(struct k_work *work) { struct k_delayed_work *timer = NULL; bt_mesh_client_node_t *node = NULL; struct bt_mesh_msg_ctx ctx = {0}; u32_t opcode = 0U; BT_WARN("Receive sensor status message timeout"); bt_mesh_sensor_client_lock(); timer = CONTAINER_OF(work, struct k_delayed_work, work); if (timer && !k_delayed_work_free(timer)) { node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work); if (node) { memcpy(&ctx, &node->ctx, sizeof(ctx)); opcode = node->opcode; bt_mesh_client_free_node(node); bt_mesh_sensor_client_cb_evt_to_btc( opcode, BTC_BLE_MESH_EVT_SENSOR_CLIENT_TIMEOUT, ctx.model, &ctx, NULL, 0); } } bt_mesh_sensor_client_unlock(); return; } static void sensor_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { bt_mesh_client_node_t *node = NULL; u8_t *val = NULL; u8_t evt = 0xFF; size_t len = 0U; BT_DBG("%s, len %d, bytes %s", __func__, buf->len, bt_hex(buf->data, buf->len)); switch (ctx->recv_op) { case BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_STATUS: { struct bt_mesh_sensor_descriptor_status *status = NULL; status = bt_mesh_calloc(sizeof(struct bt_mesh_sensor_descriptor_status)); if (!status) { BT_ERR("%s, Failed to allocate memory", __func__); return; } status->descriptor = bt_mesh_alloc_buf(buf->len); if (!status->descriptor) { BT_ERR("%s, Failed to allocate memory", __func__); bt_mesh_free(status); return; } net_buf_simple_add_mem(status->descriptor, buf->data, buf->len); val = (u8_t *)status; len = sizeof(struct bt_mesh_sensor_descriptor_status); break; } case BLE_MESH_MODEL_OP_SENSOR_CADENCE_STATUS: { struct bt_mesh_sensor_cadence_status *status = NULL; status = bt_mesh_calloc(sizeof(struct bt_mesh_sensor_cadence_status)); if (!status) { BT_ERR("%s, Failed to allocate memory", __func__); return; } status->property_id = net_buf_simple_pull_le16(buf); status->sensor_cadence_value = bt_mesh_alloc_buf(buf->len); if (!status->sensor_cadence_value) { BT_ERR("%s, Failed to allocate memory", __func__); bt_mesh_free(status); return; } net_buf_simple_add_mem(status->sensor_cadence_value, buf->data, buf->len); val = (u8_t *)status; len = sizeof(struct bt_mesh_sensor_cadence_status); break; } case BLE_MESH_MODEL_OP_SENSOR_SETTINGS_STATUS: { struct bt_mesh_sensor_settings_status *status = NULL; status = bt_mesh_calloc(sizeof(struct bt_mesh_sensor_settings_status)); if (!status) { BT_ERR("%s, Failed to allocate memory", __func__); return; } status->sensor_property_id = net_buf_simple_pull_le16(buf); status->sensor_setting_property_ids = bt_mesh_alloc_buf(buf->len); if (!status->sensor_setting_property_ids) { BT_ERR("%s, Failed to allocate memory", __func__); bt_mesh_free(status); return; } net_buf_simple_add_mem(status->sensor_setting_property_ids, buf->data, buf->len); val = (u8_t *)status; len = sizeof(struct bt_mesh_sensor_settings_status); break; } case BLE_MESH_MODEL_OP_SENSOR_SETTING_STATUS: { struct bt_mesh_sensor_setting_status *status = NULL; status = bt_mesh_calloc(sizeof(struct bt_mesh_sensor_setting_status)); if (!status) { BT_ERR("%s, Failed to allocate memory", __func__); return; } status->sensor_property_id = net_buf_simple_pull_le16(buf); status->sensor_setting_property_id = net_buf_simple_pull_le16(buf); if (buf->len) { status->op_en = true; status->sensor_setting_access = net_buf_simple_pull_u8(buf); status->sensor_setting_raw = bt_mesh_alloc_buf(buf->len); if (!status->sensor_setting_raw) { BT_ERR("%s, Failed to allocate memory", __func__); bt_mesh_free(status); return; } net_buf_simple_add_mem(status->sensor_setting_raw, buf->data, buf->len); } val = (u8_t *)status; len = sizeof(struct bt_mesh_sensor_setting_status); break; } case BLE_MESH_MODEL_OP_SENSOR_STATUS: { struct bt_mesh_sensor_status *status = NULL; status = bt_mesh_calloc(sizeof(struct bt_mesh_sensor_status)); if (!status) { BT_ERR("%s, Failed to allocate memory", __func__); return; } status->marshalled_sensor_data = bt_mesh_alloc_buf(buf->len); if (!status->marshalled_sensor_data) { BT_ERR("%s, Failed to allocate memory", __func__); bt_mesh_free(status); return; } net_buf_simple_add_mem(status->marshalled_sensor_data, buf->data, buf->len); val = (u8_t *)status; len = sizeof(struct bt_mesh_sensor_status); break; } case BLE_MESH_MODEL_OP_SENSOR_COLUMN_STATUS: { struct bt_mesh_sensor_column_status *status = NULL; status = bt_mesh_calloc(sizeof(struct bt_mesh_sensor_column_status)); if (!status) { BT_ERR("%s, Failed to allocate memory", __func__); return; } status->property_id = net_buf_simple_pull_le16(buf); status->sensor_column_value = bt_mesh_alloc_buf(buf->len); if (!status->sensor_column_value) { BT_ERR("%s, Failed to allocate memory", __func__); bt_mesh_free(status); return; } net_buf_simple_add_mem(status->sensor_column_value, buf->data, buf->len); val = (u8_t *)status; len = sizeof(struct bt_mesh_sensor_column_status); break; } case BLE_MESH_MODEL_OP_SENSOR_SERIES_STATUS: { struct bt_mesh_sensor_series_status *status = NULL; status = bt_mesh_calloc(sizeof(struct bt_mesh_sensor_series_status)); if (!status) { BT_ERR("%s, Failed to allocate memory", __func__); return; } status->property_id = net_buf_simple_pull_le16(buf); status->sensor_series_value = bt_mesh_alloc_buf(buf->len); if (!status->sensor_series_value) { BT_ERR("%s, Failed to allocate memory", __func__); bt_mesh_free(status); return; } net_buf_simple_add_mem(status->sensor_series_value, buf->data, buf->len); val = (u8_t *)status; len = sizeof(struct bt_mesh_sensor_series_status); break; } default: BT_ERR("%s, Not a Sensor Status message opcode", __func__); return; } buf->data = val; buf->len = len; bt_mesh_sensor_client_lock(); node = bt_mesh_is_client_recv_publish_msg(model, ctx, buf, true); if (!node) { BT_DBG("Unexpected sensor status message 0x%x", ctx->recv_op); } else { switch (node->opcode) { case BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_GET: case BLE_MESH_MODEL_OP_SENSOR_CADENCE_GET: case BLE_MESH_MODEL_OP_SENSOR_SETTINGS_GET: case BLE_MESH_MODEL_OP_SENSOR_SETTING_GET: case BLE_MESH_MODEL_OP_SENSOR_GET: case BLE_MESH_MODEL_OP_SENSOR_COLUMN_GET: case BLE_MESH_MODEL_OP_SENSOR_SERIES_GET: evt = BTC_BLE_MESH_EVT_SENSOR_CLIENT_GET_STATE; break; case BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET: case BLE_MESH_MODEL_OP_SENSOR_SETTING_SET: evt = BTC_BLE_MESH_EVT_SENSOR_CLIENT_SET_STATE; break; default: break; } if (!k_delayed_work_free(&node->timer)) { u32_t opcode = node->opcode; bt_mesh_client_free_node(node); bt_mesh_sensor_client_cb_evt_to_btc(opcode, evt, model, ctx, val, len); } } bt_mesh_sensor_client_unlock(); switch (ctx->recv_op) { case BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_STATUS: { struct bt_mesh_sensor_descriptor_status *status; status = (struct bt_mesh_sensor_descriptor_status *)val; bt_mesh_free_buf(status->descriptor); break; } case BLE_MESH_MODEL_OP_SENSOR_CADENCE_STATUS: { struct bt_mesh_sensor_cadence_status *status; status = (struct bt_mesh_sensor_cadence_status *)val; bt_mesh_free_buf(status->sensor_cadence_value); break; } case BLE_MESH_MODEL_OP_SENSOR_SETTINGS_STATUS: { struct bt_mesh_sensor_settings_status *status; status = (struct bt_mesh_sensor_settings_status *)val; bt_mesh_free_buf(status->sensor_setting_property_ids); break; } case BLE_MESH_MODEL_OP_SENSOR_SETTING_STATUS: { struct bt_mesh_sensor_setting_status *status; status = (struct bt_mesh_sensor_setting_status *)val; bt_mesh_free_buf(status->sensor_setting_raw); break; } case BLE_MESH_MODEL_OP_SENSOR_STATUS: { struct bt_mesh_sensor_status *status; status = (struct bt_mesh_sensor_status *)val; bt_mesh_free_buf(status->marshalled_sensor_data); break; } case BLE_MESH_MODEL_OP_SENSOR_COLUMN_STATUS: { struct bt_mesh_sensor_column_status *status; status = (struct bt_mesh_sensor_column_status *)val; bt_mesh_free_buf(status->sensor_column_value); break; } case BLE_MESH_MODEL_OP_SENSOR_SERIES_STATUS: { struct bt_mesh_sensor_series_status *status; status = (struct bt_mesh_sensor_series_status *)val; bt_mesh_free_buf(status->sensor_series_value); break; } default: break; } bt_mesh_free(val); return; } const struct bt_mesh_model_op sensor_cli_op[] = { { BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_STATUS, 0, sensor_status }, { BLE_MESH_MODEL_OP_SENSOR_CADENCE_STATUS, 2, sensor_status }, { BLE_MESH_MODEL_OP_SENSOR_SETTINGS_STATUS, 2, sensor_status }, { BLE_MESH_MODEL_OP_SENSOR_SETTING_STATUS, 4, sensor_status }, { BLE_MESH_MODEL_OP_SENSOR_STATUS, 0, sensor_status }, { BLE_MESH_MODEL_OP_SENSOR_COLUMN_STATUS, 2, sensor_status }, { BLE_MESH_MODEL_OP_SENSOR_SERIES_STATUS, 2, sensor_status }, BLE_MESH_MODEL_OP_END, }; static int sensor_act_state(bt_mesh_client_common_param_t *common, void *value, u16_t value_len, bool need_ack) { struct net_buf_simple *msg = NULL; int err = 0; msg = bt_mesh_alloc_buf(value_len); if (!msg) { BT_ERR("%s, Failed to allocate memory", __func__); return -ENOMEM; } bt_mesh_model_msg_init(msg, common->opcode); switch (common->opcode) { case BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_GET: { struct bt_mesh_sensor_descriptor_get *act; act = (struct bt_mesh_sensor_descriptor_get *)value; if (act->op_en) { net_buf_simple_add_le16(msg, act->property_id); } break; } case BLE_MESH_MODEL_OP_SENSOR_CADENCE_GET: { struct bt_mesh_sensor_cadence_get *act; act = (struct bt_mesh_sensor_cadence_get *)value; net_buf_simple_add_le16(msg, act->property_id); break; } case BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET: case BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET_UNACK: { struct bt_mesh_sensor_cadence_set *act; act = (struct bt_mesh_sensor_cadence_set *)value; net_buf_simple_add_le16(msg, act->property_id); net_buf_simple_add_u8(msg, act->status_trigger_type << 7 | act->fast_cadence_period_divisor); net_buf_simple_add_mem(msg, act->status_trigger_delta_down->data, act->status_trigger_delta_down->len); net_buf_simple_add_mem(msg, act->status_trigger_delta_up->data, act->status_trigger_delta_up->len); net_buf_simple_add_u8(msg, act->status_min_interval); net_buf_simple_add_mem(msg, act->fast_cadence_low->data, act->fast_cadence_low->len); net_buf_simple_add_mem(msg, act->fast_cadence_high->data, act->fast_cadence_high->len); break; } case BLE_MESH_MODEL_OP_SENSOR_SETTINGS_GET: { struct bt_mesh_sensor_settings_get *act; act = (struct bt_mesh_sensor_settings_get *)value; net_buf_simple_add_le16(msg, act->sensor_property_id); break; } case BLE_MESH_MODEL_OP_SENSOR_SETTING_GET: { struct bt_mesh_sensor_setting_get *act; act = (struct bt_mesh_sensor_setting_get *)value; net_buf_simple_add_le16(msg, act->sensor_property_id); net_buf_simple_add_le16(msg, act->sensor_setting_property_id); break; } case BLE_MESH_MODEL_OP_SENSOR_SETTING_SET: case BLE_MESH_MODEL_OP_SENSOR_SETTING_SET_UNACK: { struct bt_mesh_sensor_setting_set *act; act = (struct bt_mesh_sensor_setting_set *)value; net_buf_simple_add_le16(msg, act->sensor_property_id); net_buf_simple_add_le16(msg, act->sensor_setting_property_id); net_buf_simple_add_mem(msg, act->sensor_setting_raw->data, act->sensor_setting_raw->len); break; } case BLE_MESH_MODEL_OP_SENSOR_GET: { struct bt_mesh_sensor_get *act; act = (struct bt_mesh_sensor_get *)value; if (act->op_en) { net_buf_simple_add_le16(msg, act->property_id); } break; } case BLE_MESH_MODEL_OP_SENSOR_COLUMN_GET: { struct bt_mesh_sensor_column_get *act; act = (struct bt_mesh_sensor_column_get *)value; net_buf_simple_add_le16(msg, act->property_id); net_buf_simple_add_mem(msg, act->raw_value_x->data, act->raw_value_x->len); break; } case BLE_MESH_MODEL_OP_SENSOR_SERIES_GET: { struct bt_mesh_sensor_series_get *act; act = (struct bt_mesh_sensor_series_get *)value; net_buf_simple_add_le16(msg, act->property_id); if (act->op_en) { net_buf_simple_add_mem(msg, act->raw_value_x1->data, act->raw_value_x1->len); net_buf_simple_add_mem(msg, act->raw_value_x2->data, act->raw_value_x2->len); } break; } default: BT_ERR("%s, Not a Sensor Client message opcode", __func__); err = -EINVAL; goto end; } err = bt_mesh_client_send_msg(common->model, common->opcode, &common->ctx, msg, timeout_handler, common->msg_timeout, need_ack, common->cb, common->cb_data); if (err) { BT_ERR("%s, Failed to send Sensor Client message (err %d)", __func__, err); } end: bt_mesh_free_buf(msg); return err; } int bt_mesh_sensor_client_get_state(bt_mesh_client_common_param_t *common, void *get, void *status) { bt_mesh_sensor_client_t *client = NULL; u16_t length = 0U; if (!common || !common->model || !get) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; } client = (bt_mesh_sensor_client_t *)common->model->user_data; if (!client || !client->internal_data) { BT_ERR("%s, Sensor Client user data is NULL", __func__); return -EINVAL; } switch (common->opcode) { case BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_GET: length = BLE_MESH_SENSOR_DESCRIPTOR_GET_MSG_LEN; break; case BLE_MESH_MODEL_OP_SENSOR_CADENCE_GET: length = BLE_MESH_SENSOR_CADENCE_GET_MSG_LEN; break; case BLE_MESH_MODEL_OP_SENSOR_SETTINGS_GET: length = BLE_MESH_SENSOR_SETTINGS_GET_MSG_LEN; break; case BLE_MESH_MODEL_OP_SENSOR_SETTING_GET: length = BLE_MESH_SENSOR_SETTING_GET_MSG_LEN; break; case BLE_MESH_MODEL_OP_SENSOR_GET: length = BLE_MESH_SENSOR_GET_MSG_LEN; break; case BLE_MESH_MODEL_OP_SENSOR_COLUMN_GET: { struct bt_mesh_sensor_column_get *value; value = (struct bt_mesh_sensor_column_get *)get; if (!value->raw_value_x) { BT_ERR("%s, Sensor column_get is NULL", __func__); return -EINVAL; } length = (2 + 2 + value->raw_value_x->len + 4); break; } case BLE_MESH_MODEL_OP_SENSOR_SERIES_GET: { struct bt_mesh_sensor_series_get *value; value = (struct bt_mesh_sensor_series_get *)get; if (value->op_en) { if (!value->raw_value_x1 || !value->raw_value_x2) { BT_ERR("%s, Sensor series_get is NULL", __func__); return -EINVAL; } } if (value->op_en) { length = value->raw_value_x1->len + value->raw_value_x2->len; } length += (2 + 2 + 4); break; } default: BT_ERR("%s, Not a Sensor Client Get message opcode", __func__); return -EINVAL; } return sensor_act_state(common, get, length, true); } int bt_mesh_sensor_client_set_state(bt_mesh_client_common_param_t *common, void *set, void *status) { bt_mesh_sensor_client_t *client = NULL; u16_t length = 0U; bool need_ack = false; if (!common || !common->model || !set) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; } client = (bt_mesh_sensor_client_t *)common->model->user_data; if (!client || !client->internal_data) { BT_ERR("%s, Sensor Client user data is NULL", __func__); return -EINVAL; } switch (common->opcode) { case BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET: need_ack = true; case BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET_UNACK: { struct bt_mesh_sensor_cadence_set *value; value = (struct bt_mesh_sensor_cadence_set *)set; if (!value->status_trigger_delta_down || !value->status_trigger_delta_up || !value->fast_cadence_low || !value->fast_cadence_high) { BT_ERR("%s, Sensor cadence_set is NULL", __func__); return -EINVAL; } length = value->status_trigger_delta_down->len + \ value->status_trigger_delta_up->len + \ value->fast_cadence_low->len + \ value->fast_cadence_high->len; length += (1 + 2 + 1 + 1 + 4); break; } case BLE_MESH_MODEL_OP_SENSOR_SETTING_SET: need_ack = true; case BLE_MESH_MODEL_OP_SENSOR_SETTING_SET_UNACK: { struct bt_mesh_sensor_setting_set *value; value = (struct bt_mesh_sensor_setting_set *)set; if (!value->sensor_setting_raw) { BT_ERR("%s, Sensor setting_raw is NULL", __func__); return -EINVAL; } length = (1 + 2 + 2 + value->sensor_setting_raw->len + 4); break; } default: BT_ERR("%s, Not a Sensor Client Set message opcode", __func__); return -EINVAL; } return sensor_act_state(common, set, length, need_ack); } int bt_mesh_sensor_cli_init(struct bt_mesh_model *model, bool primary) { sensor_internal_data_t *internal = NULL; bt_mesh_sensor_client_t *client = NULL; BT_DBG("primary %u", primary); if (!model) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; } client = (bt_mesh_sensor_client_t *)model->user_data; if (!client) { BT_ERR("%s, Sensor Client user_data is NULL", __func__); return -EINVAL; } if (!client->internal_data) { internal = bt_mesh_calloc(sizeof(sensor_internal_data_t)); if (!internal) { BT_ERR("%s, Failed to allocate memory", __func__); return -ENOMEM; } sys_slist_init(&internal->queue); client->model = model; client->op_pair_size = ARRAY_SIZE(sensor_op_pair); client->op_pair = sensor_op_pair; client->internal_data = internal; } else { bt_mesh_client_clear_list(client->internal_data); } bt_mesh_sensor_client_mutex_new(); return 0; } int bt_mesh_sensor_cli_deinit(struct bt_mesh_model *model, bool primary) { bt_mesh_sensor_client_t *client = NULL; if (!model) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; } client = (bt_mesh_sensor_client_t *)model->user_data; if (!client) { BT_ERR("%s, Sensor Client user_data is NULL", __func__); return -EINVAL; } if (client->internal_data) { /* Remove items from the list */ bt_mesh_client_clear_list(client->internal_data); /* Free the allocated internal data */ bt_mesh_free(client->internal_data); client->internal_data = NULL; } bt_mesh_sensor_client_mutex_free(); return 0; }