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