Added compatibility list to the documentation of each individual demo.
[pub/USBasp.git] / LUFA / Drivers / USB / LowLevel / Pipe.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_HOST)
34
35 #define INCLUDE_FROM_PIPE_C
36 #include "Pipe.h"
37
38 uint8_t USB_ControlPipeSize = PIPE_CONTROLPIPE_DEFAULT_SIZE;
39
40 bool Pipe_ConfigurePipe(const uint8_t Number, const uint8_t Type, const uint8_t Token, const uint8_t EndpointNumber,
41 const uint16_t Size, const uint8_t Banks)
42 {
43 Pipe_SelectPipe(Number);
44 Pipe_EnablePipe();
45
46 UPCFG1X = 0;
47
48 UPCFG0X = ((Type << EPTYPE0) | Token | ((EndpointNumber & PIPE_EPNUM_MASK) << PEPNUM0));
49 UPCFG1X = ((1 << ALLOC) | Banks | Pipe_BytesToEPSizeMask(Size));
50
51 Pipe_SetInfiniteINRequests();
52
53 return Pipe_IsConfigured();
54 }
55
56 void Pipe_ClearPipes(void)
57 {
58 UPINT = 0;
59
60 for (uint8_t PNum = 0; PNum < PIPE_TOTAL_PIPES; PNum++)
61 {
62 Pipe_ResetPipe(PNum);
63 Pipe_SelectPipe(PNum);
64 UPIENX = 0;
65 UPINTX = 0;
66 Pipe_ClearError();
67 Pipe_ClearErrorFlags();
68 Pipe_DeallocateMemory();
69 Pipe_DisablePipe();
70 }
71 }
72
73 uint8_t Pipe_WaitUntilReady(void)
74 {
75 #if (USB_STREAM_TIMEOUT_MS < 0xFF)
76 uint8_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
77 #else
78 uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
79 #endif
80
81 for (;;)
82 {
83 if (Pipe_GetPipeToken() == PIPE_TOKEN_IN)
84 {
85 if (Pipe_IsINReceived())
86 return PIPE_READYWAIT_NoError;
87 }
88 else
89 {
90 if (Pipe_IsOUTReady())
91 return PIPE_READYWAIT_NoError;
92 }
93
94 if (Pipe_IsStalled())
95 return PIPE_READYWAIT_PipeStalled;
96 else if (!(USB_IsConnected))
97 return PIPE_READYWAIT_DeviceDisconnected;
98
99 if (USB_INT_HasOccurred(USB_INT_HSOFI))
100 {
101 USB_INT_Clear(USB_INT_HSOFI);
102
103 if (!(TimeoutMSRem--))
104 return PIPE_READYWAIT_Timeout;
105 }
106 }
107 }
108
109 uint8_t Pipe_Write_Stream_LE(const void* Data, uint16_t Length
110 #if !defined(NO_STREAM_CALLBACKS)
111 , StreamCallbackPtr_t Callback
112 #endif
113 )
114 {
115 uint8_t* DataStream = (uint8_t*)Data;
116 uint8_t ErrorCode;
117
118 Pipe_SetToken(PIPE_TOKEN_OUT);
119
120 if ((ErrorCode = Pipe_WaitUntilReady()))
121 return ErrorCode;
122
123 #if defined(FAST_STREAM_TRANSFERS)
124 uint8_t BytesRemToAlignment = (Pipe_BytesInPipe() & 0x07);
125
126 if (Length >= 8)
127 {
128 Length -= BytesRemToAlignment;
129
130 switch (BytesRemToAlignment)
131 {
132 default:
133 do
134 {
135 if (!(Pipe_IsReadWriteAllowed()))
136 {
137 Pipe_ClearOUT();
138
139 #if !defined(NO_STREAM_CALLBACKS)
140 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
141 return PIPE_RWSTREAM_CallbackAborted;
142 #endif
143
144 if ((ErrorCode = Pipe_WaitUntilReady()))
145 return ErrorCode;
146 }
147
148 Length -= 8;
149
150 Pipe_Write_Byte(*(DataStream++));
151 case 7: Pipe_Write_Byte(*(DataStream++));
152 case 6: Pipe_Write_Byte(*(DataStream++));
153 case 5: Pipe_Write_Byte(*(DataStream++));
154 case 4: Pipe_Write_Byte(*(DataStream++));
155 case 3: Pipe_Write_Byte(*(DataStream++));
156 case 2: Pipe_Write_Byte(*(DataStream++));
157 case 1: Pipe_Write_Byte(*(DataStream++));
158 } while (Length >= 8);
159 }
160 }
161 #endif
162
163 while (Length)
164 {
165 if (!(Pipe_IsReadWriteAllowed()))
166 {
167 Pipe_ClearOUT();
168
169 #if !defined(NO_STREAM_CALLBACKS)
170 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
171 return PIPE_RWSTREAM_CallbackAborted;
172 #endif
173
174 if ((ErrorCode = Pipe_WaitUntilReady()))
175 return ErrorCode;
176 }
177 else
178 {
179 Pipe_Write_Byte(*(DataStream++));
180 Length--;
181 }
182 }
183
184 return PIPE_RWSTREAM_NoError;
185 }
186
187 uint8_t Pipe_Write_Stream_BE(const void* Data, uint16_t Length
188 #if !defined(NO_STREAM_CALLBACKS)
189 , StreamCallbackPtr_t Callback
190 #endif
191 )
192 {
193 uint8_t* DataStream = (uint8_t*)(Data + Length - 1);
194 uint8_t ErrorCode;
195
196 Pipe_SetToken(PIPE_TOKEN_OUT);
197
198 if ((ErrorCode = Pipe_WaitUntilReady()))
199 return ErrorCode;
200
201 #if defined(FAST_STREAM_TRANSFERS)
202 uint8_t BytesRemToAlignment = (Pipe_BytesInPipe() & 0x07);
203
204 if (Length >= 8)
205 {
206 Length -= BytesRemToAlignment;
207
208 switch (BytesRemToAlignment)
209 {
210 default:
211 do
212 {
213 if (!(Pipe_IsReadWriteAllowed()))
214 {
215 Pipe_ClearOUT();
216
217 #if !defined(NO_STREAM_CALLBACKS)
218 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
219 return PIPE_RWSTREAM_CallbackAborted;
220 #endif
221
222 if ((ErrorCode = Pipe_WaitUntilReady()))
223 return ErrorCode;
224 }
225
226 Length -= 8;
227
228 Pipe_Write_Byte(*(DataStream--));
229 case 7: Pipe_Write_Byte(*(DataStream--));
230 case 6: Pipe_Write_Byte(*(DataStream--));
231 case 5: Pipe_Write_Byte(*(DataStream--));
232 case 4: Pipe_Write_Byte(*(DataStream--));
233 case 3: Pipe_Write_Byte(*(DataStream--));
234 case 2: Pipe_Write_Byte(*(DataStream--));
235 case 1: Pipe_Write_Byte(*(DataStream--));
236 } while (Length >= 8);
237 }
238 }
239 #endif
240
241 while (Length)
242 {
243 if (!(Pipe_IsReadWriteAllowed()))
244 {
245 Pipe_ClearOUT();
246
247 #if !defined(NO_STREAM_CALLBACKS)
248 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
249 return PIPE_RWSTREAM_CallbackAborted;
250 #endif
251
252 if ((ErrorCode = Pipe_WaitUntilReady()))
253 return ErrorCode;
254 }
255 else
256 {
257 Pipe_Write_Byte(*(DataStream--));
258 Length--;
259 }
260 }
261
262 return PIPE_RWSTREAM_NoError;
263 }
264
265 uint8_t Pipe_Discard_Stream(uint16_t Length
266 #if !defined(NO_STREAM_CALLBACKS)
267 , StreamCallbackPtr_t Callback
268 #endif
269 )
270 {
271 uint8_t ErrorCode;
272
273 Pipe_SetToken(PIPE_TOKEN_IN);
274
275 if ((ErrorCode = Pipe_WaitUntilReady()))
276 return ErrorCode;
277
278 #if defined(FAST_STREAM_TRANSFERS)
279 uint8_t BytesRemToAlignment = (Pipe_BytesInPipe() & 0x07);
280
281 if (Length >= 8)
282 {
283 Length -= BytesRemToAlignment;
284
285 switch (BytesRemToAlignment)
286 {
287 default:
288 do
289 {
290 if (!(Pipe_IsReadWriteAllowed()))
291 {
292 Pipe_ClearIN();
293
294 #if !defined(NO_STREAM_CALLBACKS)
295 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
296 return PIPE_RWSTREAM_CallbackAborted;
297 #endif
298
299 if ((ErrorCode = Pipe_WaitUntilReady()))
300 return ErrorCode;
301 }
302
303 Length -= 8;
304
305 Pipe_Discard_Byte();
306 case 7: Pipe_Discard_Byte();
307 case 6: Pipe_Discard_Byte();
308 case 5: Pipe_Discard_Byte();
309 case 4: Pipe_Discard_Byte();
310 case 3: Pipe_Discard_Byte();
311 case 2: Pipe_Discard_Byte();
312 case 1: Pipe_Discard_Byte();
313 } while (Length >= 8);
314 }
315 }
316 #endif
317
318 while (Length)
319 {
320 if (!(Pipe_IsReadWriteAllowed()))
321 {
322 Pipe_ClearIN();
323
324 #if !defined(NO_STREAM_CALLBACKS)
325 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
326 return PIPE_RWSTREAM_CallbackAborted;
327 #endif
328
329 if ((ErrorCode = Pipe_WaitUntilReady()))
330 return ErrorCode;
331 }
332 else
333 {
334 Pipe_Discard_Byte();
335 Length--;
336 }
337 }
338
339 return PIPE_RWSTREAM_NoError;
340 }
341
342 uint8_t Pipe_Read_Stream_LE(void* Buffer, uint16_t Length
343 #if !defined(NO_STREAM_CALLBACKS)
344 , StreamCallbackPtr_t Callback
345 #endif
346 )
347 {
348 uint8_t* DataStream = (uint8_t*)Buffer;
349 uint8_t ErrorCode;
350
351 Pipe_SetToken(PIPE_TOKEN_IN);
352
353 if ((ErrorCode = Pipe_WaitUntilReady()))
354 return ErrorCode;
355
356 #if defined(FAST_STREAM_TRANSFERS)
357 uint8_t BytesRemToAlignment = (Pipe_BytesInPipe() & 0x07);
358
359 if (Length >= 8)
360 {
361 Length -= BytesRemToAlignment;
362
363 switch (BytesRemToAlignment)
364 {
365 default:
366 do
367 {
368 if (!(Pipe_IsReadWriteAllowed()))
369 {
370 Pipe_ClearIN();
371
372 #if !defined(NO_STREAM_CALLBACKS)
373 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
374 return PIPE_RWSTREAM_CallbackAborted;
375 #endif
376
377 if ((ErrorCode = Pipe_WaitUntilReady()))
378 return ErrorCode;
379 }
380
381 Length -= 8;
382
383 *(DataStream++) = Pipe_Read_Byte();
384 case 7: *(DataStream++) = Pipe_Read_Byte();
385 case 6: *(DataStream++) = Pipe_Read_Byte();
386 case 5: *(DataStream++) = Pipe_Read_Byte();
387 case 4: *(DataStream++) = Pipe_Read_Byte();
388 case 3: *(DataStream++) = Pipe_Read_Byte();
389 case 2: *(DataStream++) = Pipe_Read_Byte();
390 case 1: *(DataStream++) = Pipe_Read_Byte();
391 } while (Length >= 8);
392 }
393 }
394 #endif
395
396 while (Length)
397 {
398 if (!(Pipe_IsReadWriteAllowed()))
399 {
400 Pipe_ClearIN();
401
402 #if !defined(NO_STREAM_CALLBACKS)
403 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
404 return PIPE_RWSTREAM_CallbackAborted;
405 #endif
406
407 if ((ErrorCode = Pipe_WaitUntilReady()))
408 return ErrorCode;
409 }
410 else
411 {
412 *(DataStream++) = Pipe_Read_Byte();
413 Length--;
414 }
415 }
416
417 return PIPE_RWSTREAM_NoError;
418 }
419
420 uint8_t Pipe_Read_Stream_BE(void* Buffer, uint16_t Length
421 #if !defined(NO_STREAM_CALLBACKS)
422 , StreamCallbackPtr_t Callback
423 #endif
424 )
425 {
426 uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1);
427 uint8_t ErrorCode;
428
429 Pipe_SetToken(PIPE_TOKEN_IN);
430
431 if ((ErrorCode = Pipe_WaitUntilReady()))
432 return ErrorCode;
433
434 #if defined(FAST_STREAM_TRANSFERS)
435 uint8_t BytesRemToAlignment = (Pipe_BytesInPipe() & 0x07);
436
437 if (Length >= 8)
438 {
439 Length -= BytesRemToAlignment;
440
441 switch (BytesRemToAlignment)
442 {
443 default:
444 do
445 {
446 if (!(Pipe_IsReadWriteAllowed()))
447 {
448 Pipe_ClearIN();
449
450 #if !defined(NO_STREAM_CALLBACKS)
451 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
452 return PIPE_RWSTREAM_CallbackAborted;
453 #endif
454
455 if ((ErrorCode = Pipe_WaitUntilReady()))
456 return ErrorCode;
457 }
458
459 Length -= 8;
460
461 *(DataStream--) = Pipe_Read_Byte();
462 case 7: *(DataStream--) = Pipe_Read_Byte();
463 case 6: *(DataStream--) = Pipe_Read_Byte();
464 case 5: *(DataStream--) = Pipe_Read_Byte();
465 case 4: *(DataStream--) = Pipe_Read_Byte();
466 case 3: *(DataStream--) = Pipe_Read_Byte();
467 case 2: *(DataStream--) = Pipe_Read_Byte();
468 case 1: *(DataStream--) = Pipe_Read_Byte();
469 } while (Length >= 8);
470 }
471 }
472 #endif
473
474 while (Length)
475 {
476 if (!(Pipe_IsReadWriteAllowed()))
477 {
478 Pipe_ClearIN();
479
480 #if !defined(NO_STREAM_CALLBACKS)
481 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
482 return PIPE_RWSTREAM_CallbackAborted;
483 #endif
484
485 if ((ErrorCode = Pipe_WaitUntilReady()))
486 return ErrorCode;
487 }
488 else
489 {
490 *(DataStream--) = Pipe_Read_Byte();
491 Length--;
492 }
493 }
494
495 return PIPE_RWSTREAM_NoError;
496 }
497
498 #endif