/** **************************************************************************************** * @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 Enable the StreamData client 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 sps_client_enable_req_handler(ke_msg_id_t const msgid, struct sps_client_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 sps_client_env_tag *sps_client_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, sps_client); 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) { sps_client_env = PRF_CLIENT_GET_ENV(dest_id, sps_client); // Discovery connection if (param->con_type == PRF_CON_DISCOVERY) { // Start discovering LLS on peer uint8_t sps_data_service_uuid[]=SPS_SERVICE_UUID; sps_client_env->last_uuid_req = ATT_DECL_PRIMARY_SERVICE; memcpy(sps_client_env->last_svc_req, sps_data_service_uuid, ATT_UUID_128_LEN); prf_disc_svc_send_128(&sps_client_env->con_info, sps_client_env->last_svc_req); // Set state to discovering ke_state_set(dest_id, SPS_CLIENT_DISCOVERING); } else { //copy over data that has been stored sps_client_env->sps_server = param->sps_server; //send confirmation of enable request to application sps_client_enable_cfm_send(sps_client_env, &con_info, PRF_ERR_OK); } } else { sps_client_enable_cfm_send(NULL, &con_info, status); } // message is consumed return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref FINDT_ENABLE_REQ message. * The handler enables the Find Me profile - target 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 findt_enable_req_handler(ke_msg_id_t const msgid, struct findt_enable_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Save the application task id findt_env.con_info.appid = src_id; // Save the connection index associated to the profile findt_env.con_info.conidx = gapc_get_conidx(param->conhdl); // Check if the provided connection exist if (findt_env.con_info.conidx == GAP_INVALID_CONIDX) { // The connection doesn't exist, request disallowed prf_server_error_ind_send((prf_env_struct *)&findt_env, PRF_ERR_REQ_DISALLOWED, FINDT_ERROR_IND, FINDT_ENABLE_REQ); } else { // Enable Service + Set Security Level attmdb_svc_set_permission(findt_env.shdl, param->sec_lvl); // Go to connected state ke_state_set(TASK_FINDT, FINDT_CONNECTED); } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Enable the Sample128 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 sample128_enable_req_handler(ke_msg_id_t const msgid, struct sample128_enable_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Keep source of message, to respond to it further on sample128_env.con_info.appid = src_id; // Store the connection handle for which this profile is enabled sample128_env.con_info.conidx = gapc_get_conidx(param->conhdl); // Check if the provided connection exist if (sample128_env.con_info.conidx == GAP_INVALID_CONIDX) { // The connection doesn't exist, request disallowed prf_server_error_ind_send((prf_env_struct *)&sample128_env, PRF_ERR_REQ_DISALLOWED, SAMPLE128_ERROR_IND, SAMPLE128_ENABLE_REQ); } else { // Sample128 1 attmdb_svc_set_permission(sample128_env.sample128_1_shdl, param->sec_lvl); //Set LLS Alert Level to specified value attmdb_att_set_value(sample128_env.sample128_1_shdl + SAMPLE128_1_IDX_VAL, sizeof(uint8_t), (uint8_t *)¶m->sample128_1_val); // Go to Connected state ke_state_set(TASK_SAMPLE128, SAMPLE128_CONNECTED); } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @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 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.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, 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 HRPS_ENABLE_REQ message. * The handler enables the Heart Rate Sensor Profile. * @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 hrps_enable_req_handler(ke_msg_id_t const msgid, struct hrps_enable_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { uint16_t value = 0; // Save the application task id hrps_env.con_info.appid = src_id; // Save the connection handle associated to the profile hrps_env.con_info.conidx = gapc_get_conidx(param->conhdl); // Check if the provided connection exist if (hrps_env.con_info.conidx == GAP_INVALID_CONIDX) { // The connection doesn't exist, request disallowed prf_server_error_ind_send((prf_env_struct *)&hrps_env, PRF_ERR_REQ_DISALLOWED, HRPS_ERROR_IND, HRPS_ENABLE_REQ); } else { // If this connection is a not configuration one, apply config saved by app if(param->con_type == PRF_CON_NORMAL) { value = param->hr_meas_ntf_en; if (param->hr_meas_ntf_en == PRF_CLI_START_NTF) { hrps_env.features |= HRPS_HR_MEAS_NTF_CFG; } } //Set HR Meas. Char. NTF Configuration in DB attmdb_att_set_value(hrps_env.shdl + HRS_IDX_HR_MEAS_NTF_CFG, sizeof(uint16_t), (uint8_t *)&value); if (HRPS_IS_SUPPORTED(HRPS_BODY_SENSOR_LOC_CHAR_SUP)) { //Set Body Sensor Location Char Value in DB - Not supposed to change during connection attmdb_att_set_value(hrps_env.shdl + HRS_IDX_BOBY_SENSOR_LOC_VAL, sizeof(uint8_t), (uint8_t *)¶m->body_sensor_loc); } // Enable Service + Set Security Level attmdb_svc_set_permission(hrps_env.shdl, param->sec_lvl); // Go to connected state ke_state_set(TASK_HRPS, HRPS_CONNECTED); } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref STREAMDATAD_ENABLE_REQ message. * The handler enables the StreamData Device profile. * @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 streamdatad_enable_req_handler(ke_msg_id_t const msgid, struct streamdatad_enable_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { uint16_t disable_val = 0x00; //Save Application ID //streamdatad_env.con_info.appid = src_id; streamdatad_env.con_info.prf_id = dest_id; streamdatad_env.con_info.appid = src_id; streamdatad_env.appid = src_id; //streamdatad_env.con_info.prf_id = dest_id; // Save the connection handle associated to the profile streamdatad_env.con_info.conidx = gapc_get_conidx(param->conhdl); // Save the connection handle associated to the profile streamdatad_env.conhdl = param->conhdl; streamdatad_env.next_attribute_idx = 0; streamdatad_env.nr_enabled_attributes = 0; streamdatad_env.stream_enabled = 0; // get tx buffers available nb_buf_av = l2cm_get_nb_buffer_available() - 6; attmdb_att_set_value(STREAMDATAD_HANDLE(STREAMDATAD_IDX_ENABLE_VAL), sizeof(uint16_t), (uint8_t*) &(disable_val)); attmdb_att_set_value(STREAMDATAD_HANDLE(STREAMDATAD_IDX_STREAMDATAD_D0_EN), sizeof(uint16_t),(uint8_t*) &(disable_val)); attmdb_att_set_value(STREAMDATAD_HANDLE(STREAMDATAD_IDX_STREAMDATAD_D1_EN), sizeof(uint16_t),(uint8_t*) &(disable_val)); attmdb_att_set_value(STREAMDATAD_HANDLE(STREAMDATAD_IDX_STREAMDATAD_D2_EN), sizeof(uint16_t),(uint8_t*) &(disable_val)); attmdb_att_set_value(STREAMDATAD_HANDLE(STREAMDATAD_IDX_STREAMDATAD_D3_EN), sizeof(uint16_t),(uint8_t*) &(disable_val)); attmdb_att_set_value(STREAMDATAD_HANDLE(STREAMDATAD_IDX_STREAMDATAD_D4_EN), sizeof(uint16_t),(uint8_t*) &(disable_val)); attmdb_att_set_value(STREAMDATAD_HANDLE(STREAMDATAD_IDX_STREAMDATAD_D5_EN), sizeof(uint16_t),(uint8_t*) &(disable_val)); attmdb_att_set_value(STREAMDATAD_HANDLE(STREAMDATAD_IDX_STREAMDATAD_D6_EN), sizeof(uint16_t),(uint8_t*) &(disable_val)); attmdb_att_set_value(STREAMDATAD_HANDLE(STREAMDATAD_IDX_STREAMDATAD_D7_EN), sizeof(uint16_t),(uint8_t*) &(disable_val)); attmdb_att_set_value(STREAMDATAD_HANDLE(STREAMDATAD_IDX_STREAMDATAD_D8_EN), sizeof(uint16_t),(uint8_t*) &(disable_val)); attmdb_att_set_value(STREAMDATAD_HANDLE(STREAMDATAD_IDX_STREAMDATAD_D9_EN), sizeof(uint16_t),(uint8_t*) &(disable_val)); //Enable Service attmdb_svc_set_permission(streamdatad_env.shdl, PERM(SVC, ENABLE)); // Go to active state ke_state_set(TASK_STREAMDATAD, STREAMDATAD_ACTIVE); return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Enable the ADC Notify 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 adc_notify_enable_req_handler(ke_msg_id_t const msgid, struct adc_notify_enable_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { uint16_t temp = 1; // Keep source of message, to respond to it further on adc_notify_env.con_info.appid = src_id; // Store the connection handle for which this profile is enabled adc_notify_env.con_info.conidx = gapc_get_conidx(param->conhdl); // Check if the provided connection exist if (adc_notify_env.con_info.conidx == GAP_INVALID_CONIDX) { // The connection doesn't exist, request disallowed prf_server_error_ind_send((prf_env_struct *)&adc_notify_env, PRF_ERR_REQ_DISALLOWED, ADC_NOTIFY_ERROR_IND, ADC_NOTIFY_ENABLE_REQ); } else { attmdb_svc_set_permission(adc_notify_env.adc_notify_shdl, param->sec_lvl); attmdb_att_set_value(adc_notify_env.adc_notify_shdl + ADC_NOTIFY_IDX_VAL, sizeof(uint16_t), (uint8_t *)¶m->adc_notify_val); adc_notify_env.feature = param->feature; if (!adc_notify_env.feature) { temp = 0; } attmdb_att_set_value(adc_notify_env.adc_notify_shdl + ADC_NOTIFY_IDX_CFG, sizeof(uint16_t), (uint8_t *)&temp); // Go to Connected state ke_state_set(TASK_ADC_NOTIFY, ADC_NOTIFY_CONNECTED); } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref UDSS_ENABLE_REQ 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 udss_enable_req_handler(ke_msg_id_t const msgid, struct udss_enable_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { //Save the connection handle associated to the profile udss_env.con_info.conidx = gapc_get_conidx(param->conhdl); //Save the application id udss_env.con_info.appid = src_id; // Check if the provided connection exist if (udss_env.con_info.conidx == GAP_INVALID_CONIDX) { // The connection doesn't exist, request disallowed prf_server_error_ind_send((prf_env_struct *)&udss_env, PRF_ERR_REQ_DISALLOWED, UDSS_ERROR_IND, UDSS_ENABLE_REQ); } else { //Enable Attributes + Set Security Level attmdb_svc_set_permission(udss_env.shdl, param->sec_lvl); //Set User Height to specified value attmdb_att_set_value(udss_env.shdl + UDS_IDX_USER_HEIGHT_VAL, sizeof(uint8_t), (uint8_t *)¶m->user_height); //Set User Age to specified value attmdb_att_set_value(udss_env.shdl + UDS_IDX_USER_AGE_VAL, sizeof(uint8_t), (uint8_t *)¶m->user_age); //Set User Date of Birth to specified value attmdb_att_set_value(udss_env.shdl + UDS_IDX_USER_DATE_OF_BIRTH_VAL, sizeof(struct date), (uint8_t *)¶m->user_date_of_birth); //Set User DB Change Increment to specified value attmdb_att_set_value(udss_env.shdl + UDS_IDX_USER_DB_CHANGE_INCR_VAL, sizeof(uint8_t), (uint8_t *)¶m->user_db_change_incr); // Go to connected state ke_state_set(TASK_UDSS, UDSS_CONNECTED); } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref ACCEL_ENABLE_REQ message. * The handler enables the accelerometer profile. * @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 accel_enable_req_handler(ke_msg_id_t const msgid, struct accel_enable_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { uint16_t disable_val = 0x00; //Save Application ID accel_env.con_info.appid = src_id; accel_env.con_info.prf_id = dest_id; // Save the connection index associated to the profile accel_env.con_info.conidx = gapc_get_conidx(param->conhdl); attmdb_att_set_value(ACCEL_HANDLE(ACCEL_IDX_ENABLE_VAL), sizeof(uint8_t), (uint8_t*) &(disable_val)); attmdb_att_set_value(ACCEL_HANDLE(ACCEL_IDX_RANGE_VAL), sizeof(uint8_t), (uint8_t*) &(disable_val)); attmdb_att_set_value(ACCEL_HANDLE(ACCEL_IDX_ACCEL_X_EN), sizeof(uint16_t),(uint8_t*) &(disable_val)); attmdb_att_set_value(ACCEL_HANDLE(ACCEL_IDX_ACCEL_Y_EN), sizeof(uint16_t),(uint8_t*) &(disable_val)); attmdb_att_set_value(ACCEL_HANDLE(ACCEL_IDX_ACCEL_Z_EN), sizeof(uint16_t),(uint8_t*) &(disable_val)); { uint8_t tb; // tb = battery_get_lvl(BATT_CR2032); tb = battery_get_lvl(BATT_JPLUS);//gsx,jplus battery type. // Update the value in the attribute database attmdb_att_set_value(ACCEL_HANDLE(ACCEL_IDX_ENABLE_VAL), sizeof(uint8_t), (uint8_t*) &(tb)); } //Enable Service attmdb_svc_set_permission(accel_env.shdl, PERM(SVC, ENABLE)); // Go to active state ke_state_set(TASK_ACCEL, ACCEL_ACTIVE); return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Enable the HPS Server 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 hpss_enable_req_handler(ke_msg_id_t const msgid, struct hpss_enable_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { uint16_t value = 0; // Keep source of message, to respond to it further on hpss_env.con_info.appid = src_id; // Store the connection handle for which this profile is enabled hpss_env.con_info.conidx = gapc_get_conidx(param->conhdl); // Check if the provided connection exist if (hpss_env.con_info.conidx == GAP_INVALID_CONIDX) { // The connection doesn't exist, request disallowed prf_server_error_ind_send((prf_env_struct *)&hpss_env, PRF_ERR_REQ_DISALLOWED, HPSS_ERROR_IND, HPSS_ENABLE_REQ); } else { // Enable HPS + Set Security Level attmdb_svc_set_permission(hpss_env.hps_shdl, param->sec_lvl); //Set HR Meas. Char. NTF Configuration in DB attmdb_att_set_value(hpss_env.hps_shdl + HPS_IDX_STATUS_CODE_CFG, sizeof(uint16_t), (uint8_t *)&value); //fix me? //Set LLS Alert Level to specified value // attmdb_att_set_value(hpss_env.hps_shdl + LLS_IDX_ALERT_LVL_VAL, // sizeof(uint8_t), (uint8_t *)¶m->lls_alert_lvl); // Go to Connected state ke_state_set(TASK_HPSS, HPSS_CONNECTED); } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref TIPS_ENABLE_REQ message. * The handler enables the Time Server Profile. * @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 tips_enable_req_handler(ke_msg_id_t const msgid, struct tips_enable_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Status uint8_t status; // Time Profile Server Role Task Index Environment struct tips_idx_env_tag *tips_idx_env; // Connection Information struct prf_con_info con_info; // Value used to initialize readable value in DB uint16_t value = 0; // Value used to initialize readable value whose size is upper than 2 bytes struct attm_elmt *att = NULL; // 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, tips_idx); 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) { //If this connection is a not configuration one, apply configuration saved by APP if(param->con_type == PRF_CON_NORMAL) { memcpy(&value, ¶m->current_time_ntf_en, sizeof(uint16_t)); if (param->current_time_ntf_en == PRF_CLI_START_NTF) { // Get the environment for the device tips_idx_env = PRF_CLIENT_GET_ENV(dest_id, tips_idx); tips_idx_env->ntf_state |= TIPS_CTS_CURRENT_TIME_CFG; } } //Set Current Time Char. NTF Configuration in database attmdb_att_set_value(tips_env.cts_shdl + CTS_IDX_CURRENT_TIME_CFG, sizeof(uint16_t), (uint8_t *)&value); //Reset value value = 0; // Initialize Local Time Info Char. Value - (UTC+0.00 / Standard Time) if (TIPS_IS_SUPPORTED(TIPS_CTS_LOC_TIME_INFO_SUP)) { //sizeof(struct tip_ref_time_info) = sizeof(uint16_t) attmdb_att_set_value(tips_env.cts_shdl + CTS_IDX_LOCAL_TIME_INFO_VAL, sizeof(struct tip_loc_time_info), (uint8_t *)&value); } // Initialize Reference Time Info Char. Value if (TIPS_IS_SUPPORTED(TIPS_CTS_REF_TIME_INFO_SUP)) { att = attmdb_get_attribute(tips_env.cts_shdl + tips_env.cts_att_tbl[CTS_REF_TIME_INFO_CHAR] + 1); att->length = sizeof(struct tip_ref_time_info); memset(att->value, 0, sizeof(struct tip_ref_time_info)); } //Enable CTS + Set Security Level attmdb_svc_set_permission(tips_env.cts_shdl, param->sec_lvl); if (TIPS_IS_SUPPORTED(TIPS_NDCS_SUP)) { att = attmdb_get_attribute(tips_env.ndcs_shdl + NDCS_IDX_TIME_DST_VAL); // Initialize Time With DST Char. Value - (Idle / Successful) att->length = NDCS_TIME_DST_VAL_LEN; memset(att->value, 0, NDCS_TIME_DST_VAL_LEN); attmdb_svc_set_permission(tips_env.ndcs_shdl, param->sec_lvl); } if (TIPS_IS_SUPPORTED(TIPS_RTUS_SUP)) { // Initialize Time Update State Char. Value - (Idle / Successful) attmdb_att_set_value(tips_env.rtus_shdl + RTUS_IDX_TIME_UPD_STATE_VAL, sizeof(struct tip_time_upd_state), (uint8_t *)&value); attmdb_svc_set_permission(tips_env.rtus_shdl, param->sec_lvl); } // Go to Connected State ke_state_set(dest_id, TIPS_CONNECTED); //send APP confirmation that can start normal connection tips_enable_cfm_send(&con_info, PRF_ERR_OK); } else { // Send confirmation that can start normal connection tips_enable_cfm_send(&con_info, status); } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref ANPS_NTF_ALERT_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 anps_ntf_alert_cmd_handler(ke_msg_id_t const msgid, struct anps_ntf_alert_cmd const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Message Status uint8_t msg_status = KE_MSG_CONSUMED; // Task environment struct anps_idx_env_tag *anps_idx_env = PRF_CLIENT_GET_ENV(dest_id, anps_idx); if (anps_idx_env != NULL) { // Status uint8_t status = PRF_ERR_OK; // Category ID uint8_t cat_id; // Is the category supported ? bool cat_supported; // Handle uint16_t handle; do { // Check the provided connection handle value if (anps_idx_env->con_info.conidx != gapc_get_conidx(param->conhdl)) { status = PRF_ERR_INVALID_PARAM; break; } if (ke_state_get(dest_id) == ANPS_BUSY) { // The message will be handled once the current operation is over msg_status = KE_MSG_NO_FREE; break; } ASSERT_ERR(ke_state_get(dest_id) == ANPS_CONNECTED); // Check the operation code, get the category ID. if (param->operation == ANPS_UPD_NEW_ALERT_OP_CODE) { // Check the length of the string info value if (param->value.new_alert.info_str_len > ANS_NEW_ALERT_STRING_INFO_MAX_LEN) { status = PRF_ERR_INVALID_PARAM; break; } // Get the category ID cat_id = param->value.new_alert.cat_id; // Check if the category is supported cat_supported = ANPS_IS_NEW_ALERT_CATEGORY_SUPPORTED(cat_id); } else if (param->operation == ANPS_UPD_UNREAD_ALERT_STATUS_OP_CODE) { // Get the category ID cat_id = param->value.unread_alert_status.cat_id; // Check if the category is supported cat_supported = ANPS_IS_UNREAD_ALERT_CATEGORY_SUPPORTED(cat_id); } else { status = PRF_ERR_INVALID_PARAM; break; } // Check the category ID if ((cat_id >= CAT_ID_NB) || (!cat_supported)) { status = PRF_ERR_INVALID_PARAM; break; } if (param->operation == ANPS_UPD_NEW_ALERT_OP_CODE) { // Check if sending of notification is enabled for the provided category if (ANPS_IS_NEW_ALERT_CATEGORY_ENABLED(cat_id, anps_idx_env) && ANPS_IS_ALERT_ENABLED(anps_idx_env, ANP_NEW_ALERT)) { handle = anps_env.ans_shdl + ANS_IDX_NEW_ALERT_VAL; // Notification can be sent, set the value in the database attmdb_att_set_value(handle, 2 + param->value.new_alert.info_str_len, (uint8_t *)¶m->value.new_alert.cat_id); } else { status = PRF_ERR_NTF_DISABLED; break; } } else { if (ANPS_IS_UNREAD_ALERT_CATEGORY_ENABLED(cat_id, anps_idx_env) && ANPS_IS_ALERT_ENABLED(anps_idx_env, ANP_UNREAD_ALERT)) { handle = anps_env.ans_shdl + ANS_IDX_UNREAD_ALERT_STATUS_VAL; attmdb_att_set_value(handle, sizeof(struct anp_unread_alert), (uint8_t *)¶m->value.unread_alert_status); } else { status = PRF_ERR_NTF_DISABLED; break; } } // Configure the environment anps_idx_env->operation = param->operation; // The notification can be sent, send the notification prf_server_send_event((prf_env_struct *)anps_idx_env, false, handle); // Go to Busy state ke_state_set(dest_id, ANPS_BUSY); } while (0); if (status != PRF_ERR_OK) { // Send response to application anps_send_cmp_evt(anps_idx_env->con_info.prf_id, anps_idx_env->con_info.appid, gapc_get_conhdl(anps_idx_env->con_info.conidx), param->operation, status); } } else { // Send response to application anps_send_cmp_evt(dest_id, src_id, param->conhdl, param->operation, PRF_ERR_REQ_DISALLOWED); } return (int)msg_status; }
/** **************************************************************************************** * @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 PASPS_UPDATE_CHAR_VAL_REQ 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 pasps_update_char_val_cmd_handler(ke_msg_id_t const msgid, struct pasps_update_char_val_cmd *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Status uint8_t status = PRF_ERR_INVALID_PARAM; // Message status uint8_t msg_status = KE_MSG_CONSUMED; // Get the address of the environment struct pasps_idx_env_tag *pasps_idx_env = PRF_CLIENT_GET_ENV(dest_id, pasps_idx); if (pasps_idx_env != NULL) { // Check the provided connection handle value if (pasps_idx_env->con_info.conidx != gapc_get_conidx(param->conhdl)) { status = PRF_ERR_INVALID_PARAM; } else if (ke_state_get(dest_id) == PASPS_BUSY) { // Keep the message for later msg_status = KE_MSG_NO_FREE; } else { // Handle uint16_t handle; // Notification status flag uint8_t flag; ASSERT_ERR(ke_state_get(dest_id) == PASPS_CONNECTED); switch (param->operation) { // Alert Status Characteristic case (PASPS_UPD_ALERT_STATUS_OP_CODE): { // Check the provided value if (param->value <= PASP_ALERT_STATUS_VAL_MAX) { // Set the handle value handle = pasps_env.pass_shdl + PASS_IDX_ALERT_STATUS_VAL; // Set the flag flag = PASPS_FLAG_ALERT_STATUS_CFG; status = PRF_ERR_OK; } // else status is PRF_ERR_INVALID_PARAM } break; // Ringer Setting Characteristic case (PASPS_UPD_RINGER_SETTING_OP_CODE): { // Check the provided value if (param->value <= PASP_RINGER_NORMAL) { // Set the handle value handle = pasps_env.pass_shdl + PASS_IDX_RINGER_SETTING_VAL; // Set the flag flag = PASPS_FLAG_RINGER_SETTING_CFG; status = PRF_ERR_OK; // Update the ringer state value pasps_env.ringer_state = param->value; } // else status is PRF_ERR_INVALID_PARAM } break; default: { // Nothing more to do, status is PRF_ERR_INVALID_PARAM } break; } if (status == PRF_ERR_OK) { // Set the value of the characteristic attmdb_att_set_value(handle, sizeof(uint8_t), (uint8_t *)¶m->value); // Check if sending of notifications is enabled for this connection if (PASPS_IS_NTF_ENABLED(pasps_idx_env, flag)) { // Configure the environment for the operation pasps_idx_env->operation = param->operation; // Go to the Busy state ke_state_set(dest_id, PASPS_BUSY); // The notification can be sent, send the notification prf_server_send_event((prf_env_struct *)pasps_idx_env, false, handle); } else { status = PRF_ERR_NTF_DISABLED; } } } // If the status is not OK, no notification has been sent if (status != PRF_ERR_OK) { // Send response to application pasps_send_cmp_evt(pasps_idx_env->con_info.prf_id, pasps_idx_env->con_info.appid, param->conhdl, param->operation, status); } } else { // Send response to application pasps_send_cmp_evt(dest_id, src_id, param->conhdl, param->operation, PRF_ERR_REQ_DISALLOWED); } return (int)msg_status; }
/** **************************************************************************************** * @brief Handles reception of the @ref BAPS_ENABLE_REQ message. * The handler enables the Battery 'Profile' Server 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 bass_enable_req_handler(ke_msg_id_t const msgid, struct bass_enable_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Attribute offset - Used to retrieve Char. Pres. Format Descriptor handle uint8_t offset; // Packed Char. Presentation Format value uint8_t packed_char_pres[PRF_CHAR_PRES_FMT_SIZE]; // Counter uint8_t i; // Notification Configuration uint16_t ntf_cfg = 0; // Save the application task id bass_env.con_info.appid = src_id; // Save the connection handle associated to the profile bass_env.con_info.conidx = gapc_get_conidx(param->conhdl); // Check if the provided connection exist if (bass_env.con_info.conidx == GAP_INVALID_CONIDX) { // The connection doesn't exist, request disallowed prf_server_error_ind_send((prf_env_struct *)&bass_env, PRF_ERR_REQ_DISALLOWED, BASS_ERROR_IND, BASS_ENABLE_REQ); } else { // For each BAS instance for (i = 0; i < bass_env.bas_nb; i++) { // Reset Offset value offset = BAS_IDX_BATT_LVL_NTF_CFG; // Update Battery Level value in DB attmdb_att_set_value(bass_env.shdl[i] + BAS_IDX_BATT_LVL_VAL, sizeof(uint8_t), (uint8_t *)¶m->current_batt_lvl[i]); // Check if BAS supports notifications if (bass_env.features[i] == BAS_BATT_LVL_NTF_SUP) { // Increment offset (Client Char. Cfg is placed before Char. Pres Fmt. in DB) offset++; // If client is a bonded client if (param->con_type == PRF_CON_NORMAL) { ntf_cfg = param->batt_level_ntf_cfg[i]; /* * The server shall send a notification if value of the Battery Level characteristic * has changed while the service has been disconnected from a bonded client. */ if (param->batt_level_ntf_cfg[i] == PRF_CLI_START_NTF) { // Conserve information in environment bass_env.features[i] |= BASS_FLAG_NTF_CFG_BIT; // Check if old and previous battery level values are different if (param->old_batt_lvl[i] != param->current_batt_lvl[i]) { //Notify current battery level value prf_server_send_event((prf_env_struct *)&bass_env, false, bass_env.shdl[i] + BAS_IDX_BATT_LVL_VAL); } } } // Set NTF Cfg value in the DB attmdb_att_set_value(bass_env.shdl[i] + BAS_IDX_BATT_LVL_NTF_CFG, sizeof(uint16_t), (uint8_t *)&ntf_cfg); } // Check if Characteristic Presentation Format descriptor has been added if (bass_env.bas_nb > 1) { prf_pack_char_pres_fmt(&packed_char_pres[0], ¶m->batt_level_pres_format[i]); /* * Set Characteristic Presentation Format descriptor value * Not supposed to change during connection */ attmdb_att_set_value(bass_env.shdl[i] + offset, PRF_CHAR_PRES_FMT_SIZE, &packed_char_pres[0]); } // Enable Service + Set Security Level attmdb_svc_set_permission(bass_env.shdl[i], param->sec_lvl); } // Go to connected state ke_state_set(TASK_BASS, BASS_CONNECTED); } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref ANPC_READ_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_read_cmd_handler(ke_msg_id_t const msgid, struct anpc_read_cmd *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Message status uint8_t msg_status = KE_MSG_CONSUMED; // Get the address of the environment struct anpc_env_tag *anpc_env = PRF_CLIENT_GET_ENV(dest_id, anpc); if (anpc_env != NULL) { // Attribute Handle uint16_t handle = ATT_INVALID_SEARCH_HANDLE; // Status uint8_t status = PRF_ERR_OK; // State is Connected or Busy ASSERT_ERR(ke_state_get(dest_id) != ANPC_IDLE); // Check the provided connection handle if (gapc_get_conidx(param->conhdl) == anpc_env->con_info.conidx) { // Check the current state if (ke_state_get(dest_id) == ANPC_BUSY) { // Keep the request for later, status is PRF_ERR_OK msg_status = KE_MSG_SAVED; } else // State is ANPC_CONNECTED { ASSERT_ERR(anpc_env->operation == NULL); switch (param->read_code) { // Read New Alert Characteristic Client Char. Cfg. Descriptor Value case (ANPC_RD_WR_NEW_ALERT_CFG): { handle = anpc_env->ans.descs[ANPC_DESC_NEW_ALERT_CL_CFG].desc_hdl; } break; // Read Unread Alert Characteristic Client Char. Cfg. Descriptor Value case (ANPC_RD_WR_UNREAD_ALERT_STATUS_CFG): { handle = anpc_env->ans.descs[ANPC_DESC_UNREAD_ALERT_STATUS_CL_CFG].desc_hdl; } break; default: { status = PRF_ERR_INVALID_PARAM; } break; } // Check if handle is viable if ((handle != ATT_INVALID_SEARCH_HANDLE) && (status == PRF_ERR_OK)) { // Force the operation value param->operation = ANPC_READ_OP_CODE; // Store the command structure anpc_env->operation = param; msg_status = KE_MSG_NO_FREE; // Send the read request prf_read_char_send(&(anpc_env->con_info), anpc_env->ans.svc.shdl, anpc_env->ans.svc.ehdl, handle); // Go to the Busy state ke_state_set(dest_id, ANPC_BUSY); } else { status = PRF_ERR_INEXISTENT_HDL; } } } else { status = PRF_ERR_INVALID_PARAM; } if (status != PRF_ERR_OK) { anpc_send_cmp_evt(anpc_env, ANPC_READ_OP_CODE, status); } } else { // No connection exists anpc_send_no_conn_cmp_evt(dest_id, src_id, param->conhdl, ANPC_READ_OP_CODE); } return (int)msg_status; }
/** **************************************************************************************** * @brief Handles reception of the @ref PASPS_ENABLE_REQ 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 pasps_enable_req_handler(ke_msg_id_t const msgid, struct pasps_enable_req *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Phone Alert Status Profile Server Role Task Index Environment struct pasps_idx_env_tag *pasps_idx_env = NULL; // Connection Information structure struct prf_con_info con_info; // Status uint8_t status = PRF_ERR_OK; // Message status uint8_t msg_status = KE_MSG_CONSUMED; // 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 device status = PRF_CLIENT_ENABLE(con_info, param, pasps_idx); } else { status = PRF_ERR_REQ_DISALLOWED; } if (status == PRF_ERR_OK) { pasps_idx_env = PRF_CLIENT_GET_ENV(dest_id, pasps_idx); // Keep the Connection Information structure content memcpy(&pasps_idx_env->con_info, &con_info, sizeof(struct prf_con_info)); if (param->con_type == PRF_CON_DISCOVERY) { // Force the configuration to 0 param->alert_status_ntf_cfg = PRF_CLI_STOP_NTFIND; param->ringer_setting_ntf_cfg = PRF_CLI_STOP_NTFIND; } else { if (param->alert_status_ntf_cfg != PRF_CLI_STOP_NTFIND) { // Force to PRF_CLI_START_NTF param->alert_status_ntf_cfg = PRF_CLI_START_NTF; PASPS_ENABLE_NTF(pasps_idx_env, PASPS_FLAG_ALERT_STATUS_CFG); } if (param->ringer_setting_ntf_cfg != PRF_CLI_STOP_NTFIND) { // Force to PRF_CLI_START_NTF param->ringer_setting_ntf_cfg = PRF_CLI_START_NTF; PASPS_ENABLE_NTF(pasps_idx_env, PASPS_FLAG_RINGER_SETTING_CFG); } } // Set the value of the Alert Status Client Characteristic Configuration Descriptor attmdb_att_set_value(pasps_env.pass_shdl + PASS_IDX_ALERT_STATUS_CFG, sizeof(uint16_t), (uint8_t *)¶m->alert_status_ntf_cfg); // Set the value of the Ringer Setting Client Characteristic Configuration Descriptor attmdb_att_set_value(pasps_env.pass_shdl + PASS_IDX_RINGER_SETTING_CFG, sizeof(uint16_t), (uint8_t *)¶m->ringer_setting_ntf_cfg); // Enable PAS attmdb_svc_set_permission(pasps_env.pass_shdl, param->sec_lvl); // Go to Connected State ke_state_set(dest_id, PASPS_CONNECTED); // Send response to application pasps_send_cmp_evt(dest_id, src_id, param->conhdl, PASPS_ENABLE_OP_CODE, PRF_ERR_OK); } else if (status == PRF_ERR_FEATURE_NOT_SUPPORTED) { // The message has been forwarded to another task id. msg_status = KE_MSG_NO_FREE; } else { // Send response to application pasps_send_cmp_evt(dest_id, src_id, param->conhdl, PASPS_ENABLE_OP_CODE, PRF_ERR_REQ_DISALLOWED); } return (int)msg_status; }
/** **************************************************************************************** * @brief Handles reception of the @ref GLPS_ENABLE_REQ message. * The handler enables the Glucose Sensor Profile and initialize readable values. * @param[in] msgid Id of the message received (probably unused).off * @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 glps_enable_req_handler(ke_msg_id_t const msgid, struct glps_enable_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { uint8_t status = PRF_ERR_REQ_DISALLOWED; if(!GLPS_IS(ENABLE)) { // Check if the provided connection exist if (gapc_get_conidx(param->conhdl) != GAP_INVALID_CONIDX) { status = PRF_ERR_OK; GLPS_SET(ENABLE); //Value used to initialize all readable value in DB uint16_t indntf_cfg = PRF_CLI_STOP_NTFIND; // Save the application task id glps_env.con_info.appid = src_id; // Save the connection handle associated to the profile glps_env.con_info.conidx = gapc_get_conidx(param->conhdl); // No RACP at service start. GLPS_CLEAR(RACP_ON_GOING); GLPS_CLEAR(SENDING_MEAS); // Configure Glucose Measuremment IND Cfg in DB if(param->con_type == PRF_CON_NORMAL) { glps_env.evt_cfg = param->evt_cfg; } else { glps_env.evt_cfg = 0; } if((glps_env.evt_cfg & GLPS_MEAS_NTF_CFG) != 0) { indntf_cfg = PRF_CLI_START_NTF; } //Set Glucose measurement notification configuration attmdb_att_set_value(GLPS_HANDLE(GLS_IDX_MEAS_NTF_CFG), sizeof(uint16_t), (uint8_t *)&indntf_cfg); // Configure Intermediate Cuff Pressure NTF Cfg in DB //Configure Glucose measurement context notification if (GLPS_IS(MEAS_CTX_SUPPORTED)) { indntf_cfg = PRF_CLI_STOP_NTFIND; if((glps_env.evt_cfg & GLPS_MEAS_CTX_NTF_CFG) != 0) { indntf_cfg = PRF_CLI_START_NTF; } //Set Glucose measurement context notification configuration attmdb_att_set_value(GLPS_HANDLE(GLS_IDX_MEAS_CTX_NTF_CFG), sizeof(uint16_t), (uint8_t *)&indntf_cfg); } indntf_cfg = PRF_CLI_STOP_NTFIND; if((glps_env.evt_cfg & GLPS_RACP_IND_CFG) != 0) { indntf_cfg = PRF_CLI_START_IND; } //Set record access control point indication configuration attmdb_att_set_value(GLPS_HANDLE(GLS_IDX_REC_ACCESS_CTRL_IND_CFG), sizeof(uint16_t), (uint8_t *)&indntf_cfg); //Set Glucose sensor features attmdb_att_set_value(GLPS_HANDLE(GLS_IDX_FEATURE_VAL), sizeof(uint16_t), (uint8_t *)¶m->features); // Enable Service + Set Security Level attmdb_svc_set_permission(glps_env.shdl, param->sec_lvl); // Go to connected state ke_state_set(TASK_GLPS, GLPS_CONNECTED); } } // send completed information to APP task that contains error status struct glps_enable_cfm * cmp_evt = KE_MSG_ALLOC(GLPS_ENABLE_CFM, src_id, TASK_GLPS, glps_enable_cfm); cmp_evt->conhdl = param->conhdl; cmp_evt->status = status; ke_msg_send(cmp_evt); return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref HTPT_ENABLE_REQ message. * The handler enables the Health Thermometer Profile Thermometer 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 htpt_enable_req_handler(ke_msg_id_t const msgid, struct htpt_enable_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { uint16_t value = 0; //Save the application task id htpt_env.con_info.appid = src_id; //Save the connection handle associated to the profile htpt_env.con_info.conidx = gapc_get_conidx(param->conhdl); // Check if the provided connection exist if (htpt_env.con_info.conidx == GAP_INVALID_CONIDX) { // The connection doesn't exist, request disallowed prf_server_error_ind_send((prf_env_struct *)&htpt_env, PRF_ERR_REQ_DISALLOWED, HTPT_ERROR_IND, HTPT_ENABLE_REQ); } else { //Configure Intermediate Temp Ntf Cfg in DB if (htpt_env.att_tbl[HTPT_INTERM_TEMP_CHAR] != 0x00) { //Written value is 0 is discovery connection, given value if normal if(param->con_type == PRF_CON_NORMAL) { memcpy(&value, ¶m->interm_temp_ntf_en, sizeof(uint16_t)); if (param->interm_temp_ntf_en == PRF_CLI_START_NTF) { htpt_env.features |= HTPT_MASK_INTM_MEAS_CFG; } } attmdb_att_set_value(htpt_env.shdl + htpt_env.att_tbl[HTPT_INTERM_TEMP_CHAR] + 2, sizeof(uint16_t), (uint8_t *)&value); //Reset value value = 0; } //Configure Meas. Interval value and IND Cfg in DB if (htpt_env.att_tbl[HTPT_MEAS_INTV_CHAR] != 0x00) { //----------- Meas. Intv. Value ---------------------------------------------- //Written value is 0 is discovery connection, given value if normal if(param->con_type == PRF_CON_NORMAL) { memcpy(&value, ¶m->meas_intv, sizeof(uint16_t)); } attmdb_att_set_value(htpt_env.shdl + htpt_env.att_tbl[HTPT_MEAS_INTV_CHAR] + 1, sizeof(uint16_t), (uint8_t *)&value); //Reset value value = 0; //----------- IND Cfg ---------------------------------------------- if ((htpt_env.features & HTPT_MEAS_INTV_IND_SUP) == HTPT_MEAS_INTV_IND_SUP) { //Written value is 0 is discovery connection, given value if normal if(param->con_type == PRF_CON_NORMAL) { memcpy(&value, ¶m->meas_intv_ind_en, sizeof(uint16_t)); if (param->meas_intv_ind_en == PRF_CLI_START_IND) { htpt_env.features |= HTPT_MASK_MEAS_INTV_CFG; } } attmdb_att_set_value(htpt_env.shdl + htpt_env.att_tbl[HTPT_MEAS_INTV_CHAR] + 2, sizeof(uint16_t), (uint8_t *)&value); //Reset value value = 0; } } //Configure Temp Meas value IND Cfg in DB if(param->con_type == PRF_CON_NORMAL) { memcpy(&value, ¶m->temp_meas_ind_en, sizeof(uint16_t)); if (param->temp_meas_ind_en == PRF_CLI_START_IND) { htpt_env.features |= HTPT_MASK_TEMP_MEAS_CFG; } } attmdb_att_set_value(htpt_env.shdl + HTS_IDX_TEMP_MEAS_IND_CFG, sizeof(uint16_t), (uint8_t *)&value); //Reset value value = 1; //Initialize Temp Type value in DB if (htpt_env.att_tbl[HTPT_TEMP_TYPE_CHAR] != 0x00) { attmdb_att_set_value(htpt_env.shdl + HTS_IDX_TEMP_TYPE_VAL, sizeof(uint8_t), (uint8_t *)&value); } //Enable Attributes + Set Security Level attmdb_svc_set_permission(htpt_env.shdl, param->sec_lvl); // Go to connected state ke_state_set(TASK_HTPT, HTPT_CONNECTED); } 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 Handles reception of the @ref ANPC_WRITE_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_write_cmd_handler(ke_msg_id_t const msgid, struct anpc_write_cmd *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Message status uint8_t msg_status = KE_MSG_CONSUMED; // Get the address of the environment struct anpc_env_tag *anpc_env = PRF_CLIENT_GET_ENV(dest_id, anpc); if (anpc_env != NULL) { // Status uint8_t status = PRF_ERR_OK; // State is Connected or Busy ASSERT_ERR(ke_state_get(dest_id) != ANPC_IDLE); // Check the provided connection handle if (gapc_get_conidx(param->conhdl) == anpc_env->con_info.conidx) { // Check the current state if (ke_state_get(dest_id) == ANPC_BUSY) { msg_status = KE_MSG_SAVED; } else // state = ANPC_CONNECTED { // Attribute handle uint16_t handle = ATT_INVALID_SEARCH_HANDLE; // Length uint8_t length; ASSERT_ERR(anpc_env->operation == NULL); switch (param->write_code) { // Write Alert Notification Control Point Characteristic Value case (ANPC_WR_ALERT_NTF_CTNL_PT): { // Check the Category ID and the Command ID if ((param->value.ctnl_pt.cmd_id < CMD_ID_NB) && ((param->value.ctnl_pt.cat_id < CAT_ID_NB) || (param->value.ctnl_pt.cat_id == CAT_ID_ALL_SUPPORTED_CAT))) { handle = anpc_env->ans.chars[ANPC_CHAR_ALERT_NTF_CTNL_PT].val_hdl; length = sizeof(struct anp_ctnl_pt); } else { status = PRF_ERR_INVALID_PARAM; } } break; // Write New Alert Characteristic Client Char. Cfg. Descriptor Value case (ANPC_RD_WR_NEW_ALERT_CFG): { if (param->value.new_alert_ntf_cfg <= PRF_CLI_START_NTF) { handle = anpc_env->ans.descs[ANPC_DESC_NEW_ALERT_CL_CFG].desc_hdl; length = sizeof(uint16_t); } else { status = PRF_ERR_INVALID_PARAM; } } break; // Write Unread Alert Status Characteristic Client Char. Cfg. Descriptor Value case (ANPC_RD_WR_UNREAD_ALERT_STATUS_CFG): { if (param->value.unread_alert_status_ntf_cfg <= PRF_CLI_START_NTF) { handle = anpc_env->ans.descs[ANPC_DESC_UNREAD_ALERT_STATUS_CL_CFG].desc_hdl; length = sizeof(uint16_t); } else { status = PRF_ERR_INVALID_PARAM; } } break; default: { status = PRF_ERR_INVALID_PARAM; } break; } if (status == PRF_ERR_OK) { // Check if handle is viable if (handle != ATT_INVALID_SEARCH_HANDLE) { // Send the write request prf_gatt_write(&(anpc_env->con_info), handle, (uint8_t *)¶m->value, length, GATTC_WRITE); // Force the operation value param->operation = ANPC_WRITE_OP_CODE; // Store the command structure anpc_env->operation = param; msg_status = KE_MSG_NO_FREE; // Go to the Busy state ke_state_set(dest_id, ANPC_BUSY); } else { status = PRF_ERR_INEXISTENT_HDL; } } } } else { status = PRF_ERR_INVALID_PARAM; } if (status != PRF_ERR_OK) { anpc_send_cmp_evt(anpc_env, ANPC_WRITE_OP_CODE, status); } } else { anpc_send_no_conn_cmp_evt(dest_id, src_id, param->conhdl, ANPC_WRITE_OP_CODE); } return (int)msg_status; }
/** **************************************************************************************** * @brief Handles reception of the @ref ANPS_ENABLE_REQ 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 anps_enable_req_handler(ke_msg_id_t const msgid, struct anps_enable_req *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Alert Notification Profile Server Role Task Index Environment struct anps_idx_env_tag *anps_idx_env = NULL; // Connection Information structure struct prf_con_info con_info; // Status uint8_t status = PRF_ERR_OK; // Message status uint8_t msg_status = KE_MSG_CONSUMED; // 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 device status = PRF_CLIENT_ENABLE(con_info, param, anps_idx); } else { status = PRF_ERR_REQ_DISALLOWED; } if (status == PRF_ERR_OK) { // Get the newly created environment anps_idx_env = PRF_CLIENT_GET_ENV(dest_id, anps_idx); // Keep the Connection Information structure content memcpy(&anps_idx_env->con_info, &con_info, sizeof(struct prf_con_info)); if (param->con_type == PRF_CON_DISCOVERY) { // Force the configuration to 0 param->new_alert_ntf_cfg = PRF_CLI_STOP_NTFIND; param->unread_alert_status_ntf_cfg = PRF_CLI_STOP_NTFIND; } else // PRF_CON_NORMAL (Bonded peer device) { // Update the state in the environment if (param->new_alert_ntf_cfg != PRF_CLI_STOP_NTFIND) { // Force to PRF_CLI_START_NTF param->new_alert_ntf_cfg = PRF_CLI_START_NTF; ANPS_ENABLE_ALERT(anps_idx_env, ANP_NEW_ALERT); } if (param->unread_alert_status_ntf_cfg != PRF_CLI_STOP_NTFIND) { // Force to PRF_CLI_START_NTF param->unread_alert_status_ntf_cfg = PRF_CLI_START_NTF; ANPS_ENABLE_ALERT(anps_idx_env, ANP_UNREAD_ALERT); } } // Set the value of the New Alert Client Characteristic Configuration Descriptor attmdb_att_set_value(anps_env.ans_shdl + ANS_IDX_NEW_ALERT_CFG, sizeof(uint16_t), (uint8_t *)¶m->new_alert_ntf_cfg); // Set the value of the Unread Alert Status Client Characteristic Configuration Descriptor attmdb_att_set_value(anps_env.ans_shdl + ANS_IDX_UNREAD_ALERT_STATUS_CFG, sizeof(uint16_t), (uint8_t *)¶m->unread_alert_status_ntf_cfg); // Enable ANS attmdb_svc_set_permission(anps_env.ans_shdl, param->sec_lvl); // Go to Connected State ke_state_set(dest_id, ANPS_CONNECTED); // Send a complete event status to the application anps_send_cmp_evt(anps_idx_env->con_info.prf_id, anps_idx_env->con_info.appid, gapc_get_conhdl(anps_idx_env->con_info.conidx), ANPS_ENABLE_OP_CODE, PRF_ERR_OK); } else if (status == PRF_ERR_FEATURE_NOT_SUPPORTED) { // The message has been forwarded to another task id. msg_status = KE_MSG_NO_FREE; } else { // The request is disallowed (profile already enabled for this connection, or not enough memory, ...) anps_send_cmp_evt(dest_id, src_id, param->conhdl, ANPS_ENABLE_OP_CODE, PRF_ERR_REQ_DISALLOWED); } return (int)msg_status; }