diff --git a/Cargo.lock b/Cargo.lock index ee0606d4..486957e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2016,6 +2016,7 @@ dependencies = [ "embedded-services", "num_enum", "uuid", + "zerocopy", ] [[package]] diff --git a/examples/rt633/Cargo.lock b/examples/rt633/Cargo.lock index c1215bae..1a53ab89 100644 --- a/examples/rt633/Cargo.lock +++ b/examples/rt633/Cargo.lock @@ -1531,6 +1531,7 @@ dependencies = [ "embedded-services", "num_enum", "uuid", + "zerocopy", ] [[package]] diff --git a/examples/std/Cargo.lock b/examples/std/Cargo.lock index 38bbfdb8..2230c971 100644 --- a/examples/std/Cargo.lock +++ b/examples/std/Cargo.lock @@ -1639,6 +1639,7 @@ dependencies = [ "embedded-services", "num_enum", "uuid", + "zerocopy", ] [[package]] diff --git a/examples/std/src/bin/thermal.rs b/examples/std/src/bin/thermal.rs index 653ca820..4dba35d0 100644 --- a/examples/std/src/bin/thermal.rs +++ b/examples/std/src/bin/thermal.rs @@ -12,7 +12,9 @@ use static_cell::StaticCell; use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; use thermal_service as ts; -use thermal_service_messages::ThermalRequest; +use thermal_service_messages::{ + ThermalGetTmpRequest, ThermalGetVarRequest, ThermalRequest, ThermalSetThrsRequest, ThermalSetVarRequest, +}; use ts::mptf; // Mock host service @@ -21,7 +23,7 @@ mod host { use embedded_services::comms::{self, Endpoint, EndpointID, External, MailboxDelegate}; use log::{info, warn}; use thermal_service as ts; - use thermal_service_messages::{ThermalResponse, ThermalResult}; + use thermal_service_messages::{ThermalGetTmpResponse, ThermalGetVarResponse, ThermalResponse, ThermalResult}; use ts::mptf; pub struct Host { @@ -39,10 +41,10 @@ mod host { fn handle_response(&self, response: ThermalResponse) { match response { - ThermalResponse::ThermalGetTmpResponse { temperature } => { + ThermalResponse::ThermalGetTmpResponse(ThermalGetTmpResponse { temperature }) => { info!("Host received temperature: {} °C", ts::utils::dk_to_c(temperature)) } - ThermalResponse::ThermalGetVarResponse { val } => { + ThermalResponse::ThermalGetVarResponse(ThermalGetVarResponse { val }) => { info!("Host received fan RPM: {val}") } _ => info!("Received MPTF response: {response:?}"), @@ -219,12 +221,12 @@ async fn host() { host.tp .send( thermal_id, - &ThermalRequest::ThermalSetThrsRequest { + &ThermalRequest::ThermalSetThrsRequest(ThermalSetThrsRequest { instance_id: 0, - timeout: 0, - low: 0, - high: 3131, - }, + timeout: 0.into(), + low: 0.into(), + high: 3131.into(), + }), ) .await .unwrap(); @@ -234,12 +236,12 @@ async fn host() { host.tp .send( thermal_id, - &ThermalRequest::ThermalSetVarRequest { + &ThermalRequest::ThermalSetVarRequest(ThermalSetVarRequest { instance_id: 0, - len: 4, + len: 4.into(), var_uuid: mptf::uuid_standard::FAN_ON_TEMP, - set_var: 3131, - }, + set_var: 3131.into(), + }), ) .await .unwrap(); @@ -249,12 +251,12 @@ async fn host() { host.tp .send( thermal_id, - &ThermalRequest::ThermalSetVarRequest { + &ThermalRequest::ThermalSetVarRequest(ThermalSetVarRequest { instance_id: 0, - len: 4, + len: 4.into(), var_uuid: mptf::uuid_standard::FAN_RAMP_TEMP, - set_var: 3231, - }, + set_var: 3231.into(), + }), ) .await .unwrap(); @@ -264,12 +266,12 @@ async fn host() { host.tp .send( thermal_id, - &ThermalRequest::ThermalSetVarRequest { + &ThermalRequest::ThermalSetVarRequest(ThermalSetVarRequest { instance_id: 0, - len: 4, + len: 4.into(), var_uuid: mptf::uuid_standard::FAN_MAX_TEMP, - set_var: 3531, - }, + set_var: 3531.into(), + }), ) .await .unwrap(); @@ -281,7 +283,10 @@ async fn host() { info!("Host requesting temperature in response to threshold alert"); host.tp - .send(thermal_id, &ThermalRequest::ThermalGetTmpRequest { instance_id: 0 }) + .send( + thermal_id, + &ThermalRequest::ThermalGetTmpRequest(ThermalGetTmpRequest { instance_id: 0 }), + ) .await .unwrap(); @@ -292,11 +297,11 @@ async fn host() { host.tp .send( thermal_id, - &ThermalRequest::ThermalGetVarRequest { + &ThermalRequest::ThermalGetVarRequest(ThermalGetVarRequest { instance_id: 0, - len: 4, + len: 4.into(), var_uuid: mptf::uuid_standard::FAN_CURRENT_RPM, - }, + }), ) .await .unwrap(); diff --git a/thermal-service-messages/Cargo.toml b/thermal-service-messages/Cargo.toml index 2d9dbc37..f4956788 100644 --- a/thermal-service-messages/Cargo.toml +++ b/thermal-service-messages/Cargo.toml @@ -10,6 +10,7 @@ defmt = { workspace = true, optional = true } embedded-services.workspace = true num_enum.workspace = true uuid.workspace = true +zerocopy.workspace = true [lints] workspace = true diff --git a/thermal-service-messages/src/lib.rs b/thermal-service-messages/src/lib.rs index d0325a2f..e56d8523 100644 --- a/thermal-service-messages/src/lib.rs +++ b/thermal-service-messages/src/lib.rs @@ -1,18 +1,19 @@ #![no_std] use embedded_services::relay::{MessageSerializationError, SerializableMessage}; +use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, LE, U16, U32}; /// 16-bit variable length -pub type VarLen = u16; +pub type VarLen = U16; /// Instance ID pub type InstanceId = u8; /// Time in milliseconds -pub type Milliseconds = u32; +pub type Milliseconds = U32; /// MPTF expects temperatures in tenth Kelvins -pub type DeciKelvin = u32; +pub type DeciKelvin = U32; /// Standard MPTF requests expected by the thermal subsystem #[derive(num_enum::IntoPrimitive, num_enum::TryFromPrimitive, Copy, Clone, Debug, PartialEq)] @@ -36,12 +37,12 @@ enum ThermalCmd { impl From<&ThermalRequest> for ThermalCmd { fn from(request: &ThermalRequest) -> Self { match request { - ThermalRequest::ThermalGetTmpRequest { .. } => ThermalCmd::GetTmp, - ThermalRequest::ThermalSetThrsRequest { .. } => ThermalCmd::SetThrs, - ThermalRequest::ThermalGetThrsRequest { .. } => ThermalCmd::GetThrs, - ThermalRequest::ThermalSetScpRequest { .. } => ThermalCmd::SetScp, - ThermalRequest::ThermalGetVarRequest { .. } => ThermalCmd::GetVar, - ThermalRequest::ThermalSetVarRequest { .. } => ThermalCmd::SetVar, + ThermalRequest::ThermalGetTmpRequest(_) => ThermalCmd::GetTmp, + ThermalRequest::ThermalSetThrsRequest(_) => ThermalCmd::SetThrs, + ThermalRequest::ThermalGetThrsRequest(_) => ThermalCmd::GetThrs, + ThermalRequest::ThermalSetScpRequest(_) => ThermalCmd::SetScp, + ThermalRequest::ThermalGetVarRequest(_) => ThermalCmd::GetVar, + ThermalRequest::ThermalSetVarRequest(_) => ThermalCmd::SetVar, } } } @@ -49,94 +50,94 @@ impl From<&ThermalRequest> for ThermalCmd { impl From<&ThermalResponse> for ThermalCmd { fn from(response: &ThermalResponse) -> Self { match response { - ThermalResponse::ThermalGetTmpResponse { .. } => ThermalCmd::GetTmp, + ThermalResponse::ThermalGetTmpResponse(_) => ThermalCmd::GetTmp, ThermalResponse::ThermalSetThrsResponse => ThermalCmd::SetThrs, - ThermalResponse::ThermalGetThrsResponse { .. } => ThermalCmd::GetThrs, + ThermalResponse::ThermalGetThrsResponse(_) => ThermalCmd::GetThrs, ThermalResponse::ThermalSetScpResponse => ThermalCmd::SetScp, - ThermalResponse::ThermalGetVarResponse { .. } => ThermalCmd::GetVar, + ThermalResponse::ThermalGetVarResponse(_) => ThermalCmd::GetVar, ThermalResponse::ThermalSetVarResponse => ThermalCmd::SetVar, } } } +#[derive(PartialEq, Clone, Copy, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct ThermalGetTmpRequest { + pub instance_id: u8, +} + +#[derive(PartialEq, Clone, Copy, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)] +pub struct ThermalSetThrsRequest { + pub instance_id: u8, + pub timeout: Milliseconds, + pub low: DeciKelvin, + pub high: DeciKelvin, +} + +#[derive(PartialEq, Clone, Copy, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct ThermalGetThrsRequest { + pub instance_id: u8, +} + +#[derive(PartialEq, Clone, Copy, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)] +pub struct ThermalSetScpRequest { + pub instance_id: u8, + pub policy_id: U32, + pub acoustic_lim: U32, + pub power_lim: U32, +} + +#[derive(PartialEq, Clone, Copy, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)] +pub struct ThermalGetVarRequest { + pub instance_id: u8, + pub len: VarLen, // TODO why is there a len here? as far as I can tell we're always discarding it, and I think values are only u32? + pub var_uuid: uuid::Bytes, +} + +#[derive(PartialEq, Clone, Copy, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)] +pub struct ThermalSetVarRequest { + pub instance_id: u8, + pub len: VarLen, // TODO why is there a len here? as far as I can tell we're always discarding it, and I think values are only u32? + pub var_uuid: uuid::Bytes, + pub set_var: U32, +} + #[derive(PartialEq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum ThermalRequest { - ThermalGetTmpRequest { - instance_id: u8, - }, - ThermalSetThrsRequest { - instance_id: u8, - timeout: Milliseconds, - low: DeciKelvin, - high: DeciKelvin, - }, - ThermalGetThrsRequest { - instance_id: u8, - }, - ThermalSetScpRequest { - instance_id: u8, - policy_id: u32, - acoustic_lim: u32, - power_lim: u32, - }, - ThermalGetVarRequest { - instance_id: u8, - len: VarLen, // TODO why is there a len here? as far as I can tell we're always discarding it, and I think values are only u32? - var_uuid: uuid::Bytes, - }, - ThermalSetVarRequest { - instance_id: u8, - len: VarLen, // TODO why is there a len here? as far as I can tell we're always discarding it, and I think values are only u32? - var_uuid: uuid::Bytes, - set_var: u32, - }, + ThermalGetTmpRequest(ThermalGetTmpRequest), + ThermalSetThrsRequest(ThermalSetThrsRequest), + ThermalGetThrsRequest(ThermalGetThrsRequest), + ThermalSetScpRequest(ThermalSetScpRequest), + ThermalGetVarRequest(ThermalGetVarRequest), + ThermalSetVarRequest(ThermalSetVarRequest), } -// TODO this is essentially a hand-written reinterpret_cast - can we codegen some of this instead? impl SerializableMessage for ThermalRequest { - fn serialize(self, _buffer: &mut [u8]) -> Result { - Err(MessageSerializationError::Other( - "unimplemented - don't need to serialize requests on the EC side", - )) + fn serialize(self, buffer: &mut [u8]) -> Result { + match self { + Self::ThermalGetTmpRequest(req) => serialize_inner(req, buffer), + Self::ThermalSetThrsRequest(req) => serialize_inner(req, buffer), + Self::ThermalGetThrsRequest(req) => serialize_inner(req, buffer), + Self::ThermalSetScpRequest(req) => serialize_inner(req, buffer), + Self::ThermalGetVarRequest(req) => serialize_inner(req, buffer), + Self::ThermalSetVarRequest(req) => serialize_inner(req, buffer), + } } fn deserialize(discriminant: u16, buffer: &[u8]) -> Result { - Ok( - match ThermalCmd::try_from(discriminant) - .map_err(|_| MessageSerializationError::UnknownMessageDiscriminant(discriminant))? - { - ThermalCmd::GetTmp => Self::ThermalGetTmpRequest { - instance_id: safe_get_u8(buffer, 0)?, - }, - ThermalCmd::SetThrs => Self::ThermalSetThrsRequest { - instance_id: safe_get_u8(buffer, 0)?, - timeout: safe_get_dword(buffer, 1)?, - low: safe_get_dword(buffer, 5)?, - high: safe_get_dword(buffer, 9)?, - }, - ThermalCmd::GetThrs => Self::ThermalGetThrsRequest { - instance_id: safe_get_u8(buffer, 0)?, - }, - ThermalCmd::SetScp => Self::ThermalSetScpRequest { - instance_id: safe_get_u8(buffer, 0)?, - policy_id: safe_get_dword(buffer, 1)?, - acoustic_lim: safe_get_dword(buffer, 5)?, - power_lim: safe_get_dword(buffer, 9)?, - }, - ThermalCmd::GetVar => Self::ThermalGetVarRequest { - instance_id: safe_get_u8(buffer, 0)?, - len: safe_get_u16(buffer, 1)?, - var_uuid: safe_get_uuid(buffer, 3)?, - }, - ThermalCmd::SetVar => Self::ThermalSetVarRequest { - instance_id: safe_get_u8(buffer, 0)?, - len: safe_get_u16(buffer, 1)?, - var_uuid: safe_get_uuid(buffer, 3)?, - set_var: safe_get_dword(buffer, 19)?, - }, - }, - ) + let cmd = ThermalCmd::try_from(discriminant) + .map_err(|_| MessageSerializationError::UnknownMessageDiscriminant(discriminant))?; + + Ok(match cmd { + ThermalCmd::GetTmp => Self::ThermalGetTmpRequest(deserialize_inner(buffer)?), + ThermalCmd::SetThrs => Self::ThermalSetThrsRequest(deserialize_inner(buffer)?), + ThermalCmd::GetThrs => Self::ThermalGetThrsRequest(deserialize_inner(buffer)?), + ThermalCmd::SetScp => Self::ThermalSetScpRequest(deserialize_inner(buffer)?), + ThermalCmd::GetVar => Self::ThermalGetVarRequest(deserialize_inner(buffer)?), + ThermalCmd::SetVar => Self::ThermalSetVarRequest(deserialize_inner(buffer)?), + }) } fn discriminant(&self) -> u16 { @@ -145,68 +146,56 @@ impl SerializableMessage for ThermalRequest { } } +#[derive(PartialEq, Clone, Copy, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)] +pub struct ThermalGetTmpResponse { + pub temperature: DeciKelvin, +} + +#[derive(PartialEq, Clone, Copy, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)] +pub struct ThermalGetThrsResponse { + pub timeout: Milliseconds, + pub low: DeciKelvin, + pub high: DeciKelvin, +} + +#[derive(PartialEq, Clone, Copy, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)] +pub struct ThermalGetVarResponse { + pub val: U32, +} + #[derive(PartialEq, Clone, Copy, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum ThermalResponse { - ThermalGetTmpResponse { - temperature: DeciKelvin, - }, + ThermalGetTmpResponse(ThermalGetTmpResponse), ThermalSetThrsResponse, - ThermalGetThrsResponse { - timeout: Milliseconds, - low: DeciKelvin, - high: DeciKelvin, - }, + ThermalGetThrsResponse(ThermalGetThrsResponse), ThermalSetScpResponse, - ThermalGetVarResponse { - val: u32, - }, + ThermalGetVarResponse(ThermalGetVarResponse), ThermalSetVarResponse, } impl SerializableMessage for ThermalResponse { fn serialize(self, buffer: &mut [u8]) -> Result { match self { - Self::ThermalGetTmpResponse { temperature } => { - buffer - .get_mut(..4) - .ok_or(MessageSerializationError::BufferTooSmall)? - .copy_from_slice(&u32::to_le_bytes(temperature)); - - Ok(4) - } - Self::ThermalGetThrsResponse { timeout, low, high } => { - buffer - .get_mut(..4) - .ok_or(MessageSerializationError::BufferTooSmall)? - .copy_from_slice(&u32::to_le_bytes(timeout)); - buffer - .get_mut(4..8) - .ok_or(MessageSerializationError::BufferTooSmall)? - .copy_from_slice(&u32::to_le_bytes(low)); - buffer - .get_mut(8..12) - .ok_or(MessageSerializationError::BufferTooSmall)? - .copy_from_slice(&u32::to_le_bytes(high)); - - Ok(12) - } - - Self::ThermalGetVarResponse { val } => { - buffer - .get_mut(..4) - .ok_or(MessageSerializationError::BufferTooSmall)? - .copy_from_slice(&u32::to_le_bytes(val)); - Ok(4) - } - Self::ThermalSetVarResponse | Self::ThermalSetScpResponse | Self::ThermalSetThrsResponse => Ok(0), + Self::ThermalGetTmpResponse(resp) => serialize_inner(resp, buffer), + Self::ThermalGetThrsResponse(resp) => serialize_inner(resp, buffer), + Self::ThermalGetVarResponse(resp) => serialize_inner(resp, buffer), + Self::ThermalSetVarResponse | Self::ThermalSetThrsResponse | Self::ThermalSetScpResponse => Ok(0), } } - fn deserialize(_discriminant: u16, _buffer: &[u8]) -> Result { - Err(MessageSerializationError::Other( - "unimplemented - don't need to deserialize responses on the EC side", - )) + fn deserialize(discriminant: u16, buffer: &[u8]) -> Result { + let cmd = ThermalCmd::try_from(discriminant) + .map_err(|_| MessageSerializationError::UnknownMessageDiscriminant(discriminant))?; + + Ok(match cmd { + ThermalCmd::GetTmp => Self::ThermalGetTmpResponse(deserialize_inner(buffer)?), + ThermalCmd::GetThrs => Self::ThermalGetThrsResponse(deserialize_inner(buffer)?), + ThermalCmd::GetVar => Self::ThermalGetVarResponse(deserialize_inner(buffer)?), + ThermalCmd::SetThrs => Self::ThermalSetThrsResponse, + ThermalCmd::SetScp => Self::ThermalSetScpResponse, + ThermalCmd::SetVar => Self::ThermalSetVarResponse, + }) } fn discriminant(&self) -> u16 { @@ -225,15 +214,12 @@ pub enum ThermalError { impl SerializableMessage for ThermalError { fn serialize(self, _buffer: &mut [u8]) -> Result { - match self { - Self::UnsupportedRevision | Self::InvalidParameter | Self::HardwareError => Ok(0), - } + Ok(0) } - fn deserialize(_discriminant: u16, _buffer: &[u8]) -> Result { - Err(MessageSerializationError::Other( - "unimplemented - don't need to deserialize responses on the EC side", - )) + fn deserialize(discriminant: u16, _buffer: &[u8]) -> Result { + ThermalError::try_from(discriminant) + .map_err(|_| MessageSerializationError::UnknownMessageDiscriminant(discriminant)) } fn discriminant(&self) -> u16 { @@ -243,35 +229,102 @@ impl SerializableMessage for ThermalError { pub type ThermalResult = Result; -fn safe_get_u8(buffer: &[u8], index: usize) -> Result { - buffer - .get(index) - .copied() - .ok_or(MessageSerializationError::BufferTooSmall) +#[inline(always)] +fn serialize_inner(req: T, buffer: &mut [u8]) -> Result { + req.write_to_prefix(buffer) + .map_err(|_| MessageSerializationError::BufferTooSmall)?; + Ok(req.as_bytes().len()) } -fn safe_get_u16(buffer: &[u8], index: usize) -> Result { - let bytes = buffer - .get(index..index + 2) - .ok_or(MessageSerializationError::BufferTooSmall)? - .try_into() - .map_err(|_| MessageSerializationError::BufferTooSmall)?; - Ok(u16::from_le_bytes(bytes)) +#[inline(always)] +fn deserialize_inner(buffer: &[u8]) -> Result { + Ok(T::read_from_prefix(buffer) + .map_err(|_| MessageSerializationError::BufferTooSmall)? + .0) } -fn safe_get_dword(buffer: &[u8], index: usize) -> Result { - let bytes = buffer - .get(index..index + 4) - .ok_or(MessageSerializationError::BufferTooSmall)? - .try_into() - .map_err(|_| MessageSerializationError::BufferTooSmall)?; - Ok(u32::from_le_bytes(bytes)) +// NOTE: zerocopy::byteorder::UN types unfortunately don't implement `defmt::Format`, so the structs +// can't derive it. Thus we have to manually implement it. +// +// Revisit: Upstream defmt support to zerocopy? +#[cfg(feature = "defmt")] +impl defmt::Format for ThermalSetThrsRequest { + fn format(&self, f: defmt::Formatter) { + defmt::write!( + f, + "ThermalSetThrsRequest {{ instance_id: {}, timeout: {}, low: {}, high: {} }}", + self.instance_id, + self.timeout.get(), + self.low.get(), + self.high.get(), + ); + } +} + +#[cfg(feature = "defmt")] +impl defmt::Format for ThermalSetScpRequest { + fn format(&self, f: defmt::Formatter) { + defmt::write!( + f, + "ThermalSetScpRequest {{ instance_id: {}, policy_id: {}, acoustic_lim: {}, power_lim: {} }}", + self.instance_id, + self.policy_id.get(), + self.acoustic_lim.get(), + self.power_lim.get(), + ); + } +} + +#[cfg(feature = "defmt")] +impl defmt::Format for ThermalGetVarRequest { + fn format(&self, f: defmt::Formatter) { + defmt::write!( + f, + "ThermalGetVarRequest {{ instance_id: {}, len: {}, var_uuid: {=[u8; 16]} }}", + self.instance_id, + self.len.get(), + self.var_uuid, + ); + } +} + +#[cfg(feature = "defmt")] +impl defmt::Format for ThermalSetVarRequest { + fn format(&self, f: defmt::Formatter) { + defmt::write!( + f, + "ThermalSetVarRequest {{ instance_id: {}, len: {}, var_uuid: {=[u8; 16]}, set_var: {} }}", + self.instance_id, + self.len.get(), + self.var_uuid, + self.set_var.get(), + ); + } +} + +#[cfg(feature = "defmt")] +impl defmt::Format for ThermalGetTmpResponse { + fn format(&self, f: defmt::Formatter) { + defmt::write!(f, "ThermalGetTmpResponse {{ temperature: {} }}", self.temperature.get()); + } +} + +#[cfg(feature = "defmt")] +impl defmt::Format for ThermalGetThrsResponse { + fn format(&self, f: defmt::Formatter) { + defmt::write!( + f, + "ThermalGetThrsResponse {{ timeout: {}, low: {}, high: {} }}", + self.timeout.get(), + self.low.get(), + self.high.get(), + ); + } } -fn safe_get_uuid(buffer: &[u8], index: usize) -> Result { - buffer - .get(index..index + 16) - .ok_or(MessageSerializationError::BufferTooSmall)? - .try_into() - .map_err(|_| MessageSerializationError::BufferTooSmall) +#[cfg(feature = "defmt")] +impl defmt::Format for ThermalGetVarResponse { + fn format(&self, f: defmt::Formatter) { + defmt::write!(f, "ThermalGetVarResponse {{ val: {} }}", self.val.get()); + } } diff --git a/thermal-service/src/mptf.rs b/thermal-service/src/mptf.rs index dc9e3940..4ea2b761 100644 --- a/thermal-service/src/mptf.rs +++ b/thermal-service/src/mptf.rs @@ -4,7 +4,11 @@ //! //! This interface is subject to change as the eSPI OOB service is developed use crate::{self as ts, fan, sensor, utils}; -use thermal_service_messages::{DeciKelvin, Milliseconds}; +use thermal_service_messages::{ + DeciKelvin, Milliseconds, ThermalError, ThermalGetThrsRequest, ThermalGetThrsResponse, ThermalGetTmpRequest, + ThermalGetTmpResponse, ThermalGetVarRequest, ThermalGetVarResponse, ThermalRequest, ThermalResponse, ThermalResult, + ThermalSetScpRequest, ThermalSetThrsRequest, ThermalSetVarRequest, +}; use embedded_services::error; @@ -33,19 +37,19 @@ pub enum Notify { Critical, } -async fn sensor_get_tmp(instance_id: u8) -> thermal_service_messages::ThermalResult { +async fn sensor_get_tmp(instance_id: u8) -> ThermalResult { if let Ok(ts::sensor::ResponseData::Temp(temp)) = ts::execute_sensor_request(sensor::DeviceId(instance_id), sensor::Request::GetTemp).await { - Ok(thermal_service_messages::ThermalResponse::ThermalGetTmpResponse { + Ok(ThermalResponse::ThermalGetTmpResponse(ThermalGetTmpResponse { temperature: utils::c_to_dk(temp), - }) + })) } else { - Err(thermal_service_messages::ThermalError::InvalidParameter) + Err(ThermalError::InvalidParameter) } } -async fn get_var_handler(instance_id: u8, var_uuid: uuid::Bytes) -> thermal_service_messages::ThermalResult { +async fn get_var_handler(instance_id: u8, var_uuid: uuid::Bytes) -> ThermalResult { match var_uuid { uuid_standard::CRT_TEMP => sensor_get_thrs(instance_id, sensor::ThresholdType::Critical).await, uuid_standard::PROC_HOT_TEMP => sensor_get_thrs(instance_id, sensor::ThresholdType::Prochot).await, @@ -63,7 +67,7 @@ async fn get_var_handler(instance_id: u8, var_uuid: uuid::Bytes) -> thermal_serv // TODO: Allow OEM to handle these? uuid => { error!("Received GetVar for unrecognized UUID: {:?}", uuid); - Err(thermal_service_messages::ThermalError::InvalidParameter) + Err(ThermalError::InvalidParameter) } } } @@ -80,12 +84,14 @@ async fn set_var_handler( uuid_standard::PROFILE_TYPE => { todo!() } - uuid_standard::FAN_ON_TEMP => fan_set_var(instance_id, fan::Request::SetOnTemp(utils::dk_to_c(set_var))).await, + uuid_standard::FAN_ON_TEMP => { + fan_set_var(instance_id, fan::Request::SetOnTemp(utils::dk_to_c(set_var.into()))).await + } uuid_standard::FAN_RAMP_TEMP => { - fan_set_var(instance_id, fan::Request::SetRampTemp(utils::dk_to_c(set_var))).await + fan_set_var(instance_id, fan::Request::SetRampTemp(utils::dk_to_c(set_var.into()))).await } uuid_standard::FAN_MAX_TEMP => { - fan_set_var(instance_id, fan::Request::SetMaxTemp(utils::dk_to_c(set_var))).await + fan_set_var(instance_id, fan::Request::SetMaxTemp(utils::dk_to_c(set_var.into()))).await } // TODO: What does it mean to set the min/max RPM? Aren't these hardware defined? uuid_standard::FAN_MIN_RPM => { @@ -99,12 +105,12 @@ async fn set_var_handler( // TODO: Allow OEM to handle these? uuid => { error!("Received SetVar for unrecognized UUID: {:?}", uuid); - Err(thermal_service_messages::ThermalError::InvalidParameter) + Err(ThermalError::InvalidParameter) } } } -async fn sensor_get_warn_thrs(instance_id: u8) -> thermal_service_messages::ThermalResult { +async fn sensor_get_warn_thrs(instance_id: u8) -> ThermalResult { let low = ts::execute_sensor_request( sensor::DeviceId(instance_id), sensor::Request::GetThreshold(sensor::ThresholdType::WarnLow), @@ -118,13 +124,13 @@ async fn sensor_get_warn_thrs(instance_id: u8) -> thermal_service_messages::Ther match (low, high) { (Ok(sensor::ResponseData::Threshold(low)), Ok(sensor::ResponseData::Threshold(high))) => { - Ok(thermal_service_messages::ThermalResponse::ThermalGetThrsResponse { - timeout: 0, + Ok(ThermalResponse::ThermalGetThrsResponse(ThermalGetThrsResponse { + timeout: 0.into(), low: utils::c_to_dk(low), high: utils::c_to_dk(high), - }) + })) } - _ => Err(thermal_service_messages::ThermalError::InvalidParameter), + _ => Err(ThermalError::InvalidParameter), } } @@ -133,7 +139,7 @@ async fn sensor_set_warn_thrs( _timeout: Milliseconds, low: DeciKelvin, high: DeciKelvin, -) -> thermal_service_messages::ThermalResult { +) -> ThermalResult { let low_res = ts::execute_sensor_request( sensor::DeviceId(instance_id), sensor::Request::SetThreshold(sensor::ThresholdType::WarnLow, utils::dk_to_c(low)), @@ -146,9 +152,9 @@ async fn sensor_set_warn_thrs( .await; if low_res.is_ok() && high_res.is_ok() { - Ok(thermal_service_messages::ThermalResponse::ThermalSetThrsResponse) + Ok(ThermalResponse::ThermalSetThrsResponse) } else { - Err(thermal_service_messages::ThermalError::InvalidParameter) + Err(ThermalError::InvalidParameter) } } @@ -162,82 +168,76 @@ async fn sensor_get_thrs( ) .await { - Ok(sensor::ResponseData::Temp(temp)) => Ok(thermal_service_messages::ThermalResponse::ThermalGetVarResponse { + Ok(sensor::ResponseData::Temp(temp)) => Ok(ThermalResponse::ThermalGetVarResponse(ThermalGetVarResponse { val: utils::c_to_dk(temp), - }), - _ => Err(thermal_service_messages::ThermalError::HardwareError), + })), + _ => Err(ThermalError::HardwareError), } } -async fn fan_get_temp(instance: u8, fan_request: fan::Request) -> thermal_service_messages::ThermalResult { +async fn fan_get_temp(instance: u8, fan_request: fan::Request) -> ThermalResult { match ts::execute_fan_request(fan::DeviceId(instance), fan_request).await { - Ok(fan::ResponseData::Temp(temp)) => Ok(thermal_service_messages::ThermalResponse::ThermalGetVarResponse { + Ok(fan::ResponseData::Temp(temp)) => Ok(ThermalResponse::ThermalGetVarResponse(ThermalGetVarResponse { val: utils::c_to_dk(temp), - }), - _ => Err(thermal_service_messages::ThermalError::HardwareError), + })), + _ => Err(ThermalError::HardwareError), } } -async fn fan_get_rpm(instance: u8, fan_request: fan::Request) -> thermal_service_messages::ThermalResult { +async fn fan_get_rpm(instance: u8, fan_request: fan::Request) -> ThermalResult { match ts::execute_fan_request(fan::DeviceId(instance), fan_request).await { - Ok(fan::ResponseData::Rpm(rpm)) => { - Ok(thermal_service_messages::ThermalResponse::ThermalGetVarResponse { val: rpm.into() }) - } - _ => Err(thermal_service_messages::ThermalError::HardwareError), + Ok(fan::ResponseData::Rpm(rpm)) => Ok(ThermalResponse::ThermalGetVarResponse(ThermalGetVarResponse { + val: u32::from(rpm).into(), + })), + _ => Err(ThermalError::HardwareError), } } -async fn sensor_set_thrs( - instance: u8, - threshold_type: sensor::ThresholdType, - threshold_dk: u32, -) -> thermal_service_messages::ThermalResult { +async fn sensor_set_thrs(instance: u8, threshold_type: sensor::ThresholdType, threshold_dk: u32) -> ThermalResult { match ts::execute_sensor_request( sensor::DeviceId(instance), - sensor::Request::SetThreshold(threshold_type, utils::dk_to_c(threshold_dk)), + sensor::Request::SetThreshold(threshold_type, utils::dk_to_c(threshold_dk.into())), ) .await { - Ok(sensor::ResponseData::Success) => Ok(thermal_service_messages::ThermalResponse::ThermalSetVarResponse), - _ => Err(thermal_service_messages::ThermalError::HardwareError), + Ok(sensor::ResponseData::Success) => Ok(ThermalResponse::ThermalSetVarResponse), + _ => Err(ThermalError::HardwareError), } } -async fn fan_set_var(instance: u8, fan_request: fan::Request) -> thermal_service_messages::ThermalResult { +async fn fan_set_var(instance: u8, fan_request: fan::Request) -> ThermalResult { match ts::execute_fan_request(fan::DeviceId(instance), fan_request).await { - Ok(fan::ResponseData::Success) => Ok(thermal_service_messages::ThermalResponse::ThermalSetVarResponse), - _ => Err(thermal_service_messages::ThermalError::HardwareError), + Ok(fan::ResponseData::Success) => Ok(ThermalResponse::ThermalSetVarResponse), + _ => Err(ThermalError::HardwareError), } } -pub(crate) async fn process_request( - request: &thermal_service_messages::ThermalRequest, -) -> thermal_service_messages::ThermalResult { +pub(crate) async fn process_request(request: &ThermalRequest) -> ThermalResult { match request { - thermal_service_messages::ThermalRequest::ThermalGetTmpRequest { instance_id } => { + ThermalRequest::ThermalGetTmpRequest(ThermalGetTmpRequest { instance_id }) => { sensor_get_tmp(*instance_id).await } - thermal_service_messages::ThermalRequest::ThermalSetThrsRequest { + ThermalRequest::ThermalSetThrsRequest(ThermalSetThrsRequest { instance_id, timeout, low, high, - } => sensor_set_warn_thrs(*instance_id, *timeout, *low, *high).await, - thermal_service_messages::ThermalRequest::ThermalGetThrsRequest { instance_id } => { + }) => sensor_set_warn_thrs(*instance_id, *timeout, *low, *high).await, + ThermalRequest::ThermalGetThrsRequest(ThermalGetThrsRequest { instance_id }) => { sensor_get_warn_thrs(*instance_id).await } // TODO: How do we handle this generically? - thermal_service_messages::ThermalRequest::ThermalSetScpRequest { .. } => todo!(), - thermal_service_messages::ThermalRequest::ThermalGetVarRequest { + ThermalRequest::ThermalSetScpRequest(ThermalSetScpRequest { .. }) => todo!(), + ThermalRequest::ThermalGetVarRequest(ThermalGetVarRequest { instance_id, len: _len, var_uuid, - } => get_var_handler(*instance_id, *var_uuid).await, - thermal_service_messages::ThermalRequest::ThermalSetVarRequest { + }) => get_var_handler(*instance_id, *var_uuid).await, + ThermalRequest::ThermalSetVarRequest(ThermalSetVarRequest { instance_id, len: _len, var_uuid, set_var, - } => set_var_handler(*instance_id, *var_uuid, *set_var).await, + }) => set_var_handler(*instance_id, *var_uuid, set_var.get()).await, } } diff --git a/thermal-service/src/utils.rs b/thermal-service/src/utils.rs index 58c70c12..250fa13a 100644 --- a/thermal-service/src/utils.rs +++ b/thermal-service/src/utils.rs @@ -42,10 +42,11 @@ impl SampleBuf { /// Convert deciKelvin to degrees Celsius pub const fn dk_to_c(dk: thermal_service_messages::DeciKelvin) -> f32 { - (dk as f32 / 10.0) - 273.15 + (dk.get() as f32 / 10.0) - 273.15 } /// Convert degrees Celsius to deciKelvin pub const fn c_to_dk(c: f32) -> thermal_service_messages::DeciKelvin { - ((c + 273.15) * 10.0) as thermal_service_messages::DeciKelvin + let dk = ((c + 273.15) * 10.0) as u32; + thermal_service_messages::DeciKelvin::new(dk) }