ipmi_rs_core/connection/
mod.rs1#![deny(missing_docs)]
2mod completion_code;
5use std::num::NonZeroU8;
6
7pub use completion_code::CompletionErrorCode;
8
9mod netfn;
10pub use netfn::NetFn;
11
12mod request;
13pub use request::{Request, RequestTargetAddress};
14
15mod response;
16pub use response::Response;
17
18#[derive(Copy, Clone, Debug, PartialEq)]
20pub struct Address(pub u8);
21
22#[derive(Copy, Clone, Debug, PartialEq)]
26pub struct ChannelNumber(NonZeroU8);
27
28impl ChannelNumber {
29 pub fn new(value: NonZeroU8) -> Option<Self> {
33 if value.get() <= 0xB {
34 Some(Self(value))
35 } else {
36 None
37 }
38 }
39
40 pub fn value(&self) -> NonZeroU8 {
45 self.0
46 }
47}
48
49#[derive(Copy, Clone, Debug, PartialEq)]
51pub enum Channel {
52 Primary,
54 Numbered(ChannelNumber),
56 System,
58 Current,
60}
61
62impl Channel {
63 pub fn new(value: u8) -> Option<Self> {
67 match value {
68 0 => Some(Self::Primary),
69 0xE => Some(Self::Current),
70 0xF => Some(Self::System),
71 v => Some(Self::Numbered(ChannelNumber::new(NonZeroU8::new(v)?)?)),
72 }
73 }
74
75 pub fn value(&self) -> u8 {
80 match self {
81 Channel::Primary => 0x0,
82 Channel::Numbered(v) => v.value().get(),
83 Channel::Current => 0xE,
84 Channel::System => 0xF,
85 }
86 }
87}
88
89impl core::fmt::Display for Channel {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 match self {
92 Channel::Primary => write!(f, "Primary channel"),
93 Channel::Numbered(number) => write!(f, "Channel 0x{:01X}", number.value()),
94 Channel::Current => write!(f, "Current channel"),
95 Channel::System => write!(f, "System channel"),
96 }
97 }
98}
99
100#[derive(Clone, Copy, Debug, PartialEq)]
102#[allow(missing_docs)]
103pub enum LogicalUnit {
104 Zero,
105 One,
106 Two,
107 Three,
108}
109
110impl LogicalUnit {
111 pub fn from_low_bits(value: u8) -> Self {
114 let value = value & 0b11;
115
116 match value {
117 0b00 => Self::Zero,
118 0b01 => Self::One,
119 0b10 => Self::Two,
120 0b11 => Self::Three,
121 _ => unreachable!("Value bitmasked with 0b11 has value greater than 3"),
122 }
123 }
124}
125
126impl TryFrom<u8> for LogicalUnit {
127 type Error = ();
128
129 fn try_from(value: u8) -> Result<Self, Self::Error> {
130 if value <= 0b11 {
131 Ok(Self::from_low_bits(value))
132 } else {
133 Err(())
134 }
135 }
136}
137
138impl LogicalUnit {
139 pub fn value(&self) -> u8 {
143 match self {
144 LogicalUnit::Zero => 0,
145 LogicalUnit::One => 1,
146 LogicalUnit::Two => 2,
147 LogicalUnit::Three => 3,
148 }
149 }
150}
151
152impl From<LogicalUnit> for u8 {
153 fn from(value: LogicalUnit) -> Self {
154 value.value()
155 }
156}
157
158#[derive(Debug, Clone, Copy, PartialEq)]
161pub struct NotEnoughData;
162
163pub trait IpmiConnection {
165 type SendError: core::fmt::Debug;
167 type RecvError: core::fmt::Debug;
169 type Error: core::fmt::Debug + From<Self::SendError> + From<Self::RecvError>;
171
172 fn send(&mut self, request: &mut Request) -> Result<(), Self::SendError>;
174
175 fn recv(&mut self) -> Result<Response, Self::RecvError>;
177
178 fn send_recv(&mut self, request: &mut Request) -> Result<Response, Self::Error>;
180}
181
182#[derive(Clone, Debug, PartialEq)]
184pub struct Message {
185 netfn: u8,
186 cmd: u8,
187 data: Vec<u8>,
188}
189
190impl Message {
191 pub fn new_request(netfn: NetFn, cmd: u8, data: Vec<u8>) -> Self {
193 Self {
194 netfn: netfn.request_value(),
195 cmd,
196 data,
197 }
198 }
199
200 pub fn new_response(netfn: NetFn, cmd: u8, data: Vec<u8>) -> Self {
202 Self {
203 netfn: netfn.response_value(),
204 cmd,
205 data,
206 }
207 }
208
209 pub fn new_raw(netfn: u8, cmd: u8, data: Vec<u8>) -> Self {
211 Self { netfn, cmd, data }
212 }
213
214 pub fn netfn(&self) -> NetFn {
216 NetFn::from(self.netfn)
217 }
218
219 pub fn netfn_raw(&self) -> u8 {
221 self.netfn
222 }
223
224 pub fn cmd(&self) -> u8 {
226 self.cmd
227 }
228
229 pub fn data(&self) -> &[u8] {
231 &self.data
232 }
233
234 pub fn data_mut(&mut self) -> &mut [u8] {
236 &mut self.data
237 }
238}
239
240pub trait IpmiCommand: Into<Message> {
243 type Output;
245 type Error;
248
249 #[allow(unused)]
258 fn handle_completion_code(
259 completion_code: CompletionErrorCode,
260 data: &[u8],
261 ) -> Option<Self::Error> {
262 None
263 }
264
265 fn parse_success_response(data: &[u8]) -> Result<Self::Output, Self::Error>;
268
269 fn target(&self) -> Option<(Address, Channel)> {
271 None
272 }
273}