socketcan-rs 0.2.6

SocketCAN driver with UDS protocol.
Documentation
socketcan-rs-0.2.6 has been yanked.

Latest version Documentation LGPL MIT

Overview

socketcan-rs is a driver for SocketCAN device.

It is a part of rust-can driver.

Prerequisites

  • Rust 1.70 or higher
  • Cargo (included with Rust)

Adding to Your Project

To use socketcan-rs in your Rust project, add it as a dependency in your Cargo.toml:

[dependencies]
socketcan-rs = { version="lastest-version" }

UDS example

[dependencies]
docan = { git = "https://github.com/jesses2025smith/docan-rs", branch = "develop" }
iso14229-1 = { git = "https://github.com/jesses2025smith/iso14229-1", branch = "develop" }
rs-can = { git = "https://github.com/jesses2025smith/rust-can", branch = "develop", package = "rs-can", features = ["isotp-std2004"]  }
socketcan-rs = { git = "https://github.com/jesses2025smith/rust-can", branch = "develop", package = "socketcan-rs" }
anyhow = "1"
sudo ip link add dev vcan0 type vcan
sudo ip link set dev vcan0 up
candump vcan0   # show vcan0 message
use docan::{Client as _, DoCanClient, DoCanServer, Server as _};
use iso14229_1::SessionType;
use rs_can::{Frame, isotp::{Address, AddressType, IsoTpAdapter}};
use socketcan_rs::{CanMessage, SocketCan};

type Client = (IsoTpAdapter<SocketCan, String, CanMessage>, DoCanClient<SocketCan, String, CanMessage>);
type Server = (IsoTpAdapter<SocketCan, String, CanMessage>, DoCanServer<SocketCan, String, CanMessage>);

fn init_client() -> anyhow::Result<Client> {
    let channel = "vcan0";
    let mut builder = DeviceBuilder::new();
    builder.add_config(channel, Default::default());
    let device: SocketCan = builder.build()?;

    let mut adapter = IsoTpAdapter::new(device);
    let mut client = DoCanClient::new(adapter.clone(), None);

    client.init_channel(channel.into(), Address {
        tx_id: 0x7E0,
        rx_id: 0x7E8,
        fid: 0x7DF,
    })?;

    adapter.start(100);

    Ok((adapter, client))
}

fn init_server() -> anyhow::Result<Server> {
    let channel = "vcan0";
    let mut builder = DeviceBuilder::new();
    builder.add_config(channel, Default::default());
    let device: SocketCan = builder.build()?;

    let mut adapter = IsoTpAdapter::new(device);
    let server = DoCanServer::new(adapter.clone(), channel.into(), Address {
        tx_id: 0x7E8,
        rx_id: 0x7E0,
        fid: 0x7DF,
    });

    adapter.start(100);

    Ok((adapter, server))
}

#[test]
fn test_uds() -> anyhow::Result<()> {
    let channel = "vcan0";
    let (_, mut client) = init_client()?;
    let (_, mut server) = init_server()?;

    std::thread::spawn(move || {
        if let Err(e) = server.service_forever(100) {
            println!("docan server start error: {}", e);
        }
    });

    let mut message = CanMessage::new(0x123, &[0x01, 0x02, 0x03, 0x04]).unwrap();
    message.set_channel(channel.to_string());
    client.adapter().sender().send(message)?;

    client.session_ctrl(channel.to_string(), SessionType::Default, false, AddressType::Physical)?;
    client.session_ctrl(channel.to_string(), SessionType::Default, true, AddressType::Physical)?;
    client.session_ctrl(channel.to_string(), SessionType::Default, true, AddressType::Functional)?;

    Ok(())
}

Contributing

We're always looking for users who have thoughts on how to make socketcan-rs better, or users with interesting use cases.

Of course, we're also happy to accept code contributions for outstanding feature requests!