adding additional features

Files at this revision

API Documentation at this revision

Comitter:
sam_grove
Date:
Wed Jun 26 20:35:10 2013 +0000
Commit message:
add dynamic connection and terminal status feedback to the embedded application

Changed in this revision

CircBuffer.h Show annotated file Show diff for this revision Revisions of this file
USBCDC.cpp Show annotated file Show diff for this revision Revisions of this file
USBCDC.h Show annotated file Show diff for this revision Revisions of this file
USBSerial.cpp Show annotated file Show diff for this revision Revisions of this file
USBSerial.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 2d90573426d7 CircBuffer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CircBuffer.h	Wed Jun 26 20:35:10 2013 +0000
@@ -0,0 +1,82 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef CIRCBUFFER_H
+#define CIRCBUFFER_H
+
+template <class T>
+class CircBuffer
+{
+public:
+    CircBuffer( int length )
+    {
+        write = 0;
+        read = 0;
+        size = length + 1;
+        buf = ( T * )malloc( size * sizeof( T ) );
+    };
+
+    bool isFull()
+    {
+        return ( ( write + 1 ) % size == read );
+    };
+
+    bool isEmpty()
+    {
+        return ( read == write );
+    };
+
+    void queue( T k )
+    {
+        if ( isFull() )
+        {
+            read++;
+            read %= size;
+        }
+
+        buf[write++] = k;
+        write %= size;
+    }
+
+    uint16_t available()
+    {
+        return ( write >= read ) ? write - read : size - read + write;
+    };
+
+    bool dequeue( T *c )
+    {
+        bool empty = isEmpty();
+
+        if ( !empty )
+        {
+            *c = buf[read++];
+            read %= size;
+        }
+
+        return( !empty );
+    };
+
+private:
+    volatile uint16_t write;
+    volatile uint16_t read;
+    uint16_t size;
+    T *buf;
+};
+
+#endif
+
diff -r 000000000000 -r 2d90573426d7 USBCDC.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBCDC.cpp	Wed Jun 26 20:35:10 2013 +0000
@@ -0,0 +1,280 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBCDC.h"
+
+static uint8_t cdc_line_coding[7] = {0x80, 0x25, 0x00, 0x00, 0x00, 0x00, 0x08};
+// baud[0,1] stop[x], parity[x], bits[6]
+
+#define DEFAULT_CONFIGURATION (1)
+
+#define CDC_SET_LINE_CODING        0x20
+#define CDC_GET_LINE_CODING        0x21
+#define CDC_SET_CONTROL_LINE_STATE 0x22
+
+#define MAX_CDC_REPORT_SIZE MAX_PACKET_SIZE_EPBULK
+
+USBCDC::USBCDC( uint16_t vendor_id, uint16_t product_id, uint16_t product_release ): USBDevice( vendor_id, product_id, product_release )
+{
+    // Moving this up into the USBSerial class
+    //USBDevice::connect();
+    terminal_status = 0;
+}
+
+uint8_t USBCDC::terminalIsOpen( void )
+{
+    return ( terminal_status ) ? 1 : 0;
+}
+
+bool USBCDC::USBCallback_request( void )
+{
+    /* Called in ISR context */
+    bool success = false;
+    CONTROL_TRANSFER *transfer = getTransferPtr();
+
+    /* Process class-specific requests */
+
+    if ( transfer->setup.bmRequestType.Type == CLASS_TYPE )
+    {
+        switch ( transfer->setup.bRequest )
+        {
+            case CDC_GET_LINE_CODING:
+                transfer->remaining = 7;
+                transfer->ptr = cdc_line_coding;
+                transfer->direction = DEVICE_TO_HOST;
+                success = true;
+                break;
+
+            case CDC_SET_LINE_CODING:
+                transfer->remaining = 7;
+                success = true;
+                break;
+
+            case CDC_SET_CONTROL_LINE_STATE:
+                // Look at DTR to determine if the terminal is opened on the PC
+                terminal_status = ( uint8_t )transfer->setup.wValue & 0x01;
+                success = true;
+                break;
+
+            default:
+                break;
+        }
+    }
+
+    return success;
+}
+
+
+// Called in ISR context
+// Set configuration. Return false if the
+// configuration is not supported.
+bool USBCDC::USBCallback_setConfiguration( uint8_t configuration )
+{
+    if ( configuration != DEFAULT_CONFIGURATION )
+    {
+        return false;
+    }
+
+    // Configure endpoints > 0
+    addEndpoint( EPINT_IN, MAX_PACKET_SIZE_EPINT );
+    addEndpoint( EPBULK_IN, MAX_PACKET_SIZE_EPBULK );
+    addEndpoint( EPBULK_OUT, MAX_PACKET_SIZE_EPBULK );
+    // We activate the endpoint to be able to recceive data
+    readStart( EPBULK_OUT, MAX_PACKET_SIZE_EPBULK );
+    return true;
+}
+
+bool USBCDC::send( uint8_t *buffer, uint32_t size )
+{
+    return USBDevice::write( EPBULK_IN, buffer, size, MAX_CDC_REPORT_SIZE );
+}
+
+bool USBCDC::readEP( uint8_t *buffer, uint32_t *size )
+{
+    if ( !USBDevice::readEP( EPBULK_OUT, buffer, size, MAX_CDC_REPORT_SIZE ) )
+    {
+        return false;
+    }
+
+    if ( !readStart( EPBULK_OUT, MAX_CDC_REPORT_SIZE ) )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool USBCDC::readEP_NB( uint8_t *buffer, uint32_t *size )
+{
+    if ( !USBDevice::readEP_NB( EPBULK_OUT, buffer, size, MAX_CDC_REPORT_SIZE ) )
+    {
+        return false;
+    }
+
+    if ( !readStart( EPBULK_OUT, MAX_CDC_REPORT_SIZE ) )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+
+uint8_t *USBCDC::deviceDesc()
+{
+    static uint8_t deviceDescriptor[] =
+    {
+        18,                   // bLength
+        1,                    // bDescriptorType
+        0x10, 0x01,           // bcdUSB
+        2,                    // bDeviceClass
+        0,                    // bDeviceSubClass
+        0,                    // bDeviceProtocol
+        MAX_PACKET_SIZE_EP0,  // bMaxPacketSize0
+        LSB( VENDOR_ID ), MSB( VENDOR_ID ), // idVendor
+        LSB( PRODUCT_ID ), MSB( PRODUCT_ID ), // idProduct
+        0x00, 0x01,           // bcdDevice
+        1,                    // iManufacturer
+        2,                    // iProduct
+        3,                    // iSerialNumber
+        1                     // bNumConfigurations
+    };
+    return deviceDescriptor;
+}
+
+uint8_t *USBCDC::stringIinterfaceDesc()
+{
+    static uint8_t stringIinterfaceDescriptor[] =
+    {
+        0x08,
+        STRING_DESCRIPTOR,
+        'C', 0, 'D', 0, 'C', 0,
+    };
+    return stringIinterfaceDescriptor;
+}
+
+uint8_t *USBCDC::stringIproductDesc()
+{
+    static uint8_t stringIproductDescriptor[] =
+    {
+        0x16,
+        STRING_DESCRIPTOR,
+        'C', 0, 'D', 0, 'C', 0, ' ', 0, 'D', 0, 'E', 0, 'V', 0, 'I', 0, 'C', 0, 'E', 0
+    };
+    return stringIproductDescriptor;
+}
+
+
+#define CONFIG1_DESC_SIZE (9+9+5+5+4+5+7+9+7+7)
+
+uint8_t *USBCDC::configurationDesc()
+{
+    static uint8_t configDescriptor[] =
+    {
+        9,                      // bLength;
+        2,                      // bDescriptorType;
+        LSB( CONFIG1_DESC_SIZE ), // wTotalLength
+        MSB( CONFIG1_DESC_SIZE ),
+        2,                      // bNumInterfaces
+        1,                      // bConfigurationValue
+        0,                      // iConfiguration
+        0x80,                   // bmAttributes
+        50,                     // bMaxPower
+
+        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+        9,                      // bLength
+        4,                      // bDescriptorType
+        0,                      // bInterfaceNumber
+        0,                      // bAlternateSetting
+        1,                      // bNumEndpoints
+        0x02,                   // bInterfaceClass
+        0x02,                   // bInterfaceSubClass
+        0x01,                   // bInterfaceProtocol
+        0,                      // iInterface
+
+        // CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26
+        5,                      // bFunctionLength
+        0x24,                   // bDescriptorType
+        0x00,                   // bDescriptorSubtype
+        0x10, 0x01,             // bcdCDC
+
+        // Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27
+        5,                      // bFunctionLength
+        0x24,                   // bDescriptorType
+        0x01,                   // bDescriptorSubtype
+        0x03,                   // bmCapabilities
+        1,                      // bDataInterface
+
+        // Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28
+        4,                      // bFunctionLength
+        0x24,                   // bDescriptorType
+        0x02,                   // bDescriptorSubtype
+        0x06,                   // bmCapabilities
+
+        // Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33
+        5,                      // bFunctionLength
+        0x24,                   // bDescriptorType
+        0x06,                   // bDescriptorSubtype
+        0,                      // bMasterInterface
+        1,                      // bSlaveInterface0
+
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
+        ENDPOINT_DESCRIPTOR,            // bDescriptorType
+        PHY_TO_DESC( EPINT_IN ),        // bEndpointAddress
+        E_INTERRUPT,                    // bmAttributes (0x03=intr)
+        LSB( MAX_PACKET_SIZE_EPINT ),   // wMaxPacketSize (LSB)
+        MSB( MAX_PACKET_SIZE_EPINT ),   // wMaxPacketSize (MSB)
+        16,                             // bInterval
+
+
+
+
+        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+        9,          // bLength
+        4,          // bDescriptorType
+        1,          // bInterfaceNumber
+        0,          // bAlternateSetting
+        2,          // bNumEndpoints
+        0x0A,       // bInterfaceClass
+        0x00,       // bInterfaceSubClass
+        0x00,       // bInterfaceProtocol
+        0,          // iInterface
+
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        7,                      // bLength
+        5,                      // bDescriptorType
+        PHY_TO_DESC( EPBULK_IN ), // bEndpointAddress
+        0x02,                   // bmAttributes (0x02=bulk)
+        LSB( MAX_PACKET_SIZE_EPBULK ),  // wMaxPacketSize (LSB)
+        MSB( MAX_PACKET_SIZE_EPBULK ),  // wMaxPacketSize (MSB)
+        0,                      // bInterval
+
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        7,                      // bLength
+        5,                      // bDescriptorType
+        PHY_TO_DESC( EPBULK_OUT ), // bEndpointAddress
+        0x02,                   // bmAttributes (0x02=bulk)
+        LSB( MAX_PACKET_SIZE_EPBULK ),  // wMaxPacketSize (LSB)
+        MSB( MAX_PACKET_SIZE_EPBULK ),   // wMaxPacketSize (MSB)
+        0                       // bInterval
+    };
+    return configDescriptor;
+}
+
diff -r 000000000000 -r 2d90573426d7 USBCDC.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBCDC.h	Wed Jun 26 20:35:10 2013 +0000
@@ -0,0 +1,115 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBCDC_H
+#define USBCDC_H
+
+/* These headers are included for child class. */
+#include "USBDevice/USBDevice/USBEndpoints.h"
+#include "USBDevice/USBDevice/USBDescriptor.h"
+#include "USBDevice/USBDevice/USBDevice_Types.h"
+
+#include "USBDevice/USBDevice/USBDevice.h"
+
+class USBCDC: public USBDevice
+{
+private:
+    volatile uint8_t terminal_status;
+
+public:
+
+    /*
+    * Constructor
+    *
+    * @param vendor_id Your vendor_id
+    * @param product_id Your product_id
+    * @param product_release Your preoduct_release
+    */
+    USBCDC( uint16_t vendor_id, uint16_t product_id, uint16_t product_release );
+
+    uint8_t terminalIsOpen( void );
+
+protected:
+
+    /*
+    * Get device descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
+    *
+    * @returns pointer to the device descriptor
+    */
+    virtual uint8_t *deviceDesc();
+
+    /*
+    * Get string product descriptor
+    *
+    * @returns pointer to the string product descriptor
+    */
+    virtual uint8_t *stringIproductDesc();
+
+    /*
+    * Get string interface descriptor
+    *
+    * @returns pointer to the string interface descriptor
+    */
+    virtual uint8_t *stringIinterfaceDesc();
+
+    /*
+    * Get configuration descriptor
+    *
+    * @returns pointer to the configuration descriptor
+    */
+    virtual uint8_t *configurationDesc();
+
+    /*
+    * Send a buffer
+    *
+    * @param endpoint endpoint which will be sent the buffer
+    * @param buffer buffer to be sent
+    * @param size length of the buffer
+    * @returns true if successful
+    */
+    bool send( uint8_t *buffer, uint32_t size );
+
+    /*
+    * Read a buffer from a certain endpoint. Warning: blocking
+    *
+    * @param endpoint endpoint to read
+    * @param buffer buffer where will be stored bytes
+    * @param size the number of bytes read will be stored in *size
+    * @param maxSize the maximum length that can be read
+    * @returns true if successful
+    */
+    bool readEP( uint8_t *buffer, uint32_t *size );
+
+    /*
+    * Read a buffer from a certain endpoint. Warning: non blocking
+    *
+    * @param endpoint endpoint to read
+    * @param buffer buffer where will be stored bytes
+    * @param size the number of bytes read will be stored in *size
+    * @param maxSize the maximum length that can be read
+    * @returns true if successful
+    */
+    bool readEP_NB( uint8_t *buffer, uint32_t *size );
+
+    virtual bool USBCallback_request();
+    virtual bool USBCallback_setConfiguration( uint8_t configuration );
+
+};
+
+#endif
+
diff -r 000000000000 -r 2d90573426d7 USBSerial.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBSerial.cpp	Wed Jun 26 20:35:10 2013 +0000
@@ -0,0 +1,151 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBSerial.h"
+#include <stdarg.h>
+
+USBSerial::USBSerial( uint16_t vendor_id, uint16_t product_id, uint16_t product_release )
+    : USBCDC( vendor_id, product_id, product_release )
+    , buf( 128 )
+#ifdef USB_ERRATA_WORKAROUND
+    , _connect( P0_6 )
+    , _vbus( P0_3 )
+#endif
+{
+#ifdef USB_ERRATA_WORKAROUND
+    _connect = 1;
+#endif
+    return;
+}
+
+int USBSerial::_putc( int c )
+{
+    send( ( uint8_t * )&c, 1 );
+    return 1;
+}
+
+int USBSerial::_getc()
+{
+    uint8_t c;
+
+    while ( buf.isEmpty() );
+
+    buf.dequeue( &c );
+    return c;
+}
+
+void USBSerial::flush( void )
+{
+    while( available() )
+    {
+        _getc();
+    }
+
+    return;
+}
+
+void USBSerial::printf( const char *format, ... )
+{
+    static char buf[128];
+    uint32_t len = 0;
+    va_list arg;
+
+    if ( strlen( format ) < 64 )
+    {
+        va_start( arg, format );
+        vsprintf( buf, format, arg );
+        va_end( arg );
+        // write to the peripheral
+        len = strlen( buf );
+        send( ( uint8_t * )buf, len );
+        // and erase the buffer conents
+        memset( buf, 0, len );
+    }
+
+    return;
+}
+
+bool USBSerial::writeBlock( uint8_t *buf, uint16_t size )
+{
+    if( size > MAX_PACKET_SIZE_EPBULK )
+    {
+        return false;
+    }
+
+    if( !send( buf, size ) )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool USBSerial::writeBlock( const char *buf )
+{
+    uint16_t cnt = 0;
+
+    while( buf[cnt++] != 0 );
+
+    return writeBlock( ( uint8_t * )buf, cnt );
+}
+
+bool USBSerial::EP2_OUT_callback()
+{
+    uint8_t c[65];
+    uint32_t size = 0;
+    //we read the packet received and put it on the circular buffer
+    readEP( c, &size );
+
+    for ( int i = 0; i < size; i++ )
+    {
+        buf.queue( c[i] );
+    }
+
+    //call a potential handler
+    rx.call();
+    // We reactivate the endpoint to receive next characters
+    readStart( EPBULK_OUT, MAX_PACKET_SIZE_EPBULK );
+    return true;
+}
+
+uint8_t USBSerial::available()
+{
+    return buf.available();
+}
+
+#ifdef USB_ERRATA_WORKAROUND
+void USBSerial::connect( void )
+{
+    _connect = 0;
+    USBHAL::connect();
+    return;
+}
+void USBSerial::disconnect( void )
+{
+    _connect = 1;
+    USBHAL::disconnect();
+    return;
+}
+bool USBSerial::vbusDetected( void )
+{
+    return _vbus;
+}
+#endif
+
+
diff -r 000000000000 -r 2d90573426d7 USBSerial.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBSerial.h	Wed Jun 26 20:35:10 2013 +0000
@@ -0,0 +1,154 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBSERIAL_H
+#define USBSERIAL_H
+
+#include "USBCDC.h"
+#include "Stream.h"
+#include "CircBuffer.h"
+
+
+/**
+* USBSerial example
+*
+* @code
+* #include "mbed.h"
+* #include "USBSerial.h"
+*
+* //Virtual serial port over USB
+* USBSerial serial;
+*
+* int main(void) {
+*
+*    while(1)
+*    {
+*        serial.printf("I am a virtual serial port\n");
+*        wait(1);
+*    }
+* }
+* @endcode
+*/
+class USBSerial: public USBCDC//, public Stream
+{
+public:
+
+    /**
+    *   Constructor
+    *
+    * @param vendor_id Your vendor_id (default: 0x1f00)
+    * @param product_id Your product_id (default: 0x2012)
+    * @param product_release Your preoduct_release (default: 0x0001)
+    *
+    */
+    USBSerial( uint16_t vendor_id = 0x1f00, uint16_t product_id = 0x2012, uint16_t product_release = 0x0001 );
+
+
+    /**
+    * Send a character. You can use puts, printf.
+    *
+    * @param c character to be sent
+    * @returns true if there is no error, false otherwise
+    */
+    virtual int _putc( int c );
+
+    /**
+    * Read a character: blocking
+    *
+    * @returns character read
+    */
+    virtual int _getc();
+
+    /**
+    * Check the number of bytes available.
+    *
+    * @returns the number of bytes available
+    */
+    uint8_t available();
+
+
+    /**
+     * Check the number of bytes available.
+     */
+    void flush( void );
+
+    /**
+    * Write a block of data.
+    *
+    * For more efficiency, a block of size 64 (maximum size of a bulk endpoint) has to be written.
+    *
+    * @param buf pointer on data which will be written
+    * @param size size of the buffer. The maximum size of a block is limited by the size of the endpoint (64 bytes)
+    *
+    * @returns true if successfull
+    */
+    bool writeBlock( uint8_t *buf, uint16_t size );
+    bool writeBlock( const char *buf );
+    void printf( const char *format, ... );
+
+#ifdef USB_ERRATA_WORKAROUND
+    void connect( void );
+    void disconnect( void );
+    bool vbusDetected( void );
+#endif
+
+    /**
+     *  Attach a member function to call when a packet is received.
+     *
+     *  @param tptr pointer to the object to call the member function on
+     *  @param mptr pointer to the member function to be called
+     */
+    template<typename T>
+    void attach( T *tptr, void ( T::*mptr )( void ) )
+    {
+        if( ( mptr != NULL ) && ( tptr != NULL ) )
+        {
+            rx.attach( tptr, mptr );
+        }
+    }
+
+    /**
+     * Attach a callback called when a packet is received
+     *
+     * @param fptr function pointer
+     */
+    void attach( void ( *fn )( void ) )
+    {
+        if( fn != NULL )
+        {
+            rx.attach( fn );
+        }
+    }
+
+
+protected:
+    virtual bool EP2_OUT_callback();
+
+private:
+    FunctionPointer rx;
+    CircBuffer<uint8_t> buf;
+
+#ifdef USB_ERRATA_WORKAROUND
+    DigitalOut _connect;
+    DigitalIn _vbus;
+#endif
+
+};
+
+#endif
+