3

I have a USB-CAN adapter called USBtin (http://www.fischl.de/usbtin/). It's connected to a Raspberry Pi 2 running Raspbian (Linux raspberrypi 4.4.16-v7+ #1 SMP Fri Aug 5 14:49:49 UTC 2016 armv7l GNU/Linux).

My goal is to send and receive CAN messages in a Python application. For that I thought using slcan would be a good idea. I compiled slcan-support into the kernel, and to use it I basically followed the Lawicel CANUSB tutorial.

I added 90-slcan.rules to /etc/udev/rules.d/ so it should work with the USBtin:

ACTION=="add", ENV{ID_MODEL}=="USBtin", ENV{SUBSYSTEM}=="tty", \
    RUN+="/usr/bin/logger [udev] USBtin detected - running slcan_add.sh!", \
    RUN+="/usr/local/bin/slcan_add.sh $kernel"

ACTION=="remove", ENV{ID_MODEL}=="USBtin", ENV{SUBSYSTEM}=="usb", \
    RUN+="/usr/bin/logger [udev] USBtin removed - running slcan_remove.sh!", \
    RUN+="/usr/local/bin/slcan_remove.sh"

The add script looks like this:

#!/bin/sh
sleep 7
#slcand -o -c -f -s4 /dev/$1 slcan0
/usr/local/bin/slcand -o -c -f -s4 /dev/$1
logger Return value of slcand was $?
sleep 2
ifconfig slcan0 up

In the syslog I can see that these are executed when I plug-in / remove the adapter. I also see the sys-logging produced by slcand. The last thing I see from the slcand in the syslog is: attached TTY /dev/ttyACM0 to netdevice slcan0 (see below). However, afterwards the daemon is not running and the slcan0 interface is also not there.

If I manually run

sudo /usr/local/bin/slcand -o -c -f -s4 /dev/ttyACM0

on a console though, the daemon runs just fine.

Any idea why it doesn't work when I just plug it in and let udev do it? The code of slcand can be found on GitHub (I'm using the latest version from the trunk).

Syslog:

Feb 12 17:38:28 raspberrypi kernel: [  668.511547] usb 1-1.4: new full-speed USB device number 4 using dwc_otg
Feb 12 17:38:28 raspberrypi kernel: [  668.616867] usb 1-1.4: New USB device found, idVendor=04d8, idProduct=000a
Feb 12 17:38:28 raspberrypi kernel: [  668.616899] usb 1-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=0
Feb 12 17:38:28 raspberrypi kernel: [  668.616916] usb 1-1.4: Product: USBtin
Feb 12 17:38:28 raspberrypi kernel: [  668.616933] usb 1-1.4: Manufacturer: Microchip Technology, Inc.
Feb 12 17:38:28 raspberrypi mtp-probe: checking bus 1, device 4: "/sys/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4"
Feb 12 17:38:28 raspberrypi mtp-probe: bus: 1, device: 4 was not an MTP device
Feb 12 17:38:28 raspberrypi kernel: [  668.671845] cdc_acm 1-1.4:1.0: ttyACM0: USB ACM device
Feb 12 17:38:28 raspberrypi kernel: [  668.673109] usbcore: registered new interface driver cdc_acm
Feb 12 17:38:28 raspberrypi kernel: [  668.673130] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
Feb 12 17:38:28 raspberrypi logger: [udev] USBtin detected - running slcan_add.sh!
Feb 12 17:38:35 raspberrypi slcand[1379]: starting on TTY device /dev/ttyACM0
Feb 12 17:38:35 raspberrypi slcand[1380]: attached TTY /dev/ttyACM0 to netdevice slcan0
Feb 12 17:38:35 raspberrypi logger: Return value of slcand was 0
Feb 12 17:42:29 raspberrypi systemd[1]: Starting Cleanup of Temporary Directories...

