summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPete Batard <pbatard@gmail.com>2010-03-15 13:54:09 +0000
committerPete Batard <pbatard@gmail.com>2010-03-15 13:54:09 +0000
commitf06e130f77f08b60642ff7ca085126375a7a7ea2 (patch)
treeec9512a64db7b9d2bd86be9b2f05770c32145387
parent78710622a4ccf385950965edc6973c44cb570667 (diff)
downloadlibusb-f06e130f77f08b60642ff7ca085126375a7a7ea2.tar.gz
added partial CancelIoEx emulation for XP and earlierr207
also added warning when CancelIo tries to cancel I/O started from another thread
-rw-r--r--libusb/os/poll_windows.c33
-rw-r--r--libusb/os/windows_usb.c17
2 files changed, 40 insertions, 10 deletions
diff --git a/libusb/os/poll_windows.c b/libusb/os/poll_windows.c
index 0fa2dce..0d8d487 100644
--- a/libusb/os/poll_windows.c
+++ b/libusb/os/poll_windows.c
@@ -123,7 +123,9 @@ struct winfd poll_fd[MAX_FDS];
struct {
CRITICAL_SECTION mutex; // lock for fds
BYTE marker; // 1st byte of a usbi_read operation gets stored here
-
+ // Additional variables for XP CancelIoEx partial emulation
+ HANDLE original_handle;
+ DWORD thread_id;
} _poll_fd[MAX_FDS];
// globals
@@ -146,11 +148,19 @@ __inline BOOL cancel_io(int index)
if ((index < 0) || (index >= MAX_FDS)) {
return FALSE;
}
+
+ if ( (poll_fd[index].fd < 0) || (poll_fd[index].handle == INVALID_HANDLE_VALUE)
+ || (poll_fd[index].handle == 0) || (poll_fd[index].overlapped == NULL) ) {
+ return TRUE;
+ }
if (pCancelIoEx != NULL) {
return (*pCancelIoEx)(poll_fd[index].handle, poll_fd[index].overlapped);
- } else {
+ }
+ if (_poll_fd[index].thread_id == GetCurrentThreadId()) {
return CancelIo(poll_fd[index].handle);
}
+ usbi_warn(NULL, "Unable to cancel I/O that was started from another thread");
+ return FALSE;
}
// Init
@@ -169,6 +179,8 @@ void init_polling(void)
for (i=0; i<MAX_FDS; i++) {
poll_fd[i] = INVALID_WINFD;
_poll_fd[i].marker = 0;
+ _poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
+ _poll_fd[i].thread_id = 0;
InitializeCriticalSection(&_poll_fd[i].mutex);
}
#if defined(DYNAMIC_FDS)
@@ -470,7 +482,19 @@ struct winfd usbi_create_fd(HANDLE handle, int access_mode)
continue;
}
wfd.fd = fd;
- wfd.handle = handle;
+ // Attempt to emulate some of the CancelIoEx behaviour on platforms
+ // that don't have it
+ if (pCancelIoEx == NULL) {
+ _poll_fd[i].thread_id = GetCurrentThreadId();
+ _poll_fd[i].original_handle = handle;
+ if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(),
+ &wfd.handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
+ usbi_warn(NULL, "could not duplicate handle for CancelIo - using orignal one");
+ wfd.handle = handle;
+ }
+ } else {
+ wfd.handle = handle;
+ }
wfd.overlapped = overlapped;
memcpy(&poll_fd[i], &wfd, sizeof(struct winfd));
LeaveCriticalSection(&_poll_fd[i].mutex);
@@ -499,6 +523,9 @@ void _free_index(int index)
_close(poll_fd[index].fd);
}
free_overlapped(poll_fd[index].overlapped);
+ CloseHandle(_poll_fd[index].original_handle);
+ _poll_fd[index].original_handle = INVALID_HANDLE_VALUE;
+ _poll_fd[index].thread_id = 0;
poll_fd[index] = INVALID_WINFD;
}
diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c
index 53a6a96..8bd1344 100644
--- a/libusb/os/windows_usb.c
+++ b/libusb/os/windows_usb.c
@@ -2555,6 +2555,7 @@ static int winusb_submit_control_transfer(struct usbi_transfer *itransfer)
winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
wfd = usbi_create_fd(winusb_handle, _O_RDONLY);
+ // Always use the handle returned from usbi_create_fd (wfd.handle)
if (wfd.fd < 0) {
return LIBUSB_ERROR_NO_MEM;
}
@@ -2631,16 +2632,17 @@ static int winusb_submit_bulk_transfer(struct usbi_transfer *itransfer)
direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN;
wfd = usbi_create_fd(winusb_handle, direction_in?_O_RDONLY:_O_WRONLY);
+ // Always use the handle returned from usbi_create_fd (wfd.handle)
if (wfd.fd < 0) {
return LIBUSB_ERROR_NO_MEM;
}
if (direction_in) {
usbi_dbg("reading %d bytes", transfer->length);
- ret = WinUsb_ReadPipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped);
+ ret = WinUsb_ReadPipe(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped);
} else {
usbi_dbg("writing %d bytes", transfer->length);
- ret = WinUsb_WritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped);
+ ret = WinUsb_WritePipe(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped);
}
if (!ret) {
if(GetLastError() != ERROR_IO_PENDING) {
@@ -3593,7 +3595,7 @@ static int hid_submit_control_transfer(struct usbi_transfer *itransfer)
usbi_dbg("will use interface %d", current_interface);
hid_handle = handle_priv->interface_handle[current_interface].api_handle;
-
+ // Always use the handle returned from usbi_create_fd (wfd.handle)
wfd = usbi_create_fd(hid_handle, _O_RDONLY);
if (wfd.fd < 0) {
return LIBUSB_ERROR_NO_MEM;
@@ -3603,7 +3605,7 @@ static int hid_submit_control_transfer(struct usbi_transfer *itransfer)
case LIBUSB_REQUEST_TYPE_STANDARD:
switch(setup->request) {
case LIBUSB_REQUEST_GET_DESCRIPTOR:
- r = _hid_get_descriptor(priv->hid, hid_handle, LIBUSB_REQ_RECIPIENT(setup->request_type),
+ r = _hid_get_descriptor(priv->hid, wfd.handle, LIBUSB_REQ_RECIPIENT(setup->request_type),
(setup->value >> 8) & 0xFF, setup->value & 0xFF, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, &size);
break;
case LIBUSB_REQUEST_GET_CONFIGURATION:
@@ -3638,7 +3640,7 @@ static int hid_submit_control_transfer(struct usbi_transfer *itransfer)
}
break;
case LIBUSB_REQUEST_TYPE_CLASS:
- r =_hid_class_request(priv->hid, hid_handle, setup->request_type, setup->request, setup->value,
+ r =_hid_class_request(priv->hid, wfd.handle, setup->request_type, setup->request, setup->value,
setup->index, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, transfer_priv,
&size, wfd.overlapped);
break;
@@ -3697,6 +3699,7 @@ static int hid_submit_bulk_transfer(struct usbi_transfer *itransfer) {
direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN;
wfd = usbi_create_fd(hid_handle, direction_in?_O_RDONLY:_O_WRONLY);
+ // Always use the handle returned from usbi_create_fd (wfd.handle)
if (wfd.fd < 0) {
return LIBUSB_ERROR_NO_MEM;
}
@@ -3709,13 +3712,13 @@ static int hid_submit_bulk_transfer(struct usbi_transfer *itransfer) {
if (direction_in) {
transfer_priv->hid_buffer[0] = priv->hid->input_report_id;
usbi_dbg("reading %d bytes (report ID: 0x%02X)", transfer->length+1, transfer_priv->hid_buffer[0]);
- ret = ReadFile(hid_handle, transfer_priv->hid_buffer, transfer->length+1, &size, wfd.overlapped);
+ ret = ReadFile(wfd.handle, transfer_priv->hid_buffer, transfer->length+1, &size, wfd.overlapped);
} else {
transfer_priv->hid_buffer[0] = priv->hid->output_report_id;
memcpy(transfer_priv->hid_buffer+1, transfer->buffer, transfer->length);
usbi_dbg("writing %d bytes (report ID: 0x%02X)", transfer->length+1, transfer_priv->hid_buffer[0]);
transfer_priv->hid_buffer[0] = 0;
- ret = WriteFile(hid_handle, transfer_priv->hid_buffer, transfer->length+1, &size, wfd.overlapped);
+ ret = WriteFile(wfd.handle, transfer_priv->hid_buffer, transfer->length+1, &size, wfd.overlapped);
}
if (!ret) {
if (GetLastError() != ERROR_IO_PENDING) {