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 #include "../../HighLevel/USBMode.h" 
  32 #if defined(USB_CAN_BE_HOST) 
  34 #define  INCLUDE_FROM_CDC_CLASS_HOST_C 
  37 uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
, uint16_t ConfigDescriptorSize
, 
  38                                 void* ConfigDescriptorData
) 
  40         uint8_t FoundEndpoints 
= 0; 
  42         memset(&CDCInterfaceInfo
->State
, 0x00, sizeof(CDCInterfaceInfo
->State
)); 
  44         if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
) 
  45           return CDC_ENUMERROR_InvalidConfigDescriptor
; 
  47         if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  48                                       DComp_CDC_Host_NextCDCControlInterface
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  50                 return CDC_ENUMERROR_NoCDCInterfaceFound
; 
  53         CDCInterfaceInfo
->State
.ControlInterfaceNumber 
= DESCRIPTOR_CAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
).InterfaceNumber
; 
  55         while (FoundEndpoints 
!= (CDC_FOUND_NOTIFICATION_IN 
| CDC_FOUND_DATAPIPE_IN 
| CDC_FOUND_DATAPIPE_OUT
)) 
  57                 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  58                                               DComp_CDC_Host_NextCDCInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  60                         if (FoundEndpoints 
& CDC_FOUND_NOTIFICATION_IN
) 
  62                                 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,  
  63                                                               DComp_CDC_Host_NextCDCDataInterface
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  65                                         return CDC_ENUMERROR_NoCDCInterfaceFound
; 
  72                                 Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataINPipeNumber
); 
  74                                 Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataOUTPipeNumber
); 
  76                                 Pipe_SelectPipe(CDCInterfaceInfo
->Config
.NotificationPipeNumber
); 
  79                                 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  80                                                               DComp_CDC_Host_NextCDCControlInterface
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  82                                         return CDC_ENUMERROR_NoCDCInterfaceFound
; 
  86                         if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  87                                                       DComp_CDC_Host_NextCDCInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  89                                 return CDC_ENUMERROR_EndpointsNotFound
; 
  93                 USB_Descriptor_Endpoint_t
* EndpointData 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
); 
  95                 if ((EndpointData
->Attributes 
& EP_TYPE_MASK
) == EP_TYPE_INTERRUPT
) 
  97                         if (EndpointData
->EndpointAddress 
& ENDPOINT_DESCRIPTOR_DIR_IN
) 
  99                                 Pipe_ConfigurePipe(CDCInterfaceInfo
->Config
.NotificationPipeNumber
, EP_TYPE_INTERRUPT
, PIPE_TOKEN_IN
, 
 100                                                                    EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
, 
 101                                                                    CDCInterfaceInfo
->Config
.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE 
: PIPE_BANK_SINGLE
); 
 102                                 CDCInterfaceInfo
->State
.NotificationPipeSize 
= EndpointData
->EndpointSize
; 
 104                                 Pipe_SetInterruptPeriod(EndpointData
->PollingIntervalMS
); 
 106                                 FoundEndpoints 
|= CDC_FOUND_NOTIFICATION_IN
; 
 111                         if (EndpointData
->EndpointAddress 
& ENDPOINT_DESCRIPTOR_DIR_IN
) 
 113                                 Pipe_ConfigurePipe(CDCInterfaceInfo
->Config
.DataINPipeNumber
, EP_TYPE_BULK
, PIPE_TOKEN_IN
, 
 114                                                    EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
,  
 115                                                    CDCInterfaceInfo
->Config
.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE 
: PIPE_BANK_SINGLE
); 
 117                                 CDCInterfaceInfo
->State
.DataINPipeSize 
= EndpointData
->EndpointSize
; 
 119                                 FoundEndpoints 
|= CDC_FOUND_DATAPIPE_IN
; 
 123                                 Pipe_ConfigurePipe(CDCInterfaceInfo
->Config
.DataOUTPipeNumber
, EP_TYPE_BULK
, PIPE_TOKEN_OUT
, 
 124                                                                    EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
,  
 125                                                                    CDCInterfaceInfo
->Config
.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE 
: PIPE_BANK_SINGLE
); 
 127                                 CDCInterfaceInfo
