|
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
|
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011,2012 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT 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.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
/**
* @defgroup USB USB Driver
* @brief Generic USB Driver.
* @details This module implements a generic USB (Universal Serial Bus) driver
* supporting device-mode operations.
* @pre In order to use the USB driver the @p HAL_USE_USB option
* must be enabled in @p halconf.h.
*
* @section usb_1 Driver State Machine
* The driver implements a state machine internally, not all the driver
* functionalities can be used in any moment, any transition not explicitly
* shown in the following diagram has to be considered an error and shall
* be captured by an assertion (if enabled).
* @if LATEX_PDF
* @dot
digraph example {
size="5, 7";
rankdir="LR";
node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true",
width="0.9", height="0.9"];
edge [fontname=Helvetica, fontsize=8];
stop [label="USB_STOP\nLow Power"];
uninit [label="USB_UNINIT", style="bold"];
ready [label="USB_READY\nClock Enabled"];
selected [label="\nUSB_SELECTED\naddress\nassigned"];
configured [label="\nUSB_ACTIVE\nconfiguration\nselected"];
uninit -> stop [label=" usbInit()", constraint=false];
stop -> stop [label="\nusbStop()"];
stop -> ready [label="\nusbStart()"];
ready -> stop [label="\nusbStop()"];
ready -> ready [label="\n\nusbStart()"];
ready -> ready [label="\nSUSPEND/WAKEUP\n>event_cb<"];
ready -> selected [label="\nSET_ADDRESS\n>event_cb<"];
selected -> ready [label="\nUSB RESET\n>event_cb<"];
selected -> selected [label="\nSUSPEND/WAKEUP\n>event_cb<\n\nValid EP0 Message\n>requests_hook_cb<\n\nGET DESCRIPTOR\n>get_descriptor_cb<"];
selected -> configured [label="\nSET_CONF(n)\n>event_cb<"];
configured -> selected [label="\nSET_CONF(0)\n>event_cb<"];
configured -> configured [label="\nSUSPEND/WAKEUP\n>event_cb<\n\nValid EP0 Message\n>requests_hook_cb<\n\nGET DESCRIPTOR\n>get_descriptor_cb<\n\nEndpoints Activity\n >in_cb< or >out_cb<"];
configured -> ready [label="\nUSB RESET\n>event_cb<"];
}
* @enddot
* @else
* @dot
digraph example {
rankdir="LR";
node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true",
width="0.9", height="0.9"];
edge [fontname=Helvetica, fontsize=8];
stop [label="USB_STOP\nLow Power"];
uninit [label="USB_UNINIT", style="bold"];
ready [label="USB_READY\nClock Enabled"];
selected [label="\nUSB_SELECTED\naddress\nassigned"];
configured [label="\nUSB_ACTIVE\nconfiguration\nselected"];
uninit -> stop [label=" usbInit()", constraint=false];
stop -> stop [label="\nusbStop()"];
stop -> ready [label="\nusbStart()"];
ready -> stop [label="\nusbStop()"];
ready -> ready [label="\n\nusbStart()"];
ready -> ready [label="\nSUSPEND/WAKEUP\n>event_cb<"];
ready -> selected [label="\nSET_ADDRESS\n>event_cb<"];
selected -> ready [label="\nUSB RESET\n>event_cb<"];
selected -> selected [label="\nSUSPEND/WAKEUP\n>event_cb<\n\nValid EP0 Message\n>requests_hook_cb<\n\nGET DESCRIPTOR\n>get_descriptor_cb<"];
selected -> configured [label="\nSET_CONF(n)\n>event_cb<"];
configured -> selected [label="\nSET_CONF(0)\n>event_cb<"];
configured -> configured [label="\nSUSPEND/WAKEUP\n>event_cb<\n\nValid EP0 Message\n>requests_hook_cb<\n\nGET DESCRIPTOR\n>get_descriptor_cb<\n\nEndpoints Activity\n >in_cb< or >out_cb<"];
configured -> ready [label="\nUSB RESET\n>event_cb<"];
}
* @enddot
* @endif
*
* @section usb_2 USB Operations
* The USB driver is quite complex and USB is complex in itself, it is
* recommended to study the USB specification before trying to use the
* driver.
*
* @subsection usb_2_1 USB Implementation
* The USB driver abstracts the inner details of the underlying USB hardware.
* The driver works asynchronously and communicates with the application
* using callbacks. The application is responsible of the descriptors and
* strings required by the USB device class to be implemented and of the
* handling of the specific messages sent over the endpoint zero. Standard
* messages are handled internally to the driver. The application can use
* hooks in order to handle custom messages or override the handling of the
* default handling of standard messages.
*
* @subsection usb_2_2 USB Endpoints
* USB endpoints are the objects that the application uses to exchange
* data with the host. There are two kind of endpoints:
* - <b>IN</b> endpoints are used by the application to transmit data to
* the host.<br>
* - <b>OUT</b> endpoints are used by the application to receive data from
* the host.
* .
* In ChibiOS/RT the endpoints can be configured in two distinct ways:
* - <b>Packet Mode</b>. In this mode the driver invokes a callback each
* time a packet has been received or transmitted. This mode is especially
* suited for those applications handling continuous streams of data.
* <br><br>
* States diagram for OUT endpoints in packet mode:
* @dot
digraph example {
rankdir="LR";
node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true",
width="0.9", height="0.9"];
edge [fontname=Helvetica, fontsize=8];
disabled [label="EP_DISABLED\nDisabled", style="bold"];
receiving [label="EP_BUSY\nReceiving Packet"];
idle [label="EP_IDLE\nPacket in Buffer"];
disabled -> receiving [label="\nusbInitEndpointI()"];
receiving -> idle [label="\npacket received\n>out_cb<"];
idle -> receiving [label="\nusbReadPacketBuffer()\nusbStartReceiveI()"];
receiving -> disabled [label="\nUSB RESET\nusbDisableEndpointsI()"];
idle -> disabled [label="\nUSB RESET\nusbDisableEndpointsI()"];
}
* @enddot
* <br><br>
* States diagram for IN endpoints in packet mode:
* @dot
digraph example {
rankdir="LR";
node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true",
width="0.9", height="0.9"];
edge [fontname=Helvetica, fontsize=8];
disabled [label="EP_DISABLED\nDisabled", style="bold"];
transmitting [label="EP_BUSY\nSending Packet"];
idle [label="EP_IDLE\nBuffer Empty"];
disabled -> idle [label="\nusbInitEndpointI()"];
idle -> transmitting [label="\nusbWritePacketBuffer()\nusbStartTransmitI()"];
transmitting -> idle [label="\npacket sent\n>in_cb<"];
transmitting -> disabled [label="\nUSB RESET\nusbDisableEndpointsI()"];
idle -> disabled [label="\nUSB RESET\nusbDisableEndpointsI()"];
}
* @enddot
* <br><br>
* - <b>Transaction Mode</b>. In this mode the driver invokes a callback
* only after a large, potentially multi-packet, transfer has been
* completed, a callback is invoked only at the end of the transfer.
* <br><br>
* States diagram for OUT endpoints in transaction mode:
* @dot
digraph example {
rankdir="LR";
node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true",
width="0.9", height="0.9"];
edge [fontname=Helvetica, fontsize=8];
disabled [label="EP_DISABLED\nDisabled", style="bold"];
receiving [label="EP_BUSY\nReceiving"];
idle [label="EP_IDLE\nReady"];
disabled -> idle [label="\nusbInitEndpointI()"];
idle -> receiving [label="\nusbPrepareReceive()\nusbStartReceiveI()"];
receiving -> receiving [label="\nmore packets"];
receiving -> idle [label="\nreception end\n>out_cb<"];
receiving -> disabled [label="\nUSB RESET\nusbDisableEndpointsI()"];
idle -> disabled [label="\nUSB RESET\nusbDisableEndpointsI()"];
}
* @enddot
* <br><br>
* States diagram for IN endpoints in transaction mode:
* @dot
digraph example {
rankdir="LR";
node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true",
width="0.9", height="0.9"];
edge [fontname=Helvetica, fontsize=8];
disabled [label="EP_DISABLED\nDisabled", style="bold"];
transmitting [label="EP_BUSY\nTransmitting"];
idle [label="EP_IDLE\nReady"];
disabled -> idle [label="\usbInitEndpointI()"];
idle -> transmitting [label="\nusbPrepareTransmit()\nusbStartTransmitI()"];
transmitting -> transmitting [label="\nmore packets"];
transmitting -> idle [label="\ntransmission end\n>in_cb<"];
transmitting -> disabled [label="\nUSB RESET\nusbDisableEndpointsI()"];
idle -> disabled [label="\nUSB RESET\nusbDisableEndpointsI()"];
}
* @enddot
* <br><br>
* .
* @subsection usb_2_3 USB Packet Buffers
* An important difference between packet and transaction modes is that there
* is a dedicated endpoint buffer in packet mode while in transaction mode
* the application has to specify its own buffer for duration of the whole
* transfer.<br>
* Packet buffers cannot be accessed directly by the application because those
* could not be necessarily memory mapped, a buffer could be a FIFO or some
* other kind of memory accessible in a special way depending on the
* underlying hardware architecture, the functions @p usbReadPacketI() and
* @p usbWritePacketI() allow to access packet buffers in an abstract way.
*
* @subsection usb_2_4 USB Callbacks
* The USB driver uses callbacks in order to interact with the application.
* There are several kinds of callbacks to be handled:
* - Driver events callback. As example errors, suspend event, reset event
* etc.
* - Messages Hook callback. This hook allows the application to implement
* handling of custom messages or to override the default handling of
* standard messages on endpoint zero.
* - Descriptor Requested callback. When the driver endpoint zero handler
* receives a GET DESCRIPTOR message and needs to send a descriptor to
* the host it queries the application using this callback.
* - Start of Frame callback. This callback is invoked each time a SOF
* packet is received.
* - Endpoint callbacks. Each endpoint informs the application about I/O
* conditions using those callbacks.
* .
*
* @ingroup IO
*/
|