This is the output of udevadm info -a -n /dev/ttyACM0:

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/platform/soc/3f980000.usb/usb1/1-1/1-1.4/1-1.4:1.0/tty/ttyACM0':
    KERNEL=="ttyACM0"
    SUBSYSTEM=="tty"
    DRIVER==""

  looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4/1-1.4:1.0':
    KERNELS=="1-1.4:1.0"
    SUBSYSTEMS=="usb"
    DRIVERS=="cdc_acm"
    ATTRS{bInterfaceClass}=="02"
    ATTRS{bmCapabilities}=="2"
    ATTRS{bInterfaceSubClass}=="02"
    ATTRS{bInterfaceProtocol}=="01"
    ATTRS{bNumEndpoints}=="01"
    ATTRS{authorized}=="1"
    ATTRS{supports_autosuspend}=="1"
    ATTRS{bAlternateSetting}==" 0"
    ATTRS{bInterfaceNumber}=="00"

  looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4':
    KERNELS=="1-1.4"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{devpath}=="1.4"
    ATTRS{idVendor}=="04d8"
    ATTRS{speed}=="12"
    ATTRS{bNumInterfaces}==" 2"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bMaxPacketSize0}=="8"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="4"
    ATTRS{configuration}==""
    ATTRS{bMaxPower}=="100mA"
    ATTRS{authorized}=="1"
    ATTRS{bmAttributes}=="80"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{maxchild}=="0"
    ATTRS{bcdDevice}=="0100"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{version}==" 2.00"
    ATTRS{urbnum}=="77"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="Microchip Technology, Inc."
    ATTRS{removable}=="removable"
    ATTRS{idProduct}=="000a"
    ATTRS{bDeviceClass}=="02"
    ATTRS{product}=="USBtin"

  looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1':
    KERNELS=="1-1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="02"
    ATTRS{devpath}=="1"
    ATTRS{idVendor}=="0424"
    ATTRS{speed}=="480"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="2"
    ATTRS{configuration}==""
    ATTRS{bMaxPower}=="2mA"
    ATTRS{authorized}=="1"
    ATTRS{bmAttributes}=="e0"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{maxchild}=="5"
    ATTRS{bcdDevice}=="0200"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{version}==" 2.00"
    ATTRS{urbnum}=="38"
    ATTRS{ltm_capable}=="no"
    ATTRS{removable}=="unknown"
    ATTRS{idProduct}=="9514"
    ATTRS{bDeviceClass}=="09"

  looking at parent device '/devices/platform/soc/3f980000.usb/usb1':
    KERNELS=="usb1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="01"
    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}=="1"
    ATTRS{interface_authorized_default}=="1"
    ATTRS{bcdDevice}=="0404"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{serial}=="3f980000.usb"
    ATTRS{version}==" 2.00"
    ATTRS{urbnum}=="26"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="Linux 4.4.16-v7+ dwc_otg_hcd"
    ATTRS{removable}=="unknown"
    ATTRS{idProduct}=="0002"
    ATTRS{bDeviceClass}=="09"
    ATTRS{product}=="DWC OTG Controller"

  looking at parent device '/devices/platform/soc/3f980000.usb':
    KERNELS=="3f980000.usb"
    SUBSYSTEMS=="platform"
    DRIVERS=="dwc_otg"
    ATTRS{hnp}=="HstNegScs = 0x0"
    ATTRS{srp}=="SesReqScs = 0x1"
    ATTRS{regvalue}=="invalid offset"
    ATTRS{hsic_connect}=="HSIC Connect = 0x1"
    ATTRS{guid}=="GUID = 0x2708a000"
    ATTRS{mode}=="Mode = 0x1"
    ATTRS{srpcapable}=="SRPCapable = 0x1"
    ATTRS{regdump}=="Register Dump"
    ATTRS{gpvndctl}=="GPVNDCTL = 0x00000000"
    ATTRS{ggpio}=="GGPIO = 0x00000000"
    ATTRS{hprt0}=="HPRT0 = 0x00001005"
    ATTRS{wr_reg_test}=="Time to write GNPTXFSIZ reg 10000000 times: 500 msecs (50 jiffies)"
    ATTRS{driver_override}=="(null)"
    ATTRS{hcd_frrem}=="HCD Dump Frame Remaining"
    ATTRS{mode_ch_tim_en}=="Mode Change Ready Timer Enable = 0x0"
    ATTRS{gnptxfsiz}=="GNPTXFSIZ = 0x01000306"
    ATTRS{remote_wakeup}=="Remote Wakeup Sig = 0 Enabled = 0 LPM Remote Wakeup = 0"
    ATTRS{busconnected}=="Bus Connected = 0x1"
    ATTRS{hcddump}=="HCD Dump"
    ATTRS{gotgctl}=="GOTGCTL = 0x001c0001"
    ATTRS{spramdump}=="SPRAM Dump"
    ATTRS{grxfsiz}=="GRXFSIZ = 0x00000306"
    ATTRS{gsnpsid}=="GSNPSID = 0x4f54280a"
    ATTRS{gusbcfg}=="GUSBCFG = 0x20001700"
    ATTRS{hptxfsiz}=="HPTXFSIZ = 0x02000406"
    ATTRS{devspeed}=="Device Speed = 0x0"
    ATTRS{fr_interval}=="Frame Interval = 0x1d4c"
    ATTRS{rem_wakeup_pwrdn}==""
    ATTRS{bussuspend}=="Bus Suspend = 0x0"
    ATTRS{buspower}=="Bus Power = 0x1"
    ATTRS{hnpcapable}=="HNPCapable = 0x1"
    ATTRS{rd_reg_test}=="Time to read GNPTXFSIZ reg 10000000 times: 1410 msecs (141 jiffies)"
    ATTRS{enumspeed}=="Device Enumeration Speed = 0x1"
    ATTRS{inv_sel_hsic}=="Invert Select HSIC = 0x0"
    ATTRS{regoffset}=="0xffffffff"

  looking at parent device '/devices/platform/soc':
    KERNELS=="soc"
    SUBSYSTEMS=="platform"
    DRIVERS==""
    ATTRS{driver_override}=="(null)"

  looking at parent device '/devices/platform':
    KERNELS=="platform"
    SUBSYSTEMS==""
    DRIVERS==""
