Commit 81fd444a authored by Takashi Iwai's avatar Takashi Iwai

ALSA: seq: Bind UMP device

This patch introduces a new ALSA sequencer client for the kernel UMP
object, snd-seq-ump-client.  It's a UMP version of snd-seq-midi
driver, while this driver creates a sequencer client per UMP endpoint
which contains (fixed) 16 ports.

The UMP rawmidi device is opened in APPEND mode for output, so that
multiple sequencer clients can share the same UMP endpoint, as well as
the legacy UMP rawmidi devices that are opened in APPEND mode, too.
For input, on the other hand, the incoming data is processed on the
fly in the dedicated hook, hence it doesn't open a rawmidi device.

The UMP packet group is updated upon delivery depending on the target
sequencer port (which corresponds to the actual UMP group).

Each sequencer port sets a new port type bit,
SNDRV_SEQ_PORT_TYPE_MIDI_UMP, in addition to the other standard
types for MIDI.
Reviewed-by: default avatarJaroslav Kysela <perex@perex.cz>
Link: https://lore.kernel.org/r/20230523075358.9672-33-tiwai@suse.deSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 329ffe11
......@@ -78,5 +78,6 @@ void snd_seq_driver_unregister(struct snd_seq_driver *drv);
*/
#define SNDRV_SEQ_DEV_ID_MIDISYNTH "seq-midi"
#define SNDRV_SEQ_DEV_ID_OPL3 "opl3-synth"
#define SNDRV_SEQ_DEV_ID_UMP "seq-ump-client"
#endif /* __SOUND_SEQ_DEVICE_H */
......@@ -11,6 +11,7 @@ struct snd_ump_endpoint;
struct snd_ump_block;
struct snd_ump_ops;
struct ump_cvt_to_ump;
struct snd_seq_ump_ops;
struct snd_ump_endpoint {
struct snd_rawmidi core; /* raw UMP access */
......@@ -30,9 +31,9 @@ struct snd_ump_endpoint {
int input_buf_head;
int input_pending;
#if IS_ENABLED(CONFIG_SND_UMP_LEGACY_RAWMIDI)
struct mutex open_mutex;
#if IS_ENABLED(CONFIG_SND_UMP_LEGACY_RAWMIDI)
spinlock_t legacy_locks[2];
struct snd_rawmidi *legacy_rmidi;
struct snd_rawmidi_substream *legacy_substreams[2][SNDRV_UMP_MAX_GROUPS];
......@@ -42,6 +43,12 @@ struct snd_ump_endpoint {
struct snd_rawmidi_file legacy_out_rfile;
struct ump_cvt_to_ump *out_cvts;
#endif
#if IS_ENABLED(CONFIG_SND_SEQUENCER)
struct snd_seq_device *seq_dev;
const struct snd_seq_ump_ops *seq_ops;
void *seq_client;
#endif
};
/* ops filled by UMP drivers */
......@@ -52,6 +59,12 @@ struct snd_ump_ops {
void (*drain)(struct snd_ump_endpoint *ump, int dir);
};
/* ops filled by sequencer binding */
struct snd_seq_ump_ops {
void (*input_receive)(struct snd_ump_endpoint *ump,
const u32 *data, int words);
};
struct snd_ump_block {
struct snd_ump_block_info info;
struct snd_ump_endpoint *ump;
......
......@@ -439,6 +439,7 @@ struct snd_seq_remove_events {
#define SNDRV_SEQ_PORT_TYPE_MIDI_XG (1<<4) /* XG compatible device */
#define SNDRV_SEQ_PORT_TYPE_MIDI_MT32 (1<<5) /* MT-32 compatible device */
#define SNDRV_SEQ_PORT_TYPE_MIDI_GM2 (1<<6) /* General MIDI 2 compatible device */
#define SNDRV_SEQ_PORT_TYPE_MIDI_UMP (1<<7) /* UMP */
/* other standards...*/
#define SNDRV_SEQ_PORT_TYPE_SYNTH (1<<10) /* Synth device (no MIDI compatible - direct wavetable) */
......
......@@ -62,6 +62,7 @@ config SND_SEQ_VIRMIDI
config SND_SEQ_UMP
bool "Support for UMP events"
default y if SND_SEQ_UMP_CLIENT
help
Say Y here to enable the support for handling UMP (Universal MIDI
Packet) events via ALSA sequencer infrastructure, which is an
......@@ -69,4 +70,8 @@ config SND_SEQ_UMP
It includes the automatic conversion of ALSA sequencer events
among legacy and UMP clients.
config SND_SEQ_UMP_CLIENT
tristate
def_tristate SND_UMP
endif # SND_SEQUENCER
......@@ -14,12 +14,14 @@ snd-seq-midi-emul-objs := seq_midi_emul.o
snd-seq-midi-event-objs := seq_midi_event.o
snd-seq-dummy-objs := seq_dummy.o
snd-seq-virmidi-objs := seq_virmidi.o
snd-seq-ump-client-objs := seq_ump_client.o
obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o
obj-$(CONFIG_SND_SEQUENCER_OSS) += oss/
obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o
obj-$(CONFIG_SND_SEQ_MIDI) += snd-seq-midi.o
obj-$(CONFIG_SND_SEQ_UMP_CLIENT) += snd-seq-ump-client.o
obj-$(CONFIG_SND_SEQ_MIDI_EMUL) += snd-seq-midi-emul.o
obj-$(CONFIG_SND_SEQ_MIDI_EVENT) += snd-seq-midi-event.o
obj-$(CONFIG_SND_SEQ_VIRMIDI) += snd-seq-virmidi.o
This diff is collapsed.
......@@ -132,8 +132,8 @@ int snd_ump_endpoint_new(struct snd_card *card, char *id, int device,
if (!ump)
return -ENOMEM;
INIT_LIST_HEAD(&ump->block_list);
#if IS_ENABLED(CONFIG_SND_UMP_LEGACY_RAWMIDI)
mutex_init(&ump->open_mutex);
#if IS_ENABLED(CONFIG_SND_UMP_LEGACY_RAWMIDI)
spin_lock_init(&ump->legacy_locks[0]);
spin_lock_init(&ump->legacy_locks[1]);
#endif
......@@ -166,8 +166,30 @@ EXPORT_SYMBOL_GPL(snd_ump_endpoint_new);
* Device register / unregister hooks;
* do nothing, placeholders for avoiding the default rawmidi handling
*/
#if IS_ENABLED(CONFIG_SND_SEQUENCER)
static void snd_ump_dev_seq_free(struct snd_seq_device *device)
{
struct snd_ump_endpoint *ump = device->private_data;
ump->seq_dev = NULL;
}
#endif
static int snd_ump_dev_register(struct snd_rawmidi *rmidi)
{
#if IS_ENABLED(CONFIG_SND_SEQUENCER)
struct snd_ump_endpoint *ump = rawmidi_to_ump(rmidi);
int err;
err = snd_seq_device_new(ump->core.card, ump->core.device,
SNDRV_SEQ_DEV_ID_UMP, 0, &ump->seq_dev);
if (err < 0)
return err;
ump->seq_dev->private_data = ump;
ump->seq_dev->private_free = snd_ump_dev_seq_free;
snd_device_register(ump->core.card, ump->seq_dev);
#endif
return 0;
}
......@@ -280,6 +302,10 @@ int snd_ump_receive(struct snd_ump_endpoint *ump, const u32 *buffer, int count)
n = snd_ump_receive_ump_val(ump, *p++);
if (!n)
continue;
#if IS_ENABLED(CONFIG_SND_SEQUENCER)
if (ump->seq_ops)
ump->seq_ops->input_receive(ump, ump->input_buf, n);
#endif
process_legacy_input(ump, ump->input_buf, n);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment