[sane-devel] backend coding overview

Henning Meier-Geinitz henning@meier-geinitz.de
Thu, 2 Sep 2004 13:03:29 +0200


On Tue, Aug 31, 2004 at 10:33:33PM -0400, Mbosowo I Sampson wrote:
> I'm interested in writing a back end for the 3970. I've been reading 
> specs, looking at other back ends, trying to get familiar with sane, 
> etc... Its all a little daunting. I feel as though I know more than I did 
> a few days ago, but not nearly enough to even begin to know where to 
> start.

I usually recommend to start with something taht's easy (or at least
not that complex). E.g. to add a test to tools/check-usb-chip.c so
that the chipset can be detected by sane-find-scanner. After you have
done this you'll know a bit about USB descriptors, libusb and
hopefully even on how to communicate with the scanner's chipset.

> I think what I'm looking for here is a general overview of how sane 
> interacts with a USB scanner.

I don't think that such a document exists yet.

> I feel like I can't see the forest because 
> I'm preoccupied with studying the composition of bark on each tree. Once I 
> have the conceptual part down, I think all the details will fall into 
> place as I continue reading the documentation.
> What I'm asking for is a break down of the steps involved for a scan to be 
> made. I'm trying to conceptualize how libusb, the driver I will write, the 
> front end, and the chip set all interact together to execute a successful 
> scan. Doesn't have to be in minute detail, but some detail is always good.

Ok, some hints:
Think of the communication with an USB scanner in layers. E.g. if you
look at how the scanned data goes from the scanner to a SANE frontend:

- scanner sensor (+motor etc.)
- scanner control chip(s)
- scanner firmware
- scanner USB chip
- USB cable
- computer USB hostdadapter (uhci, ohci or ehci)
- operating system hostadapter driver (e.g. ohci-hcd on Linux 2.6)
- operating system driver for communication with userspace (e.g.
  devio/usbfs or kernel scanner driver on Linux)
- userspace library (e.g. libusb)
- sanei_usb.c (e.g. sanei_usb_read_bulk)
- backend (e.g. your new backend: sane_read)
- frontend (calls sane_read of the backend)

SANE itsself (the standard) doesn't care how the scanner is connected.
In fact the standard doesn't really care if there is a scanner at all.
That's why backend like the test backend exist which simulate a scanner.

In theory you could communicate with a scanner from the backend
dirctly. In fact, that's what was done before usining sanei_usb.c. But
that means that you must add code for every operating system and every
implementation of USB access. That's why we have sanei_usb. It's a
wrapper around all the operating-system specific USB details. As a
backend author you (usually) don't need to care if a kernel scanner module,
libusb or something else is used.

Depending on the scanners chipset, you communicate with the scanner by
sending and receiving USB control or bulk messages. The messages
contain commands or are used for setting registers of the scanner's

Usually you tell the scanner in which mode (bits/pixel etc.) it is to
scan, the dimensions of the scan area, the resolution and some more
details. Then you tell the scanner to start scanning. Most backends
implement that code in sane_start. Once the scanner scans, image data
is read from it in sane_read. Usually the data must be converted to
the SANE image data format. After all the data is received, the
scanner head is moved to its home position.

In reality, it's more complicated as you need to do calibration and
handle gamma curves etc. It depends on the scanner's chip if this is
done in the hardware itsself or if the backend has to do it.

If you want more details, just ask :-)

Good luck!