Earlier this year I encountered a bizarre problem – the Das Keyboard 4 Professional would not work on my Windows Vista desktop when connected to the onboard ICH10 USB controller. Whether connected directly or through a hub, front panel or back panel port – the results were always the same: USB enumeration fails with USBView showing the “bLength of 0 incorrect, should be 18” message, which suggests some sort of ‘handshake’ problem between the host controller and the device. This was the only system and only USB device where I’ve ever encountered this.
Troubleshooting narrowed down the problem to the USB 2.0 (EHCI) driver stack of Windows Vista. No other OS (including the older Windows XP) exhibited the issue; the keyboard worked fine in pre-boot environments (BIOS); it also worked fine when connected to a third-party USB 3.0 controller on a PCI-Express card (which has its own driver and does not use the Windows inbox one). The problem affected even the Windows installation environment running off DVD/USB, on multiple PCs, so it was not a configuration-specific glitch.
Additional testing with earlier Windows 7 installation media suggested that this bug persisted through early Windows 7 releases, and was fixed sometime around the release of Service Pack 1; despite multiple updates to Vista’s USB drivers since then, the issue is still present in all of them. My guess is the bug was introduced by some minor change, which has later been fixed half-accidentally, and due the rarity and obscurity of the issue, was never fully understood and backported.
I tried to find some documentation on registry keys for controlling USB device initialization, with the hope that some may randomly fix the issue, but found none. The next idea was trying to get the Win7 USB drivers to run on Vista. The USB driver stack is essentially the same between the two, and system file replacement between closely-related Windows versions has been moderately successful in some cases.
The relevant driver packages are usbport.inf (representing a USB controller), which includes usbd.sys, usbehci.sys, usbohci.sys, ubsuhci.sys, usbport.sys and usbhub.sys, and usb.inf (representing a USB hub), which includes usbccgp.sys and usbhub.sys. Yes, usbhub.sys is part of both packages, which posed a minor challenge.
My first idea was to use Win7’s original usb.inf and usbport.inf to generate proper driver packages, with catalog files and all, signing them, and installing them as private builds of the inbox drivers. However, because these are not just inbox drivers, but built-in Windows components, turns out, the driver signing tools refuse to sign a package which uses these filenames.
After changing the filenames and modifying the INF to refer to the new names, I could build the package; however it proved insufficient. After enabling test-signing I attempted to update the USB controller drivers via the Device Manager, but at some point the system crashed with a SYSTEM_THREAD_EXCEPTION_NOT_HANDLED. The problem, I believe, is that I wasn’t dealing with a simple driver for a specific device, but with the entire USB stack, consisting of multiple drivers, running multiple instances (for each USB controller and root hub in the system). It was probably not designed to be replaced on the fly like this.
So I went back to the original idea of just replacing the drivers with Win7’s versions. This requires taking ownership of the .sys files before overwriting them, or booting into a different OS and replacing the files there, while the system file protection is not running. My favorite solution is to boot from a Windows install CD, then hit Shift+F10 to open up a command prompt and perform the manipulations there.
At first I tried to replace all 7 .sys files. It sort of looked like it worked at first, but as I was connecting USB devices, the system eventually crashed. Turns out the culprit is usbhub.sys, which is used for the controller, as well as the root hub and any USB hub under it. Because of the complex ways Windows manages its driver store (which I don’t fully understand), at some point it would load a different copy of usbhub.sys, which it would take from the Vista package, creating a conflict with the Win7 version already loaded. Either that, or something in Win7’s usbhub.sys just doesn’t play nice with Vista.
The next (and final) thing I tried was to replace all the files related to usbport.inf, except the hub-related one, with Win7 versions, and leave the others in their Vista versions. This led to replacing a total of 5 files: usbd.sys, usbehci.sys, usbohci.sys, ubsuhci.sys and usbport.sys. Voila! The system booted fine, demonstrated full stability, and the problem with the Das Keyboard was gone! Checking the driver details in Device Manager shows that all the aforementioned files have versions 6.1.7601.xxxxx (from Win7 SP1), whereas usbhub.sys is 6.0.6002.xxxxx (from Vista SP2).
I proceeded to run with the above configuration for about half a year, until I decided to upgrade the PC in question from Vista to 7, for reasons unrelated to the issue described here. During this time, I encountered no issues, which suggests the configuration is fairly stable.
- On 64-bit Windows, you may need to enable test-signing and test-sign the individual .sys files, unless you want to use other methods to disable driver signature enforcement on every boot. This is because the signature embedded in the appropriate catalog files for the Vista drivers will not match the Win7 driver files.
- If you want to run in test-mode without the permanent watermark, use this utility.
- If ever you need to run the System File Checker (sfc /scannow), to fix some system files, it will restore the original Vista USB drivers, and you will need to repeat the process.
So there you have it – kernel-mode Windows drivers may be replaced with compatible ones from a later version with a few simple tricks. I doubt many will encounter the particular obscure bug that prompted me to attempt this, but the principles may be applied to other cases (provided that the drivers really are drop-in compatible, which is not always true).