6ecadb00d85667d00191fb2d78c16a36ac1dfaa0
[pub/USBasp.git] / LUFA / Drivers / USB / LowLevel / DevChapter9.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_DEVCHAPTER9_C
36 #include "DevChapter9.h"
37
38 uint8_t USB_ConfigurationNumber;
39 bool USB_RemoteWakeupEnabled;
40 bool USB_CurrentlySelfPowered;
41
42 void USB_Device_ProcessControlPacket(void)
43 {
44 bool RequestHandled = false;
45 uint8_t* RequestHeader = (uint8_t*)&USB_ControlRequest;
46
47 for (uint8_t RequestHeaderByte = 0; RequestHeaderByte < sizeof(USB_Request_Header_t); RequestHeaderByte++)
48 *(RequestHeader++) = Endpoint_Read_Byte();
49
50 uint8_t bmRequestType = USB_ControlRequest.bmRequestType;
51
52 switch (USB_ControlRequest.bRequest)
53 {
54 case REQ_GetStatus:
55 if ((bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) ||
56 (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_ENDPOINT)))
57 {
58 USB_Device_GetStatus();
59 RequestHandled = true;
60 }
61
62 break;
63 case REQ_ClearFeature:
64 case REQ_SetFeature:
65 if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_ENDPOINT))
66 {
67 USB_Device_ClearSetFeature();
68 RequestHandled = true;
69 }
70
71 break;
72 case REQ_SetAddress:
73 if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE))
74 {
75 USB_Device_SetAddress();
76 RequestHandled = true;
77 }
78
79 break;
80 case REQ_GetDescriptor:
81 if ((bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) ||
82 (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE)))
83 {
84 USB_Device_GetDescriptor();
85 RequestHandled = true;
86 }
87
88 break;
89 case REQ_GetConfiguration:
90 if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE))
91 {
92 USB_Device_GetConfiguration();
93 RequestHandled = true;
94 }
95
96 break;
97 case REQ_SetConfiguration:
98 if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE))
99 {
100 USB_Device_SetConfiguration();
101 RequestHandled = true;
102 }
103
104 break;
105 }
106
107 if (!(RequestHandled))
108 RAISE_EVENT(USB_UnhandledControlPacket);
109
110 if (Endpoint_IsSETUPReceived())
111 {
112 Endpoint_StallTransaction();
113 Endpoint_ClearSETUP();
114 }
115 }
116
117 static void USB_Device_SetAddress(void)
118 {
119 Endpoint_ClearSETUP();
120
121 Endpoint_ClearIN();
122
123 while (!(Endpoint_IsINReady()));
124
125 UDADDR = ((1 << ADDEN) | ((uint8_t)USB_ControlRequest.wValue & 0x7F));
126
127 return;
128 }
129
130 static void USB_Device_SetConfiguration(void)
131 {
132 bool AlreadyConfigured = (USB_ConfigurationNumber != 0);
133
134 #if defined(USE_SINGLE_DEVICE_CONFIGURATION)
135 if ((uint8_t)USB_ControlRequest.wValue > 1)
136 #else
137 USB_Descriptor_Device_t* DevDescriptorPtr;
138
139 if ((USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DevDescriptorPtr) == NO_DESCRIPTOR) ||
140 #if defined(USE_RAM_DESCRIPTORS)
141 ((uint8_t)USB_ControlRequest.wValue > DevDescriptorPtr->NumberOfConfigurations))
142 #elif defined (USE_EEPROM_DESCRIPTORS)
143 ((uint8_t)USB_ControlRequest.wValue > eeprom_read_byte(&DevDescriptorPtr->NumberOfConfigurations)))
144 #else
145 ((uint8_t)USB_ControlRequest.wValue > pgm_read_byte(&DevDescriptorPtr->NumberOfConfigurations)))
146 #endif
147 #endif
148 {
149 return;
150 }
151
152 Endpoint_ClearSETUP();
153
154 USB_ConfigurationNumber = (uint8_t)USB_ControlRequest.wValue;
155
156 Endpoint_ClearIN();
157
158 if (!(AlreadyConfigured) && USB_ConfigurationNumber)
159 RAISE_EVENT(USB_DeviceEnumerationComplete);
160
161 RAISE_EVENT(USB_ConfigurationChanged);
162 }
163
164 void USB_Device_GetConfiguration(void)
165 {
166 Endpoint_ClearSETUP();
167
168 Endpoint_Write_Byte(USB_ConfigurationNumber);
169
170 Endpoint_ClearIN();
171
172 while (!(Endpoint_IsOUTReceived()));
173 Endpoint_ClearOUT();
174 }
175
176 static void USB_Device_GetDescriptor(void)
177 {
178 void* DescriptorPointer;
179 uint16_t DescriptorSize;
180
181 if ((DescriptorSize = USB_GetDescriptor(USB_ControlRequest.wValue, USB_ControlRequest.wIndex, &DescriptorPointer)) == NO_DESCRIPTOR)
182 return;
183
184 Endpoint_ClearSETUP();
185
186 #if defined(USE_RAM_DESCRIPTORS)
187 Endpoint_Write_Control_Stream_LE(DescriptorPointer, DescriptorSize);
188 #else
189 bool SendZLP;
190
191 if (USB_ControlRequest.wLength > DescriptorSize)
192 USB_ControlRequest.wLength = DescriptorSize;
193
194 while (USB_ControlRequest.wLength)
195 {
196 while (!(Endpoint_IsINReady()))
197 {
198 if (Endpoint_IsOUTReceived())
199 {
200 Endpoint_ClearOUT();
201 return;
202 }
203 }
204
205 while (USB_ControlRequest.wLength && (Endpoint_BytesInEndpoint() < USB_ControlEndpointSize))
206 {
207 #if defined (USE_EEPROM_DESCRIPTORS)
208 Endpoint_Write_Byte(eeprom_read_byte(DescriptorPointer++));
209 #else
210 Endpoint_Write_Byte(pgm_read_byte(DescriptorPointer++));
211 #endif
212
213 USB_ControlRequest.wLength--;
214 }
215
216 SendZLP = (Endpoint_BytesInEndpoint() == USB_ControlEndpointSize);
217 Endpoint_ClearIN();
218 }
219
220 if (SendZLP)
221 {
222 while (!(Endpoint_IsINReady()));
223 Endpoint_ClearIN();
224 }
225
226 while (!(Endpoint_IsOUTReceived()));
227 #endif
228
229 Endpoint_ClearOUT();
230 }
231
232 static void USB_Device_GetStatus(void)
233 {
234 uint8_t CurrentStatus = 0;
235
236 switch (USB_ControlRequest.bmRequestType)
237 {
238 case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE):
239 if (USB_CurrentlySelfPowered)
240 CurrentStatus |= FEATURE_SELFPOWERED_ENABLED;
241
242 if (USB_RemoteWakeupEnabled)
243 CurrentStatus |= FEATURE_REMOTE_WAKEUP_ENABLED;
244
245 break;
246 #if !defined(CONTROL_ONLY_DEVICE)
247 case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_ENDPOINT):
248 Endpoint_SelectEndpoint((uint8_t)USB_ControlRequest.wIndex);
249
250 CurrentStatus = Endpoint_IsStalled();
251
252 Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
253
254 break;
255 #endif
256 }
257
258 Endpoint_ClearSETUP();
259
260 Endpoint_Write_Word_LE(CurrentStatus);
261
262 Endpoint_ClearIN();
263
264 while (!(Endpoint_IsOUTReceived()));
265 Endpoint_ClearOUT();
266 }
267
268 static void USB_Device_ClearSetFeature(void)
269 {
270 switch (USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT)
271 {
272 case REQREC_DEVICE:
273 if ((uint8_t)USB_ControlRequest.wValue == FEATURE_REMOTE_WAKEUP)
274 USB_RemoteWakeupEnabled = (USB_ControlRequest.bRequest == REQ_SetFeature);
275 else
276 return;
277
278 break;
279 #if !defined(CONTROL_ONLY_DEVICE)
280 case REQREC_ENDPOINT:
281 if ((uint8_t)USB_ControlRequest.wValue == FEATURE_ENDPOINT_HALT)
282 {
283 uint8_t EndpointIndex = ((uint8_t)USB_ControlRequest.wIndex & ENDPOINT_EPNUM_MASK);
284
285 if (EndpointIndex == ENDPOINT_CONTROLEP)
286 return;
287
288 Endpoint_SelectEndpoint(EndpointIndex);
289
290 if (Endpoint_IsEnabled())
291 {
292 if (USB_ControlRequest.bRequest == REQ_ClearFeature)
293 {
294 Endpoint_ClearStall();
295 Endpoint_ResetFIFO(EndpointIndex);
296 Endpoint_ResetDataToggle();
297 }
298 else
299 {
300 Endpoint_StallTransaction();
301 }
302 }
303 }
304
305 break;
306 #endif
307 }
308
309 Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
310
311 Endpoint_ClearSETUP();
312
313 Endpoint_ClearIN();
314 }
315
316 #endif