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