mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -05:00 
			
		
		
		
	ucm: Improve cset command parsing
The cset command parsing in ucm/main.c assumes implicitly that the
argument contains no space, thus an example below wouldn't work:
    cset "name='Input Select' Digital Mic"
This patch introduces a new internal API function
__snd_ctl_ascii_elem_id_parse() to improve the cset parser.
Reported-by: Tanu Kaskinen <tanu.kaskinen@digia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
			
			
This commit is contained in:
		
							parent
							
								
									c34f74c818
								
							
						
					
					
						commit
						58d10c09e1
					
				
					 2 changed files with 46 additions and 24 deletions
				
			
		| 
						 | 
				
			
			@ -143,21 +143,19 @@ char *snd_ctl_ascii_elem_id_get(snd_ctl_elem_id_t *id)
 | 
			
		|||
	return strdup(buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief parse ASCII string as CTL element identifier
 | 
			
		||||
 * \param dst destination CTL identifier
 | 
			
		||||
 * \param str source ASCII string
 | 
			
		||||
 * \return zero on success, otherwise a negative error code
 | 
			
		||||
 */
 | 
			
		||||
int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str)
 | 
			
		||||
#ifndef DOC_HIDDEN
 | 
			
		||||
/* used by UCM parser, too */
 | 
			
		||||
int __snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str,
 | 
			
		||||
				  const char **ret_ptr)
 | 
			
		||||
{
 | 
			
		||||
	int c, size, numid;
 | 
			
		||||
	int err = -EINVAL;
 | 
			
		||||
	char *ptr;
 | 
			
		||||
 | 
			
		||||
	while (*str == ' ' || *str == '\t')
 | 
			
		||||
	while (isspace(*str))
 | 
			
		||||
		str++;
 | 
			
		||||
	if (!(*str))
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
		goto out;
 | 
			
		||||
	snd_ctl_elem_id_set_interface(dst, SND_CTL_ELEM_IFACE_MIXER);	/* default */
 | 
			
		||||
	while (*str) {
 | 
			
		||||
		if (!strncasecmp(str, "numid=", 6)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -165,7 +163,7 @@ int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str)
 | 
			
		|||
			numid = atoi(str);
 | 
			
		||||
			if (numid <= 0) {
 | 
			
		||||
				fprintf(stderr, "amixer: Invalid numid %d\n", numid);
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
				goto out;
 | 
			
		||||
			}
 | 
			
		||||
			snd_ctl_elem_id_set_numid(dst, atoi(str));
 | 
			
		||||
			while (isdigit(*str))
 | 
			
		||||
| 
						 | 
				
			
			@ -191,7 +189,7 @@ int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str)
 | 
			
		|||
				snd_ctl_elem_id_set_interface(dst, SND_CTL_ELEM_IFACE_SEQUENCER);
 | 
			
		||||
				str += 9;
 | 
			
		||||
			} else {
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
				goto out;
 | 
			
		||||
			}
 | 
			
		||||
		} else if (!strncasecmp(str, "name=", 5)) {
 | 
			
		||||
			char buf[64];
 | 
			
		||||
| 
						 | 
				
			
			@ -239,11 +237,33 @@ int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str)
 | 
			
		|||
		if (*str == ',') {
 | 
			
		||||
			str++;
 | 
			
		||||
		} else {
 | 
			
		||||
			/* when ret_ptr is given, allow to terminate gracefully
 | 
			
		||||
			 * at the next space letter
 | 
			
		||||
			 */
 | 
			
		||||
			if (ret_ptr && isspace(*str))
 | 
			
		||||
				break;
 | 
			
		||||
			if (*str)
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
				goto out;
 | 
			
		||||
		}
 | 
			
		||||
	}			
 | 
			
		||||
	return 0;
 | 
			
		||||
	err = 0;
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
	if (ret_ptr)
 | 
			
		||||
		*ret_ptr = str;
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief parse ASCII string as CTL element identifier
 | 
			
		||||
 * \param dst destination CTL identifier
 | 
			
		||||
 * \param str source ASCII string
 | 
			
		||||
 * \return zero on success, otherwise a negative error code
 | 
			
		||||
 */
 | 
			
		||||
int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str)
 | 
			
		||||
{
 | 
			
		||||
	return __snd_ctl_ascii_elem_id_parse(dst, str, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_ctl_enum_item_index(snd_ctl_t *handle,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,6 +31,7 @@
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
#include "ucm_local.h"
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -158,9 +159,13 @@ static int open_ctl(snd_use_case_mgr_t *uc_mgr,
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern int __snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst,
 | 
			
		||||
					 const char *str,
 | 
			
		||||
					 const char **ret_ptr);
 | 
			
		||||
 | 
			
		||||
static int execute_cset(snd_ctl_t *ctl, char *cset)
 | 
			
		||||
{
 | 
			
		||||
	char *pos;
 | 
			
		||||
	const char *pos;
 | 
			
		||||
	int err;
 | 
			
		||||
	snd_ctl_elem_id_t *id;
 | 
			
		||||
	snd_ctl_elem_value_t *value;
 | 
			
		||||
| 
						 | 
				
			
			@ -170,16 +175,16 @@ static int execute_cset(snd_ctl_t *ctl, char *cset)
 | 
			
		|||
	snd_ctl_elem_value_malloc(&value);
 | 
			
		||||
	snd_ctl_elem_info_malloc(&info);
 | 
			
		||||
 | 
			
		||||
	pos = strrchr(cset, ' ');
 | 
			
		||||
	if (pos == NULL) {
 | 
			
		||||
	err = __snd_ctl_ascii_elem_id_parse(id, cset, &pos);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		goto __fail;
 | 
			
		||||
	while (*pos && isspace(*pos))
 | 
			
		||||
		pos++;
 | 
			
		||||
	if (!*pos) {
 | 
			
		||||
		uc_error("undefined value for cset >%s<", cset);
 | 
			
		||||
		err = -EINVAL;
 | 
			
		||||
		goto __fail;
 | 
			
		||||
	}
 | 
			
		||||
	*pos = '\0';
 | 
			
		||||
	err = snd_ctl_ascii_elem_id_parse(id, cset);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		goto __fail;
 | 
			
		||||
	snd_ctl_elem_value_set_id(value, id);
 | 
			
		||||
	snd_ctl_elem_info_set_id(info, id);
 | 
			
		||||
	err = snd_ctl_elem_read(ctl, value);
 | 
			
		||||
| 
						 | 
				
			
			@ -188,7 +193,7 @@ static int execute_cset(snd_ctl_t *ctl, char *cset)
 | 
			
		|||
	err = snd_ctl_elem_info(ctl, info);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		goto __fail;
 | 
			
		||||
	err = snd_ctl_ascii_value_parse(ctl, value, info, pos + 1);
 | 
			
		||||
	err = snd_ctl_ascii_value_parse(ctl, value, info, pos);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		goto __fail;
 | 
			
		||||
	err = snd_ctl_elem_write(ctl, value);
 | 
			
		||||
| 
						 | 
				
			
			@ -196,9 +201,6 @@ static int execute_cset(snd_ctl_t *ctl, char *cset)
 | 
			
		|||
		goto __fail;
 | 
			
		||||
	err = 0;
 | 
			
		||||
      __fail:
 | 
			
		||||
	if (pos != NULL)
 | 
			
		||||
		*pos = ' ';
 | 
			
		||||
 | 
			
		||||
	if (id != NULL)
 | 
			
		||||
		free(id);
 | 
			
		||||
	if (value != NULL)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue