3 Copyright (C) Dean Camera, 2011.
5 dean [at] fourwalledcubicle [dot] com
10 Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
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.
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 #define __INCLUDE_FROM_USB_DRIVER
32 #include "../../Core/USBMode.h"
34 #if defined(USB_CAN_BE_HOST)
36 #define __INCLUDE_FROM_PRINTER_DRIVER
37 #define __INCLUDE_FROM_PRINTER_HOST_C
40 uint8_t PRNT_Host_ConfigurePipes(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
,
41 uint16_t ConfigDescriptorSize
,
42 void* ConfigDescriptorData
)
44 USB_Descriptor_Endpoint_t
* DataINEndpoint
= NULL
;
45 USB_Descriptor_Endpoint_t
* DataOUTEndpoint
= NULL
;
46 USB_Descriptor_Interface_t
* PrinterInterface
= NULL
;
48 memset(&PRNTInterfaceInfo
->State
, 0x00, sizeof(PRNTInterfaceInfo
->State
));
50 if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
)
51 return PRNT_ENUMERROR_InvalidConfigDescriptor
;
53 while (!(DataINEndpoint
) || !(DataOUTEndpoint
))
55 if (!(PrinterInterface
) ||
56 USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
57 DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
)
59 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
60 DCOMP_PRNT_Host_NextPRNTInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
62 return PRNT_ENUMERROR_NoCompatibleInterfaceFound
;
65 PrinterInterface
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
);
67 DataINEndpoint
= NULL
;
68 DataOUTEndpoint
= NULL
;
73 USB_Descriptor_Endpoint_t
* EndpointData
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
);
75 if (EndpointData
->EndpointAddress
& ENDPOINT_DESCRIPTOR_DIR_IN
)
76 DataINEndpoint
= EndpointData
;
78 DataOUTEndpoint
= EndpointData
;
81 for (uint8_t PipeNum
= 1; PipeNum
< PIPE_TOTAL_PIPES
; PipeNum
++)
86 uint8_t EndpointAddress
;
89 if (PipeNum
== PRNTInterfaceInfo
->Config
.DataINPipeNumber
)
91 Size
= DataINEndpoint
->EndpointSize
;
92 EndpointAddress
= DataINEndpoint
->EndpointAddress
;
93 Token
= PIPE_TOKEN_IN
;
95 DoubleBanked
= PRNTInterfaceInfo
->Config
.DataINPipeDoubleBank
;
97 PRNTInterfaceInfo
->State
.DataINPipeSize
= DataINEndpoint
->EndpointSize
;
99 else if (PipeNum
== PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
)
101 Size
= DataOUTEndpoint
->EndpointSize
;
102 EndpointAddress
= DataOUTEndpoint
->EndpointAddress
;
103 Token
= PIPE_TOKEN_OUT
;
105 DoubleBanked
= PRNTInterfaceInfo
->Config
.DataOUTPipeDoubleBank
;
107 PRNTInterfaceInfo
->State
.DataOUTPipeSize
= DataOUTEndpoint
->EndpointSize
;
114 if (!(Pipe_ConfigurePipe(PipeNum
, Type
, Token
, EndpointAddress
, Size
,
115 DoubleBanked ? PIPE_BANK_DOUBLE
: PIPE_BANK_SINGLE
)))
117 return PRNT_ENUMERROR_PipeConfigurationFailed
;
121 PRNTInterfaceInfo
->State
.InterfaceNumber
= PrinterInterface
->InterfaceNumber
;
122 PRNTInterfaceInfo
->State
.AlternateSetting
= PrinterInterface
->AlternateSetting
;
123 PRNTInterfaceInfo
->State
.IsActive
= true;
125 return PRNT_ENUMERROR_NoError
;
128 static uint8_t DCOMP_PRNT_Host_NextPRNTInterface(void* CurrentDescriptor
)
130 USB_Descriptor_Header_t
* Header
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
);
132 if (Header
->Type
== DTYPE_Interface
)
134 USB_Descriptor_Interface_t
* Interface
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Interface_t
);
136 if ((Interface
->Class
== PRNT_CSCP_PrinterClass
) &&
137 (Interface
->SubClass
== PRNT_CSCP_PrinterSubclass
) &&
138 (Interface
->Protocol
== PRNT_CSCP_BidirectionalProtocol
))
140 return DESCRIPTOR_SEARCH_Found
;
144 return DESCRIPTOR_SEARCH_NotFound
;
147 static uint8_t DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint(void* CurrentDescriptor
)
149 USB_Descriptor_Header_t
* Header
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
);
151 if (Header
->Type
== DTYPE_Endpoint
)
153 USB_Descriptor_Endpoint_t
* Endpoint
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Endpoint_t
);
155 uint8_t EndpointType
= (Endpoint
->Attributes
& EP_TYPE_MASK
);
157 if (EndpointType
== EP_TYPE_BULK
)
158 return DESCRIPTOR_SEARCH_Found
;
160 else if (Header
->Type
== DTYPE_Interface
)
162 return DESCRIPTOR_SEARCH_Fail
;
165 return DESCRIPTOR_SEARCH_NotFound
;
168 void PRNT_Host_USBTask(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
)
170 if ((USB_HostState
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
))
173 #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
174 PRNT_Host_Flush(PRNTInterfaceInfo
);
178 uint8_t PRNT_Host_SetBidirectionalMode(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
)
180 if (PRNTInterfaceInfo
->State
.AlternateSetting
)
184 USB_ControlRequest
= (USB_Request_Header_t
)
186 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_STANDARD
| REQREC_INTERFACE
),
187 .bRequest
= REQ_SetInterface
,
188 .wValue
= PRNTInterfaceInfo
->State
.AlternateSetting
,
189 .wIndex
= PRNTInterfaceInfo
->State
.InterfaceNumber
,
193 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
195 if ((ErrorCode
= USB_Host_SendControlRequest(NULL
)) != HOST_SENDCONTROL_Successful
)
199 return HOST_SENDCONTROL_Successful
;
202 uint8_t PRNT_Host_GetPortStatus(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
,
203 uint8_t* const PortStatus
)
205 USB_ControlRequest
= (USB_Request_Header_t
)
207 .bmRequestType
= (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
),
208 .bRequest
= PRNT_REQ_GetPortStatus
,
210 .wIndex
= PRNTInterfaceInfo
->State
.InterfaceNumber
,
211 .wLength
= sizeof(uint8_t),
214 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
216 return USB_Host_SendControlRequest(PortStatus
);
219 uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
)
221 USB_ControlRequest
= (USB_Request_Header_t
)
223 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_CLASS
| REQREC_INTERFACE
),
224 .bRequest
= PRNT_REQ_SoftReset
,
226 .wIndex
= PRNTInterfaceInfo
->State
.InterfaceNumber
,
230 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
232 return USB_Host_SendControlRequest(NULL
);
235 uint8_t PRNT_Host_Flush(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
)
237 if ((USB_HostState
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
))
238 return PIPE_READYWAIT_DeviceDisconnected
;
242 Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
);
245 if (!(Pipe_BytesInPipe()))
246 return PIPE_READYWAIT_NoError
;
248 bool BankFull
= !(Pipe_IsReadWriteAllowed());
254 if ((ErrorCode
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
)
262 return PIPE_READYWAIT_NoError
;
265 uint8_t PRNT_Host_SendByte(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
,
268 if ((USB_HostState
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
))
269 return PIPE_READYWAIT_DeviceDisconnected
;
273 Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
);
276 if (!(Pipe_IsReadWriteAllowed()))
280 if ((ErrorCode
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
)
284 Pipe_Write_Byte(Data
);
287 return PIPE_READYWAIT_NoError
;
290 uint8_t PRNT_Host_SendString(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
,
295 if ((USB_HostState
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
))
296 return PIPE_RWSTREAM_DeviceDisconnected
;
298 Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
);
301 if ((ErrorCode
= Pipe_Write_Stream_LE(String
, strlen(String
), NULL
)) != PIPE_RWSTREAM_NoError
)
306 ErrorCode
= Pipe_WaitUntilReady();
313 uint8_t PRNT_Host_SendData(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
,
315 const uint16_t Length
)
319 if ((USB_HostState
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
))
320 return PIPE_RWSTREAM_DeviceDisconnected
;
322 Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
);
325 if ((ErrorCode
= Pipe_Write_Stream_LE(Buffer
, Length
, NULL
)) != PIPE_RWSTREAM_NoError
)
330 ErrorCode
= Pipe_WaitUntilReady();
337 uint16_t PRNT_Host_BytesReceived(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
)
339 if ((USB_HostState
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
))
342 Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataINPipeNumber
);
345 if (Pipe_IsINReceived())
347 if (!(Pipe_BytesInPipe()))
356 return Pipe_BytesInPipe();
367 int16_t PRNT_Host_ReceiveByte(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
)
369 if ((USB_HostState
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
))
370 return PIPE_RWSTREAM_DeviceDisconnected
;
372 int16_t ReceivedByte
= -1;
374 Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataINPipeNumber
);
377 if (Pipe_IsINReceived())
379 if (Pipe_BytesInPipe())
380 ReceivedByte
= Pipe_Read_Byte();
382 if (!(Pipe_BytesInPipe()))
391 uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
,
392 char* const DeviceIDString
,
393 const uint16_t BufferSize
)
395 uint8_t ErrorCode
= HOST_SENDCONTROL_Successful
;
396 uint16_t DeviceIDStringLength
= 0;
398 USB_ControlRequest
= (USB_Request_Header_t
)
400 .bmRequestType
= (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
),
401 .bRequest
= PRNT_REQ_GetDeviceID
,
403 .wIndex
= PRNTInterfaceInfo
->State
.InterfaceNumber
,
404 .wLength
= sizeof(DeviceIDStringLength
),
407 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
409 if ((ErrorCode
= USB_Host_SendControlRequest(&DeviceIDStringLength
)) != HOST_SENDCONTROL_Successful
)
412 if (!(DeviceIDStringLength
))
414 DeviceIDString
[0] = 0x00;
415 return HOST_SENDCONTROL_Successful
;
418 DeviceIDStringLength
= SwapEndian_16(DeviceIDStringLength
);
420 if (DeviceIDStringLength
> BufferSize
)
421 DeviceIDStringLength
= BufferSize
;
423 USB_ControlRequest
.wLength
= DeviceIDStringLength
;
425 if ((ErrorCode
= USB_Host_SendControlRequest(DeviceIDString
)) != HOST_SENDCONTROL_Successful
)
428 memmove(&DeviceIDString
[0], &DeviceIDString
[2], DeviceIDStringLength
- 2);
430 DeviceIDString
[DeviceIDStringLength
- 2] = 0x00;
432 return HOST_SENDCONTROL_Successful
;