summaryrefslogtreecommitdiffstats
path: root/sound/usb/helper.c
diff options
context:
space:
mode:
authorSang-Heon Jeon <ekffu200098@gmail.com>2026-08-24 01:18:14 +0900
committerJulia Lawall <Julia.Lawall@inria.fr>2026-08-23 22:12:11 +0200
commit2bd30b8dc75b823dd7bbef9d7bc68e1fd7ecee5c (patch)
treedcc4da1d99f17541c5590ac63c77da4bf372a4ab /sound/usb/helper.c
downloadlinux-stable-2bd30b8dc75b823dd7bbef9d7bc68e1fd7ecee5c.tar.gz
linux-stable-2bd30b8dc75b823dd7bbef9d7bc68e1fd7ecee5c.zip
coccinelle: alloc_cast: drop removed allocatorsgrafted
- pci_alloc_consistent() and pci_zalloc_consistent() were removed by commit 7968778914e5 ("PCI: Remove the deprecated "pci-dma-compat.h" API") - kmem_alloc() was removed by commit f078d4ea8276 ("xfs: convert kmem_alloc() to kmalloc()") - kmem_zalloc() was removed by commit 10634530f7ba ("xfs: convert kmem_zalloc() to kzalloc()") - kmem_zone_alloc() and kmem_zone_zalloc() were removed by commit bae633a4a283 ("xfs: remove xfs_zone_{alloc,zalloc} helpers") So drop them from the rules. No functional change. Signed-off-by: Sang-Heon Jeon <ekffu200098@gmail.com> Signed-off-by: Julia Lawall <Julia.Lawall@inria.fr>
Diffstat (limited to 'sound/usb/helper.c')
-rw-r--r--sound/usb/helper.c167
1 files changed, 167 insertions, 0 deletions
diff --git a/sound/usb/helper.c b/sound/usb/helper.c
new file mode 100644
index 000000000..497d2b27f
--- /dev/null
+++ b/sound/usb/helper.c
@@ -0,0 +1,167 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include "usbaudio.h"
+#include "helper.h"
+#include "quirks.h"
+
+/*
+ * combine bytes and get an integer value
+ */
+unsigned int snd_usb_combine_bytes(unsigned char *bytes, int size)
+{
+ switch (size) {
+ case 1: return *bytes;
+ case 2: return combine_word(bytes);
+ case 3: return combine_triple(bytes);
+ case 4: return combine_quad(bytes);
+ default: return 0;
+ }
+}
+
+/*
+ * parse descriptor buffer and return the pointer starting the given
+ * descriptor type.
+ */
+void *snd_usb_find_desc(void *descstart, int desclen, void *after, u8 dtype)
+{
+ u8 *p, *end, *next;
+
+ p = descstart;
+ end = p + desclen;
+ for (; p < end;) {
+ if (p[0] < 2)
+ return NULL;
+ next = p + p[0];
+ if (next > end)
+ return NULL;
+ if (p[1] == dtype && (!after || (void *)p > after)) {
+ return p;
+ }
+ p = next;
+ }
+ return NULL;
+}
+
+/*
+ * find a class-specified interface descriptor with the given subtype.
+ */
+void *snd_usb_find_csint_desc(void *buffer, int buflen, void *after, u8 dsubtype)
+{
+ unsigned char *p = after;
+
+ while ((p = snd_usb_find_desc(buffer, buflen, p,
+ USB_DT_CS_INTERFACE)) != NULL) {
+ if (p[0] >= 3 && p[2] == dsubtype)
+ return p;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(snd_usb_find_csint_desc);
+
+/*
+ * Wrapper for usb_control_msg().
+ * Allocates a temp buffer to prevent dmaing from/to the stack.
+ */
+int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
+ __u8 requesttype, __u16 value, __u16 index, void *data,
+ __u16 size)
+{
+ int err;
+ void *buf = NULL;
+ int timeout;
+
+ if (usb_pipe_type_check(dev, pipe))
+ return -EINVAL;
+
+ if (size > 0) {
+ buf = kmemdup(data, size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ }
+
+ if (requesttype & USB_DIR_IN)
+ timeout = USB_CTRL_GET_TIMEOUT;
+ else
+ timeout = USB_CTRL_SET_TIMEOUT;
+
+ err = usb_control_msg(dev, pipe, request, requesttype,
+ value, index, buf, size, timeout);
+
+ if (size > 0) {
+ memcpy(data, buf, size);
+ kfree(buf);
+ }
+
+ snd_usb_ctl_msg_quirk(dev, pipe, request, requesttype,
+ value, index, data, size);
+
+ return err;
+}
+
+unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
+ struct usb_host_interface *alts)
+{
+ switch (snd_usb_get_speed(chip->dev)) {
+ case USB_SPEED_HIGH:
+ case USB_SPEED_SUPER:
+ case USB_SPEED_SUPER_PLUS:
+ if (get_endpoint(alts, 0)->bInterval >= 1 &&
+ get_endpoint(alts, 0)->bInterval <= 4)
+ return get_endpoint(alts, 0)->bInterval - 1;
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+struct usb_host_interface *
+snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting)
+{
+ struct usb_interface *iface;
+
+ iface = usb_ifnum_to_if(chip->dev, ifnum);
+ if (!iface)
+ return NULL;
+ return usb_altnum_to_altsetting(iface, altsetting);
+}
+
+int snd_usb_add_ctrl_interface_link(struct snd_usb_audio *chip, int ifnum,
+ int ctrlif)
+{
+ struct usb_device *dev = chip->dev;
+ struct usb_host_interface *host_iface;
+
+ if (chip->num_intf_to_ctrl >= MAX_CARD_INTERFACES) {
+ dev_info(&dev->dev, "Too many interfaces assigned to the single USB-audio card\n");
+ return -EINVAL;
+ }
+
+ /* find audiocontrol interface */
+ host_iface = &usb_ifnum_to_if(dev, ctrlif)->altsetting[0];
+
+ chip->intf_to_ctrl[chip->num_intf_to_ctrl].interface = ifnum;
+ chip->intf_to_ctrl[chip->num_intf_to_ctrl].ctrl_intf = host_iface;
+ chip->num_intf_to_ctrl++;
+
+ return 0;
+}
+
+struct usb_host_interface *snd_usb_find_ctrl_interface(struct snd_usb_audio *chip,
+ int ifnum)
+{
+ int i;
+
+ for (i = 0; i < chip->num_intf_to_ctrl; ++i)
+ if (chip->intf_to_ctrl[i].interface == ifnum)
+ return chip->intf_to_ctrl[i].ctrl_intf;
+
+ /* Fallback to first audiocontrol interface */
+ return chip->ctrl_intf;
+}