示例#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);
    }
}
示例#2
0
uint32_t hci_transport_open(void)
{
    mp_tx_buffer                 = NULL;
    m_tx_buffer_length           = 0;
    m_tx_retry_counter           = 0;
    m_is_slip_decode_ready       = false;
    m_tx_state                   = TX_STATE_IDLE;
    m_packet_expected_seq_number = INITIAL_ACK_NUMBER_EXPECTED;
    m_packet_transmit_seq_number = INITIAL_ACK_NUMBER_TX;
    m_tx_done_result_code        = HCI_TRANSPORT_TX_DONE_FAILURE;
    
    uint32_t err_code = app_timer_create(&m_app_timer_id, 
                                         APP_TIMER_MODE_REPEATED, 
                                         hci_transport_timeout_handle);
    if (err_code != NRF_SUCCESS)
    {    
        // @note: conduct required interface adjustment.
        return NRF_ERROR_INTERNAL;
    }
    
    err_code = hci_mem_pool_open();
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }    
    
    err_code = hci_slip_open();
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }     
    
    err_code = hci_mem_pool_rx_produce(RX_BUF_SIZE, (void **)&mp_slip_used_rx_buffer);
    if (err_code != NRF_SUCCESS)
    {
        // @note: conduct required interface adjustment.
        return NRF_ERROR_INTERNAL;
    }   
    
    err_code = hci_slip_rx_buffer_register(mp_slip_used_rx_buffer, RX_BUF_SIZE);
    
    return err_code;    
}
示例#3
0
/**@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);
    }
}
示例#4
0
/**@brief Function for handling slip events.
 *
 * @param[in] event The event structure.
 */
void slip_event_handle(hci_slip_evt_t event)
{
    uint32_t return_code;
    uint32_t err_code;

    switch (event.evt_type)
    {
        case HCI_SLIP_TX_DONE:
            tx_sm_event_handle(TX_EVENT_SLIP_TX_DONE);
            break;

        case HCI_SLIP_RX_RDY:
            return_code = packet_type_decode(event.packet, event.packet_length);

            switch (return_code)
            {
                case PKT_TYPE_VENDOR_SPECIFIC:
                    rx_vendor_specific_pkt_type_handle(event.packet, event.packet_length);
                    break;

                case PKT_TYPE_ACK:
                    if (rx_ack_pkt_type_handle(event.packet))
                    {
                        // Valid expected acknowledgement packet received: set correct TX done event
                        // callback function result code and execute state change.
                        m_tx_done_result_code = HCI_TRANSPORT_TX_DONE_SUCCESS;
                        tx_sm_event_handle(TX_EVENT_VALID_RX_ACK);
                    }

                /* fall-through */
                default:
                    // RX packet dropped: reset memory buffer to slip in order to avoid RX buffer
                    // overflow.
                    // If existing mem pool produced RX buffer exists reuse that one. If existing
                    // mem pool produced RX buffer does not exist try to produce new one. If
                    // producing fails use the internal acknowledgement buffer.
                    if (mp_slip_used_rx_buffer != NULL)
                    {
                        err_code = hci_slip_rx_buffer_register(mp_slip_used_rx_buffer, HCI_RX_BUF_SIZE);
                        APP_ERROR_CHECK(err_code);
                    }
                    else
                    {
                        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));

                        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);
                    }
                    break;
            }
            break;

        case HCI_SLIP_RX_OVERFLOW:
            err_code = hci_slip_rx_buffer_register(m_rx_ack_buffer, ACK_BUF_SIZE);
            APP_ERROR_CHECK(err_code);
            break;

        case HCI_SLIP_ERROR:
            APP_ERROR_HANDLER(event.evt_type);
            break;

        default:
            APP_ERROR_HANDLER(event.evt_type);
            break;
    }
}