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
)); 
  68                                 EVENT_CDC_Device_LineEncodingChanged(CDCInterfaceInfo
); 
  73                 case REQ_SetControlLineState
: 
  74                         if (USB_ControlRequest
.bmRequestType 
== (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
)) 
  76                                 Endpoint_ClearSETUP(); 
  78                                 CDCInterfaceInfo
->State
.ControlLineStates
.HostToDevice 
= USB_ControlRequest
.wValue
; 
  79                                 EVENT_CDC_Device_ControLineStateChanged(CDCInterfaceInfo
); 
  81                                 Endpoint_ClearStatusStage(); 
  86                         if (USB_ControlRequest
.bmRequestType 
== (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
)) 
  88                                 Endpoint_ClearSETUP(); 
  90                                 EVENT_CDC_Device_BreakSent(CDCInterfaceInfo
, (uint8_t)USB_ControlRequest
.wValue
); 
  92                                 Endpoint_ClearStatusStage(); 
  99 bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t
* CDCInterfaceInfo
) 
 101         memset(&CDCInterfaceInfo
->State
, 0x00, sizeof(CDCInterfaceInfo
->State
)); 
 103         if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo
->Config
.DataINEndpointNumber
, EP_TYPE_BULK
, 
 104                                                                  ENDPOINT_DIR_IN
, CDCInterfaceInfo
->Config
.DataINEndpointSize
, 
 105                                                                  CDCInterfaceInfo
->Config
.DataINEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE 
: ENDPOINT_BANK_SINGLE
))) 
 110         if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo
->Config
.DataOUTEndpointNumber
, EP_TYPE_BULK
, 
 111                                          ENDPOINT_DIR_OUT
, CDCInterfaceInfo
->Config
.DataOUTEndpointSize
, 
 112                                          CDCInterfaceInfo
->Config
.DataOUTEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE 
: ENDPOINT_BANK_SINGLE
))) 
 117         if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo
->Config
.NotificationEndpointNumber
, EP_TYPE_INTERRUPT
, 
 118                                          ENDPOINT_DIR_IN
, CDCInterfaceInfo
->Config
.NotificationEndpointSize
, 
 119                                          CDCInterfaceInfo
->Config
.NotificationEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE 
: ENDPOINT_BANK_SINGLE
))) 
 127 void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t
* CDCInterfaceInfo
) 
 129         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 132         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataOUTEndpointNumber
); 
 134         if (Endpoint_IsOUTReceived() && !(Endpoint_BytesInEndpoint())) 
 137         CDC_Device_Flush(CDCInterfaceInfo
); 
 140 uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
, char* const Data
, const uint16_t Length
) 
 142         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 143           return ENDPOINT_RWSTREAM_DeviceDisconnected
; 
 145         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataINEndpointNumber
); 
 146         return Endpoint_Write_Stream_LE(Data
, Length
, NO_STREAM_CALLBACK
); 
 149 uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
, const uint8_t Data
) 
 151         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 152           return ENDPOINT_RWSTREAM_DeviceDisconnected
; 
 154         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataINEndpointNumber
); 
 156         if (!(Endpoint_IsReadWriteAllowed())) 
 162                 if ((ErrorCode 
= Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError
) 
 166         Endpoint_Write_Byte(Data
); 
 167         return ENDPOINT_READYWAIT_NoError
; 
 170 uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
) 
 172         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 173           return ENDPOINT_RWSTREAM_DeviceDisconnected
; 
 177         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataINEndpointNumber
); 
 179         if (!(Endpoint_BytesInEndpoint())) 
 180           return ENDPOINT_READYWAIT_NoError
; 
 182         bool BankFull 
= !(Endpoint_IsReadWriteAllowed()); 
 188                 if ((ErrorCode 
= Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError
) 
 194         return ENDPOINT_READYWAIT_NoError
; 
 197 uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
) 
 199         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 202         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataOUTEndpointNumber
); 
 204         if (Endpoint_IsOUTReceived()) 
 206                 if (!(Endpoint_BytesInEndpoint())) 
 213                         return Endpoint_BytesInEndpoint(); 
 222 uint8_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t
* CDCInterfaceInfo
) 
 224         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 227         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.DataOUTEndpointNumber
); 
 229         uint8_t DataByte 
= Endpoint_Read_Byte(); 
 231         if (!(Endpoint_BytesInEndpoint())) 
 237 void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t
* const CDCInterfaceInfo
) 
 239         if ((USB_DeviceState 
!= DEVICE_STATE_Configured
) || !(CDCInterfaceInfo
->State
.LineEncoding
.BaudRateBPS
)) 
 242         Endpoint_SelectEndpoint(CDCInterfaceInfo
->Config
.NotificationEndpointNumber
); 
 244         USB_Request_Header_t Notification 
= (USB_Request_Header_t
) 
 246                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 247                         .bRequest      
= NOTIF_SerialState
, 
 250                         .wLength       
= sizeof(CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost
), 
 253         Endpoint_Write_Stream_LE(&Notification
, sizeof(USB_Request_Header_t
), NO_STREAM_CALLBACK
); 
 254         Endpoint_Write_Stream_LE(&CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost
, 
 255                                  sizeof(CDCInterfaceInfo
->State
.ControlLineStates
.DeviceToHost
), 
 260 void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t
* CDCInterfaceInfo
, FILE* Stream
) 
 262         *Stream 
= (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar
, CDC_Device_getchar
, _FDEV_SETUP_RW
); 
 263         fdev_set_udata(Stream
, CDCInterfaceInfo
); 
 266 void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t
* CDCInterfaceInfo
, FILE* Stream
) 
 268         *Stream 
= (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar
, CDC_Device_getchar_Blocking
, _FDEV_SETUP_RW
); 
 269         fdev_set_udata(Stream
, CDCInterfaceInfo
); 
 272 static int CDC_Device_putchar(char c
, FILE* Stream
) 
 274         return CDC_Device_SendByte((USB_ClassInfo_CDC_Device_t
*)fdev_get_udata(Stream
), c
) ? _FDEV_ERR 
: 0; 
 277 static int CDC_Device_getchar(FILE* Stream
) 
 279         if (!(CDC_Device_BytesReceived((USB_ClassInfo_CDC_Device_t
*)fdev_get_udata(Stream
)))) 
 282         return CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t
*)fdev_get_udata(Stream
)); 
 285 static int CDC_Device_getchar_Blocking(FILE* Stream
) 
 287         while (!(CDC_Device_BytesReceived((USB_ClassInfo_CDC_Device_t
*)fdev_get_udata(Stream
)))) 
 289                 if (USB_DeviceState 
== DEVICE_STATE_Unattached
) 
 292                 CDC_Device_USBTask((USB_ClassInfo_CDC_Device_t
*)fdev_get_udata(Stream
)); 
 296         return CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t
*)fdev_get_udata(Stream
));