Git Product home page Git Product logo

libusb-win32's Introduction

libusb-win32

libusb-win32 is a port of the libusb-0.1 API for Windows with some additional asynchronous transfer support. The library allows user space applications to access many USB device on Windows.

There are two parts of this project: digital signed kernel driver (libusb0.sys) and user space library (libusb0.dll).

Status: supported

Maintained by:

Peter Dons Tychsen (developer)

mcuee (project manager)

Xiaofan Chen (technical support)

libusb-win32's People

Contributors

dontech avatar mcuee avatar tormodvolden avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libusb-win32's Issues

Release plan discussion

We will use 1.2.7.x as snapshot release version. Probably the next formal version should be labeled as 1.2.8.0.

V1.2.7.3 (11/13/2021) - SNAPSHOT RELEASE

  • driver: sign the drivers using SHA1 as well as SHA256

  • driver: sign the drivers after microsoft and not before (win7 fix)

V1.2.7.2 (10/25/2021) - SNAPSHOT RELEASE

  • driver: sign the drivers using EV certificate: #24

  • driver: fix possible stack corruption: #19

  • lib: fix missing check for failed CloseHandle(): #12

V1.2.7.1 (09/18/2019) - SNAPSHOT RELEASE

  • Removed support for IA64
  • Removed support for W2K
  • Properly allocate NX pool memory on Win8+

V1.2.6.0 (01/17/2012)

  • Official release.
  • Removed ISO maximum transfer size restrictions/transfer splitting.
  • Fixed inf-wizard device notification issue.

Missing data for In transfer of size >65536 bytes

Hello,
I discovered by accident that as soon as I want to use transfer size > 65536, for inbound transfers, I start randomly missing some pieces of data, even if the actual length of transferred data is well beyond 65536.

I am only using bulk In transfer on a USB2.0 High Speed link/device.

For instance: I am using libusb-1.0 with libusb0.sys driver (and therefore libusbK.dll in the middle).

  1. I submit one transfer with a buffer of 131072 bytes and set the Length field at this value to read data on my endpoint
  2. I get a callback saying (via ActualLength field) 1024 bytes have been transferred. Everything OK, I resubmit
  3. I get another callback saying 1592 bytes have been transferred. Everything OK, I resubmit
  4. I get another callback saying 1328 have been transferred: I can clearly see from the data that there is an large amount of missing bytes, in the order of 1000.

If I use 65536 or less, everything is fine. If I use 65536+512, or any value larger than 66536 + N * 512, I get the missing data issue.

If I use Zadig to switch to libusbK.sys or WinUSB.sys, I get no issues at all, for larger or smaller than 65536 transfer buffer size.

I can see from the comment at line 352 of transfer.c that "each bulk/interrupt irp/urb pair can request at the most 65536 bytes" but I don't see how this value is actually used in the code, I find no other occurrence of this value. Instead I can see that "maxTransferSize" is used somehow, but I do not expect maxTransferSize to be equal to 65536 on my system (Windows 10).

And even if maxTransferSize was equal to 65536, I would expect the code to work, but it doesn't seem it does correctly.

Is this a known issue / limitation?

Feature request: HUB support

https://sourceforge.net/p/libusb-win32/bugs/74/

Updated: 2012-07-06 Created: 2010-09-08 Creator: Manuel Kauf

I use the USB Lib in the version 1.1.14-3 long since, with this i had no problems. The device is a USB Hub
(SMSC USB2513)

At least in V 1.1.14-3 it was visible in the Device list.

With the V 1.2.2.1 or V 1.2.2.0 does not find this hub any more in the list.

Feature request: isochronous buffer packets offset/length

https://sourceforge.net/p/libusb-win32/feature-requests/12/

Updated: 2012-07-06 Created: 2010-11-23 Creator: Tim Schuerewegen

I am using libusb-win32 to communicate with a OV550/OV5620 based webcam. I am using isochronous async reads to get the video data from the webcam. However, there is one problem. The data in the buffer (after a reap) is not contiguous, ie. there are holes in it. In order for me to know which parts in the buffer are data and which parts are garbage/empty, I need access to the URB's IsoPacket array. The Offset/Length value pairs of the IsoPacket array are the only way I can piece the video frames back together.

Example:

usb_reap_async returned 0x60

IsoPacket 0 - Offset = 0, Length = 0
IsoPacket 1 - Offset = 0xBF4, Length = 0
IsoPacket 2 - Offset = 0x17E8, Length = 0x54
...
IsoPacket 29 - Offset = 0x15AA4, Length = 0xC
..
IsoPacket 31 - Offset = 0x1728C, Length = 0

As you can see the 0x60 bytes of data are spread across 2 iso packets. Without the IsoPacket array Offset/Length information I can not locate the 0x60 bytes of data from the buffer.

