示例#1
0
/**@brief     Function for handling the @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST event from the
 *            SoftDevice.
 *
 * @param[in] p_dfu     DFU Service Structure.
 * @param[in] p_ble_evt Pointer to the event received from BLE stack.
 */
static bool on_rw_authorize_req(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt)
{
    uint32_t                                err_code;
    ble_gatts_rw_authorize_reply_params_t   auth_reply = {0};
    ble_gatts_evt_rw_authorize_request_t  * p_authorize_request;
    ble_gatts_evt_write_t                 * p_ble_write_evt;
    
    p_authorize_request = &(p_ble_evt->evt.gatts_evt.params.authorize_request);
    p_ble_write_evt = &(p_ble_evt->evt.gatts_evt.params.authorize_request.request.write);

    if ((p_authorize_request->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE)                           &&
        (p_authorize_request->request.write.handle == p_dfu->dfu_ctrl_pt_handles.value_handle)  &&
        (p_authorize_request->request.write.op != BLE_GATTS_OP_PREP_WRITE_REQ)                  &&
        (p_authorize_request->request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_NOW)              &&
        (p_authorize_request->request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)            )
    {
        auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
        auth_reply.params.write.update = 1;
        auth_reply.params.write.offset = p_ble_write_evt->offset;
        auth_reply.params.write.len = p_ble_write_evt->len;
        auth_reply.params.write.p_data = p_ble_write_evt->data;

        if (!is_cccd_configured(p_dfu))
        {
            // Send an error response to the peer indicating that the CCCD is improperly configured.
            auth_reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR;
 
            // Ignore response of auth reply
            (void)sd_ble_gatts_rw_authorize_reply(m_conn_handle, &auth_reply);
            return false;
        }

        auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;

        err_code = sd_ble_gatts_rw_authorize_reply(m_conn_handle, &auth_reply);
        return err_code  == NRF_SUCCESS ? true: false;
    }
    else
    {
        return false;
    }
}
示例#2
0
/**@brief     Function for handling a Write event on the Control Point characteristic.
 *
 * @param[in] p_dfu             DFU Service Structure.
 * @param[in] p_ble_write_evt   Pointer to the write event received from BLE stack.
 *
 * @return    NRF_SUCCESS on successful processing of control point write. Otherwise an error code.
 */
