3      Copyright (C) Dean Camera, 2011. 
   5   dean [at] fourwalledcubicle [dot] com 
  10   Copyright 2011  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_DEVICE) 
  35 #define  __INCLUDE_FROM_CDC_DRIVER 
  36 #define  __INCLUDE_FROM_CDC_DEVICE_C 
  39 void CDC_Device_Event_Stub(void) 
  44 void CDC_Device_ProcessControlRequest(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
) 
  46         if (!(Endpoint_IsSETUPReceived())) 
  49         if (USB_ControlRequest
.wIndex 
!= CDCInterfaceInfo
->Config
.ControlInterfaceNumber
) 
  52         switch (USB_ControlRequest
.bRequest
) 
  54                 case CDC_REQ_GetLineEncoding
: 
  55                         if (USB_ControlRequest
.bmRequestType 
== (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
)) 
  57                                 Endpoint_ClearSETUP(); 
  58                                 Endpoint_Write_Control_Stream_LE(&CDCInterfaceInfo
->State
.LineEncoding
, sizeof(CDCInterfaceInfo
->State
.LineEncoding
)); 
  63                 case CDC_REQ_SetLineEncoding
: 
  64                         if (USB_ControlRequest
.bmRequestType 
== (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
)) 
  66                                 Endpoint_ClearSETUP(); 
  67                                 Endpoint_Read_Control_Stream_LE(&CDCInterfaceInfo
->State
.LineEncoding
, sizeof(CDCInterfaceInfo
->State
.LineEncoding
)); 
  70                                 EVENT_CDC_Device_LineEncodingChanged(CDCInterfaceInfo
); 
  74                 case CDC_REQ_SetControlLineState
: 
  75                         if (USB_ControlRequest
.bmRequestType 
== (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
)) 
  77                                 Endpoint_ClearSETUP(); 
  78                                 Endpoint_ClearStatusStage(); 
  80                                 CDCInterfaceInfo
->State
.ControlLineStates
.HostToDevice 
= USB_ControlRequest
.wValue
; 
  82                                 EVENT_CDC_Device_ControLineStateChanged(CDCInterfaceInfo
); 
  86                 case CDC_REQ_SendBreak
: 
  87                         if (USB_ControlRequest
.bmRequestType 
== (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
)) 
  89                                 Endpoint_ClearSETUP(); 
  90                                 Endpoint_ClearStatusStage(); 
  92                                 EVENT_CDC_Device_BreakSent(CDCInterfaceInfo
, (uint8_t)USB_ControlRequest
.wValue
); 
  99 bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
) 
 101         memset(&CDCInterfaceInfo
->State
, 0x00, sizeof(CDCInterfaceInfo
->State
)); 
 103         for (uint8_t EndpointNum 
= 1; EndpointNum 
< ENDPOINT_TOTAL_ENDPOINTS
; EndpointNum
++) 
 110                 if (EndpointNum 
== CDCInterfaceInfo
->Config
.DataINEndpointNumber
) 
 112                         Size         
= CDCInterfaceInfo
->Config
.DataINEndpointSize
; 
 113                         Direction    
= ENDPOINT_DIR_IN
; 
 115                         DoubleBanked 
= CDCInterfaceInfo
->Config
.DataINEndpointDoubleBank
; 
 117                 else if (EndpointNum 
== CDCInterfaceInfo
->Config
.DataOUTEndpointNumber
) 
 119                         Size         
= CDCInterfaceInfo
->Config
.DataOUTEndpointSize
; 
 120                         Direction    
= ENDPOINT_DIR_OUT
; 
 122                         DoubleBanked 
= CDCInterfaceInfo
->Config
.DataOUTEndpointDoubleBank
; 
 124                 else if (EndpointNum 
== CDCInterfaceInfo
->Config
.NotificationEndpointNumber
) 
 126                         Size         
= CDCInterfaceInfo
->Config
.NotificationEndpointSize
; 
 127                         Direction    
= ENDPOINT_DIR_IN
; 
 128                         Type         
= EP_TYPE_INTERRUPT
; 
 129                         DoubleBanked 
= CDCInterfaceInfo
->Config
.NotificationEndpointDoubleBank
; 
 136                 if (!(Endpoint_ConfigureEndpoint(EndpointNum
, Type
, Direction
, Size
, 
 137                                                  DoubleBanked ? ENDPOINT_BANK_DOUBLE 
: ENDPOINT_BANK_SINGLE
))) 
 146 void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
) 
 148         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 151         #if !defined(NO_CLASS_DRIVER_AUTOFLUSH) 
 152         CDC_Device_Flush(CDCInterfaceInfo
); 
 156 uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
