3      Copyright (C) Dean Camera, 2010. 
   5   dean [at] fourwalledcubicle [dot] com 
   6       www.fourwalledcubicle.com 
  10   Copyright 2010  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_CDC_CLASS_HOST_C 
  36 #define  __INCLUDE_FROM_CDC_DRIVER 
  39 uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
, uint16_t ConfigDescriptorSize
, 
  40                                 void* ConfigDescriptorData
) 
  42         uint8_t FoundEndpoints 
= 0; 
  44         memset(&CDCInterfaceInfo
->State
, 0x00, sizeof(CDCInterfaceInfo
->State
)); 
  46         if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
) 
  47           return CDC_ENUMERROR_InvalidConfigDescriptor
; 
  49         if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  50                                       DCOMP_CDC_Host_NextCDCControlInterface
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  52                 return CDC_ENUMERROR_NoCDCInterfaceFound
; 
  55         CDCInterfaceInfo
->State
.ControlInterfaceNumber 
= DESCRIPTOR_CAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
).InterfaceNumber
; 
  57         while (FoundEndpoints 
!= (CDC_FOUND_NOTIFICATION_IN 
| CDC_FOUND_DATAPIPE_IN 
| CDC_FOUND_DATAPIPE_OUT
)) 
  59                 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  60                                               DCOMP_CDC_Host_NextCDCInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  62                         if (FoundEndpoints 
& CDC_FOUND_NOTIFICATION_IN
) 
  64                                 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,  
  65                                                               DCOMP_CDC_Host_NextCDCDataInterface
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  67                                         return CDC_ENUMERROR_NoCDCInterfaceFound
; 
  74                                 Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataINPipeNumber
); 
  76                                 Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataOUTPipeNumber
); 
  78                                 Pipe_SelectPipe(CDCInterfaceInfo
->Config
.NotificationPipeNumber
); 
  81                                 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  82                                                               DCOMP_CDC_Host_NextCDCControlInterface
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  84                                         return CDC_ENUMERROR_NoCDCInterfaceFound
; 
  88                         if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  89                                                       DCOMP_CDC_Host_NextCDCInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  91                                 return CDC_ENUMERROR_EndpointsNotFound
; 
  95                 USB_Descriptor_Endpoint_t
* EndpointData 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
); 
  97                 if ((EndpointData
->Attributes 
& EP_TYPE_MASK
) == EP_TYPE_INTERRUPT
) 
  99                         if (EndpointData
->EndpointAddress 
& ENDPOINT_DESCRIPTOR_DIR_IN
) 
 101                                 Pipe_ConfigurePipe(CDCInterfaceInfo
->Config
.NotificationPipeNumber
, EP_TYPE_INTERRUPT
, PIPE_TOKEN_IN
, 
 102                                                                    EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
, 
 103                                                                    CDCInterfaceInfo
->Config
.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE 
: PIPE_BANK_SINGLE
); 
 104                                 CDCInterfaceInfo
->State
.NotificationPipeSize 
= EndpointData
->EndpointSize
; 
 106                                 Pipe_SetInterruptPeriod(EndpointData
->PollingIntervalMS
); 
 108                                 FoundEndpoints 
|= CDC_FOUND_NOTIFICATION_IN
; 
 113                         if (EndpointData
->EndpointAddress 
& ENDPOINT_DESCRIPTOR_DIR_IN
) 
 115                                 Pipe_ConfigurePipe(CDCInterfaceInfo
->Config
.DataINPipeNumber
, EP_TYPE_BULK
, PIPE_TOKEN_IN
, 
 116                                                    EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
,  
 117                                                    CDCInterfaceInfo
->Config
.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE 
: PIPE_BANK_SINGLE
); 
 119                                 CDCInterfaceInfo
->State
.DataINPipeSize 
= EndpointData
->EndpointSize
; 
 121                                 FoundEndpoints 
|= CDC_FOUND_DATAPIPE_IN
; 
 125                                 Pipe_ConfigurePipe(CDCInterfaceInfo
->Config
.DataOUTPipeNumber
, EP_TYPE_BULK
, PIPE_TOKEN_OUT
, 
 126                                                                    EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
,  
 127                                                                    CDCInterfaceInfo
->Config
.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE 
: PIPE_BANK_SINGLE
); 
 129                                 CDCInterfaceInfo
->State
.DataOUTPipeSize 
= EndpointData
->EndpointSize
; 
 131                                 FoundEndpoints 
