|
| 1 | +// Copyright 2024, Linaro Limited |
| 2 | +// Author(s): Manos Pitsidianakis <[email protected]> |
| 3 | +// SPDX-License-Identifier: GPL-2.0-or-later |
| 4 | + |
| 5 | +use std::sync::OnceLock; |
| 6 | + |
| 7 | +use crate::bindings::Property; |
| 8 | + |
| 9 | +#[macro_export] |
| 10 | +macro_rules! device_class_init { |
| 11 | + ($func:ident, props => $props:ident, realize_fn => $realize_fn:expr, legacy_reset_fn => $legacy_reset_fn:expr, vmsd => $vmsd:ident$(,)*) => { |
| 12 | + #[no_mangle] |
| 13 | + pub unsafe extern "C" fn $func( |
| 14 | + klass: *mut $crate::bindings::ObjectClass, |
| 15 | + _: *mut ::core::ffi::c_void, |
| 16 | + ) { |
| 17 | + let mut dc = |
| 18 | + ::core::ptr::NonNull::new(klass.cast::<$crate::bindings::DeviceClass>()).unwrap(); |
| 19 | + dc.as_mut().realize = $realize_fn; |
| 20 | + dc.as_mut().vmsd = &$vmsd; |
| 21 | + $crate::bindings::device_class_set_legacy_reset(dc.as_mut(), $legacy_reset_fn); |
| 22 | + $crate::bindings::device_class_set_props(dc.as_mut(), $props.as_mut_ptr()); |
| 23 | + } |
| 24 | + }; |
| 25 | +} |
| 26 | + |
| 27 | +#[macro_export] |
| 28 | +macro_rules! define_property { |
| 29 | + ($name:expr, $state:ty, $field:expr, $prop:expr, $type:expr, default = $defval:expr$(,)*) => { |
| 30 | + $crate::bindings::Property { |
| 31 | + name: { |
| 32 | + #[used] |
| 33 | + static _TEMP: &::core::ffi::CStr = $name; |
| 34 | + _TEMP.as_ptr() |
| 35 | + }, |
| 36 | + info: $prop, |
| 37 | + offset: ::core::mem::offset_of!($state, $field) |
| 38 | + .try_into() |
| 39 | + .expect("Could not fit offset value to type"), |
| 40 | + bitnr: 0, |
| 41 | + bitmask: 0, |
| 42 | + set_default: true, |
| 43 | + defval: $crate::bindings::Property__bindgen_ty_1 { u: $defval.into() }, |
| 44 | + arrayoffset: 0, |
| 45 | + arrayinfo: ::core::ptr::null(), |
| 46 | + arrayfieldsize: 0, |
| 47 | + link_type: ::core::ptr::null(), |
| 48 | + } |
| 49 | + }; |
| 50 | + ($name:expr, $state:ty, $field:expr, $prop:expr, $type:expr$(,)*) => { |
| 51 | + $crate::bindings::Property { |
| 52 | + name: { |
| 53 | + #[used] |
| 54 | + static _TEMP: &::core::ffi::CStr = $name; |
| 55 | + _TEMP.as_ptr() |
| 56 | + }, |
| 57 | + info: $prop, |
| 58 | + offset: ::core::mem::offset_of!($state, $field) |
| 59 | + .try_into() |
| 60 | + .expect("Could not fit offset value to type"), |
| 61 | + bitnr: 0, |
| 62 | + bitmask: 0, |
| 63 | + set_default: false, |
| 64 | + defval: $crate::bindings::Property__bindgen_ty_1 { i: 0 }, |
| 65 | + arrayoffset: 0, |
| 66 | + arrayinfo: ::core::ptr::null(), |
| 67 | + arrayfieldsize: 0, |
| 68 | + link_type: ::core::ptr::null(), |
| 69 | + } |
| 70 | + }; |
| 71 | +} |
| 72 | + |
| 73 | +#[repr(C)] |
| 74 | +pub struct Properties<const N: usize>(pub OnceLock<[Property; N]>, pub fn() -> [Property; N]); |
| 75 | + |
| 76 | +impl<const N: usize> Properties<N> { |
| 77 | + pub fn as_mut_ptr(&mut self) -> *mut Property { |
| 78 | + _ = self.0.get_or_init(self.1); |
| 79 | + self.0.get_mut().unwrap().as_mut_ptr() |
| 80 | + } |
| 81 | +} |
| 82 | + |
| 83 | +#[macro_export] |
| 84 | +macro_rules! declare_properties { |
| 85 | + ($ident:ident, $($prop:expr),*$(,)*) => { |
| 86 | + |
| 87 | + const fn _calc_prop_len() -> usize { |
| 88 | + let mut len = 1; |
| 89 | + $({ |
| 90 | + _ = stringify!($prop); |
| 91 | + len += 1; |
| 92 | + })* |
| 93 | + len |
| 94 | + } |
| 95 | + const PROP_LEN: usize = _calc_prop_len(); |
| 96 | + |
| 97 | + fn _make_properties() -> [$crate::bindings::Property; PROP_LEN] { |
| 98 | + [ |
| 99 | + $($prop),*, |
| 100 | + unsafe { ::core::mem::MaybeUninit::<$crate::bindings::Property>::zeroed().assume_init() }, |
| 101 | + ] |
| 102 | + } |
| 103 | + |
| 104 | + #[no_mangle] |
| 105 | + pub static mut $ident: $crate::device_class::Properties<PROP_LEN> = $crate::device_class::Properties(::std::sync::OnceLock::new(), _make_properties); |
| 106 | + }; |
| 107 | +} |
| 108 | + |
| 109 | +#[macro_export] |
| 110 | +macro_rules! vm_state_description { |
| 111 | + ($(#[$outer:meta])* |
| 112 | + $name:ident, |
| 113 | + $(name: $vname:expr,)* |
| 114 | + $(unmigratable: $um_val:expr,)* |
| 115 | + ) => { |
| 116 | + #[used] |
| 117 | + $(#[$outer])* |
| 118 | + pub static $name: $crate::bindings::VMStateDescription = $crate::bindings::VMStateDescription { |
| 119 | + $(name: { |
| 120 | + #[used] |
| 121 | + static VMSTATE_NAME: &::core::ffi::CStr = $vname; |
| 122 | + $vname.as_ptr() |
| 123 | + },)* |
| 124 | + unmigratable: true, |
| 125 | + ..unsafe { ::core::mem::MaybeUninit::<$crate::bindings::VMStateDescription>::zeroed().assume_init() } |
| 126 | + }; |
| 127 | + } |
| 128 | +} |
0 commit comments