LCOV - code coverage report
Current view: top level - src/MIDI_Interfaces/USBMIDI/LowLevel - BulkTX.hpp (source / functions) Coverage Total Hit
Test: 73449d9b107c772cf65493691543348214e5d5eb Lines: 100.0 % 3 3
Test Date: 2026-06-06 17:44:35 Functions: 100.0 % 2 2
Legend: Lines:     hit not hit

            Line data    Source code
       1              : #pragma once
       2              : 
       3              : #include <cstddef>
       4              : 
       5              : #include <MIDI_Interfaces/USBMIDI/util/Atomic.hpp>
       6              : #include <Settings/NamespaceSettings.hpp>
       7              : 
       8              : BEGIN_CS_NAMESPACE
       9              : 
      10              : /// Sends Bulk packets (IN for device mode, OUT for host mode)
      11              : template <class Derived, class MessageTypeT, uint16_t MaxPacketSizeV>
      12              : struct BulkTX {
      13              :   public:
      14              :     using MessageType = MessageTypeT;
      15              : 
      16              :     /// Send a MIDI USB message. May block.
      17              :     ///
      18              :     /// @param  msg
      19              :     ///         The 4-byte MIDI USB message to send.
      20              :     void write(MessageType msg);
      21              : 
      22              :     /// Send multiple MIDI USB messages. May block.
      23              :     ///
      24              :     /// @param  msgs
      25              :     ///         An array of 4-byte MIDI USB messages to send.
      26              :     /// @param  num_msgs
      27              :     ///         The number of messages in the array.
      28              :     void write(const MessageType *msgs, uint32_t num_msgs);
      29              : 
      30              :     /// Send multiple MIDI USB messages. May block.
      31              :     template <size_t N>
      32              :     void write(const MessageType (&msgs)[N]) {
      33              :         write(msgs, N);
      34              :     }
      35              : 
      36              :     /// Send multiple MIDI USB messages without blocking.
      37              :     ///
      38              :     /// @param  msgs
      39              :     ///         An array of 4-byte MIDI USB messages to send.
      40              :     /// @param  num_msgs
      41              :     ///         The number of messages in the array.
      42              :     /// @return The number of messages that were actually sent.
      43              :     uint32_t write_nonblock(const MessageType *msgs, uint32_t num_msgs);
      44              : 
      45              :     /// Try sending the buffered data now.
      46              :     /// Start transmitting the latest packet if possible, even if it isn't full
      47              :     /// yet. If the latest packet is empty, this function has no effect.
      48              :     void send_now();
      49              : 
      50              :     /// Check if all transfers have completed.
      51              :     bool is_done() const;
      52              : 
      53              :     /// Get the number messages that failed to send.
      54              :     uint32_t getWriteError() const { return writing.error.load(mo_rlx); }
      55              :     /// Get and clear the number messages that failed to send.
      56              :     uint32_t clearWriteError() { return writing.error.exchange(0, mo_rlx); }
      57              : 
      58              :   protected:
      59              :     void reset(uint16_t packet_size = MaxPacketSize);
      60              :     bool wait_connect();
      61              : 
      62              :   private:
      63              :     static constexpr uint16_t MaxPacketSize = MaxPacketSizeV;
      64              :     static constexpr uint16_t SizeReserved = MaxPacketSize + 1;
      65              : 
      66              :   protected:
      67              :     // Derived should implement the following methods:
      68              : 
      69              :     /// Start a timeout (e.g. using a timer interrupt) that later calls
      70              :     /// @ref timeout_callback().
      71              :     void start_timeout() = delete;
      72              :     /// Cancel the timeout started by @ref timeout_callback().
      73              :     void cancel_timeout() = delete;
      74              :     /// Start a USB transfer (from the main program).
      75              :     void tx_start(const void *data, uint32_t size) = delete;
      76              :     /// Start a USB transfer (from the timeout callback).
      77              :     void tx_start_timeout(const void *data, uint32_t size) = delete;
      78              :     /// Start a USB transfer (from the USB interrupt handler).
      79              :     void tx_start_isr(const void *data, uint32_t size) = delete;
      80              : 
      81              :   private:
      82              :     constexpr static std::memory_order mo_seq = std::memory_order_seq_cst;
      83              :     constexpr static std::memory_order mo_rel = std::memory_order_release;
      84              :     constexpr static std::memory_order mo_acq = std::memory_order_acquire;
      85              :     constexpr static std::memory_order mo_rlx = std::memory_order_relaxed;
      86              :     constexpr static std::memory_order mo_acq_rel = std::memory_order_acq_rel;
      87              : 
      88              :     /// State for writing outgoing USB-MIDI data.
      89              :     struct Writing {
      90              :         struct Buffer {
      91              :             uint16_t size {0};
      92              :             alignas(MessageType) uint8_t buffer[MaxPacketSize];
      93              :         } buffers[2];
      94              :         interrupt_atomic<Buffer *> active_writebuffer {&buffers[0]};
      95              :         interrupt_atomic<Buffer *> sending {nullptr};
      96              :         interrupt_atomic<Buffer *> send_later {nullptr};
      97              :         interrupt_atomic<Buffer *> send_now {nullptr};
      98              :         interrupt_atomic<uint32_t> error {0};
      99              :         uint16_t packet_size = MaxPacketSize;
     100              :     } writing;
     101              :     using wbuffer_t = typename Writing::Buffer;
     102              :     bool disconnected = false;
     103              : 
     104        94936 :     uint32_t index_of(wbuffer_t *p) const { return p - writing.buffers; }
     105        94936 :     wbuffer_t *other_buf(wbuffer_t *p) {
     106        94936 :         return &writing.buffers[!index_of(p)];
     107              :     }
     108              :     uint32_t write_impl(const MessageType *msgs, uint32_t num_msgs);
     109              : 
     110              :   protected:
     111              :     void timeout_callback();
     112              :     void tx_callback();
     113              : };
     114              : 
     115              : END_CS_NAMESPACE
     116              : 
     117              : #include "BulkTX.ipp"
        

Generated by: LCOV version 2.4-beta