Move the length decrements in the pipe and endpoint stream functions to the point...
[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 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 Length--;
138 }
139 }
140
141 return ENDPOINT_RWSTREAM_ERROR_NoError;
142 }
143
144 uint8_t Endpoint_Write_Stream_LE(const void* Buffer, uint16_t Length
145 #if !defined(NO_STREAM_CALLBACKS)
146 , uint8_t (* const Callback)(void)
147 #endif
148 )
149 {
150 uint8_t* DataStream = (uint8_t*)Buffer;
151 uint8_t ErrorCode;
152
153 if ((ErrorCode = Endpoint_WaitUntilReady()))
154 return ErrorCode;
155
156 while (Length)
157 {
158 if (!(Endpoint_IsReadWriteAllowed()))
159 {
160 Endpoint_ClearIN();
161
162 #if !defined(NO_STREAM_CALLBACKS)
163 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
164 return ENDPOINT_RWSTREAM_ERROR_CallbackAborted;
165 #endif
166
167 if ((ErrorCode = Endpoint_WaitUntilReady()))
168 return ErrorCode;
169 }
170 else
171 {
172 Endpoint_Write_Byte(*(DataStream++));
173 Length--;
174 }
175 }
176
177 return ENDPOINT_RWSTREAM_ERROR_NoError;
178 }
179
180 uint8_t Endpoint_Write_Stream_BE(const void* Buffer, uint16_t Length
181 #if !defined(NO_STREAM_CALLBACKS)
182 , uint8_t (* const Callback)(void)
183 #endif
184 )
185 {
186 uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1);
187 uint8_t ErrorCode;
188
189 if ((ErrorCode = Endpoint_WaitUntilReady()))
190 return ErrorCode;
191
192 while (Length)
193 {
194 if (!(Endpoint_IsReadWriteAllowed()))
195 {
196 Endpoint_ClearIN();
197
198 #if !defined(NO_STREAM_CALLBACKS)
199 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
200 return ENDPOINT_RWSTREAM_ERROR_CallbackAborted;
201 #endif
202
203 if ((ErrorCode = Endpoint_WaitUntilReady()))
204 return ErrorCode;
205 }
206 else
207 {
208 Endpoint_Write_Byte(*(DataStream--));
209 Length--;
210 }
211 }
212
213 return ENDPOINT_RWSTREAM_ERROR_NoError;
214 }
215
216 uint8_t Endpoint_Read_Stream_LE(void* Buffer, uint16_t Length
217 #if !defined(NO_STREAM_CALLBACKS)
218 , uint8_t (* const Callback)(void)
219 #endif
220 )
221 {
222 uint8_t* DataStream = (uint8_t*)Buffer;
223 uint8_t ErrorCode;
224
225 if ((ErrorCode = Endpoint_WaitUntilReady()))
226 return ErrorCode;
227
228 while (Length)
229 {
230 if (!(Endpoint_IsReadWriteAllowed()))
231 {
232 Endpoint_ClearOUT();
233
234 #if !defined(NO_STREAM_CALLBACKS)
235 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
236 return ENDPOINT_RWSTREAM_ERROR_CallbackAborted;
237 #endif
238
239 if ((ErrorCode = Endpoint_WaitUntilReady()))
240 return ErrorCode;
241 }
242 else
243 {
244 *(DataStream++) = Endpoint_Read_Byte();
245 Length--;
246 }
247 }
248
249 return ENDPOINT_RWSTREAM_ERROR_NoError;
250 }
251
252 uint8_t Endpoint_Read_Stream_BE(void* Buffer, uint16_t Length
253 #if !defined(NO_STREAM_CALLBACKS)
254 , uint8_t (* const Callback)(void)
255 #endif
256 )
257 {
258 uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1);
259 uint8_t ErrorCode;
260
261 if ((ErrorCode = Endpoint_WaitUntilReady()))
262 return ErrorCode;
263
264 while (Length)
265 {
266 if (!(Endpoint_IsReadWriteAllowed()))
267 {
268 Endpoint_ClearOUT();
269
270 #if !defined(NO_STREAM_CALLBACKS)
271 if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
272 return ENDPOINT_RWSTREAM_ERROR_CallbackAborted;
273 #endif
274
275 if ((ErrorCode = Endpoint_WaitUntilReady()))
276 return ErrorCode;
277 }
278 else
279 {
280 *(DataStream--) = Endpoint_Read_Byte();
281 Length--;
282 }
283 }
284
285 return ENDPOINT_RWSTREAM_ERROR_NoError;
286 }
287 #endif
288
289 uint8_t Endpoint_Write_Control_Stream_LE(const void* Buffer, uint16_t Length)
290 {
291 uint8_t* DataStream = (uint8_t*)Buffer;
292 bool LastPacketFull = false;
293 bool ShortTransfer = (Length < USB_ControlRequest.wLength);
294
295 while (Length && !(Endpoint_IsOUTReceived()))
296 {
297 while (!(Endpoint_IsINReady()));
298
299 while (Length && (Endpoint_BytesInEndpoint() < USB_ControlEndpointSize))
300 {
301 Endpoint_Write_Byte(*(DataStream++));
302 Length--;
303 }
304
305 LastPacketFull = (Endpoint_BytesInEndpoint() == USB_ControlEndpointSize);
306 Endpoint_ClearIN();
307 }
308
309 if (Endpoint_IsOUTReceived())
310 return ENDPOINT_RWCSTREAM_ERROR_HostAborted;
311
312 if (LastPacketFull || ShortTransfer)
313 {
314 while (!(Endpoint_IsINReady()));
315 Endpoint_ClearIN();
316 }
317
318 while (!(Endpoint_IsOUTReceived()));
319
320 return ENDPOINT_RWCSTREAM_ERROR_NoError;
321 }
322
323 uint8_t Endpoint_Write_Control_Stream_BE(const void* Buffer, uint16_t Length)
324 {
325 uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1);
326 bool LastPacketFull = false;
327 bool ShortTransfer = (Length < USB_ControlRequest.wLength);
328
329 while (Length && !(Endpoint_IsOUTReceived()))
330 {
331 while (!(Endpoint_IsINReady()));
332
333 while (Length && (Endpoint_BytesInEndpoint() < USB_ControlEndpointSize))
334 {
335 Endpoint_Write_Byte(*(DataStream--));
336 Length--;
337 }
338
339 LastPacketFull = (Endpoint_BytesInEndpoint() == USB_ControlEndpointSize);
340 Endpoint_ClearIN();
341 }
342
343 if (Endpoint_IsOUTReceived())
344 return ENDPOINT_RWCSTREAM_ERROR_HostAborted;
345
346 if (LastPacketFull || ShortTransfer)
347 {
348 while (!(Endpoint_IsINReady()));
349 Endpoint_ClearIN();
350 }
351
352 while (!(Endpoint_IsOUTReceived()));
353
354 return ENDPOINT_RWCSTREAM_ERROR_NoError;
355 }
356
357 uint8_t Endpoint_Read_Control_Stream_LE(void* Buffer, uint16_t Length)
358 {
359 uint8_t* DataStream = (uint8_t*)Buffer;
360
361 while (Length)
362 {
363 while (!(Endpoint_IsOUTReceived()));
364
365 while (Length && Endpoint_BytesInEndpoint())
366 {
367 *(DataStream++) = Endpoint_Read_Byte();
368 Length--;
369 }
370
371 Endpoint_ClearOUT();
372 }
373
374 while (!(Endpoint_IsINReady()));
375
376 return ENDPOINT_RWCSTREAM_ERROR_NoError;
377 }
378
379 uint8_t Endpoint_Read_Control_Stream_BE(void* Buffer, uint16_t Length)
380 {
381 uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1);
382
383 while (Length)
384 {
385 while (!(Endpoint_IsOUTReceived()));
386
387 while (Length && Endpoint_BytesInEndpoint())
388 {
389 *(DataStream--) = Endpoint_Read_Byte();
390 Length--;
391 }
392
393 Endpoint_ClearOUT();
394 }
395
396 while (!(Endpoint_IsINReady()));
397
398 return ENDPOINT_RWCSTREAM_ERROR_NoError;
399 }
400
401 #endif