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                 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
); 
 208         return USB_Host_SendControlRequest(PortStatus
); 
 211 uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
) 
 213         USB_ControlRequest 
= (USB_Request_Header_t
) 
 215                         .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 216                         .bRequest      
= PRNT_REQ_SoftReset
, 
 218                         .wIndex        
= PRNTInterfaceInfo
->State
.InterfaceNumber
, 
 222         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 224         return USB_Host_SendControlRequest(NULL
); 
 227 uint8_t PRNT_Host_Flush(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
) 
 229         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 230           return PIPE_READYWAIT_DeviceDisconnected
; 
 234         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 237         if (!(Pipe_BytesInPipe())) 
 238           return PIPE_READYWAIT_NoError
; 
 240         bool BankFull 
= !(Pipe_IsReadWriteAllowed()); 
 246                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 254         return PIPE_READYWAIT_NoError
; 
 257 uint8_t PRNT_Host_SendByte(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
, 
 260         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 261           return PIPE_READYWAIT_DeviceDisconnected
; 
 265         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 268         if (!(Pipe_IsReadWriteAllowed())) 
 272                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 279         return PIPE_READYWAIT_NoError
; 
 282 uint8_t PRNT_Host_SendString(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
, 
 287         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 288           return PIPE_RWSTREAM_DeviceDisconnected
; 
 290         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 293         if ((ErrorCode 
= Pipe_Write_Stream_LE(String
, strlen(String
), NULL
)) != PIPE_RWSTREAM_NoError
) 
 298         ErrorCode 
= Pipe_WaitUntilReady(); 
 305 uint8_t PRNT_Host_SendData(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
, 
 307                            const uint16_t Length
) 
 311         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 312           return PIPE_RWSTREAM_DeviceDisconnected
; 
 314         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 317         if ((ErrorCode 
= Pipe_Write_Stream_LE(Buffer
, Length
, NULL
)) != PIPE_RWSTREAM_NoError
) 
 322         ErrorCode 
= Pipe_WaitUntilReady(); 
 329 uint16_t PRNT_Host_BytesReceived(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
) 
 331         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 334         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataINPipeNumber
); 
 337         if (Pipe_IsINReceived()) 
 339                 if (!(Pipe_BytesInPipe())) 
 348                         return Pipe_BytesInPipe(); 
 359 int16_t PRNT_Host_ReceiveByte(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
) 
 361         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 362           return PIPE_RWSTREAM_DeviceDisconnected
; 
 364         int16_t ReceivedByte 
= -1; 
 366         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataINPipeNumber
); 
 369         if (Pipe_IsINReceived()) 
 371                 if (Pipe_BytesInPipe()) 
 372                   ReceivedByte 
= Pipe_Read_8(); 
 374                 if (!(Pipe_BytesInPipe())) 
 383 uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
, 
 384                               char* const DeviceIDString
, 
 385                               const uint16_t BufferSize
) 
 387         uint8_t  ErrorCode 
= HOST_SENDCONTROL_Successful
; 
 388         uint16_t DeviceIDStringLength 
= 0; 
 390         USB_ControlRequest 
= (USB_Request_Header_t
) 
 392                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 393                         .bRequest      
= PRNT_REQ_GetDeviceID
, 
 395                         .wIndex        
= PRNTInterfaceInfo
->State
.InterfaceNumber
, 
 396                         .wLength       
= sizeof(DeviceIDStringLength
), 
 399         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 401         if ((ErrorCode 
= USB_Host_SendControlRequest(&DeviceIDStringLength
)) != HOST_SENDCONTROL_Successful
) 
 404         if (!(DeviceIDStringLength
)) 
 406                 DeviceIDString
[0] = 0x00; 
 407                 return HOST_SENDCONTROL_Successful
; 
 410         DeviceIDStringLength 
= SwapEndian_16(DeviceIDStringLength
); 
 412         if (DeviceIDStringLength 
> BufferSize
) 
 413           DeviceIDStringLength 
= BufferSize
; 
 415         USB_ControlRequest
.wLength 
= DeviceIDStringLength
; 
 417         if ((ErrorCode 
= USB_Host_SendControlRequest(DeviceIDString
)) != HOST_SENDCONTROL_Successful
) 
 420         memmove(&DeviceIDString
[0], &DeviceIDString
[2], DeviceIDStringLength 
- 2); 
 422         DeviceIDString
[DeviceIDStringLength 
- 2] = 0x00; 
 424         return HOST_SENDCONTROL_Successful
;