Back to index

VueScan's Autofocus is Nonfunctional

Background

In my previous post I mentioned that while VueScan has the option to use manual or automatic focus, it doesn't actually change how the scanner operates. This post is proof that it doesn't do anything. To be clear, as far as I can tell, the v550 does not support changing focus at all. This is not a shortcoming of VueScan, aside from presenting an option when it shouldn't.

VueScan has a drop down for autofocus with the options of "Always", "Scan", "Preview" and "Manual". Selecting "Manual" adds a slider that can be used to set the focus from -1.0 to 1.0. For my tests I compared the commands sent to the scanner with it set to "Always" and "Manual" at both -1.0 and 1.0.

The Epson v550 and Linux

Epson's v550 scanner driver is split into an open source part (named epkowa) and a v550 specific proprietary plugin. Both of these are installed as shared libraries at /usr/lib/sane/libsane-epkowa.so and /usr/lib/iscan/libiscan-plugin-perfection-v550.so, respectively. After digging around a while I discovered that the open source driver communicates to the scanner in a protocol called ESC/I which doesn't seem to be documented anywhere. Some manuals make reference to it though. The v550 does not implement ESC/I directly, so the proprietary plugin interprets the ESC/I and converts it to the scanner's native protocol. This is why it's referred to as an interpreter in the /usr/var/lib/iscan/interpreter config file.

What is VueScan using?

Running

$ strace -P /usr/lib/sane/libsane-epkowa.so ./vuescan
and
$ strace -P /usr/lib/iscan/libiscan-plugin-perfection-v550.so ./vuescan
shows that while VueScan does not use the open source SANE interface, it does use the proprietary plugin. Fortunately, since the main epkowa driver is open source, the API for that plugin is documented. This means I can create a shim that intercepts and logs calls to the shared library (see more details here).

You can find the source for my shim here. It's pretty simple and just logs everything being sent to/from the scanner to stderr with a R or W prefix to indicate reads/writes.

Results

Full logs (except for image data) are available here

I ran VueScan both in normal scanning mode and in preview mode collecting logs scanning with autofocus, with manual focus at the minimum, and with manual focus at the maximum. The first thing that's clear is that there is no difference between the minimum and maximum focus:

$ diff close_focus.log far_focus.log && echo Same
> Same

There is a slight difference between autofocus and the manual focus:

$ diff close_focus.log auto_focus.log
> W: 1b 65
> R: 6
> W: 1
> R: 6

The first line is ESC-e which is the command to control an extension. Extensions refer to extra parts like automatic document feeds or the transparency scanning unit. It then reads back 6, writes 1 and reads another 6. I'm not sure what the one ands sixes mean, but the open source driver call this function when enabling an extension. My guess as to what's happening is VueScan has a common code path for turning on autofocus that starts by enabling the transparency unit then does something device specific (which is nothing for this scanner). But that's just a guess; I have no data to back that up. In any case, it isn't doing anything to change how the scanner focuses.

Why not use LD_PRELOAD? Or ltrace?

I tried but neither works in this case. Since VueScan is loading the shared library directly from it's absolute path with dlopen(), LD_PRELOAD doesn't have any effect. From man 3 dlopen:

If filename is NULL, then the returned handle is for the main program. If filename contains a slash ("/"), then it is interpreted as a (relative or absolute) pathname. Otherwise, the dynamic linker searches for the object as follows (see ld.so(8) for further details)

Since the path does have a slash, the dynamic linker does not search for the object and thus LD_PRELOAD is not used

I tried using ltrace but could not get it to work. Perhaps it has issues with dlopen as well?

Final Thoughts

It's still possible that VueScan communicates with the scanner directly without the interpreter. I didn't snoop on the USB traffic. I do think that it's unlikely, especially since my previous post showed VueScan is no sharper than just using the SANE API.
Back to index