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
* CDCInterfaceInfo
) 
  46         if (!(Endpoint_IsSETUPReceived())) 
  49         if (USB_ControlRequest
.wIndex 
!= CDCInterfaceInfo
->Config
.ControlInterfaceNumber
) 
  52         switch (USB_ControlRequest
.bRequest
) 
  54                 case 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 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 REQ_SetControlLineState
: 
  75                         if (USB_ControlRequest
.bmRequestType 
== (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
)) 
  77                                 Endpoint_ClearSETUP(); 
  79                                 CDCInterfaceInfo
->State
.ControlLineStates
.HostToDevice 
= USB_ControlRequest
.wValue
; 
  81                                 EVENT_CDC_Device_ControLineStateChanged(CDCInterfaceInfo
); 
  83                                 Endpoint_ClearStatusStage(); 
  90 bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t
* CDCInterfaceInfo
) 
  92         memset(&CDCInterfaceInfo
->State
, 0x00, sizeof(CDCInterfaceInfo
->State
)); 
  94         if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo
->Config
.DataINEndpointNumber
, EP_TYPE_BULK
, 
  95                                                                  ENDPOINT_DIR_IN
, CDCInterfaceInfo
->Config
.DataINEndpointSize
, 
  96                                                                  CDCInterfaceInfo
->Config
.DataINEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE 
: ENDPOINT_BANK_SINGLE
))) 
 101         if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo
->Config
.DataOUTEndpointNumber
, EP_TYPE_BULK
, 
 102                                          ENDPOINT_DIR_OUT
, CDCInterfaceInfo
->Config
.DataOUTEndpointSize
, 
 103                                          CDCInterfaceInfo
->Config
.DataOUTEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE 
: ENDPOINT_BANK_SINGLE
))) 
 108         if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo
->Config
.NotificationEndpointNumber
, EP_TYPE_INTERRUPT
, 
 109                                          ENDPOINT_DIR_IN
, CDCInterfaceInfo
->Config
.NotificationEndpointSize
, 
 110                                          CDCInterfaceInfo
->Config
.NotificationEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE 
: ENDPOINT_BANK_SINGLE
))) 
 118 void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t
* CDCInterfaceInfo
) 
 120         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 123         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataOUTEndpointNumber
); 
 125         if (Endpoint_IsOUTReceived() && !(Endpoint_BytesInEndpoint())) 
 128         CDC_Device_Flush(CDCInterfaceInfo
); 
 131 uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
, char* const Data
, const uint16_t Length
) 
 133         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 134           return ENDPOINT_RWSTREAM_DeviceDisconnected
; 
 136         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataINEndpointNumber
); 
 137         return Endpoint_Write_Stream_LE(Data
, Length
, NO_STREAM_CALLBACK
); 
 140 uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
, const uint8_t Data
) 
 142         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 143           return ENDPOINT_RWSTREAM_DeviceDisconnected
; 
 145         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataINEndpointNumber
); 
 147         if (!(Endpoint_IsReadWriteAllowed())) 
 153                 if ((ErrorCode 
= Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError
) 
 157         Endpoint_Write_Byte(Data
); 
 158         return ENDPOINT_READYWAIT_NoError
; 
 161 uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
) 
 163         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 164           return ENDPOINT_RWSTREAM_DeviceDisconnected
; 
 168         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataINEndpointNumber
); 
 170         if (!(Endpoint_BytesInEndpoint())) 
 171           return ENDPOINT_READYWAIT_NoError
; 
 173         bool BankFull 
= !(Endpoint_IsReadWriteAllowed()); 
 179                 if ((ErrorCode 
= Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError
) 
 185         return ENDPOINT_READYWAIT_NoError
; 
 188 uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
) 
 190         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 193         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataOUTEndpointNumber
); 
 195         if (Endpoint_IsOUTReceived()) 
 197                 if (!(Endpoint_BytesInEndpoint())) 
 200                 return Endpoint_BytesInEndpoint(); 
 208 uint8_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t
* CDCInterfaceInfo
) 
 210         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 213         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataOUTEndpointNumber
); 
 215         uint8_t DataByte 
= Endpoint_Read_Byte(); 
 217         if (!(Endpoint_BytesInEndpoint())) 
 223 void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
) 
 225         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 228         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.NotificationEndpointNumber
); 
 230         USB_Request_Header_t Notification 
= (USB_Request_Header_t
) 
 232                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 233                         .bRequest      
= NOTIF_SerialState
, 
 236                         .wLength       
= sizeof(CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost
), 
 239         Endpoint_Write_Stream_LE(&Notification
, sizeof(USB_Request_Header_t
), NO_STREAM_CALLBACK
); 
 240         Endpoint_Write_Stream_LE(&CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost
, 
 241                                  sizeof(CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost
), 
 246 void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t
* CDCInterfaceInfo
, FILE* Stream
) 
 248         *Stream 
= (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar
, CDC_Device_getchar
, _FDEV_SETUP_RW
); 
 249         fdev_set_udata(Stream
, CDCInterfaceInfo
); 
 252 void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t
* CDCInterfaceInfo
, FILE* Stream
) 
 254         *Stream 
= (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar
, CDC_Device_getchar_Blocking
, _FDEV_SETUP_RW
); 
 255         fdev_set_udata(Stream
, CDCInterfaceInfo
); 
 258 static int CDC_Device_putchar(char c
, FILE* Stream
) 
 260         return CDC_Device_SendByte((USB_ClassInfo_CDC_Device_t
*)fdev_get_udata(Stream
), c
) ? _FDEV_ERR 
: 0; 
 263 static int CDC_Device_getchar(FILE* Stream
) 
 265         if (!(CDC_Device_BytesReceived((USB_ClassInfo_CDC_Device_t
*)fdev_get_udata(Stream
)))) 
 268         return CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t
*)fdev_get_udata(Stream
)); 
 271 static int CDC_Device_getchar_Blocking(FILE* Stream
) 
 273         while (!(CDC_Device_BytesReceived((USB_ClassInfo_CDC_Device_t
*)fdev_get_udata(Stream
)))) 
 275                 if (USB_DeviceState 
== DEVICE_STATE_Unattached
) 
 278                 CDC_Device_USBTask((USB_ClassInfo_CDC_Device_t
*)fdev_get_udata(Stream
)); 
 282         return CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t
*)fdev_get_udata(Stream
));