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 "../../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
++) 
  85                 uint8_t  EndpointAddress
; 
  88                 if (PipeNum 
== PRNTInterfaceInfo
->Config
.DataINPipeNumber
) 
  90                         Size            
= DataINEndpoint
->EndpointSize
; 
  91                         EndpointAddress 
= DataINEndpoint
->EndpointAddress
; 
  92                         Token           
= PIPE_TOKEN_IN
; 
  94                         DoubleBanked    
= PRNTInterfaceInfo
->Config
.DataINPipeDoubleBank
; 
  96                         PRNTInterfaceInfo
->State
.DataINPipeSize 
= DataINEndpoint
->EndpointSize
; 
  98                 else if (PipeNum 
== PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
) 
 100                         Size            
= DataOUTEndpoint
->EndpointSize
; 
 101                         EndpointAddress 
= DataOUTEndpoint
->EndpointAddress
; 
 102                         Token           
= PIPE_TOKEN_OUT
; 
 104                         DoubleBanked    
= PRNTInterfaceInfo
->Config
.DataOUTPipeDoubleBank
; 
 106                         PRNTInterfaceInfo
->State
.DataOUTPipeSize 
= DataOUTEndpoint
->EndpointSize
; 
 113                 if (!(Pipe_ConfigurePipe(PipeNum
, Type
, Token
, EndpointAddress
, Size
, 
 114                                          DoubleBanked ? PIPE_BANK_DOUBLE 
: PIPE_BANK_SINGLE
))) 
 116                         return PRNT_ENUMERROR_PipeConfigurationFailed
; 
 120         PRNTInterfaceInfo
->State
.InterfaceNumber  
= PrinterInterface
->InterfaceNumber
; 
 121         PRNTInterfaceInfo
->State
.AlternateSetting 
= PrinterInterface
->AlternateSetting
; 
 122         PRNTInterfaceInfo
->State
.IsActive 
= true; 
 124         return PRNT_ENUMERROR_NoError
; 
 127 static uint8_t DCOMP_PRNT_Host_NextPRNTInterface(void* CurrentDescriptor
) 
 129         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 131         if (Header
->Type 
== DTYPE_Interface
) 
 133                 USB_Descriptor_Interface_t
* Interface 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Interface_t
); 
 135                 if ((Interface
->Class    
== PRNT_CSCP_PrinterClass
)    && 
 136                     (Interface
->SubClass 
== PRNT_CSCP_PrinterSubclass
) && 
 137                     (Interface
->Protocol 
== PRNT_CSCP_BidirectionalProtocol
)) 
 139                         return DESCRIPTOR_SEARCH_Found
; 
 143         return DESCRIPTOR_SEARCH_NotFound
; 
 146 static uint8_t DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint(void* CurrentDescriptor
) 
 148         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 150         if (Header
->Type 
== DTYPE_Endpoint
) 
 152                 USB_Descriptor_Endpoint_t
* Endpoint 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Endpoint_t
); 
 154                 uint8_t EndpointType 
= (Endpoint
->Attributes 
& EP_TYPE_MASK
); 
 156                 if (EndpointType 
== EP_TYPE_BULK
) 
 157                   return DESCRIPTOR_SEARCH_Found
; 
 159         else if (Header
->Type 
== DTYPE_Interface
) 
 161                 return DESCRIPTOR_SEARCH_Fail
; 
 164         return DESCRIPTOR_SEARCH_NotFound
; 
 167 void PRNT_Host_USBTask(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
) 
 169         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 172         #if !defined(NO_CLASS_DRIVER_AUTOFLUSH) 
 173         PRNT_Host_Flush(PRNTInterfaceInfo
); 
 177 uint8_t PRNT_Host_SetBidirectionalMode(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
) 
 179         if (PRNTInterfaceInfo
->State
.AlternateSetting
) 
 183                 USB_ControlRequest 
= (USB_Request_Header_t
) 
 185                                 .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_STANDARD 
| REQREC_INTERFACE
), 
 186                                 .bRequest      
= REQ_SetInterface
, 
 187                                 .wValue        
= PRNTInterfaceInfo
->State
.AlternateSetting
, 
 188                                 .wIndex        
= PRNTInterfaceInfo
->State
.InterfaceNumber
, 
 192                 Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 194                 if ((ErrorCode 
= USB_Host_SendControlRequest(NULL
)) != HOST_SENDCONTROL_Successful
) 
 198         return HOST_SENDCONTROL_Successful
