udev/Palm

We had at least two Linux boxes where JPilot used to work just fine, but it abruptly stopped working on one of them and then later on the other. Trying it on a third system, more recently-installed, gave the same results. These are the steps I took in order to fix the problem. --Woozle (talk) 10:14 11 January 2014 (EST)

Can Device Be Seen on USB?
The Palm can only be seen as a USB device when the "sync" button (on the cradle) is active. When you push it for about a second, it signals the Palm unit to go into USB communication mode. If no communication takes place, this times out after a little bit more than a minute. The Palm should be visible as a USB device for as long as it is displaying the "Connecting with the desktop using Cradle/Cable" screen.

Use lsusb to see if the Palm is visible to the Linux system. It should have "Palm" in the name, e.g.: Bus 001 Device 026: ID 0830:0003 Palm, Inc. m515 The listing shows where it may be found in the /dev directory -- in this case, it will be under /dev/bus/usb/001/026 (the "bus/usb" part may be different for different flavors of Linux).

Is Symlink Being Created?
JPilot apparently expects to see a symbolic link, called /dev/pilot, to wherever the device actually is (e.g. in this case, it would link to /dev/bus/usb/001/026). If that is not being created, then udev is not configured properly. (This seems to have been the case on our systems.)

Note that the USB path changes every time you activate the sync button (on my system, it increments by one), so you can't just create a symlink by hand and be done with it; it needs to be done automatically when the Palm appears on the USB listing. This is udev's job.

What Is the Device's System Path?
In order to do any further debugging, you need to know the device's system name (i.e. where it is under the /sys directory). Assuming your device is found at /dev/bus/usb/001/018, this command will return that information:

sudo udevadm info -q path -n /dev/bus/usb/001/018

In my case, this returned: /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1.2

