All of lore.kernel.org
 help / color / mirror / Atom feed
From: Takashi Iwai <tiwai@suse.de>
To: alsa-devel@alsa-project.org
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH v2 34/37] ALSA: seq: Add ioctls for client UMP info query and setup
Date: Tue, 23 May 2023 09:53:55 +0200	[thread overview]
Message-ID: <20230523075358.9672-35-tiwai@suse.de> (raw)
In-Reply-To: <20230523075358.9672-1-tiwai@suse.de>

Add new ioctls for sequencer clients to query and set the UMP endpoint
and block information.

As a sequencer client corresponds to a UMP Endpoint, one UMP Endpoint
information can be assigned at most to a single sequencer client while
multiple UMP block infos can be assigned by passing the type with the
offset of block id (i.e. type = block_id + 1).

For the kernel client, only SNDRV_SEQ_IOCTL_GET_CLIENT_UMP_INFO is
allowed.

Reviewed-by: Jaroslav Kysela <perex@perex.cz>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/uapi/sound/asequencer.h |  14 ++++
 sound/core/seq/seq_clientmgr.c  | 120 +++++++++++++++++++++++++++++++-
 sound/core/seq/seq_clientmgr.h  |   4 +-
 sound/core/seq/seq_compat.c     |   2 +
 sound/core/seq/seq_ump_client.c |  15 ++++
 5 files changed, 153 insertions(+), 2 deletions(-)

diff --git a/include/uapi/sound/asequencer.h b/include/uapi/sound/asequencer.h
index 3fa6b17aa7a2..c75f594f21e3 100644
--- a/include/uapi/sound/asequencer.h
+++ b/include/uapi/sound/asequencer.h
@@ -585,6 +585,18 @@ struct snd_seq_query_subs {
 	char reserved[64];	/* for future use */
 };
 
+/*
+ * UMP-specific information
+ */
+/* type of UMP info query */
+#define SNDRV_SEQ_CLIENT_UMP_INFO_ENDPOINT	0
+#define SNDRV_SEQ_CLIENT_UMP_INFO_BLOCK		1
+
+struct snd_seq_client_ump_info {
+	int client;			/* client number to inquire/set */
+	int type;			/* type to inquire/set */
+	unsigned char info[512];	/* info (either UMP ep or block info) */
+} __packed;
 
 /*
  *  IOCTL commands
@@ -598,6 +610,8 @@ struct snd_seq_query_subs {
 
 #define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO	_IOWR('S', 0x10, struct snd_seq_client_info)
 #define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO	_IOW ('S', 0x11, struct snd_seq_client_info)
+#define SNDRV_SEQ_IOCTL_GET_CLIENT_UMP_INFO	_IOWR('S', 0x12, struct snd_seq_client_ump_info)
+#define SNDRV_SEQ_IOCTL_SET_CLIENT_UMP_INFO	_IOWR('S', 0x13, struct snd_seq_client_ump_info)
 
 #define SNDRV_SEQ_IOCTL_CREATE_PORT	_IOWR('S', 0x20, struct snd_seq_port_info)
 #define SNDRV_SEQ_IOCTL_DELETE_PORT	_IOW ('S', 0x21, struct snd_seq_port_info)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 3b1adcb1ccdd..03ca78ea2cce 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -14,6 +14,7 @@
 #include <linux/kmod.h>
 
 #include <sound/seq_kernel.h>
+#include <sound/ump.h>
 #include "seq_clientmgr.h"
 #include "seq_memory.h"
 #include "seq_queue.h"
@@ -71,6 +72,10 @@ static int snd_seq_deliver_single_event(struct snd_seq_client *client,
 					struct snd_seq_event *event,
 					int filter, int atomic, int hop);
 
+#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
+static void free_ump_info(struct snd_seq_client *client);
+#endif
+
 /*
  */
 static inline unsigned short snd_seq_file_flags(struct file *file)
@@ -382,6 +387,9 @@ static int snd_seq_release(struct inode *inode, struct file *file)
 		seq_free_client(client);
 		if (client->data.user.fifo)
 			snd_seq_fifo_delete(&client->data.user.fifo);
+#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
+		free_ump_info(client);
+#endif
 		put_pid(client->data.user.owner);
 		kfree(client);
 	}
@@ -1282,7 +1290,6 @@ static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client,
 	if (client->user_pversion >= SNDRV_PROTOCOL_VERSION(1, 0, 3))
 		client->midi_version = client_info->midi_version;
 	memcpy(client->event_filter, client_info->event_filter, 32);
