mirror of
https://github.com/rust-vmm/vhost-device.git
synced 2025-12-27 15:45:44 +00:00
scmi: Provide help for devices
Writing `--device help' on the command line will list all the available devices and their parameters. Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
This commit is contained in:
parent
4014a6366f
commit
73c536df2e
@ -30,6 +30,7 @@ the Examples section below.
|
||||
Can be used multiple times for multiple exposed devices.
|
||||
If no device is specified then no device will be provided to the
|
||||
guest OS but VirtIO SCMI will be still available there.
|
||||
Use `help` as the device ID to list help on all the available devices.
|
||||
|
||||
You can set `RUST_LOG` environment variable to `debug` to get maximum
|
||||
messages on the standard error output.
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
// SPDX-FileCopyrightText: Red Hat, Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use log::debug;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Write;
|
||||
use std::process::exit;
|
||||
|
||||
use crate::{
|
||||
scmi::{
|
||||
@ -15,6 +16,10 @@ use crate::{
|
||||
DeviceProperties,
|
||||
};
|
||||
|
||||
enum ExitCodes {
|
||||
Help = 1,
|
||||
}
|
||||
|
||||
type DeviceSpecification = fn() -> Box<dyn ScmiDevice>;
|
||||
type NameDeviceMapping = HashMap<String, DeviceSpecification>;
|
||||
|
||||
@ -24,6 +29,40 @@ pub fn available_devices() -> NameDeviceMapping {
|
||||
devices
|
||||
}
|
||||
|
||||
fn devices_help() -> String {
|
||||
let mut help = String::new();
|
||||
writeln!(help, "Available devices:").unwrap();
|
||||
for (name, constructor) in available_devices().iter() {
|
||||
let device = constructor();
|
||||
let short_help = device.short_help();
|
||||
let long_help = device.long_help();
|
||||
let parameters_help = device.parameters_help();
|
||||
writeln!(help, "\n- {name}: {short_help}").unwrap();
|
||||
for line in long_help.lines() {
|
||||
writeln!(help, " {line}").unwrap();
|
||||
}
|
||||
if !parameters_help.is_empty() {
|
||||
writeln!(help, " Parameters:").unwrap();
|
||||
for parameter in parameters_help {
|
||||
writeln!(help, " - {parameter}").unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
writeln!(help, "\nDevice specification example:").unwrap();
|
||||
writeln!(
|
||||
help,
|
||||
"--device iio,path=/sys/bus/iio/devices/iio:device0,channel=in_accel"
|
||||
)
|
||||
.unwrap();
|
||||
help
|
||||
}
|
||||
|
||||
pub(crate) fn print_devices_help() {
|
||||
let help = devices_help();
|
||||
println!("{}", help);
|
||||
exit(ExitCodes::Help as i32);
|
||||
}
|
||||
|
||||
// Common sensor infrastructure
|
||||
|
||||
pub struct Sensor {
|
||||
@ -44,6 +83,18 @@ trait SensorT: Send {
|
||||
fn sensor(&self) -> &Sensor;
|
||||
fn sensor_mut(&mut self) -> &mut Sensor;
|
||||
|
||||
fn short_help(&self) -> String {
|
||||
"sensor".to_owned()
|
||||
}
|
||||
|
||||
fn long_help(&self) -> String {
|
||||
"".to_owned()
|
||||
}
|
||||
|
||||
fn parameters_help(&self) -> Vec<String> {
|
||||
vec!["name: an optional name of the sensor, max. 15 characters".to_owned()]
|
||||
}
|
||||
|
||||
fn protocol(&self) -> ProtocolId {
|
||||
SENSOR_PROTOCOL_ID
|
||||
}
|
||||
@ -182,6 +233,18 @@ impl ScmiDevice for SensorDevice {
|
||||
self.0.configure(properties)
|
||||
}
|
||||
|
||||
fn short_help(&self) -> String {
|
||||
self.0.short_help()
|
||||
}
|
||||
|
||||
fn long_help(&self) -> String {
|
||||
self.0.long_help()
|
||||
}
|
||||
|
||||
fn parameters_help(&self) -> Vec<String> {
|
||||
self.0.parameters_help()
|
||||
}
|
||||
|
||||
fn protocol(&self) -> ProtocolId {
|
||||
self.0.protocol()
|
||||
}
|
||||
@ -207,6 +270,14 @@ impl SensorT for FakeSensor {
|
||||
&mut self.sensor
|
||||
}
|
||||
|
||||
fn short_help(&self) -> String {
|
||||
"fake accelerometer".to_owned()
|
||||
}
|
||||
|
||||
fn long_help(&self) -> String {
|
||||
"A simple 3-axes sensor providing fake pre-defined values.".to_owned()
|
||||
}
|
||||
|
||||
fn number_of_axes(&self) -> u32 {
|
||||
3
|
||||
}
|
||||
@ -245,3 +316,25 @@ impl FakeSensor {
|
||||
Box::new(sensor_device)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_help() {
|
||||
let help = devices_help();
|
||||
assert!(
|
||||
help.contains("Available devices:\n"),
|
||||
"global label missing"
|
||||
);
|
||||
assert!(help.contains("fake:"), "sensor name missing");
|
||||
assert!(
|
||||
help.contains("fake accelerometer"),
|
||||
"short description missing"
|
||||
);
|
||||
assert!(help.contains("3-axes sensor"), "long description missing");
|
||||
assert!(help.contains("Parameters:\n"), "parameter label missing");
|
||||
assert!(help.contains("- name:"), "parameter `name' missing");
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,7 +29,11 @@ struct ScmiArgs {
|
||||
#[clap(short, long, help = "vhost-user socket to use")]
|
||||
socket_path: String,
|
||||
// Specification of SCMI devices to create.
|
||||
#[clap(short, long)]
|
||||
#[clap(
|
||||
short,
|
||||
long,
|
||||
help = "Devices to expose (use `help' device for more info)"
|
||||
)]
|
||||
#[arg(num_args(1..))]
|
||||
device: Vec<String>,
|
||||
}
|
||||
|
||||
@ -480,6 +480,9 @@ pub enum ScmiDeviceError {
|
||||
}
|
||||
|
||||
pub trait ScmiDevice: Send {
|
||||
fn short_help(&self) -> String;
|
||||
fn long_help(&self) -> String;
|
||||
fn parameters_help(&self) -> Vec<String>;
|
||||
fn configure(&mut self, properties: &DeviceProperties) -> Result<(), String>;
|
||||
fn protocol(&self) -> ProtocolId;
|
||||
fn handle(
|
||||
|
||||
@ -21,6 +21,7 @@ use vmm_sys_util::epoll::EventSet;
|
||||
use vmm_sys_util::eventfd::{EventFd, EFD_NONBLOCK};
|
||||
|
||||
use crate::devices::available_devices;
|
||||
use crate::devices::print_devices_help;
|
||||
use crate::scmi::ScmiDevice;
|
||||
use crate::scmi::{MessageHeader, ScmiHandler, ScmiRequest};
|
||||
use crate::VuScmiConfig;
|
||||
@ -99,6 +100,9 @@ impl VuScmiBackend {
|
||||
let mut handler = ScmiHandler::new();
|
||||
let device_mapping = available_devices();
|
||||
for (name, properties) in config.devices.iter() {
|
||||
if name == "help" {
|
||||
print_devices_help();
|
||||
}
|
||||
match device_mapping.get(name) {
|
||||
Some(constructor) => {
|
||||
let mut device: Box<dyn ScmiDevice> = constructor();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user