mirror of
https://github.com/rust-vmm/vhost-device.git
synced 2026-01-15 05:10:09 +00:00
sound: code refactoring
This commit is contained in:
parent
8d3ebf35e1
commit
b81c55fbe2
@ -1,16 +1,10 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
|
||||
|
||||
mod vhu_sound;
|
||||
|
||||
use std::{convert::TryFrom, sync::Arc};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use clap::Parser;
|
||||
use log::{info, warn};
|
||||
use vhost::{vhost_user, vhost_user::Listener};
|
||||
use vhost_user_backend::VhostUserDaemon;
|
||||
use vm_memory::{GuestMemoryAtomic, GuestMemoryMmap};
|
||||
|
||||
use crate::vhu_sound::{Error, Result, SoundConfig, VhostUserSoundBackend};
|
||||
use vhost_user_sound::{start_backend_server, Error, Result, SoundConfig};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(version, about, long_about = None)]
|
||||
@ -30,45 +24,14 @@ impl TryFrom<SoundArgs> for SoundConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// This is the public API through which an external program starts the
|
||||
/// vhost-user-sound backend server.
|
||||
pub(crate) fn start_backend_server(config: SoundConfig) {
|
||||
loop {
|
||||
let backend = Arc::new(VhostUserSoundBackend::new(config.clone()).unwrap());
|
||||
|
||||
let listener = Listener::new(config.get_socket_path(), true).unwrap();
|
||||
|
||||
let mut daemon = VhostUserDaemon::new(
|
||||
String::from("vhost-user-sound"),
|
||||
backend.clone(),
|
||||
GuestMemoryAtomic::new(GuestMemoryMmap::new()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
daemon.start(listener).unwrap();
|
||||
|
||||
match daemon.wait() {
|
||||
Ok(()) => {
|
||||
info!("Stopping cleanly");
|
||||
}
|
||||
Err(vhost_user_backend::Error::HandleRequest(vhost_user::Error::PartialMessage)) => {
|
||||
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.
|
||||
backend.exit_event.write(1).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
|
||||
let config = SoundConfig::try_from(SoundArgs::parse()).unwrap();
|
||||
start_backend_server(config);
|
||||
|
||||
loop {
|
||||
start_backend_server(config.clone());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -1,100 +1,21 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
|
||||
|
||||
use std::{
|
||||
io::{self, Result as IoResult},
|
||||
sync::RwLock,
|
||||
u16, u32, u64, u8,
|
||||
};
|
||||
use thiserror::Error as ThisError;
|
||||
use crate::virtio_sound::*;
|
||||
use crate::{Error, Result, SoundConfig};
|
||||
|
||||
use std::{io::Result as IoResult, sync::RwLock, u16, u32, u64, u8};
|
||||
use vhost::vhost_user::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};
|
||||
use vhost_user_backend::{VhostUserBackend, VringRwLock};
|
||||
use virtio_bindings::bindings::{
|
||||
virtio_config::VIRTIO_F_NOTIFY_ON_EMPTY, virtio_config::VIRTIO_F_VERSION_1,
|
||||
virtio_ring::VIRTIO_RING_F_EVENT_IDX, virtio_ring::VIRTIO_RING_F_INDIRECT_DESC,
|
||||
};
|
||||
use vm_memory::{ByteValued, GuestMemoryAtomic, GuestMemoryMmap, Le32};
|
||||
use vm_memory::{ByteValued, GuestMemoryAtomic, GuestMemoryMmap};
|
||||
use vmm_sys_util::{
|
||||
epoll::EventSet,
|
||||
eventfd::{EventFd, EFD_NONBLOCK},
|
||||
};
|
||||
|
||||
const CONTROL_QUEUE_IDX: u16 = 0;
|
||||
const EVENT_QUEUE_IDX: u16 = 1;
|
||||
const TX_QUEUE_IDX: u16 = 2;
|
||||
const RX_QUEUE_IDX: u16 = 3;
|
||||
const NUM_QUEUES: u16 = 4;
|
||||
|
||||
pub(crate) type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// Custom error types
|
||||
#[derive(Debug, ThisError)]
|
||||
pub(crate) enum Error {
|
||||
#[error("Failed to handle event other than EPOLLIN event")]
|
||||
HandleEventNotEpollIn,
|
||||
#[error("Failed to handle unknown event")]
|
||||
HandleUnknownEvent,
|
||||
#[error("Failed to create a new EventFd")]
|
||||
EventFdCreate(std::io::Error),
|
||||
}
|
||||
|
||||
impl std::convert::From<Error> for std::io::Error {
|
||||
fn from(e: Error) -> Self {
|
||||
std::io::Error::new(io::ErrorKind::Other, e)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// This structure is the public API through which an external program
|
||||
/// is allowed to configure the backend.
|
||||
pub(crate) struct SoundConfig {
|
||||
/// vhost-user Unix domain socket
|
||||
socket: String,
|
||||
multi_thread: bool,
|
||||
}
|
||||
|
||||
impl SoundConfig {
|
||||
/// Create a new instance of the SoundConfig struct, containing the
|
||||
/// parameters to be fed into the sound-backend server.
|
||||
pub fn new(socket: String, multi_thread: bool) -> Self {
|
||||
Self {
|
||||
socket,
|
||||
multi_thread,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the path of the unix domain socket which is listening to
|
||||
/// requests from the guest.
|
||||
pub fn get_socket_path(&self) -> String {
|
||||
String::from(&self.socket)
|
||||
}
|
||||
}
|
||||
|
||||
/// Virtio Sound Configuration
|
||||
#[derive(Copy, Clone, Debug, Default, PartialEq)]
|
||||
#[repr(C)]
|
||||
struct VirtioSoundConfig {
|
||||
/// total number of all available jacks
|
||||
jacks: Le32,
|
||||
/// total number of all available PCM streams
|
||||
streams: Le32,
|
||||
/// total number of all available channel maps
|
||||
chmpas: Le32,
|
||||
}
|
||||
// SAFETY: The layout of the structure is fixed and can be initialized by
|
||||
// reading its content from byte array.
|
||||
unsafe impl ByteValued for VirtioSoundConfig {}
|
||||
|
||||
/// Virtio Sound Request / Response common header
|
||||
#[derive(Copy, Clone, Debug, Default, PartialEq)]
|
||||
#[repr(C)]
|
||||
struct VirtioSoundHeader {
|
||||
/// request type / response status
|
||||
code: Le32,
|
||||
}
|
||||
// SAFETY: The layout of the structure is fixed and can be initialized by
|
||||
// reading its content from byte array.
|
||||
unsafe impl ByteValued for VirtioSoundHeader {}
|
||||
|
||||
struct VhostUserSoundThread {
|
||||
mem: Option<GuestMemoryAtomic<GuestMemoryMmap>>,
|
||||
event_idx: bool,
|
||||
@ -161,10 +82,10 @@ impl VhostUserSoundThread {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct VhostUserSoundBackend {
|
||||
pub struct VhostUserSoundBackend {
|
||||
threads: Vec<RwLock<VhostUserSoundThread>>,
|
||||
virtio_cfg: VirtioSoundConfig,
|
||||
pub(crate) exit_event: EventFd,
|
||||
exit_event: EventFd,
|
||||
}
|
||||
|
||||
impl VhostUserSoundBackend {
|
||||
@ -197,6 +118,10 @@ impl VhostUserSoundBackend {
|
||||
exit_event: EventFd::new(EFD_NONBLOCK).map_err(Error::EventFdCreate)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn send_exit_event(&self) {
|
||||
self.exit_event.write(1).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl VhostUserBackend<VringRwLock, ()> for VhostUserSoundBackend {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user