// Copyright 2024 Red Hat, Inc.
// Author(s): Paolo Bonzini <pbonzini@redhat.com>
// SPDX-License-Identifier: GPL-2.0-or-later

//! Bindings for character devices
//!
//! Character devices in QEMU can run under the big QEMU lock or in a separate
//! `GMainContext`. Here we only support the former, because the bindings
//! enforce that the BQL is taken whenever the functions in [`CharFrontend`] are
//! called.

use std::{
    ffi::{c_int, c_void, CStr},
    fmt::{self, Debug},
    io::{self, ErrorKind, Write},
    marker::PhantomPinned,
    ptr::addr_of_mut,
    slice,
};

use bql::{prelude::*, BqlRefMut};
use common::{callbacks::FnCall, errno, Opaque};
use qom::prelude::*;

use crate::bindings;

/// A safe wrapper around [`bindings::Chardev`].
#[repr(transparent)]
#[derive(common::Wrapper)]
pub struct Chardev(Opaque<bindings::Chardev>);

pub type ChardevClass = bindings::ChardevClass;
pub type Event = bindings::QEMUChrEvent;

/// A safe wrapper around [`bindings::CharFrontend`], denoting the character
/// back-end that is used for example by a device.  Compared to the
/// underlying C struct it adds BQL protection, and is marked as pinned
/// because the QOM object ([`bindings::Chardev`]) contains a pointer to
/// the `CharFrontend`.
pub struct CharFrontend {
    inner: BqlRefCell<bindings::CharFrontend>,
    _pin: PhantomPinned,
}

pub struct CharFrontendMut<'a>(BqlRefMut<'a, bindings::CharFrontend>);

impl Write for CharFrontendMut<'_> {
    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }

    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let chr: &mut bindings::CharFrontend = &mut self.0;

        let len = buf.len().try_into().unwrap();
        let r = unsafe { bindings::qemu_chr_fe_write(addr_of_mut!(*chr), buf.as_ptr(), len) };
        errno::into_io_result(r).map(|cnt| cnt as usize)
    }

    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        let chr: &mut bindings::CharFrontend = &mut self.0;

        let len = buf.len().try_into().unwrap();
        let r = unsafe { bindings::qemu_chr_fe_write_all(addr_of_mut!(*chr), buf.as_ptr(), len) };
        errno::into_io_result(r).and_then(|cnt| {
            if cnt as usize == buf.len() {
                Ok(())
            } else {
                Err(ErrorKind::WriteZero.into())
            }
        })
    }
}

impl Debug for CharFrontend {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // SAFETY: accessed just to print the values
        let chr = self.inner.as_ptr();
        Debug::fmt(unsafe { &*chr }, f)
    }
}

// FIXME: use something like PinnedDrop from the pinned_init crate
impl Drop for CharFrontend {
    fn drop(&mut self) {
        self.disable_handlers();
    }
}