7
  • 2
    All RUN examples in /lib/udev/rules.d only contain programs that are executed once and then return, so I'm not actually sure if you can spawn demons inside RUN at all (but I don't know). What happens when you schedule the demon with at to run shortly after the udev rule finishes?
    – dirkt
    Feb 15, 2017 at 10:10
  • Thank you for the reply. I don't know much about daemons but when I run slcand on a console it seems to return. I also looked at the code, internally it's calling daemon(0, 0) which according to the man page does The daemon() function is for programs wishing to detach themselves. What do you mean with schedule it to run after the rule with at? Feb 17, 2017 at 10:13
  • Linux has the concept of parent processes and controlling terminals. Udev rules are called from the kernel, and I'm not sure if you can demonize (detach from controlling terminal) a process inside that call when "the kernel" is the parent. There's a program called at which allows you to schedule programs to run at a specific time (see man at). If you do something like echo '/usr/local/bin/slcand -o -c -f -s4 /dev/ttyACM0' | sudo at now + 1 min, then slcand should be called by the atd demon, i.e. outside the udev call. That could solve your problem (or not).
    – dirkt
    Feb 17, 2017 at 10:33
  • I would start your skript over a systemd-unit. can you show sudo udevadmin info -a -n /dev/ttyACM0
    – user192526
    Feb 21, 2017 at 19:51
  • You can find the output attached to my original question Feb 27, 2017 at 14:31

1 Answer 1

0

Apparently it's not possible to start long-running commands via UDEV (at least on raspbian). What works however, is to trigger systemd to start a service from UDEV. The service can then start long-running commands.

In my case I did it with:

ENV{SYSTEMD_WANTS}="can-usb.service"

In the can-usb.service I start the script described before.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .