[alsa-devel] [PATCH v4 1/2] ucm: Load device-specific configuration file based on the card long name

Takashi Iwai tiwai at suse.de
Sun Jan 15 09:25:14 CET 2017


On Sat, 14 Jan 2017 09:23:55 +0100,
mengdong.lin at linux.intel.com wrote:
> 
> From: Mengdong Lin <mengdong.lin at linux.intel.com>
> 
> Intel DSP platform drivers are used by many different devices. For user
> space to differentiate them, ASoC machine drivers may use the DMI info
> (vendor-product-version-board) as card long name. Possible card long names
> are:
> DellInc.-XPS139343-01-0310JH
> ASUSTeKCOMPUTERINC.-T100TA-1.0-T100TA
> Circuitco-MinnowboardMaxD0PLATFORM-D0-MinnowBoardMAX
> ...
> 
> And user space can define configuration files like longname\longname.conf
> for a specific device.

Do you mean a file name containing a backslash?
I didn't find the relevant code in your patch...


> When being asked to load configuration file of a card, UCM will try to
> find the card in the local machine and get its long name. If the card
> long name is available, try to load the file longname\longname.conf to
> get the best device-specific configuration; if this file is not available,
> fall back to load the default configuration file shortname\shortname.conf
> as before.
> 
> This update is backward compatible, because if ASoC machine drivers don't
> explicity use DMI or other means to set the card long name, ASoC core
> will use the card short name as the long name. And so UCM will load the
> config file that matches both the card short name and the long name.
> 
> Signed-off-by: Mengdong Lin <mengdong.lin at linux.intel.com>
> 
> diff --git a/src/ucm/parser.c b/src/ucm/parser.c
> index c98373a..14ee33f 100644
> --- a/src/ucm/parser.c
> +++ b/src/ucm/parser.c
> @@ -55,6 +55,9 @@ static const char * const component_dir[] = {
>  	NULL,		/* terminator */
>  };
>  
> +static int filename_filter(const struct dirent *dirent);
> +static int is_component_directory(const char *dir);
> +
>  static int parse_sequence(snd_use_case_mgr_t *uc_mgr,
>  			  struct list_head *base,
>  			  snd_config_t *cfg);
> @@ -1328,6 +1331,66 @@ static int parse_master_file(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg)
>  	return 0;
>  }
>  
> +/* find the card in the local machine and store the card long name */
> +static int get_card_long_name(snd_use_case_mgr_t *mgr)
> +{
> +	const char *card_name = mgr->card_name;
> +	snd_ctl_t *handle;
> +	int card, err;
> +	snd_ctl_card_info_t *info;
> +	const char *_name, *_long_name;
> +
> +	snd_ctl_card_info_alloca(&info);
> +
> +	card = -1;
> +	if (snd_card_next(&card) < 0 || card < 0) {
> +		uc_error("no soundcards found...");
> +		return -1;
> +	}
> +
> +	while (card >= 0) {
> +		char name[32];
> +
> +		sprintf(name, "hw:%d", card);
> +		err = snd_ctl_open(&handle, name, 0);
> +		if (err < 0) {
> +			uc_error("control open (%i): %s", card,
> +				 snd_strerror(err));
> +			goto next_card;
> +		}
> +
> +		err = snd_ctl_card_info(handle, info);
> +		if (err < 0) {
> +			uc_error("control hardware info (%i): %s", card,
> +				 snd_strerror(err));
> +			snd_ctl_close(handle);
> +			goto next_card;
> +		}
> +
> +		/* Find the local card by comparing the given name with the
> +		 * card name and long name. User may open a card by its long
> +		 * name, so the given card name may be a long name.
> +		 */
> +		_name = snd_ctl_card_info_get_name(info);
> +		_long_name = snd_ctl_card_info_get_longname(info);
> +		if (!strncmp(card_name, _name, MAX_CARD_LONG_NAME)
> +		    || !strncmp(card_name, _long_name, MAX_CARD_LONG_NAME)) {
> +			strncpy(mgr->card_long_name, _long_name,
> +				MAX_CARD_LONG_NAME - 1);

It's safer to assure the NUL-terminated string in mgr->card_name &
co.  Then the above strncmp() can be a simple strcmp().


thanks,

Takashi

> +			snd_ctl_close(handle);
> +			return 0;
> +		}
> +
> +		snd_ctl_close(handle);
> +next_card:
> +		if (snd_card_next(&card) < 0) {
> +			uc_error("snd_card_next");
> +			break;
> +		}
> +	}
> +
> +	return -1;
> +}
>  static int load_master_config(const char *card_name, snd_config_t **cfg)
>  {
>  	char filename[MAX_FILE];
> @@ -1349,15 +1412,45 @@ static int load_master_config(const char *card_name, snd_config_t **cfg)
>  	return 0;
>  }
>  
> -/* load master use case file for sound card */
> +/* load master use case file for sound card
> + *
> + * The same ASoC machine driver can be shared by many different devices.
> + * For user space to differentiate them and get the best device-specific
> + * configuration, ASoC machine drivers may use the DMI info
> + * (vendor.product.board) as the card long name. And user space can define
> + * configuration files like longname\longname.conf for a specific device.
> + *
> + * This function will try to find the card in the local machine and get its
> + * long name, then load the file longname\longname.conf to get the best
> + * device-specific configuration. If the card is not found in the local
> + * machine or the device-specific file is not available, fall back to load
> + * the default configuration file name\name.conf.
> + */
>  int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr)
>  {
>  	snd_config_t *cfg;
>  	int err;
>  
> -	err = load_master_config(uc_mgr->card_name, &cfg);
> -	if (err < 0)
> -		return err;
> +	err = get_card_long_name(uc_mgr);
> +	if (err == 0)	/* load file that maches the card long name */
> +		err = load_master_config(uc_mgr->card_long_name, &cfg);
> +
> +	if (err == 0) {
> +		/* got device-specific file that matches the card long name */
> +		strncpy(uc_mgr->conf_file_name, uc_mgr->card_long_name,
> +			MAX_CARD_LONG_NAME - 1);
> +	} else {
> +		/* Fall back to the file that maches the given card name,
> +		 * either short name or long name (users may open a card by
> +		 * its name or long name).
> +		 */
> +		err = load_master_config(uc_mgr->card_name, &cfg);
> +		if (err < 0)
> +			return err;
> +		strncpy(uc_mgr->conf_file_name, uc_mgr->card_name,
> +			MAX_CARD_LONG_NAME - 1);
> +	}
> +
>  	err = parse_master_file(uc_mgr, cfg);
>  	snd_config_delete(cfg);
>  	if (err < 0)
> diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h
> index 6d3302f..299a5b9 100644
> --- a/src/ucm/ucm_local.h
> +++ b/src/ucm/ucm_local.h
> @@ -41,6 +41,7 @@
>  #include "use-case.h"
>  
>  #define MAX_FILE		256
> +#define MAX_CARD_LONG_NAME	80
>  #define ALSA_USE_CASE_DIR	ALSA_CONFIG_DIR "/ucm"
>  
>  #define SEQUENCE_ELEMENT_TYPE_CDEV	1
> @@ -190,6 +191,8 @@ struct use_case_verb {
>   */
>  struct snd_use_case_mgr {
>  	char *card_name;
> +	char card_long_name[MAX_CARD_LONG_NAME];
> +	char conf_file_name[MAX_CARD_LONG_NAME];
>  	char *comment;
>  
>  	/* use case verb, devices and modifier configs parsed from files */
> -- 
> 2.7.4
> 


More information about the Alsa-devel mailing list