From f39e0425a67277556db1c55547574b4205ed03e9 Mon Sep 17 00:00:00 2001 From: Brian Cully Date: Sun, 28 Jul 2019 10:22:33 -0400 Subject: Use TryFrom where possible, instead of panicking. --- usbh/src/lib.rs | 2 +- usbh/src/pipe.rs | 12 ++++-- usbh/src/usbproto.rs | 111 ++++++++++++++++++++++++--------------------------- 3 files changed, 62 insertions(+), 63 deletions(-) diff --git a/usbh/src/lib.rs b/usbh/src/lib.rs index c4e2426..4bad707 100755 --- a/usbh/src/lib.rs +++ b/usbh/src/lib.rs @@ -374,7 +374,7 @@ where match self.devices.next(self.millis) { // TODO: new error for being out of devices. - None => Err(PipeErr::Other), + None => Err(PipeErr::Other("out of devices")), Some(device) => { device.max_packet_size = desc.b_max_packet_size; debug!("Setting address to {}.", device.addr); diff --git a/usbh/src/pipe.rs b/usbh/src/pipe.rs index 936aa23..0a8503b 100644 --- a/usbh/src/pipe.rs +++ b/usbh/src/pipe.rs @@ -41,8 +41,14 @@ pub(crate) enum PipeErr { HWTimeout, DataToggle, SWTimeout, - Other, + Other(&'static str), } +impl From<&'static str> for PipeErr { + fn from(v: &'static str) -> Self { + Self::Other(v) + } +} + pub(crate) struct PipeTable { tbl: [PipeDesc; MAX_PIPES], } @@ -135,7 +141,7 @@ impl Pipe<'_, '_> { if let Some(b) = buf { // TODO: data stage, has up to 5,000ms (in 500ms // per-packet chunks) to complete. cf ยง9.2.6.4 of USB 2.0. - match bm_request_type.direction() { + match bm_request_type.direction()? { USBSetupDirection::DeviceToHost => { trace!("buf0: {:?}", &b); self.in_transfer(&b, NAK_LIMIT, millis)?; @@ -159,7 +165,7 @@ impl Pipe<'_, '_> { unsafe { w.multi_packet_size().bits(0) } }); - let token = match bm_request_type.direction() { + let token = match bm_request_type.direction()? { USBSetupDirection::DeviceToHost => USBToken::Out, USBSetupDirection::HostToDevice => USBToken::In, }; diff --git a/usbh/src/usbproto.rs b/usbh/src/usbproto.rs index 690cb40..0b7a8eb 100644 --- a/usbh/src/usbproto.rs +++ b/usbh/src/usbproto.rs @@ -2,6 +2,8 @@ /// /// Everything in here is defined by the USB specification, and /// hardware independent. +use core::convert::TryFrom; +use core::convert::TryInto; // TODO: Put protocol section references in for types and // documentation. @@ -79,15 +81,14 @@ pub enum USBSetupDirection { HostToDevice = 0x00, DeviceToHost = 0x80, } -impl From for USBSetupDirection -where - T: Into, -{ - fn from(v: T) -> Self { - match v.into() { - 0x00 => Self::HostToDevice, - 0x80 => Self::DeviceToHost, - _ => panic!("direction can only be 0x00 or 0x80"), +impl TryFrom for USBSetupDirection { + type Error = &'static str; + + fn try_from(v: u8) -> Result { + match v { + 0x00 => Ok(Self::HostToDevice), + 0x80 => Ok(Self::DeviceToHost), + _ => Err("direction can only be 0x00 or 0x80"), } } } @@ -98,16 +99,15 @@ pub enum USBSetupType { Class = 0x20, Vendor = 0x40, } -impl From for USBSetupType -where - T: Into, -{ - fn from(v: T) -> Self { - match v.into() { - 0x00 => Self::Standard, - 0x20 => Self::Class, - 0x40 => Self::Vendor, - _ => panic!("type can only be 0x00, 0x20, or 0x40"), +impl TryFrom for USBSetupType { + type Error = &'static str; + + fn try_from(v: u8) -> Result { + match v { + 0x00 => Ok(Self::Standard), + 0x20 => Ok(Self::Class), + 0x40 => Ok(Self::Vendor), + _ => Err("type can only be 0x00, 0x20, or 0x40"), } } } @@ -119,17 +119,16 @@ pub enum USBSetupRecipient { Endpoint = 0x02, Other = 0x03, } -impl From for USBSetupRecipient -where - T: Into, -{ - fn from(v: T) -> Self { - match v.into() { - 0x00 => Self::Device, - 0x01 => Self::Interface, - 0x02 => Self::Endpoint, - 0x03 => Self::Other, - _ => panic!("recipient can only be between 0 and 3"), +impl TryFrom for USBSetupRecipient { + type Error = &'static str; + + fn try_from(v: u8) -> Result { + match v { + 0x00 => Ok(Self::Device), + 0x01 => Ok(Self::Interface), + 0x02 => Ok(Self::Endpoint), + 0x03 => Ok(Self::Other), + _ => Err("recipient can only be between 0 and 3"), } } } @@ -165,10 +164,10 @@ impl RequestType { )) } - pub fn recipient(&self) -> USBSetupRecipient { + pub fn recipient(&self) -> Result { const POS: u8 = 0; const MASK: u8 = 0x1f; - (self.0 & (MASK << POS)).into() + (self.0 & (MASK << POS)).try_into() } pub fn set_recipient(&mut self, v: USBSetupRecipient) { @@ -178,10 +177,10 @@ impl RequestType { self.0 |= v as u8 & MASK; } - pub fn typ(&self) -> USBSetupType { + pub fn typ(&self) -> Result { const POS: u8 = 5; const MASK: u8 = 0x3; - (self.0 & (MASK << POS)).into() + (self.0 & (MASK << POS)).try_into() } pub fn set_typ(&mut self, v: USBSetupType) { @@ -191,10 +190,10 @@ impl RequestType { self.0 |= v as u8 & MASK; } - pub fn direction(&self) -> USBSetupDirection { + pub fn direction(&self) -> Result { const POS: u8 = 7; const MASK: u8 = 0x1; - (self.0 & (MASK << POS)).into() + (self.0 & (MASK << POS)).try_into() } pub fn set_direction(&mut self, v: USBSetupDirection) { @@ -204,11 +203,6 @@ impl RequestType { self.0 |= v as u8 & MASK; } } -impl From for RequestType { - fn from(v: u8) -> Self { - Self(v) - } -} impl From<(USBSetupDirection, USBSetupType, USBSetupRecipient)> for RequestType { fn from(v: (USBSetupDirection, USBSetupType, USBSetupRecipient)) -> Self { Self(v.0 as u8 | v.1 as u8 | v.2 as u8) @@ -268,24 +262,23 @@ pub enum RequestCode { SetInterface = 11, SynchFrame = 12, } -impl From for RequestCode -where - T: Into, -{ - fn from(v: T) -> Self { - match v.into() { - 0 => Self::GetStatus, - 1 => Self::ClearFeature, - 3 => Self::SetFeature, - 5 => Self::SetAddress, - 6 => Self::GetDescriptor, - 7 => Self::SetDescriptor, - 8 => Self::GetConfiguration, - 9 => Self::SetConfiguration, - 10 => Self::GetInterface, - 11 => Self::SetInterface, - 12 => Self::SynchFrame, - _ => panic!("invalid request value"), +impl TryFrom for RequestCode { + type Error = &'static str; + + fn try_from(v: u8) -> Result { + match v { + 0 => Ok(Self::GetStatus), + 1 => Ok(Self::ClearFeature), + 3 => Ok(Self::SetFeature), + 5 => Ok(Self::SetAddress), + 6 => Ok(Self::GetDescriptor), + 7 => Ok(Self::SetDescriptor), + 8 => Ok(Self::GetConfiguration), + 9 => Ok(Self::SetConfiguration), + 10 => Ok(Self::GetInterface), + 11 => Ok(Self::SetInterface), + 12 => Ok(Self::SynchFrame), + _ => Err("invalid request value"), } } } -- cgit v1.2.3