コード例 #1
0
ファイル: anpc_task.c プロジェクト: FuangCao/jwaoo-toy
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATTC_READ_IND message.
 * Generic event received after every simple read command sent to peer server.
 * @param[in] msgid Id of the message received (probably unused).
 * @param[in] param Pointer to the parameters of the message.
 * @param[in] dest_id ID of the receiving task instance (probably unused).
 * @param[in] src_id ID of the sending task instance.
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
static int gattc_read_ind_handler(ke_msg_id_t const msgid,
                                    struct gattc_read_ind const *param,
                                    ke_task_id_t const dest_id,
                                    ke_task_id_t const src_id)
{
    // Get the address of the environment
    struct anpc_env_tag *anpc_env = PRF_CLIENT_GET_ENV(dest_id, anpc);

    if (anpc_env != NULL)
    {
        ASSERT_ERR(anpc_env->operation != NULL);

        // Prepare the indication to send to the application
        struct anpc_value_ind *ind = KE_MSG_ALLOC(ANPC_VALUE_IND,
                                                  anpc_env->con_info.appid,
                                                  anpc_env->con_info.prf_id,
                                                  anpc_value_ind);

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

        switch (((struct anpc_cmd *)anpc_env->operation)->operation)
        {
            // Read Supported New Alert Category Characteristic value
            case (ANPC_ENABLE_RD_NEW_ALERT_OP_CODE):
            {
                ind->att_code = ANPC_RD_SUP_NEW_ALERT_CAT;
                ind->value.supp_cat.cat_id_mask_0 = param->value[0];
                // If cat_id_mask_1 not present, shall be considered as 0
                ind->value.supp_cat.cat_id_mask_1 = (param->length > 1)
                                                    ? param->value[1] : 0x00;
            } break;

            case (ANPC_ENABLE_RD_UNREAD_ALERT_OP_CODE):
            {
                ind->att_code = ANPC_RD_SUP_UNREAD_ALERT_CAT;
                ind->value.supp_cat.cat_id_mask_0 = param->value[0];
                // If cat_id_mask_1 not present, shall be considered as 0
                ind->value.supp_cat.cat_id_mask_1 = (param->length > 1)
                                                    ? param->value[1] : 0;
            } break;

            case (ANPC_READ_OP_CODE):
            {
                ind->att_code      = ((struct anpc_read_cmd *)anpc_env->operation)->read_code;
                ind->value.ntf_cfg = co_read16(&param->value[0]);
            } break;

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

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

    return (KE_MSG_CONSUMED);
}
コード例 #2
0
ファイル: glps_task.c プロジェクト: nephen/BluetoothLamp
/**
 ****************************************************************************************
 * @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);
}