Message ID | s5hlhrur8nu.wl%tiwai@suse.de (mailing list archive) |
---|---|
State | Accepted |
Commit | 0cea76f3393782d67ccea8f07e9abf341bc4f60e |
Headers | show |
On Tue, Jul 15, 2014 at 04:36:21PM +0200, Takashi Iwai wrote: > At Tue, 15 Jul 2014 12:17:45 +0530, > Vinod Koul wrote: > > > > From: Omair Mohammed Abdullah <omair.m.abdullah@intel.com> > > > > ALSA supports arbitrary length TLVs for each kcontrol that can be used > > to pass metadata about the control (e.g. volumes, enum information). The > > same transport mechanism is now used for arbitrary length data by > > defining a new helper. > > > > Signed-off-by: Omair Mohammed Abdullah <omair.m.abdullah@intel.com> > > Signed-off-by: Vinod Koul <vinod.koul@intel.com> > > --- > > As discussed in [1] we are adding a new approach to solve the byte control > > extensions by using existing TLVs and combining them with byte controls. The > > usermode on seeing byte control + TLV can treat it differently as it does for > > control + TLV combination today. This way we don't change kernel API and > > existing users will be happy, while providing embedded folks facility to pass > > large bytes data to kcontrols > > [1]: > > http://mailman.alsa-project.org/pipermail/alsa-devel/2013-November/069483.html > > Yeah, this would bypass the limitation nicely. Yes thats what I realized when Omair pointed this out! > > +int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag, > > + unsigned int size, unsigned int __user *tlv) > > +{ > > + struct soc_bytes_ext *params = (void *)kcontrol->private_value; > > + unsigned int count = size < params->max ? size : params->max; > > + > > + switch (op_flag) { > > + case 0: > > + if (params->get) > > + params->get(tlv, count); > > + break; > > + case 1: > > + if (params->put) > > + params->put(tlv, count); > > + break; > > No error propagation from the callback? > Also, if a driver doesn't provide get or put, it gets no error? Will fix that > > BTW, about the value of op_flag: I have a patch to define the > constants (attached below), which I forgot until now. Now I put it > into topic/tlv-opflag branch of sound git tree. If you'd like to use > the new constants, merge (or base on) this branch. yes rebased now..
diff --git a/include/sound/control.h b/include/sound/control.h index 5358892b1b39..042613938a1d 100644 --- a/include/sound/control.h +++ b/include/sound/control.h @@ -31,10 +31,15 @@ typedef int (snd_kcontrol_info_t) (struct snd_kcontrol * kcontrol, struct snd_ct typedef int (snd_kcontrol_get_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol); typedef int (snd_kcontrol_put_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol); typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol, - int op_flag, /* 0=read,1=write,-1=command */ + int op_flag, /* SNDRV_CTL_TLV_OP_XXX */ unsigned int size, unsigned int __user *tlv); +enum { + SNDRV_CTL_TLV_OP_READ = 0, + SNDRV_CTL_TLV_OP_WRITE = 1, + SNDRV_CTL_TLV_OP_CMD = -1, +}; struct snd_kcontrol_new { snd_ctl_elem_iface_t iface; /* interface identifier */ diff --git a/sound/core/control.c b/sound/core/control.c index f0b0e14497a5..b9611344ff9e 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -1406,11 +1406,11 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS: return snd_ctl_subscribe_events(ctl, ip); case SNDRV_CTL_IOCTL_TLV_READ: - return snd_ctl_tlv_ioctl(ctl, argp, 0); + return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_READ); case SNDRV_CTL_IOCTL_TLV_WRITE: - return snd_ctl_tlv_ioctl(ctl, argp, 1); + return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_WRITE); case SNDRV_CTL_IOCTL_TLV_COMMAND: - return snd_ctl_tlv_ioctl(ctl, argp, -1); + return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_CMD); case SNDRV_CTL_IOCTL_POWER: return -ENOPROTOOPT; case SNDRV_CTL_IOCTL_POWER_STATE: