In the year 2014, I tried to be smart with my old Samsung SCX-3205 printer/scanner device. I wanted to get the physical Scan to -button to work. I went with Windows first. It failed eventually, and as a result, I had to reverse-engineer the Samsung USB protocol to get things to work in Linux.
System-Crashing Samsung Windows Drivers
The whole ruckus started when my father donated me old Samsung SCX-3205 printer/scanner. I researched for a while, but I was unable to get the Scan To -button to work on Linux. After a bit of delicate driver and software gymnastics (see earlier post), I was able to set the device up with a Windows virtual machine. Unfortunately, I started to experience crashes on the virtual machine. It turned out, the Scan To -button driver was allocating new file handles without releasing old ones! As a result, at some point, Windows had tens, if not hundreds of thousands of allocated file handles. In such a situation the system grinds to halt and eventually crashes. I had to abandon the Windows approach and try something else. The crashing is a very severe issue, and I have no idea how the Samsung QA were unable to catch this.
Sniffing the Scan To -Button Protocol
I decided, that if I wrote a driver for the device myself for Linux, it would be less prone to errors. The logical first task was to sniff the needed protocol.
On my laptop, I installed a fresh Windows 7 VMWare virtual machine. Then I connected the printer/scanner USB cable to the laptop and passed it through to the virtual machine. Next, I installed all the necessary Windows drivers and auxiliary software to make the Scan To -button work. Finally, I installed the USBlyzer software from http://www.usblyzer.com/.
I started the capture from the USBlyzer software and toyed around a bit. The UI of the program is very self-explanatory. The USB device hierarchy is shown on left, and data streams on the right. At the bottom, there is data analysis screen. It was fast to get known to USBlyzer and get some actual work going.
Then I actually got to work. I pressed down the physical Scan to -button and then pressed Start on the printer/scanner device. I was met with the familiar Windows dialog box about a scan ongoing.
At the same time, I paid attention to the USBlyzer capture screen. Every time scan started, the executable Scan2Pc.exe was run. This led me to believe that one of the very previous data transfers was triggering the scan.
From the return data can be seen, that when a scan process starts, the 2nd last data position is one instead of zero when compared to return data of a situation where the Scan to -button has not been pressed. The definite conclusion is that the scanning system operates on polling principle. If polled data is found to contain the directive, the separate program (Scan2Pc.exe) starts the scan.
Writing a Program to Read the State on Linux
Try 1: Extend Sane Backends
After having found out about the protocol, next logical step was to write a program to perform the task of reading the Scan to -button state. In the Sane project, there also exists functionality to read the button states. My Samsung SCX-3205 was, of course, unimplemented in this sense in the Sane backends, so I proceeded to try adding my own. The problem became, however, that I was unable to build the Sane project from source codes! Either the build documentation was out-of-date, or I made some errors I overlooked. I tried many times without success, and eventually, I abandoned compiling Sane for this specific purpose.
Try 2: Use Raw libusb Access
I proceeded to take another approach by trying to create a C program directly using the raw libusb access to poll the printer/scanner for data. So, I created the samsungpoll.c. Setting up the necessary USB request was quite easy; I basically just took the data given me by USBlyzer packet capture and added it as definitions to the program. The data is passed to the libusb_control_transfer function, which returns data from the device. This data is searched for the Scan to -button bit. The state of the button is printed out.
For automating the scanning, I created a simple shell script called scanbutton_poller.sh. On my system, the script first uses samsungpoll binary to check, whether the physical Scan to -button has been pressed. If it has, the script creates a name for the file to be scanned, based on date and time. Every year has a dedicated directory. The script then uses the scanimage command from Sane project to scan the document to pnm, and then convert from ImageMagick to transform it to jpg. I run the script periodically from a screen session on my Ubuntu Linux print server virtual machine. I have configured the output destination to be a shared folder on the local network, which I can easily access when I need to get the scans.
I have had tremendous time savings in scanning after I the scanning solution described above. Earlier I needed to log into the system every time I needed a scan, then manually issue the scan and convert commands. Now the scanning is done automatically with the pressing of only two buttons on the printer/scanner device. It also feels that programming with the libusb library on Linux seems to be quite easy even for a beginner, after the necessary USB protocol is figured out, of course!
I have placed all the files created in this project to my GitHub repository, at the location https://github.com/usvi/random/tree/master/c/samsungpoll.