1 /* 2 * usb/gadget/config.c -- simplify building config descriptors 3 * 4 * Copyright (C) 2003 David Brownell 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21 #include <linux/errno.h> 22 #include <linux/slab.h> 23 #include <linux/kernel.h> 24 #include <linux/list.h> 25 #include <linux/string.h> 26 #include <linux/device.h> 27 28 #include <linux/usb/ch9.h> 29 #include <linux/usb/gadget.h> 30 31 32 /** 33 * usb_descriptor_fillbuf - fill buffer with descriptors 34 * @buf: Buffer to be filled 35 * @buflen: Size of buf 36 * @src: Array of descriptor pointers, terminated by null pointer. 37 * 38 * Copies descriptors into the buffer, returning the length or a 39 * negative error code if they can't all be copied. Useful when 40 * assembling descriptors for an associated set of interfaces used 41 * as part of configuring a composite device; or in other cases where 42 * sets of descriptors need to be marshaled. 43 */ 44 int 45 usb_descriptor_fillbuf(void *buf, unsigned buflen, 46 const struct usb_descriptor_header **src) 47 { 48 u8 *dest = buf; 49 50 if (!src) 51 return -EINVAL; 52 53 /* fill buffer from src[] until null descriptor ptr */ 54 for (; NULL != *src; src++) { 55 unsigned len = (*src)->bLength; 56 57 if (len > buflen) 58 return -EINVAL; 59 memcpy(dest, *src, len); 60 buflen -= len; 61 dest += len; 62 } 63 return dest - (u8 *)buf; 64 } 65 66 67 /** 68 * usb_gadget_config_buf - builts a complete configuration descriptor 69 * @config: Header for the descriptor, including characteristics such 70 * as power requirements and number of interfaces. 71 * @desc: Null-terminated vector of pointers to the descriptors (interface, 72 * endpoint, etc) defining all functions in this device configuration. 73 * @buf: Buffer for the resulting configuration descriptor. 74 * @length: Length of buffer. If this is not big enough to hold the 75 * entire configuration descriptor, an error code will be returned. 76 * 77 * This copies descriptors into the response buffer, building a descriptor 78 * for that configuration. It returns the buffer length or a negative 79 * status code. The config.wTotalLength field is set to match the length 80 * of the result, but other descriptor fields (including power usage and 81 * interface count) must be set by the caller. 82 * 83 * Gadget drivers could use this when constructing a config descriptor 84 * in response to USB_REQ_GET_DESCRIPTOR. They will need to patch the 85 * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed. 86 */ 87 int usb_gadget_config_buf( 88 const struct usb_config_descriptor *config, 89 void *buf, 90 unsigned length, 91 const struct usb_descriptor_header **desc 92 ) 93 { 94 struct usb_config_descriptor *cp = buf; 95 int len; 96 97 /* config descriptor first */ 98 if (length < USB_DT_CONFIG_SIZE || !desc) 99 return -EINVAL; 100 *cp = *config; 101 102 /* then interface/endpoint/class/vendor/... */ 103 len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf, 104 length - USB_DT_CONFIG_SIZE, desc); 105 if (len < 0) 106 return len; 107 len += USB_DT_CONFIG_SIZE; 108 if (len > 0xffff) 109 return -EINVAL; 110 111 /* patch up the config descriptor */ 112 cp->bLength = USB_DT_CONFIG_SIZE; 113 cp->bDescriptorType = USB_DT_CONFIG; 114 cp->wTotalLength = cpu_to_le16(len); 115 cp->bmAttributes |= USB_CONFIG_ATT_ONE; 116 return len; 117 } 118 119 /** 120 * usb_copy_descriptors - copy a vector of USB descriptors 121 * @src: null-terminated vector to copy 122 * Context: initialization code, which may sleep 123 * 124 * This makes a copy of a vector of USB descriptors. Its primary use 125 * is to support usb_function objects which can have multiple copies, 126 * each needing different descriptors. Functions may have static 127 * tables of descriptors, which are used as templates and customized 128 * with identifiers (for interfaces, strings, endpoints, and more) 129 * as needed by a given function instance. 130 */ 131 struct usb_descriptor_header ** 132 usb_copy_descriptors(struct usb_descriptor_header **src) 133 { 134 struct usb_descriptor_header **tmp; 135 unsigned bytes; 136 unsigned n_desc; 137 void *mem; 138 struct usb_descriptor_header **ret; 139 140 /* count descriptors and their sizes; then add vector size */ 141 for (bytes = 0, n_desc = 0, tmp = src; *tmp; tmp++, n_desc++) 142 bytes += (*tmp)->bLength; 143 bytes += (n_desc + 1) * sizeof(*tmp); 144 145 mem = kmalloc(bytes, GFP_KERNEL); 146 if (!mem) 147 return NULL; 148 149 /* fill in pointers starting at "tmp", 150 * to descriptors copied starting at "mem"; 151 * and return "ret" 152 */ 153 tmp = mem; 154 ret = mem; 155 mem += (n_desc + 1) * sizeof(*tmp); 156 while (*src) { 157 memcpy(mem, *src, (*src)->bLength); 158 *tmp = mem; 159 tmp++; 160 mem += (*src)->bLength; 161 src++; 162 } 163 *tmp = NULL; 164 165 return ret; 166 } 167 168 /** 169 * usb_find_endpoint - find a copy of an endpoint descriptor 170 * @src: original vector of descriptors 171 * @copy: copy of @src 172 * @match: endpoint descriptor found in @src 173 * 174 * This returns the copy of the @match descriptor made for @copy. Its 175 * intended use is to help remembering the endpoint descriptor to use 176 * when enabling a given endpoint. 177 */ 178 struct usb_endpoint_descriptor * 179 usb_find_endpoint( 180 struct usb_descriptor_header **src, 181 struct usb_descriptor_header **copy, 182 struct usb_endpoint_descriptor *match 183 ) 184 { 185 while (*src) { 186 if (*src == (void *) match) 187 return (void *)*copy; 188 src++; 189 copy++; 190 } 191 return NULL; 192 } 193