summaryrefslogtreecommitdiff
path: root/include/usb_descriptor.h
blob: aadb5dc80a673772d0c4ec84ac6e26efb60eefd2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * USB definitions.
 */

#ifndef __CROS_EC_USB_DESCRIPTOR_H
#define __CROS_EC_USB_DESCRIPTOR_H

#include <stddef.h> /* for wchar_t */

#define USB_MAX_PACKET_SIZE 64

/* USB 2.0 chapter 9 definitions */

/* Descriptor types */
#define USB_DT_DEVICE                     0x01
#define USB_DT_CONFIGURATION              0x02
#define USB_DT_STRING                     0x03
#define USB_DT_INTERFACE                  0x04
#define USB_DT_ENDPOINT                   0x05
#define USB_DT_DEVICE_QUALIFIER           0x06
#define USB_DT_OTHER_SPEED_CONFIG         0x07
#define USB_DT_INTERFACE_POWER            0x08
#define USB_DT_DEBUG                      0x0a
#define USB_DT_BOS                        0x0f
#define USB_DT_DEVICE_CAPABILITY          0x10

/* USB Device Descriptor */
struct usb_device_descriptor {
	uint8_t bLength;
	uint8_t bDescriptorType;
	uint16_t bcdUSB;
	uint8_t bDeviceClass;
	uint8_t bDeviceSubClass;
	uint8_t bDeviceProtocol;
	uint8_t bMaxPacketSize0;
	uint16_t idVendor;
	uint16_t idProduct;
	uint16_t bcdDevice;
	uint8_t iManufacturer;
	uint8_t iProduct;
	uint8_t iSerialNumber;
	uint8_t bNumConfigurations;
} __packed;
#define USB_DT_DEVICE_SIZE                18

/* BOS Descriptor ( USB3.1 rev1 Section 9.6.2 ) */
struct bos_context {
	void *descp;
	int size;
};

struct usb_bos_hdr_descriptor {
	uint8_t bLength;
	uint8_t bDescriptorType; /* USB_DT_BOS */
	uint16_t wTotalLength;   /* Total length of of hdr + all dev caps */
	uint8_t bNumDeviceCaps;  /* Container ID Descriptor + others */
} __packed;
#define USB_DT_BOS_SIZE 5

/* Container ID Descriptor */
struct usb_contid_caps_descriptor {
	uint8_t  bLength;
	uint8_t  bDescriptorType;     /* USB_DT_DEVICE_CAPABILITY */
	uint8_t  bDevCapabilityType;  /* USB_DC_DTYPE_xxx */
	uint8_t  bReserved;           /* SBZ */
	uint8_t  ContainerID[16];     /* UUID */
} __packed;
#define USB_DT_CONTID_SIZE         20

/* Device Cap Type Codes ( offset 2 of Device Capability Descriptor */
#define USB_DC_DTYPE_WIRELESS  0x01
#define USB_DC_DTYPE_USB20EXT  0x02
#define USB_DC_DTYPE_USBSS     0x03
#define USB_DC_DTYPE_CONTID    0x04
#define USB_DC_DTYPE_PLATFORM  0x05
#define USB_DC_DTYPE_PD        0x06
#define USB_DC_DTYPE_BATTINFO  0x07
#define USB_DC_DTYPE_CONSUMER  0x08
#define USB_DC_DTYPE_PRODUCER  0x09
#define USB_DC_DTYPE_USBSSP    0x0a
#define USB_DC_DTYPE_PCSTIME   0x0b
#define USB_DC_DTYPE_WUSBEXT   0x0c
#define USB_DC_DTYPE_BILLBOARD 0x0d
/* RESERVED 0x00, 0xOe - 0xff */

/* Platform descriptor */
struct usb_platform_descriptor {
	uint8_t  bLength;
	uint8_t  bDescriptorType;     /* USB_DT_DEVICE_CAPABILITY */
	uint8_t  bDevCapabilityType;  /* USB_DC_DTYPE_PLATFORM */
	uint8_t  bReserved;           /* SBZ */
	uint8_t  PlatformCapUUID[16]; /* USB_PLAT_CAP_xxx */
	uint16_t bcdVersion;          /* 0x0100 */
	uint8_t  bVendorCode;
	uint8_t  iLandingPage;
} __packed;
#define USB_DT_PLATFORM_SIZE   24

/* Platform Capability UUIDs */
#define USB_PLAT_CAP_WEBUSB /*{3408b638-09a9-47a0-8bfd-a0768815b665}*/ \
	{0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47,               \
	 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65}

/* Qualifier Descriptor */
struct usb_qualifier_descriptor {
	uint8_t  bLength;
	uint8_t  bDescriptorType;
	uint16_t bcdUSB;
	uint8_t  bDeviceClass;
	uint8_t  bDeviceSubClass;
	uint8_t  bDeviceProtocol;
	uint8_t  bMaxPacketSize0;
	uint8_t  bNumConfigurations;
	uint8_t  bReserved;
} __packed;
#define USB_DT_QUALIFIER_SIZE		10

/* Configuration Descriptor */
struct usb_config_descriptor {
	uint8_t  bLength;
	uint8_t  bDescriptorType;
	uint16_t wTotalLength;
	uint8_t  bNumInterfaces;
	uint8_t  bConfigurationValue;
	uint8_t  iConfiguration;
	uint8_t  bmAttributes;
	uint8_t  bMaxPower;
} __packed;
#define USB_DT_CONFIG_SIZE                9

/* String Descriptor */
struct usb_string_descriptor {
	uint8_t  bLength;
	uint8_t  bDescriptorType;
	uint16_t wData[1];
} __packed;

/* Interface Descriptor */
struct usb_interface_descriptor {
	uint8_t  bLength;
	uint8_t  bDescriptorType;
	uint8_t  bInterfaceNumber;
	uint8_t  bAlternateSetting;
	uint8_t  bNumEndpoints;
	uint8_t  bInterfaceClass;
	uint8_t  bInterfaceSubClass;
	uint8_t  bInterfaceProtocol;
	uint8_t  iInterface;
} __packed;
#define USB_DT_INTERFACE_SIZE           9

/* Endpoint Descriptor */
struct usb_endpoint_descriptor {
	uint8_t  bLength;
	uint8_t  bDescriptorType;
	uint8_t  bEndpointAddress;
	uint8_t  bmAttributes;
	uint16_t wMaxPacketSize;
	uint8_t  bInterval;
} __packed;
#define USB_DT_ENDPOINT_SIZE            7

/* USB Class codes */
#define USB_CLASS_PER_INTERFACE           0x00
#define USB_CLASS_AUDIO                   0x01
#define USB_CLASS_COMM                    0x02
#define USB_CLASS_HID                     0x03
#define USB_CLASS_PHYSICAL                0x05
#define USB_CLASS_STILL_IMAGE             0x06
#define USB_CLASS_PRINTER                 0x07
#define USB_CLASS_MASS_STORAGE            0x08
#define USB_CLASS_HUB                     0x09
#define USB_CLASS_CDC_DATA                0x0a
#define USB_CLASS_CSCID                   0x0b
#define USB_CLASS_CONTENT_SEC             0x0d
#define USB_CLASS_VIDEO                   0x0e
#define USB_CLASS_BILLBOARD               0x11
#define USB_CLASS_WIRELESS_CONTROLLER     0xe0
#define USB_CLASS_MISC                    0xef
#define USB_CLASS_APP_SPEC                0xfe
#define USB_CLASS_VENDOR_SPEC             0xff

/* USB Vendor ID assigned to Google Inc. */
#define USB_VID_GOOGLE 0x18d1

/* Google specific SubClass/Protocol assignments */
#define USB_SUBCLASS_GOOGLE_SERIAL 0x50
#define USB_PROTOCOL_GOOGLE_SERIAL 0x01

#define USB_SUBCLASS_GOOGLE_SPI    0x51
#define USB_PROTOCOL_GOOGLE_SPI    0x01

#define USB_SUBCLASS_GOOGLE_I2C    0x52
#define USB_PROTOCOL_GOOGLE_I2C    0x01

#define USB_SUBCLASS_GOOGLE_UPDATE 0x53
#define USB_PROTOCOL_GOOGLE_UPDATE 0xff

/* Double define for cr50 code freeze.
 * TODO(vbendeb): dedup this. */
#define USB_SUBCLASS_GOOGLE_CR50   0x53
/* We can use any protocol we want */
#define USB_PROTOCOL_GOOGLE_CR50_NON_HC_FW_UPDATE 0xff

#define USB_SUBCLASS_GOOGLE_POWER  0x54
#define USB_PROTOCOL_GOOGLE_POWER  0x01

#define USB_SUBCLASS_GOOGLE_HEATMAP 0x55
#define USB_PROTOCOL_GOOGLE_HEATMAP 0x01

/* Control requests */

/* bRequestType fields */
/* direction field */
#define USB_DIR_OUT                0    /* from host to uC */
#define USB_DIR_IN                 0x80 /* from uC to host */
/* type field */
#define USB_TYPE_MASK              (0x03 << 5)
#define USB_TYPE_STANDARD          (0x00 << 5)
#define USB_TYPE_CLASS             (0x01 << 5)
#define USB_TYPE_VENDOR            (0x02 << 5)
#define USB_TYPE_RESERVED          (0x03 << 5)
/* recipient field */
#define USB_RECIP_MASK             0x1f
#define USB_RECIP_DEVICE           0x00
#define USB_RECIP_INTERFACE        0x01
#define USB_RECIP_ENDPOINT         0x02
#define USB_RECIP_OTHER            0x03

/* Standard requests for bRequest field in a SETUP packet. */
#define USB_REQ_GET_STATUS         0x00
#define USB_REQ_GET_STATUS_SELF_POWERED  (1 << 0)
#define USB_REQ_GET_STATUS_REMOTE_WAKEUP (1 << 1)
#define USB_REQ_CLEAR_FEATURE      0x01
#define USB_REQ_SET_FEATURE        0x03
#define USB_REQ_FEATURE_ENDPOINT_HALT        0x0000
#define USB_REQ_FEATURE_DEVICE_REMOTE_WAKEUP 0x0001
#define USB_REQ_FEATURE_TEST_MODE            0x0002
#define USB_REQ_SET_ADDRESS        0x05
#define USB_REQ_GET_DESCRIPTOR     0x06
#define USB_REQ_SET_DESCRIPTOR     0x07
#define USB_REQ_GET_CONFIGURATION  0x08
#define USB_REQ_SET_CONFIGURATION  0x09
#define USB_REQ_GET_INTERFACE      0x0A
#define USB_REQ_SET_INTERFACE      0x0B
#define USB_REQ_SYNCH_FRAME        0x0C

/* WebUSB URL descriptors */
#define WEBUSB_REQ_GET_URL         0x02
#define USB_DT_WEBUSB_URL          0x03

#define USB_URL_SCHEME_HTTP       0x00
#define USB_URL_SCHEME_HTTPS      0x01
#define USB_URL_SCHEME_NONE       0xff

/*
 * URL descriptor helper.
 * (similar to string descriptor but UTF-8 instead of UTF-16)
 */
#define USB_URL_DESC(scheme, str) \
	(const void *)&(const struct { \
		uint8_t _len; \
		uint8_t _type; \
		uint8_t _scheme; \
		char _data[sizeof(str)]; \
	}) { \
		/* Total size of the descriptor is : \
		 * size of the UTF-8 text plus the len/type fields \
		 * minus the string 0-termination \
		 */ \
		sizeof(str) + 3 - 1, \
		USB_DT_WEBUSB_URL, \
		USB_URL_SCHEME_##scheme, \
		str \
	}

/* Setup Packet */
struct usb_setup_packet {
	uint8_t  bmRequestType;
	uint8_t  bRequest;
	uint16_t wValue;
	uint16_t wIndex;
	uint16_t wLength;
};

/* Helpers for descriptors */

#define WIDESTR(quote) WIDESTR2(quote)
#define WIDESTR2(quote) L##quote

#define USB_STRING_DESC(str) \
	(const void *)&(const struct { \
		uint8_t _len; \
		uint8_t _type; \
		wchar_t _data[sizeof(str)]; \
	}) { \
		/* Total size of the descriptor is : \
		 * size of the UTF-16 text plus the len/type fields \
                 * minus the string 0-termination \
                 */ \
		sizeof(WIDESTR(str)) + 2 - 2, \
		USB_DT_STRING, \
		WIDESTR(str) \
	}

#ifdef CONFIG_USB_SERIALNO
/* String Descriptor for USB, for editable strings. */
struct usb_string_desc {
	uint8_t _len;
	uint8_t _type;
	wchar_t _data[CONFIG_SERIALNO_LEN];
};
#define USB_WR_STRING_DESC(str) \
	(&(struct usb_string_desc) { \
		/* As above, two bytes metadata, no null terminator. */ \
		sizeof(WIDESTR(str)) + 2 - 2, \
		USB_DT_STRING, \
		WIDESTR(str) \
})
extern struct usb_string_desc *usb_serialno_desc;
#endif

/* Use these macros for declaring descriptors, to order them properly */
#define USB_CONF_DESC_VAR(name, varname) varname		\
	__keep __attribute__((section(".rodata.usb_desc_" STRINGIFY(name))))
#define USB_CONF_DESC(name) USB_CONF_DESC_VAR(name, CONCAT2(usb_desc_, name))
#define USB_IFACE_DESC(num) USB_CONF_DESC(CONCAT3(iface, num, _0iface))
#define USB_CUSTOM_DESC_VAR(i, name, varname)			\
	USB_CONF_DESC_VAR(CONCAT4(iface, i, _1, name), varname)
#define USB_CUSTOM_DESC(i, name) USB_CONF_DESC(CONCAT4(iface, i, _1, name))
#define USB_EP_DESC(i, num) USB_CONF_DESC(CONCAT4(iface, i, _2ep, num))

/* USB Linker data */
extern const uint8_t __usb_desc[];
extern const uint8_t __usb_desc_end[];
#define USB_DESC_SIZE (__usb_desc_end - __usb_desc)

/* These descriptors defined in board code */
extern const void * const usb_strings[];
extern const uint8_t usb_string_desc[];
/* USB string descriptor with the firmware version */
extern const void * const usb_fw_version;
extern const struct bos_context bos_ctx;
extern const void *webusb_url;

#endif /* __CROS_EC_USB_DESCRIPTOR_H */