1#![allow(async_fn_in_trait)]
2#![cfg_attr(not(test), no_std)]
3#![warn(missing_docs)]
4#![doc = include_str!(concat!("../", env!("CARGO_PKG_README")))]
5
6use core::fmt::{Debug, Display};
7use core::marker::PhantomData;
8
9mod buffer;
10mod command;
11mod fieldset;
12mod register;
13
14mod repeats;
15
16pub use buffer::*;
17pub use command::*;
18pub use fieldset::*;
19pub use register::*;
20
21pub use repeats::*;
22
23#[doc(hidden)]
24pub mod ops;
25
26#[cfg(feature = "macros")]
27pub use device_driver_macros::*;
28
29pub trait Block: Sized {
31 type Interface;
33 type RegisterAddressType: Address;
35 type CommandAddressType: Address;
37 type BufferAddressType: Address;
39 type RegisterAddressMode;
41
42 fn interface(&mut self) -> &mut Self::Interface;
45
46 fn bulk_read(
51 &mut self,
52 ) -> register::BulkRegisterOperation<
53 '_,
54 Self,
55 <Self::Interface as RegisterInterfaceBase>::AddressType,
56 (),
57 RO,
58 >
59 where
60 Self::Interface: RegisterInterfaceBase,
61 Self::RegisterAddressMode: AddressMode,
62 {
63 register::BulkRegisterOperation {
64 block: self,
65 start_address: None,
66 next_address: None,
67 field_sets: (),
68 _phantom: PhantomData,
69 }
70 }
71
72 fn bulk_write(
77 &mut self,
78 ) -> register::BulkRegisterOperation<
79 '_,
80 Self,
81 <Self::Interface as RegisterInterfaceBase>::AddressType,
82 (),
83 WO,
84 >
85 where
86 Self::Interface: RegisterInterfaceBase,
87 Self::RegisterAddressMode: AddressMode,
88 {
89 register::BulkRegisterOperation {
90 block: self,
91 start_address: None,
92 next_address: None,
93 field_sets: (),
94 _phantom: PhantomData,
95 }
96 }
97
98 fn bulk_modify(
103 &mut self,
104 ) -> register::BulkRegisterOperation<
105 '_,
106 Self,
107 <Self::Interface as RegisterInterfaceBase>::AddressType,
108 (),
109 RW,
110 >
111 where
112 Self::Interface: RegisterInterfaceBase,
113 Self::RegisterAddressMode: AddressMode,
114 {
115 register::BulkRegisterOperation {
116 block: self,
117 start_address: None,
118 next_address: None,
119 field_sets: (),
120 _phantom: PhantomData,
121 }
122 }
123}
124
125#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
127#[cfg_attr(feature = "defmt", derive(defmt::Format))]
128pub enum ByteOrder {
129 LE,
131 BE,
133}
134
135#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
138#[cfg_attr(feature = "defmt", derive(defmt::Format))]
139pub struct ConversionError<T> {
140 pub source: T,
142 pub target: &'static str,
144}
145
146impl<T: Display> Display for ConversionError<T> {
147 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
148 write!(
149 f,
150 "Could not convert value from `{}` to type `{}`",
151 self.source, self.target
152 )
153 }
154}
155
156impl<T: Display + Debug> core::error::Error for ConversionError<T> {}
157
158#[doc(hidden)]
159pub struct WO;
160#[doc(hidden)]
161pub struct RO;
162#[doc(hidden)]
163pub struct RW;
164
165#[doc(hidden)]
166pub trait ReadCapability {}
167#[doc(hidden)]
168pub trait WriteCapability {}
169
170impl WriteCapability for WO {}
171
172impl ReadCapability for RO {}
173
174impl WriteCapability for RW {}
175impl ReadCapability for RW {}
176
177trait SealedAddress {}
178
179#[expect(private_bounds, reason = "sealed on purpose")]
181#[cfg(feature = "defmt")]
182pub trait Address: Copy + Eq + Display + Debug + defmt::Format + SealedAddress {
183 #[doc(hidden)]
184 const ZERO: Self;
185 #[doc(hidden)]
186 fn add(self, val: i32) -> Self;
187}
188#[expect(private_bounds, reason = "sealed on purpose")]
190#[cfg(not(feature = "defmt"))]
191pub trait Address: Copy + Eq + Display + Debug + SealedAddress {
192 #[doc(hidden)]
193 const ZERO: Self;
194 #[doc(hidden)]
195 fn add(self, val: i32) -> Self;
196}
197
198impl SealedAddress for u8 {}
199impl Address for u8 {
200 const ZERO: Self = 0;
201 fn add(self, val: i32) -> Self {
202 (self as i32 + val).try_into().unwrap()
203 }
204}
205impl SealedAddress for u16 {}
206impl Address for u16 {
207 const ZERO: Self = 0;
208 fn add(self, val: i32) -> Self {
209 (self as i32 + val).try_into().unwrap()
210 }
211}
212impl SealedAddress for u32 {}
213impl Address for u32 {
214 const ZERO: Self = 0;
215 fn add(self, val: i32) -> Self {
216 self.checked_add_signed(val).unwrap()
217 }
218}
219impl SealedAddress for u64 {}
220impl Address for u64 {
221 const ZERO: Self = 0;
222 fn add(self, val: i32) -> Self {
223 self.checked_add_signed(val as i64).unwrap()
224 }
225}
226impl SealedAddress for i8 {}
227impl Address for i8 {
228 const ZERO: Self = 0;
229 fn add(self, val: i32) -> Self {
230 (self as i32 + val).try_into().unwrap()
231 }
232}
233impl SealedAddress for i16 {}
234impl Address for i16 {
235 const ZERO: Self = 0;
236 fn add(self, val: i32) -> Self {
237 (self as i32 + val).try_into().unwrap()
238 }
239}
240impl SealedAddress for i32 {}
241impl Address for i32 {
242 const ZERO: Self = 0;
243 fn add(self, val: i32) -> Self {
244 self + val
245 }
246}
247impl SealedAddress for i64 {}
248impl Address for i64 {
249 const ZERO: Self = 0;
250 fn add(self, val: i32) -> Self {
251 self + val as i64
252 }
253}
254
255#[diagnostic::on_unimplemented(
256 message = "no `register-address-mode` is specified in the driver, so bulk register operations are not possible",
257 label = "not supported for this driver",
258 note = "if you are the author of the driver, specify `register-address-mode` in the device config to enable this feature if the device supports it",
259 note = "not all devices support this feature"
260)]
261#[doc(hidden)]
262pub trait AddressMode {
263 #[doc(hidden)]
264 fn next_address<A: Address>(current_address: A, current_size: usize) -> A;
265}
266
267#[doc(hidden)]
268pub struct MappedAddressMode;
269impl AddressMode for MappedAddressMode {
270 #[inline]
271 fn next_address<A: Address>(current_address: A, current_size: usize) -> A {
272 current_address.add(current_size as i32)
276 }
277}
278
279#[doc(hidden)]
280pub struct IndexedAddressMode;
281impl AddressMode for IndexedAddressMode {
282 #[inline]
283 fn next_address<A: Address>(current_address: A, _current_size: usize) -> A {
284 current_address.add(1)
285 }
286}