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==""
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 insideRUN
at all (but I don't know). What happens when you schedule the demon withat
to run shortly after the udev rule finishes?daemon(0, 0)
which according to the man page doesThe daemon() function is for programs wishing to detach themselves
. What do you mean with schedule it to run after the rule withat
?at
which allows you to schedule programs to run at a specific time (seeman at
). If you do something likeecho '/usr/local/bin/slcand -o -c -f -s4 /dev/ttyACM0' | sudo at now + 1 min
, thenslcand
should be called by theatd
demon, i.e. outside the udev call. That could solve your problem (or not).sudo udevadmin info -a -n /dev/ttyACM0