From: "Geoffrey D. Bennett" <g@b4.vu>
To: Takashi Iwai <tiwai@suse.com>
Cc: alsa-devel@alsa-project.org
Subject: [PATCH RFC] ALSA: scarlett2: Add ioctls for user-space access
Date: Sun, 15 Oct 2023 00:28:28 +1030 [thread overview]
Message-ID: <ZSqehHhedJQY9h/1@m.b4.vu> (raw)
In order to support functions such as firmware upgrade from
user-space, add ioctls for submitting arbitrary proprietary requests
through scarlett2_usb() and requesting/releasing exclusive access.
---
Hi Takashi,
I recently figured how to update the firmware on Scarlett Gen 2+
devices. I think the best way to implement this is with an ioctl
giving access to the scarlett2_usb() function from user-space, plus
two ioctls to request/release exclusive access.
Does something like this seem reasonable?
What ioctl magic/command values should I use?
Should lock/unlock be separate, or one ioctl takes an argument for
which operation to do?
Thanks,
Geoffrey.
MAINTAINERS | 1 +
include/uapi/sound/scarlett_gen2.h | 28 +++++++++
sound/usb/mixer_scarlett_gen2.c | 94 +++++++++++++++++++++++++++++-
3 files changed, 121 insertions(+), 2 deletions(-)
create mode 100644 include/uapi/sound/scarlett_gen2.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 4cc6bf79fdd8..25e5e40f7118 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8066,6 +8066,7 @@ M: Geoffrey D. Bennett <g@b4.vu>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
+F: include/uapi/sound/scarlett_gen2.h
F: sound/usb/mixer_scarlett_gen2.c
FORCEDETH GIGABIT ETHERNET DRIVER
diff --git a/include/uapi/sound/scarlett_gen2.h b/include/uapi/sound/scarlett_gen2.h
new file mode 100644
index 000000000000..0b51a9754ba2
--- /dev/null
+++ b/include/uapi/sound/scarlett_gen2.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Focusrite Scarlett Gen 2/3 and Clarett USB/Clarett+ Driver for ALSA
+ *
+ * Copyright (c) 2023 by Geoffrey D. Bennett <g at b4.vu>
+ */
+#ifndef __UAPI_SOUND_SCARLETT_GEN2_H
+#define __UAPI_SOUND_SCARLETT_GEN2_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+/* Send a proprietary format request to the interface */
+struct snd_scarlett_gen2_usb_cmd {
+ u32 cmd;
+ void *req_data;
+ u16 req_size;
+ void *resp_data;
+ u16 resp_size;
+};
+
+#define SCARLETT2_IOCTL_USB_CMD _IOWR('S', 0x60, struct snd_scarlett_gen2_usb_cmd)
+
+/* Request/release exclusive access */
+#define SCARLETT2_IOCTL_LOCK _IO('S', 0x61)
+#define SCARLETT2_IOCTL_UNLOCK _IO('S', 0x62)
+
+#endif /* __UAPI_SOUND_SCARLETT_GEN2_H */
diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c
index ffd398f26d2c..f1ef87b54813 100644
--- a/sound/usb/mixer_scarlett_gen2.c
+++ b/sound/usb/mixer_scarlett_gen2.c
@@ -144,6 +144,9 @@
#include <sound/control.h>
#include <sound/tlv.h>
+#include <sound/hwdep.h>
+
+#include <uapi/sound/scarlett_gen2.h>
#include "usbaudio.h"
#include "mixer.h"
@@ -4262,10 +4265,84 @@ static int snd_scarlett_gen2_controls_create(
return 0;
}
+static int scarlett_gen2_ioctl_usb_cmd(struct snd_hwdep *hw, unsigned long arg)
+{
+ struct scarlett2_data *private = hw->private_data;
+ struct snd_scarlett_gen2_usb_cmd usb_cmd;
+ int err;
+ void *req_data = NULL;
+ void *resp_data = NULL;
+
+ // get cmd & req/resp buffers
+ if (copy_from_user(&usb_cmd, (void __user *)arg, sizeof(usb_cmd)))
+ return -EFAULT;
+
+ // allocate request buffer, copy data from user
+ if (usb_cmd.req_size > 0) {
+ req_data = kmalloc(usb_cmd.req_size, GFP_KERNEL);
+ if (!req_data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ if (copy_from_user(req_data, usb_cmd.req_data,
+ usb_cmd.req_size)) {
+ err = -EFAULT;
+ goto exit;
+ }
+ }
+
+ // allocate response buffer
+ if (usb_cmd.resp_size > 0) {
+ resp_data = kmalloc(usb_cmd.resp_size, GFP_KERNEL);
+ if (!resp_data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ }
+
+ // send request, get response
+ err = scarlett2_usb(private->mixer, usb_cmd.cmd,
+ req_data, usb_cmd.req_size,
+ resp_data, usb_cmd.resp_size);
+ if (err < 0)
+ goto exit;
+
+ // copy response to user
+ if (usb_cmd.resp_size > 0)
+ if (copy_to_user(usb_cmd.resp_data, resp_data,
+ usb_cmd.resp_size))
+ err = -EFAULT;
+
+exit:
+ kfree(req_data);
+ kfree(resp_data);
+
+ return err;
+}
+
+static int scarlett_gen2_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ switch (cmd) {
+
+ case SCARLETT2_IOCTL_USB_CMD:
+ return scarlett_gen2_ioctl_usb_cmd(hw, arg);
+
+ // TODO
+ case SCARLETT2_IOCTL_LOCK:
+ case SCARLETT2_IOCTL_UNLOCK:
+ return -EINVAL;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer)
{
struct snd_usb_audio *chip = mixer->chip;
const struct scarlett2_device_entry *entry;
+ struct snd_hwdep *hw;
int err;
/* only use UAC_VERSION_2 */
@@ -4302,11 +4379,24 @@ int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer)
USB_ID_PRODUCT(chip->usb_id));
err = snd_scarlett_gen2_controls_create(mixer, entry);
- if (err < 0)
+ if (err < 0) {
usb_audio_err(mixer->chip,
"Error initialising %s Mixer Driver: %d",
entry->series_name,
err);
+ return err;
+ }
+
+ err = snd_hwdep_new(mixer->chip->card, "Focusrite Control", 0, &hw);
+ if (err < 0) {
+ usb_audio_err(mixer->chip,
+ "Error creating hwdep device: %d",
+ err);
+ return err;
+ }
- return err;
+ hw->private_data = mixer->private_data;
+ hw->ops.ioctl = scarlett_gen2_hwdep_ioctl;
+
+ return 0;
}
--
2.41.0
next reply other threads:[~2023-10-14 14:00 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-14 13:58 Geoffrey D. Bennett [this message]
2023-10-16 7:04 ` [PATCH RFC] ALSA: scarlett2: Add ioctls for user-space access Jaroslav Kysela
2023-10-16 12:32 ` Geoffrey D. Bennett
2023-10-16 13:28 ` Jaroslav Kysela
2023-10-16 15:45 ` Geoffrey D. Bennett
2023-10-17 7:53 ` Takashi Iwai
2023-11-19 17:35 ` [PATCH RFC v2] " Geoffrey D. Bennett
2023-11-24 13:39 ` Takashi Iwai
2023-11-27 18:32 ` Geoffrey D. Bennett
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=ZSqehHhedJQY9h/1@m.b4.vu \
--to=g@b4.vu \
--cc=alsa-devel@alsa-project.org \
--cc=tiwai@suse.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox