You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/05/28 18:22:56 UTC

[incubator-nuttx] branch master updated (20ef084 -> 5a9f792)

This is an automated email from the ASF dual-hosted git repository.

gnutt pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git.


    from 20ef084  Fix the indentation and spacing that don't conform to the coding standard.
     new 560ba3a  usbhost: adds a driver for the FTDI FT232R USB to serial converter
     new 5a9f792  nxstyle fixes

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 drivers/usbhost/Kconfig                            |   92 ++
 drivers/usbhost/Make.defs                          |    4 +
 .../usbhost/{usbhost_cdcacm.c => usbhost_ft232r.c} | 1161 +++++++++-----------
 include/nuttx/usb/usbhost.h                        |  157 +--
 4 files changed, 714 insertions(+), 700 deletions(-)
 copy drivers/usbhost/{usbhost_cdcacm.c => usbhost_ft232r.c} (72%)


[incubator-nuttx] 01/02: usbhost: adds a driver for the FTDI FT232R USB to serial converter

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnutt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 560ba3adcd1a80555cbab4d0ebbd49789e5052fe
Author: Nicholas Chin <Ni...@gmail.com>
AuthorDate: Wed May 27 15:32:29 2020 -0400

    usbhost: adds a driver for the FTDI FT232R USB to serial converter
---
 drivers/usbhost/Kconfig          |   92 ++
 drivers/usbhost/Make.defs        |    4 +
 drivers/usbhost/usbhost_ft232r.c | 2798 ++++++++++++++++++++++++++++++++++++++
 include/nuttx/usb/usbhost.h      |   93 +-
 4 files changed, 2952 insertions(+), 35 deletions(-)

diff --git a/drivers/usbhost/Kconfig b/drivers/usbhost/Kconfig
index ae98c2e..0c389b3 100644
--- a/drivers/usbhost/Kconfig
+++ b/drivers/usbhost/Kconfig
@@ -600,4 +600,96 @@ config USBHOST_TRACE_VERBOSE
 
 endif
 
+config USBHOST_FT232R
+	bool "FTDI FT232R support"
+	default n
+	depends on !USBHOST_BULK_DISABLE && !USBHOST_INT_DISABLE
+	select SERIAL_REMOVABLE
+	---help---
+		Select this option to build in host support for FTDI FT232R
+		serial devices.
+
+if USBHOST_FT232R
+
+config USBHOST_FT232R_RXDELAY
+	int "RX poll delay (MSec)"
+	default 200
+	---help---
+		When the CDC/ACM device is inactive, the host must poll it at this
+		rate in order to discover if it has serial data to send to us.
+
+config USBHOST_FT232R_TXDELAY
+	int "TX poll delay (MSec)"
+	default 200
+	---help---
+		When the appellation is inactive, the host must poll it at this
+		rate in order to discover if it has serial data to send to the
+		device.
+
+config USBHOST_FT232R_NPREALLOC
+	int "Preallocated state"
+	default 0
+	---help---
+		If this setting is zero, the FT232R driver will allocate
+		memory as needed for FT232R device state.  If this value is non-
+		zero, then it provides a number of preallocated FT232R state
+		structures.  This increases the static size of the code image, but
+		eliminates all, direct, run-time allocations by the driver.
+
+config USBHOST_FT232R_BAUD
+	int "Initialize FT232R BAUD"
+	default 115200
+
+config USBHOST_FT232R_PARITY
+	int "Initialize FT232R parity"
+	default 0
+	range 0 2
+	---help---
+		Initialize FT232R parity.  0=None, 1=Odd, 2=Even.  Default: None
+
+config USBHOST_FT232R_BITS
+	int "Initialize FT232R transfer size"
+	default 8
+	range 7 8
+	---help---
+		Initialize FT232R number of bits.  Default: 8
+
+config USBHOST_FT232R_2STOP
+	bool "FT232R use two stop bits"
+	default n
+	---help---
+		False = 1 stop bit, True = Two stop bits.  Default: 1 stop bit
+
+config USBHOST_FT232R_HWFLOWCTRL
+	bool "Use FT232R RTS/CTS"
+	default n
+	---help---
+		Enables the FT232R to use its flow control signals
+
+config USBHOST_FT232R_RXBUFSIZE
+	int "Serial RX buffer size"
+	default 128
+	---help---
+		This is the size of the serial buffer that will be used to hold
+		received data.
+
+config USBHOST_FT232R_TXBUFSIZE
+	int "Serial TX buffer size"
+	default 128
+	---help---
+		This is the size of the serial buffer that will be used to hold
+		data waiting for transmission.
+
+config USBHOST_FT232R_LATENCY
+	int "Latency Timer"
+	default 16
+	range 0 255
+	---help---
+		A timeout for UART to USB packet reception. The FT232R will
+		release its buffer for sending to the USB host once this timeout
+		occurs or the buffer is full. Measured in ms.
+
+endif # USBHOST_FT232R
+
+
 endif # USBHOST
diff --git a/drivers/usbhost/Make.defs b/drivers/usbhost/Make.defs
index cf058a1..332e83c 100644
--- a/drivers/usbhost/Make.defs
+++ b/drivers/usbhost/Make.defs
@@ -74,6 +74,10 @@ ifeq ($(CONFIG_USBHOST_MAX3421E),y)
 CSRCS += usbhost_max3421e.c
 endif
 
+ifeq ($(CONFIG_USBHOST_FT232R),y)
+CSRCS += usbhost_ft232r.c
+endif
+
 # HCD debug/trace logic
 
 ifeq ($(CONFIG_USBHOST_TRACE),y)
