1 // Copyright 2021 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 use std::fs::OpenOptions;
6 use std::path::Path;
7 use std::path::PathBuf;
8
9 use base::open_file;
10 use remain::sorted;
11 use thiserror::Error;
12
13 #[cfg(feature = "gpu")]
14 pub use crate::gpu::*;
15 pub use crate::sys::handle_request;
16 pub use crate::*;
17
18 #[sorted]
19 #[derive(Error, Debug)]
20 enum ModifyBatError {
21 #[error("{0}")]
22 BatControlErr(BatControlResult),
23 }
24
25 #[sorted]
26 #[derive(Error, Debug)]
27 pub enum ModifyUsbError {
28 #[error("failed to open device {0}: {1}")]
29 FailedToOpenDevice(PathBuf, base::Error),
30 #[error("socket failed")]
31 SocketFailed,
32 #[error("unexpected response: {0}")]
33 UnexpectedResponse(VmResponse),
34 #[error("{0}")]
35 UsbControl(UsbControlResult),
36 }
37
38 pub type ModifyUsbResult<T> = std::result::Result<T, ModifyUsbError>;
39
40 pub type VmsRequestResult = std::result::Result<(), ()>;
41
42 /// Send a `VmRequest` that expects a `VmResponse::Ok` reply.
vms_request<T: AsRef<Path> + std::fmt::Debug>( request: &VmRequest, socket_path: T, ) -> VmsRequestResult43 pub fn vms_request<T: AsRef<Path> + std::fmt::Debug>(
44 request: &VmRequest,
45 socket_path: T,
46 ) -> VmsRequestResult {
47 match handle_request(request, socket_path)? {
48 VmResponse::Ok => Ok(()),
49 r => {
50 println!("unexpected response: {r}");
51 Err(())
52 }
53 }
54 }
55
do_usb_attach<T: AsRef<Path> + std::fmt::Debug>( socket_path: T, dev_path: &Path, ) -> ModifyUsbResult<UsbControlResult>56 pub fn do_usb_attach<T: AsRef<Path> + std::fmt::Debug>(
57 socket_path: T,
58 dev_path: &Path,
59 ) -> ModifyUsbResult<UsbControlResult> {
60 let usb_file = open_file(dev_path, OpenOptions::new().read(true).write(true))
61 .map_err(|e| ModifyUsbError::FailedToOpenDevice(dev_path.into(), e))?;
62
63 let request = VmRequest::UsbCommand(UsbControlCommand::AttachDevice { file: usb_file });
64 let response =
65 handle_request(&request, socket_path).map_err(|_| ModifyUsbError::SocketFailed)?;
66 match response {
67 VmResponse::UsbResponse(usb_resp) => Ok(usb_resp),
68 r => Err(ModifyUsbError::UnexpectedResponse(r)),
69 }
70 }
71
do_usb_detach<T: AsRef<Path> + std::fmt::Debug>( socket_path: T, port: u8, ) -> ModifyUsbResult<UsbControlResult>72 pub fn do_usb_detach<T: AsRef<Path> + std::fmt::Debug>(
73 socket_path: T,
74 port: u8,
75 ) -> ModifyUsbResult<UsbControlResult> {
76 let request = VmRequest::UsbCommand(UsbControlCommand::DetachDevice { port });
77 let response =
78 handle_request(&request, socket_path).map_err(|_| ModifyUsbError::SocketFailed)?;
79 match response {
80 VmResponse::UsbResponse(usb_resp) => Ok(usb_resp),
81 r => Err(ModifyUsbError::UnexpectedResponse(r)),
82 }
83 }
84
do_usb_list<T: AsRef<Path> + std::fmt::Debug>( socket_path: T, ) -> ModifyUsbResult<UsbControlResult>85 pub fn do_usb_list<T: AsRef<Path> + std::fmt::Debug>(
86 socket_path: T,
87 ) -> ModifyUsbResult<UsbControlResult> {
88 let mut ports: [u8; USB_CONTROL_MAX_PORTS] = Default::default();
89 for (index, port) in ports.iter_mut().enumerate() {
90 *port = index as u8
91 }
92 let request = VmRequest::UsbCommand(UsbControlCommand::ListDevice { ports });
93 let response =
94 handle_request(&request, socket_path).map_err(|_| ModifyUsbError::SocketFailed)?;
95 match response {
96 VmResponse::UsbResponse(usb_resp) => Ok(usb_resp),
97 r => Err(ModifyUsbError::UnexpectedResponse(r)),
98 }
99 }
100
101 pub type DoModifyBatteryResult = std::result::Result<(), ()>;
102
do_modify_battery<T: AsRef<Path> + std::fmt::Debug>( socket_path: T, battery_type: &str, property: &str, target: &str, ) -> DoModifyBatteryResult103 pub fn do_modify_battery<T: AsRef<Path> + std::fmt::Debug>(
104 socket_path: T,
105 battery_type: &str,
106 property: &str,
107 target: &str,
108 ) -> DoModifyBatteryResult {
109 let response = match battery_type.parse::<BatteryType>() {
110 Ok(type_) => match BatControlCommand::new(property.to_string(), target.to_string()) {
111 Ok(cmd) => {
112 let request = VmRequest::BatCommand(type_, cmd);
113 Ok(handle_request(&request, socket_path)?)
114 }
115 Err(e) => Err(ModifyBatError::BatControlErr(e)),
116 },
117 Err(e) => Err(ModifyBatError::BatControlErr(e)),
118 };
119
120 match response {
121 Ok(response) => {
122 println!("{}", response);
123 Ok(())
124 }
125 Err(e) => {
126 println!("error {}", e);
127 Err(())
128 }
129 }
130 }
131
do_swap_status<T: AsRef<Path> + std::fmt::Debug>(socket_path: T) -> VmsRequestResult132 pub fn do_swap_status<T: AsRef<Path> + std::fmt::Debug>(socket_path: T) -> VmsRequestResult {
133 let response = handle_request(&VmRequest::Swap(SwapCommand::Status), socket_path)?;
134 match &response {
135 VmResponse::SwapStatus(_) => {
136 println!("{}", response);
137 Ok(())
138 }
139 r => {
140 println!("unexpected response: {r:?}");
141 Err(())
142 }
143 }
144 }
145
146 pub type HandleRequestResult = std::result::Result<VmResponse, ()>;
147