->State
.DataOUTPipeSize 
= EndpointData
->EndpointSize
; 
 129                                 FoundEndpoints 
|= CDC_FOUND_DATAPIPE_OUT
; 
 134         CDCInterfaceInfo
->State
.ControlLineStates
.HostToDevice 
= (CDC_CONTROL_LINE_OUT_RTS 
| CDC_CONTROL_LINE_OUT_DTR
); 
 135         CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost 
= (CDC_CONTROL_LINE_IN_DCD  
| CDC_CONTROL_LINE_IN_DSR
); 
 136         CDCInterfaceInfo
->State
.IsActive 
= true; 
 137         return CDC_ENUMERROR_NoError
; 
 140 static uint8_t DComp_CDC_Host_NextCDCControlInterface(void* const CurrentDescriptor
) 
 142         if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
) 
 144                 USB_Descriptor_Interface_t
* CurrentInterface 
= DESCRIPTOR_PCAST(CurrentDescriptor
, 
 145                                                                                 USB_Descriptor_Interface_t
); 
 147                 if ((CurrentInterface
->Class    
== CDC_CONTROL_CLASS
)    && 
 148                     (CurrentInterface
->SubClass 
== CDC_CONTROL_SUBCLASS
) && 
 149                         (CurrentInterface
->Protocol 
== CDC_CONTROL_PROTOCOL
)) 
 151                         return DESCRIPTOR_SEARCH_Found
; 
 155         return DESCRIPTOR_SEARCH_NotFound
; 
 158 static uint8_t DComp_CDC_Host_NextCDCDataInterface(void* const CurrentDescriptor
) 
 160         if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
) 
 162                 USB_Descriptor_Interface_t
* CurrentInterface 
= DESCRIPTOR_PCAST(CurrentDescriptor
, 
 163                                                                                 USB_Descriptor_Interface_t
); 
 165                 if ((CurrentInterface
->Class    
== CDC_DATA_CLASS
)    && 
 166                     (CurrentInterface
->SubClass 
== CDC_DATA_SUBCLASS
) && 
 167                         (CurrentInterface
->Protocol 
== CDC_DATA_PROTOCOL
)) 
 169                         return DESCRIPTOR_SEARCH_Found
; 
 173         return DESCRIPTOR_SEARCH_NotFound
; 
 176 static uint8_t DComp_CDC_Host_NextCDCInterfaceEndpoint(void* const CurrentDescriptor
) 
 178         if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Endpoint
) 
 180                 USB_Descriptor_Endpoint_t
* CurrentEndpoint 
= DESCRIPTOR_PCAST(CurrentDescriptor
, 
 181                                                                               USB_Descriptor_Endpoint_t
); 
 183                 uint8_t EndpointType 
= (CurrentEndpoint
->Attributes 
& EP_TYPE_MASK
); 
 185                 if ((EndpointType 
== EP_TYPE_BULK
) || (EndpointType 
== EP_TYPE_INTERRUPT
)) 
 187                         return DESCRIPTOR_SEARCH_Found
; 
 190         else if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
) 
 192                 return DESCRIPTOR_SEARCH_Fail
; 
 195         return DESCRIPTOR_SEARCH_NotFound
; 
 198 void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 200         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 203         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.NotificationPipeNumber
); 
 204         Pipe_SetPipeToken(PIPE_TOKEN_IN
); 
 207         if (Pipe_IsINReceived()) 
 209                 USB_Request_Header_t Notification