Thank you in advance.

Remove inf-wizard from the formal release

As mentioned in the wiki, "The installer from libusb-win32 does not either under Windows 7/10, please use the GUI installer from libusbK or Zadig". So I think it is better to just remove the inf-wizard GUI from the release.

BTW, the filter installer wizard GUI works fine so please keep it.

libusb0.dll missing

I am building an application that utilizes libusb-0.1. It was able to be compiled and built on Microsoft Visual Studio 2022 up until yesterday where system error was raised upon debugging. The description of the error is "The code execution cannot proceed because libusb0.dll was not found. Reinstalling the program may fix this problem." I did try debugging the program on another machine but the problem still persists. Was there any commit changes to the repository yesterday that might cause this to occur?
libusb dll missing

Using async API can re-order the arrival of packets.

Found during the investigation of: #51

@dontech Well, I quickly modified my loopback test program for handling multiple transfers at once, but it doesn't show the issue...

The difference in between this simple version and my full application is that in loopback test each transfer has a fixed constant buffer pointer and buffer contents are verified sequentially, given transfer callback all happens within the same "handling thread". Given that verifying buffers is a "long" process, I am suspecting that all transfers are done while I am verifying the first one, I then resubmit it, verify the second, etc. but de facto there might be only one active transfer at a time.

In my full application what I do is that, in callback function, I put the transfer buffer pointer into a list then quickly allocate a new buffer, set the transfer buffer pointer with it and submit the transfer again.

I will try to improve loopback test for simulating this, but it might not be easy.

In the meantime: do you have any idea how your changes could create the behavior I am observing? Thanks.

Remove libusb1 folder

There is a copy in the root folder called libusb1, which is not used for anything, and has not been touched for 15 years.

Is there anyone who wants to keep this. If not, it will be removed.

Hotplug support

It may be good to provide hotplug support.

As of now, libusb-win32 does not support hotplug. libusb-1.0 does not support hotplug under Windows.
libusbK has hotplug support.

libusb-win32 1.2.7.x debug version

Right now there is no debug build of libusb-win32 1.2.7.3. Sometimes it is useful to use DebugView to print the debug message. I am not so sure if there is an issue to get the debug version of the driver signed or not by Microsoft.

libusb-win32 libusb.a for Codeblocks 20.03

I would like to compile my code with the GNU GCC compiler that comes with Codeblocks 20.03. I get an error that says "skipping incopatible" libusb.a, that uses to work. They says that happens when there is a 32/64 bit incompatibility. How can I get a 64 bit libusb.a that will link? I am using libusb-win32 1.2.6.0 with function calls usb_bulk_setup_async(), usb_submit_async(), usb_reap_async().

Enhancement with patch: Exposing usb overlapped event

https://sourceforge.net/p/libusb-win32/patches/12/
Updated: 2014-08-20 Created: 2011-03-14 Creator: Piotr Foltyn
Exposing usb overlapped event to the upper code layers.

Index: libusb/src/usb.h
===================================================================
--- libusb/src/usb.h	(revision 381)
+++ libusb/src/usb.h	(working copy)
@@ -401,6 +401,7 @@
     int usb_interrupt_setup_async(usb_dev_handle *dev, void **context,
                                   unsigned char ep);
 
+    int usb_get_overlapped_event_handle(void *context, void **eventHandle);
     int usb_submit_async(void *context, char *bytes, int size);
     int usb_reap_async(void *context, int timeout);
     int usb_reap_async_nocancel(void *context, int timeout);
Index: libusb/src/windows.c
===================================================================
--- libusb/src/windows.c	(revision 381)
+++ libusb/src/windows.c	(working copy)
@@ -417,6 +417,26 @@
     return 0;
 }
 
