From 0c8f1b56d7297497182baaa87fee9ec0b465d14e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 14 Dec 2025 17:51:37 +0100 Subject: [PATCH] drivers/graphics/graphics-ipc: Add counterparts for the VERSION, GET_CAP and SET_CLIENT_CAP drm ioctls --- drivers/graphics/driver-graphics/src/lib.rs | 36 +++++++++++++++++++++ drivers/graphics/graphics-ipc/src/v2.rs | 28 ++++++++++++++++ drivers/graphics/vesad/src/scheme.rs | 27 +++++++++++++++- drivers/graphics/virtio-gpud/src/scheme.rs | 30 ++++++++++++++++- 4 files changed, 119 insertions(+), 2 deletions(-) diff --git a/drivers/graphics/driver-graphics/src/lib.rs b/drivers/graphics/driver-graphics/src/lib.rs index 13d8546941..32cb4253fd 100644 --- a/drivers/graphics/driver-graphics/src/lib.rs +++ b/drivers/graphics/driver-graphics/src/lib.rs @@ -18,6 +18,12 @@ pub trait GraphicsAdapter { type Framebuffer: Framebuffer; type Cursor: CursorFramebuffer; + fn name(&self) -> [u8;16]; + fn desc(&self) -> [u8;16]; + + fn get_cap(&self, cap: u64) -> Result; + fn set_client_cap(&self, cap: u64, value: u64) -> Result<()>; + /// The maximum amount of displays that could be attached. /// /// This must be constant for the lifetime of the graphics adapter. @@ -430,6 +436,36 @@ impl SchemeSync for GraphicsScheme { return Err(Error::new(EOPNOTSUPP)); } Handle::V2 { vt, next_id, fbs } => match metadata[0] { + ipc::VERSION => { + if payload.len() < size_of::() { + return Err(Error::new(EINVAL)); + } + let payload = unsafe { + transmute::<&mut [u8; size_of::()], &mut ipc::Version>( + payload.as_mut_array().unwrap(), + ) + }; + payload.version_major = 1; + payload.version_minor = 4; + payload.version_patchlevel = 0; + payload.name = self.adapter.name(); + payload.desc = self.adapter.desc(); + Ok(size_of::()) + } + + ipc::GET_CAP => { + if payload.len() < size_of::() { + return Err(Error::new(EINVAL)); + } + let payload = unsafe { + transmute::<&mut [u8; size_of::()], &mut ipc::GetCap>( + payload.as_mut_array().unwrap(), + ) + }; + payload.value = self.adapter.get_cap(payload.capability)?; + Ok(size_of::()) + } + ipc::DISPLAY_COUNT => { if payload.len() < size_of::() { return Err(Error::new(EINVAL)); diff --git a/drivers/graphics/graphics-ipc/src/v2.rs b/drivers/graphics/graphics-ipc/src/v2.rs index ca23f82e25..6cd9a80a71 100644 --- a/drivers/graphics/graphics-ipc/src/v2.rs +++ b/drivers/graphics/graphics-ipc/src/v2.rs @@ -153,6 +153,34 @@ impl V2GraphicsHandle { pub mod ipc { use crate::common::Damage; + pub const VERSION: u64 = 0; + #[repr(C, packed)] + pub struct Version { + pub version_major: u32, + pub version_minor: u32, + pub version_patchlevel: u32, + // FIXME allow variable sized fields + pub name: [u8; 16], + pub desc: [u8; 16], + } + + pub const GET_CAP: u64 = 0x0C; + pub const CAP_DUMB_BUFFER: u64 = 0x1; + #[repr(C, packed)] + pub struct GetCap { + pub capability: u64, + pub value: u64, + } + + pub const SET_CLIENT_CAP: u64 = 0x0D; + pub const CLIENT_CAP_CURSOR_PLANE_HOTSPOT: u64 = 6; + #[repr(C, packed)] + pub struct SetClientCap { + pub capability: u64, + pub value: u64, + } + + // FIXME replace these with proper drm interfaces pub const DISPLAY_COUNT: u64 = 1; #[repr(C, packed)] pub struct DisplayCount { diff --git a/drivers/graphics/vesad/src/scheme.rs b/drivers/graphics/vesad/src/scheme.rs index 42e4054e41..6d66ec9ade 100644 --- a/drivers/graphics/vesad/src/scheme.rs +++ b/drivers/graphics/vesad/src/scheme.rs @@ -4,7 +4,8 @@ use std::ptr::{self, NonNull}; use driver_graphics::{CursorFramebuffer, CursorPlane, Framebuffer, GraphicsAdapter}; use graphics_ipc::v1::Damage; -use syscall::PAGE_SIZE; +use graphics_ipc::v2::ipc::{CAP_DUMB_BUFFER, CLIENT_CAP_CURSOR_PLANE_HOTSPOT}; +use syscall::{EINVAL, PAGE_SIZE}; pub struct FbAdapter { pub framebuffers: Vec, @@ -18,6 +19,30 @@ impl GraphicsAdapter for FbAdapter { type Framebuffer = GraphicScreen; type Cursor = VesadCursor; + fn name(&self) -> [u8; 16] { + [ + b'v', b'e', b's', b'a', b'd', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ] + } + + fn desc(&self) -> [u8; 16] { + [b'V', b'E', b'S', b'A', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + } + + fn get_cap(&self, cap: u64) -> syscall::Result { + match cap { + CAP_DUMB_BUFFER => Ok(1), + _ => Err(syscall::Error::new(EINVAL)) + } + } + + fn set_client_cap(&self, cap: u64, _value: u64) -> syscall::Result<()> { + match cap { + CLIENT_CAP_CURSOR_PLANE_HOTSPOT => Ok(()), + _ => Err(syscall::Error::new(EINVAL)) + } + } + fn display_count(&self) -> usize { self.framebuffers.len() } diff --git a/drivers/graphics/virtio-gpud/src/scheme.rs b/drivers/graphics/virtio-gpud/src/scheme.rs index 34159dac3f..cc92684546 100644 --- a/drivers/graphics/virtio-gpud/src/scheme.rs +++ b/drivers/graphics/virtio-gpud/src/scheme.rs @@ -5,9 +5,10 @@ use driver_graphics::{ CursorFramebuffer, CursorPlane, Framebuffer, GraphicsAdapter, GraphicsScheme, }; use graphics_ipc::v1::Damage; +use graphics_ipc::v2::ipc::{CAP_DUMB_BUFFER, CLIENT_CAP_CURSOR_PLANE_HOTSPOT}; use inputd::DisplayHandle; -use syscall::PAGE_SIZE; +use syscall::{EINVAL, PAGE_SIZE}; use virtio_core::spec::{Buffer, ChainBuilder, DescriptorFlags}; use virtio_core::transport::{Error, Queue, Transport}; @@ -200,6 +201,33 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> { type Framebuffer = VirtGpuFramebuffer<'a>; type Cursor = VirtGpuCursor; + fn name(&self) -> [u8; 16] { + [ + b'v', b'i', b'r', b't', b'i', b'o', b'-', b'g', b'p', b'u', b'd', 0, 0, 0, 0, 0, + ] + } + + fn desc(&self) -> [u8; 16] { + [ + b'V', b'i', b'r', b't', b'I', b'O', b' ', b'G', b'P', b'U', 0, 0, 0, 0, 0, 0, + ] + } + + fn get_cap(&self, cap: u64) -> syscall::Result { + match cap { + CAP_DUMB_BUFFER => Ok(1), + _ => Err(syscall::Error::new(EINVAL)) + } + } + + fn set_client_cap(&self, cap: u64, _value: u64) -> syscall::Result<()> { + match cap { + // FIXME hide cursor plane unless this client cap is set + CLIENT_CAP_CURSOR_PLANE_HOTSPOT => Ok(()), + _ => Err(syscall::Error::new(EINVAL)) + } + } + fn display_count(&self) -> usize { self.displays.len() }