smbus_request_parser/
lib.rs1#![no_std]
2
3#[cfg(test)]
4extern crate std;
5
6#[cfg(test)]
7mod tests;
8
9pub trait CommandHandler {
10 fn handle_read_byte(&self) -> Option<u8>;
11 fn handle_read_byte_data(&self, reg: u8) -> Option<u8>;
12 fn handle_read_word_data(&self, reg: u8) -> Option<u16>;
13 fn handle_read_block_data(&self, reg: u8, index: u8) -> Option<u8>;
14
15 fn handle_write_byte(&mut self, data: u8) -> Result<(), ()>;
16 fn handle_write_byte_data(&mut self, reg: u8, data: u8) -> Result<(), ()>;
17 fn handle_write_word_data(&mut self, reg: u8, data: u16) -> Result<(), ()>;
18 fn handle_write_block_data(&mut self, reg: u8, count: u8, block: &[u8]) -> Result<(), ()>;
19
20 fn handle_i2c_event(
21 &mut self,
22 event: &mut I2CEvent,
23 mut bus_state: &mut SMBusState,
24 ) -> Result<(), SMBusProtocolError> {
25 match event {
26 I2CEvent::Initiated { direction } => bus_state.direction = Some(*direction),
27 I2CEvent::ReceivedByte { byte } => {
28 if bus_state.index >= RECEIVE_BUFFER_SIZE {
29 let err = Err(SMBusProtocolError::InvalidWriteBound(bus_state.index - 2));
30 *bus_state = SMBusState::default();
31 return err;
32 }
33 bus_state.received_data[bus_state.index as usize] = *byte;
34 bus_state.index += 1;
35 }
36 I2CEvent::RequestedByte { byte } => {
37 if bus_state.direction != Some(Direction::SlaveToMaster) {
38 return Err(SMBusProtocolError::WrongDirection(bus_state.direction));
39 }
40 match bus_state.index {
41 0 => {
42 if let Some(Direction::SlaveToMaster) = bus_state.direction {
43 if let Some(data) = self.handle_read_byte() {
44 **byte = data;
45 } else {
46 return Err(SMBusProtocolError::ReadByteUnsupported);
47 }
48 } else {
49 return Err(SMBusProtocolError::WrongDirection(bus_state.direction));
50 }
51 }
52 1 => {
53 let register = bus_state.received_data[0];
54 if let Some(data) = self.handle_read_byte_data(register) {
55 bus_state.current_transfer = Some(StatefulTransfer::ReadByte(data));
56 **byte = data;
57 } else if let Some(data) = self.handle_read_word_data(register) {
58 bus_state.current_transfer = Some(StatefulTransfer::ReadWord(data));
59 **byte = data as u8;
60 } else if let Some(data) = self.handle_read_block_data(register, 0) {
61 bus_state.current_transfer = Some(StatefulTransfer::ReadBlock(data));
62 **byte = data;
63 } else {
64 return Err(SMBusProtocolError::InvalidReadRegister(register));
65 }
66 }
67 2 => {
68 let first_byte = bus_state.received_data[0];
69 match bus_state.current_transfer {
70 Some(StatefulTransfer::ReadByte(_)) => {},
71 Some(StatefulTransfer::ReadWord(data)) => {
72 **byte = (data >> 8) as u8;
73 bus_state.current_transfer = None;
74 }
75 Some(StatefulTransfer::ReadBlock(_)) => {
76 if let Some(data) = self.handle_read_block_data(first_byte, 1) {
77 **byte = data;
78 } else {
79 return Err(SMBusProtocolError::InvalidReadBound(1));
80 }
81 }
82 _ => return Err(SMBusProtocolError::InvalidReadBound(2)),
83 }
84 }
85 n => {
86 if let Some(StatefulTransfer::ReadBlock(_)) = bus_state.current_transfer {
87 if let Some(data) =
88 self.handle_read_block_data(bus_state.received_data[0], n - 1)
89 {
90 **byte = data;
91 }
92 }
93 }
94 }
95 bus_state.index += 1;
96 }
97 I2CEvent::Stopped => {
98 if bus_state.direction == Some(Direction::MasterToSlave) {
99 match bus_state.index {
100 0 => return Err(SMBusProtocolError::QuickCommandUnsupported),
101 1 => {
102 if let Err(()) = self.handle_write_byte(bus_state.received_data[0]) {
103 return Err(SMBusProtocolError::WriteByteUnsupported);
104 }
105 }
106 2 => {
107 if let Err(()) = self.handle_write_byte_data(
108 bus_state.received_data[0],
109 bus_state.received_data[1],
110 ) {
111 return Err(SMBusProtocolError::InvalidWriteRegister(
112 bus_state.received_data[0],
113 ));
114 }
115 }
116 3 => {
117 let data: u16 = bus_state.received_data[1] as u16
118 | (bus_state.received_data[2] as u16) << 8;
119 if let Err(()) =
120 self.handle_write_word_data(bus_state.received_data[0], data)
121 {
122 return Err(SMBusProtocolError::InvalidWriteRegister(
123 bus_state.received_data[0],
124 ));
125 };
126 }
127 4..=RECEIVE_BUFFER_SIZE => {
128 let reg = bus_state.received_data[0];
129 let count = bus_state.received_data[1];
130 if count > 32 {
131 return Err(SMBusProtocolError::InvalidWriteBlockSize(count));
132 }
133 let slice = &bus_state.received_data[2usize..count as usize + 2];
134 if let Err(()) = self.handle_write_block_data(reg, count, slice) {
135 return Err(SMBusProtocolError::InvalidWriteBound(count));
136 }
137 }
138 n => return Err(SMBusProtocolError::InvalidWriteBound(n))
139 };
140 }
141 bus_state.received_data.iter_mut().for_each(|x| *x = 0);
142 bus_state.index = 0;
143 bus_state.direction = None;
144 }
145 }
146 return Ok(());
147 }
148}
149
150#[derive(Debug, Copy, Clone, Eq, PartialEq)]
151pub enum Direction {
152 MasterToSlave,
153 SlaveToMaster,
154}
155
156#[derive(Debug)]
157pub enum I2CEvent<'a> {
158 Initiated { direction: Direction },
159 ReceivedByte { byte: u8 },
160 RequestedByte { byte: &'a mut u8 },
161 Stopped,
162}
163
164#[derive(Debug, PartialEq, Eq)]
165enum StatefulTransfer {
166 ReadByte(u8),
167 ReadWord(u16),
168 ReadBlock(u8),
169}
170
171const RECEIVE_BUFFER_SIZE: u8 = 34;
172
173#[derive(Debug)]
174pub struct SMBusState {
175 index: u8,
176 received_data: [u8; RECEIVE_BUFFER_SIZE as usize],
177 direction: Option<Direction>,
178 current_transfer: Option<StatefulTransfer>,
179}
180
181impl Default for SMBusState {
182 fn default() -> Self {
183 Self {
184 index: 0,
185 received_data: [0; RECEIVE_BUFFER_SIZE as usize],
186 direction: None,
187 current_transfer: None,
188 }
189 }
190}
191
192#[derive(Debug, Eq, PartialEq, Clone, Copy)]
193pub enum SMBusProtocolError {
194 WrongDirection(Option<Direction>),
195 QuickCommandUnsupported,
196 UnsupportedBlockLength(u8),
197 ReadByteUnsupported,
198 WriteByteUnsupported,
199 InvalidWriteBound(u8),
200 InvalidReadBound(u8),
201 InvalidWriteBlockSize(u8),
202 InvalidReadBlockSize(u8),
203 InvalidReadRegister(u8),
204 InvalidWriteRegister(u8),
205}