mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-06 10:32:10 +00:00
crosvm: argh-ify usb command
Change-Id: Ifd4f5a252f363277c551c1c2efadeedaacbbc011 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3674005 Commit-Queue: Anton Romanov <romanton@google.com> Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Reviewed-by: Dennis Kempin <denniskempin@google.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
3eef0ed379
commit
72c9c20be8
2 changed files with 86 additions and 78 deletions
|
@ -21,6 +21,7 @@ use std::path::{Path, PathBuf};
|
|||
use std::str::FromStr;
|
||||
|
||||
use argh::FromArgs;
|
||||
use base::debug;
|
||||
use devices::virtio::vhost::user::device;
|
||||
|
||||
use super::sys;
|
||||
|
@ -197,10 +198,13 @@ pub struct GpeCommand {
|
|||
pub socket_path: String,
|
||||
}
|
||||
|
||||
#[generate_catchall_args]
|
||||
#[derive(FromArgs)]
|
||||
#[argh(subcommand, name = "usb")]
|
||||
/// Manage attached virtual USB devices.
|
||||
pub struct UsbCommand {}
|
||||
pub struct UsbCommand {
|
||||
#[argh(subcommand)]
|
||||
pub command: UsbSubCommand,
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
#[argh(subcommand, name = "version")]
|
||||
|
@ -234,6 +238,53 @@ pub enum DevicesSubcommand {
|
|||
Sys(sys::DevicesSubcommand),
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
#[argh(subcommand)]
|
||||
pub enum UsbSubCommand {
|
||||
Attach(UsbAttachCommand),
|
||||
Detach(UsbDetachCommand),
|
||||
List(UsbListCommand),
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
/// Attach usb device
|
||||
#[argh(subcommand, name = "attach")]
|
||||
pub struct UsbAttachCommand {
|
||||
#[argh(
|
||||
positional,
|
||||
arg_name = "BUS_ID:ADDR:BUS_NUM:DEV_NUM",
|
||||
from_str_fn(parse_bus_id_addr)
|
||||
)]
|
||||
pub addr: (u8, u8, u16, u16),
|
||||
#[argh(positional)]
|
||||
/// usb device path
|
||||
pub dev_path: String,
|
||||
#[argh(positional, arg_name = "VM_SOCKET")]
|
||||
/// VM Socket path
|
||||
pub socket_path: String,
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
/// Detach usb device
|
||||
#[argh(subcommand, name = "detach")]
|
||||
pub struct UsbDetachCommand {
|
||||
#[argh(positional, arg_name = "PORT")]
|
||||
/// usb port
|
||||
pub port: u8,
|
||||
#[argh(positional, arg_name = "VM_SOCKET")]
|
||||
/// VM Socket path
|
||||
pub socket_path: String,
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
/// Detach usb device
|
||||
#[argh(subcommand, name = "list")]
|
||||
pub struct UsbListCommand {
|
||||
#[argh(positional, arg_name = "VM_SOCKET")]
|
||||
/// VM Socket path
|
||||
pub socket_path: String,
|
||||
}
|
||||
|
||||
/// Indicates the location and kind of executable kernel for a VM.
|
||||
#[derive(Debug)]
|
||||
pub enum Executable {
|
||||
|
@ -539,6 +590,22 @@ impl Default for JailConfig {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_bus_id_addr(v: &str) -> Result<(u8, u8, u16, u16), String> {
|
||||
debug!("parse_bus_id_addr: {}", v);
|
||||
let mut ids = v.split(':');
|
||||
let errorre = move |item| move |e| format!("{}: {}", item, e);
|
||||
match (ids.next(), ids.next(), ids.next(), ids.next()) {
|
||||
(Some(bus_id), Some(addr), Some(vid), Some(pid)) => {
|
||||
let bus_id = bus_id.parse::<u8>().map_err(errorre("bus_id"))?;
|
||||
let addr = addr.parse::<u8>().map_err(errorre("addr"))?;
|
||||
let vid = u16::from_str_radix(vid, 16).map_err(errorre("vid"))?;
|
||||
let pid = u16::from_str_radix(pid, 16).map_err(errorre("pid"))?;
|
||||
Ok((bus_id, addr, vid, pid))
|
||||
}
|
||||
_ => Err(String::from("BUS_ID:ADDR:BUS_NUM:DEV_NUM")),
|
||||
}
|
||||
}
|
||||
|
||||
/// Aggregate of all configurable options for a running VM.
|
||||
#[remain::sorted]
|
||||
pub struct Config {
|
||||
|
|
93
src/main.rs
93
src/main.rs
|
@ -25,7 +25,7 @@ use arch::{
|
|||
Pstore, VcpuAffinity,
|
||||
};
|
||||
use base::syslog::LogConfig;
|
||||
use base::{debug, error, getpid, info, pagesize, syslog};
|
||||
use base::{error, getpid, info, pagesize, syslog};
|
||||
mod crosvm;
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64", feature = "direct"))]
|
||||
use crosvm::argument::parse_hex_or_decimal;
|
||||
|
@ -64,7 +64,7 @@ use uuid::Uuid;
|
|||
use vm_control::{
|
||||
client::{
|
||||
do_modify_battery, do_usb_attach, do_usb_detach, do_usb_list, handle_request, vms_request,
|
||||
ModifyUsbError, ModifyUsbResult,
|
||||
ModifyUsbResult,
|
||||
},
|
||||
BalloonControlCommand, BatteryType, DiskControlCommand, UsbControlResult, VmRequest,
|
||||
VmResponse,
|
||||
|
@ -3118,88 +3118,29 @@ fn make_rt(cmd: crosvm::MakeRTCommand) -> std::result::Result<(), ()> {
|
|||
vms_request(&VmRequest::MakeRT, socket_path)
|
||||
}
|
||||
|
||||
fn parse_bus_id_addr(v: &str) -> ModifyUsbResult<(u8, u8, u16, u16)> {
|
||||
debug!("parse_bus_id_addr: {}", v);
|
||||
let mut ids = v.split(':');
|
||||
match (ids.next(), ids.next(), ids.next(), ids.next()) {
|
||||
(Some(bus_id), Some(addr), Some(vid), Some(pid)) => {
|
||||
let bus_id = bus_id
|
||||
.parse::<u8>()
|
||||
.map_err(|e| ModifyUsbError::ArgParseInt("bus_id", bus_id.to_owned(), e))?;
|
||||
let addr = addr
|
||||
.parse::<u8>()
|
||||
.map_err(|e| ModifyUsbError::ArgParseInt("addr", addr.to_owned(), e))?;
|
||||
let vid = u16::from_str_radix(vid, 16)
|
||||
.map_err(|e| ModifyUsbError::ArgParseInt("vid", vid.to_owned(), e))?;
|
||||
let pid = u16::from_str_radix(pid, 16)
|
||||
.map_err(|e| ModifyUsbError::ArgParseInt("pid", pid.to_owned(), e))?;
|
||||
Ok((bus_id, addr, vid, pid))
|
||||
}
|
||||
_ => Err(ModifyUsbError::ArgParse(
|
||||
"BUS_ID_ADDR_BUS_NUM_DEV_NUM",
|
||||
v.to_owned(),
|
||||
)),
|
||||
}
|
||||
fn usb_attach(cmd: crosvm::UsbAttachCommand) -> ModifyUsbResult<UsbControlResult> {
|
||||
let (bus, addr, vid, pid) = cmd.addr;
|
||||
let socket_path = Path::new(&cmd.socket_path);
|
||||
let dev_path = Path::new(&cmd.dev_path);
|
||||
|
||||
do_usb_attach(socket_path, bus, addr, vid, pid, dev_path)
|
||||
}
|
||||
|
||||
fn usb_attach(args: Vec<String>) -> ModifyUsbResult<UsbControlResult> {
|
||||
let mut args = args.into_iter();
|
||||
let val = args
|
||||
.next()
|
||||
.ok_or(ModifyUsbError::ArgMissing("BUS_ID_ADDR_BUS_NUM_DEV_NUM"))?;
|
||||
let (bus, addr, vid, pid) = parse_bus_id_addr(&val)?;
|
||||
let dev_path = PathBuf::from(
|
||||
args.next()
|
||||
.ok_or(ModifyUsbError::ArgMissing("usb device path"))?,
|
||||
);
|
||||
|
||||
let socket_path = args
|
||||
.next()
|
||||
.ok_or(ModifyUsbError::ArgMissing("control socket path"))?;
|
||||
let socket_path = Path::new(&socket_path);
|
||||
|
||||
do_usb_attach(socket_path, bus, addr, vid, pid, &dev_path)
|
||||
fn usb_detach(cmd: crosvm::UsbDetachCommand) -> ModifyUsbResult<UsbControlResult> {
|
||||
let socket_path = Path::new(&cmd.socket_path);
|
||||
do_usb_detach(socket_path, cmd.port)
|
||||
}
|
||||
|
||||
fn usb_detach(args: Vec<String>) -> ModifyUsbResult<UsbControlResult> {
|
||||
let mut args = args.into_iter();
|
||||
let port: u8 = args
|
||||
.next()
|
||||
.map_or(Err(ModifyUsbError::ArgMissing("PORT")), |p| {
|
||||
p.parse::<u8>()
|
||||
.map_err(|e| ModifyUsbError::ArgParseInt("PORT", p.to_owned(), e))
|
||||
})?;
|
||||
let socket_path = args
|
||||
.next()
|
||||
.ok_or(ModifyUsbError::ArgMissing("control socket path"))?;
|
||||
let socket_path = Path::new(&socket_path);
|
||||
do_usb_detach(socket_path, port)
|
||||
}
|
||||
|
||||
fn usb_list(args: Vec<String>) -> ModifyUsbResult<UsbControlResult> {
|
||||
let mut args = args.into_iter();
|
||||
let socket_path = args
|
||||
.next()
|
||||
.ok_or(ModifyUsbError::ArgMissing("control socket path"))?;
|
||||
let socket_path = Path::new(&socket_path);
|
||||
fn usb_list(cmd: crosvm::UsbListCommand) -> ModifyUsbResult<UsbControlResult> {
|
||||
let socket_path = Path::new(&cmd.socket_path);
|
||||
do_usb_list(socket_path)
|
||||
}
|
||||
|
||||
fn modify_usb(cmd: crosvm::UsbCommand) -> std::result::Result<(), ()> {
|
||||
let mut args = cmd.args;
|
||||
if args.len() < 2 {
|
||||
print_help("crosvm usb",
|
||||
"[attach BUS_ID:ADDR:VENDOR_ID:PRODUCT_ID [USB_DEVICE_PATH|-] | detach PORT | list] VM_SOCKET...", &[]);
|
||||
return Err(());
|
||||
}
|
||||
|
||||
// This unwrap will not panic because of the above length check.
|
||||
let command = args.remove(0);
|
||||
let result = match command.as_ref() {
|
||||
"attach" => usb_attach(args),
|
||||
"detach" => usb_detach(args),
|
||||
"list" => usb_list(args),
|
||||
other => Err(ModifyUsbError::UnknownCommand(other.to_owned())),
|
||||
let result = match cmd.command {
|
||||
crosvm::UsbSubCommand::Attach(cmd) => usb_attach(cmd),
|
||||
crosvm::UsbSubCommand::Detach(cmd) => usb_detach(cmd),
|
||||
crosvm::UsbSubCommand::List(cmd) => usb_list(cmd),
|
||||
};
|
||||
match result {
|
||||
Ok(response) => {
|
||||
|
|
Loading…
Reference in a new issue