1 /* 2 * This program is free software; you can redistribute it and/or modify 3 * it under the terms of the GNU General Public License as published by 4 * the Free Software Foundation; either version 2 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, write to the Free Software 14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 15 * 16 */ 17 18 #include <linux/init.h> 19 #include <linux/slab.h> 20 #include <linux/usb.h> 21 22 #include "usbaudio.h" 23 #include "helper.h" 24 #include "quirks.h" 25 26 /* 27 * combine bytes and get an integer value 28 */ 29 unsigned int snd_usb_combine_bytes(unsigned char *bytes, int size) 30 { 31 switch (size) { 32 case 1: return *bytes; 33 case 2: return combine_word(bytes); 34 case 3: return combine_triple(bytes); 35 case 4: return combine_quad(bytes); 36 default: return 0; 37 } 38 } 39 40 /* 41 * parse descriptor buffer and return the pointer starting the given 42 * descriptor type. 43 */ 44 void *snd_usb_find_desc(void *descstart, int desclen, void *after, u8 dtype) 45 { 46 u8 *p, *end, *next; 47 48 p = descstart; 49 end = p + desclen; 50 for (; p < end;) { 51 if (p[0] < 2) 52 return NULL; 53 next = p + p[0]; 54 if (next > end) 55 return NULL; 56 if (p[1] == dtype && (!after || (void *)p > after)) { 57 return p; 58 } 59 p = next; 60 } 61 return NULL; 62 } 63 64 /* 65 * find a class-specified interface descriptor with the given subtype. 66 */ 67 void *snd_usb_find_csint_desc(void *buffer, int buflen, void *after, u8 dsubtype) 68 { 69 unsigned char *p = after; 70 71 while ((p = snd_usb_find_desc(buffer, buflen, p, 72 USB_DT_CS_INTERFACE)) != NULL) { 73 if (p[0] >= 3 && p[2] == dsubtype) 74 return p; 75 } 76 return NULL; 77 } 78 79 /* 80 * Wrapper for usb_control_msg(). 81 * Allocates a temp buffer to prevent dmaing from/to the stack. 82 */ 83 int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, 84 __u8 requesttype, __u16 value, __u16 index, void *data, 85 __u16 size) 86 { 87 int err; 88 void *buf = NULL; 89 90 if (size > 0) { 91 buf = kmemdup(data, size, GFP_KERNEL); 92 if (!buf) 93 return -ENOMEM; 94 } 95 err = usb_control_msg(dev, pipe, request, requesttype, 96 value, index, buf, size, 1000); 97 if (size > 0) { 98 memcpy(data, buf, size); 99 kfree(buf); 100 } 101 102 snd_usb_ctl_msg_quirk(dev, pipe, request, requesttype, 103 value, index, data, size); 104 105 return err; 106 } 107 108 unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip, 109 struct usb_host_interface *alts) 110 { 111 switch (snd_usb_get_speed(chip->dev)) { 112 case USB_SPEED_HIGH: 113 case USB_SPEED_SUPER: 114 if (get_endpoint(alts, 0)->bInterval >= 1 && 115 get_endpoint(alts, 0)->bInterval <= 4) 116 return get_endpoint(alts, 0)->bInterval - 1; 117 break; 118 default: 119 break; 120 } 121 return 0; 122 } 123 124