changeset 2493:3adca3f92ff7

* Generic USB Serial package created. Some files were rearranged during the import and the Documentation written Andrew Lunn.
author asl
date Sat, 12 Jul 2008 10:30:34 +0000
parents 7c92e5146d0a
children a60e1febd035
files packages/io/usb/serial/slave/current/ChangeLog packages/io/usb/serial/slave/current/cdl/usbs_serial.cdl packages/io/usb/serial/slave/current/doc/usbs_serial.sgml packages/io/usb/serial/slave/current/host/linux/.cvsignore packages/io/usb/serial/slave/current/host/linux/Makefile packages/io/usb/serial/slave/current/host/linux/ecos_usbserial.c packages/io/usb/serial/slave/current/host/windows/eCosUsbSerial.inf packages/io/usb/serial/slave/current/include/usbs_serial.h packages/io/usb/serial/slave/current/src/usbs_serial.c packages/io/usb/serial/slave/current/tests/usb2serial.c packages/io/usb/serial/slave/current/tests/usbserial_echo.c
diffstat 11 files changed, 2075 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/packages/io/usb/serial/slave/current/ChangeLog
@@ -0,0 +1,37 @@
+2008-07-12  Frank Pagliughi <fpagliughi@mindspring.com>
+
+	* Generic USB Serial package created.  
+  	  Some files were rearranged during the import and the Documentation
+	  written Andrew Lunn.
+
+//===========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 FSF
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//===========================================================================
new file mode 100644
--- /dev/null
+++ b/packages/io/usb/serial/slave/current/cdl/usbs_serial.cdl
@@ -0,0 +1,260 @@
+# ====================================================================
+#
+#      usbs_serial.cdl
+#
+#      USB slave-side serial package.
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+##
+## eCos is free software; you can redistribute it and/or modify it under
+## the terms of the GNU General Public License as published by the Free
+## Software Foundation; either version 2 or (at your option) any later version.
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+## WARRANTY; without even the implied warranty of MERCHANTABILITY or
+## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License along
+## with eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):      Frank M. Pagliughi (fmp), SoRo Systems, Inc.
+# Contributors:
+# Date:           2008-06-04
+#
+#####DESCRIPTIONEND####
+# ====================================================================
+
+cdl_package CYGPKG_IO_USB_SLAVE_SERIAL {
+    display     "USB slave serial support"
+    include_dir "cyg/io/usb"
+    parent      CYGPKG_IO_USB_SLAVE
+    requires    { CYGHWR_IO_USB_SLAVE_OUT_ENDPOINTS >= 1 }
+    requires    { CYGHWR_IO_USB_SLAVE_IN_ENDPOINTS >= 1 }
+    compile     usbs_serial.c
+    implements  CYGINT_IO_USB_SLAVE_CLIENTS
+#    doc         ref/io-usb-slave-eth.html
+    
+    description "
+        The USB slave serial package supports the development of USB
+        peripherals which mimic a serial connection to the host
+        machine. Such a device creates a relatively simple upgrade to
+        USB from a legacy serial connection, especially from the
+        perspective of the host software and device drivers."
+
+    cdl_option CYGDAT_IO_USB_SLAVE_CLASS_TYPE {
+        display         "Serial USB Class"
+        flavor          data
+        default_value   { "ACM" }
+        legal_values    { "ACM" "generic" }
+        description     "
+            The USB serial module can enumerate as either a generic
+            (vendor-specific) usb device or a communications class ACM
+            device. The generic device requires a pair of Bulk
+            endpoints, while the ACM device also requires an Interrupt
+            IN endpoint.  For a Windows host, the ACM configuration is
+            required to use the standard 'usbser.sys' device driver,
+            but for a Linux host, the generic configuration works, and
+            saves the additional endpoint."
+    }
+    cdl_option CYGDAT_IO_USB_SLAVE_SERIAL_EP0 {
+        display       "Name of EP0 structure"
+        flavor        data               
+        default_value { "usbs_at91_ep0" }
+        description   "
+            The name of the variable that contains the endpoint 0
+            structure.  This should be set to the EP0 structure for
+            the desired USB device driver such as usbs_at91_ep0,
+            usbs_sa11x0_ep0, etc"
+    }
+    cdl_option CYGNUM_IO_USB_SLAVE_SERIAL_EP0_MAX_PACKET_SIZE {
+        display       "The size of EP0"
+        flavor        data
+        default_value 8
+        legal_values  { 8 16 64 } 
+        description   "
+            The size of the EP0 hardware buffer on the specific USB
+            chip used."
+    } 
+    cdl_option CYGNUM_IO_USB_SLAVE_SERIAL_TX_EP_NUM {
+        display       "Tx (USB IN) endpoint number"
+        flavor        data
+        default_value 1
+        description   "
+            The endpoint that should be used for the device-side
+            transmitter, which is the USB IN direction."
+    }
+    cdl_option CYGDAT_IO_USB_SLAVE_SERIAL_TX_EP {
+        display         "The Tx (USB IN) endpoint structure"
+         flavor         data               
+         default_value  { "usbs_at91_ep1" }
+         description    "
+             The endpoint structure that corresponds to the selected
+             Tx endpoint number. This is dependent on the USBS device
+             driver selected, and could be usbs_at91_ep1,
+             usbs_sa11x0_ep1, etc"
+
+    }
+    cdl_option CYGNUM_IO_USB_SLAVE_SERIAL_RX_EP_NUM {
+        display         "Rx (USB OUT) endpoint number"
+        flavor          data
+        default_value   2
+        description     "
+            The endpoint that should be used for the device-side
+            receiver, which is the USB OUT direction."
+    } 
+    cdl_option CYGDAT_IO_USB_SLAVE_SERIAL_RX_EP {
+        display         "The Rx (USB OUT) endpoint structure"
+         flavor         data               
+         default_value  { "usbs_at91_ep2" }
+         description    "
+             The endpoint structure that corresponds to the selected
+             Rx endpoint number. This is dependent on the USBS device
+             driver selected, and could be usbs_at91_ep2,
+             usbs_sa11x0_ep2, etc"
+    }
+    cdl_option CYGNUM_IO_USB_SLAVE_SERIAL_INTR_EP_NUM {
+        display         "Interrupt IN endpoint number"
+        flavor          data
+        default_value   3
+        active_if       { CYGDAT_IO_USB_SLAVE_CLASS_TYPE == "ACM" }
+        description     "
+            The endpoint that should be used for the ACM Interrupt IN"
+    }
+    cdl_option CYGDAT_IO_USB_SLAVE_SERIAL_INTR_EP {
+        display         "Interrupt IN endpoint structure"
+         flavor         data               
+         default_value  { "usbs_at91_ep3" }
+         active_if      { CYGDAT_IO_USB_SLAVE_CLASS_TYPE == "ACM" }
+         description    "
+             The endpoint structure that corresponds to the selected ACM
+             Interrupt IN endpoint."
+    }
+    cdl_option CYGNUM_IO_USB_SLAVE_SERIAL_VENDOR_ID {
+        display       "USB Forum Vendor ID"
+        flavor        data
+        default_value 0xFFFF
+        legal_values  1 to 0xFFFF
+        description   "
+            Each USB vendor has an Vendor ID allocated to it by the
+            USB-IF organization.  Any arbitrary value can be selected
+            for testing provided that it doesn't conflict with devices
+            on the development host, but a device should NEVER be
+            released publicly without a valid Vendor ID"
+
+    }
+    cdl_option CYGNUM_IO_USB_SLAVE_SERIAL_PRODUCT_ID {
+        display       "USB product ID"
+        flavor        data
+        default_value 1
+        legal_values  1 to 0xFFFF
+        description   "
+            You are free to select an arbitrary 16-bit Product ID for
+            a device. The combination of Vendor ID and Product ID
+            uniquely identified a USB device."
+    }
+    cdl_option CYGDAT_IO_USB_SLAVE_SERIAL_MFG_STR {
+        display       "The Device Vendor's Name (Manufacturer String)"
+        flavor        data
+        default_value { "\"eCos\"" }
+        description "
+                The standard USB enumeration allows for a
+                manufacturer's name which is normally reported to the
+                user when the device is first plugged into the host."
+    }
+    cdl_option CYGDAT_IO_USB_SLAVE_SERIAL_PRODUCT_STR {
+        display       "The Device Product Name"
+        flavor        data
+        default_value { "\"eCos USB Serial Device\"" }
+        description "
+                The standard USB enumeration allows for a product name
+                which is normally reported to the user when the device
+                is first plugged into the host."
+    }
+
+    cdl_option  CYGBLD_IO_USB_SLAVE_SERIAL_DEBUG {
+        display       "Enable debug output from the driver"
+        default_value 0
+        flavor        bool
+        description   "
+            The driver may produce debug output which can be
+            useful to work out why it is not working as expected."
+    }
+
+    cdl_component CYGPKG_IO_USB_SLAVE_SERIAL_OPTIONS {
+    display     "Build options"
+    flavor      none
+
+    description "
+        Package-specific build options including control over compiler
+        flags used only in building this package."
+
+        cdl_option CYGPKG_IO_USB_SLAVE_SERIAL_CFLAGS_ADD {
+            display "Additional compiler flags"
+            flavor  data
+            no_define
+            default_value { "" }
+            description   "
+                This option modifies the set of compiler flags for
+                building this package. These flags are used in addition
+                to the set of global flags."
+        }
+ 
+        cdl_option CYGPKG_IO_USB_SLAVE_SERIAL_CFLAGS_REMOVE {
+            display "Suppressed compiler flags"
+            flavor  data
+            no_define
+            default_value { "" }
+            description   "
+                This option modifies the set of compiler flags for
+                building this package. These flags are removed from
+                the set of global flags if present."
+        }
+    
+
+        cdl_component CYGBLD_IO_USB_SLAVE_SERIAL_EXAMPLES {
+            display "Build example programs"
+            no_define
+            requires    { CYGPKG_IO_FILEIO }         
+            requires    { CYGPKG_IO_SERIAL_DEVICES }         
+            description "
+                Enabling this option will cause the example programs
+                to be built using the normal test case infrastructure.
+                They are however not test cases and should not be used
+                with any automatic test farm running all the
+                tests. Hence this option is disabled by default."
+            
+             cdl_option CYGPKG_IO_USB_SLAVE_SERIAL_TESTS {
+                 display "USBS serial example/test programs"
+                 no_define
+                 flavor data
+                 calculated { "tests/usbserial_echo.c tests/usb2serial.c" }
+                 description "
+                     usbserial_echo will echo charactors received
+                     over the usb serial port back to the sender.
+                     usb2serial acts as a bridge between a USB serial
+                     slave and a real serial port. It is hard coded to use
+                     /dev/ser0."
+             }
+        }
+    }
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/packages/io/usb/serial/slave/current/doc/usbs_serial.sgml
@@ -0,0 +1,391 @@
+<!-- DOCTYPE reference  PUBLIC "-//OASIS//DTD DocBook V3.1//EN" -->
+
+<!-- {{{ Banner                         -->
+
+<!-- =============================================================== -->
+<!--                                                                 -->
+<!--     usbs_serial.sgml                                            -->
+<!--                                                                 -->
+<!--     USB slave-side serial port package.                         -->
+<!--                                                                 -->
+<!-- =============================================================== -->
+<!-- ####COPYRIGHTBEGIN####                                          -->
+<!--                                                                 -->
+<!-- =============================================================== -->
+<!-- Copyright (C) 2008 FSF                                          -->
+<!-- This material may be distributed only subject to the terms      -->
+<!-- and conditions set forth in the Open Publication License, v1.0  -->
+<!-- or later (the latest version is presently available at          -->
+<!-- http://www.opencontent.org/openpub/)                            -->
+<!-- Distribution of the work or derivative of the work in any       -->
+<!-- standard (paper) book form is prohibited unless prior           -->
+<!-- permission obtained from the copyright holder                   -->
+<!-- =============================================================== -->
+<!--                                                                 -->      
+<!-- ####COPYRIGHTEND####                                            -->
+<!-- =============================================================== -->
+<!-- #####DESCRIPTIONBEGIN####                                       -->
+<!--                                                                 -->
+<!-- Author(s):   Andrew Lunn, Frank Pagliughi                       -->
+<!-- Contact(s):  asl                                                -->
+<!-- Date:        2008/06/18                                         -->
+<!-- Version:     0.01                                               -->
+<!--                                                                 -->
+<!-- ####DESCRIPTIONEND####                                          -->
+<!-- =============================================================== -->
+
+<!-- }}} -->
+
+<part id="io-usb-slave-serial">
+  <!-- reference id="io-usb-slave-serial" -->
+  <title>eCos Support for USB Serial like Peripherals</title>
+  
+  <!-- {{{ Intro                          -->
+  
+  <refentry id="usbs-serial-intro">
+    <refmeta>
+      <refentrytitle>Introduction</refentrytitle>
+    </refmeta>
+    <refnamediv>
+      <refname>Introduction</refname>
+      <refpurpose>
+        eCos support for USB Serial like Peripherals
+      </refpurpose>
+    </refnamediv>
+    
+    <refsect1><title>Introduction</title>
+      <para>
+        The eCos USB-Serial package provides additional support for
+        USB peripherals that look like a serial port to the
+        host. These can follow the ACM communication device
+        specification or simpler devices which just have two bulk
+        endpoints. Microsoft Windows requires ACM mode. Linux should
+        operate with both modes, however ACM may cause problems since
+        the eCos driver does not implement all the class descriptors,
+        so generic mode is recommended.
+      </para>
+      <para>
+        The USB-Serial package is not tied to any specific
+        hardware. It requires the presence of USB hardware on the
+        target and a suitable device driver to make endpoints
+        available for this code to use.  The configuration system
+        cannot load the eCos package automatically for specific
+        targets, in the way that a USB device driver or an ethernet
+        driver can be loaded automatically. Instead, the package has
+        to be added explicitly. When using the command line tools this
+        will involve an operation like the following:
+      </para>
+      <screen width=72 format=linespecific>
+        $ ecosconfig add usbs_serial
+      </screen>
+      <para>
+        Typically, this will automatically cause the USB device driver
+        to become active. 
+      </para>
+    </refsect1>
+  </refentry>
+  
+  <!-- }}} -->
+  <!-- {{{ Config                          -->
+  
+  <refentry id="usbs-serial-config">
+    <refmeta>
+      <refentrytitle>Configuration</refentrytitle>
+    </refmeta>
+    <refnamediv>
+      <refname>Configuration</refname>
+      <refpurpose>Configuration USB Serial like Peripherals</refpurpose>
+    </refnamediv>
+    
+    <refsect1><title>Configuration</title>
+      <para>
+        The package requires a few basic configurations plus
+        optionally some additional configuration options.
+      </para>
+      <para>
+        The driver needs two or three endpoints, depending if ACM
+        communications or a more generic model is used. This is
+        configured
+        with <literal>CYGDAT_IO_USB_SLAVE_CLASS_TYPE</literal> which
+        can take the value <literal>ACM</literal>
+        or <literal>generic</literal>.
+      </para>
+      <para>
+        The <literal>CYGDAT_IO_USB_SLAVE_SERIAL_EP0</literal> must be
+        configured with the control end point of the USB
+        device. <literal>CYGDAT_IO_USB_SLAVE_SERIAL_TX_EP</literal>
+        must be configured with the endpoint to be used for
+        transmission and  
+        <literal>CYGDAT_IO_USB_SLAVE_SERIAL_RX_EP</literal> must be
+        configured with the end point used for reception. Associated
+        with these
+        are <literal>CYGNUM_IO_USB_SLAVE_SERIAL_RX_EP_NUM</literal>
+        and <literal>CYGNUM_IO_USB_SLAVE_SERIAL_TX_EP_NUM</literal>
+        which are the endpoint numbers and are used during enumeration
+        of the device. The TX and RX endpoints must operate in BULK
+        mode.
+      </para>
+      <para>
+        If operation mode ACM is selected a third endpoint is
+        needed. This must operate in interrupt mode and should be
+        configured
+        in <literal>CYGNUM_IO_USB_SLAVE_SERIAL_INTR_EP</literal>
+        and <literal>
+        CYGNUM_IO_USB_SLAVE_SERIAL_INTR_EP_NUM</literal>.
+      </para>
+      <para>
+        The USB serial device will make its vendor:product ID known to
+        the host. This should be configured
+        with <literal>CYGNUM_IO_USB_SLAVE_SERIAL_VENDOR_ID</literal>
+        and <literal>CYGNUM_IO_USB_SLAVE_SERIAL_PRODUCT_ID</literal>. NOTE:
+        The default configurations are not valid for products, but
+        should work for testing.
+      </para>
+      <para>
+        The USB enumeration also contains text strings to describe the
+        device. This text string can be set
+        with <literal>CYGDAT_IO_USB_SLAVE_SERIAL_PRODUCT_STR</literal>.
+      </para>
+      <para>
+        The last configuration option of interest
+        is <literal>CYGPKG_IO_USB_SLAVE_SERIAL_EXAMPLES</literal>. When
+        true example programs will be built when the eCos tests are
+        built. These are not pass/fail test like other eCos tests, but
+        examples of how the eCos USB serial class can be used.
+      </para>
+    </refsect1>
+  </refentry>
+  
+  <!-- }}} -->
+  <!-- {{{ Host Config                          -->
+  
+  <refentry id="usbs-serial-host-config">
+    <refmeta>
+      <refentrytitle>Host Configuration</refentrytitle>
+    </refmeta>
+    <refnamediv>
+      <refname>Host Configuration</refname>
+      <refpurpose>Host Configuration for USB Serial like Peripherals
+      </refpurpose>
+    </refnamediv>
+    
+    <refsect1>
+      <title>Host Configuration</title>
+      <para>
+        Configuration for two hosts are listed here, Microsoft Windows
+        and Linux. It should also be possible to use the eCos USB
+        serial like peripheral driver with other hosts.
+      </para>
+      <refsect2><title>Linux</title>
+        <para>
+          The eCos USB serial like peripheral driver can be used in
+          Linux in one of two ways.
+          <itemizedlist>
+            <listitem>
+              <para>
+                Using the generic usbserial kernel module passing the
+                vendor and product ID as module parameters. e.g.
+              </para>
+              <programlisting width=72>
+                modprobe usbserial vendor=0xabcd product=0x1234
+              </programlisting>
+              <para>
+                would load the kernel module so that it would use a
+                USB device abcd:1234 as a serial device.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                Using the mini driver provided with eCos in the
+                <filename class=directory>host/linux</filename>
+                directory. This driver must be edited and the correct
+                vendor and product ID set to match the vendor and
+                product ID used by the device. Once compiled this
+                driver can be loaded with:
+              </para>
+              <programlisting width=72>
+                modprobe usbserial
+                modprobe ecos_usbserial
+              </programlisting>
+              <para>
+                This driver is known to compile with kernel versions
+                2.6.18 and probably works fine with other
+                kernels. However it fails to compile with kernels
+                after 2.6.25.
+              </para>
+            </listitem>
+          </itemizedlist>
+          Both of these methods will result in the Linux Kernel making
+          a new serial device available. This is typically
+          named <filename>/dev/ttyUSB0</filename>.
+        </para>
+      </refsect2>
+      <refsect2><title>Microsoft Windows</title>
+        <para>
+          To install the device in a Microsoft Windows system make use
+          of the INF file
+          in <filename>host/windows/eCosUsbSerial.inf</filename>. Copy
+          this INF file and <filename>usbser.sys</filename> from your
+          version of Windows into an empty directory. Then plug in the
+          USB device. When prompted to load a driver navigate to the
+          INF file and select it.
+        </para>
+      </refsect2>
+    </refsect1>
+    
+  </refentry>
+  
+  <!-- }}} -->
+  <!-- {{{ Using                         -->
+  <refentry id="usbs-serial-using">
+    <refmeta>
+      <refentrytitle>API Function</refentrytitle>
+    </refmeta>
+    <refnamediv>
+      <refname>usbs_serial_start</refname>
+      <refname>usbs_serial_init</refname>
+      <refname>usbs_serial_start</refname>
+      <refname>usbs_serial_wait_until_configured</refname>
+      <refname>usbs_serial_is_configured</refname>
+      <refname>usbs_serial_start_tx</refname>
+      <refname>usbs_serial_wait_for_tx</refname>
+      <refname>usbs_serial_tx</refname>
+      <refname>usbs_serial_start_rx</refname>
+      <refname>usbs_serial_wait_for_rx</refname>
+      <refname>usbs_serial_rx</refname>
+      <refname>usbs_serial_state_change_handler</refname>
+      <refpurpose>
+        eCos USB Serial like Peripherals API
+      </refpurpose>
+    </refnamediv>
+    
+    <refsynopsisdiv>
+      <funcsynopsis>
+        <funcsynopsisinfo>
+#include &lt;cyg/io/usb/usbs_serial.h&gt;
+        </funcsynopsisinfo>
+        <funcprototype>
+          <funcdef>void 
+            <function>usbs_serial_start</function>
+          </funcdef>
+          <paramdef>void</paramdef>
+        </funcprototype>
+        <funcprototype>
+          <funcdef>void 
+            <function>usbs_serial_init</function>
+          </funcdef>
+          <paramdef>usbs_serial * <parameter>ser</parameter></paramdef>
+          <paramdef>usbs_tx_endpoint * <parameter>tx_ep</parameter></paramdef>
+          <paramdef>usbs_rx_endpoint * <parameter>rx_ep</parameter></paramdef>
+        </funcprototype>
+        <funcprototype>
+          <funcdef>void 
+            <function>usbs_serial_wait_until_configured</function>
+          </funcdef>
+          <paramdef>void></paramdef>
+        </funcprototype>
+        <funcprototype>
+          <funcdef>cyg_bool
+            <function>usbs_serial_is_configured</function>
+          </funcdef>
+          <paramdef>void</paramdef>
+        </funcprototype>
+        <funcprototype>
+          <funcdef>void 
+            <function>usbs_serial_start_tx</function>
+          </funcdef>
+          <paramdef>usbs_serial * <parameter>ser</parameter></paramdef>
+          <paramdef>const void *<parameter>buf</parameter></paramdef>
+          <paramdef>int * <parameter>n</parameter></paramdef>
+        </funcprototype>
+        <funcprototype>
+          <funcdef>int 
+            <function>usbs_serial_wait_for_tx</function>
+          </funcdef>
+          <paramdef>usbs_serial * <parameter>ser</parameter></paramdef>
+        </funcprototype>
+        <funcprototype>
+          <funcdef>void 
+            <function>usbs_serial_start_rx</function>
+          </funcdef>
+          <paramdef>usbs_serial * <parameter>ser</parameter></paramdef>
+          <paramdef>const void *<parameter>buf</parameter></paramdef>
+          <paramdef>int * <parameter>n</parameter></paramdef>
+        </funcprototype>
+        <funcprototype>
+          <funcdef>int 
+            <function>usbs_serial_wait_for_rx</function>
+          </funcdef>
+          <paramdef>usbs_serial * <parameter>ser</parameter></paramdef>
+        </funcprototype>
+        <funcprototype>
+          <funcdef>int 
+            <function>usbs_serial_rx</function>
+          </funcdef>
+          <paramdef>usbs_serial * <parameter>ser</parameter></paramdef>
+          <paramdef>const void *<parameter>buf</parameter></paramdef>
+          <paramdef>int * <parameter>n</parameter></paramdef>
+        </funcprototype>
+        <funcprototype>
+          <funcdef>void 
+            <function>usbs_serial_state_change_handler</function>
+          </funcdef>
+          <paramdef>usbs_control_endpoint * <parameter>ep</parameter></paramdef>
+          <paramdef>void * <parameter>data</parameter></paramdef>
+          <paramdef>usbs_state_change <parameter>change</parameter></paramdef>
+          <paramdef>int <parameter>prev_state</parameter></paramdef>
+        </funcprototype>
+      </funcsynopsis>
+    </refsynopsisdiv>
+    
+    <refsect1 id="usbs-serial-api-description">
+      <title>Description</title>
+      <para>
+        For examples of how to use this API see the
+        files <filename>.../tests/usbserial_echo.c</filename>
+        and <filename>.../tests/usb2serial.c</filename>
+      </para>
+      
+      <para>
+        The first function that needs calling
+        is <function>usbs_serial_start()</function>. This will initialise
+        the eCos USB slave layer, creating all the enumeration data and
+        then let the host know that the device exists.
+      </para>
+      <para>
+        Once the USB subsystem has been started it is necessary to wait
+        for the host to configure the device using the
+        function <function>usbs_serial_wait_until_configured()</function>. The
+        host will assign the device an ID and then load the appropriate
+        device driver in the host in order to make use the device.
+      </para>
+      <para>
+        Once the device is configured it is then possible to make use of
+        it, i.e. send and receive data. This transfer of data can be
+        accomplished either asynchronously or synchronously. It is also
+        possible to mix asynchronously and synchronously between
+        receiving and sending data.
+      </para>
+      <para>
+        To perform asynchronous operations the
+        functions <function>usbs_serial_start_rx()</function>
+        and <function>usbs_serial_start_tx()</function> is used to
+        start the operation. These functions start the necessary
+        actions and then return immediately. At a later time the
+        functions <function>usbs_serial_wait_for_tx()</function>
+        or <function>usbs_serial_wait_for_rx()</function> should be
+        called. These will, if necessary, block and then return the
+        status and any data for the previously started asynchronous
+        call.
+      </para>
+      <para>
+        To perform synchronous operations the
+        functions <function>usbs_serial_rx()</function>
+        and <function>usbs_serial_tx()</function> are used. These
+        functions will block until the requested action is complete.
+      </para>
+    </refsect1>
+  </refentry>    
+  <!-- }}} -->
+</part>
+<!-- /reference -->
new file mode 100644
--- /dev/null
+++ b/packages/io/usb/serial/slave/current/host/linux/.cvsignore
@@ -0,0 +1,3 @@
+.ecos_usbserial.o.d
+.tmp_versions
+*.ko
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/packages/io/usb/serial/slave/current/host/linux/Makefile
@@ -0,0 +1,11 @@
+# Makefile for ecos_usbserial Linux kernel module
+
+ifneq ($(KERNELRELEASE),)
+	obj-m := ecos_usbserial.o
+else
+	KDIR ?= /lib/modules/$(shell uname -r)/build
+	PWD := $(shell pwd)
+default:
+	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
+endif
+
new file mode 100644
--- /dev/null
+++ b/packages/io/usb/serial/slave/current/host/linux/ecos_usbserial.c
@@ -0,0 +1,111 @@
+//==========================================================================
+//
+//      ecos_usbserial.c
+//
+//      Kernel driver for the eCos USB serial driver
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//===========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Frank M. Pagliughi (fmp), SoRo Systems, Inc.
+// Contributors: 
+// Date:         2008-06-02
+// Description:  Kernel driver for the eCos USB serial driver
+//
+//####DESCRIPTIONEND####
+//===========================================================================
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+
+#define VENDOR_ID	0xFFFF
+#define PRODUCT_ID	1
+
+static struct usb_device_id id_table[] = {
+	{ USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver ecos_usbserial_driver = {
+	.name	 	= "ecos_usbserial",
+	.probe		= usb_serial_probe,
+	.disconnect	= usb_serial_disconnect,
+	.id_table	= id_table
+};
+
+static struct usb_serial_driver ecos_usbserial_device = {
+	.driver = {
+		.owner			= THIS_MODULE,
+		.name			= "ecos_usbserial",
+	},
+	.id_table			= id_table, 
+	.num_interrupt_in	= NUM_DONT_CARE,
+	.num_bulk_in		= NUM_DONT_CARE,
+	.num_bulk_out		= NUM_DONT_CARE,
+	.num_ports			= 1
+};
+
+static int __init ecos_usbserial_init(void)
+{
+	int retval;
+
+	retval = usb_serial_register(&ecos_usbserial_device);
+	if (retval)
+		return retval;
+
+	retval = usb_register(&ecos_usbserial_driver);
+	if (retval) {
+		usb_serial_deregister(&ecos_usbserial_device);
+		return retval;
+	}
+
+	return 0;
+}
+
+static void __exit ecos_usbserial_exit(void)
+{
+	usb_deregister(&ecos_usbserial_driver);
+	usb_serial_deregister(&ecos_usbserial_device);
+}
+
+module_init(ecos_usbserial_init);
+module_exit(ecos_usbserial_exit);
+
+MODULE_LICENSE("GPL");
+
new file mode 100644
--- /dev/null
+++ b/packages/io/usb/serial/slave/current/host/windows/eCosUsbSerial.inf
@@ -0,0 +1,49 @@
+; eCos USB Serial INF file for Windows
+; This can be used for any USB device that emulates a serial port connection.
+; Simply set the VID & PID numbers in this file to the proper values for the
+; device, copy this file and the 'usbser.sys' file from your version of Windows
+; into the same directory, and load these when prompted by the Windows device
+; manager.
+
+[Version]
+Signature="$Windows NT$"
+Class=Ports
+ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
+Provider=eCosUsbSerial
+DriverVer=06/02/2008,0.0.0.1
+
+[DestinationDirs]
+DefaultDestDir=12	; %windir$\System32\drivers
+
+[Manufacturer]
+eCosUsbSerial=eCosDevices
+
+[eCosDevices]
+"eCosUsbSerial"=InstalleCosUsbSerial,USB\VID_FFFF&PID_0001
+
+[InstalleCosUsbSerial]
+CopyFiles=CopyeCosUsbFiles
+AddReg=eCosUsbReg
+
+[CopyeCosUsbFiles]
+usbser.sys			; The standard Windows USB serial driver
+
+[eCosUsbReg]
+HKR,,DevLoader,,*ntkern
+HKR,,NTMPDriver,,usbser.sys
+HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
+
+[InstalleCosUsbSerial.Services]
+AddService = usbser,2,eCosUsbSerialService
+
+[eCosUsbSerialService]
+DisplayName = ECOS_USB_SERIAL_NAME
+ServiceType = 1				; driver
+StartType = 3				; on-demand or manual
+ErrorControl = 1			; report errors
+ServiceBinary = %12%\usbser.sys		; Driver path: %windir%\System32\drivers
+LoadOrderGroup = Base
+
+[Strings]
+ECOS_USB_SERIAL_NAME = "eCos USB Serial Driver"
+
new file mode 100644
--- /dev/null
+++ b/packages/io/usb/serial/slave/current/include/usbs_serial.h
@@ -0,0 +1,184 @@
+#ifndef CYGONCE_USBS_SERIAL_H
+#define CYGONCE_USBS_SERIAL_H
+//==========================================================================
+//
+//      include/usbs_serial.h
+//
+//      Description of the USB slave-side serial device support
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Frank M. Pagliughi (fmp), SoRo Systems, Inc.
+// Contributors: 
+// Date:         2008-06-02
+// Purpose:
+// Description:  USB slave-side serial support
+//
+//
+//####DESCRIPTIONEND####
+//==========================================================================
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+    
+//
+// The primary purpose of the USB slave-side serial code is to provide a 
+// simple USB connection to the host, especially for embedded systems that
+// are upgrading from RS-232 serial connections. The host would see the 
+// device as if through a serial port, and thus the host software would
+// remain unchanged. It would also eliminate the need for a new device
+// driver on the host.
+// 
+// On this side (the eCos USB slave side), the application sees the host
+// through a normal USB slave connection with two Bulk endpoints - one in 
+// the IN direction and one in the OUT direction. This module provides the
+// necessary USB descriptors to enumerate the device for a single serial
+// port, but then the application is free to communicate with the host
+// using any desired API:
+//  - The standard eCos USB slave API
+//  - The low-level File I/O layer (if USB devtab entries configured)
+//  - The C stdio functions (again, if USB devtab entries configured)
+//  - The USB serial API defined here.
+// 
+// The USB serial API is a thin layer over the standard eCos USB functions
+// to provide common synchronous and asynchronous transfers over the assigned
+// Bulk endpoints.
+//
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/io/usb/usbs.h>
+
+// ----------------------------------------------------------------------------
+// The ACM class requests
+// 
+
+#define USBS_SERIAL_SEND_ENCAPSULATED_COMMAND   0x00
+#define USBS_SERIAL_GET_ENCAPSULATED_RESPONSE   0x01
+#define USBS_SERIAL_SET_COMM_FEATURE            0x02
+#define USBS_SERIAL_GET_COMM_FEATURE            0x03
+#define USBS_SERIAL_CLEAR_COMM_FEATURE          0x04
+
+#define USBS_SERIAL_SET_LINE_CODING             0x20
+#define USBS_SERIAL_GET_LINE_CODING             0x21
+#define USBS_SERIAL_SET_CONTROL_LINE_STATE      0x22
+#define USBS_SERIAL_SEND_BREAK                  0x23
+
+// ----------------------------------------------------------------------------
+// Data structure to manage the pair of USB endpoints that comprise a single
+// serial port connection. Each "port" requires one Bulk IN endpoint and one
+// Bulk OUT endpoint.
+
+typedef struct usbs_serial {
+    // The communication endpoints. For the first (default) channel, these
+    // are normally set by the configuration, but can be changed by the
+    // application, if desired.
+    usbs_tx_endpoint*   tx_ep;
+    usbs_rx_endpoint*   rx_ep;
+
+    // The signal that a transmit operation is complete, and it's result.
+    cyg_sem_t   tx_ready;
+    int         tx_result;
+
+    // The signal that a receive operation is complete, and it's result.
+    cyg_sem_t   rx_ready;
+    int         rx_result;
+
+} usbs_serial;
+
+// The package contains one USB serial device.
+extern usbs_serial usbs_ser0;
+
+// It's assumed that there's a single USB slave chip in the system, with a
+// single control endpoint 0. The actual variable is contained in the device
+// driver, but the USB serial code keeps a pointer to it for driver 
+// independence. The application might find it useful for overriding low-level
+// code or callbacks.
+extern usbs_control_endpoint* usbs_serial_ep0;
+
+// ----------------------------------------------------------------------------
+// A C interface to the serial USB code.
+// The application can use this interface, the standard (low-level) USB slave
+// API, the standard Unix-like I/O API, or C stdio API.
+    
+// Initialize support for a particular USB serial "port"
+// This associates a usbs_serial structure with specific endpoints and 
+// initializes the structure for communications.
+void usbs_serial_init(usbs_serial*, usbs_tx_endpoint*, usbs_rx_endpoint*);
+
+// Block the calling thread until the host configures the USB device.
+void usbs_serial_wait_until_configured(void);
+
+// Determines if the USB subsystem is configured
+cyg_bool usbs_serial_is_configured(void);
+
+// Start an asynchronous transmit of a single buffer.
+void usbs_serial_start_tx(usbs_serial*, const void* buf, int n);
+
+// Block the calling thread until the transmit completes.
+// Returns the result code for the transfer
+int usbs_serial_wait_for_tx(usbs_serial*);
+
+// Blocking, synchronous transmit of a single buffer.
+int usbs_serial_tx(usbs_serial*, const void* buf, int n);
+
+// Start an asynchronous receive of a buffer.
+void usbs_serial_start_rx(usbs_serial*, void* buf, int n);
+
+// Block the calling thread until the receive completes.
+// Returns the result code for the transfer
+int usbs_serial_wait_for_rx(usbs_serial*);
+
+// Blocking, synchronous receive of a single buffer.
+int usbs_serial_rx(usbs_serial*, void* buf, int n);
+
+// The default USB-serial state change handler paces the functions
+// usbs_serial_wait_until_configured() and usbs_serial_is_configured().
+// The application can override the state chain handler, but chain to 
+// this function to keep the full USB-serial system working.
+void usbs_serial_state_change_handler(usbs_control_endpoint*, void*, 
+                                      usbs_state_change, int);
+
+// Starts the USB subsystem
+void usbs_serial_start(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // CYGONCE_USBS_SERIAL_H
+
new file mode 100644
--- /dev/null
+++ b/packages/io/usb/serial/slave/current/src/usbs_serial.c
@@ -0,0 +1,545 @@
+//==========================================================================
+//
+//      usbs_serial.c
+//
+//      Support for slave-side USB serial devices.
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Frank M. Pagliughi (fmp), SoRo Systems, Inc.
+// Date:         2008-06-02
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/cyg_ass.h>
+#include <cyg/infra/cyg_trac.h>
+#include <cyg/infra/diag.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/drv_api.h>
+#include <cyg/kernel/kapi.h>
+
+#include <pkgconf/io_usb_slave_serial.h>
+#include <cyg/io/usb/usbs_serial.h>
+#include <string.h>
+
+#if defined(CYGBLD_IO_USB_SLAVE_SERIAL_DEBUG)
+#define DBG diag_printf
+#else
+#define DBG (1) ? (void)0 : diag_printf
+#endif
+
+#define EP0_MAX_PACKET_SIZE     CYGNUM_IO_USB_SLAVE_SERIAL_EP0_MAX_PACKET_SIZE
+
+extern usbs_control_endpoint    CYGDAT_IO_USB_SLAVE_SERIAL_EP0;
+extern usbs_tx_endpoint         CYGDAT_IO_USB_SLAVE_SERIAL_TX_EP;
+extern usbs_rx_endpoint         CYGDAT_IO_USB_SLAVE_SERIAL_RX_EP;
+
+#define TX_EP_NUM               CYGNUM_IO_USB_SLAVE_SERIAL_TX_EP_NUM
+#define RX_EP_NUM               CYGNUM_IO_USB_SLAVE_SERIAL_RX_EP_NUM
+#define INTR_EP_NUM             CYGNUM_IO_USB_SLAVE_SERIAL_INTR_EP_NUM
+#define EP0                     (&CYGDAT_IO_USB_SLAVE_SERIAL_EP0)
+#define TX_EP                   (&CYGDAT_IO_USB_SLAVE_SERIAL_TX_EP)
+#define RX_EP                   (&CYGDAT_IO_USB_SLAVE_SERIAL_RX_EP)
+#define INTR_EP                 (&CYGDAT_IO_USB_SLAVE_SERIAL_INTR_EP)
+
+
+#define VENDOR_ID               CYGNUM_IO_USB_SLAVE_SERIAL_VENDOR_ID
+#define PRODUCT_ID              CYGNUM_IO_USB_SLAVE_SERIAL_PRODUCT_ID
+
+#define USB_MAX_STR_LEN         256
+
+#define LO_BYTE_16(word16)      ((cyg_uint8) ((word16) & 0xFF))
+#define HI_BYTE_16(word16)      ((cyg_uint8) (((word16) >> 8) & 0xFF))
+
+#define BYTE0_32(word32)        ((cyg_uint8) ((word32) & 0xFF))
+#define BYTE1_32(word32)        ((cyg_uint8) (((word32) >>  8) & 0xFF))
+#define BYTE2_32(word32)        ((cyg_uint8) (((word32) >> 16) & 0xFF))
+#define BYTE3_32(word32)        ((cyg_uint8) (((word32) >> 24) & 0xFF))
+
+
+#define MFG_STR_INDEX           '\x01'
+#define PRODUCT_STR_INDEX       '\x02'
+
+#define USB_CONFIGURATION_DESCRIPTOR_TOTAL_LENGTH(interfaces, endpoints) \
+            (USB_CONFIGURATION_DESCRIPTOR_LENGTH +            \
+            ((interfaces) * USB_INTERFACE_DESCRIPTOR_LENGTH) +  \
+            ((endpoints)  * USB_ENDPOINT_DESCRIPTOR_LENGTH))
+
+
+#ifdef CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM
+    #define USBS_SERIAL_DEVICE_CLASS        2
+    #define USBS_SERIAL_NUM_IFACE           2
+    #define USBS_SERIAL_NUM_ENDP            3
+    #define USBS_SERIAL_DATA_IFACE_CLASS    0x0A    // Data
+#else
+    #define USBS_SERIAL_DEVICE_CLASS        0
+    #define USBS_SERIAL_NUM_IFACE           1
+    #define USBS_SERIAL_NUM_ENDP            2
+    #define USBS_SERIAL_DATA_IFACE_CLASS    0xFF    // Vendor
+#endif
+
+// ----- Configuration Descriptor -----
+
+static const usb_configuration_descriptor usb_configuration = {
+    length:             sizeof(usb_configuration_descriptor),
+    type:               USB_CONFIGURATION_DESCRIPTOR_TYPE,
+    total_length_lo:    
+        USB_CONFIGURATION_DESCRIPTOR_TOTAL_LENGTH_LO(USBS_SERIAL_NUM_IFACE, 
+                                                     USBS_SERIAL_NUM_ENDP),
+    total_length_hi:    
+        USB_CONFIGURATION_DESCRIPTOR_TOTAL_LENGTH_HI(USBS_SERIAL_NUM_IFACE, 
+                                                     USBS_SERIAL_NUM_ENDP),
+    number_interfaces:  USBS_SERIAL_NUM_IFACE,
+    configuration_id:   1,
+    configuration_str:  0,
+    attributes:         (USB_CONFIGURATION_DESCRIPTOR_ATTR_REQUIRED |
+                         USB_CONFIGURATION_DESCRIPTOR_ATTR_SELF_POWERED),
+    max_power:          50
+};
+
+// ----- Interface Descriptor -----
+
+static const usb_interface_descriptor usb_interface[] = {
+
+#ifdef CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM
+    {
+        length:             sizeof(usb_interface_descriptor),
+        type:               USB_INTERFACE_DESCRIPTOR_TYPE,
+        interface_id:       0,
+        alternate_setting:  0,
+        number_endpoints:   1,
+        interface_class:    0x02,   // Comm class
+        interface_subclass: 0x02,
+        interface_protocol: 0x01,
+        interface_str:      0x00
+    },
+    {
+        length:             sizeof(usb_interface_descriptor),
+        type:               USB_INTERFACE_DESCRIPTOR_TYPE,
+        interface_id:       1,
+        alternate_setting:  0,
+        number_endpoints:   2,
+        interface_class:    USBS_SERIAL_DATA_IFACE_CLASS,
+        interface_subclass: 0x00,
+        interface_protocol: 0x00,
+        interface_str:      0x00
+    }
+#else
+    {
+        length:             sizeof(usb_interface_descriptor),
+        type:               USB_INTERFACE_DESCRIPTOR_TYPE,
+        interface_id:       0,
+        alternate_setting:  0,
+        number_endpoints:   2,
+        interface_class:    USBS_SERIAL_DATA_IFACE_CLASS,
+        interface_subclass: 0x00,
+        interface_protocol: 0x00,
+        interface_str:      0x00
+    }
+#endif
+};
+
+// ----- Endpoint Descriptors -----
+
+static const usb_endpoint_descriptor usb_endpoints[] =
+{ 
+#ifdef CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM
+    // Interrupt in endpoint
+    {
+        sizeof(usb_endpoint_descriptor),
+        USB_ENDPOINT_DESCRIPTOR_TYPE,
+        USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN | INTR_EP_NUM,
+        USB_ENDPOINT_DESCRIPTOR_ATTR_INTERRUPT,
+        0x40,
+        0,
+        255
+    },
+#endif
+
+    // Tx (Bulk IN) Endpoint Descriptor
+    {
+        sizeof(usb_endpoint_descriptor),
+        USB_ENDPOINT_DESCRIPTOR_TYPE,
+        USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN | TX_EP_NUM,
+        USB_ENDPOINT_DESCRIPTOR_ATTR_BULK,
+        0x40,
+        0,
+        0
+    },
+
+    // Rx (Bulk OUT) Endpoint Descriptor
+    {
+        sizeof(usb_endpoint_descriptor),
+        USB_ENDPOINT_DESCRIPTOR_TYPE,
+        USB_ENDPOINT_DESCRIPTOR_ENDPOINT_OUT | RX_EP_NUM,
+        USB_ENDPOINT_DESCRIPTOR_ATTR_BULK,
+        0x40,
+        0,
+        0
+    }
+};
+
+// ----- String Descriptors -----
+
+static char mfg_str_descr[USB_MAX_STR_LEN],
+            product_str_descr[USB_MAX_STR_LEN];
+
+
+static const char* usb_strings[] = {
+    "\x04\x03\x09\x04",
+    mfg_str_descr,
+    product_str_descr
+};
+
+// ----- Enumeration Data w/ Device Descriptor -----
+
+static usbs_enumeration_data usb_enum_data = {
+    {
+        length:                 sizeof(usb_device_descriptor),
+        type:                   USB_DEVICE_DESCRIPTOR_TYPE,
+        usb_spec_lo:            0x00, 
+        usb_spec_hi:            0x02,
+        device_class:           USBS_SERIAL_DEVICE_CLASS,
+        device_subclass:        0,
+        device_protocol:        0,
+        max_packet_size:        EP0_MAX_PACKET_SIZE,
+        vendor_lo:              LO_BYTE_16(VENDOR_ID),
+        vendor_hi:              HI_BYTE_16(VENDOR_ID),
+        product_lo:             LO_BYTE_16(PRODUCT_ID),
+        product_hi:             HI_BYTE_16(PRODUCT_ID),
+        device_lo:              0x00,
+        device_hi:              0x00,
+        manufacturer_str:       MFG_STR_INDEX,
+        product_str:            PRODUCT_STR_INDEX,
+        serial_number_str:      0,
+        number_configurations:  1
+    },
+
+    total_number_interfaces:    USBS_SERIAL_NUM_IFACE,
+    total_number_endpoints:     USBS_SERIAL_NUM_ENDP,
+    total_number_strings:       3,
+    configurations:             &usb_configuration,
+    interfaces:                 usb_interface,
+    endpoints:                  usb_endpoints,
+    strings:                    (const unsigned char **) usb_strings
+};
+
+// --------------------------------------------------------------------------
+// USBS Serial Data
+// --------------------------------------------------------------------------
+
+usbs_control_endpoint* usbs_serial_ep0 = EP0;
+
+// Lock for the state.
+cyg_mutex_t usbs_serial_lock;   
+
+// Condition variable for state changes
+cyg_cond_t  usbs_serial_state_cond;
+
+int usbs_serial_state;
+
+usbs_serial usbs_ser0 = {
+    tx_ep:      TX_EP,
+    rx_ep:      RX_EP,
+    tx_result:  0,    
+    rx_result:  0,    
+};
+
+static void (*usbs_serial_app_state_change_fn)(struct usbs_control_endpoint*, 
+                                               void*, usbs_state_change, int) 
+= 0;
+
+// --------------------------------------------------------------------------
+// Create a USB String Descriptor from a C string.
+
+void
+usbs_serial_create_str_descriptor(char descr[], const char *str)
+{
+    int i, n = strlen(str);
+
+    if (n > (USB_MAX_STR_LEN/2 - 2))
+        n = USB_MAX_STR_LEN/2 - 2;
+
+    descr[0] = (cyg_uint8) (2*n + 2);
+    descr[1] = USB_DEVREQ_DESCRIPTOR_TYPE_STRING;
+
+    for (i=0; i<n; i++) {
+        descr[i*2+2] = str[i];
+        descr[i*2+3] = '\x00';
+    }
+}
+
+// --------------------------------------------------------------------------
+// ACM Class Handler
+//
+// For a Windows host, the device must, at least, respond to a SetLineCoding
+// request (0x20), otherwise Windows will report that it's unable to open the 
+// port. This request normally sets the standard serial parameters:
+//          baud rate, # stop bits, parity, and # data bits
+// If we're just making believe that we're a serial port to communicate with
+// the host via USB, then these values don't matter. So we ACK the request,
+// but ignore the parameters.
+// If we were actually creating a USB-serial converter, then we would need to
+// read these values and configure the serial port accordingly.
+// 
+// Similarly, the host can request the current settings through a 
+// GetLineCoding request (0x21). Since we're just faking it, we return some
+// arbitrary values: 38400,1,N,8
+
+#ifdef CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM
+
+static usbs_control_return 
+usbs_serial_acm_class_handler(usbs_control_endpoint* ep0, void* data)
+{
+  usbs_control_return result = USBS_CONTROL_RETURN_UNKNOWN;
+  usb_devreq      *req = (usb_devreq *) ep0->control_buffer;
+  static cyg_uint8 rsp_buf[32];
+  cyg_uint32 baud = 38400;  // Arbitrary, fake value to return to the host.
+
+  DBG("USB Serial ACM Class Handler: ");
+  
+  switch (req->request) {
+    
+    case USBS_SERIAL_SET_LINE_CODING :
+      DBG("ACM Request: Set Line Coding\n");
+      result = USBS_CONTROL_RETURN_HANDLED;
+      break;
+      
+    case USBS_SERIAL_GET_LINE_CODING :
+      DBG("ACM Request: Get Line Coding\n");
+      rsp_buf[0] = BYTE0_32(baud);
+      rsp_buf[1] = BYTE1_32(baud);
+      rsp_buf[2] = BYTE2_32(baud);
+      rsp_buf[3] = BYTE3_32(baud);
+      rsp_buf[4] = 0; // One stop bit
+      rsp_buf[5] = 0; // No parity
+      rsp_buf[6] = 8; // 8 data bits
+      ep0->buffer = rsp_buf;
+      ep0->buffer_size = 7;
+      result = USBS_CONTROL_RETURN_HANDLED;
+      break;
+      
+    default :
+      DBG("*** Unhandled ACM Request: 0x%02X ***\n",
+          (unsigned) req->request);
+  }
+  
+  return result;
+}
+#endif      // CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM
+
+// --------------------------------------------------------------------------
+// Callback for a USB state change
+
+void
+usbs_serial_state_change_handler(usbs_control_endpoint* ep, void* data,
+                                 usbs_state_change change, int prev_state)
+{
+#if defined(CYGBLD_IO_USB_SLAVE_SERIAL_DEBUG)
+  const char *STATE_CHG_STR[] = { "Detached", "Attached", "Powered", "Reset",
+                                  "Addressed", "Configured", "Deconfigured",
+                                  "Suspended", "Resumed" };
+  
+  if (change > 0) {
+    DBG("### %d:%s ###\n", change, STATE_CHG_STR[(int) change-1]);
+  }
+#endif
+  
+  // Called from DSR, cond broadcast should be ok without mutex lock
+  usbs_serial_state = usbs_serial_ep0->state;
+  cyg_cond_broadcast(&usbs_serial_state_cond);
+  
+  if (usbs_serial_app_state_change_fn)
+    (*usbs_serial_app_state_change_fn)(ep, data, change, prev_state);
+}
+
+// --------------------------------------------------------------------------
+// Block the calling thread until the USB is configured.
+ 
+void
+usbs_serial_wait_until_configured(void)
+{
+  cyg_mutex_lock(&usbs_serial_lock);
+  while (usbs_serial_state != USBS_STATE_CONFIGURED)
+    cyg_cond_wait(&usbs_serial_state_cond);
+  cyg_mutex_unlock(&usbs_serial_lock);
+}
+
+// --------------------------------------------------------------------------
+// Determine if the device is currently configured.
+
+cyg_bool
+usbs_serial_is_configured(void)
+{
+  return usbs_serial_state == USBS_STATE_CONFIGURED;
+}
+
+// --------------------------------------------------------------------------
+// Callback for when a transmit is complete
+
+static void 
+usbs_serial_tx_complete(void *p, int result)
+{
+  usbs_serial* ser = (usbs_serial*) p;
+  ser->tx_result = result;
+  cyg_semaphore_post(&ser->tx_ready);
+}
+
+// --------------------------------------------------------------------------
+// Callback for when a receive is complete
+
+static void 
+usbs_serial_rx_complete(void *p, int result)
+{
+  usbs_serial* ser = (usbs_serial*) p;
+  ser->rx_result = result;
+  cyg_semaphore_post(&ser->rx_ready);
+}
+
+// --------------------------------------------------------------------------
+// Start an asynchronous transmit of a buffer.
+// 
+ 
+void
+usbs_serial_start_tx(usbs_serial* ser, const void* buf, int n)
+{
+  usbs_start_tx_buffer(ser->tx_ep, (unsigned char*) buf, n,
+                       usbs_serial_tx_complete, ser);
+}
+
+// --------------------------------------------------------------------------
+// Block the caller until the transmit is complete
+
+int
+usbs_serial_wait_for_tx(usbs_serial* ser)
+{
+  cyg_semaphore_wait(&ser->tx_ready);
+  return ser->tx_result;
+}
+
+// --------------------------------------------------------------------------
+// Perform a synchronous transmit and wait for it to complete.
+
+int
+usbs_serial_tx(usbs_serial* ser, const void* buf, int n)
+{
+  usbs_serial_start_tx(ser, buf, n);
+  return usbs_serial_wait_for_tx(ser);
+}
+
+// --------------------------------------------------------------------------
+// Start an asynchronous receive of a buffer.
+
+void
+usbs_serial_start_rx(usbs_serial* ser, void* buf, int n)
+{
+  usbs_start_rx_buffer(ser->rx_ep, (unsigned char*) buf, n,
+                       usbs_serial_rx_complete, ser);
+}
+
+// --------------------------------------------------------------------------
+// Block the caller until the receive is complete
+
+int
+usbs_serial_wait_for_rx(usbs_serial* ser)
+{
+  cyg_semaphore_wait(&ser->rx_ready);
+  return ser->rx_result;
+}
+
+// --------------------------------------------------------------------------
+// Perform a synchronous receive and wait for it to complete.
+
+int
+usbs_serial_rx(usbs_serial* ser, void* buf, int n)
+{
+  usbs_serial_start_rx(ser, buf, n);
+  return usbs_serial_wait_for_rx(ser);
+}
+
+// --------------------------------------------------------------------------
+// Initialize a serial port structure.
+
+void
+usbs_serial_init(usbs_serial* ser, usbs_tx_endpoint* tx_ep, 
+                 usbs_rx_endpoint* rx_ep)
+{
+  ser->tx_ep = tx_ep;
+  ser->rx_ep = rx_ep;
+  
+  cyg_semaphore_init(&ser->tx_ready, 0);
+  cyg_semaphore_init(&ser->rx_ready, 0);
+}
+
+// --------------------------------------------------------------------------
+// Start the USB subsystem
+
+void
+usbs_serial_start(void)
+{
+  usbs_serial_init(&usbs_ser0, TX_EP, RX_EP);
+  
+  cyg_mutex_init(&usbs_serial_lock);
+  cyg_cond_init(&usbs_serial_state_cond, &usbs_serial_lock);
+  
+  // Make the mfg & product names into USB string descriptors
+  
+  usbs_serial_create_str_descriptor(mfg_str_descr, 
+                                    CYGDAT_IO_USB_SLAVE_SERIAL_MFG_STR);
+  usbs_serial_create_str_descriptor(product_str_descr, 
+                                    CYGDAT_IO_USB_SLAVE_SERIAL_PRODUCT_STR);
+  
+  // ----- Set up enumeration & USB callbacks -----
+  
+  usbs_serial_state = usbs_serial_ep0->state;
+  
+  usbs_serial_ep0->enumeration_data   = &usb_enum_data;
+  
+  if (usbs_serial_ep0->state_change_fn)
+    usbs_serial_app_state_change_fn = usbs_serial_ep0->state_change_fn;
+  
+  usbs_serial_ep0->state_change_fn = usbs_serial_state_change_handler;
+  
+#ifdef CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM
+  if (!usbs_serial_ep0->class_control_fn)
+    usbs_serial_ep0->class_control_fn = usbs_serial_acm_class_handler;
+#endif
+  
+  // ----- Start USB subsystem -----
+  
+  usbs_start(usbs_serial_ep0);
+}
new file mode 100644
--- /dev/null
+++ b/packages/io/usb/serial/slave/current/tests/usb2serial.c
@@ -0,0 +1,358 @@
+//==========================================================================
+//
+//      usb2serial.c
+//
+//      Example application for the USB serial layer in eCos.
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//===========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Frank M. Pagliughi (fmp), SoRo Systems, Inc.
+// Contributors: 
+// Date:         2008-06-02
+// Description:  USB serial example application.
+//
+//####DESCRIPTIONEND####
+//===========================================================================
+
+#include <cyg/kernel/kapi.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/infra/diag.h>
+#include <pkgconf/kernel.h>
+#include <cyg/io/serialio.h>
+
+// Replace this with any other USB driver desired.
+#include <cyg/io/usb/usbs_at91.h>
+#include <cyg/io/usb/usbs_serial.h>
+#include <pkgconf/io_usb_slave_serial.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+// This application creates a USB-serial converter. To the host it will appear
+// as a single serial USB port, such as /dev/ttyUSB0 for a Linux host.
+// Any characters received from the USB host will be sent out the serial port
+// and visa-verse. It creates a separate, dedicated thread for each direction.
+// 
+// It uses the eCos USB-serial layer to enumerate with the USB host and monitor
+// the connection, but then uses standard C I/O functions to perform the 
+// communications.
+// 
+// The USB serial module can be configured as a generic adapter or an an ACM
+// communications class device. For the latter, the application handles the
+// USB communications class requests which allows it to receive requests from
+// the host to set serial parameters, like the baud rate. This actually turns
+// this example into a more realistic USB-serial adapter that can be configured
+// dynamically by the host.
+// 
+// The eCos library must be configured with the packages for USB slave, USB 
+// serial, and File I/O. It also requires the proper serial port driver for the
+// target platform.
+// 
+// This example was tested with the AT91SAM7S-EK board, but should work with any
+// board that has a USB slave and serial port, and the necessary drivers.
+
+
+// Comment this line out to remove debug output.
+#define DEBUG_OUTPUT
+
+#if defined(DEBUG_OUTPUT)
+#define DBG diag_printf
+#else
+#define DBG (1) ? (void)0 : diag_printf
+#endif
+
+// Set these to the USB devtab entries for the Tx and Rx Bulk endpoints 
+// selected in the configuration of the USB serial subsystem.
+#define USB_TX_DEV  "/dev/usbs1"
+#define USB_RX_DEV  "/dev/usbs2"
+
+// Set this for any available serial port on the target.
+#define SER_DEV     "/dev/ser0"
+
+// Buffer for incoming USB bulk data. The local USB driver can probably split
+// packets, but just in case, making this the page size of the host might be
+// helpful.
+#define BUF_SIZE 4096
+static char usb2ser_buf[BUF_SIZE];
+
+// The threads
+cyg_thread thread[2];
+
+// Space for two 4K stacks
+#define THREAD_STACK_SIZE 4096
+char stack[2][THREAD_STACK_SIZE];
+
+// The handles for the threads
+cyg_handle_t    usb2ser_thread, 
+                ser2usb_thread;
+
+// --------------------------------------------------------------------------
+// For an ACM serial device we can handle the USB class messages to deal with
+// requests from the host like setting the serial parameters (baud rate, 
+// etc).
+
+#ifdef CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM
+
+static cyg_uint8    acm_buf[32];
+static cyg_uint32   baud = 34800;
+
+// --------------------------------------------------------------------------
+// Handler for the completion of a SetLineCoding request from the host.
+// The 'acm_buf' should contain the 7-byte request OUT packet from the
+// host. This contains a request to change the serial parameters.
+// In this example function, we will accept a few different baud rates.
+// To keep the example relatively simple, though, we keep the other serial
+// parameters to 1 stop bit, no parity, 8 data bits.
+
+static usbs_control_return
+acm_set_line_coding(usbs_control_endpoint* ep0, int n)
+{
+  int err;
+  cyg_uint32 req_baud;
+  cyg_io_handle_t handle;
+  
+  // Get the requested baud rate from the received ctrl OUT packet
+  req_baud = ((acm_buf[3] << 24) | (acm_buf[2] << 16) | 
+              (acm_buf[1] << 8) | acm_buf[0]);
+  
+  DBG("Set Baud: %u\n", (unsigned) baud);
+  
+  // Look up the serial handle and attempt to set the baud rate.
+  if (cyg_io_lookup(SER_DEV, &handle) == 0) {
+    cyg_serial_info_t ser_info;
+    cyg_uint32 len = sizeof(ser_info);
+    
+    switch (baud) {
+      case   9600 : ser_info.baud = CYGNUM_SERIAL_BAUD_9600;      break;
+      case  38400 : ser_info.baud = CYGNUM_SERIAL_BAUD_38400;     break;
+      case 115200 : ser_info.baud = CYGNUM_SERIAL_BAUD_115200;    break;
+      default:
+        DBG("Unsupported baud rate\n");
+        return USBS_CONTROL_RETURN_HANDLED;
+    }
+    ser_info.stop = CYGNUM_SERIAL_STOP_1;
+    ser_info.parity = CYGNUM_SERIAL_PARITY_NONE;
+    ser_info.word_length = CYGNUM_SERIAL_WORD_LENGTH_8;
+    ser_info.flags = 0;
+    
+    err = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO, 
+                            &ser_info, &len);
+    if (err == 0)
+      baud = req_baud;
+    else {
+      DBG("Error setting serial params\n");
+    }
+  }
+  else {
+    DBG("Error looking up serial device: %s\n", SER_DEV);
+  }
+  return USBS_CONTROL_RETURN_HANDLED;
+}
+
+// --------------------------------------------------------------------------
+// Handler for the ACM class messages.
+// 
+static usbs_control_return 
+acm_class_handler(usbs_control_endpoint* ep0, void* data)
+{
+  usbs_control_return result = USBS_CONTROL_RETURN_UNKNOWN;
+  
+  usb_devreq  *req = (usb_devreq *) ep0->control_buffer;
+  
+  static cyg_uint8 rsp_buf[32];
+  
+  DBG("ACM Class Handler\n");
+  
+  switch (req->request) {
+    
+    case USBS_SERIAL_SET_LINE_CODING :
+      DBG("Set Line Coding\n");
+      memset(acm_buf, 0, 32);
+      ep0->buffer = acm_buf;
+      ep0->buffer_size = 7;
+      ep0->complete_fn = acm_set_line_coding;
+      result = USBS_CONTROL_RETURN_HANDLED;
+      break;
+      
+    case USBS_SERIAL_GET_LINE_CODING :
+      DBG("Get Line Coding\n");
+      rsp_buf[0] = baud & 0xFF;
+      rsp_buf[1] = (baud >>  8) & 0xFF;
+      rsp_buf[2] = (baud >> 16) & 0xFF;
+      rsp_buf[3] = (baud >> 24) & 0xFF;
+      rsp_buf[4] = 0; // One stop bit
+      rsp_buf[5] = 0; // No parity
+      rsp_buf[6] = 8; // 8 data bits
+      ep0->buffer = rsp_buf;
+      ep0->buffer_size = 7;
+      result = USBS_CONTROL_RETURN_HANDLED;
+      break;
+      
+    default :
+      DBG("*** Unhandled ACM Request: 0x%02X ***\n",
+          (unsigned) req->request);
+  }
+  
+  return result;
+}
+
+#endif      // CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM
+
+// --------------------------------------------------------------------------
+// Thread receives packets from the USB and sends them out the serial port
+// It uses a buffered stdio input, an un-buffered low-level file output.
+// This isn't terribly efficient, but rather an example of both methods.
+
+void usb2ser_func(cyg_addrword_t data)
+{
+  int  c;
+  FILE *rxf = fopen(USB_RX_DEV, "r");
+  int   txh = open(SER_DEV, O_WRONLY, 0);
+  
+  DBG("Usb2Ser: Thread starting\n");
+  
+  if (!rxf) {
+    DBG("Error opening USB rx port\n");
+    return;
+  }
+  
+  if (txh < 0) {
+    DBG("Error opening serial tx port\n");
+    return;
+  }
+  
+  // Give the USB receiver an adequate buffer.
+  setvbuf(rxf, usb2ser_buf, _IOFBF, BUF_SIZE);
+  
+  while (1) {
+    
+    // ----- Wait for the host to configure -----
+    
+    DBG("Usb2Ser: Waiting for USB configuration\n");
+    usbs_serial_wait_until_configured();
+    cyg_thread_delay((cyg_tick_count_t) 10);
+    
+    // ----- While configured read data & send out serial port -----
+    
+    DBG("Usb2Ser: USB configured\n");
+    while (usbs_serial_is_configured()) {
+      if ((c = getc(rxf)) < 0) {
+        DBG("*** USB Read Error: %d ***\n", c);
+      }
+      else {
+        char ch = (char) c;
+        write(txh, &ch, 1);
+      }
+    }
+  }
+}
+
+// --------------------------------------------------------------------------
+// Thread receives packets from the serial port and sends them out the USB
+// It uses a buffered stdio input, an un-buffered low-level file output.
+// This isn't terribly efficient, but rather an example of both methods.
+
+void ser2usb_func(cyg_addrword_t data)
+{
+  int  c;
+  FILE *rxf = fopen(SER_DEV, "r");
+  int  txh = open(USB_TX_DEV, O_WRONLY, 0);
+  
+  DBG("Ser2Usb: Thread starting\n");
+  
+  if (!rxf) {
+    DBG("Error opening serial rx port\n");
+    return;
+  }
+  
+  if (txh < 0) {
+    DBG("Error opening USB tx port\n");
+    return;
+  }
+  
+  while (1) {
+    
+    // ----- Wait for the host to configure -----
+    
+    DBG("Ser2Usb: Waiting for USB configuration\n");
+    usbs_serial_wait_until_configured();
+    cyg_thread_delay((cyg_tick_count_t) 10);
+    
+    // ----- While configured read data & send out serial port -----
+    
+    DBG("Ser2Usb: USB configured\n");
+    while (usbs_serial_is_configured()) {
+      if ((c = getc(rxf)) < 0) {
+        DBG("*** Console Read Error: %d ***\n", c);
+      }
+      else {
+        char ch = (char) c;
+        write(txh, &ch, 1);
+      }
+    }
+  }
+}
+
+// --------------------------------------------------------------------------
+//  Application Startup
+// --------------------------------------------------------------------------
+
+void cyg_user_start(void)
+{
+  DBG("Entering cyg_user_start() function\n");
+  
+#ifdef CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM
+  // Override the class handler to use ours.
+  usbs_serial_ep0->class_control_fn = acm_class_handler;
+#endif
+  
+  cyg_thread_create(4, usb2ser_func, (cyg_addrword_t) 0,
+                    "Usb2Serial", (void *) stack[0], THREAD_STACK_SIZE,
+                    &usb2ser_thread, &thread[0]);
+  
+  cyg_thread_create(4, ser2usb_func, (cyg_addrword_t) 1,
+                    "Serial2Usb", (void *) stack[1], THREAD_STACK_SIZE,
+                    &ser2usb_thread, &thread[1]);
+  
+  // Start USB subsystem
+  usbs_serial_start();
+  
+  // Start the threads running.
+  cyg_thread_resume(usb2ser_thread);
+  cyg_thread_resume(ser2usb_thread);
+}
+
new file mode 100644
--- /dev/null
+++ b/packages/io/usb/serial/slave/current/tests/usbserial_echo.c
@@ -0,0 +1,126 @@
+//==========================================================================
+//
+//      usb_serial_echo.c
+//
+//      Example application for the USB serial layer in eCos.
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//===========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Frank M. Pagliughi (fmp), SoRo Systems, Inc.
+// Contributors: 
+// Date:         2008-06-02
+// Description:  USB serial example application.
+//
+//####DESCRIPTIONEND####
+//===========================================================================
+
+#include <cyg/kernel/kapi.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/infra/diag.h>
+#include <pkgconf/kernel.h>
+#include <cyg/io/usb/usbs_at91.h>
+#include <cyg/io/usb/usbs_serial.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define DEBUG_OUTPUT
+
+#if defined(DEBUG_OUTPUT)
+#define DBG diag_printf
+#else
+#define DBG (1) ? (void)0 : diag_printf
+#endif
+
+typedef unsigned char byte;
+
+// --------------------------------------------------------------------------
+//                                                         Data & Callback(s)
+// --------------------------------------------------------------------------
+
+#define BUF_SIZE        4096
+
+static byte     rx_buf[2][BUF_SIZE+1], tx_buf[BUF_SIZE+1];
+
+// --------------------------------------------------------------------------
+//                                                              Main Routine
+// --------------------------------------------------------------------------
+
+int main(void)
+{
+  int             n;
+  unsigned        ibuf, next_buf;
+  
+  // ----- Start USB subsystem -----
+  
+  usbs_serial_start();
+  
+  // ----- Get data from host and send it back -----
+  
+  while (1) {
+    ibuf = 0;
+    
+    // ----- Wait for the host to configure -----
+    
+    usbs_serial_wait_until_configured();
+    cyg_thread_delay((cyg_tick_count_t) 10);
+    
+    // ----- While configured read data & print to screen -----
+    
+    usbs_serial_start_rx(&usbs_ser0, rx_buf[ibuf], BUF_SIZE);
+    
+    while (usbs_serial_is_configured()) {
+      
+      n = usbs_serial_wait_for_rx(&usbs_ser0);
+      next_buf = ibuf ^ 1;
+      
+      usbs_serial_start_rx(&usbs_ser0, rx_buf[next_buf], BUF_SIZE);
+      
+      if (n < 0) {
+        DBG("*** I/O Error: %d ***\n", n);
+      }
+      else {
+        memcpy(tx_buf, rx_buf[ibuf], n);
+        usbs_serial_tx(&usbs_ser0, tx_buf, n);
+        rx_buf[ibuf][n] = '\0';
+        DBG("%s", rx_buf[ibuf]);
+      }
+      
+      ibuf = next_buf;
+    }
+  }
+  
+  return 0;
+}
+