Skip to content

Commit 6b39e30

Browse files
committed
ALSA: docs: Add MIDI 2.0 documentation
Add the brief document for describing the MIDI 2.0 implementation on Linux kernel. Both rawmidi and sequencer API extensions are described. Acked-by: Jaroslav Kysela <perex@perex.cz> Link: https://lore.kernel.org/r/20230523075358.9672-38-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent d2b7060 commit 6b39e30

2 files changed

Lines changed: 352 additions & 0 deletions

File tree

Documentation/sound/designs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ Designs and Implementations
1515
oss-emulation
1616
seq-oss
1717
jack-injection
18+
midi-2.0
Lines changed: 351 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,351 @@
1+
=================
2+
MIDI 2.0 on Linux
3+
=================
4+
5+
General
6+
=======
7+
8+
MIDI 2.0 is an extended protocol for providing higher resolutions and
9+
more fine controls over the legacy MIDI 1.0. The fundamental changes
10+
introduced for supporting MIDI 2.0 are:
11+
12+
- Support of Universal MIDI Packet (UMP)
13+
- Support of MIDI 2.0 protocol messages
14+
- Transparent conversions between UMP and legacy MIDI 1.0 byte stream
15+
- MIDI-CI for property and profile configurations
16+
17+
UMP is a new container format to hold all MIDI protocol 1.0 and MIDI
18+
2.0 protocol messages. Unlike the former byte stream, it's 32bit
19+
aligned, and each message can be put in a single packet. UMP can send
20+
the events up to 16 "UMP Groups", where each UMP Group contain up to
21+
16 MIDI channels.
22+
23+
MIDI 2.0 protocol is an extended protocol to achieve the higher
24+
resolution and more controls over the old MIDI 1.0 protocol.
25+
26+
MIDI-CI is a high-level protocol that can talk with the MIDI device
27+
for the flexible profiles and configurations. It's represented in the
28+
form of special SysEx.
29+
30+
For Linux implementations, the kernel supports the UMP transport and
31+
the encoding/decoding of MIDI protocols on UMP, while MIDI-CI is
32+
supported in user-space over the standard SysEx.
33+
34+
As of this writing, only USB MIDI device supports the UMP and Linux
35+
2.0 natively. The UMP support itself is pretty generic, hence it
36+
could be used by other transport layers, although it could be
37+
implemented differently (e.g. as a ALSA sequencer client), too.
38+
39+
The access to UMP devices are provided in two ways: the access via
40+
rawmidi device and the access via ALSA sequencer API.
41+
42+
ALSA sequencer API was extended to allow the payload of UMP packets.
43+
It's allowed to connect freely between MIDI 1.0 and MIDI 2.0 sequencer
44+
clients, and the events are converted transparently.
45+
46+
47+
Kernel Configuration
48+
====================
49+
50+
The following new configs are added for supporting MIDI 2.0:
51+
`CONFIG_SND_UMP`, `CONFIG_SND_UMP_LEGACY_RAWMIDI`,
52+
`CONFIG_SND_SEQ_UMP`, `CONFIG_SND_SEQ_UMP_CLIENT`, and
53+
`CONFIG_SND_USB_AUDIO_MIDI_V2`. The first visible one is
54+
`CONFIG_SND_USB_AUDIO_MIDI_V2`, and when you choose it (to set `=y`),
55+
the core support for UMP (`CONFIG_SND_UMP`) and the sequencer binding
56+
(`CONFIG_SND_SEQ_UMP_CLIENT`) will be automatically selected.
57+
58+
Additionally, `CONFIG_SND_UMP_LEGACY_RAWMIDI=y` will enable the
59+
support for the legacy raw MIDI device for UMP Endpoints.
60+
61+
62+
Rawmidi Device with USB MIDI 2.0
63+
================================
64+
65+
When a device supports MIDI 2.0, the USB-audio driver probes and uses
66+
the MIDI 2.0 interface (that is found always at the altset 1) as
67+
default instead of the MIDI 1.0 interface (at altset 0). You can
68+
switch back to the binding with the old MIDI 1.0 interface by passing
69+
`midi2_enable=0` option to snd-usb-audio driver module, too.
70+
71+
When the MIDI 2.0 device is probed, the kernel creates a rawmidi
72+
device for each UMP Endpoint of the device. Its device name is
73+
`/dev/snd/umpC*D*` and different from the standard rawmidi device name
74+
`/dev/snd/midiC*D*` for MIDI 1.0, in order to avoid confusing the
75+
legacy applications accessing mistakenly to UMP devices.
76+
77+
You can read and write UMP packet data directly from/to this UMP
78+
rawmidi device. For example, reading via `hexdump` like below will
79+
show the incoming UMP packets of the card 0 device 0 in the hex
80+
format::
81+
82+
% hexdump -C /dev/snd/umpC0D0
83+
00000000 01 07 b0 20 00 07 b0 20 64 3c 90 20 64 3c 80 20 |... ... d<. d<. |
84+
85+
Unlike the MIDI 1.0 byte stream, UMP is a 32bit packet, and the size
86+
for reading or writing the device is also aligned to 32bit (which is 4
87+
bytes).
88+
89+
The 32-bit words in the UMP packet payload are always in CPU native
90+
endianness. Transport drivers are responsible to convert UMP words
91+
from / to system endianness to required transport endianness / byte
92+
order.
93+
94+
When `CONFIG_SND_UMP_LEGACY_RAWMIDI` is set, the driver creates
95+
another standard raw MIDI device additionally as `/dev/snd/midiC*D*`.
96+
This contains 16 substreams, and each substream corresponds to a
97+
(0-based) UMP Group. Legacy applications can access to the specified
98+
group via each substream in MIDI 1.0 byte stream format. With the
99+
ALSA rawmidi API, you can open the arbitrary substream, while just
100+
opening `/dev/snd/midiC*D*` will end up with opening the first
101+
substream.
102+
103+
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.
109+
The information of UMP Endpoints and UMP Blocks are found in the proc
110+
file `/proc/asound/card*/midi*`. For example::
111+
112+
% cat /proc/asound/card1/midi0
113+
ProtoZOA MIDI
114+
115+
Type: UMP
116+
EP Name: ProtoZOA
117+
EP Product ID: ABCD12345678
118+
UMP Version: 0x0000
119+
Protocol Caps: 0x00000100
120+
Protocol: 0x00000100
121+
Num Blocks: 3
122+
123+
Block 0 (ProtoZOA Main)
124+
Direction: bidirection
125+
Active: Yes
126+
Groups: 1-1
127+
Is MIDI1: No
128+
129+
Block 1 (ProtoZOA Ext IN)
130+
Direction: output
131+
Active: Yes
132+
Groups: 2-2
133+
Is MIDI1: Yes (Low Speed)
134+
....
135+
136+
Note that `Groups` field shown in the proc file above indicates the
137+
1-based UMP Group numbers (from-to).
138+
139+
Those additional UMP Endpoint and UMP Block information can be
140+
obtained via the new ioctls `SNDRV_UMP_IOCTL_ENDPOINT_INFO` and
141+
`SNDRV_UMP_IOCTL_BLOCK_INFO`, respectively.
142+
143+
The rawmidi name and the UMP Endpoint name are usually identical, and
144+
in the case of USB MIDI, it's taken from `iInterface` of the
145+
corresponding USB MIDI interface descriptor. If it's not provided,
146+
it's copied from `iProduct` of the USB device descriptor as a
147+
fallback.
148+
149+
The Endpoint Product ID is a string field and supposed to be unique.
150+
It's copied from `iSerialNumber` of the device for USB MIDI.
151+
152+
The protocol capabilities and the actual protocol bits are defined in
153+
`asound.h`.
154+
155+
156+
ALSA Sequencer with USB MIDI 2.0
157+
================================
158+
159+
In addition to the rawmidi interfaces, ALSA sequencer interface
160+
supports the new UMP MIDI 2.0 device, too. Now, each ALSA sequencer
161+
client may set its MIDI version (0, 1 or 2) to declare itself being
162+
either the legacy, UMP MIDI 1.0 or UMP MIDI 2.0 device, respectively.
163+
The first, legacy client is the one that sends/receives the old
164+
sequencer event as was. Meanwhile, UMP MIDI 1.0 and 2.0 clients send
165+
and receive in the extended event record for UMP. The MIDI version is
166+
seen in the new `midi_version` field of `snd_seq_client_info`.
167+
168+
A UMP packet can be sent/received in a sequencer event embedded by
169+
specifying the new event flag bit `SNDRV_SEQ_EVENT_UMP`. When this
170+
flag is set, the event has 16 byte (128 bit) data payload for holding
171+
the UMP packet. Without the `SNDRV_SEQ_EVENT_UMP` bit flag, the event
172+
is treated as a legacy event as it was (with max 12 byte data
173+
payload).
174+
175+
With `SNDRV_SEQ_EVENT_UMP` flag set, the type field of a UMP sequencer
176+
event is ignored (but it should be set to 0 as default).
177+
178+
The type of each client can be seen in `/proc/asound/seq/clients`.
179+
For example::
180+
181+
% cat /proc/asound/seq/clients
182+
Client info
183+
cur clients : 3
184+
....
185+
Client 14 : "Midi Through" [Kernel Legacy]
186+
Port 0 : "Midi Through Port-0" (RWe-)
187+
Client 20 : "ProtoZOA" [Kernel UMP MIDI1]
188+
UMP Endpoint: ProtoZOA
189+
UMP Block 0: ProtoZOA Main [Active]
190+
Groups: 1-1
191+
UMP Block 1: ProtoZOA Ext IN [Active]
192+
Groups: 2-2
193+
UMP Block 2: ProtoZOA Ext OUT [Active]
194+
Groups: 3-3
195+
Port 0 : "MIDI 2.0" (RWeX) [In/Out]
196+
Port 1 : "ProtoZOA Main" (RWeX) [In/Out]
197+
Port 2 : "ProtoZOA Ext IN" (-We-) [Out]
198+
Port 3 : "ProtoZOA Ext OUT" (R-e-) [In]
199+
200+
Here you can find two types of kernel clients, "Legacy" for client 14,
201+
and "UMP MIDI1" for client 20, which is a USB MIDI 2.0 device.
202+
A USB MIDI 2.0 client gives always the port 0 as "MIDI 2.0" and the
203+
rest ports from 1 for each UMP Group (e.g. port 1 for Group 1).
204+
In this example, the device has three active groups (Main, Ext IN and
205+
Ext OUT), and those are exposed as sequencer ports from 1 to 3.
206+
The "MIDI 2.0" port is for a UMP Endpoint, and its difference from
207+
other UMP Group ports is that UMP Endpoint port sends the events from
208+
the all ports on the device ("catch-all"), while each UMP Group port
209+
sends only the events from the given UMP Group.
210+
211+
Note that, although each UMP sequencer client usually creates 16
212+
ports, those ports that don't belong to any UMP Blocks (or belonging
213+
to inactive UMP Blocks) are marked as inactive, and they don't appear
214+
in the proc outputs. In the example above, the sequencer ports from 4
215+
to 16 are present but not shown there.
216+
217+
The proc file above shows the UMP Block information, too. The same
218+
entry (but with more detailed information) is found in the rawmidi
219+
proc output.
220+
221+
When clients are connected between different MIDI versions, the events
222+
are translated automatically depending on the client's version, not
223+
only between the legacy and the UMP MIDI 1.0/2.0 types, but also
224+
between UMP MIDI 1.0 and 2.0 types, too. For example, running
225+
`aseqdump` program on the ProtoZOA Main port in the legacy mode will
226+
give you the output like::
227+
228+
% aseqdump -p 20:1
229+
Waiting for data. Press Ctrl+C to end.
230+
Source Event Ch Data
231+
20:1 Note on 0, note 60, velocity 100
232+
20:1 Note off 0, note 60, velocity 100
233+
20:1 Control change 0, controller 11, value 4
234+
235+
When you run `aseqdump` in MIDI 2.0 mode, it'll receive the high
236+
precision data like::
237+
238+
% aseqdump -u 2 -p 20:1
239+
Waiting for data. Press Ctrl+C to end.
240+
Source Event Ch Data
241+
20:1 Note on 0, note 60, velocity 0xc924, attr type = 0, data = 0x0
242+
20:1 Note off 0, note 60, velocity 0xc924, attr type = 0, data = 0x0
243+
20:1 Control change 0, controller 11, value 0x2000000
244+
245+
while the data is automatically converted by ALSA sequencer core.
246+
247+
248+
Rawmidi API Extensions
249+
======================
250+
251+
* The additional UMP Endpoint information can be obtained via the new
252+
ioctl `SNDRV_UMP_IOCTL_ENDPOINT_INFO`. It contains the associated
253+
card and device numbers, the bit flags, the protocols, the number of
254+
UMP Blocks, the name string of the endpoint, etc.
255+
256+
The protocols are specified in two field, the protocol capabilities
257+
and the current protocol. Both contain the bit flags specifying the
258+
MIDI protocol version (`SNDRV_UMP_EP_INFO_PROTO_MIDI1` or
259+
`SNDRV_UMP_EP_INFO_PROTO_MIDI2`) in the upper byte and the jitter
260+
reduction timestamp (`SNDRV_UMP_EP_INFO_PROTO_JRTS_TX` and
261+
`SNDRV_UMP_EP_INFO_PROTO_JRTS_RX`) in the lower byte.
262+
263+
A UMP Endpoint may contain up to 32 UMP Blocks, and the number of
264+
the currently assigned blocks are shown in the Endpoint information.
265+
266+
* Each UMP Block information can be obtained via another new ioctl
267+
`SNDRV_UMP_IOCTL_BLOCK_INFO`. The block ID number (0-based) has to
268+
be passed for the block to query. The received data contains the
269+
associated the direction of the block, the first associated group ID
270+
(0-based) and the number of groups, the name string of the block,
271+
etc.
272+
273+
The direction is either `SNDRV_UMP_DIR_INPUT`,
274+
`SNDRV_UMP_DIR_OUTPUT` or `SNDRV_UMP_DIR_BIDIRECTION`.
275+
276+
277+
Control API Extensions
278+
======================
279+
280+
* The new ioctl `SNDRV_CTL_IOCTL_UMP_NEXT_DEVICE` is introduced for
281+
querying the next UMP rawmidi device, while the existing ioctl
282+
`SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE` queries only the legacy
283+
rawmidi devices.
284+
285+
For setting the subdevice (substream number) to be opened, use the
286+
ioctl `SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE` like the normal
287+
rawmidi.
288+
289+
* Two new ioctls `SNDRV_CTL_IOCTL_UMP_ENDPOINT_INFO` and
290+
`SNDRV_CTL_IOCTL_UMP_BLOCK_INFO` provide the UMP Endpoint and UMP
291+
Block information of the specified UMP device via ALSA control API
292+
without opening the actual (UMP) rawmidi device.
293+
The `card` field is ignored upon inquiry, always tied with the card
294+
of the control interface.
295+
296+
297+
Sequencer API Extensions
298+
========================
299+
300+
* `midi_version` field is added to `snd_seq_client_info` to indicate
301+
the current MIDI version (either 0, 1 or 2) of each client.
302+
When `midi_version` is 1 or 2, the alignment of read from a UMP
303+
sequencer client is also changed from the former 28 bytes to 32
304+
bytes for the extended payload. The alignment size for the write
305+
isn't changed, but each event size may differ depending on the new
306+
bit flag below.
307+
308+
* `SNDRV_SEQ_EVENT_UMP` flag bit is added for each sequencer event
309+
flags. When this bit flag is set, the sequencer event is extended
310+
to have a larger payload of 16 bytes instead of the legacy 12
311+
bytes, and the event contains the UMP packet in the payload.
312+
313+
* The new sequencer port type bit (`SNDRV_SEQ_PORT_TYPE_MIDI_UMP`)
314+
indicates the port being UMP-capable.
315+
316+
* The sequencer ports have new capability bits to indicate the
317+
inactive ports (`SNDRV_SEQ_PORT_CAP_INACTIVE`) and the UMP Endpoint
318+
port (`SNDRV_SEQ_PORT_CAP_UMP_ENDPOINT`).
319+
320+
* The event conversion of ALSA sequencer clients can be suppressed the
321+
new filter bit `SNDRV_SEQ_FILTER_NO_CONVERT` set to the client info.
322+
For example, the kernel pass-through client (`snd-seq-dummy`) sets
323+
this flag internally.
324+
325+
* The port information gained the new field `direction` to indicate
326+
the direction of the port (either `SNDRV_SEQ_PORT_DIR_INPUT`,
327+
`SNDRV_SEQ_PORT_DIR_OUTPUT` or `SNDRV_SEQ_PORT_DIR_BIDIRECTION`).
328+
329+
* Another additional field for the port information is `ump_group`
330+
which specifies the associated UMP Group Number (1-based).
331+
When it's non-zero, the UMP group field in the UMP packet updated
332+
upon delivery to the specified group (corrected to be 0-based).
333+
Each sequencer port is supposed to set this field if it's a port to
334+
specific to a certain UMP group.
335+
336+
* Each client may set the additional event filter for UMP Groups in
337+
`group_filter` bitmap. The filter consists of bitmap from 1-based
338+
Group numbers. For example, when the bit 1 is set, messages from
339+
Group 1 (i.e. the very first group) are filtered and not delivered.
340+
The bit 0 is reserved for future use.
341+
342+
* Two new ioctls are added for UMP-capable clients:
343+
`SNDRV_SEQ_IOCTL_GET_CLIENT_UMP_INFO` and
344+
`SNDRV_SEQ_IOCTL_SET_CLIENT_UMP_INFO`. They are used to get and set
345+
either `snd_ump_endpoint_info` or `snd_ump_block_info` data
346+
associated with the sequencer client. The USB MIDI driver provides
347+
those information from the underlying UMP rawmidi, while a
348+
user-space client may provide its own data via `*_SET` ioctl.
349+
For an Endpoint data, pass 0 to the `type` field, while for a Block
350+
data, pass the block number + 1 to the `type` field.
351+
Setting the data for a kernel client shall result in an error.

0 commit comments

Comments
 (0)