Skip to content

Commit 3ab4a31

Browse files
committed
ALSA: seq: Notify UMP EP and FB changes
So far we notify the sequencer client and port changes upon UMP FB changes, but those aren't really corresponding to the UMP updates. e.g. when a FB info gets updated, it's not notified but done only when some of sequencer port attribute is changed. This is no ideal behavior. This patch adds the two new sequencer event types for notifying the UMP EP and FB changes via the announce port. The new event takes snd_seq_ev_ump_notify type data, which is compatible with snd_seq_addr (where the port number is replaced with the block number). The events are sent when the EP and FB info gets updated explicitly via ioctl, or the backend UMP receives the corresponding UMP messages. The sequencer protocol version is bumped to 1.0.5 along with it. Signed-off-by: Takashi Iwai <[email protected]> Link: https://patch.msgid.link/[email protected]
1 parent 10a29de commit 3ab4a31

File tree

7 files changed

+97
-6
lines changed

7 files changed

+97
-6
lines changed

Documentation/sound/designs/midi-2.0.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,13 @@ Sequencer API Extensions
388388
announcement to the ALSA sequencer system port, similarly like the
389389
normal port change notification.
390390

391+
* There are two extended event types for notifying the UMP Endpoint and
392+
Function Block changes via the system announcement port:
393+
type 68 (`SNDRV_SEQ_EVENT_UMP_EP_CHANGE`) and type 69
394+
(`SNDRV_SEQ_EVENT_UMP_BLOCK_CHANGE`). They take the new type,
395+
`snd_seq_ev_ump_notify` in the payload, indicating the client number
396+
and the FB number that are changed.
397+
391398

392399
MIDI2 USB Gadget Function Driver
393400
================================

include/sound/ump.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ struct snd_ump_ops {
8383
struct snd_seq_ump_ops {
8484
void (*input_receive)(struct snd_ump_endpoint *ump,
8585
const u32 *data, int words);
86+
int (*notify_ep_change)(struct snd_ump_endpoint *ump);
8687
int (*notify_fb_change)(struct snd_ump_endpoint *ump,
8788
struct snd_ump_block *fb);
8889
int (*switch_protocol)(struct snd_ump_endpoint *ump);

include/uapi/sound/asequencer.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include <sound/asound.h>
1111

1212
/** version of the sequencer */
13-
#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 4)
13+
#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 5)
1414

1515
/**
1616
* definition of sequencer event types
@@ -92,6 +92,9 @@
9292
#define SNDRV_SEQ_EVENT_PORT_SUBSCRIBED 66 /* ports connected */
9393
#define SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED 67 /* ports disconnected */
9494

95+
#define SNDRV_SEQ_EVENT_UMP_EP_CHANGE 68 /* UMP EP info has changed */
96+
#define SNDRV_SEQ_EVENT_UMP_BLOCK_CHANGE 69 /* UMP block info has changed */
97+
9598
/* 70-89: synthesizer events - obsoleted */
9699

97100
/** user-defined events with fixed length
@@ -253,6 +256,12 @@ struct snd_seq_ev_quote {
253256
struct snd_seq_event *event; /* quoted event */
254257
} __packed;
255258

259+
/* UMP info change notify */
260+
struct snd_seq_ev_ump_notify {
261+
unsigned char client; /**< Client number */
262+
unsigned char block; /**< Block number (optional) */
263+
};
264+
256265
union snd_seq_event_data { /* event data... */
257266
struct snd_seq_ev_note note;
258267
struct snd_seq_ev_ctrl control;
@@ -265,6 +274,7 @@ union snd_seq_event_data { /* event data... */
265274
struct snd_seq_connect connect;
266275
struct snd_seq_result result;
267276
struct snd_seq_ev_quote quote;
277+
struct snd_seq_ev_ump_notify ump_notify;
268278
};
269279

270280
/* sequencer event */

sound/core/seq/seq_clientmgr.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2230,6 +2230,16 @@ static int snd_seq_ioctl_client_ump_info(struct snd_seq_client *caller,
22302230
error:
22312231
mutex_unlock(&cptr->ioctl_mutex);
22322232
snd_seq_client_unlock(cptr);
2233+
if (!err && cmd == SNDRV_SEQ_IOCTL_SET_CLIENT_UMP_INFO) {
2234+
if (type == SNDRV_SEQ_CLIENT_UMP_INFO_ENDPOINT)
2235+
snd_seq_system_ump_notify(client, 0,
2236+
SNDRV_SEQ_EVENT_UMP_EP_CHANGE,
2237+
false);
2238+
else
2239+
snd_seq_system_ump_notify(client, type - 1,
2240+
SNDRV_SEQ_EVENT_UMP_BLOCK_CHANGE,
2241+
false);
2242+
}
22332243
return err;
22342244
}
22352245
#endif

sound/core/seq/seq_system.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ void snd_seq_system_broadcast(int client, int port, int type, bool atomic);
1616
#define notify_event(client, port, type) \
1717
snd_seq_system_broadcast(client, port, type, false)
1818

19+
/* notify UMP EP/FB change event */
20+
static inline void snd_seq_system_ump_notify(int client, int block, int type,
21+
bool atomic)
22+
{
23+
/* reuse the existing snd_seq_system_broadcast():
24+
* struct snd_seq_ev_ump_notify is compatible with struct snd_seq_addr
25+
*/
26+
snd_seq_system_broadcast(client, block, type, atomic);
27+
}
28+
1929
#define snd_seq_system_client_ev_client_start(client) notify_event(client, 0, SNDRV_SEQ_EVENT_CLIENT_START)
2030
#define snd_seq_system_client_ev_client_exit(client) notify_event(client, 0, SNDRV_SEQ_EVENT_CLIENT_EXIT)
2131
#define snd_seq_system_client_ev_client_change(client) notify_event(client, 0, SNDRV_SEQ_EVENT_CLIENT_CHANGE)

sound/core/seq/seq_ump_client.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,33 @@ static void handle_group_notify(struct work_struct *work)
388388
setup_client_group_filter(client);
389389
}
390390

391+
/* UMP EP change notification */
392+
static int seq_ump_notify_ep_change(struct snd_ump_endpoint *ump)
393+
{
394+
struct seq_ump_client *client = ump->seq_client;
395+
struct snd_seq_client *cptr;
396+
int client_id;
397+
398+
if (!client)
399+
return -ENODEV;
400+
client_id = client->seq_client;
401+
cptr = snd_seq_kernel_client_get(client_id);
402+
if (!cptr)
403+
return -ENODEV;
404+
405+
snd_seq_system_ump_notify(client_id, 0, SNDRV_SEQ_EVENT_UMP_EP_CHANGE,
406+
true);
407+
408+
/* update sequencer client name if needed */
409+
if (*ump->core.name && strcmp(ump->core.name, cptr->name)) {
410+
strscpy(cptr->name, ump->core.name, sizeof(cptr->name));
411+
snd_seq_system_client_ev_client_change(client_id);
412+
}
413+
414+
snd_seq_kernel_client_put(cptr);
415+
return 0;
416+
}
417+
391418
/* UMP FB change notification */
392419
static int seq_ump_notify_fb_change(struct snd_ump_endpoint *ump,
393420
struct snd_ump_block *fb)
@@ -397,20 +424,29 @@ static int seq_ump_notify_fb_change(struct snd_ump_endpoint *ump,
397424
if (!client)
398425
return -ENODEV;
399426
schedule_work(&client->group_notify_work);
427+
snd_seq_system_ump_notify(client->seq_client, fb->info.block_id,
428+
SNDRV_SEQ_EVENT_UMP_BLOCK_CHANGE,
429+
true);
400430
return 0;
401431
}
402432

403433
/* UMP protocol change notification; just update the midi_version field */
404434
static int seq_ump_switch_protocol(struct snd_ump_endpoint *ump)
405435
{
406-
if (!ump->seq_client)
436+
struct seq_ump_client *client = ump->seq_client;
437+
438+
if (!client)
407439
return -ENODEV;
408-
setup_client_midi_version(ump->seq_client);
440+
setup_client_midi_version(client);
441+
snd_seq_system_ump_notify(client->seq_client, 0,
442+
SNDRV_SEQ_EVENT_UMP_EP_CHANGE,
443+
true);
409444
return 0;
410445
}
411446

412447
static const struct snd_seq_ump_ops seq_ump_ops = {
413448
.input_receive = seq_ump_input_receive,
449+
.notify_ep_change = seq_ump_notify_ep_change,
414450
.notify_fb_change = seq_ump_notify_fb_change,
415451
.switch_protocol = seq_ump_switch_protocol,
416452
};

sound/core/ump.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,15 @@ static void choose_default_protocol(struct snd_ump_endpoint *ump)
695695
ump->info.protocol |= SNDRV_UMP_EP_INFO_PROTO_MIDI1;
696696
}
697697

698+
/* notify the EP info/name change to sequencer */
699+
static void seq_notify_ep_change(struct snd_ump_endpoint *ump)
700+
{
701+
#if IS_ENABLED(CONFIG_SND_SEQUENCER)
702+
if (ump->parsed && ump->seq_ops && ump->seq_ops->notify_ep_change)
703+
ump->seq_ops->notify_ep_change(ump);
704+
#endif
705+
}
706+
698707
/* handle EP info stream message; update the UMP attributes */
699708
static int ump_handle_ep_info_msg(struct snd_ump_endpoint *ump,
700709
const union snd_ump_stream_msg *buf)
@@ -719,6 +728,7 @@ static int ump_handle_ep_info_msg(struct snd_ump_endpoint *ump,
719728

720729
ump->info.protocol &= ump->info.protocol_caps;
721730
choose_default_protocol(ump);
731+
seq_notify_ep_change(ump);
722732

723733
return 1; /* finished */
724734
}
@@ -741,6 +751,7 @@ static int ump_handle_device_info_msg(struct snd_ump_endpoint *ump,
741751
ump->info.family_id,
742752
ump->info.model_id,
743753
ump->info.sw_revision);
754+
seq_notify_ep_change(ump);
744755
return 1; /* finished */
745756
}
746757

@@ -762,6 +773,7 @@ static int ump_handle_ep_name_msg(struct snd_ump_endpoint *ump,
762773
if (ret && ump->parsed) {
763774
ump_set_rawmidi_name(ump);
764775
ump_legacy_set_rawmidi_name(ump);
776+
seq_notify_ep_change(ump);
765777
}
766778

767779
return ret;
@@ -771,9 +783,14 @@ static int ump_handle_ep_name_msg(struct snd_ump_endpoint *ump,
771783
static int ump_handle_product_id_msg(struct snd_ump_endpoint *ump,
772784
const union snd_ump_stream_msg *buf)
773785
{
774-
return ump_append_string(ump, ump->info.product_id,
775-
sizeof(ump->info.product_id),
776-
buf->raw, 2);
786+
int ret;
787+
788+
ret = ump_append_string(ump, ump->info.product_id,
789+
sizeof(ump->info.product_id),
790+
buf->raw, 2);
791+
if (ret)
792+
seq_notify_ep_change(ump);
793+
return ret;
777794
}
778795

779796
/* notify the protocol change to sequencer */

0 commit comments

Comments
 (0)