Added compatibility list to the documentation of each individual demo.
[pub/USBasp.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 #if (USB_STREAM_TIMEOUT_MS < 0xFF)
78 uint8_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
79 #else
80 uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
81 #endif
82
83 for (;;)
84 {
85 if (Endpoint_GetEndpointDirection() == ENDPOINT_DIR_IN)
86 {
87 if (Endpoint_IsINReady())
88 return ENDPOINT_READYWAIT_NoError;
89 }
90 else
91 {
92 if (Endpoint_IsOUTReceived())
93 return ENDPOINT_READYWAIT_NoError;
94 }
95
96 if (!(USB_IsConnected))
97 return ENDPOINT_READYWAIT_DeviceDisconnected;
98 else if (Endpoint_IsStalled())
99 return ENDPOINT_READYWAIT_EndpointStalled;
100
101 if (USB_INT_HasOccurred(USB_INT_SOFI))
102 {
103 USB_INT_Clear(USB_INT_SOFI);
104
105 if (!(TimeoutMSRem--))
106 return ENDPOINT_READYWAIT_Timeout;
107 }
108 }
109 }
110
111 uint8_t Endpoint_Discard_Stream(uint16_t Length
112 #if !defined(NO_STREAM_CALLBACKS)
113 , StreamCallbackPtr_t Callback
114 #endif
115 )
116 {
117 uint8_t ErrorCode;
118
119 if ((ErrorCode = Endpoint_WaitUntilReady()))
120 return ErrorCode;
121
122 #if defined(FAST_STREAM_TRANSFERS)
123 uint8_t BytesRemToAlignment = (Endpoint_BytesInEndpoint() & 0x07);
124
125 if (Length >= 8)
126 {
127 Length -= BytesRemToAlignment;
128
129 switch (BytesRemToAlignment)
130 {
131 default:
132 do
133 {
134 if (!(Endpoint_IsReadWriteAllowed()))
135 {
136 Endpoint_ClearOUT();
137
138 #if !defined(NO_STREAM_CALLBACKS)
139 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
140 return ENDPOINT_RWSTREAM_CallbackAborted;
141 #endif
142
143 if ((ErrorCode = Endpoint_WaitUntilReady()))
144 return ErrorCode;
145 }
146
147 Length -= 8;
148
149 Endpoint_Discard_Byte();
150 case 7: Endpoint_Discard_Byte();
151 case 6: Endpoint_Discard_Byte();
152 case 5: Endpoint_Discard_Byte();
153 case 4: Endpoint_Discard_Byte();
154 case 3: Endpoint_Discard_Byte();
155 case 2: Endpoint_Discard_Byte();
156 case 1: Endpoint_Discard_Byte();
157 } while (Length >= 8);
158 }
159 }
160 #endif
161
162 while (Length)
163 {
164 if (!(Endpoint_IsReadWriteAllowed()))
165 {
166 Endpoint_ClearOUT();
167
168 #if !defined(NO_STREAM_CALLBACKS)
169 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
170 return ENDPOINT_RWSTREAM_CallbackAborted;
171 #endif
172
173 if ((ErrorCode = Endpoint_WaitUntilReady()))
174 return ErrorCode;
175 }
176 else
177 {
178 Endpoint_Discard_Byte();
179 Length--;
180 }
181 }
182
183 return ENDPOINT_RWSTREAM_NoError;
184 }
185
186 uint8_t Endpoint_Write_Stream_LE(const void* Buffer, uint16_t Length
187 #if !defined(NO_STREAM_CALLBACKS)
188 , StreamCallbackPtr_t Callback
189 #endif
190 )
191 {
192 uint8_t* DataStream = (uint8_t*)Buffer;
193 uint8_t ErrorCode;
194
195 if ((ErrorCode = Endpoint_WaitUntilReady()))
196 return ErrorCode;
197
198 #if defined(FAST_STREAM_TRANSFERS)
199 uint8_t BytesRemToAlignment = (Endpoint_BytesInEndpoint() & 0x07);
200
201 if (Length >= 8)
202 {
203 Length -= BytesRemToAlignment;
204
205 switch (BytesRemToAlignment)
206 {
207 default:
208 do
209 {
210 if (!(Endpoint_IsReadWriteAllowed()))
211 {
212 Endpoint_ClearIN();
213
214 #if !defined(NO_STREAM_CALLBACKS)
215 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
216 return ENDPOINT_RWSTREAM_CallbackAborted;
217 #endif
218
219 if ((ErrorCode = Endpoint_WaitUntilReady()))
220 return ErrorCode;
221 }
222
223 Length -= 8;
224
225 Endpoint_Write_Byte(*(DataStream++));
226 case 7: Endpoint_Write_Byte(*(DataStream++));
227 case 6: Endpoint_Write_Byte(*(DataStream++));
228 case 5: Endpoint_Write_Byte(*(DataStream++));
229 case 4: Endpoint_Write_Byte(*(DataStream++));
230 case 3: Endpoint_Write_Byte(*(DataStream++));
231 case 2: Endpoint_Write_Byte(*(DataStream++));
232 case 1: Endpoint_Write_Byte(*(DataStream++));
233 } while (Length >= 8);
234 }
235 }
236 #endif
237
238 while (Length)
239 {
240 if (!(Endpoint_IsReadWriteAllowed()))
241 {
242 Endpoint_ClearIN();
243
244 #if !defined(NO_STREAM_CALLBACKS)
245 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
246 return ENDPOINT_RWSTREAM_CallbackAborted;
247 #endif
248
249 if ((ErrorCode = Endpoint_WaitUntilReady()))
250 return ErrorCode;
251 }
252 else
253 {
254 Endpoint_Write_Byte(*(DataStream++));
255 Length--;
256 }
257 }
258
259 return ENDPOINT_RWSTREAM_NoError;
260 }
261
262 uint8_t Endpoint_Write_Stream_BE(const void* Buffer, uint16_t Length
263 #if !defined(NO_STREAM_CALLBACKS)
264 , StreamCallbackPtr_t Callback
265 #endif
266 )
267 {
268 uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1);
269 uint8_t ErrorCode;
270
271 if ((ErrorCode = Endpoint_WaitUntilReady()))
272 return ErrorCode;
273
274 #if defined(FAST_STREAM_TRANSFERS)
275 uint8_t BytesRemToAlignment = (Endpoint_BytesInEndpoint() & 0x07);
276
277 if (Length >= 8)
278 {
279 Length -= BytesRemToAlignment;
280
281 switch (BytesRemToAlignment)
282 {
283 default:
284 do
285 {
286 if (!(Endpoint_IsReadWriteAllowed()))
287 {
288 Endpoint_ClearIN();
289
290 #if !defined(NO_STREAM_CALLBACKS)
291 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
292 return ENDPOINT_RWSTREAM_CallbackAborted;
293 #endif
294
295 if ((ErrorCode = Endpoint_WaitUntilReady()))
296 return ErrorCode;
297 }
298
299 Length -= 8;
300
301 Endpoint_Write_Byte(*(DataStream--));
302 case 7: Endpoint_Write_Byte(*(DataStream--));
303 case 6: Endpoint_Write_Byte(*(DataStream--));
304 case 5: Endpoint_Write_Byte(*(DataStream--));
305 case 4: Endpoint_Write_Byte(*(DataStream--));
306 case 3: Endpoint_Write_Byte(*(DataStream--));
307 case 2: Endpoint_Write_Byte(*(DataStream--));
308 case 1: Endpoint_Write_Byte(*(DataStream--));
309 } while (Length >= 8);
310 }
311 }
312 #endif
313
314 while (Length)
315 {
316 if (!(Endpoint_IsReadWriteAllowed()))
317 {
318 Endpoint_ClearIN();
319
320 #if !defined(NO_STREAM_CALLBACKS)
321 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
322 return ENDPOINT_RWSTREAM_CallbackAborted;
323 #endif
324
325 if ((ErrorCode = Endpoint_WaitUntilReady()))
326 return ErrorCode;
327 }
328 else
329 {
330 Endpoint_Write_Byte(*(DataStream--));
331 Length--;
332 }
333 }
334
335 return ENDPOINT_RWSTREAM_NoError;
336 }
337
338 uint8_t Endpoint_Read_Stream_LE(void* Buffer, uint16_t Length
339 #if !defined(NO_STREAM_CALLBACKS)
340 , StreamCallbackPtr_t Callback
341 #endif
342 )
343 {
344 uint8_t* DataStream = (uint8_t*)Buffer;
345 uint8_t ErrorCode;
346
347 if ((ErrorCode = Endpoint_WaitUntilReady()))
348 return ErrorCode;
349
350 #if defined(FAST_STREAM_TRANSFERS)
351 uint8_t BytesRemToAlignment = (Endpoint_BytesInEndpoint() & 0x07);
352
353 if (Length >= 8)
354 {
355 Length -= BytesRemToAlignment;
356
357 switch (BytesRemToAlignment)
358 {
359 default:
360 do
361 {
362 if (!(Endpoint_IsReadWriteAllowed()))
363 {
364 Endpoint_ClearOUT();
365
366 #if !defined(NO_STREAM_CALLBACKS)
367 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
368 return ENDPOINT_RWSTREAM_CallbackAborted;
369 #endif
370
371 if ((ErrorCode = Endpoint_WaitUntilReady()))
372 return ErrorCode;
373 }
374
375 Length -= 8;
376
377 *(DataStream++) = Endpoint_Read_Byte();
378 case 7: *(DataStream++) = Endpoint_Read_Byte();
379 case 6: *(DataStream++) = Endpoint_Read_Byte();
380 case 5: *(DataStream++) = Endpoint_Read_Byte();
381 case 4: *(DataStream++) = Endpoint_Read_Byte();
382 case 3: *(DataStream++) = Endpoint_Read_Byte();
383 case 2: *(DataStream++) = Endpoint_Read_Byte();
384 case 1: *(DataStream++) = Endpoint_Read_Byte();
385 } while (Length >= 8);
386 }
387 }
388 #endif
389
390 while (Length)
391 {
392 if (!(Endpoint_IsReadWriteAllowed()))
393 {
394 Endpoint_ClearOUT();
395
396 #if !defined(NO_STREAM_CALLBACKS)
397 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
398 return ENDPOINT_RWSTREAM_CallbackAborted;
399 #endif
400
401 if ((ErrorCode = Endpoint_WaitUntilReady()))
402 return ErrorCode;
403 }
404 else
405 {
406 *(DataStream++) = Endpoint_Read_Byte();
407 Length--;
408 }
409 }
410
411 return ENDPOINT_RWSTREAM_NoError;
412 }
413
414 uint8_t Endpoint_Read_Stream_BE(void* Buffer, uint16_t Length
415 #if !defined(NO_STREAM_CALLBACKS)
416 , StreamCallbackPtr_t Callback
417 #endif
418 )
419 {
420 uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1);
421 uint8_t ErrorCode;
422
423 if ((ErrorCode = Endpoint_WaitUntilReady()))
424 return ErrorCode;
425
426 #if defined(FAST_STREAM_TRANSFERS)
427 uint8_t BytesRemToAlignment = (Endpoint_BytesInEndpoint() & 0x07);
428
429 if (Length >= 8)
430 {
431 Length -= BytesRemToAlignment;
432
433 switch (BytesRemToAlignment)
434 {
435 default:
436 do
437 {
438 if (!(Endpoint_IsReadWriteAllowed()))
439 {
440 Endpoint_ClearOUT();
441
442 #if !defined(NO_STREAM_CALLBACKS)
443 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
444 return ENDPOINT_RWSTREAM_CallbackAborted;
445 #endif
446
447 if ((ErrorCode = Endpoint_WaitUntilReady()))
448 return ErrorCode;
449 }
450
451 Length -= 8;
452
453 *(DataStream--) = Endpoint_Read_Byte();
454 case 7: *(DataStream--) = Endpoint_Read_Byte();
455 case 6: *(DataStream--) = Endpoint_Read_Byte();
456 case 5: *(DataStream--) = Endpoint_Read_Byte();
457 case 4: *(DataStream--) = Endpoint_Read_Byte();
458 case 3: *(DataStream--) = Endpoint_Read_Byte();
459 case 2: *(DataStream--) = Endpoint_Read_Byte();
460 case 1: *(DataStream--) = Endpoint_Read_Byte();
461 } while (Length >= 8);
462 }
463 }
464 #endif
465
466 while (Length)
467 {
468 if (!(Endpoint_IsReadWriteAllowed()))
469 {
470 Endpoint_ClearOUT();
471
472 #if !defined(NO_STREAM_CALLBACKS)
473 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
474 return ENDPOINT_RWSTREAM_CallbackAborted;
475 #endif
476
477 if ((ErrorCode = Endpoint_WaitUntilReady()))
478 return ErrorCode;
479 }
480 else
481 {
482 *(DataStream--) = Endpoint_Read_Byte();
483 Length--;
484 }
485 }
486
487 return ENDPOINT_RWSTREAM_NoError;
488 }
489 #endif
490
491 uint8_t Endpoint_Write_Control_Stream_LE(const void* Buffer, uint16_t Length)
492 {
493 uint8_t* DataStream = (uint8_t*)Buffer;
494 bool LastPacketFull = false;
495
496 if (Length > USB_ControlRequest.wLength)
497 Length = USB_ControlRequest.wLength;
498
499 while (Length && !(Endpoint_IsOUTReceived()))
500 {
501 while (!(Endpoint_IsINReady()));
502
503 while (Length && (Endpoint_BytesInEndpoint() < USB_ControlEndpointSize))
504 {
505 Endpoint_Write_Byte(*(DataStream++));
506 Length--;
507 }
508
509 LastPacketFull = (Endpoint_BytesInEndpoint() == USB_ControlEndpointSize);
510 Endpoint_ClearIN();
511 }
512
513 if (Endpoint_IsOUTReceived())
514 return ENDPOINT_RWCSTREAM_HostAborted;
515
516 if (LastPacketFull)
517 {
518 while (!(Endpoint_IsINReady()));
519 Endpoint_ClearIN();
520 }
521
522 while (!(Endpoint_IsOUTReceived()));
523
524 return ENDPOINT_RWCSTREAM_NoError;
525 }
526
527 uint8_t Endpoint_Write_Control_Stream_BE(const void* Buffer, uint16_t Length)
528 {
529 uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1);
530 bool LastPacketFull = false;
531
532 if (Length > USB_ControlRequest.wLength)
533 Length = USB_ControlRequest.wLength;
534
535 while (Length && !(Endpoint_IsOUTReceived()))
536 {
537 if (Endpoint_IsINReady())
538 {
539 while (Length && (Endpoint_BytesInEndpoint() < USB_ControlEndpointSize))
540 {
541 Endpoint_Write_Byte(*(DataStream--));
542 Length--;
543 }
544
545 LastPacketFull = (Endpoint_BytesInEndpoint() == USB_ControlEndpointSize);
546 Endpoint_ClearIN();
547 }
548 }
549
550 if (Endpoint_IsOUTReceived())
551 return ENDPOINT_RWCSTREAM_HostAborted;
552
553 if (LastPacketFull)
554 {
555 while (!(Endpoint_IsINReady()));
556 Endpoint_ClearIN();
557 }
558
559 while (!(Endpoint_IsOUTReceived()));
560
561 return ENDPOINT_RWCSTREAM_NoError;
562 }
563
564 uint8_t Endpoint_Read_Control_Stream_LE(void* Buffer, uint16_t Length)
565 {
566 uint8_t* DataStream = (uint8_t*)Buffer;
567
568 while (Length)
569 {
570 if (Endpoint_IsOUTReceived())
571 {
572 while (Length && Endpoint_BytesInEndpoint())
573 {
574 *(DataStream++) = Endpoint_Read_Byte();
575 Length--;
576 }
577
578 Endpoint_ClearOUT();
579 }
580 }
581
582 while (!(Endpoint_IsINReady()));
583
584 return ENDPOINT_RWCSTREAM_NoError;
585 }
586
587 uint8_t Endpoint_Read_Control_Stream_BE(void* Buffer, uint16_t Length)
588 {
589 uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1);
590
591 while (Length)
592 {
593 if (Endpoint_IsOUTReceived())
594 {
595 while (Length && Endpoint_BytesInEndpoint())
596 {
597 *(DataStream--) = Endpoint_Read_Byte();
598 Length--;
599 }
600
601 Endpoint_ClearOUT();
602 }
603 }
604
605 while (!(Endpoint_IsINReady()));
606
607 return ENDPOINT_RWCSTREAM_NoError;
608 }
609
610 #endif