Skip to content

Commit

Permalink
- rename tuh_midi_stream_flush() to tuh_midi_write_flush()
Browse files Browse the repository at this point in the history
- add tuh_midi_packet_read_n() and tuh_midi_packet_write_n()
- add CFG_TUH_MIDI_STREAM_API to opt out stream API
  • Loading branch information
hathach committed Feb 14, 2025
1 parent 31a2696 commit 997771f
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 64 deletions.
102 changes: 58 additions & 44 deletions src/class/midi/midi_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,14 @@ typedef struct {
uint8_t num_cables_rx; // IN endpoint CS descriptor bNumEmbMIDIJack value
uint8_t num_cables_tx; // OUT endpoint CS descriptor bNumEmbMIDIJack value

#if CFG_TUH_MIDI_STREAM_API
// For Stream read()/write() API
// Messages are always 4 bytes long, queue them for reading and writing so the
// callers can use the Stream interface with single-byte read/write calls.
midi_driver_stream_t stream_write;
midi_driver_stream_t stream_read;
#endif

/*------------- From this point, data is not cleared by bus reset -------------*/
// Endpoint stream
struct {
tu_edpt_stream_t tx;
Expand Down Expand Up @@ -433,6 +434,57 @@ bool tuh_midi_configured(uint8_t dev_addr) {
return p_midi_host->configured;
}

uint8_t tuh_midi_get_num_tx_cables (uint8_t dev_addr) {
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
TU_VERIFY(p_midi_host != NULL, 0);
TU_VERIFY(p_midi_host->ep_stream.tx.ep_addr != 0, 0);
return p_midi_host->num_cables_tx;
}

uint8_t tuh_midi_get_num_rx_cables (uint8_t dev_addr) {
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
TU_VERIFY(p_midi_host != NULL, 0);
TU_VERIFY(p_midi_host->ep_stream.rx.ep_addr != 0, 0);
return p_midi_host->num_cables_rx;
}

uint32_t tuh_midi_read_available(uint8_t dev_addr) {
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
TU_VERIFY(p_midi_host != NULL);
return tu_edpt_stream_read_available(&p_midi_host->ep_stream.rx);
}

uint32_t tuh_midi_write_flush(uint8_t dev_addr) {
midih_interface_t *p_midi = find_midi_by_daddr(dev_addr);
TU_VERIFY(p_midi != NULL);
return tu_edpt_stream_write_xfer(p_midi->dev_addr, &p_midi->ep_stream.tx);
}

//--------------------------------------------------------------------+
// Packet API
//--------------------------------------------------------------------+

uint32_t tuh_midi_packet_read_n(uint8_t dev_addr, uint8_t* buffer, uint32_t bufsize) {
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
TU_VERIFY(p_midi_host != NULL);

uint32_t count4 = tu_min32(bufsize, tu_edpt_stream_read_available(&p_midi_host->ep_stream.rx));
count4 = tu_align4(count4); // round down to multiple of 4
TU_VERIFY(count4 > 0, 0);
return tu_edpt_stream_read(dev_addr, &p_midi_host->ep_stream.rx, buffer, count4);
}

uint32_t tuh_midi_packet_write_n(uint8_t dev_addr, const uint8_t* buffer, uint32_t bufsize) {
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
TU_VERIFY(p_midi_host != NULL, 0);
uint32_t bufsize4 = tu_align4(bufsize);
return tu_edpt_stream_write(dev_addr, &p_midi_host->ep_stream.tx, buffer, bufsize4);
}

//--------------------------------------------------------------------+
// Stream API
//--------------------------------------------------------------------+
#if CFG_TUH_MIDI_STREAM_API
uint32_t tuh_midi_stream_write(uint8_t dev_addr, uint8_t cable_num, uint8_t const *buffer, uint32_t bufsize) {
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
TU_VERIFY(p_midi_host != NULL);
Expand Down Expand Up @@ -530,47 +582,6 @@ uint32_t tuh_midi_stream_write(uint8_t dev_addr, uint8_t cable_num, uint8_t cons
return i;
}

bool tuh_midi_packet_write (uint8_t dev_addr, uint8_t const packet[4]) {
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
TU_VERIFY(p_midi_host != NULL);
return 4 == tu_edpt_stream_write(dev_addr, &p_midi_host->ep_stream.tx, packet, 4);
}

uint32_t tuh_midi_stream_flush(uint8_t dev_addr) {
midih_interface_t *p_midi = find_midi_by_daddr(dev_addr);
TU_VERIFY(p_midi != NULL);
return tu_edpt_stream_write_xfer(p_midi->dev_addr, &p_midi->ep_stream.tx);
}
//--------------------------------------------------------------------+
// Helper
//--------------------------------------------------------------------+
uint8_t tuh_midi_get_num_tx_cables (uint8_t dev_addr) {
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
TU_VERIFY(p_midi_host != NULL, 0);
TU_VERIFY(p_midi_host->ep_stream.tx.ep_addr != 0, 0);
return p_midi_host->num_cables_tx;
}

uint8_t tuh_midi_get_num_rx_cables (uint8_t dev_addr) {
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
TU_VERIFY(p_midi_host != NULL, 0);
TU_VERIFY(p_midi_host->ep_stream.rx.ep_addr != 0, 0);
return p_midi_host->num_cables_rx;
}

uint32_t tuh_midi_read_available(uint8_t dev_addr) {
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
TU_VERIFY(p_midi_host != NULL);
return tu_edpt_stream_read_available(&p_midi_host->ep_stream.rx);
}

bool tuh_midi_packet_read (uint8_t dev_addr, uint8_t packet[4]) {
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
TU_VERIFY(p_midi_host != NULL);
TU_VERIFY(tu_edpt_stream_read_available(&p_midi_host->ep_stream.rx) >= 4);
return 4 == tu_edpt_stream_read(dev_addr, &p_midi_host->ep_stream.rx, packet, 4);
}

uint32_t tuh_midi_stream_read(uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize) {
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
TU_VERIFY(p_midi_host != NULL);
Expand Down Expand Up @@ -669,6 +680,9 @@ uint32_t tuh_midi_stream_read(uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p
return bytes_buffered;
}

//--------------------------------------------------------------------+
// String API
//--------------------------------------------------------------------+
#if CFG_MIDI_HOST_DEVSTRINGS
static uint8_t find_string_index(midih_interface_t *ptr, uint8_t jack_id)
{
Expand All @@ -690,9 +704,7 @@ static uint8_t find_string_index(midih_interface_t *ptr, uint8_t jack_id)
}
return index;
}
#endif

#if CFG_MIDI_HOST_DEVSTRINGS
uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings) {
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
TU_VERIFY(p_midi_host != NULL, 0);
Expand Down Expand Up @@ -732,3 +744,5 @@ uint8_t tuh_midi_get_all_istrings(uint8_t dev_addr, const uint8_t** istrings)
return nstrings;
}
#endif

#endif
59 changes: 39 additions & 20 deletions src/class/midi/midi_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
* This file is part of the TinyUSB stack.
*/

#ifndef _TUSB_MIDI_HOST_H_
#define _TUSB_MIDI_HOST_H_
#ifndef TUSB_MIDI_HOST_H_
#define TUSB_MIDI_HOST_H_

#include "class/audio/audio.h"
#include "midi.h"
Expand Down Expand Up @@ -53,14 +53,20 @@
#define CFG_TUH_MIDI_EP_BUFSIZE TUH_EPSIZE_BULK_MPS
#endif

// Enable the MIDI stream read/write API. Some library can work with raw USB MIDI packet
// Disable this can save driver footprint.
#ifndef CFG_TUH_MIDI_STREAM_API
#define CFG_TUH_MIDI_STREAM_API 1
#endif

#ifndef CFG_MIDI_HOST_DEVSTRINGS
#define CFG_MIDI_HOST_DEVSTRINGS 0
#endif

//--------------------------------------------------------------------+
// Application API
//--------------------------------------------------------------------+
bool tuh_midi_configured (uint8_t dev_addr);
bool tuh_midi_configured (uint8_t dev_addr);

// return the number of virtual midi cables on the device's IN endpoint
uint8_t tuh_midi_get_num_rx_cables(uint8_t dev_addr);
Expand All @@ -74,40 +80,51 @@ uint8_t tuh_midi_get_tx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint
uint8_t tuh_midi_get_all_istrings(uint8_t dev_addr, const uint8_t** istrings);
#endif

// return the raw number of bytes available from device endpoint.
// return the raw number of bytes available.
// Note: this is related but not the same as number of stream bytes available.
uint32_t tuh_midi_read_available(uint8_t dev_addr);

// Send any queued packets to the device if the host hardware is able to do it
// Returns the number of bytes flushed to the host hardware or 0 if
// the host hardware is busy or there is nothing in queue to send.
uint32_t tuh_midi_write_flush( uint8_t dev_addr);

//--------------------------------------------------------------------+
// Packet API
//--------------------------------------------------------------------+

// Read all available MIDI packets from the connected device
// Return number of bytes read (always multiple of 4)
uint32_t tuh_midi_packet_read_n(uint8_t dev_addr, uint8_t* buffer, uint32_t bufsize);

// Read a raw MIDI packet from the connected device
// This function does not parse the packet format
// Return true if a packet was returned
bool tuh_midi_packet_read (uint8_t dev_addr, uint8_t packet[4]);
TU_ATTR_ALWAYS_INLINE static inline
bool tuh_midi_packet_read (uint8_t dev_addr, uint8_t packet[4]) {
return 4 == tuh_midi_packet_read_n(dev_addr, packet, 4);
}

// Write all 4-byte packets, data is locally buffered and only transferred when buffered bytes
// reach the endpoint packet size or tuh_midi_write_flush() is called
uint32_t tuh_midi_packet_write_n(uint8_t dev_addr, const uint8_t* buffer, uint32_t bufsize);

// Queue a packet to the device. The application
// must call tuh_midi_stream_flush to actually have the
// data go out. It is up to the application to properly
// format this packet; this function does not check.
// Write a 4-bytes packet to the device.
// Returns true if the packet was successfully queued.
bool tuh_midi_packet_write (uint8_t dev_addr, uint8_t const packet[4]);
TU_ATTR_ALWAYS_INLINE static inline
bool tuh_midi_packet_write (uint8_t dev_addr, uint8_t const packet[4]) {
return 4 == tuh_midi_packet_write_n(dev_addr, packet, 4);
}

//--------------------------------------------------------------------+
// Stream API
//--------------------------------------------------------------------+
#if CFG_TUH_MIDI_STREAM_API

// Queue a message to the device. The application
// must call tuh_midi_stream_flush to actually have the
// data go out.
// Queue a message to the device using stream API. data is locally buffered and only transferred when buffered bytes
// reach the endpoint packet size or tuh_midi_write_flush() is called
// Returns number of bytes was successfully queued.
uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t const* p_buffer, uint32_t bufsize);

// Send any queued packets to the device if the host hardware is able to do it
// Returns the number of bytes flushed to the host hardware or 0 if
// the host hardware is busy or there is nothing in queue to send.
uint32_t tuh_midi_stream_flush( uint8_t dev_addr);

// Get the MIDI stream from the device. Set the value pointed
// to by p_cable_num to the MIDI cable number intended to receive it.
// The MIDI stream will be stored in the buffer pointed to by p_buffer.
Expand All @@ -117,6 +134,8 @@ uint32_t tuh_midi_stream_flush( uint8_t dev_addr);
// it properly.
uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize);

#endif

//--------------------------------------------------------------------+
// Callbacks (Weak is optional)
//--------------------------------------------------------------------+
Expand Down Expand Up @@ -144,4 +163,4 @@ void midih_close (uint8_t dev_addr);
}
#endif

#endif /* _TUSB_MIDI_HOST_H_ */
#endif

0 comments on commit 997771f

Please sign in to comment.