On Fri, 08 Apr 2016 19:52:01 +0200, Daniel Mack wrote: > > UAC2 specifies clock sources that optionally have validity controls. > This patch exposes them as mixer controls, so they can be read (and > at least in theory even be written) by userspace applications in order > to make clock selection policy decisions. > > This implementation does nothing if the device is not UAC2 compliant, > or if the clock source does not define said validity control bits. > > Tested with a miniDSP USBStreamer (0x2752/0x0016), > > Signed-off-by: Daniel Mack <daniel@xxxxxxxxxx> > --- > sound/usb/mixer.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 65 insertions(+), 1 deletion(-) > > diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c > index 4f85757..973274b 100644 > --- a/sound/usb/mixer.c > +++ b/sound/usb/mixer.c > @@ -45,6 +45,7 @@ > #include <linux/bitops.h> > #include <linux/init.h> > #include <linux/list.h> > +#include <linux/log2.h> > #include <linux/slab.h> > #include <linux/string.h> > #include <linux/usb.h> > @@ -1378,6 +1379,68 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, > snd_usb_mixer_add_control(&cval->head, kctl); > } > > +static int parse_clock_source_unit(struct mixer_build *state, int unitid, > + void *_ftr) > + > +{ > + struct uac_clock_source_descriptor *hdr = _ftr; > + struct usb_mixer_elem_info *cval; > + struct snd_kcontrol *kctl; > + char name[100]; No need for 100. SNDRV_CTL_ELEM_ID_NAME_MAXLEN should suffice. > + int ret; > + > + if (state->mixer->protocol != UAC_VERSION_2) > + return -EINVAL; > + > + if (hdr->bLength != sizeof(*hdr)) > + return -EINVAL; I wonder whether we should abort here and return an error. It's a wacky firmware, and no kernel error, after all. > + /* > + * The only property of this unit we are interested in is the > + * clock source validity. If that isn't readable, just bail out. > + */ > + if (!uac2_control_is_readable(hdr->bmControls, > + ilog2(UAC2_CS_CONTROL_CLOCK_VALID))) > + return 0; > + > + cval = kzalloc(sizeof(*cval), GFP_KERNEL); > + if (!cval) > + return -ENOMEM; > + > + snd_usb_mixer_elem_init_std(&cval->head, state->mixer, hdr->bClockID); > + > + cval->min = 0; > + cval->max = 1; > + cval->channels = 1; > + cval->val_type = USB_MIXER_BOOLEAN; > + cval->control = UAC2_CS_CONTROL_CLOCK_VALID; > + > + if (uac2_control_is_writeable(hdr->bmControls, > + ilog2(UAC2_CS_CONTROL_CLOCK_VALID))) > + kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval); > + else { > + cval->master_readonly = 1; > + kctl = snd_ctl_new1(&usb_feature_unit_ctl_ro, cval); > + } > + > + if (!kctl) { > + kfree(cval); > + return -ENOMEM; > + } > + > + kctl->private_free = snd_usb_mixer_elem_free; > + ret = snd_usb_copy_string_desc(state, hdr->iClockSource, > + name, sizeof(name)); > + if (ret > 0) > + snprintf(kctl->id.name, sizeof(kctl->id.name), > + "%s validity", name); > + else > + snprintf(kctl->id.name, sizeof(kctl->id.name), > + "Clock source %d validity", hdr->bClockID); Each word in control name is usually starting with a capital letter. thanks, Takashi _______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx http://mailman.alsa-project.org/mailman/listinfo/alsa-devel