Commit for the 090401 release.
[pub/USBasp.git] / LUFA / Drivers / USB / HighLevel / USBTask.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 "../LowLevel/USBMode.h"
32
33 #define INCLUDE_FROM_USBTASK_C
34 #include "USBTask.h"
35
36 volatile bool USB_IsSuspended;
37 volatile bool USB_IsConnected;
38 volatile bool USB_IsInitialized;
39
40 #if defined(USB_CAN_BE_HOST)
41 volatile uint8_t USB_HostState;
42 #endif
43
44 TASK(USB_USBTask)
45 {
46 #if defined(USB_HOST_ONLY)
47 USB_HostTask();
48 #elif defined(USB_DEVICE_ONLY)
49 USB_DeviceTask();
50 #else
51 if (USB_CurrentMode == USB_MODE_DEVICE)
52 USB_DeviceTask();
53 else if (USB_CurrentMode == USB_MODE_HOST)
54 USB_HostTask();
55 #endif
56 }
57
58 #if defined(USB_CAN_BE_DEVICE)
59 static void USB_DeviceTask(void)
60 {
61 if (USB_IsConnected)
62 {
63 uint8_t PrevEndpoint = Endpoint_GetCurrentEndpoint();
64
65 Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
66
67 if (Endpoint_IsSetupReceived())
68 {
69 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
70 {
71 USB_Device_ProcessControlPacket();
72 }
73 }
74
75 Endpoint_SelectEndpoint(PrevEndpoint);
76 }
77 }
78 #endif
79
80 #if defined(USB_CAN_BE_HOST)
81 static void USB_HostTask(void)
82 {
83 uint8_t ErrorCode = HOST_ENUMERROR_NoError;
84 uint8_t SubErrorCode = HOST_ENUMERROR_NoError;
85
86 static uint16_t WaitMSRemaining;
87 static uint8_t PostWaitState;
88
89 switch (USB_HostState)
90 {
91 case HOST_STATE_WaitForDevice:
92 if (WaitMSRemaining)
93 {
94 if ((SubErrorCode = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful)
95 {
96 USB_HostState = PostWaitState;
97 ErrorCode = HOST_ENUMERROR_WaitStage;
98 break;
99 }
100
101 WaitMSRemaining--;
102 }
103 else
104 {
105 USB_HostState = PostWaitState;
106 }
107
108 break;
109 case HOST_STATE_Attached:
110 WaitMSRemaining = HOST_DEVICE_SETTLE_DELAY_MS;
111
112 USB_HostState = HOST_STATE_Attached_WaitForDeviceSettle;
113 break;
114 case HOST_STATE_Attached_WaitForDeviceSettle:
115 _delay_ms(1);
116
117 if (!(WaitMSRemaining--))
118 {
119 USB_Host_VBUS_Manual_Off();
120
121 USB_OTGPAD_On();
122 USB_Host_VBUS_Auto_Enable();
123 USB_Host_VBUS_Auto_On();
124
125 USB_HostState = HOST_STATE_Attached_WaitForConnect;
126 }
127
128 break;
129 case HOST_STATE_Attached_WaitForConnect:
130 if (USB_INT_HasOccurred(USB_INT_DCONNI))
131 {
132 USB_INT_Clear(USB_INT_DCONNI);
133 USB_INT_Clear(USB_INT_DDISCI);
134
135 USB_INT_Clear(USB_INT_VBERRI);
136 USB_INT_Enable(USB_INT_VBERRI);
137
138 USB_IsConnected = true;
139 RAISE_EVENT(USB_Connect);
140
141 USB_Host_ResumeBus();
142 Pipe_ClearPipes();
143
144 HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Attached_DoReset);
145 }
146
147 break;
148 case HOST_STATE_Attached_DoReset:
149 USB_Host_ResetDevice();
150
151 HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Powered);
152 break;
153 case HOST_STATE_Powered:
154 Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL,
155 PIPE_TOKEN_SETUP, PIPE_CONTROLPIPE,
156 PIPE_CONTROLPIPE_DEFAULT_SIZE, PIPE_BANK_SINGLE);
157
158 if (!(Pipe_IsConfigured()))
159 {
160 ErrorCode = HOST_ENUMERROR_PipeConfigError;
161 SubErrorCode = 0;
162 break;
163 }
164
165 USB_HostState = HOST_STATE_Default;
166 break;
167 case HOST_STATE_Default:
168 USB_HostRequest = (USB_Host_Request_Header_t)
169 {
170 bmRequestType: (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE),
171 bRequest: REQ_GetDescriptor,
172 wValue: (DTYPE_Device << 8),
173 wIndex: 0,
174 wLength: PIPE_CONTROLPIPE_DEFAULT_SIZE,
175 };
176
177 uint8_t DataBuffer[PIPE_CONTROLPIPE_DEFAULT_SIZE];
178
179 if ((SubErrorCode = USB_Host_SendControlRequest(DataBuffer)) != HOST_SENDCONTROL_Successful)
180 {
181 ErrorCode = HOST_ENUMERROR_ControlError;
182 break;
183 }
184
185 #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES)
186 USB_ControlPipeSize = DataBuffer[offsetof(USB_Descriptor_Device_t, Endpoint0Size)];
187 #else
188 USB_ControlPipeSize = DataBuffer[offsetof(USB_Descriptor_Device_t, bMaxPacketSize0)];
189 #endif
190
191 USB_Host_ResetDevice();
192
193 HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Default_PostReset);
194 break;
195 case HOST_STATE_Default_PostReset:
196 Pipe_DisablePipe();
197 Pipe_DeallocateMemory();
198 Pipe_ResetPipe(PIPE_CONTROLPIPE);
199
200 Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL,
201 PIPE_TOKEN_SETUP, PIPE_CONTROLPIPE,
202 USB_ControlPipeSize, PIPE_BANK_SINGLE);
203
204 if (!(Pipe_IsConfigured()))
205 {
206 ErrorCode = HOST_ENUMERROR_PipeConfigError;
207 SubErrorCode = 0;
208 break;
209 }
210
211 Pipe_SetInfiniteINRequests();
212
213 USB_HostRequest = (USB_Host_Request_Header_t)
214 {
215 bmRequestType: (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE),
216 bRequest: REQ_SetAddress,
217 wValue: USB_HOST_DEVICEADDRESS,
218 wIndex: 0,
219 wLength: 0,
220 };
221
222 if ((SubErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
223 {
224 ErrorCode = HOST_ENUMERROR_ControlError;
225 break;
226 }
227
228 HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Default_PostAddressSet);
229 break;
230 case HOST_STATE_Default_PostAddressSet:
231 USB_Host_SetDeviceAddress(USB_HOST_DEVICEADDRESS);
232
233 RAISE_EVENT(USB_DeviceEnumerationComplete);
234 USB_HostState = HOST_STATE_Addressed;
235
236 break;
237 }
238
239 if ((ErrorCode != HOST_ENUMERROR_NoError) && (USB_HostState != HOST_STATE_Unattached))
240 {
241 RAISE_EVENT(USB_DeviceEnumerationFailed, ErrorCode, SubErrorCode);
242
243 USB_Host_VBUS_Auto_Off();
244
245 RAISE_EVENT(USB_DeviceUnattached);
246
247 if (USB_IsConnected)
248 RAISE_EVENT(USB_Disconnect);
249
250 USB_ResetInterface();
251 }
252 }
253 #endif