Skip to content

Commit 5eae3cd

Browse files
committed
Use num_enum instead of hand-rolling a parse function.
Also fixes the unit tests for neotron-bmc-protocol.
1 parent 9b3a89c commit 5eae3cd

File tree

6 files changed

+40
-83
lines changed

6 files changed

+40
-83
lines changed

neotron-bmc-commands/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ edition = "2021"
66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77

88
[dependencies]
9+
num_enum = { version = "0.5", default-features=false }

neotron-bmc-commands/src/lib.rs

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
#![no_std]
66

7-
#[derive(Debug, Copy, Clone)]
7+
#[derive(Debug, Copy, Clone, num_enum::IntoPrimitive, num_enum::TryFromPrimitive)]
88
#[repr(u8)]
99
pub enum Command {
1010
/// # Protocol Version
@@ -138,37 +138,3 @@ pub enum Command {
138138
/// * Mode: R/W
139139
I2cBaudRate = 0x64,
140140
}
141-
142-
impl Command {
143-
pub fn parse(byte: u8) -> Option<Command> {
144-
match byte {
145-
0x00 => Some(Command::ProtocolVersion),
146-
0x01 => Some(Command::FirmwareVersion),
147-
0x10 => Some(Command::InterruptStatus),
148-
0x11 => Some(Command::InterruptControl),
149-
0x20 => Some(Command::ButtonStatus),
150-
0x21 => Some(Command::SystemTemperature),
151-
0x22 => Some(Command::SystemVoltage33S),
152-
0x23 => Some(Command::SystemVoltage33),
153-
0x24 => Some(Command::SystemVoltage55),
154-
0x25 => Some(Command::PowerControl),
155-
0x30 => Some(Command::UartBuffer),
156-
0x31 => Some(Command::UartFifoControl),
157-
0x32 => Some(Command::UartControl),
158-
0x33 => Some(Command::UartStatus),
159-
0x34 => Some(Command::UartBaudRate),
160-
0x40 => Some(Command::Ps2KbBuffer),
161-
0x41 => Some(Command::Ps2KbControl),
162-
0x42 => Some(Command::Ps2KbStatus),
163-
0x50 => Some(Command::Ps2MouseBuffer),
164-
0x51 => Some(Command::Ps2MouseControl),
165-
0x52 => Some(Command::Ps2MouseStatus),
166-
0x60 => Some(Command::I2cBuffer),
167-
0x61 => Some(Command::I2cFifoControl),
168-
0x62 => Some(Command::I2cControl),
169-
0x63 => Some(Command::I2cStatus),
170-
0x64 => Some(Command::I2cBaudRate),
171-
_ => None,
172-
}
173-
}
174-
}

neotron-bmc-pico/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ defmt-rtt = "0.4"
1313
heapless= "0.7"
1414
panic-probe = { version = "0.3", features = ["print-defmt"] }
1515
stm32f0xx-hal = { version = "0.18", features = ["stm32f030x6", "rt"] }
16-
neotron-bmc-protocol = { version = "0.1", path = "../neotron-bmc-protocol" }
16+
neotron-bmc-protocol = { version = "0.1", path = "../neotron-bmc-protocol", features = ["defmt"] }
1717
neotron-bmc-commands = { version = "0.1", path = "../neotron-bmc-commands" }
1818
systick-monotonic = "1.0"
1919
embedded-hal = "*"

neotron-bmc-pico/src/main.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#![no_main]
1212
#![no_std]
1313

14+
use core::convert::TryFrom;
15+
1416
use heapless::spsc::{Consumer, Producer, Queue};
1517
use rtic::app;
1618
use stm32f0xx_hal::{
@@ -347,6 +349,7 @@ mod app {
347349
/// This task is called when there is nothing else to do.
348350
#[idle(shared = [msg_q_out, msg_q_in, spi])]
349351
fn idle(mut ctx: idle::Context) -> ! {
352+
// TODO: Get this from the VERSION static variable or from PKG_VERSION
350353
let mut register_state = RegisterState {
351354
firmware_version: *b"Neotron BMC v0.4.1-alpha\x00\x00\x00\x00\x00\x00\x00\x00",
352355
..Default::default()
@@ -645,9 +648,9 @@ where
645648
register_state.last_req = None;
646649

647650
// What do they want?
648-
let rsp = match (req.request_type, Command::parse(req.register)) {
649-
(proto::RequestType::Read, Some(Command::ProtocolVersion))
650-
| (proto::RequestType::ReadAlt, Some(Command::ProtocolVersion)) => {
651+
let rsp = match (req.request_type, Command::try_from(req.register)) {
652+
(proto::RequestType::Read, Ok(Command::ProtocolVersion))
653+
| (proto::RequestType::ReadAlt, Ok(Command::ProtocolVersion)) => {
651654
defmt::debug!("Reading ProtocolVersion");
652655
// They want the Protocol Version we support. Give them v0.1.1.
653656
let length = req.length_or_data as usize;
@@ -658,8 +661,8 @@ where
658661
proto::Response::new_without_data(proto::ResponseResult::BadLength)
659662
}
660663
}
661-
(proto::RequestType::Read, Some(Command::FirmwareVersion))
662-
| (proto::RequestType::ReadAlt, Some(Command::FirmwareVersion)) => {
664+
(proto::RequestType::Read, Ok(Command::FirmwareVersion))
665+
| (proto::RequestType::ReadAlt, Ok(Command::FirmwareVersion)) => {
663666
defmt::debug!("Reading FirmwareVersion");
664667
// They want the Firmware Version string.
665668
let length = req.length_or_data as usize;
@@ -671,8 +674,8 @@ where
671674
proto::Response::new_without_data(proto::ResponseResult::BadLength)
672675
}
673676
}
674-
(proto::RequestType::Read, Some(Command::Ps2KbBuffer))
675-
| (proto::RequestType::ReadAlt, Some(Command::Ps2KbBuffer)) => {
677+
(proto::RequestType::Read, Ok(Command::Ps2KbBuffer))
678+
| (proto::RequestType::ReadAlt, Ok(Command::Ps2KbBuffer)) => {
676679
defmt::debug!("Reading Ps2KbBuffer");
677680
let length = req.length_or_data as usize;
678681
if length > 0 && length <= register_state.scratch.len() {

neotron-bmc-protocol/Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,8 @@ readme = "README.md"
99
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1010

1111
[dependencies]
12-
defmt = "0.3"
12+
defmt = { version = "0.3", optional = true }
13+
num_enum = { version = "0.5", default-features = false }
14+
15+
[features]
16+
defmt = ["dep:defmt"]

neotron-bmc-protocol/src/lib.rs

Lines changed: 22 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// Modules and Imports
66
// ============================================================================
77

8+
#[cfg(feature = "defmt")]
89
use defmt::Format;
910

1011
mod crc;
@@ -34,7 +35,8 @@ pub trait Receivable<'a>: Sized {
3435
// ============================================================================
3536

3637
/// The ways this API can fail
37-
#[derive(Debug, Copy, Clone, Format, PartialEq, Eq)]
38+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
39+
#[cfg_attr(feature = "defmt", derive(Format))]
3840
pub enum Error {
3941
BadCrc,
4042
BadLength,
@@ -44,8 +46,11 @@ pub enum Error {
4446
}
4547

4648
/// The kinds of [`Request`] the *Host* can make to the NBMC
49+
#[derive(
50+
Debug, Copy, Clone, PartialEq, Eq, num_enum::IntoPrimitive, num_enum::TryFromPrimitive,
51+
)]
52+
#[cfg_attr(feature = "defmt", derive(Format))]
4753
#[repr(u8)]
48-
#[derive(Debug, Copy, Clone, Format, PartialEq, Eq)]
4954
pub enum RequestType {
5055
Read = 0xC0,
5156
ReadAlt = 0xC1,
@@ -57,7 +62,11 @@ pub enum RequestType {
5762

5863
/// The NBMC returns this code to indicate whether the previous [`Request`] was
5964
/// succesful or not.
60-
#[derive(Debug, Copy, Clone, Format, PartialEq, Eq)]
65+
#[derive(
66+
Debug, Copy, Clone, PartialEq, Eq, num_enum::IntoPrimitive, num_enum::TryFromPrimitive,
67+
)]
68+
#[cfg_attr(feature = "defmt", derive(Format))]
69+
#[repr(u8)]
6170
pub enum ResponseResult {
6271
/// The [`Request`] was correctly understood and actioned.
6372
Ok = 0xA0,
@@ -85,7 +94,8 @@ pub enum ResponseResult {
8594
// ============================================================================
8695

8796
/// A *Request* made by the *Host* to the *NBMC*
88-
#[derive(Debug, Clone, Format, PartialEq, Eq)]
97+
#[derive(Debug, Clone, PartialEq, Eq)]
98+
#[cfg_attr(feature = "defmt", derive(Format))]
8999
pub struct Request {
90100
pub request_type: RequestType,
91101
pub register: u8,
@@ -94,7 +104,8 @@ pub struct Request {
94104
}
95105

96106
/// A *Response* sent by the *NBMC* in reply to a [`Request`] from a *Host*
97-
#[derive(Debug, Clone, Format, PartialEq, Eq)]
107+
#[derive(Debug, Clone, PartialEq, Eq)]
108+
#[cfg_attr(feature = "defmt", derive(Format))]
98109
pub struct Response<'a> {
99110
pub result: ResponseResult,
100111
pub data: &'a [u8],
@@ -103,7 +114,8 @@ pub struct Response<'a> {
103114

104115
/// Describes the [semantic version](https://semver.org) of this implementation
105116
/// of the NBMC interface.
106-
#[derive(Debug, Copy, Clone, Format, PartialEq, Eq)]
117+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
118+
#[cfg_attr(feature = "defmt", derive(Format))]
107119
pub struct ProtocolVersion {
108120
major: u8,
109121
minor: u8,
@@ -114,22 +126,6 @@ pub struct ProtocolVersion {
114126
// Impls
115127
// ============================================================================
116128

117-
impl TryFrom<u8> for RequestType {
118-
type Error = Error;
119-
120-
fn try_from(byte: u8) -> Result<Self, Error> {
121-
match byte {
122-
0xC0 => Ok(RequestType::Read),
123-
0xC1 => Ok(RequestType::ReadAlt),
124-
0xC2 => Ok(RequestType::ShortWrite),
125-
0xC3 => Ok(RequestType::ShortWriteAlt),
126-
0xC4 => Ok(RequestType::LongWrite),
127-
0xC5 => Ok(RequestType::LongWriteAlt),
128-
_ => Err(Error::BadRequestType),
129-
}
130-
}
131-
}
132-
133129
impl Request {
134130
/// Make a new Read Request, requesting the given register and number of
135131
/// bytes.
@@ -208,6 +204,7 @@ impl Request {
208204
]
209205
}
210206
}
207+
211208
impl Sendable for Request {
212209
/// Convert to bytes for transmission.
213210
///
@@ -223,6 +220,7 @@ impl Sendable for Request {
223220
Ok(bytes.len())
224221
}
225222
}
223+
226224
impl<'a> Receivable<'a> for Request {
227225
/// Convert from received bytes.
228226
///
@@ -244,29 +242,14 @@ impl<'a> Receivable<'a> for Request {
244242
return Err(Error::BadCrc);
245243
}
246244
Ok(Request {
247-
request_type: data[0].try_into()?,
245+
request_type: data[0].try_into().map_err(|_| Error::BadRequestType)?,
248246
register: data[1],
249247
length_or_data: data[2],
250248
crc: data[3],
251249
})
252250
}
253251
}
254252

255-
impl TryFrom<u8> for ResponseResult {
256-
type Error = Error;
257-
258-
fn try_from(byte: u8) -> Result<Self, Error> {
259-
match byte {
260-
0xA0 => Ok(ResponseResult::Ok),
261-
0xA1 => Ok(ResponseResult::CrcFailure),
262-
0xA2 => Ok(ResponseResult::BadRequestType),
263-
0xA3 => Ok(ResponseResult::BadRegister),
264-
0xA4 => Ok(ResponseResult::BadLength),
265-
_ => Err(Error::BadResponseResult),
266-
}
267-
}
268-
}
269-
270253
impl<'a> Response<'a> {
271254
/// Make a new OK response, with some optional data
272255
pub fn new_ok_with_data(data: &'a [u8]) -> Response<'a> {
@@ -346,7 +329,7 @@ impl<'a> Receivable<'a> for Response<'a> {
346329
return Err(Error::BadCrc);
347330
}
348331
Ok(Response {
349-
result: data[0].try_into()?,
332+
result: data[0].try_into().map_err(|_| Error::BadResponseResult)?,
350333
data: &data[1..=(data.len() - 2)],
351334
crc: data[data.len() - 1],
352335
})

0 commit comments

Comments
 (0)