, 
 157                               const char* const String
) 
 159         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 160           return ENDPOINT_RWSTREAM_DeviceDisconnected
; 
 162         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataINEndpointNumber
); 
 163         return Endpoint_Write_Stream_LE(String
, strlen(String
), NULL
); 
 166 uint8_t CDC_Device_SendData(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
, 
 167                             const char* const Buffer
, 
 168                             const uint16_t Length
) 
 170         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 171           return ENDPOINT_RWSTREAM_DeviceDisconnected
; 
 173         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataINEndpointNumber
); 
 174         return Endpoint_Write_Stream_LE(Buffer
, Length
, NULL
); 
 177 uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
, 
 180         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 181           return ENDPOINT_RWSTREAM_DeviceDisconnected
; 
 183         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataINEndpointNumber
); 
 185         if (!(Endpoint_IsReadWriteAllowed())) 
 191                 if ((ErrorCode 
= Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError
) 
 195         Endpoint_Write_Byte(Data
); 
 196         return ENDPOINT_READYWAIT_NoError
; 
 199 uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
) 
 201         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 202           return ENDPOINT_RWSTREAM_DeviceDisconnected
; 
 206         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataINEndpointNumber
); 
 208         if (!(Endpoint_BytesInEndpoint())) 
 209           return ENDPOINT_READYWAIT_NoError
; 
 211         bool BankFull 
= !(Endpoint_IsReadWriteAllowed()); 
 217                 if ((ErrorCode 
= Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError
) 
 223         return ENDPOINT_READYWAIT_NoError
; 
 226 uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
) 
 228         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 231         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataOUTEndpointNumber
); 
 233         if (Endpoint_IsOUTReceived()) 
 235                 if (!(Endpoint_BytesInEndpoint())) 
 242                         return Endpoint_BytesInEndpoint(); 
 251 int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
) 
 253         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 256         int16_t ReceivedByte 
= -1; 
 258         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataOUTEndpointNumber
); 
 260         if (Endpoint_IsOUTReceived()) 
 262                 if (Endpoint_BytesInEndpoint()) 
 263                   ReceivedByte 
= Endpoint_Read_Byte(); 
 265                 if (!(Endpoint_BytesInEndpoint())) 
 272 void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
) 
 274         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 277         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.NotificationEndpointNumber
); 
 279         USB_Request_Header_t Notification 
= (USB_Request_Header_t
) 
 281                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 282                         .bRequest      
= CDC_NOTIF_SerialState
, 
 285                         .wLength       
= sizeof(CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost
), 
 288         Endpoint_Write_Stream_LE(&Notification
, sizeof(USB_Request_Header_t
), NULL
); 
 289         Endpoint_Write_Stream_LE(&CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost
, 
 290                                  sizeof(CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost
), 
 295 void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
, 
 298         *Stream 
= (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar
, CDC_Device_getchar
, _FDEV_SETUP_RW
); 
 299         fdev_set_udata(Stream
, CDCInterfaceInfo
); 
 302 void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
, 
 305         *Stream 
= (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar
, CDC_Device_getchar_Blocking
, _FDEV_SETUP_RW
); 
 306         fdev_set_udata(Stream
, CDCInterfaceInfo
); 
 309 static int CDC_Device_putchar(char c
, 
 312         return CDC_Device_SendByte((USB_ClassInfo_CDC_Device_t
*)fdev_get_udata(Stream
), c
) ? _FDEV_ERR 
: 0; 
 315 static int CDC_Device_getchar(FILE* Stream
) 
 317         int16_t ReceivedByte 
= CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t
*)fdev_get_udata(Stream
)); 
 319         if (ReceivedByte 
< 0) 
 325 static int CDC_Device_getchar_Blocking(FILE* Stream
) 
 327         int16_t ReceivedByte
; 
 329         while ((ReceivedByte 
= CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t
*)fdev_get_udata(Stream
))) < 0) 
 331                 if (USB_DeviceState 
== DEVICE_STATE_Unattached
) 
 334                 CDC_Device_USBTask((USB_ClassInfo_CDC_Device_t
*)fdev_get_udata(Stream
));