3 Copyright (C) Dean Camera, 2010.
5 dean [at] fourwalledcubicle [dot] com
10 Copyright 2010 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 "../../HighLevel/USBMode.h"
33 #if defined(USB_CAN_BE_HOST)
35 #define __INCLUDE_FROM_PRINTER_DRIVER
36 #define __INCLUDE_FROM_PRINTER_HOST_C
39 uint8_t PRNT_Host_ConfigurePipes(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
,
40 uint16_t ConfigDescriptorSize
,
41 void* ConfigDescriptorData
)
43 USB_Descriptor_Endpoint_t
* DataINEndpoint
= NULL
;
44 USB_Descriptor_Endpoint_t
* DataOUTEndpoint
= NULL
;
45 USB_Descriptor_Interface_t
* PrinterInterface
= NULL
;
47 memset(&PRNTInterfaceInfo
->State
, 0x00, sizeof(PRNTInterfaceInfo
->State
));
49 if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
)
50 return PRNT_ENUMERROR_InvalidConfigDescriptor
;
52 while (!(DataINEndpoint
) || !(DataOUTEndpoint
))
54 if (!(PrinterInterface
) ||
55 USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
56 DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
)
58 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
59 DCOMP_PRNT_Host_NextPRNTInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
61 return PRNT_ENUMERROR_NoCompatibleInterfaceFound
;
64 PrinterInterface
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
);
66 DataINEndpoint
= NULL
;
67 DataOUTEndpoint
= NULL
;
72 USB_Descriptor_Endpoint_t
* EndpointData
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
);
74 if (EndpointData
->EndpointAddress
& ENDPOINT_DESCRIPTOR_DIR_IN
)
75 DataINEndpoint
= EndpointData
;
77 DataOUTEndpoint
= EndpointData
;
80 for (uint8_t PipeNum
= 1; PipeNum
< PIPE_TOTAL_PIPES
; PipeNum
++)
82 if (PipeNum
== PRNTInterfaceInfo
->Config
.DataINPipeNumber
)
84 Pipe_ConfigurePipe(PipeNum
, EP_TYPE_BULK
, PIPE_TOKEN_IN
,
85 DataINEndpoint
->EndpointAddress
, DataINEndpoint
->EndpointSize
,
86 PRNTInterfaceInfo
->Config
.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE
: PIPE_BANK_SINGLE
);
88 PRNTInterfaceInfo
->State
.DataINPipeSize
= DataINEndpoint
->EndpointSize
;
90 else if (PipeNum
== PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
)
92 Pipe_ConfigurePipe(PipeNum
, EP_TYPE_BULK
, PIPE_TOKEN_OUT
,
93 DataOUTEndpoint
->EndpointAddress
, DataOUTEndpoint
->EndpointSize
,
94 PRNTInterfaceInfo
->Config
.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE
: PIPE_BANK_SINGLE
);
96 PRNTInterfaceInfo
->State
.DataOUTPipeSize
= DataOUTEndpoint
->EndpointSize
;
100 PRNTInterfaceInfo
->State
.InterfaceNumber
= PrinterInterface
->InterfaceNumber
;
101 PRNTInterfaceInfo
->State
.AlternateSetting
= PrinterInterface
->AlternateSetting
;
102 PRNTInterfaceInfo
->State
.IsActive
= true;
104 return PRNT_ENUMERROR_NoError
;
107 static uint8_t DCOMP_PRNT_Host_NextPRNTInterface(void* CurrentDescriptor
)
109 USB_Descriptor_Header_t
* Header
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
);
111 if (Header
->Type
== DTYPE_Interface
)
113 USB_Descriptor_Interface_t
* Interface
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Interface_t
);
115 if ((Interface
->Class
== PRNT_CSCP_PrinterClass
) &&
116 (Interface
->SubClass
== PRNT_CSCP_PrinterSubclass
) &&
117 (Interface
->Protocol
== PRNT_CSCP_BidirectionalProtocol
))
119 return DESCRIPTOR_SEARCH_Found
;
123 return DESCRIPTOR_SEARCH_NotFound
;
126 static uint8_t DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint(void* CurrentDescriptor
)
128 USB_Descriptor_Header_t
* Header
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
);
130 if (Header
->Type
== DTYPE_Endpoint
)
132 USB_Descriptor_Endpoint_t
* Endpoint
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Endpoint_t
);
134 uint8_t EndpointType
= (Endpoint
->Attributes
& EP_TYPE_MASK
);
136 if (EndpointType
== EP_TYPE_BULK
)
137 return DESCRIPTOR_SEARCH_Found
;
139 else if (Header
->Type
== DTYPE_Interface
)
141 return DESCRIPTOR_SEARCH_Fail
;
144 return DESCRIPTOR_SEARCH_NotFound
;
147 void PRNT_Host_USBTask(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
)
149 if ((USB_HostState
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
))
152 #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
153 PRNT_Host_Flush(PRNTInterfaceInfo
);
157 uint8_t PRNT_Host_SetBidirectionalMode(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
)
159 if (PRNTInterfaceInfo
->State
.AlternateSetting
)
163 USB_ControlRequest
= (USB_Request_Header_t
)
165 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_STANDARD
| REQREC_INTERFACE
),
166 .bRequest
= REQ_SetInterface
,
167 .wValue
= PRNTInterfaceInfo
->State
.AlternateSetting
,
168 .wIndex
= PRNTInterfaceInfo
->State
.InterfaceNumber
,
172 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
174 if ((ErrorCode
= USB_Host_SendControlRequest(NULL
)) != HOST_SENDCONTROL_Successful
)
178 return HOST_SENDCONTROL_Successful
;
181 uint8_t PRNT_Host_GetPortStatus(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
,
182 uint8_t* const PortStatus
)
184 USB_ControlRequest
= (USB_Request_Header_t
)
186 .bmRequestType
= (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
),
187 .bRequest
= PRNT_REQ_GetPortStatus
,
189 .wIndex
= PRNTInterfaceInfo
->State
.InterfaceNumber
,
190 .wLength
= sizeof(uint8_t),
193 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
195 return USB_Host_SendControlRequest(PortStatus
);
198 uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
)
200 USB_ControlRequest
= (USB_Request_Header_t
)
202 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_CLASS
| REQREC_INTERFACE
),
203 .bRequest
= PRNT_REQ_SoftReset
,
205 .wIndex
= PRNTInterfaceInfo
->State
.InterfaceNumber
,
209 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
211 return USB_Host_SendControlRequest(NULL
);
214 uint8_t PRNT_Host_Flush(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
)
216 if ((USB_HostState
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
))
217 return PIPE_READYWAIT_DeviceDisconnected
;
221 Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
);
224 if (!(Pipe_BytesInPipe()))
225 return PIPE_READYWAIT_NoError
;
227 bool BankFull
= !(Pipe_IsReadWriteAllowed());
233 if ((ErrorCode
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
)
241 return PIPE_READYWAIT_NoError
;
244 uint8_t PRNT_Host_SendByte(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
,
247 if ((USB_HostState
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
))
248 return PIPE_READYWAIT_DeviceDisconnected
;
252 Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
);
255 if (!(Pipe_IsReadWriteAllowed()))
259 if ((ErrorCode
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
)
263 Pipe_Write_Byte(Data
);
266 return PIPE_READYWAIT_NoError
;
269 uint8_t PRNT_Host_SendString(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
,
271 const uint16_t Length
)
275 if ((USB_HostState
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
))
276 return PIPE_RWSTREAM_DeviceDisconnected
;
278 Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
);
281 if ((ErrorCode
= Pipe_Write_Stream_LE(Buffer
, Length
, NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
)
286 ErrorCode
= Pipe_WaitUntilReady();
293 uint16_t PRNT_Host_BytesReceived(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
)
295 if ((USB_HostState
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
))
298 Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataINPipeNumber
);
301 if (Pipe_IsINReceived())
303 if (!(Pipe_BytesInPipe()))
312 return Pipe_BytesInPipe();
323 int16_t PRNT_Host_ReceiveByte(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
)
325 if ((USB_HostState
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
))
326 return PIPE_RWSTREAM_DeviceDisconnected
;
328 int16_t ReceivedByte
= -1;
330 Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataINPipeNumber
);
333 if (Pipe_IsINReceived())
335 if (Pipe_BytesInPipe())
336 ReceivedByte
= Pipe_Read_Byte();
338 if (!(Pipe_BytesInPipe()))
347 uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
,
348 char* const DeviceIDString
,
349 const uint16_t BufferSize
)
351 uint8_t ErrorCode
= HOST_SENDCONTROL_Successful
;
352 uint16_t DeviceIDStringLength
= 0;
354 USB_ControlRequest
= (USB_Request_Header_t
)
356 .bmRequestType
= (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
),
357 .bRequest
= PRNT_REQ_GetDeviceID
,
359 .wIndex
= PRNTInterfaceInfo
->State
.InterfaceNumber
,
360 .wLength
= sizeof(DeviceIDStringLength
),
363 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
365 if ((ErrorCode
= USB_Host_SendControlRequest(&DeviceIDStringLength
)) != HOST_SENDCONTROL_Successful
)
368 if (!(DeviceIDStringLength
))
370 DeviceIDString
[0] = 0x00;
371 return HOST_SENDCONTROL_Successful
;
374 DeviceIDStringLength
= SwapEndian_16(DeviceIDStringLength
);
376 if (DeviceIDStringLength
> BufferSize
)
377 DeviceIDStringLength
= BufferSize
;
379 USB_ControlRequest
.wLength
= DeviceIDStringLength
;
381 if ((ErrorCode
= USB_Host_SendControlRequest(DeviceIDString
)) != HOST_SENDCONTROL_Successful
)
384 memmove(&DeviceIDString
[0], &DeviceIDString
[2], DeviceIDStringLength
- 2);
386 DeviceIDString
[DeviceIDStringLength
- 2] = 0x00;
388 return HOST_SENDCONTROL_Successful
;