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.
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/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
/usr/var/lib/iscan/interpreter config file.
$ strace -P /usr/lib/sane/libsane-epkowa.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).
$ strace -P /usr/lib/iscan/libiscan-plugin-perfection-v550.so ./vuescan
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.
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
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.
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?