Pipe.c 9.95 KB
Newer Older
1
2
/*
             LUFA Library
Dean Camera's avatar
Dean Camera committed
3
     Copyright (C) Dean Camera, 2010.
4
5
6
7
8
9
              
  dean [at] fourwalledcubicle [dot] com
      www.fourwalledcubicle.com
*/

/*
Dean Camera's avatar
Dean Camera committed
10
  Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com)
11

12
13
14
15
16
17
18
  Permission to use, copy, modify, distribute, and sell this 
  software and its documentation for any purpose is hereby granted
  without fee, provided that the above copyright notice appear in 
  all copies and that both that the copyright notice and this
  permission notice and warranty disclaimer appear in supporting 
  documentation, and that the name of the author not be used in 
  advertising or publicity pertaining to distribution of the 
19
20
21
22
23
24
25
26
27
28
29
  software without specific, written prior permission.

  The author disclaim all warranties with regard to this
  software, including all implied warranties of merchantability
  and fitness.  In no event shall the author be liable for any
  special, indirect or consequential damages or any damages
  whatsoever resulting from loss of use, data or profits, whether
  in an action of contract, negligence or other tortious action,
  arising out of or in connection with the use or performance of
  this software.
*/
30

31
#define  __INCLUDE_FROM_USB_DRIVER
32
33
#include "../HighLevel/USBMode.h"

34
35
#if defined(USB_CAN_BE_HOST)

36
#define  __INCLUDE_FROM_PIPE_C
37
38
39
40
#include "Pipe.h"

uint8_t USB_ControlPipeSize = PIPE_CONTROLPIPE_DEFAULT_SIZE;

41
bool Pipe_ConfigurePipe(const uint8_t Number, const uint8_t Type, const uint8_t Token, const uint8_t EndpointNumber,
42
43
44
45
46
47
48
						const uint16_t Size, const uint8_t Banks)
{
	Pipe_SelectPipe(Number);
	Pipe_EnablePipe();

	UPCFG1X = 0;
	
49
	UPCFG0X = ((Type << EPTYPE0) | Token | ((EndpointNumber & PIPE_EPNUM_MASK) << PEPNUM0));
50
51
	UPCFG1X = ((1 << ALLOC) | Banks | Pipe_BytesToEPSizeMask(Size));

52
	Pipe_SetInfiniteINRequests();
53

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
	return Pipe_IsConfigured();
}

void Pipe_ClearPipes(void)
{
	UPINT = 0;

	for (uint8_t PNum = 0; PNum < PIPE_TOTAL_PIPES; PNum++)
	{
		Pipe_ResetPipe(PNum);
		Pipe_SelectPipe(PNum);
		UPIENX = 0;
		UPINTX = 0;
		Pipe_ClearError();
		Pipe_ClearErrorFlags();
		Pipe_DeallocateMemory();
		Pipe_DisablePipe();
	}
}

74
bool Pipe_IsEndpointBound(const uint8_t EndpointAddress)
75
{
76
	uint8_t PrevPipeNumber = Pipe_GetCurrentPipe();
77
78
79
80
81

	for (uint8_t PNum = 0; PNum < PIPE_TOTAL_PIPES; PNum++)
	{
		Pipe_SelectPipe(PNum);
		
82
		uint8_t PipeToken = Pipe_GetPipeToken();
83
		bool    PipeTokenCorrect = true;
84
85

		if (PipeToken != PIPE_TOKEN_SETUP)
86
		  PipeTokenCorrect = (PipeToken == ((EndpointAddress & PIPE_EPDIR_MASK) ? PIPE_TOKEN_IN : PIPE_TOKEN_OUT));
87
		
88
89
		if (Pipe_IsConfigured() && PipeTokenCorrect && (Pipe_BoundEndpointNumber() == (EndpointAddress & PIPE_EPNUM_MASK)))
		  return true;
90
91
92
93
94
95
	}
	
	Pipe_SelectPipe(PrevPipeNumber);
	return false;
}

96
97
uint8_t Pipe_WaitUntilReady(void)
{
98
99
100
	#if (USB_STREAM_TIMEOUT_MS < 0xFF)
	uint8_t  TimeoutMSRem = USB_STREAM_TIMEOUT_MS;	
	#else
101
	uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
102
	#endif
103
	
104
	for (;;)
105
	{
106
107
108
109
110
111
112
113
114
115
116
		if (Pipe_GetPipeToken() == PIPE_TOKEN_IN)
		{
			if (Pipe_IsINReceived())
			  return PIPE_READYWAIT_NoError;
		}
		else
		{
			if (Pipe_IsOUTReady())
			  return PIPE_READYWAIT_NoError;		
		}

117
118
		if (Pipe_IsStalled())
		  return PIPE_READYWAIT_PipeStalled;
119
		else if (USB_HostState == HOST_STATE_Unattached)
120
121
		  return PIPE_READYWAIT_DeviceDisconnected;
			  
122
		if (USB_INT_HasOccurred(USB_INT_HSOFI))
123
		{
124
			USB_INT_Clear(USB_INT_HSOFI);
125
126
127
128
129
130
131
132
133

			if (!(TimeoutMSRem--))
			  return PIPE_READYWAIT_Timeout;
		}
	}
}