static uint32_t on_ctrl_pt_write(ble_dfu_t * p_dfu, ble_gatts_evt_write_t * p_ble_write_evt)
{
    ble_gatts_rw_authorize_reply_params_t write_authorize_reply;

    write_authorize_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;

    if (!is_cccd_configured(p_dfu))
    {
        // Send an error response to the peer indicating that the CCCD is improperly configured.
        write_authorize_reply.params.write.gatt_status =
            BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR;

        return (sd_ble_gatts_rw_authorize_reply(p_dfu->conn_handle, &write_authorize_reply));

    }
    else
    {
        uint32_t err_code;

        write_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;

        err_code = (sd_ble_gatts_rw_authorize_reply(p_dfu->conn_handle, &write_authorize_reply));

        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    }

    ble_dfu_evt_t ble_dfu_evt;

    switch (p_ble_write_evt->data[0])
    {
        case OP_CODE_START_DFU:
            ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_START;

            if (p_ble_write_evt->len < PKT_START_DFU_PARAM_LEN)
            {
                return ble_dfu_response_send(p_dfu,
                                             (ble_dfu_procedure_t) p_ble_write_evt->data[0],
                                             BLE_DFU_RESP_VAL_OPER_FAILED);
            }

            ble_dfu_evt.evt.ble_dfu_pkt_write.len    = 1;
            ble_dfu_evt.evt.ble_dfu_pkt_write.p_data = &(p_ble_write_evt->data[1]);

            p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
            break;

        case OP_CODE_RECEIVE_INIT:
            ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_RECEIVE_INIT_DATA;

            if (p_ble_write_evt->len < PKT_INIT_DFU_PARAM_LEN)
            {
                return ble_dfu_response_send(p_dfu,
                                             (ble_dfu_procedure_t) p_ble_write_evt->data[0],
                                             BLE_DFU_RESP_VAL_OPER_FAILED);
            }
            
            ble_dfu_evt.evt.ble_dfu_pkt_write.len    = 1;
            ble_dfu_evt.evt.ble_dfu_pkt_write.p_data = &(p_ble_write_evt->data[1]);

            p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
            break;

        case OP_CODE_RECEIVE_FW:
            ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_RECEIVE_APP_DATA;

            p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
            break;

        case OP_CODE_VALIDATE:
            ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_VALIDATE;

            p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
            break;

        case OP_CODE_ACTIVATE_N_RESET:
            ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_ACTIVATE_N_RESET;

            p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
            break;

        case OP_CODE_SYS_RESET:
            ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_SYS_RESET;

            p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
            break;

        case OP_CODE_PKT_RCPT_NOTIF_REQ:
            if (p_ble_write_evt->len < PKT_RCPT_NOTIF_REQ_LEN)
            {
                return (ble_dfu_response_send(p_dfu,
                                              BLE_DFU_PKT_RCPT_REQ_PROCEDURE,
                                              BLE_DFU_RESP_VAL_NOT_SUPPORTED));
            }

            ble_dfu_evt.evt.pkt_rcpt_notif_req.num_of_pkts =
                uint16_decode(&(p_ble_write_evt->data[1]));

            if (ble_dfu_evt.evt.pkt_rcpt_notif_req.num_of_pkts == 0)
            {
                ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_PKT_RCPT_NOTIF_DISABLED;
            }
            else
            {
                ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_PKT_RCPT_NOTIF_ENABLED;
            }

            p_dfu->evt_handler(p_dfu, &ble_dfu_evt);

            break;

        case OP_CODE_IMAGE_SIZE_REQ:
            ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_BYTES_RECEIVED_SEND;

            p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
            break;

        default:
            // Unsupported op code.
            return ble_dfu_response_send(p_dfu,
                                         (ble_dfu_procedure_t) p_ble_write_evt->data[0],
                                         BLE_DFU_RESP_VAL_NOT_SUPPORTED);
    }
    return NRF_SUCCESS;
}
示例#3
0
/**@brief Handle a write event to the Speed and Cadence Control Point.
 *
 * @param[in]   p_sc_ctrlpt      SC Ctrlpt structure.
 * @param[in]   p_evt_write      WRITE event to be handled.
 */
