diff --git a/src/api/legacy.rs b/src/api/legacy.rs index 8a160db..552c553 100644 --- a/src/api/legacy.rs +++ b/src/api/legacy.rs @@ -18,7 +18,6 @@ use crate::api::streaming_data_service::StreamingDataService; use crate::app::bmc_application::{BmcApplication, Encoding, UsbConfig}; use crate::app::transfer_action::{TransferType, UpgradeAction, UpgradeType}; use crate::hal::{NodeId, UsbMode, UsbRoute}; -use crate::utils::logging_sink; use actix_multipart::Multipart; use actix_web::guard::{fn_guard, GuardContext}; use actix_web::http::StatusCode; @@ -29,7 +28,6 @@ use std::collections::HashMap; use std::ops::Deref; use std::str::FromStr; use tokio::io::AsyncBufReadExt; -use tokio::sync::mpsc; use tokio_stream::StreamExt; type Query = web::Query>; @@ -160,10 +158,7 @@ fn get_node_info(_bmc: &BmcApplication) -> impl Into { async fn set_node_to_msd(bmc: &BmcApplication, query: Query) -> LegacyResult<()> { let node = get_node_param(&query)?; - - let (tx, rx) = mpsc::channel(64); - logging_sink(rx); - bmc.set_node_in_msd(node, UsbRoute::Bmc, tx) + bmc.set_node_in_msd(node, UsbRoute::Bmc) .await .map(|_| ()) .map_err(Into::into) diff --git a/src/app/bmc_application.rs b/src/app/bmc_application.rs index 1bf41cd..b87a638 100644 --- a/src/app/bmc_application.rs +++ b/src/app/bmc_application.rs @@ -12,9 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. use crate::firmware_update::transport::FwUpdateTransport; -use crate::firmware_update::{ - fw_update_transport, FlashProgress, FlashStatus, SUPPORTED_MSD_DEVICES, -}; +use crate::firmware_update::{fw_update_transport, SUPPORTED_DEVICES}; use crate::hal::power_controller::PowerController; use crate::hal::serial::SerialConnections; use crate::hal::usbboot; @@ -25,12 +23,11 @@ use crate::utils::{string_from_utf16, string_from_utf32}; use anyhow::{ensure, Context}; use log::{debug, info, trace}; use serde::{Deserialize, Serialize}; -use std::ops::Deref; use std::process::Command; use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; -use tokio::sync::mpsc; use tokio::time::sleep; + /// Stores which slots are actually used. This information is used to determine /// for instance, which nodes need to be powered on, when such command is given pub const ACTIVATED_NODES_KEY: &str = "activated_nodes"; @@ -223,47 +220,24 @@ impl BmcApplication { self.power_controller.reset_node(node).await } - pub async fn set_node_in_msd( - &self, - node: NodeId, - router: UsbRoute, - progress_sender: mpsc::Sender, - ) -> anyhow::Result<()> { + pub async fn set_node_in_msd(&self, node: NodeId, router: UsbRoute) -> anyhow::Result<()> { // The SUPPORTED_MSD_DEVICES list contains vid_pids of USB drivers we know will load the // storage of a node as a MSD device. - self.configure_node_for_fwupgrade( - node, - router, - progress_sender, - SUPPORTED_MSD_DEVICES.deref(), - ) - .await - .map(|_| ()) + self.configure_node_for_fwupgrade(node, router, SUPPORTED_DEVICES.keys().into_iter()) + .await + .map(|_| ()) } pub async fn configure_node_for_fwupgrade<'a, I>( &self, node: NodeId, router: UsbRoute, - progress_sender: mpsc::Sender, any_of: I, ) -> anyhow::Result> where I: IntoIterator, { - let mut progress_state = FlashProgress { - message: String::new(), - status: FlashStatus::Idle, - }; - - progress_state.message = format!("Powering off node {:?}...", node); - progress_state.status = FlashStatus::Progress { - read_percent: 0, - est_minutes: u64::MAX, - est_seconds: u64::MAX, - }; - progress_sender.send(progress_state.clone()).await?; - + log::info!("Powering off node {:?}...", node); self.activate_slot(!node.to_bitfield(), node.to_bitfield()) .await?; self.pin_controller @@ -278,29 +252,17 @@ impl BmcApplication { self.usb_boot(node, true).await?; self.configure_usb(config).await?; - progress_state.message = String::from("Prerequisite settings toggled, powering on..."); - progress_sender.send(progress_state.clone()).await?; - + log::info!("Prerequisite settings toggled, powering on..."); self.activate_slot(node.to_bitfield(), node.to_bitfield()) .await?; tokio::time::sleep(Duration::from_secs(2)).await; - progress_state.message = String::from("Checking for presence of a USB device..."); - progress_sender.send(progress_state.clone()).await?; + log::info!("Checking for presence of a USB device..."); let matches = usbboot::get_usb_devices(any_of)?; - let usb_device = usbboot::extract_one_device(&matches).map_err(|e| { - progress_sender - .try_send(FlashProgress { - status: FlashStatus::Error(e), - message: String::new(), - }) - .unwrap(); - e - })?; - - fw_update_transport(usb_device, progress_sender)? + let usb_device = usbboot::extract_one_device(&matches)?; + fw_update_transport(usb_device)? .await .context("USB driver init error") } diff --git a/src/app/firmware_runner.rs b/src/app/firmware_runner.rs index 355fa16..854ac8c 100644 --- a/src/app/firmware_runner.rs +++ b/src/app/firmware_runner.rs @@ -13,9 +13,10 @@ // limitations under the License. use super::bmc_application::UsbConfig; use crate::app::bmc_application::BmcApplication; -use crate::utils::{logging_sink, reader_with_crc64, WriteWatcher}; +use crate::firmware_update::FwUpdateError; +use crate::utils::{reader_with_crc64, WriteWatcher}; use crate::{ - firmware_update::{FlashProgress, FlashingError, SUPPORTED_DEVICES}, + firmware_update::SUPPORTED_DEVICES, hal::{NodeId, UsbRoute}, }; use anyhow::bail; @@ -30,10 +31,11 @@ use std::{sync::Arc, time::Duration}; use tokio::fs::OpenOptions; use tokio::io::sink; use tokio::io::AsyncReadExt; -use tokio::sync::{mpsc, watch}; +use tokio::io::AsyncSeekExt; +use tokio::sync::watch; use tokio::{ fs, - io::{self, AsyncRead, AsyncSeekExt, AsyncWrite, AsyncWriteExt}, + io::{self, AsyncRead, AsyncWrite, AsyncWriteExt}, time::sleep, }; use tokio_util::sync::CancellationToken; @@ -49,7 +51,6 @@ pub struct FirmwareRunner { size: u64, cancel: CancellationToken, written_sender: watch::Sender, - progress_sender: mpsc::Sender, } impl FirmwareRunner { @@ -60,26 +61,18 @@ impl FirmwareRunner { cancel: CancellationToken, written_sender: watch::Sender, ) -> Self { - let (sender, receiver) = mpsc::channel(16); - logging_sink(receiver); Self { reader, file_name, size, cancel, written_sender, - progress_sender: sender, } } pub async fn flash_node(self, bmc: Arc, node: NodeId) -> anyhow::Result<()> { let mut device = bmc - .configure_node_for_fwupgrade( - node, - UsbRoute::Bmc, - self.progress_sender.clone(), - SUPPORTED_DEVICES.keys(), - ) + .configure_node_for_fwupgrade(node, UsbRoute::Bmc, SUPPORTED_DEVICES.keys()) .await?; let write_watcher = WriteWatcher::new(&mut device, self.written_sender); @@ -105,7 +98,7 @@ impl FirmwareRunner { dev_checksum ); - bail!(FlashingError::ChecksumMismatch) + bail!(FwUpdateError::ChecksumMismatch) } log::info!("Flashing successful, restarting device..."); diff --git a/src/firmware_update/mod.rs b/src/firmware_update/mod.rs index 0befed1..0750d10 100644 --- a/src/firmware_update/mod.rs +++ b/src/firmware_update/mod.rs @@ -15,137 +15,70 @@ mod rockusb_fwudate; use self::rockusb_fwudate::new_rockusb_transport; mod rpi_fwupdate; use rpi_fwupdate::new_rpi_transport; -use serde::Serialize; +use thiserror::Error; pub mod transport; use self::transport::FwUpdateTransport; use futures::future::BoxFuture; use once_cell::sync::Lazy; use rusb::GlobalContext; -use std::{ - collections::HashMap, - fmt::{self, Display}, -}; -use tokio::sync::mpsc::Sender; - -#[allow(clippy::vec_init_then_push)] -pub static SUPPORTED_MSD_DEVICES: Lazy> = Lazy::new(|| { - let mut supported = Vec::<(u16, u16)>::new(); - supported.push(rpi_fwupdate::VID_PID); - supported -}); +use std::collections::HashMap; pub static SUPPORTED_DEVICES: Lazy> = Lazy::new(|| { let mut creators = HashMap::<(u16, u16), FactoryItemCreator>::new(); creators.insert( rpi_fwupdate::VID_PID, - Box::new(|_, logging| { - Box::pin(async move { new_rpi_transport(&logging).await.map(Into::into) }) - }), + Box::new(|_| Box::pin(async move { new_rpi_transport().await.map(Into::into) })), ); creators.insert( rockusb_fwudate::RK3588_VID_PID, - Box::new(|device, logging| { + Box::new(|device| { let clone = device.clone(); - Box::pin(async move { new_rockusb_transport(clone, &logging).await.map(Into::into) }) + Box::pin(async move { new_rockusb_transport(clone).await.map(Into::into) }) }), ); creators }); -pub type FactoryItem = BoxFuture<'static, Result, FlashingError>>; +pub type FactoryItem = BoxFuture<'static, Result, FwUpdateError>>; pub type FactoryItemCreator = - Box, Sender) -> FactoryItem + Send + Sync>; + Box) -> FactoryItem + Send + Sync>; pub fn fw_update_transport( device: &rusb::Device, - logging: Sender, -) -> anyhow::Result { +) -> Result { let descriptor = device.device_descriptor()?; let vid_pid = (descriptor.vendor_id(), descriptor.product_id()); SUPPORTED_DEVICES .get(&vid_pid) - .map(|creator| creator(device, logging)) - .ok_or(anyhow::anyhow!("no driver available for {:?}", device)) + .map(|creator| creator(device)) + .ok_or(FwUpdateError::NoDriver(device.clone())) } -#[derive(Serialize, Debug, Clone, Copy)] -pub enum FlashingError { - DeviceNotFound, - GpioError, - UsbError, - IoError, +#[derive(Error, Debug)] +pub enum FwUpdateError { + #[error("Device {0:#06x}:{1:#06x} not found")] + DeviceNotFound(u16, u16), + #[error("No supported devices found")] + NoDevices, + #[error("Several supported devices found: found {0:?}, expected 1")] + MultipleDevicesFound(usize), + #[error("rusb error")] + RusbError(#[from] rusb::Error), + #[error("IO error")] + IoError(#[from] std::io::Error), + #[error("Error loading as USB MSD: {0}")] + InternalError(String), + #[error("integrity check of written image failed")] ChecksumMismatch, + #[error("no firmware update driver available for {0:?}")] + NoDriver(rusb::Device), } -impl fmt::Display for FlashingError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - FlashingError::DeviceNotFound => write!(f, "Device not found"), - FlashingError::GpioError => write!(f, "Error toggling GPIO lines"), - FlashingError::UsbError => write!(f, "Error enumerating USB devices"), - FlashingError::IoError => write!(f, "File IO error"), - FlashingError::ChecksumMismatch => { - write!(f, "Failed to verify image after writing to the node") - } - } - } -} - -impl std::error::Error for FlashingError {} - -pub trait FlashingErrorExt { - fn map_err_into_logged_usb(self, logging: &Sender) -> Result; - fn map_err_into_logged_io(self, logging: &Sender) -> Result; -} - -impl FlashingErrorExt for Result { - fn map_err_into_logged_usb(self, logging: &Sender) -> Result { - self.map_err(|e| { - logging - .try_send(FlashProgress { - status: FlashStatus::Error(FlashingError::UsbError), - message: format!("{}", e), - }) - .expect("logging channel to be open"); - FlashingError::UsbError - }) - } - fn map_err_into_logged_io(self, logging: &Sender) -> Result { - self.map_err(|e| { - logging - .try_send(FlashProgress { - status: FlashStatus::Error(FlashingError::IoError), - message: format!("{}", e), - }) - .expect("logging channel to be open"); - FlashingError::IoError - }) - } -} - -#[derive(Debug, Clone, Copy)] -pub enum FlashStatus { - Idle, - Setup, - Progress { - read_percent: usize, - est_minutes: u64, - est_seconds: u64, - }, - Error(FlashingError), -} - -#[derive(Debug, Clone)] -pub struct FlashProgress { - pub status: FlashStatus, - pub message: String, -} - -impl Display for FlashProgress { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.message) +impl FwUpdateError { + pub fn internal_error(error: E) -> FwUpdateError { + FwUpdateError::InternalError(error.to_string()) } } diff --git a/src/firmware_update/rockusb_fwudate.rs b/src/firmware_update/rockusb_fwudate.rs index d650cfe..e8feb78 100644 --- a/src/firmware_update/rockusb_fwudate.rs +++ b/src/firmware_update/rockusb_fwudate.rs @@ -11,88 +11,69 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -use super::transport::{StdFwUpdateTransport, StdTransportWrapper}; -use super::{FlashProgress, FlashingError, FlashingErrorExt}; -use crate::firmware_update::FlashStatus; +use super::FwUpdateError; use crate::hal::usbboot; -use anyhow::Context; -use log::info; +use log::{debug, info}; use rockfile::boot::{ RkBootEntry, RkBootEntryBytes, RkBootHeader, RkBootHeaderBytes, RkBootHeaderEntry, }; -use rockusb::libusb::{Transport, TransportIO}; -use rusb::DeviceDescriptor; +use rockusb::libusb::Transport; use rusb::GlobalContext; use std::{mem::size_of, ops::Range, time::Duration}; -use tokio::sync::mpsc::Sender; +use tokio::fs::{File, OpenOptions}; const SPL_LOADER_RK3588: &[u8] = include_bytes!("./rk3588_spl_loader_v1.08.111.bin"); - pub const RK3588_VID_PID: (u16, u16) = (0x2207, 0x350b); + pub async fn new_rockusb_transport( device: rusb::Device, - logging: &Sender, -) -> Result>, FlashingError> { - let mut transport = Transport::from_usb_device(device.open().map_err_into_logged_usb(logging)?) - .map_err(|_| FlashingError::UsbError)?; - - if BootMode::Maskrom - == device - .device_descriptor() - .map_err_into_logged_usb(logging)? - .into() - { +) -> Result { + if requires_usb_plug(&device)? { info!("Maskrom mode detected. loading usb-plug.."); - transport = download_boot(&mut transport, logging).await?; - logging - .try_send(FlashProgress { - status: FlashStatus::Setup, - message: format!( - "Chip Info bytes: {:0x?}", - transport - .chip_info() - .map_err_into_logged_usb(logging)? - .inner() - ), - }) - .map_err(|_| FlashingError::IoError)?; + let mut transport = + Transport::from_usb_device(device.open()?).map_err(FwUpdateError::internal_error)?; + transport = download_boot(&mut transport).await?; + debug!( + "Chip Info bytes: {:0x?}", + transport + .chip_info() + .map_err(FwUpdateError::internal_error)? + ); } - Ok(StdTransportWrapper::new( - transport.into_io().map_err_into_logged_io(logging)?, - )) + let file = OpenOptions::new() + .read(true) + .write(true) + .open("todo") + .await?; + Ok(file) } -impl StdFwUpdateTransport for TransportIO {} - -async fn download_boot( - transport: &mut Transport, - logging: &Sender, -) -> Result { - let boot_entries = parse_boot_entries(SPL_LOADER_RK3588).map_err_into_logged_io(logging)?; - load_boot_entries(transport, boot_entries) - .await - .map_err_into_logged_io(logging)?; +async fn download_boot(transport: &mut Transport) -> Result { + let boot_entries = parse_boot_entries(SPL_LOADER_RK3588)?; + load_boot_entries(transport, boot_entries).await?; // Rockchip will reconnect to USB, back off a bit tokio::time::sleep(Duration::from_secs(1)).await; - let devices = usbboot::get_usb_devices([&RK3588_VID_PID]).map_err_into_logged_usb(logging)?; + let devices = usbboot::get_usb_devices([&RK3588_VID_PID])?; log::debug!("re-enumerated usb devices={:?}", devices); assert!(devices.len() == 1); - Transport::from_usb_device(devices[0].open().map_err_into_logged_usb(logging)?) - .map_err_into_logged_usb(logging) + Transport::from_usb_device(devices[0].open()?).map_err(FwUpdateError::internal_error) } fn parse_boot_entries( raw_boot_bytes: &'static [u8], -) -> anyhow::Result> { - let boot_header_raw = raw_boot_bytes[0..size_of::()].try_into()?; - let boot_header = - RkBootHeader::from_bytes(boot_header_raw).context("Boot header loader corrupt")?; - - let entry_471 = parse_boot_header_entry(0x471, raw_boot_bytes, boot_header.entry_471)?; - let entry_472 = parse_boot_header_entry(0x472, raw_boot_bytes, boot_header.entry_472)?; +) -> Result, FwUpdateError> { + let boot_header_raw = raw_boot_bytes[0..size_of::()] + .try_into() + .expect("enough bytes to read boot header"); + let boot_header = RkBootHeader::from_bytes(boot_header_raw).ok_or( + FwUpdateError::InternalError("Boot header loader corrupt".to_string()), + )?; + + let entry_471 = parse_boot_header_entry(0x471, raw_boot_bytes, boot_header.entry_471); + let entry_472 = parse_boot_header_entry(0x472, raw_boot_bytes, boot_header.entry_472); Ok(entry_471.chain(entry_472)) } @@ -100,11 +81,11 @@ fn parse_boot_header_entry( entry_type: u16, blob: &[u8], header: RkBootHeaderEntry, -) -> anyhow::Result> { +) -> impl Iterator { let mut results = Vec::new(); let mut range = header.offset..header.offset + header.size as u32; for _ in 0..header.count as usize { - let boot_entry = parse_boot_entry(blob, &range)?; + let boot_entry = parse_boot_entry(blob, &range); let name = String::from_utf16(boot_entry.name.as_slice()).unwrap_or_default(); log::debug!( "Found boot entry [{:x}] {} {} KiB", @@ -127,23 +108,27 @@ fn parse_boot_header_entry( range.end += header.size as u32; } - Ok(results.into_iter()) + results.into_iter() } -fn parse_boot_entry(blob: &[u8], range: &Range) -> anyhow::Result { +fn parse_boot_entry(blob: &[u8], range: &Range) -> RkBootEntry { let boot_entry_size = size_of::(); let narrowed_range = range.start as usize..range.start as usize + boot_entry_size; - let narrowed_slice: RkBootEntryBytes = blob[narrowed_range].try_into()?; - Ok(RkBootEntry::from_bytes(&narrowed_slice)) + let narrowed_slice: RkBootEntryBytes = blob[narrowed_range] + .try_into() + .expect("valid range inside blob"); + RkBootEntry::from_bytes(&narrowed_slice) } async fn load_boot_entries( transport: &mut Transport, iterator: impl Iterator, -) -> anyhow::Result<()> { +) -> Result<(), FwUpdateError> { let mut size = 0; for (area, delay, data) in iterator { - transport.write_maskrom_area(area, data)?; + transport + .write_maskrom_area(area, data) + .map_err(FwUpdateError::internal_error)?; tokio::time::sleep(Duration::from_millis(delay.into())).await; size += data.len(); } @@ -151,18 +136,25 @@ async fn load_boot_entries( Ok(()) } -#[derive(Debug, PartialEq, Eq, Copy, Clone)] -pub enum BootMode { - Maskrom = 0, - Loader = 1, -} - -impl From for BootMode { - fn from(dd: DeviceDescriptor) -> BootMode { - match dd.usb_version().sub_minor() & 0x1 { - 0 => BootMode::Maskrom, - 1 => BootMode::Loader, - _ => unreachable!(), - } - } +/// Detecting maskrom is tricky, because the USB descriptor used by the maskrom +/// is extremely similar to the one used by Rockchip's "usbplug" stub. The only +/// difference is that the maskrom descriptor has no device strings, while the +/// "usbplug" stub (and U-Boot bootloaders in Rockusb mode) populate at least +/// one of them. +fn requires_usb_plug(device: &rusb::Device) -> rusb::Result { + let handle = device.open()?; + let device = handle.device().device_descriptor()?; + let timeout = Duration::from_secs(1); + let language = handle.read_languages(timeout)?[0]; + + let result = handle + .read_manufacturer_string(language, &device, timeout)? + .is_empty() + && handle + .read_product_string(language, &device, timeout)? + .is_empty() + && handle + .read_serial_number_string(language, &device, timeout)? + .is_empty(); + Ok(result) } diff --git a/src/firmware_update/rpi_fwupdate.rs b/src/firmware_update/rpi_fwupdate.rs index 1449f50..2326549 100644 --- a/src/firmware_update/rpi_fwupdate.rs +++ b/src/firmware_update/rpi_fwupdate.rs @@ -11,71 +11,46 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +use crate::firmware_update::FwUpdateError; use std::{path::PathBuf, time::Duration}; -use tokio::{fs::File, sync::mpsc::Sender, time::sleep}; - -use super::{FlashProgress, FlashStatus, FlashingError}; +use tokio::{fs::File, time::sleep}; pub const VID_PID: (u16, u16) = (0x0a5c, 0x2711); -pub async fn new_rpi_transport(logging: &Sender) -> Result { +pub async fn new_rpi_transport() -> Result { let options = rustpiboot::Options { delay: 500 * 1000, ..Default::default() }; - let _ = logging - .send(FlashProgress { - status: FlashStatus::Setup, - message: "Rebooting as a USB mass storage device...".to_string(), - }) - .await; + log::info!("Rebooting as a USB mass storage device..."); rustpiboot::boot(options).map_err(|err| { - logging - .try_send(FlashProgress { - status: FlashStatus::Error(FlashingError::IoError), - message: format!("Failed to reboot {:?} as USB MSD: {:?}", VID_PID, err), - }) - .unwrap(); - FlashingError::UsbError + FwUpdateError::internal_error(format!( + "Failed to reboot {:?} as USB MSD: {:?}", + VID_PID, err + )) })?; sleep(Duration::from_secs(3)).await; - let _ = logging - .send(FlashProgress { - status: FlashStatus::Setup, - message: "Checking for presence of a device file...".to_string(), - }) - .await; - + log::info!("Checking for presence of a device file..."); let device_path = get_device_path(["RPi-MSD-"]).await?; let msd_device = tokio::fs::OpenOptions::new() .write(true) .read(true) .open(&device_path) - .await - .map_err(|e| { - logging - .try_send(FlashProgress { - status: FlashStatus::Error(FlashingError::DeviceNotFound), - message: format!("cannot open {:?} : {:?}", device_path, e), - }) - .unwrap(); - FlashingError::DeviceNotFound - })?; + .await?; Ok(msd_device) } async fn get_device_path>( allowed_vendors: I, -) -> Result { +) -> Result { let mut contents = tokio::fs::read_dir("/dev/disk/by-id") .await .map_err(|err| { - log::error!("Failed to list devices: {}", err); - FlashingError::IoError + std::io::Error::new(err.kind(), format!("Failed to list devices: {}", err)) })?; let target_prefixes = allowed_vendors @@ -86,8 +61,10 @@ async fn get_device_path>( let mut matching_devices = vec![]; while let Some(entry) = contents.next_entry().await.map_err(|err| { - log::warn!("Intermittent IO error while listing devices: {}", err); - FlashingError::IoError + std::io::Error::new( + err.kind(), + format!("Intermittent IO error while listing devices: {}", err), + ) })? { let Ok(file_name) = entry.file_name().into_string() else { continue; @@ -113,23 +90,15 @@ async fn get_device_path>( let symlink = match unique_root_devices[..] { [] => { - log::error!("No supported devices found"); - return Err(FlashingError::DeviceNotFound); + return Err(FwUpdateError::NoDevices); } [device] => device.clone(), _ => { - log::error!( - "Several supported devices found: found {}, expected 1", - unique_root_devices.len() - ); - return Err(FlashingError::GpioError); + return Err(FwUpdateError::MultipleDevicesFound( + unique_root_devices.len(), + )); } }; - tokio::fs::canonicalize(format!("/dev/disk/by-id/{}", symlink)) - .await - .map_err(|err| { - log::error!("Failed to read link: {}", err); - FlashingError::IoError - }) + Ok(tokio::fs::canonicalize(format!("/dev/disk/by-id/{}", symlink)).await?) } diff --git a/src/firmware_update/transport.rs b/src/firmware_update/transport.rs index 6fb2678..392a9e0 100644 --- a/src/firmware_update/transport.rs +++ b/src/firmware_update/transport.rs @@ -50,6 +50,7 @@ pub struct StdTransportWrapper { } impl StdTransportWrapper { + #[allow(unused)] pub fn new(object: T) -> Self { Self { transport: object, diff --git a/src/hal/usbboot.rs b/src/hal/usbboot.rs index b23d00a..968314a 100644 --- a/src/hal/usbboot.rs +++ b/src/hal/usbboot.rs @@ -11,19 +11,16 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -use crate::firmware_update::FlashingError; use anyhow::{Context, Result}; use rusb::{Device, GlobalContext, UsbContext}; use std::time::Duration; +use crate::firmware_update::FwUpdateError; + pub(crate) fn get_usb_devices<'a, I: IntoIterator>( filter: I, -) -> std::result::Result>, FlashingError> { - let all_devices = rusb::DeviceList::new().map_err(|err| { - log::error!("failed to get USB device list: {}", err); - FlashingError::UsbError - })?; - +) -> std::result::Result>, FwUpdateError> { + let all_devices = rusb::DeviceList::new()?; let filter = filter.into_iter().collect::>(); let devices = all_devices .iter() @@ -48,16 +45,10 @@ fn map_to_serial(dev: &rusb::Device) -> anyhow::Result .context("error reading serial") } -pub(crate) fn extract_one_device(devices: &[T]) -> Result<&T, FlashingError> { +pub(crate) fn extract_one_device(devices: &[T]) -> Result<&T, FwUpdateError> { match devices.len() { 1 => Ok(devices.first().unwrap()), - 0 => { - log::error!("No supported devices found"); - Err(FlashingError::DeviceNotFound) - } - n => { - log::error!("Several supported devices found: found {}, expected 1", n); - Err(FlashingError::GpioError) - } + 0 => Err(FwUpdateError::NoDevices), + n => Err(FwUpdateError::MultipleDevicesFound(n)), } } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 6574de2..1a81e85 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -12,27 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. mod event_listener; +mod io; pub mod ring_buf; - -use std::fmt::Display; - #[doc(inline)] pub use event_listener::*; -mod io; pub use io::*; -use tokio::sync::mpsc::Receiver; - -// for now we print the status updates to console. In the future we would like to pass -// this back to the clients. -pub fn logging_sink( - mut receiver: Receiver, -) -> tokio::task::JoinHandle<()> { - tokio::spawn(async move { - while let Some(msg) = receiver.recv().await { - log::info!("{}", msg); - } - }) -} pub fn string_from_utf16(bytes: &[u8], little_endian: bool) -> String { let u16s = bytes.chunks_exact(2).map(|pair| {