-
 	return 0;
 }
 
@@ -2087,6 +2094,108 @@ static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client,
 	return 0;
 }
 
+#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
+#define NUM_UMP_INFOS (SNDRV_UMP_MAX_BLOCKS + 1)
+
+static void free_ump_info(struct snd_seq_client *client)
+{
+	int i;
+
+	if (!client->ump_info)
+		return;
+	for (i = 0; i < NUM_UMP_INFOS; i++)
+		kfree(client->ump_info[i]);
+	kfree(client->ump_info);
+	client->ump_info = NULL;
+}
+
+static void terminate_ump_info_strings(void *p, int type)
+{
+	if (type == SNDRV_SEQ_CLIENT_UMP_INFO_ENDPOINT) {
+		struct snd_ump_endpoint_info *ep = p;
+		ep->name[sizeof(ep->name) - 1] = 0;
+	} else {
+		struct snd_ump_block_info *bp = p;
+		bp->name[sizeof(bp->name) - 1] = 0;
+	}
+}
+
+/* UMP-specific ioctls -- called directly without data copy */
+static int snd_seq_ioctl_client_ump_info(struct snd_seq_client *caller,
+					 unsigned int cmd,
+					 unsigned long arg)
+{
+	struct snd_seq_client_ump_info __user *argp =
+		(struct snd_seq_client_ump_info __user *)arg;
+	struct snd_seq_client *cptr;
+	int client, type, err = 0;
+	size_t size;
+	void *p;
+
+	if (get_user(client, &argp->client) || get_user(type, &argp->type))
+		return -EFAULT;
+	if (cmd == SNDRV_SEQ_IOCTL_SET_CLIENT_UMP_INFO &&
+	    caller->number != client)
+		return -EPERM;
+	if (type < 0 || type >= NUM_UMP_INFOS)
+		return -EINVAL;
+	if (type == SNDRV_SEQ_CLIENT_UMP_INFO_ENDPOINT)
+		size = sizeof(struct snd_ump_endpoint_info);
+	else
+		size = sizeof(struct snd_ump_block_info);
+	cptr = snd_seq_client_use_ptr(client);
+	if (!cptr)
+		return -ENOENT;
+
+	mutex_lock(&cptr->ioctl_mutex);
+	if (!cptr->midi_version) {
+		err = -EBADFD;
+		goto error;
+	}
+
+	if (cmd == SNDRV_SEQ_IOCTL_GET_CLIENT_UMP_INFO) {
+		if (!cptr->ump_info)
+			p = NULL;
+		else
+			p = cptr->ump_info[type];
+		if (!p) {
+			err = -ENODEV;
+			goto error;
+		}
+		if (copy_to_user(argp->info, p, size)) {
+			err = -EFAULT;
+			goto error;
+		}
+	} else {
+		if (cptr->type != USER_CLIENT) {
+			err = -EBADFD;
+			goto error;
+		}
+		if (!cptr->ump_info) {
+			cptr->ump_info = kcalloc(NUM_UMP_INFOS,
+						 sizeof(void *), GFP_KERNEL);
+			if (!cptr->ump_info) {
+				err = -ENOMEM;
+				goto error;
+			}
+		}
+		p = memdup_user(argp->info, size);
+		if (IS_ERR(p)) {
+			err = PTR_ERR(p);
+			goto error;
+		}
+		kfree(cptr->ump_info[type]);
+		terminate_ump_info_strings(p, type);
+		cptr->ump_info[type] = p;
+	}
+
+ error:
+	mutex_unlock(&cptr->ioctl_mutex);
+	snd_seq_client_unlock(cptr);
+	return err;
+}
+#endif
+
 /* -------------------------------------------------------- */
 
 static const struct ioctl_handler {
@@ -2157,6 +2266,15 @@ static long snd_seq_ioctl(struct file *file, unsigned int cmd,
 	if (snd_BUG_ON(!client))
 		return -ENXIO;
 
+#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
+	/* exception - handling large data */
+	switch (cmd) {
+	case SNDRV_SEQ_IOCTL_GET_CLIENT_UMP_INFO:
+	case SNDRV_SEQ_IOCTL_SET_CLIENT_UMP_INFO:
+		return snd_seq_ioctl_client_ump_info(client, cmd, arg);
+	}
+#endif
+
 	for (handler = ioctl_handlers; handler->cmd > 0; ++handler) {
 		if (handler->cmd == cmd)
 			break;
diff --git a/sound/core/seq/seq_clientmgr.h b/sound/core/seq/seq_clientmgr.h
index 97762892ffab..be3fe555f233 100644
--- a/sound/core/seq/seq_clientmgr.h
+++ b/sound/core/seq/seq_clientmgr.h
@@ -12,7 +12,6 @@
 #include "seq_ports.h"
 #include "seq_lock.h"
 
-
 /* client manager */
 
 struct snd_seq_user_client {
@@ -59,6 +58,9 @@ struct snd_seq_client {
 		struct snd_seq_user_client user;
 		struct snd_seq_kernel_client kernel;
 	} data;
+
+	/* for UMP */
+	void **ump_info;
 };
 
 /* usage statistics */
diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c
index c0ce6236dc7f..1e35bf086a51 100644
--- a/sound/core/seq/seq_compat.c
+++ b/sound/core/seq/seq_compat.c
@@ -86,6 +86,8 @@ static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
 	case SNDRV_SEQ_IOCTL_SYSTEM_INFO:
 	case SNDRV_SEQ_IOCTL_GET_CLIENT_INFO:
 	case SNDRV_SEQ_IOCTL_SET_CLIENT_INFO:
+	case SNDRV_SEQ_IOCTL_GET_CLIENT_UMP_INFO:
+	case SNDRV_SEQ_IOCTL_SET_CLIENT_UMP_INFO:
 	case SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT:
 	case SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT:
 	case SNDRV_SEQ_IOCTL_CREATE_QUEUE:
diff --git a/sound/core/seq/seq_ump_client.c b/sound/core/seq/seq_ump_client.c
index 600b061ac8c3..e24833804094 100644
--- a/sound/core/seq/seq_ump_client.c
+++ b/sound/core/seq/seq_ump_client.c
@@ -47,6 +47,7 @@ struct seq_ump_client {
 	struct snd_rawmidi_file out_rfile; /* rawmidi for output */
 	struct seq_ump_input_buffer input; /* input parser context */
 	struct seq_ump_group groups[SNDRV_UMP_MAX_GROUPS]; /* table of groups */
+	void *ump_info[SNDRV_UMP_MAX_BLOCKS + 1]; /* shadow of seq client ump_info */
 };
 
 /* number of 32bit words for each UMP message type */
@@ -384,6 +385,8 @@ static int snd_seq_ump_probe(struct device *_dev)
 	struct snd_ump_endpoint *ump = dev->private_data;
 	struct snd_card *card = dev->card;
 	struct seq_ump_client *client;
+	struct snd_ump_block *fb;
+	struct snd_seq_client *cptr;
 	int p, err;
 
 	client = kzalloc(sizeof(*client), GFP_KERNEL);
@@ -400,6 +403,10 @@ static int snd_seq_ump_probe(struct device *_dev)
 		goto error;
 	}
 
+	client->ump_info[0] = &ump->info;
+	list_for_each_entry(fb, &ump->block_list, list)
+		client->ump_info[fb->info.block_id + 1] = &fb->info;
+
 	setup_client_midi_version(client);
 	update_group_attrs(client);
 
@@ -413,6 +420,14 @@ static int snd_seq_ump_probe(struct device *_dev)
 	if (err < 0)
 		goto error;
 
+	cptr = snd_seq_kernel_client_get(client->seq_client);
+	if (!cptr) {
+		err = -EINVAL;
+		goto error;
+	}
+	cptr->ump_info = client->ump_info;
+	snd_seq_kernel_client_put(cptr);
+
 	ump->seq_client = client;
 	ump->seq_ops = &seq_ump_ops;
 	return 0;
-- 
2.35.3


  parent reply	other threads:[~2023-05-23  7:57 UTC|newest]

Thread overview: 69+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-23  7:53 [PATCH v2 00/37] ALSA: Add MIDI 2.0 support Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 01/37] ALSA: rawmidi: Pass rawmidi directly to snd_rawmidi_kernel_open() Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 02/37] ALSA: rawmidi: Add ioctl callback to snd_rawmidi_global_ops Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 03/37] ALSA: rawmidi: UMP support Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 04/37] ALSA: rawmidi: Skip UMP devices at SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 05/37] ALSA: ump: Add ioctls to inquiry UMP EP and Block info via control API Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 06/37] ALSA: ump: Additional proc output Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 07/37] ALSA: usb-audio: Manage number of rawmidis globally Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 08/37] ALSA: usb-audio: Define USB MIDI 2.0 specs Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 09/37] ALSA: usb-audio: USB MIDI 2.0 UMP support Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 10/37] ALSA: usb-audio: Get UMP EP name string from USB interface Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 11/37] ALSA: usb-audio: Trim superfluous "MIDI" suffix from UMP EP name Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 12/37] ALSA: usb-audio: Create UMP blocks from USB MIDI GTBs Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 13/37] ALSA: ump: Redirect rawmidi substream access via own helpers Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 14/37] ALSA: ump: Add legacy raw MIDI support Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 15/37] ALSA: usb-audio: Enable the " Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 16/37] ALSA: usb-audio: Inform inconsistent protocols in GTBs Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 17/37] ALSA: seq: Clear padded bytes at expanding events Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 18/37] ALSA: seq: Add snd_seq_expand_var_event_at() helper Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 19/37] ALSA: seq: Treat snd_seq_client object directly in client drivers Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 20/37] ALSA: seq: Drop dead code for the old broadcast support Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 21/37] ALSA: seq: Check the conflicting port at port creation Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 22/37] ALSA: seq: Check validity before creating a port object Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 23/37] ALSA: seq: Prohibit creating ports with special numbers Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 24/37] ALSA: seq: Introduce SNDRV_SEQ_IOCTL_USER_PVERSION ioctl Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 25/37] ALSA: seq: Add UMP support Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 26/37] ALSA: seq: Add port inactive flag Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 27/37] ALSA: seq: Support MIDI 2.0 UMP Endpoint port Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 28/37] ALSA: seq: Add port direction to snd_seq_port_info Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 29/37] ALSA: seq: Add UMP group number " Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 30/37] ALSA: seq: Automatic conversion of UMP events Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 31/37] ALSA: seq: Allow suppressing UMP conversions Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 32/37] ALSA: seq: Bind UMP device Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 33/37] ALSA: seq: ump: Create UMP Endpoint port for broadcast Takashi Iwai
2023-05-23  7:53 ` Takashi Iwai [this message]
2023-05-23  7:53 ` [PATCH v2 35/37] ALSA: seq: Print UMP Endpoint and Block information in proc outputs Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 36/37] ALSA: seq: Add UMP group filter Takashi Iwai
2023-05-23  7:53 ` [PATCH v2 37/37] ALSA: docs: Add MIDI 2.0 documentation Takashi Iwai
2023-06-13 12:41 ` [PATCH v2 00/37] ALSA: Add MIDI 2.0 support happy.debugging
2023-06-13 12:53   ` Takashi Iwai
2023-06-13 13:24     ` Happy Debugging
2023-06-13 13:31       ` Takashi Iwai
2023-06-13 15:23         ` Symbolic Debugger
2023-06-14  6:01           ` Symbolic Debugger
2023-06-14  6:09             ` Takashi Iwai
2023-06-14  6:53               ` Takashi Iwai
2023-06-15 11:39                 ` Symbolic Debugger
2023-06-16 12:23                   ` Symbolic Debugger
2023-06-16 12:27                     ` Takashi Iwai
2023-06-16 14:17                       ` Symbolic Debugger
2023-06-17 15:07                         ` Symbolic Debugger
2023-06-18  8:54                           ` Takashi Iwai
2023-06-20 13:29                             ` Symbolic Debugger
2023-06-28  6:52                               ` Symbolic Debugger
2023-06-28 11:12                                 ` Takashi Iwai
2023-06-28 11:32                                   ` Symbolic Debugger
2023-06-28 14:20                                     ` Takashi Iwai
2023-06-29  2:03                                       ` Symbolic Debugger
2023-06-29  6:40                                         ` Takashi Iwai
2023-06-29  8:38                                           ` Symbolic Debugger
2023-07-03 10:15                                             ` Symbolic Debugger
2023-07-03 10:19                                               ` Takashi Iwai
2023-07-03 11:25                                                 ` Symbolic Debugger
2023-07-03 12:09                                                   ` Takashi Iwai
2023-07-03 12:54                                                     ` Symbolic Debugger
2023-07-03 13:01                                                       ` Takashi Iwai
2023-07-03 13:53                                                         ` Symbolic Debugger
2023-07-12 13:26                                                           ` Symbolic Debugger
2023-07-12 13:58                                                             ` Takashi Iwai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230523075358.9672-35-tiwai@suse.de \
    --to=tiwai@suse.de \
    --cc=alsa-devel@alsa-project.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.