USB Device Support

Damjan Jovanovic damjan.jov at gmail.com
Tue Sep 21 05:03:13 CDT 2010


On Wed, Sep 15, 2010 at 1:39 AM, Eric Durbin <eadurbin at gmail.com> wrote:
>
>
> On Tue, Sep 14, 2010 at 10:48 AM, Damjan Jovanovic <damjan.jov at gmail.com>
> wrote:
>>
>> When last I heard from Alexander Morozov (October 2009), he wasn't
>> working on those patches much, and had no interest in sending them to
>> wine-patches.
>>
>> I did some work on USB since then, and sent some patches starting from
>> around March 2010 (too many attempts to list, search for them). Most
>> were rejected.
>>
>> The USB story goes as follows:
>>
>> My libusb patch was rejected IIRC because the libusb situation was
>> unclear. There's the old libusb-0.1 and the new more powerful
>> libusb-1.0. IIRC each *nix hacked up its own specific variation of
>> libusb that had to be detected specifically, and some *nixes didn't
>> support the libusb-1.0 interface yet (libusb-1.0 itself only supports
>> Linux and MacOS when last I checked, and they were doing a Windows
>> port).
>>
>> The ntoskrnl that Wine currently emulates is total bogus: one process
>> per driver, drivers all in separate processes from each other. On
>> Windows there's a single address space for all drivers and they can
>> communicate amongst themselves. I don't think inter-driver
>> communication is that crucial initially, but it will be eventually
>> (eg. last I heard, the iPod driver stacks on top of USBSTOR.SYS, and
>> multi-function USB devices can use a different driver for each
>> interface - these may communicate among themselves with private ioctl
>> requests). The big problem with the multi process situation is
>> hardware sharing: how do you set it up so each driver accesses its own
>> and only its own hardware?
>>
>> Drivers either start on system startup (Wine starts those with the
>> first process that starts), or get loaded on-demand as the hardware is
>> plugged in. Most drivers should install themselves to be loaded
>> on-demand. Who loads those and how?
>>
>> Windows uses USBHUB.SYS to do device I/O and load drivers on demand.
>> Alexandre didn't want that dll because it exports nothing (all its
>> features are accessible via internal ioctls), and suggested adding the
>> features to USBD.SYS instead, which we already have and which has
>> exports. Now USBD.SYS is linked to by most (but not all) USB drivers
>> so (most of the time) it automatically gets loaded into each one -
>> great right? - but it has no idea which driver it got loaded with, nor
>> a straightforward way to determine which device(s!) that driver wants
>> to drive. Also, since most drivers only load on-demand, the driver
>> will never load, and thus this won't work unless we load those drivers
>> on startup instead. The other approach, which I tried, was to get
>> Wine's mountmgr.sys to detect USB devices using HAL, then pass them to
>> a loaded-on-startup instance of USBHUB.SYS using a Wine-private ioctl,
>> which would detect the driver for the device and launch a new instance
>> of itself that would make a device object and load the driver to
>> attach to it. This was all a bit a hack (USBHUB.SYS uses environment
>> variables to tell the child which device and driver to run) and
>> Alexandre also didn't the the Wine-private ioctls. Alexander Morozov's
>> patch did things the Windows way: all drivers in one ntoskrnl process
>> - this won't work properly in Wine for years, if ever, since ntoskrnl
>> is so incomplete and one bad driver will crash them all. Another
>> possibility could be to keep drivers in separate processes, but allow
>> inter-process communication, but I see serializing IRPs between
>> processes as being complex and very slow.
>>
>> Driver installation is also quite a mission. Windows detects that the
>> hardware doesn't have a driver installed, and then generates the
>> device ID and compatible IDs and searches .INF files for one that can
>> support it. Our setupapi needs to be substantially improved to be able
>> to do the same, and some newdev.dll and manual INF parsing work to
>> install the driver may also be necessary, and I can already think of
>> cases where even class installers will be necessary too :-(.
>>
>> Wine only sends DeviceIoControl to drivers. For anything non-trivial,
>> other file-related user-space functions (at least ReadFile, WriteFile)
>> need to go to the driver too. The infrastructure for this does not
>> even exist yet, and would probably affects wineserver as well.
>>
>> Regression tests for ntosnkrl.exe and kernel drivers don't exist, and
>> are difficult to come up with, since we'd have to compile and load
>> drivers on Windows and run tests that don't crash Windows :-).
>>
>> So the architecture for USB support is tricky to say the least. But
>> I'd still like to resume work on my USB patches some time soon, would
>> you like to help?
>
> I'd be willing to help if you want some assistance. I don't know much about
> the subject yet, but I'm reading  programming the wdm atm.

Firstly I'd like to find a cheap simple USB device that we can
actually get working quickly. Earlier I was experimenting with my
Blackberry driver, but that's not going far quickly, since it's a
multi-protocol device (modem, mass storage, and proprietary protocols,
etc.). I've got a USB scanner that's unsupported by SANE, but that
needs ReadFile/WriteFile which is a lot of work by itself. Same with
USB flash sticks. I can get hold of an iPod but that's probably the
most complex, needing to stack on top of USBSTOR.SYS IIRC. Ironically
drivers for the easy hardware (USB mice) are unnecessary anyway, since
the Linux drivers are good enough, and the Windows drivers probably
need to be driven from user-space by bits Wine doesn't have. Maybe I
should give up and just get something partially working, add the rest
later gradually. Any ideas?

Then it's largely a matter of design. I think Alexandre's idea
(process per driver, host all USB code in USBD.SYS) is good enough
initially.

Essentially the first steps would be:
1. libusb integration
2. driver loading hacks
3. driver -> devices lookup
4. usb bus enumeration for devices
5. create pdo and fdo for each device
6. AddDevice to driver
7. perform I/O for IRPs coming down from the driver using libusb I/O functions

That should get a very basic driver (that only uses the control pipe)
working. I'll try to get some of this done later this week/weekend.

Damjan



More information about the wine-devel mailing list