ae7525bee7838ce8ff02ab563727ba2c8914917c
[pub/USBasp.git] / LUFA / Drivers / USB / LowLevel / Host.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_HOST)
34
35 #define INCLUDE_FROM_HOST_C
36 #include "Host.h"
37
38 void USB_Host_ProcessNextHostState(void)
39 {
40 uint8_t ErrorCode = HOST_ENUMERROR_NoError;
41 uint8_t SubErrorCode = HOST_ENUMERROR_NoError;
42
43 static uint16_t WaitMSRemaining;
44 static uint8_t PostWaitState;
45
46 switch (USB_HostState)
47 {
48 case HOST_STATE_WaitForDevice:
49 if (WaitMSRemaining)
50 {
51 if ((SubErrorCode = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful)
52 {
53 USB_HostState = PostWaitState;
54 ErrorCode = HOST_ENUMERROR_WaitStage;
55 break;
56 }
57
58 if (!(--WaitMSRemaining))
59 USB_HostState = PostWaitState;
60 }
61
62 break;
63 case HOST_STATE_Powered:
64 WaitMSRemaining = HOST_DEVICE_SETTLE_DELAY_MS;
65
66 USB_HostState = HOST_STATE_Powered_WaitForDeviceSettle;
67 break;
68 case HOST_STATE_Powered_WaitForDeviceSettle:
69 #if HOST_DEVICE_SETTLE_DELAY_MS > 0
70 _delay_ms(1);
71
72 if (!(WaitMSRemaining--))
73 {
74 USB_Host_VBUS_Manual_Off();
75
76 USB_OTGPAD_On();
77 USB_Host_VBUS_Auto_Enable();
78 USB_Host_VBUS_Auto_On();
79
80 USB_HostState = HOST_STATE_Powered_WaitForConnect;
81 }
82 #else
83 USB_HostState = HOST_STATE_Powered_WaitForConnect;
84 #endif
85
86 break;
87 case HOST_STATE_Powered_WaitForConnect:
88 if (USB_INT_HasOccurred(USB_INT_DCONNI))
89 {
90 USB_INT_Clear(USB_INT_DCONNI);
91 USB_INT_Clear(USB_INT_DDISCI);
92
93 USB_INT_Clear(USB_INT_VBERRI);
94 USB_INT_Enable(USB_INT_VBERRI);
95
96 EVENT_USB_Connect();
97
98 USB_Host_ResumeBus();
99 Pipe_ClearPipes();
100
101 HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Powered_DoReset);
102 }
103
104 break;
105 case HOST_STATE_Powered_DoReset:
106 USB_Host_ResetDevice();
107
108 HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Powered_ConfigPipe);
109 break;
110 case HOST_STATE_Powered_ConfigPipe:
111 Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL,
112 PIPE_TOKEN_SETUP, ENDPOINT_CONTROLEP,
113 PIPE_CONTROLPIPE_DEFAULT_SIZE, PIPE_BANK_SINGLE);
114
115 if (!(Pipe_IsConfigured()))
116 {
117 ErrorCode = HOST_ENUMERROR_PipeConfigError;
118 SubErrorCode = 0;
119 break;
120 }
121
122 USB_HostState = HOST_STATE_Default;
123 break;
124 case HOST_STATE_Default:
125 USB_ControlRequest = (USB_Request_Header_t)
126 {
127 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE),
128 .bRequest = REQ_GetDescriptor,
129 .wValue = (DTYPE_Device << 8),
130 .wIndex = 0,
131 .wLength = 8,
132 };
133
134 uint8_t DataBuffer[8];
135
136 if ((SubErrorCode = USB_Host_SendControlRequest(DataBuffer)) != HOST_SENDCONTROL_Successful)
137 {
138 ErrorCode = HOST_ENUMERROR_ControlError;
139 break;
140 }
141
142 #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES)
143 USB_ControlPipeSize = DataBuffer[offsetof(USB_Descriptor_Device_t, Endpoint0Size)];
144 #else
145 USB_ControlPipeSize = DataBuffer[offsetof(USB_Descriptor_Device_t, bMaxPacketSize0)];
146 #endif
147
148 USB_Host_ResetDevice();
149
150 HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Default_PostReset);
151 break;
152 case HOST_STATE_Default_PostReset:
153 Pipe_DisablePipe();
154 Pipe_DeallocateMemory();
155 Pipe_ResetPipe(PIPE_CONTROLPIPE);
156
157 Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL,
158 PIPE_TOKEN_SETUP, ENDPOINT_CONTROLEP,
159 USB_ControlPipeSize, PIPE_BANK_SINGLE);
160
161 if (!(Pipe_IsConfigured()))
162 {
163 ErrorCode = HOST_ENUMERROR_PipeConfigError;
164 SubErrorCode = 0;
165 break;
166 }
167
168 USB_ControlRequest = (USB_Request_Header_t)
169 {
170 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE),
171 .bRequest = REQ_SetAddress,
172 .wValue = USB_HOST_DEVICEADDRESS,
173 .wIndex = 0,
174 .wLength = 0,
175 };
176
177 if ((SubErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
178 {
179 ErrorCode = HOST_ENUMERROR_ControlError;
180 break;
181 }
182
183 HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Default_PostAddressSet);
184 break;
185 case HOST_STATE_Default_PostAddressSet:
186 USB_Host_SetDeviceAddress(USB_HOST_DEVICEADDRESS);
187
188 EVENT_USB_DeviceEnumerationComplete();
189 USB_HostState = HOST_STATE_Addressed;
190
191 break;
192 }
193
194 if ((ErrorCode != HOST_ENUMERROR_NoError) && (USB_HostState != HOST_STATE_Unattached))
195 {
196 EVENT_USB_DeviceEnumerationFailed(ErrorCode, SubErrorCode);
197
198 USB_Host_VBUS_Auto_Off();
199
200 EVENT_USB_DeviceUnattached();
201 EVENT_USB_Disconnect();
202
203 USB_ResetInterface();
204 }
205 }
206
207 uint8_t USB_Host_WaitMS(uint8_t MS)
208 {
209 bool BusSuspended = USB_Host_IsBusSuspended();
210 uint8_t ErrorCode = HOST_WAITERROR_Successful;
211
212 USB_Host_ResumeBus();
213
214 while (MS)
215 {
216 if (USB_INT_HasOccurred(USB_INT_HSOFI))
217 {
218 USB_INT_Clear(USB_INT_HSOFI);
219 MS--;
220 }
221
222 if ((USB_HostState == HOST_STATE_Unattached) || (USB_CurrentMode == USB_MODE_DEVICE))
223 {
224 ErrorCode = HOST_WAITERROR_DeviceDisconnect;
225
226 break;
227 }
228
229 if (Pipe_IsError() == true)
230 {
231 Pipe_ClearError();
232 ErrorCode = HOST_WAITERROR_PipeError;
233
234 break;
235 }
236
237 if (Pipe_IsStalled() == true)
238 {
239 Pipe_ClearStall();
240 ErrorCode = HOST_WAITERROR_SetupStalled;
241
242 break;
243 }
244 }
245
246 if (BusSuspended)
247 USB_Host_SuspendBus();
248
249 return ErrorCode;
250 }
251
252 static void USB_Host_ResetDevice(void)
253 {
254 bool BusSuspended = USB_Host_IsBusSuspended();
255
256 USB_INT_Disable(USB_INT_DDISCI);
257
258 USB_Host_ResetBus();
259 while (!(USB_Host_IsBusResetComplete()));
260
261 USB_Host_ResumeBus();
262
263 USB_INT_Clear(USB_INT_HSOFI);
264
265 for (uint8_t MSRem = 10; MSRem != 0; MSRem--)
266 {
267 /* Workaround for powerless-pull-up devices. After a USB bus reset,
268 all disconnection interrupts are suppressed while a USB frame is
269 looked for - if it is found within 10ms, the device is still
270 present. */
271
272 if (USB_INT_HasOccurred(USB_INT_HSOFI))
273 {
274 USB_INT_Clear(USB_INT_HSOFI);
275 USB_INT_Clear(USB_INT_DDISCI);
276 break;
277 }
278
279 _delay_ms(1);
280 }
281
282 if (BusSuspended)
283 USB_Host_SuspendBus();
284
285 USB_INT_Enable(USB_INT_DDISCI);
286 }
287
288 uint8_t USB_Host_SetDeviceConfiguration(const uint8_t ConfigNumber)
289 {
290 USB_ControlRequest = (USB_Request_Header_t)
291 {
292 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE),
293 .bRequest = REQ_SetConfiguration,
294 .wValue = ConfigNumber,
295 .wIndex = 0,
296 .wLength = 0,
297 };
298
299 Pipe_SelectPipe(PIPE_CONTROLPIPE);
300
301 return USB_Host_SendControlRequest(NULL);
302 }
303
304 uint8_t USB_Host_GetDeviceDescriptor(void* const DeviceDescriptorPtr)
305 {
306 USB_ControlRequest = (USB_Request_Header_t)
307 {
308 bmRequestType: (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE),
309 bRequest: REQ_GetDescriptor,
310 wValue: (DTYPE_Device << 8),
311 wIndex: 0,
312 wLength: sizeof(USB_Descriptor_Device_t),
313 };
314
315 Pipe_SelectPipe(PIPE_CONTROLPIPE);
316
317 return USB_Host_SendControlRequest(DeviceDescriptorPtr);
318 }
319
320 uint8_t USB_Host_ClearPipeStall(uint8_t EndpointNum)
321 {
322 if (Pipe_GetPipeToken() == PIPE_TOKEN_IN)
323 EndpointNum |= (1 << 7);
324
325 USB_ControlRequest = (USB_Request_Header_t)
326 {
327 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_ENDPOINT),
328 .bRequest = REQ_ClearFeature,
329 .wValue = FEATURE_ENDPOINT_HALT,
330 .wIndex = EndpointNum,
331 .wLength = 0,
332 };
333
334 Pipe_SelectPipe(PIPE_CONTROLPIPE);
335
336 return USB_Host_SendControlRequest(NULL);
337 }
338
339 #endif