USB LIN Converter

io.github.Lukasz-Juranek由 GitHub 账号 Lukasz-Juranek 发布v0.1.2更新于 Nov 7, 2026

嗅探并逆向工程汽车的LIN总线:捕获、变化位、速度检测、LDF解码

AI 翻译由 AI 模型根据下方的原文描述翻译,可能有误。

原文描述

Sniff and reverse-engineer a car's LIN bus: capture, changing bits, speed detect, LDF decode

已验证STDIO仅桌面开发者工具数据与分析

概览

USB LIN Converter 的本地 MCP 服务;无需登录;STDIO;9 个工具。

暂无 AI 概览:以下信息来自注册中心条目和服务本身。

安装

在 SourceWeft 中

  1. 打开 控制台中的 USB LIN Converter,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

README

USB LIN Converter (uLC)

[Buy on Tindie] [Buy on Lectronz] [Product page]

Open source USB ↔ LIN bus dongle. LIN 2.1 master, slave or monitor. SLCAN-compatible virtual COM port - works on Windows, Linux and macOS with no proprietary drivers.

[USB LIN Converter (uLC) - dongle photo]

The USB LIN Converter (uLC) is a small open-source USB dongle (STM32F042C6, ~31 × 18 mm) that lets a PC act as a LIN bus master, slave or passive monitor. It enumerates as a USB CDC virtual COM port and speaks an SLCAN-style ASCII protocol, so it bridges into Linux SocketCAN via slcand and works with parts of can-utils.

A commercial automotive LIN analyzer typically costs hundreds to thousands of euros. This one is around $27 on Tindie.

The LIN protocol implementation is based on openLIN.


Features

  • LIN 2.1 support
  • Monitor mode - full frame reception plus single-frame transmission
  • Master mode - up to 16 scheduled frame slots
  • Slave mode - up to 16 scheduled frame slots for slave simulation
  • 9600 / 19200 baud rate selection
  • Optical isolation between LIN and the USB / PC side
  • Software-controlled termination resistors
  • External 4.5 - 28 V powers the LIN transceiver
  • Device size 31 × 18 mm (without USB connector)
  • USB DFU bootloader for firmware updates
  • No proprietary drivers - Linux / macOS / Windows
  • MCP server so AI agents can sniff and reverse-engineer a LIN bus (see below)

Where to buy


Quickstart

  1. Plug the device into a USB port. It enumerates as a virtual COM port (COM3 on Windows, /dev/ttyACM0 on Linux, /dev/cu.usbmodem* on macOS).
  2. No driver is needed on Windows 10/11, Linux or macOS: the built-in USB CDC driver is used. Since firmware 3.5 the device has its own USB ID from pid.codes, 1209:2779; older firmware used ST's generic 0483:5740 (on Windows 7/8 that needs the ST Virtual COM Port driver).
  3. Open the port at any baud rate (USB CDC ignores baud). Line ending must be CR (0x0D).
  4. Power the LIN side with 4.5 - 28 V on the external supply pin.
  5. Send S0 to select 19200 baud, then l to enter monitor mode. Bus traffic will start to appear.

Linux SocketCAN bridge

bash
sudo slcand -o -s8 -t hw -S 921600 /dev/ttyACM0 slcan0sudo ip link set slcan0 upcandump slcan0

Python (pyserial) sniff snippet

python
import serialser = serial.Serial('/dev/ttyACM0', timeout=1)ser.write(b'S0\r')   # 19200 baudser.write(b'l\r')    # monitor modewhile True:    line = ser.readline()    if line:        print(line.decode(errors='replace').strip())

A higher-level Python library is provided in python_lib/ (package ucanlintools).

AI agents (MCP server)

python_lib/ucanlintools/mcp_server.py is an MCP server that lets an AI agent sniff and reverse-engineer a LIN bus: capture traffic with per-id periods and changing bits, log every data change while you press a button, find the bus speed and checksum type automatically, and decode or encode signals from an LDF file. It is read-only by default; sending frames and acting as master or slave needs --allow-transmit.

