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
, 
 294         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 295           return PIPE_RWSTREAM_DeviceDisconnected
; 
 297         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 300         if ((ErrorCode 
= Pipe_Write_Stream_LE(String
, strlen(String
), NULL
)) != PIPE_RWSTREAM_NoError
) 
 305         ErrorCode 
= Pipe_WaitUntilReady(); 
 312 uint8_t PRNT_Host_SendData(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
, 
 314                            const uint16_t Length
) 
 318         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 319           return PIPE_RWSTREAM_DeviceDisconnected
; 
 321         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 324         if ((ErrorCode 
= Pipe_Write_Stream_LE(Buffer
, Length
, NULL
)) != PIPE_RWSTREAM_NoError
) 
 329         ErrorCode 
= Pipe_WaitUntilReady(); 
 336 uint16_t PRNT_Host_BytesReceived(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
) 
 338         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 341         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataINPipeNumber
); 
 344         if (Pipe_IsINReceived()) 
 346                 if (!(Pipe_BytesInPipe())) 
 355                         return Pipe_BytesInPipe(); 
 366 int16_t PRNT_Host_ReceiveByte(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
) 
 368         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(PRNTInterfaceInfo
->State
.IsActive
)) 
 369           return PIPE_RWSTREAM_DeviceDisconnected
; 
 371         int16_t ReceivedByte 
= -1; 
 373         Pipe_SelectPipe(PRNTInterfaceInfo
->Config
.DataINPipeNumber
); 
 376         if (Pipe_IsINReceived()) 
 378                 if (Pipe_BytesInPipe()) 
 379                   ReceivedByte 
= Pipe_Read_Byte(); 
 381                 if (!(Pipe_BytesInPipe())) 
 390 uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t
* const PRNTInterfaceInfo
, 
 391                               char* const DeviceIDString
, 
 392                               const uint16_t BufferSize
) 
 394         uint8_t  ErrorCode 
= HOST_SENDCONTROL_Successful
; 
 395         uint16_t DeviceIDStringLength 
= 0; 
 397         USB_ControlRequest 
= (USB_Request_Header_t
) 
 399                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 400                         .bRequest      
= PRNT_REQ_GetDeviceID
, 
 402                         .wIndex        
= PRNTInterfaceInfo
->State
.InterfaceNumber
, 
 403                         .wLength       
= sizeof(DeviceIDStringLength
), 
 406         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 408         if ((ErrorCode 
= USB_Host_SendControlRequest(&DeviceIDStringLength
)) != HOST_SENDCONTROL_Successful
) 
 411         if (!(DeviceIDStringLength
)) 
 413                 DeviceIDString
[0] = 0x00; 
 414                 return HOST_SENDCONTROL_Successful
; 
 417         DeviceIDStringLength 
= SwapEndian_16(DeviceIDStringLength
); 
 419         if (DeviceIDStringLength 
> BufferSize
) 
 420           DeviceIDStringLength 
= BufferSize
; 
 422         USB_ControlRequest
.wLength 
= DeviceIDStringLength
; 
 424         if ((ErrorCode 
= USB_Host_SendControlRequest(DeviceIDString
)) != HOST_SENDCONTROL_Successful
) 
 427         memmove(&DeviceIDString
[0], &DeviceIDString
[2], DeviceIDStringLength 
- 2); 
 429         DeviceIDString
[DeviceIDStringLength 
- 2] = 0x00; 
 431         return HOST_SENDCONTROL_Successful
;