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_DEVICE) 
  35 #define  __INCLUDE_FROM_CDC_CLASS_DEVICE_C 
  36 #define  __INCLUDE_FROM_CDC_DRIVER 
  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         CDC_Device_Flush(CDCInterfaceInfo
); 
 154 uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
, 
 155                               const char* const Data
, 
 156                               const uint16_t Length
) 
 158         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 159           return ENDPOINT_RWSTREAM_DeviceDisconnected
; 
 161         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataINEndpointNumber
); 
 162         return Endpoint_Write_Stream_LE(Data
, Length
, NO_STREAM_CALLBACK
); 
 165 uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
, 
 168         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 169           return ENDPOINT_RWSTREAM_DeviceDisconnected
; 
 171         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataINEndpointNumber
); 
 173         if (!(Endpoint_IsReadWriteAllowed())) 
 179                 if ((ErrorCode 
= Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError
) 
 183         Endpoint_Write_Byte(Data
); 
 184         return ENDPOINT_READYWAIT_NoError
; 
 187 uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
) 
 189         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 190           return ENDPOINT_RWSTREAM_DeviceDisconnected
; 
 194         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataINEndpointNumber
); 
 196         if (!(Endpoint_BytesInEndpoint())) 
 197           return ENDPOINT_READYWAIT_NoError
; 
 199         bool BankFull 
= !(Endpoint_IsReadWriteAllowed()); 
 205                 if ((ErrorCode 
= Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError
) 
 211         return ENDPOINT_READYWAIT_NoError
; 
 214 uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
) 
 216         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 219         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataOUTEndpointNumber
); 
 221         if (Endpoint_IsOUTReceived()) 
 223                 if (!(Endpoint_BytesInEndpoint())) 
 230                         return Endpoint_BytesInEndpoint(); 
 239 int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
) 
 241         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 244         int16_t ReceivedByte 
= -1; 
 246         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataOUTEndpointNumber
); 
 248         if (Endpoint_IsOUTReceived()) 
 250                 if (Endpoint_BytesInEndpoint()) 
 251                   ReceivedByte 
= Endpoint_Read_Byte(); 
 253                 if (!(Endpoint_BytesInEndpoint())) 
 260 void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
) 
 262         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 265         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.NotificationEndpointNumber
); 
 267         USB_Request_Header_t Notification 
= (USB_Request_Header_t
) 
 269                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 270                         .bRequest      
= CDC_NOTIF_SerialState
, 
 273                         .wLength       
= sizeof(CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost
), 
 276         Endpoint_Write_Stream_LE(&Notification
, sizeof(USB_Request_Header_t
), NO_STREAM_CALLBACK
); 
 277         Endpoint_Write_Stream_LE(&CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost
, 
 278                                  sizeof(CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost
), 
 283 void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
, 
 286         *Stream 
= (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar
, CDC_Device_getchar
, _FDEV_SETUP_RW
); 
 287         fdev_set_udata(Stream
, CDCInterfaceInfo
); 
 290 void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
, 
 293         *Stream 
= (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar
, CDC_Device_getchar_Blocking
, _FDEV_SETUP_RW
); 
 294         fdev_set_udata(Stream
, CDCInterfaceInfo
); 
 297 static int CDC_Device_putchar(char c
, 
 300         return CDC_Device_SendByte((USB_ClassInfo_CDC_Device_t
*)fdev_get_udata(Stream
), c
) ? _FDEV_ERR 
: 0; 
 303 static int CDC_Device_getchar(FILE* Stream
) 
 305         int16_t ReceivedByte 
= CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t
*)fdev_get_udata(Stream
)); 
 307         if (ReceivedByte 
< 0) 
 313 static int CDC_Device_getchar_Blocking(FILE* Stream
) 
 315         int16_t ReceivedByte
; 
 317         while ((ReceivedByte 
= CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t
*)fdev_get_udata(Stream
))) < 0) 
 319                 if (USB_DeviceState 
== DEVICE_STATE_Unattached
) 
 322                 CDC_Device_USBTask((USB_ClassInfo_CDC_Device_t
*)fdev_get_udata(Stream
));