/** **************************************************************************************** * @brief Enable the Proximity Monitor role, used after connection. * @param[in] msgid Id of the message received. * @param[in] param Pointer to the parameters of the message. * @param[in] dest_id ID of the receiving task instance * @param[in] src_id ID of the sending task instance. * @return If the message was consumed or not. **************************************************************************************** */ static int proxm_enable_req_handler(ke_msg_id_t const msgid, struct proxm_enable_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Status uint8_t status; // Device Information Service Client Role Task Environment struct proxm_env_tag *proxm_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, proxm); 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) { proxm_env = PRF_CLIENT_GET_ENV(dest_id, proxm); // Discovery connection if (param->con_type == PRF_CON_DISCOVERY) { // Start discovering LLS on peer prf_disc_svc_send(&proxm_env->con_info, ATT_SVC_LINK_LOSS); proxm_env->last_uuid_req = ATT_SVC_LINK_LOSS; proxm_env->last_svc_req = ATT_SVC_LINK_LOSS; // Set state to discovering ke_state_set(dest_id, PROXM_DISCOVERING); } else { //copy over data that has been stored proxm_env->ias = param->ias; proxm_env->lls = param->lls; proxm_env->txps = param->txps; //send confirmation of enable request to application proxm_enable_cfm_send(proxm_env, &con_info, PRF_ERR_OK); } } else { proxm_enable_cfm_send(NULL, &con_info, status); } // message is consumed 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; // Battery Service Client Role Task Environment struct tipc_env_tag *tipc_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, tipc); 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) { tipc_env = PRF_CLIENT_GET_ENV(dest_id, tipc); //config connection, start discovering if(param->con_type == PRF_CON_DISCOVERY) { //start discovering CTS on peer prf_disc_svc_send(&(tipc_env->con_info), ATT_SVC_CURRENT_TIME); tipc_env->last_uuid_req = ATT_SVC_CURRENT_TIME; tipc_env->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->cts = param->cts; tipc_env->ndcs = param->ndcs; tipc_env->rtus = param->rtus; //send APP confirmation that can start normal connection tipc_enable_cfm_send(tipc_env, &con_info, PRF_ERR_OK); } } else { // Send confirmation that can start normal connection tipc_enable_cfm_send(NULL, &con_info, status); } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref BASC_ENABLE_REQ message. * The handler enables the Battery Service 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 basc_enable_req_handler(ke_msg_id_t const msgid, struct basc_enable_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Status uint8_t status; // Battery Service Client Role Task Environment struct basc_env_tag *basc_env; // Connection Information struct prf_con_info con_info; // Fill the Connection Information structure con_info.conhdl = 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, basc); 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) { basc_env = PRF_CLIENT_GET_ENV(dest_id, basc); // Config connection, start discovering if(param->con_type == PRF_CON_DISCOVERY) { // Start discovering BAS on peer prf_disc_svc_send(&(basc_env->con_info), ATT_SVC_BATTERY_SERVICE); basc_env->last_uuid_req = ATT_SVC_BATTERY_SERVICE; // Go to DISCOVERING state ke_state_set(dest_id, BASC_DISCOVERING); } // Normal connection, get saved att details else { memcpy(&basc_env->bas[0], ¶m->bas[0], BASC_NB_BAS_INSTANCES_MAX*sizeof(struct bas_content)); basc_env->bas_nb = param->bas_nb; // Send APP confirmation that can start normal connection to TH basc_enable_cfm_send(basc_env, &con_info, PRF_ERR_OK); } } else { // An error has been raised during the process, env is NULL and won't be handled basc_enable_cfm_send(NULL, &con_info, status); } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref HTPC_ENABLE_REQ message. * The handler enables the Health Thermometer Profile Collector 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 htpc_enable_req_handler(ke_msg_id_t const msgid, struct htpc_enable_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Status uint8_t status; // Health Thermometer Profile Collector Role Task Environment struct htpc_env_tag *htpc_env; // Connection Information struct prf_con_info con_info; // Fill the Connection Information structure con_info.conhdl = 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, htpc); 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) { htpc_env = PRF_CLIENT_GET_ENV(dest_id, htpc); //Config connection, start discovering if(param->con_type == PRF_CON_DISCOVERY) { htpc_env->last_uuid_req = ATT_SVC_HEALTH_THERMOM; // Start discovering HTS on peer prf_disc_svc_send(&htpc_env->con_info, ATT_SVC_HEALTH_THERMOM); // Go to DISCOVERING state ke_state_set(dest_id, HTPC_DISCOVERING); } // Normal connection, get saved att details else { htpc_env->hts = param->hts; //send APP confirmation that can start normal connection to TH htpc_enable_cfm_send(htpc_env, &htpc_env->con_info, PRF_ERR_OK); } } else { // An error has been raised during the process, hts is NULL and won't be handled htpc_enable_cfm_send(NULL, &con_info, status); } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref HOGPBH_ENABLE_REQ message. * The handler enables the HID Over GATT Profile Boot Host 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 hogpbh_enable_req_handler(ke_msg_id_t const msgid, struct hogpbh_enable_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Status uint8_t status; // HID Over GATT Profile Client Role Task Environment struct hogpbh_env_tag *hogpbh_env; // Connection Information struct prf_con_info con_info; // Fill the Connection Information structure con_info.conhdl = 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, hogpbh); 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) { hogpbh_env = PRF_CLIENT_GET_ENV(dest_id, hogpbh); //config connection, start discovering if(param->con_type == PRF_CON_DISCOVERY) { //start discovering HIDS on peer prf_disc_svc_send(&(hogpbh_env->con_info), ATT_SVC_HID); hogpbh_env->last_uuid_req = ATT_SVC_HID; // Go to DISCOVERING state ke_state_set(dest_id, HOGPBH_DISCOVERING); } //normal connection, get saved att details else { memcpy(&hogpbh_env->hids[0], ¶m->hids[0], HOGPBH_NB_HIDS_INST_MAX*sizeof(struct hids_content)); hogpbh_env->hids_nb = param->hids_nb; //send APP confirmation that can start normal connection to TH hogpbh_enable_cfm_send(hogpbh_env, &con_info, PRF_ERR_OK); } } else { hogpbh_enable_cfm_send(NULL, &con_info, status); } 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 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 CSCPC_ENABLE_CMD message. * @param[in] msgid Id of the message received. * @param[in] param Pointer to the parameters of the message. * @param[in] dest_id ID of the receiving task instance. * @param[in] src_id ID of the sending task instance. * @return If the message was consumed or not. **************************************************************************************** */ static int cscpc_enable_cmd_handler(ke_msg_id_t const msgid, struct cscpc_enable_cmd *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Status uint8_t status = PRF_ERR_OK; // Message status uint8_t msg_status = KE_MSG_CONSUMED; // Cycling Speed and Cadence Profile Collector Role Task Environment struct cscpc_env_tag *cscpc_env; // Connection Information struct prf_con_info con_info; // Check if the provided conhdl is valid if (gap_get_rec_idx(param->conhdl) != GAP_INVALID_CONIDX) { // Fill the Connection Information structure con_info.conhdl = param->conhdl; con_info.prf_id = dest_id; con_info.appid = src_id; // Add an environment for the provided connection status = PRF_CLIENT_ENABLE(con_info, param, cscpc); } else { status = PRF_ERR_REQ_DISALLOWED; } if (status == PRF_ERR_OK) { // Get the newly created environment cscpc_env = PRF_CLIENT_GET_ENV(dest_id, cscpc); // Keep the connection info memcpy(&cscpc_env->con_info, &con_info, sizeof(struct prf_con_info)); // Start discovering if (param->con_type == PRF_CON_DISCOVERY) { // Configure the environment for a discovery procedure cscpc_env->last_req = ATT_SVC_CYCLING_SPEED_CADENCE; // Force the operation value param->operation = CSCPC_ENABLE_OP_CODE; prf_disc_svc_send(&(cscpc_env->con_info), ATT_SVC_CYCLING_SPEED_CADENCE); // Keep the operation cscpc_env->operation = (void *)param; // Do not free the message msg_status = KE_MSG_NO_FREE; // Go to BUSY state ke_state_set(dest_id, CSCPC_BUSY); } // Bond information are provided else { // Keep the provided database content memcpy(&cscpc_env->cscs, ¶m->cscs, sizeof(struct cscpc_cscs_content)); // Register in GATT for notifications/indications prf_register_atthdl2gatt(&cscpc_env->con_info, &cscpc_env->cscs.svc); // Send a complete event status to the application cscpc_send_cmp_evt(cscpc_env, CSCPC_ENABLE_OP_CODE, PRF_ERR_OK); } } else if (status == PRF_ERR_FEATURE_NOT_SUPPORTED) { // The message will be forwarded towards the good task instance msg_status = KE_MSG_NO_FREE; } else { // The request is disallowed (profile already enabled for this connection, or not enough memory, ...) cscpc_send_no_conn_cmp_evt(dest_id, src_id, param->conhdl, CSCPC_ENABLE_OP_CODE); } return (int)msg_status; }
/** **************************************************************************************** * @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 = 0; // Get the address of the environment struct proxm_env_tag *proxm_env = PRF_CLIENT_GET_ENV(dest_id, proxm); if(state == PROXM_DISCOVERING) { if ((param->status == ATT_ERR_ATTRIBUTE_NOT_FOUND)|| (param->status == ATT_ERR_NO_ERROR)) { //Currently discovering Link Loss Service if (proxm_env->last_svc_req == ATT_SVC_LINK_LOSS) { if (proxm_env->last_uuid_req == ATT_SVC_LINK_LOSS) { if (proxm_env->lls.svc.shdl == ATT_INVALID_HANDLE) { proxm_enable_cfm_send(proxm_env, &proxm_env->con_info, PRF_ERR_STOP_DISC_CHAR_MISSING); } // Too many services found only one such service should exist else if(proxm_env->nb_svc > 1) { // stop discovery procedure. proxm_enable_cfm_send(proxm_env, &proxm_env->con_info, PRF_ERR_MULTIPLE_SVC); } else { // Discover LLS characteristics prf_disc_char_all_send(&(proxm_env->con_info), &(proxm_env->lls.svc)); // Keep last UUID requested and for which service in env proxm_env->last_uuid_req = ATT_DECL_CHARACTERISTIC; } } else if (proxm_env->last_uuid_req == ATT_DECL_CHARACTERISTIC) { status = prf_check_svc_char_validity(1, &proxm_env->lls.charact, &proxm_lls_char); if (status == PRF_ERR_OK) { proxm_env->nb_svc = 0; // Start discovering TXPS on peer prf_disc_svc_send(&(proxm_env->con_info), ATT_SVC_TX_POWER); proxm_env->last_uuid_req = ATT_SVC_TX_POWER; proxm_env->last_svc_req = ATT_SVC_TX_POWER; } else { // Stop discovery procedure. proxm_enable_cfm_send(proxm_env, &proxm_env->con_info, status); } } } //Currently discovering TX Power Service else if (proxm_env->last_svc_req == ATT_SVC_TX_POWER) { if (proxm_env->last_uuid_req == ATT_SVC_TX_POWER) { // TXPS is optional if (proxm_env->txps.svc.shdl == ATT_INVALID_HANDLE) { proxm_env->nb_svc = 0; // Start discovering IAS on peer prf_disc_svc_send(&(proxm_env->con_info), ATT_SVC_IMMEDIATE_ALERT); proxm_env->last_uuid_req = ATT_SVC_IMMEDIATE_ALERT; proxm_env->last_svc_req = ATT_SVC_IMMEDIATE_ALERT; } else { // Discover TXPS characteristics prf_disc_char_all_send(&(proxm_env->con_info), &(proxm_env->txps.svc)); // Keep last UUID requested and for which service in env proxm_env->last_uuid_req = ATT_DECL_CHARACTERISTIC; } } else if (proxm_env->last_uuid_req == ATT_DECL_CHARACTERISTIC) { status = prf_check_svc_char_validity(1, &proxm_env->txps.charact, &proxm_txps_char); if (status == PRF_ERR_OK) { proxm_env->nb_svc = 0; // Start discovering IAS on peer prf_disc_svc_send(&(proxm_env->con_info), ATT_SVC_IMMEDIATE_ALERT); proxm_env->last_uuid_req = ATT_SVC_IMMEDIATE_ALERT; proxm_env->last_svc_req = ATT_SVC_IMMEDIATE_ALERT; } else { // Stop discovery procedure. proxm_enable_cfm_send(proxm_env, &proxm_env->con_info, status); } } } //Currently discovering Immediate Alert Service else if (proxm_env->last_svc_req == ATT_SVC_IMMEDIATE_ALERT) { if (proxm_env->last_uuid_req == ATT_SVC_IMMEDIATE_ALERT) { // IAS is optional if (proxm_env->ias.svc.shdl == ATT_INVALID_HANDLE) { proxm_enable_cfm_send(proxm_env, &proxm_env->con_info, PRF_ERR_OK); } else { // Discover IAS characteristics prf_disc_char_all_send(&(proxm_env->con_info), &(proxm_env->ias.svc)); // Keep last UUID requested and for which service in env proxm_env->last_uuid_req = ATT_DECL_CHARACTERISTIC; } } else if (proxm_env->last_uuid_req == ATT_DECL_CHARACTERISTIC) { status = prf_check_svc_char_validity(1, &proxm_env->txps.charact, &proxm_txps_char); proxm_enable_cfm_send(proxm_env, &proxm_env->con_info, status); } } } } else if (state == PROXM_CONNECTED) { switch(param->req_type) { case GATTC_WRITE: case GATTC_WRITE_NO_RESPONSE: { proxm_write_char_rsp_send(proxm_env, param->status); } break; case GATTC_READ: { if(param->status != GATT_ERR_NO_ERROR) { // an error occurs while reading peer device attribute prf_client_att_info_rsp((prf_env_struct*) proxm_env, PROXM_RD_CHAR_RSP, param->status, NULL); } } break; default: break; } } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref ANPC_ENABLE_CMD message. * @param[in] msgid Id of the message received. * @param[in] param Pointer to the parameters of the message. * @param[in] dest_id ID of the receiving task instance. * @param[in] src_id ID of the sending task instance. * @return If the message was consumed or not. **************************************************************************************** */ static int anpc_enable_cmd_handler(ke_msg_id_t const msgid, struct anpc_enable_cmd *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Status uint8_t status = PRF_ERR_OK; // Message status uint8_t msg_status = KE_MSG_CONSUMED; // Alert Notification Profile Client Role Task Environment struct anpc_env_tag *anpc_env; // Connection Information struct prf_con_info con_info; // Check if the provided connection handle is valid if (gapc_get_conidx(param->conhdl) != GAP_INVALID_CONIDX) { // 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 connection status = PRF_CLIENT_ENABLE(con_info, param, anpc); } else { status = PRF_ERR_REQ_DISALLOWED; } if (status == PRF_ERR_OK) { // Get the newly created environment anpc_env = PRF_CLIENT_GET_ENV(dest_id, anpc); // Keep the connection info memcpy(&anpc_env->con_info, &con_info, sizeof(struct prf_con_info)); // Start discovering if (param->con_type == PRF_CON_DISCOVERY) { // Configure the environment for a discovery procedure anpc_env->last_req = ATT_SVC_ALERT_NTF; // Force the operation value param->operation = ANPC_ENABLE_OP_CODE; prf_disc_svc_send(&(anpc_env->con_info), ATT_SVC_ALERT_NTF); } // Bond information are provided else { // Keep the provided database content memcpy(&anpc_env->ans, ¶m->ans, sizeof(struct anpc_ans_content)); // Register in GATT for notifications/indications prf_register_atthdl2gatt(&anpc_env->con_info, &anpc_env->ans.svc); // Force the operation value param->operation = ANPC_ENABLE_RD_NEW_ALERT_OP_CODE; // Check Supported New Alert Category prf_read_char_send(&(anpc_env->con_info), anpc_env->ans.svc.shdl, anpc_env->ans.svc.ehdl, anpc_env->ans.chars[ANPC_CHAR_SUP_NEW_ALERT_CAT].val_hdl); } // Keep the operation anpc_env->operation = (void *)param; // Do not free the message msg_status = KE_MSG_NO_FREE; // Go to BUSY state ke_state_set(dest_id, ANPC_BUSY); } else if (status == PRF_ERR_FEATURE_NOT_SUPPORTED) { // The message will be forwarded towards the good task instance msg_status = KE_MSG_NO_FREE; } else { // The request is disallowed (profile already enabled for this connection, or not enough memory, ...) anpc_send_no_conn_cmp_evt(dest_id, src_id, param->conhdl, ANPC_ENABLE_OP_CODE); } return (int)msg_status; }
/** **************************************************************************************** * @brief Enable the StreamData Host role, used after connection. * @param[in] msgid Id of the message received. * @param[in] param Pointer to the parameters of the message. * @param[in] dest_id ID of the receiving task instance * @param[in] src_id ID of the sending task instance. * @return If the message was consumed or not. **************************************************************************************** */ static int streamdatah_enable_req_handler(ke_msg_id_t const msgid, struct streamdatah_enable_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Status uint8_t status; // Device Information Service Client Role Task Environment struct streamdatah_env_tag *streamdatah_env; // Connection Information struct prf_con_info con_info; // Fill the Connection Information structure con_info.conhdl = 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, streamdatah); 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) { streamdatah_env = PRF_CLIENT_GET_ENV(dest_id, streamdatah); streamdatah_env->streamon = 0; streamdatah_env->next_attribute_idx = 0; streamdatah_env->receive_sequence_number = 0; // Discovery connection if (param->con_type == PRF_CON_DISCOVERY) { // Start discovering LLS on peer streamdatah_env->last_uuid_req = STREAMDATAD_SERVICE_UUID; streamdatah_env->last_svc_req = STREAMDATAD_SERVICE_UUID; prf_disc_svc_send(&streamdatah_env->con_info, streamdatah_env->last_svc_req); // Set state to discovering ke_state_set(dest_id, STREAMDATAH_DISCOVERING); } else { //copy over data that has been stored streamdatah_env->streamdatad = param->streamdatad; //send confirmation of enable request to application streamdatah_enable_cfm_send(streamdatah_env, &con_info, PRF_ERR_OK); } } else { streamdatah_enable_cfm_send(NULL, &con_info, status); } // message is consumed 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) { uint8_t status; // Get the address of the environment struct tipc_env_tag *tipc_env = PRF_CLIENT_GET_ENV(dest_id, tipc); 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); } } } } return (KE_MSG_CONSUMED); }