use super::enum_value;
use crate::vhost_user::message::{MsgHeader, Req, VhostUserMsgValidator};
use crate::vhost_user::Error;
use std::fmt::Debug;
use std::marker::PhantomData;
use vm_memory::ByteValued;
enum_value! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
pub enum GpuBackendReq: u32 {
GET_PROTOCOL_FEATURES = 1,
SET_PROTOCOL_FEATURES = 2,
GET_DISPLAY_INFO = 3,
CURSOR_POS = 4,
CURSOR_POS_HIDE = 5,
CURSOR_UPDATE = 6,
SCANOUT = 7,
UPDATE = 8,
DMABUF_SCANOUT = 9,
DMABUF_UPDATE = 10,
GET_EDID = 11,
DMABUF_SCANOUT2 = 12,
}
}
impl Req for GpuBackendReq {}
bitflags! {
pub struct VhostUserGpuHeaderFlag: u32 {
const REPLY = 0x4;
}
}
#[repr(C, packed)]
#[derive(Clone, Copy)]
pub(super) struct VhostUserGpuMsgHeader<R: Req> {
request: u32,
flags: u32,
size: u32,
_r: PhantomData<R>,
}
impl<R: Req> Debug for VhostUserGpuMsgHeader<R> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("VhostUserMsgHeader")
.field("request", &{ self.request })
.field("flags", &{ self.flags })
.field("size", &{ self.size })
.finish()
}
}
impl<R: Req> PartialEq for VhostUserGpuMsgHeader<R> {
fn eq(&self, other: &Self) -> bool {
self.request == other.request && self.flags == other.flags && self.size == other.size
}
}
#[allow(dead_code)]
impl<R: Req> VhostUserGpuMsgHeader<R> {
pub fn new(request: R, flags: u32, size: u32) -> Self {
VhostUserGpuMsgHeader {
request: request.into(),
flags,
size,
_r: PhantomData,
}
}
pub fn get_code(&self) -> crate::vhost_user::Result<R> {
R::try_from(self.request).map_err(|_| Error::InvalidMessage)
}
pub fn is_reply(&self) -> bool {
(self.flags & VhostUserGpuHeaderFlag::REPLY.bits()) != 0
}
pub fn set_reply(&mut self, is_reply: bool) {
if is_reply {
self.flags |= VhostUserGpuHeaderFlag::REPLY.bits();
} else {
self.flags &= !VhostUserGpuHeaderFlag::REPLY.bits();
}
}
pub fn is_reply_for(&self, req: &VhostUserGpuMsgHeader<R>) -> bool {
if let (Ok(code1), Ok(code2)) = (self.get_code(), req.get_code()) {
self.is_reply() && !req.is_reply() && code1 == code2
} else {
false
}
}
pub fn get_size(&self) -> u32 {
self.size
}
pub fn set_size(&mut self, size: u32) {
self.size = size;
}
}
impl<R: Req> Default for VhostUserGpuMsgHeader<R> {
fn default() -> Self {
VhostUserGpuMsgHeader {
request: 0,
flags: 0,
size: 0,
_r: PhantomData,
}
}
}
unsafe impl<R: Req> ByteValued for VhostUserGpuMsgHeader<R> {}
impl<T: Req> VhostUserMsgValidator for VhostUserGpuMsgHeader<T> {
fn is_valid(&self) -> bool {
self.get_code().is_ok() && VhostUserGpuHeaderFlag::from_bits(self.flags).is_some()
}
}
impl<R: Req> MsgHeader for VhostUserGpuMsgHeader<R> {
type Request = R;
const MAX_MSG_SIZE: usize = u32::MAX as usize;
}
bitflags! {
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct VhostUserGpuProtocolFeatures: u64 {
const EDID = 0;
const DMABUF2 = 1;
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
#[repr(C)]
pub struct VirtioGpuCtrlHdr {
pub type_: u32,
pub flags: u32,
pub fence_id: u64,
pub ctx_id: u32,
pub ring_idx: u8,
pub padding: [u8; 3],
}
unsafe impl ByteValued for VirtioGpuCtrlHdr {}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
#[repr(C)]
pub struct VirtioGpuRect {
pub x: u32,
pub y: u32,
pub width: u32,
pub height: u32,
}
unsafe impl ByteValued for VirtioGpuRect {}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
#[repr(C)]
pub struct VirtioGpuDisplayOne {
pub r: VirtioGpuRect,
pub enabled: u32,
pub flags: u32,
}
unsafe impl ByteValued for VirtioGpuDisplayOne {}
pub const VIRTIO_GPU_MAX_SCANOUTS: usize = 16;
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
#[repr(C)]
pub struct VirtioGpuRespDisplayInfo {
pub hdr: VirtioGpuCtrlHdr,
pub pmodes: [VirtioGpuDisplayOne; VIRTIO_GPU_MAX_SCANOUTS],
}
unsafe impl ByteValued for VirtioGpuRespDisplayInfo {}
impl VhostUserMsgValidator for VirtioGpuRespDisplayInfo {}
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
#[repr(C)]
pub struct VhostUserGpuEdidRequest {
pub scanout_id: u32,
}
unsafe impl ByteValued for VhostUserGpuEdidRequest {}
impl VhostUserMsgValidator for VhostUserGpuEdidRequest {}
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
#[repr(C)]
pub struct VhostUserGpuUpdate {
pub scanout_id: u32,
pub x: u32,
pub y: u32,
pub width: u32,
pub height: u32,
}
unsafe impl ByteValued for VhostUserGpuUpdate {}
impl VhostUserMsgValidator for VhostUserGpuUpdate {}
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
#[repr(C)]
pub struct VhostUserGpuDMABUFScanout {
pub scanout_id: u32,
pub x: u32,
pub y: u32,
pub width: u32,
pub height: u32,
pub fd_width: u32,
pub fd_height: u32,
pub fd_stride: u32,
pub fd_flags: u32,
pub fd_drm_fourcc: u32,
}
unsafe impl ByteValued for VhostUserGpuDMABUFScanout {}
impl VhostUserMsgValidator for VhostUserGpuDMABUFScanout {}
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
#[repr(C, packed)]
pub struct VhostUserGpuDMABUFScanout2 {
pub dmabuf_scanout: VhostUserGpuDMABUFScanout,
pub modifier: u64,
}
unsafe impl ByteValued for VhostUserGpuDMABUFScanout2 {}
impl VhostUserMsgValidator for VhostUserGpuDMABUFScanout2 {}
#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]
#[repr(C)]
pub struct VhostUserGpuCursorPos {
pub scanout_id: u32,
pub x: u32,
pub y: u32,
}
unsafe impl ByteValued for VhostUserGpuCursorPos {}
impl VhostUserMsgValidator for VhostUserGpuCursorPos {}
#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]
#[repr(C)]
pub struct VhostUserGpuCursorUpdate {
pub pos: VhostUserGpuCursorPos,
pub hot_x: u32,
pub hot_y: u32,
}
unsafe impl ByteValued for VhostUserGpuCursorUpdate {}
impl VhostUserMsgValidator for VhostUserGpuCursorUpdate {}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(C)]
pub struct VirtioGpuRespGetEdid {
pub hdr: VirtioGpuCtrlHdr,
pub size: u32,
pub padding: u32,
pub edid: [u8; 1024],
}
unsafe impl ByteValued for VirtioGpuRespGetEdid {}
impl Default for VirtioGpuRespGetEdid {
fn default() -> Self {
VirtioGpuRespGetEdid {
hdr: VirtioGpuCtrlHdr::default(),
size: u32::default(),
padding: u32::default(),
edid: [0; 1024], }
}
}
impl VhostUserMsgValidator for VirtioGpuRespGetEdid {}
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
#[repr(C)]
pub struct VhostUserGpuScanout {
pub scanout_id: u32,
pub width: u32,
pub height: u32,
}
unsafe impl ByteValued for VhostUserGpuScanout {}
impl VhostUserMsgValidator for VhostUserGpuScanout {}