3      Copyright (C) Dean Camera, 2009. 
   5   dean [at] fourwalledcubicle [dot] com 
   6       www.fourwalledcubicle.com 
  10   Copyright 2009  Dean Camera (dean [at] fourwalledcubicle [dot] com) 
  12   Permission to use, copy, modify, and distribute this software 
  13   and its documentation for any purpose and without fee is hereby 
  14   granted, provided that the above copyright notice appear in all 
  15   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
); 
 116                                 CDCInterfaceInfo
->State
.DataINPipeSize 
= EndpointData
->EndpointSize
; 
 118                                 FoundEndpoints 
|= CDC_FOUND_DATAPIPE_IN
; 
 122                                 Pipe_ConfigurePipe(CDCInterfaceInfo
->Config
.DataOUTPipeNumber
, EP_TYPE_BULK
, PIPE_TOKEN_OUT
, 
 123                                                                    EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
,  
 124                                                                    CDCInterfaceInfo
->Config
.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE 
: PIPE_BANK_SINGLE
); 
 125                                 CDCInterfaceInfo
->State
.DataOUTPipeSize 
= EndpointData
->EndpointSize
; 
 127                                 FoundEndpoints 
|= CDC_FOUND_DATAPIPE_OUT
; 
 132         CDCInterfaceInfo
->State
.ControlLineStates
.HostToDevice 
= (CDC_CONTROL_LINE_OUT_RTS 
| CDC_CONTROL_LINE_OUT_DTR
); 
 133         CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost 
= (CDC_CONTROL_LINE_IN_DCD  
| CDC_CONTROL_LINE_IN_DSR
); 
 134         CDCInterfaceInfo
->State
.IsActive 
= true; 
 135         return CDC_ENUMERROR_NoError
; 
 138 static uint8_t DComp_CDC_Host_NextCDCControlInterface(void* const CurrentDescriptor
) 
 140         if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
) 
 142                 USB_Descriptor_Interface_t
* CurrentInterface 
= DESCRIPTOR_PCAST(CurrentDescriptor
, 
 143                                                                                 USB_Descriptor_Interface_t
); 
 145                 if ((CurrentInterface
->Class    
== CDC_CONTROL_CLASS
)    && 
 146                     (CurrentInterface
->SubClass 
== CDC_CONTROL_SUBCLASS
) && 
 147                         (CurrentInterface
->Protocol 
== CDC_CONTROL_PROTOCOL
)) 
 149                         return DESCRIPTOR_SEARCH_Found
; 
 153         return DESCRIPTOR_SEARCH_NotFound
; 
 156 static uint8_t DComp_CDC_Host_NextCDCDataInterface(void* const CurrentDescriptor
) 
 158         if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
) 
 160                 USB_Descriptor_Interface_t
* CurrentInterface 
= DESCRIPTOR_PCAST(CurrentDescriptor
, 
 161                                                                                 USB_Descriptor_Interface_t
); 
 163                 if ((CurrentInterface
->Class    
== CDC_DATA_CLASS
)    && 
 164                     (CurrentInterface
->SubClass 
== CDC_DATA_SUBCLASS
) && 
 165                         (CurrentInterface
->Protocol 
== CDC_DATA_PROTOCOL
)) 
 167                         return DESCRIPTOR_SEARCH_Found
; 
 171         return DESCRIPTOR_SEARCH_NotFound
; 
 174 static uint8_t DComp_CDC_Host_NextCDCInterfaceEndpoint(void* const CurrentDescriptor
) 
 176         if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Endpoint
) 
 178                 USB_Descriptor_Endpoint_t
* CurrentEndpoint 
= DESCRIPTOR_PCAST(CurrentDescriptor
, 
 179                                                                               USB_Descriptor_Endpoint_t
); 
 181                 uint8_t EndpointType 
= (CurrentEndpoint
->Attributes 
& EP_TYPE_MASK
); 
 183                 if (((EndpointType 
== EP_TYPE_BULK
) || (EndpointType 
== EP_TYPE_INTERRUPT
)) && 
 184                     !(Pipe_IsEndpointBound(CurrentEndpoint
->EndpointAddress
))) 
 186                         return DESCRIPTOR_SEARCH_Found
; 
 189         else if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
) 
 191                 return DESCRIPTOR_SEARCH_Fail
; 
 194         return DESCRIPTOR_SEARCH_NotFound
; 
 197 void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 199         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 202         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.NotificationPipeNumber
);        
 205         if (Pipe_IsINReceived()) 
 207                 USB_Request_Header_t Notification
