[sane-standard] SANE 2 driver suggestion

Donald Straney burntfuse at gmail.com
Tue Feb 20 16:17:10 CET 2007


> these detection systems are relatively similar probing, across all OS's
> that sane supports. while i agree that they are archaic, they are easily
> abstracted into 'hunt thru scsi bus for X' and 'hunt thru usb bus for Y'.
> doing linux differently would require some sort of backend registration
> mechanism that we do not currently have.

Right, that would be handled by the wrapper.  I was thinking of
something like this:

register_bus_ids(bus_enum bus_type, char **id_array)
register_probe_func(probe_function func)

> this point presumes that 'HAL support' is a good thing, without explaining
> why. to a certain extent, sane devels are a wide-ranging group, and dont
> spend much time keeping up with everything new in Linux-only land. :)

Sorry, I should've been more specific.  What I meant is that all
scanners (or other image-capture devices) would show up consistently
in HAL, and have something to identify them, like an "image capture"
capability.  As it is right now, any scanner hardware recognized by
the kernel (including the USB and probably the SCSI devices) is going
to show up in HAL, so it wouldn't be hard to just have a list of HAL
rules which match the bus IDs and mark those with the "image capture"
capability.  The problem is that scanners on the parallel port, or
networked scanners handled by saned, aren't going to be in the kobject
system, so they're not going to be shown in HAL.

The reason for all this is that it could make everything easier if
done right.  For one thing, it would be nice to just be able to see
all scanners consistently recognized in the HAL device manager, so you
could keep track of them more easily.  Also, it could make getting a
scanner list much more efficient.  Instead of the program having to
probe for devices each time it has to get a list of available
scanners, it can just get a list from HAL, which I'm sure would be
faster.  That way, programs could also handle hotplugging more easily.
 Right now, if a USB scanner was plugged in while xsane was running,
