From ea1c2b1c1a483664d6af7df40d5a76a1ef1149a0 Mon Sep 17 00:00:00 2001 From: Willem Melching Date: Sat, 11 May 2024 08:59:15 +0200 Subject: [PATCH] docs --- README.md | 2 +- src/socketcan/mod.rs | 8 +++++--- src/socketcan/socket.rs | 20 ++++++++++++++++++-- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 258d965..a9206b6 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ The automotive crate also supplies interfaces for various diagnostic protocols s The following CAN adapters are supported. ### Supported CAN adapters - - SocketCAN (Linux only, supported using [socketcan-rs](https://github.com/socketcan-rs/socketcan-rs)) + - SocketCAN (Linux only) - comma.ai panda (all platforms using [rusb](https://crates.io/crates/rusb)) ### Known limitations / Notes diff --git a/src/socketcan/mod.rs b/src/socketcan/mod.rs index d203235..4edc30c 100644 --- a/src/socketcan/mod.rs +++ b/src/socketcan/mod.rs @@ -1,4 +1,4 @@ -//! This module provides a [`CanAdapter`] implementation for the [`socketcan`] crate. +//! This module provides a [`CanAdapter`] implementation for SocketCAN interfaces use crate::can::{AsyncCanAdapter, CanAdapter, Frame}; use crate::socketcan::socket::CanFdSocket; use crate::Result; @@ -10,7 +10,7 @@ mod socket; const IFF_ECHO: u64 = 1 << 18; // include/uapi/linux/if.h -/// Aadapter for a [`socketcan::CanFdSocket`]. +/// SocketCAN Adapter pub struct SocketCan { socket: CanFdSocket, /// If the IFF_ECHO flag is set on the interface, it will implement proper ACK logic. @@ -33,11 +33,13 @@ fn read_iff_echo(if_name: &str) -> Option { } impl SocketCan { + /// Creates a new [`AsyncCanAdapter`] from a SocketCAN iface name (e.g. `can0`) pub fn new_async(name: &str) -> Result { let socket = SocketCan::new(name)?; Ok(AsyncCanAdapter::new(socket)) } + /// Creates a new blocking [`SocketCan`] from a SocketCAN iface name (e.g. `can0`) pub fn new(name: &str) -> Result { let socket = match CanFdSocket::open(name) { Ok(socket) => socket, @@ -65,7 +67,7 @@ impl SocketCan { }; if iff_echo { - // socket.set_recv_own_msgs(true).unwrap(); + socket.set_recv_own_msgs(true).unwrap(); } else { tracing::warn!("IFF_ECHO is not set on the interface. ACK support is emulated."); } diff --git a/src/socketcan/socket.rs b/src/socketcan/socket.rs index c9cc8f6..ae7a3f6 100644 --- a/src/socketcan/socket.rs +++ b/src/socketcan/socket.rs @@ -1,8 +1,8 @@ //! Low Level SocketCAN code -//! Code based on https://github.com/socketcan-rs/socketcan-rs +//! Code based on socketcan-rs use libc::{ c_int, c_void, can_frame, canfd_frame, sa_family_t, sockaddr_can, socklen_t, AF_CAN, CANFD_MTU, - CAN_MTU, CAN_RAW, CAN_RAW_FD_FRAMES, CAN_RAW_LOOPBACK, SOL_CAN_RAW, + CAN_MTU, CAN_RAW, CAN_RAW_FD_FRAMES, CAN_RAW_LOOPBACK, CAN_RAW_RECV_OWN_MSGS, SOL_CAN_RAW, }; use nix::net::if_::if_nametoindex; use std::io::Write; @@ -106,15 +106,22 @@ impl CanFdSocket { } } + /// Enable or disable FD mode on a socket. pub fn set_fd_mode(&self, enabled: bool) -> std::io::Result<()> { let enable = c_int::from(enabled); self.set_socket_option(SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &enable) } + /// Change socket to non-blocking mode or back to blocking mode. pub fn set_nonblocking(&self, nonblocking: bool) -> std::io::Result<()> { self.as_raw_socket().set_nonblocking(nonblocking) } + /// Enable or disable loopback. + /// + /// By default, loopback is enabled, causing other applications that open + /// the same CAN bus to see frames emitted by different applications on + /// the same system. pub fn set_loopback(&self, enabled: bool) -> std::io::Result<()> { let loopback = c_int::from(enabled); self.set_socket_option(SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback) @@ -128,6 +135,15 @@ impl CanFdSocket { self.as_raw_socket().recv_buffer_size() } + /// Enable or disable receiving of own frames. + /// + /// When enabled, this settings controls if CAN frames sent + /// are received back by sender when ACKed. Default is off. + pub fn set_recv_own_msgs(&self, enabled: bool) -> std::io::Result<()> { + let recv_own_msgs = c_int::from(enabled); + self.set_socket_option(SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &recv_own_msgs) + } + fn as_raw_socket(&self) -> &socket2::Socket { &self.0 }