static void on_ctrlpt_write(ble_sc_ctrlpt_t             * p_sc_ctrlpt,
                            ble_gatts_evt_write_t const * p_evt_write)
{
    ble_sc_ctrlpt_val_t                   rcvd_ctrlpt =
    { BLE_SCPT_RESPONSE_CODE , 0, BLE_SENSOR_LOCATION_OTHER };

    ble_sc_ctrlpt_rsp_t                   rsp;
    uint32_t                              err_code;
    ble_gatts_rw_authorize_reply_params_t auth_reply;
    ble_sc_ctrlpt_evt_t                   evt;

    auth_reply.type                     = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
    auth_reply.params.write.offset      = 0;
    auth_reply.params.write.len         = 0;
    auth_reply.params.write.p_data      = NULL;
    auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
    auth_reply.params.write.update      = 1;

    if (is_cccd_configured(p_sc_ctrlpt))
    {
        if (p_sc_ctrlpt->procedure_status == BLE_SCPT_NO_PROC_IN_PROGRESS)
        {
            auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
        }
        else
        {
            auth_reply.params.write.gatt_status = SC_CTRLPT_NACK_PROC_ALREADY_IN_PROGRESS;
        }
    }
    else
    {
        auth_reply.params.write.gatt_status = SC_CTRLPT_NACK_CCCD_IMPROPERLY_CONFIGURED;
    }

    err_code = sd_ble_gatts_rw_authorize_reply(p_sc_ctrlpt->conn_handle, &auth_reply);
    if (err_code != NRF_SUCCESS)
    {
        // Report error to application.
        if (p_sc_ctrlpt->error_handler != NULL)
        {
            p_sc_ctrlpt->error_handler(err_code);
        }
    }

    if (auth_reply.params.write.gatt_status != BLE_GATT_STATUS_SUCCESS)
    {
        return;
    }

    p_sc_ctrlpt->procedure_status = BLE_SCPT_INDICATION_PENDING;
    rsp.status                    = BLE_SCPT_OP_CODE_NOT_SUPPORTED;

    err_code = sc_ctrlpt_decode(p_evt_write->data, p_evt_write->len, &rcvd_ctrlpt);
    if (err_code != NRF_SUCCESS)
    {
        rsp.opcode = rcvd_ctrlpt.opcode;
        rsp.status = BLE_SCPT_OP_CODE_NOT_SUPPORTED;
    }
    else
    {
        rsp.opcode = rcvd_ctrlpt.opcode;

        switch (rcvd_ctrlpt.opcode)
        {
            case BLE_SCPT_REQUEST_SUPPORTED_SENSOR_LOCATIONS:
                if ((p_sc_ctrlpt->supported_functions &
                     BLE_SRV_SC_CTRLPT_SENSOR_LOCATIONS_OP_SUPPORTED) ==
                     BLE_SRV_SC_CTRLPT_SENSOR_LOCATIONS_OP_SUPPORTED)
                {
                    rsp.status = BLE_SCPT_SUCCESS;
                }
                else
                {
                    rsp.status = BLE_SCPT_OP_CODE_NOT_SUPPORTED;
                }
                break;

            case BLE_SCPT_UPDATE_SENSOR_LOCATION:
                if ((p_sc_ctrlpt->supported_functions &
                     BLE_SRV_SC_CTRLPT_SENSOR_LOCATIONS_OP_SUPPORTED) ==
                     BLE_SRV_SC_CTRLPT_SENSOR_LOCATIONS_OP_SUPPORTED)
                {
                    if (is_location_supported(p_sc_ctrlpt, rcvd_ctrlpt.location))
                    {
                        ble_gatts_value_t gatts_value;
                        uint8_t  rcvd_location = (uint8_t)rcvd_ctrlpt.location;
                        rsp.status = BLE_SCPT_SUCCESS;

                        // Initialize value struct.
                        memset(&gatts_value, 0, sizeof(gatts_value));

                        gatts_value.len     = sizeof(uint8_t);
                        gatts_value.offset  = 0;
                        gatts_value.p_value = &rcvd_location;

                        evt.evt_type               = BLE_SC_CTRLPT_EVT_UPDATE_LOCATION;
                        evt.params.update_location = rcvd_ctrlpt.location;
                        if (p_sc_ctrlpt->evt_handler != NULL)
                        {
                            rsp.status = p_sc_ctrlpt->evt_handler(p_sc_ctrlpt, &evt);
                        }
                        if (rsp.status == BLE_SCPT_SUCCESS)
                        {
                            err_code = sd_ble_gatts_value_set(p_sc_ctrlpt->conn_handle,
                                                              p_sc_ctrlpt->sensor_location_handle,
                                                              &gatts_value);
                            if (err_code != NRF_SUCCESS)
                            {
                                // Report error to application
                                if (p_sc_ctrlpt->error_handler != NULL)
                                {
                                    p_sc_ctrlpt->error_handler(err_code);
                                }
                                rsp.status = BLE_SCPT_OPERATION_FAILED;
                            }
                        }
                    }
                    else
                    {
                        rsp.status = BLE_SCPT_INVALID_PARAMETER;
                    }
                }
                else
                {
                    rsp.status = BLE_SCPT_OP_CODE_NOT_SUPPORTED;
                }
                break;

            case BLE_SCPT_SET_CUMULATIVE_VALUE:
                if ((p_sc_ctrlpt->supported_functions &
                     BLE_SRV_SC_CTRLPT_CUM_VAL_OP_SUPPORTED) ==
                     BLE_SRV_SC_CTRLPT_CUM_VAL_OP_SUPPORTED)
                {
                    rsp.status = BLE_SCPT_SUCCESS;

                    evt.evt_type                = BLE_SC_CTRLPT_EVT_SET_CUMUL_VALUE;
                    evt.params.cumulative_value = rcvd_ctrlpt.cumulative_value;
                    if (p_sc_ctrlpt->evt_handler != NULL)
                    {
                        rsp.status = p_sc_ctrlpt->evt_handler(p_sc_ctrlpt, &evt);
                    }
                }
                else
                {
                    rsp.status = BLE_SCPT_OP_CODE_NOT_SUPPORTED;
                }
                break;

            case BLE_SCPT_START_AUTOMATIC_CALIBRATION:
                if ((p_sc_ctrlpt->supported_functions &
                     BLE_SRV_SC_CTRLPT_START_CALIB_OP_SUPPORTED) ==
                     BLE_SRV_SC_CTRLPT_START_CALIB_OP_SUPPORTED)
                {
                    p_sc_ctrlpt->procedure_status = BLE_SCPT_AUTOMATIC_CALIB_IN_PROGRESS;
                    evt.evt_type                  = BLE_SC_CTRLPT_EVT_START_CALIBRATION;
                    if (p_sc_ctrlpt->evt_handler != NULL)
                    {
                        rsp.status = p_sc_ctrlpt->evt_handler(p_sc_ctrlpt, &evt);
                        if (rsp.status != BLE_SCPT_SUCCESS)
                        {
                            // If the application returns an error, the response is to be sent
                            // right away and the calibration is considered as not started.
                            p_sc_ctrlpt->procedure_status = BLE_SCPT_INDICATION_PENDING;
                        }
                    }
                }
                else
                {
                    rsp.status = BLE_SCPT_OP_CODE_NOT_SUPPORTED;
                }
                break;

            default:
                rsp.status = BLE_SCPT_OP_CODE_NOT_SUPPORTED;
                break;
        }

    }

    p_sc_ctrlpt->response.len = ctrlpt_rsp_encode(p_sc_ctrlpt, &rsp,
                                                  p_sc_ctrlpt->response.encoded_ctrl_rsp);


    if (p_sc_ctrlpt->procedure_status == BLE_SCPT_INDICATION_PENDING)
    {
        sc_ctrlpt_resp_send(p_sc_ctrlpt);
    }
}
static void on_ctrlpt_write(ble_achs_t *            p_achs,
                            ble_gatts_evt_write_t * p_evt_write)
{
    ble_gatts_rw_authorize_reply_params_t auth_reply;

    auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;

    if (is_cccd_configured())
    {
        auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
        uint32_t err_code = sd_ble_gatts_rw_authorize_reply(p_achs->conn_handle, &auth_reply);
        (void)err_code;
    }
    else
    {
        auth_reply.params.write.gatt_status = ACH_CTRLPT_NACK_CCCD_IMPROPERLY_CONFIGURED;
        uint32_t err_code = sd_ble_gatts_rw_authorize_reply(p_achs->conn_handle, &auth_reply);
        (void)err_code;
        return;
    }

    uint8_t op_code = p_evt_write->data[0];
//lint --e{415}         
    uint8_t command = p_evt_write->data[1];

    if (op_code == ACH_OP_COMMAND)
    {
        switch (command)
        {
            case ACH_CMD_REPORTING_MODE_OFF:
                {
                    //Load up the last received command structure so the application
                    //gets recent data when it asks for it
                    m_last_received_command.command = REPORTING_MODE_OFF;
                    m_last_received_command.master_id = EVERY_MASTER_ID;

                    //Set the command received flag so the application will know to ask for
                    //the most recent command.
                    asc_event_set(&m_event_flags, EVENT_ASC_COMMAND_RECEIVED);
                }
                break;

            case ACH_CMD_REPORTING_MODE_ON:
                {
                    //Load up the last received command structure so the application
                    //gets recent data when it asks for it
                    m_last_received_command.command = REPORTING_MODE_ON;
                    m_last_received_command.master_id = EVERY_MASTER_ID;

                    //Set the command received flag so the application will know to ask for
                    //the most recent command.
                    asc_event_set(&m_event_flags, EVENT_ASC_COMMAND_RECEIVED);
                }
                break;

            case ACH_CMD_REPORTING_MODE_WARNINGS:
                {
                    /* this command is not currently supported by this demo
                    //Load up the last received command structure so the application
                    //gets recent data when it asks for it
                    m_last_received_command.command = REPORTING_MODE_WARNINGS;
                    m_last_received_command.master_id = EVERY_MASTER_ID;

                    //Set the command received flag so the application will know to ask for
                    //the most recent command.
                    asc_event_set(&m_event_flags, EVENT_ASC_COMMAND_RECEIVED);
                    */
                }
                break;

            case ACH_CMD_PERI_ON:
                {
                    //Load up the last received command structure so the application
                    //gets recent data when it asks for it
                    m_last_received_command.command = TURN_ON;
//lint --e{415}                                                 
//lint --e{416}                             
                    m_last_received_command.shared_address = p_evt_write->data[2];
//lint --e{415}                                                 
//lint --e{416}                                                 
                    m_last_received_command.master_id = uint16_decode(&p_evt_write->data[4]);
                    m_last_received_command.group_number = NO_GROUPS;/**< @todo can the demo actually use groups? Double check this everywhere*/
                    //Set the command received flag so the application will know to ask for
                    //the most recent command.
                    asc_event_set(&m_event_flags, EVENT_ASC_COMMAND_RECEIVED);
                }
                break;

            case ACH_CMD_PERI_OFF:
                {
                    //Load up the last received command structure so the application
                    //gets recent data when it asks for it
                    m_last_received_command.command = TURN_OFF;
//lint --e{416}                                                 
                    m_last_received_command.shared_address = p_evt_write->data[2];
//lint --e{416}                                                 
                    m_last_received_command.master_id = uint16_decode(&p_evt_write->data[4]);
                    m_last_received_command.group_number = NO_GROUPS;

                    //Set the command received flag so the application will know to ask for
                    //the most recent command.
                    asc_event_set(&m_event_flags, EVENT_ASC_COMMAND_RECEIVED);
                }
                break;

            case ACH_CMD_GROUP_ASSIGN:
                {
                    //Load up the last received command structure so the application
                    //gets recent data when it asks for it
                    m_last_received_command.command = ASSIGN_TO_GROUP;
//lint --e{416}                                                 
                    m_last_received_command.shared_address = p_evt_write->data[2];
//lint --e{416}                                                 
                    m_last_received_command.master_id = uint16_decode(&p_evt_write->data[4]);
                    m_last_received_command.group_number = p_evt_write->data[3];

                    //Set the command received flag so the application will know to ask for
                    //the most recent command.
                    asc_event_set(&m_event_flags, EVENT_ASC_COMMAND_RECEIVED);

                }
                break;

            case ACH_CMD_GROUP_ON:
                {
                    //Load up the last received command structure so the application
                    //gets recent data when it asks for it
                    m_last_received_command.command = TURN_ON;
                    m_last_received_command.shared_address = EVERY_DEVICE_ADDRESS;
//lint --e{416}                                                 
                    m_last_received_command.master_id = uint16_decode(&p_evt_write->data[3]);
                    m_last_received_command.group_number = p_evt_write->data[2];

                    asc_event_set(&m_event_flags, EVENT_ASC_COMMAND_RECEIVED);
                }
                break;

            case ACH_CMD_GROUP_OFF:
                {
                    //Load up the last received command structure so the application
                    //gets recent data when it asks for it
                    m_last_received_command.command = TURN_OFF;
                    m_last_received_command.shared_address = EVERY_DEVICE_ADDRESS;
//lint --e{416}                                                 
                    m_last_received_command.master_id = uint16_decode(&p_evt_write->data[3]);
                    m_last_received_command.group_number = p_evt_write->data[2];

                    asc_event_set(&m_event_flags, EVENT_ASC_COMMAND_RECEIVED);
                }
                break;

            default:
                break;

        } // end switch(command)
    }
}