diff --git a/drivers/usbhost/usbhost_ft232r.c b/drivers/usbhost/usbhost_ft232r.c
new file mode 100644
index 0000000..d85bfb8
--- /dev/null
+++ b/drivers/usbhost/usbhost_ft232r.c
@@ -0,0 +1,2798 @@
+/****************************************************************************
+ * drivers/usbhost/usbhost_ft232r.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/arch.h>
+#include <nuttx/wqueue.h>
+#include <nuttx/clock.h>
+#include <nuttx/fs/ioctl.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/serial/serial.h>
+
+#include <nuttx/usb/usb.h>
+#include <nuttx/usb/usbhost.h>
+#include <nuttx/usb/usbhost_devaddr.h>
+
+#ifdef CONFIG_USBHOST_FT232R
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+#ifndef CONFIG_USBHOST
+#  warning USB host support not enabled (CONFIG_USBHOST)
+#endif
+
+#ifdef CONFIG_USBHOST_BULK_DISABLE
+#  warning USB bulk endpoint support is disabled (CONFIG_USBHOST_BULK_DISABLE)
+#endif
+
+#ifdef CONFIG_USBHOST_INT_DISABLE
+#  warning USB interrupt endpoint support is disabled (CONFIG_USBHOST_INT_DISABLE)
+#endif
+
+#if !defined(CONFIG_SCHED_WORKQUEUE)
+#  warning Worker thread support is required (CONFIG_SCHED_WORKQUEUE)
+#else
+#  ifndef CONFIG_SCHED_HPWORK
+#    warning High priority work thread support is required (CONFIG_SCHED_HPWORK)
+#  endif
+#  ifndef CONFIG_SCHED_LPWORK
+#    warning Low priority work thread support is required (CONFIG_SCHED_LPWORK)
+#  endif
+#  if CONFIG_SCHED_LPNTHREADS < 2
+#    warning Multiple low priority work threads recommended for performance (CONFIG_SCHED_LPNTHREADS > 1)
+#  endif
+#endif
+
+#ifndef CONFIG_SERIAL_REMOVABLE
+#  warning Removable serial device support is required (CONFIG_SERIAL_REMOVABLE)
+#endif
+
+#ifdef CONFIG_USBHOST_FT232R_RXDELAY
+#  define USBHOST_FT232R_RXDELAY MSEC2TICK(CONFIG_USBHOST_FT232R_RXDELAY)
+#else
+#  define USBHOST_FT232R_RXDELAY MSEC2TICK(200)
+#endif
+
+#ifdef CONFIG_USBHOST_FT232R_TXDELAY
+#  define USBHOST_FT232R_TXDELAY MSEC2TICK(CONFIG_USBHOST_FT232R_TXDELAY)
+#else
+#  define USBHOST_FT232R_TXDELAY MSEC2TICK(200)
+#endif
+
+/* If the create() method is called by the USB host device driver from an
+ * interrupt handler, then it will be unable to call kmm_malloc() in order to
+ * allocate a new class instance.  If the create() method is called from the
+ * interrupt level, then class instances must be pre-allocated.
+ */
+
+#ifndef CONFIG_USBHOST_FT232R_NPREALLOC
+#  define CONFIG_USBHOST_FT232R_NPREALLOC 0
+#endif
+
+#if CONFIG_USBHOST_FT232R_NPREALLOC > 32
+#  error Currently limited to 32 devices /dev/ttyUSB[n]
+#endif
+
+#ifndef CONFIG_USBHOST_FT232R_RXBUFSIZE
+#  define CONFIG_USBHOST_FT232R_RXBUFSIZE 128
+#endif
+
+#ifndef CONFIG_USBHOST_FT232R_TXBUFSIZE
+#  define CONFIG_USBHOST_FT232R_TXBUFSIZE 128
+#endif
+
+/* Initial line coding */
+
+#ifndef CONFIG_USBHOST_FT232R_BAUD
+#  define CONFIG_USBHOST_FT232R_BAUD 115200
+#endif
+
+#ifndef CONFIG_USBHOST_FT232R_PARITY
+#  define CONFIG_USBHOST_FT232R_PARITY 0
+#endif
+
+#ifndef CONFIG_USBHOST_FT232R_BITS
+#  define CONFIG_USBHOST_FT232R_BITS 8
+#endif
+
+#ifndef CONFIG_USBHOST_FT232R_2STOP
+#  define CONFIG_USBHOST_FT232R_2STOP 0
+#endif
+
+#ifndef CONFIG_USBHOST_FT232R_LATENCY
+#  define CONFIG_USBHOST_FT232R_LATENCY 16
+#endif
+
+/* Driver support ***********************************************************/
+
+/* This format is used to construct the /dev/sd[n] device driver path.  It
+ * defined here so that it will be used consistently in all places.
+ */
+
+#define DEV_FORMAT             "/dev/ttyUSB%d"
+#define DEV_NAMELEN            16
+
+#define MAX_NOTIFICATION       32
+
+/* Used in usbhost_connect() */
+
+#define USBHOST_DATAIF_FOUND   0x01      /* Data interface found */
+#define USBHOST_BULKIN_FOUND   0x02      /* Bulk IN interface found */
+#define USBHOST_BULKOUT_FOUND  0x04      /* Bulk OUT interface found */
+
+#define USBHOST_ALLFOUND     0x07     /* All configuration things */
+
+#define USBHOST_MAX_CREFS      INT16_MAX /* Max cref count before signed overflow */
+
+/* Configuration options */
+
+/* Special case baud rates */
+
+#define USBHOST_FT232R_BAUD_2MHZ 2000000
+#define USBHOST_FT232R_BAUD_3MHZ 3000000
+#define USBHOST_FT232R_MAX_BAUD USBHOST_FT232R_BAUD_3MHZ
+
+/* FT232R Control Transfer Request Types */
+
+#define USBHOST_FT232R_CTRLREQ_RESET        0x0
+#define USBHOST_FT232R_CTRLREQ_MODEMCTRL    0x1
+#define USBHOST_FT232R_CTRLREQ_SETFLOWCTRL  0x2
+#define USBHOST_FT232R_CTRLREQ_SETBAUD      0x3
+#define USBHOST_FT232R_CTRLREQ_SETDATA      0x4
+#define USBHOST_FT232R_CTRLREQ_GETMODEMSTAT 0x5
+#define USBHOST_FT232R_CTRLREQ_SETLATTIMER  0x9
+#define USBHOST_FT232R_CTRLREQ_GETLATTIMER  0xA
+
+#define USBHOST_FT232R_MODEMCTRL_VAL_DTR 0x1
+#define USBHOST_FT232R_MODEMCTRL_VAL_RTS 0x2
+#define USBHOST_FT232R_MODEMCTRL_VAL_DTR_EN 0x100
+#define USBHOST_FT232R_MODEMCTRL_VAL_RTS_EN 0x200
+
+#define USBHOST_FT232R_SETDATA_NBIT_MASK    0xFF
+#define USBHOST_FT232R_SETDATA_PARITY_MASK  0x7
+#define USBHOST_FT232R_SETDATA_PARITY_SHIFT 8
+#define USBHOST_FT232R_SETDATA_2STOP        0x1000
+#define USBHOST_FT232R_SETDATA_BREAK        0x4000
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure contains the internal, private state of the USB host ftdi.
+ */
+
+struct usbhost_ft232r_s
+{
+  /* This is the externally visible portion of the state.  The usbclass must
+   * the first element of the structure.  It is then cast compatible with
+   * struct usbhost_ft232r_s.
+   */
+
+  struct usbhost_class_s usbclass;
+
+  /* This is the standard of the lower-half serial interface.  It is not
+   * the first element of the structure, but includes a pointer back to the
+   * the beginning of this structure.
+   */
+
+  struct uart_dev_s uartdev;
+
+  /* The remainder of the fields are provide to the FTDI class */
+
+  volatile bool  disconnected;   /* TRUE: Device has been disconnected */
+  bool           stop2;          /* True: 2 stop bits (for line coding) */
+  bool           txena;          /* True: TX "interrupts" enabled */
+  bool           rxena;          /* True: RX "interrupts" enabled */
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+  bool           iflow;          /* True: Input flow control (RTS) enabled */
+  bool           rts;            /* True: Input flow control is in effect */
+#endif
+#ifdef CONFIG_SERIAL_OFLOWCONTROL
+  bool           oflow;          /* True: Output flow control (CTS) enabled */
+#endif
+#ifdef CONFIG_USBHOST_FT232R_HWFLOWCTRL
+  bool           cts;            /* True: Clear to send to FTDI chip */
+#endif
+  uint8_t        minor;          /* Minor number identifying the /dev/ttyUSB[n] device */
+  uint8_t        dataif;         /* Data interface number */
+  uint8_t        nbits;          /* Number of bits (for line encoding) */
+  uint8_t        parity;         /* Parity (for line encoding) */
+  uint16_t       pktsize;        /* Allocated size of transfer buffers */
+  uint16_t       nrxbytes;       /* Number of bytes in the RX packet buffer */
+  uint16_t       rxndx;          /* Index to the next byte in the RX packet buffer */
+  int16_t        crefs;          /* Reference count on the driver instance */
+  int16_t        nbytes;         /* The number of bytes actually transferred */
+  sem_t          exclsem;        /* Used to maintain mutual exclusive access */
+  struct work_s  ntwork;         /* For asynchronous notification work */
+  struct work_s  rxwork;         /* For RX packet work */
+  struct work_s  txwork;         /* For TX packet work */
+  FAR uint8_t   *ctrlreq;        /* Allocated ctrl request structure */
+  FAR uint8_t   *inbuf;          /* Allocated RX buffer for the Bulk IN endpoint */
+  FAR uint8_t   *outbuf;         /* Allocated TX buffer for the Bulk OUT endpoint */
+  uint32_t       baud;           /* Current baud for line coding */
+  usbhost_ep_t   bulkin;         /* Bulk IN endpoint */
+  usbhost_ep_t   bulkout;        /* Bulk OUT endpoint */
+
+  /* This is the serial data buffer */
+
+  char           rxbuffer[CONFIG_USBHOST_FT232R_RXBUFSIZE];
+  char           txbuffer[CONFIG_USBHOST_FT232R_TXBUFSIZE];
+};
+
+/* This is how struct usbhost_ft232r_s looks to the free list logic */
+
+struct usbhost_freestate_s
+{
+  FAR struct usbhost_freestate_s *flink;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Semaphores */
+
+static int usbhost_takesem(FAR sem_t *sem);
+static void usbhost_forcetake(FAR sem_t *sem);
+#define usbhost_givesem(s) nxsem_post(s);
+
+/* Memory allocation services */
+
+static FAR struct usbhost_ft232r_s *usbhost_allocclass(void);
+static void usbhost_freeclass(FAR struct usbhost_ft232r_s *usbclass);
+
+/* Device name management */
+
+static int  usbhost_devno_alloc(FAR struct usbhost_ft232r_s *priv);
+static void usbhost_devno_free(FAR struct usbhost_ft232r_s *priv);
+static inline void usbhost_mkdevname(FAR struct usbhost_ft232r_s *priv,
+              FAR char *devname);
+
+/* UART buffer data transfer */
+
+static void usbhost_txdata_work(FAR void *arg);
+static void usbhost_rxdata_work(FAR void *arg);
+
+/* Worker thread actions */
+
+static void usbhost_destroy(FAR void *arg);
+
+/* Helpers for usbhost_connect() */
+
+static int  usbhost_cfgdesc(FAR struct usbhost_ft232r_s *priv,
+              FAR const uint8_t *configdesc, int desclen);
+
+/* (Little Endian) Data helpers */
+
+static inline uint16_t usbhost_getle16(FAR const uint8_t *val);
+static inline uint16_t usbhost_getbe16(FAR const uint8_t *val);
+static inline void usbhost_putle16(FAR uint8_t *dest, uint16_t val);
+
+/* Transfer descriptor memory management */
+
+static int  usbhost_alloc_buffers(FAR struct usbhost_ft232r_s *priv);
+static void usbhost_free_buffers(FAR struct usbhost_ft232r_s *priv);
+
+/* struct usbhost_registry_s methods */
+
+static struct usbhost_class_s *usbhost_create(
+              FAR struct usbhost_hubport_s *hport,
+              FAR const struct usbhost_id_s *id);
+
+/* struct usbhost_class_s methods */
+
+static int  usbhost_connect(FAR struct usbhost_class_s *usbclass,
+              FAR const uint8_t *configdesc, int desclen);
+static int  usbhost_disconnected(FAR struct usbhost_class_s *usbclass);
+
+/* Serial driver lower-half interfaces */
+
+static int  usbhost_setup(FAR struct uart_dev_s *uartdev);
+static void usbhost_shutdown(FAR struct uart_dev_s *uartdev);
+static int  usbhost_attach(FAR struct uart_dev_s *uartdev);
+static void usbhost_detach(FAR struct uart_dev_s *uartdev);
+static int  usbhost_ioctl(FAR struct file *filep, int cmd,
+              unsigned long arg);
+static void usbhost_rxint(FAR struct uart_dev_s *uartdev, bool enable);
+static bool usbhost_rxavailable(FAR struct uart_dev_s *uartdev);
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+static bool usbhost_rxflowcontrol(FAR struct uart_dev_s *uartdev,
+              unsigned int nbuffered, bool upper);
+#endif
+static void usbhost_txint(FAR struct uart_dev_s *uartdev, bool enable);
+static bool usbhost_txready(FAR struct uart_dev_s *uartdev);
+static bool usbhost_txempty(FAR struct uart_dev_s *uartdev);
+
+/* FTDI control transfer helpers */
+
+static int ft232r_ctrlxfer(FAR struct usbhost_ft232r_s *priv, uint8_t req,
+                          uint16_t value, uint16_t index);
+static int ft232r_reset(FAR struct usbhost_ft232r_s *priv, bool purgerxtx);
+static int ft232r_modemctrl(FAR struct usbhost_ft232r_s *priv);
+static int ft232r_setflowctrl(FAR struct usbhost_ft232r_s *priv);
+static int ft232r_setdivisor(uint32_t *divisor, uint32_t baud);
+static int ft232r_setbaud(FAR struct usbhost_ft232r_s *priv);
+static int ft232r_setdata(FAR struct usbhost_ft232r_s *priv);
+static int ft232r_setlat(FAR struct usbhost_ft232r_s *priv);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* This structure provides the registry entry ID information that will  be
+ * used to associate the USB host FTDI class to a connected USB
+ * device.
+ */
+
+static const struct usbhost_id_s g_id[4] =
+{
+  {
+    USB_CLASS_VENDOR_SPEC,  /* base     */
+    0xff,                   /* subclass */
+    0xff,                   /* proto    */
+    0x0403,                 /* vid      */
+    0x6001                  /* pid      */
+  },
+  {
+    USB_CLASS_VENDOR_SPEC,  /* base     */
+    0xff,                   /* subclass */
+    0xff,                   /* proto    */
+    0x0403,                 /* vid      */
+    0x6015                  /* pid      */
+  }
+};
+
+/* This is the USB host FTDI class's registry entry */
+
+static struct usbhost_registry_s g_ft232r =
+{
+  NULL,                   /* flink    */
+  usbhost_create,         /* create   */
+  2,                      /* nids     */
+  &g_id[0]                /* id[]     */
+};
+
+/* Serial driver lower half interface */
+
+static const struct uart_ops_s g_uart_ops =
+{
+  usbhost_setup,         /* setup */
+  usbhost_shutdown,      /* shutdown */
+  usbhost_attach,        /* attach */
+  usbhost_detach,        /* detach */
+  usbhost_ioctl,         /* ioctl */
+  NULL           ,       /* receive */
+  usbhost_rxint,         /* rxinit */
+  usbhost_rxavailable,   /* rxavailable */
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+  usbhost_rxflowcontrol, /* rxflowcontrol */
+#endif
+  NULL,                  /* send */
+  usbhost_txint,         /* txinit */
+  usbhost_txready,       /* txready */
+  usbhost_txempty        /* txempty */
+};
+
+/* This is an array of pre-allocated USB host FTDI class instances */
+
+#if CONFIG_USBHOST_FT232R_NPREALLOC > 0
+static struct usbhost_ft232r_s g_prealloc[CONFIG_USBHOST_FT232R_NPREALLOC];
+#endif
+
+/* This is a list of free, pre-allocated USB host FTDI class instances */
+
+#if CONFIG_USBHOST_FT232R_NPREALLOC > 0
+static FAR struct usbhost_freestate_s *g_freelist;
+#endif
+
+/* This is a bitmap that is used to allocate device
+ * minor numbers /dev/ttyUSB[n].
+ */
+
+static uint32_t g_devinuse;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: usbhost_takesem
+ *
+ * Description:
+ *   This is just a wrapper to handle the annoying behavior of semaphore
+ *   waits that return due to the receipt of a signal.
+ *
+ ****************************************************************************/
+
+static int usbhost_takesem(FAR sem_t *sem)
+{
+  return nxsem_wait_uninterruptible(sem);
+}
+
+/****************************************************************************
+ * Name: usbhost_forcetake
+ *
+ * Description:
+ *   This is just another wrapper but this one continues even if the thread
+ *   is canceled.  This must be done in certain conditions where were must
+ *   continue in order to clean-up resources.
+ *
+ ****************************************************************************/
+
+static void usbhost_forcetake(FAR sem_t *sem)
+{
+  int ret;
+
+  do
+    {
+      ret = nxsem_wait_uninterruptible(sem);
+
+      /* The only expected error would -ECANCELED meaning that the
+       * parent thread has been canceled.  We have to continue and
+       * terminate the poll in this case.
+       */
+
+      DEBUGASSERT(ret == OK || ret == -ECANCELED);
+    }
+  while (ret < 0);
+}
+
+/****************************************************************************
+ * Name: usbhost_allocclass
+ *
+ * Description:
+ *   This is really part of the logic that implements the create() method
+ *   of struct usbhost_registry_s.  This function allocates memory for one
+ *   new class instance.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   On success, this function will return a non-NULL instance of struct
+ *   usbhost_class_s.  NULL is returned on failure; this function will
+ *   will fail only if there are insufficient resources to create another
+ *   USB host class instance.
+ *
+ ****************************************************************************/
+
+#if CONFIG_USBHOST_FT232R_NPREALLOC > 0
+static FAR struct usbhost_ft232r_s *usbhost_allocclass(void)
+{
+  FAR struct usbhost_freestate_s *entry;
+  irqstate_t flags;
+
+  /* We may be executing from an interrupt handler so we need to take one of
+   * our pre-allocated class instances from the free list.
+   */
+
+  flags = enter_critical_section();
+  entry = g_freelist;
+  if (entry)
+    {
+      g_freelist = entry->flink;
+    }
+
+  leave_critical_section(flags);
+  uinfo("Allocated: %p\n", entry);
+  return (FAR struct usbhost_ft232r_s *)entry;
+}
+#else
+static FAR struct usbhost_ft232r_s *usbhost_allocclass(void)
+{
+  FAR struct usbhost_ft232r_s *priv;
+
+  /* We are not executing from an interrupt handler so we can just call
+   * kmm_malloc() to get memory for the class instance.
+   */
+
+  DEBUGASSERT(!up_interrupt_context());
+  priv = (FAR struct usbhost_ft232r_s *)
+    kmm_malloc(sizeof(struct usbhost_ft232r_s));
+
+  uinfo("Allocated: %p\n", priv);
+  return priv;
+}
+#endif
+
+/****************************************************************************
+ * Name: usbhost_freeclass
+ *
+ * Description:
+ *   Free a class instance previously allocated by usbhost_allocclass().
+ *
+ * Input Parameters:
+ *   usbclass - A reference to the class instance to be freed.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#if CONFIG_USBHOST_FT232R_NPREALLOC > 0
+static void usbhost_freeclass(FAR struct usbhost_ft232r_s *usbclass)
+{
+  FAR struct usbhost_freestate_s *entry =
+    (FAR struct usbhost_freestate_s *)usbclass;
+  irqstate_t flags;
+  DEBUGASSERT(entry != NULL);
+
+  uinfo("Freeing: %p\n", entry);
+
+  /* Just put the pre-allocated class structure back on the freelist */
+
+  flags = enter_critical_section();
+  entry->flink = g_freelist;
+  g_freelist = entry;
+  leave_critical_section(flags);
+}
+#else
+static void usbhost_freeclass(FAR struct usbhost_ft232r_s *usbclass)
+{
+  DEBUGASSERT(usbclass != NULL);
+
+  /* Free the class instance (calling kmm_free() in case we are executing
+   * from an interrupt handler.
+   */
+
+  uinfo("Freeing: %p\n", usbclass);
+  kmm_free(usbclass);
+}
+#endif
+
+/****************************************************************************
+ * Name: usbhost_devno_alloc
+ *
+ * Description:
+ *   Allocate a unique /dev/ttyACM[n] minor number in the range 0-31.
+ *
+ ****************************************************************************/
+
+static int usbhost_devno_alloc(FAR struct usbhost_ft232r_s *priv)
+{
+  irqstate_t flags;
+  int devno;
+
+  flags = enter_critical_section();
+  for (devno = 0; devno < 32; devno++)
+    {
+      uint32_t bitno = 1 << devno;
+      if ((g_devinuse & bitno) == 0)
+        {
+          g_devinuse |= bitno;
+          priv->minor = devno;
+          leave_critical_section(flags);
+          return OK;
+        }
+    }
+
+  leave_critical_section(flags);
+  return -EMFILE;
+}
+
+/****************************************************************************
+ * Name: usbhost_devno_free
+ *
+ * Description:
+ *   Free a /dev/ttyACM[n] minor number so that it can be used.
+ *
+ ****************************************************************************/
+
+static void usbhost_devno_free(FAR struct usbhost_ft232r_s *priv)
+{
+  int devno = priv->minor;
+
+  if (devno >= 0 && devno < 32)
+    {
+      irqstate_t flags = enter_critical_section();
+      g_devinuse &= ~(1 << devno);
+      leave_critical_section(flags);
+    }
+}
+
+/****************************************************************************
+ * Name: usbhost_mkdevname
+ *
+ * Description:
+ *   Format a /dev/ttyACM[n] device name given a minor number.
+ *
+ ****************************************************************************/
+
+static inline void usbhost_mkdevname(FAR struct usbhost_ft232r_s *priv,
+                                     FAR char *devname)
+{
+  snprintf(devname, DEV_NAMELEN, DEV_FORMAT, priv->minor);
+}
+
+/****************************************************************************
+ * Name: ft232r_ctrlxfer
+ *
+ * Description:
+ *   Free a class instance previously allocated by usbhost_allocclass().
+ *
+ * Input Parameters:
+ *   priv  - A reference to the USB host class instance.
+ *   req   - FTDI control transfer type.
+ *   value - Value for control transfer.
+ *   index - Index for control transfer.
+ *
+ * Returned Value:
+ *   0 on success. Negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int ft232r_ctrlxfer(FAR struct usbhost_ft232r_s *priv, uint8_t req,
+                          uint16_t value, uint16_t index)
+{
+  FAR struct usbhost_hubport_s *hport;
+  FAR struct usb_ctrlreq_s *ctrlreq;
+  int ret;
+
+  hport = priv->usbclass.hport;
+  DEBUGASSERT(hport);
+
+  /* Initialize the control request */
+
+  ctrlreq          = (FAR struct usb_ctrlreq_s *)priv->ctrlreq;
+  ctrlreq->type    = USB_DIR_OUT | USB_REQ_TYPE_VENDOR |
+                    USB_REQ_RECIPIENT_DEVICE;
+  ctrlreq->req     = req;
+
+  usbhost_putle16(ctrlreq->value, value);
+  usbhost_putle16(ctrlreq->index, index);
+  usbhost_putle16(ctrlreq->len,   0);
+
+  /* And send the request */
+
+  ret = DRVR_CTRLOUT(hport->drvr, hport->ep0, ctrlreq, NULL);
+  if (ret < 0)
+    {
+      uerr("ERROR: DRVR_CTRLOUT failed: %d\n", ret);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: ft232r_reset
+ *
+ * Description:
+ *   Resets the FT232.
+ *
+ * Input Parameters:
+ *   priv  - A reference to the USB host class instance.
+ *   purgerxtx - True if the RX and TX buffers of the FTDI chip
+ *               should be flushed.
+ *
+ * Returned Value:
+ *   0 on success. Negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int ft232r_reset(FAR struct usbhost_ft232r_s *priv, bool purgerxtx)
+{
+  int ret = ft232r_ctrlxfer(priv, USBHOST_FT232R_CTRLREQ_RESET,
+                              purgerxtx, 0);
+  if (ret < 0)
+    {
+      uerr("ERROR: ft232r_ctrlxfer failed: %d\n", ret);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: ft232r_modemctrl
+ *
+ * Description:
+ *   Sets RTS and DTR.
+ *
+ * Input Parameters:
+ *   priv  - A reference to the USB host class instance.
+ *
+ * Returned Value:
+ *   0 on success. Negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int ft232r_modemctrl(FAR struct usbhost_ft232r_s *priv)
+{
+  uint16_t value =  USBHOST_FT232R_MODEMCTRL_VAL_RTS |
+                    USBHOST_FT232R_MODEMCTRL_VAL_DTR |
+                    USBHOST_FT232R_MODEMCTRL_VAL_RTS_EN |
+                    USBHOST_FT232R_MODEMCTRL_VAL_DTR_EN;
+
+  int ret = ft232r_ctrlxfer(priv, USBHOST_FT232R_CTRLREQ_MODEMCTRL,
+                              value, 0);
+  if (ret < 0)
+    {
+      uerr("ERROR: ft232r_ctrlxfer failed: %d\n", ret);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: ft232r_setflowctrl
+ *
+ * Description:
+ *   Enables/ disables hardware flow control.
+ *
+ * Input Parameters:
+ *   priv  - A reference to the USB host class instance.
+ *
+ * Returned Value:
+ *   0 on success. Negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int ft232r_setflowctrl(FAR struct usbhost_ft232r_s *priv)
+{
+  /* upper byte XOFF char, lower byte XON char */
+
+  uint16_t value = 0;
+
+  /* Upper byte: flow control settings.
+   *    0th bit: RTS/CTS flow control.
+   *    1st bit: DTR/DSR flow control.
+   *    2nd bit: XON/XOFF flow control.
+   * Lower byte: 0
+   */
+
+  uint16_t index = 0;
+
+#ifdef CONFIG_USBHOST_FT232R_HWFLOWCTRL
+  index = 0x100;
+#endif
+
+  int ret = ft232r_ctrlxfer(priv, USBHOST_FT232R_CTRLREQ_SETFLOWCTRL,
+                            value, index);
+  if (ret < 0)
+    {
+      uerr("ERROR: ft232r_ctrlxfer failed: %d\n", ret);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: ft232r_setdivisor
+ *
+ * Description:
+ *   Converts a baud rate to the corresponding FT232R divisor. Returns an
+ *   error if the requested baud rate is not possible.
+ *
+ * Input Parameters:
+ *   divisor - Where the calculated divisor will be written to.
+ *   baud    - The requested baud rate.
+ * Returned Value:
+ *   0 on success. Negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int ft232r_setdivisor(uint32_t *divisor, uint32_t baud)
+{
+  int ret = 0;
+
+  /* Deal with special case baud rates: 3MHz and 2MHz */
+
+  if (baud == USBHOST_FT232R_BAUD_3MHZ)
+    {
+      *divisor = 0;
+    }
+  else if (baud == USBHOST_FT232R_BAUD_2MHZ)
+    {
+      *divisor = 1;
+    }
+  else if (baud > USBHOST_FT232R_BAUD_3MHZ / 2)
+    {
+      /* FT232 doesn't support fractional divisors between 0 and 2. */
+
+      ret = -EINVAL;
+    }
+  else
+    {
+      int divfrac[9] = {0,
+                        500,
+                        250,
+                        125,
+                        375,
+                        625,
+                        750,
+                        875,
+                        1000
+                       };
+
+      double frac = (double)USBHOST_FT232R_MAX_BAUD / (double)baud;
+
+      *divisor = (uint32_t)frac;
+      int rem = (frac - *divisor) * 1000.0;
+
+      if (rem > 0)
+        {
+          int i;
+          int j = 0;
+          int closest = rem;
+
+          for (i = 1; i < 9; i++)
+            {
+              if (rem == divfrac[i])
+                {
+                  j = i;
+                  break;
+                }
+
+              if ((rem > divfrac[i] && (rem - divfrac[i]) < closest))
+                {
+                  j = i;
+                  closest = rem - divfrac[i];
+                }
+              else if (rem < divfrac[i] && (divfrac[i] - rem) < closest)
+                {
+                  j = i;
+                  closest = divfrac[i] - rem;
+                }
+            }
+
+          /* Make sure the calculated baud is within 3% of the
+           * requested baud rate.
+           */
+
+          double err = (frac -
+                      (double)(*divisor + (double)divfrac[j] / 1000.0))
+                      / frac;
+          if (err < -0.03 || err > 0.03)
+            {
+              ret = -ENOTSUP;
+            }
+
+          if (j == 9)
+            {
+              *divisor += 1;
+            }
+          else
+            {
+              *divisor |= (j & 0x7) << 14;
+            }
+        }
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: ft232r_setbaud
+ *
+ * Description:
+ *   Sets the FT232 baud rate.
+ *
+ * Input Parameters:
+ *   priv  - A reference to the USB host class instance.
+ *
+ * Returned Value:
+ *   0 on success. Negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int ft232r_setbaud(FAR struct usbhost_ft232r_s *priv)
+{
+  /* Convert baud to FT232 divisor */
+
+  uint32_t divisor;
+  int ret = ft232r_setdivisor(&divisor, priv->baud);
+  if (ret < 0)
+    {
+      uerr("ERROR: ft232r_setdivisor failed: %d\n", ret);
+    }
+  else
+    {
+      ret = ft232r_ctrlxfer(priv, USBHOST_FT232R_CTRLREQ_SETBAUD,
+              divisor & 0xffff, divisor && 0x10000);
+      if (ret < 0)
+        {
+          uerr("ERROR: ft232r_ctrlxfer failed: %d\n", ret);
+        }
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: ft232r_setdata
+ *
+ * Description:
+ *   Sets the packet characteristics for the UART side of the FT232.
+ *
+ * Input Parameters:
+ *   priv  - A reference to the USB host class instance.
+ *
+ * Returned Value:
+ *   0 on success. Negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int ft232r_setdata(FAR struct usbhost_ft232r_s *priv)
+{
+  /* Build up line coding */
+
+  uint16_t linecoding = (priv->nbits & USBHOST_FT232R_SETDATA_NBIT_MASK) |
+      ((priv->parity & USBHOST_FT232R_SETDATA_PARITY_MASK)
+      << USBHOST_FT232R_SETDATA_PARITY_SHIFT);
+  if (priv->stop2)
+    {
+      linecoding |= CONFIG_USBHOST_FT232R_2STOP;
+    }
+
+  int ret = ft232r_ctrlxfer(priv, USBHOST_FT232R_CTRLREQ_SETDATA,
+                            linecoding, 0);
+  if (ret < 0)
+    {
+      uerr("ERROR: ft232r_ctrlxfer failed: %d\n", ret);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: ft232r_setlat
+ *
+ * Description:
+ *   Sets the UART latency of the FT232.
+ *
+ * Input Parameters:
+ *   priv  - A reference to the USB host class instance.
+ *
+ * Returned Value:
+ *   0 on success. Negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int ft232r_setlat(FAR struct usbhost_ft232r_s *priv)
+{
+  int ret = ft232r_ctrlxfer(priv, USBHOST_FT232R_CTRLREQ_SETLATTIMER,
+                            CONFIG_USBHOST_FT232R_LATENCY, 0);
+  if (ret < 0)
+    {
+      uerr("ERROR: ft232r_ctrlxfer failed: %d\n", ret);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * UART buffer data transfer
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: usbhost_txdata_work
+ *
+ * Description:
+ *   Send more OUT data to the attached FTDI device.
+ *
+ * Input Parameters:
+ *   arg - A reference to the FTDI class private data
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void usbhost_txdata_work(FAR void *arg)
+{
+  FAR struct usbhost_ft232r_s *priv;
+  FAR struct usbhost_hubport_s *hport;
+  FAR struct uart_dev_s *uartdev;
+  FAR struct uart_buffer_s *txbuf;
+  ssize_t nwritten;
+  int txndx;
+  int txtail;
+  int ret;
+
+  priv = (FAR struct usbhost_ft232r_s *)arg;
+  DEBUGASSERT(priv);
+
+  hport = priv->usbclass.hport;
+  DEBUGASSERT(hport);
+
+  uartdev = &priv->uartdev;
+  txbuf   = &uartdev->xmit;
+
+  /* Do nothing if TX transmission is disabled */
+
+  if (!priv->txena)
+    {
+      /* Terminate the work now *without* rescheduling */
+
+      return;
+    }
+
+  /* Loop until The UART TX buffer is empty (or we become disconnected) */
+
+  txtail = txbuf->tail;
+  txndx  = 0;
+
+#ifdef CONFIG_USBHOST_FT232R_HWFLOWCTRL
+  while (txtail != txbuf->head && priv->txena &&
+          !priv->disconnected && priv->cts)
+#else
+  while (txtail != txbuf->head && priv->txena && !priv->disconnected)
+#endif
+    {
+      /* Copy data from the UART TX buffer until either 1) the UART TX
+       * buffer has been emptied, or 2) the Bulk OUT buffer is full.
+       */
+
+      txndx = 0;
+      while (txtail != txbuf->head && txndx < priv->pktsize)
+        {
+          /* Copy the next byte */
+
+          priv->outbuf[txndx] = txbuf->buffer[txtail];
+
+          /* Increment counters and indices */
+
+          txndx++;
+          if (++txtail >= txbuf->size)
+            {
+             txtail = 0;
+            }
+        }
+
+      /* Save the updated tail pointer so that it cannot be sent again */
+
+      txbuf->tail = txtail;
+
+      /* Bytes were removed from the TX buffer.  Inform any waiters that
+       * there is space available in the TX buffer.
+       */
+
+      uart_datasent(uartdev);
+
+      /* Send the filled TX buffer to the FTDI device */
+
+      nwritten = DRVR_TRANSFER(hport->drvr, priv->bulkout,
+                               priv->outbuf, txndx);
+      if (nwritten < 0)
+        {
+          /* The most likely reason for a failure is that FTDI device
+           * NAK'ed our packet OR that the device has been disconnected.
+           *
+           * Just break out of the loop, rescheduling the work (unless
+           * the device is disconnected).
+           */
+
+          uerr("ERROR: DRVR_TRANSFER for packet failed: %d\n",
+               (int)nwritten);
+          break;
+        }
+    }
+
+  /* We get here because: 1) the UART TX buffer is empty and there is
+   * nothing more to send, 2) the FTDI device was not ready to accept our
+   * data, or the device is no longer available.
+   *
+   * If the last packet sent was and even multiple of the packet size, then
+   * we need to send a zero length packet (ZLP).
+   */
+
+  if (txndx == priv->pktsize && !priv->disconnected)
+    {
+      /* Send the ZLP to the FTDI device */
+
+      nwritten = DRVR_TRANSFER(hport->drvr, priv->bulkout,
+                               priv->outbuf, 0);
+      if (nwritten < 0)
+        {
+          /* The most likely reason for a failure is that FTDI device
+           * NAK'ed our packet.
+           */
+
+          uerr("ERROR: DRVR_TRANSFER for ZLP failed: %d\n", (int)nwritten);
+        }
+    }
+
+  /* Check again if TX reception is enabled and that the device is still
+   * connected.  These states could have changed since we started the
+   * transfer.
+   */
+
+  if (priv->txena && !priv->disconnected)
+    {
+      /* Schedule TX data work to occur after a delay. */
+
+      ret = work_queue(LPWORK, &priv->txwork, usbhost_txdata_work, priv,
+                       USBHOST_FT232R_TXDELAY);
+      DEBUGASSERT(ret >= 0);
+      UNUSED(ret);
+    }
+}
+
+/****************************************************************************
+ * Name: usbhost_rxdata_work
+ *
+ * Description:
+ *   Get more IN data from the attached FTDI device.
+ *
+ * Input Parameters:
+ *   arg - A reference to the FTDI class private data
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void usbhost_rxdata_work(FAR void *arg)
+{
+  FAR struct usbhost_ft232r_s *priv;
+  FAR struct usbhost_hubport_s *hport;
+  FAR struct uart_dev_s *uartdev;
+  FAR struct uart_buffer_s *rxbuf;
+  ssize_t nread;
+  int nxfrd;
+  int nexthead;
+  int rxndx;
+  int ret;
+
+  priv    = (FAR struct usbhost_ft232r_s *)arg;
+  DEBUGASSERT(priv);
+
+  hport   = priv->usbclass.hport;
+  DEBUGASSERT(hport);
+
+  uartdev = &priv->uartdev;
+  rxbuf   = &uartdev->recv;
+
+  /* Get the index in the RX packet buffer where we will take the first
+   * byte of data.
+   */
+
+  rxndx    = priv->rxndx;
+  nxfrd    = 0;
+
+  /* Get the index to the value of the UART RX buffer head AFTER the
+   * first character has been stored.  We need to know this in order
+   * to test if the UART RX buffer is full.
+   */
+
+  nexthead = rxbuf->head + 1;
+  if (nexthead >= rxbuf->size)
+    {
+      nexthead = 0;
+    }
+
+  /* Loop until either:
+   *
+   * 1. The UART RX buffer is full
+   * 2. There is no more data available from the FTDI device
+   * 3. RX rec
+   */
+
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+  while (priv->rxena && priv->rts && !priv->disconnected)
+#else
+  while (priv->rxena && !priv->disconnected)
+#endif
+    {
+      /* Stop now if there is no room for another
+       * character in the RX buffer.
+       */
+
+      if (nexthead == rxbuf->tail)
+        {
+          /* Break out of the loop, rescheduling the work */
+
+          break;
+        }
+
+      /* Do we have any buffer RX data to transfer? */
+
+      if (priv->nrxbytes < 1)
+        {
+          /* No.. Read more data from the FTDI device */
+
+          nread = DRVR_TRANSFER(hport->drvr, priv->bulkin,
+                                priv->inbuf, priv->pktsize);
+          if (nread < 0)
+            {
+              /* The most likely reason for a failure is that the has no
+               * data available now and NAK'ed the IN token OR that the
+               * transfer was cancelled because the device was disconnected.
+               *
+               * Just break out of the loop, rescheduling the work (if the
+               * device was not disconnected.
+               */
+
+              uerr("ERROR: DRVR_TRANSFER for packet failed: %d\n",
+                   (int)nread);
+              break;
+            }
+
+          /* Save the number of bytes read.  This might be zero if
+           * a Zero Length Packet (ZLP) is received.  The ZLP is
+           * part of the bulk transfer protocol, but otherwise of
+           * no interest to us. Alternatively it can be 2 bytes of
+           * only FTDI status information.
+           */
+
+          priv->nrxbytes = (uint16_t)nread - 2;
+          rxndx          = 0;
+
+          /* When Hardware flow control is used, CTS is reported in the
+           * first byte of RX payload.
+           */
+
+#ifdef CONFIG_USBHOST_FT232R_HWFLOWCTRL
+          if (nread >= 2)
+            {
+              priv->cts = priv->inbuf[0] & 0x10;
+            }
+#endif
+
+          /* Ignore ZLPs and RX of only FTDI status */
+
+          if (nread < 3)
+            {
+              continue;
+            }
+        }
+
+      /* Transfer one byte from the RX packet buffer into UART RX buffer */
+
+      rxbuf->buffer[rxbuf->head] = priv->inbuf[rxndx + 2]; /* +2 to account for the two status byes */
+      nxfrd++;
+
+      /* Save the updated indices */
+
+      rxbuf->head = nexthead;
+      priv->rxndx = rxndx;
+
+      /* Update the head point for for the next pass through the loop
+       * handling. If nexthead incremented to rxbuf->tail, then the
+       * RX buffer will and we will exit the loop at the top.
+       */
+
+      if (++nexthead >= rxbuf->size)
+        {
+           nexthead = 0;
+        }
+
+      /* Increment the index in the USB IN packet buffer.  If the
+       * index becomes equal to the number of bytes in the buffer, then
+       * we have consumed all of the RX data.
+       */
+
+      if (++rxndx >= priv->nrxbytes)
+        {
+          /* In that case set the number of bytes in the buffer to zero.
+           * This will force re-reading on the next time through the loop.
+           */
+
+          priv->nrxbytes = 0;
+          priv->rxndx    = 0;
+
+          /* Inform any waiters there there is new incoming data available. */
+
+          uart_datareceived(uartdev);
+          nxfrd = 0;
+        }
+    }
+
+  /* We break out to here:  1) the UART RX buffer is full, 2) the FTDI
+   * device is not ready to provide us with more serial data, or 3) the
+   * device has been disconnected.
+   *
+   * Check if the device is still available:  RX enabled, no RX flow
+   * control in effect, and that the device is not disconnected. These
+   * states could have changed since we started the transfer.
+   */
+
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+  if (priv->rxena && priv->rts && work_available(&priv->rxwork) &&
+      !priv->disconnected)
+#else
+  if (priv->rxena && work_available(&priv->rxwork) && !priv->disconnected)
+#endif
+    {
+      /* Schedule RX data reception work to occur after a delay.  This will
+       * affect our responsive in certain cases.  The delayed work, however,
+       * will be cancelled and replaced with immediate work when the upper
+       * layer demands more data.
+       */
+
+      ret = work_queue(LPWORK, &priv->rxwork, usbhost_rxdata_work, priv,
+                       USBHOST_FT232R_RXDELAY);
+      DEBUGASSERT(ret >= 0);
+      UNUSED(ret);
+    }
+
+  /* If any bytes were added to the buffer, inform any waiters there there
+   * is new incoming data available.
+   */
+
+  if (nxfrd)
+    {
+      uart_datareceived(uartdev);
+    }
+}
+
+/****************************************************************************
+ * Name: usbhost_destroy
+ *
+ * Description:
+ *   The USB FTDI device has been disconnected and the reference count
+ *   on the USB host class instance has gone to 1.. Time to destroy the USB
+ *   host class instance.
+ *
+ * Input Parameters:
+ *   arg - A reference to the class instance to be destroyed.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void usbhost_destroy(FAR void *arg)
+{
+  FAR struct usbhost_ft232r_s *priv = (FAR struct usbhost_ft232r_s *)arg;
+  FAR struct usbhost_hubport_s *hport;
+  char devname[DEV_NAMELEN];
+
+  DEBUGASSERT(priv != NULL && priv->usbclass.hport != NULL);
+  hport = priv->usbclass.hport;
+
+  uinfo("crefs: %d\n", priv->crefs);
+
+  /* Unregister the serial lower half driver */
+
+  usbhost_mkdevname(priv, devname);
+  unregister_driver(devname);
+
+  /* Release the device name used by this connection */
+
+  usbhost_devno_free(priv);
+
+  /* Free the allocated endpoints */
+
+  if (priv->bulkout)
+    {
+      DRVR_EPFREE(hport->drvr, priv->bulkout);
+    }
+
+  if (priv->bulkin)
+    {
+      DRVR_EPFREE(hport->drvr, priv->bulkin);
+    }
+
+  /* Free any transfer buffers */
+
+  usbhost_free_buffers(priv);
+
+  /* Destroy the semaphores */
+
+  nxsem_destroy(&priv->exclsem);
+
+  /* Disconnect the USB host device */
+
+  DRVR_DISCONNECT(hport->drvr, hport);
+
+  /* Free the function address assigned to this device */
+
+  usbhost_devaddr_destroy(hport, hport->funcaddr);
+  hport->funcaddr = 0;
+
+  /* And free the class instance.  */
+
+  usbhost_freeclass(priv);
+}
+
+/****************************************************************************
+ * Name: usbhost_cfgdesc
+ *
+ * Description:
+ *   This function implements the connect() method of struct
+ *   usbhost_class_s.  This method is a callback into the class
+ *   implementation.  It is used to provide the device's configuration
+ *   descriptor to the class so that the class may initialize properly
+ *
+ * Input Parameters:
+ *   priv - The USB host class instance.
+ *   configdesc - A pointer to a uint8_t buffer container the configuration
+ *     descriptor.
+ *   desclen - The length in bytes of the configuration descriptor.
+ *
+ * Returned Value:
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
+ *
+ * Assumptions:
+ *   This function will *not* be called from an interrupt handler.
+ *
+ ****************************************************************************/
+
+static int usbhost_cfgdesc(FAR struct usbhost_ft232r_s *priv,
+                           FAR const uint8_t *configdesc, int desclen)
+{
+  FAR struct usbhost_hubport_s *hport;
+  FAR struct usb_cfgdesc_s *cfgdesc;
+  FAR struct usb_desc_s *desc;
+  struct usbhost_epdesc_s bindesc;
+  struct usbhost_epdesc_s boutdesc;
+  struct usbhost_epdesc_s iindesc;
+  int remaining;
+  uint8_t found  = 0;
+  uint8_t currif = 0;
+  int ret;
+
+  DEBUGASSERT(priv != NULL && priv->usbclass.hport &&
+              configdesc != NULL && desclen >= sizeof(struct usb_cfgdesc_s));
+  hport = priv->usbclass.hport;
+
+  /* Keep the compiler from complaining about uninitialized variables */
+
+  memset(&bindesc, 0, sizeof(struct usbhost_epdesc_s));
+  memset(&boutdesc, 0, sizeof(struct usbhost_epdesc_s));
+  memset(&iindesc, 0, sizeof(struct usbhost_epdesc_s));
+
+  /* Verify that we were passed a configuration descriptor */
+
+  cfgdesc = (FAR struct usb_cfgdesc_s *)configdesc;
+  if (cfgdesc->type != USB_DESC_TYPE_CONFIG)
+    {
+      return -EINVAL;
+    }
+
+  /* Get the total length of the configuration descriptor (little endian).
+   * It might be a good check to get the number of interfaces here too.
+   */
+
+  remaining = (int)usbhost_getle16(cfgdesc->totallen);
+
+  /* Skip to the next entry descriptor */
+
+  configdesc += cfgdesc->len;
+  remaining  -= cfgdesc->len;
+
+  /* Loop where there are more descriptors to examine */
+
+  while (remaining >= sizeof(struct usb_desc_s))
+    {
+      /* What is the next descriptor? */
+
+      desc = (FAR struct usb_desc_s *)configdesc;
+      switch (desc->type)
+        {
+        /* Interface descriptor. The FTDI device may include two
+         * interfaces:
+         *
+         * 1) A data interface which consists of two endpoints (bulk in +
+         *    bulk out) and
+         * 2) A control interface which consists of one interrupt in
+         *    endpoint.
+         */
+
+        case USB_DESC_TYPE_INTERFACE:
+          {
+            FAR struct usb_ifdesc_s *ifdesc =
+              (FAR struct usb_ifdesc_s *)configdesc;
+
+            uinfo("Interface descriptor: class: %d subclass: %d proto: %d\n",
+                  ifdesc->classid, ifdesc->subclass, ifdesc->protocol);
+            DEBUGASSERT(remaining >= USB_SIZEOF_IFDESC);
+
+            /* Check for the FTDI data interface */
+
+            if (ifdesc->classid == USB_CLASS_VENDOR_SPEC &&
+                (found & USBHOST_DATAIF_FOUND) == 0)
+              {
+                /* Save the data interface number and mark that the data
+                 * interface found has been found.
+                 */
+
+                priv->dataif  = ifdesc->ifno;
+                found        |= USBHOST_DATAIF_FOUND;
+                currif        = USBHOST_DATAIF_FOUND;
+              }
+            else
+              {
+                /* Its something else */
+
+                currif        = 0;
+              }
+          }
+          break;
+
+        /* Endpoint descriptor.  We expect two bulk endpoints, an IN and an
+         * OUT.
+         */
+
+        case USB_DESC_TYPE_ENDPOINT:
+          {
+            FAR struct usb_epdesc_s *epdesc =
+              (FAR struct usb_epdesc_s *)configdesc;
+
+            uinfo("Endpoint descriptor: currif: %02x attr: %02x\n",
+                  currif, epdesc->attr);
+            DEBUGASSERT(remaining >= USB_SIZEOF_EPDESC);
+
+            /* Check for a bulk endpoint. */
+
+            if (currif == USBHOST_DATAIF_FOUND &&
+                (epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) ==
+                USB_EP_ATTR_XFER_BULK)
+              {
+                /* Yes.. it is a bulk endpoint.  IN or OUT? */
+
+                if (USB_ISEPOUT(epdesc->addr))
+                  {
+                    /* It is an OUT bulk endpoint.  There should be only one
+                     * bulk OUT endpoint.
+                     */
+
+                    if ((found & USBHOST_BULKOUT_FOUND) != 0)
+                      {
+                        /* Oops.. more than one endpoint.  We don't know
+                         * what to do with this.
+                         */
+
+                        return -EINVAL;
+                      }
+
+                    found |= USBHOST_BULKOUT_FOUND;
+
+                    /* Save the bulk OUT endpoint information */
+
+                    boutdesc.hport        = hport;
+                    boutdesc.addr         = epdesc->addr &
+                                            USB_EP_ADDR_NUMBER_MASK;
+                    boutdesc.in           = false;
+                    boutdesc.xfrtype      = USB_EP_ATTR_XFER_BULK;
+                    boutdesc.interval     = epdesc->interval;
+                    boutdesc.mxpacketsize =
+                      usbhost_getle16(epdesc->mxpacketsize);
+
+                    uinfo("Bulk OUT EP addr:%d mxpacketsize:%d\n",
+                          boutdesc.addr, boutdesc.mxpacketsize);
+                  }
+                else
+                  {
+                    /* It is an IN bulk endpoint.  There should be only one
+                     * bulk IN endpoint.
+                     */
+
+                    if ((found & USBHOST_BULKIN_FOUND) != 0)
+                      {
+                        /* Oops.. more than one endpoint.  We don't know
+                         * what to do with this.
+                         */
+
+                        return -EINVAL;
+                      }
+
+                    found |= USBHOST_BULKIN_FOUND;
+
+                    /* Save the bulk IN endpoint information */
+
+                    bindesc.hport        = hport;
+                    bindesc.addr         = epdesc->addr &
+                                           USB_EP_ADDR_NUMBER_MASK;
+                    bindesc.in           = 1;
+                    bindesc.xfrtype      = USB_EP_ATTR_XFER_BULK;
+                    bindesc.interval     = epdesc->interval;
+                    bindesc.mxpacketsize =
+                      usbhost_getle16(epdesc->mxpacketsize);
+
+                    uinfo("Bulk IN EP addr:%d mxpacketsize:%d\n",
+                          bindesc.addr, bindesc.mxpacketsize);
+                  }
+              }
+          }
+          break;
+
+        /* Other descriptors are just ignored for now */
+
+        default:
+          break;
+        }
+
+      /* If we found everything we need with this interface, then break out
+       * of the loop early.
+       */
+
+      if (found == USBHOST_ALLFOUND)
+        {
+          break;
+        }
+
+      /* Increment the address of the next descriptor */
+
+      configdesc += desc->len;
+      remaining  -= desc->len;
+    }
+
+  /* Sanity checking... did we find all of things that we needed for the
+   * FT232R interface?
+   */
+
+  if (found != USBHOST_ALLFOUND)
+    {
+      uerr("ERROR: Found DATA IF:%s BULK IN:%s BULK OUT:%s\n",
+           (found & USBHOST_DATAIF_FOUND)  != 0  ? "YES" : "NO",
+           (found & USBHOST_BULKIN_FOUND)  != 0 ? "YES" : "NO",
+           (found & USBHOST_BULKOUT_FOUND) != 0 ? "YES" : "NO");
+      return -EINVAL;
+    }
+
+  /* We are good... Allocate the endpoints */
+
+  ret = DRVR_EPALLOC(hport->drvr, &boutdesc, &priv->bulkout);
+  if (ret < 0)
+    {
+      uerr("ERROR: Failed to allocate Bulk OUT endpoint\n");
+      return ret;
+    }
+
+  ret = DRVR_EPALLOC(hport->drvr, &bindesc, &priv->bulkin);
+  if (ret < 0)
+    {
+      uerr("ERROR: Failed to allocate Bulk IN endpoint\n");
+      DRVR_EPFREE(hport->drvr, priv->bulkout);
+      return ret;
+    }
+
+  uinfo("Endpoints allocated\n");
+  return OK;
+}
+
+/****************************************************************************
+ * Name: usbhost_getle16
+ *
+ * Description:
+ *   Get a (possibly unaligned) 16-bit little endian value.
+ *
+ * Input Parameters:
+ *   val - A pointer to the first byte of the little endian value.
+ *
+ * Returned Value:
+ *   A uint16_t representing the whole 16-bit integer value
+ *
+ ****************************************************************************/
+
+static inline uint16_t usbhost_getle16(FAR const uint8_t *val)
+{
+  return (uint16_t)val[1] << 8 | (uint16_t)val[0];
+}
+
+/****************************************************************************
+ * Name: usbhost_getbe16
+ *
+ * Description:
+ *   Get a (possibly unaligned) 16-bit big endian value.
+ *
+ * Input Parameters:
+ *   val - A pointer to the first byte of the big endian value.
+ *
+ * Returned Value:
+ *   A uint16_t representing the whole 16-bit integer value
+ *
+ ****************************************************************************/
+
+static inline uint16_t usbhost_getbe16(FAR const uint8_t *val)
+{
+  return (uint16_t)val[0] << 8 | (uint16_t)val[1];
+}
+
+/****************************************************************************
+ * Name: usbhost_putle16
+ *
+ * Description:
+ *   Put a (possibly unaligned) 16-bit little endian value.
+ *
+ * Input Parameters:
+ *   dest - A pointer to the first byte to save the little endian value.
+ *   val - The 16-bit value to be saved.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void usbhost_putle16(FAR uint8_t *dest, uint16_t val)
+{
+  dest[0] = val & 0xff; /* Little endian means LS byte first in byte stream */
+  dest[1] = val >> 8;
+}
+
+/****************************************************************************
+ * Name: usbhost_alloc_buffers
+ *
+ * Description:
+ *   Allocate transfer buffer memory.
+ *
+ * Input Parameters:
+ *   priv - A reference to the class instance.
+ *
+ * Returned Value:
+ *   On success, zero (OK) is returned.  On failure, an negated errno value
+ *   is returned to indicate the nature of the failure.
+ *
+ ****************************************************************************/
+
+static int usbhost_alloc_buffers(FAR struct usbhost_ft232r_s *priv)
+{
+  FAR struct usbhost_hubport_s *hport;
+  size_t maxlen;
+  int ret;
+
+  DEBUGASSERT(priv != NULL && priv->usbclass.hport != NULL);
+  hport = priv->usbclass.hport;
+
+  /* Allocate memory for control requests */
+
+  ret = DRVR_ALLOC(hport->drvr, (FAR uint8_t **)&priv->ctrlreq, &maxlen);
+  if (ret < 0)
+    {
+      uerr("ERROR: DRVR_ALLOC of ctrlreq failed: %d\n", ret);
+      goto errout;
+    }
+
+  DEBUGASSERT(maxlen >= sizeof(struct usb_ctrlreq_s));
+
+  /* Set the size of Bulk IN and OUT buffers to the max packet size */
+
+  priv->pktsize = (hport->speed == USB_SPEED_HIGH) ? 512 : 64;
+
+  /* Allocate a RX buffer for Bulk IN transfers */
+
+  ret = DRVR_IOALLOC(hport->drvr, &priv->inbuf, priv->pktsize);
+  if (ret < 0)
+    {
+      uerr("ERROR: DRVR_IOALLOC of Bulk IN buffer failed: %d (%d bytes)\n",
+           ret, priv->pktsize);
+      goto errout;
+    }
+
+  /* Allocate a TX buffer for Bulk IN transfers */
+
+  ret = DRVR_IOALLOC(hport->drvr, &priv->outbuf, priv->pktsize);
+  if (ret < 0)
+    {
+      uerr("ERROR: DRVR_IOALLOC of Bulk OUT buffer failed: %d (%d bytes)\n",
+           ret, priv->pktsize);
+      goto errout;
+    }
+
+  return OK;
+
+errout:
+  usbhost_free_buffers(priv);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: usbhost_free_buffers
+ *
+ * Description:
+ *   Free transfer buffer memory.
+ *
+ * Input Parameters:
+ *   priv - A reference to the class instance.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void usbhost_free_buffers(FAR struct usbhost_ft232r_s *priv)
+{
+  FAR struct usbhost_hubport_s *hport;
+
+  DEBUGASSERT(priv != NULL && priv->usbclass.hport != NULL);
+  hport = priv->usbclass.hport;
+
+  if (priv->ctrlreq)
+    {
+      DRVR_FREE(hport->drvr, priv->ctrlreq);
+    }
+
+  if (priv->inbuf)
+    {
+      DRVR_IOFREE(hport->drvr, priv->inbuf);
+    }
+
+  if (priv->outbuf)
+    {
+      DRVR_IOFREE(hport->drvr, priv->outbuf);
+    }
+
+  priv->pktsize      = 0;
+  priv->ctrlreq      = NULL;
+  priv->inbuf        = NULL;
+  priv->outbuf       = NULL;
+}
+
+/****************************************************************************
+ * struct usbhost_registry_s methods
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: usbhost_create
+ *
+ * Description:
+ *   This function implements the create() method of struct
+ *   usbhost_registry_s.  The create() method is a callback into the class
+ *   implementation.  It is used to (1) create a new instance of the USB
+ *   host class state and to (2) bind a USB host driver "session" to the
+ *   class instance.  Use of this create() method will support environments
+ *   where there may be multiple USB ports and multiple USB devices
+ *   simultaneously connected.
+ *
+ * Input Parameters:
+ *   hport - The hub port that manages the new class instance.
+ *   id - In the case where the device supports multiple base classes,
+ *     subclasses, or protocols, this specifies which to configure for.
+ *
+ * Returned Value:
+ *   On success, this function will return a non-NULL instance of struct
+ *   usbhost_class_s that can be used by the USB host driver to communicate
+ *   with the USB host class.  NULL is returned on failure; this function
+ *   will fail only if the hport input parameter is NULL or if there are
+ *   insufficient resources to create another USB host class instance.
+ *
+ ****************************************************************************/
+
+static FAR struct usbhost_class_s *
+usbhost_create(FAR struct usbhost_hubport_s *hport,
+               FAR const struct usbhost_id_s *id)
+{
+  FAR struct usbhost_ft232r_s *priv;
+  FAR struct uart_dev_s *uartdev;
+
+  /* Allocate a USB host FTDI class instance */
+
+  priv = usbhost_allocclass();
+  if (priv)
+    {
+      /* Initialize the allocated FTDI class instance */
+
+      memset(priv, 0, sizeof(struct usbhost_ft232r_s));
+
+      /* Assign a device number to this class instance */
+
+      if (usbhost_devno_alloc(priv) == OK)
+        {
+          /* Initialize class method function pointers */
+
+          priv->usbclass.hport        = hport;
+          priv->usbclass.connect      = usbhost_connect;
+          priv->usbclass.disconnected = usbhost_disconnected;
+
+          /* The initial reference count is 1...
+           * One reference is held by the driver
+           */
+
+          priv->crefs = 1;
+
+          /* Initialize semaphores
+           * (this works okay in the interrupt context)
+           */
+
+          nxsem_init(&priv->exclsem, 0, 1);
+
+          /* Set up the serial lower-half interface */
+
+          uartdev              = &priv->uartdev;
+          uartdev->recv.size   = CONFIG_USBHOST_FT232R_RXBUFSIZE;
+          uartdev->recv.buffer = priv->rxbuffer;
+          uartdev->xmit.size   = CONFIG_USBHOST_FT232R_TXBUFSIZE;
+          uartdev->xmit.buffer = priv->txbuffer;
+          uartdev->ops         = &g_uart_ops;
+          uartdev->priv        = priv;
+
+          /* Set up the initial line status */
+
+          priv->baud           = CONFIG_USBHOST_FT232R_BAUD;
+          priv->nbits          = CONFIG_USBHOST_FT232R_BITS;
+          priv->parity         = CONFIG_USBHOST_FT232R_PARITY;
+          priv->stop2          = CONFIG_USBHOST_FT232R_2STOP;
+
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+          priv->rts            = true;
+#endif
+
+          /* Return the instance of the USB FTDI class */
+
+          return &priv->usbclass;
+        }
+    }
+
+  /* An error occurred. Free the allocation and return NULL on all failures */
+
+  if (priv)
+    {
+      usbhost_freeclass(priv);
+    }
+
+  return NULL;
+}
+
+/****************************************************************************
+ * struct usbhost_class_s methods
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: usbhost_connect
+ *
+ * Description:
+ *   This function implements the connect() method of struct
+ *   usbhost_class_s.  This method is a callback into the class
+ *   implementation.  It is used to provide the device's configuration
+ *   descriptor to the class so that the class may initialize properly
+ *
+ * Input Parameters:
+ *   usbclass - The USB host class entry previously obtained from a call to
+ *     create().
+ *   configdesc - A pointer to a uint8_t buffer container the configuration
+ *     descriptor.
+ *   desclen - The length in bytes of the configuration descriptor.
+ *
+ * Returned Value:
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
+ *
+ *   NOTE that the class instance remains valid upon return with a failure.
+ *   It is the responsibility of the higher level enumeration logic to call
+ *   CLASS_DISCONNECTED to free up the class driver resources.
+ *
+ * Assumptions:
+ *   - This function will *not* be called from an interrupt handler.
+ *   - If this function returns an error, the USB host controller driver
+ *     must call to DISCONNECTED method to recover from the error
+ *
+ ****************************************************************************/
+
+static int usbhost_connect(FAR struct usbhost_class_s *usbclass,
+                           FAR const uint8_t *configdesc, int desclen)
+{
+  FAR struct usbhost_ft232r_s *priv =
+                  (FAR struct usbhost_ft232r_s *)usbclass;
+  char devname[DEV_NAMELEN];
+  int ret;
+
+  DEBUGASSERT(priv != NULL &&
+              configdesc != NULL &&
+              desclen >= sizeof(struct usb_cfgdesc_s));
+
+  /* Get exclusive access to the device structure */
+
+  ret = usbhost_takesem(&priv->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* Increment the reference count.  This will prevent usbhost_destroy() from
+   * being called asynchronously if the device is removed.
+   */
+
+  priv->crefs++;
+  DEBUGASSERT(priv->crefs == 2);
+
+  /* Parse the configuration descriptor to get the bulk I/O endpoints */
+
+  ret = usbhost_cfgdesc(priv, configdesc, desclen);
+  if (ret < 0)
+    {
+      uerr("ERROR: usbhost_cfgdesc() failed: %d\n", ret);
+      goto errout;
+    }
+
+  /* Set aside a transfer buffer for exclusive use by the FTDI driver */
+
+  ret = usbhost_alloc_buffers(priv);
+  if (ret < 0)
+    {
+      uerr("ERROR: Failed to allocate transfer buffer\n");
+      goto errout;
+    }
+
+  /* Send the initial line encoding */
+
+  ret = ft232r_reset(priv, true);
+  if (ret < 0)
+    {
+      uerr("ERROR: ft232r_reset() failed: %d\n", ret);
+    }
+
+  ret = ft232r_setflowctrl(priv);
+  if (ret < 0)
+    {
+      uerr("ERROR: ft232r_setflowctrl() failed: %d\n", ret);
+    }
+
+  ret = ft232r_modemctrl(priv);
+  if (ret < 0)
+    {
+      uerr("ERROR: ft232r_modemctrl() failed: %d\n", ret);
+    }
+
+  ret = ft232r_setbaud(priv);
+  if (ret < 0)
+    {
+      uerr("ERROR: ft232r_setbaud() failed: %d\n", ret);
+    }
+
+  ret = ft232r_setdata(priv);
+  if (ret < 0)
+    {
+      uerr("ERROR: ft232r_setdata() failed: %d\n", ret);
+    }
+
+  ret = ft232r_setlat(priv);
+  if (ret < 0)
+    {
+      uerr("ERROR: ft232r_setlat() failed: %d\n", ret);
+    }
+
+  /* Register the lower half serial instance with the upper half serial
+   * driver.
+   */
+
+  usbhost_mkdevname(priv, devname);
+  uinfo("Register device: %s\n", devname);
+
+  ret = uart_register(devname, &priv->uartdev);
+  if (ret < 0)
+    {
+      uerr("ERROR: uart_register() failed: %d\n", ret);
+      goto errout;
+    }
+
+errout:
+  /* Decrement the reference count.  We incremented the reference count
+   * above so that usbhost_destroy() could not be called.  We now have to
+   * be concerned about asynchronous modification of crefs because the
+   * serial driver has been registered.
+   */
+
+  DEBUGASSERT(priv->crefs >= 2);
+  priv->crefs--;
+
+  /* Release the semaphore... there is a race condition here.
+   * Decrementing the reference count and releasing the semaphore
+   * allows usbhost_destroy() to execute (on the worker thread);
+   * the class driver instance could get destroyed before we are
+   * ready to handle it!
+   */
+
+  usbhost_givesem(&priv->exclsem);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: usbhost_disconnected
+ *
+ * Description:
+ *   This function implements the disconnected() method of struct
+ *   usbhost_class_s.  This method is a callback into the class
+ *   implementation.  It is used to inform the class that the USB device has
+ *   been disconnected.
+ *
+ * Input Parameters:
+ *   usbclass - The USB host class entry previously obtained from a call to
+ *     create().
+ *
+ * Returned Value:
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
+ *
+ * Assumptions:
+ *   This function may be called from an interrupt handler.
+ *
+ ****************************************************************************/
+
+static int usbhost_disconnected(FAR struct usbhost_class_s *usbclass)
+{
+  FAR struct usbhost_ft232r_s *priv =
+    (FAR struct usbhost_ft232r_s *)usbclass;
+  irqstate_t flags;
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Set an indication to any users of the FTDI device that the device
+   * is no longer available.
+   */
+
+  flags              = enter_critical_section();
+  priv->disconnected = true;
+
+  /* Let the upper half driver know that serial device is no longer
+   * connected.
+   */
+
+  uart_connected(&priv->uartdev, false);
+
+  /* Now check the number of references on the class instance.  If it is one,
+   * then we can free the class instance now.  Otherwise, we will have to
+   * wait until the holders of the references free them by closing the
+   * serial driver.
+   */
+
+  uinfo("crefs: %d\n", priv->crefs);
+  if (priv->crefs == 1)
+    {
+      /* Destroy the class instance.  If we are executing from an interrupt
+       * handler, then defer the destruction to the worker thread.
+       * Otherwise, destroy the instance now.
+       */
+
+      if (up_interrupt_context())
+        {
+          /* Destroy the instance on the worker thread. */
+
+          uinfo("Queuing destruction: worker %p->%p\n",
+                priv->ntwork.worker, usbhost_destroy);
+
+          DEBUGASSERT(work_available(&priv->ntwork));
+          work_queue(HPWORK, &priv->ntwork, usbhost_destroy, priv, 0);
+        }
+      else
+        {
+          /* Do the work now */
+
+          usbhost_destroy(priv);
+        }
+    }
+
+  leave_critical_section(flags);
+  return OK;
+}
+
+/****************************************************************************
+ * Serial Lower-Half Interfaces
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: usbhost_setup
+ *
+ * Description:
+ *   Configure the USART baud, bits, parity, etc. This method is called the
+ *   first time that the serial port is opened.
+ *
+ ****************************************************************************/
+
+static int usbhost_setup(FAR struct uart_dev_s *uartdev)
+{
+  FAR struct usbhost_ft232r_s *priv;
+  irqstate_t flags;
+  int ret;
+
+  uinfo("Entry\n");
+  DEBUGASSERT(uartdev && uartdev->priv);
+  priv = (FAR struct usbhost_ft232r_s *)uartdev->priv;
+
+  /* Make sure that we have exclusive access to the private data structure */
+
+  DEBUGASSERT(priv->crefs > 0 && priv->crefs < USBHOST_MAX_CREFS);
+  ret = usbhost_takesem(&priv->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* Check if the FTDI device is still connected.  We need to disable
+   * interrupts momentarily to assure that there are no asynchronous
+   * isconnect events.
+   */
+
+  flags = enter_critical_section();
+  if (priv->disconnected)
+    {
+      /* No... the block driver is no longer bound to the class.  That means
+       * that the USB FTDI device is no longer connected.  Refuse any
+       * further attempts to open the driver.
+       */
+
+      ret = -ENODEV;
+    }
+  else
+    {
+      /* Otherwise, just increment the reference count on the driver */
+
+      priv->crefs++;
+      ret = OK;
+    }
+
+  leave_critical_section(flags);
+  usbhost_givesem(&priv->exclsem);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: usbhost_shutdown
+ *
+ * Description:
+ *   Disable the USART.  This method is called when the serial
+ *   port is closed
+ *
+ ****************************************************************************/
+
+static void usbhost_shutdown(FAR struct uart_dev_s *uartdev)
+{
+  FAR struct usbhost_ft232r_s *priv;
+  irqstate_t flags;
+
+  uinfo("Entry\n");
+  DEBUGASSERT(uartdev && uartdev->priv);
+  priv = (FAR struct usbhost_ft232r_s *)uartdev->priv;
+
+  /* Decrement the reference count on the block driver */
+
+  DEBUGASSERT(priv->crefs > 1);
+  usbhost_forcetake(&priv->exclsem);
+  priv->crefs--;
+
+  /* Release the semaphore.  The following operations when crefs == 1 are
+   * safe because we know that there is no outstanding open references to
+   * the block driver.
+   */
+
+  usbhost_givesem(&priv->exclsem);
+
+  /* We need to disable interrupts momentarily to assure that there are
+   * no asynchronous disconnect events.
+   */
+
+  flags = enter_critical_section();
+
+  /* Check if the USB FTDI device is still connected.  If the
+   * FTDI device is not connected and the reference count just
+   * decremented to one, then unregister the block driver and free
+   * the class instance.
+   */
+
+  if (priv->crefs <= 1 && priv->disconnected)
+    {
+      /* Destroy the class instance */
+
+      DEBUGASSERT(priv->crefs == 1);
+      usbhost_destroy(priv);
+    }
+
+  leave_critical_section(flags);
+}
+
+/****************************************************************************
+ * Name: usbhost_attach
+ *
+ * Description:
+ *   Configure the USART to operation in interrupt driven mode.  This method
+ *   is called when the serial port is opened.  Normally, this is just after
+ *   the setup() method is called, however, the serial console may operate in
+ *   a non-interrupt driven mode during the boot phase.
+ *
+ *   RX and TX interrupts are not enabled when by the attach method (unless
+ *   the hardware supports multiple levels of interrupt enabling).  The RX
+ *   and TX interrupts are not enabled until the txint() and rxint() methods
+ *   are called.
+ *
+ ****************************************************************************/
+
+static int usbhost_attach(FAR struct uart_dev_s *uartdev)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name: usbhost_detach
+ *
+ * Description:
+ *   Detach USART interrupts.  This method is called when the serial port is
+ *   closed normally just before the shutdown method is called.  The
+ *   exception is the serial console which is never shutdown.
+ *
+ ****************************************************************************/
+
+static void usbhost_detach(FAR struct uart_dev_s *uartdev)
+{
+}
+
+/****************************************************************************
+ * Name: usbhost_ioctl
+ *
+ * Description:
+ *   All ioctl calls will be routed through this method
+ *
+ ****************************************************************************/
+
+static int usbhost_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
+{
+  FAR struct inode *inode;
+  FAR struct usbhost_ft232r_s *priv;
+  FAR struct uart_dev_s *uartdev;
+  int ret = 0;
+
+  uinfo("Entry\n");
+  DEBUGASSERT(filep && filep->f_inode);
+  inode = filep->f_inode;
+
+  DEBUGASSERT(inode && inode->i_private);
+  uartdev = (FAR struct uart_dev_s *)inode->i_private;
+
+  DEBUGASSERT(uartdev && uartdev->priv);
+  priv  = (FAR struct usbhost_ft232r_s *)uartdev->priv;
+
+  /* Check if the FTDI device is still connected */
+
+  if (priv->disconnected)
+    {
+      /* No... the serial device has been disconnecgted.  Refuse to process
+       * any ioctl commands.
+       */
+
+      ret = -ENODEV;
+    }
+  else
+    {
+      /* Process the IOCTL by command */
+
+      ret = usbhost_takesem(&priv->exclsem);
+      if (ret < 0)
+        {
+          return ret;
+        }
+
+      switch (cmd)
+        {
+#ifdef CONFIG_SERIAL_TIOCSERGSTRUCT
+        case TIOCSERGSTRUCT:
+          {
+            FAR struct usbhost_ft232r_s *user =
+              (FAR struct usbhost_ft232r_s *)arg;
+            if (!user)
+              {
+                ret = -EINVAL;
+              }
+            else
+              {
+                memcpy(user, uartdev, sizeof(struct usbhost_ft232r_s));
+              }
+          }
+          break;
+#endif
+
+#ifdef CONFIG_SERIAL_TERMIOS
+        case TCGETS:
+          {
+            FAR struct termios *termiosp = (FAR struct termios *)arg;
+
+            if (!termiosp)
+              {
+                ret = -EINVAL;
+                break;
+              }
+
+            cfsetispeed(termiosp, priv->baud);
+
+            termiosp->c_cflag =
+              ((priv->parity != 0) ? PARENB : 0) |
+              ((priv->parity == 1) ? PARODD : 0) |
+              ((priv->stop2) ? CSTOPB : 0)
+#ifdef CONFIG_SERIAL_OFLOWCONTROL
+              | ((priv->oflow) ? CCTS_OFLOW : 0)
+#endif
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+              | ((priv->iflow) ? CRTS_IFLOW : 0)
+#endif
+              ;
+
+            switch (priv->nbits)
+              {
+              case 7:
+                termiosp->c_cflag |= CS7;
+                break;
+
+              default:
+              case 8:
+                termiosp->c_cflag |= CS8;
+                break;
+              }
+          }
+          break;
+
+        case TCSETS:
+          {
+            FAR struct termios *termiosp = (FAR struct termios *)arg;
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+            bool iflow;
+#endif
+
+            if (!termiosp)
+              {
+                ret = -EINVAL;
+                break;
+              }
+
+            if (termiosp->c_cflag & PARENB)
+              {
+                priv->parity = (termiosp->c_cflag & PARODD) ? 1 : 2;
+              }
+            else
+               {
+                priv->parity = 0;
+              }
+
+            priv->stop2 = (termiosp->c_cflag & CSTOPB) != 0;
+#ifdef CONFIG_SERIAL_OFLOWCONTROL
+            priv->oflow = (termiosp->c_cflag & CCTS_OFLOW) != 0;
+#endif
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+            iflow       = priv->iflow;
+            priv->iflow = (termiosp->c_cflag & CRTS_IFLOW) != 0;
+#endif
+
+            switch (termiosp->c_cflag & CSIZE)
+              {
+              case CS7:
+                priv->nbits = 7;
+                break;
+
+              default:
+              case CS8:
+                priv->nbits = 8;
+                break;
+              }
+
+            /* Note that only cfgetispeed is used because we have knowledge
+             * that only one speed is supported.
+             */
+
+            priv->baud = cfgetispeed(termiosp);
+
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+            /* Set RTS if input flow control changed */
+
+            if (iflow != !priv->iflow)
+              {
+                 priv->rts = true;
+              }
+#endif
+
+            ret = ft232r_setbaud(priv);
+            if (ret < 0)
+              {
+                uerr("ERROR: ft232r_setbaud failed: %d\n", ret);
+              }
+
+            ret = ft232r_setdata(priv);
+            if (ret < 0)
+              {
+                uerr("ERROR: ft232r_setdata failed: %d\n", ret);
+              }
+
+            ret = ft232r_setflowctrl(priv);
+            if (ret < 0)
+              {
+                uerr("ERROR: ft232r_setflowctrl failed: %d\n", ret);
+              }
+          }
+
+          break;
+
+#endif /* CONFIG_SERIAL_TERMIOS */
+
+        default:
+          ret = -ENOTTY;
+          break;
+        }
+
+      usbhost_givesem(&priv->exclsem);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: usbhost_rxint
+ *
+ * Description:
+ *   Call to enable or disable RX interrupts
+ *
+ ****************************************************************************/
+
+static void usbhost_rxint(FAR struct uart_dev_s *uartdev, bool enable)
+{
+  FAR struct usbhost_ft232r_s *priv;
+  int ret;
+
+  DEBUGASSERT(uartdev && uartdev->priv);
+  priv = (FAR struct usbhost_ft232r_s *)uartdev->priv;
+
+  /* Are we enabling or disabling RX reception? */
+
+  if (enable && !priv->rxena)
+    {
+      /* Cancel any pending, delayed RX data reception work */
+
+      work_cancel(LPWORK, &priv->rxwork);
+
+      /* Restart immediate RX data reception work (unless RX flow control
+       * is in effect.
+       */
+
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+      if (priv->rts)
+#endif
+        {
+          ret = work_queue(LPWORK, &priv->rxwork,
+                           usbhost_rxdata_work, priv, 0);
+          DEBUGASSERT(ret >= 0);
+          UNUSED(ret);
+        }
+    }
+  else if (!enable && priv->rxena)
+    {
+      /* Cancel any pending RX data reception work */
+
+      work_cancel(LPWORK, &priv->rxwork);
+    }
+
+  /* Save the new RX enable state */
+
+  priv->rxena = enable;
+}
+
+/****************************************************************************
+ * Name: usbhost_rxavailable
+ *
+ * Description:
+ *   Return true if the receive buffer is not empty
+ *
+ ****************************************************************************/
+
+static bool usbhost_rxavailable(FAR struct uart_dev_s *uartdev)
+{
+  FAR struct usbhost_ft232r_s *priv;
+
+  DEBUGASSERT(uartdev && uartdev->priv);
+  priv = (FAR struct usbhost_ft232r_s *)uartdev->priv;
+  return (priv->nrxbytes > 0);
+}
+
+/****************************************************************************
+ * Name: usbhost_rxflowcontrol
+ *
+ * Description:
+ *   Called when Rx buffer is full (or exceeds configured watermark levels
+ *   if CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS is defined).
+ *   Return true if UART activated RX flow control to block more incoming
+ *   data
+ *
+ * Input Parameters:
+ *   uartdev   - UART device instance
+ *   nbuffered - the number of characters currently buffered
+ *               (if CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS is
+ *               not defined the value will be 0 for an empty buffer or the
+ *               defined buffer size for a full buffer)
+ *   upper     - true indicates the upper watermark was crossed where
+ *               false indicates the lower watermark has been crossed
+ *
+ * Returned Value:
+ *   true if RX flow control activated.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+static bool usbhost_rxflowcontrol(FAR struct uart_dev_s *uartdev,
+                                  unsigned int nbuffered, bool upper)
+{
+  FAR struct usbhost_ft232r_s *priv;
+  bool newrts;
+  int ret;
+
+  DEBUGASSERT(uartdev && uartdev->priv);
+  priv = (FAR struct usbhost_ft232r_s *)uartdev->priv
+
+  /* Is RX flow control enabled? */
+
+  if (!priv->iflow)
+    {
+      /* Now.. make sure that RTS is set */
+
+      priv->rts = true;
+      return false;
+    }
+
+  /* Are we enabling or disabling RX flow control? */
+
+  if (priv->rts && upper)
+    {
+      /* RX flow control is not in effect (RTS is true) but we have just
+       * crossed the upper threshold, meaning that we should now clear
+       * RTS.
+       */
+
+      priv->rts = false;
+
+      /* Cancel any pending RX data reception work */
+
+      work_cancel(LPWORK, &priv->rxwork);
+      return true;
+    }
+  else if (!priv->rts && !upper)
+    {
+      /* RX flow control is in effect (RTS is false) and we have just
+       * crossed the lower threshold, meaning that we should now set
+       * RTS.
+       */
+
+       priv->rts = true;
+
+      /* Restart RX data reception work flow unless RX reception is
+       * disabled.
+       */
+
+      if (priv->rxena && work_available(&priv->rxwork))
+        {
+          ret = work_queue(LPWORK, &priv->rxwork,
+                           usbhost_rxdata_work, priv, 0);
+          DEBUGASSERT(ret >= 0);
+          UNUSED(ret);
+        }
+
+      return false;
+    }
+}
+#endif
+
+/****************************************************************************
+ * Name: usbhost_txint
+ *
+ * Description:
+ *   Call to enable or disable TX interrupts
+ *
+ ****************************************************************************/
+
+static void usbhost_txint(FAR struct uart_dev_s *uartdev, bool enable)
+{
+  FAR struct usbhost_ft232r_s *priv;
+  int ret;
+
+  DEBUGASSERT(uartdev && uartdev->priv);
+  priv = (FAR struct usbhost_ft232r_s *)uartdev->priv;
+
+  /* Are we enabling or disabling TX transmission? */
+
+  if (enable && !priv->txena)
+    {
+      /* Cancel any pending, delayed TX data transmission work */
+
+      work_cancel(LPWORK, &priv->txwork);
+
+      /* Restart immediate TX data transmission work */
+
+      ret = work_queue(LPWORK, &priv->txwork,
+                       usbhost_txdata_work, priv, 0);
+      DEBUGASSERT(ret >= 0);
+      UNUSED(ret);
+    }
+  else if (!enable && priv->txena)
+    {
+      /* Cancel any pending TX data transmission work */
+
+      work_cancel(LPWORK, &priv->txwork);
+    }
+
+  /* Save the new TX enable state */
+
+  priv->txena = enable;
+}
+
+/****************************************************************************
+ * Name: usbhost_txready
+ *
+ * Description:
+ *   Return true if the transmit data register is not full.
+ *
+ ****************************************************************************/
+
+static bool usbhost_txready(FAR struct uart_dev_s *uartdev)
+{
+  return true;
+}
+
+/****************************************************************************
+ * Name: usbhost_txempty
+ *
+ * Description:
+ *   Return true if the transmit data buffer is empty
+ *
+ ****************************************************************************/
+
+static bool usbhost_txempty(FAR struct uart_dev_s *uartdev)
+{
+  return true;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: usbhost_ft232r_initialize
+ *
+ * Description:
+ *   Initialize the USB host FTDI. This function should be called
+ *   by platform-specific code in order to initialize and register support
+ *   for the FT232.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   On success this function will return zero (OK);  A negated errno value
+ *   will be returned on failure.
+ *
+ ****************************************************************************/
+
+int usbhost_ft232r_initialize(void)
+{
+  /* If we have been configured to use pre-allocated FTDI class instances,
+   * then place all of the pre-allocated USB host FTDI class instances
+   * into a free list.
+   */
+
+#if CONFIG_USBHOST_FT232R_NPREALLOC > 0
+  FAR struct usbhost_freestate_s *entry;
+  int i;
+
+  g_freelist = NULL;
+  for (i = 0; i < CONFIG_USBHOST_FT232R_NPREALLOC; i++)
+    {
+      entry        = (FAR struct usbhost_freestate_s *)&g_prealloc[i];
+      entry->flink = g_freelist;
+      g_freelist   = entry;
+    }
+#endif
+
+  /* Advertise our availability to support (certain) FTDI devices */
+
+  return usbhost_registerclass(&g_ft232r);
+}
+
+#endif /* CONFIG_USBHOST_FT232R */
diff --git a/include/nuttx/usb/usbhost.h b/include/nuttx/usb/usbhost.h
index 7baf5d2..b1f06fd 100644
--- a/include/nuttx/usb/usbhost.h
+++ b/include/nuttx/usb/usbhost.h
@@ -77,12 +77,12 @@
  * Name: CLASS_CREATE
  *
  * Description:
- *   This macro will call the create() method of struct usbhost_registry_s.  The create()
- *   method is a callback into the class implementation.  It is used to (1) create
- *   a new instance of the USB host class state and to (2) bind a USB host driver
- *   "session" to the class instance.  Use of this create() method will support
- *   environments where there may be multiple USB ports and multiple USB devices
- *   simultaneously connected.
+ *   This macro will call the create() method of struct usbhost_registry_s.
+ *   The create() method is a callback into the class implementation.  It is used
+ *   to (1) create a new instance of the USB host class state and to (2) bind a
+ *   USB host driver "session" to the class instance.  Use of this create() method
+ *   will support environments where there may be multiple USB ports and multiple
+ *   USB devices simultaneously connected.
  *
  * Input Parameters:
  *   reg - The USB host class registry entry previously obtained from a call to
@@ -112,14 +112,16 @@
  *
  * Description:
  *   This macro will call the connect() method of struct usbhost_class_s.  This
- *   method is a callback into the devclass implementation.  It is used to provide the
- *   device's configuration descriptor to the devclass so that the devclass may initialize
- *   properly
+ *   method is a callback into the devclass implementation.  It is used to provide
+ *   the device's configuration descriptor to the devclass so that the devclass may
+ *   initialize properly.
  *
  * Input Parameters:
- *   devclass - The USB host class entry previously obtained from a call to create().
- *   configdesc - A pointer to a uint8_t buffer container the configuration descriptor.
- *   desclen - The length in bytes of the configuration descriptor.
+ *   devclass   - The USB host class entry previously obtained from a call
+ *                to create().
+ *   configdesc - A pointer to a uint8_t buffer containing the configuration
+ *                descriptor.
+ *   desclen    - The length in bytes of the configuration descriptor.
  *
  * Returned Value:
  *   On success, zero (OK) is returned. On a failure, a negated errno value is
@@ -163,7 +165,7 @@
 
 #define CLASS_DISCONNECTED(devclass) ((devclass)->disconnected(devclass))
 
-/****************************************************************************
+/************************************************************************************
  * Name: CONN_WAIT
  *
  * Description:
@@ -186,7 +188,7 @@
  *   - Called from a single thread so no mutual exclusion is required.
  *   - Never called from an interrupt handler.
  *
- ****************************************************************************/
+ ************************************************************************************/
 
 #define CONN_WAIT(conn,hport) ((conn)->wait(conn,hport))
 
@@ -644,8 +646,8 @@ struct usbhost_id_s
  * connected to the USB port.
  */
 
-struct usbhost_hubport_s;    /* Forward reference to the hub state structure */
-struct usbhost_class_s;  /* Forward reference to the class state structure */
+struct usbhost_hubport_s;   /* Forward reference to the hub state structure */
+struct usbhost_class_s;     /* Forward reference to the class state structure */
 struct usbhost_registry_s
 {
   /* This field is used to implement a singly-link registry structure.  Because of
@@ -730,9 +732,9 @@ struct usbhost_roothubport_s
 
 struct usbhost_class_s
 {
- /* Class instances are associated with devices connected on one port on a
-  * hub and are represented by this structure.
-  */
+  /* Class instances are associated with devices connected on one port on a
+   * hub and are represented by this structure.
+   */
 
   FAR struct usbhost_hubport_s *hport;  /* The port used by this class instance */
 
@@ -985,7 +987,7 @@ const struct usbhost_registry_s *
   usbhost_findclass(FAR const struct usbhost_id_s *id);
 
 #ifdef CONFIG_USBHOST_HUB
- /****************************************************************************
+ /***********************************************************************************
  * Name: usbhost_hub_initialize
  *
  * Description:
@@ -1000,13 +1002,13 @@ const struct usbhost_registry_s *
  *   On success this function will return zero (OK);  A negated errno value
  *   will be returned on failure.
  *
- ****************************************************************************/
+ ************************************************************************************/
 
 int usbhost_hub_initialize(void);
 #endif
 
 #ifdef CONFIG_USBHOST_MSC
-/****************************************************************************
+/************************************************************************************
  * Name: usbhost_msc_initialize
  *
  * Description:
@@ -1021,13 +1023,13 @@ int usbhost_hub_initialize(void);
  *   On success this function will return zero (OK);  A negated errno value
  *   will be returned on failure.
  *
- ****************************************************************************/
+ ************************************************************************************/
 
 int usbhost_msc_initialize(void);
 #endif
 
 #ifdef CONFIG_USBHOST_CDCACM
-/****************************************************************************
+/************************************************************************************
  * Name: usbhost_cdcacm_initialize
  *
  * Description:
@@ -1042,13 +1044,34 @@ int usbhost_msc_initialize(void);
  *   On success this function will return zero (OK);  A negated errno value
  *   will be returned on failure.
  *
- ****************************************************************************/
+ ************************************************************************************/
 
 int usbhost_cdcacm_initialize(void);
 #endif
 
+#ifdef CONFIG_USBHOST_FT232R
+/************************************************************************************
+ * Name: usbhost_ft232r_initialize
+ *
+ * Description:
+ *   Initialize the USB FT232R driver.  This function should be called
+ *   be platform-specific code in order to initialize and register support
+ *   for the FT232R.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   On success this function will return zero (OK);  A negated errno value
+ *   will be returned on failure.
+ *
+ ************************************************************************************/
+
+int usbhost_ft232r_initialize(void);
+#endif
+
 #ifdef CONFIG_USBHOST_HIDKBD
-/****************************************************************************
+/************************************************************************************
  * Name: usbhost_kbdinit
  *
  * Description:
@@ -1063,13 +1086,13 @@ int usbhost_cdcacm_initialize(void);
  *   On success this function will return zero (OK);  A negated errno value
  *   will be returned on failure.
  *
- ****************************************************************************/
+ ************************************************************************************/
 
 int usbhost_kbdinit(void);
 #endif
 
 #ifdef CONFIG_USBHOST_HIDMOUSE
-/****************************************************************************
+/************************************************************************************
  * Name: usbhost_mouse_init
  *
  * Description:
@@ -1084,13 +1107,13 @@ int usbhost_kbdinit(void);
  *   On success this function will return zero (OK);  A negated errno value
  *   will be returned on failure.
  *
- ****************************************************************************/
+ ************************************************************************************/
 
 int usbhost_mouse_init(void);
 #endif
 
 #ifdef CONFIG_USBHOST_XBOXCONTROLLER
-/****************************************************************************
+/************************************************************************************
  * Name: usbhost_xboxcontroller_init
  *
  * Description:
@@ -1105,12 +1128,12 @@ int usbhost_mouse_init(void);
  *   On success this function will return zero (OK);  A negated errno value
  *   will be returned on failure.
  *
- ****************************************************************************/
+ ************************************************************************************/
 
 int usbhost_xboxcontroller_init(void);
 #endif
 
-/****************************************************************************
+/************************************************************************************
  * Name: usbhost_wlaninit
  *
  * Description:
@@ -1125,11 +1148,11 @@ int usbhost_xboxcontroller_init(void);
  *   On success this function will return zero (OK);  A negated errno value
  *   will be returned on failure.
  *
- ****************************************************************************/
+ ************************************************************************************/
 
 int usbhost_wlaninit(void);
 
-/****************************************************************************
+/************************************************************************************
  * Name: usbhost_enumerate
  *
  * Description:
@@ -1161,7 +1184,7 @@ int usbhost_wlaninit(void);
  *   - Called from a single thread so no mutual exclusion is required.
  *   - Never called from an interrupt handler.
  *
- ****************************************************************************/
+ ************************************************************************************/
 
 int usbhost_enumerate(FAR struct usbhost_hubport_s *hub,
                       FAR struct usbhost_class_s **devclass);


[incubator-nuttx] 02/02: nxstyle fixes

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnutt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 5a9f7927ee43d6561f163796242383483264eb54
Author: Gregory Nutt <gn...@nuttx.org>
AuthorDate: Thu May 28 10:53:16 2020 -0600

    nxstyle fixes
---
 drivers/usbhost/usbhost_ft232r.c | 14 +++------
 include/nuttx/usb/usbhost.h      | 66 ++++++++++++++++------------------------
 2 files changed, 31 insertions(+), 49 deletions(-)

diff --git a/drivers/usbhost/usbhost_ft232r.c b/drivers/usbhost/usbhost_ft232r.c
index d85bfb8..bfabcf8 100644
--- a/drivers/usbhost/usbhost_ft232r.c
+++ b/drivers/usbhost/usbhost_ft232r.c
@@ -828,16 +828,10 @@ static int ft232r_setdivisor(uint32_t *divisor, uint32_t baud)
     }
   else
     {
-      int divfrac[9] = {0,
-                        500,
-                        250,
-                        125,
-                        375,
-                        625,
-                        750,
-                        875,
-                        1000
-                       };
+      int divfrac[9] =
+        {
+          0, 500, 250, 125, 375, 625, 750, 875, 1000
+        };
 
       double frac = (double)USBHOST_FT232R_MAX_BAUD / (double)baud;
 
diff --git a/include/nuttx/usb/usbhost.h b/include/nuttx/usb/usbhost.h
index b1f06fd..f217b59 100644
--- a/include/nuttx/usb/usbhost.h
+++ b/include/nuttx/usb/usbhost.h
@@ -1,44 +1,30 @@
 /************************************************************************************
  * include/nuttx/usb/usbhost.h
  *
- *   Copyright (C) 2010-2015 Gregory Nutt. All rights reserved.
- *   Author: Gregory Nutt <gn...@nuttx.org>
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
  *
- * References:
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ************************************************************************************/
+
+/* References:
  *   "Universal Serial Bus Mass Storage Class, Specification Overview,"
  *   Revision 1.2,  USB Implementer's Forum, June 23, 2003.
  *
  *   "Universal Serial Bus Mass Storage Class, Bulk-Only Transport,"
  *   Revision 1.0, USB Implementer's Forum, September 31, 1999.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- *    used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- ************************************************************************************/
+ */
 
 #ifndef __INCLUDE_NUTTX_USB_USBHOST_H
 #define __INCLUDE_NUTTX_USB_USBHOST_H
@@ -687,6 +673,7 @@ typedef FAR void *usbhost_ep_t;
  * represented by struct usbhost_driver_s.  Connected to the HCD are one
  * or more hubs.  At a minimum, the root hub is always present. Each hub
  * has from 1 to 4 ports.
+ */
 
 /* Every class connects to the host controller driver (HCD) via a port on a
  * hub.  That hub may be an external hub or the internal, root hub.  The
@@ -760,11 +747,12 @@ struct usbhost_class_s
 struct usbhost_epdesc_s
 {
   FAR struct usbhost_hubport_s *hport; /* Hub port that supports the endpoint */
-  uint8_t addr;                  /* Endpoint address */
-  bool in;                       /* Direction: true->IN */
-  uint8_t xfrtype;               /* Transfer type.  See USB_EP_ATTR_XFER_* in usb.h */
-  uint8_t interval;              /* Polling interval */
-  uint16_t mxpacketsize;         /* Max packetsize */
+  uint8_t addr;                        /* Endpoint address */
+  bool in;                             /* Direction: true->IN */
+  uint8_t xfrtype;                     /* Transfer type.  See USB_EP_ATTR_XFER_*
+                                        * in usb.h */
+  uint8_t interval;                    /* Polling interval */
+  uint16_t mxpacketsize;               /* Max packetsize */
 };
 
 /* struct usbhost_connection_s provides as interface between platform-specific
@@ -938,7 +926,7 @@ extern "C"
 #endif
 
 /************************************************************************************
- * Public Functions
+ * Public Function Prototypes
  ************************************************************************************/
 
 /************************************************************************************
@@ -987,7 +975,7 @@ const struct usbhost_registry_s *
   usbhost_findclass(FAR const struct usbhost_id_s *id);
 
 #ifdef CONFIG_USBHOST_HUB
- /***********************************************************************************
+/************************************************************************************
  * Name: usbhost_hub_initialize
  *
  * Description: