[sane-devel] sane_get_devices and sanei_usb_init

Olaf Meeuwissen olaf.meeuwissen at avasys.jp
Fri Dec 12 01:57:29 UTC 2008

"m. allan noah" <kitno455 at gmail.com> writes:

> On Thu, Dec 11, 2008 at 6:38 PM, Olaf Meeuwissen
> <olaf.meeuwissen at avasys.jp> wrote:
>> "m. allan noah" <kitno455 at gmail.com> writes:
>>> On Thu, Dec 11, 2008 at 4:24 PM, ABC <abc at telekom.ru> wrote:
>>>> On Thu, Dec 11, 2008 at 04:06:24PM -0500, m. allan noah wrote:
>>>>> On Mon, Dec 1, 2008 at 10:23 PM, ABC <abc at telekom.ru> wrote:
>>>>> > First of all sanei_usb_init() is not designed to be used for rescanning
>>>>> > after any other sanei_usb functions is called. It is just initialization
>>>>> > and rescanning ability is not documented side effect. As stated in
>>>>> > documentation: "Call this before any other sanei_usb function". So don't
>>>>> > call it after. (This doesn't state it should be called just once, so we
>>>>> > could rescan before first device is opened.)
>>>>> sanei_usb_init() will blast the existing info, and assign all new
>>>>> device indexes to whatever it finds.
>>>> Exactly how it works now.
>>>>> However, sanei_usb_init() is only
>>>>> called by backends in sane_init() and sane_get_devices(). A frontend
>>>>> will only call sane_init() once, so that is not a problem, and the
>>>>> sane standard says this about sane_get_devices():
>> Calling sane_init() only once is not a SANE standard requirement.  If
>> it were, what's the point of sane_exit().
>> BTW, from the spec of sane_exit():
>>  [...] After this function returns, no function other than
>>  sane_init() may be called [...]
> but after you exit, there is no expectation that previously opened
> devices will work, so the sane_init that follows it is fine.

Indeed, but I would have expected sane_exit() to clean up in that case
rather than have the next call of sanei_usb_init() clobber whatever is
still there.

# I know libusb-0.1 doesn't have a usb_exit() and I think that sucks.
# Fortunately, this has been fixed with libusb_exit() in libusb-1.0.

Anyway, my main point was really that backend implementations should
not assume that frontends behave in well-defined ways that are not
required by the SANE standard.

>>>>> The returned list is guaranteed to remain unchanged and valid until
>>>>> (a) another call to this function is performed or (b) a call to
>>>>> sane_exit() is performed.
>>>> This don't says calling sane_get_devices will or should break any
>>>> already opened device.
>>> That is strongly implied. Why else would it bother to guarantee only
>>> half of the cycle?
>> I don't see why, unless the name member explicitly contains the index
>> used by sanei_usb.  On, at least, GNU/Linux that is not the case.  If
>> it does anywhere else, I'd consider that a bug.
>> If sane_get_devices() is allowed to break already opened devices, that
>> should be explicitly mentioned in the spec.
> it is implied, otherwise it would say that the list was guaranteed
> never to change. instead, it says that the list will be ruined if you
> call sane_get_devices again. and, since the response to that function
> provides the name you use in sane_open, it is implied that sane_open
> should be called again too.

Frontend calls sane_get_devices(), finds the device of interest,
strdup()s device->name and passes that to sane_open().  There is no
need for a backend to hang on to the returned list of devices other
than release its resources at sane_exit().  If necessary, backends
can strdup() the name they get passed to sane_open() themselves.

I fully expect a valid SANE_Handle returned by sane_open() to remain
valid until you call sane_close() on it (or call sane_exit() which,
per spec, has to close it for you).  If calling sane_get_devices()
nukes a _valid_ SANE_Handle, that's a bug.

>>>>> However, you have a valid point that most backends only call
>>>>> sanei_usb_init() in sane_init(), and I think that should change.
>>>> In backend I'm writing I call sanei_usb_init multiple times (in each
>>>> sane_get_devices) only if I don't have opened devices. I think that's ok.
>>> Unfortunately, that is not enough. if a person has another brand of
>>> scanner on their machine, alongside yours, and they open the other
>>> scanner and then call sane_get_devices(), your backend won't know.
>>> Then you will blast the list with the other backend's open device in
>>> it.
>> Eh, wait.  Aren't backends supposed to link statically with libsanei?
>> If they do, do they still share sanei_usb.c's
>>  static device_list_type devices[MAX_DEVICES];
>> # It still before my first coffee so I can't quite think this one
>> # through yet.
> ahh, yes, you are right. makes MAX_DEVICES = 100 look sort of overkill :)

Unless someone wants to make a double door-sized scanner by combining
a pile of A4 scanners ;-)

> let me see if i can hammer stef's patch into doing proper removal.

Effort appreciated.  It seems that will at least fix (the USB part of)
all the sane_get_devices() that rely on sanei_usb.

Hope this helps,
Olaf Meeuwissen, LPIC-2           FLOSS Engineer -- AVASYS Corporation
FSF Associate Member #1962               Help support software freedom

More information about the sane-devel mailing list