diff options
-rw-r--r-- | examples/xusb.c | 32 | ||||
-rw-r--r-- | libusb/os/windows_compat.c | 60 | ||||
-rw-r--r-- | libusb/os/windows_compat.h | 5 | ||||
-rw-r--r-- | libusb/os/windows_usb.c | 23 |
4 files changed, 69 insertions, 51 deletions
diff --git a/examples/xusb.c b/examples/xusb.c index 9925f07..fbe8f07 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -136,6 +136,19 @@ enum test_type { } test_mode; uint16_t VID, PID; +void display_buffer_hex(unsigned char *buffer, unsigned size) +{ + unsigned i; + + for (i=0; i<size; i++) { + if (!(i%0x10)) + printf("\n "); + printf(" %02X", buffer[i]); + } + printf("\n"); +} + + // The XBOX Controller is really a HID device that got its HID Report Descriptors // removed by Microsoft. // Input/Output reports described at http://euc.jp/periphs/xbox-controller.ja.html @@ -261,7 +274,7 @@ int get_mass_storage_status(libusb_device_handle *handle, uint8_t endpoint, uint expected_tag, csw.dCSWTag); return -1; } - // Strictly speaking, we should also should check dCSWSignature for validity, which we don't. + // For this test, we ignore the dCSWSignature check for validity... printf(" Mass Storage Status: %02X (%s)\n", csw.bCSWStatus, csw.bCSWStatus?"FAILED":"Success"); if (csw.dCSWTag != expected_tag) return -1; @@ -395,12 +408,7 @@ int test_mass_storage(libusb_device_handle *handle, uint8_t endpoint_in, uint8_t if (get_mass_storage_status(handle, endpoint_in, expected_tag) == -2) { get_sense(handle, endpoint_in, endpoint_out); } else { - for (i=0; i<size; i++) { - if (!(i%0x10)) - printf("\n "); - printf(" %02X", data[i]); - } - printf("\n"); + display_buffer_hex(data, size); } return 0; @@ -434,6 +442,8 @@ int display_sidewinder_status(libusb_device_handle *handle) { int r; uint8_t input_report[6]; + unsigned char buffer[8]; + int size; printf("\nReading SideWinder Input Report.\n"); r = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, HID_GET_REPORT, (HID_REPORT_TYPE_INPUT<<8)|0x00, 0, input_report, 6, 5000); @@ -449,6 +459,14 @@ int display_sidewinder_status(libusb_device_handle *handle) break; } } + // Attempt a bulk read from endpoint 0 (this should just return a raw input report) + printf("\nTesting bulk read (raw input report)...\n"); + r = libusb_bulk_transfer(handle, 0x81, buffer, 8, &size, 5000); + if (r >= 0) { + display_buffer_hex(buffer, size); + } else { + printf(" %s\n", libusb_strerror(r)); + } return 0; } diff --git a/libusb/os/windows_compat.c b/libusb/os/windows_compat.c index 4ff0c4f..a191e03 100644 --- a/libusb/os/windows_compat.c +++ b/libusb/os/windows_compat.c @@ -29,26 +29,26 @@ * For USB pollable async I/O, you would typically: * - obtain a Windows HANDLE to a file or device that has been opened in * OVERLAPPED mode - * - call create_fd_for_poll with this handle to obtain a custom fd. + * - call _libusb_create_fd with this handle to obtain a custom fd. * Note that if you need simultaneous R/W access, you need to call create_fd * twice, once in _O_RDONLY and once in _O_WRONLY mode to obtain 2 separate * pollable fds * - leave the core functions call the poll routine and flag POLLIN/POLLOUT * * For pipe pollable synchronous I/O (read end polling only), you would: - * - create an anonymous pipe with pipe_for_poll to obtain 2 fds (r & w) - * - use write_for_poll / read_for_poll to write to either end of the pipe + * - create an anonymous pipe with _libusb_pipe to obtain 2 fds (r & w) + * - use _libusb_write / _libusb_read to write to either end of the pipe * - use poll to check for data to read - * Note that the read_for_poll/write_for_poll function actually perform + * Note that the _libusb_read/_libusb_write function actually perform * asynchronous I/O internally, and could potentially be modified to support * O_NON_BLOCK * - * The way the polling on read_for_poll works is by splitting all read I/O + * The way the polling on _libusb_read works is by splitting all read I/O * into a dual 1 byte/n-1 bytes asynchronous read operation. * The 1 byte data (called the marker), is always armed for asynchronous * readout, so that as soon as data becomes available, an OVERLAPPED event * will be flagged, which poll can report. - * Then during the read_for_poll routine itself, this 1 byte marker is copied + * Then during the _libusb_read routine itself, this 1 byte marker is copied * to the buffer, along with the rest of the data. * * Note that, since most I/O is buffered, being notified when only the first @@ -56,7 +56,7 @@ * rest of the data should be available in system buffers by the time read * is called. * - * Also note that if you don't use read_for_poll to read inbound data, but + * Also note that if you don't use _libusb_read to read inbound data, but * use the OVERLAPPED directly (which is what we do in the USB async I/O * functions), the marker is not used at all. */ @@ -129,7 +129,7 @@ struct winfd poll_fd[MAX_FDS]; // internal fd data struct { CRITICAL_SECTION mutex; // lock for fds - BYTE marker; // 1st byte of a read_for_poll operation gets stored here + BYTE marker; // 1st byte of a _libusb_read operation gets stored here } _poll_fd[MAX_FDS]; @@ -386,7 +386,7 @@ out1: * read and one for write. Using a single R/W fd is unsupported and will * produce unexpected results */ -struct winfd create_fd_for_poll(HANDLE handle, int access_mode) +struct winfd _libusb_create_fd(HANDLE handle, int access_mode) { int i, fd; struct winfd wfd = INVALID_WINFD; @@ -399,7 +399,7 @@ struct winfd create_fd_for_poll(HANDLE handle, int access_mode) } if ((access_mode != _O_RDONLY) && (access_mode != _O_WRONLY)) { - printb("create_fd_for_poll: only one of _O_RDONLY or _O_WRONLY are supported.\n" + printb("_libusb_create_fd: only one of _O_RDONLY or _O_WRONLY are supported.\n" "If you want to poll for R/W simultaneously, create multiple fds from the same handle.\n"); return INVALID_WINFD; } @@ -461,7 +461,7 @@ void _free_index(int index) * * Note that the associated Windows handle is not closed by this call */ -void free_fd_for_poll(int fd) +void _libusb_free_fd(int fd) { int index; @@ -584,7 +584,7 @@ int _libusb_poll(struct pollfd *fds, unsigned int nfds, int timeout) if ((fds[i].events & ~POLLIN) && (!(fds[i].events & POLLOUT))) { fds[i].revents |= POLLERR; errno = EACCES; - printb("poll: unsupported set of events\n"); + printb("_libusb_poll: unsupported set of events\n"); return -1; } @@ -596,7 +596,7 @@ int _libusb_poll(struct pollfd *fds, unsigned int nfds, int timeout) if (index >= 0) { LeaveCriticalSection(&_poll_fd[index].mutex); } - printb("poll: invalid fd\n"); + printb("_libusb_poll: invalid fd\n"); return -1; } @@ -604,7 +604,7 @@ int _libusb_poll(struct pollfd *fds, unsigned int nfds, int timeout) if ((fds[i].events & POLLIN) && (poll_fd[index].rw != RW_READ)) { fds[i].revents |= POLLNVAL | POLLERR; errno = EBADF; - printb("poll: attempted POLLIN on fd[%d] without READ access\n", i); + printb("_libusb_poll: attempted POLLIN on fd[%d] without READ access\n", i); LeaveCriticalSection(&_poll_fd[index].mutex); return -1; } @@ -612,12 +612,12 @@ int _libusb_poll(struct pollfd *fds, unsigned int nfds, int timeout) if ((fds[i].events & POLLOUT) && (poll_fd[index].rw != RW_WRITE)) { fds[i].revents |= POLLNVAL | POLLERR; errno = EBADF; - printb("poll: attempted POLLOUT on fd[%d] without WRITE access\n", i); + printb("_libusb_poll: attempted POLLOUT on fd[%d] without WRITE access\n", i); LeaveCriticalSection(&_poll_fd[index].mutex); return -1; } - printb("poll: fd[%d]=%d (overlapped = %p) got events %04X\n", i, poll_fd[index].fd, poll_fd[index].overlapped, fds[i].events); + printb("_libusb_poll: fd[%d]=%d (overlapped = %p) got events %04X\n", i, poll_fd[index].fd, poll_fd[index].overlapped, fds[i].events); // The following macro only works if overlapped I/O was reported pending if ( (HasOverlappedIoCompleted(poll_fd[index].overlapped)) @@ -639,7 +639,7 @@ int _libusb_poll(struct pollfd *fds, unsigned int nfds, int timeout) // If nothing was triggered, wait on all fds that require it if (nb_handles_to_wait_on != 0) { - printb("poll: starting %d ms wait for %d handles...\n", timeout, (int)nb_handles_to_wait_on); + printb("_libusb_poll: starting %d ms wait for %d handles...\n", timeout, (int)nb_handles_to_wait_on); ret = WaitForMultipleObjects(nb_handles_to_wait_on, handles_to_wait_on, FALSE, (timeout==-1)?INFINITE:(DWORD)timeout); @@ -726,11 +726,11 @@ ssize_t _libusb_write(int fd, const void *buf, size_t count) // For sync mode, we shouldn't get pending async write I/O if (!HasOverlappedIoCompleted(poll_fd[index].overlapped)) { - printb("write_for_poll: previous write I/O was flagged pending!\n"); + printb("_libusb_write: previous write I/O was flagged pending!\n"); CancelIo(poll_fd[index].handle); } - printb("write_for_poll: writing %d bytes to fd=%d\n", count, poll_fd[index].fd); + printb("_libusb_write: writing %d bytes to fd=%d\n", count, poll_fd[index].fd); reset_overlapped(poll_fd[index].overlapped); if (!WriteFile(poll_fd[index].handle, buf, (DWORD)count, &wr_count, poll_fd[index].overlapped)) { @@ -744,7 +744,7 @@ ssize_t _libusb_write(int fd, const void *buf, size_t count) errno = 0; goto out; } else { - printb("write_for_poll: GetOverlappedResult failed with error %d\n", (int)GetLastError()); + printb("_libusb_write: GetOverlappedResult failed with error %d\n", (int)GetLastError()); errno = EIO; goto out; } @@ -754,7 +754,7 @@ ssize_t _libusb_write(int fd, const void *buf, size_t count) } } else { // I/O started and failed - printb("write_for_poll: WriteFile failed with error %d\n", (int)GetLastError()); + printb("_libusb_write: WriteFile failed with error %d\n", (int)GetLastError()); errno = EIO; goto out; } @@ -806,7 +806,7 @@ ssize_t _libusb_read(int fd, void *buf, size_t count) // still waiting for completion => force completion if (!HasOverlappedIoCompleted(poll_fd[index].overlapped)) { if (WaitForSingleObject(poll_fd[index].overlapped->hEvent, INFINITE) != WAIT_OBJECT_0) { - printb("read_for_poll: waiting for marker failed: %d\n", (int)GetLastError()); + printb("_libusb_read: waiting for marker failed: %d\n", (int)GetLastError()); errno = EIO; goto out; } @@ -815,19 +815,19 @@ ssize_t _libusb_read(int fd, void *buf, size_t count) // Find out if we've read the first byte if (!GetOverlappedResult(poll_fd[index].handle, poll_fd[index].overlapped, &rd_count, FALSE)) { if (GetLastError() != ERROR_MORE_DATA) { - printb("read_for_poll: readout of marker failed: %d\n", (int)GetLastError()); + printb("_libusb_read: readout of marker failed: %d\n", (int)GetLastError()); errno = EIO; goto out; } else { - printb("read_for_poll: readout of marker reported more data\n"); + printb("_libusb_read: readout of marker reported more data\n"); } } - printb("read_for_poll: count = %d, rd_count(marker) = %d\n", count, (int)rd_count); + printb("_libusb_read: count = %d, rd_count(marker) = %d\n", count, (int)rd_count); // We should have our marker by now if (rd_count != 1) { - printb("read_for_poll: unexpected number of bytes for marker (%d)\n", (int)rd_count); + printb("_libusb_read: unexpected number of bytes for marker (%d)\n", (int)rd_count); errno = EIO; goto out; } @@ -841,22 +841,22 @@ ssize_t _libusb_read(int fd, void *buf, size_t count) if(GetLastError() == ERROR_IO_PENDING) { if (!GetOverlappedResult(poll_fd[index].handle, poll_fd[index].overlapped, &rd_count, TRUE)) { // TODO: handle more data! - printb("read_for_poll: readout of supplementary data failed: %d\n", (int)GetLastError()); + printb("_libusb_read: readout of supplementary data failed: %d\n", (int)GetLastError()); errno = EIO; goto out; } } else { - printb("read_for_poll: could not start blocking read of supplementary: %d\n", (int)GetLastError()); + printb("_libusb_read: could not start blocking read of supplementary: %d\n", (int)GetLastError()); errno = EIO; goto out; } } // If ReadFile completed synchronously, we're fine too - printb("read_for_poll: rd_count(supplementary ) = %d\n", (int)rd_count); + printb("_libusb_read: rd_count(supplementary ) = %d\n", (int)rd_count); if ((rd_count+1) != count) { - printb("read_for_poll: wanted %d-1, got %d\n", count, (int)rd_count); + printb("_libusb_read: wanted %d-1, got %d\n", count, (int)rd_count); errno = EIO; goto out; } diff --git a/libusb/os/windows_compat.h b/libusb/os/windows_compat.h index e3fe695..f228782 100644 --- a/libusb/os/windows_compat.h +++ b/libusb/os/windows_compat.h @@ -75,9 +75,8 @@ int _libusb_close(int fd); void init_polling(void); void exit_polling(void); -struct winfd create_fd_for_poll(HANDLE handle, int access_mode); -void free_fd_for_poll(int fd); -void free_overlapped_for_poll(int fd); +struct winfd _libusb_create_fd(HANDLE handle, int access_mode); +void _libusb_free_fd(int fd); struct winfd fd_to_winfd(int fd); struct winfd handle_to_winfd(HANDLE handle); struct winfd overlapped_to_winfd(OVERLAPPED* overlapped); diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c index 860097d..de4e224 100644 --- a/libusb/os/windows_usb.c +++ b/libusb/os/windows_usb.c @@ -1641,7 +1641,7 @@ static void windows_clear_transfer_priv(struct usbi_transfer *itransfer) struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); usbi_remove_pollfd(ITRANSFER_CTX(itransfer), transfer_priv->pollable_fd.fd); - free_fd_for_poll(transfer_priv->pollable_fd.fd); + _libusb_free_fd(transfer_priv->pollable_fd.fd); } static int submit_bulk_transfer(struct usbi_transfer *itransfer) @@ -1839,7 +1839,7 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, io_result = GetLastError(); } usbi_remove_pollfd(ctx, transfer_priv->pollable_fd.fd); - free_fd_for_poll(transfer_priv->pollable_fd.fd); + _libusb_free_fd(transfer_priv->pollable_fd.fd); windows_handle_callback(transfer, io_result, io_size); } else { usbi_err(ctx, "could not find a matching transfer for fd %x", fds[i]); @@ -2422,7 +2422,7 @@ static int winusb_submit_control_transfer(struct usbi_transfer *itransfer) usbi_dbg("will use interface %d", current_interface); winusb_handle = handle_priv->interface_handle[current_interface].api_handle; - wfd = create_fd_for_poll(winusb_handle, _O_RDONLY); + wfd = _libusb_create_fd(winusb_handle, _O_RDONLY); if (wfd.fd < 0) { return LIBUSB_ERROR_NO_MEM; } @@ -2430,7 +2430,7 @@ static int winusb_submit_control_transfer(struct usbi_transfer *itransfer) if (!WinUsb_ControlTransfer(wfd.handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, NULL, wfd.overlapped)) { if(GetLastError() != ERROR_IO_PENDING) { usbi_err(ctx, "WinUsb_ControlTransfer failed: %s", windows_error_str(0)); - free_fd_for_poll(wfd.fd); + _libusb_free_fd(wfd.fd); return LIBUSB_ERROR_IO; } } else { @@ -2498,7 +2498,7 @@ static int winusb_submit_bulk_transfer(struct usbi_transfer *itransfer) winusb_handle = handle_priv->interface_handle[current_interface].api_handle; direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN; - wfd = create_fd_for_poll(winusb_handle, direction_in?_O_RDONLY:_O_WRONLY); + wfd = _libusb_create_fd(winusb_handle, direction_in?_O_RDONLY:_O_WRONLY); if (wfd.fd < 0) { return LIBUSB_ERROR_NO_MEM; } @@ -2513,7 +2513,7 @@ static int winusb_submit_bulk_transfer(struct usbi_transfer *itransfer) if (!ret) { if(GetLastError() != ERROR_IO_PENDING) { usbi_err(ctx, "WinUsb_Pipe Transfer failed: %s", windows_error_str(0)); - free_fd_for_poll(wfd.fd); + _libusb_free_fd(wfd.fd); return LIBUSB_ERROR_IO; } } else { @@ -2620,7 +2620,7 @@ static int winusb_reset_device(struct libusb_device_handle *dev_handle) { // Cancel any pollable I/O usbi_remove_pollfd(ctx, wfd.fd); - free_fd_for_poll(wfd.fd); + _libusb_free_fd(wfd.fd); wfd = handle_to_winfd(winusb_handle); } @@ -3320,7 +3320,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; - wfd = create_fd_for_poll(hid_handle, _O_RDONLY); + wfd = _libusb_create_fd(hid_handle, _O_RDONLY); if (wfd.fd < 0) { return LIBUSB_ERROR_NO_MEM; } @@ -3386,7 +3386,7 @@ static int hid_submit_control_transfer(struct usbi_transfer *itransfer) transfer_priv->pollable_fd = wfd; transfer_priv->interface_number = (uint8_t)current_interface; } else { - free_fd_for_poll(wfd.fd); + _libusb_free_fd(wfd.fd); } return r; @@ -3403,6 +3403,7 @@ static int hid_submit_bulk_transfer(struct usbi_transfer *itransfer) { bool direction_in, ret; int current_interface; DWORD size; + unsigned char buf[256]; CHECK_HID_AVAILABLE; @@ -3417,7 +3418,7 @@ static int hid_submit_bulk_transfer(struct usbi_transfer *itransfer) { hid_handle = handle_priv->interface_handle[current_interface].api_handle; direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN; - wfd = create_fd_for_poll(hid_handle, direction_in?_O_RDONLY:_O_WRONLY); + wfd = _libusb_create_fd(hid_handle, direction_in?_O_RDONLY:_O_WRONLY); if (wfd.fd < 0) { return LIBUSB_ERROR_NO_MEM; } @@ -3432,7 +3433,7 @@ static int hid_submit_bulk_transfer(struct usbi_transfer *itransfer) { if (!ret) { if(GetLastError() != ERROR_IO_PENDING) { usbi_err(ctx, "HID transfer failed: %s", windows_error_str(0)); - free_fd_for_poll(wfd.fd); + _libusb_free_fd(wfd.fd); return LIBUSB_ERROR_IO; } } else { |