Пример #1
0
void bass_disable(void)
{
    // Counter
    uint8_t i;
    // Information get in the DB
    atts_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 = bass_env.con_info.conhdl;

    for (i = 0; i < bass_env.bas_nb; i++)
    {
        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
        attsdb_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);
}
Пример #2
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 = ATT_ERR_INSUFF_AUTHOR;

    // check connection
    if (param->conhdl == glps_env.con_info.conhdl)
    {
        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
                attsdb_att_set_value(param->handle, sizeof(uint16_t), (uint8_t *)&cli_cfg);
                ind->conhdl = glps_env.con_info.conhdl;
                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* value;
            uint16_t length;
            struct glp_racp_req racp_req;

            // If a request is on going
            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 = glps_env.con_info.conhdl;
                    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)
                attsdb_att_update_value(param->handle, param->length, param->offset,
                        (uint8_t*)&(param->value[0]));

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

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

                // check unpacked status
                switch(status)
                {
                    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:
                            {
                                if((glps_env.evt_cfg & GLPS_RACP_IND_CFG) != 0)
                                {
                                    //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 = glps_env.con_info.conhdl;
                                    req->racp_req = racp_req;
    
                                    ke_msg_send(req);
                                }
                                else
                                {
                                    status = PRF_CCCD_IMPR_CONFIGURED;
                                }
                            }
                            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 = status;

                        // 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(param->conhdl, param->handle, status);
    }

    return (KE_MSG_CONSUMED);
}
Пример #3
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);
}