1use std::{
7 sync::{Arc, Mutex},
8 time::{Duration, Instant},
9};
10
11pub use embedded_hal::spi::Mode as SpiMode;
12use rusb::{Context as UsbContext, Device as UsbDevice, DeviceDescriptor};
13
14pub mod device;
15pub mod manager;
16pub mod prelude;
17
18use crate::device::*;
19pub use crate::device::{GpioLevel, GpioMode, SpiClock, SpiConfig, UsbOptions};
20
21#[derive(Debug, thiserror::Error)]
22pub enum Error {
23 #[error("USB error: {0}")]
25 Usb(rusb::Error),
26
27 #[error("No matching endpoint languages found")]
28 NoLanguages,
29
30 #[error("No valid endpoint configuration found")]
31 Configurations,
32 #[error("No matching endpoint found")]
33 Endpoint,
34 #[error("GPIO pin already in use")]
35 GpioInUse,
36 #[error("Invalid SPI index")]
37 InvalidIndex,
38 #[error("Invalid SPI baud rate")]
39 InvalidBaud,
40}
41
42impl From<rusb::Error> for Error {
43 fn from(e: rusb::Error) -> Self {
44 Error::Usb(e)
45 }
46}
47
48pub struct Cp2130 {
50 inner: Arc<Mutex<Inner>>,
51 info: Info,
52}
53
54pub trait Device {
56 fn spi_read(&self, buff: &mut [u8]) -> Result<usize, Error>;
58
59 fn spi_write(&self, buff: &[u8]) -> Result<(), Error>;
61
62 fn spi_write_read(&self, buff_out: &[u8], buff_in: &mut [u8]) -> Result<usize, Error>;
64
65 fn version(&self) -> Result<u16, Error>;
67
68 fn set_gpio_mode_level(&self, pin: u8, mode: GpioMode, level: GpioLevel) -> Result<(), Error>;
70
71 fn get_gpio_values(&self) -> Result<GpioLevels, Error>;
73
74 fn get_gpio_level(&self, pin: u8) -> Result<bool, Error>;
76}
77
78impl Cp2130 {
79 pub fn new(
81 device: UsbDevice<UsbContext>,
82 descriptor: DeviceDescriptor,
83 options: UsbOptions,
84 ) -> Result<Self, Error> {
85 let (inner, info) = Inner::new(device, descriptor, options)?;
87 let inner = Arc::new(Mutex::new(inner));
88
89 Ok(Self { info, inner })
91 }
92
93 pub fn info(&self) -> Info {
95 self.info.clone()
96 }
97
98 pub fn reset(&self) -> Result<(), Error> {
99 self.inner.lock().unwrap().reset()
100 }
101
102 pub fn spi(&self, channel: u8, config: SpiConfig, cs_pin: Option<u8>) -> Result<Spi, Error> {
104 let mut inner = self.inner.lock().unwrap();
105
106 if let Some(cs) = cs_pin {
108 inner.set_gpio_mode_level(cs, GpioMode::PushPull, GpioLevel::High)?;
109 }
110
111 inner.spi_configure(channel, config)?;
113
114 Ok(Spi {
115 inner: self.inner.clone(),
116 _channel: channel,
117 cs: cs_pin,
118 })
119 }
120
121 pub fn gpio_out(
123 &self,
124 index: u8,
125 mode: GpioMode,
126 level: GpioLevel,
127 ) -> Result<OutputPin, Error> {
128 let mut inner = self.inner.lock().unwrap();
129
130 if inner.gpio_allocated[index as usize] {
131 return Err(Error::GpioInUse);
132 }
133
134 inner.set_gpio_mode_level(index, mode, level)?;
135 inner.gpio_allocated[index as usize] = true;
136
137 Ok(OutputPin {
138 index,
139 mode,
140 inner: self.inner.clone(),
141 })
142 }
143
144 pub fn gpio_in(&self, index: u8) -> Result<InputPin, Error> {
146 let mut inner = self.inner.lock().unwrap();
147
148 if inner.gpio_allocated[index as usize] {
149 return Err(Error::GpioInUse);
150 }
151
152 inner.set_gpio_mode_level(index, GpioMode::Input, GpioLevel::Low)?;
153 inner.gpio_allocated[index as usize] = true;
154
155 Ok(InputPin {
156 index,
157 inner: self.inner.clone(),
158 })
159 }
160}
161
162impl Device for Cp2130 {
164 fn spi_read(&self, buff: &mut [u8]) -> Result<usize, Error> {
165 let mut inner = self.inner.lock().unwrap();
166 inner.spi_read(buff)
167 }
168
169 fn spi_write(&self, buff: &[u8]) -> Result<(), Error> {
170 let mut inner = self.inner.lock().unwrap();
171 inner.spi_write(buff)
172 }
173
174 fn spi_write_read(&self, buff_out: &[u8], buff_in: &mut [u8]) -> Result<usize, Error> {
175 let mut inner = self.inner.lock().unwrap();
176 inner.spi_write_read(buff_out, buff_in)
177 }
178
179 fn version(&self) -> Result<u16, Error> {
180 let mut inner = self.inner.lock().unwrap();
181 inner.version()
182 }
183
184 fn set_gpio_mode_level(&self, pin: u8, mode: GpioMode, level: GpioLevel) -> Result<(), Error> {
185 let mut inner = self.inner.lock().unwrap();
186 inner.set_gpio_mode_level(pin, mode, level)
187 }
188
189 fn get_gpio_values(&self) -> Result<GpioLevels, Error> {
190 let mut inner = self.inner.lock().unwrap();
191 inner.get_gpio_values()
192 }
193
194 fn get_gpio_level(&self, pin: u8) -> Result<bool, Error> {
195 let mut inner = self.inner.lock().unwrap();
196 inner.get_gpio_level(pin)
197 }
198}
199
200pub struct Spi {
202 _channel: u8,
204 inner: Arc<Mutex<Inner>>,
206 cs: Option<u8>,
208}
209
210use embedded_hal::spi::Operation as SpiOp;
211
212impl embedded_hal::spi::SpiDevice<u8> for Spi {
213 fn transaction(&mut self, operations: &mut [SpiOp<'_, u8>]) -> Result<(), Self::Error> {
214 let mut i = self.inner.lock().unwrap();
215
216 if let Some(cs) = self.cs {
218 i.set_gpio_mode_level(cs, GpioMode::PushPull, GpioLevel::Low)?;
219 }
220
221 for o in operations {
222 let err = match o {
224 SpiOp::Write(w) => i.spi_write(w).err(),
225 SpiOp::Transfer(r, w) => i.spi_write_read(w, r).err(),
226 SpiOp::TransferInPlace(b) => {
227 let out = b.to_vec();
228 i.spi_write_read(&out, b).err()
229 }
230 SpiOp::Read(r) => {
231 let out = vec![0u8; r.len()];
232 i.spi_write_read(&out, r).err()
233 }
234 SpiOp::DelayNs(ns) => {
235 let now = Instant::now();
236 while now.elapsed() < Duration::from_nanos(*ns as u64) {}
237 None
238 }
239 };
240
241 if let Some(e) = err {
243 if let Some(cs) = self.cs {
245 i.set_gpio_mode_level(cs, GpioMode::PushPull, GpioLevel::High)?;
246 }
247
248 return Err(e);
250 }
251 }
252
253 if let Some(cs) = self.cs {
255 i.set_gpio_mode_level(cs, GpioMode::PushPull, GpioLevel::Low)?;
256 }
257
258 Ok(())
259 }
260}
261
262impl embedded_hal::spi::ErrorType for Spi {
263 type Error = Error;
264}
265
266impl embedded_hal::spi::Error for Error {
267 fn kind(&self) -> embedded_hal::spi::ErrorKind {
268 embedded_hal::spi::ErrorKind::Other
269 }
270}
271pub struct InputPin {
273 index: u8,
274 inner: Arc<Mutex<Inner>>,
275}
276
277impl embedded_hal::digital::InputPin for InputPin {
278 fn is_high(&mut self) -> Result<bool, Self::Error> {
279 self.inner.lock().unwrap().get_gpio_level(self.index)
280 }
281
282 fn is_low(&mut self) -> Result<bool, Self::Error> {
283 let v = self.is_high()?;
284 Ok(!v)
285 }
286}
287
288impl embedded_hal::digital::ErrorType for InputPin {
289 type Error = Error;
290}
291
292impl embedded_hal::digital::Error for Error {
293 fn kind(&self) -> embedded_hal::digital::ErrorKind {
294 embedded_hal::digital::ErrorKind::Other
295 }
296}
297
298pub struct OutputPin {
300 index: u8,
301 mode: GpioMode,
302 inner: Arc<Mutex<Inner>>,
303}
304
305impl embedded_hal::digital::OutputPin for OutputPin {
306 fn set_high(&mut self) -> Result<(), Self::Error> {
307 self.inner
308 .lock()
309 .unwrap()
310 .set_gpio_mode_level(self.index, self.mode, GpioLevel::High)
311 }
312
313 fn set_low(&mut self) -> Result<(), Self::Error> {
314 self.inner
315 .lock()
316 .unwrap()
317 .set_gpio_mode_level(self.index, self.mode, GpioLevel::Low)
318 }
319}
320
321impl embedded_hal::digital::ErrorType for OutputPin {
322 type Error = Error;
323}