Exemple #1
0
/**@brief Function for processing a received vendor specific packet.
 *
 * @param[in] p_buffer Pointer to the packet data.
 * @param[in] length   Length of packet data in bytes.
 */
static void rx_vendor_specific_pkt_type_handle(const uint8_t * p_buffer, uint32_t length)
{
    // @note: no pointer validation check needed as allready checked by calling function.
    uint32_t err_code;

    if (is_rx_pkt_valid(p_buffer, length))
    {
        // RX packet is valid: validate sequence number.
        const uint8_t rx_seq_number = packet_seq_nmbr_extract(p_buffer);
        if (packet_number_expected_get() == rx_seq_number)
        {
            // Sequence number is valid: transmit acknowledgement.
            packet_number_expected_inc();
            ack_transmit();

            m_is_slip_decode_ready = true;

            err_code = hci_mem_pool_rx_data_size_set(length);
            APP_ERROR_CHECK(err_code);

            err_code = hci_mem_pool_rx_produce(HCI_RX_BUF_SIZE, (void **)&mp_slip_used_rx_buffer);
            APP_ERROR_CHECK_BOOL((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NO_MEM));

            // If memory pool RX buffer produce succeeded we register that buffer to slip layer
            // otherwise we register the internal acknowledgement buffer.
            err_code = hci_slip_rx_buffer_register(
                (err_code == NRF_SUCCESS) ? mp_slip_used_rx_buffer : m_rx_ack_buffer,
                (err_code == NRF_SUCCESS) ? HCI_RX_BUF_SIZE : ACK_BUF_SIZE);

            APP_ERROR_CHECK(err_code);

            if (m_transport_event_handle != NULL)
            {
                // Send application event of RX packet reception.
                const hci_transport_evt_t evt = {HCI_TRANSPORT_RX_RDY};
                m_transport_event_handle(evt);
            }
        }
        else
        {
            // RX packet discarded: sequence number not valid, set the same buffer to slip layer in
            // order to avoid buffer overrun.
            err_code = hci_slip_rx_buffer_register(mp_slip_used_rx_buffer, HCI_RX_BUF_SIZE);
            APP_ERROR_CHECK(err_code);

            // As packet did not have expected sequence number: send acknowledgement with the
            // current expected sequence number.
            ack_transmit();
        }
    }
    else
    {
        // RX packet discarded: reset the same buffer to slip layer in order to avoid buffer
        // overrun.
        err_code = hci_slip_rx_buffer_register(mp_slip_used_rx_buffer, HCI_RX_BUF_SIZE);
        APP_ERROR_CHECK(err_code);
    }
}
/**@brief     Function for processing application data written by the peer to the DFU Packet
 *            Characteristic.
 *
 * @param[in] p_dfu     DFU Service Structure.
 * @param[in] p_evt     Pointer to the event received from the S110 SoftDevice.
 */
static void app_data_process(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt)
{
    uint32_t err_code;

    if ((p_evt->evt.ble_dfu_pkt_write.len & (sizeof(uint32_t) - 1)) != 0)
    {
        // Data length is not a multiple of 4 (word size).
        err_code = ble_dfu_response_send(p_dfu,
                                         BLE_DFU_RECEIVE_APP_PROCEDURE,
                                         BLE_DFU_RESP_VAL_NOT_SUPPORTED);
        APP_ERROR_CHECK(err_code);
        return;
    }

    uint32_t length = p_evt->evt.ble_dfu_pkt_write.len;
    
    err_code = hci_mem_pool_rx_produce(length, (void**) &mp_rx_buffer);
    if (err_code != NRF_SUCCESS)
    {
        dfu_error_notify(p_dfu, err_code);
        return;
    }
    
    uint8_t * p_data_packet = p_evt->evt.ble_dfu_pkt_write.p_data;
    memcpy(mp_rx_buffer, p_data_packet, length);

    err_code = hci_mem_pool_rx_data_size_set(length);
    if (err_code != NRF_SUCCESS)
    {
        dfu_error_notify(p_dfu, err_code);
        return;
    }

    err_code = hci_mem_pool_rx_extract(&mp_rx_buffer, &length);
    if (err_code != NRF_SUCCESS)
    {
        dfu_error_notify(p_dfu, err_code);
        return;
    }

    dfu_update_packet_t dfu_pkt;

    dfu_pkt.packet_type                      = DATA_PACKET;
    dfu_pkt.params.data_packet.packet_length = length / sizeof(uint32_t);
    dfu_pkt.params.data_packet.p_data_packet = (uint32_t*)mp_rx_buffer;
    
    err_code = dfu_data_pkt_handle(&dfu_pkt);

    if (err_code == NRF_SUCCESS)
    {
        // All the expected firmware data has been received and processed successfully.

        m_num_of_firmware_bytes_rcvd += p_evt->evt.ble_dfu_pkt_write.len;

        // Notify the DFU Controller about the success about the procedure.
        err_code = ble_dfu_response_send(p_dfu,
                                         BLE_DFU_RECEIVE_APP_PROCEDURE,
                                         BLE_DFU_RESP_VAL_SUCCESS);
        APP_ERROR_CHECK(err_code);
    }
    else if (err_code == NRF_ERROR_INVALID_LENGTH)
    {
        // Firmware data packet was handled successfully. And more firmware data is expected.
        m_num_of_firmware_bytes_rcvd += p_evt->evt.ble_dfu_pkt_write.len;

        // Check if a packet receipt notification is needed to be sent.
        if (m_pkt_rcpt_notif_enabled)
        {
            // Decrement the counter for the number firmware packets needed for sending the
            // next packet receipt notification.
            m_pkt_notif_target_cnt--;

            if (m_pkt_notif_target_cnt == 0)
            {
                err_code = ble_dfu_pkts_rcpt_notify(p_dfu, m_num_of_firmware_bytes_rcvd);
                APP_ERROR_CHECK(err_code);

                // Reset the counter for the number of firmware packets.
                m_pkt_notif_target_cnt = m_pkt_notif_target;
            }
        }
    }
    else
    {
        uint32_t hci_error = hci_mem_pool_rx_consume(mp_rx_buffer);
        if (hci_error != NRF_SUCCESS)
        {
            dfu_error_notify(p_dfu, hci_error);
        }
        
        dfu_error_notify(p_dfu, err_code);
    }
}