Pipe_ConfigurePipe() now automatically defaults IN pipes to accepting infinite IN...
[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 if (Token == PIPE_TOKEN_IN)
52 Pipe_SetInfiniteINRequests();
53
54 return Pipe_IsConfigured();
55 }
56
57 void Pipe_ClearPipes(void)
58 {
59 UPINT = 0;
60
61 for (uint8_t PNum = 0; PNum < PIPE_TOTAL_PIPES; PNum++)
62 {
63 Pipe_ResetPipe(PNum);
64 Pipe_SelectPipe(PNum);
65 UPIENX = 0;
66 UPINTX = 0;
67 Pipe_ClearError();
68 Pipe_ClearErrorFlags();
69 Pipe_DeallocateMemory();
70 Pipe_DisablePipe();
71 }
72 }
73
74 uint8_t Pipe_WaitUntilReady(void)
75 {
76 #if (USB_STREAM_TIMEOUT_MS < 0xFF)
77 uint8_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
78 #else
79 uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
80 #endif
81
82 for (;;)
83 {
84 if (Pipe_GetPipeToken() == PIPE_TOKEN_IN)
85 {
86 if (Pipe_IsINReceived())
87 return PIPE_READYWAIT_NoError;
88 }
89 else
90 {
91 if (Pipe_IsOUTReady())
92 return PIPE_READYWAIT_NoError;
93 }
94
95 if (Pipe_IsStalled())
96 return PIPE_READYWAIT_PipeStalled;
97 else if (!(USB_IsConnected))
98 return PIPE_READYWAIT_DeviceDisconnected;
99
100 if (USB_INT_HasOccurred(USB_INT_HSOFI))
101 {
102 USB_INT_Clear(USB_INT_HSOFI);
103
104 if (!(TimeoutMSRem--))
105 return PIPE_READYWAIT_Timeout;
106 }
107 }
108 }
109
110 uint8_t Pipe_Write_Stream_LE(const void* Data, uint16_t Length
111 #if !defined(NO_STREAM_CALLBACKS)
112 , StreamCallbackPtr_t Callback
113 #endif
114 )
115 {
116 uint8_t* DataStream = (uint8_t*)Data;
117 uint8_t ErrorCode;
118
119 Pipe_SetToken(PIPE_TOKEN_OUT);
120
121 if ((ErrorCode = Pipe_WaitUntilReady()))
122 return ErrorCode;
123
124 while (Length)
125 {
126 if (!(Pipe_IsReadWriteAllowed()))
127 {
128 Pipe_ClearOUT();
129
130 #if !defined(NO_STREAM_CALLBACKS)
131 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
132 return PIPE_RWSTREAM_CallbackAborted;
133 #endif
134
135 if ((ErrorCode = Pipe_WaitUntilReady()))
136 return ErrorCode;
137 }
138 else
139 {
140 Pipe_Write_Byte(*(DataStream++));
141 Length--;
142 }
143 }
144
145 return PIPE_RWSTREAM_NoError;
146 }
147
148 uint8_t Pipe_Write_Stream_BE(const void* Data, uint16_t Length
149 #if !defined(NO_STREAM_CALLBACKS)
150 , StreamCallbackPtr_t Callback
151 #endif
152 )
153 {
154 uint8_t* DataStream = (uint8_t*)(Data + Length - 1);
155 uint8_t ErrorCode;
156
157 Pipe_SetToken(PIPE_TOKEN_OUT);
158
159 if ((ErrorCode = Pipe_WaitUntilReady()))
160 return ErrorCode;
161
162 while (Length)
163 {
164 if (!(Pipe_IsReadWriteAllowed()))
165 {
166 Pipe_ClearOUT();
167
168 #if !defined(NO_STREAM_CALLBACKS)
169 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
170 return PIPE_RWSTREAM_CallbackAborted;
171 #endif
172
173 if ((ErrorCode = Pipe_WaitUntilReady()))
174 return ErrorCode;
175 }
176 else
177 {
178 Pipe_Write_Byte(*(DataStream--));
179 Length--;
180 }
181 }
182
183 return PIPE_RWSTREAM_NoError;
184 }
185
186 uint8_t Pipe_Discard_Stream(uint16_t Length
187 #if !defined(NO_STREAM_CALLBACKS)
188 , StreamCallbackPtr_t Callback
189 #endif
190 )
191 {
192 uint8_t ErrorCode;
193
194 Pipe_SetToken(PIPE_TOKEN_IN);
195
196 if ((ErrorCode = Pipe_WaitUntilReady()))
197 return ErrorCode;
198
199 while (Length)
200 {
201 if (!(Pipe_IsReadWriteAllowed()))
202 {
203 Pipe_ClearIN();
204
205 #if !defined(NO_STREAM_CALLBACKS)
206 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
207 return PIPE_RWSTREAM_CallbackAborted;
208 #endif
209
210 if ((ErrorCode = Pipe_WaitUntilReady()))
211 return ErrorCode;
212 }
213 else
214 {
215 Pipe_Discard_Byte();
216 Length--;
217 }
218 }
219
220 return PIPE_RWSTREAM_NoError;
221 }
222
223 uint8_t Pipe_Read_Stream_LE(void* Buffer, uint16_t Length
224 #if !defined(NO_STREAM_CALLBACKS)
225 , StreamCallbackPtr_t Callback
226 #endif
227 )
228 {
229 uint8_t* DataStream = (uint8_t*)Buffer;
230 uint8_t ErrorCode;
231
232 Pipe_SetToken(PIPE_TOKEN_IN);
233
234 if ((ErrorCode = Pipe_WaitUntilReady()))
235 return ErrorCode;
236
237 while (Length)
238 {
239 if (!(Pipe_IsReadWriteAllowed()))
240 {
241 Pipe_ClearIN();
242
243 #if !defined(NO_STREAM_CALLBACKS)
244 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
245 return PIPE_RWSTREAM_CallbackAborted;
246 #endif
247
248 if ((ErrorCode = Pipe_WaitUntilReady()))
249 return ErrorCode;
250 }
251 else
252 {
253 *(DataStream++) = Pipe_Read_Byte();
254 Length--;
255 }
256 }
257
258 return PIPE_RWSTREAM_NoError;
259 }
260
261 uint8_t Pipe_Read_Stream_BE(void* Buffer, uint16_t Length
262 #if !defined(NO_STREAM_CALLBACKS)
263 , StreamCallbackPtr_t Callback
264 #endif
265 )
266 {
267 uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1);
268 uint8_t ErrorCode;
269
270 Pipe_SetToken(PIPE_TOKEN_IN);
271
272 if ((ErrorCode = Pipe_WaitUntilReady()))
273 return ErrorCode;
274
275 while (Length)
276 {
277 if (!(Pipe_IsReadWriteAllowed()))
278 {
279 Pipe_ClearIN();
280
281 #if !defined(NO_STREAM_CALLBACKS)
282 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
283 return PIPE_RWSTREAM_CallbackAborted;
284 #endif
285
286 if ((ErrorCode = Pipe_WaitUntilReady()))
287 return ErrorCode;
288 }
289 else
290 {
291 *(DataStream--) = Pipe_Read_Byte();
292 Length--;
293 }
294 }
295
296 return PIPE_RWSTREAM_NoError;
297 }
298
299 #endif