summaryrefslogtreecommitdiffstats
path: root/include/sound/ump.h
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2023-05-23 09:53:24 +0200
committerTakashi Iwai <tiwai@suse.de>2023-05-23 12:10:54 +0200
commite3a8a5b726bdd903de52bee6ba7c935c09d07ee8 (patch)
tree5c40120ede7a259c4a083656bb661ba15afb9aa9 /include/sound/ump.h
parentfb3bd1215909866d6105224abe1566fd52695859 (diff)
downloadlinux-e3a8a5b726bdd903de52bee6ba7c935c09d07ee8.tar.gz
linux-e3a8a5b726bdd903de52bee6ba7c935c09d07ee8.tar.bz2
linux-e3a8a5b726bdd903de52bee6ba7c935c09d07ee8.zip
ALSA: rawmidi: UMP support
This patch adds the support helpers for UMP (Universal MIDI Packet) in ALSA core. The basic design is that a rawmidi instance is assigned to each UMP Endpoint. A UMP Endpoint provides a UMP stream, typically bidirectional (but can be also uni-directional, too), which may hold up to 16 UMP Groups, where each UMP (input/output) Group corresponds to the traditional MIDI I/O Endpoint. Additionally, the ALSA UMP abstraction provides the multiple UMP Blocks that can be assigned to each UMP Endpoint. A UMP Block is a metadata to hold the UMP Group clusters, and can represent the functions assigned to each UMP Group. A typical implementation of UMP Block is the Group Terminal Blocks of USB MIDI 2.0 specification. For distinguishing from the legacy byte-stream MIDI device, a new device "umpC*D*" will be created, instead of the standard (MIDI 1.0) devices "midiC*D*". The UMP instance can be identified by the new rawmidi info bit SNDRV_RAWMIDI_INFO_UMP, too. A UMP rawmidi device reads/writes only in 4-bytes words alignment, stored in CPU native endianness. The transmit and receive functions take care of the input/out data alignment, and may return zero or aligned size, and the params ioctl may return -EINVAL when the given input/output buffer size isn't aligned. A few new UMP-specific ioctls are added for obtaining the new UMP endpoint and block information. As of this commit, no ALSA sequencer instance is attached to UMP devices yet. They will be supported by later patches. Along with those changes, the protocol version for rawmidi is bumped to 2.0.3. Reviewed-by: Jaroslav Kysela <perex@perex.cz> Link: https://lore.kernel.org/r/20230523075358.9672-4-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'include/sound/ump.h')
-rw-r--r--include/sound/ump.h118
1 files changed, 118 insertions, 0 deletions
diff --git a/include/sound/ump.h b/include/sound/ump.h
new file mode 100644
index 000000000000..8a3ac97cd1d3
--- /dev/null
+++ b/include/sound/ump.h
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Universal MIDI Packet (UMP) Support
+ */
+#ifndef __SOUND_UMP_H
+#define __SOUND_UMP_H
+
+#include <sound/rawmidi.h>
+
+struct snd_ump_endpoint;
+struct snd_ump_block;
+
+struct snd_ump_endpoint {
+ struct snd_rawmidi core; /* raw UMP access */
+
+ struct snd_ump_endpoint_info info;
+
+ void *private_data;
+ void (*private_free)(struct snd_ump_endpoint *ump);
+
+ struct list_head block_list; /* list of snd_ump_block objects */
+};
+
+struct snd_ump_block {
+ struct snd_ump_block_info info;
+ struct snd_ump_endpoint *ump;
+
+ void *private_data;
+ void (*private_free)(struct snd_ump_block *blk);
+
+ struct list_head list;
+};
+
+#define rawmidi_to_ump(rmidi) container_of(rmidi, struct snd_ump_endpoint, core)
+
+int snd_ump_endpoint_new(struct snd_card *card, char *id, int device,
+ int output, int input,
+ struct snd_ump_endpoint **ump_ret);
+int snd_ump_block_new(struct snd_ump_endpoint *ump, unsigned int blk,
+ unsigned int direction, unsigned int first_group,
+ unsigned int num_groups, struct snd_ump_block **blk_ret);
+
+/*
+ * Some definitions for UMP
+ */
+
+/* MIDI 2.0 Message Type */
+enum {
+ UMP_MSG_TYPE_UTILITY = 0x00,
+ UMP_MSG_TYPE_SYSTEM = 0x01,
+ UMP_MSG_TYPE_MIDI1_CHANNEL_VOICE = 0x02,
+ UMP_MSG_TYPE_DATA = 0x03,
+ UMP_MSG_TYPE_MIDI2_CHANNEL_VOICE = 0x04,
+ UMP_MSG_TYPE_EXTENDED_DATA = 0x05,
+};
+
+/* MIDI 2.0 SysEx / Data Status; same values for both 7-bit and 8-bit SysEx */
+enum {
+ UMP_SYSEX_STATUS_SINGLE = 0,
+ UMP_SYSEX_STATUS_START = 1,
+ UMP_SYSEX_STATUS_CONTINUE = 2,
+ UMP_SYSEX_STATUS_END = 3,
+};
+
+/*
+ * Helpers for retrieving / filling bits from UMP
+ */
+/* get the message type (4bit) from a UMP packet (header) */
+static inline unsigned char ump_message_type(u32 data)
+{
+ return data >> 28;
+}
+
+/* get the group number (0-based, 4bit) from a UMP packet (header) */
+static inline unsigned char ump_message_group(u32 data)
+{
+ return (data >> 24) & 0x0f;
+}
+
+/* get the MIDI status code (4bit) from a UMP packet (header) */
+static inline unsigned char ump_message_status_code(u32 data)
+{
+ return (data >> 20) & 0x0f;
+}
+
+/* get the MIDI channel number (0-based, 4bit) from a UMP packet (header) */
+static inline unsigned char ump_message_channel(u32 data)
+{
+ return (data >> 16) & 0x0f;
+}
+
+/* get the MIDI status + channel combo byte (8bit) from a UMP packet (header) */
+static inline unsigned char ump_message_status_channel(u32 data)
+{
+ return (data >> 16) & 0xff;
+}
+
+/* compose a UMP packet (header) from type, group and status values */
+static inline u32 ump_compose(unsigned char type, unsigned char group,
+ unsigned char status, unsigned char channel)
+{
+ return ((u32)type << 28) | ((u32)group << 24) | ((u32)status << 20) |
+ ((u32)channel << 16);
+}
+
+/* get SysEx message status (for both 7 and 8bits) from a UMP packet (header) */
+static inline unsigned char ump_sysex_message_status(u32 data)
+{
+ return (data >> 20) & 0xf;
+}
+
+/* get SysEx message length (for both 7 and 8bits) from a UMP packet (header) */
+static inline unsigned char ump_sysex_message_length(u32 data)
+{
+ return (data >> 16) & 0xf;
+}
+
+#endif /* __SOUND_UMP_H */