Skip to content

Commit 508b662

Browse files
committed
Merge branch 'topic/midi20' into for-next
As the updated MIDI 2.0 spec has been published freshly, this is a catch up to add the support for new specs, especially UMP v1.1 features, on Linux kernel. The new UMP v1.1 introduced the concept of Function Blocks (FB), which is a kind of superset of USB MIDI 2.0 Group Terminal Blocks (GTB). The patch set adds the support for FB as the primary information source while keeping the parse of GTB as fallback. Also UMP v1.1 supports the groupless messages, the protocol switch, static FBs, and other new fundamental features, and those are supported as well. Link: https://www.midi.org/midi-articles/details-about-midi-2-0-midi-ci-profiles-and-property-exchange Link: https://lore.kernel.org/r/20230612081054.17200-1-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
2 parents 9b44694 + febdfa0 commit 508b662

10 files changed

Lines changed: 962 additions & 12 deletions

File tree

Documentation/sound/designs/midi-2.0.rst

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,15 @@ default instead of the MIDI 1.0 interface (at altset 0). You can
6868
switch back to the binding with the old MIDI 1.0 interface by passing
6969
`midi2_enable=0` option to snd-usb-audio driver module, too.
7070

71+
The USB audio driver tries to query the UMP Endpoint and UMP Function
72+
Block information that are provided since UMP v1.1, and builds up the
73+
topology based on those information. When the device is older and
74+
doesn't respond to the new UMP inquiries, the driver falls back and
75+
builds the topology based on Group Terminal Block (GTB) information
76+
from the USB descriptor. Some device might be screwed up by the
77+
unexpected UMP command; in such a case, pass `midi2_probe=0` option to
78+
snd-usb-audio driver for skipping the UMP v1.1 inquiries.
79+
7180
When the MIDI 2.0 device is probed, the kernel creates a rawmidi
7281
device for each UMP Endpoint of the device. Its device name is
7382
`/dev/snd/umpC*D*` and different from the standard rawmidi device name
@@ -101,11 +110,15 @@ opening `/dev/snd/midiC*D*` will end up with opening the first
101110
substream.
102111

103112
Each UMP Endpoint can provide the additional information, constructed
104-
from USB MIDI 2.0 descriptors. And a UMP Endpoint may contain one or
105-
more UMP Blocks, where UMP Block is an abstraction introduced in the
106-
ALSA UMP implementations to represent the associations among UMP
107-
Groups. UMP Block corresponds to Group Terminal Block (GTB) in USB
108-
MIDI 2.0 specifications but provide a few more generic information.
113+
from the information inquired via UMP 1.1 Stream messages or USB MIDI
114+
2.0 descriptors. And a UMP Endpoint may contain one or more UMP
115+
Blocks, where UMP Block is an abstraction introduced in the ALSA UMP
116+
implementations to represent the associations among UMP Groups. UMP
117+
Block corresponds to Function Block in UMP 1.1 specification. When
118+
UMP 1.1 Function Block information isn't available, it's filled
119+
partially from Group Terminal Block (GTB) as defined in USB MIDI 2.0
120+
specifications.
121+
109122
The information of UMP Endpoints and UMP Blocks are found in the proc
110123
file `/proc/asound/card*/midi*`. For example::
111124

@@ -207,6 +220,8 @@ The "MIDI 2.0" port is for a UMP Endpoint, and its difference from
207220
other UMP Group ports is that UMP Endpoint port sends the events from
208221
the all ports on the device ("catch-all"), while each UMP Group port
209222
sends only the events from the given UMP Group.
223+
Also, UMP groupless messages (such as the UMP message type 0x0f) are
224+
sent only to the UMP Endpoint port.
210225

211226
Note that, although each UMP sequencer client usually creates 16
212227
ports, those ports that don't belong to any UMP Blocks (or belonging
@@ -273,6 +288,11 @@ Rawmidi API Extensions
273288
The direction is either `SNDRV_UMP_DIR_INPUT`,
274289
`SNDRV_UMP_DIR_OUTPUT` or `SNDRV_UMP_DIR_BIDIRECTION`.
275290

291+
* For the device supports UMP v1.1, the UMP MIDI protocol can be
292+
switched via "Stream Configuration Request" message (UMP type 0x0f,
293+
status 0x05). When UMP core receives such a message, it updates the
294+
UMP EP info and the corresponding sequencer clients as well.
295+
276296

277297
Control API Extensions
278298
======================
@@ -337,7 +357,7 @@ Sequencer API Extensions
337357
`group_filter` bitmap. The filter consists of bitmap from 1-based
338358
Group numbers. For example, when the bit 1 is set, messages from
339359
Group 1 (i.e. the very first group) are filtered and not delivered.
340-
The bit 0 is reserved for future use.
360+
The bit 0 is used for filtering UMP groupless messages.
341361

342362
* Two new ioctls are added for UMP-capable clients:
343363
`SNDRV_SEQ_IOCTL_GET_CLIENT_UMP_INFO` and
@@ -349,3 +369,10 @@ Sequencer API Extensions
349369
For an Endpoint data, pass 0 to the `type` field, while for a Block
350370
data, pass the block number + 1 to the `type` field.
351371
Setting the data for a kernel client shall result in an error.
372+
373+
* With UMP 1.1, Function Block information may be changed
374+
dynamically. When the update of Function Block is received from the
375+
device, ALSA sequencer core changes the corresponding sequencer port
376+
name and attributes accordingly, and notifies the changes via the
377+
announcement to the ALSA sequencer system port, similarly like the
378+
normal port change notification.

