mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2026-02-05 04:06:34 -05:00
ucm: complete dependency graphs for conflicting/supported device lists
Modify verb_dev_list_check() to ensure all devices in a conflicting or supported group reference each other. Previously, the function only ensured bidirectional relationships. Now it ensures all devices in the same group have complete dependency lists. Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
parent
3149ca0f1c
commit
22f8716af9
2 changed files with 65 additions and 6 deletions
|
|
@ -2043,11 +2043,14 @@ static int verb_dev_list_add(struct use_case_verb *verb,
|
|||
|
||||
static int verb_dev_list_check(struct use_case_verb *verb)
|
||||
{
|
||||
struct list_head *pos, *pos2;
|
||||
struct use_case_device *device;
|
||||
struct dev_list_node *dlist;
|
||||
int err;
|
||||
struct list_head *pos, *pos2, *pos3;
|
||||
struct use_case_device *device, *target_dev;
|
||||
struct dev_list_node *dlist, *dlist2;
|
||||
int err, iteration;
|
||||
int max_iterations = 100; /* safety limit to prevent infinite loops */
|
||||
bool added_something;
|
||||
|
||||
/* First pass: ensure bidirectional relationships */
|
||||
list_for_each(pos, &verb->device_list) {
|
||||
device = list_entry(pos, struct use_case_device, list);
|
||||
list_for_each(pos2, &device->dev_list.list) {
|
||||
|
|
@ -2058,6 +2061,62 @@ static int verb_dev_list_check(struct use_case_verb *verb)
|
|||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Second pass: complete other relationships for devices in group.
|
||||
* For n devices, at most n-1 iterations are needed.
|
||||
*/
|
||||
for (iteration = 0; iteration < max_iterations; iteration++) {
|
||||
added_something = false;
|
||||
|
||||
list_for_each(pos, &verb->device_list) {
|
||||
device = list_entry(pos, struct use_case_device, list);
|
||||
|
||||
if (device->dev_list.type == DEVLIST_NONE)
|
||||
continue;
|
||||
|
||||
list_for_each(pos2, &device->dev_list.list) {
|
||||
dlist = list_entry(pos2, struct dev_list_node, list);
|
||||
|
||||
target_dev = NULL;
|
||||
list_for_each(pos3, &verb->device_list) {
|
||||
struct use_case_device *tmp_dev;
|
||||
tmp_dev = list_entry(pos3, struct use_case_device, list);
|
||||
if (strcmp(tmp_dev->name, dlist->name) == 0) {
|
||||
target_dev = tmp_dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!target_dev)
|
||||
continue;
|
||||
|
||||
list_for_each(pos3, &device->dev_list.list) {
|
||||
dlist2 = list_entry(pos3, struct dev_list_node, list);
|
||||
|
||||
if (strcmp(dlist2->name, target_dev->name) == 0)
|
||||
continue;
|
||||
|
||||
/* verb_dev_list_add returns 1 if device was added, 0 if already exists */
|
||||
err = verb_dev_list_add(verb, device->dev_list.type,
|
||||
target_dev->name, dlist2->name);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (err > 0)
|
||||
added_something = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If nothing was added in this iteration, we're done */
|
||||
if (!added_something)
|
||||
break;
|
||||
}
|
||||
|
||||
if (iteration >= max_iterations) {
|
||||
snd_error(UCM, "too many device list iterations for verb '%s'", verb->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -448,7 +448,7 @@ int uc_mgr_put_to_dev_list(struct dev_list *dev_list, const char *name)
|
|||
list_for_each(pos, &dev_list->list) {
|
||||
dlist = list_entry(pos, struct dev_list_node, list);
|
||||
if (strcmp(dlist->name, name) == 0)
|
||||
return 0;
|
||||
return 0; /* already exists, no change */
|
||||
}
|
||||
|
||||
dlist = calloc(1, sizeof(*dlist));
|
||||
|
|
@ -461,7 +461,7 @@ int uc_mgr_put_to_dev_list(struct dev_list *dev_list, const char *name)
|
|||
}
|
||||
dlist->name = n;
|
||||
list_add(&dlist->list, &dev_list->list);
|
||||
return 0;
|
||||
return 1; /* new device added */
|
||||
}
|
||||
|
||||
int uc_mgr_rename_in_dev_list(struct dev_list *dev_list, const char *src,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue