From f2fe0f02882b7c830bf9c360ed7360d0dbc35b73 Mon Sep 17 00:00:00 2001 From: Noa Date: Fri, 29 Aug 2025 15:55:24 -0500 Subject: [PATCH 1/3] Add contents of linux/can/bcm.h --- libc-test/build.rs | 6 +++- libc-test/semver/linux.txt | 26 ++++++++++++++++ src/new/linux_uapi/linux/can.rs | 2 ++ src/new/linux_uapi/linux/can/bcm.rs | 47 +++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 src/new/linux_uapi/linux/can/bcm.rs diff --git a/libc-test/build.rs b/libc-test/build.rs index 3146ce669b843..791c347c3d09d 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -3736,6 +3736,7 @@ fn test_linux(target: &str) { headers! { cfg: [gnu]: "linux/aio_abi.h", "linux/can.h", + "linux/can/bcm.h", "linux/can/raw.h", "linux/can/j1939.h", "linux/cn_proc.h", @@ -4815,7 +4816,9 @@ fn test_linux(target: &str) { // the `xsk_tx_metadata_union` field is an anonymous union (struct_ == "xsk_tx_metadata" && field == "xsk_tx_metadata_union") || // After musl 1.2.0, the type becomes `int` instead of `long`. - (old_musl && struct_ == "utmpx" && field == "ut_session") + (old_musl && struct_ == "utmpx" && field == "ut_session") || + // `frames` is a VLA + (struct_ == "bcm_msg_head" && field == "frames") }); cfg.skip_roundtrip(move |s| match s { @@ -4852,6 +4855,7 @@ fn test_linux(target: &str) { "inotify_event" => true, "fanotify_event_info_fid" => true, "cmsghdr" => true, + "bcm_msg_head" => true, // FIXME(linux): the call ABI of max_align_t is incorrect on these platforms: "max_align_t" if i686 || ppc64 => true, diff --git a/libc-test/semver/linux.txt b/libc-test/semver/linux.txt index c745733f99632..d448a07f6a7bc 100644 --- a/libc-test/semver/linux.txt +++ b/libc-test/semver/linux.txt @@ -232,6 +232,7 @@ CAN_EFF_ID_BITS CAN_EFF_MASK CAN_ERR_FLAG CAN_ERR_MASK +CAN_FD_FRAME CAN_INV_FILTER CAN_ISOTP CAN_J1939 @@ -2712,6 +2713,17 @@ RT_TOS RUSAGE_CHILDREN RUSAGE_SELF RUSAGE_THREAD +RX_ANNOUNCE_RESUME +RX_CHANGED +RX_CHECK_DLC +RX_DELETE +RX_FILTER_ID +RX_NO_AUTOTIMER +RX_READ +RX_RTR_FRAME +RX_SETUP +RX_STATUS +RX_TIMEOUT SCHED_BATCH SCHED_FIFO SCHED_IDLE @@ -2845,6 +2857,7 @@ SEM_STAT SEM_STAT_ANY SEM_UNDO SETALL +SETTIMER SETVAL SFD_CLOEXEC SFD_NONBLOCK @@ -3089,6 +3102,7 @@ SPLICE_F_MOVE SPLICE_F_NONBLOCK SS_DISABLE SS_ONSTACK +STARTTIMER STICKY_TIMEOUTS ST_APPEND ST_IMMUTABLE @@ -3576,6 +3590,16 @@ TUN_TAP_DEV TUN_TUN_DEV TUN_TX_TIMESTAMP TUN_TYPE_MASK +TX_ANNOUNCE +TX_COUNTEVT +TX_CP_CAN_ID +TX_DELETE +TX_EXPIRED +TX_READ +TX_RESET_MULTI_IDX +TX_SEND +TX_SETUP +TX_STATUS T_FMT T_FMT_AMPM UDP_CORK @@ -3859,6 +3883,8 @@ arpd_request arphdr arpreq arpreq_old +bcm_msg_head +bcm_timeval blkcnt64_t brk bsearch diff --git a/src/new/linux_uapi/linux/can.rs b/src/new/linux_uapi/linux/can.rs index 971e579bc8d6e..20d1e6acfdfd2 100644 --- a/src/new/linux_uapi/linux/can.rs +++ b/src/new/linux_uapi/linux/can.rs @@ -1,8 +1,10 @@ //! Header: `uapi/linux/can.h` +pub(crate) mod bcm; pub(crate) mod j1939; pub(crate) mod raw; +pub use bcm::*; pub use j1939::*; pub use raw::*; diff --git a/src/new/linux_uapi/linux/can/bcm.rs b/src/new/linux_uapi/linux/can/bcm.rs new file mode 100644 index 0000000000000..bc2f477b0afcd --- /dev/null +++ b/src/new/linux_uapi/linux/can/bcm.rs @@ -0,0 +1,47 @@ +//! `linux/can/bcm.h` + +pub use crate::linux::can::*; + +s! { + pub struct bcm_timeval { + pub tv_sec: c_long, + pub tv_usec: c_long, + } + + pub struct bcm_msg_head { + pub opcode: crate::__u32, + pub flags: crate::__u32, + pub count: crate::__u32, + pub ival1: bcm_timeval, + pub ival2: bcm_timeval, + pub can_id: canid_t, + pub nframes: crate::__u32, + pub frames: [can_frame; 0], + } +} + +pub const TX_SETUP: crate::__u32 = 1; +pub const TX_DELETE: crate::__u32 = 2; +pub const TX_READ: crate::__u32 = 3; +pub const TX_SEND: crate::__u32 = 4; +pub const RX_SETUP: crate::__u32 = 5; +pub const RX_DELETE: crate::__u32 = 6; +pub const RX_READ: crate::__u32 = 7; +pub const TX_STATUS: crate::__u32 = 8; +pub const TX_EXPIRED: crate::__u32 = 9; +pub const RX_STATUS: crate::__u32 = 10; +pub const RX_TIMEOUT: crate::__u32 = 11; +pub const RX_CHANGED: crate::__u32 = 12; + +pub const SETTIMER: crate::__u32 = 0x0001; +pub const STARTTIMER: crate::__u32 = 0x0002; +pub const TX_COUNTEVT: crate::__u32 = 0x0004; +pub const TX_ANNOUNCE: crate::__u32 = 0x0008; +pub const TX_CP_CAN_ID: crate::__u32 = 0x0010; +pub const RX_FILTER_ID: crate::__u32 = 0x0020; +pub const RX_CHECK_DLC: crate::__u32 = 0x0040; +pub const RX_NO_AUTOTIMER: crate::__u32 = 0x0080; +pub const RX_ANNOUNCE_RESUME: crate::__u32 = 0x0100; +pub const TX_RESET_MULTI_IDX: crate::__u32 = 0x0200; +pub const RX_RTR_FRAME: crate::__u32 = 0x0400; +pub const CAN_FD_FRAME: crate::__u32 = 0x0800; From f29e25d01bb0a5f6797678c0bdbc6c07c4e9f281 Mon Sep 17 00:00:00 2001 From: Noa Date: Fri, 5 Sep 2025 13:20:32 -0500 Subject: [PATCH 2/3] Allow anonymous c_enum!s --- ci/style.sh | 5 +++++ src/macros.rs | 41 +++++++++++++++++++---------------------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/ci/style.sh b/ci/style.sh index 2d3e874e38998..844c9ac8da7d6 100755 --- a/ci/style.sh +++ b/ci/style.sh @@ -37,6 +37,10 @@ while IFS= read -r file; do # rust-lang/rustfmt#5464). perl -pi -e 's/^(\s*)(.*)\{const\}/$1\/\* FMT-CONST \*\/\n$1$2const/g' "$file" + # The `c_enum!` macro allows anonymous enums without names, which isn't + # valid syntax. Replace it with a dummy name and an indicator comment. + perl -pi -e 's/^(\s*)(.*)enum(\s*\{)/$1\/\* FMT-ANON-ENUM \*\/\n$1$2enum _Anon$3/g' "$file" + # Format the file. We need to invoke `rustfmt` directly since `cargo fmt` # can't figure out the module tree with the hacks in place. failed=false @@ -46,6 +50,7 @@ while IFS= read -r file; do perl -pi -e 's/fn (\w+)_fmt_tmp\(\)/$1!/g' "$file" perl -pi -0777 -e 's/cfg_tmp!\(\[(.*?)\]\)/#[cfg($1)]/gms' "$file" perl -pi -0777 -e 's/\/\* FMT-CONST \*\/(?:\n\s*)?(.*?)const/$1\{const\}/gms' "$file" + perl -pi -0777 -e 's/\/\* FMT-ANON-ENUM \*\/(?:\n\s*)?(.*?)enum _Anon(\s*\{)/$1enum$2/gms' "$file" # Defer emitting the failure until after the files get reset if [ "$failed" != "false" ]; then diff --git a/src/macros.rs b/src/macros.rs index afa8b23ed00f0..0cbffa70b7852 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -233,32 +233,33 @@ macro_rules! e { macro_rules! c_enum { ($( $(#[repr($repr:ty)])? - pub enum $ty_name:ident { + pub enum $($ty_name:ident)? { $($variant:ident $(= $value:expr)?,)+ } )+) => { - $(c_enum!(@expand; - $(#[repr($repr)])? - pub enum $ty_name { - $($variant $(= $value)?,)+ - } - );)+ + $(c_enum!(@expand_repr; $($repr)?; $($ty_name)?; $($variant $(= $value)?,)+);)+ }; - (@expand; - $(#[repr($repr:ty)])? - pub enum $ty_name:ident { - $($variant:ident $(= $value:expr)?,)+ - } - ) => { - pub type $ty_name = c_enum!(@ty $($repr)?); - c_enum!(@one; $ty_name; 0; $($variant $(= $value)?,)+); + (@expand_repr; ; $($ty_name:ident)?; $($variants:tt)*) => { + // Use a specific type if provided, otherwise default to `CEnumRepr` + c_enum!(@expand_tyname; $crate::prelude::CEnumRepr; $($ty_name)?; $($variants)*); + }; + (@expand_repr; $repr:ty; $($ty_name:ident)?; $($variants:tt)*) => { + c_enum!(@expand_tyname; $repr; $($ty_name)?; $($variants)*); + }; + + (@expand_tyname; $repr:ty; ; $($variants:tt)*) => { + c_enum!(@one; $repr; 0; $($variants)*); + }; + (@expand_tyname; $repr:ty; $ty_name:ident; $($variants:tt)*) => { + pub type $ty_name = $repr; + c_enum!(@one; $ty_name; 0; $($variants)*); }; // Matcher for a single variant - (@one; $_ty_name:ident; $_idx:expr;) => {}; + (@one; $_ty_name:ty; $_idx:expr;) => {}; ( - @one; $ty_name:ident; $default_val:expr; + @one; $ty_name:ty; $default_val:expr; $variant:ident $(= $value:expr)?, $($tail:tt)* ) => { @@ -273,10 +274,6 @@ macro_rules! c_enum { // set explicitly. c_enum!(@one; $ty_name; $variant + 1; $($tail)*); }; - - // Use a specific type if provided, otherwise default to `CEnumRepr` - (@ty $repr:ty) => { $repr }; - (@ty) => { $crate::prelude::CEnumRepr }; } // This is a pretty horrible hack to allow us to conditionally mark some functions as 'const', @@ -449,7 +446,7 @@ mod tests { // C enums always take one more than the previous value, unless set to a specific // value. Duplicates are allowed. c_enum! { - pub enum e { + pub enum { VAR0, VAR2_0 = 2, VAR3_0, From f5e5bdc3a8e8d2e4ecd16707e8679dffc023df46 Mon Sep 17 00:00:00 2001 From: Noa Date: Fri, 5 Sep 2025 13:20:48 -0500 Subject: [PATCH 3/3] Use c_enum in bcm.rs --- src/new/linux_uapi/linux/can/bcm.rs | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/new/linux_uapi/linux/can/bcm.rs b/src/new/linux_uapi/linux/can/bcm.rs index bc2f477b0afcd..de3cc28d5006d 100644 --- a/src/new/linux_uapi/linux/can/bcm.rs +++ b/src/new/linux_uapi/linux/can/bcm.rs @@ -20,18 +20,23 @@ s! { } } -pub const TX_SETUP: crate::__u32 = 1; -pub const TX_DELETE: crate::__u32 = 2; -pub const TX_READ: crate::__u32 = 3; -pub const TX_SEND: crate::__u32 = 4; -pub const RX_SETUP: crate::__u32 = 5; -pub const RX_DELETE: crate::__u32 = 6; -pub const RX_READ: crate::__u32 = 7; -pub const TX_STATUS: crate::__u32 = 8; -pub const TX_EXPIRED: crate::__u32 = 9; -pub const RX_STATUS: crate::__u32 = 10; -pub const RX_TIMEOUT: crate::__u32 = 11; -pub const RX_CHANGED: crate::__u32 = 12; +c_enum! { + #[repr(crate::__u32)] + pub enum { + TX_SETUP = 1, + TX_DELETE, + TX_READ, + TX_SEND, + RX_SETUP, + RX_DELETE, + RX_READ, + TX_STATUS, + TX_EXPIRED, + RX_STATUS, + RX_TIMEOUT, + RX_CHANGED, + } +} pub const SETTIMER: crate::__u32 = 0x0001; pub const STARTTIMER: crate::__u32 = 0x0002;