#![allow(non_camel_case_types, unused)]
use crate::{as_bytes, as_bytes_mut};
use libc::{c_char, c_uint};
use neli::{
FromBytes, Size, ToBytes,
consts::rtnl::{RtaType, RtaTypeWrapper},
err::{DeError, SerError},
impl_trait, neli_enum,
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::{
io::{self, Cursor, Read, Write},
mem,
mem::size_of,
};
#[repr(C)]
#[derive(Debug, Default, Clone, Copy, FromBytes, ToBytes, Size)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct can_bittiming {
pub bitrate: u32, pub sample_point: u32, pub tq: u32, pub prop_seg: u32, pub phase_seg1: u32, pub phase_seg2: u32, pub sjw: u32, pub brp: u32, }
#[repr(C)]
#[derive(Debug, Default, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct can_bittiming_const {
pub name: [c_char; 16], pub tseg1_min: u32, pub tseg1_max: u32,
pub tseg2_min: u32, pub tseg2_max: u32,
pub sjw_max: u32, pub brp_min: u32, pub brp_max: u32,
pub brp_inc: u32,
}
impl ToBytes for can_bittiming_const {
fn to_bytes(&self, buf: &mut Cursor<Vec<u8>>) -> Result<(), SerError> {
buf.write_all(unsafe { as_bytes(self) })?;
Ok(())
}
}
impl FromBytes for can_bittiming_const {
fn from_bytes(buf: &mut Cursor<impl AsRef<[u8]>>) -> Result<Self, DeError> {
let mut timing_const: can_bittiming_const = unsafe { mem::zeroed() };
buf.read_exact(unsafe { as_bytes_mut(&mut timing_const) })?;
Ok(timing_const)
}
}
impl Size for can_bittiming_const {
fn unpadded_size(&self) -> usize {
size_of::<can_bittiming_const>()
}
}
#[repr(C)]
#[derive(Debug, Default, Clone, Copy, FromBytes, ToBytes, Size)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct can_clock {
pub freq: u32, }
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, FromBytes, ToBytes, Size)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct can_berr_counter {
pub txerr: u16,
pub rxerr: u16,
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, FromBytes, ToBytes, Size)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct can_ctrlmode {
pub mask: u32,
pub flags: u32,
}
pub const NLA_F_NESTED: u16 = 0x8000;
pub const CAN_TERMINATION_DISABLED: u16 = 0;
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, FromBytes)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct can_device_stats {
pub bus_error: u32, pub error_warning: u32, pub error_passive: u32, pub bus_off: u32, pub arbitration_lost: u32, pub restarts: u32, }
#[neli_enum(serialized_type = "libc::c_ushort")]
pub enum IflaCanCtrlModeExt {
Unspec = libc::IFLA_CAN_CTRLMODE_UNSPEC as u16,
Supported = libc::IFLA_CAN_CTRLMODE_SUPPORTED as u16,
}
impl RtaType for IflaCanCtrlModeExt {}
#[neli_enum(serialized_type = "libc::c_ushort")]
pub enum IflaCan {
Unspec = libc::IFLA_CAN_UNSPEC as u16,
BitTiming = libc::IFLA_CAN_BITTIMING as u16,
BitTimingConst = libc::IFLA_CAN_BITTIMING_CONST as u16,
Clock = libc::IFLA_CAN_CLOCK as u16,
State = libc::IFLA_CAN_STATE as u16,
CtrlMode = libc::IFLA_CAN_CTRLMODE as u16,
RestartMs = libc::IFLA_CAN_RESTART_MS as u16,
Restart = libc::IFLA_CAN_RESTART as u16,
BerrCounter = libc::IFLA_CAN_BERR_COUNTER as u16,
DataBitTiming = libc::IFLA_CAN_DATA_BITTIMING as u16,
DataBitTimingConst = libc::IFLA_CAN_DATA_BITTIMING_CONST as u16,
Termination = libc::IFLA_CAN_TERMINATION as u16,
TerminationConst = libc::IFLA_CAN_TERMINATION_CONST as u16,
BitRateConst = libc::IFLA_CAN_BITRATE_CONST as u16,
DataBitRateConst = libc::IFLA_CAN_DATA_BITRATE_CONST as u16,
BitRateMax = libc::IFLA_CAN_BITRATE_MAX as u16,
Tdc = libc::IFLA_CAN_TDC as u16,
CtrlModeExt = libc::IFLA_CAN_CTRLMODE_EXT as u16,
}
impl RtaType for IflaCan {}
#[cfg(test)]
pub mod tests {
use super::*;
use std::mem::{align_of, offset_of, size_of};
#[test]
fn structs_match_libc() {
macro_rules! same_layout {
($ours:ty, $theirs:ty, [$($field:ident),+ $(,)?]) => {{
assert_eq!(
size_of::<$ours>(),
size_of::<$theirs>(),
concat!(stringify!($ours), ": size")
);
assert_eq!(
align_of::<$ours>(),
align_of::<$theirs>(),
concat!(stringify!($ours), ": alignment")
);
$(
assert_eq!(
offset_of!($ours, $field),
offset_of!($theirs, $field),
concat!(stringify!($ours), ".", stringify!($field), ": offset")
);
)+
}};
}
same_layout!(
can_bittiming,
libc::can_bittiming,
[
bitrate,
sample_point,
tq,
prop_seg,
phase_seg1,
phase_seg2,
sjw,
brp
]
);
same_layout!(
can_bittiming_const,
libc::can_bittiming_const,
[
name, tseg1_min, tseg1_max, tseg2_min, tseg2_max, sjw_max, brp_min, brp_max,
brp_inc
]
);
same_layout!(can_clock, libc::can_clock, [freq]);
same_layout!(can_berr_counter, libc::can_berr_counter, [txerr, rxerr]);
same_layout!(can_ctrlmode, libc::can_ctrlmode, [mask, flags]);
}
#[test]
fn test_as_bytes() {
let bitrate = 500000;
let sample_point = 750;
let timing = can_bittiming {
bitrate,
sample_point,
..can_bittiming::default()
};
assert_eq!(
unsafe {
std::slice::from_raw_parts::<'_, u8>(
&timing as *const _ as *const u8,
size_of::<can_bittiming>(),
)
},
unsafe { as_bytes(&timing) }
);
}
}