/** **************************************************************************************** * @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); // Get the address of the environment struct scppc_env_tag *scppc_env = PRF_CLIENT_GET_ENV(dest_id, scppc); uint8_t status = PRF_ERR_OK; if(state == SCPPC_DISCOVERING) { if ((param->status == ATT_ERR_ATTRIBUTE_NOT_FOUND) || (param->status == ATT_ERR_NO_ERROR)) { // Service start/end handles has been received if(scppc_env->last_uuid_req == ATT_SVC_SCAN_PARAMETERS) { // check if service handles are not ok if(scppc_env->scps.svc.shdl== ATT_INVALID_HANDLE) { // stop discovery procedure. scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, PRF_ERR_STOP_DISC_CHAR_MISSING); } // Too many services found only one such service should exist else if(scppc_env->nb_svc > 1) { scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, PRF_ERR_MULTIPLE_SVC); } else { // Discover all SCPS characteristics prf_disc_char_all_send(&(scppc_env->con_info), &(scppc_env->scps.svc)); scppc_env->last_uuid_req = ATT_DECL_CHARACTERISTIC; } } else if(scppc_env->last_uuid_req == ATT_DECL_CHARACTERISTIC) { status = prf_check_svc_char_validity(SCPPC_CHAR_MAX, scppc_env->scps.chars, scppc_scps_char); if(status == PRF_ERR_OK) { //If Scan Refresh Char. is present, discover its descriptor if (scppc_env->scps.chars[SCPPC_CHAR_SCAN_REFRESH].char_hdl != ATT_INVALID_HANDLE) { scppc_env->last_uuid_req = ATT_INVALID_HANDLE; scppc_env->last_char_code = scppc_scps_char_desc[SCPPC_DESC_SCAN_REFRESH_CFG].char_code; // Discover Scan Refresh Char. Descriptor - Mandatory prf_disc_char_desc_send(&(scppc_env->con_info), &(scppc_env->scps.chars[scppc_env->last_char_code])); } else { scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, status); } } else { // Stop discovery procedure. scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, status); } } else { status = prf_check_svc_char_desc_validity(SCPPC_DESC_MAX, scppc_env->scps.descs, scppc_scps_char_desc, scppc_env->scps.chars); scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, status); } if (status == PRF_ERR_OK) { // Write Scan Interval Windows value struct scppc_scan_intv_wd_wr_req * req = KE_MSG_ALLOC(SCPPC_SCAN_INTV_WD_WR_REQ, dest_id, dest_id, scppc_scan_intv_wd_wr_req); req->conhdl = gapc_get_conhdl(scppc_env->con_info.conidx); co_write16p(&req->scan_intv_wd.le_scan_intv, scppc_env->scan_intv_wd.le_scan_intv); co_write16p(&req->scan_intv_wd.le_scan_window, scppc_env->scan_intv_wd.le_scan_window); ke_msg_send(req); } } } else if (state == SCPPC_CONNECTED) { switch(param->req_type) { case GATTC_WRITE: { struct scppc_wr_char_rsp *wr_cfm = KE_MSG_ALLOC(SCPPC_WR_CHAR_RSP, scppc_env->con_info.appid, dest_id, scppc_wr_char_rsp); wr_cfm->conhdl = gapc_get_conhdl(scppc_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: { if(param->status != GATT_ERR_NO_ERROR) { // an error occurs while reading peer device attribute scppc_error_ind_send(scppc_env, param->status); } } break; default: break; } } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref SCPPC_ENABLE_REQ message. * The handler enables the Scan Parameters 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 scppc_enable_req_handler(ke_msg_id_t const msgid, struct scppc_enable_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Status uint8_t status; // Scan Parameters Profile Client Role Task Environment struct scppc_env_tag *scppc_env; // Connection Information struct prf_con_info con_info; // Fill the Connection Information structure con_info.conidx = gapc_get_conidx(param->conhdl); con_info.prf_id = dest_id; con_info.appid = src_id; // Add an environment for the provided device status = PRF_CLIENT_ENABLE(con_info, param, scppc); if (status == PRF_ERR_FEATURE_NOT_SUPPORTED) { // The message has been forwarded to another task id. return (KE_MSG_NO_FREE); } else if (status == PRF_ERR_OK) { scppc_env = PRF_CLIENT_GET_ENV(dest_id, scppc); // Save Scan Interval Window value memcpy(&scppc_env->scan_intv_wd, ¶m->scan_intv_wd, sizeof(struct scan_intv_wd)); // Config connection, start discovering if(param->con_type == PRF_CON_DISCOVERY) { //start discovering SCPS on peer prf_disc_svc_send(&(scppc_env->con_info), ATT_SVC_SCAN_PARAMETERS); scppc_env->last_uuid_req = ATT_SVC_SCAN_PARAMETERS; // Go to DISCOVERING state ke_state_set(dest_id, SCPPC_DISCOVERING); } // Normal connection, get saved att details else { scppc_env->scps = param->scps; if (scppc_env->scps.chars[SCPPC_CHAR_SCAN_REFRESH].char_hdl != ATT_INVALID_HANDLE) { /* If connected to a bonded Scan Server, the Scan Client shall enable notifications of the * Scan Refresh characteristic using the Client Characteristic Configuration descriptor. */ struct scppc_scan_refresh_ntf_cfg_req *req = KE_MSG_ALLOC(SCPPC_SCAN_REFRESH_NTF_CFG_REQ, dest_id, dest_id, scppc_scan_refresh_ntf_cfg_req); req->conhdl = gapc_get_conhdl(scppc_env->con_info.conidx); req->ntf_cfg = PRF_CLI_START_NTF; // send the message ke_msg_send(req); } else { // Write Scan Interval Windows value struct scppc_scan_intv_wd_wr_req * req = KE_MSG_ALLOC(SCPPC_SCAN_INTV_WD_WR_REQ, dest_id, dest_id, scppc_scan_intv_wd_wr_req); req->conhdl = gapc_get_conhdl(scppc_env->con_info.conidx); co_write16p(&req->scan_intv_wd.le_scan_intv, scppc_env->scan_intv_wd.le_scan_intv); co_write16p(&req->scan_intv_wd.le_scan_window, scppc_env->scan_intv_wd.le_scan_window); ke_msg_send(req); } scppc_enable_cfm_send(scppc_env, &con_info, PRF_ERR_OK); } } else { // An error has been raised during the process, scps is NULL and won't be handled scppc_enable_cfm_send(NULL, &con_info, status); } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref GATT_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 gatt_cmp_evt_handler(ke_msg_id_t const msgid, struct gatt_cmp_evt const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Get the address of the environment struct scppc_env_tag *scppc_env = PRF_CLIENT_GET_ENV(dest_id, scppc); uint8_t status = PRF_ERR_OK; if ((param->status == ATT_ERR_ATTRIBUTE_NOT_FOUND) || (param->status == ATT_ERR_NO_ERROR)) { // Service start/end handles has been received if(scppc_env->last_uuid_req == ATT_SVC_SCAN_PARAMETERS) { // check if service handles are not ok if(scppc_env->scps.svc.shdl== ATT_INVALID_HANDLE) { // stop discovery procedure. scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, PRF_ERR_STOP_DISC_CHAR_MISSING); } // Too many services found only one such service should exist else if(scppc_env->nb_svc > 1) { scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, PRF_ERR_MULTIPLE_SVC); } else { // Discover all SCPS characteristics prf_disc_char_all_send(&(scppc_env->con_info), &(scppc_env->scps.svc)); scppc_env->last_uuid_req = ATT_DECL_CHARACTERISTIC; } } else if(scppc_env->last_uuid_req == ATT_DECL_CHARACTERISTIC) { status = prf_check_svc_char_validity(SCPPC_CHAR_MAX, scppc_env->scps.chars, scppc_scps_char); if(status == PRF_ERR_OK) { //If Scan Refresh Char. is present, discover its descriptor if (scppc_env->scps.chars[SCPPC_CHAR_SCAN_REFRESH].char_hdl != ATT_INVALID_HANDLE) { scppc_env->last_uuid_req = ATT_INVALID_HANDLE; scppc_env->last_char_code = scppc_scps_char_desc[SCPPC_DESC_SCAN_REFRESH_CFG].char_code; // Discover Scan Refresh Char. Descriptor - Mandatory prf_disc_char_desc_send(&(scppc_env->con_info), &(scppc_env->scps.chars[scppc_env->last_char_code])); } else { scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, status); } } else { // Stop discovery procedure. scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, status); } } else { status = prf_check_svc_char_desc_validity(SCPPC_DESC_MAX, scppc_env->scps.descs, scppc_scps_char_desc, scppc_env->scps.chars); scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, status); } if (status == PRF_ERR_OK) { // Write Scan Interval Windows value struct scppc_scan_intv_wd_wr_req * req = KE_MSG_ALLOC(SCPPC_SCAN_INTV_WD_WR_REQ, dest_id, dest_id, scppc_scan_intv_wd_wr_req); req->conhdl = scppc_env->con_info.conhdl; co_write16p(&req->scan_intv_wd.le_scan_intv, scppc_env->scan_intv_wd.le_scan_intv); co_write16p(&req->scan_intv_wd.le_scan_window, scppc_env->scan_intv_wd.le_scan_window); ke_msg_send(req); } } return (KE_MSG_CONSUMED); }