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 12 #include <linux/errno.h> 13 #include <linux/slab.h> 14 #include <linux/kernel.h> 15 #include <linux/module.h> 16 #include <linux/list.h> 17 #include <linux/string.h> 18 #include <linux/device.h> 19 20 #include <linux/usb/ch9.h> 21 #include <linux/usb/gadget.h> 22 #include <linux/usb/composite.h> 23 #include <linux/usb/otg.h> 24 25 /** 26 * usb_descriptor_fillbuf - fill buffer with descriptors 27 * @buf: Buffer to be filled 28 * @buflen: Size of buf 29 * @src: Array of descriptor pointers, terminated by null pointer. 30 * 31 * Copies descriptors into the buffer, returning the length or a 32 * negative error code if they can't all be copied. Useful when 33 * assembling descriptors for an associated set of interfaces used 34 * as part of configuring a composite device; or in other cases where 35 * sets of descriptors need to be marshaled. 36 */ 37 int 38 usb_descriptor_fillbuf(void *buf, unsigned buflen, 39 const struct usb_descriptor_header **src) 40 { 41 u8 *dest = buf; 42 43 if (!src) 44 return -EINVAL; 45 46 /* fill buffer from src[] until null descriptor ptr */ 47 for (; NULL != *src; src++) { 48 unsigned len = (*src)->bLength; 49 50 if (len > buflen) 51 return -EINVAL; 52 memcpy(dest, *src, len); 53 buflen -= len; 54 dest += len; 55 } 56 return dest - (u8 *)buf; 57 } 58 EXPORT_SYMBOL_GPL(usb_descriptor_fillbuf); 59 60 /** 61 * usb_gadget_config_buf - builts a complete configuration descriptor 62 * @config: Header for the descriptor, including characteristics such 63 * as power requirements and number of interfaces. 64 * @desc: Null-terminated vector of pointers to the descriptors (interface, 65 * endpoint, etc) defining all functions in this device configuration. 66 * @buf: Buffer for the resulting configuration descriptor. 67 * @length: Length of buffer. If this is not big enough to hold the 68 * entire configuration descriptor, an error code will be returned. 69 * 70 * This copies descriptors into the response buffer, building a descriptor 71 * for that configuration. It returns the buffer length or a negative 72 * status code. The config.wTotalLength field is set to match the length 73 * of the result, but other descriptor fields (including power usage and 74 * interface count) must be set by the caller. 75 * 76 * Gadget drivers could use this when constructing a config descriptor 77 * in response to USB_REQ_GET_DESCRIPTOR. They will need to patch the 78 * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed. 79 */ 80 int usb_gadget_config_buf( 81 const struct usb_config_descriptor *config, 82 void *buf, 83 unsigned length, 84 const struct usb_descriptor_header **desc 85 ) 86 { 87 struct usb_config_descriptor *cp = buf; 88 int len; 89 90 /* config descriptor first */ 91 if (length < USB_DT_CONFIG_SIZE || !desc) 92 return -EINVAL; 93 *cp = *config; 94 95 /* then interface/endpoint/class/vendor/... */ 96 len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf, 97 length - USB_DT_CONFIG_SIZE, desc); 98 if (len < 0) 99 return len; 100 len += USB_DT_CONFIG_SIZE; 101 if (len > 0xffff) 102 return -EINVAL; 103 104 /* patch up the config descriptor */ 105 cp->bLength = USB_DT_CONFIG_SIZE; 106 cp->bDescriptorType = USB_DT_CONFIG; 107 cp->wTotalLength = cpu_to_le16(len); 108 cp->bmAttributes |= USB_CONFIG_ATT_ONE; 109 return len; 110 } 111 EXPORT_SYMBOL_GPL(usb_gadget_config_buf); 112 113 /** 114 * usb_copy_descriptors - copy a vector of USB descriptors 115 * @src: null-terminated vector to copy 116 * Context: initialization code, which may sleep 117 * 118 * This makes a copy of a vector of USB descriptors. Its primary use 119 * is to support usb_function objects which can have multiple copies, 120 * each needing different descriptors. Functions may have static 121 * tables of descriptors, which are used as templates and customized 122 * with identifiers (for interfaces, strings, endpoints, and more) 123 * as needed by a given function instance. 124 */ 125 struct usb_descriptor_header ** 126 usb_copy_descriptors(struct usb_descriptor_header **src) 127 { 128 struct usb_descriptor_header **tmp; 129 unsigned bytes; 130 unsigned n_desc; 131 void *mem; 132 struct usb_descriptor_header **ret; 133 134 /* count descriptors and their sizes; then add vector size */ 135 for (bytes = 0, n_desc = 0, tmp = src; *tmp; tmp++, n_desc++) 136 bytes += (*tmp)->bLength; 137 bytes += (n_desc + 1) * sizeof(*tmp); 138 139 mem = kmalloc(bytes, GFP_KERNEL); 140 if (!mem) 141 return NULL; 142 143 /* fill in pointers starting at "tmp", 144 * to descriptors copied starting at "mem"; 145 * and return "ret" 146 */ 147 tmp = mem; 148 ret = mem; 149 mem += (n_desc + 1) * sizeof(*tmp); 150 while (*src) { 151 memcpy(mem, *src, (*src)->bLength); 152 *tmp = mem; 153 tmp++; 154 mem += (*src)->bLength; 155 src++; 156 } 157 *tmp = NULL; 158 159 return ret; 160 } 161 EXPORT_SYMBOL_GPL(usb_copy_descriptors); 162 163 int usb_assign_descriptors(struct usb_function *f, 164 struct usb_descriptor_header **fs, 165 struct usb_descriptor_header **hs, 166 struct usb_descriptor_header **ss) 167 { 168 struct usb_gadget *g = f->config->cdev->gadget; 169 170 if (fs) { 171 f->fs_descriptors = usb_copy_descriptors(fs); 172 if (!f->fs_descriptors) 173 goto err; 174 } 175 if (hs && gadget_is_dualspeed(g)) { 176 f->hs_descriptors = usb_copy_descriptors(hs); 177 if (!f->hs_descriptors) 178 goto err; 179 } 180 if (ss && gadget_is_superspeed(g)) { 181 f->ss_descriptors = usb_copy_descriptors(ss); 182 if (!f->ss_descriptors) 183 goto err; 184 } 185 return 0; 186 err: 187 usb_free_all_descriptors(f); 188 return -ENOMEM; 189 } 190 EXPORT_SYMBOL_GPL(usb_assign_descriptors); 191 192 void usb_free_all_descriptors(struct usb_function *f) 193 { 194 usb_free_descriptors(f->fs_descriptors); 195 usb_free_descriptors(f->hs_descriptors); 196 usb_free_descriptors(f->ss_descriptors); 197 } 198 EXPORT_SYMBOL_GPL(usb_free_all_descriptors); 199 200 struct usb_descriptor_header *usb_otg_descriptor_alloc( 201 struct usb_gadget *gadget) 202 { 203 struct usb_descriptor_header *otg_desc; 204 unsigned length = 0; 205 206 if (gadget->otg_caps && (gadget->otg_caps->otg_rev >= 0x0200)) 207 length = sizeof(struct usb_otg20_descriptor); 208 else 209 length = sizeof(struct usb_otg_descriptor); 210 211 otg_desc = kzalloc(length, GFP_KERNEL); 212 return otg_desc; 213 } 214 EXPORT_SYMBOL_GPL(usb_otg_descriptor_alloc); 215 216 int usb_otg_descriptor_init(struct usb_gadget *gadget, 217 struct usb_descriptor_header *otg_desc) 218 { 219 struct usb_otg_descriptor *otg1x_desc; 220 struct usb_otg20_descriptor *otg20_desc; 221 struct usb_otg_caps *otg_caps = gadget->otg_caps; 222 u8 otg_attributes = 0; 223 224 if (!otg_desc) 225 return -EINVAL; 226 227 if (otg_caps && otg_caps->otg_rev) { 228 if (otg_caps->hnp_support) 229 otg_attributes |= USB_OTG_HNP; 230 if (otg_caps->srp_support) 231 otg_attributes |= USB_OTG_SRP; 232 if (otg_caps->adp_support && (otg_caps->otg_rev >= 0x0200)) 233 otg_attributes |= USB_OTG_ADP; 234 } else { 235 otg_attributes = USB_OTG_SRP | USB_OTG_HNP; 236 } 237 238 if (otg_caps && (otg_caps->otg_rev >= 0x0200)) { 239 otg20_desc = (struct usb_otg20_descriptor *)otg_desc; 240 otg20_desc->bLength = sizeof(struct usb_otg20_descriptor); 241 otg20_desc->bDescriptorType = USB_DT_OTG; 242 otg20_desc->bmAttributes = otg_attributes; 243 otg20_desc->bcdOTG = cpu_to_le16(otg_caps->otg_rev); 244 } else { 245 otg1x_desc = (struct usb_otg_descriptor *)otg_desc; 246 otg1x_desc->bLength = sizeof(struct usb_otg_descriptor); 247 otg1x_desc->bDescriptorType = USB_DT_OTG; 248 otg1x_desc->bmAttributes = otg_attributes; 249 } 250 251 return 0; 252 } 253 EXPORT_SYMBOL_GPL(usb_otg_descriptor_init); 254