include/sound/ump.h

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ struct snd_ump_endpoint {
2424
void *private_data;
2525
void (*private_free)(struct snd_ump_endpoint *ump);
2626

27+
/* UMP Stream message processing */
28+
u32 stream_wait_for; /* expected stream message status */
29+
bool stream_finished; /* set when message has been processed */
30+
bool parsed; /* UMP / FB parse finished? */
31+
wait_queue_head_t stream_wait;
32+
struct snd_rawmidi_file stream_rfile;
33+
2734
struct list_head block_list; /* list of snd_ump_block objects */
2835

2936
/* intermediate buffer for UMP input */
@@ -63,6 +70,9 @@ struct snd_ump_ops {
6370
struct snd_seq_ump_ops {
6471
void (*input_receive)(struct snd_ump_endpoint *ump,
6572
const u32 *data, int words);
73+
int (*notify_fb_change)(struct snd_ump_endpoint *ump,
74+
struct snd_ump_block *fb);
75+
int (*switch_protocol)(struct snd_ump_endpoint *ump);
6676
};
6777

6878
struct snd_ump_block {
@@ -80,6 +90,7 @@ struct snd_ump_block {
8090
int snd_ump_endpoint_new(struct snd_card *card, char *id, int device,
8191
int output, int input,
8292
struct snd_ump_endpoint **ump_ret);
93+
int snd_ump_parse_endpoint(struct snd_ump_endpoint *ump);
8394
int snd_ump_block_new(struct snd_ump_endpoint *ump, unsigned int blk,
8495
unsigned int direction, unsigned int first_group,
8596
unsigned int num_groups, struct snd_ump_block **blk_ret);
@@ -109,6 +120,8 @@ enum {
109120
UMP_MSG_TYPE_DATA = 0x03,
110121
UMP_MSG_TYPE_MIDI2_CHANNEL_VOICE = 0x04,
111122
UMP_MSG_TYPE_EXTENDED_DATA = 0x05,
123+
UMP_MSG_TYPE_FLEX_DATA = 0x0d,
124+
UMP_MSG_TYPE_STREAM = 0x0f,
112125
};
113126

114127
/* MIDI 2.0 SysEx / Data Status; same values for both 7-bit and 8-bit SysEx */
@@ -119,6 +132,62 @@ enum {
119132
UMP_SYSEX_STATUS_END = 3,
120133
};
121134

135+
/* UMP Utility Type Status (type 0x0) */
136+
enum {
137+
UMP_UTILITY_MSG_STATUS_NOOP = 0x00,
138+
UMP_UTILITY_MSG_STATUS_JR_CLOCK = 0x01,
139+
UMP_UTILITY_MSG_STATUS_JR_TSTAMP = 0x02,
140+
UMP_UTILITY_MSG_STATUS_DCTPQ = 0x03,
141+
UMP_UTILITY_MSG_STATUS_DC = 0x04,
142+
};
143+
144+
/* UMP Stream Message Status (type 0xf) */
145+
enum {
146+
UMP_STREAM_MSG_STATUS_EP_DISCOVERY = 0x00,
147+
UMP_STREAM_MSG_STATUS_EP_INFO = 0x01,
148+
UMP_STREAM_MSG_STATUS_DEVICE_INFO = 0x02,
149+
UMP_STREAM_MSG_STATUS_EP_NAME = 0x03,
150+
UMP_STREAM_MSG_STATUS_PRODUCT_ID = 0x04,
151+
UMP_STREAM_MSG_STATUS_STREAM_CFG_REQUEST = 0x05,
152+
UMP_STREAM_MSG_STATUS_STREAM_CFG = 0x06,
153+
UMP_STREAM_MSG_STATUS_FB_DISCOVERY = 0x10,
154+
UMP_STREAM_MSG_STATUS_FB_INFO = 0x11,
155+
UMP_STREAM_MSG_STATUS_FB_NAME = 0x12,
156+
UMP_STREAM_MSG_STATUS_START_CLIP = 0x20,
157+
UMP_STREAM_MSG_STATUS_END_CLIP = 0x21,
158+
};
159+
160+
/* UMP Endpoint Discovery filter bitmap */
161+
enum {
162+
UMP_STREAM_MSG_REQUEST_EP_INFO = (1U << 0),
163+
UMP_STREAM_MSG_REQUEST_DEVICE_INFO = (1U << 1),
164+
UMP_STREAM_MSG_REQUEST_EP_NAME = (1U << 2),
165+
UMP_STREAM_MSG_REQUEST_PRODUCT_ID = (1U << 3),
166+
UMP_STREAM_MSG_REQUEST_STREAM_CFG = (1U << 4),
167+
};
168+
169+
/* UMP Function Block Discovery filter bitmap */
170+
enum {
171+
UMP_STREAM_MSG_REQUEST_FB_INFO = (1U << 0),
172+
UMP_STREAM_MSG_REQUEST_FB_NAME = (1U << 1),
173+
};
174+
175+
/* UMP Endpoint Info capability bits (used for protocol request/notify, too) */
176+
enum {
177+
UMP_STREAM_MSG_EP_INFO_CAP_TXJR = (1U << 0), /* Sending JRTS */
178+
UMP_STREAM_MSG_EP_INFO_CAP_RXJR = (1U << 1), /* Receiving JRTS */
179+
UMP_STREAM_MSG_EP_INFO_CAP_MIDI1 = (1U << 8), /* MIDI 1.0 */
180+
UMP_STREAM_MSG_EP_INFO_CAP_MIDI2 = (1U << 9), /* MIDI 2.0 */
181+
};
182+
183+
/* UMP EP / FB name string format; same as SysEx string handling */
184+
enum {
185+
UMP_STREAM_MSG_FORMAT_SINGLE = 0,
186+
UMP_STREAM_MSG_FORMAT_START = 1,
187+
UMP_STREAM_MSG_FORMAT_CONTINUE = 2,
188+
UMP_STREAM_MSG_FORMAT_END = 3,
189+
};
190+
122191
/*
123192
* Helpers for retrieving / filling bits from UMP
124193
*/
@@ -172,4 +241,24 @@ static inline unsigned char ump_sysex_message_length(u32 data)
172241
return (data >> 16) & 0xf;
173242
}
174243

244+
/* For Stream Messages */
245+
static inline unsigned char ump_stream_message_format(u32 data)
246+
{
247+
return (data >> 26) & 0x03;
248+
}
249+
250+
static inline unsigned int ump_stream_message_status(u32 data)
251+
{
252+
return (data >> 16) & 0x3ff;
253+
}
254+
255+
static inline u32 ump_stream_compose(unsigned char status, unsigned short form)
256+
{
257+
return (UMP_MSG_TYPE_STREAM << 28) | ((u32)form << 26) |
258+
((u32)status << 16);
259+
}
260+
261+
#define ump_is_groupless_msg(type) \
262+
((type) == UMP_MSG_TYPE_UTILITY || (type) == UMP_MSG_TYPE_STREAM)
263+
175264
#endif /* __SOUND_UMP_H */

0 commit comments

Comments
 (0)