ALSA: documentation: Add description for USB MIDI 2.0 gadget driver

The USB MIDI 2.0 gadget driver is now supported for 6.6 kernel, and
here we show a brief instruction how to enable and use it.

Link: https://lore.kernel.org/r/20230824075108.29958-5-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2023-08-24 09:51:08 +02:00
parent b2bcbd031d
commit e240cff9e6

View File

@ -376,3 +376,191 @@ Sequencer API Extensions
name and attributes accordingly, and notifies the changes via the
announcement to the ALSA sequencer system port, similarly like the
normal port change notification.
MIDI2 USB Gadget Function Driver
================================
The latest kernel contains the support for USB MIDI 2.0 gadget
function driver, which can be used for prototyping and debugging MIDI
2.0 features.
`CONFIG_USB_GADGET`, `CONFIG_USB_CONFIGFS` and
`CONFIG_USB_CONFIGFS_F_MIDI2` need to be enabled for the MIDI2 gadget
driver.
In addition, for using a gadget driver, you need a working UDC driver.
In the example below, we use `dummy_hcd` driver (enabled via
`CONFIG_USB_DUMMY_HCD`) that is available on PC and VM for debugging
purpose. There are other UDC drivers depending on the platform, and
those can be used for a real device, instead, too.
At first, on a system to run the gadget, load `libcomposite` module::
% modprobe libcomposite
and you'll have `usb_gadget` subdirectory under configfs space
(typically `/sys/kernel/config` on modern OS). Then create a gadget
instance and add configurations there, for example::
% cd /sys/kernel/config
% mkdir usb_gadget/g1
% cd usb_gadget/g1
% mkdir configs/c.1
% mkdir functions/midi2.usb0
% echo 0x0004 > idProduct
% echo 0x17b3 > idVendor
% mkdir strings/0x409
% echo "ACME Enterprises" > strings/0x409/manufacturer
% echo "ACMESynth" > strings/0x409/product
% echo "ABCD12345" > strings/0x409/serialnumber
% mkdir configs/c.1/strings/0x409
% echo "Monosynth" > configs/c.1/strings/0x409/configuration
% echo 120 > configs/c.1/MaxPower
At this point, there must be a subdirectory `ep.0`, and that is the
configuration for a UMP Endpoint. You can fill the Endpoint
information like::
% echo "ACMESynth" > functions/midi2.usb0/iface_name
% echo "ACMESynth" > functions/midi2.usb0/ep.0/ep_name
% echo "ABCD12345" > functions/midi2.usb0/ep.0/product_id
% echo 0x0123 > functions/midi2.usb0/ep.0/family
% echo 0x4567 > functions/midi2.usb0/ep.0/model
% echo 0x123456 > functions/midi2.usb0/ep.0/manufacturer
% echo 0x12345678 > functions/midi2.usb0/ep.0/sw_revision
The default MIDI protocol can be set either 1 or 2::
% echo 2 > functions/midi2.usb0/ep.0/protocol
And, you can find a subdirectory `block.0` under this Endpoint
subdirectory. This defines the Function Block information::
% echo "Monosynth" > functions/midi2.usb0/ep.0/block.0/name
% echo 0 > functions/midi2.usb0/ep.0/block.0/first_group
% echo 1 > functions/midi2.usb0/ep.0/block.0/num_groups
Finally, link the configuration and enable it::
% ln -s functions/midi2.usb0 configs/c.1
% echo dummy_udc.0 > UDC
where `dummy_udc.0` is an example case and it differs depending on the
system. You can find the UDC instances in `/sys/class/udc` and pass
the found name instead::
% ls /sys/class/udc
dummy_udc.0
Now, the MIDI 2.0 gadget device is enabled, and the gadget host
creates a new sound card instance containing a UMP rawmidi device by
`f_midi2` driver::
% cat /proc/asound/cards
....
1 [Gadget ]: f_midi2 - MIDI 2.0 Gadget
MIDI 2.0 Gadget
And on the connected host, a similar card should appear, too, but with
the card and device names given in the configfs above::
% cat /proc/asound/cards
....
2 [ACMESynth ]: USB-Audio - ACMESynth
ACME Enterprises ACMESynth at usb-dummy_hcd.0-1, high speed
You can play a MIDI file on the gadget side::
% aplaymidi -p 20:1 to_host.mid
and this will appear as an input from a MIDI device on the connected
host::
% aseqdump -p 20:0 -u 2
Vice versa, a playback on the connected host will work as an input on
the gadget, too.
Each Function Block may have different direction and UI-hint,
specified via `direction` and `ui_hint` attributes.
Passing `1` is for input-only, `2` for out-only and `3` for
bidirectional (the default value). For example::
% echo 2 > functions/midi2.usb0/ep.0/block.0/direction
% echo 2 > functions/midi2.usb0/ep.0/block.0/ui_hint
When you need more than one Function Blocks, you can create
subdirectories `block.1`, `block.2`, etc dynamically, and configure
them in the configuration procedure above before linking.
For example, to create a second Function Block for a keyboard::
% mkdir functions/midi2.usb0/ep.0/block.1
% echo "Keyboard" > functions/midi2.usb0/ep.0/block.1/name
% echo 1 > functions/midi2.usb0/ep.0/block.1/first_group
% echo 1 > functions/midi2.usb0/ep.0/block.1/num_groups
% echo 1 > functions/midi2.usb0/ep.0/block.1/direction
% echo 1 > functions/midi2.usb0/ep.0/block.1/ui_hint
The `block.*` subdirectories can be removed dynamically, too (except
for `block.0` which is persistent).
For assigning a Function Block for MIDI 1.0 I/O, set up in `is_midi1`
attribute. 1 is for MIDI 1.0, and 2 is for MIDI 1.0 with low speed
connection::
% echo 2 > functions/midi2.usb0/ep.0/block.1/is_midi1
For disabling the processing of UMP Stream messages in the gadget
driver, pass `0` to `process_ump attribute in the top-level config::
% echo 0 > functions/midi2.usb0/process_ump
The MIDI 1.0 interface at altset 0 is supported by the gadget driver,
too. When MIDI 1.0 interface is selected by the connected host, the
UMP I/O on the gadget is translated from/to USB MIDI 1.0 packets
accordingly while the gadget driver keeps communicating with the
user-space over UMP rawmidi.
MIDI 1.0 ports are set up from the config in each Function Block.
For example::
% echo 0 > functions/midi2.usb0/ep.0/block.0/midi1_first_group
% echo 1 > functions/midi2.usb0/ep.0/block.0/midi1_num_groups
The configuration above will enable the Group 1 (the index 0) for MIDI
1.0 interface. Note that those groups must be in the groups defined
for the Function Block itself.
The gadget driver supports more than one UMP Endpoints, too.
Similarly like the Function Blocks, you can create a new subdirectory
`ep.1` (but under the card top-level config) to enable a new Endpoint::
% mkdir functions/midi2.usb0/ep.1
and create a new Function Block there. For example, to create 4
Groups for the Function Block of this new Endpoint::
% mkdir functions/midi2.usb0/ep.1/block.0
% echo 4 > functions/midi2.usb0/ep.1/block.0/num_groups
Now, you'll have 4 rawmidi devices in total: the first two are UMP
rawmidi devices for Endpoint 0 and Endpoint 1, and other two for the
legacy MIDI 1.0 rawmidi devices corresponding to both EP 0 and EP 1.
The current altsetting on the gadget can be informed via a control
element "Operation Mode" with `RAWMIDI` iface. e.g. you can read it
via `amixer` program running on the gadget host like::
% amixer -c1 cget iface=RAWMIDI,name='Operation Mode'
; type=INTEGER,access=r--v----,values=1,min=0,max=2,step=0
: values=2
The value (shown in the second returned line with `: values=`)
indicates 1 for MIDI 1.0 (altset 0), 2 for MIDI 2.0 (altset 1) and 0
for unset.
As of now, the configurations can't be changed after binding.