1use crate::{error::*, protocol};
2use rusb::{Device, DeviceHandle, GlobalContext, UsbContext};
3use std::io::{Read, Write};
4
5pub struct I2c<T: UsbContext> {
6 device_handle: DeviceHandle<T>,
7 supported_flags: (i2c::ReadFlags, i2c::WriteFlags),
8 address: u16,
9}
10
11impl<T: UsbContext> I2c<T> {
12 #[inline]
13 fn open(device: &Device<T>) -> Result<Self> {
14 let device_handle = device.open()?;
15 device_handle.claim_interface(0)?;
16 let supported_flags = protocol::check_device(&device_handle)?;
17 Ok(Self {
18 device_handle,
19 supported_flags,
20 address: 0u16,
21 })
22 }
23}
24
25impl I2c<GlobalContext> {
26 pub fn open_single_device() -> Result<Self> {
27 let devs = crate::devices();
28 if devs.is_empty() {
29 return Err(rusb::Error::NoDevice.into());
30 }
31 if devs.len() > 1 {
32 return Err(rusb::Error::Other.into());
33 }
34 I2c::open(&devs[0])
35 }
36}
37
38impl<T: UsbContext> i2c::Master for I2c<T> {
39 type Error = Error;
40}
41
42impl<T: UsbContext> i2c::Address for I2c<T> {
43 fn set_slave_address(&mut self, addr: u16, tenbit: bool) -> Result<()> {
44 if tenbit {
45 Err(rusb::Error::NotSupported.into())
46 } else {
47 self.address = addr;
48 Ok(())
49 }
50 }
51}
52
53impl<T: UsbContext> Read for I2c<T> {
54 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
55 protocol::transfer(
56 &self.device_handle,
57 &mut [i2c::Message::Read {
58 address: self.address,
59 data: buf,
60 flags: Default::default(),
61 }],
62 )?;
63 Ok(buf.len())
64 }
65}
66
67impl<T: UsbContext> Write for I2c<T> {
68 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
69 protocol::transfer(
70 &self.device_handle,
71 &mut [i2c::Message::Write {
72 address: self.address,
73 data: buf,
74 flags: Default::default(),
75 }],
76 )?;
77 Ok(buf.len())
78 }
79
80 fn flush(&mut self) -> std::io::Result<()> {
81 Ok(()) }
83}
84
85#[allow(dead_code)]
87const fn assert_impl_readwrite<T: i2c::ReadWrite>() {}
88const _: () = assert_impl_readwrite::<I2c<GlobalContext>>();
89
90impl<T: UsbContext> i2c::BulkTransfer for I2c<T> {
91 fn i2c_transfer_support(&mut self) -> Result<(i2c::ReadFlags, i2c::WriteFlags)> {
92 Ok(self.supported_flags)
93 }
94
95 fn i2c_transfer(&mut self, messages: &mut [i2c::Message]) -> Result<()> {
96 protocol::transfer(&self.device_handle, messages)
97 }
98}