; 
 208                 Pipe_Read_Stream_LE(&Notification
, sizeof(USB_Request_Header_t
), NO_STREAM_CALLBACK
); 
 210                 if ((Notification
.bRequest      
== NOTIF_SerialState
) && 
 211                     (Notification
.bmRequestType 
== (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
))) 
 213                         Pipe_Read_Stream_LE(&CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost
, 
 214                                             sizeof(CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost
), 
 221                 EVENT_CDC_Host_ControLineStateChanged(CDCInterfaceInfo
); 
 227 uint8_t CDC_Host_SetLineEncoding(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 229         USB_ControlRequest 
= (USB_Request_Header_t
) 
 231                 .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 232                 .bRequest      
= REQ_SetLineEncoding
, 
 234                 .wIndex        
= CDCInterfaceInfo
->State
.ControlInterfaceNumber
, 
 235                 .wLength       
= sizeof(CDCInterfaceInfo
->State
.LineEncoding
), 
 238         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 240         return USB_Host_SendControlRequest(&CDCInterfaceInfo
->State
.LineEncoding
); 
 243 uint8_t CDC_Host_SendControlLineStateChange(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 245         USB_ControlRequest 
= (USB_Request_Header_t
) 
 247                 .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 248                 .bRequest      
= REQ_SetControlLineState
, 
 249                 .wValue        
= CDCInterfaceInfo
->State
.ControlLineStates
.HostToDevice
, 
 250                 .wIndex        
= CDCInterfaceInfo
->State
.ControlInterfaceNumber
, 
 254         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 256         return USB_Host_SendControlRequest(NULL
); 
 259 uint8_t CDC_Host_SendString(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
, char* Data
, const uint16_t Length
) 
 261         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 262           return PIPE_READYWAIT_NoError
; 
 266         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataOUTPipeNumber
);     
 268         ErrorCode 
= Pipe_Write_Stream_LE(Data
, Length
, NO_STREAM_CALLBACK
); 
 274 uint8_t CDC_Host_SendByte(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
, const uint8_t Data
) 
 276         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 277           return PIPE_READYWAIT_NoError
;; 
 281         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataOUTPipeNumber
);     
 284         if (!(Pipe_IsReadWriteAllowed())) 
 288                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 292         Pipe_Write_Byte(Data
);   
 295         return PIPE_READYWAIT_NoError
; 
 298 uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 300         uint16_t BytesInPipe 
= 0; 
 302         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 305         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataINPipeNumber
);      
 308         if (Pipe_IsINReceived() && !(Pipe_BytesInPipe())) 
 311         BytesInPipe 
= Pipe_BytesInPipe(); 
 317 uint8_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t
* const CDCInterfaceInfo
) 
 319         uint8_t ReceivedByte 
= 0; 
 321         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(CDCInterfaceInfo
->State
.IsActive
)) 
 324         Pipe_SelectPipe(CDCInterfaceInfo
->Config
.DataINPipeNumber
);      
 327         ReceivedByte 
= Pipe_Read_Byte(); 
 329         if (!(Pipe_BytesInPipe())) 
 337 void CDC_Host_CreateStream(USB_ClassInfo_CDC_Host_t
* CDCInterfaceInfo
, FILE* Stream
) 
 339         *Stream 
= (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar
, CDC_Host_getchar
, _FDEV_SETUP_RW
); 
 340         fdev_set_udata(Stream
, CDCInterfaceInfo
); 
 343 void CDC_Host_CreateBlockingStream(USB_ClassInfo_CDC_Host_t
* CDCInterfaceInfo
, FILE* Stream
) 
 345         *Stream 
= (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar
, CDC_Host_getchar_Blocking
, _FDEV_SETUP_RW
); 
 346         fdev_set_udata(Stream
, CDCInterfaceInfo
); 
 349 static int CDC_Host_putchar(char c
, FILE* Stream
) 
 351         return CDC_Host_SendByte((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
), c
) ? _FDEV_ERR 
: 0; 
 354 static int CDC_Host_getchar(FILE* Stream
) 
 356         if (!(CDC_Host_BytesReceived((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)))) 
 359         return CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)); 
 362 static int CDC_Host_getchar_Blocking(FILE* Stream
) 
 364         while (!(CDC_Host_BytesReceived((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)))) 
 366                 CDC_Host_USBTask((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)); 
 370         return CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t
*)fdev_get_udata(Stream
)); 
 373 void CDC_Host_Event_Stub(void)