pinebuds/services/ble_profiles/dis/diss/src/diss_task.c
Ben V. Brown 75381150fd Formatting
Formatting Pass 1

Lots of fixups to adding stdint and stdbool all over the place

Formatting Pass 2
Formatting Pass 3
Formatting Pass 4

Update app_bt_stream.cpp
2023-02-02 07:56:49 +11:00

255 lines
8.9 KiB
C

/**
****************************************************************************************
* @addtogroup DISSTASK
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "rwip_config.h"
#if (BLE_DIS_SERVER)
#include "co_utils.h"
#include "diss.h"
#include "diss_task.h"
#include "gap.h"
#include "gattc_task.h"
#include "prf_utils.h"
#include "ke_mem.h"
/*
* FUNCTION DEFINITIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Handles reception of the @ref DISS_SET_VALUE_REQ message.
*
* @param[in] msgid Id of the message received (probably unused).
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance (probably unused).
* @param[in] src_id ID of the sending task instance.
* @return If the message was consumed or not.
****************************************************************************************
*/
__STATIC int diss_set_value_req_handler(ke_msg_id_t const msgid,
struct diss_set_value_req const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id) {
// Request status
uint8_t status;
// Characteristic Declaration attribute handle
uint16_t handle;
struct diss_env_tag *diss_env = PRF_ENV_GET(DISS, diss);
struct diss_set_value_rsp *rsp;
// Check Characteristic Code
if (param->value < DIS_CHAR_MAX) {
// Get Characteristic Declaration attribute handle
handle = diss_value_to_handle(diss_env, param->value);
// Check if the Characteristic exists in the database
if (handle != ATT_INVALID_HDL) {
// Check the value length
status = diss_check_val_len(param->value, param->length);
if (status == GAP_ERR_NO_ERROR) {
// Check value in already present in service
struct diss_val_elmt *val =
(struct diss_val_elmt *)co_list_pick(&(diss_env->values));
// loop until value found
while (val != NULL) {
// if value already present, remove old one
if (val->value == param->value) {
co_list_extract(&(diss_env->values), &(val->hdr));
ke_free(val);
break;
}
val = (struct diss_val_elmt *)val->hdr.next;
}
// allocate value data
val = (struct diss_val_elmt *)ke_malloc(
sizeof(struct diss_val_elmt) + param->length, KE_MEM_ATT_DB);
val->value = param->value;
val->length = param->length;
memcpy(val->data, param->data, param->length);
// insert value into the list
co_list_push_back(&(diss_env->values), &(val->hdr));
}
} else {
status = PRF_ERR_INEXISTENT_HDL;
}
} else {
status = PRF_ERR_INVALID_PARAM;
}
// send response to application
rsp = KE_MSG_ALLOC(DISS_SET_VALUE_RSP, src_id, dest_id, diss_set_value_rsp);
rsp->value = param->value;
rsp->status = status;
ke_msg_send(rsp);
return (KE_MSG_CONSUMED);
}
/**
****************************************************************************************
* @brief Handles reception of the read request from peer device
*
* @param[in] msgid Id of the message received (probably unused).
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance (probably unused).
* @param[in] src_id ID of the sending task instance.
* @return If the message was consumed or not.
****************************************************************************************
*/
__STATIC int gattc_read_req_ind_handler(ke_msg_id_t const msgid,
struct gattc_read_req_ind const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id) {
int msg_status = KE_MSG_CONSUMED;
ke_state_t state = ke_state_get(dest_id);
if (state == DISS_IDLE) {
struct diss_env_tag *diss_env = PRF_ENV_GET(DISS, diss);
// retrieve value attribute
uint8_t value = diss_handle_to_value(diss_env, param->handle);
// Check Characteristic Code
if (value < DIS_CHAR_MAX) {
// Check value in already present in service
struct diss_val_elmt *val =
(struct diss_val_elmt *)co_list_pick(&(diss_env->values));
// loop until value found
while (val != NULL) {
// value is present in service
if (val->value == value) {
break;
}
val = (struct diss_val_elmt *)val->hdr.next;
}
if (val != NULL) {
// Send value to peer device.
struct gattc_read_cfm *cfm = KE_MSG_ALLOC_DYN(
GATTC_READ_CFM, src_id, dest_id, gattc_read_cfm, val->length);
cfm->handle = param->handle;
cfm->status = ATT_ERR_NO_ERROR;
cfm->length = val->length;
memcpy(cfm->value, val->data, val->length);
ke_msg_send(cfm);
} else {
// request value to application
diss_env->req_val = value;
diss_env->req_conidx = KE_IDX_GET(src_id);
struct diss_value_req_ind *req_ind = KE_MSG_ALLOC(
DISS_VALUE_REQ_IND,
prf_dst_task_get(&(diss_env->prf_env), KE_IDX_GET(src_id)), dest_id,
diss_value_req_ind);
req_ind->value = value;
ke_msg_send(req_ind);
// Put Service in a busy state
ke_state_set(dest_id, DISS_BUSY);
}
} else {
// application error, value cannot be retrieved
struct gattc_read_cfm *cfm =
KE_MSG_ALLOC(GATTC_READ_CFM, src_id, dest_id, gattc_read_cfm);
cfm->handle = param->handle;
cfm->status = ATT_ERR_APP_ERROR;
ke_msg_send(cfm);
}
}
// postpone request if profile is in a busy state - required for multipoint
else if (state == DISS_BUSY) {
msg_status = KE_MSG_SAVED;
}
return (msg_status);
}
/**
****************************************************************************************
* @brief Handles reception of the value confirmation from application
*
* @param[in] msgid Id of the message received (probably unused).
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance (probably unused).
* @param[in] src_id ID of the sending task instance.
* @return If the message was consumed or not.
****************************************************************************************
*/
__STATIC int diss_value_cfm_handler(ke_msg_id_t const msgid,
struct diss_value_cfm const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id) {
ke_state_t state = ke_state_get(dest_id);
if (state == DISS_BUSY) {
struct diss_env_tag *diss_env = PRF_ENV_GET(DISS, diss);
// retrieve value attribute
uint16_t handle = diss_value_to_handle(diss_env, diss_env->req_val);
// chack if application provide correct value
if (diss_env->req_val == param->value) {
// Send value to peer device.
struct gattc_read_cfm *cfm = KE_MSG_ALLOC_DYN(
GATTC_READ_CFM, KE_BUILD_ID(TASK_GATTC, diss_env->req_conidx),
dest_id, gattc_read_cfm, param->length);
cfm->handle = handle;
cfm->status = ATT_ERR_NO_ERROR;
cfm->length = param->length;
memcpy(cfm->value, param->data, param->length);
ke_msg_send(cfm);
} else {
// application error, value provided by application is not the expected
// one
struct gattc_read_cfm *cfm = KE_MSG_ALLOC(
GATTC_READ_CFM, KE_BUILD_ID(TASK_GATTC, diss_env->req_conidx),
dest_id, gattc_read_cfm);
cfm->handle = handle;
cfm->status = ATT_ERR_APP_ERROR;
ke_msg_send(cfm);
}
// return to idle state
ke_state_set(dest_id, DISS_IDLE);
}
// else ignore request if not in busy state
return (KE_MSG_CONSUMED);
}
/*
* GLOBAL VARIABLE DEFINITIONS
****************************************************************************************
*/
/// Default State handlers definition
KE_MSG_HANDLER_TAB(diss){
{DISS_SET_VALUE_REQ, (ke_msg_func_t)diss_set_value_req_handler},
{GATTC_READ_REQ_IND, (ke_msg_func_t)gattc_read_req_ind_handler},
{DISS_VALUE_CFM, (ke_msg_func_t)diss_value_cfm_handler},
};
void diss_task_init(struct ke_task_desc *task_desc) {
// Get the address of the environment
struct diss_env_tag *diss_env = PRF_ENV_GET(DISS, diss);
task_desc->msg_handler_tab = diss_msg_handler_tab;
task_desc->msg_cnt = ARRAY_LEN(diss_msg_handler_tab);
task_desc->state = diss_env->state;
task_desc->idx_max = DISS_IDX_MAX;
}
#endif // BLE_DIS_SERVER
/// @} DISSTASK