Unlike the USB path, this path appears to be persistent, so you should only need to look it up once while debugging. (I'm not sure what determines it; it may change depending on which USB port the Palm is plugged into.)

Is The Appropriate Rule Being Used?
The following command supposedly simulates what udev would do without actually doing it (although I've found that it will create symlinks if the rule says to do so). This will will tell you which udev rules are being followed. It will also tell you if it ignored any of them because of syntactical problems.

sudo udevadm test /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1.2

All of the rules under /lib/udev/rules.d/ are loaded, but only some are actually triggered. You can see which ones by looking for "udev_rules_apply_to_event" in the output (there's probably a grep command to do this, but I couldn't figure it out).

There is a set of rules for Palm devices in /lib/udev/rules.d/40-libpisock9.rules. In my case, it was triggering one of them, along with rules from a number of other .rules files:

udev_rules_apply_to_event: RUN '/usr/share/virtualbox/VBoxCreateUSBNode.sh $major $minor $attr{bDeviceClass}' /etc/udev/rules.d/10-vboxdrv.rules:4 udev_rules_apply_to_event: IMPORT builtin 'usb_id' /lib/udev/rules.d/40-libgphoto2-2.rules:11 udev_rules_apply_to_event: GROUP 20 /lib/udev/rules.d/40-libpisock9.rules:27 udev_rules_apply_to_event: MODE 0664 /lib/udev/rules.d/40-libpisock9.rules:27 udev_rules_apply_to_event: MODE 0664 /lib/udev/rules.d/50-udev-default.rules:55 udev_rules_apply_to_event: IMPORT builtin skip 'usb_id' /lib/udev/rules.d/50-udev-default.rules:56 udev_rules_apply_to_event: PROGRAM 'mtp-probe /sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1.2 1 29' /lib/udev/rules.d/69-libmtp.rules:971

I noticed the attempt to invoke mtp-probe in the last line. There is no manpage for this program, but it is apparently part of the libmtp-runtime package (which is, in fact, installed on my system; the mtp-probe executable is in /lib/udev/mtp-probe). There was no indication of any problem with mtp-probe, so I assumed it was working properly.

In any case, none of these rules were creating the /dev/pilot symlink. Following suggestions on the web (all of them quite old), I tried adding this rule:

BUS=="usb", SYSFS{product}=="Palm Handheld*", KERNEL=="ttyUSB[13579]", SYMLINK+="pilot"

However, udevadm test objected to the "SYSFS{product}" and "KERNEL" rules, saying that those values were not found. Next, then, I needed to figure out what actual values (device parameters) were available to use as triggers.

What Are the Device Parameters?
The command to list all device parameters turns out to be, in my case:

sudo udevadm info -a -p /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1.2

This returned the following: Udevadm info starts with the device specified by the devpath and then walks up the chain of parent devices. It prints for every device found, all possible attributes in the udev rules key format. A rule to match, can be composed by the attributes of the device and the attributes from one single parent device. looking at device '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1.2': KERNEL=="1-1.1.2" SUBSYSTEM=="usb" DRIVER=="usb" ATTR{bDeviceSubClass}=="00" ATTR{bDeviceProtocol}=="00" ATTR{devpath}=="1.1.2" ATTR{idVendor}=="0830" ATTR{speed}=="12" ATTR{bNumInterfaces}==" 1" ATTR{bConfigurationValue}=="1" ATTR{bMaxPacketSize0}=="16" ATTR{busnum}=="1" ATTR{devnum}=="30" ATTR{configuration}=="" ATTR{bMaxPower}==" 2mA" ATTR{authorized}=="1" ATTR{bmAttributes}=="c0" ATTR{bNumConfigurations}=="1" ATTR{maxchild}=="0" ATTR{bcdDevice}=="0100" ATTR{avoid_reset_quirk}=="0" ATTR{quirks}=="0x0" ATTR{serial}=="00TAP6F2A0RX" ATTR{version}==" 1.00" ATTR{urbnum}=="10" ATTR{manufacturer}=="Palm, Inc." ATTR{removable}=="unknown" ATTR{idProduct}=="0003" ATTR{bDeviceClass}=="00" ATTR{product}=="Palm Handheld " looking at parent device '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1': KERNELS=="1-1.1" SUBSYSTEMS=="usb" DRIVERS=="usb" ATTRS{bDeviceSubClass}=="00" ATTRS{bDeviceProtocol}=="00" ATTRS{devpath}=="1.1" ATTRS{idVendor}=="05e3" ATTRS{speed}=="12" ATTRS{bNumInterfaces}==" 1" ATTRS{bConfigurationValue}=="1" ATTRS{bMaxPacketSize0}=="64" ATTRS{busnum}=="1" ATTRS{devnum}=="3" ATTRS{configuration}=="" ATTRS{bMaxPower}=="100mA" ATTRS{authorized}=="1" ATTRS{bmAttributes}=="e0" ATTRS{bNumConfigurations}=="1" ATTRS{maxchild}=="4" ATTRS{bcdDevice}=="0901" ATTRS{avoid_reset_quirk}=="0" ATTRS{quirks}=="0x0" ATTRS{version}==" 2.00" ATTRS{urbnum}=="1558734" ATTRS{removable}=="removable" ATTRS{idProduct}=="0608" ATTRS{bDeviceClass}=="09" ATTRS{product}=="USB2.0 Hub" looking at parent device '/devices/pci0000:00/0000:00:1a.0/usb1/1-1': KERNELS=="1-1" SUBSYSTEMS=="usb" DRIVERS=="usb" ATTRS{bDeviceSubClass}=="00" ATTRS{bDeviceProtocol}=="01" ATTRS{devpath}=="1" ATTRS{idVendor}=="8087" ATTRS{speed}=="480" ATTRS{bNumInterfaces}==" 1" ATTRS{bConfigurationValue}=="1" ATTRS{bMaxPacketSize0}=="64" ATTRS{busnum}=="1" ATTRS{devnum}=="2" ATTRS{configuration}=="" ATTRS{bMaxPower}==" 0mA" ATTRS{authorized}=="1" ATTRS{bmAttributes}=="e0" ATTRS{bNumConfigurations}=="1" ATTRS{maxchild}=="4" ATTRS{bcdDevice}=="0000" ATTRS{avoid_reset_quirk}=="0" ATTRS{quirks}=="0x0" ATTRS{version}==" 2.00" ATTRS{urbnum}=="102" ATTRS{removable}=="fixed" ATTRS{idProduct}=="0024" ATTRS{bDeviceClass}=="09" looking at parent device '/devices/pci0000:00/0000:00:1a.0/usb1': KERNELS=="usb1" SUBSYSTEMS=="usb" DRIVERS=="usb" ATTRS{bDeviceSubClass}=="00" ATTRS{bDeviceProtocol}=="00" ATTRS{devpath}=="0" ATTRS{idVendor}=="1d6b" ATTRS{speed}=="480" ATTRS{bNumInterfaces}==" 1" ATTRS{bConfigurationValue}=="1" ATTRS{bMaxPacketSize0}=="64" ATTRS{authorized_default}=="1" ATTRS{busnum}=="1" ATTRS{devnum}=="1" ATTRS{configuration}=="" ATTRS{bMaxPower}==" 0mA" ATTRS{authorized}=="1" ATTRS{bmAttributes}=="e0" ATTRS{bNumConfigurations}=="1" ATTRS{maxchild}=="2" ATTRS{bcdDevice}=="0305" ATTRS{avoid_reset_quirk}=="0" ATTRS{quirks}=="0x0" ATTRS{serial}=="0000:00:1a.0" ATTRS{version}==" 2.00" ATTRS{urbnum}=="24" ATTRS{manufacturer}=="Linux 3.5.0-43-generic ehci_hcd" ATTRS{removable}=="unknown" ATTRS{idProduct}=="0002" ATTRS{bDeviceClass}=="09" ATTRS{product}=="EHCI Host Controller" looking at parent device '/devices/pci0000:00/0000:00:1a.0': KERNELS=="0000:00:1a.0" SUBSYSTEMS=="pci" DRIVERS=="ehci_hcd" ATTRS{irq}=="16" ATTRS{subsystem_vendor}=="0x8086" ATTRS{broken_parity_status}=="0" ATTRS{class}=="0x0c0320" ATTRS{companion}=="" ATTRS{consistent_dma_mask_bits}=="32" ATTRS{dma_mask_bits}=="32" ATTRS{local_cpus}=="00000000,00000000,00000000,00000000,00000000,00000000,00000000,0000000f" ATTRS{device}=="0x1c2d" ATTRS{uframe_periodic_max}=="100" ATTRS{enable}=="1" ATTRS{msi_bus}=="" ATTRS{local_cpulist}=="0-3" ATTRS{vendor}=="0x8086" ATTRS{subsystem_device}=="0x200c" ATTRS{numa_node}=="-1" looking at parent device '/devices/pci0000:00': KERNELS=="pci0000:00" SUBSYSTEMS=="" DRIVERS==""

Based on this, I replaced "BUS" with "SUBSYSTEM" and "SYSFS{product}" with "ATTR{product}", and removed "KERNEL" (This page explains the special circumstance under which the KERNEL filter was needed). The result was this rule: SUBSYSTEM=="usb", ATTR{product}=="Palm Handheld*", SYMLINK+="pilot"

This now creates the /dev/pilot symlink when the sync button is pressed, but JPilot is still unable to connect.

Are You a Member of the Right Group?
On my system, /dev/bus/usb/... was set as writable only by root and the group "dialout". Some of the documentation gives this group as "dialup", so you should probably check to make sure which group has write access -- and then make sure you are a member of that group. Note that group memberships often do not seem to take effect until you log in again, which can be awkward; "ssh -X localhost" and then "groups" is one brute-force way to make sure you have the latest permissions changes. From there you can run jpilot with those permissions, even if they might not apply when it is run from the regular GUI menu.

Have You Waved the Rubber Chicken?
There are two things that are poorly documented, so I don't know why they are necessary:
 * 1) In JPilot's "Preferences" dialog, under the "Settings" tab, the "Sync port" should be set to "USB:" -- not "/dev/pilot". (I was never able to get the latter to work; see "Notes" below.)
 * 2) Start the sync operation in JPilot first, and then press the sync button on the Palm's cradle. Otherwise JPilot just sits there forever. I'm guessing that it's looking for a newly-created symlink; if the symlink is already there, it doesn't detect it.