diff --git a/src/pipe.rs b/src/pipe.rs index 43b7c92..3664b43 100644 --- a/src/pipe.rs +++ b/src/pipe.rs @@ -1,12 +1,11 @@ -use core::convert::TryFrom; use heapless::Vec; use interchange::{Interchange, Requester}; use crate::{ constants::*, types::packet::{ - Chain, ChainedPacket as _, Command as PacketCommand, DataBlock, Error as PacketError, - ExtPacket, PacketWithData as _, RawPacket, XfrBlock, + Chain, ChainedPacket as _, CommandKind, DataBlock, Error as PacketError, ExtPacket, + Packet as _, PacketWithData as _, RawPacket, }, }; @@ -179,15 +178,15 @@ where // info!("{:X?}", &packet).ok(); // let p = packet.clone(); - // match PacketCommand::try_from(packet) { - match PacketCommand::try_from(self.ext_packet.clone()) { + // match CommandKind::try_from(packet) { + match self.ext_packet.command_kind() { Ok(command) => { - self.seq = command.seq(); + self.seq = self.ext_packet.seq(); // If we receive an ABORT on the control pipe, we reject all further commands until // we receive a matching ABORT on the bulk endpoint too. if let Some(control_abort) = self.control_abort { - if matches!(command, PacketCommand::Abort(_)) && control_abort == self.seq { + if command == CommandKind::Abort && control_abort == self.seq { self.abort(); } else { self.send_slot_status_error(Error::CmdAborted); @@ -198,17 +197,17 @@ where // happy path match command { - PacketCommand::PowerOn(_command) => self.send_atr(), + CommandKind::PowerOn => self.send_atr(), - PacketCommand::PowerOff(_command) => self.send_slot_status_ok(), + CommandKind::PowerOff => self.send_slot_status_ok(), - PacketCommand::GetSlotStatus(_command) => self.send_slot_status_ok(), + CommandKind::GetSlotStatus => self.send_slot_status_ok(), - PacketCommand::XfrBlock(command) => self.handle_transfer(command), + CommandKind::XfrBlock => self.handle_transfer(), - PacketCommand::Abort(_command) => self.bulk_abort = Some(self.seq), + CommandKind::Abort => self.bulk_abort = Some(self.seq), - PacketCommand::GetParameters(_command) => self.send_parameters(), + CommandKind::GetParameters => self.send_parameters(), } } @@ -236,7 +235,7 @@ where self.interchange.cancel().ok(); } - fn handle_transfer(&mut self, command: XfrBlock) { + fn handle_transfer(&mut self) { // state: Idle, Receiving, Processing, Sending, // // conts: BeginsAndEnds, Begins, Ends, Continues, ExpectDataBlock, @@ -246,13 +245,13 @@ where match self.state { State::Idle => { // invariant: BUFFER_SIZE >= PACKET_SIZE - match command.chain() { + match self.ext_packet.chain() { Chain::BeginsAndEnds => { info!("begins and ends"); self.reset_interchange(); let message = self.interchange.request_mut().unwrap(); message.clear(); - message.extend_from_slice(command.data()).unwrap(); + message.extend_from_slice(self.ext_packet.data()).unwrap(); self.call_app(); self.state = State::Processing; // self.send_empty_datablock(); @@ -262,7 +261,7 @@ where self.reset_interchange(); let message = self.interchange.request_mut().unwrap(); message.clear(); - message.extend_from_slice(command.data()).unwrap(); + message.extend_from_slice(self.ext_packet.data()).unwrap(); self.state = State::Receiving; self.send_empty_datablock(Chain::ExpectingMore); } @@ -270,19 +269,19 @@ where } } - State::Receiving => match command.chain() { + State::Receiving => match self.ext_packet.chain() { Chain::Continues => { info!("continues"); let message = self.interchange.request_mut().unwrap(); - assert!(command.data().len() + message.len() <= MAX_MSG_LENGTH); - message.extend_from_slice(command.data()).unwrap(); + assert!(self.ext_packet.data().len() + message.len() <= MAX_MSG_LENGTH); + message.extend_from_slice(self.ext_packet.data()).unwrap(); self.send_empty_datablock(Chain::ExpectingMore); } Chain::Ends => { info!("ends"); let message = self.interchange.request_mut().unwrap(); - assert!(command.data().len() + message.len() <= MAX_MSG_LENGTH); - message.extend_from_slice(command.data()).unwrap(); + assert!(self.ext_packet.data().len() + message.len() <= MAX_MSG_LENGTH); + message.extend_from_slice(self.ext_packet.data()).unwrap(); self.call_app(); self.state = State::Processing; } @@ -294,7 +293,7 @@ where // info!("{:X?}", &command).ok(); panic!( "ccid pipe unexpectedly received command while in processing state: {:?}", - &command + &self.ext_packet ); } @@ -302,7 +301,7 @@ where panic!("unexpectedly in ready-to-send state") } - State::Sending => match command.chain() { + State::Sending => match self.ext_packet.chain() { Chain::ExpectingMore => { self.prime_outbox(); } diff --git a/src/types/packet.rs b/src/types/packet.rs index f066746..a0e77c6 100644 --- a/src/types/packet.rs +++ b/src/types/packet.rs @@ -1,9 +1,14 @@ -use core::convert::{TryFrom, TryInto}; +use core::{ + convert::{TryFrom, TryInto}, + ops::{Deref, DerefMut}, +}; use crate::constants::*; pub type RawPacket = heapless::Vec; -pub type ExtPacket = heapless::Vec; + +#[derive(Default, PartialEq, Eq)] +pub struct ExtPacket(heapless::Vec); pub trait RawPacketExt { fn data_len(&self) -> usize; @@ -20,7 +25,7 @@ pub enum Error { UnknownCommand(u8), } -pub trait Packet: core::ops::Deref { +pub trait Packet: core::ops::Deref> { #[inline] fn slot(&self) -> u8 { // we have only one slot @@ -60,7 +65,22 @@ pub trait ChainedPacket: Packet { } } -impl ChainedPacket for XfrBlock {} +impl Deref for ExtPacket { + type Target = heapless::Vec; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for ExtPacket { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl Packet for ExtPacket {} +impl PacketWithData for ExtPacket {} +impl ChainedPacket for ExtPacket {} pub struct DataBlock<'a> { seq: u8, @@ -134,8 +154,8 @@ impl From> for RawPacket { } #[repr(u8)] -#[derive(Copy, Clone, Debug)] -pub enum CommandType { +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum CommandKind { // REQUESTS // supported @@ -156,120 +176,34 @@ pub enum CommandType { // SetDataRateAndClockFrequency = 0x73, } -macro_rules! command_message { - - ($($Name:ident: $code:expr,)*) => { - $( - #[derive(Debug)] - pub struct $Name { - // use reference? pulls in lifetimes though... - ext_raw: ExtPacket, - } - - impl core::ops::Deref for $Name { - type Target = ExtPacket; - - #[inline] - fn deref(&self) -> &Self::Target { - &self.ext_raw - } - } - - impl core::ops::DerefMut for $Name { - - #[inline] - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.ext_raw - } - } - - impl Packet for $Name {} - )* - - pub enum Command { - $( - $Name($Name), - )* - } - - impl Command { - pub fn seq(&self) -> u8 { - match self { - $( - Command::$Name(packet) => packet.seq(), - )* - } - } - - pub fn command_type(&self) -> CommandType { - match self { - $( - Command::$Name(_) => CommandType::$Name, - )* - } - } +impl ExtPacket { + pub fn command_kind(&self) -> Result { + if self.len() < CCID_HEADER_LEN { + return Err(Error::ShortPacket); } - - impl core::convert::TryFrom for Command { - type Error = Error; - - #[inline] - fn try_from(packet: ExtPacket) - -> core::result::Result - { - if packet.len() < CCID_HEADER_LEN { - return Err(Error::ShortPacket); - } - if packet[5] != 0 { - // wrong slot - } - let command_byte = packet[0]; - Ok(match command_byte { - $( - $code => Command::$Name($Name { ext_raw: packet } ), - )* - _ => return Err(Error::UnknownCommand(command_byte)), - }) - } + if self[5] != 0 { + // wrong slot } - - impl core::ops::Deref for Command { - type Target = ExtPacket; - - #[inline] - fn deref(&self) -> &Self::Target { - match self { - $( - Command::$Name(packet) => &packet, - )* - } - } + let command_byte = self[0]; + match command_byte { + 0x62 => Ok(CommandKind::PowerOn), + 0x63 => Ok(CommandKind::PowerOff), + 0x65 => Ok(CommandKind::GetSlotStatus), + 0x6c => Ok(CommandKind::GetParameters), + 0x6f => Ok(CommandKind::XfrBlock), + 0x72 => Ok(CommandKind::Abort), + _ => Err(Error::UnknownCommand(command_byte)), } - - // impl core::ops::DerefMut for Command { - - // #[inline] - // fn deref_mut(&mut self) -> &mut Self::Target { - // match self { - // $( - // Command::$Name(packet) => &mut packet, - // )* - // } - // } - // } } } - -command_message!( - PowerOn: 0x62, - PowerOff: 0x63, - GetSlotStatus: 0x65, - GetParameters: 0x6c, - XfrBlock: 0x6f, - Abort: 0x72, -); - -impl PacketWithData for XfrBlock {} +// command_message!( +// PowerOn: 0x62, +// PowerOff: 0x63, +// GetSlotStatus: 0x65, +// GetParameters: 0x6c, +// XfrBlock: 0x6f, +// Abort: 0x72, +// ); #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[repr(u8)] @@ -290,19 +224,22 @@ impl Chain { } } -impl core::fmt::Debug for Command { +impl core::fmt::Debug for ExtPacket { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let mut debug_struct = f.debug_struct("Command"); // write!("Command({:?})", &self.command_type())); // // "Command"); + let Ok(command_type) = self.command_kind() else { + return debug_struct.field("cmd", &format_args!("error")).field("value", &format_args!("{:02x?}", self.0)).finish(); + }; debug_struct - .field("cmd", &self.command_type()) + .field("cmd", &command_type) .field("seq", &self.seq()); - if let Command::XfrBlock(block) = self { + if command_type == CommandKind::XfrBlock { let l = core::cmp::min(self.len(), 8); - let escaped_bytes: heapless::Vec = block + let escaped_bytes: heapless::Vec = self .data() .iter() .take(l) @@ -311,8 +248,8 @@ impl core::fmt::Debug for Command { let data_as_str = &core::str::from_utf8(&escaped_bytes).unwrap(); debug_struct - .field("chain", &block.chain()) - .field("len", &block.data().len()); + .field("chain", &self.chain()) + .field("len", &self.data().len()); if l < self.len() { debug_struct.field("data[..8]", &format_args!("b'{data_as_str}'"))