From patchwork Thu Aug 13 11:04:46 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julian Scheel X-Patchwork-Id: 7007561 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 CE7159F344 for ; Thu, 13 Aug 2015 11:05:21 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id ACCD92070E for ; Thu, 13 Aug 2015 11:05:20 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 0DC8120710 for ; Thu, 13 Aug 2015 11:05:19 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 74E80261A3D; Thu, 13 Aug 2015 13:05:17 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,NO_DNS_FOR_FROM, RCVD_IN_DNSWL_LOW,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id E9F632616C9; Thu, 13 Aug 2015 13:05:09 +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 170462617E0; Thu, 13 Aug 2015 13:05:08 +0200 (CEST) Received: from sender163-mail.zoho.com (sender163-mail.zoho.com [74.201.84.163]) by alsa0.perex.cz (Postfix) with ESMTP id 7042A2608ED for ; Thu, 13 Aug 2015 13:05:00 +0200 (CEST) Received: from juli-workstation.net.jusst.de. (x2f08d7d.dyn.telefonica.de [2.240.141.125]) by mx.zohomail.com with SMTPS id 1439463896896764.2679979093124; Thu, 13 Aug 2015 04:04:56 -0700 (PDT) From: Julian Scheel To: alsa-devel@alsa-project.org, tiwai@suse.de Date: Thu, 13 Aug 2015 13:04:46 +0200 Message-Id: <1439463886-5369-1-git-send-email-julian@jusst.de> X-Mailer: git-send-email 2.5.0 X-ZohoMail: Ss SS_10 UW UB CHF_INT_SMD_EXT SGR4_1_17065_0 X-ZohoMail-Owner: <1439463886-5369-1-git-send-email-julian@jusst.de>+zmo_0_ X-ZohoMail-Sender: 2.240.141.125 X-Zoho-Virus-Status: 2 Cc: Julian Scheel Subject: [alsa-devel] [PATCH] ALSA: usb-audio: Fix parameter block size for UAC2 control requests 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 USB Audio Class version 2.0 supports three different parameter block sizes for CUR requests, which are 1 byte (5.2.3.1 Layout 1 Parameter Block), 2 bytes (5.2.3.2 Layout 2 Parameter Block) and 4 bytes (5.2.3.3 Layout 3 Parameter Block). Use the correct size according to the specific control as it was already done for UACv1. The allocated block size for control requests is increased to support the 4 byte worst case. Signed-off-by: Julian Scheel --- sound/usb/mixer.c | 83 +++++++++++++++++++++++++++++++++++++++++-------------- sound/usb/mixer.h | 2 ++ 2 files changed, 65 insertions(+), 20 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 4a49944..675725b 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -233,6 +233,14 @@ static int convert_signed_value(struct usb_mixer_elem_info *cval, int val) if (val >= 0x8000) val -= 0x10000; break; + case USB_MIXER_U32: + val &= 0xffffffff; + break; + case USB_MIXER_S32: + val &= 0xffffffff; + if (val >= 0x80000000) + val -= 0x100000000; + break; } return val; } @@ -253,6 +261,9 @@ static int convert_bytes_value(struct usb_mixer_elem_info *cval, int val) case USB_MIXER_S16: case USB_MIXER_U16: return val & 0xffff; + case USB_MIXER_S32: + case USB_MIXER_U32: + return val & 0xffffffff; } return 0; /* not reached */ } @@ -328,14 +339,26 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) { struct snd_usb_audio *chip = cval->head.mixer->chip; - unsigned char buf[2 + 3 * sizeof(__u16)]; /* enough space for one range */ + unsigned char buf[4 + 3 * sizeof(__u32)]; /* enough space for one range */ unsigned char *val; int idx = 0, ret, size; __u8 bRequest; if (request == UAC_GET_CUR) { bRequest = UAC2_CS_CUR; - size = sizeof(__u16); + switch (cval->val_type) { + case USB_MIXER_S32: + case USB_MIXER_U32: + size = 4; + break; + case USB_MIXER_S16: + case USB_MIXER_U16: + size = 2; + break; + default: + size = 1; + break; + } } else { bRequest = UAC2_CS_RANGE; size = sizeof(buf); @@ -446,7 +469,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int value_set) { struct snd_usb_audio *chip = cval->head.mixer->chip; - unsigned char buf[2]; + unsigned char buf[4]; int idx = 0, val_len, err, timeout = 10; validx += cval->idx_off; @@ -454,8 +477,19 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, if (cval->head.mixer->protocol == UAC_VERSION_1) { val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; } else { /* UAC_VERSION_2 */ - /* audio class v2 controls are always 2 bytes in size */ - val_len = sizeof(__u16); + switch (cval->val_type) { + case USB_MIXER_S32: + case USB_MIXER_U32: + val_len = 4; + break; + case USB_MIXER_S16: + case USB_MIXER_U16: + val_len = 2; + break; + default: + val_len = 1; + break; + } /* FIXME */ if (request != UAC_SET_CUR) { @@ -469,6 +503,8 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, value_set = convert_bytes_value(cval, value_set); buf[0] = value_set & 0xff; buf[1] = (value_set >> 8) & 0xff; + buf[2] = (value_set >> 16) & 0xff; + buf[3] = (value_set >> 24) & 0xff; err = snd_usb_autoresume(chip); if (err < 0) return -EIO; @@ -799,24 +835,25 @@ static int check_input_term(struct mixer_build *state, int id, /* feature unit control information */ struct usb_feature_control_info { const char *name; - unsigned int type; /* control type (mute, volume, etc.) */ + int type; /* data type for uac1 */ + int type_uac2; /* data type for uac2 if different from uac1, else -1 */ }; static struct usb_feature_control_info audio_feature_info[] = { - { "Mute", USB_MIXER_INV_BOOLEAN }, - { "Volume", USB_MIXER_S16 }, - { "Tone Control - Bass", USB_MIXER_S8 }, - { "Tone Control - Mid", USB_MIXER_S8 }, - { "Tone Control - Treble", USB_MIXER_S8 }, - { "Graphic Equalizer", USB_MIXER_S8 }, /* FIXME: not implemeted yet */ - { "Auto Gain Control", USB_MIXER_BOOLEAN }, - { "Delay Control", USB_MIXER_U16 }, /* FIXME: U32 in UAC2 */ - { "Bass Boost", USB_MIXER_BOOLEAN }, - { "Loudness", USB_MIXER_BOOLEAN }, + { "Mute", USB_MIXER_INV_BOOLEAN, -1 }, + { "Volume", USB_MIXER_S16, -1 }, + { "Tone Control - Bass", USB_MIXER_S8, -1 }, + { "Tone Control - Mid", USB_MIXER_S8, -1 }, + { "Tone Control - Treble", USB_MIXER_S8, -1 }, + { "Graphic Equalizer", USB_MIXER_S8, -1 }, /* FIXME: not implemeted yet */ + { "Auto Gain Control", USB_MIXER_BOOLEAN, -1 }, + { "Delay Control", USB_MIXER_U16, USB_MIXER_U32 }, + { "Bass Boost", USB_MIXER_BOOLEAN, -1 }, + { "Loudness", USB_MIXER_BOOLEAN, -1 }, /* UAC2 specific */ - { "Input Gain Control", USB_MIXER_S16 }, - { "Input Gain Pad Control", USB_MIXER_S16 }, - { "Phase Inverter Control", USB_MIXER_BOOLEAN }, + { "Input Gain Control", USB_MIXER_S16, -1 }, + { "Input Gain Pad Control", USB_MIXER_S16, -1 }, + { "Phase Inverter Control", USB_MIXER_BOOLEAN, -1 }, }; /* private_free callback */ @@ -1241,7 +1278,13 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid); cval->control = control; cval->cmask = ctl_mask; - cval->val_type = audio_feature_info[control-1].type; + if (state->mixer->protocol == UAC_VERSION_1) + cval->val_type = audio_feature_info[control-1].type; + else /* UAC_VERSION_2 */ + cval->val_type = audio_feature_info[control-1].type_uac2 > -1 ? + audio_feature_info[control-1].type_uac2 : + audio_feature_info[control-1].type; + if (ctl_mask == 0) { cval->channels = 1; /* master channel */ cval->master_readonly = readonly_mask; diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index d3268f0..3417ef3 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -33,6 +33,8 @@ enum { USB_MIXER_U8, USB_MIXER_S16, USB_MIXER_U16, + USB_MIXER_S32, + USB_MIXER_U32, }; typedef void (*usb_mixer_elem_dump_func_t)(struct snd_info_buffer *buffer,