mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 10:49:33 +00:00
![Takashi Iwai](/assets/img/avatar_default.png)
Starting from this commit, we add the basic support of UMP (Universal MIDI Packet) events on ALSA sequencer infrastructure. The biggest change here is that, for transferring UMP packets that are up to 128 bits, we extend the data payload of ALSA sequencer event record when the client is declared to support for the new UMP events. A new event flag bit, SNDRV_SEQ_EVENT_UMP, is defined and it shall be set for the UMP packet events that have the larger payload of 128 bits, defined as struct snd_seq_ump_event. For controlling the UMP feature enablement in kernel, a new Kconfig, CONFIG_SND_SEQ_UMP is introduced. The extended event for UMP is available only when this Kconfig item is set. Similarly, the size of the internal snd_seq_event_cell also increases (in 4 bytes) when the Kconfig item is set. (But the size increase is effective only for 32bit architectures; 64bit archs already have padding there.) Overall, when CONFIG_SND_SEQ_UMP isn't set, there is no change in the event and cell, keeping the old sizes. For applications that want to access the UMP packets, first of all, a sequencer client has to declare the user-protocol to match with the latest one via the new SNDRV_SEQ_IOCTL_USER_PVERSION; otherwise it's treated as if a legacy client without UMP support. Then the client can switch to the new UMP mode (MIDI 1.0 or MIDI 2.0) with a new field, midi_version, in snd_seq_client_info. When switched to UMP mode (midi_version = 1 or 2), the client can write the UMP events with SNDRV_SEQ_EVENT_UMP flag. For reads, the alignment size is changed from snd_seq_event (28 bytes) to snd_seq_ump_event (32 bytes). When a UMP sequencer event is delivered to a legacy sequencer client, it's ignored or handled as an error. Conceptually, ALSA sequencer client and port correspond to the UMP Endpoint and Group, respectively; each client may have multiple ports and each port has the fixed number (16) of channels, total up to 256 channels. As of this commit, ALSA sequencer core just sends and receives the UMP events as-is from/to clients. The automatic conversions between the legacy events and the new UMP events will be implemented in a later patch. Along with this commit, bump the sequencer protocol version to 1.0.3. Reviewed-by: Jaroslav Kysela <perex@perex.cz> Link: https://lore.kernel.org/r/20230523075358.9672-26-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
105 lines
2.8 KiB
C
105 lines
2.8 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
/*
|
|
* ALSA sequencer Memory Manager
|
|
* Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
|
|
*/
|
|
#ifndef __SND_SEQ_MEMORYMGR_H
|
|
#define __SND_SEQ_MEMORYMGR_H
|
|
|
|
#include <sound/seq_kernel.h>
|
|
#include <linux/poll.h>
|
|
|
|
struct snd_info_buffer;
|
|
|
|
/* aliasing for legacy and UMP event packet handling */
|
|
union __snd_seq_event {
|
|
struct snd_seq_event legacy;
|
|
#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
|
|
struct snd_seq_ump_event ump;
|
|
#endif
|
|
struct {
|
|
struct snd_seq_event event;
|
|
#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
|
|
u32 extra;
|
|
#endif
|
|
} __packed raw;
|
|
};
|
|
|
|
/* container for sequencer event (internal use) */
|
|
struct snd_seq_event_cell {
|
|
union {
|
|
struct snd_seq_event event;
|
|
union __snd_seq_event ump;
|
|
};
|
|
struct snd_seq_pool *pool; /* used pool */
|
|
struct snd_seq_event_cell *next; /* next cell */
|
|
};
|
|
|
|
/* design note: the pool is a contiguous block of memory, if we dynamicly
|
|
want to add additional cells to the pool be better store this in another
|
|
pool as we need to know the base address of the pool when releasing
|
|
memory. */
|
|
|
|
struct snd_seq_pool {
|
|
struct snd_seq_event_cell *ptr; /* pointer to first event chunk */
|
|
struct snd_seq_event_cell *free; /* pointer to the head of the free list */
|
|
|
|
int total_elements; /* pool size actually allocated */
|
|
atomic_t counter; /* cells free */
|
|
|
|
int size; /* pool size to be allocated */
|
|
int room; /* watermark for sleep/wakeup */
|
|
|
|
int closing;
|
|
|
|
/* statistics */
|
|
int max_used;
|
|
int event_alloc_nopool;
|
|
int event_alloc_failures;
|
|
int event_alloc_success;
|
|
|
|
/* Write locking */
|
|
wait_queue_head_t output_sleep;
|
|
|
|
/* Pool lock */
|
|
spinlock_t lock;
|
|
};
|
|
|
|
void snd_seq_cell_free(struct snd_seq_event_cell *cell);
|
|
|
|
int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
|
|
struct snd_seq_event_cell **cellp, int nonblock,
|
|
struct file *file, struct mutex *mutexp);
|
|
|
|
/* return number of unused (free) cells */
|
|
static inline int snd_seq_unused_cells(struct snd_seq_pool *pool)
|
|
{
|
|
return pool ? pool->total_elements - atomic_read(&pool->counter) : 0;
|
|
}
|
|
|
|
/* return total number of allocated cells */
|
|
static inline int snd_seq_total_cells(struct snd_seq_pool *pool)
|
|
{
|
|
return pool ? pool->total_elements : 0;
|
|
}
|
|
|
|
/* init pool - allocate events */
|
|
int snd_seq_pool_init(struct snd_seq_pool *pool);
|
|
|
|
/* done pool - free events */
|
|
void snd_seq_pool_mark_closing(struct snd_seq_pool *pool);
|
|
int snd_seq_pool_done(struct snd_seq_pool *pool);
|
|
|
|
/* create pool */
|
|
struct snd_seq_pool *snd_seq_pool_new(int poolsize);
|
|
|
|
/* remove pool */
|
|
int snd_seq_pool_delete(struct snd_seq_pool **pool);
|
|
|
|
/* polling */
|
|
int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file, poll_table *wait);
|
|
|
|
void snd_seq_info_pool(struct snd_info_buffer *buffer,
|
|
struct snd_seq_pool *pool, char *space);
|
|
|
|
#endif
|