From b05512b81bbe1c90b71da9c571e742f162fc0575 Mon Sep 17 00:00:00 2001 From: Michele Paolino Date: Tue, 14 Nov 2023 18:07:09 +0100 Subject: CAN, GPIO, RNG vhost-devices for virtio-loopback [v6] This patch adds key components of the viritio-loopback architecture: - kernel-module-virtio-loopback: the virtio loopback kernel driver - CAN, GPIO and RNG vhost-user devices from meta-virtualization (commit a215d8320edee0a317a6511e7e2efa5bba867486) Notes: - libgpiod, comes from meta-openembedded commit 3029554ceb0b0bb52a8d8ec3f0a75c5113662fe6 - cleaned eg-virt from unused drivers (kernel-module-virtio-video) Bug-AGL: SPEC-4834 V2 changes: - related meta-virtualization commit message added in the cover letter - updated libgpio recipe to v2.1 - SPEC reference added in cover letter v3 - add vhost-device-can preliminary version. This is placed here with the objective to share the link when proposing the new device to the rust-vmm/vhost-device community - remove cargo-update-recipe-crates includes in bb file because it is not supported by the rust mixin layer - vhost-device folder README changes v4 - fixed libgpiod required version - tested ref hw and qemu x86/64 builds - vsock, scsi and i2c rust devices removed from the build as they are not yet integrated in virtiod-loopback - cleaned-up kernel modules kernel-module-virtio-video and gstreamer1.0-plugins-bad - virtio-loopback-driver set to 2-or-later v5 - Merge with Jan-Simon version v4: - remove broken kernel-module-virtio-video - use FEATURE_PACKAGES instead of IMAGE_INSTALL:append - rename virtio-loopback-driver.bb to kernel-module-virtio-loopback_git.bb for consistency v6 - adding version in the title - removing MODULE_GIT_REPOSITORY in kernel-modules Change-Id: Id6cc58e777b9edad03b6c50d0dddaac8601edeaf Signed-off-by: Michele Paolino Signed-off-by: Jan-Simon Moeller --- meta-egvirt/conf/include/agl-egvirt.inc | 25 +- .../vhost-device-can-0.1.0/CHANGELOG.md | 15 + .../vhost-device-can-0.1.0/Cargo.toml | 35 + .../vhost-device-can-0.1.0/LICENSE | 0 .../vhost-device-can-0.1.0/README.md | 66 + .../vhost-device-can-0.1.0/src/backend.rs | 170 +++ .../vhost-device-can-0.1.0/src/can.rs | 264 ++++ .../vhost-device-can-0.1.0/src/main.rs | 26 + .../vhost-device-can-0.1.0/src/vhu_can.rs | 732 +++++++++++ .../vhost-device-can/vhost-device-can-crates.inc | 83 ++ .../vhost-device-can/vhost-device-can_0.1.0.bb | 18 + .../recipes-extended/vhost-device/README.md | 12 + .../vhost-device/vhost-device-gpio-crates.inc | 184 +++ .../vhost-device/vhost-device-gpio_0.1.0.bb | 22 + .../vhost-device/vhost-device-rng-crates.inc | 158 +++ .../vhost-device/vhost-device-rng_0.1.0.bb | 16 + .../kernel-module-virtio-can.bb | 2 +- .../kernel-module-virtio-loopback.bb | 16 + .../virtio-loopback-driver.bb | 14 - .../kernel-module-virtio-video/files/Kbuild | 22 - .../kernel-module-virtio-video/files/Makefile | 33 - .../files/include/uapi/linux/virtio_video.h | 493 -------- .../files/virtio_video.h | 446 ------- .../files/virtio_video_cam.c | 359 ------ .../files/virtio_video_caps.c | 460 ------- .../files/virtio_video_dec.c | 424 ------- .../files/virtio_video_device.c | 1282 -------------------- .../files/virtio_video_driver.c | 246 ---- .../files/virtio_video_enc.c | 601 --------- .../files/virtio_video_helpers.c | 289 ----- .../files/virtio_video_vq.c | 981 --------------- .../kernel-module-virtio-video.bb | 12 - .../linux/linux-yocto/virtio_loopback.cfg | 1 + .../recipes-support/libgpiod/files/run-ptest | 19 + meta-egvirt/recipes-support/libgpiod/libgpiod.inc | 59 + .../recipes-support/libgpiod/libgpiod_2.1.bb | 35 + .../rust-vhost-device/rust-vhost-device_git.bb | 16 - 37 files changed, 1941 insertions(+), 5695 deletions(-) create mode 100644 meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/CHANGELOG.md create mode 100644 meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/Cargo.toml create mode 100644 meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/LICENSE create mode 100644 meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/README.md create mode 100644 meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/backend.rs create mode 100644 meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/can.rs create mode 100644 meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/main.rs create mode 100644 meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/vhu_can.rs create mode 100644 meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-crates.inc create mode 100644 meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can_0.1.0.bb create mode 100644 meta-egvirt/recipes-extended/vhost-device/README.md create mode 100644 meta-egvirt/recipes-extended/vhost-device/vhost-device-gpio-crates.inc create mode 100644 meta-egvirt/recipes-extended/vhost-device/vhost-device-gpio_0.1.0.bb create mode 100644 meta-egvirt/recipes-extended/vhost-device/vhost-device-rng-crates.inc create mode 100644 meta-egvirt/recipes-extended/vhost-device/vhost-device-rng_0.1.0.bb create mode 100644 meta-egvirt/recipes-kernel/kernel-module-virtio-loopback/kernel-module-virtio-loopback.bb delete mode 100644 meta-egvirt/recipes-kernel/kernel-module-virtio-loopback/virtio-loopback-driver.bb delete mode 100644 meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/Kbuild delete mode 100644 meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/Makefile delete mode 100644 meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/include/uapi/linux/virtio_video.h delete mode 100644 meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video.h delete mode 100644 meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_cam.c delete mode 100644 meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_caps.c delete mode 100644 meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_dec.c delete mode 100644 meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_device.c delete mode 100644 meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_driver.c delete mode 100644 meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_enc.c delete mode 100644 meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_helpers.c delete mode 100644 meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_vq.c delete mode 100644 meta-egvirt/recipes-kernel/kernel-module-virtio-video/kernel-module-virtio-video.bb create mode 100644 meta-egvirt/recipes-support/libgpiod/files/run-ptest create mode 100644 meta-egvirt/recipes-support/libgpiod/libgpiod.inc create mode 100644 meta-egvirt/recipes-support/libgpiod/libgpiod_2.1.bb delete mode 100644 meta-egvirt/recipes-virtioloopback/rust-vhost-device/rust-vhost-device_git.bb diff --git a/meta-egvirt/conf/include/agl-egvirt.inc b/meta-egvirt/conf/include/agl-egvirt.inc index 1cdfdf6b..40cb4ca7 100644 --- a/meta-egvirt/conf/include/agl-egvirt.inc +++ b/meta-egvirt/conf/include/agl-egvirt.inc @@ -1,19 +1,12 @@ -# gstreamer1.0-plugins-bad contains: -# * videoparsersbad plugin which contains h264parse element needed to demonstrate H.264 hardware decoding -# * waylandsink plugin -MACHINE_EXTRA_RDEPENDS:append = " \ - kernel-module-virtio-video \ - gstreamer1.0-plugins-bad \ -" +REQUIRED_VERSION_libgpiod = "2.1" -MACHINE_EXTRA_RDEPENDS:append = " \ - kernel-module-virtio-can \ -" +FEATURE_PACKAGES_virtio-loopback = " \ + kernel-module-virtio-can \ + kernel-module-virtio-loopback \ + vhost-device-rng \ + vhost-device-gpio \ + vhost-device-can \ + " -# add driver for supporting vhost devices loopback (virtio-loopback) -MACHINE_EXTRA_RDEPENDS:append = " \ - virtio-loopback-driver \ -" - -IMAGE_INSTALL:append = " vhost-device-i2c vhost-device-rng vhost-device-vsock vhost-device-gpio " +EXTRA_IMAGE_FEATURES += "virtio-loopback" diff --git a/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/CHANGELOG.md b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/CHANGELOG.md new file mode 100644 index 00000000..51d3f040 --- /dev/null +++ b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/CHANGELOG.md @@ -0,0 +1,15 @@ +# Changelog +## [Unreleased] + +### Added + +### Changed + +### Fixed + +### Deprecated + +## [0.1.0] + +First release + diff --git a/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/Cargo.toml b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/Cargo.toml new file mode 100644 index 00000000..08d012c2 --- /dev/null +++ b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "vhost-device-can" +version = "0.0.1" +authors = ["Timos Ampelikiotis "] +description = "vhost can backend device" +repository = "https://github.com/rust-vmm/vhost-device" +readme = "README.md" +keywords = ["can", "vhost", "virt", "backend"] +license = "Apache-2.0 OR BSD-3-Clause" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[features] +xen = ["vm-memory/xen", "vhost/xen", "vhost-user-backend/xen"] + +[dependencies] +queues = "1.0.2" +socketcan = "3.2" +clap = { version = "4.2.5", features = ["derive"] } +env_logger = "0.10" +libc = "0.2" +log = "0.4" +thiserror = "1.0" +vhost = { version = "0.8", features = ["vhost-user-slave"] } +vhost-user-backend = "0.10" +virtio-bindings = "0.2.1" +virtio-queue = "0.9" +vm-memory = "0.12" +vmm-sys-util = "0.11" + +[dev-dependencies] +assert_matches = "1.5" +virtio-queue = { version = "0.9", features = ["test-utils"] } +vm-memory = { version = "0.12", features = ["backend-mmap", "backend-atomic"] } diff --git a/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/LICENSE b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/LICENSE new file mode 100644 index 00000000..e69de29b diff --git a/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/README.md b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/README.md new file mode 100644 index 00000000..fd50c274 --- /dev/null +++ b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/README.md @@ -0,0 +1,66 @@ +# vhost-device-can - CAN emulation backend daemon + +## Description +This program is a vhost-user backend that emulates a VirtIO CAN device. +The device's binary takes three (3) parameters: a socket, a 'can-out' and a +'can-in' device name. The socket is commonly used across all vhost-devices to +communicate with the vhost-user frontend device. + +The 'can-out' represents +the actual CAN/FD device appears in the host system which vhost-device-can will +forward the messages from the frontend side. Finaly, the 'can-in' is again a +CAN/FD device connected on the host systems and vhost-device-can reads CAN/FD +frames and sends them to the frontend. The 'can-in' and 'can-out' can be find +by "ip link show" command. Also, the vhost-device-can may have the same CAN/FD +device name for both 'can-in' and 'can-out', if the user desires to setup a +loopback configuration. + + +This program is tested with Virtio-loopback's `-device vhost-user-can`. +Examples section below. + +## Synopsis + +**vhost-device-can** [*OPTIONS*] + +## Options + +.. program:: vhost-device-gpio + +.. option:: -h, --help + + Print help. + +.. option:: -s, --socket-path=PATH + +.. option:: -i, --can-int='CAN/FD interface name' + + The name of the input CAN interface to retrive CAN frames by + +.. option:: -o, --can-out='CAN/FD interface name' + + The name of the ouput CAN interface to send the CAN frames + +## Examples + +The daemon should be started first: + +:: + + host# vhost-device-can --socket-path=can.sock --can-in="can0" --can-out="can1" + +The virtio-looback invocation needs to insert the [virtio-loopback-transport](https://git.virtualopensystems.com/virtio-loopback/loopback_driver/-/tree/epsilon-release) driver +and then start the [virito-loopback-adapter](https://git.virtualopensystems.com/virtio-loopback/adapter_app/-/tree/epsilon-release) which is the intermediate between +vhost-device and virtio-loopback-transport driver. + +:: + + host# sudo insmod loopback_driver.ko + host# sudo ./adapter -s /path/to/can.sock0 -d vhucan + +## License + +This project is licensed under either of + +- [Apache License](http://www.apache.org/licenses/LICENSE-2.0), Version 2.0 +- [BSD-3-Clause License](https://opensource.org/licenses/BSD-3-Clause) diff --git a/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/backend.rs b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/backend.rs new file mode 100644 index 00000000..177c76cc --- /dev/null +++ b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/backend.rs @@ -0,0 +1,170 @@ +// VIRTIO CAN Emulation via vhost-user +// +// Copyright 2023 VIRTUAL OPEN SYSTEMS SAS. All Rights Reserved. +// Timos Ampelikiotis +// +// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause + +use log::{error, info, warn}; +use std::process::exit; +use std::sync::{Arc, RwLock}; +use std::thread::{spawn, JoinHandle}; + +use clap::Parser; +use thiserror::Error as ThisError; +use vhost::{vhost_user, vhost_user::Listener}; +use vhost_user_backend::VhostUserDaemon; +use vm_memory::{GuestMemoryAtomic, GuestMemoryMmap}; + +use crate::can::{CanController}; +use crate::vhu_can::VhostUserCanBackend; + +pub(crate) type Result = std::result::Result; + +#[derive(Debug, ThisError)] +/// Errors related to low level CAN helpers +pub(crate) enum Error { + #[error("Invalid socket count: {0}")] + SocketCountInvalid(usize), + #[error("Failed to join threads")] + FailedJoiningThreads, + #[error("Could not create can controller: {0}")] + CouldNotCreateCanController(crate::can::Error), + #[error("Could not create can backend: {0}")] + CouldNotCreateBackend(crate::vhu_can::Error), + #[error("Could not create daemon: {0}")] + CouldNotCreateDaemon(vhost_user_backend::Error), +} + +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct CanArgs { + /// Location of vhost-user Unix domain socket. This is suffixed by 0,1,2..socket_count-1. + #[clap(short, long)] + socket_path: String, + + /// A can device name to be used for reading (ex. vcan, can0, can1, ... etc.) + #[clap(short = 'i', long)] + can_in: String, + + /// A can device name to be used for writing (ex. vcan, can0, can1, ... etc.) + #[clap(short = 'o', long)] + can_out: String, + + /// Number of guests (sockets) to connect to. + #[clap(short = 'c', long, default_value_t = 1)] + socket_count: u32, +} + +#[derive(PartialEq, Debug)] +struct CanConfiguration { + socket_path: String, + socket_count: u32, + can_in: String, + can_out: String, +} + +impl TryFrom for CanConfiguration { + type Error = Error; + + fn try_from(args: CanArgs) -> Result { + + if args.socket_count == 0 { + return Err(Error::SocketCountInvalid(0)); + } + + let can_in = args.can_in.trim().to_string(); + let can_out = args.can_out.trim().to_string(); + + Ok(CanConfiguration { + socket_path: args.socket_path, + socket_count: args.socket_count, + can_in, + can_out, + }) + } +} + +fn start_backend(args: CanArgs) -> Result<()> { + + println!("start_backend function!\n"); + + let config = CanConfiguration::try_from(args).unwrap(); + let mut handles = Vec::new(); + + for _ in 0..config.socket_count { + let socket = config.socket_path.to_owned(); + let can_in = config.can_in.to_owned(); + let can_out = config.can_out.to_owned(); + + let handle: JoinHandle> = spawn(move || loop { + // A separate thread is spawned for each socket and can connect to a separate guest. + // These are run in an infinite loop to not require the daemon to be restarted once a + // guest exits. + // + // There isn't much value in complicating code here to return an error from the + // threads, and so the code uses unwrap() instead. The panic on a thread won't cause + // trouble to other threads/guests or the main() function and should be safe for the + // daemon. + + let controller = + CanController::new(can_in.clone(), can_out.clone()).map_err(Error::CouldNotCreateCanController)?; + let shared_controller_1 = Arc::new(RwLock::new(controller)); + let shared_controller_2 = shared_controller_1.clone(); + let vu_can_backend = Arc::new(RwLock::new( + VhostUserCanBackend::new(shared_controller_1).map_err(Error::CouldNotCreateBackend)?, + )); + let _read_hanlde = CanController::start_read_thread(shared_controller_2); + + let mut daemon = VhostUserDaemon::new( + String::from("vhost-device-can-backend"), + vu_can_backend.clone(), + GuestMemoryAtomic::new(GuestMemoryMmap::new()), + ) + .map_err(Error::CouldNotCreateDaemon)?; + + /* Start the read thread -- need to handle it after termination */ + let vring_workers = daemon.get_epoll_handlers(); + vu_can_backend.read() + .unwrap() + .set_vring_worker(&vring_workers[0]); + + let listener = Listener::new(socket.clone(), true).unwrap(); + daemon.start(listener).unwrap(); + + match daemon.wait() { + Ok(()) => { + info!("Stopping cleanly."); + } + Err(vhost_user_backend::Error::HandleRequest( + vhost_user::Error::PartialMessage | vhost_user::Error::Disconnected, + )) => { + info!("vhost-user connection closed with partial message. If the VM is shutting down, this is expected behavior; otherwise, it might be a bug."); + } + Err(e) => { + warn!("Error running daemon: {:?}", e); + } + } + + // No matter the result, we need to shut down the worker thread. + vu_can_backend.read().unwrap().exit_event.write(1).unwrap(); + }); + + handles.push(handle); + } + + for handle in handles { + handle.join().map_err(|_| Error::FailedJoiningThreads)??; + } + + Ok(()) +} + +pub(crate) fn can_init() { + env_logger::init(); + println!("Can_init function!"); + if let Err(e) = start_backend(CanArgs::parse()) { + error!("{e}"); + exit(1); + } +} diff --git a/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/can.rs b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/can.rs new file mode 100644 index 00000000..228266f6 --- /dev/null +++ b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/can.rs @@ -0,0 +1,264 @@ +// CAN backend device +// +// Copyright 2023 VIRTUAL OPEN SYSTEMS SAS. All Rights Reserved. +// Timos Ampelikiotis +// +// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause + +use log::{warn, error}; +use std::sync::{Arc, RwLock}; + +use thiserror::Error as ThisError; +use vm_memory::{ByteValued, Le16}; + +extern crate socketcan; +use socketcan::{ + CanFdSocket, CanFdFrame, CanAnyFrame, EmbeddedFrame, Socket, + Frame, StandardId, +}; + +use std::thread::{JoinHandle, spawn}; +use vmm_sys_util::eventfd::{EFD_NONBLOCK, EventFd}; + +extern crate queues; +use queues::*; + +use crate::vhu_can::{VirtioCanFrame, VIRTIO_CAN_STATUS_OK}; + +type Result = std::result::Result; + +#[derive(Copy, Clone, Debug, PartialEq, ThisError)] +/// Errors related to low level gpio helpers +pub(crate) enum Error { + //#[error("Can not enabled yet")] + //CanNotEnabled, + #[error("Can open socket operation failed")] + CanSocketFailed, + #[error("Can write socket operation failed")] + CanSocketWriteFailed, + #[error("Can read socket operation failed")] + CanSocketReadFailed, + #[error("Pop can element operation failed")] + CanPopFailed, + #[error("Creating Eventfd for CAN events failed")] + CanEventFdFailed, + #[error("CanQueueFailed")] + CanQueueFailed, +} + +/* CAN flags to determine type of CAN Id */ +pub(crate) const VIRTIO_CAN_FLAGS_EXTENDED: u32 = 0x8000; +pub(crate) const VIRTIO_CAN_FLAGS_FD: u32 = 0x4000; +pub(crate) const VIRTIO_CAN_FLAGS_RTR: u32 = 0x2000; + +pub(crate) const VIRTIO_CAN_TX: u16 = 0x0001; +pub(crate) const VIRTIO_CAN_RX: u16 = 0x0101; + +pub(crate) const CAN_EFF_FLAG: u32 = 0x80000000; /* EFF/SFF is set in the MSB */ +pub(crate) const CAN_RTR_FLAG: u32 = 0x40000000; /* remote transmission request */ +pub(crate) const CAN_ERR_FLAG: u32 = 0x20000000; /* error message frame */ + +pub(crate) const CAN_SFF_MASK: u32 = 0x000007FF; /* standard frame format (SFF) */ +pub(crate) const CAN_EFF_MASK: u32 = 0x1FFFFFFF; /* extended frame format (EFF) */ + +//pub(crate) const CAN_FRMF_BRS: u32 = 0x01; /* bit rate switch (2nd bitrate for data) */ +//pub(crate) const CAN_FRMF_ESI: u32 = 0x02; /* error state ind. of transmitting node */ +pub(crate) const CAN_FRMF_TYPE_FD: u32 = 0x10; /* internal bit ind. of CAN FD frame */ +pub(crate) const CAN_ERR_BUSOFF: u32 = 0x00000040; /* bus off */ + +/// Virtio Can Configuration +#[derive(Copy, Clone, Debug, Default, PartialEq)] +#[repr(C)] +pub(crate) struct VirtioCanConfig { + /* CAN controller status */ + pub(crate) status: Le16, +} + +// SAFETY: The layout of the structure is fixed and can be initialized by +// reading its content from byte array. +unsafe impl ByteValued for VirtioCanConfig {} + +#[derive(Debug)] +pub(crate) struct CanController { + config: VirtioCanConfig, + pub can_in_name: String, + pub can_out_name: String, + can_out_socket: CanFdSocket, + pub rx_event_fd: EventFd, + rx_fifo: Queue, +} + +impl CanController { + // Creates a new controller corresponding to `device`. + pub(crate) fn new(can_in_name: String, can_out_name: String) -> Result { + + let can_in_name = can_in_name.to_owned(); + println!("can_in_name: {:?}", can_in_name); + + let can_out_name = can_out_name.to_owned(); + println!("can_out_name: {:?}", can_out_name); + + let can_out_socket = Self::open_can_sockets(can_out_name.clone()); + + let rx_fifo = Queue::new(); + + let rx_efd = EventFd::new(EFD_NONBLOCK).map_err(|_| Error::CanEventFdFailed)?; + + Ok(CanController { + config: VirtioCanConfig { + status: 0x0.into(), + }, + can_in_name, + can_out_name, + can_out_socket, + rx_event_fd: rx_efd, + rx_fifo + }) + } + + pub fn print_can_frame (canframe: VirtioCanFrame) { + println!("canframe.msg_type 0x{:x}", canframe.msg_type.to_native()); + println!("canframe.can_id 0x{:x}", canframe.can_id.to_native()); + println!("canframe.length {}", canframe.length.to_native()); + println!("canframe.flags 0x{:x}", canframe.flags.to_native()); + if canframe.length.to_native() == 0 { + println!("[]"); + return; + } + print!("["); + let last_elem = canframe.length.to_native() as usize - 1; + for (index, sdu) in canframe.sdu.iter().enumerate() { + print!("0x{:x}, ", sdu); + if index == last_elem { + print!("0x{:x}", sdu); + break; + } + } + println!("]"); + } + + /* FIXME: This thread is not handle after termination */ + pub fn start_read_thread (controller: Arc>) -> JoinHandle> { + spawn(move || { + CanController::read_can_socket(controller) + } + ) + } + + pub fn push(&mut self, rx_elem: VirtioCanFrame) -> Result<()> { + match self.rx_fifo.add(rx_elem) { + Ok(_) => Ok(()), // Successfully added, so return Ok(()) + _ => Err(Error::CanQueueFailed), // Handle other errors + } + } + + pub fn pop(&mut self) -> Result { + match self.rx_fifo.remove() { + Ok(item) => Ok(item), + _ => Err(Error::CanPopFailed), + } + } + + fn open_can_sockets (can_out_name: String) -> CanFdSocket { + let can_out_socket = match CanFdSocket::open(&can_out_name) { + Ok(socket) => socket, + Err(_) => { + warn!("Error opening CAN socket"); + panic!("Failed to open CAN socket."); + //return Err(Error::CanSocketFailed); + } + }; + + can_out_socket + } + + pub fn read_can_socket (controller: Arc>) -> Result<()> { + let can_in_name = &controller.read().unwrap().can_in_name.clone(); + dbg!("Start reading from {} socket!", &can_in_name); + let socket = match CanFdSocket::open(&can_in_name) { + Ok(socket) => socket, + Err(_) => { + warn!("Error opening CAN socket"); + return Err(Error::CanSocketFailed); + } + }; + + // Receive CAN messages + loop { + if let Ok(frame) = socket.read_frame() { + + let mut controller = controller.write().unwrap(); + match frame { + CanAnyFrame::Normal(frame) => { + // Regular CAN frame + println!("Received CAN message: {:?}", frame); + } + CanAnyFrame::Fd(frame) => { + // CAN FD frame + println!("Received CAN FD message: {:?}", frame); + + let read_can_frame = VirtioCanFrame { + msg_type: VIRTIO_CAN_RX.into(), + can_id: frame.raw_id().into(), + length: (frame.data().len() as u16).into(), + reserved: 0.into(), + flags: frame.id_flags().bits().into(), + sdu: { + let mut sdu_data: [u8; 64] = [0; 64]; + for i in 0..frame.data().len() { + sdu_data[i] = frame.data()[i]; + } + sdu_data + }, + }; + + match controller.push(read_can_frame) { + Ok(_) => warn!("New Can frame was received"), + Err(_) => { + warn!("Error read/push CAN frame"); + return Err(Error::CanSocketReadFailed); + } + } + } + CanAnyFrame::Remote(frame) => { + // Remote CAN frame + println!("Received Remote CAN message: {:?}", frame); + } + CanAnyFrame::Error(frame) => { + // Error frame + println!("Received Error frame: {:?}", frame); + } + } + + controller.rx_event_fd.write(1).unwrap(); + } + } + } + + pub(crate) fn config(&self) -> &VirtioCanConfig { + log::trace!("Get config\n"); + &self.config + } + + pub(crate) fn operation(&self, tx_request: VirtioCanFrame) -> Result { + log::trace!("Can operation\n"); + + // Create a CAN frame with a specific CAN-ID and the data buffer + let can_id = StandardId::new(tx_request.can_id.to_native().try_into().unwrap()).unwrap(); + let data_len = tx_request.length.to_native() as usize; + + let data: Vec = tx_request.sdu.iter().cloned().take(data_len).collect(); + let frame = CanFdFrame::new(can_id, &data).unwrap(); + + // Send the CAN frame + let write_result = self.can_out_socket.write_frame(&frame); + match write_result { + Ok(_) => Ok(VIRTIO_CAN_STATUS_OK), + Err(_) => { + warn!("Error write CAN socket"); + Err(Error::CanSocketWriteFailed) + } + } + } +} + diff --git a/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/main.rs b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/main.rs new file mode 100644 index 00000000..e89934ea --- /dev/null +++ b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/main.rs @@ -0,0 +1,26 @@ +// VIRTIO CAN Emulation via vhost-user +// +// Copyright 2023 VIRTUAL OPEN SYSTEMS SAS. All Rights Reserved. +// Timos Ampelikiotis +// +// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause + +#[cfg(target_env = "gnu")] +mod backend; +#[cfg(target_env = "gnu")] +mod can; +#[cfg(target_env = "gnu")] +mod vhu_can; + +#[cfg(target_env = "gnu")] +fn main() { + println!("Hello to main vhost-user-can"); + backend::can_init() +} + +// Rust vmm container (https://github.com/rust-vmm/rust-vmm-container) doesn't +// have tools to do a musl build at the moment, and adding that support is +// tricky as well to the container. Skip musl builds until the time pre-built +// libgpiod library is available for musl. +#[cfg(target_env = "musl")] +fn main() {} diff --git a/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/vhu_can.rs b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/vhu_can.rs new file mode 100644 index 00000000..6aa12488 --- /dev/null +++ b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/vhu_can.rs @@ -0,0 +1,732 @@ +// vhost device can +// +// Copyright 2023 VIRTUAL OPEN SYSTEMS SAS. All Rights Reserved. +// Timos Ampelikiotis +// +// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause + +use log::{warn, error}; +use std::mem::size_of; +use std::slice::from_raw_parts; +use std::sync::{Arc, RwLock}; +use std::{ + convert, + io::{self, Result as IoResult}, +}; +use std::os::fd::AsRawFd; +use thiserror::Error as ThisError; +use vhost::vhost_user::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures}; +use vhost_user_backend::{VhostUserBackendMut, VringRwLock, VringT}; +use virtio_bindings::bindings::virtio_config::{VIRTIO_F_NOTIFY_ON_EMPTY, VIRTIO_F_VERSION_1}; +use virtio_bindings::bindings::virtio_ring::{ + VIRTIO_RING_F_EVENT_IDX, VIRTIO_RING_F_INDIRECT_DESC, +}; +use virtio_queue::{DescriptorChain, QueueOwnedT}; +use vm_memory::{ + ByteValued, Bytes, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryLoadGuard, + GuestMemoryMmap, Le16, Le32, +}; +use vmm_sys_util::epoll::EventSet; +use vmm_sys_util::eventfd::{EventFd, EFD_NONBLOCK}; +use crate::can::{ + CanController, CAN_EFF_FLAG, CAN_RTR_FLAG, CAN_ERR_FLAG, CAN_SFF_MASK, + CAN_EFF_MASK, VIRTIO_CAN_FLAGS_FD, VIRTIO_CAN_FLAGS_RTR, + VIRTIO_CAN_FLAGS_EXTENDED, VIRTIO_CAN_TX, VIRTIO_CAN_RX, + CAN_FRMF_TYPE_FD, CAN_ERR_BUSOFF, +}; +use vhost_user_backend::VringEpollHandler; + +/// Feature bit numbers +pub const VIRTIO_CAN_F_CAN_CLASSIC: u16 = 0; +pub const VIRTIO_CAN_F_CAN_FD: u16 = 1; +//pub const VIRTIO_CAN_F_LATE_TX_ACK: u16 = 2; +pub const VIRTIO_CAN_F_RTR_FRAMES: u16 = 3; + +/// Possible values of the status field +pub const VIRTIO_CAN_STATUS_OK: u8 = 0x0; +pub const VIRTIO_CAN_STATUS_ERR: u8 = 0x1; + +/// CAN Control messages +const VIRTIO_CAN_SET_CTRL_MODE_START: u16 = 0x0201; +const VIRTIO_CAN_SET_CTRL_MODE_STOP: u16 = 0x0202; + +/// Virtio configuration +const QUEUE_SIZE: usize = 64; +const NUM_QUEUES: usize = 3; + +/// Queues +const TX_QUEUE: u16 = 0; +const RX_QUEUE: u16 = 1; +const CTRL_QUEUE: u16 = 2; +const BACKEND_EFD: u16 = 4; + +type Result = std::result::Result; + +#[derive(Copy, Clone, Debug, PartialEq, ThisError)] +/// Errors related to vhost-device-gpio-daemon. +pub(crate) enum Error { + #[error("Failed to handle event, didn't match EPOLLIN")] + HandleEventNotEpollIn, + #[error("Failed to handle unknown event")] + HandleEventUnknown, + #[error("Received unexpected write only descriptor at index {0}")] + UnexpectedWriteOnlyDescriptor(usize), + #[error("Received unexpected readable descriptor at index {0}")] + UnexpectedReadableDescriptor(usize), + #[error("Invalid descriptor count {0}")] + UnexpectedDescriptorCount(usize), + #[error("Invalid descriptor size, expected: {0}, found: {1}")] + UnexpectedDescriptorSize(usize, u32), + #[error("Descriptor not found")] + DescriptorNotFound, + #[error("Descriptor read failed")] + DescriptorReadFailed, + #[error("Descriptor write failed")] + DescriptorWriteFailed, + #[error("Failed to send notification")] + NotificationFailed, + #[error("Failed to create new EventFd")] + EventFdFailed, + #[error("Unknown can message type: {0}")] + UnexpectedCanMsgType(u16), + #[error("RTR frames not negotiated")] + UnexpectedRtrFlag, + #[error("Can FD frames not negotiated")] + UnexpectedFdFlag, + #[error("Classic CAN frames not negotiated")] + UnexpectedClassicFlag, +} + +impl convert::From for io::Error { + fn from(e: Error) -> Self { + io::Error::new(io::ErrorKind::Other, e) + } +} + +/// Virtio CAN Request / Response messages +/// +/// The response message is a stream of bytes, where first byte represents the +/// status, and rest is message specific data. + +#[derive(Copy, Clone, Default)] +#[repr(C)] +struct VirtioCanTxResponse { + result: i8, +} +// SAFETY: The layout of the structure is fixed and can be initialized by +// reading its content from byte array. +unsafe impl ByteValued for VirtioCanTxResponse {} + +#[derive(Copy, Clone, Debug)] +#[repr(C)] +pub struct VirtioCanFrame { + pub msg_type: Le16, + pub length: Le16, /* 0..8 CC, 0..64 CAN­FD, 0..2048 CAN­XL, 12 bits */ + pub reserved: Le32, /* May be needed in part for CAN XL priority */ + pub flags: Le32, + pub can_id: Le32, + pub sdu: [u8; 64], +} + +impl Default for VirtioCanFrame { + fn default() -> Self { + VirtioCanFrame { + msg_type: Le16::default(), + length: Le16::default(), + reserved: Le32::default(), + flags: Le32::default(), + can_id: Le32::default(), + sdu: [0; 64], // Initialize "asd" with default value (0 in this case) + } + } +} + +// SAFETY: The layout of the structure is fixed and can be initialized by +// reading its content from byte array. +unsafe impl ByteValued for VirtioCanFrame {} + +#[derive(Copy, Clone, Default)] +#[repr(C)] +struct VirtioCanCtrlRequest { + msg_type: Le16, +} +// SAFETY: The layout of the structure is fixed and can be initialized by +// reading its content from byte array. +unsafe impl ByteValued for VirtioCanCtrlRequest {} + +#[derive(Copy, Clone, Default)] +#[repr(C)] +struct VirtioCanCtrlResponse { + result: i8, +} +// SAFETY: The layout of the structure is fixed and can be initialized by +// reading its content from byte array. +unsafe impl ByteValued for VirtioCanCtrlResponse {} + +pub(crate) struct VhostUserCanBackend { + controller: Arc>, + acked_features: u64, + event_idx: bool, + pub(crate) exit_event: EventFd, + mem: Option>, +} + +type CanDescriptorChain = DescriptorChain>>; + +impl VhostUserCanBackend { + pub(crate) fn new(controller: Arc>) -> Result { + Ok(VhostUserCanBackend { + controller: controller, + event_idx: false, + acked_features: 0x0, + exit_event: EventFd::new(EFD_NONBLOCK).map_err(|_| Error::EventFdFailed)?, + mem: None, + }) + } + + fn check_features (&self, features: u16) -> bool { + (self.acked_features & (1 << features)) != 0 + } + + fn process_ctrl_requests( + &self, + requests: Vec, + vring: &VringRwLock + ) -> Result { + dbg!("process_ctrl_requests"); + + if requests.is_empty() { + return Ok(true); + } + + for desc_chain in requests { + let descriptors: Vec<_> = desc_chain.clone().collect(); + + if descriptors.len() < 1 { + warn!("Error::UnexpectedDescriptorCount"); + return Err(Error::UnexpectedDescriptorCount(descriptors.len())); + } + + println!("descriptors.len(): {:?}", descriptors.len()); + + let desc_request = descriptors[0]; + if desc_request.is_write_only() { + warn!("Error::UnexpectedWriteOnlyDescriptor"); + return Err(Error::UnexpectedWriteOnlyDescriptor(0)); + } + + if desc_request.len() as usize != size_of::() { + println!("UnexpectedDescriptorSize, len = {:?}", desc_request.len()); + return Err(Error::UnexpectedDescriptorSize( + size_of::(), + desc_request.len(), + )); + } + + let request = desc_chain + .memory() + .read_obj::(desc_request.addr()) + .map_err(|_| Error::DescriptorReadFailed)?; + + + match request.msg_type.into() { + VIRTIO_CAN_SET_CTRL_MODE_START => { + println!("VIRTIO_CAN_SET_CTRL_MODE_START"); + //vcan->busoff = false; + Ok(()) + } + VIRTIO_CAN_SET_CTRL_MODE_STOP => { + println!("VIRTIO_CAN_SET_CTRL_MODE_STOP"); + //vcan->busoff = false; + Ok(()) + } + _ => { + println!("Ctrl queue: msg type 0x{:?} unknown", request.msg_type); + return Err(Error::HandleEventUnknown.into()) + }, + }?; + + let desc_response = descriptors[1]; + if !desc_response.is_write_only() { + println!("This is not wirtable"); + return Err(Error::UnexpectedReadableDescriptor(1)); + } + + let response = VIRTIO_CAN_STATUS_OK; + + desc_chain + .memory() + .write_slice(response.as_slice(), desc_response.addr()) + .map_err(|_| Error::DescriptorWriteFailed)?; + + if vring.add_used(desc_chain.head_index(), desc_response.len()).is_err() { + println!("Couldn't return used descriptors to the ring"); + warn!("Couldn't return used descriptors to the ring"); + } + } + + Ok(true) + } + + fn process_tx_requests( + &self, + requests: Vec, + vring: &VringRwLock + ) -> Result { + dbg!("process_tx_requests"); + + if requests.is_empty() { + return Ok(true); + } + + println!("requests.len: {:?}", requests.len()); + for desc_chain in requests { + let descriptors: Vec<_> = desc_chain.clone().collect(); + + if descriptors.len() != 2 { + println!("Error::UnexpectedDescriptorCount"); + return Err(Error::UnexpectedDescriptorCount(descriptors.len())); + } + + let desc_request = descriptors[0]; + if desc_request.is_write_only() { + println!("Error::UnexpectedReadOnlyDescriptor"); + return Err(Error::UnexpectedWriteOnlyDescriptor(0)); + } + + if desc_request.len() as usize != size_of::() { + println!("Tx UnexpectedDescriptorSize, len = {:?}", desc_request.len()); + //return Err(Error::UnexpectedDescriptorSize( + // size_of::(), + // desc_request.len(), + //)); + } + + let request = desc_chain + .memory() + .read_obj::(desc_request.addr()) + .map_err(|_| Error::DescriptorReadFailed)?; + + CanController::print_can_frame(request); + + let msg_type = request.msg_type.to_native(); + let mut can_id = request.can_id.to_native(); + let mut flags = request.flags.to_native(); + let mut length = request.length.to_native(); + + if msg_type != VIRTIO_CAN_TX { + warn!("TX: Message type 0x{:x} unknown\n", msg_type); + return Err(Error::UnexpectedCanMsgType(msg_type)); + } + + if (flags & VIRTIO_CAN_FLAGS_FD) != 0 { + if length > 64 { + println!("Cut sdu_len from {:?} to 64\n", request.length); + length = 64; + } + } else { + if length > 8 { + println!("Cut sdu_len from {:?} to 8\n", request.length); + length = 8; + } + } + + /* + * Copy Virtio frame structure to qemu frame structure and + * check while doing this whether the frame type was negotiated + */ + if (flags & VIRTIO_CAN_FLAGS_EXTENDED) != 0 { + flags &= CAN_EFF_MASK; + flags |= CAN_EFF_FLAG; + } else { + flags &= CAN_SFF_MASK; + } + + if (flags & VIRTIO_CAN_FLAGS_RTR) != 0 { + if !self.check_features(VIRTIO_CAN_F_CAN_CLASSIC) || + !self.check_features(VIRTIO_CAN_F_RTR_FRAMES) { + warn!("TX: RTR frames not negotiated"); + return Err(Error::UnexpectedRtrFlag); + } + can_id |= flags | CAN_RTR_FLAG; + } + + if (flags & VIRTIO_CAN_FLAGS_FD) != 0 { + if !self.check_features(VIRTIO_CAN_F_CAN_FD) { + warn!("TX: FD frames not negotiated\n"); + return Err(Error::UnexpectedFdFlag); + } + flags |= CAN_FRMF_TYPE_FD; + } else { + if !self.check_features(VIRTIO_CAN_F_CAN_CLASSIC) { + warn!("TX: Classic frames not negotiated\n"); + return Err(Error::UnexpectedClassicFlag); + } + flags = 0; + } + + let mut corrected_request = VirtioCanFrame::default(); + corrected_request.msg_type = msg_type.into(); + corrected_request.can_id = can_id.into(); + corrected_request.flags = flags.into(); + corrected_request.length = length.into(); + corrected_request.sdu.copy_from_slice(&request.sdu[0..64]); + + let desc_response = descriptors[1]; + if !desc_response.is_write_only() { + println!("Error::UnexpectedWriteOnlyDescriptor"); + return Err(Error::UnexpectedReadableDescriptor(1)); + } + + let response = match self.controller.write().unwrap().operation(corrected_request) { + Ok(result) => { + result + } + Err(_) => { + warn!("We got an error from controller send func"); + VIRTIO_CAN_STATUS_ERR + } + }; + + desc_chain + .memory() + .write_slice(response.as_slice(), desc_response.addr()) + .map_err(|_| Error::DescriptorWriteFailed)?; + + if vring.add_used(desc_chain.head_index(), desc_response.len()).is_err() { + println!("Couldn't return used descriptors to the ring"); + warn!("Couldn't return used descriptors to the ring"); + } + } + + Ok(true) + } + + fn process_rx_requests( + &mut self, + requests: Vec, + vring: &VringRwLock + ) -> Result { + dbg!("process_rx_requests"); + + if requests.is_empty() { + return Ok(true); + } + + let desc_chain = &requests[0]; + let descriptors: Vec<_> = desc_chain.clone().collect(); + + if descriptors.len() != 1 { + println!("Error::UnexpectedDescriptorCount"); + return Err(Error::UnexpectedDescriptorCount(descriptors.len())); + } + + let desc_response = descriptors[0]; + if !desc_response.is_write_only() { + return Err(Error::UnexpectedReadableDescriptor(1)); + } + + let mut response = match self.controller.write().unwrap().pop() { + Ok(item) => item, + Err(_) => return Err(Error::HandleEventUnknown), + }; + + CanController::print_can_frame(response); + + if (response.can_id.to_native() & CAN_ERR_FLAG) != 0 { + if (response.can_id.to_native() & CAN_ERR_BUSOFF) != 0 { + warn!("Got BusOff error frame, device does a local bus off\n"); + //vcan->busoff = true; + } else { + println!("Dropping error frame 0x{:x}\n", response.can_id.to_native()); + } + return Ok(true); + } + + let mut can_rx = VirtioCanFrame::default(); + can_rx.msg_type = VIRTIO_CAN_RX.into(); + can_rx.can_id = response.can_id; + can_rx.length = response.length; + can_rx.flags = (can_rx.flags.to_native() | VIRTIO_CAN_FLAGS_FD).into(); + + if (response.flags.to_native() & CAN_FRMF_TYPE_FD) != 0 { + if !self.check_features(VIRTIO_CAN_F_CAN_FD) { + warn!("Drop non-supported CAN FD frame"); + return Err(Error::UnexpectedFdFlag); + } + } else { + if !self.check_features(VIRTIO_CAN_F_CAN_CLASSIC) { + warn!("Drop non-supported CAN classic frame"); + return Err(Error::UnexpectedClassicFlag); + } + } + if (response.can_id.to_native() & CAN_RTR_FLAG) != 0 && + !self.check_features(VIRTIO_CAN_F_RTR_FRAMES) { + warn!("Drop non-supported RTR frame"); + return Err(Error::UnexpectedRtrFlag); + } + + if (response.can_id.to_native() & CAN_EFF_FLAG) != 0 { + can_rx.flags = VIRTIO_CAN_FLAGS_EXTENDED.into(); + can_rx.can_id = (response.can_id.to_native() & CAN_EFF_MASK).into(); + } else { + can_rx.can_id = (response.can_id.to_native() & CAN_SFF_MASK).into(); + } + if (response.can_id.to_native() & CAN_RTR_FLAG) != 0 { + can_rx.flags = (can_rx.flags.to_native() & VIRTIO_CAN_FLAGS_RTR).into(); + } + + // HACK AHEAD: Vcan can not be comfigured as CANFD interface, but possible + // to configure its MTU to 64 bytes. So if a messages bigger than 8 bytes + // is being received we consider it as CANFD message. + let can_in_name = self.controller.read().unwrap().can_in_name.clone(); + if self.check_features(VIRTIO_CAN_F_CAN_FD) && + response.length.to_native() > 8 && can_in_name == "vcan0" { + response.flags = (response.flags.to_native() | CAN_FRMF_TYPE_FD).into(); + warn!("\n\n\nCANFD VCAN0\n\n"); + } + + if (response.flags.to_native() & CAN_FRMF_TYPE_FD) != 0 { + can_rx.flags = (can_rx.flags.to_native() | VIRTIO_CAN_FLAGS_FD).into(); + if response.length.to_native() > 64 { + warn!("%s(): Cut length from {} to 64\n", response.length.to_native()); + can_rx.length = 64.into(); + } + } else { + if response.length.to_native() > 8 { + warn!("%s(): Cut length from {} to 8\n", response.length.to_native()); + can_rx.length = 8.into(); + } + } + + can_rx.sdu.copy_from_slice(&response.sdu[0..64]); + CanController::print_can_frame(can_rx); + + desc_chain + .memory() + .write_slice(can_rx.as_slice(), desc_response.addr()) + .map_err(|_| Error::DescriptorWriteFailed)?; + + if vring.add_used(desc_chain.head_index(), desc_response.len()).is_err() { + warn!("Couldn't return used descriptors to the ring"); + } + + Ok(true) + } + + /// Process the messages in the vring and dispatch replies + fn process_ctrl_queue(&mut self, vring: &VringRwLock) -> Result<()> { + dbg!("process_ctrl_queue"); + let requests: Vec<_> = vring + .get_mut() + .get_queue_mut() + .iter(self.mem.as_ref().unwrap().memory()) + .map_err(|_| Error::DescriptorNotFound)? + .collect(); + + if self.process_ctrl_requests(requests, vring)? { + // Send notification once all the requests are processed + vring + .signal_used_queue() + .map_err(|_| Error::NotificationFailed)?; + } + Ok(()) + } + + /// Process the messages in the vring and dispatch replies + fn process_tx_queue(&self, vring: &VringRwLock) -> Result<()> { + dbg!("process_tx_queue"); + let requests: Vec<_> = vring + .get_mut() + .get_queue_mut() + .iter(self.mem.as_ref().unwrap().memory()) + .map_err(|_| Error::DescriptorNotFound)? + .collect(); + + if self.process_tx_requests(requests, vring)? { + // Send notification once all the requests are processed + vring + .signal_used_queue() + .map_err(|_| { + println!("signal_used_queue error"); + Error::NotificationFailed + })?; + } + + Ok(()) + } + + /// Process the messages in the vring and dispatch replies + fn process_rx_queue(&mut self, vring: &VringRwLock) -> Result<()> { + dbg!("process_rx_queue"); + let requests: Vec<_> = vring + .get_mut() + .get_queue_mut() + .iter(self.mem.as_ref().unwrap().memory()) + .map_err(|_| Error::DescriptorNotFound)? + .collect(); + + if self.process_rx_requests(requests, vring)? { + // Send notification once all the requests are processed + vring + .signal_used_queue() + .map_err(|_| { + println!("NotificationFailed"); + Error::NotificationFailed + })?; + } + Ok(()) + } + + fn process_rx_queue_dump(&mut self, _vring: &VringRwLock) -> Result<()> { + dbg!("Do nothing, if you reach that point!"); + Ok(()) + } + + /// Set self's VringWorker. + pub(crate) fn set_vring_worker( + &self, + vring_worker: &Arc>, VringRwLock, ()>>, + ) { + let rx_event_fd = self.controller.read().unwrap().rx_event_fd.as_raw_fd(); + vring_worker + .register_listener( + rx_event_fd, + EventSet::IN, + //u64::from(BACKEND_EFD)) + 4u64 as u64) + .unwrap(); + } +} + +/// VhostUserBackendMut trait methods +impl VhostUserBackendMut + for VhostUserCanBackend +{ + fn num_queues(&self) -> usize { + println!("num_queues: {:?}", NUM_QUEUES); + NUM_QUEUES + } + + fn max_queue_size(&self) -> usize { + println!("max_queue_size: {:?}", QUEUE_SIZE); + QUEUE_SIZE + } + + fn features(&self) -> u64 { + // this matches the current libvhost defaults except VHOST_F_LOG_ALL + let features = 1 << VIRTIO_F_VERSION_1 + | 1 << VIRTIO_F_NOTIFY_ON_EMPTY + | 1 << VIRTIO_RING_F_EVENT_IDX + | 1 << VIRTIO_CAN_F_CAN_CLASSIC + | 1 << VIRTIO_CAN_F_CAN_FD + | 1 << VIRTIO_RING_F_INDIRECT_DESC + | VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits(); + + println!("vhu_can->features: {:x}", features); + features + } + + fn acked_features(&mut self, _features: u64) { + println!("\nacked_features: 0x{:x}\n", _features); + self.acked_features = _features; + } + + fn protocol_features(&self) -> VhostUserProtocolFeatures { + let protocol_features = VhostUserProtocolFeatures::MQ + | VhostUserProtocolFeatures::CONFIG + | VhostUserProtocolFeatures::REPLY_ACK; + //| VhostUserProtocolFeatures::STATUS + + println!("protocol_features: {:x}", protocol_features); + protocol_features + } + + fn get_config(&self, offset: u32, size: u32) -> Vec { + // SAFETY: The layout of the structure is fixed and can be initialized by + // reading its content from byte array. + dbg!("vhu_can->get_config"); + unsafe { + from_raw_parts( + self.controller.write().unwrap() + .config() + .as_slice() + .as_ptr() + .offset(offset as isize) as *const _ as *const _, + size as usize, + ) + .to_vec() + } + } + + fn set_event_idx(&mut self, enabled: bool) { + dbg!(self.event_idx = enabled); + } + + fn update_memory(&mut self, mem: GuestMemoryAtomic) -> IoResult<()> { + dbg!("update_memory\n"); + self.mem = Some(mem); + Ok(()) + } + + fn handle_event( + &mut self, + device_event: u16, + evset: EventSet, + vrings: &[VringRwLock], + _thread_id: usize, + ) -> IoResult { + dbg!("\nhandle_event:"); + + if evset != EventSet::IN { + return Err(Error::HandleEventNotEpollIn.into()); + } + if device_event == RX_QUEUE { + println!("RX_QUEUE\n"); + return Ok(false); + }; + let vring = if device_event != BACKEND_EFD { + &vrings[device_event as usize] + } else { + println!("BACKEND_EFD\n"); + let _ = self.controller.write().unwrap().rx_event_fd.read(); + &vrings[RX_QUEUE as usize] + }; + if self.event_idx { + // vm-virtio's Queue implementation only checks avail_index + // once, so to properly support EVENT_IDX we need to keep + // calling process_request_queue() until it stops finding + // new requests on the queue. + loop { + vring.disable_notification().unwrap(); + //match queue_idx { + match device_event { + CTRL_QUEUE => self.process_ctrl_queue(vring), + TX_QUEUE => self.process_tx_queue(vring), + RX_QUEUE => self.process_rx_queue_dump(vring), + BACKEND_EFD => self.process_rx_queue(vring), + _ => Err(Error::HandleEventUnknown.into()), + }?; + if !vring.enable_notification().unwrap() { + break; + } + } + } else { + // Without EVENT_IDX, a single call is enough. + match device_event { + CTRL_QUEUE => self.process_ctrl_queue(vring), + TX_QUEUE => self.process_tx_queue(vring), + RX_QUEUE => self.process_rx_queue_dump(vring), + BACKEND_EFD => self.process_rx_queue(vring), + _ => Err(Error::HandleEventUnknown.into()), + }?; + } + Ok(false) + } + + fn exit_event(&self, _thread_index: usize) -> Option { + dbg!("exit_event\n"); + self.exit_event.try_clone().ok() + } +} + diff --git a/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-crates.inc b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-crates.inc new file mode 100644 index 00000000..cf73bc44 --- /dev/null +++ b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-crates.inc @@ -0,0 +1,83 @@ +SRC_URI += " \ + crate://crates.io/serde_derive/1.0.193 \ + crate://crates.io/autocfg/1.1.0 \ + crate://crates.io/syn/1.0.109 \ + crate://crates.io/serde/1.0.193 \ + crate://crates.io/memoffset/0.7.0 \ + crate://crates.io/static_assertions/1.1.0 \ + crate://crates.io/pin-utils/0.1.0 \ + crate://crates.io/cfg-if/1.0.0 \ + crate://crates.io/neli-proc-macros/0.1.3 \ + crate://crates.io/byteorder/1.5.0 \ + crate://crates.io/either/1.9.0 \ + crate://crates.io/nix/0.26.0 \ + crate://crates.io/neli/0.6.4 \ + crate://crates.io/nb/1.1.0 \ + crate://crates.io/itertools/0.10.0 \ + crate://crates.io/hex/0.4.3 \ + crate://crates.io/embedded-can/0.4.1 \ + crate://crates.io/byte_conv/0.1.1 \ + crate://crates.io/queues/1.1.0 \ + crate://crates.io/socketcan/3.3.0 \ + crate://crates.io/aho-corasick/1.0.2 \ + crate://crates.io/anstream/0.3.2 \ + crate://crates.io/anstyle/1.0.1 \ + crate://crates.io/anstyle-parse/0.2.1 \ + crate://crates.io/anstyle-query/1.0.0 \ + crate://crates.io/anstyle-wincon/1.0.1 \ + crate://crates.io/arc-swap/1.6.0 \ + crate://crates.io/assert_matches/1.5.0 \ + crate://crates.io/bitflags/1.3.2 \ + crate://crates.io/bitflags/2.3.3 \ + crate://crates.io/cc/1.0.79 \ + crate://crates.io/clap/4.2.5 \ + crate://crates.io/clap_builder/4.2.5 \ + crate://crates.io/clap_derive/4.2.0 \ + crate://crates.io/clap_lex/0.4.0 \ + crate://crates.io/colorchoice/1.0.0 \ + crate://crates.io/env_logger/0.10.0 \ + crate://crates.io/errno/0.3.1 \ + crate://crates.io/errno-dragonfly/0.1.2 \ + crate://crates.io/heck/0.4.1 \ + crate://crates.io/hermit-abi/0.3.2 \ + crate://crates.io/humantime/2.1.0 \ + crate://crates.io/is-terminal/0.4.9 \ + crate://crates.io/libc/0.2.147 \ + crate://crates.io/linux-raw-sys/0.4.3 \ + crate://crates.io/log/0.4.19 \ + crate://crates.io/memchr/2.5.0 \ + crate://crates.io/once_cell/1.18.0 \ + crate://crates.io/proc-macro2/1.0.67 \ + crate://crates.io/quote/1.0.29 \ + crate://crates.io/regex/1.9.1 \ + crate://crates.io/regex-automata/0.3.2 \ + crate://crates.io/regex-syntax/0.7.4 \ + crate://crates.io/rustix/0.38.3 \ + crate://crates.io/strsim/0.10.0 \ + crate://crates.io/syn/2.0.28 \ + crate://crates.io/termcolor/1.2.0 \ + crate://crates.io/thiserror/1.0.41 \ + crate://crates.io/thiserror-impl/1.0.41 \ + crate://crates.io/unicode-ident/1.0.11 \ + crate://crates.io/utf8parse/0.2.1 \ + crate://crates.io/vhost/0.8.0 \ + crate://crates.io/vhost-user-backend/0.10.0 \ + crate://crates.io/virtio-bindings/0.2.1 \ + crate://crates.io/virtio-queue/0.9.0 \ + crate://crates.io/vm-memory/0.12.0 \ + crate://crates.io/vmm-sys-util/0.11.1 \ + crate://crates.io/winapi/0.3.9 \ + crate://crates.io/winapi-i686-pc-windows-gnu/0.4.0 \ + crate://crates.io/winapi-util/0.1.5 \ + crate://crates.io/winapi-x86_64-pc-windows-gnu/0.4.0 \ + crate://crates.io/windows-sys/0.48.0 \ + crate://crates.io/windows-targets/0.48.1 \ + crate://crates.io/windows_aarch64_gnullvm/0.48.0 \ + crate://crates.io/windows_aarch64_msvc/0.48.0 \ + crate://crates.io/windows_i686_gnu/0.48.0 \ + crate://crates.io/windows_i686_msvc/0.48.0 \ + crate://crates.io/windows_x86_64_gnu/0.48.0 \ + crate://crates.io/windows_x86_64_gnullvm/0.48.0 \ + crate://crates.io/windows_x86_64_msvc/0.48.0 \ +" + diff --git a/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can_0.1.0.bb b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can_0.1.0.bb new file mode 100644 index 00000000..c18e7517 --- /dev/null +++ b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can_0.1.0.bb @@ -0,0 +1,18 @@ +SUMMARY = "vhost CAN backend device" +DESCRIPTION = "A vhost-user backend that emulates a VirtIO CAN device" +HOMEPAGE = "https://gerrit.automotivelinux.org" + +FILESEXTRAPATHS:prepend := "${THISDIR}:" +EXTRAPATHS:prepend := "${THISDIR}:" + +SRC_URI = " file://. " + +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "\ + file://LICENSE;md5=d41d8cd98f00b204e9800998ecf8427e \ +" + +inherit cargo +inherit pkgconfig + +include vhost-device-can-crates.inc diff --git a/meta-egvirt/recipes-extended/vhost-device/README.md b/meta-egvirt/recipes-extended/vhost-device/README.md new file mode 100644 index 00000000..950ffca9 --- /dev/null +++ b/meta-egvirt/recipes-extended/vhost-device/README.md @@ -0,0 +1,12 @@ +# AGL info +This folder contains meta-virtualization recipes from master. We copy them here +waiting for vhost-device for being available for kirkstone (or AGL moving +forward). + +# vhost-device: A collection of vhost-user devices + +[vhost-device](https://github.com/rust-vmm/vhost-device) provides a series of +daemons that implement the +[vhost-user protocol](https://qemu-project.gitlab.io/qemu/interop/vhost-user.html) +for various virtio device types. + diff --git a/meta-egvirt/recipes-extended/vhost-device/vhost-device-gpio-crates.inc b/meta-egvirt/recipes-extended/vhost-device/vhost-device-gpio-crates.inc new file mode 100644 index 00000000..4d73c1fd --- /dev/null +++ b/meta-egvirt/recipes-extended/vhost-device/vhost-device-gpio-crates.inc @@ -0,0 +1,184 @@ +# Autogenerated with 'bitbake -c update_crates vhost-device-gpio' + +# from Cargo.lock +SRC_URI += " \ + crate://crates.io/aho-corasick/1.0.2 \ + crate://crates.io/anstream/0.3.2 \ + crate://crates.io/anstyle/1.0.1 \ + crate://crates.io/anstyle-parse/0.2.1 \ + crate://crates.io/anstyle-query/1.0.0 \ + crate://crates.io/anstyle-wincon/1.0.1 \ + crate://crates.io/arc-swap/1.6.0 \ + crate://crates.io/assert_matches/1.5.0 \ + crate://crates.io/bindgen/0.63.0 \ + crate://crates.io/bitflags/1.3.2 \ + crate://crates.io/bitflags/2.3.3 \ + crate://crates.io/cc/1.0.79 \ + crate://crates.io/cexpr/0.6.0 \ + crate://crates.io/cfg-if/1.0.0 \ + crate://crates.io/clang-sys/1.6.1 \ + crate://crates.io/clap/4.3.19 \ + crate://crates.io/clap_builder/4.3.19 \ + crate://crates.io/clap_derive/4.3.12 \ + crate://crates.io/clap_lex/0.5.0 \ + crate://crates.io/colorchoice/1.0.0 \ + crate://crates.io/either/1.8.1 \ + crate://crates.io/env_logger/0.10.0 \ + crate://crates.io/errno/0.2.8 \ + crate://crates.io/errno/0.3.1 \ + crate://crates.io/errno-dragonfly/0.1.2 \ + crate://crates.io/glob/0.3.1 \ + crate://crates.io/heck/0.3.3 \ + crate://crates.io/heck/0.4.1 \ + crate://crates.io/hermit-abi/0.3.2 \ + crate://crates.io/humantime/2.1.0 \ + crate://crates.io/intmap/2.0.0 \ + crate://crates.io/is-terminal/0.4.9 \ + crate://crates.io/lazy_static/1.4.0 \ + crate://crates.io/lazycell/1.3.0 \ + crate://crates.io/libc/0.2.147 \ + crate://crates.io/libgpiod/0.1.0 \ + crate://crates.io/libgpiod-sys/0.1.0 \ + crate://crates.io/libloading/0.7.4 \ + crate://crates.io/linux-raw-sys/0.4.3 \ + crate://crates.io/log/0.4.19 \ + crate://crates.io/memchr/2.5.0 \ + crate://crates.io/minimal-lexical/0.2.1 \ + crate://crates.io/nom/7.1.3 \ + crate://crates.io/once_cell/1.18.0 \ + crate://crates.io/peeking_take_while/0.1.2 \ + crate://crates.io/pkg-config/0.3.27 \ + crate://crates.io/proc-macro2/1.0.63 \ + crate://crates.io/quote/1.0.29 \ + crate://crates.io/regex/1.9.1 \ + crate://crates.io/regex-automata/0.3.2 \ + crate://crates.io/regex-syntax/0.7.4 \ + crate://crates.io/rustc-hash/1.1.0 \ + crate://crates.io/rustix/0.38.3 \ + crate://crates.io/serde/1.0.168 \ + crate://crates.io/shlex/1.1.0 \ + crate://crates.io/strsim/0.10.0 \ + crate://crates.io/strum/0.20.0 \ + crate://crates.io/strum_macros/0.20.1 \ + crate://crates.io/syn/1.0.109 \ + crate://crates.io/syn/2.0.23 \ + crate://crates.io/system-deps/2.0.3 \ + crate://crates.io/termcolor/1.2.0 \ + crate://crates.io/thiserror/1.0.41 \ + crate://crates.io/thiserror-impl/1.0.41 \ + crate://crates.io/toml/0.5.11 \ + crate://crates.io/unicode-ident/1.0.11 \ + crate://crates.io/unicode-segmentation/1.10.1 \ + crate://crates.io/utf8parse/0.2.1 \ + crate://crates.io/version-compare/0.0.11 \ + crate://crates.io/vhost/0.8.0 \ + crate://crates.io/vhost-user-backend/0.10.0 \ + crate://crates.io/virtio-bindings/0.2.1 \ + crate://crates.io/virtio-queue/0.9.0 \ + crate://crates.io/vm-memory/0.12.0 \ + crate://crates.io/vmm-sys-util/0.11.1 \ + crate://crates.io/which/4.4.0 \ + crate://crates.io/winapi/0.3.9 \ + crate://crates.io/winapi-i686-pc-windows-gnu/0.4.0 \ + crate://crates.io/winapi-util/0.1.5 \ + crate://crates.io/winapi-x86_64-pc-windows-gnu/0.4.0 \ + crate://crates.io/windows-sys/0.48.0 \ + crate://crates.io/windows-targets/0.48.1 \ + crate://crates.io/windows_aarch64_gnullvm/0.48.0 \ + crate://crates.io/windows_aarch64_msvc/0.48.0 \ + crate://crates.io/windows_i686_gnu/0.48.0 \ + crate://crates.io/windows_i686_msvc/0.48.0 \ + crate://crates.io/windows_x86_64_gnu/0.48.0 \ + crate://crates.io/windows_x86_64_gnullvm/0.48.0 \ + crate://crates.io/windows_x86_64_msvc/0.48.0 \ +" + +SRC_URI[aho-corasick-1.0.2.sha256sum] = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +SRC_URI[anstream-0.3.2.sha256sum] = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +SRC_URI[anstyle-1.0.1.sha256sum] = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" +SRC_URI[anstyle-parse-0.2.1.sha256sum] = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +SRC_URI[anstyle-query-1.0.0.sha256sum] = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +SRC_URI[anstyle-wincon-1.0.1.sha256sum] = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +SRC_URI[arc-swap-1.6.0.sha256sum] = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" +SRC_URI[assert_matches-1.5.0.sha256sum] = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" +SRC_URI[bindgen-0.63.0.sha256sum] = "36d860121800b2a9a94f9b5604b332d5cffb234ce17609ea479d723dbc9d3885" +SRC_URI[bitflags-1.3.2.sha256sum] = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +SRC_URI[bitflags-2.3.3.sha256sum] = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +SRC_URI[cc-1.0.79.sha256sum] = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +SRC_URI[cexpr-0.6.0.sha256sum] = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +SRC_URI[cfg-if-1.0.0.sha256sum] = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +SRC_URI[clang-sys-1.6.1.sha256sum] = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +SRC_URI[clap-4.3.19.sha256sum] = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d" +SRC_URI[clap_builder-4.3.19.sha256sum] = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1" +SRC_URI[clap_derive-4.3.12.sha256sum] = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" +SRC_URI[clap_lex-0.5.0.sha256sum] = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +SRC_URI[colorchoice-1.0.0.sha256sum] = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +SRC_URI[either-1.8.1.sha256sum] = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +SRC_URI[env_logger-0.10.0.sha256sum] = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +SRC_URI[errno-0.2.8.sha256sum] = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +SRC_URI[errno-0.3.1.sha256sum] = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +SRC_URI[errno-dragonfly-0.1.2.sha256sum] = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +SRC_URI[glob-0.3.1.sha256sum] = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +SRC_URI[heck-0.3.3.sha256sum] = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +SRC_URI[heck-0.4.1.sha256sum] = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +SRC_URI[hermit-abi-0.3.2.sha256sum] = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +SRC_URI[humantime-2.1.0.sha256sum] = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +SRC_URI[intmap-2.0.0.sha256sum] = "ee87fd093563344074bacf24faa0bb0227fb6969fb223e922db798516de924d6" +SRC_URI[is-terminal-0.4.9.sha256sum] = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +SRC_URI[lazy_static-1.4.0.sha256sum] = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +SRC_URI[lazycell-1.3.0.sha256sum] = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +SRC_URI[libc-0.2.147.sha256sum] = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +SRC_URI[libgpiod-0.1.0.sha256sum] = "9e9fdf4b437063f5697151f9ead12bafa223958e243f2f736107ec68c2b88231" +SRC_URI[libgpiod-sys-0.1.0.sha256sum] = "aa282e1da652deaeed776f6ef36d443689aeda19e5c0a3a2335c50b4611ce489" +SRC_URI[libloading-0.7.4.sha256sum] = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +SRC_URI[linux-raw-sys-0.4.3.sha256sum] = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +SRC_URI[log-0.4.19.sha256sum] = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +SRC_URI[memchr-2.5.0.sha256sum] = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +SRC_URI[minimal-lexical-0.2.1.sha256sum] = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +SRC_URI[nom-7.1.3.sha256sum] = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +SRC_URI[once_cell-1.18.0.sha256sum] = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +SRC_URI[peeking_take_while-0.1.2.sha256sum] = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +SRC_URI[pkg-config-0.3.27.sha256sum] = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +SRC_URI[proc-macro2-1.0.63.sha256sum] = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +SRC_URI[quote-1.0.29.sha256sum] = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +SRC_URI[regex-1.9.1.sha256sum] = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +SRC_URI[regex-automata-0.3.2.sha256sum] = "83d3daa6976cffb758ec878f108ba0e062a45b2d6ca3a2cca965338855476caf" +SRC_URI[regex-syntax-0.7.4.sha256sum] = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +SRC_URI[rustc-hash-1.1.0.sha256sum] = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +SRC_URI[rustix-0.38.3.sha256sum] = "ac5ffa1efe7548069688cd7028f32591853cd7b5b756d41bcffd2353e4fc75b4" +SRC_URI[serde-1.0.168.sha256sum] = "d614f89548720367ded108b3c843be93f3a341e22d5674ca0dd5cd57f34926af" +SRC_URI[shlex-1.1.0.sha256sum] = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +SRC_URI[strsim-0.10.0.sha256sum] = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +SRC_URI[strum-0.20.0.sha256sum] = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c" +SRC_URI[strum_macros-0.20.1.sha256sum] = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149" +SRC_URI[syn-1.0.109.sha256sum] = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +SRC_URI[syn-2.0.23.sha256sum] = "59fb7d6d8281a51045d62b8eb3a7d1ce347b76f312af50cd3dc0af39c87c1737" +SRC_URI[system-deps-2.0.3.sha256sum] = "1b59b8aafd652f3c1469f16e6c223121e8a8dbe40c71475209c1401cff3a67ef" +SRC_URI[termcolor-1.2.0.sha256sum] = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +SRC_URI[thiserror-1.0.41.sha256sum] = "c16a64ba9387ef3fdae4f9c1a7f07a0997fce91985c0336f1ddc1822b3b37802" +SRC_URI[thiserror-impl-1.0.41.sha256sum] = "d14928354b01c4d6a4f0e549069adef399a284e7995c7ccca94e8a07a5346c59" +SRC_URI[toml-0.5.11.sha256sum] = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +SRC_URI[unicode-ident-1.0.11.sha256sum] = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +SRC_URI[unicode-segmentation-1.10.1.sha256sum] = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +SRC_URI[utf8parse-0.2.1.sha256sum] = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +SRC_URI[version-compare-0.0.11.sha256sum] = "1c18c859eead79d8b95d09e4678566e8d70105c4e7b251f707a03df32442661b" +SRC_URI[vhost-0.8.0.sha256sum] = "73832f4d8d636d63d9b145e8ef22a2c50b93f4d24eb7a99c9e6781b1b08549cf" +SRC_URI[vhost-user-backend-0.10.0.sha256sum] = "e3ea9d5e8ec847cde4df1c04e586698a479706fd6beca37323f9d425b24b4c2f" +SRC_URI[virtio-bindings-0.2.1.sha256sum] = "c18d7b74098a946470ea265b5bacbbf877abc3373021388454de0d47735a5b98" +SRC_URI[virtio-queue-0.9.0.sha256sum] = "35aca00da06841bd99162c381ec65893cace23ca0fb89254302cfe4bec4c300f" +SRC_URI[vm-memory-0.12.0.sha256sum] = "a77c7a0891cbac53618f5f6eec650ed1dc4f7e506bbe14877aff49d94b8408b0" +SRC_URI[vmm-sys-util-0.11.1.sha256sum] = "dd64fe09d8e880e600c324e7d664760a17f56e9672b7495a86381b49e4f72f46" +SRC_URI[which-4.4.0.sha256sum] = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +SRC_URI[winapi-0.3.9.sha256sum] = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +SRC_URI[winapi-i686-pc-windows-gnu-0.4.0.sha256sum] = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +SRC_URI[winapi-util-0.1.5.sha256sum] = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +SRC_URI[winapi-x86_64-pc-windows-gnu-0.4.0.sha256sum] = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +SRC_URI[windows-sys-0.48.0.sha256sum] = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +SRC_URI[windows-targets-0.48.1.sha256sum] = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +SRC_URI[windows_aarch64_gnullvm-0.48.0.sha256sum] = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +SRC_URI[windows_aarch64_msvc-0.48.0.sha256sum] = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +SRC_URI[windows_i686_gnu-0.48.0.sha256sum] = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +SRC_URI[windows_i686_msvc-0.48.0.sha256sum] = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +SRC_URI[windows_x86_64_gnu-0.48.0.sha256sum] = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +SRC_URI[windows_x86_64_gnullvm-0.48.0.sha256sum] = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +SRC_URI[windows_x86_64_msvc-0.48.0.sha256sum] = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/meta-egvirt/recipes-extended/vhost-device/vhost-device-gpio_0.1.0.bb b/meta-egvirt/recipes-extended/vhost-device/vhost-device-gpio_0.1.0.bb new file mode 100644 index 00000000..179f1fb6 --- /dev/null +++ b/meta-egvirt/recipes-extended/vhost-device/vhost-device-gpio_0.1.0.bb @@ -0,0 +1,22 @@ +SUMMARY = "vhost gpio backend device" +DESCRIPTION = "A vhost-user backend that emulates a VirtIO GPIO device" +HOMEPAGE = "https://github.com/rust-vmm/vhost-device" +LICENSE = "Apache-2.0 | BSD-3-Clause" +LIC_FILES_CHKSUM = "\ + file://LICENSE-APACHE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://LICENSE-BSD-3-Clause;md5=2489db1359f496fff34bd393df63947e \ +" +DEPENDS += "libgpiod" + +# libgpiod-sys generates bindings using bindgen, which depends on clang +DEPENDS += "clang-native" + +SKIP_RECIPE[vhost-device-gpio] ?= "${@bb.utils.contains('BBFILE_COLLECTIONS', 'clang-layer', '', 'Depends on clang-native from meta-clang which is not included', d)}" + +SRC_URI += "crate://crates.io/vhost-device-gpio/0.1.0" +SRC_URI[vhost-device-gpio-0.1.0.sha256sum] = "f4789dd127ce746d4f702d50256ff09e47b19fdb2bfee88a254b7e48efbf1100" + +inherit cargo +inherit pkgconfig + +include vhost-device-gpio-crates.inc diff --git a/meta-egvirt/recipes-extended/vhost-device/vhost-device-rng-crates.inc b/meta-egvirt/recipes-extended/vhost-device/vhost-device-rng-crates.inc new file mode 100644 index 00000000..5a50da3e --- /dev/null +++ b/meta-egvirt/recipes-extended/vhost-device/vhost-device-rng-crates.inc @@ -0,0 +1,158 @@ +# Autogenerated with 'bitbake -c update_crates vhost-device-rng' + +# from Cargo.lock +SRC_URI += " \ + crate://crates.io/aho-corasick/1.0.2 \ + crate://crates.io/anstream/0.3.2 \ + crate://crates.io/anstyle/1.0.1 \ + crate://crates.io/anstyle-parse/0.2.1 \ + crate://crates.io/anstyle-query/1.0.0 \ + crate://crates.io/anstyle-wincon/1.0.1 \ + crate://crates.io/arc-swap/1.6.0 \ + crate://crates.io/assert_matches/1.5.0 \ + crate://crates.io/autocfg/1.1.0 \ + crate://crates.io/bitflags/1.3.2 \ + crate://crates.io/bitflags/2.3.3 \ + crate://crates.io/cc/1.0.79 \ + crate://crates.io/cfg-if/1.0.0 \ + crate://crates.io/clap/4.3.19 \ + crate://crates.io/clap_builder/4.3.19 \ + crate://crates.io/clap_derive/4.3.12 \ + crate://crates.io/clap_lex/0.5.0 \ + crate://crates.io/colorchoice/1.0.0 \ + crate://crates.io/env_logger/0.10.0 \ + crate://crates.io/epoll/4.3.3 \ + crate://crates.io/errno/0.3.1 \ + crate://crates.io/errno-dragonfly/0.1.2 \ + crate://crates.io/fastrand/1.9.0 \ + crate://crates.io/getrandom/0.2.10 \ + crate://crates.io/heck/0.4.1 \ + crate://crates.io/hermit-abi/0.3.2 \ + crate://crates.io/humantime/2.1.0 \ + crate://crates.io/instant/0.1.12 \ + crate://crates.io/io-lifetimes/1.0.11 \ + crate://crates.io/is-terminal/0.4.9 \ + crate://crates.io/libc/0.2.147 \ + crate://crates.io/linux-raw-sys/0.3.8 \ + crate://crates.io/linux-raw-sys/0.4.3 \ + crate://crates.io/log/0.4.19 \ + crate://crates.io/memchr/2.5.0 \ + crate://crates.io/once_cell/1.18.0 \ + crate://crates.io/ppv-lite86/0.2.17 \ + crate://crates.io/proc-macro2/1.0.63 \ + crate://crates.io/quote/1.0.29 \ + crate://crates.io/rand/0.8.5 \ + crate://crates.io/rand_chacha/0.3.1 \ + crate://crates.io/rand_core/0.6.4 \ + crate://crates.io/redox_syscall/0.3.5 \ + crate://crates.io/regex/1.9.1 \ + crate://crates.io/regex-automata/0.3.2 \ + crate://crates.io/regex-syntax/0.7.4 \ + crate://crates.io/rustix/0.37.23 \ + crate://crates.io/rustix/0.38.3 \ + crate://crates.io/strsim/0.10.0 \ + crate://crates.io/syn/2.0.23 \ + crate://crates.io/tempfile/3.6.0 \ + crate://crates.io/termcolor/1.2.0 \ + crate://crates.io/thiserror/1.0.41 \ + crate://crates.io/thiserror-impl/1.0.41 \ + crate://crates.io/unicode-ident/1.0.11 \ + crate://crates.io/utf8parse/0.2.1 \ + crate://crates.io/vhost/0.8.0 \ + crate://crates.io/vhost-user-backend/0.10.0 \ + crate://crates.io/virtio-bindings/0.2.1 \ + crate://crates.io/virtio-queue/0.9.0 \ + crate://crates.io/vm-memory/0.12.0 \ + crate://crates.io/vmm-sys-util/0.11.1 \ + crate://crates.io/wasi/0.11.0+wasi-snapshot-preview1 \ + crate://crates.io/winapi/0.3.9 \ + crate://crates.io/winapi-i686-pc-windows-gnu/0.4.0 \ + crate://crates.io/winapi-util/0.1.5 \ + crate://crates.io/winapi-x86_64-pc-windows-gnu/0.4.0 \ + crate://crates.io/windows-sys/0.48.0 \ + crate://crates.io/windows-targets/0.48.1 \ + crate://crates.io/windows_aarch64_gnullvm/0.48.0 \ + crate://crates.io/windows_aarch64_msvc/0.48.0 \ + crate://crates.io/windows_i686_gnu/0.48.0 \ + crate://crates.io/windows_i686_msvc/0.48.0 \ + crate://crates.io/windows_x86_64_gnu/0.48.0 \ + crate://crates.io/windows_x86_64_gnullvm/0.48.0 \ + crate://crates.io/windows_x86_64_msvc/0.48.0 \ +" + +SRC_URI[aho-corasick-1.0.2.sha256sum] = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +SRC_URI[anstream-0.3.2.sha256sum] = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +SRC_URI[anstyle-1.0.1.sha256sum] = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" +SRC_URI[anstyle-parse-0.2.1.sha256sum] = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +SRC_URI[anstyle-query-1.0.0.sha256sum] = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +SRC_URI[anstyle-wincon-1.0.1.sha256sum] = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +SRC_URI[arc-swap-1.6.0.sha256sum] = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" +SRC_URI[assert_matches-1.5.0.sha256sum] = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" +SRC_URI[autocfg-1.1.0.sha256sum] = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +SRC_URI[bitflags-1.3.2.sha256sum] = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +SRC_URI[bitflags-2.3.3.sha256sum] = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +SRC_URI[cc-1.0.79.sha256sum] = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +SRC_URI[cfg-if-1.0.0.sha256sum] = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +SRC_URI[clap-4.3.19.sha256sum] = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d" +SRC_URI[clap_builder-4.3.19.sha256sum] = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1" +SRC_URI[clap_derive-4.3.12.sha256sum] = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" +SRC_URI[clap_lex-0.5.0.sha256sum] = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +SRC_URI[colorchoice-1.0.0.sha256sum] = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +SRC_URI[env_logger-0.10.0.sha256sum] = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +SRC_URI[epoll-4.3.3.sha256sum] = "74351c3392ea1ff6cd2628e0042d268ac2371cb613252ff383b6dfa50d22fa79" +SRC_URI[errno-0.3.1.sha256sum] = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +SRC_URI[errno-dragonfly-0.1.2.sha256sum] = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +SRC_URI[fastrand-1.9.0.sha256sum] = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +SRC_URI[getrandom-0.2.10.sha256sum] = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +SRC_URI[heck-0.4.1.sha256sum] = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +SRC_URI[hermit-abi-0.3.2.sha256sum] = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +SRC_URI[humantime-2.1.0.sha256sum] = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +SRC_URI[instant-0.1.12.sha256sum] = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +SRC_URI[io-lifetimes-1.0.11.sha256sum] = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +SRC_URI[is-terminal-0.4.9.sha256sum] = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +SRC_URI[libc-0.2.147.sha256sum] = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +SRC_URI[linux-raw-sys-0.3.8.sha256sum] = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +SRC_URI[linux-raw-sys-0.4.3.sha256sum] = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +SRC_URI[log-0.4.19.sha256sum] = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +SRC_URI[memchr-2.5.0.sha256sum] = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +SRC_URI[once_cell-1.18.0.sha256sum] = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +SRC_URI[ppv-lite86-0.2.17.sha256sum] = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +SRC_URI[proc-macro2-1.0.63.sha256sum] = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +SRC_URI[quote-1.0.29.sha256sum] = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +SRC_URI[rand-0.8.5.sha256sum] = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +SRC_URI[rand_chacha-0.3.1.sha256sum] = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +SRC_URI[rand_core-0.6.4.sha256sum] = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +SRC_URI[redox_syscall-0.3.5.sha256sum] = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +SRC_URI[regex-1.9.1.sha256sum] = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +SRC_URI[regex-automata-0.3.2.sha256sum] = "83d3daa6976cffb758ec878f108ba0e062a45b2d6ca3a2cca965338855476caf" +SRC_URI[regex-syntax-0.7.4.sha256sum] = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +SRC_URI[rustix-0.37.23.sha256sum] = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" +SRC_URI[rustix-0.38.3.sha256sum] = "ac5ffa1efe7548069688cd7028f32591853cd7b5b756d41bcffd2353e4fc75b4" +SRC_URI[strsim-0.10.0.sha256sum] = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +SRC_URI[syn-2.0.23.sha256sum] = "59fb7d6d8281a51045d62b8eb3a7d1ce347b76f312af50cd3dc0af39c87c1737" +SRC_URI[tempfile-3.6.0.sha256sum] = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +SRC_URI[termcolor-1.2.0.sha256sum] = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +SRC_URI[thiserror-1.0.41.sha256sum] = "c16a64ba9387ef3fdae4f9c1a7f07a0997fce91985c0336f1ddc1822b3b37802" +SRC_URI[thiserror-impl-1.0.41.sha256sum] = "d14928354b01c4d6a4f0e549069adef399a284e7995c7ccca94e8a07a5346c59" +SRC_URI[unicode-ident-1.0.11.sha256sum] = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +SRC_URI[utf8parse-0.2.1.sha256sum] = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +SRC_URI[vhost-0.8.0.sha256sum] = "73832f4d8d636d63d9b145e8ef22a2c50b93f4d24eb7a99c9e6781b1b08549cf" +SRC_URI[vhost-user-backend-0.10.0.sha256sum] = "e3ea9d5e8ec847cde4df1c04e586698a479706fd6beca37323f9d425b24b4c2f" +SRC_URI[virtio-bindings-0.2.1.sha256sum] = "c18d7b74098a946470ea265b5bacbbf877abc3373021388454de0d47735a5b98" +SRC_URI[virtio-queue-0.9.0.sha256sum] = "35aca00da06841bd99162c381ec65893cace23ca0fb89254302cfe4bec4c300f" +SRC_URI[vm-memory-0.12.0.sha256sum] = "a77c7a0891cbac53618f5f6eec650ed1dc4f7e506bbe14877aff49d94b8408b0" +SRC_URI[vmm-sys-util-0.11.1.sha256sum] = "dd64fe09d8e880e600c324e7d664760a17f56e9672b7495a86381b49e4f72f46" +SRC_URI[wasi-0.11.0+wasi-snapshot-preview1.sha256sum] = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +SRC_URI[winapi-0.3.9.sha256sum] = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +SRC_URI[winapi-i686-pc-windows-gnu-0.4.0.sha256sum] = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +SRC_URI[winapi-util-0.1.5.sha256sum] = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +SRC_URI[winapi-x86_64-pc-windows-gnu-0.4.0.sha256sum] = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +SRC_URI[windows-sys-0.48.0.sha256sum] = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +SRC_URI[windows-targets-0.48.1.sha256sum] = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +SRC_URI[windows_aarch64_gnullvm-0.48.0.sha256sum] = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +SRC_URI[windows_aarch64_msvc-0.48.0.sha256sum] = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +SRC_URI[windows_i686_gnu-0.48.0.sha256sum] = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +SRC_URI[windows_i686_msvc-0.48.0.sha256sum] = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +SRC_URI[windows_x86_64_gnu-0.48.0.sha256sum] = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +SRC_URI[windows_x86_64_gnullvm-0.48.0.sha256sum] = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +SRC_URI[windows_x86_64_msvc-0.48.0.sha256sum] = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/meta-egvirt/recipes-extended/vhost-device/vhost-device-rng_0.1.0.bb b/meta-egvirt/recipes-extended/vhost-device/vhost-device-rng_0.1.0.bb new file mode 100644 index 00000000..17b5fbea --- /dev/null +++ b/meta-egvirt/recipes-extended/vhost-device/vhost-device-rng_0.1.0.bb @@ -0,0 +1,16 @@ +SUMMARY = "vhost rng backend device" +DESCRIPTION = "A vhost-user backend that emulates a VirtIO random number \ + generator device" +HOMEPAGE = "https://github.com/rust-vmm/vhost-device" +LICENSE = "Apache-2.0 | BSD-3-Clause" +LIC_FILES_CHKSUM = " \ + file://LICENSE-APACHE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://LICENSE-BSD-3-Clause;md5=2489db1359f496fff34bd393df63947e \ +" + +SRC_URI += "crate://crates.io/vhost-device-rng/0.1.0" +SRC_URI[vhost-device-rng-0.1.0.sha256sum] = "51e0af4acaaefc19a3d6c2e2cb00caf2130d728d857494c857662781da9f1329" + +inherit cargo + +include vhost-device-rng-crates.inc diff --git a/meta-egvirt/recipes-kernel/kernel-module-virtio-can/kernel-module-virtio-can.bb b/meta-egvirt/recipes-kernel/kernel-module-virtio-can/kernel-module-virtio-can.bb index e8327de4..6b180efb 100644 --- a/meta-egvirt/recipes-kernel/kernel-module-virtio-can/kernel-module-virtio-can.bb +++ b/meta-egvirt/recipes-kernel/kernel-module-virtio-can/kernel-module-virtio-can.bb @@ -16,5 +16,5 @@ SRC_URI = " \ S = "${WORKDIR}" -MAKE_TARGETS = "-C ${STAGING_KERNEL_DIR} M=${WORKDIR} MODULE_GIT_REPOSITORY_DIR=${METADIR}/meta-agl-devel" +MAKE_TARGETS = "-C ${STAGING_KERNEL_DIR} M=${WORKDIR}" MODULES_INSTALL_TARGET = "-C ${STAGING_KERNEL_DIR} M=${WORKDIR} modules_install" diff --git a/meta-egvirt/recipes-kernel/kernel-module-virtio-loopback/kernel-module-virtio-loopback.bb b/meta-egvirt/recipes-kernel/kernel-module-virtio-loopback/kernel-module-virtio-loopback.bb new file mode 100644 index 00000000..5850eb29 --- /dev/null +++ b/meta-egvirt/recipes-kernel/kernel-module-virtio-loopback/kernel-module-virtio-loopback.bb @@ -0,0 +1,16 @@ +SUMMARY = "Virtio-loopback driver" +DESCRIPTION = "Virtio-Loopback kernel driver" +LICENSE = "GPL-2.0-or-later" +LIC_FILES_CHKSUM = "file://README.md;md5=c912e5645ed908bc9570ba05c92b3723" + +inherit module + +SRC_URI = "git://gerrit.automotivelinux.org/gerrit/src/virtio/virtio-loopback-driver.git;protocol=http;branch=${AGL_BRANCH}" + +SRCREV = "f9c1c04c0a3c2a133d969c3aae8490cb25145985" + +S = "${WORKDIR}/git" + +MAKE_TARGETS = "-C ${STAGING_KERNEL_DIR} M=${WORKDIR}/git" +MODULES_INSTALL_TARGET = "-C ${STAGING_KERNEL_DIR} M=${WORKDIR}/git modules_install" + diff --git a/meta-egvirt/recipes-kernel/kernel-module-virtio-loopback/virtio-loopback-driver.bb b/meta-egvirt/recipes-kernel/kernel-module-virtio-loopback/virtio-loopback-driver.bb deleted file mode 100644 index 203a0d36..00000000 --- a/meta-egvirt/recipes-kernel/kernel-module-virtio-loopback/virtio-loopback-driver.bb +++ /dev/null @@ -1,14 +0,0 @@ -SUMMARY = "Virtio-loopback driver" -DESCRIPTION = "Virtio-Loopback kernel driver" -LICENSE = "GPL" -LIC_FILES_CHKSUM = "file://README.md;md5=c912e5645ed908bc9570ba05c92b3723" - -inherit module - -SRC_URI = "git://git.virtualopensystems.com/virtio-loopback/loopback_driver.git;protocol=https;rev=b94d81b014f322677036776e19bdf9d6fa61dd8e;branch=epsilon-release-5.15" - -S = "${WORKDIR}/git" - -MAKE_TARGETS = "-C ${STAGING_KERNEL_DIR} M=${WORKDIR}/git MODULE_GIT_REPOSITORY_DIR=${METADIR}/meta-agl-devel" -MODULES_INSTALL_TARGET = "-C ${STAGING_KERNEL_DIR} M=${WORKDIR}/git modules_install" - diff --git a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/Kbuild b/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/Kbuild deleted file mode 100644 index f16a686b..00000000 --- a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/Kbuild +++ /dev/null @@ -1,22 +0,0 @@ -# -# Kbuild for the virtio-video driver -# - -# --tags to take into account non-annotated tags -# --dirty to mark version with uncommitted changes as dirty -GIT_VERSION = $(shell git -C "$(MODULE_GIT_REPOSITORY_DIR)" describe --tags --dirty | sed 's/^v//') - -ccflags-y := -I"$(src)/include/uapi" -ccflags-y += -DDRIVER_VERSION=\"$(GIT_VERSION)\" - -virtio_video-y := \ - virtio_video_driver.o \ - virtio_video_vq.o \ - virtio_video_device.o \ - virtio_video_dec.o \ - virtio_video_enc.o \ - virtio_video_cam.o \ - virtio_video_caps.o \ - virtio_video_helpers.o - -obj-m += virtio_video.o diff --git a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/Makefile b/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/Makefile deleted file mode 100644 index e5a34b76..00000000 --- a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# -# Makefile for mod coqos -# -KDIR ?= $(KERNEL_SRC) -ifeq ($(KDIR),) -$(error "KDIR must be specified.") -endif - -# The variable "M" is used to point to the location of this module, and it is -# passed to kbuild to build this module. -# -# Allow to specify variable "M" from outside. It is needed to set it to the -# relative path to this module. It must be relative to the kernel source -# directory. -# -# If kernel is built with "O" option then setting "M" to the relative path -# empowers the build system to put output/object files (.o, .ko.) into a -# directory different from the module source directory. -M ?= $$PWD - -# Some build systems may rsync module sources out of git repository to have -# sources directory untouched during build. Then, they should specify Git -# repository directory separately for 'git describe' to work properly. -MODULE_GIT_REPOSITORY_DIR ?= $(M) - -default: - $(MAKE) -C $(KDIR) M=$(M) MODULE_GIT_REPOSITORY_DIR=$(MODULE_GIT_REPOSITORY_DIR) - -modules_install: - $(MAKE) -C $(KDIR) M=$(M) $@ - -clean: - $(MAKE) -C $(KDIR) M=$(M) $@ diff --git a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/include/uapi/linux/virtio_video.h b/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/include/uapi/linux/virtio_video.h deleted file mode 100644 index 12792129..00000000 --- a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/include/uapi/linux/virtio_video.h +++ /dev/null @@ -1,493 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Virtio Video Device - * - * This header is BSD licensed so anyone can use the definitions - * to implement compatible drivers/servers: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of IBM nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IBM OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Copyright (C) 2020 OpenSynergy GmbH. - */ - -#ifndef _UAPI_LINUX_VIRTIO_VIDEO_H -#define _UAPI_LINUX_VIRTIO_VIDEO_H - -#include -#include - -enum virtio_video_device_type { - VIRTIO_VIDEO_DEVICE_ENCODER = 0x0100, - VIRTIO_VIDEO_DEVICE_DECODER, - VIRTIO_VIDEO_DEVICE_CAMERA, -}; - -/* - * Feature bits - */ - -/* Guest pages can be used for video buffers. */ -#define VIRTIO_VIDEO_F_RESOURCE_GUEST_PAGES 0 -/* - * The host can process buffers even if they are non-contiguous memory such as - * scatter-gather lists. - */ -#define VIRTIO_VIDEO_F_RESOURCE_NON_CONTIG 1 - -#define VIRTIO_VIDEO_MAX_PLANES 8 - -/* - * Image formats - */ - -enum virtio_video_format { - /* Raw formats */ - VIRTIO_VIDEO_FORMAT_RAW_MIN = 1, - VIRTIO_VIDEO_FORMAT_ARGB8888 = VIRTIO_VIDEO_FORMAT_RAW_MIN, - VIRTIO_VIDEO_FORMAT_BGRA8888, - VIRTIO_VIDEO_FORMAT_RGBA8888, - VIRTIO_VIDEO_FORMAT_NV12, /* 12 Y/CbCr 4:2:0 */ - VIRTIO_VIDEO_FORMAT_YUV420, /* 12 YUV 4:2:0 */ - VIRTIO_VIDEO_FORMAT_YVU420, /* 12 YVU 4:2:0 */ - VIRTIO_VIDEO_FORMAT_YUV422, /* 16 YUV 4:2:2 */ - VIRTIO_VIDEO_FORMAT_RAW_MAX = VIRTIO_VIDEO_FORMAT_YUV422, - - /* Coded formats */ - VIRTIO_VIDEO_FORMAT_CODED_MIN = 0x1000, - VIRTIO_VIDEO_FORMAT_MPEG2 = - VIRTIO_VIDEO_FORMAT_CODED_MIN, /* MPEG-2 Part 2 */ - VIRTIO_VIDEO_FORMAT_MPEG4, /* MPEG-4 Part 2 */ - VIRTIO_VIDEO_FORMAT_H264, /* H.264 */ - VIRTIO_VIDEO_FORMAT_HEVC, /* HEVC aka H.265*/ - VIRTIO_VIDEO_FORMAT_VP8, /* VP8 */ - VIRTIO_VIDEO_FORMAT_VP9, /* VP9 */ - VIRTIO_VIDEO_FORMAT_CODED_MAX = VIRTIO_VIDEO_FORMAT_VP9, -}; - -enum virtio_video_profile { - /* H.264 */ - VIRTIO_VIDEO_PROFILE_H264_MIN = 0x100, - VIRTIO_VIDEO_PROFILE_H264_BASELINE = VIRTIO_VIDEO_PROFILE_H264_MIN, - VIRTIO_VIDEO_PROFILE_H264_MAIN, - VIRTIO_VIDEO_PROFILE_H264_EXTENDED, - VIRTIO_VIDEO_PROFILE_H264_HIGH, - VIRTIO_VIDEO_PROFILE_H264_HIGH10PROFILE, - VIRTIO_VIDEO_PROFILE_H264_HIGH422PROFILE, - VIRTIO_VIDEO_PROFILE_H264_HIGH444PREDICTIVEPROFILE, - VIRTIO_VIDEO_PROFILE_H264_SCALABLEBASELINE, - VIRTIO_VIDEO_PROFILE_H264_SCALABLEHIGH, - VIRTIO_VIDEO_PROFILE_H264_STEREOHIGH, - VIRTIO_VIDEO_PROFILE_H264_MULTIVIEWHIGH, - VIRTIO_VIDEO_PROFILE_H264_MAX = VIRTIO_VIDEO_PROFILE_H264_MULTIVIEWHIGH, - - /* HEVC */ - VIRTIO_VIDEO_PROFILE_HEVC_MIN = 0x200, - VIRTIO_VIDEO_PROFILE_HEVC_MAIN = VIRTIO_VIDEO_PROFILE_HEVC_MIN, - VIRTIO_VIDEO_PROFILE_HEVC_MAIN10, - VIRTIO_VIDEO_PROFILE_HEVC_MAIN_STILL_PICTURE, - VIRTIO_VIDEO_PROFILE_HEVC_MAX = - VIRTIO_VIDEO_PROFILE_HEVC_MAIN_STILL_PICTURE, - - /* VP8 */ - VIRTIO_VIDEO_PROFILE_VP8_MIN = 0x300, - VIRTIO_VIDEO_PROFILE_VP8_PROFILE0 = VIRTIO_VIDEO_PROFILE_VP8_MIN, - VIRTIO_VIDEO_PROFILE_VP8_PROFILE1, - VIRTIO_VIDEO_PROFILE_VP8_PROFILE2, - VIRTIO_VIDEO_PROFILE_VP8_PROFILE3, - VIRTIO_VIDEO_PROFILE_VP8_MAX = VIRTIO_VIDEO_PROFILE_VP8_PROFILE3, - - /* VP9 */ - VIRTIO_VIDEO_PROFILE_VP9_MIN = 0x400, - VIRTIO_VIDEO_PROFILE_VP9_PROFILE0 = VIRTIO_VIDEO_PROFILE_VP9_MIN, - VIRTIO_VIDEO_PROFILE_VP9_PROFILE1, - VIRTIO_VIDEO_PROFILE_VP9_PROFILE2, - VIRTIO_VIDEO_PROFILE_VP9_PROFILE3, - VIRTIO_VIDEO_PROFILE_VP9_MAX = VIRTIO_VIDEO_PROFILE_VP9_PROFILE3, -}; - -enum virtio_video_level { - /* H.264 */ - VIRTIO_VIDEO_LEVEL_H264_MIN = 0x100, - VIRTIO_VIDEO_LEVEL_H264_1_0 = VIRTIO_VIDEO_LEVEL_H264_MIN, - VIRTIO_VIDEO_LEVEL_H264_1_1, - VIRTIO_VIDEO_LEVEL_H264_1_2, - VIRTIO_VIDEO_LEVEL_H264_1_3, - VIRTIO_VIDEO_LEVEL_H264_2_0, - VIRTIO_VIDEO_LEVEL_H264_2_1, - VIRTIO_VIDEO_LEVEL_H264_2_2, - VIRTIO_VIDEO_LEVEL_H264_3_0, - VIRTIO_VIDEO_LEVEL_H264_3_1, - VIRTIO_VIDEO_LEVEL_H264_3_2, - VIRTIO_VIDEO_LEVEL_H264_4_0, - VIRTIO_VIDEO_LEVEL_H264_4_1, - VIRTIO_VIDEO_LEVEL_H264_4_2, - VIRTIO_VIDEO_LEVEL_H264_5_0, - VIRTIO_VIDEO_LEVEL_H264_5_1, - VIRTIO_VIDEO_LEVEL_H264_MAX = VIRTIO_VIDEO_LEVEL_H264_5_1, -}; - -/* - * Config - */ - -struct virtio_video_config { - __le32 version; - __le32 max_caps_length; - __le32 max_resp_length; -}; - -/* - * Commands - */ - -enum virtio_video_cmd_type { - /* Command */ - VIRTIO_VIDEO_CMD_QUERY_CAPABILITY = 0x0100, - VIRTIO_VIDEO_CMD_STREAM_CREATE, - VIRTIO_VIDEO_CMD_STREAM_DESTROY, - VIRTIO_VIDEO_CMD_STREAM_DRAIN, - VIRTIO_VIDEO_CMD_RESOURCE_ATTACH, - VIRTIO_VIDEO_CMD_RESOURCE_QUEUE, - VIRTIO_VIDEO_CMD_QUEUE_DETACH_RESOURCES, - VIRTIO_VIDEO_CMD_QUEUE_CLEAR, - VIRTIO_VIDEO_CMD_GET_PARAMS, - VIRTIO_VIDEO_CMD_SET_PARAMS, - VIRTIO_VIDEO_CMD_QUERY_CONTROL, - VIRTIO_VIDEO_CMD_GET_CONTROL, - VIRTIO_VIDEO_CMD_SET_CONTROL, - - /* Response */ - VIRTIO_VIDEO_RESP_OK_NODATA = 0x0200, - VIRTIO_VIDEO_RESP_OK_QUERY_CAPABILITY, - VIRTIO_VIDEO_RESP_OK_RESOURCE_QUEUE, - VIRTIO_VIDEO_RESP_OK_GET_PARAMS, - VIRTIO_VIDEO_RESP_OK_QUERY_CONTROL, - VIRTIO_VIDEO_RESP_OK_GET_CONTROL, - - VIRTIO_VIDEO_RESP_ERR_INVALID_OPERATION = 0x0300, - VIRTIO_VIDEO_RESP_ERR_OUT_OF_MEMORY, - VIRTIO_VIDEO_RESP_ERR_INVALID_STREAM_ID, - VIRTIO_VIDEO_RESP_ERR_INVALID_RESOURCE_ID, - VIRTIO_VIDEO_RESP_ERR_INVALID_PARAMETER, - VIRTIO_VIDEO_RESP_ERR_UNSUPPORTED_CONTROL, -}; - -struct virtio_video_cmd_hdr { - __le32 type; /* One of enum virtio_video_cmd_type */ - __le32 stream_id; -}; - -/* VIRTIO_VIDEO_CMD_QUERY_CAPABILITY */ -enum virtio_video_queue_type { - VIRTIO_VIDEO_QUEUE_TYPE_INPUT = 0x100, - VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT, -}; - -struct virtio_video_query_capability { - struct virtio_video_cmd_hdr hdr; - __le32 queue_type; /* One of VIRTIO_VIDEO_QUEUE_TYPE_* types */ - __u8 padding[4]; -}; - -enum virtio_video_planes_layout_flag { - VIRTIO_VIDEO_PLANES_LAYOUT_SINGLE_BUFFER = 1 << 0, - VIRTIO_VIDEO_PLANES_LAYOUT_PER_PLANE = 1 << 1, -}; - -struct virtio_video_format_range { - __le32 min; - __le32 max; - __le32 step; - __u8 padding[4]; -}; - -struct virtio_video_format_frame { - struct virtio_video_format_range width; - struct virtio_video_format_range height; - __le32 num_rates; - __u8 padding[4]; - /* Followed by struct virtio_video_format_range frame_rates[] */ -}; - -struct virtio_video_format_desc { - __le64 mask; - __le32 format; /* One of VIRTIO_VIDEO_FORMAT_* types */ - __le32 planes_layout; /* Bitmask with VIRTIO_VIDEO_PLANES_LAYOUT_* */ - __le32 plane_align; - __le32 num_frames; - /* Followed by struct virtio_video_format_frame frames[] */ -}; - -struct virtio_video_query_capability_resp { - struct virtio_video_cmd_hdr hdr; - __le32 num_descs; - __u8 padding[4]; - /* Followed by struct virtio_video_format_desc descs[] */ -}; - -/* VIRTIO_VIDEO_CMD_STREAM_CREATE */ -enum virtio_video_mem_type { - VIRTIO_VIDEO_MEM_TYPE_GUEST_PAGES, -}; - -struct virtio_video_stream_create { - struct virtio_video_cmd_hdr hdr; - __le32 in_mem_type; /* One of VIRTIO_VIDEO_MEM_TYPE_* types */ - __le32 out_mem_type; /* One of VIRTIO_VIDEO_MEM_TYPE_* types */ - __le32 coded_format; /* One of VIRTIO_VIDEO_FORMAT_* types */ - __u8 padding[4]; - __u8 tag[64]; -}; - -/* VIRTIO_VIDEO_CMD_STREAM_DESTROY */ -struct virtio_video_stream_destroy { - struct virtio_video_cmd_hdr hdr; -}; - -/* VIRTIO_VIDEO_CMD_STREAM_DRAIN */ -struct virtio_video_stream_drain { - struct virtio_video_cmd_hdr hdr; -}; - -/* VIRTIO_VIDEO_CMD_RESOURCE_ATTACH */ -struct virtio_video_resource_object { - __u8 uuid [16]; -}; - -struct virtio_video_resource_sg_entry { - __le64 addr; - __le32 length; - __u8 padding[4]; -}; - -struct virtio_video_resource_sg_list { - __le32 num_entries; - __u8 padding[4]; - struct virtio_video_resource_sg_entry entries[]; -}; -#define VIRTIO_VIDEO_RESOURCE_SG_SIZE(n) \ - offsetof(struct virtio_video_resource_sg_list, entries[n]) - -union virtio_video_resource { - struct virtio_video_resource_sg_list sg_list; - struct virtio_video_resource_object object; -}; - -struct virtio_video_resource_attach { - __le32 cmd_type; - __le32 stream_id; - __le32 queue_type; /* VIRTIO_VIDEO_QUEUE_TYPE_* */ - __le32 resource_id; - /* Followed by struct virtio_video_resource resources[] */ -}; - -/* VIRTIO_VIDEO_CMD_RESOURCE_QUEUE */ -struct virtio_video_resource_queue { - __le32 cmd_type; - __le32 stream_id; - __le32 queue_type; /* VIRTIO_VIDEO_QUEUE_TYPE_* */ - __le32 resource_id; - __le32 flags; /* Bitmask with VIRTIO_VIDEO_ENQUEUE_FLAG_ * */ - __u8 padding[4]; - __le64 timestamp; - __le32 data_sizes[VIRTIO_VIDEO_MAX_PLANES]; -}; - -enum virtio_video_dequeue_flag { - VIRTIO_VIDEO_DEQUEUE_FLAG_ERR = 0, - VIRTIO_VIDEO_DEQUEUE_FLAG_EOS, - - /* Encoder only */ - VIRTIO_VIDEO_DEQUEUE_FLAG_KEY_FRAME, - VIRTIO_VIDEO_DEQUEUE_FLAG_PFRAME, - VIRTIO_VIDEO_DEQUEUE_FLAG_BFRAME, -}; - -struct virtio_video_resource_queue_resp { - struct virtio_video_cmd_hdr hdr; - __le32 flags; - __le64 timestamp; - __le32 data_sizes[VIRTIO_VIDEO_MAX_PLANES]; -}; - -/* VIRTIO_VIDEO_CMD_QUEUE_DETACH_RESOURCES */ -struct virtio_video_queue_detach_resources { - __le32 cmd_type; - __le32 stream_id; - __le32 queue_type; /* One of VIRTIO_VIDEO_QUEUE_TYPE_* types */ - __u8 padding[4]; -}; - -/* VIRTIO_VIDEO_CMD_QUEUE_CLEAR */ -struct virtio_video_queue_clear { - struct virtio_video_cmd_hdr hdr; - __le32 queue_type; /* One of VIRTIO_VIDEO_QUEUE_TYPE_* types */ - __u8 padding[4]; -}; - -/* VIRTIO_VIDEO_CMD_GET_PARAMS */ -struct virtio_video_plane_format { - __le32 plane_size; - __le32 stride; -}; - -struct virtio_video_crop { - __le32 left; - __le32 top; - __le32 width; - __le32 height; -}; - -struct virtio_video_params { - __le32 queue_type; /* One of VIRTIO_VIDEO_QUEUE_TYPE_* types */ - __le32 format; /* One of VIRTIO_VIDEO_FORMAT_* types */ - __le32 frame_width; - __le32 frame_height; - __le32 min_buffers; - __le32 max_buffers; - struct virtio_video_crop crop; - __le32 frame_rate; - __le32 num_planes; - struct virtio_video_plane_format plane_formats[VIRTIO_VIDEO_MAX_PLANES]; -}; - -struct virtio_video_get_params { - struct virtio_video_cmd_hdr hdr; - __le32 queue_type; /* One of VIRTIO_VIDEO_QUEUE_TYPE_* types */ - __u8 padding[4]; -}; - -struct virtio_video_get_params_resp { - struct virtio_video_cmd_hdr hdr; - struct virtio_video_params params; -}; - -/* VIRTIO_VIDEO_CMD_SET_PARAMS */ -struct virtio_video_set_params { - struct virtio_video_cmd_hdr hdr; - struct virtio_video_params params; -}; - -/* VIRTIO_VIDEO_CMD_QUERY_CONTROL */ -enum virtio_video_control_type { - VIRTIO_VIDEO_CONTROL_BITRATE = 1, - VIRTIO_VIDEO_CONTROL_PROFILE, - VIRTIO_VIDEO_CONTROL_LEVEL, -}; - -struct virtio_video_query_control_profile { - __le32 format; /* One of VIRTIO_VIDEO_FORMAT_* */ - __u8 padding[4]; -}; - -struct virtio_video_query_control_level { - __le32 format; /* One of VIRTIO_VIDEO_FORMAT_* */ - __u8 padding[4]; -}; - -struct virtio_video_query_control { - struct virtio_video_cmd_hdr hdr; - __le32 control; /* One of VIRTIO_VIDEO_CONTROL_* types */ - __u8 padding[4]; - /* - * Followed by a value of struct virtio_video_query_control_* - * in accordance with the value of control. - */ -}; - -struct virtio_video_query_control_resp_profile { - __le32 num; - __u8 padding[4]; - /* Followed by an array le32 profiles[] */ -}; - -struct virtio_video_query_control_resp_level { - __le32 num; - __u8 padding[4]; - /* Followed by an array le32 level[] */ -}; - -struct virtio_video_query_control_resp { - struct virtio_video_cmd_hdr hdr; - /* Followed by one of struct virtio_video_query_control_resp_* */ -}; - -/* VIRTIO_VIDEO_CMD_GET_CONTROL */ -struct virtio_video_get_control { - struct virtio_video_cmd_hdr hdr; - __le32 control; /* One of VIRTIO_VIDEO_CONTROL_* types */ - __u8 padding[4]; -}; - -struct virtio_video_control_val_bitrate { - __le32 bitrate; - __u8 padding[4]; -}; - -struct virtio_video_control_val_profile { - __le32 profile; - __u8 padding[4]; -}; - -struct virtio_video_control_val_level { - __le32 level; - __u8 padding[4]; -}; - -struct virtio_video_get_control_resp { - struct virtio_video_cmd_hdr hdr; - /* Followed by one of struct virtio_video_control_val_* */ -}; - -/* VIRTIO_VIDEO_CMD_SET_CONTROL */ -struct virtio_video_set_control { - struct virtio_video_cmd_hdr hdr; - __le32 control; /* One of VIRTIO_VIDEO_CONTROL_* types */ - __u8 padding[4]; - /* Followed by one of struct virtio_video_control_val_* */ -}; - -struct virtio_video_set_control_resp { - struct virtio_video_cmd_hdr hdr; -}; - -/* - * Events - */ - -enum virtio_video_event_type { - /* For all devices */ - VIRTIO_VIDEO_EVENT_ERROR = 0x0100, - - /* For decoder only */ - VIRTIO_VIDEO_EVENT_DECODER_RESOLUTION_CHANGED = 0x0200, -}; - -struct virtio_video_event { - __le32 event_type; /* One of VIRTIO_VIDEO_EVENT_* types */ - __le32 stream_id; -}; - -#endif /* _UAPI_LINUX_VIRTIO_VIDEO_H */ diff --git a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video.h b/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video.h deleted file mode 100644 index 9ece57db..00000000 --- a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video.h +++ /dev/null @@ -1,446 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* Common header for virtio video driver. - * - * Copyright 2020 OpenSynergy GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#ifndef _VIRTIO_VIDEO_H -#define _VIRTIO_VIDEO_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRIVER_NAME "virtio-video" - -#define VIRTIO_ID_VIDEO_DEC 31 -#define VIRTIO_ID_VIDEO_ENC 30 -#define VIRTIO_ID_VIDEO_CAM 100 - -#define MIN_BUFS_MIN 0 -#define MIN_BUFS_MAX VIDEO_MAX_FRAME -#define MIN_BUFS_STEP 1 -#define MIN_BUFS_DEF 1 - -struct video_format_frame { - struct virtio_video_format_frame frame; - struct virtio_video_format_range *frame_rates; -}; - -struct video_format { - struct list_head formats_list_entry; - struct virtio_video_format_desc desc; - struct video_format_frame *frames; -}; - -struct video_control_fmt_data { - uint32_t min; - uint32_t max; - uint32_t num; - uint32_t skip_mask; - uint32_t *entries; -}; - -struct video_control_format { - struct list_head controls_list_entry; - uint32_t format; - struct video_control_fmt_data *profile; - struct video_control_fmt_data *level; -}; - -struct video_plane_format { - uint32_t plane_size; - uint32_t stride; -}; - -struct video_format_info { - uint32_t fourcc_format; - uint32_t frame_rate; - uint32_t frame_width; - uint32_t frame_height; - uint32_t min_buffers; - uint32_t max_buffers; - struct virtio_video_crop crop; - uint32_t num_planes; - struct video_plane_format plane_format[VIRTIO_VIDEO_MAX_PLANES]; -}; - -struct video_control_info { - uint32_t profile; - uint32_t level; - uint32_t bitrate; -}; - -struct virtio_video_device; -struct virtio_video_vbuffer; - -typedef void (*virtio_video_resp_cb)(struct virtio_video_device *vvd, - struct virtio_video_vbuffer *vbuf); - -struct virtio_video_vbuffer { - char *buf; - int size; - uint32_t id; - - void *data_buf; - uint32_t data_size; - - char *resp_buf; - int resp_size; - - void *priv; - virtio_video_resp_cb resp_cb; - - bool is_sync; - struct completion reclaimed; - - struct list_head pending_list_entry; -}; - -struct virtio_video_cmd_queue { - struct virtqueue *vq; - bool ready; - spinlock_t qlock; - wait_queue_head_t reclaim_queue; -}; - -struct virtio_video_event_queue { - struct virtqueue *vq; - bool ready; - struct work_struct work; -}; - -enum video_stream_state { - STREAM_STATE_IDLE = 0, - STREAM_STATE_INIT, - STREAM_STATE_DYNAMIC_RES_CHANGE, /* specific to decoder */ - STREAM_STATE_RUNNING, - STREAM_STATE_DRAIN, - STREAM_STATE_STOPPED, - STREAM_STATE_RESET, /* specific to encoder */ - STREAM_STATE_ERROR, -}; - -struct virtio_video_stream { - uint32_t stream_id; - atomic_t state; - struct video_device *video_dev; - struct v4l2_fh fh; - struct mutex vq_mutex; - struct v4l2_ctrl_handler ctrl_handler; - struct video_format_info in_info; - struct video_format_info out_info; - struct video_control_info control; - struct video_format_frame *current_frame; -}; - -struct virtio_video_device { - struct virtio_device *vdev; - struct virtio_video_cmd_queue commandq; - struct virtio_video_event_queue eventq; - wait_queue_head_t wq; - - struct kmem_cache *vbufs; - struct virtio_video_event *evts; - - struct idr resource_idr; - spinlock_t resource_idr_lock; - struct idr stream_idr; - spinlock_t stream_idr_lock; - - uint32_t max_caps_len; - uint32_t max_resp_len; - - bool has_iommu; - bool supp_non_contig; - - int debug; - int use_dma_mem; - - struct v4l2_device v4l2_dev; - struct video_device video_dev; - struct mutex video_dev_mutex; - - bool is_m2m_dev; - struct v4l2_m2m_dev *m2m_dev; - - /* non-m2m queue (camera) */ - struct vb2_queue vb2_output_queue; - struct list_head pending_buf_list; - spinlock_t pending_buf_list_lock; - - uint32_t vbufs_sent; - struct list_head pending_vbuf_list; - - /* device_busy - to block multiple opens for non-m2m (camera) */ - bool device_busy; - - /* vid_dev_nr - try register starting at video device number */ - int vid_dev_nr; - - /* is_mplane_cam - camera has multiplanar capabilities (default true) */ - bool is_mplane_cam; - - /* VIRTIO_VIDEO_FUNC_ */ - uint32_t type; - - uint32_t num_input_fmts; - struct list_head input_fmt_list; - - uint32_t num_output_fmts; - struct list_head output_fmt_list; - - struct list_head controls_fmt_list; - struct virtio_video_device_ops *ops; -}; - -struct virtio_video_device_ops { - int (*init_ctrls)(struct virtio_video_stream *stream); - int (*init_queues)(void *priv, struct vb2_queue *src_vq, - struct vb2_queue *dst_vq); - void* (*get_fmt_list)(struct virtio_video_device *vvd); -}; - -struct virtio_video_buffer { - struct v4l2_m2m_buffer v4l2_m2m_vb; - uint32_t resource_id; - bool queued; - struct list_head list; -}; - -static inline gfp_t -virtio_video_gfp_flags(struct virtio_video_device *vvd) -{ - if (vvd->use_dma_mem) - return GFP_DMA; - else - return 0; -} - -static inline const struct vb2_mem_ops * -virtio_video_mem_ops(struct virtio_video_device *vvd) -{ - if (vvd->supp_non_contig) - return &vb2_dma_sg_memops; - else - return &vb2_dma_contig_memops; -} - -static inline struct virtio_video_device * -to_virtio_vd(struct video_device *video_dev) -{ - return container_of(video_dev, struct virtio_video_device, - video_dev); -} - -static inline struct virtio_video_stream *file2stream(struct file *file) -{ - return container_of(file->private_data, struct virtio_video_stream, fh); -} - -static inline struct virtio_video_stream *ctrl2stream(struct v4l2_ctrl *ctrl) -{ - return container_of(ctrl->handler, struct virtio_video_stream, - ctrl_handler); -} - -static inline struct virtio_video_buffer *to_virtio_vb(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *v4l2_vb = to_vb2_v4l2_buffer(vb); - - return container_of(v4l2_vb, struct virtio_video_buffer, - v4l2_m2m_vb.vb); -} - -static inline enum virtio_video_queue_type -to_virtio_queue_type(enum v4l2_buf_type type) -{ - if (V4L2_TYPE_IS_OUTPUT(type)) - return VIRTIO_VIDEO_QUEUE_TYPE_INPUT; - else - return VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT; -} - -static inline bool within_range(uint32_t min, uint32_t val, uint32_t max) -{ - return ((min <= val) && (val <= max)); -} - -static inline bool needs_alignment(uint32_t val, uint32_t a) -{ - if (a == 0 || IS_ALIGNED(val, a)) - return false; - - return true; -} - -enum video_stream_state virtio_video_state(struct virtio_video_stream *stream); -void virtio_video_state_reset(struct virtio_video_stream *stream); -void virtio_video_state_update(struct virtio_video_stream *stream, - enum video_stream_state new_state); - -int virtio_video_alloc_vbufs(struct virtio_video_device *vvd); -void virtio_video_free_vbufs(struct virtio_video_device *vvd); -int virtio_video_alloc_events(struct virtio_video_device *vvd); - -int virtio_video_device_init(struct virtio_video_device *vvd); -void virtio_video_device_deinit(struct virtio_video_device *vvd); - -int virtio_video_dec_init(struct virtio_video_device *vvd); -int virtio_video_enc_init(struct virtio_video_device *vvd); -int virtio_video_cam_init(struct virtio_video_device *vvd); - -void virtio_video_stream_id_get(struct virtio_video_device *vvd, - struct virtio_video_stream *stream, - uint32_t *id); -void virtio_video_stream_id_put(struct virtio_video_device *vvd, uint32_t id); -void virtio_video_resource_id_get(struct virtio_video_device *vvd, - uint32_t *id); -void virtio_video_resource_id_put(struct virtio_video_device *vvd, uint32_t id); - -int virtio_video_cmd_stream_create(struct virtio_video_device *vvd, - uint32_t stream_id, - enum virtio_video_format format, - const char *tag); -int virtio_video_cmd_stream_destroy(struct virtio_video_device *vvd, - uint32_t stream_id); -int virtio_video_cmd_stream_drain(struct virtio_video_device *vvd, - uint32_t stream_id); -int virtio_video_cmd_resource_attach(struct virtio_video_device *vvd, - uint32_t stream_id, uint32_t resource_id, - enum virtio_video_queue_type queue_type, - void *buf, size_t buf_size); -int virtio_video_cmd_resource_queue(struct virtio_video_device *vvd, - uint32_t stream_id, - struct virtio_video_buffer *virtio_vb, - uint32_t data_size[], uint8_t num_data_size, - enum virtio_video_queue_type queue_type); -int virtio_video_cmd_queue_detach_resources(struct virtio_video_device *vvd, - struct virtio_video_stream *stream, - enum virtio_video_queue_type queue_type); -int virtio_video_cmd_queue_clear(struct virtio_video_device *vvd, - struct virtio_video_stream *stream, - enum virtio_video_queue_type queue_type); -int virtio_video_cmd_query_capability(struct virtio_video_device *vvd, - void *resp_buf, size_t resp_size, - enum virtio_video_queue_type queue_type); -int virtio_video_query_control_profile(struct virtio_video_device *vvd, - void *resp_buf, size_t resp_size, - enum virtio_video_format format); -int virtio_video_query_control_level(struct virtio_video_device *vvd, - void *resp_buf, size_t resp_size, - enum virtio_video_format format); -int virtio_video_cmd_set_params(struct virtio_video_device *vvd, - struct virtio_video_stream *stream, - struct video_format_info *format_info, - enum virtio_video_queue_type queue_type); -int virtio_video_cmd_get_params(struct virtio_video_device *vvd, - struct virtio_video_stream *stream, - enum virtio_video_queue_type queue_type); -int virtio_video_cmd_set_control(struct virtio_video_device *vvd, - uint32_t stream_id, - enum virtio_video_control_type control, - uint32_t value); -int virtio_video_cmd_get_control(struct virtio_video_device *vvd, - struct virtio_video_stream *stream, - enum virtio_video_control_type control); - -void virtio_video_queue_res_chg_event(struct virtio_video_stream *stream); -void virtio_video_queue_eos_event(struct virtio_video_stream *stream); -void virtio_video_handle_error(struct virtio_video_stream *stream); -int virtio_video_queue_release_buffers(struct virtio_video_stream *stream, - enum virtio_video_queue_type queue_type); - -void virtio_video_cmd_cb(struct virtqueue *vq); -void virtio_video_event_cb(struct virtqueue *vq); -void virtio_video_process_events(struct work_struct *work); - -void virtio_video_buf_done(struct virtio_video_buffer *virtio_vb, - uint32_t flags, uint64_t timestamp, - uint32_t data_sizes[]); -int virtio_video_buf_plane_init(uint32_t idx,uint32_t resource_id, - struct virtio_video_device *vvd, - struct virtio_video_stream *stream, - struct vb2_buffer *vb); -int virtio_video_queue_setup(struct vb2_queue *vq, unsigned int *num_buffers, - unsigned int *num_planes, unsigned int sizes[], - struct device *alloc_devs[]); -int virtio_video_buf_init(struct vb2_buffer *vb); -void virtio_video_buf_cleanup(struct vb2_buffer *vb); -void virtio_video_buf_queue(struct vb2_buffer *vb); -int virtio_video_qbuf(struct file *file, void *priv, - struct v4l2_buffer *buf); -int virtio_video_dqbuf(struct file *file, void *priv, - struct v4l2_buffer *buf); -int virtio_video_querycap(struct file *file, void *fh, - struct v4l2_capability *cap); -int virtio_video_enum_framesizes(struct file *file, void *fh, - struct v4l2_frmsizeenum *f); -int virtio_video_enum_framemintervals(struct file *file, void *fh, - struct v4l2_frmivalenum *f); -int virtio_video_g_fmt(struct file *file, void *fh, struct v4l2_format *f); -int virtio_video_s_fmt(struct file *file, void *fh, struct v4l2_format *f); -int virtio_video_try_fmt(struct virtio_video_stream *stream, - struct v4l2_format *f); -int virtio_video_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *rb); -int virtio_video_subscribe_event(struct v4l2_fh *fh, - const struct v4l2_event_subscription *sub); - -void virtio_video_free_caps_list(struct list_head *caps_list); -int virtio_video_parse_virtio_capabilities(struct virtio_video_device *vvd, - void *input_buf, void *output_buf); -void virtio_video_clean_capability(struct virtio_video_device *vvd); -int virtio_video_parse_virtio_control(struct virtio_video_device *vvd); -void virtio_video_clean_control(struct virtio_video_device *vvd); - -uint32_t virtio_video_format_to_v4l2(uint32_t format); -uint32_t virtio_video_control_to_v4l2(uint32_t control); -uint32_t virtio_video_profile_to_v4l2(uint32_t profile); -uint32_t virtio_video_level_to_v4l2(uint32_t level); -uint32_t virtio_video_v4l2_format_to_virtio(uint32_t v4l2_format); -uint32_t virtio_video_v4l2_control_to_virtio(uint32_t v4l2_control); -uint32_t virtio_video_v4l2_profile_to_virtio(uint32_t v4l2_profile); -uint32_t virtio_video_v4l2_level_to_virtio(uint32_t v4l2_level); - -struct video_format *virtio_video_find_video_format(struct list_head *fmts_list, - uint32_t fourcc); -void virtio_video_format_from_info(struct video_format_info *info, - struct v4l2_pix_format_mplane *pix_mp); -void virtio_video_format_fill_default_info(struct video_format_info *dst_info, - struct video_format_info *src_info); -void virtio_video_pix_fmt_sp2mp(const struct v4l2_pix_format *pix, - struct v4l2_pix_format_mplane *pix_mp); -void virtio_video_pix_fmt_mp2sp(const struct v4l2_pix_format_mplane *pix_mp, - struct v4l2_pix_format *pix); - -int virtio_video_g_selection(struct file *file, void *fh, - struct v4l2_selection *sel); - -int virtio_video_stream_get_params(struct virtio_video_device *vvd, - struct virtio_video_stream *stream); -int virtio_video_stream_get_controls(struct virtio_video_device *vvd, - struct virtio_video_stream *stream); - -#endif /* _VIRTIO_VIDEO_H */ diff --git a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_cam.c b/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_cam.c deleted file mode 100644 index d657ba8a..00000000 --- a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_cam.c +++ /dev/null @@ -1,359 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* Capture for virtio video device. - * - * Copyright 2021 OpenSynergy GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#include -#include -#include - -#include "virtio_video.h" - -static int virtio_video_cam_start_streaming(struct vb2_queue *vq, - unsigned int count) -{ - struct virtio_video_stream *stream = vb2_get_drv_priv(vq); - - if (virtio_video_state(stream) == STREAM_STATE_ERROR) - return -EIO; - - if (virtio_video_state(stream) >= STREAM_STATE_INIT) - virtio_video_state_update(stream, STREAM_STATE_RUNNING); - - return 0; -} - -static void virtio_video_cam_stop_streaming(struct vb2_queue *vq) -{ - struct virtio_video_stream *stream = vb2_get_drv_priv(vq); - - virtio_video_queue_release_buffers(stream, - VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT); - - vb2_wait_for_all_buffers(vq); -} - -static const struct vb2_ops virtio_video_cam_qops = { - .queue_setup = virtio_video_queue_setup, - .buf_init = virtio_video_buf_init, - .buf_cleanup = virtio_video_buf_cleanup, - .buf_queue = virtio_video_buf_queue, - .start_streaming = virtio_video_cam_start_streaming, - .stop_streaming = virtio_video_cam_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, -}; - -static int virtio_video_cam_g_ctrl(struct v4l2_ctrl *ctrl) -{ - int ret = 0; - struct virtio_video_stream *stream = ctrl2stream(ctrl); - - if (virtio_video_state(stream) == STREAM_STATE_ERROR) - return -EIO; - - switch (ctrl->id) { - case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: - if (virtio_video_state(stream) >= - STREAM_STATE_DYNAMIC_RES_CHANGE) - ctrl->val = stream->out_info.min_buffers; - else - ctrl->val = 0; - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static const struct v4l2_ctrl_ops virtio_video_cam_ctrl_ops = { - .g_volatile_ctrl = virtio_video_cam_g_ctrl, -}; - -int virtio_video_cam_init_ctrls(struct virtio_video_stream *stream) -{ - struct v4l2_ctrl *ctrl; - - v4l2_ctrl_handler_init(&stream->ctrl_handler, 2); - - ctrl = v4l2_ctrl_new_std(&stream->ctrl_handler, - &virtio_video_cam_ctrl_ops, - V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, - MIN_BUFS_MIN, MIN_BUFS_MAX, MIN_BUFS_STEP, - MIN_BUFS_DEF); - - if (ctrl) - ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; - - if (stream->ctrl_handler.error) - return stream->ctrl_handler.error; - - v4l2_ctrl_handler_setup(&stream->ctrl_handler); - - return 0; -} - -int virtio_video_cam_init_queues(void *priv, struct vb2_queue *src_vq, - struct vb2_queue *dst_vq) -{ - struct virtio_video_stream *stream = priv; - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - struct device *dev = vvd->v4l2_dev.dev; - int vq_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - - if (!vvd->is_mplane_cam) - vq_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - dst_vq->type = vq_type; - dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; - dst_vq->drv_priv = stream; - dst_vq->buf_struct_size = sizeof(struct virtio_video_buffer); - dst_vq->ops = &virtio_video_cam_qops; - dst_vq->mem_ops = virtio_video_mem_ops(vvd); - dst_vq->min_buffers_needed = stream->out_info.min_buffers; - dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - dst_vq->lock = &stream->vq_mutex; - dst_vq->gfp_flags = virtio_video_gfp_flags(vvd); - dst_vq->dev = dev; - - return vb2_queue_init(dst_vq); -} - -int virtio_video_cam_try_fmt(struct file *file, void *fh, struct v4l2_format *f) -{ - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - struct v4l2_format *fmt_try = f; - struct v4l2_format fmt_mp = { 0 }; - int ret; - - if (!vvd->is_mplane_cam) { - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - fmt_mp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - fmt_try = &fmt_mp; - - virtio_video_pix_fmt_sp2mp(&f->fmt.pix, &fmt_try->fmt.pix_mp); - } - - ret = virtio_video_try_fmt(stream, fmt_try); - if (ret) - return ret; - - if (!vvd->is_mplane_cam) { - if (fmt_try->fmt.pix_mp.num_planes != 1) - return -EINVAL; - - virtio_video_pix_fmt_mp2sp(&fmt_try->fmt.pix_mp, &f->fmt.pix); - } - - return 0; -} - -static int virtio_video_cam_enum_fmt_vid_cap(struct file *file, void *fh, - struct v4l2_fmtdesc *f) -{ - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - struct video_format *fmt; - int idx = 0; - - if (virtio_video_state(stream) == STREAM_STATE_ERROR) - return -EIO; - - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - return -EINVAL; - - if (f->index >= vvd->num_output_fmts) - return -EINVAL; - - list_for_each_entry(fmt, &vvd->output_fmt_list, formats_list_entry) { - if (f->index == idx) { - f->pixelformat = fmt->desc.format; - return 0; - } - idx++; - } - return -EINVAL; -} - -static int virtio_video_cam_g_fmt(struct file *file, void *fh, - struct v4l2_format *f) -{ - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - struct v4l2_format fmt_mp = { 0 }; - struct v4l2_format *fmt_get = f; - int ret; - - if (!vvd->is_mplane_cam) { - fmt_mp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - fmt_get = &fmt_mp; - } - - ret = virtio_video_g_fmt(file, fh, fmt_get); - if (ret) - return ret; - - if (virtio_video_state(stream) == STREAM_STATE_IDLE) - virtio_video_state_update(stream, STREAM_STATE_INIT); - - if (!vvd->is_mplane_cam) { - if (fmt_get->fmt.pix_mp.num_planes != 1) - return -EINVAL; - - virtio_video_pix_fmt_mp2sp(&fmt_get->fmt.pix_mp, &f->fmt.pix); - } - - return 0; -} - -static int virtio_video_cam_s_fmt(struct file *file, void *fh, - struct v4l2_format *f) -{ - int ret; - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - struct v4l2_format fmt_mp = { 0 }; - struct v4l2_format *fmt_set = f; - - if (!vvd->is_mplane_cam) { - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - fmt_mp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - fmt_set = &fmt_mp; - - virtio_video_pix_fmt_sp2mp(&f->fmt.pix, &fmt_set->fmt.pix_mp); - } - - ret = virtio_video_s_fmt(file, fh, fmt_set); - if (ret) - return ret; - - if (virtio_video_state(stream) == STREAM_STATE_IDLE) - virtio_video_state_update(stream, STREAM_STATE_INIT); - - if (!vvd->is_mplane_cam) { - if (fmt_set->fmt.pix_mp.num_planes != 1) - return -EINVAL; - - virtio_video_pix_fmt_mp2sp(&fmt_set->fmt.pix_mp, &f->fmt.pix); - } - - return 0; -} - -static int virtio_video_cam_s_selection(struct file *file, void *fh, - struct v4l2_selection *sel) -{ - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - int ret; - - if (V4L2_TYPE_IS_OUTPUT(sel->type)) - return -EINVAL; - - switch (sel->target) { - case V4L2_SEL_TGT_CROP: - stream->out_info.crop.top = sel->r.top; - stream->out_info.crop.left = sel->r.left; - stream->out_info.crop.width = sel->r.width; - stream->out_info.crop.height = sel->r.height; - v4l2_info(&vvd->v4l2_dev, - "Set : top:%d, left:%d, w:%d, h:%d\n", - sel->r.top, sel->r.left, sel->r.width, sel->r.height); - break; - default: - return -EINVAL; - } - - ret = virtio_video_cmd_set_params(vvd, stream, &stream->out_info, - VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT); - if (ret) - return -EINVAL; - - ret = virtio_video_cmd_get_params(vvd, stream, - VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT); - return ret; -} - -static const struct v4l2_ioctl_ops virtio_video_cam_ioctl_ops = { - .vidioc_querycap = virtio_video_querycap, - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 3, 0)) - .vidioc_enum_fmt_vid_cap_mplane = virtio_video_cam_enum_fmt_vid_cap, -#endif - .vidioc_try_fmt_vid_cap_mplane = virtio_video_cam_try_fmt, - .vidioc_g_fmt_vid_cap_mplane = virtio_video_cam_g_fmt, - .vidioc_s_fmt_vid_cap_mplane = virtio_video_cam_s_fmt, - - .vidioc_enum_fmt_vid_cap = virtio_video_cam_enum_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = virtio_video_cam_try_fmt, - .vidioc_g_fmt_vid_cap = virtio_video_cam_g_fmt, - .vidioc_s_fmt_vid_cap = virtio_video_cam_s_fmt, - - .vidioc_g_selection = virtio_video_g_selection, - .vidioc_s_selection = virtio_video_cam_s_selection, - - .vidioc_enum_frameintervals = virtio_video_enum_framemintervals, - .vidioc_enum_framesizes = virtio_video_enum_framesizes, - - .vidioc_reqbufs = virtio_video_reqbufs, - .vidioc_querybuf = vb2_ioctl_querybuf, - .vidioc_qbuf = virtio_video_qbuf, - .vidioc_dqbuf = virtio_video_dqbuf, - .vidioc_prepare_buf = vb2_ioctl_prepare_buf, - .vidioc_create_bufs = vb2_ioctl_create_bufs, - .vidioc_expbuf = vb2_ioctl_expbuf, - - .vidioc_streamon = vb2_ioctl_streamon, - .vidioc_streamoff = vb2_ioctl_streamoff, - - .vidioc_subscribe_event = virtio_video_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -void *virtio_video_cam_get_fmt_list(struct virtio_video_device *vvd) -{ - return &vvd->output_fmt_list; -} - -static struct virtio_video_device_ops virtio_video_cam_ops = { - .init_ctrls = virtio_video_cam_init_ctrls, - .init_queues = virtio_video_cam_init_queues, - .get_fmt_list = virtio_video_cam_get_fmt_list, -}; - -int virtio_video_cam_init(struct virtio_video_device *vvd) -{ - ssize_t num; - struct video_device *vd = &vvd->video_dev; - - vd->ioctl_ops = &virtio_video_cam_ioctl_ops; - vvd->ops = &virtio_video_cam_ops; - - num = strscpy(vd->name, "camera", sizeof(vd->name)); - if (num < 0) - return num; - - return 0; -} diff --git a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_caps.c b/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_caps.c deleted file mode 100644 index fc815b18..00000000 --- a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_caps.c +++ /dev/null @@ -1,460 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* Driver for virtio video device. - * - * Copyright 2020 OpenSynergy GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#include -#include - -#include "virtio_video.h" - -static void virtio_video_free_frame_rates(struct video_format_frame *frame) -{ - kfree(frame->frame_rates); -} - -static void virtio_video_free_frames(struct video_format *fmt) -{ - size_t idx = 0; - - for (idx = 0; idx < fmt->desc.num_frames; idx++) - virtio_video_free_frame_rates(&fmt->frames[idx]); - kfree(fmt->frames); -} - -static void virtio_video_free_fmt(struct list_head *fmts_list) -{ - struct video_format *fmt, *tmp; - - list_for_each_entry_safe(fmt, tmp, fmts_list, formats_list_entry) { - list_del(&fmt->formats_list_entry); - virtio_video_free_frames(fmt); - kfree(fmt); - } -} - -static void virtio_video_free_fmts(struct virtio_video_device *vvd) -{ - virtio_video_free_fmt(&vvd->input_fmt_list); - virtio_video_free_fmt(&vvd->output_fmt_list); -} - -static void virtio_video_copy_fmt_range(struct virtio_video_format_range *d_rge, - struct virtio_video_format_range *s_rge) -{ - d_rge->min = le32_to_cpu(s_rge->min); - d_rge->max = le32_to_cpu(s_rge->max); - d_rge->step = le32_to_cpu(s_rge->step); -} - -static size_t -virtio_video_parse_virtio_frame_rate(struct virtio_video_device *vvd, - struct virtio_video_format_range *f_rate, - void *buf) -{ - struct virtio_video_format_range *virtio_frame_rate; - - virtio_frame_rate = buf; - virtio_video_copy_fmt_range(f_rate, virtio_frame_rate); - - return sizeof(struct virtio_video_format_range); -} - -static size_t virtio_video_parse_virtio_frame(struct virtio_video_device *vvd, - struct video_format_frame *frm, - void *buf) -{ - struct virtio_video_format_frame *virtio_frame; - struct virtio_video_format_frame *frame = &frm->frame; - struct virtio_video_format_range *rate; - size_t idx, offset, extra_size; - - virtio_frame = buf; - - virtio_video_copy_fmt_range(&frame->width, &virtio_frame->width); - virtio_video_copy_fmt_range(&frame->height, &virtio_frame->height); - - frame->num_rates = le32_to_cpu(virtio_frame->num_rates); - frm->frame_rates = kcalloc(frame->num_rates, - sizeof(struct virtio_video_format_range), - GFP_KERNEL); - - offset = sizeof(struct virtio_video_format_frame); - for (idx = 0; idx < frame->num_rates; idx++) { - rate = &frm->frame_rates[idx]; - extra_size = - virtio_video_parse_virtio_frame_rate(vvd, rate, - buf + offset); - if (extra_size == 0) { - kfree(frm->frame_rates); - v4l2_err(&vvd->v4l2_dev, - "failed to parse frame rate\n"); - return 0; - } - offset += extra_size; - } - - return offset; -} - -static size_t virtio_video_parse_virtio_fmt(struct virtio_video_device *vvd, - struct video_format *fmt, void *buf) -{ - struct virtio_video_format_desc *virtio_fmt_desc; - struct virtio_video_format_desc *fmt_desc; - struct video_format_frame *frame; - size_t idx, offset, extra_size; - - virtio_fmt_desc = buf; - fmt_desc = &fmt->desc; - - fmt_desc->format = - virtio_video_format_to_v4l2 - (le32_to_cpu(virtio_fmt_desc->format)); - fmt_desc->mask = le64_to_cpu(virtio_fmt_desc->mask); - fmt_desc->planes_layout = le32_to_cpu(virtio_fmt_desc->planes_layout); - - fmt_desc->num_frames = le32_to_cpu(virtio_fmt_desc->num_frames); - fmt->frames = kcalloc(fmt_desc->num_frames, - sizeof(struct video_format_frame), - GFP_KERNEL); - - offset = sizeof(struct virtio_video_format_desc); - for (idx = 0; idx < fmt_desc->num_frames; idx++) { - frame = &fmt->frames[idx]; - extra_size = - virtio_video_parse_virtio_frame(vvd, frame, - buf + offset); - if (extra_size == 0) { - kfree(fmt->frames); - v4l2_err(&vvd->v4l2_dev, "failed to parse frame\n"); - return 0; - } - offset += extra_size; - } - - return offset; -} - -int virtio_video_parse_virtio_capability(struct virtio_video_device *vvd, - void *resp_buf, - struct list_head *ret_fmt_list, - uint32_t *ret_num_fmts) -{ - struct virtio_video_query_capability_resp *resp = resp_buf; - struct video_format *fmt; - uint32_t fmt_count; - int fmt_idx; - size_t offset; - int ret; - - if (!resp || ret_fmt_list == NULL || ret_num_fmts == NULL) { - v4l2_err(&vvd->v4l2_dev, "invalid arguments!\n"); - return -EINVAL; - } - - if (le32_to_cpu(resp->num_descs) <= 0) { - v4l2_err(&vvd->v4l2_dev, "invalid capability response\n"); - return -EINVAL; - } - - fmt_count = le32_to_cpu(resp->num_descs); - offset = sizeof(struct virtio_video_query_capability_resp); - - for (fmt_idx = 0; fmt_idx < fmt_count; fmt_idx++) { - size_t fmt_size = 0; - - fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); - if (!fmt) { - ret = -ENOMEM; - goto alloc_err; - } - - fmt_size = virtio_video_parse_virtio_fmt(vvd, fmt, - resp_buf + offset); - if (fmt_size == 0) { - v4l2_err(&vvd->v4l2_dev, "failed to parse fmt\n"); - ret = -ENOENT; - goto parse_fmt_err; - } - offset += fmt_size; - list_add(&fmt->formats_list_entry, ret_fmt_list); - } - - *ret_num_fmts = fmt_count; - return 0; - -parse_fmt_err: - kfree(fmt); -alloc_err: - virtio_video_free_fmts(vvd); - return ret; -} - -int virtio_video_parse_virtio_capabilities(struct virtio_video_device *vvd, - void *input_buf, void *output_buf) -{ - int ret; - - if (input_buf) { - ret = virtio_video_parse_virtio_capability(vvd, input_buf, - &vvd->input_fmt_list, - &vvd->num_input_fmts); - if (ret) { - v4l2_err(&vvd->v4l2_dev, - "Failed to parse input capability: %d\n", - ret); - return ret; - } - } - - if (output_buf) { - ret = virtio_video_parse_virtio_capability(vvd, output_buf, - &vvd->output_fmt_list, - &vvd->num_output_fmts); - if (ret) { - v4l2_err(&vvd->v4l2_dev, - "Failed to parse output capability: %d\n", - ret); - return ret; - } - } - - return 0; -} - -void virtio_video_clean_capability(struct virtio_video_device *vvd) -{ - virtio_video_free_fmts(vvd); -} - -static void -virtio_video_free_control_fmt_data(struct video_control_fmt_data *data) -{ - kfree(data->entries); - kfree(data); -} - -static void virtio_video_free_control_formats(struct virtio_video_device *vvd) -{ - struct video_control_format *c_fmt, *tmp; - - list_for_each_entry_safe(c_fmt, tmp, &vvd->controls_fmt_list, - controls_list_entry) { - list_del(&c_fmt->controls_list_entry); - virtio_video_free_control_fmt_data(c_fmt->profile); - virtio_video_free_control_fmt_data(c_fmt->level); - kfree(c_fmt); - } -} - -static int virtio_video_parse_control_levels(struct virtio_video_device *vvd, - struct video_control_format *fmt) -{ - int idx, ret; - struct virtio_video_query_control_resp *resp_buf; - struct virtio_video_query_control_resp_level *l_resp_buf; - struct video_control_fmt_data *level; - enum virtio_video_format virtio_format; - uint32_t *virtio_levels; - uint32_t num_levels, mask = 0; - int max = 0, min = UINT_MAX; - size_t resp_size; - - resp_size = vvd->max_resp_len; - - virtio_format = virtio_video_v4l2_format_to_virtio(fmt->format); - - resp_buf = kzalloc(resp_size, GFP_KERNEL); - if (IS_ERR(resp_buf)) { - ret = PTR_ERR(resp_buf); - goto lvl_err; - } - - ret = virtio_video_query_control_level(vvd, resp_buf, resp_size, - virtio_format); - if (ret) { - v4l2_err(&vvd->v4l2_dev, "failed to query level\n"); - goto lvl_err; - } - - l_resp_buf = (void *)((char *)resp_buf + sizeof(*resp_buf)); - num_levels = le32_to_cpu(l_resp_buf->num); - if (num_levels == 0) - goto lvl_err; - - fmt->level = kzalloc(sizeof(*level), GFP_KERNEL); - if (!fmt->level) { - ret = -ENOMEM; - goto lvl_err; - } - - level = fmt->level; - level->entries = kcalloc(num_levels, sizeof(uint32_t), GFP_KERNEL); - if (!level->entries) { - kfree(fmt->level); - ret = -ENOMEM; - goto lvl_err; - } - - virtio_levels = (void *)((char *)l_resp_buf + sizeof(*l_resp_buf)); - - for (idx = 0; idx < num_levels; idx++) { - level->entries[idx] = - virtio_video_level_to_v4l2 - (le32_to_cpu(virtio_levels[idx])); - - mask = mask | (1 << level->entries[idx]); - if (level->entries[idx] > max) - max = level->entries[idx]; - if (level->entries[idx] < min) - min = level->entries[idx]; - } - level->min = min; - level->max = max; - level->num = num_levels; - level->skip_mask = ~mask; - -lvl_err: - kfree(resp_buf); - - return ret; -} - -static int virtio_video_parse_control_profiles(struct virtio_video_device *vvd, - struct video_control_format *fmt) -{ - int idx, ret; - struct virtio_video_query_control_resp *resp_buf; - struct virtio_video_query_control_resp_profile *p_resp_buf; - struct video_control_fmt_data *profile; - uint32_t virtio_format, num_profiles, mask = 0; - uint32_t *virtio_profiles; - int max = 0, min = UINT_MAX; - size_t resp_size; - - resp_size = vvd->max_resp_len; - virtio_format = virtio_video_v4l2_format_to_virtio(fmt->format); - resp_buf = kzalloc(resp_size, GFP_KERNEL); - if (IS_ERR(resp_buf)) { - ret = PTR_ERR(resp_buf); - goto prf_err; - } - - ret = virtio_video_query_control_profile(vvd, resp_buf, resp_size, - virtio_format); - if (ret) { - v4l2_err(&vvd->v4l2_dev, "failed to query profile\n"); - goto prf_err; - } - - p_resp_buf = (void *)((char *)resp_buf + sizeof(*resp_buf)); - num_profiles = le32_to_cpu(p_resp_buf->num); - if (num_profiles == 0) - goto prf_err; - - fmt->profile = kzalloc(sizeof(*profile), GFP_KERNEL); - if (!fmt->profile) { - ret = -ENOMEM; - goto prf_err; - } - - profile = fmt->profile; - profile->entries = kcalloc(num_profiles, sizeof(uint32_t), GFP_KERNEL); - if (!profile->entries) { - kfree(fmt->profile); - ret = -ENOMEM; - goto prf_err; - } - - virtio_profiles = (void *)((char *)p_resp_buf + sizeof(*p_resp_buf)); - - for (idx = 0; idx < num_profiles; idx++) { - profile->entries[idx] = - virtio_video_profile_to_v4l2 - (le32_to_cpu(virtio_profiles[idx])); - - mask = mask | (1 << profile->entries[idx]); - if (profile->entries[idx] > max) - max = profile->entries[idx]; - if (profile->entries[idx] < min) - min = profile->entries[idx]; - } - profile->min = min; - profile->max = max; - profile->num = num_profiles; - profile->skip_mask = ~mask; - -prf_err: - kfree(resp_buf); - - return ret; -} - -int virtio_video_parse_virtio_control(struct virtio_video_device *vvd) -{ - struct video_format *fmt; - struct video_control_format *c_fmt; - uint32_t virtio_format; - int ret; - - list_for_each_entry(fmt, &vvd->output_fmt_list, formats_list_entry) { - virtio_format = - virtio_video_v4l2_format_to_virtio(fmt->desc.format); - if (virtio_format < VIRTIO_VIDEO_FORMAT_CODED_MIN || - virtio_format > VIRTIO_VIDEO_FORMAT_CODED_MAX) - continue; - - c_fmt = kzalloc(sizeof(*c_fmt), GFP_KERNEL); - if (!c_fmt) { - ret = -ENOMEM; - goto parse_ctrl_alloc_err; - } - - c_fmt->format = fmt->desc.format; - - ret = virtio_video_parse_control_profiles(vvd, c_fmt); - if (ret) { - v4l2_err(&vvd->v4l2_dev, - "failed to parse control profile\n"); - goto parse_ctrl_prf_err; - } - - ret = virtio_video_parse_control_levels(vvd, c_fmt); - if (ret) { - v4l2_err(&vvd->v4l2_dev, - "failed to parse control level\n"); - goto parse_ctrl_lvl_err; - } - list_add(&c_fmt->controls_list_entry, &vvd->controls_fmt_list); - } - return 0; - -parse_ctrl_lvl_err: - virtio_video_free_control_fmt_data(c_fmt->profile); -parse_ctrl_prf_err: - kfree(c_fmt); -parse_ctrl_alloc_err: - virtio_video_free_control_formats(vvd); - - return ret; -} - -void virtio_video_clean_control(struct virtio_video_device *vvd) -{ - virtio_video_free_control_formats(vvd); -} diff --git a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_dec.c b/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_dec.c deleted file mode 100644 index 301a9a16..00000000 --- a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_dec.c +++ /dev/null @@ -1,424 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* Decoder for virtio video device. - * - * Copyright 2020 OpenSynergy GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#include -#include -#include - -#include "virtio_video.h" - -static int virtio_video_dec_start_streaming(struct vb2_queue *vq, - unsigned int count) -{ - struct virtio_video_stream *stream = vb2_get_drv_priv(vq); - - if (virtio_video_state(stream) == STREAM_STATE_ERROR) - return -EIO; - - if (!V4L2_TYPE_IS_OUTPUT(vq->type) && - virtio_video_state(stream) >= STREAM_STATE_INIT) - virtio_video_state_update(stream, STREAM_STATE_RUNNING); - - return 0; -} - -static void virtio_video_dec_stop_streaming(struct vb2_queue *vq) -{ - int queue_type; - struct virtio_video_stream *stream = vb2_get_drv_priv(vq); - - if (V4L2_TYPE_IS_OUTPUT(vq->type)) - queue_type = VIRTIO_VIDEO_QUEUE_TYPE_INPUT; - else - queue_type = VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT; - - virtio_video_queue_release_buffers(stream, queue_type); - vb2_wait_for_all_buffers(vq); -} - -static const struct vb2_ops virtio_video_dec_qops = { - .queue_setup = virtio_video_queue_setup, - .buf_init = virtio_video_buf_init, - .buf_cleanup = virtio_video_buf_cleanup, - .buf_queue = virtio_video_buf_queue, - .start_streaming = virtio_video_dec_start_streaming, - .stop_streaming = virtio_video_dec_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, -}; - -static int virtio_video_dec_g_ctrl(struct v4l2_ctrl *ctrl) -{ - int ret = 0; - struct virtio_video_stream *stream = ctrl2stream(ctrl); - - if (virtio_video_state(stream) == STREAM_STATE_ERROR) - return -EIO; - - switch (ctrl->id) { - case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: - if (virtio_video_state(stream) >= - STREAM_STATE_DYNAMIC_RES_CHANGE) - ctrl->val = stream->out_info.min_buffers; - else - ctrl->val = 0; - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static const struct v4l2_ctrl_ops virtio_video_dec_ctrl_ops = { - .g_volatile_ctrl = virtio_video_dec_g_ctrl, -}; - -int virtio_video_dec_init_ctrls(struct virtio_video_stream *stream) -{ - struct v4l2_ctrl *ctrl; - - v4l2_ctrl_handler_init(&stream->ctrl_handler, 2); - - ctrl = v4l2_ctrl_new_std(&stream->ctrl_handler, - &virtio_video_dec_ctrl_ops, - V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, - MIN_BUFS_MIN, MIN_BUFS_MAX, MIN_BUFS_STEP, - MIN_BUFS_DEF); - - if (ctrl) - ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; - - if (stream->ctrl_handler.error) - return stream->ctrl_handler.error; - - (void)v4l2_ctrl_new_std(&stream->ctrl_handler, NULL, - V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, - MIN_BUFS_MIN, MIN_BUFS_MAX, MIN_BUFS_STEP, - stream->in_info.min_buffers); - - if (stream->ctrl_handler.error) - return stream->ctrl_handler.error; - - v4l2_ctrl_handler_setup(&stream->ctrl_handler); - - return 0; -} - -int virtio_video_dec_init_queues(void *priv, struct vb2_queue *src_vq, - struct vb2_queue *dst_vq) -{ - int ret; - struct virtio_video_stream *stream = priv; - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - struct device *dev = vvd->v4l2_dev.dev; - - src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - src_vq->io_modes = VB2_MMAP | VB2_DMABUF; - src_vq->drv_priv = stream; - src_vq->buf_struct_size = sizeof(struct virtio_video_buffer); - src_vq->ops = &virtio_video_dec_qops; - src_vq->mem_ops = virtio_video_mem_ops(vvd); - src_vq->min_buffers_needed = stream->in_info.min_buffers; - src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; - src_vq->lock = &stream->vq_mutex; - src_vq->gfp_flags = virtio_video_gfp_flags(vvd); - src_vq->dev = dev; - - ret = vb2_queue_init(src_vq); - if (ret) - return ret; - - dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; - dst_vq->drv_priv = stream; - dst_vq->buf_struct_size = sizeof(struct virtio_video_buffer); - dst_vq->ops = &virtio_video_dec_qops; - dst_vq->mem_ops = virtio_video_mem_ops(vvd); - dst_vq->min_buffers_needed = stream->out_info.min_buffers; - dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; - dst_vq->lock = &stream->vq_mutex; - dst_vq->gfp_flags = virtio_video_gfp_flags(vvd); - dst_vq->dev = dev; - - return vb2_queue_init(dst_vq); -} - -static int virtio_video_try_decoder_cmd(struct file *file, void *fh, - struct v4l2_decoder_cmd *cmd) -{ - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = video_drvdata(file); - - if (virtio_video_state(stream) == STREAM_STATE_ERROR) - return -EIO; - - if (virtio_video_state(stream) == STREAM_STATE_DRAIN) - return -EBUSY; - - switch (cmd->cmd) { - case V4L2_DEC_CMD_STOP: - case V4L2_DEC_CMD_START: - if (cmd->flags != 0) { - v4l2_err(&vvd->v4l2_dev, "flags=%u are not supported", - cmd->flags); - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - return 0; -} - -static int virtio_video_decoder_cmd(struct file *file, void *fh, - struct v4l2_decoder_cmd *cmd) -{ - int ret; - struct vb2_queue *src_vq, *dst_vq; - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = video_drvdata(file); - - ret = virtio_video_try_decoder_cmd(file, fh, cmd); - if (ret < 0) - return ret; - - dst_vq = v4l2_m2m_get_vq(stream->fh.m2m_ctx, - V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); - - switch (cmd->cmd) { - case V4L2_DEC_CMD_START: - vb2_clear_last_buffer_dequeued(dst_vq); - break; - case V4L2_DEC_CMD_STOP: - src_vq = v4l2_m2m_get_vq(stream->fh.m2m_ctx, - V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - - if (!vb2_is_streaming(src_vq)) { - v4l2_dbg(1, vvd->debug, - &vvd->v4l2_dev, "output is not streaming\n"); - return 0; - } - - if (!vb2_is_streaming(dst_vq)) { - v4l2_dbg(1, vvd->debug, - &vvd->v4l2_dev, "capture is not streaming\n"); - return 0; - } - - ret = virtio_video_cmd_stream_drain(vvd, stream->stream_id); - if (ret) { - v4l2_err(&vvd->v4l2_dev, "failed to drain stream\n"); - return ret; - } - - virtio_video_state_update(stream, STREAM_STATE_DRAIN); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int virtio_video_dec_enum_fmt_vid_cap(struct file *file, void *fh, - struct v4l2_fmtdesc *f) -{ - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - struct video_format_info *info; - struct video_format *fmt; - unsigned long input_mask = 0; - int idx = 0, bit_num = 0; - - if (virtio_video_state(stream) == STREAM_STATE_ERROR) - return -EIO; - - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - return -EINVAL; - - if (f->index >= vvd->num_output_fmts) - return -EINVAL; - - info = &stream->in_info; - list_for_each_entry(fmt, &vvd->input_fmt_list, formats_list_entry) { - if (info->fourcc_format == fmt->desc.format) { - input_mask = fmt->desc.mask; - break; - } - } - - if (input_mask == 0) - return -EINVAL; - - list_for_each_entry(fmt, &vvd->output_fmt_list, formats_list_entry) { - if (test_bit(bit_num, &input_mask)) { - if (f->index == idx) { - f->pixelformat = fmt->desc.format; - return 0; - } - idx++; - } - bit_num++; - } - return -EINVAL; -} - - -int virtio_video_dec_enum_fmt_vid_out(struct file *file, void *fh, - struct v4l2_fmtdesc *f) -{ - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - struct video_format *fmt; - int idx = 0; - - if (virtio_video_state(stream) == STREAM_STATE_ERROR) - return -EIO; - - if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) - return -EINVAL; - - if (f->index >= vvd->num_input_fmts) - return -EINVAL; - - list_for_each_entry(fmt, &vvd->input_fmt_list, formats_list_entry) { - if (f->index == idx) { - f->pixelformat = fmt->desc.format; - return 0; - } - idx++; - } - return -EINVAL; -} - -static int virtio_video_dec_s_fmt(struct file *file, void *fh, - struct v4l2_format *f) -{ - int ret; - struct virtio_video_stream *stream = file2stream(file); - - ret = virtio_video_s_fmt(file, fh, f); - if (ret) - return ret; - - if (V4L2_TYPE_IS_OUTPUT(f->type)) { - if (virtio_video_state(stream) == STREAM_STATE_IDLE) - virtio_video_state_update(stream, STREAM_STATE_INIT); - } - - return 0; -} - -static int virtio_video_dec_s_selection(struct file *file, void *fh, - struct v4l2_selection *sel) -{ - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - int ret; - - if (V4L2_TYPE_IS_OUTPUT(sel->type)) - return -EINVAL; - - switch (sel->target) { - case V4L2_SEL_TGT_COMPOSE: - stream->out_info.crop.top = sel->r.top; - stream->out_info.crop.left = sel->r.left; - stream->out_info.crop.width = sel->r.width; - stream->out_info.crop.height = sel->r.height; - break; - default: - return -EINVAL; - } - - ret = virtio_video_cmd_set_params(vvd, stream, &stream->out_info, - VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT); - if (ret) - return -EINVAL; - - return virtio_video_cmd_get_params(vvd, stream, - VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT); -} - -static const struct v4l2_ioctl_ops virtio_video_dec_ioctl_ops = { - .vidioc_querycap = virtio_video_querycap, - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) - .vidioc_enum_fmt_vid_cap = virtio_video_dec_enum_fmt_vid_cap, - .vidioc_enum_fmt_vid_out = virtio_video_dec_enum_fmt_vid_out, -#else - .vidioc_enum_fmt_vid_cap_mplane = virtio_video_dec_enum_fmt_vid_cap, - .vidioc_enum_fmt_vid_out_mplane = virtio_video_dec_enum_fmt_vid_out, -#endif - .vidioc_g_fmt_vid_cap_mplane = virtio_video_g_fmt, - .vidioc_s_fmt_vid_cap_mplane = virtio_video_dec_s_fmt, - - .vidioc_g_fmt_vid_out_mplane = virtio_video_g_fmt, - .vidioc_s_fmt_vid_out_mplane = virtio_video_dec_s_fmt, - - .vidioc_g_selection = virtio_video_g_selection, - .vidioc_s_selection = virtio_video_dec_s_selection, - - .vidioc_try_decoder_cmd = virtio_video_try_decoder_cmd, - .vidioc_decoder_cmd = virtio_video_decoder_cmd, - .vidioc_enum_frameintervals = virtio_video_enum_framemintervals, - .vidioc_enum_framesizes = virtio_video_enum_framesizes, - - .vidioc_reqbufs = virtio_video_reqbufs, - .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, - .vidioc_qbuf = virtio_video_qbuf, - .vidioc_dqbuf = virtio_video_dqbuf, - .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, - .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, - .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, - - .vidioc_streamon = v4l2_m2m_ioctl_streamon, - .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, - - .vidioc_subscribe_event = virtio_video_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -void *virtio_video_dec_get_fmt_list(struct virtio_video_device *vvd) -{ - return &vvd->input_fmt_list; -} - -static struct virtio_video_device_ops virtio_video_dec_ops = { - .init_ctrls = virtio_video_dec_init_ctrls, - .init_queues = virtio_video_dec_init_queues, - .get_fmt_list = virtio_video_dec_get_fmt_list, -}; - -int virtio_video_dec_init(struct virtio_video_device *vvd) -{ - ssize_t num; - struct video_device *vd = &vvd->video_dev; - - vd->ioctl_ops = &virtio_video_dec_ioctl_ops; - vvd->ops = &virtio_video_dec_ops; - - num = strscpy(vd->name, "stateful-decoder", sizeof(vd->name)); - if (num < 0) - return num; - - return 0; -} diff --git a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_device.c b/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_device.c deleted file mode 100644 index 2e1f90ae..00000000 --- a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_device.c +++ /dev/null @@ -1,1282 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* Driver for virtio video device. - * - * Copyright 2020 OpenSynergy GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#include -#include -#include -#include - -#include "virtio_video.h" - -enum video_stream_state virtio_video_state(struct virtio_video_stream *stream) -{ - return atomic_read(&stream->state); -} - -void virtio_video_state_reset(struct virtio_video_stream *stream) -{ - atomic_set(&stream->state, STREAM_STATE_IDLE); -} - -void virtio_video_state_update(struct virtio_video_stream *stream, - enum video_stream_state new_state) -{ - enum video_stream_state prev_state; - - do { - prev_state = atomic_read(&stream->state); - if (prev_state == STREAM_STATE_ERROR) - return; - } while (atomic_cmpxchg(&stream->state, prev_state, new_state) != - prev_state); -} - -int virtio_video_pending_buf_list_empty(struct virtio_video_device *vvd) -{ - int ret = 0; - - if (vvd->is_m2m_dev) { - v4l2_err(&vvd->v4l2_dev, "Unexpected call for m2m device!\n"); - return -EPERM; - } - - spin_lock(&vvd->pending_buf_list_lock); - if (list_empty(&vvd->pending_buf_list)) - ret = 1; - spin_unlock(&vvd->pending_buf_list_lock); - - return ret; -} - -int virtio_video_pending_buf_list_pop(struct virtio_video_device *vvd, - struct virtio_video_buffer **virtio_vb) -{ - struct virtio_video_buffer *retbuf; - - if (vvd->is_m2m_dev) { - v4l2_err(&vvd->v4l2_dev, "Unexpected call for m2m device!\n"); - return -EPERM; - } - - spin_lock(&vvd->pending_buf_list_lock); - if (list_empty(&vvd->pending_buf_list)) { - spin_unlock(&vvd->pending_buf_list_lock); - return -EAGAIN; - } - - retbuf = list_first_entry(&vvd->pending_buf_list, - struct virtio_video_buffer, list); - spin_unlock(&vvd->pending_buf_list_lock); - - *virtio_vb = retbuf; - return 0; -} - -int virtio_video_pending_buf_list_add(struct virtio_video_device *vvd, - struct virtio_video_buffer *virtio_vb) -{ - if (vvd->is_m2m_dev) { - v4l2_err(&vvd->v4l2_dev, "Unexpected call for m2m device!\n"); - return -EPERM; - } - - spin_lock(&vvd->pending_buf_list_lock); - list_add_tail(&virtio_vb->list, &vvd->pending_buf_list); - spin_unlock(&vvd->pending_buf_list_lock); - - return 0; -} - -int virtio_video_pending_buf_list_del(struct virtio_video_device *vvd, - struct virtio_video_buffer *virtio_vb) -{ - struct virtio_video_buffer *vb, *vb_tmp; - int ret = -EINVAL; - - if (vvd->is_m2m_dev) { - v4l2_err(&vvd->v4l2_dev, "Unexpected call for m2m device!\n"); - return -EPERM; - } - - spin_lock(&vvd->pending_buf_list_lock); - if (list_empty(&vvd->pending_buf_list)) { - spin_unlock(&vvd->pending_buf_list_lock); - return -EAGAIN; - } - - list_for_each_entry_safe(vb, vb_tmp, &vvd->pending_buf_list, list) { - if (vb->resource_id == virtio_vb->resource_id) { - list_del(&vb->list); - ret = 0; - break; - } - } - spin_unlock(&vvd->pending_buf_list_lock); - - return ret; -} - -int virtio_video_queue_setup(struct vb2_queue *vq, unsigned int *num_buffers, - unsigned int *num_planes, unsigned int sizes[], - struct device *alloc_devs[]) -{ - int i; - struct virtio_video_stream *stream = vb2_get_drv_priv(vq); - struct video_format_info *p_info; - - if (virtio_video_state(stream) == STREAM_STATE_ERROR) - return -EIO; - - if (*num_planes) - return 0; - - if (V4L2_TYPE_IS_OUTPUT(vq->type)) - p_info = &stream->in_info; - else - p_info = &stream->out_info; - - *num_planes = p_info->num_planes; - - for (i = 0; i < p_info->num_planes; i++) - sizes[i] = p_info->plane_format[i].plane_size; - - return 0; -} - -static unsigned int -build_virtio_video_sglist_contig(struct virtio_video_resource_sg_list *sgl, - struct vb2_buffer *vb, unsigned int plane) -{ - sgl->entries[0].addr = cpu_to_le64(vb2_dma_contig_plane_dma_addr(vb, plane)); - sgl->entries[0].length = cpu_to_le32(vb->planes[plane].length); - - sgl->num_entries = 1; - - return VIRTIO_VIDEO_RESOURCE_SG_SIZE(1); -} - -static unsigned int -build_virtio_video_sglist(struct virtio_video_resource_sg_list *sgl, - struct vb2_buffer *vb, unsigned int plane, - bool has_iommu) -{ - int i; - struct scatterlist *sg; - struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, plane); - - for_each_sg(sgt->sgl, sg, sgt->nents, i) { - sgl->entries[i].addr = cpu_to_le64(has_iommu - ? sg_dma_address(sg) - : sg_phys(sg)); - sgl->entries[i].length = cpu_to_le32(sg->length); - } - - sgl->num_entries = sgt->nents; - - return VIRTIO_VIDEO_RESOURCE_SG_SIZE(sgt->nents); -} - -int virtio_video_buf_init(struct vb2_buffer *vb) -{ - int ret = 0; - void *buf; - size_t buf_size = 0; - struct virtio_video_resource_sg_list *sg_list; - unsigned int i, offset = 0, resource_id, nents = 0; - struct vb2_queue *vq = vb->vb2_queue; - enum v4l2_buf_type queue_type = vq->type; - struct virtio_video_stream *stream = vb2_get_drv_priv(vq); - struct virtio_video_buffer *virtio_vb = to_virtio_vb(vb); - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - - if (vvd->supp_non_contig) { - for (i = 0; i < vb->num_planes; i++) { - nents = vb2_dma_sg_plane_desc(vb, i)->nents; - buf_size += VIRTIO_VIDEO_RESOURCE_SG_SIZE(nents); - } - - buf = kcalloc(1, buf_size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - for (i = 0; i < vb->num_planes; i++) { - sg_list = buf + offset; - offset += build_virtio_video_sglist(sg_list, vb, i, - vvd->has_iommu); - } - } else { - buf_size = vb->num_planes * VIRTIO_VIDEO_RESOURCE_SG_SIZE(nents); - - buf = kcalloc(1, buf_size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - for (i = 0; i < vb->num_planes; i++) { - sg_list = buf + offset; - offset += build_virtio_video_sglist_contig(sg_list, - vb, i); - } - } - - virtio_video_resource_id_get(vvd, &resource_id); - - ret = virtio_video_cmd_resource_attach(vvd, stream->stream_id, - resource_id, - to_virtio_queue_type(queue_type), - buf, buf_size); - if (ret) { - virtio_video_resource_id_put(vvd, resource_id); - kfree(buf); - return ret; - } - - virtio_vb->queued = false; - virtio_vb->resource_id = resource_id; - - return 0; -} - -void virtio_video_buf_cleanup(struct vb2_buffer *vb) -{ - struct virtio_video_stream *stream = vb2_get_drv_priv(vb->vb2_queue); - struct virtio_video_buffer *virtio_vb = to_virtio_vb(vb); - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - - virtio_video_resource_id_put(vvd, virtio_vb->resource_id); -} - -void virtio_video_buf_queue(struct vb2_buffer *vb) -{ - int i, ret; - struct virtio_video_buffer *virtio_vb; - uint32_t data_size[VB2_MAX_PLANES] = {0}; - struct virtio_video_stream *stream = vb2_get_drv_priv(vb->vb2_queue); - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - - for (i = 0; i < vb->num_planes; ++i) - data_size[i] = vb->planes[i].bytesused; - - virtio_vb = to_virtio_vb(vb); - - if (!vvd->is_m2m_dev) - virtio_video_pending_buf_list_add(vvd, virtio_vb); - - ret = virtio_video_cmd_resource_queue(vvd, stream->stream_id, - virtio_vb, data_size, - vb->num_planes, - to_virtio_queue_type(vb->type)); - if (ret) { - v4l2_err(&vvd->v4l2_dev, "failed to queue buffer\n"); - return; - } - - virtio_vb->queued = true; -} - -int virtio_video_qbuf(struct file *file, void *priv, - struct v4l2_buffer *buf) -{ - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = video_drvdata(file); - - if (virtio_video_state(stream) == STREAM_STATE_ERROR) - return -EIO; - - if (vvd->is_m2m_dev) - return v4l2_m2m_ioctl_qbuf(file, priv, buf); - - return vb2_ioctl_qbuf(file, priv, buf); -} - -int virtio_video_dqbuf(struct file *file, void *priv, - struct v4l2_buffer *buf) -{ - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = video_drvdata(file); - - if (virtio_video_state(stream) == STREAM_STATE_ERROR) - return -EIO; - - if (vvd->is_m2m_dev) - return v4l2_m2m_ioctl_dqbuf(file, priv, buf); - - return vb2_ioctl_dqbuf(file, priv, buf); -} - -int virtio_video_querycap(struct file *file, void *fh, - struct v4l2_capability *cap) -{ - struct video_device *video_dev = video_devdata(file); - struct virtio_video_device *vvd = video_drvdata(file); - - if (strscpy(cap->driver, DRIVER_NAME, sizeof(cap->driver)) < 0) - v4l2_err(&vvd->v4l2_dev, "failed to copy driver name\n"); - if (strscpy(cap->card, video_dev->name, sizeof(cap->card)) < 0) - v4l2_err(&vvd->v4l2_dev, "failed to copy card name\n"); - - snprintf(cap->bus_info, sizeof(cap->bus_info), "virtio:%s", - video_dev->name); - - cap->device_caps = video_dev->device_caps; - return 0; -} - -int virtio_video_enum_framesizes(struct file *file, void *fh, - struct v4l2_frmsizeenum *f) -{ - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - struct video_format *fmt; - struct video_format_frame *frm; - struct virtio_video_format_frame *frame; - int idx = f->index; - - fmt = virtio_video_find_video_format(&vvd->input_fmt_list, - f->pixel_format); - if (fmt == NULL) - fmt = virtio_video_find_video_format(&vvd->output_fmt_list, - f->pixel_format); - if (fmt == NULL) - return -EINVAL; - - if (idx >= fmt->desc.num_frames) - return -EINVAL; - - frm = &fmt->frames[idx]; - frame = &frm->frame; - - if (frame->width.min == frame->width.max && - frame->height.min == frame->height.max) { - f->type = V4L2_FRMSIZE_TYPE_DISCRETE; - f->discrete.width = frame->width.min; - f->discrete.height = frame->height.min; - return 0; - } - - f->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; - f->stepwise.min_width = frame->width.min; - f->stepwise.max_width = frame->width.max; - f->stepwise.min_height = frame->height.min; - f->stepwise.max_height = frame->height.max; - f->stepwise.step_width = frame->width.step; - f->stepwise.step_height = frame->height.step; - return 0; -} - -static bool in_stepped_interval(struct virtio_video_format_range range, - uint32_t point) -{ - if (point < range.min || point > range.max) - return false; - - if (range.step == 0 && range.min == range.max && range.min == point) - return true; - - if (range.step != 0 && (point - range.min) % range.step == 0) - return true; - - return false; -} - -int virtio_video_enum_framemintervals(struct file *file, void *fh, - struct v4l2_frmivalenum *f) -{ - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - struct video_format *fmt; - struct video_format_frame *frm; - struct virtio_video_format_frame *frame; - struct virtio_video_format_range *frate; - int idx = f->index; - int f_idx; - - fmt = virtio_video_find_video_format(&vvd->input_fmt_list, - f->pixel_format); - if (fmt == NULL) - fmt = virtio_video_find_video_format(&vvd->output_fmt_list, - f->pixel_format); - if (fmt == NULL) - return -EINVAL; - - for (f_idx = 0; f_idx <= fmt->desc.num_frames; f_idx++) { - frm = &fmt->frames[f_idx]; - frame = &frm->frame; - if (in_stepped_interval(frame->width, f->width) && - in_stepped_interval(frame->height, f->height)) - break; - } - - if (frame == NULL || f->index >= frame->num_rates) - return -EINVAL; - - frate = &frm->frame_rates[idx]; - if (frate->max == frate->min) { - f->type = V4L2_FRMIVAL_TYPE_DISCRETE; - f->discrete.numerator = 1; - f->discrete.denominator = frate->max; - } else { - f->stepwise.min.numerator = 1; - f->stepwise.min.denominator = frate->max; - f->stepwise.max.numerator = 1; - f->stepwise.max.denominator = frate->min; - f->stepwise.step.numerator = 1; - f->stepwise.step.denominator = frate->step; - if (frate->step == 1) - f->type = V4L2_FRMIVAL_TYPE_CONTINUOUS; - else - f->type = V4L2_FRMIVAL_TYPE_STEPWISE; - } - return 0; -} - -int virtio_video_stream_get_params(struct virtio_video_device *vvd, - struct virtio_video_stream *stream) -{ - int ret; - - if (vvd->is_m2m_dev) { - ret = virtio_video_cmd_get_params(vvd, stream, - VIRTIO_VIDEO_QUEUE_TYPE_INPUT); - if (ret) { - v4l2_err(&vvd->v4l2_dev, - "failed to get stream in params\n"); - goto err_get_parms; - } - } - - ret = virtio_video_cmd_get_params(vvd, stream, - VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT); - if (ret) - v4l2_err(&vvd->v4l2_dev, "failed to get stream out params\n"); - -err_get_parms: - return ret; -} - -int virtio_video_stream_get_controls(struct virtio_video_device *vvd, - struct virtio_video_stream *stream) -{ - int ret; - - ret = virtio_video_cmd_get_control(vvd, stream, - VIRTIO_VIDEO_CONTROL_PROFILE); - if (ret) { - v4l2_err(&vvd->v4l2_dev, "failed to get stream profile\n"); - goto err_get_ctrl; - } - - ret = virtio_video_cmd_get_control(vvd, stream, - VIRTIO_VIDEO_CONTROL_LEVEL); - if (ret) { - v4l2_err(&vvd->v4l2_dev, "failed to get stream level\n"); - goto err_get_ctrl; - } - - ret = virtio_video_cmd_get_control(vvd, stream, - VIRTIO_VIDEO_CONTROL_BITRATE); - if (ret) - v4l2_err(&vvd->v4l2_dev, "failed to get stream bitrate\n"); - -err_get_ctrl: - return ret; -} - -int virtio_video_g_fmt(struct file *file, void *fh, struct v4l2_format *f) -{ - struct video_format_info *info; - struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; - struct virtio_video_stream *stream = file2stream(file); - - if (!V4L2_TYPE_IS_OUTPUT(f->type)) - info = &stream->out_info; - else - info = &stream->in_info; - - virtio_video_format_from_info(info, pix_mp); - - return 0; -} - -int virtio_video_s_fmt(struct file *file, void *fh, struct v4l2_format *f) -{ - int i, ret; - struct virtio_video_stream *stream = file2stream(file); - struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - struct video_format_info info; - struct video_format_info *p_info; - uint32_t queue; - - ret = virtio_video_try_fmt(stream, f); - if (ret) - return ret; - - if (V4L2_TYPE_IS_OUTPUT(f->type)) { - virtio_video_format_fill_default_info(&info, &stream->in_info); - queue = VIRTIO_VIDEO_QUEUE_TYPE_INPUT; - } else { - virtio_video_format_fill_default_info(&info, &stream->out_info); - queue = VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT; - } - - info.frame_width = pix_mp->width; - info.frame_height = pix_mp->height; - info.num_planes = pix_mp->num_planes; - info.fourcc_format = pix_mp->pixelformat; - - for (i = 0; i < info.num_planes; i++) { - info.plane_format[i].stride = - pix_mp->plane_fmt[i].bytesperline; - info.plane_format[i].plane_size = - pix_mp->plane_fmt[i].sizeimage; - } - - virtio_video_cmd_set_params(vvd, stream, &info, queue); - virtio_video_stream_get_params(vvd, stream); - - if (V4L2_TYPE_IS_OUTPUT(f->type)) - p_info = &stream->in_info; - else - p_info = &stream->out_info; - - virtio_video_format_from_info(p_info, pix_mp); - - return 0; -} - -int virtio_video_g_selection(struct file *file, void *fh, - struct v4l2_selection *sel) -{ - struct video_format_info *info; - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = video_drvdata(file); - - switch (vvd->type) { - case VIRTIO_VIDEO_DEVICE_ENCODER: - if (!V4L2_TYPE_IS_OUTPUT(sel->type)) - return -EINVAL; - info = &stream->in_info; - break; - case VIRTIO_VIDEO_DEVICE_DECODER: - case VIRTIO_VIDEO_DEVICE_CAMERA: - if (V4L2_TYPE_IS_OUTPUT(sel->type)) - return -EINVAL; - info = &stream->out_info; - break; - default: - v4l2_err(&vvd->v4l2_dev, "unsupported device type\n"); - return -EINVAL; - } - - switch (sel->target) { - case V4L2_SEL_TGT_COMPOSE: - case V4L2_SEL_TGT_COMPOSE_BOUNDS: - case V4L2_SEL_TGT_COMPOSE_PADDED: - case V4L2_SEL_TGT_COMPOSE_DEFAULT: - sel->r.width = info->frame_width; - sel->r.height = info->frame_height; - break; - case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: - case V4L2_SEL_TGT_CROP: - sel->r.top = info->crop.top; - sel->r.left = info->crop.left; - sel->r.width = info->frame_width; - sel->r.height = info->frame_height; - break; - default: - v4l2_dbg(1, vvd->debug, &vvd->v4l2_dev, - "unsupported/invalid selection target: %d\n", - sel->target); - return -EINVAL; - } - - return 0; -} - -int virtio_video_try_fmt(struct virtio_video_stream *stream, - struct v4l2_format *f) -{ - int i, idx = 0; - struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - struct video_format *fmt; - bool found = false; - struct video_format_frame *frm; - struct virtio_video_format_frame *frame; - - if (virtio_video_state(stream) == STREAM_STATE_ERROR) - return -EIO; - - if (V4L2_TYPE_IS_OUTPUT(f->type)) - fmt = virtio_video_find_video_format(&vvd->input_fmt_list, - pix_mp->pixelformat); - else - fmt = virtio_video_find_video_format(&vvd->output_fmt_list, - pix_mp->pixelformat); - - if (!fmt) { - if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - virtio_video_format_from_info(&stream->out_info, - pix_mp); - else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) - virtio_video_format_from_info(&stream->in_info, - pix_mp); - else - return -EINVAL; - return 0; - } - - for (i = 0; i < fmt->desc.num_frames && !found; i++) { - frm = &fmt->frames[i]; - frame = &frm->frame; - if (!within_range(frame->width.min, pix_mp->width, - frame->width.max)) - continue; - - if (!within_range(frame->height.min, pix_mp->height, - frame->height.max)) - continue; - idx = i; - /* - * Try to find a more suitable frame size. Go with the current - * one otherwise. - */ - if (needs_alignment(pix_mp->width, frame->width.step)) - continue; - - if (needs_alignment(pix_mp->height, frame->height.step)) - continue; - - stream->current_frame = frm; - found = true; - } - - if (!found) { - frm = &fmt->frames[idx]; - if (!frm) - return -EINVAL; - - frame = &frm->frame; - pix_mp->width = clamp(pix_mp->width, frame->width.min, - frame->width.max); - if (frame->width.step != 0) - pix_mp->width = ALIGN(pix_mp->width, frame->width.step); - - pix_mp->height = clamp(pix_mp->height, frame->height.min, - frame->height.max); - if (frame->height.step != 0) - pix_mp->height = ALIGN(pix_mp->height, - frame->height.step); - stream->current_frame = frm; - } - - return 0; -} - -static int virtio_video_queue_free(struct virtio_video_device *vvd, - struct virtio_video_stream *stream, - enum v4l2_buf_type type) -{ - int ret; - enum virtio_video_queue_type queue_type = to_virtio_queue_type(type); - - ret = virtio_video_cmd_queue_detach_resources(vvd, stream, queue_type); - if (ret) { - v4l2_warn(&vvd->v4l2_dev, - "failed to destroy resources\n"); - return ret; - } - - return 0; -} - -int virtio_video_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *rb) -{ - int ret; - struct virtio_video_stream *stream = file2stream(file); - struct v4l2_m2m_ctx *m2m_ctx = stream->fh.m2m_ctx; - struct virtio_video_device *vvd = video_drvdata(file); - struct video_device *vdev = video_devdata(file); - struct vb2_queue *vq; - - if (vvd->is_m2m_dev) - vq = v4l2_m2m_get_vq(m2m_ctx, rb->type); - else - vq = vdev->queue; - - if (rb->count == 0) { - ret = virtio_video_queue_free(vvd, stream, vq->type); - if (ret < 0) - return ret; - } - - if (vvd->is_m2m_dev) - return v4l2_m2m_reqbufs(file, m2m_ctx, rb); - else - return vb2_ioctl_reqbufs(file, priv, rb); -} - -int virtio_video_subscribe_event(struct v4l2_fh *fh, - const struct v4l2_event_subscription *sub) -{ - switch (sub->type) { - case V4L2_EVENT_SOURCE_CHANGE: - return v4l2_src_change_event_subscribe(fh, sub); - default: - return v4l2_ctrl_subscribe_event(fh, sub); - } -} - -void virtio_video_queue_eos_event(struct virtio_video_stream *stream) -{ - static const struct v4l2_event eos_event = { - .type = V4L2_EVENT_EOS - }; - - v4l2_event_queue_fh(&stream->fh, &eos_event); -} - -void virtio_video_queue_res_chg_event(struct virtio_video_stream *stream) -{ - static const struct v4l2_event ev_src_ch = { - .type = V4L2_EVENT_SOURCE_CHANGE, - .u.src_change.changes = - V4L2_EVENT_SRC_CH_RESOLUTION, - }; - - v4l2_event_queue_fh(&stream->fh, &ev_src_ch); -} - -void virtio_video_handle_error(struct virtio_video_stream *stream) -{ - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - - if (vvd->is_m2m_dev) - virtio_video_queue_release_buffers - (stream, VIRTIO_VIDEO_QUEUE_TYPE_INPUT); - - virtio_video_queue_release_buffers - (stream, VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT); -} - -int virtio_video_queue_release_buffers(struct virtio_video_stream *stream, - enum virtio_video_queue_type queue_type) -{ - int ret; - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - struct vb2_v4l2_buffer *v4l2_vb; - struct virtio_video_buffer *vvb; - - ret = virtio_video_cmd_queue_clear(vvd, stream, queue_type); - if (ret) { - v4l2_err(&vvd->v4l2_dev, "failed to clear queue\n"); - return ret; - } - - if (!vvd->is_m2m_dev) { - while (!virtio_video_pending_buf_list_pop(vvd, &vvb) && vvb) { - v4l2_vb = &vvb->v4l2_m2m_vb.vb; - v4l2_m2m_buf_done(v4l2_vb, VB2_BUF_STATE_ERROR); - } - return 0; - } - - for (;;) { - if (queue_type == VIRTIO_VIDEO_QUEUE_TYPE_INPUT) - v4l2_vb = v4l2_m2m_src_buf_remove(stream->fh.m2m_ctx); - else - v4l2_vb = v4l2_m2m_dst_buf_remove(stream->fh.m2m_ctx); - if (!v4l2_vb) - break; - v4l2_m2m_buf_done(v4l2_vb, VB2_BUF_STATE_ERROR); - } - - return 0; -} - -void virtio_video_buf_done(struct virtio_video_buffer *virtio_vb, - uint32_t flags, uint64_t timestamp, - uint32_t data_sizes[]) -{ - int i; - enum vb2_buffer_state done_state = VB2_BUF_STATE_DONE; - struct vb2_v4l2_buffer *v4l2_vb = &virtio_vb->v4l2_m2m_vb.vb; - struct vb2_buffer *vb = &v4l2_vb->vb2_buf; - struct vb2_queue *vb2_queue = vb->vb2_queue; - struct virtio_video_stream *stream = vb2_get_drv_priv(vb2_queue); - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - struct video_format_info *p_info; - - virtio_vb->queued = false; - - if (flags & VIRTIO_VIDEO_DEQUEUE_FLAG_ERR) - done_state = VB2_BUF_STATE_ERROR; - - if (flags & VIRTIO_VIDEO_DEQUEUE_FLAG_KEY_FRAME) - v4l2_vb->flags |= V4L2_BUF_FLAG_KEYFRAME; - - if (flags & VIRTIO_VIDEO_DEQUEUE_FLAG_BFRAME) - v4l2_vb->flags |= V4L2_BUF_FLAG_BFRAME; - - if (flags & VIRTIO_VIDEO_DEQUEUE_FLAG_PFRAME) - v4l2_vb->flags |= V4L2_BUF_FLAG_PFRAME; - - if (flags & VIRTIO_VIDEO_DEQUEUE_FLAG_EOS) { - v4l2_vb->flags |= V4L2_BUF_FLAG_LAST; - virtio_video_state_update(stream, STREAM_STATE_STOPPED); - virtio_video_queue_eos_event(stream); - } - - if ((flags & VIRTIO_VIDEO_DEQUEUE_FLAG_ERR) || - (flags & VIRTIO_VIDEO_DEQUEUE_FLAG_EOS)) { - vb->planes[0].bytesused = 0; - - if (!vvd->is_m2m_dev) - virtio_video_pending_buf_list_del(vvd, virtio_vb); - - v4l2_m2m_buf_done(v4l2_vb, done_state); - return; - } - - if (!V4L2_TYPE_IS_OUTPUT(vb2_queue->type)) { - switch (vvd->type) { - case VIRTIO_VIDEO_DEVICE_ENCODER: - for (i = 0; i < vb->num_planes; i++) - vb->planes[i].bytesused = - le32_to_cpu(data_sizes[i]); - break; - case VIRTIO_VIDEO_DEVICE_CAMERA: - case VIRTIO_VIDEO_DEVICE_DECODER: - p_info = &stream->out_info; - for (i = 0; i < p_info->num_planes; i++) - vb->planes[i].bytesused = - p_info->plane_format[i].plane_size; - break; - } - - vb->timestamp = timestamp; - } - - if (!vvd->is_m2m_dev) - virtio_video_pending_buf_list_del(vvd, virtio_vb); - - v4l2_m2m_buf_done(v4l2_vb, done_state); -} - -static int virtio_video_set_device_busy(struct virtio_video_device *vvd) -{ - struct video_device *vd = &vvd->video_dev; - int ret = 0; - - /* Multiple open is allowed for m2m device */ - if (vvd->is_m2m_dev) - return 0; - - mutex_lock(vd->lock); - - if (vvd->device_busy) - ret = -EBUSY; - else - vvd->device_busy = true; - - mutex_unlock(vd->lock); - - return ret; -} - -static void virtio_video_clear_device_busy(struct virtio_video_device *vvd, - struct mutex *lock) -{ - /* Nothing to do for m2m device */ - if (vvd->is_m2m_dev) - return; - - if (lock) - mutex_lock(lock); - - vvd->device_busy = false; - - if (lock) - mutex_unlock(lock); -} - -static int virtio_video_device_open(struct file *file) -{ - int ret; - uint32_t stream_id; - char name[TASK_COMM_LEN]; - struct virtio_video_stream *stream; - struct video_format *default_fmt; - enum virtio_video_format format; - struct video_device *video_dev = video_devdata(file); - struct virtio_video_device *vvd = video_drvdata(file); - - ret = virtio_video_set_device_busy(vvd); - if (ret) { - v4l2_err(&vvd->v4l2_dev, "device already in use.\n"); - return ret; - } - - default_fmt = list_first_entry_or_null(vvd->ops->get_fmt_list(vvd), - struct video_format, - formats_list_entry); - if (!default_fmt) { - v4l2_err(&vvd->v4l2_dev, "device failed to start\n"); - ret = -EIO; - goto err; - } - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) { - ret = -ENOMEM; - goto err; - } - - get_task_comm(name, current); - format = virtio_video_v4l2_format_to_virtio(default_fmt->desc.format); - virtio_video_stream_id_get(vvd, stream, &stream_id); - ret = virtio_video_cmd_stream_create(vvd, stream_id, format, name); - if (ret) { - v4l2_err(&vvd->v4l2_dev, "failed to create stream\n"); - goto err_stream_create; - } - - stream->video_dev = video_dev; - stream->stream_id = stream_id; - - virtio_video_state_reset(stream); - - ret = virtio_video_stream_get_params(vvd, stream); - if (ret) - goto err_stream_create; - - if (format >= VIRTIO_VIDEO_FORMAT_CODED_MIN && - format <= VIRTIO_VIDEO_FORMAT_CODED_MAX) { - ret = virtio_video_stream_get_controls(vvd, stream); - if (ret) - goto err_stream_create; - } - - mutex_init(&stream->vq_mutex); - v4l2_fh_init(&stream->fh, video_dev); - stream->fh.ctrl_handler = &stream->ctrl_handler; - - if (vvd->is_m2m_dev) { - stream->fh.m2m_ctx = v4l2_m2m_ctx_init(vvd->m2m_dev, stream, - vvd->ops->init_queues); - if (IS_ERR(stream->fh.m2m_ctx)) { - ret = PTR_ERR(stream->fh.m2m_ctx); - goto err_init_ctx; - } - - v4l2_m2m_set_src_buffered(stream->fh.m2m_ctx, true); - v4l2_m2m_set_dst_buffered(stream->fh.m2m_ctx, true); - } else { - vvd->ops->init_queues(stream, NULL, &vvd->vb2_output_queue); - /* Video dev queue is required for vb2 ioctl wrappers */ - video_dev->queue = &vvd->vb2_output_queue; - } - - file->private_data = &stream->fh; - v4l2_fh_add(&stream->fh); - - if (vvd->ops->init_ctrls) { - ret = vvd->ops->init_ctrls(stream); - if (ret) { - v4l2_err(&vvd->v4l2_dev, "failed to init controls\n"); - goto err_init_ctrls; - } - } - return 0; - -err_init_ctrls: - v4l2_fh_del(&stream->fh); - mutex_lock(video_dev->lock); - if (vvd->is_m2m_dev) - v4l2_m2m_ctx_release(stream->fh.m2m_ctx); - mutex_unlock(video_dev->lock); -err_init_ctx: - v4l2_fh_exit(&stream->fh); -err_stream_create: - virtio_video_stream_id_put(vvd, stream_id); - kfree(stream); -err: - virtio_video_clear_device_busy(vvd, video_dev->lock); - return ret; -} - -static int virtio_video_device_release(struct file *file) -{ - struct virtio_video_stream *stream = file2stream(file); - struct video_device *video_dev = video_devdata(file); - struct virtio_video_device *vvd = video_drvdata(file); - - mutex_lock(video_dev->lock); - - v4l2_fh_del(&stream->fh); - if (vvd->is_m2m_dev) { - v4l2_m2m_ctx_release(stream->fh.m2m_ctx); - } else if (file->private_data == video_dev->queue->owner) { - vb2_queue_release(&vvd->vb2_output_queue); - video_dev->queue->owner = NULL; - } - - v4l2_fh_exit(&stream->fh); - - virtio_video_cmd_stream_destroy(vvd, stream->stream_id); - virtio_video_stream_id_put(vvd, stream->stream_id); - - kfree(stream); - - /* Mutex already locked here, passing NULL */ - virtio_video_clear_device_busy(vvd, NULL); - - mutex_unlock(video_dev->lock); - - return 0; -} - -static const struct v4l2_file_operations virtio_video_device_m2m_fops = { - .owner = THIS_MODULE, - .open = virtio_video_device_open, - .release = virtio_video_device_release, - .poll = v4l2_m2m_fop_poll, - .unlocked_ioctl = video_ioctl2, - .mmap = v4l2_m2m_fop_mmap, -}; - -static const struct v4l2_file_operations virtio_video_device_fops = { - .owner = THIS_MODULE, - .open = virtio_video_device_open, - .release = virtio_video_device_release, - .poll = vb2_fop_poll, - .unlocked_ioctl = video_ioctl2, - .mmap = vb2_fop_mmap, -}; - -static void virtio_video_device_run(void *priv) -{ - -} - -static void virtio_video_device_job_abort(void *priv) -{ - struct virtio_video_stream *stream = priv; - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - - v4l2_m2m_job_finish(vvd->m2m_dev, stream->fh.m2m_ctx); -} - -static const struct v4l2_m2m_ops virtio_video_device_m2m_ops = { - .device_run = virtio_video_device_run, - .job_abort = virtio_video_device_job_abort, -}; - -static int virtio_video_device_register(struct virtio_video_device *vvd) -{ - int ret; - struct video_device *vd; - - vd = &vvd->video_dev; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,7,0) - ret = video_register_device(vd, VFL_TYPE_VIDEO, vvd->vid_dev_nr); -#else - ret = video_register_device(vd, VFL_TYPE_GRABBER, vvd->vid_dev_nr); -#endif - if (ret) { - v4l2_err(&vvd->v4l2_dev, "failed to register video device\n"); - return ret; - } - - v4l2_info(&vvd->v4l2_dev, "Device '%s' registered as /dev/video%d\n", - vd->name, vd->num); - - return 0; -} - -static void virtio_video_device_unregister(struct virtio_video_device *vvd) -{ - video_unregister_device(&vvd->video_dev); -} - -static int -virtio_video_query_capability(struct virtio_video_device *vvd, - void *resp_buf, - enum virtio_video_queue_type queue_type) -{ - int ret; - int resp_size = vvd->max_caps_len; - - ret = virtio_video_cmd_query_capability(vvd, resp_buf, resp_size, - queue_type); - if (ret) - v4l2_err(&vvd->v4l2_dev, "failed to query capability\n"); - - return ret; -} - -int virtio_video_device_init(struct virtio_video_device *vvd) -{ - int ret; - int vfl_dir; - u32 dev_caps; - struct video_device *vd; - struct v4l2_m2m_dev *m2m_dev; - const struct v4l2_file_operations *fops; - void *input_resp_buf, *output_resp_buf; - - output_resp_buf = kzalloc(vvd->max_caps_len, GFP_KERNEL); - if (!output_resp_buf) - return -ENOMEM; - - ret = virtio_video_query_capability(vvd, output_resp_buf, - VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT); - if (ret) { - v4l2_err(&vvd->v4l2_dev, "failed to get output caps\n"); - goto err_output_cap; - } - - if (vvd->is_m2m_dev) { - input_resp_buf = kzalloc(vvd->max_caps_len, GFP_KERNEL); - if (!input_resp_buf) { - ret = -ENOMEM; - goto err_input_buf; - } - - ret = virtio_video_query_capability(vvd, input_resp_buf, - VIRTIO_VIDEO_QUEUE_TYPE_INPUT); - if (ret) { - v4l2_err(&vvd->v4l2_dev, "failed to get input caps\n"); - goto err_input_cap; - } - - m2m_dev = v4l2_m2m_init(&virtio_video_device_m2m_ops); - if (IS_ERR(m2m_dev)) { - v4l2_err(&vvd->v4l2_dev, "failed to init m2m device\n"); - ret = PTR_ERR(m2m_dev); - goto err_m2m_dev; - } - vfl_dir = VFL_DIR_M2M; - fops = &virtio_video_device_m2m_fops; - dev_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE; - } else { - input_resp_buf = NULL; - m2m_dev = NULL; - vfl_dir = VFL_DIR_RX; - fops = &virtio_video_device_fops; - dev_caps = V4L2_CAP_STREAMING; - if (vvd->is_mplane_cam) - dev_caps |= V4L2_CAP_VIDEO_CAPTURE_MPLANE; - else - dev_caps |= V4L2_CAP_VIDEO_CAPTURE; - } - - vvd->m2m_dev = m2m_dev; - mutex_init(&vvd->video_dev_mutex); - vd = &vvd->video_dev; - vd->lock = &vvd->video_dev_mutex; - vd->v4l2_dev = &vvd->v4l2_dev; - vd->vfl_dir = vfl_dir; - vd->ioctl_ops = NULL; - vd->fops = fops; - vd->device_caps = dev_caps; - vd->release = video_device_release_empty; - - /* Use the selection API instead */ - v4l2_disable_ioctl(vd, VIDIOC_CROPCAP); - v4l2_disable_ioctl(vd, VIDIOC_G_CROP); - - video_set_drvdata(vd, vvd); - - INIT_LIST_HEAD(&vvd->input_fmt_list); - INIT_LIST_HEAD(&vvd->output_fmt_list); - INIT_LIST_HEAD(&vvd->controls_fmt_list); - INIT_LIST_HEAD(&vvd->pending_buf_list); - - vvd->num_output_fmts = 0; - vvd->num_input_fmts = 0; - - switch (vvd->type) { - case VIRTIO_VIDEO_DEVICE_CAMERA: - virtio_video_cam_init(vvd); - break; - case VIRTIO_VIDEO_DEVICE_ENCODER: - virtio_video_enc_init(vvd); - break; - case VIRTIO_VIDEO_DEVICE_DECODER: - default: - virtio_video_dec_init(vvd); - break; - } - - ret = virtio_video_parse_virtio_capabilities(vvd, input_resp_buf, - output_resp_buf); - if (ret) { - v4l2_err(&vvd->v4l2_dev, "failed to parse a function\n"); - goto parse_cap_err; - } - - ret = virtio_video_parse_virtio_control(vvd); - if (ret) { - v4l2_err(&vvd->v4l2_dev, "failed to query controls\n"); - goto parse_ctrl_err; - } - - ret = virtio_video_device_register(vvd); - if (ret) { - v4l2_err(&vvd->v4l2_dev, - "failed to init virtio video device\n"); - goto register_err; - } - - goto out_cleanup; - -register_err: - virtio_video_clean_control(vvd); -parse_ctrl_err: - virtio_video_clean_capability(vvd); -parse_cap_err: - if (vvd->is_m2m_dev) - v4l2_m2m_release(vvd->m2m_dev); -err_m2m_dev: -err_input_cap: -out_cleanup: - if (vvd->is_m2m_dev) - kfree(input_resp_buf); -err_input_buf: -err_output_cap: - kfree(output_resp_buf); - - return ret; -} - -void virtio_video_device_deinit(struct virtio_video_device *vvd) -{ - vvd->commandq.ready = false; - vvd->eventq.ready = false; - - virtio_video_device_unregister(vvd); - if (vvd->is_m2m_dev) - v4l2_m2m_release(vvd->m2m_dev); - virtio_video_clean_control(vvd); - virtio_video_clean_capability(vvd); -} diff --git a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_driver.c b/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_driver.c deleted file mode 100644 index 734c5b73..00000000 --- a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_driver.c +++ /dev/null @@ -1,246 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* Driver for virtio video device. - * - * Copyright 2020 OpenSynergy GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ -#include -#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0) -#include -#else -#include -#endif - -#include "virtio_video.h" - -static unsigned int debug; -module_param(debug, uint, 0644); - -static unsigned int use_dma_mem; -module_param(use_dma_mem, uint, 0644); -MODULE_PARM_DESC(use_dma_mem, "Try to allocate buffers from the DMA zone"); - -static int vid_nr_dec = -1; -module_param(vid_nr_dec, int, 0644); -MODULE_PARM_DESC(vid_nr_dec, "videoN start number, -1 is autodetect"); - -static int vid_nr_enc = -1; -module_param(vid_nr_enc, int, 0644); -MODULE_PARM_DESC(vid_nr_enc, "videoN start number, -1 is autodetect"); - -static int vid_nr_cam = -1; -module_param(vid_nr_cam, int, 0644); -MODULE_PARM_DESC(vid_nr_cam, "videoN start number, -1 is autodetect"); - -static bool mplane_cam = true; -module_param(mplane_cam, bool, 0644); -MODULE_PARM_DESC(mplane_cam, - "1 (default) - multiplanar camera, 0 - single planar camera"); - -static int virtio_video_probe(struct virtio_device *vdev) -{ - int ret; - struct virtio_video_device *vvd; - struct virtqueue *vqs[2]; - struct device *dev = &vdev->dev; - struct device *pdev = dev->parent; - - static const char * const names[] = { "commandq", "eventq" }; - static vq_callback_t *callbacks[] = { - virtio_video_cmd_cb, - virtio_video_event_cb - }; - - if (!virtio_has_feature(vdev, VIRTIO_VIDEO_F_RESOURCE_GUEST_PAGES)) { - dev_err(dev, "device must support guest allocated buffers\n"); - return -ENODEV; - } - - vvd = devm_kzalloc(dev, sizeof(*vvd), GFP_KERNEL); - if (!vvd) - return -ENOMEM; - - vvd->is_m2m_dev = true; - - switch (vdev->id.device) { - case VIRTIO_ID_VIDEO_CAM: - vvd->is_m2m_dev = false; - vvd->vid_dev_nr = vid_nr_cam; - vvd->is_mplane_cam = mplane_cam; - vvd->type = VIRTIO_VIDEO_DEVICE_CAMERA; - break; - case VIRTIO_ID_VIDEO_ENC: - vvd->vid_dev_nr = vid_nr_enc; - vvd->type = VIRTIO_VIDEO_DEVICE_ENCODER; - break; - case VIRTIO_ID_VIDEO_DEC: - default: - vvd->vid_dev_nr = vid_nr_dec; - vvd->type = VIRTIO_VIDEO_DEVICE_DECODER; - break; - } - - vvd->vdev = vdev; - vvd->debug = debug; - vvd->use_dma_mem = use_dma_mem; - vdev->priv = vvd; - - spin_lock_init(&vvd->pending_buf_list_lock); - spin_lock_init(&vvd->resource_idr_lock); - idr_init(&vvd->resource_idr); - spin_lock_init(&vvd->stream_idr_lock); - idr_init(&vvd->stream_idr); - - init_waitqueue_head(&vvd->wq); - - if (virtio_has_feature(vdev, VIRTIO_VIDEO_F_RESOURCE_NON_CONTIG)) - vvd->supp_non_contig = true; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,9,0) - vvd->has_iommu = !virtio_has_dma_quirk(vdev); -#else - vvd->has_iommu = !virtio_has_iommu_quirk(vdev); -#endif - - if (!dev->dma_ops) - set_dma_ops(dev, pdev->dma_ops); - - /* - * Set it to coherent_dma_mask by default if the architecture - * code has not set it. - */ - if (!dev->dma_mask) - dev->dma_mask = &dev->coherent_dma_mask; - - dma_set_mask(dev, *pdev->dma_mask); - - dev_set_name(dev, "%s.%i", DRIVER_NAME, vdev->index); - ret = v4l2_device_register(dev, &vvd->v4l2_dev); - if (ret) - goto err_v4l2_reg; - - spin_lock_init(&vvd->commandq.qlock); - init_waitqueue_head(&vvd->commandq.reclaim_queue); - - INIT_WORK(&vvd->eventq.work, virtio_video_process_events); - - INIT_LIST_HEAD(&vvd->pending_vbuf_list); - - ret = virtio_find_vqs(vdev, 2, vqs, callbacks, names, NULL); - if (ret) { - v4l2_err(&vvd->v4l2_dev, "failed to find virt queues\n"); - goto err_vqs; - } - - vvd->commandq.vq = vqs[0]; - vvd->eventq.vq = vqs[1]; - - ret = virtio_video_alloc_vbufs(vvd); - if (ret) { - v4l2_err(&vvd->v4l2_dev, "failed to alloc vbufs\n"); - goto err_vbufs; - } - - virtio_cread(vdev, struct virtio_video_config, max_caps_length, - &vvd->max_caps_len); - if (!vvd->max_caps_len) { - v4l2_err(&vvd->v4l2_dev, "max_caps_len is zero\n"); - ret = -EINVAL; - goto err_config; - } - - virtio_cread(vdev, struct virtio_video_config, max_resp_length, - &vvd->max_resp_len); - if (!vvd->max_resp_len) { - v4l2_err(&vvd->v4l2_dev, "max_resp_len is zero\n"); - ret = -EINVAL; - goto err_config; - } - - ret = virtio_video_alloc_events(vvd); - if (ret) - goto err_events; - - virtio_device_ready(vdev); - vvd->commandq.ready = true; - vvd->eventq.ready = true; - - ret = virtio_video_device_init(vvd); - if (ret) { - v4l2_err(&vvd->v4l2_dev, - "failed to init virtio video\n"); - goto err_init; - } - - return 0; - -err_init: -err_events: -err_config: - virtio_video_free_vbufs(vvd); -err_vbufs: - vdev->config->del_vqs(vdev); -err_vqs: - v4l2_device_unregister(&vvd->v4l2_dev); -err_v4l2_reg: - devm_kfree(&vdev->dev, vvd); - - return ret; -} - -static void virtio_video_remove(struct virtio_device *vdev) -{ - struct virtio_video_device *vvd = vdev->priv; - - virtio_video_device_deinit(vvd); - virtio_video_free_vbufs(vvd); - vdev->config->del_vqs(vdev); - v4l2_device_unregister(&vvd->v4l2_dev); - devm_kfree(&vdev->dev, vvd); -} - -static struct virtio_device_id id_table[] = { - { VIRTIO_ID_VIDEO_DEC, VIRTIO_DEV_ANY_ID }, - { VIRTIO_ID_VIDEO_ENC, VIRTIO_DEV_ANY_ID }, - { VIRTIO_ID_VIDEO_CAM, VIRTIO_DEV_ANY_ID }, - { 0 }, -}; - -static unsigned int features[] = { - VIRTIO_VIDEO_F_RESOURCE_GUEST_PAGES, - VIRTIO_VIDEO_F_RESOURCE_NON_CONTIG, -}; - -static struct virtio_driver virtio_video_driver = { - .feature_table = features, - .feature_table_size = ARRAY_SIZE(features), - .driver.name = DRIVER_NAME, - .driver.owner = THIS_MODULE, - .id_table = id_table, - .probe = virtio_video_probe, - .remove = virtio_video_remove, -}; - -module_virtio_driver(virtio_video_driver); - -MODULE_DEVICE_TABLE(virtio, id_table); -MODULE_DESCRIPTION("virtio video driver"); -MODULE_AUTHOR("Dmitry Sepp "); -MODULE_AUTHOR("Kiran Pawar "); -MODULE_AUTHOR("Nikolay Martyanov "); -MODULE_AUTHOR("Samiullah Khawaja "); -MODULE_VERSION(DRIVER_VERSION); -MODULE_LICENSE("GPL"); diff --git a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_enc.c b/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_enc.c deleted file mode 100644 index 66730bdb..00000000 --- a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_enc.c +++ /dev/null @@ -1,601 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* Encoder for virtio video device. - * - * Copyright 2020 OpenSynergy GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#include -#include -#include - -#include "virtio_video.h" - -static int virtio_video_enc_start_streaming(struct vb2_queue *vq, - unsigned int count) -{ - struct virtio_video_stream *stream = vb2_get_drv_priv(vq); - bool input_queue = V4L2_TYPE_IS_OUTPUT(vq->type); - - if (virtio_video_state(stream) == STREAM_STATE_ERROR) - return -EIO; - - if (virtio_video_state(stream) == STREAM_STATE_INIT || - (!input_queue && - virtio_video_state(stream) == STREAM_STATE_RESET) || - (input_queue && - virtio_video_state(stream) == STREAM_STATE_STOPPED)) - virtio_video_state_update(stream, STREAM_STATE_RUNNING); - - return 0; -} - -static void virtio_video_enc_stop_streaming(struct vb2_queue *vq) -{ - int ret, queue_type; - struct virtio_video_stream *stream = vb2_get_drv_priv(vq); - - if (V4L2_TYPE_IS_OUTPUT(vq->type)) - queue_type = VIRTIO_VIDEO_QUEUE_TYPE_INPUT; - else - queue_type = VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT; - - ret = virtio_video_queue_release_buffers(stream, queue_type); - if (ret) - return; - - vb2_wait_for_all_buffers(vq); - - if (V4L2_TYPE_IS_OUTPUT(vq->type)) - virtio_video_state_update(stream, STREAM_STATE_STOPPED); - else - virtio_video_state_update(stream, STREAM_STATE_RESET); -} - -static const struct vb2_ops virtio_video_enc_qops = { - .queue_setup = virtio_video_queue_setup, - .buf_init = virtio_video_buf_init, - .buf_cleanup = virtio_video_buf_cleanup, - .buf_queue = virtio_video_buf_queue, - .start_streaming = virtio_video_enc_start_streaming, - .stop_streaming = virtio_video_enc_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, -}; - -static int virtio_video_enc_s_ctrl(struct v4l2_ctrl *ctrl) -{ - int ret = 0; - struct virtio_video_stream *stream = ctrl2stream(ctrl); - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - uint32_t control, value; - - if (virtio_video_state(stream) == STREAM_STATE_ERROR) - return -EIO; - - control = virtio_video_v4l2_control_to_virtio(ctrl->id); - - switch (ctrl->id) { - case V4L2_CID_MPEG_VIDEO_BITRATE: - ret = virtio_video_cmd_set_control(vvd, stream->stream_id, - control, ctrl->val); - break; - case V4L2_CID_MPEG_VIDEO_H264_LEVEL: - value = virtio_video_v4l2_level_to_virtio(ctrl->val); - ret = virtio_video_cmd_set_control(vvd, stream->stream_id, - control, value); - break; - case V4L2_CID_MPEG_VIDEO_H264_PROFILE: - value = virtio_video_v4l2_profile_to_virtio(ctrl->val); - ret = virtio_video_cmd_set_control(vvd, stream->stream_id, - control, value); - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static int virtio_video_enc_g_ctrl(struct v4l2_ctrl *ctrl) -{ - int ret = 0; - struct virtio_video_stream *stream = ctrl2stream(ctrl); - - if (virtio_video_state(stream) == STREAM_STATE_ERROR) - return -EIO; - - switch (ctrl->id) { - case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: - if (virtio_video_state(stream) >= STREAM_STATE_INIT) - ctrl->val = stream->in_info.min_buffers; - else - ctrl->val = 0; - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static const struct v4l2_ctrl_ops virtio_video_enc_ctrl_ops = { - .g_volatile_ctrl = virtio_video_enc_g_ctrl, - .s_ctrl = virtio_video_enc_s_ctrl, -}; - -int virtio_video_enc_init_ctrls(struct virtio_video_stream *stream) -{ - struct v4l2_ctrl *ctrl; - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - struct video_control_format *c_fmt = NULL; - - v4l2_ctrl_handler_init(&stream->ctrl_handler, 1); - - ctrl = v4l2_ctrl_new_std(&stream->ctrl_handler, - &virtio_video_enc_ctrl_ops, - V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, - MIN_BUFS_MIN, MIN_BUFS_MAX, MIN_BUFS_STEP, - MIN_BUFS_DEF); - - if (ctrl) - ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; - - list_for_each_entry(c_fmt, &vvd->controls_fmt_list, - controls_list_entry) { - switch (c_fmt->format) { - case V4L2_PIX_FMT_H264: - if (c_fmt->profile) - v4l2_ctrl_new_std_menu - (&stream->ctrl_handler, - &virtio_video_enc_ctrl_ops, - V4L2_CID_MPEG_VIDEO_H264_PROFILE, - c_fmt->profile->max, - c_fmt->profile->skip_mask, - c_fmt->profile->min); - - if (c_fmt->level) - v4l2_ctrl_new_std_menu - (&stream->ctrl_handler, - &virtio_video_enc_ctrl_ops, - V4L2_CID_MPEG_VIDEO_H264_LEVEL, - c_fmt->level->max, - c_fmt->level->skip_mask, - c_fmt->level->min); - break; - default: - v4l2_dbg(1, vvd->debug, - &vvd->v4l2_dev, "unsupported format\n"); - break; - } - } - - if (stream->control.bitrate) { - v4l2_ctrl_new_std(&stream->ctrl_handler, - &virtio_video_enc_ctrl_ops, - V4L2_CID_MPEG_VIDEO_BITRATE, - 1, S32_MAX, - 1, stream->control.bitrate); - } - - if (stream->ctrl_handler.error) - return stream->ctrl_handler.error; - - v4l2_ctrl_handler_setup(&stream->ctrl_handler); - - return 0; -} - -int virtio_video_enc_init_queues(void *priv, struct vb2_queue *src_vq, - struct vb2_queue *dst_vq) -{ - int ret; - struct virtio_video_stream *stream = priv; - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - struct device *dev = vvd->v4l2_dev.dev; - - src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - src_vq->io_modes = VB2_MMAP | VB2_DMABUF; - src_vq->drv_priv = stream; - src_vq->buf_struct_size = sizeof(struct virtio_video_buffer); - src_vq->ops = &virtio_video_enc_qops; - src_vq->mem_ops = virtio_video_mem_ops(vvd); - src_vq->min_buffers_needed = stream->in_info.min_buffers; - src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; - src_vq->lock = &stream->vq_mutex; - src_vq->gfp_flags = virtio_video_gfp_flags(vvd); - src_vq->dev = dev; - - ret = vb2_queue_init(src_vq); - if (ret) - return ret; - - dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; - dst_vq->drv_priv = stream; - dst_vq->buf_struct_size = sizeof(struct virtio_video_buffer); - dst_vq->ops = &virtio_video_enc_qops; - dst_vq->mem_ops = virtio_video_mem_ops(vvd); - dst_vq->min_buffers_needed = stream->out_info.min_buffers; - dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; - dst_vq->lock = &stream->vq_mutex; - dst_vq->gfp_flags = virtio_video_gfp_flags(vvd); - dst_vq->dev = dev; - - return vb2_queue_init(dst_vq); -} - -static int virtio_video_try_encoder_cmd(struct file *file, void *fh, - struct v4l2_encoder_cmd *cmd) -{ - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = video_drvdata(file); - - if (virtio_video_state(stream) == STREAM_STATE_ERROR) - return -EIO; - - if (virtio_video_state(stream) == STREAM_STATE_DRAIN) - return -EBUSY; - - switch (cmd->cmd) { - case V4L2_ENC_CMD_STOP: - case V4L2_ENC_CMD_START: - if (cmd->flags != 0) { - v4l2_err(&vvd->v4l2_dev, "flags=%u are not supported", - cmd->flags); - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - return 0; -} - -static int virtio_video_encoder_cmd(struct file *file, void *fh, - struct v4l2_encoder_cmd *cmd) -{ - int ret; - struct vb2_queue *src_vq, *dst_vq; - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = video_drvdata(file); - - ret = virtio_video_try_encoder_cmd(file, fh, cmd); - if (ret < 0) - return ret; - - dst_vq = v4l2_m2m_get_vq(stream->fh.m2m_ctx, - V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); - - switch (cmd->cmd) { - case V4L2_ENC_CMD_START: - vb2_clear_last_buffer_dequeued(dst_vq); - virtio_video_state_update(stream, STREAM_STATE_RUNNING); - break; - case V4L2_ENC_CMD_STOP: - src_vq = v4l2_m2m_get_vq(stream->fh.m2m_ctx, - V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - - if (!vb2_is_streaming(src_vq)) { - v4l2_dbg(1, vvd->debug, - &vvd->v4l2_dev, "output is not streaming\n"); - return 0; - } - - if (!vb2_is_streaming(dst_vq)) { - v4l2_dbg(1, vvd->debug, - &vvd->v4l2_dev, "capture is not streaming\n"); - return 0; - } - - ret = virtio_video_cmd_stream_drain(vvd, stream->stream_id); - if (ret) { - v4l2_err(&vvd->v4l2_dev, "failed to drain stream\n"); - return ret; - } - - virtio_video_state_update(stream, STREAM_STATE_DRAIN); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int virtio_video_enc_enum_fmt_vid_cap(struct file *file, void *fh, - struct v4l2_fmtdesc *f) -{ - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - struct video_format *fmt; - int idx = 0; - - if (virtio_video_state(stream) == STREAM_STATE_ERROR) - return -EIO; - - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - return -EINVAL; - - if (f->index >= vvd->num_output_fmts) - return -EINVAL; - - list_for_each_entry(fmt, &vvd->output_fmt_list, formats_list_entry) { - if (f->index == idx) { - f->pixelformat = fmt->desc.format; - return 0; - } - idx++; - } - return -EINVAL; -} - -static int virtio_video_enc_enum_fmt_vid_out(struct file *file, void *fh, - struct v4l2_fmtdesc *f) -{ - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - struct video_format_info *info = NULL; - struct video_format *fmt = NULL; - unsigned long output_mask = 0; - int idx = 0, bit_num = 0; - - if (virtio_video_state(stream) == STREAM_STATE_ERROR) - return -EIO; - - if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) - return -EINVAL; - - if (f->index >= vvd->num_input_fmts) - return -EINVAL; - - info = &stream->out_info; - list_for_each_entry(fmt, &vvd->output_fmt_list, formats_list_entry) { - if (info->fourcc_format == fmt->desc.format) { - output_mask = fmt->desc.mask; - break; - } - } - - if (output_mask == 0) - return -EINVAL; - - list_for_each_entry(fmt, &vvd->input_fmt_list, formats_list_entry) { - if (test_bit(bit_num, &output_mask)) { - if (f->index == idx) { - f->pixelformat = fmt->desc.format; - return 0; - } - idx++; - } - bit_num++; - } - return -EINVAL; -} - -static int virtio_video_enc_s_fmt(struct file *file, void *fh, - struct v4l2_format *f) -{ - int ret; - struct virtio_video_stream *stream = file2stream(file); - - ret = virtio_video_s_fmt(file, fh, f); - if (ret) - return ret; - - if (!V4L2_TYPE_IS_OUTPUT(f->type)) { - if (virtio_video_state(stream) == STREAM_STATE_IDLE) - virtio_video_state_update(stream, STREAM_STATE_INIT); - } - - return 0; -} - -static int virtio_video_enc_try_framerate(struct virtio_video_stream *stream, - unsigned int fps) -{ - int rate_idx; - struct video_format_frame *frame = NULL; - - if (stream->current_frame == NULL) - return -EINVAL; - - frame = stream->current_frame; - for (rate_idx = 0; rate_idx < frame->frame.num_rates; rate_idx++) { - struct virtio_video_format_range *frame_rate = - &frame->frame_rates[rate_idx]; - - if (within_range(frame_rate->min, fps, frame_rate->max)) - return 0; - } - - return -EINVAL; -} - -static void virtio_video_timeperframe_from_info(struct video_format_info *info, - struct v4l2_fract *timeperframe) -{ - timeperframe->numerator = 1; - timeperframe->denominator = info->frame_rate; -} - -static int virtio_video_enc_g_parm(struct file *file, void *priv, - struct v4l2_streamparm *a) -{ - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - struct v4l2_outputparm *out = &a->parm.output; - struct v4l2_fract *timeperframe = &out->timeperframe; - - if (virtio_video_state(stream) == STREAM_STATE_ERROR) - return -EIO; - - if (!V4L2_TYPE_IS_OUTPUT(a->type)) { - v4l2_err(&vvd->v4l2_dev, - "getting FPS is only possible for the output queue\n"); - return -EINVAL; - } - - out->capability = V4L2_CAP_TIMEPERFRAME; - virtio_video_timeperframe_from_info(&stream->in_info, timeperframe); - - return 0; -} - -static int virtio_video_enc_s_parm(struct file *file, void *priv, - struct v4l2_streamparm *a) -{ - int ret; - u64 frame_interval, frame_rate; - struct video_format_info info; - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - struct v4l2_outputparm *out = &a->parm.output; - struct v4l2_fract *timeperframe = &out->timeperframe; - - if (virtio_video_state(stream) == STREAM_STATE_ERROR) - return -EIO; - - if (V4L2_TYPE_IS_OUTPUT(a->type)) { - frame_interval = timeperframe->numerator * (u64)USEC_PER_SEC; - do_div(frame_interval, timeperframe->denominator); - if (!frame_interval) - return -EINVAL; - - frame_rate = (u64)USEC_PER_SEC; - do_div(frame_rate, frame_interval); - } else { - v4l2_err(&vvd->v4l2_dev, - "setting FPS is only possible for the output queue\n"); - return -EINVAL; - } - - ret = virtio_video_enc_try_framerate(stream, frame_rate); - if (ret) - return ret; - - virtio_video_format_fill_default_info(&info, &stream->in_info); - info.frame_rate = frame_rate; - - virtio_video_cmd_set_params(vvd, stream, &info, - VIRTIO_VIDEO_QUEUE_TYPE_INPUT); - virtio_video_stream_get_params(vvd, stream); - - out->capability = V4L2_CAP_TIMEPERFRAME; - virtio_video_timeperframe_from_info(&stream->in_info, timeperframe); - - return 0; -} - -static int virtio_video_enc_s_selection(struct file *file, void *fh, - struct v4l2_selection *sel) -{ - struct virtio_video_stream *stream = file2stream(file); - struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev); - int ret; - - if (!V4L2_TYPE_IS_OUTPUT(sel->type)) - return -EINVAL; - - switch (sel->target) { - case V4L2_SEL_TGT_CROP: - stream->in_info.crop.top = sel->r.top; - stream->in_info.crop.left = sel->r.left; - stream->in_info.crop.width = sel->r.width; - stream->in_info.crop.height = sel->r.height; - break; - default: - return -EINVAL; - } - - ret = virtio_video_cmd_set_params(vvd, stream, &stream->in_info, - VIRTIO_VIDEO_QUEUE_TYPE_INPUT); - if (ret) - return -EINVAL; - - return virtio_video_cmd_get_params(vvd, stream, - VIRTIO_VIDEO_QUEUE_TYPE_INPUT); -} - -static const struct v4l2_ioctl_ops virtio_video_enc_ioctl_ops = { - .vidioc_querycap = virtio_video_querycap, - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) - .vidioc_enum_fmt_vid_cap = virtio_video_enc_enum_fmt_vid_cap, - .vidioc_enum_fmt_vid_out = virtio_video_enc_enum_fmt_vid_out, -#else - .vidioc_enum_fmt_vid_cap_mplane = virtio_video_enc_enum_fmt_vid_cap, - .vidioc_enum_fmt_vid_out_mplane = virtio_video_enc_enum_fmt_vid_out, -#endif - .vidioc_g_fmt_vid_cap_mplane = virtio_video_g_fmt, - .vidioc_s_fmt_vid_cap_mplane = virtio_video_enc_s_fmt, - - .vidioc_g_fmt_vid_out_mplane = virtio_video_g_fmt, - .vidioc_s_fmt_vid_out_mplane = virtio_video_enc_s_fmt, - - .vidioc_try_encoder_cmd = virtio_video_try_encoder_cmd, - .vidioc_encoder_cmd = virtio_video_encoder_cmd, - .vidioc_enum_frameintervals = virtio_video_enum_framemintervals, - .vidioc_enum_framesizes = virtio_video_enum_framesizes, - - .vidioc_g_selection = virtio_video_g_selection, - .vidioc_s_selection = virtio_video_enc_s_selection, - - .vidioc_reqbufs = virtio_video_reqbufs, - .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, - .vidioc_qbuf = virtio_video_qbuf, - .vidioc_dqbuf = virtio_video_dqbuf, - .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, - .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, - .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, - - .vidioc_streamon = v4l2_m2m_ioctl_streamon, - .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, - - .vidioc_s_parm = virtio_video_enc_s_parm, - .vidioc_g_parm = virtio_video_enc_g_parm, - - .vidioc_subscribe_event = virtio_video_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -void *virtio_video_enc_get_fmt_list(struct virtio_video_device *vvd) -{ - return &vvd->output_fmt_list; -} - -static struct virtio_video_device_ops virtio_video_enc_ops = { - .init_ctrls = virtio_video_enc_init_ctrls, - .init_queues = virtio_video_enc_init_queues, - .get_fmt_list = virtio_video_enc_get_fmt_list, -}; - -int virtio_video_enc_init(struct virtio_video_device *vvd) -{ - ssize_t num; - struct video_device *vd = &vvd->video_dev; - - vd->ioctl_ops = &virtio_video_enc_ioctl_ops; - vvd->ops = &virtio_video_enc_ops; - - num = strscpy(vd->name, "stateful-encoder", sizeof(vd->name)); - if (num < 0) - return num; - - return 0; -} diff --git a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_helpers.c b/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_helpers.c deleted file mode 100644 index ac487053..00000000 --- a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_helpers.c +++ /dev/null @@ -1,289 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* Driver for virtio video device. - * - * Copyright 2020 OpenSynergy GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#include "virtio_video.h" - -struct virtio_video_convert_table { - uint32_t virtio_value; - uint32_t v4l2_value; -}; - -static struct virtio_video_convert_table level_table[] = { - { VIRTIO_VIDEO_LEVEL_H264_1_0, V4L2_MPEG_VIDEO_H264_LEVEL_1_0 }, - { VIRTIO_VIDEO_LEVEL_H264_1_1, V4L2_MPEG_VIDEO_H264_LEVEL_1_1 }, - { VIRTIO_VIDEO_LEVEL_H264_1_2, V4L2_MPEG_VIDEO_H264_LEVEL_1_2 }, - { VIRTIO_VIDEO_LEVEL_H264_1_3, V4L2_MPEG_VIDEO_H264_LEVEL_1_3 }, - { VIRTIO_VIDEO_LEVEL_H264_2_0, V4L2_MPEG_VIDEO_H264_LEVEL_2_0 }, - { VIRTIO_VIDEO_LEVEL_H264_2_1, V4L2_MPEG_VIDEO_H264_LEVEL_2_1 }, - { VIRTIO_VIDEO_LEVEL_H264_2_2, V4L2_MPEG_VIDEO_H264_LEVEL_2_2 }, - { VIRTIO_VIDEO_LEVEL_H264_3_0, V4L2_MPEG_VIDEO_H264_LEVEL_3_0 }, - { VIRTIO_VIDEO_LEVEL_H264_3_1, V4L2_MPEG_VIDEO_H264_LEVEL_3_1 }, - { VIRTIO_VIDEO_LEVEL_H264_3_2, V4L2_MPEG_VIDEO_H264_LEVEL_3_2 }, - { VIRTIO_VIDEO_LEVEL_H264_4_0, V4L2_MPEG_VIDEO_H264_LEVEL_4_0 }, - { VIRTIO_VIDEO_LEVEL_H264_4_1, V4L2_MPEG_VIDEO_H264_LEVEL_4_1 }, - { VIRTIO_VIDEO_LEVEL_H264_4_2, V4L2_MPEG_VIDEO_H264_LEVEL_4_2 }, - { VIRTIO_VIDEO_LEVEL_H264_5_0, V4L2_MPEG_VIDEO_H264_LEVEL_5_0 }, - { VIRTIO_VIDEO_LEVEL_H264_5_1, V4L2_MPEG_VIDEO_H264_LEVEL_5_1 }, - { 0 }, -}; - -uint32_t virtio_video_level_to_v4l2(uint32_t level) -{ - size_t idx; - - for (idx = 0; idx < ARRAY_SIZE(level_table); idx++) { - if (level_table[idx].virtio_value == level) - return level_table[idx].v4l2_value; - } - - return 0; -} - -uint32_t virtio_video_v4l2_level_to_virtio(uint32_t v4l2_level) -{ - size_t idx; - - for (idx = 0; idx < ARRAY_SIZE(level_table); idx++) { - if (level_table[idx].v4l2_value == v4l2_level) - return level_table[idx].virtio_value; - } - - return 0; -} - -static struct virtio_video_convert_table profile_table[] = { - { VIRTIO_VIDEO_PROFILE_H264_BASELINE, - V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE }, - { VIRTIO_VIDEO_PROFILE_H264_MAIN, V4L2_MPEG_VIDEO_H264_PROFILE_MAIN }, - { VIRTIO_VIDEO_PROFILE_H264_EXTENDED, - V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED }, - { VIRTIO_VIDEO_PROFILE_H264_HIGH, V4L2_MPEG_VIDEO_H264_PROFILE_HIGH }, - { VIRTIO_VIDEO_PROFILE_H264_HIGH10PROFILE, - V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10 }, - { VIRTIO_VIDEO_PROFILE_H264_HIGH422PROFILE, - V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422}, - { VIRTIO_VIDEO_PROFILE_H264_HIGH444PREDICTIVEPROFILE, - V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE }, - { VIRTIO_VIDEO_PROFILE_H264_SCALABLEBASELINE, - V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE }, - { VIRTIO_VIDEO_PROFILE_H264_SCALABLEHIGH, - V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH }, - { VIRTIO_VIDEO_PROFILE_H264_STEREOHIGH, - V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH }, - { VIRTIO_VIDEO_PROFILE_H264_MULTIVIEWHIGH, - V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH }, - { 0 }, -}; - -uint32_t virtio_video_profile_to_v4l2(uint32_t profile) -{ - size_t idx; - - for (idx = 0; idx < ARRAY_SIZE(profile_table); idx++) { - if (profile_table[idx].virtio_value == profile) - return profile_table[idx].v4l2_value; - } - - return 0; -} - -uint32_t virtio_video_v4l2_profile_to_virtio(uint32_t v4l2_profile) -{ - size_t idx; - - for (idx = 0; idx < ARRAY_SIZE(profile_table); idx++) { - if (profile_table[idx].v4l2_value == v4l2_profile) - return profile_table[idx].virtio_value; - } - - return 0; -} - -static struct virtio_video_convert_table format_table[] = { - { VIRTIO_VIDEO_FORMAT_ARGB8888, V4L2_PIX_FMT_ARGB32 }, - { VIRTIO_VIDEO_FORMAT_BGRA8888, V4L2_PIX_FMT_ABGR32 }, - { VIRTIO_VIDEO_FORMAT_RGBA8888, V4L2_PIX_FMT_RGB32 }, - { VIRTIO_VIDEO_FORMAT_NV12, V4L2_PIX_FMT_NV12 }, - { VIRTIO_VIDEO_FORMAT_YUV420, V4L2_PIX_FMT_YUV420 }, - { VIRTIO_VIDEO_FORMAT_YVU420, V4L2_PIX_FMT_YVU420 }, - { VIRTIO_VIDEO_FORMAT_YUV422, V4L2_PIX_FMT_YUYV }, - { VIRTIO_VIDEO_FORMAT_MPEG2, V4L2_PIX_FMT_MPEG2 }, - { VIRTIO_VIDEO_FORMAT_MPEG4, V4L2_PIX_FMT_MPEG4 }, - { VIRTIO_VIDEO_FORMAT_H264, V4L2_PIX_FMT_H264 }, - { VIRTIO_VIDEO_FORMAT_HEVC, V4L2_PIX_FMT_HEVC }, - { VIRTIO_VIDEO_FORMAT_VP8, V4L2_PIX_FMT_VP8 }, - { VIRTIO_VIDEO_FORMAT_VP9, V4L2_PIX_FMT_VP9 }, - { 0 }, -}; - -uint32_t virtio_video_format_to_v4l2(uint32_t format) -{ - size_t idx; - - for (idx = 0; idx < ARRAY_SIZE(format_table); idx++) { - if (format_table[idx].virtio_value == format) - return format_table[idx].v4l2_value; - } - - return 0; -} - -uint32_t virtio_video_v4l2_format_to_virtio(uint32_t v4l2_format) -{ - size_t idx; - - for (idx = 0; idx < ARRAY_SIZE(format_table); idx++) { - if (format_table[idx].v4l2_value == v4l2_format) - return format_table[idx].virtio_value; - } - - return 0; -} - -static struct virtio_video_convert_table control_table[] = { - { VIRTIO_VIDEO_CONTROL_BITRATE, V4L2_CID_MPEG_VIDEO_BITRATE }, - { VIRTIO_VIDEO_CONTROL_PROFILE, V4L2_CID_MPEG_VIDEO_H264_PROFILE }, - { VIRTIO_VIDEO_CONTROL_LEVEL, V4L2_CID_MPEG_VIDEO_H264_LEVEL }, - { 0 }, -}; - -uint32_t virtio_video_control_to_v4l2(uint32_t control) -{ - size_t idx; - - for (idx = 0; idx < ARRAY_SIZE(control_table); idx++) { - if (control_table[idx].virtio_value == control) - return control_table[idx].v4l2_value; - } - - return 0; -} - -uint32_t virtio_video_v4l2_control_to_virtio(uint32_t v4l2_control) -{ - size_t idx; - - for (idx = 0; idx < ARRAY_SIZE(control_table); idx++) { - if (control_table[idx].v4l2_value == v4l2_control) - return control_table[idx].virtio_value; - } - - return 0; -} - -uint32_t virtio_video_get_format_from_virtio_profile(uint32_t virtio_profile) -{ - if (virtio_profile >= VIRTIO_VIDEO_PROFILE_H264_MIN && - virtio_profile <= VIRTIO_VIDEO_PROFILE_H264_MAX) - return VIRTIO_VIDEO_FORMAT_H264; - else if (virtio_profile >= VIRTIO_VIDEO_PROFILE_HEVC_MIN && - virtio_profile <= VIRTIO_VIDEO_PROFILE_HEVC_MAX) - return VIRTIO_VIDEO_FORMAT_HEVC; - else if (virtio_profile >= VIRTIO_VIDEO_PROFILE_VP8_MIN && - virtio_profile <= VIRTIO_VIDEO_PROFILE_VP8_MAX) - return VIRTIO_VIDEO_FORMAT_VP8; - else if (virtio_profile >= VIRTIO_VIDEO_PROFILE_VP9_MIN && - virtio_profile <= VIRTIO_VIDEO_PROFILE_VP9_MAX) - return VIRTIO_VIDEO_FORMAT_VP9; - - return 0; -} - -struct video_format *virtio_video_find_video_format(struct list_head *fmts_list, - uint32_t format) -{ - struct video_format *fmt = NULL; - - list_for_each_entry(fmt, fmts_list, formats_list_entry) { - if (fmt->desc.format == format) - return fmt; - } - - return NULL; -} - -void virtio_video_format_from_info(struct video_format_info *info, - struct v4l2_pix_format_mplane *pix_mp) -{ - int i; - - pix_mp->width = info->frame_width; - pix_mp->height = info->frame_height; - pix_mp->field = V4L2_FIELD_NONE; - pix_mp->colorspace = V4L2_COLORSPACE_REC709; - pix_mp->xfer_func = 0; - pix_mp->ycbcr_enc = 0; - pix_mp->quantization = 0; - memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved)); - memset(pix_mp->plane_fmt[0].reserved, 0, - sizeof(pix_mp->plane_fmt[0].reserved)); - - pix_mp->num_planes = info->num_planes; - pix_mp->pixelformat = info->fourcc_format; - - for (i = 0; i < info->num_planes; i++) { - pix_mp->plane_fmt[i].bytesperline = - info->plane_format[i].stride; - pix_mp->plane_fmt[i].sizeimage = - info->plane_format[i].plane_size; - } -} - -void virtio_video_format_fill_default_info(struct video_format_info *dst_info, - struct video_format_info *src_info) -{ - memcpy(dst_info, src_info, sizeof(*dst_info)); -} - -void virtio_video_pix_fmt_sp2mp(const struct v4l2_pix_format *pix, - struct v4l2_pix_format_mplane *pix_mp) -{ - memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved)); - memset(&pix_mp->plane_fmt[0].reserved, 0, - sizeof(pix_mp->plane_fmt[0].reserved)); - pix_mp->num_planes = 1; - pix_mp->width = pix->width; - pix_mp->height = pix->height; - pix_mp->pixelformat = pix->pixelformat; - pix_mp->field = pix->field; - pix_mp->plane_fmt[0].bytesperline = pix->bytesperline; - pix_mp->plane_fmt[0].sizeimage = pix->sizeimage; - pix_mp->colorspace = pix->colorspace; - pix_mp->flags = pix->flags; - pix_mp->ycbcr_enc = pix->ycbcr_enc; - pix_mp->quantization = pix->quantization; - pix_mp->xfer_func = pix->xfer_func; -} - -void virtio_video_pix_fmt_mp2sp(const struct v4l2_pix_format_mplane *pix_mp, - struct v4l2_pix_format *pix) -{ - pix->width = pix_mp->width; - pix->height = pix_mp->height; - pix->pixelformat = pix_mp->pixelformat; - pix->field = pix_mp->field; - pix->bytesperline = pix_mp->plane_fmt[0].bytesperline; - pix->sizeimage = pix_mp->plane_fmt[0].sizeimage; - pix->colorspace = pix_mp->colorspace; - pix->priv = 0; - pix->flags = pix_mp->flags; - pix->ycbcr_enc = pix_mp->ycbcr_enc; - pix->quantization = pix_mp->quantization; - pix->xfer_func = pix_mp->xfer_func; -} diff --git a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_vq.c b/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_vq.c deleted file mode 100644 index f3c97c7e..00000000 --- a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_vq.c +++ /dev/null @@ -1,981 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* Driver for virtio video device. - * - * Copyright 2020 OpenSynergy GmbH. - * - * Based on drivers/gpu/drm/virtio/virtgpu_vq.c - * Copyright (C) 2015 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#include "virtio_video.h" - -#define MAX_INLINE_CMD_SIZE 298 -#define MAX_INLINE_RESP_SIZE 298 -#define VBUFFER_SIZE (sizeof(struct virtio_video_vbuffer) \ - + MAX_INLINE_CMD_SIZE \ - + MAX_INLINE_RESP_SIZE) - -static int virtio_video_queue_event_buffer(struct virtio_video_device *vvd, - struct virtio_video_event *evt); -static void virtio_video_handle_event(struct virtio_video_device *vvd, - struct virtio_video_event *evt); - -void virtio_video_resource_id_get(struct virtio_video_device *vvd, uint32_t *id) -{ - int handle; - - idr_preload(GFP_KERNEL); - spin_lock(&vvd->resource_idr_lock); - handle = idr_alloc(&vvd->resource_idr, NULL, 1, 0, GFP_NOWAIT); - spin_unlock(&vvd->resource_idr_lock); - idr_preload_end(); - *id = handle; -} - -void virtio_video_resource_id_put(struct virtio_video_device *vvd, uint32_t id) -{ - spin_lock(&vvd->resource_idr_lock); - idr_remove(&vvd->resource_idr, id); - spin_unlock(&vvd->resource_idr_lock); -} - -void virtio_video_stream_id_get(struct virtio_video_device *vvd, - struct virtio_video_stream *stream, - uint32_t *id) -{ - int handle; - - idr_preload(GFP_KERNEL); - spin_lock(&vvd->stream_idr_lock); - handle = idr_alloc(&vvd->stream_idr, stream, 1, 0, 0); - spin_unlock(&vvd->stream_idr_lock); - idr_preload_end(); - *id = handle; -} - -void virtio_video_stream_id_put(struct virtio_video_device *vvd, uint32_t id) -{ - spin_lock(&vvd->stream_idr_lock); - idr_remove(&vvd->stream_idr, id); - spin_unlock(&vvd->stream_idr_lock); -} - -static bool vbuf_is_pending(struct virtio_video_device *vvd, - struct virtio_video_vbuffer *vbuf) -{ - struct virtio_video_vbuffer *entry; - - list_for_each_entry(entry, &vvd->pending_vbuf_list, pending_list_entry) - { - if (entry == vbuf && entry->id == vbuf->id) - return true; - } - - return false; -} - -static void free_vbuf(struct virtio_video_device *vvd, - struct virtio_video_vbuffer *vbuf) -{ - list_del(&vbuf->pending_list_entry); - kfree(vbuf->data_buf); - kmem_cache_free(vvd->vbufs, vbuf); -} - -void virtio_video_cmd_cb(struct virtqueue *vq) -{ - struct virtio_video_device *vvd = vq->vdev->priv; - struct virtio_video_vbuffer *vbuf; - unsigned long flags; - unsigned int len; - - spin_lock_irqsave(&vvd->commandq.qlock, flags); - while (vvd->commandq.ready) { - virtqueue_disable_cb(vq); - - while ((vbuf = virtqueue_get_buf(vq, &len))) { - if (!vbuf_is_pending(vvd, vbuf)) - continue; - - if (vbuf->resp_cb) - vbuf->resp_cb(vvd, vbuf); - - if (vbuf->is_sync) - complete(&vbuf->reclaimed); - else - free_vbuf(vvd, vbuf); - } - - if (unlikely(virtqueue_is_broken(vq))) - break; - - if (virtqueue_enable_cb(vq)) - break; - } - spin_unlock_irqrestore(&vvd->commandq.qlock, flags); - - wake_up(&vvd->commandq.reclaim_queue); -} - -void virtio_video_process_events(struct work_struct *work) -{ - struct virtio_video_device *vvd = container_of(work, - struct virtio_video_device, eventq.work); - struct virtqueue *vq = vvd->eventq.vq; - struct virtio_video_event *evt; - unsigned int len; - - while (vvd->eventq.ready) { - virtqueue_disable_cb(vq); - - while ((evt = virtqueue_get_buf(vq, &len))) { - virtio_video_handle_event(vvd, evt); - virtio_video_queue_event_buffer(vvd, evt); - } - - if (unlikely(virtqueue_is_broken(vq))) - break; - - if (virtqueue_enable_cb(vq)) - break; - } -} - -void virtio_video_event_cb(struct virtqueue *vq) -{ - struct virtio_video_device *vvd = vq->vdev->priv; - - schedule_work(&vvd->eventq.work); -} - -static struct virtio_video_vbuffer * -virtio_video_get_vbuf(struct virtio_video_device *vvd, int size, int resp_size, - void *resp_buf, virtio_video_resp_cb resp_cb) -{ - struct virtio_video_vbuffer *vbuf; - - vbuf = kmem_cache_alloc(vvd->vbufs, GFP_KERNEL); - if (!vbuf) - return ERR_PTR(-ENOMEM); - memset(vbuf, 0, VBUFFER_SIZE); - - BUG_ON(size > MAX_INLINE_CMD_SIZE); - vbuf->buf = (void *)vbuf + sizeof(*vbuf); - vbuf->size = size; - - vbuf->resp_cb = resp_cb; - vbuf->resp_size = resp_size; - if (resp_size <= MAX_INLINE_RESP_SIZE && !resp_buf) - vbuf->resp_buf = (void *)vbuf->buf + size; - else - vbuf->resp_buf = resp_buf; - BUG_ON(!vbuf->resp_buf); - - return vbuf; -} - -int virtio_video_alloc_vbufs(struct virtio_video_device *vvd) -{ - vvd->vbufs = - kmem_cache_create("virtio-video-vbufs", VBUFFER_SIZE, - __alignof__(struct virtio_video_vbuffer), 0, - NULL); - if (!vvd->vbufs) - return -ENOMEM; - - return 0; -} - -void virtio_video_free_vbufs(struct virtio_video_device *vvd) -{ - struct virtio_video_vbuffer *vbuf; - - /* Release command buffers. Operation on vbufs here is lock safe, - since before device was deinitialized and queues was stopped - (in not ready state) */ - while ((vbuf = virtqueue_detach_unused_buf(vvd->commandq.vq))) { - if (vbuf_is_pending(vvd, vbuf)) - free_vbuf(vvd, vbuf); - } - - kmem_cache_destroy(vvd->vbufs); - vvd->vbufs = NULL; - - /* Release event buffers */ - while (virtqueue_detach_unused_buf(vvd->eventq.vq)); - - kfree(vvd->evts); - vvd->evts = NULL; -} - -static void *virtio_video_alloc_req(struct virtio_video_device *vvd, - struct virtio_video_vbuffer **vbuffer_p, - int size) -{ - struct virtio_video_vbuffer *vbuf; - - vbuf = virtio_video_get_vbuf(vvd, size, - sizeof(struct virtio_video_cmd_hdr), - NULL, NULL); - if (IS_ERR(vbuf)) { - *vbuffer_p = NULL; - return ERR_CAST(vbuf); - } - *vbuffer_p = vbuf; - - return vbuf->buf; -} - -static void * -virtio_video_alloc_req_resp(struct virtio_video_device *vvd, - virtio_video_resp_cb cb, - struct virtio_video_vbuffer **vbuffer_p, - int req_size, int resp_size, - void *resp_buf) -{ - struct virtio_video_vbuffer *vbuf; - - vbuf = virtio_video_get_vbuf(vvd, req_size, resp_size, resp_buf, cb); - if (IS_ERR(vbuf)) { - *vbuffer_p = NULL; - return ERR_CAST(vbuf); - } - *vbuffer_p = vbuf; - - return vbuf->buf; -} - -static int -virtio_video_queue_cmd_buffer(struct virtio_video_device *vvd, - struct virtio_video_vbuffer *vbuf) -{ - unsigned long flags; - struct virtqueue *vq = vvd->commandq.vq; - struct scatterlist *sgs[3], vreq, vout, vresp; - int outcnt = 0, incnt = 0; - int ret; - - if (!vvd->commandq.ready) - return -ENODEV; - - spin_lock_irqsave(&vvd->commandq.qlock, flags); - - vbuf->id = vvd->vbufs_sent++; - list_add_tail(&vbuf->pending_list_entry, &vvd->pending_vbuf_list); - - sg_init_one(&vreq, vbuf->buf, vbuf->size); - sgs[outcnt + incnt] = &vreq; - outcnt++; - - if (vbuf->data_size) { - sg_init_one(&vout, vbuf->data_buf, vbuf->data_size); - sgs[outcnt + incnt] = &vout; - outcnt++; - } - - if (vbuf->resp_size) { - sg_init_one(&vresp, vbuf->resp_buf, vbuf->resp_size); - sgs[outcnt + incnt] = &vresp; - incnt++; - } - -retry: - ret = virtqueue_add_sgs(vq, sgs, outcnt, incnt, vbuf, GFP_ATOMIC); - if (ret == -ENOSPC) { - spin_unlock_irqrestore(&vvd->commandq.qlock, flags); - wait_event(vvd->commandq.reclaim_queue, vq->num_free); - spin_lock_irqsave(&vvd->commandq.qlock, flags); - goto retry; - } else { - virtqueue_kick(vq); - } - - spin_unlock_irqrestore(&vvd->commandq.qlock, flags); - - return ret; -} - -static int -virtio_video_queue_cmd_buffer_sync(struct virtio_video_device *vvd, - struct virtio_video_vbuffer *vbuf) -{ - int ret; - unsigned long rem; - unsigned long flags; - - vbuf->is_sync = true; - init_completion(&vbuf->reclaimed); - - ret = virtio_video_queue_cmd_buffer(vvd, vbuf); - if (ret) - return ret; - - rem = wait_for_completion_timeout(&vbuf->reclaimed, 5 * HZ); - if (rem == 0) - ret = -ETIMEDOUT; - - spin_lock_irqsave(&vvd->commandq.qlock, flags); - if (vbuf_is_pending(vvd, vbuf)) - free_vbuf(vvd, vbuf); - spin_unlock_irqrestore(&vvd->commandq.qlock, flags); - - return ret; -} - -static int virtio_video_queue_event_buffer(struct virtio_video_device *vvd, - struct virtio_video_event *evt) -{ - int ret; - struct scatterlist sg; - struct virtqueue *vq = vvd->eventq.vq; - - memset(evt, 0, sizeof(struct virtio_video_event)); - sg_init_one(&sg, evt, sizeof(struct virtio_video_event)); - - ret = virtqueue_add_inbuf(vq, &sg, 1, evt, GFP_KERNEL); - if (ret) { - v4l2_err(&vvd->v4l2_dev, "failed to queue event buffer\n"); - return ret; - } - - virtqueue_kick(vq); - - return 0; -} - -static void virtio_video_handle_event(struct virtio_video_device *vvd, - struct virtio_video_event *evt) -{ - int ret; - struct virtio_video_stream *stream; - uint32_t stream_id = evt->stream_id; - struct video_device *vd = &vvd->video_dev; - - mutex_lock(vd->lock); - - stream = idr_find(&vvd->stream_idr, stream_id); - if (!stream) { - v4l2_warn(&vvd->v4l2_dev, "stream_id=%u not found for event\n", - stream_id); - mutex_unlock(vd->lock); - return; - } - - switch (le32_to_cpu(evt->event_type)) { - case VIRTIO_VIDEO_EVENT_DECODER_RESOLUTION_CHANGED: - v4l2_dbg(1, vvd->debug, &vvd->v4l2_dev, - "stream_id=%u: resolution change event\n", stream_id); - virtio_video_cmd_get_params(vvd, stream, - VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT); - virtio_video_queue_res_chg_event(stream); - if (virtio_video_state(stream) == STREAM_STATE_INIT) { - virtio_video_state_update(stream, - STREAM_STATE_DYNAMIC_RES_CHANGE); - wake_up(&vvd->wq); - } - break; - case VIRTIO_VIDEO_EVENT_ERROR: - v4l2_err(&vvd->v4l2_dev, "stream_id=%i: error event\n", - stream_id); - virtio_video_state_update(stream, STREAM_STATE_ERROR); - virtio_video_handle_error(stream); - break; - default: - v4l2_warn(&vvd->v4l2_dev, "stream_id=%i: unknown event\n", - stream_id); - break; - } - - mutex_unlock(vd->lock); -} - -int virtio_video_alloc_events(struct virtio_video_device *vvd) -{ - int ret; - size_t i; - struct virtio_video_event *evts; - size_t num = vvd->eventq.vq->num_free; - - evts = kzalloc(num * sizeof(struct virtio_video_event), GFP_KERNEL); - if (!evts) { - v4l2_err(&vvd->v4l2_dev, "failed to alloc event buffers!!!\n"); - return -ENOMEM; - } - vvd->evts = evts; - - for (i = 0; i < num; i++) { - ret = virtio_video_queue_event_buffer(vvd, &evts[i]); - if (ret) { - v4l2_err(&vvd->v4l2_dev, - "failed to queue event buffer\n"); - return ret; - } - } - - return 0; -} - -// TODO: replace virtio_video_cmd_hdr accoring to specification v4 -int virtio_video_cmd_stream_create(struct virtio_video_device *vvd, - uint32_t stream_id, - enum virtio_video_format format, - const char *tag) -{ - struct virtio_video_stream_create *req_p; - struct virtio_video_vbuffer *vbuf; - - req_p = virtio_video_alloc_req(vvd, &vbuf, sizeof(*req_p)); - if (IS_ERR(req_p)) - return PTR_ERR(req_p); - - req_p->hdr.type = cpu_to_le32(VIRTIO_VIDEO_CMD_STREAM_CREATE); - req_p->hdr.stream_id = cpu_to_le32(stream_id); - req_p->in_mem_type = cpu_to_le32(VIRTIO_VIDEO_MEM_TYPE_GUEST_PAGES); - req_p->out_mem_type = cpu_to_le32(VIRTIO_VIDEO_MEM_TYPE_GUEST_PAGES); - req_p->coded_format = cpu_to_le32(format); - if (strscpy(req_p->tag, tag, sizeof(req_p->tag) - 1) < 0) - v4l2_err(&vvd->v4l2_dev, "failed to copy stream tag\n"); - req_p->tag[sizeof(req_p->tag) - 1] = 0; - - return virtio_video_queue_cmd_buffer(vvd, vbuf); -} - -// TODO: replace virtio_video_cmd_hdr accoring to specification v4 -int virtio_video_cmd_stream_destroy(struct virtio_video_device *vvd, - uint32_t stream_id) -{ - struct virtio_video_stream_destroy *req_p; - struct virtio_video_vbuffer *vbuf; - - req_p = virtio_video_alloc_req(vvd, &vbuf, sizeof(*req_p)); - if (IS_ERR(req_p)) - return PTR_ERR(req_p); - - req_p->hdr.type = cpu_to_le32(VIRTIO_VIDEO_CMD_STREAM_DESTROY); - req_p->hdr.stream_id = cpu_to_le32(stream_id); - - return virtio_video_queue_cmd_buffer(vvd, vbuf); -} - -// TODO: replace virtio_video_cmd_hdr accoring to specification v4 -int virtio_video_cmd_stream_drain(struct virtio_video_device *vvd, - uint32_t stream_id) -{ - struct virtio_video_stream_drain *req_p; - struct virtio_video_vbuffer *vbuf; - - req_p = virtio_video_alloc_req(vvd, &vbuf, sizeof(*req_p)); - if (IS_ERR(req_p)) - return PTR_ERR(req_p); - - req_p->hdr.type = cpu_to_le32(VIRTIO_VIDEO_CMD_STREAM_DRAIN); - req_p->hdr.stream_id = cpu_to_le32(stream_id); - - return virtio_video_queue_cmd_buffer(vvd, vbuf); -} - -int virtio_video_cmd_resource_attach(struct virtio_video_device *vvd, - uint32_t stream_id, uint32_t resource_id, - enum virtio_video_queue_type queue_type, - void *buf, size_t buf_size) -{ - struct virtio_video_resource_attach *req_p; - struct virtio_video_vbuffer *vbuf; - - req_p = virtio_video_alloc_req(vvd, &vbuf, sizeof(*req_p)); - if (IS_ERR(req_p)) - return PTR_ERR(req_p); - - req_p->cmd_type = cpu_to_le32(VIRTIO_VIDEO_CMD_RESOURCE_ATTACH); - req_p->stream_id = cpu_to_le32(stream_id); - req_p->queue_type = cpu_to_le32(queue_type); - req_p->resource_id = cpu_to_le32(resource_id); - - vbuf->data_buf = buf; - vbuf->data_size = buf_size; - - return virtio_video_queue_cmd_buffer(vvd, vbuf); -} - -int virtio_video_cmd_queue_detach_resources(struct virtio_video_device *vvd, - struct virtio_video_stream *stream, - enum virtio_video_queue_type queue_type) -{ - int ret; - struct virtio_video_queue_detach_resources *req_p; - struct virtio_video_vbuffer *vbuf; - - req_p = virtio_video_alloc_req(vvd, &vbuf, sizeof(*req_p)); - if (IS_ERR(req_p)) - return PTR_ERR(req_p); - - req_p->cmd_type = cpu_to_le32(VIRTIO_VIDEO_CMD_QUEUE_DETACH_RESOURCES); - req_p->stream_id = cpu_to_le32(stream->stream_id); - req_p->queue_type = cpu_to_le32(queue_type); - - ret = virtio_video_queue_cmd_buffer_sync(vvd, vbuf); - if (ret == -ETIMEDOUT) - v4l2_err(&vvd->v4l2_dev, - "timed out waiting for resource destruction for %s\n", - (queue_type == VIRTIO_VIDEO_QUEUE_TYPE_INPUT) ? - "OUTPUT" : "CAPTURE"); - return ret; -} - -static void -virtio_video_cmd_resource_queue_cb(struct virtio_video_device *vvd, - struct virtio_video_vbuffer *vbuf) -{ - uint32_t flags; - uint64_t timestamp; - struct virtio_video_buffer *virtio_vb = vbuf->priv; - struct virtio_video_resource_queue_resp *resp = - (struct virtio_video_resource_queue_resp *)vbuf->resp_buf; - - flags = le32_to_cpu(resp->flags); - timestamp = le64_to_cpu(resp->timestamp); - - virtio_video_buf_done(virtio_vb, flags, timestamp, resp->data_sizes); -} - -int virtio_video_cmd_resource_queue(struct virtio_video_device *vvd, - uint32_t stream_id, - struct virtio_video_buffer *virtio_vb, - uint32_t data_size[], - uint8_t num_data_size, - enum virtio_video_queue_type queue_type) -{ - uint8_t i; - struct virtio_video_resource_queue *req_p; - struct virtio_video_resource_queue_resp *resp_p; - struct virtio_video_vbuffer *vbuf; - size_t resp_size = sizeof(struct virtio_video_resource_queue_resp); - - req_p = virtio_video_alloc_req_resp(vvd, - &virtio_video_cmd_resource_queue_cb, - &vbuf, sizeof(*req_p), resp_size, - NULL); - if (IS_ERR(req_p)) - return PTR_ERR(req_p); - - req_p->cmd_type = cpu_to_le32(VIRTIO_VIDEO_CMD_RESOURCE_QUEUE); - req_p->stream_id = cpu_to_le32(stream_id); - req_p->queue_type = cpu_to_le32(queue_type); - req_p->resource_id = cpu_to_le32(virtio_vb->resource_id); - req_p->flags = 0; - req_p->timestamp = - cpu_to_le64(virtio_vb->v4l2_m2m_vb.vb.vb2_buf.timestamp); - - for (i = 0; i < num_data_size; ++i) - req_p->data_sizes[i] = cpu_to_le32(data_size[i]); - - resp_p = (struct virtio_video_resource_queue_resp *)vbuf->resp_buf; - memset(resp_p, 0, sizeof(*resp_p)); - - vbuf->priv = virtio_vb; - - return virtio_video_queue_cmd_buffer(vvd, vbuf); -} - -// TODO: replace virtio_video_cmd_hdr accoring to specification v4 -int virtio_video_cmd_queue_clear(struct virtio_video_device *vvd, - struct virtio_video_stream *stream, - enum virtio_video_queue_type queue_type) -{ - int ret; - struct virtio_video_queue_clear *req_p; - struct virtio_video_vbuffer *vbuf; - - req_p = virtio_video_alloc_req(vvd, &vbuf, sizeof(*req_p)); - if (IS_ERR(req_p)) - return PTR_ERR(req_p); - - req_p->hdr.type = cpu_to_le32(VIRTIO_VIDEO_CMD_QUEUE_CLEAR); - req_p->hdr.stream_id = cpu_to_le32(stream->stream_id); - req_p->queue_type = cpu_to_le32(queue_type); - - ret = virtio_video_queue_cmd_buffer_sync(vvd, vbuf); - if (ret == -ETIMEDOUT) - v4l2_err(&vvd->v4l2_dev, - "timed out waiting for %s queue clear\n", - (queue_type == VIRTIO_VIDEO_QUEUE_TYPE_INPUT) ? - "OUTPUT" : "CAPTURE"); - return ret; -} - -// TODO: replace virtio_video_cmd_hdr accoring to specification v4 -int virtio_video_cmd_query_capability(struct virtio_video_device *vvd, - void *resp_buf, size_t resp_size, - enum virtio_video_queue_type queue_type) -{ - int ret; - struct virtio_video_query_capability *req_p; - struct virtio_video_vbuffer *vbuf; - - req_p = virtio_video_alloc_req_resp(vvd, NULL, &vbuf, sizeof(*req_p), - resp_size, resp_buf); - if (IS_ERR(req_p)) - return PTR_ERR(req_p); - - req_p->hdr.type = cpu_to_le32(VIRTIO_VIDEO_CMD_QUERY_CAPABILITY); - req_p->queue_type = cpu_to_le32(queue_type); - - ret = virtio_video_queue_cmd_buffer_sync(vvd, vbuf); - if (ret == -ETIMEDOUT) - v4l2_err(&vvd->v4l2_dev, - "timed out waiting for capabilities for %s\n", - (queue_type == VIRTIO_VIDEO_QUEUE_TYPE_INPUT) ? - "OUTPUT" : "CAPTURE"); - return ret; -} - -// TODO: replace virtio_video_cmd_hdr accoring to specification v4 -int virtio_video_query_control_level(struct virtio_video_device *vvd, - void *resp_buf, size_t resp_size, - enum virtio_video_format format) -{ - int ret; - struct virtio_video_query_control *req_p; - struct virtio_video_query_control_level *ctrl_l; - struct virtio_video_vbuffer *vbuf; - uint32_t req_size = 0; - - req_size = sizeof(struct virtio_video_query_control) + - sizeof(struct virtio_video_query_control_level); - - req_p = virtio_video_alloc_req_resp(vvd, NULL, &vbuf, req_size, - resp_size, resp_buf); - if (IS_ERR(req_p)) - return PTR_ERR(req_p); - - req_p->hdr.type = cpu_to_le32(VIRTIO_VIDEO_CMD_QUERY_CONTROL); - req_p->control = cpu_to_le32(VIRTIO_VIDEO_CONTROL_LEVEL); - ctrl_l = (void *)((char *)req_p + - sizeof(struct virtio_video_query_control)); - ctrl_l->format = cpu_to_le32(format); - - ret = virtio_video_queue_cmd_buffer_sync(vvd, vbuf); - if (ret == -ETIMEDOUT) - v4l2_err(&vvd->v4l2_dev, - "timed out waiting for level query\n"); - return ret; -} - -// TODO: replace virtio_video_cmd_hdr accoring to specification v4 -int virtio_video_query_control_profile(struct virtio_video_device *vvd, - void *resp_buf, size_t resp_size, - enum virtio_video_format format) -{ - int ret; - struct virtio_video_query_control *req_p; - struct virtio_video_query_control_profile *ctrl_p; - struct virtio_video_vbuffer *vbuf; - uint32_t req_size = 0; - - req_size = sizeof(struct virtio_video_query_control) + - sizeof(struct virtio_video_query_control_profile); - - req_p = virtio_video_alloc_req_resp(vvd, NULL, &vbuf, req_size, - resp_size, resp_buf); - if (IS_ERR(req_p)) - return PTR_ERR(req_p); - - req_p->hdr.type = cpu_to_le32(VIRTIO_VIDEO_CMD_QUERY_CONTROL); - req_p->control = cpu_to_le32(VIRTIO_VIDEO_CONTROL_PROFILE); - ctrl_p = (void *)((char *)req_p + - sizeof(struct virtio_video_query_control)); - ctrl_p->format = cpu_to_le32(format); - - ret = virtio_video_queue_cmd_buffer_sync(vvd, vbuf); - if (ret == -ETIMEDOUT) - v4l2_err(&vvd->v4l2_dev, - "timed out waiting for profile query\n"); - return ret; -} - -static void -virtio_video_cmd_get_params_cb(struct virtio_video_device *vvd, - struct virtio_video_vbuffer *vbuf) -{ - int i; - struct virtio_video_get_params_resp *resp = - (struct virtio_video_get_params_resp *)vbuf->resp_buf; - struct virtio_video_params *params = &resp->params; - struct virtio_video_stream *stream = vbuf->priv; - enum virtio_video_queue_type queue_type; - struct video_format_info *format_info; - - queue_type = le32_to_cpu(params->queue_type); - if (queue_type == VIRTIO_VIDEO_QUEUE_TYPE_INPUT) - format_info = &stream->in_info; - else - format_info = &stream->out_info; - - format_info->frame_rate = le32_to_cpu(params->frame_rate); - format_info->frame_width = le32_to_cpu(params->frame_width); - format_info->frame_height = le32_to_cpu(params->frame_height); - format_info->min_buffers = le32_to_cpu(params->min_buffers); - format_info->max_buffers = le32_to_cpu(params->max_buffers); - format_info->fourcc_format = - virtio_video_format_to_v4l2(le32_to_cpu(params->format)); - - format_info->crop.top = le32_to_cpu(params->crop.top); - format_info->crop.left = le32_to_cpu(params->crop.left); - format_info->crop.width = le32_to_cpu(params->crop.width); - format_info->crop.height = le32_to_cpu(params->crop.height); - - format_info->num_planes = le32_to_cpu(params->num_planes); - for (i = 0; i < le32_to_cpu(params->num_planes); i++) { - struct virtio_video_plane_format *plane_formats = - ¶ms->plane_formats[i]; - struct video_plane_format *plane_format = - &format_info->plane_format[i]; - - plane_format->plane_size = - le32_to_cpu(plane_formats->plane_size); - plane_format->stride = le32_to_cpu(plane_formats->stride); - } -} - -// TODO: replace virtio_video_cmd_hdr accoring to specification v4 -int virtio_video_cmd_get_params(struct virtio_video_device *vvd, - struct virtio_video_stream *stream, - enum virtio_video_queue_type queue_type) -{ - int ret; - struct virtio_video_get_params *req_p; - struct virtio_video_vbuffer *vbuf; - struct virtio_video_get_params_resp *resp_p; - size_t resp_size = sizeof(struct virtio_video_get_params_resp); - - req_p = virtio_video_alloc_req_resp(vvd, - &virtio_video_cmd_get_params_cb, - &vbuf, sizeof(*req_p), resp_size, - NULL); - if (IS_ERR(req_p)) - return PTR_ERR(req_p); - - req_p->hdr.type = cpu_to_le32(VIRTIO_VIDEO_CMD_GET_PARAMS); - req_p->hdr.stream_id = cpu_to_le32(stream->stream_id); - req_p->queue_type = cpu_to_le32(queue_type); - - resp_p = (struct virtio_video_get_params_resp *)vbuf->resp_buf; - - vbuf->priv = stream; - - ret = virtio_video_queue_cmd_buffer_sync(vvd, vbuf); - if (ret == -ETIMEDOUT) - v4l2_err(&vvd->v4l2_dev, - "timed out waiting for get_params\n"); - return ret; -} - -// TODO: replace virtio_video_cmd_hdr accoring to specification v4 -int -virtio_video_cmd_set_params(struct virtio_video_device *vvd, - struct virtio_video_stream *stream, - struct video_format_info *format_info, - enum virtio_video_queue_type queue_type) -{ - int i; - struct virtio_video_set_params *req_p; - struct virtio_video_vbuffer *vbuf; - - req_p = virtio_video_alloc_req(vvd, &vbuf, sizeof(*req_p)); - if (IS_ERR(req_p)) - return PTR_ERR(req_p); - - req_p->hdr.type = cpu_to_le32(VIRTIO_VIDEO_CMD_SET_PARAMS); - req_p->hdr.stream_id = cpu_to_le32(stream->stream_id); - req_p->params.queue_type = cpu_to_le32(queue_type); - req_p->params.frame_rate = cpu_to_le32(format_info->frame_rate); - req_p->params.frame_width = cpu_to_le32(format_info->frame_width); - req_p->params.frame_height = cpu_to_le32(format_info->frame_height); - req_p->params.format = virtio_video_v4l2_format_to_virtio( - cpu_to_le32(format_info->fourcc_format)); - req_p->params.min_buffers = cpu_to_le32(format_info->min_buffers); - req_p->params.max_buffers = cpu_to_le32(format_info->max_buffers); - req_p->params.num_planes = cpu_to_le32(format_info->num_planes); - - for (i = 0; i < format_info->num_planes; i++) { - struct virtio_video_plane_format *plane_formats = - &req_p->params.plane_formats[i]; - struct video_plane_format *plane_format = - &format_info->plane_format[i]; - plane_formats->plane_size = - cpu_to_le32(plane_format->plane_size); - plane_formats->stride = cpu_to_le32(plane_format->stride); - } - - return virtio_video_queue_cmd_buffer(vvd, vbuf); -} - -static void -virtio_video_cmd_get_ctrl_profile_cb(struct virtio_video_device *vvd, - struct virtio_video_vbuffer *vbuf) -{ - struct virtio_video_get_control_resp *resp = - (struct virtio_video_get_control_resp *)vbuf->resp_buf; - struct virtio_video_control_val_profile *resp_p = NULL; - struct virtio_video_stream *stream = vbuf->priv; - struct video_control_info *control = &stream->control; - - resp_p = (void *)((char *)resp + - sizeof(struct virtio_video_get_control_resp)); - - control->profile = le32_to_cpu(resp_p->profile); -} - -static void -virtio_video_cmd_get_ctrl_level_cb(struct virtio_video_device *vvd, - struct virtio_video_vbuffer *vbuf) -{ - struct virtio_video_get_control_resp *resp = - (struct virtio_video_get_control_resp *)vbuf->resp_buf; - struct virtio_video_control_val_level *resp_p; - struct virtio_video_stream *stream = vbuf->priv; - struct video_control_info *control = &stream->control; - - resp_p = (void *)((char *)resp + - sizeof(struct virtio_video_get_control_resp)); - - control->level = le32_to_cpu(resp_p->level); -} - -static void -virtio_video_cmd_get_ctrl_bitrate_cb(struct virtio_video_device *vvd, - struct virtio_video_vbuffer *vbuf) -{ - struct virtio_video_get_control_resp *resp = - (struct virtio_video_get_control_resp *)vbuf->resp_buf; - struct virtio_video_control_val_bitrate *resp_p = NULL; - struct virtio_video_stream *stream = vbuf->priv; - struct video_control_info *control = &stream->control; - - resp_p = (void *)((char *) resp + - sizeof(struct virtio_video_get_control_resp)); - - control->bitrate = le32_to_cpu(resp_p->bitrate); -} - -// TODO: replace virtio_video_cmd_hdr accoring to specification v4 -int virtio_video_cmd_get_control(struct virtio_video_device *vvd, - struct virtio_video_stream *stream, - enum virtio_video_control_type control) -{ - int ret; - struct virtio_video_get_control *req_p; - struct virtio_video_get_control_resp *resp_p; - struct virtio_video_vbuffer *vbuf; - size_t resp_size = sizeof(struct virtio_video_get_control_resp); - virtio_video_resp_cb cb; - - switch (control) { - case VIRTIO_VIDEO_CONTROL_PROFILE: - resp_size += sizeof(struct virtio_video_control_val_profile); - cb = &virtio_video_cmd_get_ctrl_profile_cb; - break; - case VIRTIO_VIDEO_CONTROL_LEVEL: - resp_size += sizeof(struct virtio_video_control_val_level); - cb = &virtio_video_cmd_get_ctrl_level_cb; - break; - case VIRTIO_VIDEO_CONTROL_BITRATE: - resp_size += sizeof(struct virtio_video_control_val_bitrate); - cb = &virtio_video_cmd_get_ctrl_bitrate_cb; - break; - default: - return -EINVAL; - } - - req_p = virtio_video_alloc_req_resp(vvd, cb, &vbuf, - sizeof(*req_p), resp_size, NULL); - if (IS_ERR(req_p)) - return PTR_ERR(req_p); - - req_p->hdr.type = cpu_to_le32(VIRTIO_VIDEO_CMD_GET_CONTROL); - req_p->hdr.stream_id = cpu_to_le32(stream->stream_id); - req_p->control = cpu_to_le32(control); - - resp_p = (struct virtio_video_get_control_resp *)vbuf->resp_buf; - - vbuf->priv = stream; - - ret = virtio_video_queue_cmd_buffer_sync(vvd, vbuf); - if (ret == -ETIMEDOUT) - v4l2_err(&vvd->v4l2_dev, - "timed out waiting for get_control\n"); - return ret; -} - -// TODO: replace virtio_video_cmd_hdr accoring to specification v4 -int virtio_video_cmd_set_control(struct virtio_video_device *vvd, - uint32_t stream_id, - enum virtio_video_control_type control, - uint32_t value) -{ - struct virtio_video_set_control *req_p; - struct virtio_video_vbuffer *vbuf; - struct virtio_video_control_val_level *ctrl_l; - struct virtio_video_control_val_profile *ctrl_p; - struct virtio_video_control_val_bitrate *ctrl_b; - size_t size; - - if (value == 0) - return -EINVAL; - - switch (control) { - case VIRTIO_VIDEO_CONTROL_PROFILE: - size = sizeof(struct virtio_video_control_val_profile); - break; - case VIRTIO_VIDEO_CONTROL_LEVEL: - size = sizeof(struct virtio_video_control_val_level); - break; - case VIRTIO_VIDEO_CONTROL_BITRATE: - size = sizeof(struct virtio_video_control_val_bitrate); - break; - default: - return -EINVAL; - } - - req_p = virtio_video_alloc_req(vvd, &vbuf, size + sizeof(*req_p)); - if (IS_ERR(req_p)) - return PTR_ERR(req_p); - - req_p->hdr.type = cpu_to_le32(VIRTIO_VIDEO_CMD_SET_CONTROL); - req_p->hdr.stream_id = cpu_to_le32(stream_id); - req_p->control = cpu_to_le32(control); - - switch (control) { - case VIRTIO_VIDEO_CONTROL_PROFILE: - ctrl_p = (void *)((char *)req_p + - sizeof(struct virtio_video_set_control)); - ctrl_p->profile = cpu_to_le32(value); - break; - case VIRTIO_VIDEO_CONTROL_LEVEL: - ctrl_l = (void *)((char *)req_p + - sizeof(struct virtio_video_set_control)); - ctrl_l->level = cpu_to_le32(value); - break; - case VIRTIO_VIDEO_CONTROL_BITRATE: - ctrl_b = (void *)((char *)req_p + - sizeof(struct virtio_video_set_control)); - ctrl_b->bitrate = cpu_to_le32(value); - break; - } - - return virtio_video_queue_cmd_buffer(vvd, vbuf); -} - diff --git a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/kernel-module-virtio-video.bb b/meta-egvirt/recipes-kernel/kernel-module-virtio-video/kernel-module-virtio-video.bb deleted file mode 100644 index 6d023d2e..00000000 --- a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/kernel-module-virtio-video.bb +++ /dev/null @@ -1,12 +0,0 @@ -SUMMARY = "VIRTIO video device driver" - -LICENSE = "GPL-2.0-only" -LIC_FILES_CHKSUM = "file://virtio_video.h;endline=17;md5=3a04f9e12610bad07c6ec369a8077ba6" - -inherit module - -SRC_URI = "file://." - -S = "${WORKDIR}" - -KERNEL_MODULE_AUTOLOAD = "virtio_video" diff --git a/meta-egvirt/recipes-kernel/linux/linux-yocto/virtio_loopback.cfg b/meta-egvirt/recipes-kernel/linux/linux-yocto/virtio_loopback.cfg index d20575e4..f9ddb374 100644 --- a/meta-egvirt/recipes-kernel/linux/linux-yocto/virtio_loopback.cfg +++ b/meta-egvirt/recipes-kernel/linux/linux-yocto/virtio_loopback.cfg @@ -1,2 +1,3 @@ CONFIG_HW_RANDOM_VIRTIO=m CONFIG_VIRTIO_INPUT=y +CONFIG_VIRTIO_GPIO=y diff --git a/meta-egvirt/recipes-support/libgpiod/files/run-ptest b/meta-egvirt/recipes-support/libgpiod/files/run-ptest new file mode 100644 index 00000000..61b9b69f --- /dev/null +++ b/meta-egvirt/recipes-support/libgpiod/files/run-ptest @@ -0,0 +1,19 @@ +#!/bin/sh + +testbins="gpiod-test gpio-tools-test gpiod-cxx-test gpiod_py_test.py" + +ptestdir=$(dirname "$(readlink -f "$0")") +cd $ptestdir/tests + +for testbin in $testbins; do + if test -e ./$testbin; then + ./$testbin > ./$testbin.out 2>&1 + if [ $? -ne 0 ]; then + echo "FAIL: $testbin" + else + echo "PASS: $testbin" + fi + else + echo "SKIP: $testbin" + fi +done diff --git a/meta-egvirt/recipes-support/libgpiod/libgpiod.inc b/meta-egvirt/recipes-support/libgpiod/libgpiod.inc new file mode 100644 index 00000000..0edb429f --- /dev/null +++ b/meta-egvirt/recipes-support/libgpiod/libgpiod.inc @@ -0,0 +1,59 @@ +SUMMARY = "C library and tools for interacting with the linux GPIO character device" +RECIPE_MAINTAINER = "Bartosz Golaszewski " + +inherit autotools pkgconfig ptest + +SRC_URI += " \ + https://www.kernel.org/pub/software/libs/libgpiod/libgpiod-${PV}.tar.xz \ + file://run-ptest \ +" + +PACKAGECONFIG[cxx] = "--enable-bindings-cxx,--disable-bindings-cxx" + +# Enable cxx bindings by default. +PACKAGECONFIG ?= " \ + cxx \ + ${@bb.utils.contains('PTEST_ENABLED', '1', 'tests', '', d)} \ +" + +# Always build tools - they don't have any additional +# requirements over the library. +EXTRA_OECONF = "--enable-tools" + +DEPENDS += "autoconf-archive-native" + +PACKAGES =+ "${PN}-tools libgpiodcxx" +FILES:${PN}-tools += " \ + ${bindir}/gpiodetect \ + ${bindir}/gpioinfo \ + ${bindir}/gpioget \ + ${bindir}/gpioset \ + ${bindir}/gpiomon \ +" +FILES:libgpiodcxx = "${libdir}/libgpiodcxx.so.*" + +RRECOMMENDS:${PN}-ptest += "coreutils" + +do_install:append() { + rm -f ${D}${bindir}/gpiod-test + rm -f ${D}${bindir}/gpio-tools-test + rm -f ${D}${bindir}/gpio-tools-test.bats + rm -f ${D}${bindir}/gpiod-cxx-test +} + +do_install_ptest() { + install -d ${D}${PTEST_PATH}/tests/ + + # These are the core C library tests + install -m 0755 ${B}/tests/.libs/gpiod-test ${D}${PTEST_PATH}/tests/ + + # Tools are always built so let's always install them for ptest even if + # we're not selecting libgpiod-tools. + for tool in ${FILES:${PN}-tools}; do + install ${B}/tools/.libs/$(basename $tool) ${D}${PTEST_PATH}/tests/ + done + + if ${@bb.utils.contains('PACKAGECONFIG', 'cxx', 'true', 'false', d)}; then + install -m 0755 ${B}/bindings/cxx/tests/.libs/gpiod-cxx-test ${D}${PTEST_PATH}/tests/ + fi +} diff --git a/meta-egvirt/recipes-support/libgpiod/libgpiod_2.1.bb b/meta-egvirt/recipes-support/libgpiod/libgpiod_2.1.bb new file mode 100644 index 00000000..6de445ed --- /dev/null +++ b/meta-egvirt/recipes-support/libgpiod/libgpiod_2.1.bb @@ -0,0 +1,35 @@ +require libgpiod.inc + +LICENSE = "GPL-2.0-or-later & LGPL-2.1-or-later & CC-BY-SA-4.0" +LIC_FILES_CHKSUM = " \ + file://LICENSES/GPL-2.0-or-later.txt;md5=b234ee4d69f5fce4486a80fdaf4a4263 \ + file://LICENSES/LGPL-2.1-or-later.txt;md5=4b54a1fd55a448865a0b32d41598759d \ + file://LICENSES/CC-BY-SA-4.0.txt;md5=fba3b94d88bfb9b81369b869a1e9a20f \ +" + +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}-2.x:" + +SRC_URI[sha256sum] = "fa4024a080121c958502f9a46a5bda44bea85e7a4dd7fcb3dead463b6fc4261c" + +# Enable all project features for ptest +PACKAGECONFIG[tests] = "--enable-tests --enable-tools --enable-bindings-cxx --enable-gpioset-interactive,--disable-tests,kmod util-linux glib-2.0 catch2 libedit" +PACKAGECONFIG[gpioset-interactive] = "--enable-gpioset-interactive,--disable-gpioset-interactive,libedit" + +PACKAGES =+ "${PN}-ptest-dev" +FILES:${PN}-tools += "${bindir}/gpionotify" +FILES:${PN}-ptest += "${libdir}/libgpiosim.so.*" +FILES:${PN}-ptest-dev += "${includedir}/gpiosim.h" + +RDEPENDS:${PN}-ptest += " \ + bash \ + ${@bb.utils.contains('PTEST_ENABLED', '1', 'shunit2', '', d)} \ +" +RRECOMMENDS:${PN}-ptest += "kernel-module-gpio-sim" + +do_install_ptest:append() { + install -m 0755 ${S}/tools/gpio-tools-test.bash ${D}${PTEST_PATH}/tests/ + install -m 0644 ${S}/tests/gpiosim/gpiosim.h ${D}${includedir}/gpiosim.h +} + + + diff --git a/meta-egvirt/recipes-virtioloopback/rust-vhost-device/rust-vhost-device_git.bb b/meta-egvirt/recipes-virtioloopback/rust-vhost-device/rust-vhost-device_git.bb deleted file mode 100644 index cdd6e71d..00000000 --- a/meta-egvirt/recipes-virtioloopback/rust-vhost-device/rust-vhost-device_git.bb +++ /dev/null @@ -1,16 +0,0 @@ -SUMMARY = "VHOST device in rust" -HOMEPAGE = "https://git.virtualopensystems.com/virtio-loopback/vhost-user-rng-rust/vhost-device" -LICENSE = "Apache-2.0" -LIC_FILES_CHKSUM="file://README.md;md5=b92c66b94b87c250f37ea0234c9e2d9a" - -inherit cargo - -SRC_URI = "git://git.virtualopensystems.com/virtio-loopback/vhost-user-rng-rust/vhost-device.git;protocol=https;rev=de0c5cf1ceb079992f7680ffc7f1f04447b869e2" -SRC_URI += "git://git.virtualopensystems.com/virtio-loopback/vhost-user-rng-rust/vhost.git;protocol=https;rev=89fcc56b86b1f165c5b00144df26430a07e1a051;destsuffix=vhost" -SRC_URI += "git://git.virtualopensystems.com/virtio-loopback/vhost-user-rng-rust/vhost-user-backend.git;protocol=https;rev=78ce5fc3ba73e5ac359dcd030b1e8b08ee7e9f2c;destsuffix=vhost-user-backend" -SRC_URI += "git://git.virtualopensystems.com/virtio-loopback/vhost-user-rng-rust/vm-virtio.git;protocol=https;rev=edb16fd8900c14c17c3ab781160aac87813d3b4a;destsuffix=vm-virtio" - -S = "${WORKDIR}/git" - -BBCLASSEXTEND = "native" -CARGO_DISABLE_BITBAKE_VENDORING = "1" -- cgit 1.2.3-korg