1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use std::{iter, cmp};
use {Master, Address, BlockTransfer, ReadWrite, Smbus, Smbus20};

/// A wrapper around an `i2c::ReadWrite` that attempts to impl `Smbus`.
///
/// Repeated START is not supported, which may confuse some devices and
/// probably makes this a non-conforming implementation.
pub struct SmbusReadWrite<I>(pub I);

impl<I: ReadWrite> SmbusReadWrite<I> {
    fn _smbus_read_block(&mut self, value: &mut [u8]) -> Result<usize, I::Error> {
        let mut buffer = vec![0u8; value.len() + 1];
        self.i2c_read(&mut buffer)
            .map(|len| {
                let len = cmp::min(cmp::min(len, buffer[0] as usize), value.len());
                value[..len].copy_from_slice(&buffer[1..len + 1]);
                buffer[0] as usize
            })
    }
}

impl<I: Master> Master for SmbusReadWrite<I> {
    type Error = I::Error;
}

impl<I: Address> Address for SmbusReadWrite<I> {
    fn set_slave_address(&mut self, addr: u16, tenbit: bool) -> Result<(), Self::Error> {
        self.0.set_slave_address(addr, tenbit)
    }
}

impl<I: ReadWrite> ReadWrite for SmbusReadWrite<I> {
    fn i2c_read(&mut self, value: &mut [u8]) -> Result<usize, Self::Error> {
        self.0.i2c_read(value)
    }

    fn i2c_write(&mut self, value: &[u8]) -> Result<(), Self::Error> {
        self.0.i2c_write(value)
    }
}

impl<I: ReadWrite> Smbus for SmbusReadWrite<I> {
    fn smbus_write_quick(&mut self, value: bool) -> Result<(), Self::Error> {
        if value {
            self.i2c_read(&mut [])
                .map(drop)
        } else {
            self.i2c_write(&[])
        }
    }

    fn smbus_read_byte(&mut self) -> Result<u8, Self::Error> {
        let mut buf = [0u8; 1];
        self.i2c_read(&mut buf)
            .and_then(|len| if len == buf.len() {
                Ok(buf[0])
            } else {
                unimplemented!()
            })
    }

    fn smbus_write_byte(&mut self, value: u8) -> Result<(), Self::Error> {
        self.i2c_write(&[value])
    }

    fn smbus_read_byte_data(&mut self, command: u8) -> Result<u8, Self::Error> {
        self.smbus_write_byte(command)?;
        self.smbus_read_byte()
    }

    fn smbus_write_byte_data(&mut self, command: u8, value: u8) -> Result<(), Self::Error> {
        self.i2c_write(&[command, value])
    }

    fn smbus_read_word_data(&mut self, command: u8) -> Result<u16, Self::Error> {
        let mut buf = [0u8; 2];
        self.smbus_write_byte(command)?;
        self.i2c_read(&mut buf)
            .and_then(|len| if len == buf.len() {
                Ok(buf[0] as u16 | (buf[1] as u16) << 8)
            } else {
                unimplemented!()
            })
    }

    fn smbus_write_word_data(&mut self, command: u8, value: u16) -> Result<(), Self::Error> {
        self.i2c_write(&[command, value as u8, (value >> 8) as u8])
    }

    fn smbus_process_call(&mut self, command: u8, value: u16) -> Result<u16, Self::Error> {
        self.smbus_write_word_data(command, value)?;
        let mut buf = [0u8; 2];
        self.i2c_read(&mut buf)
            .and_then(|len| if len == buf.len() {
                Ok(buf[0] as u16 | (buf[1] as u16) << 8)
            } else {
                unimplemented!()
            })
    }

    fn smbus_read_block_data(&mut self, command: u8, value: &mut [u8]) -> Result<usize, Self::Error> {
        self.smbus_write_byte(command)?;
        self._smbus_read_block(value)
    }

    fn smbus_write_block_data(&mut self, command: u8, value: &[u8]) -> Result<(), Self::Error> {
        let buffer: Vec<_> = [command, value.len() as u8].iter().chain(value.iter()).cloned().collect();
        self.i2c_write(&buffer)
    }
}

impl<I: ReadWrite> BlockTransfer for SmbusReadWrite<I> {
    fn i2c_read_block_data(&mut self, command: u8, value: &mut [u8]) -> Result<usize, Self::Error> {
        self.smbus_write_byte(command)?;
        self.i2c_read(value)
    }

    fn i2c_write_block_data(&mut self, command: u8, value: &[u8]) -> Result<(), Self::Error> {
        let buffer: Vec<_> = iter::once(command).chain(value.iter().cloned()).collect();
        self.i2c_write(&buffer)
    }
}

impl<I: ReadWrite> Smbus20 for SmbusReadWrite<I> {
    fn smbus_process_call_block(&mut self, command: u8, write: &[u8], read: &mut [u8]) -> Result<usize, Self::Error> {
        self.smbus_write_block_data(command, write)?;
        self._smbus_read_block(read)
    }
}