mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-11-07 04:36:52 -10:00
libusb: implement zlp flag in libusb transfer
The USB protocol defines a Zero-Length Packet (ZLP) to signal the end of a transfer when the data size is an exact multiple of the Maximum Packet Size (MPS). Without a ZLP in such cases, the device may not be able to determine that the transfer has completed. This flag is added to libusb to allow the user send a ZLP in the end of libusb_xfer. Reviewed by: adrian Sponsored by: The FreeBSD Foundataion Differential Revision: https://reviews.freebsd.org/D51759
This commit is contained in:
1 parent
964823a18e
commit
d84b639a68
2 files changed
+29
-1
No files matched your search
@@ -264,6 +264,7 @@ enum libusb_transfer_flags {
|
||||
LIBUSB_TRANSFER_SHORT_NOT_OK = 1 << 0,
|
||||
LIBUSB_TRANSFER_FREE_BUFFER = 1 << 1,
|
||||
LIBUSB_TRANSFER_FREE_TRANSFER = 1 << 2,
|
||||
LIBUSB_TRANSFER_ADD_ZERO_PACKET = 1 << 3,
|
||||
};
|
||||
|
||||
enum libusb_log_level {
|
||||
|
||||
+28
-1
@@ -1419,6 +1419,7 @@ libusb10_bulk_intr_proxy(struct libusb20_transfer *pxfer)
|
||||
uint32_t actlen;
|
||||
uint8_t status;
|
||||
uint8_t flags;
|
||||
uint8_t tr_flags;
|
||||
|
||||
status = libusb20_tr_get_status(pxfer);
|
||||
sxfer = libusb20_tr_get_priv_sc1(pxfer);
|
||||
@@ -1471,6 +1472,20 @@ libusb10_bulk_intr_proxy(struct libusb20_transfer *pxfer)
|
||||
sxfer->curr_data += max_bulk;
|
||||
sxfer->rem_len -= max_bulk;
|
||||
|
||||
/*
|
||||
* When a zero length packet (ZLP) is requested, ask the
|
||||
* kernel to terminate the last frame of the transfer with
|
||||
* a short packet. This appends a ZLP when the data length
|
||||
* is an exact multiple of the maximum packet size.
|
||||
*/
|
||||
tr_flags = libusb20_tr_get_flags(pxfer);
|
||||
if (sxfer->rem_len == 0 &&
|
||||
(flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET))
|
||||
tr_flags |= LIBUSB20_TRANSFER_FORCE_SHORT;
|
||||
else
|
||||
tr_flags &= ~LIBUSB20_TRANSFER_FORCE_SHORT;
|
||||
libusb20_tr_set_flags(pxfer, tr_flags);
|
||||
|
||||
libusb20_tr_submit(pxfer);
|
||||
|
||||
/* check if we can fork another USB transfer */
|
||||
@@ -1710,7 +1725,7 @@ libusb_submit_transfer(struct libusb_transfer *uxfer)
|
||||
struct libusb_super_transfer *sxfer;
|
||||
struct libusb_device *dev;
|
||||
uint8_t endpoint;
|
||||
int err;
|
||||
int err, mps;
|
||||
|
||||
if (uxfer == NULL)
|
||||
return (LIBUSB_ERROR_INVALID_PARAM);
|
||||
@@ -1731,6 +1746,18 @@ libusb_submit_transfer(struct libusb_transfer *uxfer)
|
||||
|
||||
pxfer0 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 0);
|
||||
pxfer1 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 1);
|
||||
mps = libusb_get_max_packet_size(dev, endpoint);
|
||||
|
||||
/*
|
||||
* The ADD_ZERO_PACKET flag only has an effect on host-to-device
|
||||
* (OUT) transfers whose length is an exact multiple of the maximum
|
||||
* packet size. Clear it otherwise so the kernel is not asked to
|
||||
* terminate the transfer with a short packet, see
|
||||
* libusb10_bulk_intr_proxy().
|
||||
*/
|
||||
if ((uxfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) &&
|
||||
((endpoint & LIBUSB_ENDPOINT_IN) || uxfer->length % mps != 0))
|
||||
uxfer->flags &= ~LIBUSB_TRANSFER_ADD_ZERO_PACKET;
|
||||
|
||||
if (pxfer0 == NULL || pxfer1 == NULL) {
|
||||
err = LIBUSB_ERROR_OTHER;
|
||||
|
||||
Reference in new issue
Block a user