예제 #1
0
static int udss_create_db_req_handler(ke_msg_id_t const msgid,
                                      struct udss_create_db_req const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    //DB Creation Statis
    uint8_t status = ATT_ERR_NO_ERROR;

    //Save profile id
    udss_env.con_info.prf_id = TASK_UDSS;

    status = attm_svc_create_db(&udss_env.shdl, NULL, UDS_IDX_NB, &udss_env.att_tbl[0],
                                dest_id, &udss_att_db[0]);

    if (status == ATT_ERR_NO_ERROR)
    {
        //Disable service
        status = attmdb_svc_set_permission(udss_env.shdl, PERM(SVC, DISABLE));

        //If we are here, database has been fulfilled with success, go to idle test
        ke_state_set(TASK_UDSS, UDSS_IDLE);
    }

    //Send response to application
    struct udss_create_db_cfm * cfm = KE_MSG_ALLOC(UDSS_CREATE_DB_CFM, src_id, TASK_UDSS,
                                                   udss_create_db_cfm);
    cfm->status = status;
    ke_msg_send(cfm);

    return (KE_MSG_CONSUMED);
}
예제 #2
0
파일: findt_task.c 프로젝트: imGit/DA14580
/**
 ****************************************************************************************
 * @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);
}
예제 #3
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);
}
예제 #4
0
void pasps_disable(struct pasps_idx_env_tag *idx_env, uint16_t conhdl)
{
    // Disable PAS service
    attmdb_svc_set_permission(pasps_env.pass_shdl, PERM(SVC, DISABLE));

    struct pasps_disable_ind *ind = KE_MSG_ALLOC(PASPS_DISABLE_IND,
                                                 idx_env->con_info.appid, idx_env->con_info.prf_id,
                                                 pasps_disable_ind);

    memset(ind, 0x00, sizeof(struct pasps_disable_ind));

    ind->conhdl = conhdl;

    if (PASPS_IS_NTF_ENABLED(idx_env, PASPS_FLAG_ALERT_STATUS_CFG))
    {
        ind->alert_status_ntf_cfg = PRF_CLI_START_NTF;
    }

    if (PASPS_IS_NTF_ENABLED(idx_env, PASPS_FLAG_RINGER_SETTING_CFG))
    {
        ind->ringer_setting_ntf_cfg = PRF_CLI_START_NTF;
    }

    ke_msg_send(ind);

    // Go to idle state
    ke_state_set(idx_env->con_info.prf_id, PASPS_IDLE);

    // Free the environment allocated for this connection
    PRF_CLIENT_DISABLE(pasps_idx_envs, KE_IDX_GET(idx_env->con_info.prf_id), PASPS);
}
예제 #5
0
void wechat_disable(void)
{
    att_size_t length;
    uint8_t *alert_lvl;

    // Disable service in database
    attmdb_svc_set_permission(wechat_env.wechat_shdl, PERM_RIGHT_DISABLE);

    struct wechat_disable_ind *ind = KE_MSG_ALLOC(WECHAT_DISABLE_IND,
                                                 wechat_env.con_info.appid, TASK_WECHAT,
                                                 wechat_disable_ind);

    //Get value stored in DB
    attmdb_att_get_value(wechat_env.wechat_shdl + WECHAT_1_IDX_VAL,
                         &length, &alert_lvl);

    // Fill in the parameter structure
    ind->conhdl     = gapc_get_conhdl(wechat_env.con_info.conidx);

    // Send the message
    ke_msg_send(ind);

    // Go to idle state
    ke_state_set(TASK_WECHAT, WECHAT_IDLE);
}
예제 #6
0
파일: htpt.c 프로젝트: imGit/DA14580
void htpt_disable(uint16_t conhdl) 
{
    att_size_t att_length;
    uint8_t *att_value;

    //Disable HTS in database
    attmdb_svc_set_permission(htpt_env.shdl, PERM_RIGHT_DISABLE);

    //Send current configuration to APP
    struct htpt_disable_ind* ind = KE_MSG_ALLOC(HTPT_DISABLE_IND,
                                                htpt_env.con_info.appid, TASK_HTPT,
                                                htpt_disable_ind);

    ind->conhdl = conhdl;

    //Temperature Measurement Char. - Indications Configuration
    if (HTPT_IS_INDNTF_ENABLED(HTPT_MASK_TEMP_MEAS_CFG))
    {
        ind->temp_meas_ind_en = PRF_CLI_START_IND;
    }

    //Intermediate Measurement Char. - Indications Configuration
    if (HTPT_IS_CHAR_SUPPORTED(HTPT_INTERM_TEMP_CHAR))
    {
        if (HTPT_IS_INDNTF_ENABLED(HTPT_MASK_INTM_MEAS_CFG))
        {
            ind->interm_temp_ntf_en = PRF_CLI_START_NTF;
        }
    }

    //Measurement Interval Char. - Value
    if (HTPT_IS_CHAR_SUPPORTED(HTPT_MEAS_INTV_CHAR))
    {
        //Measurement Interval Char. - Indications Configuration
        if (HTPT_IS_FEATURE_SUPPORTED(HTPT_MEAS_INTV_IND_SUP))
        {
            if (HTPT_IS_INDNTF_ENABLED(HTPT_MASK_MEAS_INTV_CFG))
            {
                ind->meas_intv_ind_en = PRF_CLI_START_IND;
            }
        }

        attmdb_att_get_value(htpt_env.shdl + htpt_env.att_tbl[HTPT_MEAS_INTV_CHAR] + 1,
                             &att_length, &att_value);
        memcpy(&(ind->meas_intv), att_value, sizeof(uint16_t));
    }

    ke_msg_send(ind);

    //Reset indications/notifications bit field
    htpt_env.features &= ~HTPT_CFG_NTFIND_MASK;

    //Go to idle state
    ke_state_set(TASK_HTPT, HTPT_IDLE);
}
예제 #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);
}
예제 #8
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GLPS_CREATE_DB_REQ message.
 * The handler adds GLS into the database using the database
 * configuration value given in param.
 * @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 glps_create_db_req_handler(ke_msg_id_t const msgid,
                                      struct glps_create_db_req const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    //Service Configuration Flag
    uint16_t cfg_flag = GLPS_MANDATORY_MASK;
    //Database Creation Status
    uint8_t status;

    //Save Profile ID
    glps_env.con_info.prf_id = TASK_GLPS;

    //Save Database Configuration
    if(param->meas_ctx_supported)
    {
        GLPS_SET(MEAS_CTX_SUPPORTED);
    }

    // set start handle or automatically set it when creating database (start_hdl = 0)
    glps_env.shdl=param->start_hdl;

    /*---------------------------------------------------*
     * Glucose Service Creation
     *---------------------------------------------------*/
    //Set Configuration Flag Value
    if (GLPS_IS(MEAS_CTX_SUPPORTED))
    {
        cfg_flag |= GLPS_MEAS_CTX_PRES_MASK;
    }

    //Add Service Into Database
    status = attm_svc_create_db(&glps_env.shdl, (uint8_t *)&cfg_flag, GLS_IDX_NB, NULL,
                               dest_id, &glps_att_db[0]);
    //Disable GLS
    attmdb_svc_set_permission(glps_env.shdl, PERM(SVC, DISABLE));

    //Go to Idle State
    if (status == ATT_ERR_NO_ERROR)
    {
        //If we are here, database has been fulfilled with success, go to idle test
        ke_state_set(TASK_GLPS, GLPS_IDLE);
    }

    //Send response to application
    struct glps_create_db_cfm * cfm = KE_MSG_ALLOC(GLPS_CREATE_DB_CFM, src_id,
                                                   TASK_GLPS, glps_create_db_cfm);
    cfm->status = status;
    ke_msg_send(cfm);

    return (KE_MSG_CONSUMED);
}
예제 #9
0
파일: tips.c 프로젝트: FuangCao/jwaoo-toy
void tips_disable(struct tips_idx_env_tag *tips_idx_env, uint16_t conhdl)
{
    // Disable CTS
    attmdb_svc_set_permission(tips_env.cts_shdl, PERM(SVC, DISABLE));

    if (TIPS_IS_SUPPORTED(TIPS_NDCS_SUP))
    {
        // Disable NDCS
        attmdb_svc_set_permission(tips_env.ndcs_shdl, PERM(SVC, DISABLE));
    }

    if (TIPS_IS_SUPPORTED(TIPS_RTUS_SUP))
    {
        // Disable RTUS
        attmdb_svc_set_permission(tips_env.rtus_shdl, PERM(SVC, DISABLE));
    }

    // Send APP cfg every time, C may have changed it
    struct tips_disable_ind *ind = KE_MSG_ALLOC(TIPS_DISABLE_IND,
                                                tips_idx_env->con_info.appid, tips_idx_env->con_info.prf_id,
                                                tips_disable_ind);

    ind->conhdl = conhdl;

    if ((tips_idx_env->ntf_state & TIPS_CTS_CURRENT_TIME_CFG) == TIPS_CTS_CURRENT_TIME_CFG)
    {
        ind->current_time_ntf_en    = PRF_CLI_START_NTF;

        //Reset notifications bit field
        tips_idx_env->ntf_state &= ~TIPS_CTS_CURRENT_TIME_CFG;
    }

    ke_msg_send(ind);

    //Go to idle state
    ke_state_set(tips_idx_env->con_info.prf_id, TIPS_IDLE);

    PRF_CLIENT_DISABLE(tips_idx_envs, KE_IDX_GET(tips_idx_env->con_info.prf_id), TIPS);
}
예제 #10
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref HRPS_CREATE_DB_REQ message.
 * The handler adds HRS into the database using the database
 * configuration value given in param.
 * @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_create_db_req_handler(ke_msg_id_t const msgid,
                                      struct hrps_create_db_req const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    //Service Configuration Flag
    uint8_t cfg_flag = HRPS_MANDATORY_MASK;
    //Database Creation Status
    uint8_t status;

    //Save Profile ID
    hrps_env.con_info.prf_id = TASK_HRPS;
    //Save Database Configuration
    hrps_env.features = param->features;

    /*---------------------------------------------------*
     * Heart Rate Service Creation
     *---------------------------------------------------*/
    //Set Configuration Flag Value
    if (HRPS_IS_SUPPORTED(HRPS_BODY_SENSOR_LOC_CHAR_SUP))
    {
        cfg_flag |= HRPS_BODY_SENSOR_LOC_MASK;
    }
    if (HRPS_IS_SUPPORTED(HRPS_ENGY_EXP_FEAT_SUP))
    {
        cfg_flag |= HRPS_HR_CTNL_PT_MASK;
    }

    //Add Service Into Database
    status = attm_svc_create_db(&hrps_env.shdl, (uint8_t *)&cfg_flag, HRS_IDX_NB, NULL,
                               dest_id, &hrps_att_db[0]);
    //Disable HRS
    attmdb_svc_set_permission(hrps_env.shdl, PERM(SVC, DISABLE));

    //Go to Idle State
    if (status == ATT_ERR_NO_ERROR)
    {
        //If we are here, database has been fulfilled with success, go to idle test
        ke_state_set(TASK_HRPS, HRPS_IDLE);
    }

    //Send response to application
    struct hrps_create_db_cfm * cfm = KE_MSG_ALLOC(HRPS_CREATE_DB_CFM, src_id,
                                                   TASK_HRPS, hrps_create_db_cfm);
    cfm->status = status;
    ke_msg_send(cfm);

    return (KE_MSG_CONSUMED);
}
예제 #11
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);
}
예제 #12
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);
}
예제 #13
0
파일: findt.c 프로젝트: FuangCao/jwaoo-toy
void findt_disable(uint16_t conhdl) 
{
    // Inform the application about the disconnection
    struct findt_disable_ind *ind = KE_MSG_ALLOC(FINDT_DISABLE_IND,
                                                 findt_env.con_info.appid, TASK_FINDT,
                                                 findt_disable_ind);

    ind->conhdl = conhdl;

    ke_msg_send(ind);

    //Disable IAS in database
    attmdb_svc_set_permission(findt_env.shdl, PERM_RIGHT_DISABLE);

    //Go to idle state
    ke_state_set(TASK_FINDT, FINDT_IDLE);
}
예제 #14
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);
}
예제 #15
0
void cpps_disable(uint16_t conhdl)
{
    // Disable CPS in database
    attmdb_svc_set_permission(cpps_env.shdl, PERM_RIGHT_DISABLE);

    //Send current configuration to APP
    struct cpps_disable_ind* ind = KE_MSG_ALLOC(CPPS_DISABLE_IND,
                                                 cpps_env.con_info.appid, cpps_env.con_info.prf_id,
                                                 cpps_disable_ind);

    ind->conhdl = conhdl;

    // CP Measurement Char. - Client Characteristic Configuration Descriptor
    ind->prfl_ntf_ind_cfg = CPPS_IS_NTF_IND_BCST_ENABLED(CPP_PRF_CFG_FLAG_CP_MEAS_NTF);

    if (CPPS_IS_FEATURE_SUPPORTED(cpps_env.prfl_cfg, CPPS_MEAS_BCST_MASK))
    {
        // CP Measurement Char. - Server Characteristic Configuration Descriptor
        ind->prfl_ntf_ind_cfg |= CPPS_IS_NTF_IND_BCST_ENABLED(CPP_PRF_CFG_FLAG_SP_MEAS_NTF);
    }

    if (CPPS_IS_FEATURE_SUPPORTED(cpps_env.prfl_cfg, CPPS_VECTOR_MASK))
    {
        // CP Vector. - Client Characteristic Configuration Descriptor
        ind->prfl_ntf_ind_cfg |= CPPS_IS_NTF_IND_BCST_ENABLED(CPP_PRF_CFG_FLAG_VECTOR_NTF);
    }

    if (CPPS_IS_FEATURE_SUPPORTED(cpps_env.prfl_cfg, CPPS_CTNL_PT_MASK))
    {
        // Control Point Char. - Client Characteristic Configuration Descriptor
        ind->prfl_ntf_ind_cfg |= CPPS_IS_NTF_IND_BCST_ENABLED(CPP_PRF_CFG_FLAG_CTNL_PT_IND);
    }

    // Instantaneous Power
    ind->instantaneous_power = cpps_env.inst_power;

    ke_msg_send(ind);

    // Reset the notification/indication status
    cpps_env.prfl_cfg &= CPP_FEAT_ALL_SUPP;

    // Go to idle state
    ke_state_set(TASK_CPPS, CPPS_IDLE);
}
예제 #16
0
파일: accel_task.c 프로젝트: imGit/DA14580
/**
 ****************************************************************************************
 * @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);
}
예제 #17
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref STREAMDATAD_CREATE_DB_REQ message.
 * The handler adds STREAMDATAD Service into the database using the database
 * configuration value given in param.
 * @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_create_db_req_handler(ke_msg_id_t const msgid,
                                      struct streamdatad_create_db_req const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    //Service Configuration Flag
    uint32_t cfg_flag = 0xFFFFFFFF;
    //Database Creation Status
    uint8_t status;

    //Save Application ID
    streamdatad_env.appid = src_id;


    // set start handle or automatically set it when creating database (start_hdl = 0)
    streamdatad_env.shdl=param->start_hdl;

    //Add Service Into Database
    status = attm_svc_create_db(&streamdatad_env.shdl, (uint8_t *)&cfg_flag,  STREAMDATAD_IDX_NB, NULL,
                               dest_id, &streamdatad_att_db[0]);

    //Disable GLS
    attmdb_svc_set_permission(streamdatad_env.shdl, PERM(SVC, DISABLE));

    //Go to Idle State
    if (status == ATT_ERR_NO_ERROR)
    {
        //If we are here, database has been fulfilled with success, go to idle test
        ke_state_set(TASK_STREAMDATAD, STREAMDATAD_IDLE);
    }

    //Send response to application
    struct streamdatad_create_db_cfm * cfm = KE_MSG_ALLOC(STREAMDATAD_CREATE_DB_CFM, streamdatad_env.appid,
                                                    TASK_STREAMDATAD, streamdatad_create_db_cfm);
    cfm->status = status;
    ke_msg_send(cfm);

    return (KE_MSG_CONSUMED);
}
예제 #18
0
파일: findt_task.c 프로젝트: imGit/DA14580
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref FINDT_CREATE_DB_REQ message.
 * The handler adds IAS into the database using the database
 * configuration value given in param.
 * @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_create_db_req_handler(ke_msg_id_t const msgid,
                                       struct findt_create_db_req const *param,
                                       ke_task_id_t const dest_id,
                                       ke_task_id_t const src_id)
{
    //Service Configuration Flag
    uint8_t cfg_flag = FINDT_MANDATORY_MASK;
    //Database Creation Status
    uint8_t status;

    //Save Profile ID
    findt_env.con_info.prf_id = TASK_FINDT;

    /*---------------------------------------------------*
     * Immediate Alert Service Creation
     *---------------------------------------------------*/

    //Add Service Into Database
    status = attm_svc_create_db(&findt_env.shdl, (uint8_t *)&cfg_flag, FINDT_IAS_IDX_NB, NULL,
                               dest_id, &findt_att_db[0]);
    //Disable IAS
    attmdb_svc_set_permission(findt_env.shdl, PERM(SVC, DISABLE));

    //Go to Idle State
    if (status == ATT_ERR_NO_ERROR)
    {
        //If we are here, database has been fulfilled with success, go to idle state
        ke_state_set(TASK_FINDT, FINDT_IDLE);
    }

    //Send CFM to application
    struct findt_create_db_cfm * cfm = KE_MSG_ALLOC(FINDT_CREATE_DB_CFM, src_id,
                                                    TASK_FINDT, findt_create_db_cfm);
    cfm->status = status;
    ke_msg_send(cfm);

    return (KE_MSG_CONSUMED);
}
예제 #19
0
static int diss_create_db_req_handler(ke_msg_id_t const msgid,
                                      struct diss_create_db_req const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    //Service content flag
    uint32_t cfg_flag;
    //DB Creation Statis
    uint8_t status = ATT_ERR_NO_ERROR;

    //Save profile id
    diss_env.con_info.prf_id = TASK_DISS;

    //Compute Attribute Table and save it in environment
    cfg_flag = diss_compute_cfg_flag(param->features);

    status = attm_svc_create_db(&diss_env.shdl, (uint8_t *)&cfg_flag, DIS_IDX_NB, &diss_env.att_tbl[0],
                                dest_id, &diss_att_db[0]);

    if (status == ATT_ERR_NO_ERROR)
    {
        //Disable service
        status = attmdb_svc_set_permission(diss_env.shdl, PERM(SVC, DISABLE));

        //If we are here, database has been fulfilled with success, go to idle test
        ke_state_set(TASK_DISS, DISS_IDLE);
    }

    //Send response to application
    struct diss_create_db_cfm * cfm = KE_MSG_ALLOC(DISS_CREATE_DB_CFM, src_id, TASK_DISS,
                                                   diss_create_db_cfm);
    cfm->status = status;
    ke_msg_send(cfm);

    return (KE_MSG_CONSUMED);
}
예제 #20
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);
}
예제 #21
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref HPSS_CREATE_DB_REQ message.
 * The handler adds HPS into the database.
 * @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 hpss_create_db_req_handler(ke_msg_id_t const msgid,
                                      struct hpss_create_db_req const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    //Database Creation Status
    uint8_t status;

    //Save Profile ID
    hpss_env.con_info.prf_id = TASK_HPSS;

    /*---------------------------------------------------*
     * HTTP Proxy Service Creation
     *---------------------------------------------------*/

    //Add Service Into Database
    status = attm_svc_create_db(&hpss_env.hps_shdl, NULL, HPS_IDX_NB, NULL,
                                dest_id, &hpss_att_db[0]);
    //Disable HPS
    attmdb_svc_set_permission(hpss_env.hps_shdl, PERM(SVC, DISABLE));

    //Go to Idle State
    if (status == ATT_ERR_NO_ERROR)
    {
        //If we are here, database has been fulfilled with success, go to idle state
        ke_state_set(TASK_HPSS, HPSS_IDLE);
    }

    //Send CFM to application
    struct hpss_create_db_cfm * cfm = KE_MSG_ALLOC(HPSS_CREATE_DB_CFM, src_id,
                                      TASK_HPSS, hpss_create_db_cfm);
    cfm->status = status;
    ke_msg_send(cfm);

    return (KE_MSG_CONSUMED);
}
예제 #22
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref SAMPLE128_CREATE_DB_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 sample128_create_db_req_handler(ke_msg_id_t const msgid,
                                       struct sample128_create_db_req const *param,
                                       ke_task_id_t const dest_id,
                                       ke_task_id_t const src_id)
{
    //Database Creation Status
    uint8_t status;
    uint8_t nb_att_16;
    uint8_t nb_att_128;
    uint8_t nb_att_32;
    uint16_t att_decl_svc = ATT_DECL_PRIMARY_SERVICE;
    uint16_t att_decl_char = ATT_DECL_CHARACTERISTIC;
    uint16_t att_decl_cfg = ATT_DESC_CLIENT_CHAR_CFG;
    uint16_t val_hdl;
    uint16_t char_hdl; 

    //Save Profile ID
    sample128_env.con_info.prf_id = TASK_SAMPLE128;

    /*---------------------------------------------------*
     * Link Loss Service Creation
     *---------------------------------------------------*/

        //Add Service Into Database
        nb_att_16 = 4; // 2 UUID16 atts
        nb_att_32 = 0;// No UUID32 att
        nb_att_128 = 2; //1 UUID128 att
        status = attmdb_add_service(&(sample128_env.sample128_shdl), TASK_SAMPLE128,
                                             nb_att_16, nb_att_32, nb_att_128, 58); //total attributte size = 36, 16 (svc)  + 19 (desc_char) + 1 (att)

        if (status == ATT_ERR_NO_ERROR)
        {
            //add svc attribute
            status = attmdb_add_attribute(sample128_env.sample128_shdl, ATT_UUID_128_LEN, //Data size = 16 (ATT_UUID_128_LEN)
                                               ATT_UUID_16_LEN, (uint8_t*)&att_decl_svc, PERM(RD, ENABLE),
                                               &(sample128_env.sample128_shdl));
            
            
            
            status = attmdb_att_set_value(sample128_env.sample128_shdl, ATT_UUID_128_LEN, (uint8_t *)sample128_svc.uuid);
            
            
//char 1     
            //add char attribute
            status = attmdb_add_attribute(sample128_env.sample128_shdl, ATT_UUID_128_LEN + 3, //Data size = 19 (ATT_UUID_128_LEN + 3)
                                               ATT_UUID_16_LEN, (uint8_t*) &att_decl_char, PERM(RD, ENABLE),
                                               &(char_hdl));
            
            
            
            //add val attribute
            status = attmdb_add_attribute(sample128_env.sample128_shdl, sizeof(uint8_t), //Data size = 1
                                               ATT_UUID_128_LEN, (uint8_t*)&sample128_1_val.uuid, PERM(RD, ENABLE) | PERM(WR, ENABLE),
                                               &(val_hdl));
            
            memcpy(sample128_1_char.attr_hdl, &val_hdl, sizeof(uint16_t));
            
            status = attmdb_att_set_value(char_hdl, sizeof(sample128_1_char), (uint8_t *)&sample128_1_char);
            

//////char 2
            //add char attribute
            status = attmdb_add_attribute(sample128_env.sample128_shdl, ATT_UUID_128_LEN + 3, //Data size = 19 (ATT_UUID_128_LEN + 3)
                                               ATT_UUID_16_LEN, (uint8_t*) &att_decl_char, PERM(RD, ENABLE),
                                               &(char_hdl));
                        
            //add val attribute
            status = attmdb_add_attribute(sample128_env.sample128_shdl, sizeof(uint8_t), //Data size = 1
                                               ATT_UUID_128_LEN, (uint8_t*)&sample128_2_val.uuid, PERM(RD, ENABLE) | PERM(NTF, ENABLE),
                                               &(val_hdl));
            
            memcpy(sample128_2_char.attr_hdl, &val_hdl, sizeof(uint16_t));
            
            status = attmdb_att_set_value(char_hdl, sizeof(sample128_2_char), (uint8_t *)&sample128_2_char);

            //add cfg attribute
            status = attmdb_add_attribute(sample128_env.sample128_shdl, sizeof(uint16_t), 
                                               ATT_UUID_16_LEN, (uint8_t*) &att_decl_cfg, PERM(RD, ENABLE) | PERM(WR, ENABLE),
                                               &(val_hdl));

            //Disable sample128 service
            attmdb_svc_set_permission(sample128_env.sample128_shdl, PERM(SVC, DISABLE));

            //Go to Idle State
    
            //If we are here, database has been fulfilled with success, go to idle state
            ke_state_set(TASK_SAMPLE128, SAMPLE128_IDLE);
        }
        
        //Send CFM to application
        struct sample128_create_db_cfm * cfm = KE_MSG_ALLOC(SAMPLE128_CREATE_DB_CFM, src_id,
                                                    TASK_SAMPLE128, sample128_create_db_cfm);
        cfm->status = status;
        ke_msg_send(cfm);
    

    return (KE_MSG_CONSUMED);
}
예제 #23
0
파일: htpt_task.c 프로젝트: imGit/DA14580
static int htpt_create_db_req_handler(ke_msg_id_t const msgid,
                                      struct htpt_create_db_req const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    //Valid Range value
    uint32_t valid_range;
    //Service content flag
    uint16_t cfg_flag;

    uint16_t total_size = 0;
    uint8_t nb_att = 0;
    uint8_t status = ATT_ERR_NO_ERROR;
    uint8_t i;

    // Save profile ID
    htpt_env.con_info.prf_id = TASK_HTPT;

    //Save database configuration
    htpt_env.features = param->features;

    //Compute Attribute Table and save it in environment
    cfg_flag = htpt_compute_att_table(param->features);

    status = attm_svc_create_db(&htpt_env.shdl, (uint8_t *)&cfg_flag, HTS_IDX_NB, &htpt_env.att_tbl[0],
                               dest_id, &htpt_att_db[0]);

    //Disable the service and set optional features
    if (status == ATT_ERR_NO_ERROR)
    {
        //Disable service
        status = attmdb_svc_set_permission(htpt_env.shdl, PERM(SVC, DISABLE));

        //Set optional properties and permissions
        if (htpt_env.att_tbl[HTPT_MEAS_INTV_CHAR] != 0x00)
        {
            nb_att = ATT_CHAR_PROP_RD;
            total_size = PERM(RD, ENABLE);
            i = 1;

            if ((param->features & HTPT_MEAS_INTV_IND_SUP) == HTPT_MEAS_INTV_IND_SUP)
            {
                nb_att |= ATT_CHAR_PROP_IND;
                total_size |= PERM(IND, ENABLE);
                i++;
            }

            if ((param->features & HTPT_MEAS_INTV_WR_SUP) == HTPT_MEAS_INTV_WR_SUP)
            {
                nb_att |= ATT_CHAR_PROP_WR;
                total_size |= PERM(WR, UNAUTH);
                i++;

                //Set Measurement Interval Char. - Valid Range value
                if ((param->valid_range_min) < (param->valid_range_max))
                {
                    valid_range = param->valid_range_min | (param->valid_range_max << 16);
                }
                else
                {
                    //If minimal and maximal values are the same or if maximal value is upper than minimal value
                    valid_range = HTPT_MEAS_INTV_DFLT_MIN | (HTPT_MEAS_INTV_DFLT_MAX << 16);
                }

                status = attmdb_att_set_value(htpt_env.shdl + htpt_env.att_tbl[HTPT_MEAS_INTV_CHAR] + i,
                                              sizeof(uint32_t), (uint8_t *)&valid_range);

            }

            attmdb_att_partial_value_update(htpt_env.shdl + htpt_env.att_tbl[HTPT_MEAS_INTV_CHAR], 0, 1, &nb_att);
            attmdb_att_set_permission(htpt_env.shdl + htpt_env.att_tbl[HTPT_MEAS_INTV_CHAR] + 1, total_size);
        }

        //If we are here, database has been fulfilled with success, go to idle test
        ke_state_set(TASK_HTPT, HTPT_IDLE);
    }

    //Send response to application
    struct htpt_create_db_cfm * cfm = KE_MSG_ALLOC(HTPT_CREATE_DB_CFM, src_id, TASK_HTPT,
                                                   htpt_create_db_cfm);
    cfm->status = status;
    ke_msg_send(cfm);

    return (KE_MSG_CONSUMED);
}
예제 #24
0
파일: htpt_task.c 프로젝트: imGit/DA14580
/**
 ****************************************************************************************
 * @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);
}
예제 #25
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref PASPS_CREATE_DB_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_create_db_req_handler(ke_msg_id_t const msgid,
                                       struct pasps_create_db_req const *param,
                                       ke_task_id_t const dest_id,
                                       ke_task_id_t const src_id)
{
    // Service Configuration Flag - All attributes have to be added in the database
    uint16_t cfg_flag = PASPS_DB_CFG_FLAG;
    // Database Creation Status
    uint8_t status;
    // Counter
    uint8_t counter;

    // Check if a PAS has already been added in the database
    if (ke_state_get(TASK_PASPS) == PASPS_DISABLED)
    {
        // Check the provided values
        if ((param->alert_status   <= PASP_ALERT_STATUS_VAL_MAX) &&
            (param->ringer_setting <= PASP_RINGER_NORMAL))
        {
            // Add service in the database
            status = attm_svc_create_db(&pasps_env.pass_shdl, (uint8_t *)&cfg_flag, PASS_IDX_NB, NULL,
                                        dest_id, &pasps_att_db[0]);

            // Go to Idle State
            if (status == ATT_ERR_NO_ERROR)
            {
                // Set the value of the Alert Status characteristic
                attmdb_att_set_value(pasps_env.pass_shdl + PASS_IDX_ALERT_STATUS_VAL, sizeof(uint8_t),
                                     (uint8_t *)&param->alert_status);
                // Set the value of the Ringer Setting characteristic
                attmdb_att_set_value(pasps_env.pass_shdl + PASS_IDX_RINGER_SETTING_VAL, sizeof(uint8_t),
                                     (uint8_t *)&param->ringer_setting);

                // Update the ringer state in the environment
                pasps_env.ringer_state = param->ringer_setting;

                // Disable PAS
                attmdb_svc_set_permission(pasps_env.pass_shdl, PERM(SVC, DISABLE));

                for (counter = 0; counter < PASPS_IDX_MAX; counter++)
                {
                    // If we are here, database has been fulfilled with success, go to idle state
                    ke_state_set(KE_BUILD_ID(TASK_PASPS, counter), PASPS_IDLE);
                }
            }
        }
        else
        {
            // One of the provided value in not within the defined range
            status = PRF_ERR_INVALID_PARAM;
        }
    }
    else
    {
        // Request is disallowed, a PAS has already been added
        status = PRF_ERR_REQ_DISALLOWED;
    }

    // Send response to application
    pasps_send_cmp_evt(TASK_PASPS, src_id, GAP_INVALID_CONHDL, PASPS_CREATE_DB_OP_CODE, status);

    return (KE_MSG_CONSUMED);
}
예제 #26
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;
}
예제 #27
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref TIPS_CREATE_DB_REQ message.
 * The handler adds CTS, NDCS and RTUS into the database using the database
 * configuration value given in param.
 * @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_create_db_req_handler(ke_msg_id_t const msgid,
                                      struct tips_create_db_req const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    //Service Configuration Flag - For CTS, Current Time Char. is mandatory
    uint8_t cfg_flag = TIPS_CTS_CURRENT_TIME_MASK;
    //Database Creation Status
    uint8_t status = ATT_ERR_NO_ERROR;

    //Save Database Configuration
    tips_env.features = param->features;

    /*---------------------------------------------------*
     * Current Time Service Creation
     *---------------------------------------------------*/
    //Set Configuration Flag Value
    if (TIPS_IS_SUPPORTED(TIPS_CTS_LOC_TIME_INFO_SUP))
    {
        cfg_flag |= TIPS_CTS_LOC_TIME_INFO_MASK;
    }
    if (TIPS_IS_SUPPORTED(TIPS_CTS_REF_TIME_INFO_SUP))
    {
        cfg_flag |= TIPS_CTS_REF_TIME_INFO_MASK;
    }

    //Add Service Into Database
    status = attm_svc_create_db(&tips_env.cts_shdl, (uint8_t *)&cfg_flag, CTS_IDX_NB, &tips_env.cts_att_tbl[0],
                                dest_id, &cts_att_db[0]);
    //Disable CTS
    attmdb_svc_set_permission(tips_env.cts_shdl, PERM(SVC, DISABLE));

    //All attributes are mandatory for NDCS and RTUS
    cfg_flag = 0xFF;
    /*---------------------------------------------------*
     * Next DST Change Service Creation
     *---------------------------------------------------*/
    if ((status == ATT_ERR_NO_ERROR) && (TIPS_IS_SUPPORTED(TIPS_NDCS_SUP)))
    {
        status = attm_svc_create_db(&tips_env.ndcs_shdl, (uint8_t *)&cfg_flag, NDCS_IDX_NB, &tips_env.ndcs_att_tbl[0],
                                   dest_id, &ndcs_att_db[0]);

        //Disable NDCS
        attmdb_svc_set_permission(tips_env.ndcs_shdl, PERM(SVC, DISABLE));
    }

    /*---------------------------------------------------*
     * Reference Time Update Service Creation
     *---------------------------------------------------*/
    if ((status == ATT_ERR_NO_ERROR) && (TIPS_IS_SUPPORTED(TIPS_RTUS_SUP)))
    {
        status = attm_svc_create_db(&tips_env.rtus_shdl, (uint8_t *)&cfg_flag, RTUS_IDX_NB, &tips_env.rtus_att_tbl[0],
                                   dest_id, &rtus_att_db[0]);

        //Disable RTUS
        attmdb_svc_set_permission(tips_env.rtus_shdl, PERM(SVC, DISABLE));
    }

    //Go to Idle State
    if (status == ATT_ERR_NO_ERROR)
    {
        //If we are here, database has been fulfilled with success, go to idle test
        ke_state_set(TASK_TIPS, TIPS_IDLE);
    }

    //Send response to application
    struct tips_create_db_cfm * cfm = KE_MSG_ALLOC(TIPS_CREATE_DB_CFM, src_id, TASK_TIPS,
                                                   tips_create_db_cfm);
    cfm->status = status;
    ke_msg_send(cfm);

    return (KE_MSG_CONSUMED);
}
예제 #28
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);
}
예제 #29
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);
}
예제 #30
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref BASS_CREATE_DB_REQ message.
 * The handler adds BAS into the database using value of the features param.
 * @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_create_db_req_handler(ke_msg_id_t const msgid,
                                      struct bass_create_db_req const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    // Service content flag
    uint8_t cfg_flag = BAS_CFG_FLAG_MANDATORY_MASK;
    // Status
    uint8_t status = PRF_ERR_OK;
    // Counter
    uint8_t i;
    // Battery Level characteristic value permissions
    uint16_t perm;
    // Battery Level characteristic value properties
    uint8_t prop;

    // Save profile id
    bass_env.con_info.prf_id = TASK_BASS;

    // Check number of BAS instances
    if (param->bas_nb <= BASS_NB_BAS_INSTANCES_MAX)
    {
        // Save number of BAS
        bass_env.bas_nb = param->bas_nb;

        for (i = 0; ((i < param->bas_nb) && (status == PRF_ERR_OK)); i++)
        {
            // Save database configuration
            bass_env.features[i] = param->features[i];

            // Check if notifications are supported
            if (bass_env.features[i] == BAS_BATT_LVL_NTF_SUP)
            {
                cfg_flag |= BAS_CFG_FLAG_NTF_SUP_MASK;
            }

            // Check if multiple instances
            if (bass_env.bas_nb > 1)
            {
                cfg_flag |= BAS_CFG_FLAG_MTP_BAS_MASK;
            }

            //Create BAS in the DB
            status = attm_svc_create_db(&bass_env.shdl[i], (uint8_t *)&cfg_flag, BAS_IDX_NB, NULL,
                                        dest_id, &bas_att_db[0]);

            //Disable the service and set optional features
            if (status == PRF_ERR_OK)
            {
                //Disable service
                status = attmdb_svc_set_permission(bass_env.shdl[i], PERM(SVC, DISABLE));

                //Set optional properties and permissions
                if (bass_env.features[i] == BAS_BATT_LVL_NTF_SUP)
                {
                    prop = ATT_CHAR_PROP_RD | ATT_CHAR_PROP_NTF;
                    perm = PERM(RD, ENABLE) | PERM(NTF, ENABLE);

                    attmdb_att_partial_value_update(bass_env.shdl[i] + BAS_IDX_BATT_LVL_CHAR, 0, 1, &prop);
                    attmdb_att_set_permission(bass_env.shdl[i] + BAS_IDX_BATT_LVL_VAL, perm);
                }
            }

            // Reset configuration flag
            cfg_flag = BAS_CFG_FLAG_MANDATORY_MASK;
        }

        if (status == PRF_ERR_OK)
        {
            //If we are here, database has been fulfilled with success, go to idle state
            ke_state_set(TASK_BASS, BASS_IDLE);
        }
    }
    else
    {
        status = PRF_ERR_INVALID_PARAM;
    }

    // Send confirmation to application
    struct bass_create_db_cfm * cfm = KE_MSG_ALLOC(BASS_CREATE_DB_CFM, src_id, TASK_BASS,
                                                   bass_create_db_cfm);
    cfm->status = status;
    ke_msg_send(cfm);

    return (KE_MSG_CONSUMED);
}