3 Copyright (C) Dean Camera, 2009.
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
10 Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
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.
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
31 #include "../HighLevel/USBMode.h"
33 #if defined(USB_CAN_BE_HOST)
35 #define INCLUDE_FROM_HOST_C
38 void USB_Host_ProcessNextHostState(void)
40 uint8_t ErrorCode
= HOST_ENUMERROR_NoError
;
41 uint8_t SubErrorCode
= HOST_ENUMERROR_NoError
;
43 static uint16_t WaitMSRemaining
;
44 static uint8_t PostWaitState
;
46 switch (USB_HostState
)
48 case HOST_STATE_WaitForDevice
:
51 if ((SubErrorCode
= USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful
)
53 USB_HostState
= PostWaitState
;
54 ErrorCode
= HOST_ENUMERROR_WaitStage
;
58 if (!(--WaitMSRemaining
))
59 USB_HostState
= PostWaitState
;
63 case HOST_STATE_Attached
:
64 WaitMSRemaining
= HOST_DEVICE_SETTLE_DELAY_MS
;
66 USB_HostState
= HOST_STATE_Attached_WaitForDeviceSettle
;
68 case HOST_STATE_Attached_WaitForDeviceSettle
:
69 #if HOST_DEVICE_SETTLE_DELAY_MS > 0
72 if (!(WaitMSRemaining
--))
74 USB_Host_VBUS_Manual_Off();
77 USB_Host_VBUS_Auto_Enable();
78 USB_Host_VBUS_Auto_On();
80 USB_HostState
= HOST_STATE_Attached_WaitForConnect
;
83 USB_HostState
= HOST_STATE_Attached_WaitForConnect
;
87 case HOST_STATE_Attached_WaitForConnect
:
88 if (USB_INT_HasOccurred(USB_INT_DCONNI
))
90 USB_INT_Clear(USB_INT_DCONNI
);
91 USB_INT_Clear(USB_INT_DDISCI
);
93 USB_INT_Clear(USB_INT_VBERRI
);
94 USB_INT_Enable(USB_INT_VBERRI
);
96 USB_IsConnected
= true;
102 HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Attached_DoReset
);
106 case HOST_STATE_Attached_DoReset
:
107 USB_Host_ResetDevice();
109 HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Powered
);
111 case HOST_STATE_Powered
:
112 Pipe_ConfigurePipe(PIPE_CONTROLPIPE
, EP_TYPE_CONTROL
,
113 PIPE_TOKEN_SETUP
, ENDPOINT_CONTROLEP
,
114 PIPE_CONTROLPIPE_DEFAULT_SIZE
, PIPE_BANK_SINGLE
);
116 if (!(Pipe_IsConfigured()))
118 ErrorCode
= HOST_ENUMERROR_PipeConfigError
;
123 USB_HostState
= HOST_STATE_Default
;
125 case HOST_STATE_Default
:
126 USB_ControlRequest
= (USB_Request_Header_t
)
128 .bmRequestType
= (REQDIR_DEVICETOHOST
| REQTYPE_STANDARD
| REQREC_DEVICE
),
129 .bRequest
= REQ_GetDescriptor
,
130 .wValue
= (DTYPE_Device
<< 8),
135 uint8_t DataBuffer
[8];
137 if ((SubErrorCode
= USB_Host_SendControlRequest(DataBuffer
)) != HOST_SENDCONTROL_Successful
)
139 ErrorCode
= HOST_ENUMERROR_ControlError
;
143 #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES)
144 USB_ControlPipeSize
= DataBuffer
[offsetof(USB_Descriptor_Device_t
, Endpoint0Size
)];
146 USB_ControlPipeSize
= DataBuffer
[offsetof(USB_Descriptor_Device_t
, bMaxPacketSize0
)];
149 USB_Host_ResetDevice();
151 HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Default_PostReset
);
153 case HOST_STATE_Default_PostReset
:
155 Pipe_DeallocateMemory();
156 Pipe_ResetPipe(PIPE_CONTROLPIPE
);
158 Pipe_ConfigurePipe(PIPE_CONTROLPIPE
, EP_TYPE_CONTROL
,
159 PIPE_TOKEN_SETUP
, ENDPOINT_CONTROLEP
,
160 USB_ControlPipeSize
, PIPE_BANK_SINGLE
);
162 if (!(Pipe_IsConfigured()))
164 ErrorCode
= HOST_ENUMERROR_PipeConfigError
;
169 USB_ControlRequest
= (USB_Request_Header_t
)
171 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_STANDARD
| REQREC_DEVICE
),
172 .bRequest
= REQ_SetAddress
,
173 .wValue
= USB_HOST_DEVICEADDRESS
,
178 if ((SubErrorCode
= USB_Host_SendControlRequest(NULL
)) != HOST_SENDCONTROL_Successful
)
180 ErrorCode
= HOST_ENUMERROR_ControlError
;
184 HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Default_PostAddressSet
);
186 case HOST_STATE_Default_PostAddressSet
:
187 USB_Host_SetDeviceAddress(USB_HOST_DEVICEADDRESS
);
189 EVENT_USB_DeviceEnumerationComplete();
190 USB_HostState
= HOST_STATE_Addressed
;
195 if ((ErrorCode
!= HOST_ENUMERROR_NoError
) && (USB_HostState
!= HOST_STATE_Unattached
))
197 EVENT_USB_DeviceEnumerationFailed(ErrorCode
, SubErrorCode
);
199 USB_Host_VBUS_Auto_Off();
201 EVENT_USB_DeviceUnattached();
204 EVENT_USB_Disconnect();
206 USB_ResetInterface();
210 uint8_t USB_Host_WaitMS(uint8_t MS
)
212 bool BusSuspended
= USB_Host_IsBusSuspended();
213 uint8_t ErrorCode
= HOST_WAITERROR_Successful
;
215 USB_Host_ResumeBus();
219 if (USB_INT_HasOccurred(USB_INT_HSOFI
))
221 USB_INT_Clear(USB_INT_HSOFI
);
225 if ((USB_IsConnected
== false) || (USB_CurrentMode
== USB_MODE_DEVICE
))
227 ErrorCode
= HOST_WAITERROR_DeviceDisconnect
;
232 if (Pipe_IsError() == true)
235 ErrorCode
= HOST_WAITERROR_PipeError
;
240 if (Pipe_IsStalled() == true)
243 ErrorCode
= HOST_WAITERROR_SetupStalled
;
250 USB_Host_SuspendBus();
255 static void USB_Host_ResetDevice(void)
257 bool BusSuspended
= USB_Host_IsBusSuspended();
259 USB_INT_Disable(USB_INT_DDISCI
);
262 while (!(USB_Host_IsBusResetComplete()));
264 USB_Host_ResumeBus();
266 USB_INT_Clear(USB_INT_HSOFI
);
268 for (uint8_t MSRem
= 10; MSRem
!= 0; MSRem
--)
270 /* Workaround for powerless-pull-up devices. After a USB bus reset,
271 all disconnection interrupts are suppressed while a USB frame is
272 looked for - if it is found within 10ms, the device is still
275 if (USB_INT_HasOccurred(USB_INT_HSOFI
))
277 USB_INT_Clear(USB_INT_HSOFI
);
278 USB_INT_Clear(USB_INT_DDISCI
);
286 USB_Host_SuspendBus();
288 USB_INT_Enable(USB_INT_DDISCI
);
291 uint8_t USB_Host_SetDeviceConfiguration(uint8_t ConfigNumber
)
293 USB_ControlRequest
= (USB_Request_Header_t
)
295 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_STANDARD
| REQREC_DEVICE
),
296 .bRequest
= REQ_SetConfiguration
,
297 .wValue
= ConfigNumber
,
302 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
304 return USB_Host_SendControlRequest(NULL
);
307 uint8_t USB_Host_GetDeviceDescriptor(void* DeviceDescriptorPtr
)
309 USB_ControlRequest
= (USB_Request_Header_t
)
311 bmRequestType
: (REQDIR_DEVICETOHOST
| REQTYPE_STANDARD
| REQREC_DEVICE
),
312 bRequest
: REQ_GetDescriptor
,
313 wValue
: (DTYPE_Device
<< 8),
315 wLength
: sizeof(USB_Descriptor_Device_t
),
318 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
320 return USB_Host_SendControlRequest(DeviceDescriptorPtr
);
323 uint8_t USB_Host_ClearPipeStall(uint8_t EndpointNum
)
325 if (Pipe_GetPipeToken() == PIPE_TOKEN_IN
)
326 EndpointNum
|= (1 << 7);
328 USB_ControlRequest
= (USB_Request_Header_t
)
330 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_STANDARD
| REQREC_ENDPOINT
),
331 .bRequest
= REQ_ClearFeature
,
332 .wValue
= FEATURE_ENDPOINT_HALT
,
333 .wIndex
= EndpointNum
,
337 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
339 return USB_Host_SendControlRequest(NULL
);