impl CharFrontend {
    /// Enable the front-end's character device handlers, if there is an
    /// associated `Chardev`.
    pub fn enable_handlers<
        'chardev,
        'owner: 'chardev,
        T,
        CanReceiveFn: for<'a> FnCall<(&'a T,), u32>,
        ReceiveFn: for<'a, 'b> FnCall<(&'a T, &'b [u8])>,
        EventFn: for<'a> FnCall<(&'a T, Event)>,
    >(
        // When "self" is dropped, the handlers are automatically disabled.
        // However, this is not necessarily true if the owner is dropped.
        // So require the owner to outlive the character device.
        &'chardev self,
        owner: &'owner T,
        _can_receive: CanReceiveFn,
        _receive: ReceiveFn,
        _event: EventFn,
    ) {
        unsafe extern "C" fn rust_can_receive_cb<T, F: for<'a> FnCall<(&'a T,), u32>>(
            opaque: *mut c_void,
        ) -> c_int {
            // SAFETY: the values are safe according to the contract of
            // enable_handlers() and qemu_chr_fe_set_handlers()
            let owner: &T = unsafe { &*(opaque.cast::<T>()) };
            let r = F::call((owner,));
            r.try_into().unwrap()
        }

        unsafe extern "C" fn rust_receive_cb<T, F: for<'a, 'b> FnCall<(&'a T, &'b [u8])>>(
            opaque: *mut c_void,
            buf: *const u8,
            size: c_int,
        ) {
            // SAFETY: the values are safe according to the contract of
            // enable_handlers() and qemu_chr_fe_set_handlers()
            let owner: &T = unsafe { &*(opaque.cast::<T>()) };
            let buf = unsafe { slice::from_raw_parts(buf, size.try_into().unwrap()) };
            F::call((owner, buf))
        }

        unsafe extern "C" fn rust_event_cb<T, F: for<'a> FnCall<(&'a T, Event)>>(
            opaque: *mut c_void,
            event: Event,
        ) {
            // SAFETY: the values are safe according to the contract of
            // enable_handlers() and qemu_chr_fe_set_handlers()
            let owner: &T = unsafe { &*(opaque.cast::<T>()) };
            F::call((owner, event))
        }

        const { assert!(CanReceiveFn::IS_SOME) };
        let receive_cb: Option<unsafe extern "C" fn(*mut c_void, *const u8, c_int)> =
            if ReceiveFn::is_some() {
                Some(rust_receive_cb::<T, ReceiveFn>)
            } else {
                None
            };
        let event_cb: Option<unsafe extern "C" fn(*mut c_void, Event)> = if EventFn::is_some() {
            Some(rust_event_cb::<T, EventFn>)
        } else {
            None
        };

        let mut chr = self.inner.borrow_mut();
        // SAFETY: the borrow promises that the BQL is taken
        unsafe {
            bindings::qemu_chr_fe_set_handlers(
                addr_of_mut!(*chr),
                Some(rust_can_receive_cb::<T, CanReceiveFn>),
                receive_cb,
                event_cb,
                None,
                (owner as *const T).cast_mut().cast::<c_void>(),
                core::ptr::null_mut(),
                true,
            );
        }
    }

    /// Disable the front-end's character device handlers.
    pub fn disable_handlers(&self) {
        let mut chr = self.inner.borrow_mut();
        // SAFETY: the borrow promises that the BQL is taken
        unsafe {
            bindings::qemu_chr_fe_set_handlers(
                addr_of_mut!(*chr),
                None,
                None,
                None,
                None,
                core::ptr::null_mut(),
                core::ptr::null_mut(),
                true,
            );
        }
    }

    /// Notify that the frontend is ready to receive data.
    pub fn accept_input(&self) {
        let mut chr = self.inner.borrow_mut();
        // SAFETY: the borrow promises that the BQL is taken
        unsafe { bindings::qemu_chr_fe_accept_input(addr_of_mut!(*chr)) }
    }

    /// Temporarily borrow the character device, allowing it to be used
    /// as an implementor of `Write`.  Note that it is not valid to drop
    /// the big QEMU lock while the character device is borrowed, as
    /// that might cause C code to write to the character device.
    pub fn borrow_mut(&self) -> impl Write + '_ {
        CharFrontendMut(self.inner.borrow_mut())
    }

    /// Send a continuous stream of zero bits on the line if `enabled` is
    /// true, or a short stream if `enabled` is false.
    pub fn send_break(&self, long: bool) -> io::Result<()> {
        let mut chr = self.inner.borrow_mut();
        let mut duration: c_int = long.into();
        // SAFETY: the borrow promises that the BQL is taken
        let r = unsafe {
            bindings::qemu_chr_fe_ioctl(
                addr_of_mut!(*chr),
                bindings::CHR_IOCTL_SERIAL_SET_BREAK as i32,
                addr_of_mut!(duration).cast::<c_void>(),
            )
        };

        errno::into_io_result(r).map(|_| ())
    }

    /// Write data to a character backend from the front end.  This function
    /// will send data from the front end to the back end.  Unlike
    /// `write`, this function will block if the back end cannot
    /// consume all of the data attempted to be written.
    ///
    /// Returns the number of bytes consumed (0 if no associated Chardev) or an
    /// error.
    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
        let len = buf.len().try_into().unwrap();
        // SAFETY: qemu_chr_fe_write is thread-safe
        let r = unsafe { bindings::qemu_chr_fe_write(self.inner.as_ptr(), buf.as_ptr(), len) };
        errno::into_io_result(r).map(|cnt| cnt as usize)
    }

    /// Write data to a character backend from the front end.  This function
    /// will send data from the front end to the back end.  Unlike
    /// `write`, this function will block if the back end cannot
    /// consume all of the data attempted to be written.
    ///
    /// Returns the number of bytes consumed (0 if no associated Chardev) or an
    /// error.
    pub fn write_all(&self, buf: &[u8]) -> io::Result<()> {
        let len = buf.len().try_into().unwrap();
        // SAFETY: qemu_chr_fe_write_all is thread-safe
        let r = unsafe { bindings::qemu_chr_fe_write_all(self.inner.as_ptr(), buf.as_ptr(), len) };
        errno::into_io_result(r).and_then(|cnt| {
            if cnt as usize == buf.len() {
                Ok(())
            } else {
                Err(ErrorKind::WriteZero.into())
            }
        })
    }
}

unsafe impl ObjectType for Chardev {
    type Class = ChardevClass;
    const TYPE_NAME: &'static CStr =
        unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_CHARDEV) };
}
qom_isa!(Chardev: Object);