; 
 201 uint8_t PRNT_Host_GetPortStatus(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
, 
 202                                 uint8_t* const PortStatus
) 
 204         USB_ControlRequest 
= (USB_Request_Header_t
) 
 206                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 207                         .bRequest      
= PRNT_REQ_GetPortStatus
, 
 209                         .wIndex        
= PRNTInterfaceInfo
->State
.InterfaceNumber
, 
 210                         .wLength       
= sizeof(uint8_t), 
 213         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 215         return USB_Host_SendControlRequest(PortStatus
); 
 218 uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
) 
 220         USB_ControlRequest 
= (USB_Request_Header_t
) 
 222                         .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 223                         .bRequest      
= PRNT_REQ_SoftReset
, 
 225                         .wIndex        
= PRNTInterfaceInfo
->State
.InterfaceNumber
, 
 229         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 231         return USB_Host_SendControlRequest(NULL
); 
 234 uint8_t PRNT_Host_Flush(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
) 
 236         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 237           return PIPE_READYWAIT_DeviceDisconnected
; 
 241         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 244         if (!(Pipe_BytesInPipe())) 
 245           return PIPE_READYWAIT_NoError
; 
 247         bool BankFull 
= !(Pipe_IsReadWriteAllowed()); 
 253                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 261         return PIPE_READYWAIT_NoError
; 
 264 uint8_t PRNT_Host_SendByte(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
, 
 267         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 268           return PIPE_READYWAIT_DeviceDisconnected
; 
 272         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 275         if (!(Pipe_IsReadWriteAllowed())) 
 279                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 283         Pipe_Write_Byte(Data
); 
 286         return PIPE_READYWAIT_NoError
; 
 289 uint8_t PRNT_Host_SendString(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
, 
 291                              const uint16_t Length
) 
 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(Buffer
, Length
, NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
) 
 306         ErrorCode 
= Pipe_WaitUntilReady(); 
 313 uint16_t PRNT_Host_BytesReceived(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
) 
 315         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 318         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataINPipeNumber
); 
 321         if (Pipe_IsINReceived()) 
 323                 if (!(Pipe_BytesInPipe())) 
 332                         return Pipe_BytesInPipe(); 
 343 int16_t PRNT_Host_ReceiveByte(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
) 
 345         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 346           return PIPE_RWSTREAM_DeviceDisconnected
; 
 348         int16_t ReceivedByte 
= -1; 
 350         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataINPipeNumber
); 
 353         if (Pipe_IsINReceived()) 
 355                 if (Pipe_BytesInPipe()) 
 356                   ReceivedByte 
= Pipe_Read_Byte(); 
 358                 if (!(Pipe_BytesInPipe())) 
 367 uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
, 
 368                               char* const DeviceIDString
, 
 369                               const uint16_t BufferSize
) 
 371         uint8_t  ErrorCode 
= HOST_SENDCONTROL_Successful
; 
 372         uint16_t DeviceIDStringLength 
= 0; 
 374         USB_ControlRequest 
= (USB_Request_Header_t
) 
 376                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 377                         .bRequest      
= PRNT_REQ_GetDeviceID
, 
 379                         .wIndex        
= PRNTInterfaceInfo
->State
.InterfaceNumber
, 
 380                         .wLength       
= sizeof(DeviceIDStringLength
), 
 383         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 385         if ((ErrorCode 
= USB_Host_SendControlRequest(&DeviceIDStringLength
)) != HOST_SENDCONTROL_Successful
) 
 388         if (!(DeviceIDStringLength
)) 
 390                 DeviceIDString
[0] = 0x00; 
 391                 return HOST_SENDCONTROL_Successful
; 
 394         DeviceIDStringLength 
= SwapEndian_16(DeviceIDStringLength
); 
 396         if (DeviceIDStringLength 
> BufferSize
) 
 397           DeviceIDStringLength 
= BufferSize
; 
 399         USB_ControlRequest
.wLength 
= DeviceIDStringLength
; 
 401         if ((ErrorCode 
= USB_Host_SendControlRequest(DeviceIDString
)) != HOST_SENDCONTROL_Successful
) 
 404         memmove(&DeviceIDString
[0], &DeviceIDString
[2], DeviceIDStringLength 
- 2); 
 406         DeviceIDString
[DeviceIDStringLength 
- 2] = 0x00; 
 408         return HOST_SENDCONTROL_Successful
;