From 72c9c20be87a640443b9b6647aa9aecf7abd81b2 Mon Sep 17 00:00:00 2001 From: Anton Romanov Date: Fri, 27 May 2022 21:37:45 +0000 Subject: [PATCH] crosvm: argh-ify usb command Change-Id: Ifd4f5a252f363277c551c1c2efadeedaacbbc011 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3674005 Commit-Queue: Anton Romanov Reviewed-by: Daniel Verkamp Reviewed-by: Dennis Kempin Tested-by: kokoro --- src/crosvm.rs | 71 +++++++++++++++++++++++++++++++++++++-- src/main.rs | 93 ++++++++++----------------------------------------- 2 files changed, 86 insertions(+), 78 deletions(-) diff --git a/src/crosvm.rs b/src/crosvm.rs index ace912d419..674149c02f 100644 --- a/src/crosvm.rs +++ b/src/crosvm.rs @@ -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::().map_err(errorre("bus_id"))?; + let addr = addr.parse::().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 { diff --git a/src/main.rs b/src/main.rs index 81cf3054ca..b9e4b65172 100644 --- a/src/main.rs +++ b/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::() - .map_err(|e| ModifyUsbError::ArgParseInt("bus_id", bus_id.to_owned(), e))?; - let addr = addr - .parse::() - .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 { + 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) -> ModifyUsbResult { - 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 { + let socket_path = Path::new(&cmd.socket_path); + do_usb_detach(socket_path, cmd.port) } -fn usb_detach(args: Vec) -> ModifyUsbResult { - let mut args = args.into_iter(); - let port: u8 = args - .next() - .map_or(Err(ModifyUsbError::ArgMissing("PORT")), |p| { - p.parse::() - .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) -> ModifyUsbResult { - 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 { + 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) => {