it wouldn't have any way to recognize it, unless it was constantly
probing through sane_get_device_list every second (that wouldn't even
work with some drivers, which probe only once when they're loaded -
that's more of a driver problem, though).  With HAL support, the
program could just listen for DeviceAdded and DeviceRemoved signals.
With xsane that wouldn't matter very much, since it's easy to just
close it and open it again, but for daemons like mine that run
continuously to monitor button presses or something similar, it makes
things a little harder.

> i agree with the basic idea of making backends as simple as possible,
> but i dont think your abstraction of 'changing the drivers responsibilities'
> is detailed enough to do any real work. can you make more specific
> suggestions as to how you would structure the API?

Right.  First there could be functions for accessing the different
buses. I honestly don't know much about this, so I'm not going to go
into detail here:

send_usb_command
recv_usb_command
send_scsi_command
recv_scsi_command
(ieee1284, firewire, etc.)

...something along those lines anyways, probably like what's in sanei
now.  For debugging:

show_message(char *message) [for critical messages]
show_debug_message(char *message) [wouldn't be compiled in for
non-debug versions]

...then some wrappers for the standard functions:

sane_malloc
sane_free
sane_strcpy
sane_strlen
sane_strncmp
sane_memset

...and something to get configuration values:

char **get_config_keys()
get_config_value(char *key)

Or more like what's in sanei already:

sanei_config_handle *config_open
int config_read_line(char **line, sanei_config_handle *config)

It actually doesn't seem like the sanei interface for drivers would
need to be changed too much to fit.  Is there something I'm leaving
out which scanners would need?

> and now we've got two api's to manage? can you suggest how you
> would structure the ioctl's or whatever the kernel-level interface will
> be?

To keep things consistent, the device node API could be just like the
library API, which could be almost just like the API libsane has now.
Getting a device list would be done by looking at all the "imcapX"
nodes in /dev, connecting to a device would be done by opening the
device node, and closing the device node would close the connection
(as opposed to using sane_open, sane_close, etc.), but except for
that, the set of commands could be just about the same.  The device
info (like the manufacturer and model) would probably be stored in the
device's entry in /sys, right?  It could have ioctls for setting an
option value, getting an option value, getting the name of an option,
getting the type of an option, getting constraints on an option,
starting a scan, reading data (which would be read through the device
node using "read", of course) and stopping a scan.

> i am concerned about how you would provide to your dbus code
> the level of device-specific control that the sane options functions
> provide...

Do you mean on the device node level or the dbus level?

> i feel that we are discussing a solution without having a firm
> statement of the problem. this keeps coming up, so there must be
> some sort of need here, but i dont have a concise statement of the
> issue. can you help?

Again, sorry, I should've been more specific.  I guess the way I see
the problem is that it would be nice to have better handling of
hardware recognition: First, so that the hardware (including parallel
port and networked devices) could show up in /sys and HAL, instead of
having SANE's device list functions for scanners, and /sys for
everything else (which seems inconsistent).  It seems inefficient to
me to have to probe for devices every time to get a list of them,
instead of having a persistent list somewhere that's updated when
devices are plugged in or removed, like /sys or HAL.  Of course, SANE
could be based on a daemon which listens for hotplug events, checks
the bus IDs against a list of IDs registered by the drivers, and
updates an internal list of available scanners, but I don't really
like the idea of having something like that running all that time just
to get basic scanner access (especially since it has to be portable),
and it seems like a huge waste to duplicate all that stuff in
userspace when the kernel's already got a great driver model and
hardware detection system that it could use.

One other thing I was thinking of is how it would be nice to make all
the various imaging device APIs work well together.  As it is now,
SANE and V4L are fine, since video hardware can have a V4L driver and
SANE can grab frames through the V4L backend.  It seems like
libgphoto2 is the one that doesn't quite fit in, though, since it has
its own methods for getting video and still images from cameras,
although it's the only one that can transfer images stored on the
memory cards of cameras.  Think about it from the perspective of a
driver developer: Suppose that you're from a Linux-friendly company
and you're trying to add support for your camera, which can act as a
webcam for taking video and also store images.  If you create a
libgphoto2 driver for it, then programs which capture video (which
probably use V4L) won't be able to get video from your camera.  On the
other hand, if you create a V4L driver for it, there won't be a way to
transfer the pictures off the memory card.  It gets even more complex
if it can also take still images, something that SANE should be
handling.  It would be possible to write two separate drivers, but
honestly, who thinks that's a good idea?  The libgphoto2 backend for
SANE could also be improved so that it can actually get a list of
cameras and take still images from them if they support it, but that
doesn't solve the problem of video, unless libgphoto2 adds a V4L
backend and programs switch to using libgphoto2 for all video capture.
 Then we end up with a huge mess of different APIs and backends that
will scare everyone away from writing Linux drivers or imaging
programs... ;)

Anyways, where I'm leading with all this rambling is that if all the
drivers were in-kernel, then supporting a device which can capture
images or video in multiple ways would be much simpler.  There can be
just one driver per device in the form of a kernel module, which
registers itself for V4L if it can capture video, SANE if it can
capture still images, and as a block device if it stores pictures.
That way, any shared internal code (to send common commands to a
camera or to set options, for example) also wouldn't have to be
copy-pasted between the different drivers.

Oh, and on a sort-of-unrelated topic, I agree with Etienne that
clearer scanner button handling (I'm talking about physical buttons on
the scanner here) for SANE 2 would be great.

> and kernel space drivers are a whole new kettle of fish. sane has
> slowly abandoned its earlier kernel-level driver in favor of a user-land
> solution, which has been historically favored by all kernel devels. Has
> the situation on LKML suddenly changed to become favorable to large
> chunks of code for low-speed devices (like scanners) becoming kernel
> modules again?

Not as far as I know.  If the kernel hackers think scanner drivers
should be in userspace, then I'm not going to argue.  They obviously
know a whole lot more than me about it. :)

It's too bad, though, since there's no way to take advantage of the
2.6 kernel's great hardware system without that, and as I said before,
duplicating it in userspace with a daemon and a list of bus IDs
compiled from the drivers and everything seems inefficient and
inconsistent, definitely not the right solution.  Maybe the kernel
needs a standard way for userspace drivers to register hardware in
/sys, create device nodes in some way that works well with udev, and
automatically load the right library (from userspace, of course) when
the hardware's present, but that's a whole different matter...

Donald Straney



More information about the sane-standard mailing list