^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/usb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "usbaudio.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "helper.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "quirks.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * combine bytes and get an integer value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) unsigned int snd_usb_combine_bytes(unsigned char *bytes, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) switch (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) case 1: return *bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) case 2: return combine_word(bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) case 3: return combine_triple(bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) case 4: return combine_quad(bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) default: return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * parse descriptor buffer and return the pointer starting the given
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * descriptor type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) void *snd_usb_find_desc(void *descstart, int desclen, void *after, u8 dtype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) u8 *p, *end, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) p = descstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) end = p + desclen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) for (; p < end;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (p[0] < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) next = p + p[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (next > end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (p[1] == dtype && (!after || (void *)p > after)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) p = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * find a class-specified interface descriptor with the given subtype.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) void *snd_usb_find_csint_desc(void *buffer, int buflen, void *after, u8 dsubtype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) unsigned char *p = after;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) while ((p = snd_usb_find_desc(buffer, buflen, p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) USB_DT_CS_INTERFACE)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (p[0] >= 3 && p[2] == dsubtype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * Wrapper for usb_control_msg().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * Allocates a temp buffer to prevent dmaing from/to the stack.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) __u8 requesttype, __u16 value, __u16 index, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) __u16 size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) void *buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) int timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (usb_pipe_type_check(dev, pipe))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (size > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) buf = kmemdup(data, size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (requesttype & USB_DIR_IN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) timeout = USB_CTRL_GET_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) timeout = USB_CTRL_SET_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) err = usb_control_msg(dev, pipe, request, requesttype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) value, index, buf, size, timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (size > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) memcpy(data, buf, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) snd_usb_ctl_msg_quirk(dev, pipe, request, requesttype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) value, index, data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct usb_host_interface *alts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) switch (snd_usb_get_speed(chip->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) case USB_SPEED_HIGH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) case USB_SPEED_WIRELESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) case USB_SPEED_SUPER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) case USB_SPEED_SUPER_PLUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (get_endpoint(alts, 0)->bInterval >= 1 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) get_endpoint(alts, 0)->bInterval <= 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return get_endpoint(alts, 0)->bInterval - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)