mirror of
https://github.com/apache/nuttx.git
synced 2026-05-16 05:27:45 +08:00
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 <yangsong8@xiaomi.com>
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user