123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808 |
- /**
- * Copyright (c) 2013 - 2020, Nordic Semiconductor ASA
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form, except as embedded into a Nordic
- * Semiconductor ASA integrated circuit in a product or a software update for
- * such product, must reproduce the above copyright notice, this list of
- * conditions and the following disclaimer in the documentation and/or other
- * materials provided with the distribution.
- *
- * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * 4. This software, with or without modification, must only be used with a
- * Nordic Semiconductor ASA integrated circuit.
- *
- * 5. Any software provided in binary form under this license must not be reverse
- * engineered, decompiled, modified and/or disassembled.
- *
- * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
- #include "sdk_common.h"
- #if NRF_MODULE_ENABLED(HCI_TRANSPORT)
- #include "hci_transport.h"
- #include "hci_slip.h"
- #include "crc16.h"
- #include "hci_mem_pool.h"
- #include "app_timer.h"
- #include "app_error.h"
- #include <stdio.h>
- #define PKT_HDR_SIZE 4u /**< Packet header size in number of bytes. */
- #define PKT_CRC_SIZE 2u /**< Packet CRC size in number of bytes. */
- #define PKT_TYPE_VENDOR_SPECIFIC 14u /**< Packet type vendor specific. */
- #define PKT_TYPE_ACK 0 /**< Packet type acknowledgement. */
- #define DATA_INTEGRITY_MASK (1u << 6u) /**< Mask for data integrity bit in the packet header. */
- #define RELIABLE_PKT_MASK (1u << 7u) /**< Mask for reliable packet bit in the packet header. */
- #define INITIAL_ACK_NUMBER_EXPECTED 1u /**< Initial acknowledge number expected. */
- #define INITIAL_ACK_NUMBER_TX INITIAL_ACK_NUMBER_EXPECTED /**< Initial acknowledge number transmitted. */
- #define INVALID_PKT_TYPE 0xFFFFFFFFu /**< Internal invalid packet type value. */
- #define HCI_UART_REG_VALUE_TO_BAUDRATE(BAUDRATE) ((BAUDRATE)/268) /**< Estimated relation between UART baudrate register value and actual baudrate */
- #define MAX_TRANSMISSION_TIME \
- (ROUNDED_DIV((HCI_MAX_PACKET_SIZE_IN_BITS * 1000u), \
- HCI_UART_REG_VALUE_TO_BAUDRATE(HCI_UART_BAUDRATE))) /**< Max transmission time of a single application packet over UART in units of mseconds. */
- #define RETRANSMISSION_TIMEOUT_IN_MS (3u * MAX_TRANSMISSION_TIME) /**< Retransmission timeout for application packet in units of mseconds. */
- #define RETRANSMISSION_TIMEOUT_IN_TICKS APP_TIMER_TICKS(RETRANSMISSION_TIMEOUT_IN_MS) /**< Retransmission timeout for application packet in units of timer ticks. */
- #define MAX_RETRY_COUNT 5u /**< Max retransmission retry count for application packets. */
- #define ACK_BUF_SIZE 5u /**< Length of module internal RX buffer which is big enough to hold an acknowledgement packet. */
- /**@brief States of the TX state machine. */
- typedef enum
- {
- TX_STATE_IDLE, /**< State for: no application transmission packet processing in progress. */
- TX_STATE_PENDING, /**< State for: TX in progress in slip layer and TX-done event is waited for to signal the end of transmission. */
- TX_STATE_ACTIVE /**< State for: application packet has been delivered to slip for transmission and peer transport entity acknowledgement packet is waited for. */
- } tx_state_t;
- /**@brief TX state machine events. */
- typedef enum
- {
- TX_EVENT_STATE_ENTRY, /**< Event for: state entry use case. */
- TX_EVENT_SLIP_TX_DONE, /**< Event for: HCI_SLIP_TX_DONE event use case. */
- TX_EVENT_TIMEOUT, /**< Event for: retransmission timeout use case. */
- TX_EVENT_VALID_RX_ACK /**< Event for: valid acknowledgement received for TX packet use case. */
- } tx_event_t;
- static void tx_sm_state_change(tx_state_t new_state);
- static tx_state_t m_tx_state; /**< Current TX state. */
- static hci_transport_tx_done_handler_t m_transport_tx_done_handle; /**< TX done event callback function. */
- static hci_transport_event_handler_t m_transport_event_handle; /**< Event handler callback function. */
- static uint8_t * mp_slip_used_rx_buffer; /**< Reference to RX buffer used by the slip layer. */
- static uint32_t m_packet_expected_seq_number; /**< Sequence number counter of the packet expected to be received . */
- static uint32_t m_packet_transmit_seq_number; /**< Sequence number counter of the transmitted packet for which acknowledgement packet is waited for. */
- static uint8_t * mp_tx_buffer; /**< Pointer to TX application buffer to be transmitted. */
- static uint32_t m_tx_buffer_length; /**< Length of application TX packet data to be transmitted in bytes. */
- static bool m_is_slip_decode_ready; /**< Boolean to determine has slip decode been completed or not. */
- APP_TIMER_DEF(m_app_timer_id); /**< Application timer id. */
- static uint32_t m_tx_retry_counter; /**< Application packet retransmission counter. */
- static hci_transport_tx_done_result_t m_tx_done_result_code; /**< TX done event callback function result code. */
- static uint8_t m_rx_ack_buffer[ACK_BUF_SIZE];/**< RX buffer big enough to hold an acknowledgement packet and which is taken in use upon receiving HCI_SLIP_RX_OVERFLOW event. */
- /**@brief Function for validating a received packet.
- *
- * @param[in] p_buffer Pointer to the packet data.
- * @param[in] length Length of packet data in bytes.
- *
- * @return true if received packet is valid, false in other case.
- */
- static bool is_rx_pkt_valid(const uint8_t * p_buffer, uint32_t length)
- {
- // Executed packet filtering algorithm order:
- // - verify packet overall length
- // - verify data integrity bit set
- // - verify reliable packet bit set
- // - verify supported packet type
- // - verify header checksum
- // - verify payload length field
- // - verify CRC
- if (length <= PKT_HDR_SIZE)
- {
- return false;
- }
- if (!(p_buffer[0] & DATA_INTEGRITY_MASK))
- {
- return false;
- }
- if (!(p_buffer[0] & RELIABLE_PKT_MASK))
- {
- return false;
- }
- if ((p_buffer[1] & 0x0Fu) != PKT_TYPE_VENDOR_SPECIFIC)
- {
- return false;
- }
- const uint32_t expected_checksum =
- ((p_buffer[0] + p_buffer[1] + p_buffer[2] + p_buffer[3])) & 0xFFu;
- if (expected_checksum != 0)
- {
- return false;
- }
- const uint16_t crc_calculated = crc16_compute(p_buffer, (length - PKT_CRC_SIZE), NULL);
- const uint16_t crc_received = uint16_decode(&p_buffer[length - PKT_CRC_SIZE]);
- if (crc_calculated != crc_received)
- {
- return false;
- }
- return true;
- }
- /**@brief Function for getting the sequence number of the next reliable packet expected.
- *
- * @return sequence number of the next reliable packet expected.
- */
- static __INLINE uint8_t packet_number_expected_get(void)
- {
- return (uint8_t) m_packet_expected_seq_number;
- }
- /**@brief Function for calculating a packet header checksum.
- *
- * @param[in] p_hdr Pointer to the packet header.
- *
- * @return Calculated checksum.
- */
- static uint8_t header_checksum_calculate(const uint8_t * p_hdr)
- {
- // @note: no pointer validation check needed as already checked by calling function.
- uint32_t checksum;
- checksum = p_hdr[0];
- checksum += p_hdr[1];
- checksum += p_hdr[2];
- checksum &= 0xFFu;
- checksum = (~checksum + 1u);
- return (uint8_t)checksum;
- }
- /**@brief Function for writing an acknowledgment packet for transmission.
- */
- static void ack_transmit(void)
- {
- static uint8_t ack_packet[PKT_HDR_SIZE];
- // TX ACK packet format:
- // - Unreliable Packet type
- // - Payload Length set to 0
- // - Sequence Number set to 0
- // - Header checksum calculated
- // - Acknowledge Number set correctly
- ack_packet[0] = (packet_number_expected_get() << 3u);
- ack_packet[1] = 0;
- ack_packet[2] = 0;
- ack_packet[3] = header_checksum_calculate(ack_packet);
- // @note: no return value check needed for hci_slip_write(...) call as acknowledgement packets
- // are considered to be from system design point of view unreliable packets.Use case where
- // underlying slip layer does not accept a packet for transmission is managed either by:
- // - acknowledged by possible future application packet as acknowledgement number header field
- // is included
- // - protocol peer entity will retransmit the packet
- UNUSED_VARIABLE(hci_slip_write(ack_packet, sizeof(ack_packet)));
- }
- /**@brief Function for validating a received packet.
- *
- * @param[in] p_buffer Pointer to the packet data.
- *
- * @return sequence number field of the packet header with unrelated data masked out.
- */
- static __INLINE uint8_t packet_seq_nmbr_extract(const uint8_t * p_buffer)
- {
- return (p_buffer[0] & 0x07u);
- }
- /**@brief Function for incrementing the sequence number counter for next reliable packet expected.
- */
- static __INLINE void packet_number_expected_inc(void)
- {
- ++m_packet_expected_seq_number;
- m_packet_expected_seq_number &= 0x07u;
- }
- /**@brief Function for decoding a packet type field.
- *
- * @param[in] p_buffer Pointer to the packet data.
- * @param[in] length Length of packet data in bytes.
- *
- * @return Packet type field or INVALID_PKT_TYPE in case of decode error.
- */
- static __INLINE uint32_t packet_type_decode(const uint8_t * p_buffer, uint32_t length)
- {
- // @note: no pointer validation check needed as allready checked by calling function.
- uint32_t return_value;
- if (length >= PKT_HDR_SIZE)
- {
- return_value = (p_buffer[1] & 0x0Fu);
- }
- else
- {
- return_value = INVALID_PKT_TYPE;
- }
- return return_value;
- }
- /**@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 getting the sequence number of a reliable TX packet for which peer protocol
- * entity acknowledgment is pending.
- *
- * @return sequence number of a reliable TX packet for which peer protocol entity acknowledgement
- * is pending.
- */
- static __INLINE uint8_t packet_number_to_transmit_get(void)
- {
- return m_packet_transmit_seq_number;
- }
- /**@brief Function for getting the expected acknowledgement number.
- *
- * @return expected acknowledgement number.
- */
- static __INLINE uint8_t expected_ack_number_get(void)
- {
- uint8_t seq_nmbr = packet_number_to_transmit_get();
- ++seq_nmbr;
- seq_nmbr &= 0x07u;
- return seq_nmbr;
- }
- /**@brief Function for processing a received acknowledgement packet.
- *
- * Verifies does the received acknowledgement packet has the expected acknowledgement number and
- * that the header checksum is correct.
- *
- * @param[in] p_buffer Pointer to the packet data.
- *
- * @return true if valid acknowledgement packet received.
- */
- static __INLINE bool rx_ack_pkt_type_handle(const uint8_t * p_buffer)
- {
- // @note: no pointer validation check needed as allready checked by calling function.
- // Verify header checksum.
- const uint32_t expected_checksum =
- ((p_buffer[0] + p_buffer[1] + p_buffer[2] + p_buffer[3])) & 0xFFu;
- if (expected_checksum != 0)
- {
- return false;
- }
- const uint8_t ack_number = (p_buffer[0] >> 3u) & 0x07u;
- // Verify expected acknowledgment number.
- return (ack_number == expected_ack_number_get());
- }
- /**@brief Function for incrementing the sequence number counter of the TX packet.
- */
- static __INLINE void packet_number_tx_inc(void)
- {
- ++m_packet_transmit_seq_number;
- m_packet_transmit_seq_number &= 0x07u;
- }
- /**@brief Function for TX state machine event processing in a state centric manner.
- *
- * @param[in] event Type of event occurred.
- */
- static void tx_sm_event_handle(tx_event_t event)
- {
- uint32_t err_code;
- switch (m_tx_state)
- {
- case TX_STATE_IDLE:
- if (event == TX_EVENT_STATE_ENTRY)
- {
- err_code = app_timer_stop(m_app_timer_id);
- APP_ERROR_CHECK(err_code);
- // Send TX-done event if registered handler exists.
- if (m_transport_tx_done_handle != NULL)
- {
- m_transport_tx_done_handle(m_tx_done_result_code);
- }
- }
- break;
- case TX_STATE_PENDING:
- if (event == TX_EVENT_SLIP_TX_DONE)
- {
- // @note: this call should always succeed as called from HCI_SLIP_TX_DONE context
- // and error cases are managed by dedicated error event from the slip layer.
- err_code = hci_slip_write(mp_tx_buffer,
- (m_tx_buffer_length + PKT_HDR_SIZE + PKT_CRC_SIZE));
- APP_ERROR_CHECK(err_code);
- tx_sm_state_change(TX_STATE_ACTIVE);
- }
- break;
- case TX_STATE_ACTIVE:
- switch (event)
- {
- case TX_EVENT_VALID_RX_ACK:
- // Tx sequence number counter incremented as packet transmission
- // acknowledged by peer transport entity.
- packet_number_tx_inc();
- tx_sm_state_change(TX_STATE_IDLE);
- break;
- case TX_EVENT_STATE_ENTRY:
- m_tx_retry_counter = 0;
- err_code = app_timer_start(m_app_timer_id,
- RETRANSMISSION_TIMEOUT_IN_TICKS,
- NULL);
- APP_ERROR_CHECK(err_code);
- break;
- case TX_EVENT_TIMEOUT:
- if (m_tx_retry_counter != MAX_RETRY_COUNT)
- {
- ++m_tx_retry_counter;
- // @note: no return value check done for hci_slip_write(...) call as current
- // system design allows use case where retransmission is not accepted by the
- // slip layer due to existing acknowledgement packet transmission in the
- // slip layer.
- UNUSED_VARIABLE(hci_slip_write(mp_tx_buffer,
- (m_tx_buffer_length +
- PKT_HDR_SIZE +
- PKT_CRC_SIZE)));
- }
- else
- {
- // Application packet retransmission count reached:
- // - set correct TX done event callback function result code
- // - execute state change
- // @note: m_tx_retry_counter is reset in TX_STATE_ACTIVE state entry.
- m_tx_done_result_code = HCI_TRANSPORT_TX_DONE_FAILURE;
- tx_sm_state_change(TX_STATE_IDLE);
- }
- break;
- default:
- // No implementation needed.
- break;
- }
- break;
- default:
- // No implementation needed.
- break;
- }
- }
- /**@brief Function for changing the state of the TX state machine.
- *
- * @param[in] new_state State TX state machine transits to.
- */
- static void tx_sm_state_change(tx_state_t new_state)
- {
- m_tx_state = new_state;
- tx_sm_event_handle(TX_EVENT_STATE_ENTRY);
- }
- /**@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;
- }
- }
- uint32_t hci_transport_evt_handler_reg(hci_transport_event_handler_t event_handler)
- {
- uint32_t err_code;
- m_transport_event_handle = event_handler;
- err_code = hci_slip_evt_handler_register(slip_event_handle);
- APP_ERROR_CHECK(err_code);
- return (event_handler != NULL) ? NRF_SUCCESS : NRF_ERROR_NULL;
- }
- uint32_t hci_transport_tx_done_register(hci_transport_tx_done_handler_t event_handler)
- {
- uint32_t err_code;
- m_transport_tx_done_handle = event_handler;
- err_code = hci_slip_evt_handler_register(slip_event_handle);
- APP_ERROR_CHECK(err_code);
- return (event_handler != NULL) ? NRF_SUCCESS : NRF_ERROR_NULL;
- }
- /**@brief Function for handling the application packet retransmission timeout.
- *
- * This function is registered in the @ref app_timer module when a timer is created on
- * @ref hci_transport_open.
- *
- * @note This function must be executed in APP-LO context otherwise retransmission behaviour is
- * undefined, see @ref nrf51_system_integration_serialization.
- *
- * @param[in] p_context The timeout context.
- */
- void hci_transport_timeout_handle(void * p_context)
- {
- tx_sm_event_handle(TX_EVENT_TIMEOUT);
- }
- 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();
- VERIFY_SUCCESS(err_code);
- err_code = hci_slip_open();
- VERIFY_SUCCESS(err_code);
- err_code = hci_mem_pool_rx_produce(HCI_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, HCI_RX_BUF_SIZE);
- return err_code;
- }
- uint32_t hci_transport_close(void)
- {
- uint32_t err_code;
- m_transport_tx_done_handle = NULL;
- m_transport_event_handle = NULL;
- err_code = hci_mem_pool_close();
- APP_ERROR_CHECK(err_code);
- err_code = hci_slip_close();
- APP_ERROR_CHECK(err_code);
- // @note: NRF_ERROR_NO_MEM is the only return value which should never be returned.
- err_code = app_timer_stop(m_app_timer_id);
- APP_ERROR_CHECK_BOOL(err_code != NRF_ERROR_NO_MEM);
- return NRF_SUCCESS;
- }
- uint32_t hci_transport_tx_alloc(uint8_t ** pp_memory)
- {
- const uint32_t err_code = hci_mem_pool_tx_alloc((void **)pp_memory);
- if (err_code == NRF_SUCCESS)
- {
- // @note: no need to validate pp_memory against null as validation has already been done
- // by hci_mem_pool_tx_alloc(...) and visible to us from the method return code.
- //lint -e(413) "Likely use of null pointer"
- *pp_memory += PKT_HDR_SIZE;
- }
- return err_code;
- }
- uint32_t hci_transport_tx_free(void)
- {
- return hci_mem_pool_tx_free();
- }
- /**@brief Function for constructing 1st byte of the packet header of the packet to be transmitted.
- *
- * @return 1st byte of the packet header of the packet to be transmitted
- */
- static __INLINE uint8_t tx_packet_byte_zero_construct(void)
- {
- const uint32_t value = DATA_INTEGRITY_MASK |
- RELIABLE_PKT_MASK |
- (packet_number_expected_get() << 3u) |
- packet_number_to_transmit_get();
- return (uint8_t) value;
- }
- /**@brief Function for handling the application packet write request in tx-idle state.
- */
- static uint32_t pkt_write_handle(void)
- {
- uint32_t err_code;
- // Set packet header fields.
- mp_tx_buffer -= PKT_HDR_SIZE;
- mp_tx_buffer[0] = tx_packet_byte_zero_construct();
- const uint16_t type_and_length_fields = ((m_tx_buffer_length << 4u) | PKT_TYPE_VENDOR_SPECIFIC);
- // @note: no use case for uint16_encode(...) return value.
- UNUSED_VARIABLE(uint16_encode(type_and_length_fields, &(mp_tx_buffer[1])));
- mp_tx_buffer[3] = header_checksum_calculate(mp_tx_buffer);
- // Calculate, append CRC to the packet and write it.
- const uint16_t crc = crc16_compute(mp_tx_buffer, (PKT_HDR_SIZE + m_tx_buffer_length), NULL);
- // @note: no use case for uint16_encode(...) return value.
- UNUSED_VARIABLE(uint16_encode(crc, &(mp_tx_buffer[PKT_HDR_SIZE + m_tx_buffer_length])));
- err_code = hci_slip_write(mp_tx_buffer, (m_tx_buffer_length + PKT_HDR_SIZE + PKT_CRC_SIZE));
- switch (err_code)
- {
- case NRF_SUCCESS:
- tx_sm_state_change(TX_STATE_ACTIVE);
- break;
- case NRF_ERROR_NO_MEM:
- tx_sm_state_change(TX_STATE_PENDING);
- err_code = NRF_SUCCESS;
- break;
- default:
- // No implementation needed.
- break;
- }
- return err_code;
- }
- uint32_t hci_transport_pkt_write(const uint8_t * p_buffer, uint16_t length)
- {
- uint32_t err_code;
- if (p_buffer)
- {
- switch (m_tx_state)
- {
- case TX_STATE_IDLE:
- mp_tx_buffer = (uint8_t *)p_buffer;
- m_tx_buffer_length = length;
- err_code = pkt_write_handle();
- break;
- default:
- err_code = NRF_ERROR_NO_MEM;
- break;
- }
- }
- else
- {
- err_code = NRF_ERROR_NULL;
- }
- return err_code;
- }
- uint32_t hci_transport_rx_pkt_extract(uint8_t ** pp_buffer, uint16_t * p_length)
- {
- uint32_t err_code;
- if (pp_buffer != NULL && p_length != NULL)
- {
- uint32_t length = 0;
- if (m_is_slip_decode_ready)
- {
- m_is_slip_decode_ready = false;
- err_code = hci_mem_pool_rx_extract(pp_buffer, &length);
- length -= (PKT_HDR_SIZE + PKT_CRC_SIZE);
- *p_length = (uint16_t)length;
- *pp_buffer += PKT_HDR_SIZE;
- }
- else
- {
- err_code = NRF_ERROR_NO_MEM;
- }
- }
- else
- {
- err_code = NRF_ERROR_NULL;
- }
- return err_code;
- }
- uint32_t hci_transport_rx_pkt_consume(uint8_t * p_buffer)
- {
- return (hci_mem_pool_rx_consume(p_buffer - PKT_HDR_SIZE));
- }
- #endif //NRF_MODULE_ENABLED(HCI_TRANSPORT)
|