summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Stewart <patrick@rfcreations.com>2017-06-09 20:54:45 +0100
committerNathan Hjelm <hjelmn@google.com>2021-06-07 21:08:40 -0600
commit0ce010cdb12e45f4bf81ac82755bad3b4ab050b6 (patch)
tree7a828dd7fdbbc240c699c3fdc3b0de9b73262c10
parent0ed74d76c2651b99e9d0a1f79bee6af7d151d52f (diff)
downloadlibusb-0ce010cdb12e45f4bf81ac82755bad3b4ab050b6.tar.gz
Windows: Support LIBUSB_TRANSFER_ADD_ZERO_PACKET on winusb
Closes #312 Signed-off-by: Nathan Hjelm <hjelmn@google.com>
-rw-r--r--libusb/os/windows_common.h7
-rw-r--r--libusb/os/windows_winusb.c23
-rw-r--r--libusb/version_nano.h2
3 files changed, 29 insertions, 3 deletions
diff --git a/libusb/os/windows_common.h b/libusb/os/windows_common.h
index c84f1f9..2de2b60 100644
--- a/libusb/os/windows_common.h
+++ b/libusb/os/windows_common.h
@@ -265,12 +265,19 @@ struct usbdk_device_handle_priv {
// Not currently used
char dummy;
};
+
+enum WINUSB_ZLP {
+ WINUSB_ZLP_UNSET = 0,
+ WINUSB_ZLP_OFF = 1,
+ WINUSB_ZLP_ON = 2
+};
struct winusb_device_handle_priv {
int active_interface;
struct {
HANDLE dev_handle; // WinUSB needs an extra handle for the file
HANDLE api_handle; // used by the API to communicate with the device
+ uint8_t zlp[USB_MAXENDPOINTS]; // Current per-endpoint SHORT_PACKET_TERMINATE status (enum WINUSB_ZLP)
} interface_handle[USB_MAXINTERFACES];
int autoclaim_count[USB_MAXINTERFACES]; // For auto-release
};
diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c
index e4d194a..877a2ab 100644
--- a/libusb/os/windows_winusb.c
+++ b/libusb/os/windows_winusb.c
@@ -2024,8 +2024,6 @@ static int winusb_submit_transfer(struct usbi_transfer *itransfer)
break;
case LIBUSB_TRANSFER_TYPE_BULK:
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
- if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET))
- return LIBUSB_ERROR_NOT_SUPPORTED;
transfer_fn = priv->apib->submit_bulk_transfer;
break;
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
@@ -2474,6 +2472,7 @@ static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle
continue; // Other policies don't apply to control endpoint or libusb0
policy = false;
+ handle_priv->interface_handle[iface].zlp[endpoint_address] = WINUSB_ZLP_UNSET;
if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
SHORT_PACKET_TERMINATE, sizeof(UCHAR), &policy))
usbi_dbg("failed to disable SHORT_PACKET_TERMINATE for endpoint %02X", endpoint_address);
@@ -3041,6 +3040,23 @@ static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itran
usbi_dbg("reading %d bytes", transfer->length);
ret = WinUSBX[sub_api].ReadPipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, overlapped);
} else {
+ // Set SHORT_PACKET_TERMINATE if ZLP requested.
+ // Changing this can be a problem with packets in flight, so only allow on the first transfer.
+ UCHAR policy = (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) != 0;
+ uint8_t* current_zlp = &handle_priv->interface_handle[current_interface].zlp[transfer->endpoint];
+ if (*current_zlp == WINUSB_ZLP_UNSET) {
+ if (policy &&
+ !WinUSBX[sub_api].SetPipePolicy(winusb_handle, transfer->endpoint,
+ SHORT_PACKET_TERMINATE, sizeof(UCHAR), &policy)) {
+ usbi_err(TRANSFER_CTX(transfer), "failed to set SHORT_PACKET_TERMINATE for endpoint %02X", transfer->endpoint);
+ return LIBUSB_ERROR_NOT_SUPPORTED;
+ }
+ *current_zlp = policy ? WINUSB_ZLP_ON : WINUSB_ZLP_OFF;
+ } else if (policy != (*current_zlp == WINUSB_ZLP_ON)) {
+ usbi_err(TRANSFER_CTX(transfer), "cannot change ZERO_PACKET for endpoint %02X on Windows", transfer->endpoint);
+ return LIBUSB_ERROR_NOT_SUPPORTED;
+ }
+
usbi_dbg("writing %d bytes", transfer->length);
ret = WinUSBX[sub_api].WritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, overlapped);
}
@@ -4006,6 +4022,9 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer
UNUSED(sub_api);
CHECK_HID_AVAILABLE;
+ if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET))
+ return LIBUSB_ERROR_NOT_SUPPORTED;
+
transfer_priv->hid_dest = NULL;
safe_free(transfer_priv->hid_buffer);
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index f8f80a3..53d05fe 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11620
+#define LIBUSB_NANO 11621