DevChapter9.c 8.14 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
             LUFA Library
     Copyright (C) Dean Camera, 2009.
              
  dean [at] fourwalledcubicle [dot] com
      www.fourwalledcubicle.com
*/

/*
  Copyright 2009  Dean Camera (dean [at] fourwalledcubicle [dot] com)

  Permission to use, copy, modify, and distribute this software
  and its documentation for any purpose and without fee is hereby
  granted, 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
  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.
*/

31
32
#include "../HighLevel/USBMode.h"

33
34
35
36
37
38
39
40
41
42
43
#if defined(USB_CAN_BE_DEVICE)

#define  INCLUDE_FROM_DEVCHAPTER9_C
#include "DevChapter9.h"

uint8_t USB_ConfigurationNumber;
bool    USB_RemoteWakeupEnabled;
bool    USB_CurrentlySelfPowered;

void USB_Device_ProcessControlPacket(void)
{
44
45
	bool     RequestHandled = false;
	uint8_t* RequestHeader  = (uint8_t*)&USB_ControlRequest;
46
	
47
48
	for (uint8_t RequestHeaderByte = 0; RequestHeaderByte < sizeof(USB_Request_Header_t); RequestHeaderByte++)
	  *(RequestHeader++) = Endpoint_Read_Byte();
49
50
	  
	uint8_t bmRequestType = USB_ControlRequest.bmRequestType;
51
52
	
	switch (USB_ControlRequest.bRequest)
53
54
	{
		case REQ_GetStatus:
55
56
			if ((bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) ||
			    (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_ENDPOINT)))
57
			{
58
				USB_Device_GetStatus();
59
60
61
62
63
64
				RequestHandled = true;
			}

			break;
		case REQ_ClearFeature:
		case REQ_SetFeature:
65
66
			if ((bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE)) ||
			    (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_ENDPOINT)))
67
			{
68
				USB_Device_ClearSetFeature();
69
70
71
72
73
				RequestHandled = true;
			}

			break;
		case REQ_SetAddress:
74
			if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE))
75
76
77
78
79
80
81
			{
				USB_Device_SetAddress();
				RequestHandled = true;
			}

			break;
		case REQ_GetDescriptor:
82
83
			if ((bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) ||
			    (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE)))
84
85
86
87
88
89
90
			{
				USB_Device_GetDescriptor();
				RequestHandled = true;
			}
			
			break;
		case REQ_GetConfiguration:
91
			if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE))
92
93
94
95
96
97
98
			{
				USB_Device_GetConfiguration();
				RequestHandled = true;
			}

			break;
		case REQ_SetConfiguration:
99
			if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE))
100
101
102
103
104
105
106
107
108
			{
				USB_Device_SetConfiguration();
				RequestHandled = true;
			}

			break;
	}

	if (!(RequestHandled))
109
	  EVENT_USB_UnhandledControlPacket();
110
	  
111
	if (Endpoint_IsSETUPReceived())
112
113
	{
		Endpoint_StallTransaction();
114
		Endpoint_ClearSETUP();		
115
116
117
118
119
	}
}

static void USB_Device_SetAddress(void)
{
120
	Endpoint_ClearSETUP();
121
	
122
	Endpoint_ClearIN();
123
	
124
	while (!(Endpoint_IsINReady()));
125

126
	UDADDR = ((1 << ADDEN) | ((uint8_t)USB_ControlRequest.wValue & 0x7F));
127
128
129
130
131
132

	return;
}

static void USB_Device_SetConfiguration(void)
{
133
	bool AlreadyConfigured = (USB_ConfigurationNumber != 0);
134
135

#if defined(USE_SINGLE_DEVICE_CONFIGURATION)
136
	if ((uint8_t)USB_ControlRequest.wValue > 1)
137
138
139
#else
	USB_Descriptor_Device_t* DevDescriptorPtr;

140
	if ((CALLBACK_USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DevDescriptorPtr) == NO_DESCRIPTOR) ||
141
	#if defined(USE_RAM_DESCRIPTORS)
142
	    ((uint8_t)USB_ControlRequest.wValue > DevDescriptorPtr->NumberOfConfigurations))
143
	#elif defined (USE_EEPROM_DESCRIPTORS)
144
	    ((uint8_t)USB_ControlRequest.wValue > eeprom_read_byte(&DevDescriptorPtr->NumberOfConfigurations)))
145
	#else
146
	    ((uint8_t)USB_ControlRequest.wValue > pgm_read_byte(&DevDescriptorPtr->NumberOfConfigurations)))
147
148
149
150
151
152
	#endif
#endif
	{
		return;
	}
	
153
	Endpoint_ClearSETUP();
154

155
	USB_ConfigurationNumber = (uint8_t)USB_ControlRequest.wValue;
156

157
	Endpoint_ClearIN();
158
159

	if (!(AlreadyConfigured) && USB_ConfigurationNumber)
160
	  EVENT_USB_DeviceEnumerationComplete();
161

162
	EVENT_USB_ConfigurationChanged();
163
164
165
166
}

