Example #1
0
/**
 ****************************************************************************************
 * @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);
}
Example #3
0
/**
 ****************************************************************************************
 * @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);
}
Example #4
0
/**
 ****************************************************************************************
 * @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 *)&param->sample128_1_val);

        // Go to Connected state
        ke_state_set(TASK_SAMPLE128, SAMPLE128_CONNECTED);
    }

    return (KE_MSG_CONSUMED);
}
Example #5
0
/**
 ****************************************************************************************
 * @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);
}
Example #6
0
/**
 ****************************************************************************************
 * @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);
}
Example #7
0
/**
 ****************************************************************************************
 * @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 *)&param->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);
}
Example #8
0
/**
 ****************************************************************************************
 * @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);
}
Example #9
0
/**
 ****************************************************************************************
 * @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 *)&param->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);
}
Example #10
0
/**
 ****************************************************************************************
 * @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 *)&param->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 *)&param->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 *)&param->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 *)&param->user_db_change_incr);

				
        // Go to connected state
        ke_state_set(TASK_UDSS, UDSS_CONNECTED);
    }

    return (KE_MSG_CONSUMED);
}
Example #11
0
/**
 ****************************************************************************************
 * @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);
}
Example #12
0
/**
 ****************************************************************************************
 * @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 *)&param->lls_alert_lvl);

        // Go to Connected state
        ke_state_set(TASK_HPSS, HPSS_CONNECTED);
    }

    return (KE_MSG_CONSUMED);
}
Example #13
0
/**
 ****************************************************************************************
 * @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, &param->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);
}
Example #14
0
/**
 ****************************************************************************************
 * @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 *)&param->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 *)&param->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;
}
Example #15
0
/**
 ****************************************************************************************
 * @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, &param->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);
}
Example #16
0
/**
 ****************************************************************************************
 * @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 *)&param->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;
}
Example #17
0
/**
 ****************************************************************************************
 * @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 *)&param->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], &param->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);
}
Example #18
0
/**
 ****************************************************************************************
 * @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;
}
Example #19
0
/**
 ****************************************************************************************
 * @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 *)&param->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 *)&param->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;
}
Example #20
0
/**
 ****************************************************************************************
 * @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 *)&param->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);
}
Example #21
0
/**
 ****************************************************************************************
 * @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, &param->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, &param->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, &param->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, &param->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);
}
Example #22
0
/**
 ****************************************************************************************
 * @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, &param->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;
}
Example #23
0
/**
 ****************************************************************************************
 * @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 *)&param->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;
}
Example #24
0
/**
 ****************************************************************************************
 * @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 *)&param->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 *)&param->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;
}