summaryrefslogtreecommitdiff
path: root/src/class/midi/midi_host.h
blob: 57084cb1551f915a3743ecc10350d536e478c037 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/*
 * SPDX-FileCopyrightText: Copyright (c) 2019 Ha Thach (tinyusb.org)
 * SPDX-License-Identifier: MIT
 *
 * This file is part of the TinyUSB stack.
 */

#ifndef TUSB_MIDI_HOST_H_
#define TUSB_MIDI_HOST_H_

#include "class/audio/audio.h"
#include "midi.h"

#ifdef __cplusplus
extern "C" {
#endif

//--------------------------------------------------------------------+
// Class Driver Configuration
//--------------------------------------------------------------------+
#ifndef CFG_TUH_MIDI_RX_BUFSIZE
  #define CFG_TUH_MIDI_RX_BUFSIZE TUH_EPSIZE_BULK_MAX
#endif

#ifndef CFG_TUH_MIDI_TX_BUFSIZE
  #define CFG_TUH_MIDI_TX_BUFSIZE TUH_EPSIZE_BULK_MAX
#endif

#ifndef CFG_TUH_MIDI_EP_BUFSIZE
  #define CFG_TUH_MIDI_EP_BUFSIZE TUH_EPSIZE_BULK_MAX
#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

//--------------------------------------------------------------------+
// Application Types
//--------------------------------------------------------------------+
typedef struct {
  const tusb_desc_interface_t *desc_audio_control;
  const tusb_desc_interface_t *desc_midi; // start of whole midi interface descriptor
  uint16_t                     desc_midi_total_len;

  const uint8_t              *desc_header;
  const uint8_t              *desc_element;
  const tusb_desc_endpoint_t *desc_epin;  // endpoint IN descriptor, CS_ENDPOINT is right after
  const tusb_desc_endpoint_t *desc_epout; // endpoint OUT descriptor, CS_ENDPOINT is right after

  uint8_t        jack_num;
  const uint8_t *desc_jack[32];           // list of jack descriptors (embedded + external)
} tuh_midi_descriptor_cb_t;

typedef struct {
  uint8_t daddr;
  uint8_t bInterfaceNumber; // interface number of MIDI streaming
  uint8_t rx_cable_count;
  uint8_t tx_cable_count;
} tuh_midi_mount_cb_t;

//--------------------------------------------------------------------+
// Application API
//--------------------------------------------------------------------+

// Check if MIDI interface is mounted
bool tuh_midi_mounted(uint8_t idx);

// Get Interface index from device address + interface number
// return TUSB_INDEX_INVALID_8 (0xFF) if not found
uint8_t tuh_midi_itf_get_index(uint8_t daddr, uint8_t itf_num);

// Get Interface information
// return true if index is correct and interface is currently mounted
bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t *info);

// return the number of virtual midi cables on the device's IN endpoint
uint8_t tuh_midi_get_rx_cable_count(uint8_t idx);

// return the number of virtual midi cables on the device's OUT endpoint
uint8_t tuh_midi_get_tx_cable_count(uint8_t idx);

// 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 idx);

// 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 idx);

//--------------------------------------------------------------------+
// 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 idx, uint8_t *buffer, uint32_t bufsize);

// Read a raw MIDI packet from the connected device
// Return true if a packet was returned
TU_ATTR_ALWAYS_INLINE static inline bool tuh_midi_packet_read(uint8_t idx, uint8_t packet[4]) {
  return 4 == tuh_midi_packet_read_n(idx, 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 idx, const uint8_t *buffer, uint32_t bufsize);

// Write a 4-bytes packet to the device.
// Returns true if the packet was successfully queued.
TU_ATTR_ALWAYS_INLINE static inline bool tuh_midi_packet_write(uint8_t idx, const uint8_t packet[4]) {
  return 4 == tuh_midi_packet_write_n(idx, packet, 4);
}

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

// 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 idx, uint8_t cable_num, const uint8_t *p_buffer, uint32_t bufsize);

// 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.
// Return the number of bytes added to the buffer.
// Note that this function ignores the CIN field of the MIDI packet
// because a number of commercial devices out there do not encode
// it properly.
//
// NOTE: this function terminates when it encounters an event whose cable
// number differs from the one being returned. Applications should invoke
// it in a loop until it returns 0 (or until tuh_midi_read_available()
// returns 0) to guarantee the stream FIFO is fully drained per callback.
// Leaving bytes in the FIFO across callbacks can prevent subsequent bulk
// IN transfers from landing.
uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize);

#endif

//--------------------------------------------------------------------+
// Callbacks (Weak is optional)
//--------------------------------------------------------------------+

// Invoked when MIDI interface is detected in enumeration. Application can copy/parse descriptor if needed.
// Note: may be fired before tuh_midi_mount_cb(), therefore midi interface is not mounted/ready.
void tuh_midi_descriptor_cb(uint8_t idx, const tuh_midi_descriptor_cb_t *desc_cb_data);

// Invoked when device with MIDI interface is mounted.
void tuh_midi_mount_cb(uint8_t idx, const tuh_midi_mount_cb_t *mount_cb_data);

// Invoked when device with MIDI interface is un-mounted
void tuh_midi_umount_cb(uint8_t idx);

// Invoked when received new data
void tuh_midi_rx_cb(uint8_t idx, uint32_t xferred_bytes);

// Invoked when a TX is complete and therefore space becomes available in TX buffer
void tuh_midi_tx_cb(uint8_t idx, uint32_t xferred_bytes);

//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+
bool     midih_init(void);
bool     midih_deinit(void);
uint16_t midih_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface_t *desc_itf, uint16_t max_len);
bool     midih_set_config(uint8_t dev_addr, uint8_t itf_num);
bool     midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
void     midih_close(uint8_t daddr);

#ifdef __cplusplus
}
#endif

#endif