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 25 /* 26 * combine bytes and get an integer value 27 */ 28 unsigned int snd_usb_combine_bytes(unsigned char *bytes, int size) 29 { 30 switch (size) { 31 case 1: return *bytes; 32 case 2: return combine_word(bytes); 33 case 3: return combine_triple(bytes); 34 case 4: return combine_quad(bytes); 35 default: return 0; 36 } 37 } 38 39 /* 40 * parse descriptor buffer and return the pointer starting the given 41 * descriptor type. 42 */ 43 void *snd_usb_find_desc(void *descstart, int desclen, void *after, u8 dtype) 44 { 45 u8 *p, *end, *next; 46 47 p = descstart; 48 end = p + desclen; 49 for (; p < end;) { 50 if (p[0] < 2) 51 return NULL; 52 next = p + p[0]; 53 if (next > end) 54 return NULL; 55 if (p[1] == dtype && (!after || (void *)p > after)) { 56 return p; 57 } 58 p = next; 59 } 60 return NULL; 61 } 62 63 /* 64 * find a class-specified interface descriptor with the given subtype. 65 */ 66 void *snd_usb_find_csint_desc(void *buffer, int buflen, void *after, u8 dsubtype) 67 { 68 unsigned char *p = after; 69 70 while ((p = snd_usb_find_desc(buffer, buflen, p, 71 USB_DT_CS_INTERFACE)) != NULL) { 72 if (p[0] >= 3 && p[2] == dsubtype) 73 return p; 74 } 75 return NULL; 76 } 77 78 /* 79 * Wrapper for usb_control_msg(). 80 * Allocates a temp buffer to prevent dmaing from/to the stack. 81 */ 82 int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, 83 __u8 requesttype, __u16 value, __u16 index, void *data, 84 __u16 size) 85 { 86 int err; 87 void *buf = NULL; 88 89 if (size > 0) { 90 buf = kmemdup(data, size, GFP_KERNEL); 91 if (!buf) 92 return -ENOMEM; 93 } 94 err = usb_control_msg(dev, pipe, request, requesttype, 95 value, index, buf, size, 1000); 96 if (size > 0) { 97 memcpy(data, buf, size); 98 kfree(buf); 99 } 100 return err; 101 } 102 103 unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip, 104 struct usb_host_interface *alts) 105 { 106 switch (snd_usb_get_speed(chip->dev)) { 107 case USB_SPEED_HIGH: 108 case USB_SPEED_SUPER: 109 if (get_endpoint(alts, 0)->bInterval >= 1 && 110 get_endpoint(alts, 0)->bInterval <= 4) 111 return get_endpoint(alts, 0)->bInterval - 1; 112 break; 113 default: 114 break; 115 } 116 return 0; 117 } 118 119