+int usb_get_overlapped_event_handle(void *context, void **eventHandle)
+{
+    usb_context_t *pUsbContext = (usb_context_t *)context;
+    HANDLE *pEventHandle = (HANDLE *)eventHandle;
+
+    if (NULL == pUsbContext) {
+        usb_error("usb_get_overlapped_event_handle: invalid context");
+        return -EINVAL;
+    }
+
+    if (NULL == pEventHandle) {
+        usb_error("usb_get_overlapped_event_handle: invalid event handle");
+        return -EINVAL;
+    }
+
+    *pEventHandle = &pUsbContext->ol.hEvent;
+
+    return 0;
+}
+
 int usb_submit_async(void *context, char *bytes, int size)
 {
     usb_context_t *c = (usb_context_t *)context;

Bug: usb_interrupt_write occasionally sends the same data twice

https://sourceforge.net/p/libusb-win32/bugs/79/

Updated: 2012-07-06 Created: 2012-03-15 Creator: Vince Harron

I can reproduce this easily if I call usb_interrupt_write in a tight loop. I'm sending 13 byte packets with an incrementing sequence number and crc32. My USB sniffer sees two of them go out. If I sleep 4ms between calls to usb_interrupt_write, it can send thousands of packets correctly without sending duplicate data. I've attached a USB trace from TotalPhase

This packet appears twice on OUT
07 00 06 00 09 93 F4 FD
06 B6 27 E5 A6

The USB device is setup to echo every packet it receives.

I'm reading and writing the usb device from different threads. Here is the code for the writer thread (to try to illustrate that it's unlikely/impossible that I'm sending the same packet twice.)

unsigned writer( void * udev_void )
{
struct usb_dev_handle udev = (struct usb_dev_handle)udev_void;

RingBuffer_t tx;
uint8_t tx_data[256];

DWORD    last_update = timeGetTime();
uint16_t tx_sequence_number = 0;
uint16_t sent_since_last_update = 0;
Sleep(1000); // wait for the reader thread to get started
while(1)
{
    RingBuffer_InitBuffer(&tx,tx_data,sizeof(tx_data));

    write_ude_message( &tx, tx_sequence_number, MESSAGE_ID_ECHO_REQUEST, (const uint8_t*)&g_time, sizeof(g_time) );

    while ( RingBuffer_GetCount(&tx) )
    {
        int ret = usb_interrupt_write(
            udev,
            4, //epWrite,
            (char*)tx.Out,
            RingBuffer_GetCount(&tx),
            1000);
        if ( ret > 0 )
        {
            RingBuffer_Remove_Array(&tx,0,ret);
        }
    }

    tx_sequence_number++;
    sent_since_last_update++;
    DWORD elapsed = timeGetTime() - last_update;
    if ( elapsed > 2000 )
    {
        printf("%i sent (%i)\n", sent_since_last_update, tx_sequence_number );
        last_update = timeGetTime();
        sent_since_last_update = 0;
    }
    //Sleep(1);
}
return 0;

Support ARM64

Going forward, the ARM64 platform will become more popular.
Update the system to support building this target.

Isochronous transfer improvement

One of the main improvement of libusbk.sys vs libusb0.sys is that it has better isoc transfer support.

libusb0.sys may only work with full speed isoc transfer and not really with high speed or super speed isoc transfer.

I am not so sure if it is worth the time to enhance the isoc support now that libusbk.sys and winusb both support isoc transfer.

Bug: LibUSB filter altering suspend on Z77 board with Win7 x64

Updated: 2013-02-19 Created: 2012-06-03 Creator: MaJoR

I'm using the libusb-win32 1.2.60 filter drivers on my system to get PCSX2 to work with my Dualshock3. Unfortunately that plugin is a bit outdated, and only works with the libusb filter drivers, and not the newer INF based drivers. Regardless, with a filter driver active (DS3 connected or not), the standby mode on my computer doesn't work properly. I hit standby, and it goes to sleep mostly as normal, but it takes longer and races the CPU as it sleeps (this motherboard has advanced fan controls, increases fan speed based on heat). When I try to rouse it from it's nap, the computer comes on and the monitors fire up, but the USB devices never come on, and nothing is displayed on the screens. It will be stuck in this state indefinitely, I have to hit the reset button for it to come back. Then it says "resuming windows" as if it was coming out of hibernate, and then comes back.

Obviously, this is a minor issue, but it is annoying. My Z77 motherboard has alot of advanced suspend modes, that allow it to go to sleep, but shut down akin to hibernate, while using very little power and coming back instantly. I really miss it... Removing the filter driver restores the computer to normal, but then I have no DS3, obviously.

Using LibUSB-win32 1.2.6.0
Windows 7 x64 (sp1)
Core i5 3570K @ 4.7ghz
Asus P8Z77-V LX
8GB Corsair Ballistax DDR3-1600 (4GBx2) memory

libusb_dyn.c is missing stubs for several of the libusb-win32 functions

Updated: 2012-08-09 Created: 2012-05-20 Creator: Benjamin Moody

libusb_dyn.c is missing stubs for several of the libusb-win32 functions:

usb_touch_inf_file_np
usb_install_needs_restart_np
usb_install_npW
usb_install_npA
usb_reap_async_nocancel
usb_cancel_async

(It's also missing the various _rundll stubs, but I doubt there's any point in including those.)

The first four are related to driver installation, and any program that uses those will probably want to link to libusb0.dll directly. But usb_reap_async_nocancel and usb_cancel_async should at least be included.

(I'm trying to compile a program (tilem) that links to a library (libticables2) that links to libusb (and uses those two functions), but my program doesn't currently make use of the USB features of libticables2, so I would like to avoid the libusb0.dll dependency if possible.)

Patch is attached; I have not tested it beyond making sure it compiles, but it's pretty straightforward.

github action

It may be good to set up github action for CI/CD.

#16 allow zero length control transfer (without buffer)

https://sourceforge.net/p/libusb-win32/patches/16/

Using for instance libusbk.dll 3.0.7.0 (the version currently installed with Zadig) a control transfer with zero length will fail (see libusb/libusb#1006). I suspect this is due to the check on transfer_buffer_mdl in src/driver/ioctl.c since the same check for bulk transfer write is explicitly not done. The second patch changes the control transfer check to be consistent to the bulk transfer check.

The first patch just adds missing debug tags. The second patch applies on top.

I don't have the setup to rebuild and test libusb0.sys so I can only assume this is correct without verification by own testing. BTW this issue doesn't show when using the recently released libusbk.dll 3.0.8.0 because the control transfers are done differently here.

Driver error message caught with DebugView:
libusb0-sys:err [dispatch_ioctl] (null): invalid transfer request
patches.zip

API Change: Redefining uint32_t et al. clashes with <stdint.h>

https://sourceforge.net/p/libusb-win32/bugs/77/

Updated: 2012-07-06 Created: 2012-01-19 Creator: Joerg Wunsch

When trying to compile AVRDUDE against libusb-win32-1.2.5.0, I get the following error:

In file included from usbasp.c:56:0:

/tmp/libusb-win32-src-1.2.5.0/src/usbi.h:10:23: error: conflicting types for 'uint32_t'
/usr/local/lib/gcc/mingw32/4.5.0/../../../../mingw32/include/stdint.h:32:20: note: previous declaration of 'uint32_t' was here
*** Error code 1

libusb should not attempt to redeclare type names found in <stdint.h>.

As a short-term workaround, I #if 0'ed these three lines out from usbi.h. I think a proper solution would be either to name your own types differently, or (better) to probe for C99 types availability
from <stdint.h> in some kind of configure script, and use them if available, falling back to the current way if no stdint.h is around.

(Btw., with those three lines disabled, all works well, and I could successfully build AVRDUDE on my FreeBSD host against the library. The resulting executable file works, which is great!)

Deprecate the use of pipe information about MaximumTransferSize

According to this:

https://learn.microsoft.com/en-us/windows-hardware/drivers/usbcon/usb-bandwidth-allocation

The MaximumTransferSize value is deprecated and replaced by discrete values. A bit silly that Microsoft will not support the information in pipe policy without replacing it with something else, but then again it only requires a simple look-up table.

I have not seen that this has any consequence with the current implementation however, but for correctness we might want to fix this.

Seen during the fixing of this bug: #51

Update documentation on building

As pointed out, the current documentation is either wrong or lacking.

At least detail how to:

  1. Build using Visual Studio
  2. Build using command line "build.cmd"

How to get usb position info?

Hello,i have two questions。
One is why create device like '\.\libusb0-0001' is succeed?Is this device defined in register or just defined by libusb?
The other is how i can get the detail information of usb position?In this format:Port_#0002.Hub_#0002?
Thanks.

Crash in reads with short timeout -- bug in _usb_cancel_io()

https://sourceforge.net/p/libusb-win32/mailman/message/36291183/

When calling e.g. usb_interrupt_read() that times out it will call:

  1. usb_interrupt_read
  2. _usb_transfer_sync
  3. usb_reap_async
  4. _usb_reap_async
  5. _usb_cancel_io

This is where it goes south. To cancel the I/O operation it calls:

_usb_abort_ep() to send the LIBUSB_IOCTL_ABORT_ENDPOINT to the driver
synchroniously. Even though the LIBUSB_IOCTL_ABORT_ENDPOINT is sent
synchroniously to the driver, the driver just forwards the request to
"usbd" further down the IRP chain as a "reset endpoint" request, which
has asynchrinous elements to it. So all-in-all you cannot regard the
request as cancelled when returning from _usb_abort_ep().

To fix this it was introduced that using WaitForSingleObject() would be
used to wait for the cancel to go through.

The first revision that had this was:

6eaec78aed8e34e1aaf2e835b7

It was later reformatted into being a part of _usb_cancel_io().

However, WaitForSingleObject() is not called correctly. If you want to
be sure that the cancel has been executed, you must call
WaitForSingleObject() with a timeout that is large enough to ensure
that the request is processed. In many cases on a loaded system, this
ends tragically.

libusb-win32 driver to uninstall?

sometime there are some crash,with the device self driver,so i need to uninstall it when i never use libusb-win32 driver,anything can help?

Building issue under MSYS2 mingw64 gcc

There is a minor here here.

 UCRT64 /c/work/libusb/libusb-win32/libusb
$ make
gcc -O2 -Wall -DWINVER=0x500  -Werror -Wno-unknown-pragmas -Wno-multichar -DLOG_APPNAME=\"libusb0-dll\" -DTARGETTYPE=DYNLINK -c ./src/usb.c -o usb.2.o  -I./src -I./src/driver -I.
gcc -O2 -Wall -DWINVER=0x500  -Werror -Wno-unknown-pragmas -Wno-multichar -DLOG_APPNAME=\"libusb0-dll\" -DTARGETTYPE=DYNLINK -c ./src/error.c -o error.2.o  -I./src -I./src/driver -I.
gcc -O2 -Wall -DWINVER=0x500  -Werror -Wno-unknown-pragmas -Wno-multichar -DLOG_APPNAME=\"libusb0-dll\" -DTARGETTYPE=DYNLINK -c ./src/descriptors.c -o descriptors.2.o  -I./src -I./src/driver -I.
gcc -O2 -Wall -DWINVER=0x500  -Werror -Wno-unknown-pragmas -Wno-multichar -DLOG_APPNAME=\"libusb0-dll\" -DTARGETTYPE=DYNLINK -c ./src/windows.c -o windows.2.o  -I./src -I./src/driver -I.
gcc -O2 -Wall -DWINVER=0x500  -Werror -Wno-unknown-pragmas -Wno-multichar -DLOG_APPNAME=\"libusb0-dll\" -DTARGETTYPE=DYNLINK -c ./src/install.c -o install.2.o  -I./src -I./src/driver -I.
gcc -O2 -Wall -DWINVER=0x500  -Werror -Wno-unknown-pragmas -Wno-multichar -DLOG_APPNAME=\"libusb0-dll\" -DTARGETTYPE=DYNLINK -c ./src/registry.c -o registry.2.o  -I./src -I./src/driver -I.
windres  -I./src ./src/resource.rc -o resource.2.o
gcc -O2 -Wall -DWINVER=0x500  -Werror -Wno-unknown-pragmas -Wno-multichar -DLOG_APPNAME=\"libusb0-dll\" -DTARGETTYPE=DYNLINK -o libusb0.dll -I./src  usb.2.o error.2.o descriptors.2.o windows.2.o install.2.o registry.2.o resource.2.o libusb0.def -s -mdll -Wl,--kill-at -Wl,--out-implib,libusb.a -Wl,--enable-stdcall-fixup -L. -lcfgmgr32 -lsetupapi -lgdi32
gcc -O2 -Wall -DWINVER=0x500  -Werror -Wno-unknown-pragmas -Wno-multichar -DLOG_APPNAME=\"install-filter\" -DTARGETTYPE=PROGRAMconsole -DLOG_STYLE_SHORT -c ./src/install_filter.c -o install_filter.1.o  -I./src -I./src/driver -I.
gcc -O2 -Wall -DWINVER=0x500  -Werror -Wno-unknown-pragmas -Wno-multichar -DLOG_APPNAME=\"install-filter\" -DTARGETTYPE=PROGRAMconsole -DLOG_STYLE_SHORT -c ./src/error.c -o error.1.o  -I./src -I./src/driver -I.
gcc -O2 -Wall -DWINVER=0x500  -Werror -Wno-unknown-pragmas -Wno-multichar -DLOG_APPNAME=\"install-filter\" -DTARGETTYPE=PROGRAMconsole -DLOG_STYLE_SHORT -c ./src/install.c -o install.1.o  -I./src -I./src/driver -I.
gcc -O2 -Wall -DWINVER=0x500  -Werror -Wno-unknown-pragmas -Wno-multichar -DLOG_APPNAME=\"install-filter\" -DTARGETTYPE=PROGRAMconsole -DLOG_STYLE_SHORT -c ./src/registry.c -o registry.1.o  -I./src -I./src/driver -I.
windres  -I./src ./src/install_filter_rc.rc -o install_filter_rc.1.o
gcc -O2 -Wall -DWINVER=0x500  -Werror -Wno-unknown-pragmas -Wno-multichar -DLOG_APPNAME=\"install-filter\" -DTARGETTYPE=PROGRAMconsole -DLOG_STYLE_SHORT -o install-filter.exe -I./src  install_filter.1.o error.1.o install.1.o registry.1.o install_filter_rc.1.o -s -L. -lgdi32 -luser32 -lcfgmgr32 -lsetupapi
gcc -c ./tests/testlibusb.c -o testlibusb.3.o -O2 -Wall -DWINVER=0x500  -Werror -Wno-unknown-pragmas -Wno-multichar -DLOG_APPNAME=\"testlibusb\" -DTARGETTYPE=PROGRAMconsole  -I./src -I./src/driver -I.
./tests/testlibusb.c: In function 'print_device':
./tests/testlibusb.c:95:63: error: ' - ' directive output may be truncated writing 3 bytes into a region of size between 1 and 256 [-Werror=format-truncation=]
   95 |                 snprintf(description, sizeof(description), "%s - ", string);
      |                                                               ^~~
./tests/testlibusb.c:95:17: note: 'snprintf' output between 4 and 259 bytes into a destination of size 256
   95 |                 snprintf(description, sizeof(description), "%s - ", string);
      |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1.exe: all warnings being treated as errors
make: *** [Makefile:162: testlibusb.3.o] Error 1

HPE team - found a stack override problem on libusb-win32

Hi Peter,

This is James from HPE, we recently found a stack override problem on the libusb-win32 driver.
https://sourceforge.net/projects/libusb-win32/

Please review below for details and let us know your opinion and suggestions.
It would be great if you can help us to fix this issue.
I have sent you an email around 8/5.

The problem is the irp->userIosb ptr member which points to local io_status which is allocated locally from the stack.

The kernel updates the 2 qword io_status which is originally on the stack of call_usbd_ex but sometimes the kernel stomps the stack of another routine if call_usbd_ex has already returned when the update happens.

Here’s a lot more detail from libusb_driver.c:

NTSTATUS call_usbd_ex(libusb_device_t *dev, void *urb, ULONG control_code,      <-- see note1
                                    int timeout, int max_timeout)
{
       KEVENT event;
       NTSTATUS status;
       IRP *irp;
       IO_STACK_LOCATION *next_irp_stack;
       LARGE_INTEGER _timeout;
       IO_STATUS_BLOCK io_status;                                                 <-- see note 2
 
       if (max_timeout > 0 && timeout > max_timeout)
       {
              timeout = max_timeout;
       }
       if (timeout <= 0)
              timeout = LIBUSB_MAX_CONTROL_TRANSFER_TIMEOUT;
 
       KeInitializeEvent(&event, NotificationEvent, FALSE);
 
       irp = IoBuildDeviceIoControlRequest(control_code, dev->target_device,     \
              NULL, 0, NULL, 0, TRUE,                                             > see note 3
              NULL, &io_status);                                                 /
 
       if (!irp)
       {
              return STATUS_NO_MEMORY;
       }
 
       next_irp_stack = IoGetNextIrpStackLocation(irp);
       next_irp_stack->Parameters.Others.Argument1 = urb;
       next_irp_stack->Parameters.Others.Argument2 = NULL;
 
       IoSetCompletionRoutine(irp, on_usbd_complete, &event, TRUE, TRUE, TRUE);
 
       status = IoCallDriver(dev->target_device, irp);                          \_ returns STATUS_PENDING so need to wait for irp completion
       if(status == STATUS_PENDING)                                             /
       {
              _timeout.QuadPart = -(timeout * 10000);
 
              if(KeWaitForSingleObject(&event, Executive, KernelMode,            \_ wait times-out after specified 500ms  --  see note 4
                     FALSE, &_timeout) == STATUS_TIMEOUT)                        /
              {
                     USBERR0("request timed out\n");
                     IoCancelIrp(irp);                                           <-- attempt to cancel the irp because of the time-out
              }
       }
 
       /* wait until completion routine is called */
       KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);       <-- wait (with infinite time-out) for completion
 
       status = irp->IoStatus.Status;                                           <-- see note 5
 
       /* complete the request */
       IoCompleteRequest(irp, IO_NO_INCREMENT);                                 <-- see note 6
       
       USBDBG("status = %08Xh\n",status);
       return status;                                                           <-- see note 7
}

Note 1:
The call_usbd_ex() routine executes all the time but precisely every 60sec there is a unique usb request that always times-out after 500ms and fails:
2: kd> dt _URB ffff868d`0be18570 UrbControlVendorClassRequest.Value
USBPORT!_URB
+0x000 UrbControlVendorClassRequest :
+0x082 Value : 0x3fd <-- 0x3fd = 1021 is a unique usb vendor request code that always times-out
Eaton should be able to tell us what this 0x3fd (1021) request is, why it gets sent every 60sec, and what might cause it to always time-out.
We should check a “working” system to see if this request is being sent and if it always time-out and fails.
If this request didn’t get sent or if it didn’t time-out and fail then we would not have a problem.

Note 2:
The 2 qword IO_STATUS_BLOCK io_status is allocated as a local on the stack of the current routine:
2: kd> dt IO_STATUS_BLOCK Status Information
libusb0!IO_STATUS_BLOCK
+0x000 Status : Int4B <-- low dword of first qword will be updated with ntstatus 0xc0000120 (The I/O request was canceled)
+0x008 Information : Uint8B <-- second qword will be updated with the byte count of the transfer which will be 0x00000000’00000000
This is what gets updated or stomped on the stack and the results are:

  • If the writes happen before this routine returns then this is just a normal status block update
  • If the writes happen after this routine returns then this stomps the stack possibly of some other routine and timing / stack usage determines if it crashes

Note 3:
The irp is created here. Notice that the &io_status ptr is passed as an arg and it becomes the irp member UserIosb ptr:
2: kd> dt nt!_IRP IoStatus UserIosb
+0x030 IoStatus : _IO_STATUS_BLOCK
+0x048 UserIosb : Ptr64 _IO_STATUS_BLOCK <-- ptr to local io_status allocated on this routine’s stack
The irp that’s created has the following flags:
2: kd> dt nt!_IRP 0xffffe486`c1d56990 Flags
+0x010 Flags : 0x40060000 <-- 0x40000000 => FILE_FLAG_OVERLAPPED => it can be asynchronous (or synchronous)
When the kernel is later called to complete the request, it copies IoStatus into the ptr contents of *UserIosb (ie. io_status) which is the final status info for the irp:

  • This is what can stomp the stack of another routine depending upon when it happens
  • ie. it might be a synchronous or asynchronous completion
  • if it is async then the stack will get stomped later but there will only be a crash if another routine is actively using those stack addrs at that time
    Either of the following will work-around the problem:
  • If io_status is defined as a global (instead of as a local on the stack) then the stack will not get stomped
  • If io_status is replaced with a NULL then the kernel will not update user status (*UserIosb) and the stack will not get stomped
    o Note: I don’t think it is documented that this ptr can be a NULL ptr but I verified that this works (using kd to hack the assembly code)

Note 4:
This times-out after a specified 500ms wait/time-out (ie. the request/irp event does not get signaled within 500ms).
If I hack the assembly with kd to make it an infinite wait/time-out then it works:

  • This means that this usb request (ie. the specific one that happens every 60sec) is taking far too long
  • Eaton should be able to tell us what this vendor _URB request (value 0x3fd / 1021) is and why it takes so long
  • We should also check a “working” system to see if the same request is being sent every 60sec and if it also times-out
  • ie. if this request is not being sent and/or not timing-out (or we can stop it) then the system will not fail

Note 5:
The “status = irp->IoStatus.Status” should really be “status = irp->UserIosb->Status” (where the final status is copied into) but this doesn’t cause a problem.
It does mean that irp->UserIosb is not being used here.

Note 6:
This call (IoCompleteRequest) tells the kernel to finish and do clean-up of the irp. This includes the kernel executing nt!IopCompleteRequest to copy IoStatus into *UserIosb:

  • this can happen synchronously by direct calls (w/o an APC int) as shown in one of the callstacks earlier in this email
  • this can also happen asynchronously sometime later via an APC int as shown in another of the callstacks earlier in this email

Note 7:
The call_usbd_ex routine returns here and the locals on its stack should not be accessed from this point onwards:

  • if the irp was handled synchronously then io_status on the current stack was previously written and will not be accessed again => no problem
  • if the irp is being handled asynchronously then io_status on the stack might be written sometime after the return (on some other routine’s stack):
    o if the APC int and the write of io_status happens before the penter() check then the stack is stomped w/o problems because the addr is not yet in use
    o if the APC int and the write of io_status happens after the penter() check then the stack is stomped w/o problems if the addr is not currently used
    o if the APC int and the write of io_status happens near the penter() check then the args being passed up the stack during that time window get stomped
     this last case is where we see 1 or 2 stomped args on the stack causing a penter trap or crash
     ie. stack addr of old qword io_status.Information stomped w/ 0 and old dword io_status.Status stomped w/ ntstatus 0xc0000120

Best Regards,
James

libusb0.sys snapshot release and digital signature

(Updated on 13-Nov-2021)
Please take not libusb0.sys snapshot 1.2.7.1 release is not signed. Users who want to use it will have to get it signed by themselves. 1.2.7.2 snapshot release is signed but it will not work for Windows7.

Please help to test 1.2.7.3 to see if it works under Windows 7 or not.

V1.2.7.3 (11/13/2021) - SNAPSHOT RELEASE

  • driver: sign the drivers using SHA1 as well as SHA256

  • driver: sign the drivers after microsoft and not before (win7 fix)

V1.2.7.2 (10/25/2021) - SNAPSHOT RELEASE

  • driver: sign the drivers using EV certificate: #24

  • driver: fix possible stack corruption: #19

  • lib: fix missing check for failed CloseHandle(): #12

V1.2.7.1 (09/18/2019) - SNAPSHOT RELEASE

  • Removed support for IA64
  • Removed support for W2K
  • Properly allocate NX pool memory on Win8+

V1.2.6.0 (01/17/2012)

  • Official release.
  • Removed ISO maximum transfer size restrictions/transfer splitting.
  • Fixed inf-wizard device notification issue.

Doc: Ambiguous install docs

https://sourceforge.net/p/libusb-win32/bugs/83/

Updated: 2014-12-09 Created: 2014-12-09 Creator: gwideman

Could someone please fix the Installation section of page https://sourceforge.net/p/libusb-win32/wiki/Home/ so that every instruction is clear about which executable or other names it's talking about? Examples:

Filter Driver Installation:

-- "The filters driver is installed by a user friendly GUI installer [...] a GUI for installing the filter driver (Filter Wizard) " Exactly which exe file is the GUI installer?

-- "Run the installer, and follow its instructions." Which executable is THE installer mentioned here?

Device Driver Installation:

-- "The device driver is distributed as a separate package which includes everything to use libusb-win32 for single devices as a normal device driver. The installation of the filter driver is not necessary any more!" Wait, what? Does this mean a user should never install the filter driver that was described in the preceding section? Or just that for some scenarios that previously required a filter driver, it's no longer needed, but other scenarios still use a filter driver? Confusing.

-- "Use the INF-Wizard program to generate.." What's the executable name?

Removing:

-- "To remove device filter driver, run the GUI filter driver wizard to remove it." Which executable is that?

-- "The device driver can not be easily removed from the system. You can however try to use usbdeview http://www.nirsoft.net/utils/usb_devices_view.html to remove the entries." What entries would that be? How do you know which ones to remove?

I am really hoping this page can be clearer, because though this component is so useful, it's so easy to mess these steps up, and USB is devilish to troubleshoot. And as mentioned, there's no simple uninstall process, at least for the device driver, to back out mistakes or trial runs.

Nothing Registers anymore

Since I installed this nothing I plug in like USBs Gamepads or Mics dont work anymore, I get the connected sound but they dont pop up.

Bug: usb_bulk_read() timeout to read integral multiple of 512 byte data --> 45556

https://sourceforge.net/p/libusb-win32/bugs/82/

Updated: 2013-02-19 Created: 2012-07-22

When I control the USB device to commit a 512 Bytes package or 1024, 1536,2048,2560 ... (integral multiple of 512 byte), to 1MB Max.

Then use usb_bulk_read() to read the data:(i=1,2,3,4....)
1 Worked call: usb_bulk_read(m_usb_dev, USB_BULK_EP_IN, read_buffer, 512 * i, 500);
2 Time out call: usb_bulk_read(m_usb_dev, USB_BULK_EP_IN, read_buffer, 1024 * 1024, 500);

If usb device commit a 511 or 513 bytes package (not equal to 512, or integral multiple of 512 byte), these to usb_bulk_read() call all work fine.

testlibusb-win.exe output:
DLL version: 1.2.6.0
Driver version: 1.2.6.0

bus/device idVendor/idProduct
bus-0/\.\libusb0-0001--0x4077-0x1243 4077/1243
- Manufacturer : Hell LS
- Product : Hell LS
bLength: 18
bDescriptorType: 01h
bcdUSB: 0200h
bDeviceClass: 00h
bDeviceSubClass: 00h
bDeviceProtocol: 00h
bMaxPacketSize0: 40h
idVendor: 4707h
idProduct: 2143h
bcdDevice: 0000h
iManufacturer: 1
iProduct: 2
iSerialNumber: 0
bNumConfigurations: 1
wTotalLength: 32
bNumInterfaces: 1
bConfigurationValue: 1
iConfiguration: 0
bmAttributes: a0h
MaxPower: 50
bInterfaceNumber: 0
bAlternateSetting: 0
bNumEndpoints: 2
bInterfaceClass: 255
bInterfaceSubClass: 0
bInterfaceProtocol: 0
iInterface: 0
bEndpointAddress: 02h
bmAttributes: 02h
wMaxPacketSize: 64
bInterval: 0
bRefresh: 0
bSynchAddress: 0
bEndpointAddress: 86h
bmAttributes: 02h
wMaxPacketSize: 512
bInterval: 0
bRefresh: 0
bSynchAddress: 0

Feature request: usb_get_configuration

https://sourceforge.net/p/libusb-win32/feature-requests/13/

Updated: 2012-07-06 Created: 2011-12-06 Creator: Anonymous

The documentation goes to some length about how to first check the active configuration, before attempting to set a configuraiton. However, usb_get_configuration() is not exported. Is the documentation outdated (not ncessary to check the configuraiton) or should this funciton be exported? I think that iven if the check is not necessary, this is funcitonality that should be exposed to the client.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.