pinebuds/services/ble_profiles/tip/tipc/src/tipc_task.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 *)&param->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, &param->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