800 lines
31 KiB
C
800 lines
31 KiB
C
|
/**
|
||
|
****************************************************************************************
|
||
|
* @addtogroup TIPCTASK
|
||
|
* @{
|
||
|
****************************************************************************************
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* INCLUDE FILES
|
||
|
****************************************************************************************
|
||
|
*/
|
||
|
|
||
|
#include "rwip_config.h"
|
||
|
|
||
|
#if (BLE_TIP_CLIENT)
|
||
|
#include "co_utils.h"
|
||
|
#include "tipc_task.h"
|
||
|
#include "tipc.h"
|
||
|
#include "gap.h"
|
||
|
#include "attm.h"
|
||
|
#include "gattc_task.h"
|
||
|
|
||
|
#include "ke_mem.h"
|
||
|
/*
|
||
|
* TYPE DEFINITIONS
|
||
|
****************************************************************************************
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* DEFINES
|
||
|
****************************************************************************************
|
||
|
*/
|
||
|
|
||
|
/// State machine used to retrieve Current Time service characteristics information
|
||
|
const struct prf_char_def tipc_cts_char[TIPC_CHAR_CTS_MAX] =
|
||
|
{
|
||
|
/// Current Time
|
||
|
[TIPC_CHAR_CTS_CURR_TIME] = {ATT_CHAR_CT_TIME,
|
||
|
ATT_MANDATORY,
|
||
|
ATT_CHAR_PROP_RD|ATT_CHAR_PROP_NTF},
|
||
|
/// Local Time Info
|
||
|
[TIPC_CHAR_CTS_LOCAL_TIME_INFO] = {ATT_CHAR_LOCAL_TIME_INFO,
|
||
|
ATT_OPTIONAL,
|
||
|
ATT_CHAR_PROP_RD},
|
||
|
/// Reference Time Info
|
||
|
[TIPC_CHAR_CTS_REF_TIME_INFO] = {ATT_CHAR_REFERENCE_TIME_INFO,
|
||
|
ATT_OPTIONAL,
|
||
|
ATT_CHAR_PROP_RD},
|
||
|
};
|
||
|
|
||
|
/// State machine used to retrieve Current Time service characteristic description information
|
||
|
const struct prf_char_desc_def tipc_cts_char_desc[TIPC_DESC_CTS_MAX] =
|
||
|
{
|
||
|
/// Current Time client config
|
||
|
[TIPC_DESC_CTS_CURR_TIME_CLI_CFG] = {ATT_DESC_CLIENT_CHAR_CFG,
|
||
|
ATT_MANDATORY,
|
||
|
TIPC_CHAR_CTS_CURR_TIME},
|
||
|
};
|
||
|
|
||
|
/// State machine used to retrieve Next DST Change service characteristics information
|
||
|
const struct prf_char_def tipc_ndcs_char[TIPC_CHAR_NDCS_MAX] =
|
||
|
{
|
||
|
/// Current Time
|
||
|
[TIPC_CHAR_NDCS_TIME_WITH_DST] = {ATT_CHAR_TIME_WITH_DST,
|
||
|
ATT_MANDATORY,
|
||
|
ATT_CHAR_PROP_RD},
|
||
|
};
|
||
|
|
||
|
/// State machine used to retrieve Reference Time Update service characteristics information
|
||
|
const struct prf_char_def tipc_rtus_char[TIPC_CHAR_RTUS_MAX] =
|
||
|
{
|
||
|
/// Time Update Control Point
|
||
|
[TIPC_CHAR_RTUS_TIME_UPD_CTNL_PT] = {ATT_CHAR_TIME_UPDATE_CNTL_POINT,
|
||
|
ATT_MANDATORY,
|
||
|
ATT_CHAR_PROP_WR_NO_RESP},
|
||
|
/// Time Update State
|
||
|
[TIPC_CHAR_RTUS_TIME_UPD_STATE] = {ATT_CHAR_TIME_UPDATE_STATE,
|
||
|
ATT_MANDATORY,
|
||
|
ATT_CHAR_PROP_RD},
|
||
|
};
|
||
|
|
||
|
|
||
|
/*
|
||
|
* LOCAL FUNCTIONS DEFINITIONS
|
||
|
****************************************************************************************
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
****************************************************************************************
|
||
|
* @brief Handles reception of the @ref GATTC_SDP_SVC_IND_HANDLER message.
|
||
|
* The handler stores the found service details for service discovery.
|
||
|
* @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_sdp_svc_ind_handler(ke_msg_id_t const msgid,
|
||
|
struct gattc_sdp_svc_ind const *ind,
|
||
|
ke_task_id_t const dest_id,
|
||
|
ke_task_id_t const src_id)
|
||
|
{
|
||
|
uint8_t state = ke_state_get(dest_id);
|
||
|
|
||
|
if(state == TIPC_DISCOVERING)
|
||
|
{
|
||
|
uint8_t conidx = KE_IDX_GET(dest_id);
|
||
|
|
||
|
struct tipc_env_tag *tipc_env = PRF_ENV_GET(TIPC, tipc);
|
||
|
|
||
|
ASSERT_INFO(tipc_env != NULL, dest_id, src_id);
|
||
|
ASSERT_INFO(tipc_env->env[conidx] != NULL, dest_id, src_id);
|
||
|
|
||
|
if(attm_uuid16_comp((unsigned char *)ind->uuid, ind->uuid_len, ATT_SVC_CURRENT_TIME))
|
||
|
{
|
||
|
// Retrieve TIS characteristics and descriptors
|
||
|
prf_extract_svc_info(ind, TIPC_CHAR_CTS_MAX, &tipc_cts_char[0], &tipc_env->env[conidx]->cts.chars[0],
|
||
|
TIPC_DESC_CTS_MAX, &tipc_cts_char_desc[0], &tipc_env->env[conidx]->cts.descs[0]);
|
||
|
|
||
|
//Even if we get multiple responses we only store 1 range
|
||
|
tipc_env->env[conidx]->cts.svc.shdl = ind->start_hdl;
|
||
|
tipc_env->env[conidx]->cts.svc.ehdl = ind->end_hdl;
|
||
|
}
|
||
|
|
||
|
if(attm_uuid16_comp((unsigned char *)ind->uuid, ind->uuid_len, ATT_SVC_NEXT_DST_CHANGE))
|
||
|
{
|
||
|
// Retrieve NDCS characteristics and descriptors
|
||
|
prf_extract_svc_info(ind, TIPC_CHAR_NDCS_MAX, &tipc_ndcs_char[0], &tipc_env->env[conidx]->ndcs.chars[0],
|
||
|
0, NULL, NULL);
|
||
|
|
||
|
//Even if we get multiple responses we only store 1 range
|
||
|
tipc_env->env[conidx]->ndcs.svc.shdl = ind->start_hdl;
|
||
|
tipc_env->env[conidx]->ndcs.svc.ehdl = ind->end_hdl;
|
||
|
}
|
||
|
|
||
|
if(attm_uuid16_comp((unsigned char *)ind->uuid, ind->uuid_len, ATT_SVC_REF_TIME_UPDATE))
|
||
|
{
|
||
|
// Retrieve RTUS characteristics and descriptors
|
||
|
prf_extract_svc_info(ind, TIPC_CHAR_RTUS_MAX, &tipc_rtus_char[0], &tipc_env->env[conidx]->rtus.chars[0],
|
||
|
0, NULL, NULL);
|
||
|
|
||
|
//Even if we get multiple responses we only store 1 range
|
||
|
tipc_env->env[conidx]->rtus.svc.shdl = ind->start_hdl;
|
||
|
tipc_env->env[conidx]->rtus.svc.ehdl = ind->end_hdl;
|
||
|
}
|
||
|
|
||
|
// Increment number of services
|
||
|
tipc_env->env[conidx]->nb_svc++;
|
||
|
}
|
||
|
|
||
|
return (KE_MSG_CONSUMED);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
****************************************************************************************
|
||
|
* @brief Handles reception of the @ref TIPC_ENABLE_REQ message.
|
||
|
* The handler enables the Time Profile Client Role.
|
||
|
* @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 tipc_enable_req_handler(ke_msg_id_t const msgid,
|
||
|
struct tipc_enable_req const *param,
|
||
|
ke_task_id_t const dest_id,
|
||
|
ke_task_id_t const src_id)
|
||
|
{
|
||
|
// Status
|
||
|
uint8_t status = GAP_ERR_NO_ERROR;
|
||
|
// Get connection index
|
||
|
uint8_t conidx = KE_IDX_GET(dest_id);
|
||
|
// Get state
|
||
|
uint8_t state = ke_state_get(dest_id);
|
||
|
|
||
|
// Time Service Client Role Task Environment
|
||
|
struct tipc_env_tag *tipc_env = PRF_ENV_GET(TIPC, tipc);
|
||
|
|
||
|
ASSERT_INFO(tipc_env != NULL, dest_id, src_id);
|
||
|
if ((state == TIPC_IDLE) && (tipc_env->env[conidx] == NULL))
|
||
|
{
|
||
|
// allocate environment variable for task instance
|
||
|
tipc_env->env[conidx] = (struct tipc_cnx_env*) ke_malloc(sizeof(struct tipc_cnx_env),KE_MEM_ATT_DB);
|
||
|
memset(tipc_env->env[conidx], 0, sizeof(struct tipc_cnx_env));
|
||
|
|
||
|
//config connection, start discovering
|
||
|
if(param->con_type == PRF_CON_DISCOVERY)
|
||
|
{
|
||
|
//start discovering CTS on peer
|
||
|
prf_disc_svc_send(&(tipc_env->prf_env), conidx, ATT_SVC_CURRENT_TIME);
|
||
|
|
||
|
tipc_env->env[conidx]->last_uuid_req = ATT_SVC_CURRENT_TIME;
|
||
|
tipc_env->env[conidx]->last_svc_req = ATT_SVC_CURRENT_TIME;
|
||
|
|
||
|
// Go to DISCOVERING state
|
||
|
ke_state_set(dest_id, TIPC_DISCOVERING);
|
||
|
}
|
||
|
//normal connection, get saved att details
|
||
|
else
|
||
|
{
|
||
|
tipc_env->env[conidx]->cts = param->cts;
|
||
|
tipc_env->env[conidx]->ndcs = param->ndcs;
|
||
|
tipc_env->env[conidx]->rtus = param->rtus;
|
||
|
|
||
|
//send APP confirmation that can start normal connection
|
||
|
tipc_enable_rsp_send(tipc_env, conidx, GAP_ERR_NO_ERROR);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else if(state != TIPC_FREE)
|
||
|
{
|
||
|
status = PRF_ERR_REQ_DISALLOWED;
|
||
|
}
|
||
|
|
||
|
// send an error if request fails
|
||
|
if(status != GAP_ERR_NO_ERROR)
|
||
|
{
|
||
|
tipc_enable_rsp_send(tipc_env, conidx, status);
|
||
|
}
|
||
|
|
||
|
return (KE_MSG_CONSUMED);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
****************************************************************************************
|
||
|
* @brief Handles reception of the @ref TIPC_RD_CHAR_REQ message.
|
||
|
* Check if the handle exists in profile(already discovered) and send request, otherwise
|
||
|
* error to APP.
|
||
|
* @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 tipc_rd_char_req_handler(ke_msg_id_t const msgid,
|
||
|
struct tipc_rd_char_req const *param,
|
||
|
ke_task_id_t const dest_id,
|
||
|
ke_task_id_t const src_id)
|
||
|
{
|
||
|
|
||
|
uint8_t state = ke_state_get(dest_id);
|
||
|
uint8_t status = GAP_ERR_NO_ERROR;
|
||
|
|
||
|
// Get the address of the environment
|
||
|
struct tipc_env_tag *tipc_env = PRF_ENV_GET(TIPC, tipc);
|
||
|
// Get connection index
|
||
|
uint8_t conidx = KE_IDX_GET(dest_id);
|
||
|
|
||
|
if((state == TIPC_IDLE) && (tipc_env->env[conidx] != NULL))
|
||
|
{
|
||
|
// Service
|
||
|
struct prf_svc *svc = NULL;
|
||
|
// Attribute Handle
|
||
|
uint16_t search_hdl = ATT_INVALID_SEARCH_HANDLE;
|
||
|
|
||
|
//Next DST Change Service Characteristic
|
||
|
if (((param->char_code & TIPC_CHAR_NDCS_MASK) == TIPC_CHAR_NDCS_MASK) &&
|
||
|
((param->char_code & ~TIPC_CHAR_NDCS_MASK) < TIPC_CHAR_NDCS_MAX))
|
||
|
{
|
||
|
svc = &tipc_env->env[conidx]->ndcs.svc;
|
||
|
search_hdl = tipc_env->env[conidx]->ndcs.
|
||
|
chars[param->char_code & ~TIPC_CHAR_NDCS_MASK].val_hdl;
|
||
|
}
|
||
|
//Reference Time Update Service Characteristic
|
||
|
else if (((param->char_code & TIPC_CHAR_RTUS_MASK) == TIPC_CHAR_RTUS_MASK) &&
|
||
|
((param->char_code & ~TIPC_CHAR_RTUS_MASK) < TIPC_CHAR_RTUS_MAX))
|
||
|
{
|
||
|
svc = &tipc_env->env[conidx]->rtus.svc;
|
||
|
search_hdl = tipc_env->env[conidx]->rtus.
|
||
|
chars[param->char_code & ~TIPC_CHAR_RTUS_MASK].val_hdl;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
svc = &tipc_env->env[conidx]->cts.svc;
|
||
|
|
||
|
//Current Time Characteristic Descriptor
|
||
|
if (((param->char_code & TIPC_DESC_CTS_MASK) == TIPC_DESC_CTS_MASK) &&
|
||
|
((param->char_code & ~TIPC_DESC_CTS_MASK) < TIPC_DESC_CTS_MAX))
|
||
|
{
|
||
|
search_hdl = tipc_env->env[conidx]->cts.
|
||
|
descs[param->char_code & ~TIPC_DESC_CTS_MASK].desc_hdl;
|
||
|
}
|
||
|
//Current Time Service Characteristic
|
||
|
else if (param->char_code < TIPC_CHAR_CTS_MAX)
|
||
|
{
|
||
|
search_hdl = tipc_env->env[conidx]->cts.
|
||
|
chars[param->char_code].val_hdl;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Check if handle is viable
|
||
|
if ((search_hdl != ATT_INVALID_SEARCH_HANDLE) && (svc != NULL))
|
||
|
{
|
||
|
// Save char code
|
||
|
tipc_env->env[conidx]->last_char_code = param->char_code;
|
||
|
// Send read request
|
||
|
prf_read_char_send(&(tipc_env->prf_env), conidx, svc->shdl, svc->ehdl, search_hdl);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
status = PRF_ERR_INEXISTENT_HDL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
status = PRF_ERR_REQ_DISALLOWED;
|
||
|
}
|
||
|
|
||
|
if (status != GAP_ERR_NO_ERROR)
|
||
|
{
|
||
|
//send app error indication
|
||
|
struct tipc_rd_char_rsp *ind = KE_MSG_ALLOC(
|
||
|
TIPC_RD_CHAR_RSP,
|
||
|
prf_dst_task_get(&(tipc_env->prf_env), conidx),
|
||
|
prf_src_task_get(&(tipc_env->prf_env), conidx),
|
||
|
tipc_rd_char_rsp);
|
||
|
|
||
|
// It will be an TIPC status code
|
||
|
ind->status = status;
|
||
|
ind->op_code = param->char_code;
|
||
|
|
||
|
// send the message
|
||
|
ke_msg_send(ind);
|
||
|
}
|
||
|
|
||
|
return (KE_MSG_CONSUMED);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
****************************************************************************************
|
||
|
* @brief Handles reception of the @ref TIPC_CT_NTF_CFG_REQ message.
|
||
|
* It allows configuration of the peer ind/ntf/stop characteristic for a specified characteristic.
|
||
|
* Will return an error code if that cfg char does not exist.
|
||
|
* @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 tipc_ct_ntf_cfg_req_handler(ke_msg_id_t const msgid,
|
||
|
struct tipc_ct_ntf_cfg_req const *param,
|
||
|
ke_task_id_t const dest_id,
|
||
|
ke_task_id_t const src_id)
|
||
|
{
|
||
|
uint16_t cfg_hdl = ATT_INVALID_SEARCH_HANDLE;
|
||
|
// Get the address of the environment
|
||
|
struct tipc_env_tag *tipc_env = PRF_ENV_GET(TIPC, tipc);
|
||
|
// Get connection index
|
||
|
uint8_t conidx = KE_IDX_GET(dest_id);
|
||
|
// Status
|
||
|
uint8_t status = PRF_ERR_REQ_DISALLOWED;
|
||
|
|
||
|
if((tipc_env->env[conidx] != NULL) && (ke_state_get(dest_id) == TIPC_IDLE))
|
||
|
{
|
||
|
//Only NTF
|
||
|
if((param->cfg_val == PRF_CLI_STOP_NTFIND)||(param->cfg_val == PRF_CLI_START_NTF))
|
||
|
{
|
||
|
cfg_hdl = tipc_env->env[conidx]->cts.descs[TIPC_DESC_CTS_CURR_TIME_CLI_CFG].desc_hdl;
|
||
|
|
||
|
//check if the handle value exists
|
||
|
if (cfg_hdl != ATT_INVALID_SEARCH_HANDLE)
|
||
|
{
|
||
|
// Send GATT Write Request
|
||
|
prf_gatt_write_ntf_ind(&tipc_env->prf_env, conidx, cfg_hdl, param->cfg_val);
|
||
|
status = GAP_ERR_NO_ERROR;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
status = PRF_ERR_INEXISTENT_HDL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
status = PRF_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (status != GAP_ERR_NO_ERROR)
|
||
|
{
|
||
|
struct tipc_ct_ntf_cfg_rsp *ind = KE_MSG_ALLOC(
|
||
|
TIPC_CT_NTF_CFG_RSP,
|
||
|
prf_dst_task_get(&(tipc_env->prf_env), conidx),
|
||
|
prf_src_task_get(&(tipc_env->prf_env), conidx),
|
||
|
tipc_ct_ntf_cfg_rsp);
|
||
|
|
||
|
// It will be an TIPC status code
|
||
|
ind->status = status;
|
||
|
// send the message
|
||
|
ke_msg_send(ind);
|
||
|
}
|
||
|
|
||
|
return (KE_MSG_CONSUMED);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
****************************************************************************************
|
||
|
* @brief Handles reception of the @ref TIPC_WR_TIME_UPD_CTNL_PT_REQ message.
|
||
|
* Check if the handle exists in profile(already discovered) and send request, otherwise
|
||
|
* error to APP.
|
||
|
* @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 tipc_wr_time_upd_ctnl_pt_req_handler(ke_msg_id_t const msgid,
|
||
|
struct tipc_wr_time_udp_ctnl_pt_req const *param,
|
||
|
ke_task_id_t const dest_id,
|
||
|
ke_task_id_t const src_id)
|
||
|
{
|
||
|
// Get the address of the environment
|
||
|
struct tipc_env_tag *tipc_env = PRF_ENV_GET(TIPC, tipc);
|
||
|
uint8_t conidx = KE_IDX_GET(dest_id);
|
||
|
uint8_t status = PRF_ERR_REQ_DISALLOWED;
|
||
|
|
||
|
if((ke_state_get(dest_id) == TIPC_IDLE) && (tipc_env->env[conidx] != NULL))
|
||
|
{
|
||
|
// Check provided parameters
|
||
|
if ((param->value == TIPS_TIME_UPD_CTNL_PT_GET) ||
|
||
|
(param->value == TIPS_TIME_UPD_CTNL_PT_CANCEL))
|
||
|
{
|
||
|
if (tipc_env->env[conidx]->cts.chars[TIPC_CHAR_RTUS_TIME_UPD_CTNL_PT].char_hdl != ATT_INVALID_SEARCH_HANDLE)
|
||
|
{
|
||
|
// Send GATT Write Request
|
||
|
prf_gatt_write(&tipc_env->prf_env, conidx,
|
||
|
tipc_env->env[conidx]->rtus.chars[TIPC_CHAR_RTUS_TIME_UPD_CTNL_PT].val_hdl,
|
||
|
(uint8_t *)¶m->value, sizeof(uint8_t), GATTC_WRITE_NO_RESPONSE);
|
||
|
|
||
|
status = GAP_ERR_NO_ERROR;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
status = PRF_ERR_INEXISTENT_HDL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
status = PRF_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (status != GAP_ERR_NO_ERROR)
|
||
|
{
|
||
|
//send app error indication
|
||
|
struct tipc_wr_time_upd_ctnl_pt_rsp *ind = KE_MSG_ALLOC(
|
||
|
TIPC_WR_TIME_UPD_CTNL_PT_RSP,
|
||
|
prf_dst_task_get(&(tipc_env->prf_env), conidx),
|
||
|
prf_src_task_get(&(tipc_env->prf_env), conidx),
|
||
|
tipc_wr_time_upd_ctnl_pt_rsp);
|
||
|
|
||
|
// It will be an TIPC status code
|
||
|
ind->status = status;
|
||
|
|
||
|
// send the message
|
||
|
ke_msg_send(ind);
|
||
|
}
|
||
|
|
||
|
return (KE_MSG_CONSUMED);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
****************************************************************************************
|
||
|
* @brief Handles reception of the @ref GATTC_CMP_EVT message.
|
||
|
* This generic event is received for different requests, so need to keep track.
|
||
|
* @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_cmp_evt_handler(ke_msg_id_t const msgid,
|
||
|
struct gattc_cmp_evt const *param,
|
||
|
ke_task_id_t const dest_id,
|
||
|
ke_task_id_t const src_id)
|
||
|
{
|
||
|
uint8_t state = ke_state_get(dest_id);
|
||
|
uint8_t conidx = KE_IDX_GET(dest_id);
|
||
|
uint8_t status = PRF_ERR_STOP_DISC_CHAR_MISSING;
|
||
|
bool finished = false;
|
||
|
|
||
|
// Get the address of the environment
|
||
|
struct tipc_env_tag *tipc_env = PRF_ENV_GET(TIPC, tipc);
|
||
|
|
||
|
if((state == TIPC_DISCOVERING) && (tipc_env->env[conidx] != NULL))
|
||
|
{
|
||
|
if ((param->status == ATT_ERR_ATTRIBUTE_NOT_FOUND)||
|
||
|
(param->status == ATT_ERR_NO_ERROR))
|
||
|
{
|
||
|
// check characteristic validity
|
||
|
if(tipc_env->env[conidx]->nb_svc <= 1)
|
||
|
{
|
||
|
switch(tipc_env->env[conidx]->last_svc_req)
|
||
|
{
|
||
|
case ATT_SVC_CURRENT_TIME:
|
||
|
{
|
||
|
// Check service (mandatory)
|
||
|
status = prf_check_svc_char_validity(TIPC_CHAR_CTS_MAX,
|
||
|
tipc_env->env[conidx]->cts.chars,
|
||
|
tipc_cts_char);
|
||
|
|
||
|
// Check Descriptors (mandatory)
|
||
|
if(status == GAP_ERR_NO_ERROR)
|
||
|
{
|
||
|
status = prf_check_svc_char_desc_validity(TIPC_DESC_CTS_MAX,
|
||
|
tipc_env->env[conidx]->cts.descs,
|
||
|
tipc_cts_char_desc,
|
||
|
tipc_env->env[conidx]->cts.chars);
|
||
|
// Prepare to discovery next service
|
||
|
tipc_env->env[conidx]->last_svc_req = ATT_SVC_NEXT_DST_CHANGE;
|
||
|
}
|
||
|
}break;
|
||
|
|
||
|
case ATT_SVC_NEXT_DST_CHANGE:
|
||
|
{
|
||
|
// Check service (if found)
|
||
|
if(tipc_env->env[conidx]->nb_svc)
|
||
|
{
|
||
|
status = prf_check_svc_char_validity(TIPC_CHAR_NDCS_MAX,
|
||
|
tipc_env->env[conidx]->ndcs.chars,
|
||
|
tipc_ndcs_char);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
status = GAP_ERR_NO_ERROR;
|
||
|
}
|
||
|
// Prepare to discovery next service
|
||
|
tipc_env->env[conidx]->last_svc_req = ATT_SVC_REF_TIME_UPDATE;
|
||
|
}break;
|
||
|
|
||
|
case ATT_SVC_REF_TIME_UPDATE:
|
||
|
{
|
||
|
// Check service (if found)
|
||
|
if(tipc_env->env[conidx]->nb_svc)
|
||
|
{
|
||
|
status = prf_check_svc_char_validity(TIPC_CHAR_RTUS_MAX,
|
||
|
tipc_env->env[conidx]->rtus.chars,
|
||
|
tipc_rtus_char);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
status = GAP_ERR_NO_ERROR;
|
||
|
}
|
||
|
|
||
|
if(status == GAP_ERR_NO_ERROR)
|
||
|
{
|
||
|
// send app the details about the discovered TIPS DB to save
|
||
|
tipc_enable_rsp_send(tipc_env, conidx, GAP_ERR_NO_ERROR);
|
||
|
// Discovery is finished
|
||
|
finished = true;
|
||
|
}
|
||
|
}break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
// too many services
|
||
|
else
|
||
|
{
|
||
|
status = PRF_ERR_MULTIPLE_SVC;
|
||
|
}
|
||
|
|
||
|
if(status == GAP_ERR_NO_ERROR)
|
||
|
{
|
||
|
// reset number of services
|
||
|
tipc_env->env[conidx]->nb_svc = 0;
|
||
|
|
||
|
if (!finished)
|
||
|
{
|
||
|
//start discovering following service on peer
|
||
|
prf_disc_svc_send(&(tipc_env->prf_env), conidx, tipc_env->env[conidx]->last_svc_req);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// stop discovery procedure
|
||
|
tipc_enable_rsp_send(tipc_env, conidx, status);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if(state == TIPC_IDLE)
|
||
|
{
|
||
|
switch(param->operation)
|
||
|
{
|
||
|
case GATTC_WRITE:
|
||
|
{
|
||
|
struct tipc_ct_ntf_cfg_rsp *wr_cfm = KE_MSG_ALLOC(
|
||
|
TIPC_CT_NTF_CFG_RSP,
|
||
|
prf_dst_task_get(&(tipc_env->prf_env), conidx),
|
||
|
prf_src_task_get(&(tipc_env->prf_env), conidx),
|
||
|
tipc_ct_ntf_cfg_rsp);
|
||
|
|
||
|
//it will be a GATT status code
|
||
|
wr_cfm->status = param->status;
|
||
|
// send the message
|
||
|
ke_msg_send(wr_cfm);
|
||
|
} break;
|
||
|
|
||
|
case GATTC_WRITE_NO_RESPONSE:
|
||
|
{
|
||
|
struct tipc_wr_time_upd_ctnl_pt_rsp *wr_cfm = KE_MSG_ALLOC(
|
||
|
TIPC_WR_TIME_UPD_CTNL_PT_RSP,
|
||
|
prf_dst_task_get(&(tipc_env->prf_env), conidx),
|
||
|
prf_src_task_get(&(tipc_env->prf_env), conidx),
|
||
|
tipc_wr_time_upd_ctnl_pt_rsp);
|
||
|
|
||
|
//it will be a GATT status code
|
||
|
wr_cfm->status = param->status;
|
||
|
// send the message
|
||
|
ke_msg_send(wr_cfm);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case GATTC_READ:
|
||
|
{
|
||
|
// an error occurs while reading peer attribute, inform app
|
||
|
if(param->status != GAP_ERR_NO_ERROR)
|
||
|
{
|
||
|
struct tipc_rd_char_rsp *rd_cfm = KE_MSG_ALLOC(
|
||
|
TIPC_RD_CHAR_RSP,
|
||
|
prf_dst_task_get(&(tipc_env->prf_env), conidx),
|
||
|
prf_src_task_get(&(tipc_env->prf_env), conidx),
|
||
|
tipc_rd_char_rsp);
|
||
|
|
||
|
//it will be a GATT status code
|
||
|
rd_cfm->status = param->status;
|
||
|
rd_cfm->op_code = tipc_env->env[conidx]->last_char_code;
|
||
|
// send the message
|
||
|
ke_msg_send(rd_cfm);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return (KE_MSG_CONSUMED);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
****************************************************************************************
|
||
|
* @brief Handles reception of the @ref GATTC_READ_IND message.
|
||
|
* Generic event received after every simple read command sent to peer server.
|
||
|
* @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_ind_handler(ke_msg_id_t const msgid,
|
||
|
struct gattc_read_ind const *param,
|
||
|
ke_task_id_t const dest_id,
|
||
|
ke_task_id_t const src_id)
|
||
|
{
|
||
|
// Get the address of the environment
|
||
|
struct tipc_env_tag *tipc_env = PRF_ENV_GET(TIPC, tipc);
|
||
|
uint8_t conidx = KE_IDX_GET(dest_id);
|
||
|
|
||
|
//Build the message
|
||
|
struct tipc_rd_char_rsp * ind = KE_MSG_ALLOC(
|
||
|
TIPC_RD_CHAR_RSP,
|
||
|
prf_dst_task_get(&(tipc_env->prf_env), conidx),
|
||
|
dest_id,
|
||
|
tipc_rd_char_rsp);
|
||
|
|
||
|
//Current Time Characteristic
|
||
|
if (tipc_env->env[conidx]->last_char_code == TIPC_RD_CTS_CURR_TIME)
|
||
|
{
|
||
|
ind->op_code = TIPC_RD_CTS_CURR_TIME;
|
||
|
// Unpack Current Time Value.
|
||
|
tipc_unpack_curr_time_value(&(ind->value.curr_time), (uint8_t *) param->value);
|
||
|
}
|
||
|
//Local Time Information Characteristic
|
||
|
else if (tipc_env->env[conidx]->last_char_code == TIPC_RD_CTS_LOCAL_TIME_INFO)
|
||
|
{
|
||
|
ind->op_code = TIPC_RD_CTS_LOCAL_TIME_INFO;
|
||
|
// Local Time Information Value
|
||
|
ind->value.loc_time_info.time_zone = param->value[0];
|
||
|
ind->value.loc_time_info.dst_offset = param->value[1];
|
||
|
}
|
||
|
//Reference Time Information Characteristic
|
||
|
else if (tipc_env->env[conidx]->last_char_code == TIPC_RD_CTS_REF_TIME_INFO)
|
||
|
{
|
||
|
ind->op_code = TIPC_RD_CTS_REF_TIME_INFO;
|
||
|
// Reference Time Information Value
|
||
|
ind->value.ref_time_info.time_source = param->value[0];
|
||
|
ind->value.ref_time_info.time_accuracy = param->value[1];
|
||
|
ind->value.ref_time_info.days_update = param->value[2];
|
||
|
ind->value.ref_time_info.hours_update = param->value[3];
|
||
|
}
|
||
|
//Time with DST Characteristic
|
||
|
else if (tipc_env->env[conidx]->last_char_code == TIPC_RD_NDCS_TIME_WITH_DST)
|
||
|
{
|
||
|
ind->op_code = TIPC_RD_NDCS_TIME_WITH_DST;
|
||
|
// Time with DST Value
|
||
|
tipc_unpack_time_dst_value(&ind->value.time_with_dst, (uint8_t *) param->value);
|
||
|
}
|
||
|
//Time Update State Characteristic
|
||
|
else if (tipc_env->env[conidx]->last_char_code == TIPC_RD_RTUS_TIME_UPD_STATE)
|
||
|
{
|
||
|
ind->op_code = TIPC_RD_RTUS_TIME_UPD_STATE;
|
||
|
// Reference Time Information Value
|
||
|
ind->value.time_upd_state.current_state = param->value[0];
|
||
|
ind->value.time_upd_state.result = param->value[1];
|
||
|
}
|
||
|
//Current Time Characteristic - Client Characteristic Configuration Descriptor
|
||
|
else if (tipc_env->env[conidx]->last_char_code == TIPC_RD_CTS_CURR_TIME_CLI_CFG)
|
||
|
{
|
||
|
ind->op_code = TIPC_RD_CTS_CURR_TIME_CLI_CFG;
|
||
|
// Notification Configuration
|
||
|
memcpy(&ind->value.ntf_cfg, ¶m->value[0], sizeof(uint16_t));
|
||
|
}
|
||
|
|
||
|
ke_msg_send(ind);
|
||
|
|
||
|
return (KE_MSG_CONSUMED);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
****************************************************************************************
|
||
|
* @brief Handles reception of the @ref GATTC_EVENT_IND 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 gattc_event_ind_handler(ke_msg_id_t const msgid,
|
||
|
struct gattc_event_ind const *param,
|
||
|
ke_task_id_t const dest_id,
|
||
|
ke_task_id_t const src_id)
|
||
|
{
|
||
|
// Get the address of the environment
|
||
|
struct tipc_env_tag *tipc_env = PRF_ENV_GET(TIPC, tipc);
|
||
|
uint8_t conidx = KE_IDX_GET(dest_id);
|
||
|
|
||
|
if(tipc_env->env[conidx] != NULL)
|
||
|
{
|
||
|
if(param->handle == tipc_env->env[conidx]->cts.chars[TIPC_CHAR_CTS_CURR_TIME].val_hdl)
|
||
|
{
|
||
|
//Build a TIPC_CT_IND message
|
||
|
struct tipc_ct_ind * ind = KE_MSG_ALLOC(
|
||
|
TIPC_CT_IND,
|
||
|
prf_dst_task_get(&(tipc_env->prf_env), conidx),
|
||
|
prf_src_task_get(&(tipc_env->prf_env), conidx),
|
||
|
tipc_ct_ind);
|
||
|
|
||
|
// Unpack Current Time Value.
|
||
|
tipc_unpack_curr_time_value(&(ind->ct_val), (uint8_t*) param->value);
|
||
|
|
||
|
ke_msg_send(ind);
|
||
|
}
|
||
|
}
|
||
|
return (KE_MSG_CONSUMED);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* GLOBAL VARIABLE DEFINITIONS
|
||
|
****************************************************************************************
|
||
|
*/
|
||
|
|
||
|
/// Default State handlers definition
|
||
|
KE_MSG_HANDLER_TAB(tipc)
|
||
|
{
|
||
|
{TIPC_ENABLE_REQ, (ke_msg_func_t)tipc_enable_req_handler},
|
||
|
{GATTC_SDP_SVC_IND, (ke_msg_func_t)gattc_sdp_svc_ind_handler},
|
||
|
{GATTC_CMP_EVT, (ke_msg_func_t)gattc_cmp_evt_handler},
|
||
|
{TIPC_CT_NTF_CFG_REQ, (ke_msg_func_t)tipc_ct_ntf_cfg_req_handler},
|
||
|
{GATTC_EVENT_IND, (ke_msg_func_t)gattc_event_ind_handler},
|
||
|
{TIPC_RD_CHAR_REQ, (ke_msg_func_t)tipc_rd_char_req_handler},
|
||
|
{GATTC_READ_IND, (ke_msg_func_t)gattc_read_ind_handler},
|
||
|
{TIPC_WR_TIME_UPD_CTNL_PT_REQ, (ke_msg_func_t)tipc_wr_time_upd_ctnl_pt_req_handler},
|
||
|
};
|
||
|
|
||
|
void tipc_task_init(struct ke_task_desc *task_desc)
|
||
|
{
|
||
|
// Get the address of the environment
|
||
|
struct tipc_env_tag *tipc_env = PRF_ENV_GET(TIPC, tipc);
|
||
|
|
||
|
task_desc->msg_handler_tab = tipc_msg_handler_tab;
|
||
|
task_desc->msg_cnt = ARRAY_LEN(tipc_msg_handler_tab);
|
||
|
task_desc->state = tipc_env->state;
|
||
|
task_desc->idx_max = TIPC_IDX_MAX;
|
||
|
}
|
||
|
|
||
|
#endif /* (BLE_TIP_CLIENT) */
|
||
|
/// @} TIPCTASK
|