ALSA: usb-audio: keep MIDI input running for Roland TD-11

The TD-11 hands MIDI handling off to the host once connected via
USB. If no MIDI input port is opened on the host, the device itself
becomes unusable as a standalone instrument until its input is
serviced, independent of anything happening on the computer.

Add a per-device keep_input_running flag, set for the TD-11 in
snd_usbmidi_detect_roland(), and check it alongside the existing
opened[1] check in snd_usbmidi_input_start()/snd_usbmidi_input_stop()
so that input is started at device creation and never stopped for
these devices, regardless of whether a client has the input port
open.

Signed-off-by: Nicholas Hobson <nicholas.hobson@outlook.com>
Link: https://patch.msgid.link/MN2PR15MB3472557AF39DC3A4CA9E753FF8BD2@MN2PR15MB3472.namprd15.prod.outlook.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Nicholas Hobson 2026-09-12 03:28:42 +00:00 committed by Takashi Iwai
parent 5b6ea1bb8a
commit 2e4c9ab257

View File

@ -113,6 +113,7 @@ struct snd_usb_midi {
unsigned int opened[2];
unsigned char disconnected;
unsigned char input_running;
unsigned char keep_input_running;
struct snd_kcontrol *roland_load_ctl;
};
@ -1170,7 +1171,7 @@ static int substream_open(struct snd_rawmidi_substream *substream, int dir,
snd_usbmidi_input_start(&umidi->list);
} else {
umidi->opened[dir]--;
if (!umidi->opened[1])
if (!umidi->opened[1] && !umidi->keep_input_running)
snd_usbmidi_input_stop(&umidi->list);
if (!umidi->opened[0] && !umidi->opened[1]) {
if (umidi->roland_load_ctl) {
@ -2260,6 +2261,10 @@ static int snd_usbmidi_detect_roland(struct snd_usb_midi *umidi,
struct usb_host_interface *hostif;
u8 *cs_desc;
/* TD-11 becomes unusable if input isn't serviced continuously */
if (umidi->usb_id == USB_ID(0x0582, 0x0151))
umidi->keep_input_running = 1;
intf = umidi->iface;
if (!intf)
return -ENOENT;
@ -2467,7 +2472,7 @@ void snd_usbmidi_input_start(struct list_head *p)
int i;
umidi = list_entry(p, struct snd_usb_midi, list);
if (umidi->input_running || !umidi->opened[1])
if (umidi->input_running || (!umidi->opened[1] && !umidi->keep_input_running))
return;
for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
snd_usbmidi_input_start_ep(umidi, umidi->endpoints[i].in);
@ -2642,6 +2647,10 @@ int __snd_usbmidi_create(struct snd_card *card,
if (err < 0)
goto exit;
/* start input for devices that need continuous servicing */
if (umidi->keep_input_running)
snd_usbmidi_input_start(&umidi->list);
usb_autopm_get_interface_no_resume(umidi->iface);
list_add_tail(&umidi->list, midi_list);