/** **************************************************************************************** * @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_CLIENT_GET_ENV(dest_id, tipc); // Check provided parameters if ((param->conhdl == gapc_get_conhdl(tipc_env->con_info.conidx)) && ((param->value == TIPS_TIME_UPD_CTNL_PT_GET) || (param->value == TIPS_TIME_UPD_CTNL_PT_CANCEL))) { if (tipc_env->cts.chars[TIPC_CHAR_RTUS_TIME_UPD_CTNL_PT].char_hdl != ATT_INVALID_SEARCH_HANDLE) { // Send GATT Write Request prf_gatt_write(&tipc_env->con_info, tipc_env->rtus.chars[TIPC_CHAR_RTUS_TIME_UPD_CTNL_PT].val_hdl, (uint8_t *)¶m->value, sizeof(uint8_t), GATTC_WRITE_NO_RESPONSE); } //send app error indication for inexistent handle for this characteristic else { tipc_error_ind_send(tipc_env, PRF_ERR_INEXISTENT_HDL); } } else { tipc_error_ind_send(tipc_env, PRF_ERR_INVALID_PARAM); } 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 = 0x0000; // Get the address of the environment struct tipc_env_tag *tipc_env = PRF_CLIENT_GET_ENV(dest_id, tipc); if(param->conhdl == gapc_get_conhdl(tipc_env->con_info.conidx)) { cfg_hdl = tipc_env->cts.descs[TIPC_DESC_CTS_CURR_TIME_CLI_CFG].desc_hdl; //Only NTF if(!((param->cfg_val == PRF_CLI_STOP_NTFIND)||(param->cfg_val == PRF_CLI_START_NTF))) { tipc_error_ind_send(tipc_env, PRF_ERR_INVALID_PARAM); } else { //check if the handle value exists if (cfg_hdl != ATT_INVALID_SEARCH_HANDLE) { // Send GATT Write Request prf_gatt_write_ntf_ind(&tipc_env->con_info, cfg_hdl, param->cfg_val); } else { tipc_error_ind_send(tipc_env, PRF_ERR_INEXISTENT_HDL); } } } else { tipc_error_ind_send(tipc_env, PRF_ERR_INVALID_PARAM); } 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 status; // Get the address of the environment struct tipc_env_tag *tipc_env = PRF_CLIENT_GET_ENV(dest_id, tipc); if(state == TIPC_DISCOVERING) { if ((param->status == ATT_ERR_ATTRIBUTE_NOT_FOUND)|| (param->status == ATT_ERR_NO_ERROR)) { // Currently Discovering Current Time service characteristics. if(tipc_env->last_svc_req == ATT_SVC_CURRENT_TIME) { // service start/end handles has been received if(tipc_env->last_uuid_req == ATT_SVC_CURRENT_TIME) { // check if service handles are not ok if (tipc_env->cts.svc.shdl == ATT_INVALID_HANDLE) { // stop discovery procedure. tipc_enable_cfm_send(tipc_env, &tipc_env->con_info, PRF_ERR_STOP_DISC_CHAR_MISSING); } //too many services found only one such service should exist else if(tipc_env->nb_svc != 1) { // stop discovery procedure. tipc_enable_cfm_send(tipc_env, &tipc_env->con_info, PRF_ERR_MULTIPLE_SVC); } // check if service handles are ok else { //discover all CTS characteristics prf_disc_char_all_send(&(tipc_env->con_info), &(tipc_env->cts.svc)); tipc_env->last_uuid_req = ATT_DECL_CHARACTERISTIC; } } else if(tipc_env->last_uuid_req == ATT_DECL_CHARACTERISTIC) { status = prf_check_svc_char_validity(TIPC_CHAR_CTS_MAX, tipc_env->cts.chars, tipc_cts_char); // check for characteristic properties. if(status == PRF_ERR_OK) { tipc_env->last_uuid_req = ATT_INVALID_HANDLE; tipc_env->last_char_code = TIPC_CHAR_CTS_CURR_TIME; //request all service characteristic description for CTS prf_disc_char_desc_send(&(tipc_env->con_info), &(tipc_env->cts.chars[TIPC_CHAR_CTS_CURR_TIME])); } else { // stop discovery procedure. tipc_enable_cfm_send(tipc_env, &tipc_env->con_info, status); } } else { status = prf_check_svc_char_desc_validity(TIPC_DESC_CTS_MAX, tipc_env->cts.descs, tipc_cts_char_desc, tipc_env->cts.chars); if(status == PRF_ERR_OK) { // reset number of services tipc_env->nb_svc = 0; //start discovering NDCS on peer prf_disc_svc_send(&(tipc_env->con_info), ATT_SVC_NEXT_DST_CHANGE); tipc_env->last_uuid_req = ATT_SVC_NEXT_DST_CHANGE; tipc_env->last_svc_req = ATT_SVC_NEXT_DST_CHANGE; } else { // stop discovery procedure. tipc_enable_cfm_send(tipc_env, &tipc_env->con_info, status); } } } // Currently Next DST Change service characteristics. else if(tipc_env->last_svc_req == ATT_SVC_NEXT_DST_CHANGE) { // service start/end handles has been received if(tipc_env->last_uuid_req == ATT_SVC_NEXT_DST_CHANGE) { if (tipc_env->ndcs.svc.shdl == ATT_INVALID_HANDLE) { // reset number of services tipc_env->nb_svc = 0; //start discovering RTUS on peer prf_disc_svc_send(&(tipc_env->con_info), ATT_SVC_REF_TIME_UPDATE); tipc_env->last_uuid_req = ATT_SVC_REF_TIME_UPDATE; tipc_env->last_svc_req = ATT_SVC_REF_TIME_UPDATE; } //too many services found only one such service should exist else if(tipc_env->nb_svc != 1) { // stop discovery procedure. tipc_enable_cfm_send(tipc_env, &tipc_env->con_info, PRF_ERR_MULTIPLE_SVC); } // check if service handles are ok else { //discover all NDCS characteristics prf_disc_char_all_send(&(tipc_env->con_info), &(tipc_env->ndcs.svc)); tipc_env->last_uuid_req = ATT_DECL_CHARACTERISTIC; } } else if(tipc_env->last_uuid_req == ATT_DECL_CHARACTERISTIC) { status = prf_check_svc_char_validity(TIPC_CHAR_NDCS_MAX, tipc_env->ndcs.chars, tipc_ndcs_char); // check for characteristic properties. if(status == PRF_ERR_OK) { // reset number of services tipc_env->nb_svc = 0; //start discovering RTUS on peer prf_disc_svc_send(&(tipc_env->con_info), ATT_SVC_REF_TIME_UPDATE); tipc_env->last_uuid_req = ATT_SVC_REF_TIME_UPDATE; tipc_env->last_svc_req = ATT_SVC_REF_TIME_UPDATE; } else { // stop discovery procedure. tipc_enable_cfm_send(tipc_env, &tipc_env->con_info, status); } } } // Currently Reference Time Update service characteristics. else if(tipc_env->last_svc_req == ATT_SVC_REF_TIME_UPDATE) { // service start/end handles has been received if(tipc_env->last_uuid_req == ATT_SVC_REF_TIME_UPDATE) { if (tipc_env->rtus.svc.shdl == ATT_INVALID_HANDLE) { // send app the details about the discovered TIPS DB to save tipc_enable_cfm_send(tipc_env, &tipc_env->con_info, PRF_ERR_OK); } //too many services found only one such service should exist else if(tipc_env->nb_svc != 1) { // stop discovery procedure. tipc_enable_cfm_send(tipc_env, &tipc_env->con_info, PRF_ERR_MULTIPLE_SVC); } // check if service handles are ok else { //discover all RTUS characteristics prf_disc_char_all_send(&(tipc_env->con_info), &(tipc_env->rtus.svc)); tipc_env->last_uuid_req = ATT_DECL_CHARACTERISTIC; } } else if(tipc_env->last_uuid_req == ATT_DECL_CHARACTERISTIC) { status = prf_check_svc_char_validity(TIPC_CHAR_RTUS_MAX, tipc_env->rtus.chars, tipc_rtus_char); // check for characteristic properties. if(status == PRF_ERR_OK) { // send app the details about the discovered TIPS DB to save tipc_enable_cfm_send(tipc_env, &tipc_env->con_info, PRF_ERR_OK); } else { // stop discovery procedure. tipc_enable_cfm_send(tipc_env, &tipc_env->con_info, status); } } } } } else if(state == TIPC_CONNECTED) { switch(param->req_type) { case GATTC_WRITE: case GATTC_WRITE_NO_RESPONSE: { struct tipc_wr_char_rsp *wr_cfm = KE_MSG_ALLOC(TIPC_WR_CHAR_RSP, tipc_env->con_info.appid, dest_id, tipc_wr_char_rsp); wr_cfm->conhdl = gapc_get_conhdl(tipc_env->con_info.conidx); //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 != GATT_ERR_NO_ERROR) { tipc_error_ind_send(tipc_env, param->status); } } break; default: break; } } 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) { // Attribute Handle uint16_t search_hdl = ATT_INVALID_SEARCH_HANDLE; // Service struct prf_svc *svc; // Get the address of the environment struct tipc_env_tag *tipc_env = PRF_CLIENT_GET_ENV(dest_id, tipc); if(param->conhdl == gapc_get_conhdl(tipc_env->con_info.conidx)) { //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->ndcs.svc; search_hdl = tipc_env->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->rtus.svc; search_hdl = tipc_env->rtus.chars[param->char_code & ~TIPC_CHAR_RTUS_MASK].val_hdl; } else { svc = &tipc_env->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->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->cts.chars[param->char_code].val_hdl; } } // Check if handle is viable if (search_hdl != ATT_INVALID_SEARCH_HANDLE) { tipc_env->last_char_code = param->char_code; prf_read_char_send(&(tipc_env->con_info), svc->shdl, svc->ehdl, search_hdl); } else { tipc_error_ind_send(tipc_env, PRF_ERR_INEXISTENT_HDL); } } else { tipc_error_ind_send(tipc_env, PRF_ERR_INVALID_PARAM); } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref GATT_READ_CHAR_RESP 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 gatt_rd_char_rsp_handler(ke_msg_id_t const msgid, struct gatt_read_char_resp 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_CLIENT_GET_ENV(dest_id, tipc); if (param->status == PRF_ERR_OK) { //Current Time Characteristic if (tipc_env->last_char_code == TIPC_RD_CTS_CURR_TIME) { //Build a TIPC_CT_IND message struct tipc_ct_ind * ind = KE_MSG_ALLOC(TIPC_CT_IND, tipc_env->con_info.appid, dest_id, tipc_ct_ind); // retrieve connection handle ind->conhdl = tipc_env->con_info.conhdl; // Unpack Current Time Value. tipc_unpack_curr_time_value(&(ind->ct_val), (uint8_t*) param->data.data); //Indication Type ind->ind_type = TIP_RD_RSP, ke_msg_send(ind); } //Local Time Information Characteristic else if (tipc_env->last_char_code == TIPC_RD_CTS_LOCAL_TIME_INFO) { //Build a TIPC_LTI_RD_RSP message struct tipc_lti_rd_rsp * rsp = KE_MSG_ALLOC(TIPC_LTI_RD_RSP, tipc_env->con_info.appid, dest_id, tipc_lti_rd_rsp); // Retrieve Connection handle rsp->conhdl = tipc_env->con_info.conhdl; // Local Time Information Value rsp->lti_val.time_zone = param->data.data[0]; rsp->lti_val.dst_offset = param->data.data[1]; ke_msg_send(rsp); } //Reference Time Information Characteristic else if (tipc_env->last_char_code == TIPC_RD_CTS_REF_TIME_INFO) { //Build a TIPC_RTI_RD_RSP message struct tipc_rti_rd_rsp * rsp = KE_MSG_ALLOC(TIPC_RTI_RD_RSP, tipc_env->con_info.appid, dest_id, tipc_rti_rd_rsp); // Retrieve Connection handle rsp->conhdl = tipc_env->con_info.conhdl; // Reference Time Information Value rsp->rti_val.time_source = param->data.data[0]; rsp->rti_val.time_accuracy = param->data.data[1]; rsp->rti_val.days_update = param->data.data[2]; rsp->rti_val.hours_update = param->data.data[3]; ke_msg_send(rsp); } //Time with DST Characteristic else if (tipc_env->last_char_code == TIPC_RD_NDCS_TIME_WITH_DST) { //Build a TIPC_TDST_RD_RSP message struct tipc_tdst_rd_rsp * rsp = KE_MSG_ALLOC(TIPC_TDST_RD_RSP, tipc_env->con_info.appid, dest_id, tipc_tdst_rd_rsp); // Retrieve Connection handle rsp->conhdl = tipc_env->con_info.conhdl; // Time with DST Value prf_unpack_date_time((uint8_t*) &(param->data.data[0]), &(rsp->tdst_val.date_time)); rsp->tdst_val.dst_offset = param->data.data[7]; ke_msg_send(rsp); } //Time Update State Characteristic else if (tipc_env->last_char_code == TIPC_RD_RTUS_TIME_UPD_STATE) { //Build a TIPC_TUS_RD_RSP message struct tipc_tus_rd_rsp * rsp = KE_MSG_ALLOC(TIPC_TUS_RD_RSP, tipc_env->con_info.appid, dest_id, tipc_tus_rd_rsp); // Retrieve Connection handle rsp->conhdl = tipc_env->con_info.conhdl; // Reference Time Information Value rsp->tus_val.current_state = param->data.data[0]; rsp->tus_val.result = param->data.data[1]; ke_msg_send(rsp); } //Current Time Characteristic - Client Characteristic Configuration Descriptor else if (tipc_env->last_char_code == TIPC_RD_CTS_CURR_TIME_CLI_CFG) { //Build a TIPC_CT_NTF_CFG_RD_RSP message struct tipc_ct_ntf_cfg_rd_rsp * rsp = KE_MSG_ALLOC(TIPC_CT_NTF_CFG_RD_RSP, tipc_env->con_info.appid, dest_id, tipc_ct_ntf_cfg_rd_rsp); // Retrieve Connection handle rsp->conhdl = tipc_env->con_info.conhdl; // Notification Configuration memcpy(&rsp->ntf_cfg, ¶m->data.data[0], sizeof(rsp->ntf_cfg)); ke_msg_send(rsp); } } else { tipc_error_ind_send(tipc_env, param->status); } return (KE_MSG_CONSUMED); }