1 // SPDX-License-Identifier: GPL-2.0-or-later
5 #include <linux/init.h>
6 #include <linux/slab.h>
14 * combine bytes and get an integer value
16 unsigned int snd_usb_combine_bytes(unsigned char *bytes
, int size
)
19 case 1: return *bytes
;
20 case 2: return combine_word(bytes
);
21 case 3: return combine_triple(bytes
);
22 case 4: return combine_quad(bytes
);
28 * parse descriptor buffer and return the pointer starting the given
31 void *snd_usb_find_desc(void *descstart
, int desclen
, void *after
, u8 dtype
)
43 if (p
[1] == dtype
&& (!after
|| (void *)p
> after
)) {
52 * find a class-specified interface descriptor with the given subtype.
54 void *snd_usb_find_csint_desc(void *buffer
, int buflen
, void *after
, u8 dsubtype
)
56 unsigned char *p
= after
;
58 while ((p
= snd_usb_find_desc(buffer
, buflen
, p
,
59 USB_DT_CS_INTERFACE
)) != NULL
) {
60 if (p
[0] >= 3 && p
[2] == dsubtype
)
66 /* check the validity of pipe and EP types */
67 int snd_usb_pipe_sanity_check(struct usb_device
*dev
, unsigned int pipe
)
69 static const int pipetypes
[4] = {
70 PIPE_CONTROL
, PIPE_ISOCHRONOUS
, PIPE_BULK
, PIPE_INTERRUPT
72 struct usb_host_endpoint
*ep
;
74 ep
= usb_pipe_endpoint(dev
, pipe
);
75 if (!ep
|| usb_pipetype(pipe
) != pipetypes
[usb_endpoint_type(&ep
->desc
)])
81 * Wrapper for usb_control_msg().
82 * Allocates a temp buffer to prevent dmaing from/to the stack.
84 int snd_usb_ctl_msg(struct usb_device
*dev
, unsigned int pipe
, __u8 request
,
85 __u8 requesttype
, __u16 value
, __u16 index
, void *data
,
92 if (snd_usb_pipe_sanity_check(dev
, pipe
))
96 buf
= kmemdup(data
, size
, GFP_KERNEL
);
101 if (requesttype
& USB_DIR_IN
)
102 timeout
= USB_CTRL_GET_TIMEOUT
;
104 timeout
= USB_CTRL_SET_TIMEOUT
;
106 err
= usb_control_msg(dev
, pipe
, request
, requesttype
,
107 value
, index
, buf
, size
, timeout
);
110 memcpy(data
, buf
, size
);
114 snd_usb_ctl_msg_quirk(dev
, pipe
, request
, requesttype
,
115 value
, index
, data
, size
);
120 unsigned char snd_usb_parse_datainterval(struct snd_usb_audio
*chip
,
121 struct usb_host_interface
*alts
)
123 switch (snd_usb_get_speed(chip
->dev
)) {
125 case USB_SPEED_WIRELESS
:
126 case USB_SPEED_SUPER
:
127 case USB_SPEED_SUPER_PLUS
:
128 if (get_endpoint(alts
, 0)->bInterval
>= 1 &&
129 get_endpoint(alts
, 0)->bInterval
<= 4)
130 return get_endpoint(alts
, 0)->bInterval
- 1;