[alsa-devel] [PATCH 3/3] ALSA: core: set kcontrol's count field correctly

Lu Guanqun guanqun.lu at intel.com
Wed Aug 24 13:46:13 CEST 2011


On Wed, Aug 24, 2011 at 04:42:05PM +0800, Takashi Iwai wrote:
> ---
> diff --git a/include/sound/asound.h b/include/sound/asound.h
> index 5d6074f..9f5f55d 100644
> --- a/include/sound/asound.h
> +++ b/include/sound/asound.h
> @@ -813,6 +813,33 @@ struct snd_ctl_elem_info {
>  	unsigned char reserved[64-4*sizeof(unsigned short)];
>  };
>  
> +/* The struct used for ELEM_ADD and ELEM_REPLACE ioctls;
> + * This is is identical with snd_ctl_elem_info, but just owner field is
> + * different, keeping the number of elements to be created.
> + * The unused fields are stripped for simplicity.
> + */
> +struct snd_ctl_elem_add_info {
> +	struct snd_ctl_elem_id id;	/* element ID */
> +	snd_ctl_elem_type_t type;	/* value type */
> +	unsigned int access;		/* value access (bitmask) */
> +	unsigned int count;		/* count of values */
> +	__kernel_pid_t elem_count;	/* # of elements to create (0=1) */
> +	union {
> +		struct {
> +			long min;		/* R: minimum value */
> +			long max;		/* R: maximum value */
> +			long step;		/* R: step (0 variable) */
> +		} integer;
> +		struct {
> +			long long min;		/* R: minimum value */
> +			long long max;		/* R: maximum value */
> +			long long step;		/* R: step (0 variable) */
> +		} integer64;
> +		unsigned char reserved[128];
> +	} value;
> +	unsigned char reserved[64];
> +};
> +
>  struct snd_ctl_elem_value {
>  	struct snd_ctl_elem_id id;	/* W: element ID */
>  	unsigned int indirect: 1;	/* W: indirect access - obsoleted */
> @@ -854,8 +881,8 @@ struct snd_ctl_tlv {
>  #define SNDRV_CTL_IOCTL_ELEM_LOCK	_IOW('U', 0x14, struct snd_ctl_elem_id)
>  #define SNDRV_CTL_IOCTL_ELEM_UNLOCK	_IOW('U', 0x15, struct snd_ctl_elem_id)
>  #define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
> -#define SNDRV_CTL_IOCTL_ELEM_ADD	_IOWR('U', 0x17, struct snd_ctl_elem_info)
> -#define SNDRV_CTL_IOCTL_ELEM_REPLACE	_IOWR('U', 0x18, struct snd_ctl_elem_info)
> +#define SNDRV_CTL_IOCTL_ELEM_ADD	_IOWR('U', 0x17, struct snd_ctl_elem_add_info)
> +#define SNDRV_CTL_IOCTL_ELEM_REPLACE	_IOWR('U', 0x18, struct snd_ctl_elem_add_info)
>  #define SNDRV_CTL_IOCTL_ELEM_REMOVE	_IOWR('U', 0x19, struct snd_ctl_elem_id)
>  #define SNDRV_CTL_IOCTL_TLV_READ	_IOWR('U', 0x1a, struct snd_ctl_tlv)
>  #define SNDRV_CTL_IOCTL_TLV_WRITE	_IOWR('U', 0x1b, struct snd_ctl_tlv)
> diff --git a/sound/core/control.c b/sound/core/control.c
> index dc2a440..15c171d 100644
> --- a/sound/core/control.c
> +++ b/sound/core/control.c
> @@ -1064,7 +1064,7 @@ static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol)
>  }
>  
>  static int snd_ctl_elem_add(struct snd_ctl_file *file,
> -			    struct snd_ctl_elem_info *info, int replace)
> +			    struct snd_ctl_elem_add_info *info, int replace)
>  {
>  	struct snd_card *card = file->card;
>  	struct snd_kcontrol kctl, *_kctl;
> @@ -1099,7 +1099,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
>  	if (err < 0)
>  		return err;
>  	memcpy(&kctl.id, &info->id, sizeof(info->id));
> -	kctl.count = info->owner ? info->owner : 1;
> +	kctl.count = info->elem_count ? info->elem_count : 1;

Hi Takashi,

I don't how this approach can solve this problem. There's still an
implicit assumption here that user space application will clear
info->elem_count to zero before it issues the REPLACE ioctl, right?

>  	access |= SNDRV_CTL_ELEM_ACCESS_USER;
>  	kctl.info = snd_ctl_elem_user_info;
>  	if (access & SNDRV_CTL_ELEM_ACCESS_READ)
> @@ -1139,7 +1139,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
>  	ue = kzalloc(sizeof(struct user_element) + private_size, GFP_KERNEL);
>  	if (ue == NULL)
>  		return -ENOMEM;
> -	ue->info = *info;
> +	memcpy(&ue->info, info, sizeof(*info));

Should we add some assertion here checking the size of these two
structure should be the same?

>  	ue->info.access = 0;
>  	ue->elem_data = (char *)ue + sizeof(*ue);
>  	ue->elem_data_size = private_size;
> @@ -1164,9 +1164,10 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
>  }
>  
>  static int snd_ctl_elem_add_user(struct snd_ctl_file *file,
> -				 struct snd_ctl_elem_info __user *_info, int replace)
> +				 struct snd_ctl_elem_add_info __user *_info,
> +				 int replace)
>  {
> -	struct snd_ctl_elem_info info;
> +	struct snd_ctl_elem_add_info info;
>  	if (copy_from_user(&info, _info, sizeof(info)))
>  		return -EFAULT;
>  	return snd_ctl_elem_add(file, &info, replace);

-- 
guanqun


More information about the Alsa-devel mailing list