All of lore.kernel.org
 help / color / mirror / Atom feed
From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
To: tiwai@suse.de
Cc: ffado-devel@lists.sourceforge.net, alsa-devel@alsa-project.org,
	clemens@ladisch.de
Subject: [PATCH 11/11] ALSA: firewire-motu: notify event for parameter change in register DSP model
Date: Fri, 15 Oct 2021 17:08:26 +0900	[thread overview]
Message-ID: <20211015080826.34847-12-o-takashi@sakamocchi.jp> (raw)
In-Reply-To: <20211015080826.34847-1-o-takashi@sakamocchi.jp>

This commit copies queued event for change of register DSP into
userspace when application operates ALSA hwdep character device.
The notification occurs only when packet streaming is running.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 include/uapi/sound/firewire.h                 |  8 ++++
 sound/firewire/motu/motu-hwdep.c              | 46 +++++++++++++++----
 .../motu/motu-register-dsp-message-parser.c   | 39 ++++++++++++++++
 sound/firewire/motu/motu.h                    |  2 +
 4 files changed, 86 insertions(+), 9 deletions(-)

diff --git a/include/uapi/sound/firewire.h b/include/uapi/sound/firewire.h
index d52691655d79..76190a0cb069 100644
--- a/include/uapi/sound/firewire.h
+++ b/include/uapi/sound/firewire.h
@@ -13,6 +13,7 @@
 #define SNDRV_FIREWIRE_EVENT_DIGI00X_MESSAGE	0x746e736c
 #define SNDRV_FIREWIRE_EVENT_MOTU_NOTIFICATION	0x64776479
 #define SNDRV_FIREWIRE_EVENT_TASCAM_CONTROL	0x7473636d
