aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/sound/core/ump.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2023-06-12 10:10:50 +0200
committerTakashi Iwai <tiwai@suse.de>2023-06-12 18:22:31 +0200
commit4a16a3af05712e7fd5a205f34e2908055bd9fb5e (patch)
tree470ccb8290d224d4f2b3ac559985c09b69bcd0a1 /sound/core/ump.c
parentALSA: seq: ump: Handle groupless messages (diff)
downloadwireguard-linux-4a16a3af05712e7fd5a205f34e2908055bd9fb5e.tar.xz
wireguard-linux-4a16a3af05712e7fd5a205f34e2908055bd9fb5e.zip
ALSA: seq: ump: Handle FB info update
This patch implements the handling of the dynamic update of FB info. When the FB info update is received after the initial parsing, it means the dynamic FB info update. We compare the result, and if the actual update is detected, it's notified via a new ops, notify_fb_change, to the sequencer client, and the corresponding sequencer ports are updated accordingly. Link: https://lore.kernel.org/r/20230612081054.17200-7-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core/ump.c')
-rw-r--r--sound/core/ump.c49
1 files changed, 43 insertions, 6 deletions
diff --git a/sound/core/ump.c b/sound/core/ump.c
index 7df50f0affe9..c0cda12bce10 100644
--- a/sound/core/ump.c
+++ b/sound/core/ump.c
@@ -688,6 +688,28 @@ static void fill_fb_info(struct snd_ump_endpoint *ump,
info->sysex8_streams, info->flags);
}
+/* check whether the FB info gets updated by the current message */
+static bool is_fb_info_updated(struct snd_ump_endpoint *ump,
+ struct snd_ump_block *fb,
+ const union snd_ump_stream_msg *buf)
+{
+ char tmpbuf[offsetof(struct snd_ump_block_info, name)];
+
+ memcpy(tmpbuf, &fb->info, sizeof(tmpbuf));
+ fill_fb_info(ump, (struct snd_ump_block_info *)tmpbuf, buf);
+ return memcmp(&fb->info, tmpbuf, sizeof(tmpbuf)) != 0;
+}
+
+/* notify the FB info/name change to sequencer */
+static void seq_notify_fb_change(struct snd_ump_endpoint *ump,
+ struct snd_ump_block *fb)
+{
+#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+ if (ump->seq_ops && ump->seq_ops->notify_fb_change)
+ ump->seq_ops->notify_fb_change(ump, fb);
+#endif
+}
+
/* handle FB info message; update FB info if the block is present */
static int ump_handle_fb_info_msg(struct snd_ump_endpoint *ump,
const union snd_ump_stream_msg *buf)
@@ -697,14 +719,24 @@ static int ump_handle_fb_info_msg(struct snd_ump_endpoint *ump,
blk = buf->fb_info.function_block_id;
fb = snd_ump_get_block(ump, blk);
- if (fb) {
- fill_fb_info(ump, &fb->info, buf);
- } else if (ump->parsed) {
- /* complain only if updated after parsing */
+
+ /* complain only if updated after parsing */
+ if (!fb && ump->parsed) {
ump_info(ump, "Function Block Info Update for non-existing block %d\n",
blk);
return -ENODEV;
}
+
+ /* When updated after the initial parse, check the FB info update */
+ if (ump->parsed && !is_fb_info_updated(ump, fb, buf))
+ return 1; /* no content change */
+
+ if (fb) {
+ fill_fb_info(ump, &fb->info, buf);
+ if (ump->parsed)
+ seq_notify_fb_change(ump, fb);
+ }
+
return 1; /* finished */
}
@@ -714,14 +746,19 @@ static int ump_handle_fb_name_msg(struct snd_ump_endpoint *ump,
{
unsigned char blk;
struct snd_ump_block *fb;
+ int ret;
blk = buf->fb_name.function_block_id;
fb = snd_ump_get_block(ump, blk);
if (!fb)
return -ENODEV;
- return ump_append_string(ump, fb->info.name, sizeof(fb->info.name),
- buf->raw, 3);
+ ret = ump_append_string(ump, fb->info.name, sizeof(fb->info.name),
+ buf->raw, 3);
+ /* notify the FB name update to sequencer, too */
+ if (ret > 0 && ump->parsed)
+ seq_notify_fb_change(ump, fb);
+ return ret;
}
static int create_block_from_fb_info(struct snd_ump_endpoint *ump, int blk)