uint8_t Pipe_Discard_Stream(uint16_t Length
#if !defined(NO_STREAM_CALLBACKS)
134
                                 , StreamCallbackPtr_t Callback
135
136
137
138
139
#endif
								 )
{
	uint8_t  ErrorCode;
	
140
	Pipe_SetPipeToken(PIPE_TOKEN_IN);
141

142
143
144
	if ((ErrorCode = Pipe_WaitUntilReady()))
	  return ErrorCode;

145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
	#if defined(FAST_STREAM_TRANSFERS)
	uint8_t BytesRemToAlignment = (Pipe_BytesInPipe() & 0x07);

	if (Length >= 8)
	{
		Length -= BytesRemToAlignment;

		switch (BytesRemToAlignment)
		{
			default:
				do
				{
					if (!(Pipe_IsReadWriteAllowed()))
					{
						Pipe_ClearIN();
							
						#if !defined(NO_STREAM_CALLBACKS)
						if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
						  return PIPE_RWSTREAM_CallbackAborted;
						#endif

						if ((ErrorCode = Pipe_WaitUntilReady()))
						  return ErrorCode;
					}

					Length -= 8;
					
					Pipe_Discard_Byte();
			case 7: Pipe_Discard_Byte();
			case 6: Pipe_Discard_Byte();
			case 5: Pipe_Discard_Byte();
			case 4: Pipe_Discard_Byte();
			case 3: Pipe_Discard_Byte();
			case 2: Pipe_Discard_Byte();
			case 1:	Pipe_Discard_Byte();
				} while (Length >= 8);	
		}
	}
	#endif

185
	while (Length)
186
	{
187
		if (!(Pipe_IsReadWriteAllowed()))
188
		{
189
			Pipe_ClearIN();
190
191
192
				
			#if !defined(NO_STREAM_CALLBACKS)
			if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
193
			  return PIPE_RWSTREAM_CallbackAborted;
194
195
196
197
198
			#endif

			if ((ErrorCode = Pipe_WaitUntilReady()))
			  return ErrorCode;
		}
199
200
201
		else
		{
			Pipe_Discard_Byte();
202
			Length--;
203
		}
204
205
	}

206
	return PIPE_RWSTREAM_NoError;
207
208
}

209
210
211
/* The following abuses the C preprocessor in order to copy-past common code with slight alterations,
 * so that the code needs to be written once. It is a crude form of templating to reduce code maintenance. */

212
#define  TEMPLATE_FUNC_NAME                        Pipe_Write_Stream_LE
213
#define  TEMPLATE_BUFFER_TYPE                      const void*
214
#define  TEMPLATE_TOKEN                            PIPE_TOKEN_OUT
215
216
#define  TEMPLATE_CLEAR_PIPE()                     Pipe_ClearOUT()
#define  TEMPLATE_BUFFER_OFFSET(Length)            0
217
#define  TEMPLATE_TRANSFER_BYTE(BufferPtr)         Pipe_Write_Byte(*((uint8_t*)BufferPtr++))
218
219
220
#include "Template/Template_Pipe_RW.c"

#define  TEMPLATE_FUNC_NAME                        Pipe_Write_PStream_LE
221
#define  TEMPLATE_BUFFER_TYPE                      const void*
222
#define  TEMPLATE_TOKEN                            PIPE_TOKEN_OUT
223
224
#define  TEMPLATE_CLEAR_PIPE()                     Pipe_ClearOUT()
#define  TEMPLATE_BUFFER_OFFSET(Length)            0
225
#define  TEMPLATE_TRANSFER_BYTE(BufferPtr)         Pipe_Write_Byte(pgm_read_byte((uint8_t*)BufferPtr++))
226
227
#include "Template/Template_Pipe_RW.c"

228
229
230
231
232
233
234
#define  TEMPLATE_FUNC_NAME                        Pipe_Write_EStream_LE
#define  TEMPLATE_BUFFER_TYPE                      const void*
#define  TEMPLATE_TOKEN                            PIPE_TOKEN_OUT
#define  TEMPLATE_CLEAR_PIPE()                     Pipe_ClearOUT()
#define  TEMPLATE_BUFFER_OFFSET(Length)            0
#define  TEMPLATE_TRANSFER_BYTE(BufferPtr)         Pipe_Write_Byte(eeprom_read_byte((uint8_t*)BufferPtr++))
#include "Template/Template_Pipe_RW.c"
235
236

