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                 USB_ControlRequest 
= (USB_Request_Header_t
) 
 186                                 .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_STANDARD 
| REQREC_INTERFACE
), 
 187                                 .bRequest      
= REQ_SetInterface
, 
 188                                 .wValue        
= PRNTInterfaceInfo
->State
.AlternateSetting
, 
 189                                 .wIndex        
= PRNTInterfaceInfo
->State
.InterfaceNumber
, 
 193                 Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 195                 if ((ErrorCode 
= USB_Host_SendControlRequest(NULL
)) != HOST_SENDCONTROL_Successful
) 
 199         return HOST_SENDCONTROL_Successful
; 
 202 uint8_t PRNT_Host_GetPortStatus(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
, 
 203                                 uint8_t* const PortStatus
) 
 205         USB_ControlRequest 
= (USB_Request_Header_t
) 
 207                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 208                         .bRequest      
= PRNT_REQ_GetPortStatus
, 
 210                         .wIndex        
= PRNTInterfaceInfo
->State
.InterfaceNumber
, 
 211                         .wLength       
= sizeof(uint8_t), 
 214         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 216         return USB_Host_SendControlRequest(PortStatus
); 
 219 uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
) 
 221         USB_ControlRequest 
= (USB_Request_Header_t
) 
 223                         .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 224                         .bRequest      
= PRNT_REQ_SoftReset
, 
 226                         .wIndex        
= PRNTInterfaceInfo
->State
.InterfaceNumber
, 
 230         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 232         return USB_Host_SendControlRequest(NULL
); 
 235 uint8_t PRNT_Host_Flush(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
) 
 237         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 238           return PIPE_READYWAIT_DeviceDisconnected
; 
 242         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 245         if (!(Pipe_BytesInPipe())) 
 246           return PIPE_READYWAIT_NoError
; 
 248         bool BankFull 
= !(Pipe_IsReadWriteAllowed()); 
 254                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 262         return PIPE_READYWAIT_NoError
; 
 265 uint8_t PRNT_Host_SendByte(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
, 
 268         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 269           return PIPE_READYWAIT_DeviceDisconnected
; 
 273         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 276         if (!(Pipe_IsReadWriteAllowed())) 
 280                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 284         Pipe_Write_Byte(Data
); 
 287         return PIPE_READYWAIT_NoError
; 
 290 uint8_t PRNT_Host_SendString(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
, 
 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(String
, strlen(String
), NULL
)) != PIPE_RWSTREAM_NoError
) 
 306         ErrorCode 
= Pipe_WaitUntilReady(); 
 313 uint8_t PRNT_Host_SendData(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
, 
 315                            const uint16_t Length
) 
 319         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 320           return PIPE_RWSTREAM_DeviceDisconnected
; 
 322         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 325         if ((ErrorCode 
= Pipe_Write_Stream_LE(Buffer
, Length
, NULL
)) != PIPE_RWSTREAM_NoError
) 
 330         ErrorCode 
= Pipe_WaitUntilReady(); 
 337 uint16_t PRNT_Host_BytesReceived(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
) 
 339         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 342         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataINPipeNumber
); 
 345         if (Pipe_IsINReceived()) 
 347                 if (!(Pipe_BytesInPipe())) 
 356                         return Pipe_BytesInPipe(); 
 367 int16_t PRNT_Host_ReceiveByte(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
) 
 369         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 370           return PIPE_RWSTREAM_DeviceDisconnected
; 
 372         int16_t ReceivedByte 
= -1; 
 374         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataINPipeNumber
); 
 377         if (Pipe_IsINReceived()) 
 379                 if (Pipe_BytesInPipe()) 
 380                   ReceivedByte 
= Pipe_Read_Byte(); 
 382                 if (!(Pipe_BytesInPipe())) 
 391 uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
, 
 392                               char* const DeviceIDString
, 
 393                               const uint16_t BufferSize
) 
 395         uint8_t  ErrorCode 
= HOST_SENDCONTROL_Successful
; 
 396         uint16_t DeviceIDStringLength 
= 0; 
 398         USB_ControlRequest 
= (USB_Request_Header_t
) 
 400                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 401                         .bRequest      
= PRNT_REQ_GetDeviceID
, 
 403                         .wIndex        
= PRNTInterfaceInfo
->State
.InterfaceNumber
, 
 404                         .wLength       
= sizeof(DeviceIDStringLength
), 
 407         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 409         if ((ErrorCode 
= USB_Host_SendControlRequest(&DeviceIDStringLength
)) != HOST_SENDCONTROL_Successful
) 
 412         if (!(DeviceIDStringLength
)) 
 414                 DeviceIDString
[0] = 0x00; 
 415                 return HOST_SENDCONTROL_Successful
; 
 418         DeviceIDStringLength 
= SwapEndian_16(DeviceIDStringLength
); 
 420         if (DeviceIDStringLength 
> BufferSize
) 
 421           DeviceIDStringLength 
= BufferSize
; 
 423         USB_ControlRequest
.wLength 
= DeviceIDStringLength
; 
 425         if ((ErrorCode 
= USB_Host_SendControlRequest(DeviceIDString
)) != HOST_SENDCONTROL_Successful
) 
 428         memmove(&DeviceIDString
[0], &DeviceIDString
[2], DeviceIDStringLength 
- 2); 
 430         DeviceIDString
[DeviceIDStringLength 
- 2] = 0x00; 
 432         return HOST_SENDCONTROL_Successful
;