void USB_Device_GetConfiguration(void)
{
167
	Endpoint_ClearSETUP();
168
169
170

	Endpoint_Write_Byte(USB_ConfigurationNumber);
	
171
	Endpoint_ClearIN();
172

173
	while (!(Endpoint_IsOUTReceived()));
174
	Endpoint_ClearOUT();
175
176
177
178
179
180
181
}

static void USB_Device_GetDescriptor(void)
{
	void*    DescriptorPointer;
	uint16_t DescriptorSize;
	
182
183
	if ((DescriptorSize = CALLBACK_USB_GetDescriptor(USB_ControlRequest.wValue, USB_ControlRequest.wIndex,
	                                                 &DescriptorPointer)) == NO_DESCRIPTOR)
184
185
186
	{
		return;
	}
187
	
188
189
190
191
192
	Endpoint_ClearSETUP();
	
	#if defined(USE_RAM_DESCRIPTORS)
	Endpoint_Write_Control_Stream_LE(DescriptorPointer, DescriptorSize);
	#else
193
	bool SendZLP;
194
	
195
196
	if (USB_ControlRequest.wLength > DescriptorSize)
	  USB_ControlRequest.wLength = DescriptorSize;
197
	
198
	while (USB_ControlRequest.wLength)
199
	{
200
		while (!(Endpoint_IsINReady()))
201
		{
202
			if (Endpoint_IsOUTReceived())
203
			{
204
				Endpoint_ClearOUT();
205
206
207
208
				return;
			}		
		}
		
209
		while (USB_ControlRequest.wLength && (Endpoint_BytesInEndpoint() < USB_ControlEndpointSize))
210
		{
211
			#if defined (USE_EEPROM_DESCRIPTORS)
212
			Endpoint_Write_Byte(eeprom_read_byte(DescriptorPointer++));		
213
214
215
216
			#else
			Endpoint_Write_Byte(pgm_read_byte(DescriptorPointer++));
			#endif
			
217
			USB_ControlRequest.wLength--;
218
219
220
		}
		
		SendZLP = (Endpoint_BytesInEndpoint() == USB_ControlEndpointSize);
221
		Endpoint_ClearIN();
222
223
224
225
	}
	
	if (SendZLP)
	{
226
		while (!(Endpoint_IsINReady()));
227
		Endpoint_ClearIN();
228
229
	}

230
	while (!(Endpoint_IsOUTReceived()));
231
232
	#endif
	
233
	Endpoint_ClearOUT();
234
235
}

236
static void USB_Device_GetStatus(void)
237
238
239
{
	uint8_t CurrentStatus = 0;

240
	switch (USB_ControlRequest.bmRequestType)
241
242
243
244
245
246
247
248
249
	{
		case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE):
			if (USB_CurrentlySelfPowered)
			  CurrentStatus |= FEATURE_SELFPOWERED_ENABLED;
			
			if (USB_RemoteWakeupEnabled)
			  CurrentStatus |= FEATURE_REMOTE_WAKEUP_ENABLED;
			
			break;
250
#if !defined(CONTROL_ONLY_DEVICE)
251
		case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_ENDPOINT):
252
			Endpoint_SelectEndpoint((uint8_t)USB_ControlRequest.wIndex);
253
254
255

			CurrentStatus = Endpoint_IsStalled();

256
257
			Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);			  

258
			break;
259
#endif
260
	}
261

262
	Endpoint_ClearSETUP();
263

264
265
	Endpoint_Write_Word_LE(CurrentStatus);

266
	Endpoint_ClearIN();
267
	
268
	while (!(Endpoint_IsOUTReceived()));
269
	Endpoint_ClearOUT();
270
271
}

272
273
274
static void USB_Device_ClearSetFeature(void)
{	
	switch (USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT)
275
	{
276
277
278
		case REQREC_DEVICE:
			if ((uint8_t)USB_ControlRequest.wValue == FEATURE_REMOTE_WAKEUP)
			  USB_RemoteWakeupEnabled = (USB_ControlRequest.bRequest == REQ_SetFeature);
279
280
			else
			  return;
281
282
283
			
			break;			
#if !defined(CONTROL_ONLY_DEVICE)
284
		case REQREC_ENDPOINT:
285
			if ((uint8_t)USB_ControlRequest.wValue == FEATURE_ENDPOINT_HALT)
286
			{
287
				uint8_t EndpointIndex = ((uint8_t)USB_ControlRequest.wIndex & ENDPOINT_EPNUM_MASK);
288
				
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
				if (EndpointIndex == ENDPOINT_CONTROLEP)
				  return;

				Endpoint_SelectEndpoint(EndpointIndex);

				if (Endpoint_IsEnabled())
				{				
					if (USB_ControlRequest.bRequest == REQ_ClearFeature)
					{
						Endpoint_ClearStall();
						Endpoint_ResetFIFO(EndpointIndex);
						Endpoint_ResetDataToggle();
					}
					else
					{
304
						Endpoint_StallTransaction();
305
306
307
308
309
					}
				}
			}
			
			break;
310
#endif
311
	}
312
313
314
315
316
317

	Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);

	Endpoint_ClearSETUP();

	Endpoint_ClearIN();
318
319
320
}

#endif