[sane-devel] Proposal: sanei_usb interface for USB scanners

Oliver Neukum Oliver.Neukum@lrz.uni-muenchen.de
Mon, 6 Aug 2001 21:26:07 +0200

Am Montag,  6. August 2001 20:35 schrieben Sie:
> Hi,
> On Mon, Aug 06, 2001 at 12:07:46AM +0200, Oliver Neukum wrote:
> > > I have just written a quick-and-dirty interface for USB scanners like
> > > sanei_scsi is for SCSI scanners. It's not as generic as the SCSI one,
> > > however. Currently it works only with device files, so e.g. the Linux
> > > USB scanner module is supported. I don't know if it's easy to add
> >
> > The architecture you use will work with nothing else.
> I'm quite new to USB so I may be wrong:
> Question 1: Is there anything else?
> I know of:
> - libsusb (Linux, *BSD, others?)

Not always. Your IO model is too inflexible.

> - scanner module (Linux, FreeBSD)


> - special kernel modules for some scanners (Linux only?)

as yet unneeded

> What about USB support on other operating systems?

BSD should be doable. I have no idea about others.

> Question 2: Is there a more generic way?
> My idea to use the scanner module resulted from the fact, that this
> module knows which USB device is a scanner and which isn't (at least
> in theory). While libusb looks more generic, I can't ask this lib
> questions like: "Is any scanner connected to this system", because
> there is no class "scanner" (unlike SCSI). So I can't write something
> for sane-find-scanner without having a list of the ids of scanners.

You are right.

> Would it be possible to support both libusb and the scanner module by
> using opaque handles like that:
> sanei_usb_open_by_id (some_handle_type * handle, SANE_Word vendor,
> SANE_Word product);
> If this fails (no libusb and no ioctl support for scanner module):
> sanei_usb_open_by_name (some_handle_type * handle, SANE_String_Const
> device_file);
> Or even something like:
> sanei_usb_open_by_name (some_handle_type * handle, SANE_Word vendor,
> SANE_Word product SANE_String_Const device_file,);
> Open device with given ids if possible (and ids != 0), if not try to
> open based on device_file.
> The handles could point to file descriptors, libusb usb_dev_handle or
> whatever. Just something to identify the scanner.
> However I don't really know how to handle two (or more) identical
> devices (same vendor and product id).

The problem is not so much recognition and opening, but the actual IO.

> > > support for libusb; is there documentation for it anywhere? Would it
> > > be possible to add support for the scanners with their own kernel
> > > drivers without too much dirty tricks?
> >
> > Which would be ?
> I don't know. e.g. USB-over-SCSI-over-USB :-)
> > There are three scanner drivers in the Linux kernel, the
> > generic, microtek and hp5300. The latter two use SCSI over USB.
> So they look like SCSI devices and can be used by sanei_scsi
> functions? That's fine. No need to include them into sanei_usb.

They are SCSI to anything but the low level driver.

> > Generally speaking scanners which cannot use the generic driver cannot be
> > used in a way that would map to only bulk read/write.
> They use control messages and/or interrupts? But if this
> scsi-over-usb works, it doesn't matter.

There are even others, most notably sm3600 which uses libusb.

> Question 3:
> Is sanei_usb needed? Which backend could use it? Currently mustek_usb
> can use it but if this is the only one, it's no problem to include the
> necessary code in the backend itsself and something similar in
> sane-find-scanner.

Anything that supports USB scanners, save for sm3600, might have a need for 

> Question 4:
> Can libusb do everything the scanner module can do? If yes, would it
> be sensible to use libusb instead of the scanner module? One drawback
> would be that the user has to install one more library before he can
> use USB scanners. Is libusb included in Linux distributions?

libusb can do anything a kernel module can do (except for real time 
requirements). However it cannot do the permissions thing.

libusb internally uses usbdevfs, which being virtual, cannot store persistant 
permissions. By using the generic scanner kernel driver you save users lots 
of administration hasseles. Besides it has an easier interface.

> What can the "special" Linux scanner modules that libusb can't do?

Seamless integration into the SCSI system. Handling SCSI isn't that easy.
It's better to use what is in the kernel.

> > > sanei_scsi_find_devices goes the other way round: it returns a device
> > > file for a given vendor and device id. It has the same limitations as
> > > above. With this function it's possible to use "usb 0x1233 0x321" in
> > > the config file (similar to the "scsi" command) to find a device file
> > > for the USB scanner with these ids.
> >
> > This is dangerous. In fact it's a race. The id might be invalid by the
> > time the device is actually opened. You should return an fd.
> Don't we have the same problem with SCSI scanners? If someone
> exchanges the scanner between the detection (usually in sane_init) and
> usage (sane_open) we will access the wrong device. At least the mustek
> backend doesn't check for the identity of the device again, when it
> sane_opens it. Should it?

No. SCSI scanners are not hotpluggable (exception: firewire scanners are SCSI 
to the kernel)
USB devices however are very hotpluggable.

> What about something like
> SANE_Status
> sanei_usb_get_vendor_product (SANE_Int fd, SANE_Word * vendor, SANE_Word *
> product);
> SANE_Status
> sanei_usb_find_devices (SANE_Int vendor, SANE_Int product,
>                         SANE_Status (*attach) (SANE_Int fd));
> If the ids are checked again after sane_open nothing should go wrong
> as far as I see. And sane-find-scanner should also work.

Yes. Doing so is safe.

Perhaps I should mention that I think your code is good.
It won't work for sm3600, but I don't consider this important.