I am developing a virtual USB Bus driver for windows (2000/XP).
The driver adds virtual USB devices to the system.
The software
redirects all USB Requests over the ethernet to a USB device server and than to
the physical USB device.
A lot of USB devices works fine (e.g. printer, scanner or mass-storage).
But the different to a local connected USB device is a missing entry
in the registry:
The USB hub driver writes out this value for every enumerated device in the device’s devnode. It is the string created registering a device interface on the PDO. For a hub PDO, it is GUID_CLASS_USBHUB, for a non hub device it is GUID_CLASS_USB_DEVICE
My virtual bus driver enumerates no hub devices. So i think my bus driver need to register an inteface
for all enumerted virtual devices (GUID_CLASS_USB_DEVICE).
The problem was, that my bus driver enumerates no hub device. The driver usbhub.sys is not used. My bus driver enumerates the devices that are connected to the USB Device Server. But the interface was missing.
I tested a Kyocera Multifunction printer (MFP). But the installation
routine of the printer driver and the usermode software did not
closed. The Installer was waiting for something.
Now my bus driver registers the device interface and add the symbolic link to the registry. The Kyocera installer installs all driver and
software components and after that it close itselfs.
Now i can use the MFP over the network. It seems to be, that there
is no different to a local connected MFP. The Scanner and printer a working fine.
hi Stefan Witt,
can u share ur ideas and code on USB virtual HUB driver ? it will really help me in doing something similar as im novice to drivers…
mail me to this id : xxxxx@gmail.com
thanks in advance,
When developing a similar program, I encountered a serious problem about interrupt transfer.
The devices I tested use this kind of transfer to detect the buttons on them. In the beginning, my program redirects the request and gets response quickly, then returns to the caller. In most time, the response is nothing detected and my program sets Status to STATUS_CANCELLED and Information to 0, and then completes the requests. The problem is that the caller sends the same request all the time and the CPU usage keeps on 100%. While searching the solution, I found the useful utility: “USB sniffer.” By the result log, I found my driver should block the request until the interrupt happens.
After some modifications, the problem was gone. BUT, one new serious problem happened. Just as I said, my program blocks some requests. The blocking will be terminated when my program receives URB_FUNCTION_ABORT_PIPE or URB_FUNCTION_RESET_PIPE for these pipes, or the related devices stops. It works for some devices, but not all. For some devices, after the applications and the related devices drivers closed, my program won’t receive these requests and the devices won’t be stopped because they are still connected on the host virtually. I know they are kept opened because I can see them in the Task Manager.
I have tried to find the information about the problem on the internet for a few days and found nothing. How can and what will my program be informed when the applications closed?
It is said that my program should receive IRP_MJ_CLEANUP and IRP_MJ_CLOSE when the application closed. But this is not real for my program. It will receive those requests only when the device is removed from the system. By using “USB sniffer” to log the information for the device on the host, which is in the normal situation and nothing about my program, I opened the application and the last captured request was listed below and please note the request was not returned:
the usb bus driver has no idea about application handles. 0xc0000120 is STATUS_CANCELLED, which means that the FDO canceled the IRP itself (which it created) in response to the handle being closed or the FDO formatted the stack location of a user mode irp and the i/o manager canceled the irp b/c it was pending on the file handle when it was closed. the usb sniffer is not giving you the entire story, you need to look at other irps like create/cleanup/close. the OSR irp tracker will probably work for you here.
I had tried to use IrpTracker downloaded from this site but unfortunately it could not work on my system. After selecting the device and then starting the application, the blue screen came and my system rebooted automatically. I also had used SoftIce and, in the situation, it broke at “ntoskrnl!KeRegisterBugCheckReasonCallback+020A” with the following messages.
Break Due to KeBugCheckEx (Unhandled kernel mode exception)
Error=C2 (BAD_POOL_CALLER)
I think I need to search another utility to try to know all the process because I can not find the complete information about the USB bus driver on Windows. Furthermore, I do think the USB Sniffer can capture the IRPs like IRP_MJ_CREATE, IRP_MJ_CLEANUP and IRP_MJ_CLOSE because I can see them in the logged information and I also can receive them in my code. The problem is, just as I said before, IRP_MJ_CLEANUP and IRP_MJ_CLOSE come only when the device is removed.
If the USB sniffer is sitting below the FDO sending the URBs, I don’t see how it can sniff IRP_MJ_CREATE/CLEANUP/CLOSE since the FDO typically does not send those PIRPs down the stack. As for the bugcheck, you need to fix your symbols.
The application probably closes the handle when the app is removed because it has registered for PnP notifications on the handle (see RegisterDeviceNotification) and is notified when the device has been removed. When the notification arrives, the app closes the handle and cancels all I/O.
I reinstalled my system and finally IrpTracker can work successfully. I found that IRP_MJ_CLEANUP and IRP_MJ_CLOSE were processed by USBSCAN and they were not sent to my program. My situation is that the application creates a thread and then sends a request, by DeviceIoControl, to wait for data coming from an interrupt endpoint (pipe) of the device. When it is going to close, it calls CloseHandle. At that time, my program, a bus driver, needs to complete the blocked IRP and to return to the application. I had tried two methods to try to know when to do the cancelling: to set up a cancel routine and to check IRP->Cancel repeatedly. Neither of them can achieve the goal. I think there must be something I do not know because the bus driver in Windows processes it successfully. Please help. Thanks.
I don’t think I can help you any further. You will need to figure out why your design is not working, perhaps by setting breakpoints on completion routines and cancel routines in the “normal” bus scenario and see when each of these are executed.
Deeply appreciate your kindly help.
Actually I have no idea of how to debug (break) the system program, USBD.SYS maybe. I think I need to find more detail information about the bus drivers. The books I owned mention nothing about the situation.