HotSync'ing and Web Surfing a Palm Tungsten C over USB with a FreeBSD 4.8 Host
Grenville Armitage, December 2003This documentation is largely for my own benefit, although I've written it in the hope it will be useful to others (like you, if you're reading this page and you aren't me).
In December 2003 I purchased a lovely new Palm Tungsten C, an 802.11b-enabled PDA with tiny little keyboard and colour touch screen. When it is in the cradle the USB port can be used to establish a PPP-over-USB session to a FreeBSD host, over which web-surfing and hotsync'ing is possible. However, the scheme described here is not bullet-proof and can easily tickle a kernel panic (at least under FreeBSD 4.8). Use with care.
I've never had a PDA before, and if Palm hadn't released the Tungsten C with in-built 802.11b support I probably still wouldn't. But they did, and we're doing experiments with mobile Internet communucations at the Centre for Advanced Internet Architectures, so I'm now the proud owner. There's only one problem - Windows. Palm supplies software for Windows machines to talk to the Tungsten C, typically over a USB connection to the PDA's cradle. I also (predominantly) use FreeBSD. The challenge.... make my Tungsten C talk to my FreeBSD box over USB when in the cradle!
The Tungsten C runs PalmOS 5.2.1, which enables a variety of network connections (including 802.11b and PPP over modem or USB/serial connection) for web surfing and hotsync'ing. My solution was inspired by a post from David A. Desrosiers to the pilot-link-general mailing list in February 2003. Pilot-link is a software package designed for sync'ing Palm Pilots over USB or network links, and is available as a FreeBSD "Package" (pre-compiled) or "Port" (patched and compiled locally). I made a few changes to David's suggested configuration, hence the need to document them here.
There are four key components to the solution:
The patch needs to be applied in order for FreeBSD's usb subsystem (specifically the uvisor.c driver) to recognize the Palm Tungsten C's vendor code. Once this is done, the usb daemon's configuration file is updated so that ppp is launched on the laptop whenever the Tungsten C establishes its serial-over-USB link.
- Palm Tungsten C (Palm OS 5.2.1)
- Toshiba R100 laptop running FreeBSD 4.8-RELEASE
- A patch to FreeBSD 4.8's usb drivers
- The pilot-link package
In my particular situation I also used the freely available 'tinyproxy' HTTP proxy package on the laptop so that the PDA could surf the web through whatever existing network link the laptop had to the outside world.
Patching the kernel
By default the FreeBSD 4.8-RELEASE GENERIC kernel already includes the following necessary components in the /sys/i386/conf/GENERIC configuration file:
pseudo-device ppp 1 # Kernel PPP
pseudo-device tun # Packet tunnel.
device uhci # UHCI PCI->USB interface
device ohci # OHCI PCI->USB interface
device usb # USB Bus (required)
You must add (if they're not already present) the following two additional entries to your /sys/i386/conf/GENERIC configuration file before rebuilding the kernel:
device uvisor # For Palm->USB interface
device ucom # Generic serial layer
Unfortunately the Tungsten C's product code 0x0060 is not recognized by the FreeBSD 4.8 usb drivers, so we need to patch and rebuild the kernel:
With the kernel patched, plugging the PDA and hitting the HotSync button on the cradle results in the kernel detecting it as:
- Patch /usr/src/sys/dev/usb/usbdevs with this patch file (Use 'save link as' from your browser to copy the patch file, then run "patch < patchfile" from within /usr/src/sys/dev/usb/. If the patch operation fails, try "patch -l < patchfile" instead)
- Patch /usr/src/sys/dev/usb/uvisor.c with this patch file
- In /usr/src/sys/dev/usb/ run "make -f Makefile.usbdevs" (rebuilds the files that usb drivers use for header information)
- Do "cd ../../modules/usb && make" to ensure the new uvisor module compiles okay
- Rebuild kernel to include new uvisor code
- cd /sys/i386/conf/
- config GENERIC (my kernel config file is GENERIC, yours may differ)
- cd ../../compile/GENERIC
- make depend && make && make install
- Reboot FreeBSD host
ucom0: Palm, Inc. Palm Handheld, rev 1.00/1.00, addr 2
(Note that simply plugging the cradle into the FreeBSD host's USB port does not make the PDA appear as a USB device. You must actually trigger a connection from the PDA, either by pressing the cradle's HotSync button or initiating a Network Connection from the PDA itself. This is described below.)
http://wiki.pilot-link.org/index.php/DeviceMatrix shows that vendor 0x0830, product 0x0060 applies to a number of other models including the Tungsten T, T2, T3 and E.
Launching ppp when Palm Tungsten C connects
In order to web-surf and HotSync from the cradled PDA we're going to run PPP over USB/serial connection to the FreeBSD 4.8 host. This requires ppp to be started on the FreeBSD host whenever the PDA is "attached" to the USB port.
First we add the following entry to /etc/usbd.conf and restart the usbd daemon:
device "Palm Handheld Device"
attach "/usr/sbin/ppp -background -unit0 palm"
Restart the daemon with 'kill <pid-of-usbd> && /usr/sbin/usbd'
The above entry ensures that ppp is launched whenever the Tungsten C attaches as a USB device. The ucom0 interface provides an emulated serial-over-USB interface. (/usr/sbin/ppp is launched with "-background" rather than "-auto" to ensure that ppp exits and releases /dev/ucom0 when the PDA shuts down the serial-over-USB link. The "-unit0" ensures ppp launched in this fashion always tries to create interface tun0.)
Then we add the following to /etc/ppp/ppp.conf to create a ppp profile ("system") called "palm" that connects to the PDA over /dev/ucom0:
set device /dev/ucom0
set cd off
set speed 115200
set timeout 0
set ctsrts on
set ifaddr 192.168.200.40 192.168.200.41
add default HISADDR
This configuration ensures that the FreeBSD side of the ppp link never pre-emptively times out the link, nor does it attempt to restart the link if the PDA shuts down the link. (I removed the redial and reconnect lines from David's suggested configuration and set the timeout to 0. Also for some reason my Tungsten C doesn't offer a speed above 115200, so that's what I've set here in the ppp configuration too.)
The two IP addresses are somewhat arbitrarily chosen - as shown above the FreeBSD host is 192.168.200.40 and the PDA will be assigned 192.168.200.41 during the usual ppp link negotiations. These numbers do not have to be related to any other IP addresses the FreeBSD host may have assigned to 'regular' network interfaces (primarily because our goal here is to HotSync between this FreeBSD host and the PDA, and allow the PDA to access a web proxy running on the FreeBSD host).
Getting the Tungsten C's IP link up
The following steps enable the Tungsten C to establish a PPP connection to the FreeBSD host. With the ppp.conf file entry above, the FreeBSD host assigns IP addresses to both ends of the link.
Now tap/press "Connect" from the Preferences->Network page. The PDA will attach itself as a USB device, the FreeBSD host will launch ppp, and the PDA should successfully negotiate the PPP connection with 10 seconds. If everything is successful there will be a new tun0 network interface on the FreeBSD host, like this:
- Under Preferences select Connection, then create a Custom connection that has "Connect to: PC" and "Via: Cradle/Cable".
- Go under Details and select "Speed: 115200 bps" and "Flow Ctl: Automatic"
- Under Preferences select Network, create a New service and select "Connection: Custom" (the new Connection created above)
- Leave "User Name:" blank and "Password: -Prompt-"
- Under Details select "Connection type: PPP", "Idle timeout: 1min", "Query DNS: [ticked]" and "IP Address: Automatic"
- Under Script make sure there's only one entry, "End".
- Under Preferences select VPN and ensure it is Disabled.
tun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1500
inet 192.168.200.40 --> 192.168.200.41 netmask 0xffffffff
Opened by PID 202
At this point you can run ping from the FreeBSD host to verify the IP link to the PDA:
gjatmp-laptop# ping 192.168.200.41
PING 192.168.200.41 (192.168.200.41): 56 data bytes
64 bytes from 192.168.200.41: icmp_seq=0 ttl=255 time=4.431 ms
64 bytes from 192.168.200.41: icmp_seq=1 ttl=255 time=4.554 ms
64 bytes from 192.168.200.41: icmp_seq=2 ttl=255 time=4.369 ms
Tap/press "Disconnect" from the Preferences->Network page and within a few seconds you should see tun0 be disabled and /usr/sbin/ppp disappear from the FreeBSD host's process list. You will also see the following logged to the FreeBSD host's console:
ucom0: ucomreadcb: IOERROR
ucom0: at uhub0 port 2 (addr 2) disconnected
ucom0: still open, forcing close
Doesn't look like a particularly clean exit, but it works none-the-less. Sort of.
Surfing the Web
I didn't want to assign the PDA a properly routable IP address so I run a web proxy on the FreeBSD host. Point the PDA at the proxy, let the proxy reach out to the rest of the world. Fortunately there's a perfectly functional and simple proxy available as a FreeBSD package called 'tinyproxy'. While logged in as root, install tinyproxy with:
pkg_add -r tinyproxy
Running pkg_info confirms "tinyproxy-1.5.0" has been installed. You may find your version is higher. (A similar result should be achieved building from the port with "cd /usr/ports/www/tinyproxy && make install".)
You'll need to add one line to /usr/local/etc/tinyproxy/tinyproxy.conf:
Then just start up tinyproxy as root. (The tinyproxy man page is short because there's really not much you need to know. It works.)
Back on the PDA, call up the web browser. This should trigger the PPP-over-USB connection again (if it has timed out). Select the menu (tap top left of screen), select Options->Preferences->Connecting and select "Use Proxy Server: 192.168.200.40". Select "Done". (Naturally you'd replace 192.168.200.40 with the IP address assigned to the FreeBSD host if you've used different addresses in your /etc/ppp/ppp.conf file.)
Provided that your FreeBSD host itself has working IP connectivity to the rest of the net, your PDA's web browser should now start happily surfing the web!
(In theory I could have turned on NAT in the ppp server and thus enabled IP access from a non-routable IP address without needing a web proxy. I have not tried this approach.)
HotSync'ing with pilot-link
The final piece of this puzzle is hotsync'ing my Tungsten C to my FreeBSD host's filesystem over the PPP-over-USB link. Key to this step is the pilot-link package, also available as a FreeBSD Package. While logged in as root, install pilot-link:
pkg_add -r pilot-link
Running pkg_info reveals that pilot-link-0.11.7_1 is installed. You may find your version is higher. (A similar result should be achieved building from the port with "cd /usr/ports/palm/pilot-link && make install".)
The main tool for doing hotsync's is pilot-xfer. For example, to sync the entire PDA to /tmp/backups you would use:
pilot-xfer -p net:any -b /tmp/backup
This initiates a sync across IP (the "net:any" port looks for available PDAs, you could also use "net:192.168.200.41" to explicitly specify the Tungsten C at the other end of your PPP link).
First, hit the HotSync button/function on your PDA (not on the cradle itself). Then select "Network" hotsync, and specify 192.168.200.40 as the target PC. Start pilot-xfre, then tap the HotSync icon on your PDA (this re-initiates the usb connection, and thus the PPP-over-USB link). Both the PDA and pilot-xfer should announce that synchronization is in progress.
(Note: The pilot-link package includes another application called pi-csd, which calls itself a "Connection Service Daemon for Palm Devices". David's note says it is required, but I was able to use pilot-xfer without running pi-csd. There's almost no documentation about what this app supposedly does. Perhaps it was required by an earlier version of pilot-link, or for versions of PalmOS before 5.x?)
I have not tried using pilot-xfer directly over the ucom0 port, since this would not allow concurrent PPP-over-USB.
There's something in the way that /usr/sbin/ppp interacts with /dev/ucom0 that causes kernel panics. Not when the PPP link is up and operational, but if the USB link goes down first before the PPP session terminates /usr/sbin/ppp can fail to exit after noticing /dev/ucom0 giving wierd errors. This leaves tun0 up, and /usr/sbin/ppp still running, although internally it is in a wierd state. Sending a packet out tun0, or attempting to 'kill -9' the ppp process, can trigger the kernel panic.
Be religious about "disconnecting" the network link from your PDA before anything else happens - this is probably the safest way to avoid confusing /usr/sbin/ppp. This way, ppp itself tidies up and closes before /dev/ucom0 disappears and starts causing errors. Avoid just pulling the PDA from the cradle when the PPP link is up - this will cause the usb device to disappear first, and thus ucom0 disappears with it, leaving /usr/sbin/ppp very confused. Setting the idle timeout on the PDA to 1 minute increases the chances that the PDA's PPP client will have shutdown the session gracefully before you pull the unit out of the cradle.
How much of this is specific to FreeBSD 4.8 I do not know.
With certain caveats (that may be specifically related to FreeBSD 4.8) this report documents a method of establishing PPP-over-USB IP link between a Palm Tungsten C and a FreeBSD 4.8 host. The solution requires two small patches to the FreeBSD 4.8 kernel to enable PPP-over-USB (because the Tungsten C's product code is unknown to FreeBSD 4.8), the pilot-link package to enable network-based hotsync'ing over the PPP link, and optionally a small web proxy (e.g. tinyproxy) on the FreeBSD host to enable web surfing from the PDA while in the cradle.