+#define SNDRV_FIREWIRE_EVENT_MOTU_REGISTER_DSP_CHANGE	0x4d545244
 
 struct snd_firewire_event_common {
 	unsigned int type; /* SNDRV_FIREWIRE_EVENT_xxx */
@@ -65,6 +66,12 @@ struct snd_firewire_event_tascam_control {
 	struct snd_firewire_tascam_change changes[0];
 };
 
+struct snd_firewire_event_motu_register_dsp_change {
+	unsigned int type;
+	__u32 count;		// The number of changes.
+	__u32 changes[];	// Encoded event for change of register DSP.
+};
+
 union snd_firewire_event {
 	struct snd_firewire_event_common            common;
 	struct snd_firewire_event_lock_status       lock_status;
@@ -73,6 +80,7 @@ union snd_firewire_event {
 	struct snd_firewire_event_digi00x_message   digi00x_message;
 	struct snd_firewire_event_tascam_control    tascam_control;
 	struct snd_firewire_event_motu_notification motu_notification;
+	struct snd_firewire_event_motu_register_dsp_change motu_register_dsp_change;
 };
 
 
diff --git a/sound/firewire/motu/motu-hwdep.c b/sound/firewire/motu/motu-hwdep.c
index 389e59ff768b..9c2e457ce692 100644
--- a/sound/firewire/motu/motu-hwdep.c
+++ b/sound/firewire/motu/motu-hwdep.c
@@ -25,7 +25,8 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
 
 	spin_lock_irq(&motu->lock);
 
-	while (!motu->dev_lock_changed && motu->msg == 0) {
+	while (!motu->dev_lock_changed && motu->msg == 0 &&
+			snd_motu_register_dsp_message_parser_count_event(motu) == 0) {
 		prepare_to_wait(&motu->hwdep_wait, &wait, TASK_INTERRUPTIBLE);
 		spin_unlock_irq(&motu->lock);
 		schedule();
@@ -40,20 +41,46 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
 		event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
 		event.lock_status.status = (motu->dev_lock_count > 0);
 		motu->dev_lock_changed = false;
+		spin_unlock_irq(&motu->lock);
 
-		count = min_t(long, count, sizeof(event.lock_status));
-	} else {
+		count = min_t(long, count, sizeof(event));
+		if (copy_to_user(buf, &event, count))
+			return -EFAULT;
+	} else if (motu->msg > 0) {
 		event.motu_notification.type = SNDRV_FIREWIRE_EVENT_MOTU_NOTIFICATION;
 		event.motu_notification.message = motu->msg;
 		motu->msg = 0;
+		spin_unlock_irq(&motu->lock);
 
-		count = min_t(long, count, sizeof(event.motu_notification));
-	}
+		count = min_t(long, count, sizeof(event));
+		if (copy_to_user(buf, &event, count))
+			return -EFAULT;
+	} else if (snd_motu_register_dsp_message_parser_count_event(motu) > 0) {
+		size_t consumed = 0;
+		u32 __user *ptr;
+		u32 ev;
 
-	spin_unlock_irq(&motu->lock);
+		spin_unlock_irq(&motu->lock);
 
-	if (copy_to_user(buf, &event, count))
-		return -EFAULT;
+		// Header is filled later.
+		consumed += sizeof(event.motu_register_dsp_change);
+
+		while (consumed < count &&
+		       snd_motu_register_dsp_message_parser_copy_event(motu, &ev)) {
+			ptr = (u32 __user *)(buf + consumed);
+			if (put_user(ev, ptr))
+				return -EFAULT;
+			consumed += sizeof(ev);
+		}
+
+		event.motu_register_dsp_change.type = SNDRV_FIREWIRE_EVENT_MOTU_REGISTER_DSP_CHANGE;
+		event.motu_register_dsp_change.count =
+			(consumed - sizeof(event.motu_register_dsp_change)) / 4;
+		if (copy_to_user(buf, &event, sizeof(event.motu_register_dsp_change)))
+			return -EFAULT;
+
+		count = consumed;
+	}
 
 	return count;
 }
@@ -67,7 +94,8 @@ static __poll_t hwdep_poll(struct snd_hwdep *hwdep, struct file *file,
 	poll_wait(file, &motu->hwdep_wait, wait);
 
 	spin_lock_irq(&motu->lock);
-	if (motu->dev_lock_changed || motu->msg)
+	if (motu->dev_lock_changed || motu->msg ||
+	    snd_motu_register_dsp_message_parser_count_event(motu) > 0)
 		events = EPOLLIN | EPOLLRDNORM;
 	else
 		events = 0;
diff --git a/sound/firewire/motu/motu-register-dsp-message-parser.c b/sound/firewire/motu/motu-register-dsp-message-parser.c
index cda8e6d987cc..cbc06b3b70f6 100644
--- a/sound/firewire/motu/motu-register-dsp-message-parser.c
+++ b/sound/firewire/motu/motu-register-dsp-message-parser.c
@@ -95,6 +95,7 @@ struct msg_parser {
 
 	u32 event_queue[EVENT_QUEUE_SIZE];
 	unsigned int push_pos;
+	unsigned int pull_pos;
 };
 
 int snd_motu_register_dsp_message_parser_new(struct snd_motu *motu)
@@ -122,6 +123,7 @@ int snd_motu_register_dsp_message_parser_init(struct snd_motu *motu)
 	return 0;
 }
 
+// Rough implementaion of queue without overrun check.
 static void queue_event(struct snd_motu *motu, u8 msg_type, u8 identifier0, u8 identifier1, u8 val)
 {
 	struct msg_parser *parser = motu->message_parser;
@@ -145,6 +147,7 @@ void snd_motu_register_dsp_message_parser_parse(struct snd_motu *motu, const str
 {
 	struct msg_parser *parser = motu->message_parser;
 	bool meter_pos_quirk = parser->meter_pos_quirk;
+	unsigned int pos = parser->push_pos;
 	unsigned long flags;
 	int i;
 
@@ -351,6 +354,9 @@ void snd_motu_register_dsp_message_parser_parse(struct snd_motu *motu, const str
 		}
 	}
 
+	if (pos != parser->push_pos)
+		wake_up(&motu->hwdep_wait);
+
 	spin_unlock_irqrestore(&parser->lock, flags);
 }
 
@@ -375,3 +381,36 @@ void snd_motu_register_dsp_message_parser_copy_parameter(struct snd_motu *motu,
 	memcpy(param, &parser->param, sizeof(*param));
 	spin_unlock_irqrestore(&parser->lock, flags);
 }
+
+unsigned int snd_motu_register_dsp_message_parser_count_event(struct snd_motu *motu)
+{
+	struct msg_parser *parser = motu->message_parser;
+
+	if (parser->pull_pos > parser->push_pos)
+		return EVENT_QUEUE_SIZE - parser->pull_pos + parser->push_pos;
+	else
+		return parser->push_pos - parser->pull_pos;
+}
+
+bool snd_motu_register_dsp_message_parser_copy_event(struct snd_motu *motu, u32 *event)
+{
+	struct msg_parser *parser = motu->message_parser;
+	unsigned int pos = parser->pull_pos;
+	unsigned long flags;
+
+	if (pos == parser->push_pos)
+		return false;
+
+	spin_lock_irqsave(&parser->lock, flags);
+
+	*event = parser->event_queue[pos];
+
+	++pos;
+	if (pos >= EVENT_QUEUE_SIZE)
+		pos = 0;
+	parser->pull_pos = pos;
+
+	spin_unlock_irqrestore(&parser->lock, flags);
+
+	return true;
+}
diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h
index 9703d3af59ec..79704ae6a73e 100644
--- a/sound/firewire/motu/motu.h
+++ b/sound/firewire/motu/motu.h
@@ -283,6 +283,8 @@ void snd_motu_register_dsp_message_parser_copy_meter(struct snd_motu *motu,
 					struct snd_firewire_motu_register_dsp_meter *meter);
 void snd_motu_register_dsp_message_parser_copy_parameter(struct snd_motu *motu,
 					struct snd_firewire_motu_register_dsp_parameter *params);
+unsigned int snd_motu_register_dsp_message_parser_count_event(struct snd_motu *motu);
+bool snd_motu_register_dsp_message_parser_copy_event(struct snd_motu *motu, u32 *event);
 
 int snd_motu_command_dsp_message_parser_new(struct snd_motu *motu);
 int snd_motu_command_dsp_message_parser_init(struct snd_motu *motu, enum cip_sfc sfc);
-- 
2.30.2


  parent reply	other threads:[~2021-10-15  8:12 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-15  8:08 [PATCH 00/11] ALSA: firewire-motu: add ioctl commands to retrieve information in messages delivered by isoc packet Takashi Sakamoto
2021-10-15  8:08 ` [PATCH 01/11] ALSA: firewire-motu: add message parser to gather meter information in register DSP model Takashi Sakamoto
2021-10-15  8:08 ` [PATCH 02/11] ALSA: firewire-motu: add message parser for meter information in command " Takashi Sakamoto
2021-10-15  8:08 ` [PATCH 03/11] ALSA: firewire-motu: add ioctl command to read cached hardware meter Takashi Sakamoto
2021-10-15  8:08 ` [PATCH 04/11] ALSA: firewire-motu: parse messages for mixer source parameters in register-DSP model Takashi Sakamoto
2021-10-15  8:08 ` [PATCH 05/11] ALSA: firewire-motu: parse messages for mixer output parameters in register DSP model Takashi Sakamoto
2021-10-15  8:08 ` [PATCH 06/11] ALSA: firewire-motu: parse messages for " Takashi Sakamoto
2021-10-15  8:08 ` [PATCH 07/11] ALSA: firewire-motu: parse messages for line input " Takashi Sakamoto
2021-10-15  8:08 ` [PATCH 08/11] ALSA: firewire-motu: parse messages for " Takashi Sakamoto
2021-10-15  8:08 ` [PATCH 09/11] ALSA: firewire-motu: add ioctl command to read cached " Takashi Sakamoto
2021-10-15  8:08 ` [PATCH 10/11] ALSA: firewire-motu: queue event for parameter change " Takashi Sakamoto
2021-10-15  8:08 ` Takashi Sakamoto [this message]
2021-10-15 15:54 ` [PATCH 00/11] ALSA: firewire-motu: add ioctl commands to retrieve information in messages delivered by isoc packet Takashi Iwai
2021-10-17  1:22   ` Takashi Sakamoto
2021-10-17  7:02     ` Takashi Iwai
2021-10-17  9:25       ` Takashi Sakamoto
2021-10-18  8:05         ` Takashi Iwai
2021-10-18 12:46           ` Takashi Sakamoto
2021-10-18 12:57             ` Takashi Iwai
2021-10-20  7:14               ` Takashi Sakamoto

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=20211015080826.34847-12-o-takashi@sakamocchi.jp \
    --to=o-takashi@sakamocchi.jp \
    --cc=alsa-devel@alsa-project.org \
    --cc=clemens@ladisch.de \
    --cc=ffado-devel@lists.sourceforge.net \
    --cc=tiwai@suse.de \
    /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.