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            
= le16_to_cpu(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            
= le16_to_cpu(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                 if ((ErrorCode 
= USB_Host_SetInterfaceAltSetting(PRNTInterfaceInfo
->State
.InterfaceNumber
, 
 185                                                                  PRNTInterfaceInfo
->State
.AlternateSetting
)) != HOST_SENDCONTROL_Successful
) 
 191         return HOST_SENDCONTROL_Successful
; 
 194 uint8_t PRNT_Host_GetPortStatus(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
, 
 195                                 uint8_t* const PortStatus
) 
 197         USB_ControlRequest 
= (USB_Request_Header_t
) 
 199                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 200                         .bRequest      
= PRNT_REQ_GetPortStatus
, 
 202                         .wIndex        
= PRNTInterfaceInfo
->State
.InterfaceNumber
, 
 203                         .wLength       
= sizeof(uint8_t), 
 206         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 207         return USB_Host_SendControlRequest(PortStatus
); 
 210 uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
) 
 212         USB_ControlRequest 
= (USB_Request_Header_t
) 
 214                         .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 215                         .bRequest      
= PRNT_REQ_SoftReset
, 
 217                         .wIndex        
= PRNTInterfaceInfo
->State
.InterfaceNumber
, 
 221         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 222         return USB_Host_SendControlRequest(NULL
); 
 225 uint8_t PRNT_Host_Flush(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
) 
 227         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 228           return PIPE_READYWAIT_DeviceDisconnected
; 
 232         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 235         if (!(Pipe_BytesInPipe())) 
 236           return PIPE_READYWAIT_NoError
; 
 238         bool BankFull 
= !(Pipe_IsReadWriteAllowed()); 
 244                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 252         return PIPE_READYWAIT_NoError
; 
 255 uint8_t PRNT_Host_SendByte(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
, 
 258         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 259           return PIPE_READYWAIT_DeviceDisconnected
; 
 263         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 266         if (!(Pipe_IsReadWriteAllowed())) 
 270                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 277         return PIPE_READYWAIT_NoError
; 
 280 uint8_t PRNT_Host_SendString(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
, 
 285         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 286           return PIPE_RWSTREAM_DeviceDisconnected
; 
 288         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 291         if ((ErrorCode 
= Pipe_Write_Stream_LE(String
, strlen(String
), NULL
)) != PIPE_RWSTREAM_NoError
) 
 296         ErrorCode 
= Pipe_WaitUntilReady(); 
 303 uint8_t PRNT_Host_SendData(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
, 
 305                            const uint16_t Length
) 
 309         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 310           return PIPE_RWSTREAM_DeviceDisconnected
; 
 312         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 315         if ((ErrorCode 
= Pipe_Write_Stream_LE(Buffer
, Length
, NULL
)) != PIPE_RWSTREAM_NoError
) 
 320         ErrorCode 
= Pipe_WaitUntilReady(); 
 327 uint16_t PRNT_Host_BytesReceived(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
) 
 329         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 332         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataINPipeNumber
); 
 335         if (Pipe_IsINReceived()) 
 337                 if (!(Pipe_BytesInPipe())) 
 346                         return Pipe_BytesInPipe(); 
 357 int16_t PRNT_Host_ReceiveByte(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
) 
 359         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 360           return PIPE_RWSTREAM_DeviceDisconnected
; 
 362         int16_t ReceivedByte 
= -1; 
 364         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataINPipeNumber
); 
 367         if (Pipe_IsINReceived()) 
 369                 if (Pipe_BytesInPipe()) 
 370                   ReceivedByte 
= Pipe_Read_8(); 
 372                 if (!(Pipe_BytesInPipe())) 
 381 uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
, 
 382                               char* const DeviceIDString
, 
 383                               const uint16_t BufferSize
) 
 385         uint8_t  ErrorCode 
= HOST_SENDCONTROL_Successful
; 
 386         uint16_t DeviceIDStringLength 
= 0; 
 388         USB_ControlRequest 
= (USB_Request_Header_t
) 
 390                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 391                         .bRequest      
= PRNT_REQ_GetDeviceID
, 
 393                         .wIndex        
= PRNTInterfaceInfo
->State
.InterfaceNumber
, 
 394                         .wLength       
= sizeof(DeviceIDStringLength
), 
 397         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 399         if ((ErrorCode 
= USB_Host_SendControlRequest(&DeviceIDStringLength
)) != HOST_SENDCONTROL_Successful
) 
 402         if (!(DeviceIDStringLength
)) 
 404                 DeviceIDString
[0] = 0x00; 
 405                 return HOST_SENDCONTROL_Successful
; 
 408         DeviceIDStringLength 
= be16_to_cpu(DeviceIDStringLength
); 
 410         if (DeviceIDStringLength 
> BufferSize
) 
 411           DeviceIDStringLength 
= BufferSize
; 
 413         USB_ControlRequest
.wLength 
= DeviceIDStringLength
; 
 415         if ((ErrorCode 
= USB_Host_SendControlRequest(DeviceIDString
)) != HOST_SENDCONTROL_Successful
) 
 418         memmove(&DeviceIDString
[0], &DeviceIDString
[2], DeviceIDStringLength 
- 2); 
 420         DeviceIDString
[DeviceIDStringLength 
- 2] = 0x00; 
 422         return HOST_SENDCONTROL_Successful
;