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_SendString(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
, char* Data
, const uint16_t Length
) 
 266         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 267           return PIPE_READYWAIT_DeviceDisconnected
; 
 271         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataOUTPipeNumber
);     
 274         ErrorCode 
= Pipe_Write_Stream_LE(Data
, Length
, NO_STREAM_CALLBACK
); 
 280 uint8_t CDC_Host_SendByte(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
, const uint8_t Data
) 
 282         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 283           return PIPE_READYWAIT_DeviceDisconnected
; 
 287         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataOUTPipeNumber
);     
 290         if (!(Pipe_IsReadWriteAllowed())) 
 294                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 298         Pipe_Write_Byte(Data
);   
 301         return PIPE_READYWAIT_NoError
; 
 304 uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 306         uint16_t BytesInPipe 
= 0; 
 308         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 311         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataINPipeNumber
); 
 312         Pipe_SetPipeToken(PIPE_TOKEN_IN
); 
 315         if (Pipe_IsINReceived()) 
 317                 if (!(Pipe_BytesInPipe())) 
 320                 BytesInPipe 
= Pipe_BytesInPipe(); 
 333 uint8_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 335         uint8_t ReceivedByte 
= 0; 
 337         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 340         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataINPipeNumber
); 
 341         Pipe_SetPipeToken(PIPE_TOKEN_IN
); 
 344         ReceivedByte 
= Pipe_Read_Byte(); 
 346         if (!(Pipe_BytesInPipe())) 
 354 uint8_t CDC_Host_Flush(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 356         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 357           return PIPE_READYWAIT_DeviceDisconnected
; 
 361         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataOUTPipeNumber
);     
 364         if (!(Pipe_BytesInPipe())) 
 365           return PIPE_READYWAIT_NoError
; 
 367         bool BankFull 
= !(Pipe_IsReadWriteAllowed()); 
 373                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 381         return PIPE_READYWAIT_NoError
; 
 384 void CDC_Host_CreateStream(USB_ClassInfo_CDC_Host_t
* CDCInterfaceInfo
, FILE* Stream
) 
 386         *Stream 
= (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar
, CDC_Host_getchar
, _FDEV_SETUP_RW
); 
 387         fdev_set_udata(Stream
, CDCInterfaceInfo
); 
 390 void CDC_Host_CreateBlockingStream(USB_ClassInfo_CDC_Host_t
* CDCInterfaceInfo
, FILE* Stream
) 
 392         *Stream 
= (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar
, CDC_Host_getchar_Blocking
, _FDEV_SETUP_RW
); 
 393         fdev_set_udata(Stream
, CDCInterfaceInfo
); 
 396 static int CDC_Host_putchar(char c
, FILE* Stream
) 
 398         return CDC_Host_SendByte((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
), c
) ? _FDEV_ERR 
: 0; 
 401 static int CDC_Host_getchar(FILE* Stream
) 
 403         if (!(CDC_Host_BytesReceived((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)))) 
 406         return CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)); 
 409 static int CDC_Host_getchar_Blocking(FILE* Stream
) 
 411         while (!(CDC_Host_BytesReceived((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)))) 
 413                 if (USB_HostState 
== HOST_STATE_Unattached
) 
 416                 CDC_Host_USBTask((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)); 
 420         return CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)); 
 423 void CDC_Host_Event_Stub(void)