bash
uvx ucan-lin-mcp --mock             # from PyPI, no install step (Python 3.10+)# or from this repo: pip install -e "python_lib[mcp]" && ucanlin-mcp --mock

Register it with any MCP client as a stdio server:

json
{  "mcpServers": {    "lin": {"command": "uvx", "args": ["ucan-lin-mcp", "--port", "COM3"]}  }}

--mock runs a simulated bus. mcp_package/ is the ucan-lin-mcp launcher package and server.json its MCP Registry entry.

Tools: device_info, monitor_bus, detect_bus, load_ldf, decode_frame, encode_frame, and with --allow-transmit also send_frame, run_master, run_slave.


ASCII command reference

All commands are ASCII terminated with CR (0x0D). Errors return 0x07 (BEL).

CommandDescription
OOpen in master mode
LOpen in slave mode
lOpen in monitor mode
CClose LIN port
SxBaud: S2 = 9600, others = 19200
V / v / NHardware / firmware version / serial number query
tiiildd...Transmit full header + data frame (id, length, data)
r0iilHeader only request (slave answers)
r1ff0Master mode: start sending frames from schedule table
r2ff0Clear schedule table
r31 / r30Checksum for all frames: r31 classic (LIN 1.x), r30 enhanced (LIN 2.x, default). Diagnostic frames 0x3C/0x3D always use classic. Replies Z. Kept until power off; t31/t30 work too.
t04bbbbCustom LIN baud rate, bbbb = 4 hex digits (e.g. t0428B1 = 10417 baud). Send before adding frames. Replies Z.
T0iipptt0ldd... / R0iipptt0lFrame with explicit delay pp and response wait time tt (ms, hex), e.g. T00A643001A5. pp is the time from the start of the previous slot's header to this slot's header (firmware 3.4 and later; older firmware started it when the previous frame ended).
Commands are executed one at a time: wait for the reply (CR, z/Z or BEL) before sending the next one.

Full command reference and examples: https://ucandevices.github.io/ulc.html


Repository layout

DirectoryContents
embedded/STM32F042C6 firmware sources (STM32CubeMX project LUCEmbedded.ioc, Atollic TrueSTUDIO project under embedded/TrueSTUDIO/). USB layer generated with STM32CubeMX.
pcb/Open-hardware KiCad project for the LIN_USB_CONVERTER board, Gerbers and 1-click BOM.
python_lib/ucanlintools Python package with high-level master / slave / monitor helpers and examples.
doc/LIN 2.2A specification, MCU datasheet, LIN transceiver datasheet and supporting documents.

Build

Source is pure C. Import the Eclipse project in embedded/TrueSTUDIO/LUCEmbedded into STM32CubeIDE (tested with 1.19) and build the Debug configuration; the image is Debug/LUCEmbedded.bin. The openLIN stack is vendored in embedded/Src (open_lin_*.c/h, implementation/ST32). The USB CDC layer was generated with STM32CubeMX from embedded/LUCEmbedded.ioc.

Bootloader

The STM32F042 has an embedded ROM USB DFU bootloader. To enter it from a running device send boot\r over the virtual COM port. See this tutorial for the flashing flow.

With STM32CubeProgrammer installed, the flashing can be scripted:

bash
python -c "import serial; serial.Serial('COM3').write(b'boot\r')"STM32_Programmer_CLI -c port=usb1 -w LUC_0307.bin 0x08000000 -v -g 0x08000000

Testing

The test suite lives in python_lib/tests (pytest). It covers the firmware and the ucanlintools library:

FileHardwareWhat it tests
test_ldf_parser.py, test_linframe.py, test_luc_encoding.pynoneLDF parsing, signal encode/decode, frame formatting
test_luc_hardware.py1-2 donglesLibrary: version query, mode switching, monitor loopback, master → slave
test_firmware_protocol.py1-2 donglesFirmware over raw serial: malformed-command rejection, 16-row table limit, all frame lengths 1-8 in both directions with exact data check, live data update, diagnostic frames 0x3C/0x3D, unanswered headers, extended T/R row timing, custom baud rate, monitor reception and monitor transmit. Parametrized for 19200 and 9600 baud.
test_lib_simulation.py2 donglesScripted MasterSimulation.py / SlaveSimulation.py: LDF-encoded master frame, slave response, both changing at runtime, at both speeds

