ucm: add _fboot / FixedBootSequence
Actually, the BootSequence is executed only when the driver controls
(identifiers or value types) are changed. It may be handy to have
also a sequence which is executed at _each_ boot without any condition.
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Jaroslav Kysela
3 years ago
417 | 417 | * \return Zero if success, otherwise a negative error code |
418 | 418 | * |
419 | 419 | * Known identifiers: |
420 | * - _fboot - execute the fixed boot sequence (value = NULL) | |
420 | 421 | * - _boot - execute the boot sequence (value = NULL) |
422 | * - only when driver controls identifiers are changed | |
423 | * (otherwise the old control values are restored) | |
421 | 424 | * - _defaults - execute the 'defaults' sequence (value = NULL) |
422 | 425 | * - _verb - set current verb = value |
423 | 426 | * - _enadev - enable given device = value |
593 | 593 | } |
594 | 594 | if (!list_empty(&uc_mgr->verb_list)) |
595 | 595 | return 0; |
596 | if (!list_empty(&uc_mgr->fixedboot_list)) | |
597 | return 0; | |
596 | 598 | if (!list_empty(&uc_mgr->boot_list)) |
597 | 599 | return 0; |
598 | 600 | return -ENXIO; |
992 | 994 | if (mgr == NULL) |
993 | 995 | return -ENOMEM; |
994 | 996 | INIT_LIST_HEAD(&mgr->verb_list); |
997 | INIT_LIST_HEAD(&mgr->fixedboot_list); | |
995 | 998 | INIT_LIST_HEAD(&mgr->boot_list); |
996 | 999 | INIT_LIST_HEAD(&mgr->default_list); |
997 | 1000 | INIT_LIST_HEAD(&mgr->value_list); |
1885 | 1888 | return err; |
1886 | 1889 | } |
1887 | 1890 | |
1891 | static int set_fixedboot_user(snd_use_case_mgr_t *uc_mgr, | |
1892 | const char *value) | |
1893 | { | |
1894 | int err; | |
1895 | ||
1896 | if (value != NULL && *value) { | |
1897 | uc_error("error: wrong value for _fboot (%s)", value); | |
1898 | return -EINVAL; | |
1899 | } | |
1900 | err = execute_sequence(uc_mgr, &uc_mgr->fixedboot_list, | |
1901 | &uc_mgr->value_list, NULL, NULL); | |
1902 | if (err < 0) { | |
1903 | uc_error("Unable to execute force boot sequence"); | |
1904 | return err; | |
1905 | } | |
1906 | return err; | |
1907 | } | |
1908 | ||
1888 | 1909 | static int set_boot_user(snd_use_case_mgr_t *uc_mgr, |
1889 | 1910 | const char *value) |
1890 | 1911 | { |
2124 | 2145 | int err = 0; |
2125 | 2146 | |
2126 | 2147 | pthread_mutex_lock(&uc_mgr->mutex); |
2127 | if (strcmp(identifier, "_boot") == 0) | |
2148 | if (strcmp(identifier, "_fboot") == 0) | |
2149 | err = set_fixedboot_user(uc_mgr, value); | |
2150 | else if (strcmp(identifier, "_boot") == 0) | |
2128 | 2151 | err = set_boot_user(uc_mgr, value); |
2129 | 2152 | else if (strcmp(identifier, "_defaults") == 0) |
2130 | 2153 | err = set_defaults_user(uc_mgr, value); |
1739 | 1739 | } |
1740 | 1740 | |
1741 | 1741 | /* |
1742 | * parse controls which should be run only at initial boot (forcefully) | |
1743 | */ | |
1744 | static int parse_controls_fixedboot(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg) | |
1745 | { | |
1746 | int err; | |
1747 | ||
1748 | if (!list_empty(&uc_mgr->fixedboot_list)) { | |
1749 | uc_error("FixedBoot list is not empty"); | |
1750 | return -EINVAL; | |
1751 | } | |
1752 | err = parse_sequence(uc_mgr, &uc_mgr->fixedboot_list, cfg); | |
1753 | if (err < 0) { | |
1754 | uc_error("Unable to parse FixedBootSequence"); | |
1755 | return err; | |
1756 | } | |
1757 | ||
1758 | return 0; | |
1759 | } | |
1760 | ||
1761 | /* | |
1742 | 1762 | * parse controls which should be run only at initial boot |
1743 | 1763 | */ |
1744 | 1764 | static int parse_controls_boot(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg) |
1885 | 1905 | err = parse_compound(uc_mgr, n, |
1886 | 1906 | parse_master_section, |
1887 | 1907 | NULL, NULL); |
1908 | if (err < 0) | |
1909 | return err; | |
1910 | continue; | |
1911 | } | |
1912 | ||
1913 | /* find default control values section (force boot sequence only) */ | |
1914 | if (strcmp(id, "FixedBootSequence") == 0) { | |
1915 | err = parse_controls_fixedboot(uc_mgr, n); | |
1888 | 1916 | if (err < 0) |
1889 | 1917 | return err; |
1890 | 1918 | continue; |