Received: by 10.192.165.148 with SMTP id m20csp213371imm; Thu, 3 May 2018 18:26:39 -0700 (PDT) X-Google-Smtp-Source: AB8JxZpi57oTOJaLyYbo4jR1SbQWcGvp083Ri6OCpqJGuQtSAsm6BfXLlx3OslTdNsk6qBCK/JpC X-Received: by 2002:a17:902:784c:: with SMTP id e12-v6mr14154285pln.60.1525397199128; Thu, 03 May 2018 18:26:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1525397199; cv=none; d=google.com; s=arc-20160816; b=txIXf7vIVVq3P5jpVuiV84kQZwKiBVg1cZKBOSmZhx1aVpJ/DcMBYwXvCtP27Ug/6B dN64AykOD3JU/iGsQM6uSY1IK8AMr3ubjhR5bhurvdtQer5PQQqqDJkd3e1z/0ZDu7XX +J2yjW7FNOmXrzq0SKiRsbf28p/VMYJuewnWUvZH5w+NVStVgydx1EdUBzIeNAg8luuD tTTeL/WZtfNpzb7bXt0sbGW7lKfeMKz98Ne3zBjDjfevZtM9DPwTLDO3YAKB1teT1JFj rGKlrp8RCu+byDnbUbvjXWXxE8nCb8cY3UqJHF0BmMGexUTM8Y/H4hIBM1MyKeSk+5xP DklA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=Brmc9jH2qrqVJEuvXXiZBJOteg8YSQtvLE6IJtkc8A8=; b=iBjNfqHgh/4dkvYMssJIHyMf9Pb7NBlXSKypPonhyRMt+tZ5P8OSF94EsvYW7FtmSD fb/z9yCMq8gYnM4aHMJmJjmwLEH8gjx/EH6YFRohp78P9g6YQqwqLOghXWj71KabJtcZ 2x26+yTgzLB6DIdff9mlf3YawG1Uw7sABYOgmUvUSOi/l/8PzzAtOgEbG7jjSCcC2KBP wxMUmMJNwqU1pVIunwv9FNuPtFDS1vCXaJQhA9bYprlnvFEMJucr2bQDSaopEW7rql/K LMdB+/0flymRiiHyp/KN/LAKPP+eI1HkHpTcdheSiCJStjMi2kGpjH8x4UUEnVZCRLGq hgWg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=grgArWhN; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h22-v6si1482689pgv.189.2018.05.03.18.26.25; Thu, 03 May 2018 18:26:39 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=grgArWhN; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751511AbeEDBY6 (ORCPT + 99 others); Thu, 3 May 2018 21:24:58 -0400 Received: from mail-lf0-f67.google.com ([209.85.215.67]:44857 "EHLO mail-lf0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751477AbeEDBY4 (ORCPT ); Thu, 3 May 2018 21:24:56 -0400 Received: by mail-lf0-f67.google.com with SMTP id h197-v6so28609416lfg.11 for ; Thu, 03 May 2018 18:24:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Brmc9jH2qrqVJEuvXXiZBJOteg8YSQtvLE6IJtkc8A8=; b=grgArWhNidH2byiwbsJ7yxL759k3BuaKrT7/72XrRaj2mG4bfKb5SvD+g8Kq1UPgAu 4VYIjvfNidWJHlVkvJwZiG/8P5/bdEBA0q7slIvL4wJm4ql+alxPYv/RODehRQ5vfttW HL7p/WHF+5Ps6DIXAo6vSopPhFKlwr8ueTwwS3GhP1vCC7tFrOQYXoz/9//S8qvpiFSy tXee+WKlN2dL2fyqP3ncajOh2LP3adwVtYAEw3w2bGt0AoY73S2lahwGOOPwSPtE43Sc 46oev5MEY456vlwKadiEMoaoZd39jjs8ySOGh9HtW9RROruYQeFvFMapx7R8VPNfGz8B unPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Brmc9jH2qrqVJEuvXXiZBJOteg8YSQtvLE6IJtkc8A8=; b=aaVNvrIf1KJFwx8Ke0tk1bEehXxc2bJHrW+qwC861jT4WBo4XR04KB6TZKmJfHA5hM C6CM6VUhcYrnOgYc9j1ds7MvobRLneOClJZbNE37v9/rTPwlHzvHNj6HH1V6ILH2rr8B HXwp4Nim4zfcWpkwho+GwhMnOki+UNjS+EQJGcH71NWylBLveI/qbHuf4y5rmaMj/iCX 0CYZtzQmsFhI5Clp0qX/m5qwIC0lo4+wlN18jgFSNtay5arX9AdfwA4xqMrPjr/RBGaE pdowxSrIrGhzT1i0tmzvRiH5T+bD6GQWqQesNjm5+XT2o+D1cvrH4m3BIR2cLZQHrLCD lL4g== X-Gm-Message-State: ALQs6tCt3nHJlwgDX1IG2ZSLlzr8dt1zv0iI00PYnR0oUHhll67Mub+S 3Ktct6DTzZyCqhdJEsUPkF4X0D0e500= X-Received: by 2002:a2e:404d:: with SMTP id n74-v6mr18115038lja.6.1525397094473; Thu, 03 May 2018 18:24:54 -0700 (PDT) Received: from localhost ([62.216.57.27]) by smtp.gmail.com with ESMTPSA id y18-v6sm3029819ljc.52.2018.05.03.18.24.53 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Thu, 03 May 2018 18:24:53 -0700 (PDT) From: Ruslan Bilovol To: Takashi Iwai Cc: Jorge , Andrew Chant , Greg Kroah-Hartman , alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 3/7] ALSA: usb: stream: refactor uac3 audio interface parsing Date: Fri, 4 May 2018 04:24:00 +0300 Message-Id: <1525397044-15080-4-git-send-email-ruslan.bilovol@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1525397044-15080-1-git-send-email-ruslan.bilovol@gmail.com> References: <1525397044-15080-1-git-send-email-ruslan.bilovol@gmail.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Offload snd_usb_parse_audio_interface() function which became quite long after adding UAC3 spec support. Move class-specific parts of uac3 parsing to separate function which now produce audioformat structure that is ready to be fed to snd_usb_add_audio_stream(). Signed-off-by: Ruslan Bilovol --- sound/usb/stream.c | 289 +++++++++++++++++++++++++++-------------------------- 1 file changed, 146 insertions(+), 143 deletions(-) diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 3369226..764be07 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -807,19 +807,154 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, return fp; } +static struct audioformat * +snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip, + struct usb_host_interface *alts, + int iface_no, int altset_idx, + int altno, int stream) +{ + struct usb_device *dev = chip->dev; + struct uac3_input_terminal_descriptor *input_term; + struct uac3_output_terminal_descriptor *output_term; + struct uac3_cluster_header_descriptor *cluster; + struct uac3_as_header_descriptor *as; + struct uac3_hc_descriptor_header hc_header; + struct snd_pcm_chmap_elem *chmap; + unsigned int num_channels; + struct audioformat *fp; + u16 cluster_id, wLength; + int clock = 0; + int err; + + as = snd_usb_find_csint_desc(alts->extra, alts->extralen, + NULL, UAC_AS_GENERAL); + if (!as) { + dev_err(&dev->dev, + "%u:%d : UAC_AS_GENERAL descriptor not found\n", + iface_no, altno); + return NULL; + } + + if (as->bLength < sizeof(*as)) { + dev_err(&dev->dev, + "%u:%d : invalid UAC_AS_GENERAL desc\n", + iface_no, altno); + return NULL; + } + + cluster_id = le16_to_cpu(as->wClusterDescrID); + if (!cluster_id) { + dev_err(&dev->dev, + "%u:%d : no cluster descriptor\n", + iface_no, altno); + return NULL; + } + + /* + * Get number of channels and channel map through + * High Capability Cluster Descriptor + * + * First step: get High Capability header and + * read size of Cluster Descriptor + */ + err = snd_usb_ctl_msg(chip->dev, + usb_rcvctrlpipe(chip->dev, 0), + UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, + cluster_id, + snd_usb_ctrl_intf(chip), + &hc_header, sizeof(hc_header)); + if (err < 0) + return ERR_PTR(err); + else if (err != sizeof(hc_header)) { + dev_err(&dev->dev, + "%u:%d : can't get High Capability descriptor\n", + iface_no, altno); + return ERR_PTR(-EIO); + } + + /* + * Second step: allocate needed amount of memory + * and request Cluster Descriptor + */ + wLength = le16_to_cpu(hc_header.wLength); + cluster = kzalloc(wLength, GFP_KERNEL); + if (!cluster) + return ERR_PTR(-ENOMEM); + err = snd_usb_ctl_msg(chip->dev, + usb_rcvctrlpipe(chip->dev, 0), + UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, + cluster_id, + snd_usb_ctrl_intf(chip), + cluster, wLength); + if (err < 0) { + kfree(cluster); + return ERR_PTR(err); + } else if (err != wLength) { + dev_err(&dev->dev, + "%u:%d : can't get Cluster Descriptor\n", + iface_no, altno); + kfree(cluster); + return ERR_PTR(-EIO); + } + + num_channels = cluster->bNrChannels; + chmap = convert_chmap_v3(cluster); + kfree(cluster); + + /* + * lookup the terminal associated to this interface + * to extract the clock + */ + input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, + as->bTerminalLink); + if (input_term) { + clock = input_term->bCSourceID; + goto found_clock; + } + + output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf, + as->bTerminalLink); + if (output_term) { + clock = output_term->bCSourceID; + goto found_clock; + } + + dev_err(&dev->dev, "%u:%d : bogus bTerminalLink %d\n", + iface_no, altno, as->bTerminalLink); + return NULL; + +found_clock: + fp = audio_format_alloc_init(chip, alts, UAC_VERSION_3, iface_no, + altset_idx, altno, num_channels, clock); + if (!fp) + return ERR_PTR(-ENOMEM); + + fp->attributes = parse_uac_endpoint_attributes(chip, alts, + UAC_VERSION_3, + iface_no); + fp->chmap = chmap; + + /* ok, let's parse further... */ + if (snd_usb_parse_audio_format_v3(chip, fp, as, stream) < 0) { + kfree(fp->rate_table); + kfree(fp); + return NULL; + } + + return fp; +} + int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) { struct usb_device *dev; struct usb_interface *iface; struct usb_host_interface *alts; struct usb_interface_descriptor *altsd; - struct uac3_as_header_descriptor *as = NULL; int i, altno, err, stream; - u64 format = 0; - unsigned int num_channels = 0; struct audioformat *fp = NULL; - int num, protocol, clock = 0; - struct snd_pcm_chmap_elem *chmap_v3 = NULL; + int num, protocol; dev = chip->dev; @@ -900,149 +1035,17 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) stream, bm_quirk); break; } - case UAC_VERSION_3: { - struct uac3_input_terminal_descriptor *input_term; - struct uac3_output_terminal_descriptor *output_term; - struct uac3_cluster_header_descriptor *cluster; - struct uac3_hc_descriptor_header hc_header; - u16 cluster_id, wLength; - - as = snd_usb_find_csint_desc(alts->extra, - alts->extralen, - NULL, UAC_AS_GENERAL); - - if (!as) { - dev_err(&dev->dev, - "%u:%d : UAC_AS_GENERAL descriptor not found\n", - iface_no, altno); - continue; - } - - if (as->bLength < sizeof(*as)) { - dev_err(&dev->dev, - "%u:%d : invalid UAC_AS_GENERAL desc\n", - iface_no, altno); - continue; - } - - cluster_id = le16_to_cpu(as->wClusterDescrID); - if (!cluster_id) { - dev_err(&dev->dev, - "%u:%d : no cluster descriptor\n", - iface_no, altno); - continue; - } - - /* - * Get number of channels and channel map through - * High Capability Cluster Descriptor - * - * First step: get High Capability header and - * read size of Cluster Descriptor - */ - err = snd_usb_ctl_msg(chip->dev, - usb_rcvctrlpipe(chip->dev, 0), - UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR, - USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - cluster_id, - snd_usb_ctrl_intf(chip), - &hc_header, sizeof(hc_header)); - if (err < 0) - return err; - else if (err != sizeof(hc_header)) { - dev_err(&dev->dev, - "%u:%d : can't get High Capability descriptor\n", - iface_no, altno); - return -EIO; - } - - /* - * Second step: allocate needed amount of memory - * and request Cluster Descriptor - */ - wLength = le16_to_cpu(hc_header.wLength); - cluster = kzalloc(wLength, GFP_KERNEL); - if (!cluster) - return -ENOMEM; - err = snd_usb_ctl_msg(chip->dev, - usb_rcvctrlpipe(chip->dev, 0), - UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR, - USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - cluster_id, - snd_usb_ctrl_intf(chip), - cluster, wLength); - if (err < 0) { - kfree(cluster); - return err; - } else if (err != wLength) { - dev_err(&dev->dev, - "%u:%d : can't get Cluster Descriptor\n", - iface_no, altno); - kfree(cluster); - return -EIO; - } - - num_channels = cluster->bNrChannels; - chmap_v3 = convert_chmap_v3(cluster); - - kfree(cluster); - - format = le64_to_cpu(as->bmFormats); - - /* lookup the terminal associated to this interface - * to extract the clock */ - input_term = snd_usb_find_input_terminal_descriptor( - chip->ctrl_intf, - as->bTerminalLink); - - if (input_term) { - clock = input_term->bCSourceID; - break; - } - - output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf, - as->bTerminalLink); - if (output_term) { - clock = output_term->bCSourceID; - break; - } - - dev_err(&dev->dev, - "%u:%d : bogus bTerminalLink %d\n", - iface_no, altno, as->bTerminalLink); - continue; - } - } - - if (protocol == UAC_VERSION_1 || protocol == UAC_VERSION_2) { - if (!fp) - continue; - else if (IS_ERR(fp)) - return PTR_ERR(fp); - - goto skip_uac3; + case UAC_VERSION_3: + fp = snd_usb_get_audioformat_uac3(chip, alts, + iface_no, i, altno, stream); + break; } - fp = audio_format_alloc_init(chip, alts, protocol, iface_no, i, - altno, num_channels, clock); if (!fp) - return -ENOMEM; - - fp->attributes = parse_uac_endpoint_attributes(chip, alts, - protocol, - iface_no); - fp->chmap = chmap_v3; - - /* ok, let's parse further... */ - if (snd_usb_parse_audio_format_v3(chip, fp, as, - stream) < 0) { - kfree(fp->rate_table); - kfree(fp); - fp = NULL; continue; - } + else if (IS_ERR(fp)) + return PTR_ERR(fp); -skip_uac3: dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint); err = snd_usb_add_audio_stream(chip, stream, fp); if (err < 0) { -- 1.9.1