Setup: two converters on one LIN bus (LIN pins connected, external LIN supply applied). LUC_MASTER_PORT is used as LIN master, LUC_SLAVE_PORT as slave / monitor. Tests skip automatically when a port can't be opened, so the offline tests always run.

bash
cd python_libpip install pyserial lark pytestLUC_MASTER_PORT=COM3 LUC_SLAVE_PORT=COM56 PYTHONPATH=. pytest tests -v# swap the ports and run again to test each converter in both rolesLUC_MASTER_PORT=COM56 LUC_SLAVE_PORT=COM3 PYTHONPATH=. pytest tests -v

On Windows PowerShell set the variables with $env:LUC_MASTER_PORT="COM3" etc.

How firmware 3.7 was tested

  • Same setup, both converters flashed with LUC_0307.bin.
  • Slave fix traced byte by byte with a diagnostic build: when the slave subscribed a frame nobody answered, the next header's break byte was counted as that frame's data, and the stale count made the slave take the following frame's last data byte as its checksum and drop it. With the fix the slave receives every following frame (23 of 23 in 1.5 s, before 0).
  • New regression test test_slave_subscribed_to_unanswered_header_keeps_next_frame; full suite run twice with the roles swapped: 65/65 passed in each direction.

How firmware 3.6 was tested

  • Same setup, both converters flashed with LUC_0306.bin.
  • Clock recovery checked with a test-only build that reported the CRS registers: the CRS synchronised to the USB SOF within the first seconds (SYNCOK set, no errors afterwards) and moved the HSI48 trim from 32 to 35 on one converter, i.e. that converter's clock ran measurably slow without it.
  • Full suite run twice with the roles swapped: 63/63 passed in each direction; master slot periods unchanged from 3.4 (within about 1 ms of the configured delay).

How firmware 3.5 was tested

  • Same setup, both converters flashed with LUC_0305.bin. They enumerate as 1209:2779 and Windows 10 loads its built-in CDC driver without any installation.
  • Full suite run twice with the roles swapped: 55/55 passed in each direction. Firmware 3.5 changes only the USB ID, the LIN code is the same as 3.4.

How firmware 3.4 was tested

  • Two uLC converters (hardware V0001), both flashed with LUC_0304.bin, connected on one powered LIN bus.
  • Full suite run twice with the roles swapped: 55/55 passed in each direction (110 test runs).
  • Master slot timing measured with the second converter as monitor (3 s window, 19200 baud): the slot period now matches the configured delay within about 1 ms for 0, 2, 4 and 8 data bytes, for 10, 20 and 40 ms delays, and for unanswered subscriber slots. Firmware 3.3 added the frame time to every slot (+2 to +6 ms) and the full response timeout to unanswered subscriber slots (+12 ms).

How firmware 3.3 was tested

  • Two uLC converters (hardware V0001), both flashed with LUC_0303.bin, connected on one powered LIN bus.
  • Full suite run twice with the roles swapped: 47/47 passed in each direction (94 test runs).
  • Bus throughput measured during testing (4 s window, 16-frame schedule): every frame scheduled 12-14 times at 19200 baud and 10-11 times at 9600 baud, no lost or corrupted frames, no unexpected serial output.
  • The bugs fixed in 3.3 each have a regression test: malformed row locking the table, slave mode stalling after the first response at 9600 baud, slave mode not answering at all, master not reporting slave responses, 6-8 byte responses timing out at 9600 baud, and the classic checksum setting being ignored. The checksum tests were also run against the previous firmware and fail there, as expected.

FAQ

