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