summaryrefslogtreecommitdiffstats
path: root/hid/firmware/usb.h
blob: c2813befa5c070471f61a8a43f74dbee7b2087f0 (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
#ifndef USBSTACK_H_
#define USBSTACK_H_
/*
 *   Tiny USB stack
 *
 *   Copyright (C) 2009-2014 Michael Buesch <m@bues.ch>
 *
 *   USB data structure and constant definitions
 *   taken from libusb-0.1 and the Linux kernel.
 *   Copyright (c) 2000-2003 Johannes Erdfelt and others
 *
 *   This program is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU General Public License
 *   version 2 as published by the Free Software Foundation.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 */

#include "usb_config.h"

#include <stdint.h>
#include <avr/pgmspace.h>


#if USBCFG_ARCH_BE
# define le16_to_cpu(value)	usb_swap16(value)
# define le32_to_cpu(value)	usb_swap32(value)
# define cpu_to_le16(value)	usb_swap16(value)
# define cpu_to_le32(value)	usb_swap32(value)
#else
# define le16_to_cpu(value)	(value)
# define le32_to_cpu(value)	(value)
# define cpu_to_le16(value)	(value)
# define cpu_to_le32(value)	(value)
#endif

#define usb_swap16(value)	(((value & 0xFF00) >> 8) | \
				 ((value & 0x00FF) << 8))
#define usb_swap32(value)	(((value & 0xFF000000) >> 24) | \
				 ((value & 0x00FF0000) >> 8) | \
				 ((value & 0x0000FF00) << 8) | \
				 ((value & 0x000000FF) << 24))

#undef DBG
#if DEBUG
# define DBG(x) x
#else
# define DBG(x) /* nothing */
#endif


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;
} __attribute__ ((packed));

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;
} __attribute__ ((packed));

/* from config descriptor bmAttributes */
#define USB_CONFIG_ATT_ONE		(1 << 7)	/* must be set */
#define USB_CONFIG_ATT_SELFPOWER	(1 << 6)	/* self powered */
#define USB_CONFIG_ATT_WAKEUP		(1 << 5)	/* can wakeup */
#define USB_CONFIG_ATT_BATTERY		(1 << 4)	/* battery powered */

struct usb_string_descriptor {
	uint8_t bLength;
	uint8_t bDescriptorType;
	uint8_t string[0];
} __attribute__ ((packed));

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;
} __attribute__ ((packed));

struct usb_endpoint_descriptor {
	uint8_t bLength;
	uint8_t bDescriptorType;
	uint8_t bEndpointAddress;
	uint8_t bmAttributes;
	uint16_t wMaxPacketSize;
	uint8_t bInterval;
} __attribute__ ((packed));

struct usb_audio_endpoint_descriptor {
	uint8_t bLength;
	uint8_t bDescriptorType;
	uint8_t bEndpointAddress;
	uint8_t bmAttributes;
	uint16_t wMaxPacketSize;
	uint8_t bInterval;
	uint8_t bRefresh;
	uint8_t bSynchAddress;
} __attribute__ ((packed));


#define USB_ENDPOINT_XFERTYPE_MASK	0x03	/* in bmAttributes */
#define USB_ENDPOINT_XFER_CONTROL	0
#define USB_ENDPOINT_XFER_ISOC		1
#define USB_ENDPOINT_XFER_BULK		2
#define USB_ENDPOINT_XFER_INT		3
#define USB_ENDPOINT_MAX_ADJUSTABLE	0x80

struct usb_ctrl {
	uint8_t bRequestType;
	uint8_t bRequest;
	uint16_t wValue;
	uint16_t wIndex;
	uint16_t wLength;
} __attribute__ ((packed));


/* Device and/or Interface Class codes */
#define USB_CLASS_PER_INTERFACE		0	/* for DeviceClass */
#define USB_CLASS_AUDIO			1
#define USB_CLASS_COMM			2
#define USB_CLASS_HID			3
#define USB_CLASS_PRINTER		7
#define USB_CLASS_PTP			6
#define USB_CLASS_MASS_STORAGE		8
#define USB_CLASS_HUB			9
#define USB_CLASS_DATA			10
#define USB_CLASS_VENDOR_SPEC		0xff

/* Descriptor types */
#define USB_DT_DEVICE			0x01
#define USB_DT_CONFIG			0x02
#define USB_DT_STRING			0x03
#define USB_DT_INTERFACE		0x04
#define USB_DT_ENDPOINT			0x05

#define USB_DT_HID			0x21
#define USB_DT_REPORT			0x22
#define USB_DT_PHYSICAL			0x23
#define USB_DT_HUB			0x29

/* Descriptor sizes per descriptor type */
#define USB_DT_DEVICE_SIZE		18
#define USB_DT_CONFIG_SIZE		9
#define USB_DT_INTERFACE_SIZE		9
#define USB_DT_ENDPOINT_SIZE		7
#define USB_DT_ENDPOINT_AUDIO_SIZE	9	/* Audio extension */
#define USB_DT_HUB_NONVAR_SIZE		7

/* Request types */
#define USB_REQ_GET_STATUS		0x00
#define USB_REQ_CLEAR_FEATURE		0x01
/* 0x02 is reserved */
#define USB_REQ_SET_FEATURE		0x03
/* 0x04 is reserved */
#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

#define USB_TYPE_STANDARD		(0x00 << 5)
#define USB_TYPE_CLASS			(0x01 << 5)
#define USB_TYPE_VENDOR			(0x02 << 5)
#define USB_TYPE_RESERVED		(0x03 << 5)
#define USB_TYPE_MASK			(0x03 << 5)

#define USB_RECIP_DEVICE		0x00
#define USB_RECIP_INTERFACE		0x01
#define USB_RECIP_ENDPOINT		0x02
#define USB_RECIP_OTHER			0x03
#define USB_RECIP_MASK			0x03

#define USB_ENDPOINT_IN			0x80
#define USB_ENDPOINT_OUT		0x00

static inline uint8_t usb_ep_is_in(uint8_t ep)
{
	return ep & USB_ENDPOINT_IN;
}
static inline uint8_t usb_ep_is_out(uint8_t ep)
{
	return !(ep & USB_ENDPOINT_IN);
}

static inline uint8_t usb_ctrl_is_in(const struct usb_ctrl *ctrl)
{
	return (ctrl->bRequestType & USB_ENDPOINT_IN);
}
static inline uint8_t usb_ctrl_is_out(const struct usb_ctrl *ctrl)
{
	return !(ctrl->bRequestType & USB_ENDPOINT_IN);
}

/* USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and
 * are read as a bit array returned by USB_REQ_GET_STATUS.  (So there
 * are at most sixteen features of each type.)  Hubs may also support a
 * new USB_REQ_TEST_AND_SET_FEATURE to put ports into L1 suspend. */
#define USB_DEVICE_SELF_POWERED		0	/* (read only) */
#define USB_DEVICE_REMOTE_WAKEUP	1	/* dev may initiate wakeup */
#define USB_DEVICE_TEST_MODE		2	/* (wired high speed only) */
#define USB_DEVICE_BATTERY		2	/* (wireless) */
#define USB_DEVICE_B_HNP_ENABLE		3	/* (otg) dev may initiate HNP */
#define USB_DEVICE_WUSB_DEVICE		3	/* (wireless)*/
#define USB_DEVICE_A_HNP_SUPPORT	4	/* (otg) RH port supports HNP */
#define USB_DEVICE_A_ALT_HNP_SUPPORT	5	/* (otg) other RH port does */
#define USB_DEVICE_DEBUG_MODE		6	/* (special devices only) */

#define USB_ENDPOINT_HALT		0	/* IN/OUT will STALL */


/*** Device driver calls ***/

/** usb_reset - Reset the USB statemachine.
 * Called by the lowlevel device driver. */
void usb_reset(void);

/** usb_control_rx - Received setup token on control-EP.
 * Returns enum usb_rx_returncode.
 * Called by the lowlevel device driver. */
uint8_t usb_control_setup_rx(struct usb_ctrl *ctl);

/** usb_control_rx - Received data on control-EP.
 * Returns enum usb_rx_returncode.
 * Called by the lowlevel device driver. */
uint8_t usb_control_rx(void *data, uint8_t size);

#define USB_TX_POLL_NONE	0xFF

/** usb_control_tx_poll - Poll TX data on control-EP.
 * Returns the number of octets or USB_TX_POLL_NONE on error.
 * Called by the lowlevel device driver. */
uint8_t usb_control_tx_poll(void **data, uint8_t chunksize);

/** usb_ep1_rx - Received data on EP1.
 * Returns enum usb_rx_returncode.
 * Called by the lowlevel device driver. */
uint8_t usb_ep1_rx(void *data, uint8_t size);

/** usb_ep1_tx_poll - Poll TX data on EP1.
 * Returns the number of octets or USB_TX_POLL_NONE on error.
 * Called by the lowlevel device driver. */
uint8_t usb_ep1_tx_poll(void **data, uint8_t chunksize);

/** usb_ep2_rx - Received data on EP2.
 * Returns enum usb_rx_returncode.
 * Called by the lowlevel device driver. */
uint8_t usb_ep2_rx(void *data, uint8_t size);

/** usb_ep2_tx_poll - Poll TX data on EP2.
 * Returns the number of octets or USB_TX_POLL_NONE on error.
 * Called by the lowlevel device driver. */
uint8_t usb_ep2_tx_poll(void **data, uint8_t chunksize);

/** enum usb_rx_returncode - Returncode to usb_*_rx() */
enum usb_rx_returncode {
	USB_RX_DONE,		/* Everything is done */
	USB_RX_ERROR,		/* An error occured while processing the frame */
};




/*** Callbacks to device driver - Defined in the lowlevel driver ***/

extern void usb_set_address(uint8_t address);
extern void usb_enable_endpoints(uint8_t enable);
extern void usb_stall_endpoint(uint8_t ep);
extern void usb_unstall_endpoint(uint8_t ep);
extern uint8_t usb_endpoint_is_stalled(uint8_t ep);

#endif /* USBSTACK_H_ */
bues.ch cgit interface