lkml.org 
[lkml]   [2018]   [May]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 3/7] ALSA: usb: stream: refactor uac3 audio interface parsing
    Date
    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
    \
     
     \ /
      Last update: 2018-05-04 03:26    [W:3.340 / U:0.152 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site