1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use audio_streams::shm_streams::NullShmStreamSource;
use audio_streams::shm_streams::ShmStreamSource;
#[cfg(feature = "audio_cras")]
use base::error;
#[cfg(feature = "audio_cras")]
use libcras::CrasClient;
#[cfg(feature = "audio_cras")]
use libcras::CrasClientType;
#[cfg(feature = "audio_cras")]
use libcras::CrasSocketType;
use serde::Deserialize;
use serde::Serialize;
use vm_memory::GuestMemory;
use crate::pci::ac97::Ac97Dev;
use crate::pci::ac97::Ac97Error;
use crate::pci::ac97::Ac97Parameters;
#[cfg(feature = "audio_cras")]
use crate::pci::pci_device;
use crate::pci::pci_device::Result;
pub(crate) type AudioStreamSource = Box<dyn ShmStreamSource<base::Error>>;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Ac97Backend {
#[cfg(feature = "audio_cras")]
Cras,
}
impl Ac97Dev {
pub(in crate::pci::ac97) fn initialize_backend(
ac97_backend: &Ac97Backend,
#[allow(unused_variables)] mem: GuestMemory,
#[allow(unused_variables)] param: &Ac97Parameters,
) -> Result<Self> {
match *ac97_backend {
#[cfg(feature = "audio_cras")]
Ac97Backend::Cras => Self::create_cras_audio_device(param, mem.clone()).or_else(|e| {
error!(
"Ac97Dev: create_cras_audio_device: {}. Fallback to null audio device",
e
);
Ok(Self::create_null_audio_device(mem))
}),
}
}
#[cfg(feature = "audio_cras")]
fn create_cras_audio_device(params: &Ac97Parameters, mem: GuestMemory) -> Result<Self> {
let mut server = Box::new(
CrasClient::with_type(params.socket_type.unwrap_or(CrasSocketType::Unified))
.map_err(pci_device::Error::CreateCrasClientFailed)?,
);
server.set_client_type(
params
.client_type
.unwrap_or(CrasClientType::CRAS_CLIENT_TYPE_CROSVM),
);
if params.capture {
server.enable_cras_capture();
}
let cras_audio = Self::new(
mem,
crate::pci::ac97::Ac97Backend::System(Ac97Backend::Cras),
server,
);
Ok(cras_audio)
}
pub fn minijail_policy(&self) -> &'static str {
match &self.backend {
crate::pci::ac97::Ac97Backend::System(backend) => match *backend {
#[cfg(feature = "audio_cras")]
Ac97Backend::Cras => "cras_audio_device",
},
crate::pci::ac97::Ac97Backend::NULL => "null_audio_device",
}
}
}
pub(in crate::pci::ac97) fn ac97_backend_from_str(
s: &str,
) -> std::result::Result<crate::pci::ac97::Ac97Backend, Ac97Error> {
match s {
#[cfg(feature = "audio_cras")]
"cras" => Ok(crate::pci::ac97::Ac97Backend::System(Ac97Backend::Cras)),
_ => Err(Ac97Error::InvalidBackend),
}
}
pub(in crate::pci::ac97) fn create_null_server() -> AudioStreamSource {
Box::new(NullShmStreamSource::new())
}
#[cfg(test)]
pub(in crate::pci::ac97) mod tests {
use audio_streams::shm_streams::MockShmStreamSource;
use super::*;
pub(in crate::pci::ac97) fn create_ac97_device(
mem: GuestMemory,
backend: crate::pci::ac97::Ac97Backend,
) -> Ac97Dev {
Ac97Dev::new(mem, backend, Box::new(MockShmStreamSource::new()))
}
}