|= CDC_FOUND_DATAPIPE_OUT
; 
 136         CDCInterfaceInfo
->State
.ControlLineStates
.HostToDevice 
= (CDC_CONTROL_LINE_OUT_RTS 
| CDC_CONTROL_LINE_OUT_DTR
); 
 137         CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost 
= (CDC_CONTROL_LINE_IN_DCD  
| CDC_CONTROL_LINE_IN_DSR
); 
 138         CDCInterfaceInfo
->State
.IsActive 
= true; 
 139         return CDC_ENUMERROR_NoError
; 
 142 static uint8_t DCOMP_CDC_Host_NextCDCControlInterface(void* const CurrentDescriptor
) 
 144         if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
) 
 146                 USB_Descriptor_Interface_t
* CurrentInterface 
= DESCRIPTOR_PCAST(CurrentDescriptor
, 
 147                                                                                 USB_Descriptor_Interface_t
); 
 149                 if ((CurrentInterface
->Class    
== CDC_CONTROL_CLASS
)    && 
 150                     (CurrentInterface
->SubClass 
== CDC_CONTROL_SUBCLASS
) && 
 151                         (CurrentInterface
->Protocol 
== CDC_CONTROL_PROTOCOL
)) 
 153                         return DESCRIPTOR_SEARCH_Found
; 
 157         return DESCRIPTOR_SEARCH_NotFound
; 
 160 static uint8_t DCOMP_CDC_Host_NextCDCDataInterface(void* const CurrentDescriptor
) 
 162         if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
) 
 164                 USB_Descriptor_Interface_t
* CurrentInterface 
= DESCRIPTOR_PCAST(CurrentDescriptor
, 
 165                                                                                 USB_Descriptor_Interface_t
); 
 167                 if ((CurrentInterface
->Class    
== CDC_DATA_CLASS
)    && 
 168                     (CurrentInterface
->SubClass 
== CDC_DATA_SUBCLASS
) && 
 169                         (CurrentInterface
->Protocol 
== CDC_DATA_PROTOCOL
)) 
 171                         return DESCRIPTOR_SEARCH_Found
; 
 175         return DESCRIPTOR_SEARCH_NotFound
; 
 178 static uint8_t DCOMP_CDC_Host_NextCDCInterfaceEndpoint(void* const CurrentDescriptor
) 
 180         if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Endpoint
) 
 182                 USB_Descriptor_Endpoint_t
* CurrentEndpoint 
= DESCRIPTOR_PCAST(CurrentDescriptor
, 
 183                                                                               USB_Descriptor_Endpoint_t
); 
 185                 uint8_t EndpointType 
= (CurrentEndpoint
->Attributes 
& EP_TYPE_MASK
); 
 187                 if (((EndpointType 
== EP_TYPE_BULK
) || (EndpointType 
== EP_TYPE_INTERRUPT
)) && 
 188                     !(Pipe_IsEndpointBound(CurrentEndpoint
->EndpointAddress
))) 
 190                         return DESCRIPTOR_SEARCH_Found
; 
 193         else if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
) 
 195                 return DESCRIPTOR_SEARCH_Fail
; 
 198         return DESCRIPTOR_SEARCH_NotFound
; 
 201 void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 203         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 206         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.NotificationPipeNumber
); 
 207         Pipe_SetPipeToken(PIPE_TOKEN_IN
); 
 210         if (Pipe_IsINReceived()) 
 212                 USB_Request_Header_t Notification
