Skip to content

Commit

Permalink
Add support for FD frames
Browse files Browse the repository at this point in the history
  • Loading branch information
pd0wm committed Mar 19, 2024
1 parent 9ef3eec commit 30ee516
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 5 deletions.
6 changes: 5 additions & 1 deletion src/can.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,21 @@ pub struct Frame {
pub data: Vec<u8>,
/// Wheter the frame was sent out by the adapter
pub loopback: bool,
// TODO: Add timestamp, can-fd, rtr, dlc
/// CAN-FD Frame
pub fd: bool,
// TODO: Add timestamp, rtr, dlc
}
impl Unpin for Frame {}

impl Frame {
pub fn new(bus: u8, id: Identifier, data: &[u8]) -> Frame {
// TODO: Check if data has a valid length (check DLC table)
Frame {
bus,
id,
data: data.to_vec(),
loopback: false,
fd: data.len() > 8,
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use thiserror::Error;
pub enum Error {
#[error("Not Found")]
NotFound,
#[error("Not Supported")]
NotSupported,
#[error("Malformed Frame")]
MalformedFrame,
#[error("Timeout")]
Expand Down
13 changes: 13 additions & 0 deletions src/panda/usb_protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ pub fn pack_can_buffer(frames: &[Frame]) -> Result<Vec<Vec<u8>>, Error> {
return Err(Error::MalformedFrame);
}

if frame.fd {
return Err(Error::NotSupported);
}

let dlc = DLC_TO_LEN.iter().position(|&x| x == frame.data.len());
let dlc = dlc.ok_or(Error::MalformedFrame)? as u8;

Expand Down Expand Up @@ -111,11 +115,16 @@ pub fn unpack_can_buffer(dat: &mut Vec<u8>) -> Result<Vec<Frame>, Error> {
));
}

// Panda doesn't properly communicate if a frame was FD or not.
// We'll assume it was FD when the data length is > 8.
let fd = data_len > 8;

ret.push(Frame {
id,
bus,
data: dat[CANPACKET_HEAD_SIZE..(CANPACKET_HEAD_SIZE + data_len)].to_vec(),
loopback: returned,
fd,
});

dat.drain(0..(CANPACKET_HEAD_SIZE + data_len));
Expand Down Expand Up @@ -171,12 +180,14 @@ mod tests {
id: Identifier::Standard(0x123),
data: vec![1, 2, 3, 4, 5, 6, 7, 8],
loopback: false,
fd: false,
},
Frame {
bus: 1,
id: Identifier::Extended(0x123),
data: vec![1, 2, 3, 4],
loopback: false,
fd: false,
},
];

Expand All @@ -194,6 +205,7 @@ mod tests {
id: Identifier::Standard(0x123),
data: vec![1, 2, 3, 4, 5, 6, 7, 8, 9],
loopback: false,
fd: false,
}];
let r = pack_can_buffer(&frames);
assert_eq!(r, Err(Error::MalformedFrame));
Expand All @@ -206,6 +218,7 @@ mod tests {
id: Identifier::Standard(0xfff),
data: vec![1, 2, 3, 4, 5, 6, 7, 8],
loopback: false,
fd: false,
}];
let r = pack_can_buffer(&frames);
assert_eq!(r, Err(Error::MalformedFrame));
Expand Down
15 changes: 11 additions & 4 deletions src/socketcan/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ impl From<socketcan::frame::CanDataFrame> for crate::can::Frame {
id: frame.id().into(),
data: frame.data().to_vec(),
loopback: false,
fd: false,
}
}
}
Expand All @@ -28,16 +29,22 @@ impl From<socketcan::frame::CanFdFrame> for crate::can::Frame {
id: frame.id().into(),
data: frame.data().to_vec(),
loopback: false,
fd: true,
}
}
}

impl From<crate::can::Frame> for socketcan::frame::CanAnyFrame {
fn from(frame: crate::can::Frame) -> Self {
// TODO: Check if source is FD frame
socketcan::frame::CanAnyFrame::Normal(
socketcan::frame::CanDataFrame::new(frame.id, &frame.data).unwrap(),
)
let id: socketcan::Id = frame.id.into();
match frame.fd {
true => socketcan::frame::CanAnyFrame::Fd(
socketcan::frame::CanFdFrame::new(id, &frame.data).unwrap(),
),
false => socketcan::frame::CanAnyFrame::Normal(
socketcan::frame::CanDataFrame::new(id, &frame.data).unwrap(),
),
}
}
}

Expand Down
34 changes: 34 additions & 0 deletions tests/adapter_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,37 @@ async fn socketcan_bulk_send_async() {
let adapter = automotive::socketcan::SocketCan::new_async_from_name("can0").unwrap();
bulk_send(&adapter).await;
}

// #[cfg(feature = "test_socketcan")]
// #[tokio::test]
// #[serial_test::serial]
// async fn vcan_bulk_send_fd() {
// let adapter = automotive::socketcan::SocketCan::new_async_from_name("can0").unwrap();
// adapter.send(&Frame::new(0, 0x123.into(), &[0u8; 64])).await;
// }

#[cfg(feature = "test_vcan")]
#[test]
#[serial_test::serial]
fn vcan_bulk_send_sync() {
use socketcan::Socket;
let socket = socketcan::CanFdSocket::open("vcan0").unwrap();
let mut adapter = automotive::socketcan::SocketCan::new(socket);
bulk_send_sync(&mut adapter);
}

#[cfg(feature = "test_vcan")]
#[tokio::test]
#[serial_test::serial]
async fn vcan_bulk_send_async() {
let adapter = automotive::socketcan::SocketCan::new_async_from_name("vcan0").unwrap();
bulk_send(&adapter).await;
}

#[cfg(feature = "test_vcan")]
#[tokio::test]
#[serial_test::serial]
async fn vcan_bulk_send_fd() {
let adapter = automotive::socketcan::SocketCan::new_async_from_name("vcan0").unwrap();
adapter.send(&Frame::new(0, 0x123.into(), &[0u8; 64])).await;
}

0 comments on commit 30ee516

Please sign in to comment.