3 Copyright (C) Dean Camera, 2010.
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.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* DeviceConfigDescriptor
)
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(DeviceConfigDescriptor
) != DTYPE_Configuration
)
50 return PRNT_ENUMERROR_InvalidConfigDescriptor
;
52 while (!(DataINEndpoint
) || !(DataOUTEndpoint
))
54 if (!(PrinterInterface
) ||
55 USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &DeviceConfigDescriptor
,
56 DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
)
58 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &DeviceConfigDescriptor
,
59 DCOMP_PRNT_Host_NextPRNTInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
61 return PRNT_ENUMERROR_NoCompatibleInterfaceFound
;
64 PrinterInterface
= DESCRIPTOR_PCAST(DeviceConfigDescriptor
, USB_Descriptor_Interface_t
);
66 DataINEndpoint
= NULL
;
67 DataOUTEndpoint
= NULL
;
72 USB_Descriptor_Endpoint_t
* EndpointData
= DESCRIPTOR_PCAST(DeviceConfigDescriptor
, 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 if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
)
111 USB_Descriptor_Interface_t
* CurrentInterface
= DESCRIPTOR_PCAST(CurrentDescriptor
,
112 USB_Descriptor_Interface_t
);
114 if ((CurrentInterface
->Class
== PRINTER_CLASS
) &&
115 (CurrentInterface
->SubClass
== PRINTER_SUBCLASS
) &&
116 (CurrentInterface
->Protocol
== PRINTER_PROTOCOL
))
118 return DESCRIPTOR_SEARCH_Found
;
122 return DESCRIPTOR_SEARCH_NotFound
;
125 static uint8_t DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint(void* CurrentDescriptor
)
127 if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Endpoint
)
129 uint8_t EndpointType
= (DESCRIPTOR_CAST(CurrentDescriptor
,
130 USB_Descriptor_Endpoint_t
).Attributes
& EP_TYPE_MASK
);
132 if (EndpointType
== EP_TYPE_BULK
)
133 return DESCRIPTOR_SEARCH_Found
;
135 else if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
)
137 return DESCRIPTOR_SEARCH_Fail
;
140 return DESCRIPTOR_SEARCH_NotFound
;
143 void PRNT_Host_USBTask(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
)
145 PRNT_Host_Flush(PRNTInterfaceInfo
);
148 uint8_t PRNT_Host_SetBidirectionalMode(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
)
150 if (PRNTInterfaceInfo
->State
.AlternateSetting
)
154 USB_ControlRequest
= (USB_Request_Header_t
)
156 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_STANDARD
| REQREC_INTERFACE
),
157 .bRequest
= REQ_SetInterface
,
158 .wValue
= PRNTInterfaceInfo
->State
.AlternateSetting
,
159 .wIndex
= PRNTInterfaceInfo
->State
.InterfaceNumber
,
163 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
165 if ((ErrorCode
= USB_Host_SendControlRequest(NULL
)) != HOST_SENDCONTROL_Successful
)
169 return HOST_SENDCONTROL_Successful
;
172 uint8_t PRNT_Host_GetPortStatus(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
,
173 uint8_t* const PortStatus
)
175 USB_ControlRequest
= (USB_Request_Header_t
)
177 .bmRequestType
= (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
),
178 .bRequest
= PRNT_REQ_GetPortStatus
,
180 .wIndex
= PRNTInterfaceInfo
->State
.InterfaceNumber
,
181 .wLength
= sizeof(uint8_t),
184 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
186 return USB_Host_SendControlRequest(PortStatus
);
189 uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
)
191 USB_ControlRequest
= (USB_Request_Header_t
)
193 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_CLASS
| REQREC_INTERFACE
),
194 .bRequest
= PRNT_REQ_SoftReset
,
196 .wIndex
= PRNTInterfaceInfo
->State
.InterfaceNumber
,
200 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
202 return USB_Host_SendControlRequest(NULL
);
205 uint8_t PRNT_Host_Flush(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
)
207 if ((USB_HostState
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
))
208 return PIPE_READYWAIT_DeviceDisconnected
;
212 Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
);
215 if (!(Pipe_BytesInPipe()))
216 return PIPE_READYWAIT_NoError
;
218 bool BankFull
= !(Pipe_IsReadWriteAllowed());
224 if ((ErrorCode
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
)
232 return PIPE_READYWAIT_NoError
;
235 uint8_t PRNT_Host_SendByte(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
,
238 if ((USB_HostState
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
))
239 return PIPE_READYWAIT_DeviceDisconnected
;
243 Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
);
246 if (!(Pipe_IsReadWriteAllowed()))
250 if ((ErrorCode
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
)
254 Pipe_Write_Byte(Data
);
257 return PIPE_READYWAIT_NoError
;
260 uint8_t PRNT_Host_SendString(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
,
262 const uint16_t Length
)
266 if ((USB_HostState
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
))
267 return PIPE_RWSTREAM_DeviceDisconnected
;
269 Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
);
272 if ((ErrorCode
= Pipe_Write_Stream_LE(Buffer
, Length
, NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
)
277 ErrorCode
= Pipe_WaitUntilReady();
284 uint16_t PRNT_Host_BytesReceived(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
)
286 if ((USB_HostState
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
))
289 Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataINPipeNumber
);
292 if (Pipe_IsINReceived())
294 if (!(Pipe_BytesInPipe()))
303 return Pipe_BytesInPipe();
314 int16_t PRNT_Host_ReceiveByte(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
)
316 if ((USB_HostState
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
))
317 return PIPE_RWSTREAM_DeviceDisconnected
;
319 int16_t ReceivedByte
= -1;
321 Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataINPipeNumber
);
324 if (Pipe_IsINReceived())
326 if (Pipe_BytesInPipe())
327 ReceivedByte
= Pipe_Read_Byte();
329 if (!(Pipe_BytesInPipe()))
338 uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
,
339 char* const DeviceIDString
,
340 const uint16_t BufferSize
)
342 uint8_t ErrorCode
= HOST_SENDCONTROL_Successful
;
343 uint16_t DeviceIDStringLength
= 0;
345 USB_ControlRequest
= (USB_Request_Header_t
)
347 .bmRequestType
= (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
),
348 .bRequest
= PRNT_REQ_GetDeviceID
,
350 .wIndex
= PRNTInterfaceInfo
->State
.InterfaceNumber
,
351 .wLength
= sizeof(DeviceIDStringLength
),
354 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
356 if ((ErrorCode
= USB_Host_SendControlRequest(&DeviceIDStringLength
)) != HOST_SENDCONTROL_Successful
)
359 if (!(DeviceIDStringLength
))
361 DeviceIDString
[0] = 0x00;
362 return HOST_SENDCONTROL_Successful
;
365 DeviceIDStringLength
= SwapEndian_16(DeviceIDStringLength
);
367 if (DeviceIDStringLength
> BufferSize
)
368 DeviceIDStringLength
= BufferSize
;
370 USB_ControlRequest
.wLength
= DeviceIDStringLength
;
372 if ((ErrorCode
= USB_Host_SendControlRequest(DeviceIDString
)) != HOST_SENDCONTROL_Successful
)
375 memmove(&DeviceIDString
[0], &DeviceIDString
[2], DeviceIDStringLength
- 2);
377 DeviceIDString
[DeviceIDStringLength
- 2] = 0x00;
379 return HOST_SENDCONTROL_Successful
;