#define  TEMPLATE_FUNC_NAME                        Pipe_Write_Stream_BE
237
#define  TEMPLATE_BUFFER_TYPE                      const void*
238
#define  TEMPLATE_TOKEN                            PIPE_TOKEN_OUT
239
#define  TEMPLATE_CLEAR_PIPE()                     Pipe_ClearOUT()
240
#define  TEMPLATE_BUFFER_OFFSET(Length)            (Length - 1)
241
#define  TEMPLATE_TRANSFER_BYTE(BufferPtr)         Pipe_Write_Byte(*((uint8_t*)BufferPtr--))
242
243
244
#include "Template/Template_Pipe_RW.c"

#define  TEMPLATE_FUNC_NAME                        Pipe_Write_PStream_BE
245
#define  TEMPLATE_BUFFER_TYPE                      const void*
246
#define  TEMPLATE_TOKEN                            PIPE_TOKEN_OUT
247
#define  TEMPLATE_CLEAR_PIPE()                     Pipe_ClearOUT()
248
#define  TEMPLATE_BUFFER_OFFSET(Length)            (Length - 1)
249
#define  TEMPLATE_TRANSFER_BYTE(BufferPtr)         Pipe_Write_Byte(pgm_read_byte((uint8_t*)BufferPtr--))
250
251
#include "Template/Template_Pipe_RW.c"

252
253
254
255
256
257
258
#define  TEMPLATE_FUNC_NAME                        Pipe_Write_EStream_BE
#define  TEMPLATE_BUFFER_TYPE                      const void*
#define  TEMPLATE_TOKEN                            PIPE_TOKEN_OUT
#define  TEMPLATE_CLEAR_PIPE()                     Pipe_ClearOUT()
#define  TEMPLATE_BUFFER_OFFSET(Length)            (Length - 1)
#define  TEMPLATE_TRANSFER_BYTE(BufferPtr)         Pipe_Write_Byte(eeprom_read_byte((uint8_t*)BufferPtr--))
#include "Template/Template_Pipe_RW.c"
259
260

#define  TEMPLATE_FUNC_NAME                        Pipe_Read_Stream_LE
261
#define  TEMPLATE_BUFFER_TYPE                      void*
262
#define  TEMPLATE_TOKEN                            PIPE_TOKEN_IN
263
264
#define  TEMPLATE_CLEAR_PIPE()                     Pipe_ClearIN()
#define  TEMPLATE_BUFFER_OFFSET(Length)            0
265
#define  TEMPLATE_TRANSFER_BYTE(BufferPtr)         *((uint8_t*)BufferPtr++) = Pipe_Read_Byte()
266
267
#include "Template/Template_Pipe_RW.c"

268
269
270
271
272
273
274
#define  TEMPLATE_FUNC_NAME                        Pipe_Read_EStream_LE
#define  TEMPLATE_BUFFER_TYPE                      void*
#define  TEMPLATE_TOKEN                            PIPE_TOKEN_IN
#define  TEMPLATE_CLEAR_PIPE()                     Pipe_ClearIN()
#define  TEMPLATE_BUFFER_OFFSET(Length)            0
#define  TEMPLATE_TRANSFER_BYTE(BufferPtr)         eeprom_write_byte((uint8_t*)BufferPtr++, Pipe_Read_Byte())
#include "Template/Template_Pipe_RW.c"
275
276

#define  TEMPLATE_FUNC_NAME                        Pipe_Read_Stream_BE
277
#define  TEMPLATE_BUFFER_TYPE                      void*
278
#define  TEMPLATE_TOKEN                            PIPE_TOKEN_IN
279
#define  TEMPLATE_CLEAR_PIPE()                     Pipe_ClearIN()
280
#define  TEMPLATE_BUFFER_OFFSET(Length)            (Length - 1)
281
#define  TEMPLATE_TRANSFER_BYTE(BufferPtr)         *((uint8_t*)BufferPtr--) = Pipe_Read_Byte()
282
283
#include "Template/Template_Pipe_RW.c"

284
285
286
287
288
289
290
#define  TEMPLATE_FUNC_NAME                        Pipe_Read_EStream_BE
#define  TEMPLATE_BUFFER_TYPE                      void*
#define  TEMPLATE_TOKEN                            PIPE_TOKEN_IN
#define  TEMPLATE_CLEAR_PIPE()                     Pipe_ClearIN()
#define  TEMPLATE_BUFFER_OFFSET(Length)            (Length - 1)
#define  TEMPLATE_TRANSFER_BYTE(BufferPtr)         eeprom_write_byte((uint8_t*)BufferPtr--, Pipe_Read_Byte())
#include "Template/Template_Pipe_RW.c"
291
292

#endif