Exemple #1
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));
        attmdb_att_get_value(ACCEL_DIR_EN_HANDLE(i), &(len), (uint8_t**)&(axis_en));

        if ((*axis_en) && (param->accel[i] != *axis_val))
        {
            // Update the value in the attribute database
            attmdb_att_set_value(ACCEL_DIR_VAL_HANDLE(i),   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 #2
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);
}
Exemple #3
0
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);
}
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);
}
void app_param_update_func(void)
{
#if 1 
    int temp=4;    
    uint8_t *temp_v;

    attmdb_att_get_value(ACCEL_HANDLE(ACCEL_IDX_ACCEL_X_EN), &(temp), &(temp_v));
    if(temp_v[1] > 1)
        accel_con_interval = temp_v[1]-1;
    if(accel_con_interval < 2 || accel_con_interval > 500)
        return;
    
    // Send a param update request
    struct gapc_param_update_cmd *cmd = KE_MSG_ALLOC(GAPC_PARAM_UPDATE_CMD,
            KE_BUILD_ID(TASK_GAPC, app_env.conidx), TASK_APP,
            gapc_param_update_cmd);

    // Fill up parameters
    cmd->operation = GAPC_UPDATE_PARAMS;
#if 0
    cmd->params.intv_min = 70;         // 10ms (8*1.25ms)
    cmd->params.intv_max = 80;        // 20ms (16*1.25ms)
    cmd->params.latency  = 0;
//GZ    cmd->params.time_out = 100;
    cmd->params.time_out = 320;
#endif
    
    cmd->params.intv_min = (accel_con_interval-1)*10/1.25;
    cmd->params.intv_max = (accel_con_interval)*10/1.25;
    cmd->params.latency = 0;
    if(accel_con_interval < 30)
        cmd->params.time_out = accel_con_interval*32;
    else
        cmd->params.time_out = 10000;
        
    // Send message
    ke_msg_send(cmd);

//GZ tmp
rwip_env.sleep_enable = false;
    
    // Go to Param update state
    ke_state_set(TASK_APP, APP_PARAM_UPD);
#endif

    return;
}
Exemple #6
0
void bass_disable(uint16_t conhdl) 
{
#ifndef USE_ONE_BAS_INSTANCE
    // Counter
    uint8_t i;
#endif    
    // Information get in the DB
    att_size_t att_length;
    uint8_t *att_value;

    // Send current configuration to the application
    struct bass_disable_ind *ind = KE_MSG_ALLOC(BASS_DISABLE_IND,
                                                bass_env.con_info.appid, TASK_BASS,
                                                bass_disable_ind);

    ind->conhdl = conhdl;

#ifndef USE_ONE_BAS_INSTANCE
    for (i = 0; i < bass_env.bas_nb; i++)
#else
    const int i = 0;
#endif    
    {
        if((bass_env.features[i] & BASS_FLAG_NTF_CFG_BIT)
                                 == BASS_FLAG_NTF_CFG_BIT)
        {
            ind->batt_level_ntf_cfg[i] = PRF_CLI_START_NTF;

            // Reset ntf cfg bit in features
            bass_env.features[i] &= ~BASS_FLAG_NTF_CFG_BIT;
        }
        else
        {
            ind->batt_level_ntf_cfg[i] = PRF_CLI_STOP_NTFIND;
        }

        // Get Battery Level value
        attmdb_att_get_value(bass_env.shdl[i] + BAS_IDX_BATT_LVL_VAL,
                             &att_length, &att_value);
        ind->batt_lvl[i] = *att_value;
    }

    ke_msg_send(ind);

    // Go to idle state
    ke_state_set(TASK_BASS, BASS_IDLE);
}
Exemple #7
0
void streamdatad_streamonoff(void)
{
    uint16_t len = 0;
    uint8_t* streamdatad_en = NULL;

    attmdb_att_get_value(STREAMDATAD_HANDLE(STREAMDATAD_IDX_ENABLE_VAL), &(len), &(streamdatad_en));


    // Indicate to the application the state of the profile
    int on = ((len == 2) && (streamdatad_en && (*streamdatad_en))) ? 1 : 0;

    if (on)
    {
        // Allocate the start indication message
        struct streamdatad_start_ind *ind = KE_MSG_ALLOC(STREAMDATAD_START_IND,
                                            streamdatad_env.appid, TASK_STREAMDATAD,
                                            streamdatad_start_ind);
        streamdatad_env.stream_enabled = (*streamdatad_en);
        ind->status = PRF_ERR_OK;
        // Send the message
        ke_msg_send(ind);
    }
    else
    {
        streamdatad_env.next_attribute_idx = 0;
        streamdatad_env.stream_enabled = 0;

        // Send the stop indication
        ke_msg_send_basic(STREAMDATAD_STOP_IND, streamdatad_env.appid, TASK_STREAMDATAD);
    }

    uint16_t enable_val = streamdatad_en?(*streamdatad_en):0;
    // Enable or disable all data notifications
    streamdatad_env.nr_enabled_attributes = 0;
    int lastattr = enable_val?((STREAMDATAD_MAX>MAX_TRANSMIT_BUFFER_PACKETS)?MAX_TRANSMIT_BUFFER_PACKETS:STREAMDATAD_MAX):STREAMDATAD_MAX;

    attmdb_att_set_value(STREAMDATAD_IDX_ENABLE_EN, sizeof(uint16_t),(uint8_t*) &(enable_val));
    for (int i = 0; i < lastattr; i++)
    {
        attmdb_att_set_value(STREAMDATAD_DIR_EN_HANDLE(i), sizeof(uint16_t),(uint8_t*) &(enable_val));
        streamdatad_env.nr_enabled_attributes++;
    }
    if (!enable_val) streamdatad_env.nr_enabled_attributes = 0;
}
Exemple #8
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;
}
void app_custom_connection(struct gapc_connection_req_ind const *param)
{
#if BLE_ACCEL
    int temp=4;
    uint8_t *temp_v;
    
    app_accel_adv_stopped();
    
    if (!param->con_latency)
    {
        // Not completely verified, but this improves the stability of the connection.
        
        struct gapc_param_update_req_ind * req = KE_MSG_ALLOC(GAPC_PARAM_UPDATE_REQ_IND, TASK_GAPC, TASK_APP, gapc_param_update_req_ind);

        // Fill in the parameter structure
        //req->conhdl = param->conn_info.conhdl;
        //GZ req->conn_par.intv_min = param->conn_info.con_interval;
        //GZ req->conn_par.intv_max = param->conn_info.con_interval;
        attmdb_att_get_value(ACCEL_HANDLE(ACCEL_IDX_ACCEL_X_EN), &(temp), &(temp_v));
        if(temp_v[1] > 1)
            accel_con_interval = temp_v[1];
        
        req->params.intv_min = (accel_con_interval-1)*10/1.25;
        req->params.intv_max = (accel_con_interval)*10/1.25;
        req->params.latency = param->con_latency;
        if(param->sup_to * 8 / 1.25 <= 3200)
            req->params.time_out = param->sup_to * 8 / 1.25;
        else
            req->params.time_out = 3200/1.25;
    #if BLE_HID_DEVICE
        puts("Send GAP_PARAM_UPDATE_REQ");
    #endif
        ke_msg_send(req);
    }    
#endif
}
Exemple #10
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GL2C_CODE_ATT_WR_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 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 *meas_intv_range;
    uint16_t meas_intv_rge[2];

    uint16_t value = 0x0000;
    uint8_t status = PRF_ERR_OK;
    uint8_t char_code = 0;

    if (KE_IDX_GET(src_id) == htpt_env.con_info.conidx)
    {
        //Extract value before check
        memcpy(&value, &(param->value), sizeof(uint16_t));

        //Measurement Interval Char. - Value
        if (param->handle == (htpt_env.shdl + htpt_env.att_tbl[HTPT_MEAS_INTV_CHAR] + 1))
        {
            /*
             * Get Measurement Interval range in database
             * Valid Range descriptor exists because measurement interval is writable
             */
            attmdb_att_get_value(param->handle + htpt_get_valid_rge_offset(), &meas_intv_rge[0], &meas_intv_range);

            memcpy(&meas_intv_rge[0], meas_intv_range, sizeof(uint16_t));
            memcpy(&meas_intv_rge[1], meas_intv_range + 2, sizeof(uint16_t));

            //Check if value to write is in allowed range
            if (((value >= meas_intv_rge[0]) && (value <= meas_intv_rge[1])) || (value == 0))
            {
                //Send APP the indication with the new value
                struct htpt_meas_intv_chg_ind * ind = KE_MSG_ALLOC(HTPT_MEAS_INTV_CHG_IND,
                                                                   htpt_env.con_info.appid, TASK_HTPT,
                                                                   htpt_meas_intv_chg_ind);

                memcpy(&ind->intv, &value, sizeof(uint16_t));

                ke_msg_send(ind);
            }
            else
            {
                status = HTPT_OUT_OF_RANGE_ERR_CODE;
            }
        }
        else
        {
            //Temperature Measurement Char. - Client Char. Configuration
            if (param->handle == (htpt_env.shdl + HTS_IDX_TEMP_MEAS_IND_CFG))
            {
                char_code = HTPT_TEMP_MEAS_CHAR;

                if (value == PRF_CLI_STOP_NTFIND)
                {
                    htpt_env.features &= ~HTPT_MASK_TEMP_MEAS_CFG;
                }
                else if (value == PRF_CLI_START_IND)
                {
                    htpt_env.features |= HTPT_MASK_TEMP_MEAS_CFG;
                }
                else
                {
                    //Invalid value
                    status = HTPT_OUT_OF_RANGE_ERR_CODE;
                }
            }
            //Measurement Interval Char. - Client Char. Configuration
            else if (param->handle == (htpt_env.shdl + htpt_env.att_tbl[HTPT_MEAS_INTV_CHAR] + 2))
            {
                char_code = HTPT_MEAS_INTV_CHAR;

                if (value == PRF_CLI_STOP_NTFIND)
                {
                    htpt_env.features &= ~HTPT_MASK_MEAS_INTV_CFG;
                }
                else if (value == PRF_CLI_START_IND)
                {
                    htpt_env.features |= HTPT_MASK_MEAS_INTV_CFG;
                }
                else
                {
                    //Invalid value
                    status = HTPT_OUT_OF_RANGE_ERR_CODE;
                }
            }
            //Intermediate Measurement Char. - Client Char. Configuration
            else if (param->handle == (htpt_env.shdl + htpt_env.att_tbl[HTPT_INTERM_TEMP_CHAR] + 2))
            {
                char_code = HTPT_INTERM_TEMP_CHAR;

                if (value == PRF_CLI_STOP_NTFIND)
                {
                    htpt_env.features &= ~HTPT_MASK_INTM_MEAS_CFG;
                }
                else if (value == PRF_CLI_START_NTF)
                {
                    htpt_env.features |= HTPT_MASK_INTM_MEAS_CFG;
                }
                else
                {
                    //Invalid value
                    status = HTPT_OUT_OF_RANGE_ERR_CODE;
                }
            }

            if (status == PRF_ERR_OK)
            {
                if(param->last)
                {
                    //Inform APP of configuration change
                    struct htpt_cfg_indntf_ind * ind = KE_MSG_ALLOC(HTPT_CFG_INDNTF_IND,
                                                                    htpt_env.con_info.appid, TASK_HTPT,
                                                                    htpt_cfg_indntf_ind);

                    ind->conhdl = gapc_get_conhdl(htpt_env.con_info.conidx);
                    ind->char_code = char_code;
                    memcpy(&ind->cfg_val, &value, sizeof(uint16_t));

                    ke_msg_send(ind);
                }
            }
        }

        if (status == PRF_ERR_OK)
        {
            //Update the attribute value
            attmdb_att_set_value(param->handle, sizeof(uint16_t), (uint8_t *)&value);
        }

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

    return (KE_MSG_CONSUMED);
}
Exemple #11
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GL2C_CODE_ATT_WR_CMD_IND message.
 * The handler will analyse what has been set and decide alert level
 * @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 = UDSS_ERR_CHAR;
    uint8_t status = PRF_APP_ERROR;

    if (KE_IDX_GET(src_id) == udss_env.con_info.conidx)
    {
//        uint8_t att_idx = GLPS_IDX(param->handle);
        status = PRF_ERR_OK;

        if (param->handle == udss_env.shdl + UDS_IDX_USER_HEIGHT_VAL)
        {
            char_code = UDSS_USER_HEIGHT_CHAR;
            //Set User Height to specified value
            attmdb_att_set_value(udss_env.shdl + UDS_IDX_USER_HEIGHT_VAL,
                             sizeof(uint8_t), (uint8_t *)&param->value[0]);
        }
        else if (param->handle == udss_env.shdl + UDS_IDX_USER_AGE_VAL)
        {
            char_code = UDSS_USER_AGE_CHAR;
            //Set User Age to specified value
            attmdb_att_set_value(udss_env.shdl + UDS_IDX_USER_AGE_VAL,
                                 sizeof(uint8_t), (uint8_t *)&param->value[0]);
        }
        else if (param->handle == udss_env.shdl + UDS_IDX_USER_DATE_OF_BIRTH_VAL)
        {
            char_code = UDSS_USER_DATE_OF_BIRTH_CHAR;
            //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->value[0]);
        }
        else if (param->handle == udss_env.shdl + UDS_IDX_USER_DB_CHANGE_INCR_VAL)
        {
            char_code = UDSS_USER_DB_CHANGE_INCR_CHAR;
            //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->value[0]);
        }
        else if (param->handle == udss_env.shdl + UDS_IDX_USER_CTRL_POINT_VAL)
        {
            uint8_t reqstatus;
            uint8_t* value;
            uint16_t length;
            struct uds_ucp_req ucp_req;

            // Update the attribute value (note several write could be required since
            // attribute length > (ATT_MTU-3)
            attmdb_att_update_value(param->handle, param->length, param->offset,
                    (uint8_t*)&(param->value[0]));

            // retrieve full data.
            attmdb_att_get_value(param->handle, &length, &value);

            // unpack user control point value
            reqstatus = udss_unpack_ucp_req(value, length, &ucp_req);

            // check unpacked status
            switch(reqstatus)
            {
                case PRF_APP_ERROR:
                {
                    /* Do nothing, ignore request since it's not complete and maybe
                     * requires several peer write to be performed.
                     */
                }
                break;
                case PRF_ERR_OK:
                {
                    // check wich request shall be send to api task
                    switch(ucp_req.op_code)
                    {
                        case UDS_REQ_REG_NEW_USER:
                        case UDS_REQ_CONSENT:
                        case UDS_REQ_DEL_USER_DATA:
                        {
                            //forward request operation to application
                            struct udss_ucp_req_ind * req = KE_MSG_ALLOC(UDSS_UCP_REQ_IND,
                                    udss_env.con_info.appid, TASK_UDSS,
                                    udss_ucp_req_ind);

                            // UCP on going.
//                            UDSS_SET(UCP_ON_GOING);

                            req->conhdl = gapc_get_conhdl(udss_env.con_info.conidx);
                            req->ucp_req = ucp_req;

                            ke_msg_send(req);
                        }
                        break;
//                        case UDS_REQ_ABORT_OP:
//                        {
//                            // nothing to abort, send an error message.
//                            struct uds_ucp_rsp ucp_rsp;

//                            ucp_rsp.op_code = UDS_REQ_RSP_CODE;
//                            ucp_rsp.operand.rsp.op_code_req =
//                                    ucp_req.op_code;
//                            ucp_rsp.operand.rsp.status = UDS_RSP_ABORT_UNSUCCESSFUL;

//                            // send user control response indication
//                            udss_send_ucp_rsp(&(ucp_rsp),
//                                    TASK_UDSS);
//                        }
//                        break;
                        default:
                        {
                            // nothing to do since it's handled during unpack
                        }
                        break;
                    }
                }
                break;
                default:
                {
                    /* There is an error in user control request, inform peer
                     * device that request is incorrect. */
                    struct uds_ucp_rsp ucp_rsp;

                    ucp_rsp.op_code = UDS_REQ_RSP_CODE;
                    ucp_rsp.req_op_code = ucp_req.op_code;
                    ucp_rsp.rsp_val = reqstatus;

                    // send user control response indication
                    udss_send_ucp_rsp(&(ucp_rsp),
                            TASK_UDSS);
                }
                break;
            }
            
        }
        // not expected request
        else
        {
            status = ATT_ERR_WRITE_NOT_PERMITTED;
        }
    }
    
    if(param->response)
    {
        // Send Write Response
        atts_write_rsp_send(udss_env.con_info.conidx, param->handle, status);
    }

    return (KE_MSG_CONSUMED);
}
Exemple #12
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GL2C_CODE_ATT_WR_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 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)
{
    // Update the attribute value
    attmdb_att_update_value(param->handle, param->length, param->offset,
            (uint8_t*)&(param->value[0]));

    switch (ACCEL_IDX(param->handle))
    {
        case ACCEL_IDX_ENABLE_VAL:
        {
            uint16_t len;
            uint8_t* accel_en;
            uint8_t* axis_en;
            uint8_t* range;

            if(*(uint8_t*)&(param->value[0]) > 1)
                accel_threshold = *(uint8_t*)&(param->value[0]) - 2;
//            set_accel_thr();
                        
            attmdb_att_get_value(ACCEL_HANDLE(ACCEL_IDX_ENABLE_VAL), &(len), &(accel_en));

            // Indicate to the application the state of the profile
            if (accel_en)
            {
                // Allocate the start indication message
                struct accel_start_ind *ind = KE_MSG_ALLOC(ACCEL_START_IND,
                                                           accel_env.con_info.appid, dest_id,
                                                           accel_start_ind);

                // Fill in the parameter structure
                for (int i = 0; i < ACCEL_MAX; i++)
                {
                    attmdb_att_get_value(ACCEL_DIR_VAL_HANDLE(i), &(len), &(axis_en));

                    ind->accel_en[i] = *axis_en;
                }


                attmdb_att_get_value(ACCEL_HANDLE(ACCEL_IDX_RANGE_VAL), &(len), &(range));

                ind->range = *range;

                // Send the message
                ke_msg_send(ind);
            }
            else
            {
                // Send the stop indication
                ke_msg_send_basic(ACCEL_STOP_IND, accel_env.con_info.appid, TASK_ACCEL);
            }
        }
        break;

        case ACCEL_IDX_ACCEL_DISPLAY1_VAL:
        case ACCEL_IDX_ACCEL_DISPLAY2_VAL:            
            if(*(uint8_t*)&(param->value[0]) == 0xFF)
            {
                if(param->length > 1 && *(uint8_t*)&(param->value[1]) > 1)
					accel_con_interval = *(uint8_t*)&(param->value[1]);
                if(param->length > 2 && *(uint8_t*)&(param->value[2]) > 1)
					accel_mode = *(uint8_t*)&(param->value[2])-2;
				if(param->length > 3 && *(uint8_t*)&(param->value[3]) > 1)
					accel_latency = *(uint8_t*)&(param->value[3])-2;
				if(param->length > 4 && *(uint8_t*)&(param->value[4]) > 1)
					accel_window = *(uint8_t*)&(param->value[4]);
            }
        {
            uint8_t line;
            uint16_t len;
            uint8_t* display;

            struct accel_write_line_ind *ind = KE_MSG_ALLOC(ACCEL_WRITE_LINE_IND,
                                                            accel_env.con_info.appid, TASK_ACCEL,
                                                            accel_write_line_ind);
            line = (param->handle == ACCEL_HANDLE(ACCEL_IDX_ACCEL_DISPLAY1_VAL))?0:1;


            attmdb_att_get_value(param->handle, &(len), &(display));

            // Fill in the parameter structure
            memcpy(ind->text, display, len);
            ind->line = line;

            // Send the message
            ke_msg_send(ind);
        }
            atts_write_rsp_send(accel_env.con_info.conidx, param->handle, PRF_ERR_OK);
            break;        
        case ACCEL_IDX_ACCEL_X_VAL:
        case ACCEL_IDX_ACCEL_X_EN:
					if(*(uint8_t*)&(param->value[0]) > 1)
					accel_adv_interval1 = *(uint8_t*)&(param->value[0]);
						atts_write_rsp_send(accel_env.con_info.conidx, param->handle, PRF_ERR_OK);
            break;
        case ACCEL_IDX_ACCEL_Y_VAL:
        case ACCEL_IDX_ACCEL_Y_EN:
					if(*(uint8_t*)&(param->value[0]) > 1)
					accel_adv_interval2 = *(uint8_t*)&(param->value[0]);
					if(*(uint8_t*)&(param->value[0]) == 255)
					accel_adv_interval2 = 0;
						atts_write_rsp_send(accel_env.con_info.conidx, param->handle, PRF_ERR_OK);
            break;
        case ACCEL_IDX_ACCEL_Z_VAL:
        case ACCEL_IDX_ACCEL_Z_EN:
					if(*(uint8_t*)&(param->value[0]) > 1)
					accel_adv_interval3 = *(uint8_t*)&(param->value[0]);
					if(*(uint8_t*)&(param->value[0]) == 255)
					accel_adv_interval3 = 0;
						atts_write_rsp_send(accel_env.con_info.conidx, param->handle, PRF_ERR_OK);
            break;
        
        default:
            atts_write_rsp_send(accel_env.con_info.conidx, param->handle, PRF_ERR_OK);
            break;
            
    }

    return (KE_MSG_CONSUMED);
}
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GL2C_CODE_ATT_WR_CMD_IND message.
 * The handler will
 * @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)
{
    uint16_t value = 0x0000;
    uint8_t char_code = HPS_ERR_CHAR;
    uint8_t status = PRF_APP_ERROR;

    if (KE_IDX_GET(src_id) == hpss_env.con_info.conidx)
    {
        if (param->handle == hpss_env.hps_shdl + HPS_IDX_URI_VAL)
        {
            char_code = HPS_URI_CHAR;
        }
        else if (param->handle == hpss_env.hps_shdl + HPS_IDX_HEADER_VAL)
        {
            char_code = HPS_HEADER_CHAR;
        }
        else if (param->handle == hpss_env.hps_shdl + HPS_IDX_BODY_VAL)
        {
            char_code = HPS_BODY_CHAR;
        }
        else if (param->handle == hpss_env.hps_shdl + HPS_IDX_CNTL_PT_VAL)
        {
            char_code = HPS_CNTL_PT_CHAR;
        }
        //this case is processed seperately
        else if (param->handle == hpss_env.hps_shdl + HPS_IDX_STATUS_CODE_CFG)
        {
            //Extract value before check
            memcpy(&value, &(param->value), sizeof(uint16_t));

            if ((value == PRF_CLI_STOP_NTFIND) || (value == PRF_CLI_START_NTF))
            {
                status = PRF_ERR_OK;
                if (value == PRF_CLI_STOP_NTFIND)
                {
                    hpss_env.features &= ~HPSS_STATUS_CODE_NTF_CFG;
                }
                else //PRF_CLI_START_NTF
                {
                    hpss_env.features |= HPSS_STATUS_CODE_NTF_CFG;
                }
            }
            else
            {
                status = PRF_APP_ERROR;
            }

            if (status == PRF_ERR_OK)
            {
                //Update the attribute value
                attmdb_att_set_value(param->handle, sizeof(uint16_t), (uint8_t *)&value);
                if(param->last)
                {
                    //Inform APP of configuration change
                    struct hpss_cfg_indntf_ind * ind = KE_MSG_ALLOC(HPSS_CFG_INDNTF_IND,
                                                       hpss_env.con_info.appid, TASK_HPSS,
                                                       hpss_cfg_indntf_ind);

                    ind->conhdl = gapc_get_conhdl(hpss_env.con_info.conidx);
                    memcpy(&ind->cfg_val, &value, sizeof(uint16_t));

                    ke_msg_send(ind);
                }
            }
            //If HPS, send write response
            if (param->response != 0x00)
            {
                // Send Write Response
                atts_write_rsp_send(hpss_env.con_info.conidx, param->handle, status);
            }
            return  (KE_MSG_CONSUMED);
        }
        if (char_code != HPS_ERR_CHAR)
        {
            //Save value in DB
            attmdb_att_set_value(param->handle, sizeof(uint8_t), (uint8_t *)&param->value[0]);

            status = PRF_ERR_OK;

            switch(char_code)
            {
            case  HPS_URI_CHAR:
                if ((param->length + param->offset) <= HPS_URI_MAX_LEN)
                {
                    // First part of the uri value
                    if (param->offset == 0)
                    {
                        // Set value in the database
                        attmdb_att_set_value(param->handle, param->length, (uint8_t *)&param->value[0]);
                    }
                    else
                    {
                        // Complete the value stored in the database
                        attmdb_att_update_value(param->handle, param->length, param->offset,
                                                (uint8_t *)&param->value[0]);
                    }
                    if(param->last)
                    {
                        uint16_t len = 0;
                        uint8_t *data = NULL;
                        // Get complete uri value and length
                        attmdb_att_get_value(param->handle, &len, &data);
                        // Inform APP. Allocate the URI value change indication
                        struct hpss_uri_ind *ind = KE_MSG_ALLOC(HPSS_URI_IND,
                                                                hpss_env.con_info.appid, TASK_HPSS,
                                                                hpss_uri_ind);


                        // Fill in the parameter structure
                        ind->conhdl = gapc_get_conhdl(hpss_env.con_info.conidx);
                        ind->char_code = HPS_URI_CHAR;
                        ind->len = len;

                        memcpy(&ind->uri, data, len);

                        ke_msg_send(ind);
                    }
                }
                break;
            case  HPS_HEADER_CHAR:
                if ((param->length + param->offset) <= HPS_HEADER_MAX_LEN)
                {
                    // First part of the uri value
                    if (param->offset == 0)
                    {
                        // Set value in the database
                        attmdb_att_set_value(param->handle, param->length, (uint8_t *)&param->value[0]);
                    }
                    else
                    {
                        // Complete the value stored in the database
                        attmdb_att_update_value(param->handle, param->length, param->offset,
                                                (uint8_t *)&param->value[0]);
                    }
                    if(param->last)
                    {
                        uint16_t len = 0;
                        uint8_t *data = NULL;
                        // Get complete uri value and length
                        attmdb_att_get_value(param->handle, &len, &data);
                        // Inform APP. Allocate the URI value change indication
                        struct hpss_header_ind *ind = KE_MSG_ALLOC(HPSS_HEADER_IND,
                                                      hpss_env.con_info.appid, TASK_HPSS,
                                                      hpss_header_ind);


                        // Fill in the parameter structure
                        ind->conhdl = gapc_get_conhdl(hpss_env.con_info.conidx);
                        ind->char_code = HPS_HEADER_CHAR;
                        ind->len = len;

                        memcpy(&ind->header, data, len);

                        ke_msg_send(ind);
                    }
                }
                break;
            case  HPS_BODY_CHAR:
                if ((param->length + param->offset) <= HPS_BODY_MAX_LEN)
                {
                    // First part of the uri value
                    if (param->offset == 0)
                    {
                        // Set value in the database
                        attmdb_att_set_value(param->handle, param->length, (uint8_t *)&param->value[0]);
                    }
                    else
                    {
                        // Complete the value stored in the database
                        attmdb_att_update_value(param->handle, param->length, param->offset,
                                                (uint8_t *)&param->value[0]);
                    }
                    if(param->last)
                    {
                        uint16_t len = 0;
                        uint8_t *data = NULL;
                        // Get complete uri value and length
                        attmdb_att_get_value(param->handle, &len, &data);
                        // Inform APP. Allocate the URI value change indication
                        struct hpss_body_ind *ind = KE_MSG_ALLOC(HPSS_BODY_IND,
                                                    hpss_env.con_info.appid, TASK_HPSS,
                                                    hpss_body_ind);


                        // Fill in the parameter structure
                        ind->conhdl = gapc_get_conhdl(hpss_env.con_info.conidx);
                        ind->char_code = HPS_BODY_CHAR;
                        ind->len = len;

                        memcpy(&ind->body, data, len);

                        ke_msg_send(ind);
                    }
                }
                break;
            case  HPS_CNTL_PT_CHAR:
                if ((param->length + param->offset) <= HPS_CNTL_PT_MAX_LEN)
                {
                    // First part of the uri value
                    if (param->offset == 0)
                    {
                        // Set value in the database
                        attmdb_att_set_value(param->handle, param->length, (uint8_t *)&param->value[0]);
                    }
                    else
                    {
                        // Complete the value stored in the database
                        attmdb_att_update_value(param->handle, param->length, param->offset,
                                                (uint8_t *)&param->value[0]);
                    }
                    if(param->last)
                    {
                        uint16_t len = 0;
                        uint8_t *data = NULL;
                        // Get complete uri value and length
                        attmdb_att_get_value(param->handle, &len, &data);
                        // Inform APP. Allocate the URI value change indication
                        struct hpss_cntl_pt_ind *ind = KE_MSG_ALLOC(HPSS_CNTL_PT_IND,
                                                       hpss_env.con_info.appid, TASK_HPSS,
                                                       hpss_cntl_pt_ind);


                        // Fill in the parameter structure
                        ind->conhdl = gapc_get_conhdl(hpss_env.con_info.conidx);
                        ind->char_code = HPS_CNTL_PT_CHAR;
                        ind->len = len;

                        memcpy(&ind->cntl_pt, data, len);

                        ke_msg_send(ind);
                    }
                }
                break;
            default:
                break;
            }
            //If HPS, send write response
            if (param->response != 0x00)
            {
                // Send Write Response
                atts_write_rsp_send(hpss_env.con_info.conidx, param->handle, status);
            }
        }
    }
    return (KE_MSG_CONSUMED);
}
Exemple #14
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GL2C_CODE_ATT_WR_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 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 status = ATT_ERR_INSUFF_AUTHOR;

    // check connection
    if (KE_IDX_GET(src_id) == glps_env.con_info.conidx)
    {
        uint8_t att_idx = GLPS_IDX(param->handle);
        status = PRF_ERR_OK;

        // check if it's a client configuration char
        if(glps_att_db[att_idx].uuid == ATT_DESC_CLIENT_CHAR_CFG)
        {
            uint16_t cli_cfg;
            uint8_t evt_mask = GLPS_IND_NTF_EVT(att_idx);

            // get client configuration
            cli_cfg = co_read16(&(param->value));

            // stop indication/notification
            if(cli_cfg == PRF_CLI_STOP_NTFIND)
            {
                glps_env.evt_cfg &= ~evt_mask;
            }
            // start indication/notification (check that char value accept it)
            else if((((glps_att_db[att_idx-1].perm & PERM(IND, ENABLE)) != 0)
                && cli_cfg == PRF_CLI_START_IND)
               ||(((glps_att_db[att_idx-1].perm & PERM(NTF, ENABLE)) != 0)
                       && cli_cfg == PRF_CLI_START_NTF))
            {
                glps_env.evt_cfg |= evt_mask;
            }
            // improper value
            else
            {
                status = GLP_ERR_IMPROPER_CLI_CHAR_CFG;
            }

            if (status == PRF_ERR_OK)
            {
                //Inform APP of configuration change
                struct glps_cfg_indntf_ind * ind = KE_MSG_ALLOC(GLPS_CFG_INDNTF_IND,
                        glps_env.con_info.appid, TASK_GLPS,
                        glps_cfg_indntf_ind);

                //Update the attribute value
                attmdb_att_set_value(param->handle, sizeof(uint16_t), (uint8_t *)&cli_cfg);
                ind->conhdl = gapc_get_conhdl(glps_env.con_info.conidx);
                ind->evt_cfg = glps_env.evt_cfg;

                ke_msg_send(ind);
            }
        }

        else if (glps_att_db[att_idx].uuid == ATT_CHAR_REC_ACCESS_CTRL_PT)
        {
            uint8_t reqstatus;
            uint8_t* value;
            uint16_t length;
            struct glp_racp_req racp_req;

            if((glps_env.evt_cfg & GLPS_RACP_IND_CFG) == 0)
            {
                // do nothing since indication not enabled for this characteristic
                status = GLP_ERR_IMPROPER_CLI_CHAR_CFG;
            }
            // If a request is on going
            else if(GLPS_IS(RACP_ON_GOING))
            {
                // if it's an abort command, execute it.
                if((param->offset == 0) && (param->value[0] == GLP_REQ_ABORT_OP))
                {
                    //forward abort operation to application
                    struct glps_racp_req_ind * req = KE_MSG_ALLOC(GLPS_RACP_REQ_IND,
                            glps_env.con_info.appid, TASK_GLPS,
                            glps_racp_req_ind);

                    req->conhdl = gapc_get_conhdl(glps_env.con_info.conidx);
                    req->racp_req.op_code = GLP_REQ_ABORT_OP;
                    req->racp_req.filter.operator = 0;

                    ke_msg_send(req);
                }
                else
                {
                    // do nothing since a procedure already in progress
                    status = GLP_ERR_PROC_ALREADY_IN_PROGRESS;
                }
            }
            else
            {
                // Update the attribute value (note several write could be required since
                // attribute length > (ATT_MTU-3)
                attmdb_att_update_value(param->handle, param->length, param->offset,
                        (uint8_t*)&(param->value[0]));

                // retrieve full data.
                attmdb_att_get_value(param->handle, &length, &value);

                // unpack record access control point value
                reqstatus = glps_unpack_racp_req(value, length, &racp_req);

                // check unpacked status
                switch(reqstatus)
                {
                    case PRF_APP_ERROR:
                    {
                        /* Do nothing, ignore request since it's not complete and maybe
                         * requires several peer write to be performed.
                         */
                    }
                    break;
                    case PRF_ERR_OK:
                    {
                        // check wich request shall be send to api task
                        switch(racp_req.op_code)
                        {
                            case GLP_REQ_REP_STRD_RECS:
                            case GLP_REQ_DEL_STRD_RECS:
                            case GLP_REQ_REP_NUM_OF_STRD_RECS:
                            {
                                //forward request operation to application
                                struct glps_racp_req_ind * req = KE_MSG_ALLOC(GLPS_RACP_REQ_IND,
                                        glps_env.con_info.appid, TASK_GLPS,
                                        glps_racp_req_ind);

                                // RACP on going.
                                GLPS_SET(RACP_ON_GOING);

                                req->conhdl = gapc_get_conhdl(glps_env.con_info.conidx);
                                req->racp_req = racp_req;

                                ke_msg_send(req);
                            }
                            break;
                            case GLP_REQ_ABORT_OP:
                            {
                                // nothing to abort, send an error message.
                                struct glp_racp_rsp racp_rsp;

                                racp_rsp.op_code = GLP_REQ_RSP_CODE;
                                racp_rsp.operand.rsp.op_code_req =
                                        racp_req.op_code;
                                racp_rsp.operand.rsp.status = GLP_RSP_ABORT_UNSUCCESSFUL;

                                // send record access control response indication
                                glps_send_racp_rsp(&(racp_rsp),
                                        TASK_GLPS);
                            }
                            break;
                            default:
                            {
                                // nothing to do since it's handled during unpack
                            }
                            break;
                        }
                    }
                    break;
                    default:
                    {
                        /* There is an error in record access control request, inform peer
                         * device that request is incorrect. */
                        struct glp_racp_rsp racp_rsp;

                        racp_rsp.op_code = GLP_REQ_RSP_CODE;
                        racp_rsp.operand.rsp.op_code_req = racp_req.op_code;
                        racp_rsp.operand.rsp.status = reqstatus;

                        // send record access control response indication
                        glps_send_racp_rsp(&(racp_rsp),
                                TASK_GLPS);
                    }
                    break;
                }
            }
        }
        // not expected request
        else
        {
            status = ATT_ERR_WRITE_NOT_PERMITTED;
        }
    }

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

    return (KE_MSG_CONSUMED);
}