ldube commented on code in PR #11552:
URL: https://github.com/apache/nuttx/pull/11552#discussion_r1454683254


##########
drivers/usbhost/usbhost_bthci.c:
##########
@@ -0,0 +1,1536 @@
+/****************************************************************************
+ * drivers/usbhost/usbhost_bthci.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 <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/irq.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/kthread.h>
+#include <nuttx/nuttx.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/signal.h>
+#include <nuttx/wqueue.h>
+
+#include <nuttx/net/bluetooth.h>
+#include <nuttx/usb/usb.h>
+#include <nuttx/usb/usbhost.h>
+#include <nuttx/wireless/bluetooth/bt_core.h>
+#include <nuttx/wireless/bluetooth/bt_hci.h>
+#include <nuttx/wireless/bluetooth/bt_driver.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+#ifndef CONFIG_SCHED_WORKQUEUE
+#  warning "Worker thread support is required (CONFIG_SCHED_WORKQUEUE)"
+#endif
+
+/* Driver support ***********************************************************/
+
+/* This format is used to construct the /dev/bthci[n] device driver path.  It
+ * defined here so that it will be used consistently in all places.
+ */
+
+#define DEV_FORMAT          "/dev/bthci%c"
+#define DEV_NAMELEN         12
+
+/* Used in usbhci_cfgdesc() */
+
+#define USBHOST_IFFOUND     0x01
+#define USBHOST_BINFOUND    0x02
+#define USBHOST_BOUTFOUND   0x04
+#define USBHOST_IINFOUND    0x08
+#define USBHOST_ALLFOUND    0x0F
+
+#define USBHOST_MAX_CREFS   0x7fff
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure contains the internal, private state of the USB host class
+ * driver.
+ */
+
+struct usbhost_state_s
+{
+  /* This is the externally visible portion of the state */
+
+  struct usbhost_class_s  usbclass;
+  struct bt_driver_s      btdev;
+
+  /* The remainder of the fields are provide to the class driver */
+
+  char                    devchar;      /* Character identifying the 
/dev/bthci[n] device */
+  volatile bool           disconnected; /* TRUE: Device has been disconnected 
*/
+  uint8_t                 ifno;         /* Interface number */
+  sem_t                   exclsem;      /* Used to maintain mutual exclusive 
access */
+  struct work_s           work;         /* For interacting with the worker 
thread */
+  FAR uint8_t            *tbuffer;      /* The allocated transfer buffer */
+  size_t                  tbuflen;      /* Size of the allocated transfer 
buffer */
+  usbhost_ep_t            bulkin;       /* Bulk IN endpoint */
+  usbhost_ep_t            bulkout;      /* Bulk OUT endpoint */
+  usbhost_ep_t            intin;        /* Interrupt endpoint */
+  FAR uint8_t            *ctrlreq;      /* Allocated ctrl request structure */
+  FAR uint8_t            *evbuffer;     /* Allocated event buffer */
+  size_t                  evbuflen;     /* Size of the allocated event buffer 
*/
+  struct work_s           acwork;       /* For asynchronous event work */
+  struct work_s           evwork;       /* For asynchronous event work */
+  int16_t                 acbytes;      /* The number of bytes actually 
transferred */
+  int16_t                 evbytes;      /* The number of bytes actually 
transferred */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Memory allocation services */
+
+static inline FAR struct usbhost_state_s *usbhost_allocclass(void);
+static inline void usbhost_freeclass(FAR struct usbhost_state_s *usbclass);
+
+/* Device name management */
+
+static int usbhost_allocdevno(FAR struct usbhost_state_s *priv);
+static void usbhost_freedevno(FAR struct usbhost_state_s *priv);
+static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv,
+                                     FAR char *devname);
+
+/* Worker thread actions */
+
+static void usbhost_destroy(FAR void *arg);
+
+/* Helpers for usbhci_connect() */
+
+static inline int usbhci_cfgdesc(FAR struct usbhost_state_s *priv,
+                                  FAR const uint8_t *configdesc,
+                                  int desclen);
+static inline int usbhost_devinit(FAR struct usbhost_state_s *priv);
+
+/* (Little Endian) Data helpers */
+
+static inline uint16_t usbhost_getle16(const uint8_t *val);
+static inline void usbhost_putle16(uint8_t *dest, uint16_t val);
+
+/* Transfer descriptor memory management */
+
+static inline int usbhost_talloc(FAR struct usbhost_state_s *priv);
+static inline int usbhost_tfree(FAR struct usbhost_state_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 usbhci_connect(FAR struct usbhost_class_s *usbclass,
+                           FAR const uint8_t *configdesc, int desclen);
+static int usbhost_disconnected(FAR struct usbhost_class_s *usbclass);
+
+/* Driver methods --
+ * depend upon the type of NuttX driver interface exported
+ */
+
+static int usbhost_ctrl_cmd(FAR struct usbhost_state_s *priv,
+                            uint8_t type, uint8_t req, uint16_t value,
+                            uint16_t iface, uint8_t *payload, uint16_t len);
+static void usbhost_event_work(FAR void *arg);
+static void usbhost_event_callback(FAR void *arg, ssize_t nbytes);
+static void usbhost_acl_callback(FAR void *arg, ssize_t nbytes);
+
+static ssize_t usbhost_cmd_tx(FAR struct usbhost_state_s *priv,
+                      FAR const void *buffer, size_t buflen);
+static ssize_t usbhost_acl_tx(FAR struct usbhost_state_s *priv,
+                      FAR const void *buffer, size_t buflen);
+
+static int usbhost_bthci_send(FAR struct bt_driver_s *dev,
+                enum bt_buf_type_e type,
+                FAR void *data, size_t len);
+static int usbhost_bthci_open(FAR struct bt_driver_s *dev);
+static void usbhost_bthci_close(FAR struct bt_driver_s *dev);
+static int usbhost_bthci_ioctl(FAR struct bt_driver_s *dev,
+                 int cmd, unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* This structure provides the registry entry ID information that will  be
+ * used to associate the USB class driver to a connected USB device.
+ */
+
+static struct usbhost_id_s g_id[] =
+{
+  {
+    USB_CLASS_WIRELESS_CONTROLLER,  /* base     */
+    0x01,                           /* subclass */
+    0x01,                           /* proto    */
+    0,                              /* vid      */
+    0                               /* pid      */
+  },
+};
+
+/* This is the USB host bthci class's registry entry */
+
+static struct usbhost_registry_s g_bthci =
+{
+  NULL,                   /* flink    */
+  usbhost_create,         /* create   */
+  1,                      /* nids     */
+  &g_id[0]                /* id[]     */
+};
+
+/* This is a bitmap that is used to allocate device names /dev/bthcia-z. */
+
+static uint32_t g_devinuse;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * 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.
+ *
+ ****************************************************************************/
+
+static inline FAR struct usbhost_state_s *usbhost_allocclass(void)
+{
+  FAR struct usbhost_state_s *priv;
+
+  DEBUGASSERT(!up_interrupt_context());
+
+  priv = (FAR struct usbhost_state_s *)
+    kmm_malloc(sizeof(struct usbhost_state_s));
+
+  uinfo("Allocated: %p\n", priv);
+  return priv;
+}
+
+/****************************************************************************
+ * 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
+ *
+ ****************************************************************************/
+
+static inline void usbhost_freeclass(FAR struct usbhost_state_s *usbclass)
+{
+  DEBUGASSERT(usbclass != NULL);
+
+  /* Free the class instance (perhaps calling sched_kmm_free() in case we are
+   * executing from an interrupt handler.
+   */
+
+  uinfo("Freeing: %p\n", usbclass);
+  kmm_free(usbclass);
+}
+
+/****************************************************************************
+ * Name: Device name management
+ *
+ * Description:
+ *   Some tiny functions to coordinate management of device names.
+ *
+ ****************************************************************************/
+
+static int usbhost_allocdevno(FAR struct usbhost_state_s *priv)
+{
+  irqstate_t flags;
+  int devno;
+
+  flags = enter_critical_section();
+  for (devno = 0; devno < 26; devno++)
+    {
+      uint32_t bitno = 1 << devno;
+      if ((g_devinuse & bitno) == 0)
+        {
+          g_devinuse |= bitno;
+          priv->devchar = 'a' + devno;
+          leave_critical_section(flags);
+          return OK;
+        }
+    }
+
+  leave_critical_section(flags);
+  return -EMFILE;
+}
+
+static void usbhost_freedevno(FAR struct usbhost_state_s *priv)
+{
+  if (priv->devchar >= 'a')
+    {
+      int devno = priv->devchar - 'a';
+
+      if (devno >= 0 && devno < 26)
+        {
+          irqstate_t flags = enter_critical_section();
+          g_devinuse &= ~(1 << devno);
+          leave_critical_section(flags);
+        }
+    }
+}
+
+static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv,
+                                     FAR char *devname)
+{
+  snprintf(devname, DEV_NAMELEN, DEV_FORMAT, priv->devchar);
+}
+
+/****************************************************************************
+ * Name: usbhost_destroy
+ *
+ * Description:
+ *   The USB 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_state_s *priv = (FAR struct usbhost_state_s *)arg;
+  FAR struct usbhost_hubport_s *hport;
+  FAR struct usbhost_driver_s *drvr;
+
+  DEBUGASSERT(priv != NULL && priv->usbclass.hport != NULL);
+  hport = priv->usbclass.hport;
+
+  DEBUGASSERT(hport->drvr);
+  drvr = hport->drvr;
+
+  /* Release the device name used by this connection */
+
+  usbhost_freedevno(priv);
+
+  /* Free the endpoints */
+
+  if (priv->bulkin)
+    {
+      DRVR_EPFREE(hport->drvr, priv->bulkin);
+    }
+
+  if (priv->bulkout)
+    {
+      DRVR_EPFREE(hport->drvr, priv->bulkout);
+    }
+
+  /* Cancel any pending asynchronous I/O */
+
+  if (priv->intin)
+    {
+      DRVR_EPFREE(hport->drvr, priv->intin);
+    }
+
+  /* Free any transfer buffers */
+
+  usbhost_tfree(priv);
+
+  /* Free the function address assigned to this device */
+
+  usbhost_devaddr_destroy(hport, hport->funcaddr);
+  hport->funcaddr = 0;
+
+  /* Destroy the semaphores */
+
+  nxsem_destroy(&priv->exclsem);
+
+  /* Disconnect the USB host device */
+
+  DRVR_DISCONNECT(drvr, hport);
+
+  /* Free the function address assigned to this device */
+
+  usbhost_devaddr_destroy(hport, hport->funcaddr);

Review Comment:
   Ok



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to