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