USB device support in wine

Damjan Jovanovic damjan.jov at gmail.com
Fri May 4 06:08:26 CDT 2007


On 5/4/07, Jon Burgess <jkburges at gmail.com> wrote:
>
> > > I have found some talk of implementing USB device support in wine in
> this
> > > list some time ago (2005), but as far as I know, nothing ever came of
> it.
> > >
> > > I would perhaps be interested in getting this going again, as I have an
> > > application (Serato Scratch Live:
> > > http://www.rane.com/scratch.html) for which the
> software
> > > appears to run ok under wine (not that I am able to test much of its
> > > functionality on the other hand), but is utterly useless without support
> for
> > > its associated USB hardware device.
> > >
> > > Any ideas, or anyone else who would be interested in helping me?
> >
> > Does the software come with a .SYS file?
>
> yes:  the is a directory .../Serato/Drivers/ containing "MP4Usb.sys" and
> "MP4Usb.inf", although I seem to remember reading somewhere that the MP4
> driver is for another Serato product (not Scratch live).

It probably doesn't refer to the MP4 music format.

> > That website doesn't much, please post lsusb -v output.

> Bus 004 Device 002: ID 13e5:0001
> Device Descriptor:
>    bLength                18
>   bDescriptorType         1
>   bcdUSB               1.00
>   bDeviceClass          255 Vendor Specific Class
>   bDeviceSubClass       255 Vendor Specific Subclass
>   bDeviceProtocol       255 Vendor Specific Protocol

This there is no "standard" driver for your USB device (like for
example there is just 1 driver for all USB flash disks, because
they're all in the same device class). You have the use the
vendor-supplied .SYS file.

Will it work on wine right now? Not even remotely.
Will it ever? Read on...

There is no standard user-mode interface for accessing USB hardware -
there is no equivalent of Linux's libusb on Windows (there is
apparently some user-space USB stuff in mingw's headers, but I
couldn't find any official docs on it, and it's not enough to write a
user-space driver because there is no bulk/interrupt/isochronous pipe
support, so I doubt anybody actually uses it). There is only
kernel-mode interfaces for talking to USB - and different kernel mode
drivers will export different user-mode interfaces (if any).

So user-space software uses a kernel-mode driver. If that driver is
documented, like USBSCAN.SYS and USBPRINT.SYS, its interface can be
done in wine, and wine can be connected to USB in a number of ways
(which I'll discuss later). If that driver is undocumented, either you
have to document it by reverse-engineering (very hard) and continue
with the first way, or (the second way:) make wine's not-yet-existing
NTOSKRNL.EXE load that driver, *and* provide NTOSKRNL.EXE with all the
USB interfaces that Windows has.

CONNECTING WINE TO USB: A HOW-TO GUIDE

There is 4 ways to do it:

1. Make a kernel module in your OS (eg. a Linux kernel module) that
exports the same interface that the software expects and works the
same way as the Windows driver. Using USBSCAN.SYS as an example,
reading does a USB bulk read, writing does a USB bulk write, and 13 or
so i/o control codes do various other things, among them USB control
and interrupt tranfers. Change kernel32's CreateFileW() to open the
/dev device node used by the kernel module and send it to the wine
server using wine_server_fd_to_handle(), then reading and writing will
go to your kernel module, where you can implement them by doing USB
reads and writes. Change ntdll's file.c's NtDeviceIoControlFile to
capture i/o control codes used by your device, call
wine_server_handle_to_fd(), and do an ioctl() on that fd to send that
i/o control call to the kernel module, which then reacts
appropriately. This way has been tested by me, it works and it's fast,
but it's non-portable (eg. Linux-only, and Linux's USB interface keep
changing so an out-of-tree module will only work on some versions, the
usual problems...), difficult (kernel-mode code is hard to write), and
generally a royal PITA.

2. Like (1) but use a framework like FUSD (the xiph.org version works
on 2.6 kernels) to write the driver in user-space and then do USB I/O
using libusb. I'm currently testing this approach, I suspect it's slow
(how significantly remains to be seen), but at least it's more
portable between Linux versions and easier to write and maintain.

3. Integrate your device into wine directly the way eg. serial ports
have been done. This is hard, and requires introducing a new FD_TYPE,
changing ntdll's file.c's NtReadFile, NtWriteFile, and
NtDeviceIoControlFile (and asynchronous versions of those) to use
special behavior for that FD_TYPE, and managing global device state
(eg. i/o timeouts) in wineserver (look at server/serial.c). With a lot
of time, and some changes to both wine and libusb, you could get it to
work properly. This should IMO only be done for generally useful
drivers, not drivers for just 1 type of device.

4. Integrate NTOSKRNL.EXE into wine, add USB infrastructure to
NTOSKRNL.EXE so that kernel-mode drivers can access USB (probably
through libusb), and modify ntdll to forward the appropriate reads,
writes, and i/o control requests to NTOSKRNL.EXE so that the .SYS file
can handle them. This is the only way that works with .SYS files
out-of-the-box, the others all require a rewrite of the .SYS driver's
functionality. Architecturally, this is the best way, you wouldn't
need to change any code in wine to add a new driver.

Way 4 is probably the best and I hope it works at some stage, but it's
still a long way off seeing as how NTOSKRNL.EXE itself still isn't in
wine.

>  In the mean time, looks like I have some reading to do regarding USB spec,
> dbus and hal :-)

There is only 1 or 2 chapters you need from the USB spec. DBus is just
an RPC framework, and HAL just lists devices and their properties, so
they won't help much.

> Thanks for the help so far.
>
> Regards,
> Jono
>

Damjan



More information about the wine-devel mailing list