DevChapter9.c 8.08 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
	  RAISE_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
140
141
#else
	USB_Descriptor_Device_t* DevDescriptorPtr;

	if ((USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DevDescriptorPtr) == NO_DESCRIPTOR) ||
	#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
160
161
162
163
164
165
166

	if (!(AlreadyConfigured) && USB_ConfigurationNumber)
	  RAISE_EVENT(USB_DeviceEnumerationComplete);

	RAISE_EVENT(USB_ConfigurationChanged);
}

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

227
	while (!(Endpoint_IsOUTReceived()));
228
229
	#endif
	
230
	Endpoint_ClearOUT();
231
232
}

233
static void USB_Device_GetStatus(void)
234
235
236
{
	uint8_t CurrentStatus = 0;

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

			CurrentStatus = Endpoint_IsStalled();

253
254
			Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);			  

255
			break;
256
#endif
257
	}
258

259
	Endpoint_ClearSETUP();
260

261
262
	Endpoint_Write_Word_LE(CurrentStatus);

263
	Endpoint_ClearIN();
264
	
265
	while (!(Endpoint_IsOUTReceived()));
266
	Endpoint_ClearOUT();
267
268
}

269
270
271
static void USB_Device_ClearSetFeature(void)
{	
	switch (USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT)
272
	{
273
274
275
		case REQREC_DEVICE:
			if ((uint8_t)USB_ControlRequest.wValue == FEATURE_REMOTE_WAKEUP)
			  USB_RemoteWakeupEnabled = (USB_ControlRequest.bRequest == REQ_SetFeature);
276
277
			else
			  return;
278
279
280
			
			break;			
#if !defined(CONTROL_ONLY_DEVICE)
281
		case REQREC_ENDPOINT:
282
			if ((uint8_t)USB_ControlRequest.wValue == FEATURE_ENDPOINT_HALT)
283
			{
284
				uint8_t EndpointIndex = ((uint8_t)USB_ControlRequest.wIndex & ENDPOINT_EPNUM_MASK);
285
				
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
				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
					{
301
						Endpoint_StallTransaction();
302
303
304
305
306
					}
				}
			}
			
			break;
307
#endif
308
	}
309
310
311
312
313
314

	Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);

	Endpoint_ClearSETUP();

	Endpoint_ClearIN();
315
316
317
}

#endif