@@ -9,35 +9,118 @@ use std::io;
99use std:: ops;
1010use std:: path:: Path ;
1111
12- /// Newtype around [`spidev:: Spidev`] that implements the ` embedded-hal` traits
12+ /// Spidev wrapper providing the embedded-hal [`SpiDevice`] trait.
1313///
14- /// [Delay operations][delay] are capped to 65535 microseconds.
14+ /// Use this struct when you want a single spidev device, using a Linux-managed CS (chip-select) pin,
15+ /// which is already defined in your device tree. Linux will handle sharing the bus
16+ /// between different SPI devices, even between different processes.
1517///
16- /// [`spidev::Spidev`]: https://docs.rs/spidev/0.5.2/spidev/struct.Spidev.html
17- /// [delay]: embedded_hal::spi::Operation::DelayUs
18- pub struct Spidev ( pub spidev:: Spidev ) ;
18+ /// You get an object that implements [`SpiDevice`], which is what most drivers require,
19+ /// but does not implement [`SpiBus`]. In some rare cases, you may require [`SpiBus`]
20+ /// instead; for that refer to [`SpidevBus`] below. You may also want to use [`SpiBus`]
21+ /// if you want to handle all the CS pins yourself using GPIO.
22+ ///
23+ /// This struct wraps a [`spidev::Spidev`] struct, so it can be constructed directly
24+ /// and the inner struct accessed if needed, for example to (re)configure the SPI settings.
25+ ///
26+ /// Note that [delay operations] on this device are capped to 65535 microseconds.
27+ ///
28+ /// [`SpiDevice`]: embedded_hal::spi::SpiDevice
29+ /// [`SpiBus`]: embedded_hal::spi::SpiBus
30+ /// [`spidev::Spidev`]: spidev::Spidev
31+ /// [delay operations]: embedded_hal::spi::Operation::DelayUs
32+ pub struct SpidevDevice ( pub spidev:: Spidev ) ;
33+
34+ /// Spidev wrapper providing the embedded-hal [`SpiBus`] trait.
35+ ///
36+ /// Use this struct when you require direct access to the underlying SPI bus, for
37+ /// example when you want to use GPIOs as software-controlled CS (chip-select) pins to share the
38+ /// bus with multiple devices, or because a driver requires the entire bus (for
39+ /// example to drive smart LEDs).
40+ ///
41+ /// Do not use this struct if you're accessing SPI devices that already appear in your
42+ /// device tree; you will not be able to drive CS pins that are already used by `spidev`
43+ /// as GPIOs. Instead use [`SpidevDevice`].
44+ ///
45+ /// This struct must still be created from a [`spidev::Spidev`] device, but there are two
46+ /// important notes:
47+ ///
48+ /// 1. The CS pin associated with this `spidev` device will be driven whenever any device accesses
49+ /// this bus, so it should be an unconnected or unused pin.
50+ /// 2. No other `spidev` device on the same bus may be used as long as this `SpidevBus` exists,
51+ /// as Linux will _not_ do anything to ensure this bus has exclusive access.
52+ ///
53+ /// It is recommended to use a dummy `spidev` device associated with an unused CS pin, and then use
54+ /// regular GPIOs as CS pins if required. If you are planning to share this bus using GPIOs, the
55+ /// [`embedded-hal-bus`] crate may be of interest.
56+ ///
57+ /// If necessary, you can [configure] the underlying [`spidev::Spidev`] instance with the
58+ /// [`SPI_NO_CS`] flag set to prevent any CS pin activity.
59+ ///
60+ /// [`SpiDevice`]: embedded_hal::spi::SpiDevice
61+ /// [`SpiBus`]: embedded_hal::spi::SpiBus
62+ /// [`embedded-hal-bus`]: https://docs.rs/embedded-hal-bus/
63+ /// [`spidev::Spidev`]: spidev::Spidev
64+ /// [delay operations]: embedded_hal::spi::Operation::DelayUs
65+ /// [configure]: spidev::Spidev::configure
66+ /// [`SPI_NO_CS`]: spidev::SpiModeFlags::SPI_NO_CS
67+ pub struct SpidevBus ( pub spidev:: Spidev ) ;
68+
69+ impl SpidevDevice {
70+ /// See [`spidev::Spidev::open`] for details.
71+ ///
72+ /// The provided `path` is for the specific device you wish to access.
73+ /// Access to the bus is shared with other devices via the Linux kernel.
74+ pub fn open < P > ( path : P ) -> Result < Self , SPIError >
75+ where
76+ P : AsRef < Path > ,
77+ {
78+ spidev:: Spidev :: open ( path)
79+ . map ( SpidevDevice )
80+ . map_err ( |e| e. into ( ) )
81+ }
82+ }
1983
20- impl Spidev {
21- /// See [`spidev::Spidev::open`][0] for details.
84+ impl SpidevBus {
85+ /// See [`spidev::Spidev::open`] for details.
2286 ///
23- /// [0]: https://docs.rs/spidev/0.5.2/spidev/struct.Spidev.html#method.open
87+ /// The provided `path` must be the _only_ device in use on its bus,
88+ /// and note its own CS pin will be asserted for all device access,
89+ /// so the path should be to a dummy device used only to access
90+ /// the underlying bus.
2491 pub fn open < P > ( path : P ) -> Result < Self , SPIError >
2592 where
2693 P : AsRef < Path > ,
2794 {
28- spidev:: Spidev :: open ( path) . map ( Spidev ) . map_err ( |e| e. into ( ) )
95+ spidev:: Spidev :: open ( path)
96+ . map ( SpidevBus )
97+ . map_err ( |e| e. into ( ) )
2998 }
3099}
31100
32- impl ops:: Deref for Spidev {
101+ impl ops:: Deref for SpidevDevice {
33102 type Target = spidev:: Spidev ;
34103
35104 fn deref ( & self ) -> & Self :: Target {
36105 & self . 0
37106 }
38107}
39108
40- impl ops:: DerefMut for Spidev {
109+ impl ops:: DerefMut for SpidevDevice {
110+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
111+ & mut self . 0
112+ }
113+ }
114+
115+ impl ops:: Deref for SpidevBus {
116+ type Target = spidev:: Spidev ;
117+
118+ fn deref ( & self ) -> & Self :: Target {
119+ & self . 0
120+ }
121+ }
122+
123+ impl ops:: DerefMut for SpidevBus {
41124 fn deref_mut ( & mut self ) -> & mut Self :: Target {
42125 & mut self . 0
43126 }
@@ -51,11 +134,15 @@ mod embedded_hal_impl {
51134 use std:: convert:: TryInto ;
52135 use std:: io:: { Read , Write } ;
53136
54- impl ErrorType for Spidev {
137+ impl ErrorType for SpidevDevice {
138+ type Error = SPIError ;
139+ }
140+
141+ impl ErrorType for SpidevBus {
55142 type Error = SPIError ;
56143 }
57144
58- impl SpiBus < u8 > for Spidev {
145+ impl SpiBus < u8 > for SpidevBus {
59146 fn read ( & mut self , words : & mut [ u8 ] ) -> Result < ( ) , Self :: Error > {
60147 self . 0 . read_exact ( words) . map_err ( |err| SPIError { err } )
61148 }
@@ -97,7 +184,7 @@ mod embedded_hal_impl {
97184 }
98185 }
99186
100- impl SpiDevice for Spidev {
187+ impl SpiDevice for SpidevDevice {
101188 /// Perform a transaction against the device. [Read more][transaction]
102189 ///
103190 /// [Delay operations][delay] are capped to 65535 microseconds.
0 commit comments