From: Ruslan Bilovol <ruslan.bilovol@gmail.com>
To: Takashi Iwai <tiwai@suse.com>
Cc: Jorge <jorge.sanjuan@codethink.co.uk>,
Andrew Chant <achant@google.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
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 [thread overview]
Message-ID: <1525397044-15080-4-git-send-email-ruslan.bilovol@gmail.com> (raw)
In-Reply-To: <1525397044-15080-1-git-send-email-ruslan.bilovol@gmail.com>
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 <ruslan.bilovol@gmail.com>
---
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
next prev parent reply other threads:[~2018-05-04 1:24 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-05-04 1:23 [PATCH v2 0/7] USB Audio Device Class 3.0 BADD profiles support Ruslan Bilovol
2018-05-04 1:23 ` [PATCH v2 1/7] ALSA: usb: stream: move audioformat alloc/init into separate function Ruslan Bilovol
2018-05-04 1:23 ` [PATCH v2 2/7] ALSA: usb: stream: refactor uac1/2 audio interface parsing Ruslan Bilovol
2018-05-04 1:24 ` Ruslan Bilovol [this message]
2018-05-04 1:24 ` [PATCH v2 4/7] ALSA: usb: Only get AudioControl header for UAC1 class Ruslan Bilovol
2018-05-04 1:24 ` [PATCH v2 5/7] ALSA: usb: mixer: make string parsing independent of mixer_build state Ruslan Bilovol
2018-05-04 1:24 ` [PATCH v2 6/7] include: usb: audio-v3: add BADD-specific values Ruslan Bilovol
2018-05-04 1:24 ` [PATCH v2 7/7] ALSA: usb: add UAC3 BADD profiles support Ruslan Bilovol
2018-05-11 15:36 ` Jorge
2018-05-13 7:06 ` Takashi Iwai
2018-05-04 7:44 ` [PATCH v2 0/7] USB Audio Device Class 3.0 " Takashi Iwai
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1525397044-15080-4-git-send-email-ruslan.bilovol@gmail.com \
--to=ruslan.bilovol@gmail.com \
--cc=achant@google.com \
--cc=alsa-devel@alsa-project.org \
--cc=gregkh@linuxfoundation.org \
--cc=jorge.sanjuan@codethink.co.uk \
--cc=linux-kernel@vger.kernel.org \
--cc=tiwai@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).