1 /* 2 * usb/gadget/config.c -- simplify building config descriptors 3 * 4 * Copyright (C) 2003 David Brownell 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 * 8 * Ported to U-boot by: Thomas Smits <ts.smits@gmail.com> and 9 * Remy Bohmer <linux@bohmer.net> 10 */ 11 12 #include <common.h> 13 #include <asm/unaligned.h> 14 #include <asm/errno.h> 15 #include <linux/list.h> 16 #include <linux/string.h> 17 18 #include <linux/usb/ch9.h> 19 #include <linux/usb/gadget.h> 20 21 22 /** 23 * usb_descriptor_fillbuf - fill buffer with descriptors 24 * @buf: Buffer to be filled 25 * @buflen: Size of buf 26 * @src: Array of descriptor pointers, terminated by null pointer. 27 * 28 * Copies descriptors into the buffer, returning the length or a 29 * negative error code if they can't all be copied. Useful when 30 * assembling descriptors for an associated set of interfaces used 31 * as part of configuring a composite device; or in other cases where 32 * sets of descriptors need to be marshaled. 33 */ 34 int 35 usb_descriptor_fillbuf(void *buf, unsigned buflen, 36 const struct usb_descriptor_header **src) 37 { 38 u8 *dest = buf; 39 40 if (!src) 41 return -EINVAL; 42 43 /* fill buffer from src[] until null descriptor ptr */ 44 for (; NULL != *src; src++) { 45 unsigned len = (*src)->bLength; 46 47 if (len > buflen) 48 return -EINVAL; 49 memcpy(dest, *src, len); 50 buflen -= len; 51 dest += len; 52 } 53 return dest - (u8 *)buf; 54 } 55 56 57 /** 58 * usb_gadget_config_buf - builts a complete configuration descriptor 59 * @config: Header for the descriptor, including characteristics such 60 * as power requirements and number of interfaces. 61 * @desc: Null-terminated vector of pointers to the descriptors (interface, 62 * endpoint, etc) defining all functions in this device configuration. 63 * @buf: Buffer for the resulting configuration descriptor. 64 * @length: Length of buffer. If this is not big enough to hold the 65 * entire configuration descriptor, an error code will be returned. 66 * 67 * This copies descriptors into the response buffer, building a descriptor 68 * for that configuration. It returns the buffer length or a negative 69 * status code. The config.wTotalLength field is set to match the length 70 * of the result, but other descriptor fields (including power usage and 71 * interface count) must be set by the caller. 72 * 73 * Gadget drivers could use this when constructing a config descriptor 74 * in response to USB_REQ_GET_DESCRIPTOR. They will need to patch the 75 * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed. 76 */ 77 int usb_gadget_config_buf( 78 const struct usb_config_descriptor *config, 79 void *buf, 80 unsigned length, 81 const struct usb_descriptor_header **desc 82 ) 83 { 84 struct usb_config_descriptor *cp = buf; 85 int len; 86 87 /* config descriptor first */ 88 if (length < USB_DT_CONFIG_SIZE || !desc) 89 return -EINVAL; 90 /* config need not be aligned */ 91 memcpy(cp, config, sizeof(*cp)); 92 93 /* then interface/endpoint/class/vendor/... */ 94 len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8 *)buf, 95 length - USB_DT_CONFIG_SIZE, desc); 96 if (len < 0) 97 return len; 98 len += USB_DT_CONFIG_SIZE; 99 if (len > 0xffff) 100 return -EINVAL; 101 102 /* patch up the config descriptor */ 103 cp->bLength = USB_DT_CONFIG_SIZE; 104 cp->bDescriptorType = USB_DT_CONFIG; 105 put_unaligned_le16(len, &cp->wTotalLength); 106 cp->bmAttributes |= USB_CONFIG_ATT_ONE; 107 return len; 108 } 109