What is the cheapest USB LIN bus converter that works on Linux? The uCanDevices USB LIN Converter (uLC) is an open source dongle around $27 that enumerates as a USB CDC virtual COM port on Linux, macOS and Windows. It uses an SLCAN-style ASCII protocol so it bridges into SocketCAN via slcand.

Does it support master and slave mode? Yes - monitor (full reception plus single-frame transmission), master (up to 16 scheduled slots) and slave (up to 16 slots for slave simulation). Modes are selected with the O, L and l commands.

Is the LIN side optically isolated from the USB host? Yes. The LIN transceiver is optically isolated from the PC side, protecting the host from automotive transients. The LIN side needs an external 4.5 - 28 V supply since USB only powers the MCU.

Which LIN baud rates and LIN version are supported? LIN 2.1, with selectable 9600 and 19200 baud. Classic and enhanced checksum are switchable with the r31 / r30 commands (firmware 3.3 and later). Custom frame timing is supported in master mode.

Can I use it to flash an ECU over LIN? It is a generic LIN interface. ECU flashing depends entirely on the target ECU's own LIN bootloader; if that bootloader is documented or already supported by an existing tool, you can drive it through this dongle.

Is the firmware open source? Yes - this repository contains firmware (embedded/), hardware (pcb/) and the Python helper library (python_lib/). The device also has a USB DFU bootloader for in-field updates.


Related projects

Links

License

See LICENSE.

来源:README.md,提交 8d05ae5

工具

9

device_info

Converter port, firmware version, whether transmitting is allowed, and the loaded LDF (if any).

无需输入参数。

monitor_bus

Listen to the bus passively and summarize what is on it. Per frame id: count, period, last data, how many distinct values were seen and changing_bits (a per-byte mask of bits that changed). 'changes' lists every data change in time order, so asking the user to press a button during the capture shows which id and bit it drives. speed: 19200 (most cars), 10417 or 9600. checksum: 'enhanced' (LIN 2.x) or 'classic' (LIN 1.x); frames with the other checksum are dropped by the converter. ids: optional filter, e.g. ["0x0C"].

输入参数idsspeedchecksumduration_s

detect_bus

Try every speed and checksum combination and report which one sees valid frames. Use when monitor_bus shows nothing on a live bus.

输入参数seconds_per_try

load_ldf

Load a LIN Description File so captures show signal names and values. Returns its frames and signals. Pass path "mock" with a --mock server to load the simulated bus's LDF.

输入参数path必填

decode_frame

Decode raw frame bytes into signal values with the loaded LDF. id like "0x0C", data hex like "05 1e".

输入参数id必填data必填

encode_frame

Build frame bytes from signal values with the loaded LDF. Signals not given keep their LDF default. Returns id and data ready for send_frame.

输入参数frame必填signals必填

send_frame

Inject a complete frame (header + data) on the bus from monitor mode, `repeat` times about 20 ms apart, and capture the bus for a moment after. Needs --allow-transmit. The converter echoes only the header of its own frame back, so check the effect in the following traffic.

输入参数id必填data必填speedrepeatchecksum

run_master

Act as the LIN master for duration_s: run a schedule that sends the `transmit` frames ([{"id": "0x0B", "data": "05"}]) and polls the `receive` ids ([{"id": "0x0C", "length": 2}]), then summarize the slave responses. Use only with the real master disconnected. Needs --allow-transmit.

输入参数speedreceivechecksumtransmitduration_s

run_slave

Simulate a slave node for duration_s: answer the master's headers for the `respond` ids with fixed data ([{"id": "0x0C", "data": "01 1e"}]) and capture the `listen` ids the master sends ([{"id": "0x0B", "length": 1}]). Use only with the real slave disconnected. Needs --allow-transmit.

输入参数speedlistenrespondchecksumduration_s

版本历史

2
  1. v0.1.2最新Nov 3, 2026
  2. v0.1.1Oct 23, 2026

评分

已满足适用检查项的 90%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通25 分
  • 已声明认证方式10 分

    请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。

  • 已列出工具必需15 分
  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分