diff --git a/drivers/usbhost/Kconfig b/drivers/usbhost/Kconfig index 2997567947b..0c0896791e9 100644 --- a/drivers/usbhost/Kconfig +++ b/drivers/usbhost/Kconfig @@ -30,10 +30,19 @@ config USBHOST_ISOC_DISABLE On some architectures, selecting this setting will reduce driver size by disabling isochronous endpoint support +config USBHOST_ASYNCH + bool "Asynchronous transfer support" + default n + ---help--- + Select if the host controller driver needs to support asynchronous + I/O transfer. This may be required, for example, to receive + infrequent, asynchronous input from an interrupt pipe. + config USBHOST_HUB bool "USB Hub Support" default n depends on EXPERIMENTAL + select USBHOST_ASYNCH ---help--- Select this option to build in support for USB hubs. diff --git a/drivers/usbhost/usbhost_hub.c b/drivers/usbhost/usbhost_hub.c index 033f688071e..4135576264b 100644 --- a/drivers/usbhost/usbhost_hub.c +++ b/drivers/usbhost/usbhost_hub.c @@ -102,6 +102,7 @@ struct usbhost_hubdev_s sem_t exclsem; /* Used to maintain mutual exclusive access */ struct usb_hubtt_s tt; /* Transaction translator */ + struct work_s work; /* Used for deferred callback work */ usbhost_ep_t intin; /* Interrupt IN endpoint */ struct usbhost_class_s *childclass[USBHUB_MAX_PORTS]; @@ -139,7 +140,7 @@ static void usbhost_hubevent(FAR void *arg); static inline uint16_t usbhost_getle16(const uint8_t *val); static void usbhost_putle16(uint8_t *dest, uint16_t val); -static void usbhost_callback(FAR struct usbhost_transfer_s *xfer); +static void usbhost_callback(FAR void *arg, int result); /* struct usbhost_registry_s methods */ @@ -1001,10 +1002,12 @@ static void usbhost_hubevent(FAR void *arg) udbg("WARNING: Hub status changed, not handled\n"); } - xfer->status = -EIO; + /* Get the number hub event */ - ret = DRVR_ASYNCH(hubclass->drvr, &priv->ctrlreq, sizeof(struct usb_ctrlreq_s) - usbhost_callback, hubclass); + ret = DRVR_ASYNCH(hubclass->drvr, priv->intin, + (FAR uint8_t *)priv->ctrlreq, + sizeof(struct usb_ctrlreq_s), usbhost_callback, + hubclass); if (ret != OK) { udbg("ERROR: Failed to queue interrupt endpoint: %d\n", ret); @@ -1066,7 +1069,7 @@ static void usbhost_putle16(uint8_t *dest, uint16_t val) * ****************************************************************************/ -static void usbhost_callback(FAR void *arg) +static void usbhost_callback(FAR void *arg, int result) { FAR struct usbhost_class_s *hubclass; FAR struct usbhost_hubdev_s *priv; @@ -1077,12 +1080,13 @@ static void usbhost_callback(FAR void *arg) DEBUGASSERT(hubclass != NULL && hubclass->priv != NULL); priv = (FAR struct usbhost_hubdev_s *)hubclass->priv; - if (xfer->status != OK) + if (result != OK) { priv->buffer[0] = 0; } - (void)work_queue(HPWORK, &xfer->work, (worker_t)usbhost_hubevent, hubclass, 0); + (void)work_queue(HPWORK, &priv->work, (worker_t)usbhost_hubevent, + hubclass, 0); } /**************************************************************************** @@ -1256,7 +1260,8 @@ static int usbhost_connect(FAR struct usbhost_class_s *hubclass, /* INT request to periodically check port status */ - ret = DRVR_ASYNCH(hubclass->drvr, &priv->ctrlreq, + ret = DRVR_ASYNCH(hubclass->drvr, priv->intin, + (FAR uint8_t *)&priv->ctrlreq, sizeof(struct usb_ctrlreq_s), usbhost_callback, hubclass); } diff --git a/include/nuttx/usb/usbhost.h b/include/nuttx/usb/usbhost.h index f067a9e5718..63e43663a12 100644 --- a/include/nuttx/usb/usbhost.h +++ b/include/nuttx/usb/usbhost.h @@ -686,7 +686,7 @@ struct usbhost_connection_s /* Callback type used with asynchronous transfers */ -typedef void (*usbhost_asynch_t)(FAR void *arg); +typedef CODE void (*usbhost_asynch_t)(FAR void *arg, int result); /* struct usbhost_driver_s provides access to the USB host driver from the * USB host class implementation.