STR_OUT = SNDRV_RAWMIDI_STREAM_OUTPUT
};
-/* object per UMP group; corresponding to a sequencer port */
-struct seq_ump_group {
- int group; /* group index (0-based) */
- unsigned int dir_bits; /* directions */
- bool active; /* activeness */
- bool valid; /* valid group (referred by blocks) */
- char name[64]; /* seq port name */
-};
-
/* context for UMP input parsing, per EP */
struct seq_ump_input_buffer {
unsigned char len; /* total length in words */
int opened[2]; /* current opens for each direction */
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 */
struct work_struct group_notify_work; /* FB change notification */
};
/* fill port_info from the given UMP EP and group info */
static void fill_port_info(struct snd_seq_port_info *port,
struct seq_ump_client *client,
- struct seq_ump_group *group)
+ struct snd_ump_group *group)
{
unsigned int rawmidi_info = client->ump->core.info_flags;
}
/* skip non-existing group for static blocks */
-static bool skip_group(struct seq_ump_client *client, struct seq_ump_group *group)
+static bool skip_group(struct seq_ump_client *client, struct snd_ump_group *group)
{
return !group->valid &&
(client->ump->info.flags & SNDRV_UMP_EP_INFO_STATIC_BLOCKS);
/* create a new sequencer port per UMP group */
static int seq_ump_group_init(struct seq_ump_client *client, int group_index)
{
- struct seq_ump_group *group = &client->groups[group_index];
+ struct snd_ump_group *group = &client->ump->groups[group_index];
struct snd_seq_port_info *port __free(kfree) = NULL;
struct snd_seq_port_callback pcallbacks;
return;
for (i = 0; i < SNDRV_UMP_MAX_GROUPS; i++) {
- if (skip_group(client, &client->groups[i]))
+ if (skip_group(client, &client->ump->groups[i]))
continue;
old->addr.client = client->seq_client;
old);
if (err < 0)
return;
- fill_port_info(new, client, &client->groups[i]);
+ fill_port_info(new, client, &client->ump->groups[i]);
if (old->capability == new->capability &&
!strcmp(old->name, new->name))
continue;
}
}
-/* update dir_bits and active flag for all groups in the client */
-static void update_group_attrs(struct seq_ump_client *client)
-{
- struct snd_ump_block *fb;
- struct seq_ump_group *group;
- int i;
-
- for (i = 0; i < SNDRV_UMP_MAX_GROUPS; i++) {
- group = &client->groups[i];
- *group->name = 0;
- group->dir_bits = 0;
- group->active = 0;
- group->group = i;
- group->valid = false;
- }
-
- list_for_each_entry(fb, &client->ump->block_list, list) {
- if (fb->info.first_group + fb->info.num_groups > SNDRV_UMP_MAX_GROUPS)
- break;
- group = &client->groups[fb->info.first_group];
- for (i = 0; i < fb->info.num_groups; i++, group++) {
- group->valid = true;
- if (fb->info.active)
- group->active = 1;
- switch (fb->info.direction) {
- case SNDRV_UMP_DIR_INPUT:
- group->dir_bits |= (1 << STR_IN);
- break;
- case SNDRV_UMP_DIR_OUTPUT:
- group->dir_bits |= (1 << STR_OUT);
- break;
- case SNDRV_UMP_DIR_BIDIRECTION:
- group->dir_bits |= (1 << STR_OUT) | (1 << STR_IN);
- break;
- }
- if (!*fb->info.name)
- continue;
- if (!*group->name) {
- /* store the first matching name */
- strscpy(group->name, fb->info.name,
- sizeof(group->name));
- } else {
- /* when overlapping, concat names */
- strlcat(group->name, ", ", sizeof(group->name));
- strlcat(group->name, fb->info.name,
- sizeof(group->name));
- }
- }
- }
-}
-
/* create a UMP Endpoint port */
static int create_ump_endpoint_port(struct seq_ump_client *client)
{
return;
filter = ~(1U << 0); /* always allow groupless messages */
for (p = 0; p < SNDRV_UMP_MAX_GROUPS; p++) {
- if (client->groups[p].active)
+ if (client->ump->groups[p].active)
filter &= ~(1U << (p + 1));
}
cptr->group_filter = filter;
struct seq_ump_client *client =
container_of(work, struct seq_ump_client, group_notify_work);
- update_group_attrs(client);
update_port_infos(client);
setup_client_group_filter(client);
}
client->ump_info[fb->info.block_id + 1] = &fb->info;
setup_client_midi_version(client);
- update_group_attrs(client);
for (p = 0; p < SNDRV_UMP_MAX_GROUPS; p++) {
err = seq_ump_group_init(client, p);
}
}
+/* update dir_bits and active flag for all groups in the client */
+static void update_group_attrs(struct snd_ump_endpoint *ump)
+{
+ struct snd_ump_block *fb;
+ struct snd_ump_group *group;
+ int i;
+
+ for (i = 0; i < SNDRV_UMP_MAX_GROUPS; i++) {
+ group = &ump->groups[i];
+ *group->name = 0;
+ group->dir_bits = 0;
+ group->active = 0;
+ group->group = i;
+ group->valid = false;
+ }
+
+ list_for_each_entry(fb, &ump->block_list, list) {
+ if (fb->info.first_group + fb->info.num_groups > SNDRV_UMP_MAX_GROUPS)
+ break;
+ group = &ump->groups[fb->info.first_group];
+ for (i = 0; i < fb->info.num_groups; i++, group++) {
+ group->valid = true;
+ if (fb->info.active)
+ group->active = 1;
+ switch (fb->info.direction) {
+ case SNDRV_UMP_DIR_INPUT:
+ group->dir_bits |= (1 << SNDRV_RAWMIDI_STREAM_INPUT);
+ break;
+ case SNDRV_UMP_DIR_OUTPUT:
+ group->dir_bits |= (1 << SNDRV_RAWMIDI_STREAM_OUTPUT);
+ break;
+ case SNDRV_UMP_DIR_BIDIRECTION:
+ group->dir_bits |= (1 << SNDRV_RAWMIDI_STREAM_INPUT) |
+ (1 << SNDRV_RAWMIDI_STREAM_OUTPUT);
+ break;
+ }
+ if (!*fb->info.name)
+ continue;
+ if (!*group->name) {
+ /* store the first matching name */
+ strscpy(group->name, fb->info.name,
+ sizeof(group->name));
+ } else {
+ /* when overlapping, concat names */
+ strlcat(group->name, ", ", sizeof(group->name));
+ strlcat(group->name, fb->info.name,
+ sizeof(group->name));
+ }
+ }
+ }
+}
+
/*
* UMP endpoint and function block handling
*/
if (fb) {
fill_fb_info(ump, &fb->info, buf);
- if (ump->parsed)
+ if (ump->parsed) {
+ update_group_attrs(ump);
seq_notify_fb_change(ump, fb);
+ }
}
return 1; /* finished */
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)
+ if (ret > 0 && ump->parsed) {
+ update_group_attrs(ump);
seq_notify_fb_change(ump, fb);
+ }
return ret;
}
continue;
}
+ /* initialize group attributions */
+ update_group_attrs(ump);
+
error:
ump->parsed = true;
ump_request_close(ump);
struct snd_rawmidi *rmidi, int dir)
{
struct snd_rawmidi_substream *s;
-
- list_for_each_entry(s, &rmidi->streams[dir].substreams, list)
+ const char *name;
+ int idx;
+
+ list_for_each_entry(s, &rmidi->streams[dir].substreams, list) {
+ idx = ump->legacy_mapping[s->number];
+ name = ump->groups[idx].name;
+ if (!*name)
+ name = ump->info.name;
snprintf(s->name, sizeof(s->name), "Group %d (%.16s)",
- ump->legacy_mapping[s->number] + 1, ump->info.name);
+ idx + 1, name);
+ }
}
int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump,