Sunday, February 15, 2015

Improving FabulaTech USB over Network

I've been looking for a solution to share a USB device over the network for years. Unfortunately, as of today, no viable opensource solution exists. usbip is supposed to be that solution, but it's broken and I never managed to make it work on Ubuntu, despite the program being available in universe. The installation on Windows is a very tedious process, even more complicated IMO than the procedure below.

There are however commercial solutions. One of them is Fabulatech USB over Network. It will work on Windows, Mac and Linux.

On Linux, there is no graphical user interface, and they don't provide anything that would make our lives easier. Only a server program and a client program that can be invoked from the command-line.
That's why we'll have to write a daemon and a script to automatically share some devices after they are plugged in.

Step 0 : Unzip the Linux tarball somewhere

Let's say this somewhere is /opt/ftusbnet.

Step 1: Start the daemon (ftusbnetd) at boot

Install supervisord: sudo apt-get install supervisor

Write a configuration file for supervisor by editing /etc/supervisor/conf.d/ftusbnetd.conf:

[program:ftusbnetd]
command=/opt/ftusbnet/sbin/ftusbnetd
autostart=true
autorestart=unexpected

Restart supervisord: sudo service supervisor restart
(You can use supervisorctl if you don't want to restart all the running services.)

If you have never used supervisor before, you really should. Regular init scripts are still useful, but most of the time supervisor does the job much better, with only two lines.

UPDATE: supervisor 3.0b2-1 distributed with Ubuntu 14.04.1 LTS has a little bug. It won't start, after complaining that /var/log/supervisor doesn't exist.
You can either change the line childlogdir=/var/log/supervisor in /etc/supervisor/supervisord.conf, or create the directory before starting supervisord by modifying /etc/init.d/supervisor and adding the line mkdir /var/log/supervisor after case "$1" in start)

Step 2: Run a script when a USB device is connected

Read the previous blog post.
Let's assume the "add" script is /opt/ftusbnet/bin/udev-connect.

Usually, to share a device you would issue the ftusbnetctl command like this:
ftusbnetctl share 1234, where 1234 is an ID generated by ftusbnet and that even changes each time you plug the device.
It would be nice if we could tell udev to run a script only after ftusbnetctl "sees" the USB device. Unfortunately we can't do that. The device won't be accessible until udev has run all the scripts we told him to run. We can't just "sleep" or start a background process. 

The only workaround I found is to run the script 1 to 60 seconds after the USB device is processed by udev. So yes: You might have to wait up to a minute before the device is shared. 
For this we will use the at utility. Unfortunately, at is an old UNIX tool and it only works with minutes, days, and weeks. Tell me if you find a better solution!

/opt/ftusbnet/bin/udev-connect contains this:

#!/bin/sh
echo "/opt/ftusbnet/bin/scansnap-connect" | at 'now + 1 minute'

In my case I am connecting a device that is shown as "ScanSnap" when executing ftusbnetctl list.
Make sure the script is executable.

Step 3: (Cont'd)

Here is the content of /opt/ftusbnet/bin/scansnap-connect:

#!/bin/sh

ftusbclient=/opt/ftusbnet/bin/ftusbnetctl

while ! $ftusbclient list | grep ScanSnap
do  
    sleep 1
done
sleep 1

ftid=$( ${ftusbclient} list | grep ScanSnap | awk '{print $1;}' )
logger -t ftusbnet-udev "Sharing device ID $ftid"
$ftusbclient share $ftid

Make sure the script is executable.

The before-last line will print a message in the syslog. If all you never see the line or the ID is truncated, you have a problem.

No comments:

Post a Comment