Exemple #1
0
/**
 ****************************************************************************************
 * @brief Request to update Measurement Interval Value
 * @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 htpt_meas_intv_upd_req_handler(ke_msg_id_t const msgid,
                                          struct htpt_meas_intv_upd_req const *param,
                                          ke_task_id_t const dest_id,
                                          ke_task_id_t const src_id)
{
    uint16_t handle;

    //Check if Measurement Interval is supported
    if (htpt_env.att_tbl[HTPT_MEAS_INTV_CHAR] != 0x00)
    {
        //Check Connection Handle
        if(param->conhdl == gapc_get_conhdl(htpt_env.con_info.conidx))
        {
            handle = htpt_env.shdl + htpt_env.att_tbl[HTPT_MEAS_INTV_CHAR] + 1;

            //Update saved value in database
            attmdb_att_set_value(handle, sizeof(param->meas_intv), (uint8_t *)&param->meas_intv);

            //Must be indicated if enabled
            if((htpt_env.features & HTPT_MASK_MEAS_INTV_CFG) == HTPT_MASK_MEAS_INTV_CFG)
            {
                prf_server_send_event((prf_env_struct *)&htpt_env, true, handle);
            }
        }
        else
        {
            //Wrong Connection Handle
            prf_server_error_ind_send((prf_env_struct *)&htpt_env, PRF_ERR_INVALID_PARAM,
                                      HTPT_ERROR_IND, HTPT_MEAS_INTV_UPD_REQ);
        }
    }

    return (KE_MSG_CONSUMED);
}
static int sample128_upd_char2_req_handler(ke_msg_id_t const msgid,
                                    struct sample128_upd_char2_req const *param,
                                    ke_task_id_t const dest_id,
                                    ke_task_id_t const src_id)
{
    uint8_t status = PRF_ERR_OK;

    // Check provided values
    if(param->conhdl == gapc_get_conhdl(sample128_env.con_info.conidx))
    {
        // Update value in DB
        attmdb_att_set_value(sample128_env.sample128_shdl + SAMPLE128_2_IDX_VAL,
                             sizeof(uint8_t), (uint8_t *)&param->val);

        if((sample128_env.feature & PRF_CLI_START_NTF))
            // Send notification through GATT
            prf_server_send_event((prf_env_struct *)&sample128_env, false,
                    sample128_env.sample128_shdl + SAMPLE128_2_IDX_VAL);
        
    }
    else
    {
        status = PRF_ERR_INVALID_PARAM;
    }

    if (status != PRF_ERR_OK)
    {
        sample128_upd_char2_cfm_send(status);
    }

    return (KE_MSG_CONSUMED);
}
Exemple #3
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref ACCEL_VALUE_REQ 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 accel_value_req_handler(ke_msg_id_t const msgid,
                                   struct accel_value_req const *param,
                                   ke_task_id_t const dest_id,
                                   ke_task_id_t const src_id)
{
//    uint16_t len;
//    uint16_t* axis_en;
//    uint8_t* axis_val;

    // Check if acceleration changed on each axis and notify it if required
    for (int i = 0; i < ACCEL_MAX; i++)
    {
        //attmdb_att_get_value(ACCEL_DIR_VAL_HANDLE(i), &(len), (uint8_t**)&(axis_val));	////gsx
        //attmdb_att_get_value(ACCEL_DIR_EN_HANDLE(i), &(len), (uint8_t**)&(axis_en));	////gsx

        //if ((*axis_en) && (param->accel[i] != *axis_val))	////gsx
        {
            // Update the value in the attribute database
            attmdb_att_set_value(ACCEL_DIR_VAL_HANDLE(i),   sizeof(uint16_t), (uint8_t*) &(param->accel[i]));//gsx  sizeof(uint8_t), (uint8_t*) &(param->accel[i]

            // Send notification
            prf_server_send_event((prf_env_struct *)&accel_env, false, ACCEL_DIR_VAL_HANDLE(i));

        }
    }

    return (KE_MSG_CONSUMED);
}
Exemple #4
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref TIPS_UPD_CURR_TIME_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 tips_upd_curr_time_req_handler(ke_msg_id_t const msgid,
                                          struct tips_upd_curr_time_req const *param,
                                          ke_task_id_t const dest_id,
                                          ke_task_id_t const src_id)
{
    // Packed Current Time value
    uint8_t pckd_time[CTS_CURRENT_TIME_VAL_LEN];
    // Status
    uint8_t status = PRF_ERR_INVALID_PARAM;

    // Get the address of the environment
    struct tips_idx_env_tag *tips_idx_env = PRF_CLIENT_GET_ENV(dest_id, tips_idx);

    if (param->conhdl == gapc_get_conhdl(tips_idx_env->con_info.conidx))
    {
        // Pack the Current Time value
        tips_pack_curr_time_value(&pckd_time[0], &param->current_time);
        // Set the value in the database
        status = attmdb_att_set_value(tips_env.cts_shdl + CTS_IDX_CURRENT_TIME_VAL,
                                      CTS_CURRENT_TIME_VAL_LEN, (uint8_t *)&pckd_time[0]);

        //Check if Notifications are enabled
        if ((tips_idx_env->ntf_state & TIPS_CTS_CURRENT_TIME_CFG) == TIPS_CTS_CURRENT_TIME_CFG)
        {
            //Check if notification can be sent
            if ((param->current_time.adjust_reason & TIPS_FLAG_EXT_TIME_UPDATE) == TIPS_FLAG_EXT_TIME_UPDATE)
            {
                if (param->enable_ntf_send == 0)
                {
                    status = PRF_ERR_REQ_DISALLOWED;
                }
            }

            if (status == PRF_ERR_OK)
            {
                // The notification can be sent, send the notification
                prf_server_send_event((prf_env_struct *)tips_idx_env, false,
                                      tips_env.cts_shdl + CTS_IDX_CURRENT_TIME_VAL);
            }
        }
        else
        {
            status = PRF_ERR_NTF_DISABLED;
        }
    }

    if (status != PRF_ERR_OK)
    {
        // Wrong Connection Handle
        tips_error_ind_send(&(tips_idx_env->con_info), status, TIPS_UPD_CURR_TIME_REQ);
    }

    return (KE_MSG_CONSUMED);
}
int streamdatad_send_data_packets_req_handler(ke_msg_id_t const msgid,
                                   struct streamdatad_send_data_packets_req const *param,
                                   ke_task_id_t const dest_id,
                                   ke_task_id_t const src_id)
{
	uint16_t next_packet;
	uint16_t nr_packets;
    uint16_t* packet_buffer_enabled;
    uint16_t len = 0;

	if (!streamdatad_env.stream_enabled) return KE_MSG_CONSUMED; 

	next_packet = 0;
	nr_packets = param->nr_packets;

    nb_buf_av = l2cm_get_nb_buffer_available();
    
    for (int li = 0; (li < STREAMDATAD_MAX) && (nr_packets > 0) && (nb_buf_av > 0); li++)
	{		
        packet_buffer_enabled = NULL;
        attmdb_att_get_value(STREAMDATAD_DIR_EN_HANDLE(streamdatad_env.next_attribute_idx), &(len), (uint8_t**)&(packet_buffer_enabled));
        
        if ((packet_buffer_enabled && (*packet_buffer_enabled)))
        {        
            // Update the value in the attribute database
            attmdb_att_set_value(STREAMDATAD_DIR_VAL_HANDLE(streamdatad_env.next_attribute_idx), sizeof(uint8_t) * STREAMDATAD_PACKET_SIZE, (uint8_t*) &(param->packets[next_packet][0]));

            // Send notification
            prf_server_send_event((prf_env_struct *)&(streamdatad_env.con_info), false, STREAMDATAD_DIR_VAL_HANDLE(streamdatad_env.next_attribute_idx));
        }
        else
        {
            len = 2;
        }
        
        //set_pxact_gpio();
        next_packet++; nr_packets--;
        nb_buf_av--;
        
        streamdatad_env.next_attribute_idx++; 
        if (streamdatad_env.next_attribute_idx >= STREAMDATAD_MAX) {
            
            streamdatad_env.next_attribute_idx = 0;
            break; // the for loop
        }
        
		// else notification at this index was not enabled;
    }
    //set_pxact_gpio();
    return (KE_MSG_CONSUMED);
}
Exemple #6
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref HRPS_MEAS_SEND_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 hrps_meas_send_req_handler(ke_msg_id_t const msgid,
                                      struct hrps_meas_send_req const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    // Status
    uint8_t status = PRF_ERR_OK;
    // Packed Heart Measurement Value
    uint8_t packed_hr[HRPS_HT_MEAS_MAX_LEN];
    // Packet size
    uint8_t size;

    if((param->conhdl == gapc_get_conhdl(hrps_env.con_info.conidx))
            && (param->meas_val.nb_rr_interval <= HRS_MAX_RR_INTERVAL))
    {
        //Pack the HR Measurement value
        size = hrps_pack_meas_value(&packed_hr[0], &param->meas_val);

        // Check if notifications are enabled
        if(HRPS_IS_SUPPORTED(HRPS_HR_MEAS_NTF_CFG))
        {
            //Update value in DB
            attmdb_att_set_value(hrps_env.shdl + HRS_IDX_HR_MEAS_VAL,
                                 size, &packed_hr[0]);

            //send notification through GATT
            prf_server_send_event((prf_env_struct *)&hrps_env, false,
                    hrps_env.shdl + HRS_IDX_HR_MEAS_VAL);
        }
        //notification not enabled, simply don't send anything
        else
        {
            status = PRF_ERR_NTF_DISABLED;
        }
    }
    else
    {
        status = PRF_ERR_INVALID_PARAM;
    }

    if (status != PRF_ERR_OK)
    {
        // Value has not been sent
        hrps_meas_send_cfm_send(status);
    }

    return (KE_MSG_CONSUMED);
}
Exemple #7
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref BAPS_BATT_LEVEL_SEND_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 bass_batt_level_upd_req_handler(ke_msg_id_t const msgid,
                                            struct bass_batt_level_upd_req const *param,
                                            ke_task_id_t const dest_id,
                                            ke_task_id_t const src_id)
{
    uint8_t status = PRF_ERR_OK;

    // Check provided values
    if((param->conhdl == gapc_get_conhdl(bass_env.con_info.conidx)) &&
       (param->bas_instance < bass_env.bas_nb)     &&
       (param->batt_level <= BAS_BATTERY_LVL_MAX))
    {
        // Update Battery Level value in DB
        attmdb_att_set_value(bass_env.shdl[param->bas_instance] + BAS_IDX_BATT_LVL_VAL,
                             sizeof(uint8_t), (uint8_t *)&param->batt_level);

        // Check if notifications are enabled
        if((bass_env.features[param->bas_instance] & BASS_FLAG_NTF_CFG_BIT)
                                                  == BASS_FLAG_NTF_CFG_BIT)
        {
            // Send notification through GATT
            prf_server_send_event((prf_env_struct *)&bass_env, false,
                    bass_env.shdl[param->bas_instance] + BAS_IDX_BATT_LVL_VAL);
        }
        else
        {
            status = PRF_ERR_NTF_DISABLED;
        }
    }
    else
    {
        status = PRF_ERR_INVALID_PARAM;
    }

    if (status != PRF_ERR_OK)
    {
        bass_batt_level_upd_cfm_send(status);
    }

    return (KE_MSG_CONSUMED);
}
Exemple #8
0
void cpps_send_rsp_ind(uint16_t handle, uint8_t req_op_code, uint8_t status)
{
    // Error response
    uint8_t rsp[CPP_CP_CNTL_PT_RSP_MIN_LEN];

    // Response Code
    rsp[0] = CPP_CTNL_PT_RSP_CODE;
    // Request Operation Code
    rsp[1] = req_op_code;
    // Response value
    rsp[2] = status;

    // Set the value in the database - If we are here the handle is valid
    attmdb_att_set_value(handle, 3, (uint8_t *)&rsp);

    // Send an indication
    prf_server_send_event((prf_env_struct *)&cpps_env, true, handle);

    // Wait for Confirm
    ke_state_set(TASK_CPPS, CPPS_WAIT_FOR_CFM);
}
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref HPSS_HTTP_SEND_STATUS_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 hpss_status_code_send_req_handler(ke_msg_id_t const msgid,
        struct hpss_status_code_send_req const *param,
        ke_task_id_t const dest_id,
        ke_task_id_t const src_id)
{
    // Status
    uint8_t status = PRF_ERR_OK;

    if(param->conhdl == gapc_get_conhdl(hpss_env.con_info.conidx))
    {
//fix me
        // Check if notifications are enabled
        if(HPSS_IS_SUPPORTED(HPSS_STATUS_CODE_NTF_CFG))
        {
            //Update value in DB
            attmdb_att_set_value(hpss_env.hps_shdl + HPS_IDX_STATUS_CODE_VAL,
                                 HPS_STATUS_CODE_LEN, (uint8_t *)&param->status_code);//fix me, LSB?

            //send notification through GATT
            prf_server_send_event((prf_env_struct *)&hpss_env, false,
                                  hpss_env.hps_shdl + HPS_IDX_STATUS_CODE_VAL);
        }
        //notification not enabled, simply don't send anything
        else
        {
            status = PRF_ERR_NTF_DISABLED;
        }
    }
    else
    {
        status = PRF_ERR_INVALID_PARAM;
    }

    if (status != PRF_ERR_OK)
    {
        // Value has not been sent
        hpss_status_code_send_cfm_send(status);
    }
    return (KE_MSG_CONSUMED);
}
Exemple #10
0
int streamdatad_send_data_packet(uint8_t *data)
{
    uint16_t* packet_buffer_enabled;
	int retval = 0;
    uint16_t len = 0;
	packet_buffer_enabled = NULL;
	attmdb_att_get_value(STREAMDATAD_DIR_EN_HANDLE(streamdatad_env.next_attribute_idx), &(len), (uint8_t**)&(packet_buffer_enabled));

	if ((packet_buffer_enabled && (*packet_buffer_enabled)))
	{        
        // Update the value in the attribute database
        attmdb_att_set_value(STREAMDATAD_DIR_VAL_HANDLE(streamdatad_env.next_attribute_idx), sizeof(uint8_t) * STREAMDATAD_PACKET_SIZE, data);

        // Send notification
        prf_server_send_event((prf_env_struct *)&(streamdatad_env.con_info), false, STREAMDATAD_DIR_VAL_HANDLE(streamdatad_env.next_attribute_idx));
        
		retval = 1;
	}

	streamdatad_env.next_attribute_idx++; if (streamdatad_env.next_attribute_idx >= STREAMDATAD_MAX) streamdatad_env.next_attribute_idx = 0;
	return retval;
}
Exemple #11
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref HTPT_TEMP_UPD_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 htpt_temp_send_req_handler(ke_msg_id_t const msgid,
                                      struct htpt_temp_send_req const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    // Packed Temperature Measurement value
    uint8_t packed_temp[HTPT_TEMP_MEAS_MAX_LEN];
    // Status
    uint8_t status = PRF_ERR_OK;
    // Packet size
    uint8_t size;

    if(param->conhdl == gapc_get_conhdl(htpt_env.con_info.conidx))
    {
        //Pack the temperature measurement value
        size = htpt_pack_temp_value(&packed_temp[0], param->temp_meas);

        //Intermediate Measurement, must be notified if enabled
        if(param->flag_stable_meas == 0x00)
        {
            //Check if Intermediate Measurement Char. is supported
            if (htpt_env.att_tbl[HTPT_INTERM_TEMP_CHAR] != 0x00)
            {
                //Check if notifications are enabled
                if((htpt_env.features & HTPT_MASK_INTM_MEAS_CFG) == HTPT_MASK_INTM_MEAS_CFG)
                {
                    attmdb_att_set_value(htpt_env.shdl + htpt_env.att_tbl[HTPT_INTERM_TEMP_CHAR] + 1,
                                         size, &packed_temp[0]);

                    //Send notification through GATT
                    prf_server_send_event((prf_env_struct *)&htpt_env, false,
                            htpt_env.shdl + htpt_env.att_tbl[HTPT_INTERM_TEMP_CHAR] + 1);
                }
                else
                {
                    status = PRF_ERR_NTF_DISABLED;
                }
            }
            else
            {
                status = PRF_ERR_FEATURE_NOT_SUPPORTED;
            }
        }
        //Temperature Measurement, must be indicated if enabled
        else
        {
            if((htpt_env.features & HTPT_MASK_TEMP_MEAS_CFG) == HTPT_MASK_TEMP_MEAS_CFG)
            {
                attmdb_att_set_value(htpt_env.shdl + HTS_IDX_TEMP_MEAS_VAL, size, &packed_temp[0]);

                prf_server_send_event((prf_env_struct *)&htpt_env, true,
                        htpt_env.shdl + HTS_IDX_TEMP_MEAS_VAL);
            }
            else
            {
                status = PRF_ERR_IND_DISABLED;
            }
        }
    }
    else
    {
        //Wrong Connection Handle
        status = PRF_ERR_INVALID_PARAM;
    }

    if (status != PRF_ERR_OK)
    {
        /*
         * The cfm_type value is HTPT_CENTRAL_IND_CFM (1) if param->flag_stable_meas = 1,
         * HTPT_THERM_TEMP_SEND (0) if param->flag_stable_meas = 0
         */
        htpt_temp_send_cfm_send(status, param->flag_stable_meas);
    }

    return (KE_MSG_CONSUMED);
}
Exemple #12
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref PASPS_UPDATE_CHAR_VAL_REQ message.
 * @param[in] msgid Id of the message received.
 * @param[in] param Pointer to the parameters of the message.
 * @param[in] dest_id ID of the receiving task instance.
 * @param[in] src_id ID of the sending task instance.
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
static int pasps_update_char_val_cmd_handler(ke_msg_id_t const msgid,
                                             struct pasps_update_char_val_cmd *param,
                                             ke_task_id_t const dest_id,
                                             ke_task_id_t const src_id)
{
    // Status
    uint8_t status = PRF_ERR_INVALID_PARAM;
    // Message status
    uint8_t msg_status = KE_MSG_CONSUMED;
    // Get the address of the environment
    struct pasps_idx_env_tag *pasps_idx_env = PRF_CLIENT_GET_ENV(dest_id, pasps_idx);


    if (pasps_idx_env != NULL)
    {
        // Check the provided connection handle value
        if (pasps_idx_env->con_info.conidx != gapc_get_conidx(param->conhdl))
        {
            status = PRF_ERR_INVALID_PARAM;
        }
        else if (ke_state_get(dest_id) == PASPS_BUSY)
        {
            // Keep the message for later
            msg_status = KE_MSG_NO_FREE;
        }
        else
        {
            // Handle
            uint16_t handle;
            // Notification status flag
            uint8_t flag;

            ASSERT_ERR(ke_state_get(dest_id) == PASPS_CONNECTED);

            switch (param->operation)
            {
                // Alert Status Characteristic
                case (PASPS_UPD_ALERT_STATUS_OP_CODE):
                {
                    // Check the provided value
                    if (param->value <= PASP_ALERT_STATUS_VAL_MAX)
                    {
                        // Set the handle value
                        handle = pasps_env.pass_shdl + PASS_IDX_ALERT_STATUS_VAL;
                        // Set the flag
                        flag   = PASPS_FLAG_ALERT_STATUS_CFG;

                        status = PRF_ERR_OK;
                    }
                    // else status is PRF_ERR_INVALID_PARAM
                } break;

                // Ringer Setting Characteristic
                case (PASPS_UPD_RINGER_SETTING_OP_CODE):
                {
                    // Check the provided value
                    if (param->value <= PASP_RINGER_NORMAL)
                    {
                        // Set the handle value
                        handle = pasps_env.pass_shdl + PASS_IDX_RINGER_SETTING_VAL;
                        // Set the flag
                        flag   = PASPS_FLAG_RINGER_SETTING_CFG;

                        status = PRF_ERR_OK;

                        // Update the ringer state value
                        pasps_env.ringer_state = param->value;
                    }
                    // else status is PRF_ERR_INVALID_PARAM
                } break;

                default:
                {
                    // Nothing more to do, status is PRF_ERR_INVALID_PARAM
                } break;
            }

            if (status == PRF_ERR_OK)
            {
                // Set the value of the characteristic
                attmdb_att_set_value(handle, sizeof(uint8_t), (uint8_t *)&param->value);

                // Check if sending of notifications is enabled for this connection
                if (PASPS_IS_NTF_ENABLED(pasps_idx_env, flag))
                {
                    // Configure the environment for the operation
                    pasps_idx_env->operation = param->operation;
                    // Go to the Busy state
                    ke_state_set(dest_id, PASPS_BUSY);

                    // The notification can be sent, send the notification
                    prf_server_send_event((prf_env_struct *)pasps_idx_env, false, handle);
                }
                else
                {
                    status = PRF_ERR_NTF_DISABLED;
                }
            }
        }

        // If the status is not OK, no notification has been sent
        if (status != PRF_ERR_OK)
        {
            // Send response to application
            pasps_send_cmp_evt(pasps_idx_env->con_info.prf_id, pasps_idx_env->con_info.appid,
                               param->conhdl,
                               param->operation, status);
        }
    }
    else
    {
        // Send response to application
        pasps_send_cmp_evt(dest_id, src_id, param->conhdl, param->operation, PRF_ERR_REQ_DISALLOWED);
    }

    return (int)msg_status;
}
Exemple #13
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);
}
Exemple #14
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref ANPS_NTF_ALERT_CMD message.
 * @param[in] msgid Id of the message received.
 * @param[in] param Pointer to the parameters of the message.
 * @param[in] dest_id ID of the receiving task instance.
 * @param[in] src_id ID of the sending task instance.
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
static int anps_ntf_alert_cmd_handler(ke_msg_id_t const msgid,
                                      struct anps_ntf_alert_cmd const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{

    // Message Status
    uint8_t msg_status = KE_MSG_CONSUMED;
    // Task environment
    struct anps_idx_env_tag *anps_idx_env = PRF_CLIENT_GET_ENV(dest_id, anps_idx);

    if (anps_idx_env != NULL)
    {
        // Status
        uint8_t status     = PRF_ERR_OK;
        // Category ID
        uint8_t cat_id;
        // Is the category supported ?
        bool cat_supported;
        // Handle
        uint16_t handle;

        do
        {
            // Check the provided connection handle value
            if (anps_idx_env->con_info.conidx != gapc_get_conidx(param->conhdl))
            {
                status = PRF_ERR_INVALID_PARAM;
                break;
            }

            if (ke_state_get(dest_id) == ANPS_BUSY)
            {
                // The message will be handled once the current operation is over
                msg_status = KE_MSG_NO_FREE;
                break;
            }

            ASSERT_ERR(ke_state_get(dest_id) == ANPS_CONNECTED);

            // Check the operation code, get the category ID.
            if (param->operation == ANPS_UPD_NEW_ALERT_OP_CODE)
            {
                // Check the length of the string info value
                if (param->value.new_alert.info_str_len > ANS_NEW_ALERT_STRING_INFO_MAX_LEN)
                {
                    status = PRF_ERR_INVALID_PARAM;
                    break;
                }

                // Get the category ID
                cat_id = param->value.new_alert.cat_id;
                // Check if the category is supported
                cat_supported = ANPS_IS_NEW_ALERT_CATEGORY_SUPPORTED(cat_id);
            }
            else if (param->operation == ANPS_UPD_UNREAD_ALERT_STATUS_OP_CODE)
            {
                // Get the category ID
                cat_id = param->value.unread_alert_status.cat_id;
                // Check if the category is supported
                cat_supported = ANPS_IS_UNREAD_ALERT_CATEGORY_SUPPORTED(cat_id);
            }
            else
            {
                status = PRF_ERR_INVALID_PARAM;
                break;
            }

            // Check the category ID
            if ((cat_id >= CAT_ID_NB) || (!cat_supported))
            {
                status = PRF_ERR_INVALID_PARAM;
                break;
            }

            if (param->operation == ANPS_UPD_NEW_ALERT_OP_CODE)
            {
                // Check if sending of notification is enabled for the provided category
                if (ANPS_IS_NEW_ALERT_CATEGORY_ENABLED(cat_id, anps_idx_env) &&
                    ANPS_IS_ALERT_ENABLED(anps_idx_env, ANP_NEW_ALERT))
                {
                    handle = anps_env.ans_shdl + ANS_IDX_NEW_ALERT_VAL;

                    // Notification can be sent, set the value in the database
                    attmdb_att_set_value(handle, 2 + param->value.new_alert.info_str_len,
                                         (uint8_t *)&param->value.new_alert.cat_id);
                }
                else
                {
                    status = PRF_ERR_NTF_DISABLED;
                    break;
                }
            }
            else
            {
                if (ANPS_IS_UNREAD_ALERT_CATEGORY_ENABLED(cat_id, anps_idx_env) &&
                    ANPS_IS_ALERT_ENABLED(anps_idx_env, ANP_UNREAD_ALERT))
                {
                    handle = anps_env.ans_shdl + ANS_IDX_UNREAD_ALERT_STATUS_VAL;

                    attmdb_att_set_value(handle, sizeof(struct anp_unread_alert),
                                         (uint8_t *)&param->value.unread_alert_status);
                }
                else
                {
                    status = PRF_ERR_NTF_DISABLED;
                    break;
                }
            }

            // Configure the environment
            anps_idx_env->operation = param->operation;

            // The notification can be sent, send the notification
            prf_server_send_event((prf_env_struct *)anps_idx_env, false, handle);

            // Go to Busy state
            ke_state_set(dest_id, ANPS_BUSY);
        } while (0);

        if (status != PRF_ERR_OK)
        {
            // Send response to application
            anps_send_cmp_evt(anps_idx_env->con_info.prf_id, anps_idx_env->con_info.appid,
                              gapc_get_conhdl(anps_idx_env->con_info.conidx),
                              param->operation, status);
        }
    }
    else
    {
        // Send response to application
        anps_send_cmp_evt(dest_id, src_id, param->conhdl, param->operation, PRF_ERR_REQ_DISALLOWED);
    }

    return (int)msg_status;
}
Exemple #15
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GLPS_MEAS_SEND_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 glps_meas_send_req_handler(ke_msg_id_t const msgid,
                                      struct glps_send_meas_with_ctx_req 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 == gapc_get_conhdl(glps_env.con_info.conidx))
    {
        // device already sending a measurement
        if(GLPS_IS(SENDING_MEAS))
        {
            //Cannot send another measurement in parallel
            status = (PRF_ERR_REQ_DISALLOWED);
        }
        else
        {
            // inform that device is sending a measurement
            GLPS_SET(SENDING_MEAS);


            // check if context is supported
            if((msgid == GLPS_SEND_MEAS_WITH_CTX_REQ) && !(GLPS_IS(MEAS_CTX_SUPPORTED)))
            {
                // Context not supported
                status = (PRF_ERR_FEATURE_NOT_SUPPORTED);
            }
            // check if notifications enabled
            else if(((glps_env.evt_cfg & GLPS_MEAS_NTF_CFG) == 0)
                    || (((glps_env.evt_cfg & GLPS_MEAS_CTX_NTF_CFG) == 0)
                        && (msgid == GLPS_SEND_MEAS_WITH_CTX_REQ)))
            {
                // Not allowed to send measurement if Notifications not enabled.
                status = (PRF_ERR_NTF_DISABLED);

            }
            else
            {
                struct attm_elmt * attm_elmt;

                // retrieve value pointer in database
                attm_elmt = attmdb_get_attribute(GLPS_HANDLE(GLS_IDX_MEAS_VAL));

                // pack measured value in database
                attm_elmt->length = glps_pack_meas_value(attm_elmt->value, &(param->meas),
                        param->seq_num);

                prf_server_send_event((prf_env_struct *)&glps_env, false,
                        GLPS_HANDLE(GLS_IDX_MEAS_VAL));

                // Measurement value notification not yet sent
                GLPS_CLEAR(MEAS_SENT);

                if(msgid == GLPS_SEND_MEAS_WITH_CTX_REQ)
                {
                    // 2 notification complete messages expected
                    GLPS_SET(MEAS_CTX_SENT);

                    // retrieve value pointer in database
                    attm_elmt = attmdb_get_attribute(GLPS_HANDLE(GLS_IDX_MEAS_CTX_VAL));

                    // pack measured value in database
                    attm_elmt->length = glps_pack_meas_ctx_value(attm_elmt->value,
                                                            &(param->ctx), param->seq_num);

                    prf_server_send_event((prf_env_struct *)&glps_env, false,
                            GLPS_HANDLE(GLS_IDX_MEAS_CTX_VAL));
                }
                else
                {
                    // 1 notification complete messages expected
                    GLPS_CLEAR(MEAS_CTX_SENT);
                }
            }
        }
    }
    else
    {
        //Wrong Connection Handle
        status = (PRF_ERR_INVALID_PARAM);
    }

    // send command complete if an error occurs
    if(status != PRF_ERR_OK)
    {
        // allow to send other measurements
        GLPS_CLEAR(SENDING_MEAS);

        // send completed information to APP task that contains error status
        struct glps_req_cmp_evt * cmp_evt = KE_MSG_ALLOC(GLPS_REQ_CMP_EVT, glps_env.con_info.appid,
                TASK_GLPS, glps_req_cmp_evt);

        cmp_evt->conhdl     = param->conhdl;
        cmp_evt->request    = GLPS_SEND_MEAS_REQ_NTF_CMP;
        cmp_evt->status     = status;

        ke_msg_send(cmp_evt);
    }

    return (KE_MSG_CONSUMED);
}