feat: CANable 2.0 bringup with udev rule and systemd service (Issue #643)

- udev: 70-canable.rules — gs_usb VID/PID 1d50:606f, names iface can0 and brings it up at 500 kbps on plug-in
- systemd: can-bringup.service — oneshot service bound to sys-subsystem-net-devices-can0.device
- scripts: can_setup.sh — manual up/down/verify helper; candump verify for VESC IDs 61 (0x3D) and 79 (0x4F)
- install_systemd.sh updated to install can-bringup.service and all udev rules

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
sl-jetson 2026-03-17 09:49:21 -04:00
parent 0fcad75cb4
commit a506989af6
4 changed files with 110 additions and 0 deletions

View File

@ -0,0 +1,21 @@
[Unit]
Description=CANable 2.0 CAN bus bringup (can0, 500 kbps)
Documentation=https://gitea.vayrette.com/seb/saltylab-firmware/issues/643
# Wait until the gs_usb net device appears; udev fires After=sys-subsystem-net-devices-can0.device
After=network.target sys-subsystem-net-devices-can0.device
Requires=sys-subsystem-net-devices-can0.device
BindsTo=sys-subsystem-net-devices-can0.device
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/ip link set can0 up type can bitrate 500000
ExecStop=/usr/sbin/ip link set can0 down
StandardOutput=journal
StandardError=journal
SyslogIdentifier=can-bringup
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,19 @@
# CANable 2.0 USB-CAN adapter (gs_usb driver)
# Exposes the adapter as can0 via the SocketCAN subsystem.
# Issue: https://gitea.vayrette.com/seb/saltylab-firmware/issues/643
#
# Install:
# sudo cp 70-canable.rules /etc/udev/rules.d/
# sudo udevadm control --reload && sudo udevadm trigger
#
# CANable 2.0 USB IDs (Geschwister Schneider / candleLight firmware):
# idVendor = 1d50 (OpenMoko)
# idProduct = 606f (candleLight / gs_usb)
#
# Verify with: lsusb | grep -i candl
# ip link show can0
SUBSYSTEM=="net", ACTION=="add", \
ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="606f", \
NAME="can0", \
RUN+="/sbin/ip link set can0 up type can bitrate 500000"

52
jetson/scripts/can_setup.sh Executable file
View File

@ -0,0 +1,52 @@
#!/usr/bin/env bash
# can_setup.sh — Bring up CANable 2.0 (gs_usb) as can0 at 500 kbps
# Issue: https://gitea.vayrette.com/seb/saltylab-firmware/issues/643
#
# Usage:
# sudo ./can_setup.sh # bring up
# sudo ./can_setup.sh down # bring down
# sudo ./can_setup.sh verify # candump one-shot check (Ctrl-C to stop)
#
# VESCs on bus: CAN ID 61 (0x3D) and CAN ID 79 (0x4F), 500 kbps
set -euo pipefail
IFACE="${CAN_IFACE:-can0}"
BITRATE="${CAN_BITRATE:-500000}"
log() { echo "[can_setup] $*"; }
die() { echo "[can_setup] ERROR: $*" >&2; exit 1; }
cmd="${1:-up}"
case "$cmd" in
up)
# Verify the interface exists (gs_usb module loaded by kernel on plug-in)
if ! ip link show "$IFACE" &>/dev/null; then
die "$IFACE not found — is CANable 2.0 plugged in and gs_usb loaded?"
fi
log "Bringing up $IFACE at ${BITRATE} bps..."
ip link set "$IFACE" down 2>/dev/null || true
ip link set "$IFACE" up type can bitrate "$BITRATE"
ip link set "$IFACE" up
log "$IFACE is up."
ip -details link show "$IFACE"
;;
down)
log "Bringing down $IFACE..."
ip link set "$IFACE" down
log "$IFACE is down."
;;
verify)
log "Listening on $IFACE — expecting frames from VESC IDs 0x3D (61) and 0x4F (79)"
log "Press Ctrl-C to stop."
exec candump "$IFACE"
;;
*)
echo "Usage: $0 [up|down|verify]"
exit 1
;;
esac

View File

@ -7,6 +7,9 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_DIR="$(dirname "${SCRIPT_DIR}")"
SYSTEMD_DIR="/etc/systemd/system"
DEPLOY_DIR="/opt/saltybot/jetson"
UDEV_DIR="/etc/udev/rules.d"
BRINGUP_SYSTEMD="${REPO_DIR}/ros2_ws/src/saltybot_bringup/systemd"
BRINGUP_UDEV="${REPO_DIR}/ros2_ws/src/saltybot_bringup/udev"
log() { echo "[install_systemd] $*"; }
@ -23,15 +26,30 @@ log "Installing systemd units..."
cp "${SCRIPT_DIR}/saltybot.target" "${SYSTEMD_DIR}/"
cp "${SCRIPT_DIR}/saltybot-social.service" "${SYSTEMD_DIR}/"
cp "${SCRIPT_DIR}/tailscale-vpn.service" "${SYSTEMD_DIR}/"
cp "${BRINGUP_SYSTEMD}/can-bringup.service" "${SYSTEMD_DIR}/"
# Install udev rules
log "Installing udev rules..."
mkdir -p "${UDEV_DIR}"
cp "${BRINGUP_UDEV}/70-canable.rules" "${UDEV_DIR}/"
cp "${BRINGUP_UDEV}/90-magedok-touch.rules" "${UDEV_DIR}/"
udevadm control --reload
udevadm trigger --subsystem-match=net --action=add
# Reload and enable
systemctl daemon-reload
systemctl enable saltybot.target
systemctl enable saltybot-social.service
systemctl enable tailscale-vpn.service
systemctl enable can-bringup.service
log "Services installed. Start with:"
log " systemctl start saltybot-social"
log " systemctl start tailscale-vpn"
log " systemctl start can-bringup"
log " journalctl -fu saltybot-social"
log " journalctl -fu tailscale-vpn"
log " journalctl -fu can-bringup"
log ""
log "Verify CAN bus: candump can0"
log " VESC CAN IDs: 61 (0x3D) and 79 (0x4F)"