[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [RFC 04/13] rust: add bindings for gpio_{in|out} initialization
From: |
Paolo Bonzini |
Subject: |
Re: [RFC 04/13] rust: add bindings for gpio_{in|out} initialization |
Date: |
Thu, 5 Dec 2024 19:53:42 +0100 |
User-agent: |
Mozilla Thunderbird |
On 12/5/24 07:07, Zhao Liu wrote:
The qdev_init_gpio_{in|out} are qdev interfaces, so that it's natural to
wrap them as DeviceState's methods in Rust API, which could eliminate
unsafe cases in the device lib.
Wrap qdev_init_gpio_{in|out} as methods in a new trait DeviceGPIOImpl.
In addition, for qdev_init_gpio_in(), to convert the idiomatic Rust
callback into a C-style callback qemu_irq_handler, add a handler pointer
member in DeviceGPIOImpl. For any device needs to initialize GPIO in, it
needs to define a handler. And for device which just wants to initialize
GPIO out, it can leave the GPIO_IRQ_HANDLER as None.
This has the same issue as timers, in that you could have (especially
once someone adds named GPIOs) multiple handlers. So we need the same
kind of Fn-based thing here too.
+/// Trait that defines the irq handler for GPIO in.
+pub trait DeviceGPIOImpl {
+ const GPIO_IRQ_HANDLER: Option<fn(&mut Self, lines_num: u32, level: u32)>
= None;
Ah, I see that you're placing the qdev_init_gpio_in here so that you
only make that accessible for devices that did implement DeviceGPIOImpl.
However you are not guaranteeing that this _is_ a DeviceState.
If the handler can be passed as a function, the problem of getting the
GPIO_INT_HANDLER does not exist anymore. So with the code in rust-next
you can add these to a trait like
/// Trait for methods of [`DeviceState`] and its subclasses.
pub trait DeviceMethods: ObjectDeref
where
Self::Target: IsA<DeviceState>,
{
fn init_gpio_in<F: ...)(&self, lines_num: u32, f: &F) {
}
}
impl<R: ObjectDeref> DeviceMethods for R where R::Target:
IsA<DeviceState> {}
+ fn init_gpio_out(&self, pins: &InterruptSource, lines_num: u32) {
+ unsafe {
+ qdev_init_gpio_out(addr_of!(*self) as *mut _, pins.as_ptr(),
lines_num as c_int);
+ }
+ }
+}
Pass a slice &[InterruptSource], and get the "len" from the length of
the slice.
Paolo
[RFC 05/13] rust: add a bit operation binding for deposit64, Zhao Liu, 2024/12/05
[RFC 06/13] rust: add bindings for memattrs, Zhao Liu, 2024/12/05