From bc2daa48cce2b14af6f86a5bfbc8decb30daa8b4 Mon Sep 17 00:00:00 2001 From: yangsong8 Date: Tue, 14 Oct 2025 22:49:56 +0800 Subject: [PATCH] arch/sim: Optimize sim usbhost isoc endpoint transmission The USB driver framework only implements a single ISOC transfer. If multiple transfers are needed, the class driver can initiate multiple urbs to meet the real-time requirements of the ISOC endpoint. The class driver's urb record the buf address, length, and number of packets sent. The callback function calculates the data location in the buf based on the callback number and length returned. Signed-off-by: yangsong8 --- arch/sim/src/sim/posix/sim_libusb.c | 31 ++++++++++++++++++----------- arch/sim/src/sim/sim_usbhost.c | 8 +++++--- arch/sim/src/sim/sim_usbhost.h | 1 + include/nuttx/usb/usb.h | 8 ++++++++ 4 files changed, 33 insertions(+), 15 deletions(-) diff --git a/arch/sim/src/sim/posix/sim_libusb.c b/arch/sim/src/sim/posix/sim_libusb.c index bf745c499c0..d99021248c1 100644 --- a/arch/sim/src/sim/posix/sim_libusb.c +++ b/arch/sim/src/sim/posix/sim_libusb.c @@ -286,8 +286,11 @@ static void host_libusb_inttransfer_cb(struct libusb_transfer *transfer) #ifndef CONFIG_USBHOST_ISOC_DISABLE static void host_libusb_isotransfer_cb(struct libusb_transfer *transfer) { - struct host_libusb_hostdev_s *dev = &g_libusb_dev; + struct libusb_iso_packet_descriptor *packet; struct host_usb_datareq_s *datareq; + usbhost_asynch_t callback; + size_t length; + int i; if (!transfer) { @@ -298,18 +301,24 @@ static void host_libusb_isotransfer_cb(struct libusb_transfer *transfer) } datareq = (struct host_usb_datareq_s *)transfer->user_data; + callback = datareq->callback; - if (transfer->status == LIBUSB_TRANSFER_COMPLETED) + for (i = 0; i < transfer->num_iso_packets; i++) { - datareq->success = true; - datareq->xfer += transfer->actual_length; - } - else - { - datareq->success = false; + packet = &transfer->iso_packet_desc[i]; + length = packet->status == LIBUSB_TRANSFER_COMPLETED ? + packet->actual_length : 0; + + /* If there are multiple isoc packages, only the actual length + * of the data in each package is returned here. Because each + * package has the same size, the number of packages returned + * needs to be recorded in class driver. + */ + + callback(datareq->priv, length); } - host_libusb_fifopush(&dev->completed, datareq); + free(datareq); host_uninterruptible_no_return(libusb_free_transfer, transfer); } #endif @@ -486,9 +495,7 @@ host_libusb_isotransfer(struct host_libusb_hostdev_s *dev, uint8_t addr, int num_iso_pack; int ret; - max_packet_size = host_uninterruptible(libusb_get_max_iso_packet_size, - dev->priv, - addr); + max_packet_size = datareq->maxpacketsize; num_iso_pack = (datareq->len + max_packet_size - 1) / max_packet_size; transfer = host_uninterruptible(libusb_alloc_transfer, num_iso_pack); if (!transfer) diff --git a/arch/sim/src/sim/sim_usbhost.c b/arch/sim/src/sim/sim_usbhost.c index 65931cd7632..8c559fcd03e 100644 --- a/arch/sim/src/sim/sim_usbhost.c +++ b/arch/sim/src/sim/sim_usbhost.c @@ -77,9 +77,9 @@ struct sim_epinfo_s uint8_t toggle:1; /* Next data toggle */ uint8_t interval; /* Polling interval */ uint8_t status; /* Retained token status bits (for debug purposes) */ - uint16_t maxpacket:11; /* Maximum packet size */ + uint16_t maxpacket:14; /* Maximum packet size */ uint16_t xfrtype:2; /* See USB_EP_ATTR_XFER_* definitions in usb.h */ - uint16_t speed:2; /* See USB_*_SPEED definitions */ + uint8_t speed; /* See USB_*_SPEED definitions */ int result; /* The result of the transfer */ ssize_t xfrd; /* On completion, will hold the number of bytes transferred */ sem_t iocsem; /* Semaphore used to wait for transfer completion */ @@ -406,7 +406,8 @@ static int sim_usbhost_epalloc(struct usbhost_driver_s *drvr, epinfo->dirin = epdesc->in; epinfo->devaddr = hport->funcaddr; epinfo->interval = epdesc->interval; - epinfo->maxpacket = epdesc->mxpacketsize; + epinfo->maxpacket = (epdesc->mxpacketsize & USB_EP_MAXP_MASK) * + (USB_EP_MAX_PACKET_MULT(epdesc->mxpacketsize) + 1); epinfo->xfrtype = epdesc->xfrtype; epinfo->speed = hport->speed; nxsem_init(&epinfo->iocsem, 0, 0); @@ -610,6 +611,7 @@ static int sim_usbhost_asynch(struct usbhost_driver_s *drvr, datareq->addr = (epinfo->dirin << 7) + epinfo->epno; datareq->len = buflen; datareq->xfrtype = epinfo->xfrtype; + datareq->maxpacketsize = epinfo->maxpacket; datareq->callback = callback; datareq->data = buffer; datareq->priv = arg; diff --git a/arch/sim/src/sim/sim_usbhost.h b/arch/sim/src/sim/sim_usbhost.h index 9db8c583954..b559a6debe0 100644 --- a/arch/sim/src/sim/sim_usbhost.h +++ b/arch/sim/src/sim/sim_usbhost.h @@ -78,6 +78,7 @@ struct host_usb_datareq_s struct host_usb_datareq_s *flink; uint8_t addr; uint8_t xfrtype; + uint16_t maxpacketsize; uint8_t *data; uint16_t len; uint16_t xfer; diff --git a/include/nuttx/usb/usb.h b/include/nuttx/usb/usb.h index d9bffad3ce6..9bc96ca2314 100644 --- a/include/nuttx/usb/usb.h +++ b/include/nuttx/usb/usb.h @@ -256,6 +256,14 @@ # define USB_EP_ATTR_USAGE_IMPLICIT (2 << USB_EP_ATTR_USAGE_SHIFT) #define USB_EP_ATTR_MAX_ADJUSTABLE (1 << 7) +/* Endpoint descriptor max packet size */ + +#define USB_EP_MAX_PACKET_MASK (0x07ff) +#define USB_EP_MAX_PACKET_MULT_SHIFT (11) +#define USB_EP_MAX_PACKET_MULT_MASK (3 << USB_EP_MAX_PACKET_MULT_SHIFT) +#define USB_EP_MAX_PACKET_MULT(m) (((m) & USB_EP_MAX_PACKET_MULT_MASK) >> \ + USB_EP_MAX_PACKET_MULT_SHIFT) + /* OTG Definitions */ /* OTG SET FEATURE Constants */