Skip to content

Commit ff49d1d

Browse files
committed
ALSA: usb-audio: USB MIDI 2.0 UMP support
This patch provides a basic support for USB MIDI 2.0. As of this patch, the driver creates a UMP device per MIDI I/O endpoints, which serves as a dumb terminal to read/write UMP streams. A new Kconfig CONFIG_SND_USB_AUDIO_MIDI_V2 manages whether to enable or disable the MIDI 2.0 support. Also, the driver provides a new module option, midi2_enable, to allow disabling the MIDI 2.0 at runtime, too. When MIDI 2.0 support is disabled, the driver tries to fall back to the already existing MIDI 1.0 device (each MIDI 2.0 device is supposed to provide the MIDI 1.0 interface at the altset 0). For now, the driver doesn't manage any MIDI-CI or other protocol setups by itself, but relies on the default protocol given via the group terminal block descriptors. The MIDI 1.0 messages on MIDI 2.0 device will be automatically converted in ALSA sequencer in a later patch. As of this commit, the driver accepts merely the rawmidi UMP accesses. The driver builds up the topology in the following way: - Create an object for each MIDI endpoint belonging to the USB interface - Find MIDI EP "pairs" that share the same GTB; note that MIDI EP is unidirectional, while UMP is (normally) bidirectional, so two MIDI EPs can form a single UMP EP - A UMP endpoint object is created for each I/O pair - For remaining "solo" MIDI EPs, create unidirectional UMP EPs - Finally, parse GTBs and fill the protocol bits on each UMP So the driver may support multiple UMP Endpoints in theory, although most devices are supposed to have a single UMP EP that can contain up to 16 groups -- which should be large enough. Reviewed-by: Jaroslav Kysela <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent f8ddb0f commit ff49d1d

File tree

7 files changed

+1109
-5
lines changed

7 files changed

+1109
-5
lines changed

sound/usb/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ config SND_USB_AUDIO
1515
select SND_HWDEP
1616
select SND_RAWMIDI
1717
select SND_PCM
18+
select SND_UMP if SND_USB_AUDIO_MIDI_V2
1819
select BITREVERSE
1920
select SND_USB_AUDIO_USE_MEDIA_CONTROLLER if MEDIA_CONTROLLER && (MEDIA_SUPPORT=y || MEDIA_SUPPORT=SND_USB_AUDIO)
2021
help
@@ -24,6 +25,16 @@ config SND_USB_AUDIO
2425
To compile this driver as a module, choose M here: the module
2526
will be called snd-usb-audio.
2627

28+
config SND_USB_AUDIO_MIDI_V2
29+
bool "MIDI 2.0 support by USB Audio driver"
30+
depends on SND_USB_AUDIO
31+
help
32+
Say Y here to include the support for MIDI 2.0 by USB Audio driver.
33+
When the config is set, the driver tries to probe MIDI 2.0 interface
34+
at first, then falls back to MIDI 1.0 interface as default.
35+
The MIDI 2.0 support can be disabled dynamically via midi2_enable
36+
module option, too.
37+
2738
config SND_USB_AUDIO_USE_MEDIA_CONTROLLER
2839
bool
2940

sound/usb/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ snd-usb-audio-objs := card.o \
2222
stream.o \
2323
validate.o
2424

25+
snd-usb-audio-$(CONFIG_SND_USB_AUDIO_MIDI_V2) += midi2.o
2526
snd-usb-audio-$(CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER) += media.o
2627

2728
snd-usbmidi-lib-objs := midi.o

sound/usb/card.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include "usbaudio.h"
4545
#include "card.h"
4646
#include "midi.h"
47+
#include "midi2.h"
4748
#include "mixer.h"
4849
#include "proc.h"
4950
#include "quirks.h"
@@ -178,10 +179,8 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int
178179
if ((altsd->bInterfaceClass == USB_CLASS_AUDIO ||
179180
altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC) &&
180181
altsd->bInterfaceSubClass == USB_SUBCLASS_MIDISTREAMING) {
181-
int err = __snd_usbmidi_create(chip->card, iface,
182-
&chip->midi_list, NULL,
183-
chip->usb_id,
184-
&chip->num_rawmidis);
182+
int err = snd_usb_midi_v2_create(chip, iface, NULL,
183+
chip->usb_id);
185184
if (err < 0) {
186185
dev_err(&dev->dev,
187186
"%u:%d: cannot create sequencer device\n",
@@ -486,6 +485,7 @@ static void snd_usb_audio_free(struct snd_card *card)
486485
struct snd_usb_audio *chip = card->private_data;
487486

488487
snd_usb_endpoint_free_all(chip);
488+
snd_usb_midi_v2_free_all(chip);
489489

490490
mutex_destroy(&chip->mutex);
491491
if (!atomic_read(&chip->shutdown))
@@ -645,6 +645,7 @@ static int snd_usb_audio_create(struct usb_interface *intf,
645645
INIT_LIST_HEAD(&chip->iface_ref_list);
646646
INIT_LIST_HEAD(&chip->clock_ref_list);
647647
INIT_LIST_HEAD(&chip->midi_list);
648+
INIT_LIST_HEAD(&chip->midi_v2_list);
648649
INIT_LIST_HEAD(&chip->mixer_list);
649650

650651
if (quirk_flags[idx])
@@ -969,6 +970,7 @@ static void usb_audio_disconnect(struct usb_interface *intf)
969970
list_for_each(p, &chip->midi_list) {
970971
snd_usbmidi_disconnect(p);
971972
}
973+
snd_usb_midi_v2_disconnect_all(chip);
972974
/*
973975
* Nice to check quirk && quirk->shares_media_device and
974976
* then call the snd_media_device_delete(). Don't have
@@ -1080,6 +1082,7 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
10801082
snd_usbmidi_suspend(p);
10811083
list_for_each_entry(mixer, &chip->mixer_list, list)
10821084
snd_usb_mixer_suspend(mixer);
1085+
snd_usb_midi_v2_suspend_all(chip);
10831086
}
10841087

10851088
if (!PMSG_IS_AUTO(message) && !chip->system_suspend) {
@@ -1125,6 +1128,8 @@ static int usb_audio_resume(struct usb_interface *intf)
11251128
snd_usbmidi_resume(p);
11261129
}
11271130

1131+
snd_usb_midi_v2_resume_all(chip);
1132+
11281133
out:
11291134
if (chip->num_suspended_intf == chip->system_suspend) {
11301135
snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);

0 commit comments

Comments
 (0)