Fixed minor issue with the RNDISEthernet demo DHCP protocol decoder routine using...
[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 "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 uint8_t PrevPipe = Pipe_GetCurrentPipe();
90
91 Pipe_SelectPipe(PIPE_CONTROLPIPE);
92
93 switch (USB_HostState)
94 {
95 case HOST_STATE_WaitForDevice:
96 if (WaitMSRemaining)
97 {
98 if ((SubErrorCode = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful)
99 {
100 USB_HostState = PostWaitState;
101 ErrorCode = HOST_ENUMERROR_WaitStage;
102 break;
103 }
104
105 WaitMSRemaining--;
106 }
107 else
108 {
109 USB_HostState = PostWaitState;
110 }
111
112 break;
113 case HOST_STATE_Attached:
114 WaitMSRemaining = HOST_DEVICE_SETTLE_DELAY_MS;
115
116 USB_HostState = HOST_STATE_Attached_WaitForDeviceSettle;
117 break;
118 case HOST_STATE_Attached_WaitForDeviceSettle:
119 _delay_ms(1);
120
121 if (!(WaitMSRemaining--))
122 {
123 USB_Host_VBUS_Manual_Off();
124
125 USB_OTGPAD_On();
126 USB_Host_VBUS_Auto_Enable();
127 USB_Host_VBUS_Auto_On();
128
129 USB_HostState = HOST_STATE_Attached_WaitForConnect;
130 }
131
132 break;
133 case HOST_STATE_Attached_WaitForConnect:
134 if (USB_INT_HasOccurred(USB_INT_DCONNI))
135 {
136 USB_INT_Clear(USB_INT_DCONNI);
137 USB_INT_Clear(USB_INT_DDISCI);
138
139 USB_INT_Clear(USB_INT_VBERRI);
140 USB_INT_Enable(USB_INT_VBERRI);
141
142 USB_IsConnected = true;
143 RAISE_EVENT(USB_Connect);
144
145 USB_Host_ResumeBus();
146 Pipe_ClearPipes();
147
148 HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Attached_DoReset);
149 }
150
151 break;
152 case HOST_STATE_Attached_DoReset:
153 USB_Host_ResetDevice();
154
155 HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Powered);
156 break;
157 case HOST_STATE_Powered:
158 Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL,
159 PIPE_TOKEN_SETUP, PIPE_CONTROLPIPE,
160 PIPE_CONTROLPIPE_DEFAULT_SIZE, PIPE_BANK_SINGLE);
161
162 if (!(Pipe_IsConfigured()))
163 {
164 ErrorCode = HOST_ENUMERROR_PipeConfigError;
165 SubErrorCode = 0;
166 break;
167 }
168
169 USB_HostState = HOST_STATE_Default;
170 break;
171 case HOST_STATE_Default:
172 USB_HostRequest = (USB_Host_Request_Header_t)
173 {
174 bmRequestType: (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE),
175 bRequest: REQ_GetDescriptor,
176 wValue: (DTYPE_Device << 8),
177 wIndex: 0,
178 wLength: PIPE_CONTROLPIPE_DEFAULT_SIZE,
179 };
180
181 uint8_t DataBuffer[PIPE_CONTROLPIPE_DEFAULT_SIZE];
182
183 if ((SubErrorCode = USB_Host_SendControlRequest(DataBuffer)) != HOST_SENDCONTROL_Successful)
184 {
185 ErrorCode = HOST_ENUMERROR_ControlError;
186 break;
187 }
188
189 #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES)
190 USB_ControlPipeSize = DataBuffer[offsetof(USB_Descriptor_Device_t, Endpoint0Size)];
191 #else
192 USB_ControlPipeSize = DataBuffer[offsetof(USB_Descriptor_Device_t, bMaxPacketSize0)];
193 #endif
194
195 USB_Host_ResetDevice();
196
197 HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Default_PostReset);
198 break;
199 case HOST_STATE_Default_PostReset:
200 Pipe_DisablePipe();
201 Pipe_DeallocateMemory();
202 Pipe_ResetPipe(PIPE_CONTROLPIPE);
203
204 Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL,
205 PIPE_TOKEN_SETUP, PIPE_CONTROLPIPE,
206 USB_ControlPipeSize, PIPE_BANK_SINGLE);
207
208 if (!(Pipe_IsConfigured()))
209 {
210 ErrorCode = HOST_ENUMERROR_PipeConfigError;
211 SubErrorCode = 0;
212 break;
213 }
214
215 Pipe_SetInfiniteINRequests();
216
217 USB_HostRequest = (USB_Host_Request_Header_t)
218 {
219 bmRequestType: (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE),
220 bRequest: REQ_SetAddress,
221 wValue: USB_HOST_DEVICEADDRESS,
222 wIndex: 0,
223 wLength: 0,
224 };
225
226 if ((SubErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
227 {
228 ErrorCode = HOST_ENUMERROR_ControlError;
229 break;
230 }
231
232 HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Default_PostAddressSet);
233 break;
234 case HOST_STATE_Default_PostAddressSet:
235 USB_Host_SetDeviceAddress(USB_HOST_DEVICEADDRESS);
236
237 RAISE_EVENT(USB_DeviceEnumerationComplete);
238 USB_HostState = HOST_STATE_Addressed;
239
240 break;
241 }
242
243 if ((ErrorCode != HOST_ENUMERROR_NoError) && (USB_HostState != HOST_STATE_Unattached))
244 {
245 RAISE_EVENT(USB_DeviceEnumerationFailed, ErrorCode, SubErrorCode);
246
247 USB_Host_VBUS_Auto_Off();
248
249 RAISE_EVENT(USB_DeviceUnattached);
250
251 if (USB_IsConnected)
252 RAISE_EVENT(USB_Disconnect);
253
254 USB_ResetInterface();
255 }
256
257 Pipe_SelectPipe(PrevPipe);
258 }
259 #endif