|
| 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