예제 #1
0
파일: glpc.c 프로젝트: FuangCao/jwaoo-toy
uint8_t glpc_unpack_meas_value(uint8_t *packed_meas, struct glp_meas* meas_val,
                               uint16_t *seq_num)
{
    uint8_t cursor = 0;

    // Flags
    meas_val->flags = packed_meas[cursor];
    cursor += 1;

    // Sequence Number
    *seq_num = co_read16p(packed_meas + cursor);
    cursor += 2;

    // Base Time
    cursor += prf_unpack_date_time(packed_meas + cursor, &(meas_val->base_time));

    //Time Offset
    if((meas_val->flags & GLP_MEAS_TIME_OFF_PRES) != 0)
    {
        meas_val->time_offset = co_read16p(packed_meas + cursor);
        cursor += 2;
    }

    // Glucose Concentration, type and location
    if((meas_val->flags & GLP_MEAS_GL_CTR_TYPE_AND_SPL_LOC_PRES) != 0)
    {
        meas_val->concentration = co_read16p(packed_meas + cursor);
        cursor += 2;

        /* type and location are 2 nibble values */
        meas_val->type = packed_meas[cursor] >> 4;
        meas_val->location = packed_meas[cursor] & 0xF;

        cursor += 1;
    }
예제 #2
0
파일: prf_utils.c 프로젝트: imGit/DA14580
void prf_unpack_char_pres_fmt(const uint8_t *packed_val, struct prf_char_pres_fmt* char_pres_fmt)
{

    char_pres_fmt->format       = *packed_val;
    char_pres_fmt->exponent     = *(packed_val + 1);
    char_pres_fmt->unit         = co_read16p(packed_val + 2);
    char_pres_fmt->name_space    = *(packed_val + 4);
    char_pres_fmt->description  = co_read16p(packed_val + 5);
}
예제 #3
0
파일: blpc.c 프로젝트: imGit/DA14580
void blpc_unpack_meas_value(struct bps_bp_meas* pmeas_val, uint8_t* packed_bp)
{
    uint8_t cursor;

    // blood pressure measurement flags
    pmeas_val->flags = packed_bp[0];

    // Blood Pressure Measurement Compound Value - Systolic
    pmeas_val->systolic = co_read16p(&(packed_bp[1]));

    // Blood Pressure Measurement Compound Value - Diastolic (mmHg)
    pmeas_val->diastolic = co_read16p(&(packed_bp[3]));

    //  Blood Pressure Measurement Compound Value - Mean Arterial Pressure (mmHg)
    pmeas_val->mean_arterial_pressure = co_read16p(&(packed_bp[5]));

    cursor = 7;

    // time flag set
    if ((pmeas_val->flags & BPS_FLAG_TIME_STAMP_PRESENT) == BPS_FLAG_TIME_STAMP_PRESENT)
    {
        cursor += prf_unpack_date_time(packed_bp + cursor, &(pmeas_val->time_stamp));
    }

    // pulse rate flag set
    if ((pmeas_val->flags & BPS_FLAG_PULSE_RATE_PRESENT) == BPS_FLAG_PULSE_RATE_PRESENT)
    {
        pmeas_val->pulse_rate = co_read16p(&(packed_bp[cursor + 0]));
        cursor += 2;
    }

    // User ID flag set
    if ((pmeas_val->flags & BPS_FLAG_USER_ID_PRESENT) == BPS_FLAG_USER_ID_PRESENT)
    {
        pmeas_val->user_id = packed_bp[cursor + 0];
        cursor += 1;
    }

    // measurement status flag set
    if ((pmeas_val->flags & BPS_FLAG_MEAS_STATUS_PRESENT) == BPS_FLAG_MEAS_STATUS_PRESENT)
    {
        pmeas_val->meas_status = co_read16p(&(packed_bp[cursor + 0]));
        cursor += 2;
    }
}
예제 #4
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATT_WRITE_CMD_IND 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 gattc_write_cmd_ind_handler(ke_msg_id_t const msgid,
                                      struct gattc_write_cmd_ind const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    uint8_t char_code = ADC_NOTIFY_ERR_CHAR;
    uint8_t status = PRF_APP_ERROR;

    if (KE_IDX_GET(src_id) == adc_notify_env.con_info.conidx)
    {
                
        if (param->handle == adc_notify_env.adc_notify_shdl + ADC_NOTIFY_IDX_CFG)
        {
            char_code = ADC_NOTIFY_CFG;
        }
        
        if (char_code == ADC_NOTIFY_CFG)
        {
            
            // Written value
            uint16_t ntf_cfg;

            // Extract value before check
            ntf_cfg = co_read16p(&param->value[0]);
        
            // Only update configuration if value for stop or notification enable
            if ((ntf_cfg == PRF_CLI_STOP_NTFIND) || (ntf_cfg == PRF_CLI_START_NTF))
            {
                //Save value in DB
                attmdb_att_set_value(param->handle, sizeof(uint16_t), (uint8_t *)&param->value[0]);
                
                // Conserve information in environment
                if (ntf_cfg == PRF_CLI_START_NTF)
                {
                    // Ntf cfg bit set to 1
                    adc_notify_env.feature |= PRF_CLI_START_NTF;
                }
                else
                {
                    // Ntf cfg bit set to 0
                    adc_notify_env.feature &= ~PRF_CLI_START_NTF;
                }                
                
                adc_notify_send_cfg(ntf_cfg);
                
                status = PRF_ERR_OK; 
                
            }
        }
    }

    // Send Write Response
    atts_write_rsp_send(adc_notify_env.con_info.conidx, param->handle, status);
    
    return (KE_MSG_CONSUMED);
}
예제 #5
0
파일: prf_utils.c 프로젝트: imGit/DA14580
uint8_t prf_unpack_date_time(uint8_t *packed_date, struct prf_date_time* date_time)
{
    date_time->year = co_read16p(&(packed_date[0]));
    date_time->month = packed_date[2];
    date_time->day   = packed_date[3];
    date_time->hour  = packed_date[4];
    date_time->min   = packed_date[5];
    date_time->sec   = packed_date[6];

    return 7;
}
예제 #6
0
파일: glpc_task.c 프로젝트: imGit/DA14580
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATTC_READ_IND message.
 * Generic event received after every simple read command sent to peer server.
 * @param[in] msgid Id of the message received (probably unused).
 * @param[in] param Pointer to the parameters of the message.
 * @param[in] dest_id ID of the receiving task instance (probably unused).
 * @param[in] src_id ID of the sending task instance.
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
static int gattc_read_ind_handler(ke_msg_id_t const msgid,
                                    struct gattc_read_ind const *param,
                                    ke_task_id_t const dest_id,
                                    ke_task_id_t const src_id)
{
    // Get the address of the environment
    struct glpc_env_tag *glpc_env = PRF_CLIENT_GET_ENV(dest_id, glpc);

    struct glpc_read_features_rsp * rsp = KE_MSG_ALLOC(GLPC_READ_FEATURES_RSP,
                                                       glpc_env->con_info.appid, dest_id,
                                                       glpc_read_features_rsp);
    // set connection handle
    rsp->conhdl = gapc_get_conhdl(glpc_env->con_info.conidx);
    // set error status
    rsp->status = ATT_ERR_NO_ERROR;

    // unpack feature information
    rsp->features = co_read16p(param->value);

    ke_msg_send(rsp);

    return (KE_MSG_CONSUMED);
}
예제 #7
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATT_WRITE_CMD_IND 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 gattc_write_cmd_ind_handler(ke_msg_id_t const msgid,
                                      struct gattc_write_cmd_ind const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    uint8_t char_code = SAMPLE128_ERR_CHAR;
    uint8_t status = PRF_APP_ERROR;

    if (KE_IDX_GET(src_id) == sample128_env.con_info.conidx)
    {
        if (param->handle == sample128_env.sample128_shdl + SAMPLE128_1_IDX_VAL)
        {
            char_code = SAMPLE128_1_CHAR;
        }
        
        if (param->handle == sample128_env.sample128_shdl + SAMPLE128_2_IDX_CFG)
        {
            char_code = SAMPLE128_2_CFG;
        }
        
        if (char_code == SAMPLE128_1_CHAR)
        {
            
            //Save value in DB
            attmdb_att_set_value(param->handle, sizeof(uint8_t), (uint8_t *)&param->value[0]);
            
            if(param->last)
            {
                sample128_send_val(param->value[0]);
							  leds_state.flag = param->value[0];
							  //app_sample128_start_leds();
            }

            status = PRF_ERR_OK;
               
        }
        else if (char_code == SAMPLE128_2_CFG)
        {
            
            // Written value
            uint16_t ntf_cfg;

            // Extract value before check
            ntf_cfg = co_read16p(&param->value[0]);
        
            // Only update configuration if value for stop or notification enable
            if ((ntf_cfg == PRF_CLI_STOP_NTFIND) || (ntf_cfg == PRF_CLI_START_NTF))
            {
                //Save value in DB
                attmdb_att_set_value(param->handle, sizeof(uint16_t), (uint8_t *)&param->value[0]);
                
                // Conserve information in environment
                if (ntf_cfg == PRF_CLI_START_NTF)
                {
                    // Ntf cfg bit set to 1
                    sample128_env.feature |= PRF_CLI_START_NTF;
                }
                else
                {
                    // Ntf cfg bit set to 0
                    sample128_env.feature &= ~PRF_CLI_START_NTF;
                }                
                
                status = PRF_ERR_OK; 
                
            }
        }
    }

    // Send Write Response
    atts_write_rsp_send(sample128_env.con_info.conidx, param->handle, status);
    
    return (KE_MSG_CONSUMED);
}
예제 #8
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATT_HANDLE_VALUE_NTF 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 gatt_handle_value_ntf_handler(ke_msg_id_t const msgid,
                                        struct gatt_handle_value_notif const *param,
                                        ke_task_id_t const dest_id,
                                        ke_task_id_t const src_id)
{
    // Get the address of the environment
    struct cscpc_env_tag *cscpc_env = PRF_CLIENT_GET_ENV(dest_id, cscpc);

    if (cscpc_env != NULL)
    {
        // Offset
        uint8_t offset = CSCP_CSC_MEAS_MIN_LEN;

        // CSC Measurement value has been received
        struct cscpc_value_ind *ind = KE_MSG_ALLOC(CSCPC_VALUE_IND,
                                                   cscpc_env->con_info.appid,
                                                   cscpc_env->con_info.prf_id,
                                                   cscpc_value_ind);

        // Connection Handle
        ind->conhdl   = param->conhdl;
        // Attribute code
        ind->att_code = CSCPC_NTF_CSC_MEAS;

        /*----------------------------------------------------
         * Unpack Measurement --------------------------------
         *----------------------------------------------------*/

        // Flags
        ind->value.csc_meas.flags = param->value[0];

        // Cumulative Wheel Revolutions
        // Last Wheel Event Time
        if ((param->value[0] & CSCP_MEAS_WHEEL_REV_DATA_PRESENT) == CSCP_MEAS_WHEEL_REV_DATA_PRESENT)
        {
            // Cumulative Wheel Revolutions
            ind->value.csc_meas.cumul_wheel_rev = co_read32p(&param->value[offset]);
            offset += 4;

            // Last Wheel Event Time
            ind->value.csc_meas.last_wheel_evt_time = co_read16p(&param->value[offset]);
            offset += 2;
        }

        // Cumulative Crank Revolutions
        // Last Crank Event Time
        if ((param->value[0] & CSCP_MEAS_CRANK_REV_DATA_PRESENT) == CSCP_MEAS_CRANK_REV_DATA_PRESENT)
        {
            // Cumulative Crank Revolutions
            ind->value.csc_meas.cumul_crank_rev = co_read16p(&param->value[offset]);
            offset += 2;

            // Last Crank Event Time
            ind->value.csc_meas.last_crank_evt_time = co_read16p(&param->value[offset]);
        }

        ke_msg_send(ind);
    }
    // else ignore the message

    return (KE_MSG_CONSUMED);
}
예제 #9
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATTC_WRITE_CMD_IND 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 gattc_write_cmd_ind_handler(ke_msg_id_t const msgid,
                                       struct gattc_write_cmd_ind const *param,
                                       ke_task_id_t const dest_id,
                                       ke_task_id_t const src_id)
{
    // Get the conidx
    uint8_t conidx = KE_IDX_GET(src_id);
    // Get the address of the environment
    struct pasps_idx_env_tag *pasps_idx_env = PRF_CLIENT_GET_ENV(KE_BUILD_ID(dest_id, conidx), pasps_idx);

    // Check if the connection exists
    if (pasps_idx_env != NULL)
    {
        /*
         * ---------------------------------------------------------------------------------------------
         * Alert Status Client Characteristic Configuration Descriptor Value - Write
         * ---------------------------------------------------------------------------------------------
         */
        /*
         * ---------------------------------------------------------------------------------------------
         * Ringer Setting Client Characteristic Configuration Descriptor Value - Write
         * ---------------------------------------------------------------------------------------------
         */
        if ((param->handle == (pasps_env.pass_shdl + PASS_IDX_ALERT_STATUS_CFG)) ||
            (param->handle == (pasps_env.pass_shdl + PASS_IDX_RINGER_SETTING_CFG)))
        {
            // Status
            uint8_t status = PRF_ERR_OK;
            // Received configuration value
            uint16_t ntf_cfg = co_read16p(&param->value[0]);

            if ((ntf_cfg == PRF_CLI_STOP_NTFIND) || (ntf_cfg == PRF_CLI_START_NTF))
            {
                // Set the value of the Alert Status Client Characteristic Configuration Descriptor
                attmdb_att_set_value(param->handle, sizeof(uint16_t), (uint8_t *)&ntf_cfg);

                struct pasps_written_char_val_ind *ind = KE_MSG_ALLOC(PASPS_WRITTEN_CHAR_VAL_IND,
                                                                      pasps_idx_env->con_info.appid, dest_id,
                                                                      pasps_written_char_val_ind);

                ind->conhdl   = gapc_get_conhdl(pasps_idx_env->con_info.conidx);

                if (param->handle == pasps_env.pass_shdl + PASS_IDX_ALERT_STATUS_CFG)
                {
                    ind->value.alert_status_ntf_cfg = ntf_cfg;
                    ind->att_code = PASPS_ALERT_STATUS_NTF_CFG;

                    if (ntf_cfg == PRF_CLI_STOP_NTFIND)
                    {
                        PASPS_DISABLE_NTF(pasps_idx_env, PASPS_FLAG_ALERT_STATUS_CFG);
                    }
                    else
                    {
                        PASPS_ENABLE_NTF(pasps_idx_env, PASPS_FLAG_ALERT_STATUS_CFG);
                    }
                }
                else
                {
                    ind->value.ringer_setting_ntf_cfg = ntf_cfg;
                    ind->att_code = PASPS_RINGER_SETTING_NTF_CFG;

                    if (ntf_cfg == PRF_CLI_STOP_NTFIND)
                    {
                        PASPS_DISABLE_NTF(pasps_idx_env, PASPS_FLAG_RINGER_SETTING_CFG);
                    }
                    else
                    {
                        PASPS_ENABLE_NTF(pasps_idx_env, PASPS_FLAG_RINGER_SETTING_CFG);
                    }
                }

                ke_msg_send(ind);
            }
            else
            {
                status = PRF_APP_ERROR;
            }

            // Send write response
            atts_write_rsp_send(pasps_idx_env->con_info.conidx, param->handle, status);
        }
        /*
         * ---------------------------------------------------------------------------------------------
         * Ringer Control Point Characteristic Value - Write Without Response
         * ---------------------------------------------------------------------------------------------
         */
        else if (param->handle == (pasps_env.pass_shdl + PASS_IDX_RINGER_CTNL_PT_VAL))
        {
            // Inform the HL ?
            bool inform_hl = false;

            // Check the received value
            switch (param->value[0])
            {
                case (PASP_SILENT_MODE):
                {
                    // Ignore if ringer is already silent
                    if (pasps_env.ringer_state == PASP_RINGER_NORMAL)
                    {
                        inform_hl = true;
                    }
                } break;

                case (PASP_CANCEL_SILENT_MODE):
                {
                    // Ignore if ringer is not silent
                    if (pasps_env.ringer_state == PASP_RINGER_SILENT)
                    {
                        inform_hl = true;
                    }
                } break;

                case (PASP_MUTE_ONCE):
                {
                    inform_hl = true;
                } break;

                // No need to respond with an error (Write Without Response)
                default: break;
            }

            if (inform_hl)
            {
                struct pasps_written_char_val_ind *ind = KE_MSG_ALLOC(PASPS_WRITTEN_CHAR_VAL_IND,
                                                                      pasps_idx_env->con_info.appid, TASK_PASPS,
                                                                      pasps_written_char_val_ind);

                ind->conhdl   = gapc_get_conhdl(pasps_idx_env->con_info.conidx);;
                ind->att_code = PASPS_RINGER_CTNL_PT_CHAR_VAL;
                ind->value.ringer_ctnl_pt = param->value[0];

                ke_msg_send(ind);
            }
        }
        else
        {
            ASSERT_ERR(0);
        }
    }
    // else ignore the message

    return (KE_MSG_CONSUMED);
}
예제 #10
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATT_WRITE_CMD_IND message.
 * The handler compares the new values with current ones and notifies them if they changed.
 * @param[in] msgid Id of the message received (probably unused).
 * @param[in] param Pointer to the parameters of the message.
 * @param[in] dest_id ID of the receiving task instance (probably unused).
 * @param[in] src_id ID of the sending task instance.
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
static int gatt_write_cmd_ind_handler(ke_msg_id_t const msgid,
                                      struct gatt_write_cmd_ind const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    uint8_t status = PRF_ERR_OK;

    if (param->conhdl == qpps_env.conhdl)
    {
        // Client Char. Configuration
		uint8_t char_index = param->handle - (qpps_env.shdl + QPPS_IDX_VAL_NTF_CFG);
        if ((param->handle > (qpps_env.shdl + QPPS_IDX_VAL_CHAR)) && ((char_index % 3) == 0))
        {
            uint16_t value = 0x0000;

            //Extract value before check
            memcpy(&value, &(param->value), sizeof(uint16_t));

            if ((value == PRF_CLI_STOP_NTFIND) || (value == PRF_CLI_START_NTF))
            {
                if (value == PRF_CLI_STOP_NTFIND)
                {
                    qpps_env.features &= ~(QPPS_VALUE_NTF_CFG << (char_index / 3));
                }
                else //PRF_CLI_START_NTF
                {
                    qpps_env.features |= QPPS_VALUE_NTF_CFG << (char_index / 3);
                }
            }
            else
            {
                status = PRF_APP_ERROR;
            }

            if (status == PRF_ERR_OK)
            {
                uint8_t *old_value;
                atts_size_t length;

                attsdb_att_get_value(param->handle, &length, &old_value);
                if (value != co_read16p(old_value))
                {
                    //Update the attribute value
                    attsdb_att_set_value(param->handle, sizeof(uint16_t), (uint8_t *)&value);

                    if(param->last)
                    {
                        //Inform APP of configuration change
                        struct qpps_cfg_indntf_ind * ind = KE_MSG_ALLOC(QPPS_CFG_INDNTF_IND,
                                                                        qpps_env.appid, TASK_QPPS,
                                                                        qpps_cfg_indntf_ind);

                        ind->char_index = (char_index / 3);
                        memcpy(&ind->cfg_val, &value, sizeof(uint16_t));

                        ke_msg_send(ind);
                    }
                }
            }
        }
        else if (param->handle == (qpps_env.shdl + QPPS_IDX_RX_DATA_VAL))
        {
			if (param->length <= QPP_DATA_MAX_LEN)
			{
				//inform APP of configuration change
				struct qpps_data_val_ind * ind = KE_MSG_ALLOC_DYN(QPPS_DAVA_VAL_IND,
																  qpps_env.appid,
																  TASK_QPPS,
																  qpps_data_val_ind, param->length);

				memcpy(&ind->conhdl, &(qpps_env.conhdl), sizeof(uint16_t));
				//Send received data to app value
				ind->length = param->length;
				memcpy(ind->data, param->value, param->length);

				ke_msg_send(ind);
			}
			else
			{
				status = QPPS_ERR_RX_DATA_EXCEED_MAX_LENGTH;
			}
        }
		else
		{
			status = QPPS_ERR_INVALID_PARAM;
		}
    }

    if (param->response)
    {
        //Send write response
        atts_write_rsp_send(qpps_env.conhdl, param->handle, status);
    }

    return (KE_MSG_CONSUMED);
}
예제 #11
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GL2C_CODE_ATT_WR_CMD_IND 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 gattc_write_cmd_ind_handler(ke_msg_id_t const msgid,
                                      struct gattc_write_cmd_ind const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    // Counter
    uint8_t i;
    // Status
    uint8_t status = PRF_APP_ERROR;
    // Written value
    uint16_t ntf_cfg;

    // Look for the BAS instance
    for (i = 0; ((i < bass_env.bas_nb) && (status == PRF_APP_ERROR)); i++)
    {
        if (param->handle == bass_env.shdl[i] + BAS_IDX_BATT_LVL_NTF_CFG)
        {
            // Go out of the loop
            status = PRF_ERR_OK;
        }
    }

    //Revert Last incrementation
    i--;

    // If the attribute has been found, status is PRF_ERR_OK
    if (status == PRF_ERR_OK)
    {
        // Extract value before check
        ntf_cfg = co_read16p(&param->value[0]);

        // Only update configuration if value for stop or notification enable
        if ((ntf_cfg == PRF_CLI_STOP_NTFIND) || (ntf_cfg == PRF_CLI_START_NTF))
        {
            // 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);

            // Conserve information in environment
            if (ntf_cfg == PRF_CLI_START_NTF)
            {
                // Ntf cfg bit set to 1
                bass_env.features[i] |= BASS_FLAG_NTF_CFG_BIT;
            }
            else
            {
                // Ntf cfg bit set to 0
                bass_env.features[i] &= ~BASS_FLAG_NTF_CFG_BIT;
            }
            if(param->last)
            {
                // Inform APP of configuration change
                struct bass_batt_level_ntf_cfg_ind * ind = KE_MSG_ALLOC(BASS_BATT_LEVEL_NTF_CFG_IND,
                                                                        bass_env.con_info.appid, TASK_BASS,
                                                                        bass_batt_level_ntf_cfg_ind);
                ind->conhdl = gapc_get_conhdl(bass_env.con_info.conidx);
                co_write16p(&ind->ntf_cfg, ntf_cfg);
                ind->bas_instance = i;

                ke_msg_send(ind);
            }
        }
        else
        {
            status = PRF_APP_ERROR;
        }

        // Send write response
        atts_write_rsp_send(bass_env.con_info.conidx, param->handle, status);
    }

    return (KE_MSG_CONSUMED);
}
예제 #12
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATT_READ_CHAR_RESP message.
 * Generic event received after every simple read command sent to peer server.
 * @param[in] msgid Id of the message received (probably unused).
 * @param[in] param Pointer to the parameters of the message.
 * @param[in] dest_id ID of the receiving task instance (probably unused).
 * @param[in] src_id ID of the sending task instance.
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
static int gatt_rd_char_rsp_handler(ke_msg_id_t const msgid,
                                    struct gatt_read_char_resp const *param,
                                    ke_task_id_t const dest_id,
                                    ke_task_id_t const src_id)
{
    // Status
    uint8_t error_status = param->status;
    // Get the address of the environment
    struct basc_env_tag *basc_env = PRF_CLIENT_GET_ENV(dest_id, basc);

    if (error_status == PRF_ERR_OK)
    {
        // Battery Level Value
        if (basc_env->last_char_code == BASC_RD_BAS_BATT_LEVEL)
        {
            struct basc_batt_level_ind *ind = KE_MSG_ALLOC(BASC_BATT_LEVEL_IND,
                                                           basc_env->con_info.appid, dest_id,
                                                           basc_batt_level_ind);

            ind->conhdl     = basc_env->con_info.conhdl;
            ind->ind_type   = BASC_BATT_LEVEL_RD_RSP;
            ind->batt_level = param->data.data[0];
            ind->bas_nb     = basc_env->last_svc_inst_req;

            ke_msg_send(ind);
        }

        // Battery Level Client Characteristic Configuration Descriptor value
        else if (basc_env->last_char_code == BASC_RD_BAS_BATT_LEVEL_CLI_CFG)
        {
            struct basc_batt_level_ntf_cfg_rd_rsp *rsp = KE_MSG_ALLOC(BASC_BATT_LEVEL_NTF_CFG_RD_RSP,
                                                                      basc_env->con_info.appid, dest_id,
                                                                      basc_batt_level_ntf_cfg_rd_rsp);

            rsp->conhdl     = basc_env->con_info.conhdl;
            rsp->bas_nb     = basc_env->last_svc_inst_req;
            rsp->ntf_cfg    = co_read16p(&param->data.data[0]);

            ke_msg_send(rsp);
        }

        // Battery Level Client Presentation Format Descriptor value
        else if (basc_env->last_char_code == BASC_RD_BAS_BATT_LEVEL_PRES_FORMAT)
        {
            struct basc_batt_level_pres_format_rd_rsp *rsp = KE_MSG_ALLOC(BASC_BATT_LEVEL_PRES_FORMAT_RD_RSP,
                                                                          basc_env->con_info.appid, dest_id,
                                                                          basc_batt_level_pres_format_rd_rsp);

            rsp->conhdl     = basc_env->con_info.conhdl;
            rsp->bas_nb     = basc_env->last_svc_inst_req;

            prf_unpack_char_pres_fmt(&param->data.data[0], &rsp->char_pres_format);

            ke_msg_send(rsp);
        }

        //Unsupported Characteristic
        else
        {
            error_status = PRF_ERR_INEXISTENT_HDL;
        }
    }

    // Send Error indication to APP if needed
    if (error_status != PRF_ERR_OK)
    {
        basc_error_ind_send(basc_env, error_status);
    }

    return (KE_MSG_CONSUMED);
}
예제 #13
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATTC_WRITE_CMD_IND 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 gattc_write_cmd_ind_handler(ke_msg_id_t const msgid,
                                       struct gattc_write_cmd_ind const *param,
                                       ke_task_id_t const dest_id,
                                       ke_task_id_t const src_id)
{
    uint8_t conidx = KE_IDX_GET(src_id);
    // Get the address of the environment
    struct anps_idx_env_tag *anps_idx_env = PRF_CLIENT_GET_ENV(KE_BUILD_ID(dest_id, conidx), anps_idx);

    // Check if the connection exists
    if (anps_idx_env != NULL)
    {
        // Status
        uint8_t status = PRF_ERR_OK;

        /*
         * ---------------------------------------------------------------------------------------------
         * New Alert Client Characteristic Configuration Descriptor Value - Write
         * ---------------------------------------------------------------------------------------------
         */
        /*
         * ---------------------------------------------------------------------------------------------
         * Unread Status Alert Client Characteristic Configuration Descriptor Value - Write
         * ---------------------------------------------------------------------------------------------
         */
        if ((param->handle == (anps_env.ans_shdl + ANS_IDX_NEW_ALERT_CFG)) ||
            (param->handle == (anps_env.ans_shdl + ANS_IDX_UNREAD_ALERT_STATUS_CFG)))
        {
            // Received configuration value
            uint16_t ntf_cfg = co_read16p(&param->value[0]);

            if (ntf_cfg <= PRF_CLI_START_NTF)
            {
                // Alert type
                uint8_t alert_type = (param->handle == (anps_env.ans_shdl + ANS_IDX_NEW_ALERT_CFG))
                                     ? ANP_NEW_ALERT : ANP_UNREAD_ALERT;

                // Set the value of the Alert Status Client Characteristic Configuration Descriptor (Readable)
                attmdb_att_set_value(param->handle, sizeof(uint16_t), (uint8_t *)&ntf_cfg);

                // Update the status in the environment
                if (ntf_cfg == PRF_CLI_START_NTF)
                {
                    ANPS_ENABLE_ALERT(anps_idx_env, alert_type);
                }
                else
                {
                    ANPS_DISABLE_ALERT(anps_idx_env, alert_type);
                }

                // Inform the HL that the notification configuration status has been written
                anps_send_ntf_status_update_ind(anps_idx_env, alert_type);
            }
            else
            {
                status = PRF_APP_ERROR;
            }
        }
        /*
         * ---------------------------------------------------------------------------------------------
         * Alert Notification Control Point Characteristic Value - Write
         * ---------------------------------------------------------------------------------------------
         */
        else if (param->handle == (anps_env.ans_shdl + ANS_IDX_ALERT_NTF_CTNL_PT_VAL))
        {
            do
            {
                // Check the command ID value
                if (param->value[0] >= CMD_ID_NB)
                {
                    status = ANP_CMD_NOT_SUPPORTED;
                    break;
                }

                // Check the category ID value
                if ((param->value[1] >= CAT_ID_NB) &&
                    (param->value[1] != CAT_ID_ALL_SUPPORTED_CAT))
                {
                    status = ANP_CAT_NOT_SUPPORTED;
                    break;
                }

                if (param->value[1] < CAT_ID_NB)
                {
                    // New Alert
                    if ((param->value[0] % 2) == 0)
                    {
                        // Check if the category is supported
                        if (!ANPS_IS_NEW_ALERT_CATEGORY_SUPPORTED(param->value[1]))
                        {
                            status = ANP_CAT_NOT_SUPPORTED;
                            break;
                        }
                    }
                    // Unread Alert Status
                    else
                    {
                        // Check if the category is supported
                        if (!ANPS_IS_UNREAD_ALERT_CATEGORY_SUPPORTED(param->value[1]))
                        {
                            status = ANP_CAT_NOT_SUPPORTED;
                            break;
                        }
                    }
                }

                // React according to the received command id value
                switch (param->value[0])
                {
                    // Enable New Alert Notification
                    case (CMD_ID_EN_NEW_IN_ALERT_NTF):
                    {
                        if (param->value[1] != CAT_ID_ALL_SUPPORTED_CAT)
                        {
                            // Enable sending of new alert notification for the specified category
                            ANPS_ENABLE_NEW_ALERT_CATEGORY(param->value[1], anps_idx_env);
                        }
                        else
                        {
                            // Enable sending of new alert notification for all supported category
                            anps_idx_env->ntf_new_alert_cfg |= anps_env.supp_new_alert_cat;
                        }

                        anps_send_ntf_status_update_ind(anps_idx_env, ANP_NEW_ALERT);
                    } break;

                    // Enable Unread Alert Status Notification
                    case (CMD_ID_EN_UNREAD_CAT_STATUS_NTF):
                    {
                        if (param->value[1] != CAT_ID_ALL_SUPPORTED_CAT)
                        {
                            // Enable sending of unread alert notification for the specified category
                            ANPS_ENABLE_UNREAD_ALERT_CATEGORY(param->value[1], anps_idx_env);
                        }
                        else
                        {
                            // Enable sending of unread alert notification for all supported category
                            anps_idx_env->ntf_unread_alert_cfg |= anps_env.supp_unread_alert_cat;
                        }

                        anps_send_ntf_status_update_ind(anps_idx_env, ANP_UNREAD_ALERT);
                    } break;

                    // Disable New Alert Notification
                    case (CMD_ID_DIS_NEW_IN_ALERT_NTF):
                    {
                        if (param->value[1] != CAT_ID_ALL_SUPPORTED_CAT)
                        {
                            // Disable sending of new alert notification for the specified category
                            ANPS_DISABLE_NEW_ALERT_CATEGORY(param->value[1], anps_idx_env);
                        }
                        else
                        {
                            // Disable sending of new alert notification for all supported category
                            anps_idx_env->ntf_new_alert_cfg &= ~anps_env.supp_new_alert_cat;
                        }

                        anps_send_ntf_status_update_ind(anps_idx_env, ANP_NEW_ALERT);
                    } break;

                    // Disable Unread Alert Status Notification
                    case (CMD_ID_DIS_UNREAD_CAT_STATUS_NTF):
                    {
                        if (param->value[1] != CAT_ID_ALL_SUPPORTED_CAT)
                        {
                            // Disable sending of unread alert notification for the specified category
                            ANPS_DISABLE_UNREAD_ALERT_CATEGORY(param->value[1], anps_idx_env);
                        }
                        else
                        {
                            // Enable sending of unread alert notification for all supported category
                            anps_idx_env->ntf_unread_alert_cfg &= ~anps_env.supp_unread_alert_cat;
                        }

                        anps_send_ntf_status_update_ind(anps_idx_env, ANP_UNREAD_ALERT);
                    } break;

                    // Notify New Alert immediately
                    case (CMD_ID_NTF_NEW_IN_ALERT_IMM):
                    {
                        // Check if sending of notification is enabled
                        if (ANPS_IS_ALERT_ENABLED(anps_idx_env, ANP_NEW_ALERT))
                        {
                            if (param->value[1] == CAT_ID_ALL_SUPPORTED_CAT)
                            {
                                // Check if at least one category can be notified
                                if (anps_idx_env->ntf_new_alert_cfg != 0)
                                {
                                    anps_send_ntf_immediate_req_ind(anps_idx_env, ANP_NEW_ALERT,
                                                                    CAT_ID_ALL_SUPPORTED_CAT);
                                }
                            }
                            else
                            {
                                // Check if sending of notifications has been enabled for the specified category.
                                if (ANPS_IS_NEW_ALERT_CATEGORY_ENABLED(param->value[1], anps_idx_env))
                                {
                                    anps_send_ntf_immediate_req_ind(anps_idx_env, ANP_NEW_ALERT,
                                                                    param->value[1]);
                                }
                            }
                        }
                    } break;

                    // Notify Unread Alert Status immediately
                    case (CMD_ID_NTF_UNREAD_CAT_STATUS_IMM):
                    {
                        if (ANPS_IS_ALERT_ENABLED(anps_idx_env, ANP_UNREAD_ALERT))
                        {
                            // Check if sending of notification is enabled
                            if (ANPS_IS_ALERT_ENABLED(anps_idx_env, ANP_UNREAD_ALERT))
                            {
                                if (param->value[1] == CAT_ID_ALL_SUPPORTED_CAT)
                                {
                                    // Check if at least one category can be notified
                                    if (anps_idx_env->ntf_unread_alert_cfg != 0)
                                    {
                                        anps_send_ntf_immediate_req_ind(anps_idx_env, ANP_UNREAD_ALERT,
                                                                        CAT_ID_ALL_SUPPORTED_CAT);
                                    }
                                }
                                else
                                {
                                    // Check if sending of notifications has been enabled for the specified category.
                                    if (ANPS_IS_UNREAD_ALERT_CATEGORY_ENABLED(param->value[1], anps_idx_env))
                                    {
                                        anps_send_ntf_immediate_req_ind(anps_idx_env, ANP_UNREAD_ALERT,
                                                                        param->value[1]);
                                    }
                                }
                            }
                        }
                    } break;

                    default:
                    {
                        ASSERT_ERR(0);
                    } break;
                }
            } while (0);
        }
        else
        {
            ASSERT_ERR(0);
        }

        // Send write response
        atts_write_rsp_send(anps_idx_env->con_info.conidx, param->handle, status);
    }
    // else ignore the message

    return (KE_MSG_CONSUMED);
}