; 
 210                 Pipe_Read_Stream_LE(&Notification
, sizeof(USB_Request_Header_t
), NO_STREAM_CALLBACK
); 
 212                 if ((Notification
.bRequest      
== NOTIF_SerialState
) && 
 213                     (Notification
.bmRequestType 
== (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
))) 
 215                         Pipe_Read_Stream_LE(&CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost
, 
 216                                             sizeof(CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost
), 
 223                 EVENT_CDC_Host_ControLineStateChanged(CDCInterfaceInfo
); 
 229 uint8_t CDC_Host_SetLineEncoding(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 231         USB_ControlRequest 
= (USB_Request_Header_t
) 
 233                 .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 234                 .bRequest      
= REQ_SetLineEncoding
, 
 236                 .wIndex        
= CDCInterfaceInfo
->State
.ControlInterfaceNumber
, 
 237                 .wLength       
= sizeof(CDCInterfaceInfo
->State
.LineEncoding
), 
 240         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 242         return USB_Host_SendControlRequest(&CDCInterfaceInfo
->State
.LineEncoding
); 
 245 uint8_t CDC_Host_SendControlLineStateChange(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 247         USB_ControlRequest 
= (USB_Request_Header_t
) 
 249                 .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 250                 .bRequest      
= REQ_SetControlLineState
, 
 251                 .wValue        
= CDCInterfaceInfo
->State
.ControlLineStates
.HostToDevice
, 
 252                 .wIndex        
= CDCInterfaceInfo
->State
.ControlInterfaceNumber
, 
 256         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 258         return USB_Host_SendControlRequest(NULL
); 
 261 uint8_t CDC_Host_SendString(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
, char* Data
, const uint16_t Length
) 
 263         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 264           return PIPE_READYWAIT_DeviceDisconnected
; 
 268         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataOUTPipeNumber
);     
 271         ErrorCode 
= Pipe_Write_Stream_LE(Data
, Length
, NO_STREAM_CALLBACK
); 
 277 uint8_t CDC_Host_SendByte(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
, const uint8_t Data
) 
 279         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 280           return PIPE_READYWAIT_DeviceDisconnected
; 
 284         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataOUTPipeNumber
);     
 287         if (!(Pipe_IsReadWriteAllowed())) 
 291                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 295         Pipe_Write_Byte(Data
);   
 298         return PIPE_READYWAIT_NoError
; 
 301 uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 303         uint16_t BytesInPipe 
= 0; 
 305         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 308         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataINPipeNumber
); 
 309         Pipe_SetPipeToken(PIPE_TOKEN_IN
); 
 312         if (Pipe_IsINReceived()) 
 314                 if (!(Pipe_BytesInPipe())) 
 317                 BytesInPipe 
= Pipe_BytesInPipe(); 
 330 uint8_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 332         uint8_t ReceivedByte 
= 0; 
 334         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 337         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataINPipeNumber
); 
 338         Pipe_SetPipeToken(PIPE_TOKEN_IN
); 
 341         ReceivedByte 
= Pipe_Read_Byte(); 
 343         if (!(Pipe_BytesInPipe())) 
 351 uint8_t CDC_Host_Flush(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 353         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 354           return PIPE_READYWAIT_DeviceDisconnected
; 
 358         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataOUTPipeNumber
);     
 361         if (!(Pipe_BytesInPipe())) 
 362           return PIPE_READYWAIT_NoError
; 
 364         bool BankFull 
= !(Pipe_IsReadWriteAllowed()); 
 370                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 378         return PIPE_READYWAIT_NoError
; 
 381 void CDC_Host_CreateStream(USB_ClassInfo_CDC_Host_t
* CDCInterfaceInfo
, FILE* Stream
) 
 383         *Stream 
= (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar
, CDC_Host_getchar
, _FDEV_SETUP_RW
); 
 384         fdev_set_udata(Stream
, CDCInterfaceInfo
); 
 387 void CDC_Host_CreateBlockingStream(USB_ClassInfo_CDC_Host_t
* CDCInterfaceInfo
, FILE* Stream
) 
 389         *Stream 
= (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar
, CDC_Host_getchar_Blocking
, _FDEV_SETUP_RW
); 
 390         fdev_set_udata(Stream
, CDCInterfaceInfo
); 
 393 static int CDC_Host_putchar(char c
, FILE* Stream
) 
 395         return CDC_Host_SendByte((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
), c
) ? _FDEV_ERR 
: 0; 
 398 static int CDC_Host_getchar(FILE* Stream
) 
 400         if (!(CDC_Host_BytesReceived((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)))) 
 403         return CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)); 
 406 static int CDC_Host_getchar_Blocking(FILE* Stream
) 
 408         while (!(CDC_Host_BytesReceived((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)))) 
 410                 if (USB_HostState 
== HOST_STATE_Unattached
) 
 413                 CDC_Host_USBTask((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)); 
 417         return CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)); 
 420 void CDC_Host_Event_Stub(void)