mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2026-02-26 01:40:07 -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)
|
static int verb_dev_list_check(struct use_case_verb *verb)
|
||||||
{
|
{
|
||||||
struct list_head *pos, *pos2;
|
struct list_head *pos, *pos2, *pos3;
|
||||||
struct use_case_device *device;
|
struct use_case_device *device, *target_dev;
|
||||||
struct dev_list_node *dlist;
|
struct dev_list_node *dlist, *dlist2;
|
||||||
int err;
|
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) {
|
list_for_each(pos, &verb->device_list) {
|
||||||
device = list_entry(pos, struct use_case_device, list);
|
device = list_entry(pos, struct use_case_device, list);
|
||||||
list_for_each(pos2, &device->dev_list.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;
|
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;
|
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) {
|
list_for_each(pos, &dev_list->list) {
|
||||||
dlist = list_entry(pos, struct dev_list_node, list);
|
dlist = list_entry(pos, struct dev_list_node, list);
|
||||||
if (strcmp(dlist->name, name) == 0)
|
if (strcmp(dlist->name, name) == 0)
|
||||||
return 0;
|
return 0; /* already exists, no change */
|
||||||
}
|
}
|
||||||
|
|
||||||
dlist = calloc(1, sizeof(*dlist));
|
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;
|
dlist->name = n;
|
||||||
list_add(&dlist->list, &dev_list->list);
|
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,
|
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