Endpoint configuration is now refined to give better output when all configurations...
[pub/lufa.git] / LUFA / Drivers / USB / LowLevel / Endpoint.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2009.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
7 */
8
9 /*
10 Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, and distribute this software
13 and its documentation for any purpose and without fee is hereby
14 granted, provided that the above copyright notice appear in all
15 copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20
21 The author disclaim all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
28 this software.
29 */
30
31 #include "../HighLevel/USBMode.h"
32
33 #if defined(USB_CAN_BE_DEVICE)
34
35 #define INCLUDE_FROM_ENDPOINT_C
36 #include "Endpoint.h"
37
38 #if !defined(FIXED_CONTROL_ENDPOINT_SIZE)
39 uint8_t USB_ControlEndpointSize = ENDPOINT_CONTROLEP_DEFAULT_SIZE;
40 #endif
41
42 uint8_t Endpoint_BytesToEPSizeMaskDynamic(const uint16_t Size)
43 {
44 return Endpoint_BytesToEPSizeMask(Size);
45 }
46
47 bool Endpoint_ConfigureEndpoint_Prv(const uint8_t Number, const uint8_t UECFG0XData, const uint8_t UECFG1XData)
48 {
49 Endpoint_SelectEndpoint(Number);
50 Endpoint_EnableEndpoint();
51
52 UECFG1X = 0;
53
54 UECFG0X = UECFG0XData;
55 UECFG1X = UECFG1XData;
56
57 return Endpoint_IsConfigured();
58 }
59
60 void Endpoint_ClearEndpoints(void)
61 {
62 UEINT = 0;
63
64 for (uint8_t EPNum = 0; EPNum < ENDPOINT_TOTAL_ENDPOINTS; EPNum++)
65 {
66 Endpoint_SelectEndpoint(EPNum);
67 UEIENX = 0;
68 UEINTX = 0;
69 Endpoint_DeallocateMemory();
70 Endpoint_DisableEndpoint();
71 }
72 }
73
74 #if !defined(CONTROL_ONLY_DEVICE)
75 uint8_t Endpoint_WaitUntilReady(void)
76 {
77 uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
78
79 USB_INT_Clear(USB_INT_SOFI);
80
81 for (;;)
82 {
83 if (Endpoint_GetEndpointDirection() == ENDPOINT_DIR_IN)
84 {
85 if (Endpoint_IsINReady())
86 return ENDPOINT_READYWAIT_NoError;
87 }
88 else
89 {
90 if (Endpoint_IsOUTReceived())
91 return ENDPOINT_READYWAIT_NoError;
92 }
93
94 if (!(USB_IsConnected))
95 return ENDPOINT_READYWAIT_DeviceDisconnected;
96 else if (Endpoint_IsStalled())
97 return ENDPOINT_READYWAIT_EndpointStalled;
98
99 if (USB_INT_HasOccurred(USB_INT_SOFI))
100 {
101 USB_INT_Clear(USB_INT_SOFI);
102
103 if (!(TimeoutMSRem--))
104 return ENDPOINT_READYWAIT_Timeout;
105 }
106 }
107 }
108
109 uint8_t Endpoint_Discard_Stream(uint16_t Length
110 #if !defined(NO_STREAM_CALLBACKS)
111 , uint8_t (* const Callback)(void)
112 #endif
113 )
114 {
115 uint8_t ErrorCode;
116
117 if ((ErrorCode = Endpoint_WaitUntilReady()))
118 return ErrorCode;
119
120 while (Length--)
121 {
122 if (!(Endpoint_IsReadWriteAllowed()))
123 {
124 Endpoint_ClearOUT();
125
126 #if !defined(NO_STREAM_CALLBACKS)
127 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
128 return ENDPOINT_RWSTREAM_ERROR_CallbackAborted;
129 #endif
130
131 if ((ErrorCode = Endpoint_WaitUntilReady()))
132 return ErrorCode;
133 }
134 else
135 {
136 Endpoint_Discard_Byte();
137 }
138 }
139
140 return ENDPOINT_RWSTREAM_ERROR_NoError;
141 }
142
143 uint8_t Endpoint_Write_Stream_LE(const void* Buffer, uint16_t Length
144 #if !defined(NO_STREAM_CALLBACKS)
145 , uint8_t (* const Callback)(void)
146 #endif
147 )
148 {
149 uint8_t* DataStream = (uint8_t*)Buffer;
150 uint8_t ErrorCode;
151
152 if ((ErrorCode = Endpoint_WaitUntilReady()))
153 return ErrorCode;
154
155 while (Length--)
156 {
157 if (!(Endpoint_IsReadWriteAllowed()))
158 {
159 Endpoint_ClearIN();
160
161 #if !defined(NO_STREAM_CALLBACKS)
162 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
163 return ENDPOINT_RWSTREAM_ERROR_CallbackAborted;
164 #endif
165
166 if ((ErrorCode = Endpoint_WaitUntilReady()))
167 return ErrorCode;
168 }
169 else
170 {
171 Endpoint_Write_Byte(*(DataStream++));
172 }
173 }
174
175 return ENDPOINT_RWSTREAM_ERROR_NoError;
176 }
177
178 uint8_t Endpoint_Write_Stream_BE(const void* Buffer, uint16_t Length
179 #if !defined(NO_STREAM_CALLBACKS)
180 , uint8_t (* const Callback)(void)
181 #endif
182 )
183 {
184 uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1);
185 uint8_t ErrorCode;
186
187 if ((ErrorCode = Endpoint_WaitUntilReady()))
188 return ErrorCode;
189
190 while (Length--)
191 {
192 if (!(Endpoint_IsReadWriteAllowed()))
193 {
194 Endpoint_ClearIN();
195
196 #if !defined(NO_STREAM_CALLBACKS)
197 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
198 return ENDPOINT_RWSTREAM_ERROR_CallbackAborted;
199 #endif
200
201 if ((ErrorCode = Endpoint_WaitUntilReady()))
202 return ErrorCode;
203 }
204 else
205 {
206 Endpoint_Write_Byte(*(DataStream--));
207 }
208 }
209
210 return ENDPOINT_RWSTREAM_ERROR_NoError;
211 }
212
213 uint8_t Endpoint_Read_Stream_LE(void* Buffer, uint16_t Length
214 #if !defined(NO_STREAM_CALLBACKS)
215 , uint8_t (* const Callback)(void)
216 #endif
217 )
218 {
219 uint8_t* DataStream = (uint8_t*)Buffer;
220 uint8_t ErrorCode;
221
222 if ((ErrorCode = Endpoint_WaitUntilReady()))
223 return ErrorCode;
224
225 while (Length--)
226 {
227 if (!(Endpoint_IsReadWriteAllowed()))
228 {
229 Endpoint_ClearOUT();
230
231 #if !defined(NO_STREAM_CALLBACKS)
232 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
233 return ENDPOINT_RWSTREAM_ERROR_CallbackAborted;
234 #endif
235
236 if ((ErrorCode = Endpoint_WaitUntilReady()))
237 return ErrorCode;
238 }
239 else
240 {
241 *(DataStream++) = Endpoint_Read_Byte();
242 }
243 }
244
245 return ENDPOINT_RWSTREAM_ERROR_NoError;
246 }
247
248 uint8_t Endpoint_Read_Stream_BE(void* Buffer, uint16_t Length
249 #if !defined(NO_STREAM_CALLBACKS)
250 , uint8_t (* const Callback)(void)
251 #endif
252 )
253 {
254 uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1);
255 uint8_t ErrorCode;
256
257 if ((ErrorCode = Endpoint_WaitUntilReady()))
258 return ErrorCode;
259
260 while (Length--)
261 {
262 if (!(Endpoint_IsReadWriteAllowed()))
263 {
264 Endpoint_ClearOUT();
265
266 #if !defined(NO_STREAM_CALLBACKS)
267 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
268 return ENDPOINT_RWSTREAM_ERROR_CallbackAborted;
269 #endif
270
271 if ((ErrorCode = Endpoint_WaitUntilReady()))
272 return ErrorCode;
273 }
274 else
275 {
276 *(DataStream--) = Endpoint_Read_Byte();
277 }
278 }
279
280 return ENDPOINT_RWSTREAM_ERROR_NoError;
281 }
282 #endif
283
284 uint8_t Endpoint_Write_Control_Stream_LE(const void* Buffer, uint16_t Length)
285 {
286 uint8_t* DataStream = (uint8_t*)Buffer;
287 bool LastPacketFull = false;
288 bool ShortTransfer = (Length < USB_ControlRequest.wLength);
289
290 while (Length && !(Endpoint_IsOUTReceived()))
291 {
292 while (!(Endpoint_IsINReady()));
293
294 while (Length && (Endpoint_BytesInEndpoint() < USB_ControlEndpointSize))
295 {
296 Endpoint_Write_Byte(*(DataStream++));
297
298 Length--;
299 }
300
301 LastPacketFull = (Endpoint_BytesInEndpoint() == USB_ControlEndpointSize);
302 Endpoint_ClearIN();
303 }
304
305 if (Endpoint_IsOUTReceived())
306 return ENDPOINT_RWCSTREAM_ERROR_HostAborted;
307
308 if (LastPacketFull || ShortTransfer)
309 {
310 while (!(Endpoint_IsINReady()));
311 Endpoint_ClearIN();
312 }
313
314 while (!(Endpoint_IsOUTReceived()));
315
316 return ENDPOINT_RWCSTREAM_ERROR_NoError;
317 }
318
319 uint8_t Endpoint_Write_Control_Stream_BE(const void* Buffer, uint16_t Length)
320 {
321 uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1);
322 bool LastPacketFull = false;
323 bool ShortTransfer = (Length < USB_ControlRequest.wLength);
324
325 while (Length && !(Endpoint_IsOUTReceived()))
326 {
327 while (!(Endpoint_IsINReady()));
328
329 while (Length && (Endpoint_BytesInEndpoint() < USB_ControlEndpointSize))
330 {
331 Endpoint_Write_Byte(*(DataStream--));
332
333 Length--;
334 }
335
336 LastPacketFull = (Endpoint_BytesInEndpoint() == USB_ControlEndpointSize);
337 Endpoint_ClearIN();
338 }
339
340 if (Endpoint_IsOUTReceived())
341 return ENDPOINT_RWCSTREAM_ERROR_HostAborted;
342
343 if (LastPacketFull || ShortTransfer)
344 {
345 while (!(Endpoint_IsINReady()));
346 Endpoint_ClearIN();
347 }
348
349 while (!(Endpoint_IsOUTReceived()));
350
351 return ENDPOINT_RWCSTREAM_ERROR_NoError;
352 }
353
354 uint8_t Endpoint_Read_Control_Stream_LE(void* Buffer, uint16_t Length)
355 {
356 uint8_t* DataStream = (uint8_t*)Buffer;
357
358 while (Length)
359 {
360 while (!(Endpoint_IsOUTReceived()));
361
362 while (Length && Endpoint_BytesInEndpoint())
363 {
364 *(DataStream++) = Endpoint_Read_Byte();
365
366 Length--;
367 }
368
369 Endpoint_ClearOUT();
370 }
371
372 while (!(Endpoint_IsINReady()));
373
374 return ENDPOINT_RWCSTREAM_ERROR_NoError;
375 }
376
377 uint8_t Endpoint_Read_Control_Stream_BE(void* Buffer, uint16_t Length)
378 {
379 uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1);
380
381 while (Length)
382 {
383 while (!(Endpoint_IsOUTReceived()));
384
385 while (Length && Endpoint_BytesInEndpoint())
386 {
387 *(DataStream--) = Endpoint_Read_Byte();
388
389 Length--;
390 }
391
392 Endpoint_ClearOUT();
393 }
394
395 while (!(Endpoint_IsINReady()));
396
397 return ENDPOINT_RWCSTREAM_ERROR_NoError;
398 }
399
400 #endif