From patchwork Fri Apr 8 17:52:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Mack X-Patchwork-Id: 8785141 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 48AC09F659 for ; Fri, 8 Apr 2016 17:52:58 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 59F90202FF for ; Fri, 8 Apr 2016 17:52:57 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 262B6202EB for ; Fri, 8 Apr 2016 17:52:56 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 385C326641C; Fri, 8 Apr 2016 19:52:52 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,NO_DNS_FOR_FROM, RCVD_IN_DNSWL_NONE,UNPARSEABLE_RELAY autolearn=no version=3.3.1 Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 287332666C2; Fri, 8 Apr 2016 19:52:21 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 832FD2655E3; Fri, 8 Apr 2016 19:52:19 +0200 (CEST) Received: from mail.zonque.de (svenfoo.org [82.94.215.22]) by alsa0.perex.cz (Postfix) with ESMTP id 1BD3A265132 for ; Fri, 8 Apr 2016 19:52:12 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by mail.zonque.de (Postfix) with ESMTP id 6830DC0130; Fri, 8 Apr 2016 19:52:11 +0200 (CEST) Received: from mail.zonque.de ([127.0.0.1]) by localhost (rambrand.bugwerft.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id UoHo_asrHy3M; Fri, 8 Apr 2016 19:52:11 +0200 (CEST) Received: from tamtam.fritz.box (p5DDC4AA7.dip0.t-ipconnect.de [93.220.74.167]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.zonque.de (Postfix) with ESMTPSA id D6561C0028; Fri, 8 Apr 2016 19:52:10 +0200 (CEST) From: Daniel Mack To: alsa-devel@alsa-project.org Date: Fri, 8 Apr 2016 19:52:01 +0200 Message-Id: <1460137922-8993-1-git-send-email-daniel@zonque.org> X-Mailer: git-send-email 2.4.3 Cc: tiwai@suse.de, orm.finnendahl@selma.hfmdk-frankfurt.de, clemens@ladisch.de, jan.baumgart@selma.hfmdk-frankfurt.de, Daniel Mack Subject: [alsa-devel] [PATCH 1/2] sound: usb: add UAC2 clock sources as mixer controls X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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 #include #include +#include #include #include #include @@ -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]; + int ret; + + if (state->mixer->protocol != UAC_VERSION_2) + return -EINVAL; + + if (hdr->bLength != sizeof(*hdr)) + return -EINVAL; + + /* + * 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); + + return snd_usb_mixer_add_control(&cval->head, kctl); +} + /* * parse a feature unit * @@ -2126,10 +2189,11 @@ static int parse_audio_unit(struct mixer_build *state, int unitid) switch (p1[2]) { case UAC_INPUT_TERMINAL: - case UAC2_CLOCK_SOURCE: return 0; /* NOP */ case UAC_MIXER_UNIT: return parse_audio_mixer_unit(state, unitid, p1); + case UAC2_CLOCK_SOURCE: + return parse_clock_source_unit(state, unitid, p1); case UAC_SELECTOR_UNIT: case UAC2_CLOCK_SELECTOR: return parse_audio_selector_unit(state, unitid, p1);