smbus_request_parser/
lib.rs

1#![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}