; 
 213                 Pipe_Read_Stream_LE(&Notification
, sizeof(USB_Request_Header_t
), NO_STREAM_CALLBACK
); 
 215                 if ((Notification
.bRequest      
== NOTIF_SerialState
) && 
 216                     (Notification
.bmRequestType 
== (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
))) 
 218                         Pipe_Read_Stream_LE(&CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost
, 
 219                                             sizeof(CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost
), 
 226                 EVENT_CDC_Host_ControLineStateChanged(CDCInterfaceInfo
); 
 232 uint8_t CDC_Host_SetLineEncoding(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 234         USB_ControlRequest 
= (USB_Request_Header_t
) 
 236                 .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 237                 .bRequest      
= REQ_SetLineEncoding
, 
 239                 .wIndex        
= CDCInterfaceInfo
->State
.ControlInterfaceNumber
, 
 240                 .wLength       
= sizeof(CDCInterfaceInfo
->State
.LineEncoding
), 
 243         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 245         return USB_Host_SendControlRequest(&CDCInterfaceInfo
->State
.LineEncoding
); 
 248 uint8_t CDC_Host_SendControlLineStateChange(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 250         USB_ControlRequest 
= (USB_Request_Header_t
) 
 252                 .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 253                 .bRequest      
= REQ_SetControlLineState
, 
 254                 .wValue        
= CDCInterfaceInfo
->State
.ControlLineStates
.HostToDevice
, 
 255                 .wIndex        
= CDCInterfaceInfo
->State
.ControlInterfaceNumber
, 
 259         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 261         return USB_Host_SendControlRequest(NULL
); 
 264 uint8_t CDC_Host_SendBreak(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
, const uint8_t Duration
) 
 266         USB_ControlRequest 
= (USB_Request_Header_t
) 
 268                 .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 269                 .bRequest      
= REQ_SendBreak
, 
 271                 .wIndex        
= CDCInterfaceInfo
->State
.ControlInterfaceNumber
, 
 275         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 277         return USB_Host_SendControlRequest(NULL
); 
 280 uint8_t CDC_Host_SendString(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
, char* Data
, const uint16_t Length
) 
 282         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 283           return PIPE_READYWAIT_DeviceDisconnected
; 
 287         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataOUTPipeNumber
);     
 290         ErrorCode 
= Pipe_Write_Stream_LE(Data
, Length
, NO_STREAM_CALLBACK
); 
 296 uint8_t CDC_Host_SendByte(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
, const uint8_t Data
) 
 298         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 299           return PIPE_READYWAIT_DeviceDisconnected
; 
 303         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataOUTPipeNumber
);     
 306         if (!(Pipe_IsReadWriteAllowed())) 
 310                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 314         Pipe_Write_Byte(Data
);   
 317         return PIPE_READYWAIT_NoError
; 
 320 uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 322         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 325         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataINPipeNumber
); 
 326         Pipe_SetPipeToken(PIPE_TOKEN_IN
); 
 329         if (Pipe_IsINReceived()) 
 331                 if (!(Pipe_BytesInPipe())) 
 340                         return Pipe_BytesInPipe(); 
 351 uint8_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 353         uint8_t ReceivedByte 
= 0; 
 355         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 358         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataINPipeNumber
); 
 359         Pipe_SetPipeToken(PIPE_TOKEN_IN
); 
 362         ReceivedByte 
= Pipe_Read_Byte(); 
 364         if (!(Pipe_BytesInPipe())) 
 372 uint8_t CDC_Host_Flush(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 374         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 375           return PIPE_READYWAIT_DeviceDisconnected
; 
 379         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataOUTPipeNumber
);     
 382         if (!(Pipe_BytesInPipe())) 
 383           return PIPE_READYWAIT_NoError
; 
 385         bool BankFull 
= !(Pipe_IsReadWriteAllowed()); 
 391                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 399         return PIPE_READYWAIT_NoError
; 
 402 void CDC_Host_CreateStream(USB_ClassInfo_CDC_Host_t
* CDCInterfaceInfo
, FILE* Stream
) 
 404         *Stream 
= (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar
, CDC_Host_getchar
, _FDEV_SETUP_RW
); 
 405         fdev_set_udata(Stream
, CDCInterfaceInfo
); 
 408 void CDC_Host_CreateBlockingStream(USB_ClassInfo_CDC_Host_t
* CDCInterfaceInfo
, FILE* Stream
) 
 410         *Stream 
= (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar
, CDC_Host_getchar_Blocking
, _FDEV_SETUP_RW
); 
 411         fdev_set_udata(Stream
, CDCInterfaceInfo
); 
 414 static int CDC_Host_putchar(char c
, FILE* Stream
) 
 416         return CDC_Host_SendByte((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
), c
) ? _FDEV_ERR 
: 0; 
 419 static int CDC_Host_getchar(FILE* Stream
) 
 421         if (!(CDC_Host_BytesReceived((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)))) 
 424         return CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)); 
 427 static int CDC_Host_getchar_Blocking(FILE* Stream
) 
 429         while (!(CDC_Host_BytesReceived((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)))) 
 431                 if (USB_HostState 
== HOST_STATE_Unattached
) 
 434                 CDC_Host_USBTask((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)); 
 438         return CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)); 
 441 void CDC_Host_Event_Stub(void)