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
)) && 
 186                     !(Pipe_IsEndpointBound(CurrentEndpoint
->EndpointAddress
))) 
 188                         return DESCRIPTOR_SEARCH_Found
; 
 191         else if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
) 
 193                 return DESCRIPTOR_SEARCH_Fail
; 
 196         return DESCRIPTOR_SEARCH_NotFound
; 
 199 void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 201         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 204         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.NotificationPipeNumber
); 
 205         Pipe_SetPipeToken(PIPE_TOKEN_IN
); 
 208         if (Pipe_IsINReceived()) 
 210                 USB_Request_Header_t Notification
; 
 211                 Pipe_Read_Stream_LE(&Notification
, sizeof(USB_Request_Header_t
), NO_STREAM_CALLBACK
); 
 213                 if ((Notification
.bRequest      
== NOTIF_SerialState
) && 
 214                     (Notification
.bmRequestType 
== (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
))) 
 216                         Pipe_Read_Stream_LE(&CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost
, 
 217                                             sizeof(CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost
), 
 224                 EVENT_CDC_Host_ControLineStateChanged(CDCInterfaceInfo
); 
 230 uint8_t CDC_Host_SetLineEncoding(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 232         USB_ControlRequest 
= (USB_Request_Header_t
) 
 234                 .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 235                 .bRequest      
= REQ_SetLineEncoding
, 
 237                 .wIndex        
= CDCInterfaceInfo
->State
.ControlInterfaceNumber
, 
 238                 .wLength       
= sizeof(CDCInterfaceInfo
->State
.LineEncoding
), 
 241         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 243         return USB_Host_SendControlRequest(&CDCInterfaceInfo
->State
.LineEncoding
); 
 246 uint8_t CDC_Host_SendControlLineStateChange(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 248         USB_ControlRequest 
= (USB_Request_Header_t
) 
 250                 .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 251                 .bRequest      
= REQ_SetControlLineState
, 
 252                 .wValue        
= CDCInterfaceInfo
->State
.ControlLineStates
.HostToDevice
, 
 253                 .wIndex        
= CDCInterfaceInfo
->State
.ControlInterfaceNumber
, 
 257         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 259         return USB_Host_SendControlRequest(NULL
); 
 262 uint8_t CDC_Host_SendString(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
, char* Data
, const uint16_t Length
) 
 264         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 265           return PIPE_READYWAIT_DeviceDisconnected
; 
 269         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataOUTPipeNumber
);     
 272         ErrorCode 
= Pipe_Write_Stream_LE(Data
, Length
, NO_STREAM_CALLBACK
); 
 278 uint8_t CDC_Host_SendByte(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
, const uint8_t Data
) 
 280         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 281           return PIPE_READYWAIT_DeviceDisconnected
; 
 285         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataOUTPipeNumber
);     
 288         if (!(Pipe_IsReadWriteAllowed())) 
 292                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 296         Pipe_Write_Byte(Data
);   
 299         return PIPE_READYWAIT_NoError
; 
 302 uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 304         uint16_t BytesInPipe 
= 0; 
 306         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 309         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataINPipeNumber
); 
 310         Pipe_SetPipeToken(PIPE_TOKEN_IN
); 
 313         if (Pipe_IsINReceived()) 
 315                 if (!(Pipe_BytesInPipe())) 
 318                 BytesInPipe 
= Pipe_BytesInPipe(); 
 331 uint8_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 333         uint8_t ReceivedByte 
= 0; 
 335         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 338         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataINPipeNumber
); 
 339         Pipe_SetPipeToken(PIPE_TOKEN_IN
); 
 342         ReceivedByte 
= Pipe_Read_Byte(); 
 344         if (!(Pipe_BytesInPipe())) 
 352 uint8_t CDC_Host_Flush(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 354         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 355           return PIPE_READYWAIT_DeviceDisconnected
; 
 359         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataOUTPipeNumber
);     
 362         if (!(Pipe_BytesInPipe())) 
 363           return PIPE_READYWAIT_NoError
; 
 365         bool BankFull 
= !(Pipe_IsReadWriteAllowed()); 
 371                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 379         return PIPE_READYWAIT_NoError
; 
 382 void CDC_Host_CreateStream(USB_ClassInfo_CDC_Host_t
* CDCInterfaceInfo
, FILE* Stream
) 
 384         *Stream 
= (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar
, CDC_Host_getchar
, _FDEV_SETUP_RW
); 
 385         fdev_set_udata(Stream
, CDCInterfaceInfo
); 
 388 void CDC_Host_CreateBlockingStream(USB_ClassInfo_CDC_Host_t
* CDCInterfaceInfo
, FILE* Stream
) 
 390         *Stream 
= (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar
, CDC_Host_getchar_Blocking
, _FDEV_SETUP_RW
); 
 391         fdev_set_udata(Stream
, CDCInterfaceInfo
); 
 394 static int CDC_Host_putchar(char c
, FILE* Stream
) 
 396         return CDC_Host_SendByte((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
), c
) ? _FDEV_ERR 
: 0; 
 399 static int CDC_Host_getchar(FILE* Stream
) 
 401         if (!(CDC_Host_BytesReceived((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)))) 
 404         return CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)); 
 407 static int CDC_Host_getchar_Blocking(FILE* Stream
) 
 409         while (!(CDC_Host_BytesReceived((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)))) 
 411                 if (USB_HostState 
== HOST_STATE_Unattached
) 
 414                 CDC_Host_USBTask((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)); 
 418         return CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)); 
 421 void CDC_Host_Event_Stub(void)