i2cdev/
mock.rs

1// Copyright 2015, Paul Osborne <osbpau@gmail.com>
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/license/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option.  This file may not be copied, modified, or distributed
7// except according to those terms.
8use core::{I2CDevice, I2CMessage, I2CTransfer};
9use std::io;
10
11/// I2C mock result type
12pub type I2CResult<T> = io::Result<T>;
13
14/// Mock I2C device register map
15pub struct I2CRegisterMap {
16    registers: [u8; 0xFF],
17    offset: usize,
18}
19
20impl Default for I2CRegisterMap {
21    fn default() -> Self {
22        Self::new()
23    }
24}
25
26impl I2CRegisterMap {
27    /// Create new mock I2C register map
28    pub fn new() -> I2CRegisterMap {
29        I2CRegisterMap {
30            registers: [0x00; 0xFF],
31            offset: 0,
32        }
33    }
34
35    /// Set several registers starting at the given offset
36    pub fn write_regs(&mut self, offset: usize, data: &[u8]) {
37        println!("WRITE | 0x{:X} : {:?}", offset, data);
38        self.registers[offset..(data.len() + offset)].clone_from_slice(data);
39    }
40}
41
42impl I2CRegisterMap {
43    /// Read data from the device to fill the provided slice
44    fn read(&mut self, data: &mut [u8]) -> I2CResult<()> {
45        let len = data.len();
46        data.clone_from_slice(&self.registers[self.offset..(self.offset + len)]);
47        println!("READ  | 0x{:X} : {:?}", self.offset - data.len(), data);
48        Ok(())
49    }
50
51    /// Write the provided buffer to the device
52    fn write(&mut self, data: &[u8]) -> I2CResult<()> {
53        // ASSUMPTION: first byte sets the offset
54        // ASSUMPTION: write has length of at least one (will panic)
55        let offset = data[0] as usize;
56        let remdata = &data[1..];
57        self.write_regs(offset, remdata);
58        self.offset = offset + remdata.len();
59        Ok(())
60    }
61}
62
63/// Mock I2C device exposing a register map
64#[derive(Default)]
65pub struct MockI2CDevice {
66    /// I2C register map
67    pub regmap: I2CRegisterMap,
68}
69
70impl MockI2CDevice {
71    /// Create a new mock I2C device
72    pub fn new() -> MockI2CDevice {
73        MockI2CDevice {
74            regmap: I2CRegisterMap::new(),
75        }
76    }
77}
78
79impl I2CDevice for MockI2CDevice {
80    type Error = io::Error;
81
82    fn read(&mut self, data: &mut [u8]) -> I2CResult<()> {
83        self.regmap.read(data)
84    }
85
86    fn write(&mut self, data: &[u8]) -> I2CResult<()> {
87        self.regmap.write(data)
88    }
89
90    fn smbus_write_quick(&mut self, _bit: bool) -> I2CResult<()> {
91        unimplemented!()
92    }
93
94    fn smbus_read_block_data(&mut self, _register: u8) -> I2CResult<Vec<u8>> {
95        unimplemented!()
96    }
97
98    fn smbus_write_block_data(&mut self, _register: u8, _values: &[u8]) -> I2CResult<()> {
99        unimplemented!()
100    }
101
102    fn smbus_process_block(&mut self, _register: u8, _values: &[u8]) -> I2CResult<Vec<u8>> {
103        unimplemented!()
104    }
105
106    fn smbus_read_i2c_block_data(&mut self, _register: u8, _len: u8) -> I2CResult<Vec<u8>> {
107        unimplemented!()
108    }
109
110    fn smbus_write_i2c_block_data(&mut self, _register: u8, _values: &[u8]) -> I2CResult<()> {
111        unimplemented!()
112    }
113}
114
115#[derive(Debug)]
116enum MessageType<'a> {
117    Write(&'a [u8]),
118    Read(&'a mut [u8]),
119}
120
121/// Mock I2C message
122pub struct MockI2CMessage<'a> {
123    msg_type: MessageType<'a>,
124}
125
126impl<'a> I2CMessage<'a> for MockI2CMessage<'a> {
127    fn read(data: &'a mut [u8]) -> Self {
128        Self {
129            msg_type: MessageType::Read(data),
130        }
131    }
132
133    /// Write data to device
134    fn write(data: &'a [u8]) -> Self {
135        Self {
136            msg_type: MessageType::Write(data),
137        }
138    }
139}
140
141impl<'a> I2CTransfer<'a> for MockI2CDevice
142where
143    MockI2CDevice: I2CDevice,
144{
145    type Error = io::Error;
146    type Message = MockI2CMessage<'a>;
147
148    /// Issue the provided sequence of I2C transactions
149    fn transfer(&mut self, messages: &'a mut [Self::Message]) -> Result<u32, Self::Error> {
150        for msg in messages.iter_mut() {
151            match &mut msg.msg_type {
152                MessageType::Read(data) => self.read(data)?,
153                MessageType::Write(data) => self.write(data)?,
154            }
155        }
156        Ok(messages.len() as u32)
157    }
158}