device_driver/
command.rs

1use core::marker::PhantomData;
2
3use crate::FieldSet;
4
5/// A trait to represent the interface to the device.
6///
7/// This is called to dispatch commands.
8pub trait CommandInterface {
9    /// The error type
10    type Error;
11    /// The address type used by this interface. Should likely be an integer.
12    type AddressType: Copy;
13
14    /// Dispatch a command on the device by sending the command.
15    ///
16    /// The input is the content that needs to be sent to the device.
17    /// The output is the buffer where the response needs to be written to.
18    ///
19    /// The slices are empty if the respective in or out fields are not specified.
20    fn dispatch_command(
21        &mut self,
22        address: Self::AddressType,
23        size_bits_in: u32,
24        input: &[u8],
25        size_bits_out: u32,
26        output: &mut [u8],
27    ) -> Result<(), Self::Error>;
28}
29
30/// A trait to represent the interface to the device.
31///
32/// This is called to asynchronously dispatch commands.
33pub trait AsyncCommandInterface {
34    /// The error type
35    type Error;
36    /// The address type used by this interface. Should likely be an integer.
37    type AddressType: Copy;
38
39    /// Dispatch a command on the device by sending the command.
40    ///
41    /// The input is the content that needs to be sent to the device.
42    /// The output is the buffer where the response needs to be written to.
43    ///
44    /// The slices are empty if the respective in or out fields are not specified.
45    async fn dispatch_command(
46        &mut self,
47        address: Self::AddressType,
48        size_bits_in: u32,
49        input: &[u8],
50        size_bits_out: u32,
51        output: &mut [u8],
52    ) -> Result<(), Self::Error>;
53}
54
55/// Intermediate type for doing command operations
56pub struct CommandOperation<'i, Interface, AddressType: Copy, InFieldSet, OutFieldSet> {
57    interface: &'i mut Interface,
58    address: AddressType,
59    _phantom: PhantomData<(InFieldSet, OutFieldSet)>,
60}
61
62impl<'i, Interface, AddressType: Copy, InFieldSet, OutFieldSet>
63    CommandOperation<'i, Interface, AddressType, InFieldSet, OutFieldSet>
64{
65    #[doc(hidden)]
66    pub fn new(interface: &'i mut Interface, address: AddressType) -> Self {
67        Self {
68            interface,
69            address,
70            _phantom: PhantomData,
71        }
72    }
73}
74
75/// Simple command
76impl<Interface, AddressType: Copy> CommandOperation<'_, Interface, AddressType, (), ()>
77where
78    Interface: CommandInterface<AddressType = AddressType>,
79{
80    /// Dispatch the command to the device
81    pub fn dispatch(self) -> Result<(), Interface::Error> {
82        self.interface
83            .dispatch_command(self.address, 0, &[], 0, &mut [])
84    }
85}
86
87/// Only input
88impl<Interface, AddressType: Copy, InFieldSet: FieldSet>
89    CommandOperation<'_, Interface, AddressType, InFieldSet, ()>
90where
91    Interface: CommandInterface<AddressType = AddressType>,
92{
93    /// Dispatch the command to the device
94    pub fn dispatch(self, f: impl FnOnce(&mut InFieldSet)) -> Result<(), Interface::Error> {
95        let mut in_fields = InFieldSet::new_with_zero();
96        f(&mut in_fields);
97
98        self.interface.dispatch_command(
99            self.address,
100            InFieldSet::SIZE_BITS,
101            in_fields.get_inner_buffer(),
102            0,
103            &mut [],
104        )
105    }
106}
107
108/// Only output
109impl<Interface, AddressType: Copy, OutFieldSet: FieldSet>
110    CommandOperation<'_, Interface, AddressType, (), OutFieldSet>
111where
112    Interface: CommandInterface<AddressType = AddressType>,
113{
114    /// Dispatch the command to the device
115    pub fn dispatch(self) -> Result<OutFieldSet, Interface::Error> {
116        let mut out_fields = OutFieldSet::new_with_zero();
117
118        self.interface.dispatch_command(
119            self.address,
120            0,
121            &[],
122            OutFieldSet::SIZE_BITS,
123            out_fields.get_inner_buffer_mut(),
124        )?;
125
126        Ok(out_fields)
127    }
128}
129
130/// Input and output
131impl<Interface, AddressType: Copy, InFieldSet: FieldSet, OutFieldSet: FieldSet>
132    CommandOperation<'_, Interface, AddressType, InFieldSet, OutFieldSet>
133where
134    Interface: CommandInterface<AddressType = AddressType>,
135{
136    /// Dispatch the command to the device
137    pub fn dispatch(
138        self,
139        f: impl FnOnce(&mut InFieldSet),
140    ) -> Result<OutFieldSet, Interface::Error> {
141        let mut in_fields = InFieldSet::new_with_zero();
142        f(&mut in_fields);
143
144        let mut out_fields = OutFieldSet::new_with_zero();
145
146        self.interface.dispatch_command(
147            self.address,
148            InFieldSet::SIZE_BITS,
149            in_fields.get_inner_buffer(),
150            OutFieldSet::SIZE_BITS,
151            out_fields.get_inner_buffer_mut(),
152        )?;
153
154        Ok(out_fields)
155    }
156}
157
158/// Simple command async
159impl<Interface, AddressType: Copy> CommandOperation<'_, Interface, AddressType, (), ()>
160where
161    Interface: AsyncCommandInterface<AddressType = AddressType>,
162{
163    /// Dispatch the command to the device
164    pub async fn dispatch_async(self) -> Result<(), Interface::Error> {
165        self.interface
166            .dispatch_command(self.address, 0, &[], 0, &mut [])
167            .await
168    }
169}
170
171/// Only input async
172impl<Interface, AddressType: Copy, InFieldSet: FieldSet>
173    CommandOperation<'_, Interface, AddressType, InFieldSet, ()>
174where
175    Interface: AsyncCommandInterface<AddressType = AddressType>,
176{
177    /// Dispatch the command to the device
178    pub async fn dispatch_async(
179        self,
180        f: impl FnOnce(&mut InFieldSet),
181    ) -> Result<(), Interface::Error> {
182        let mut in_fields = InFieldSet::new_with_zero();
183        f(&mut in_fields);
184
185        self.interface
186            .dispatch_command(
187                self.address,
188                InFieldSet::SIZE_BITS,
189                in_fields.get_inner_buffer(),
190                0,
191                &mut [],
192            )
193            .await
194    }
195}
196
197/// Only output async
198impl<Interface, AddressType: Copy, OutFieldSet: FieldSet>
199    CommandOperation<'_, Interface, AddressType, (), OutFieldSet>
200where
201    Interface: AsyncCommandInterface<AddressType = AddressType>,
202{
203    /// Dispatch the command to the device
204    pub async fn dispatch_async(self) -> Result<OutFieldSet, Interface::Error> {
205        let mut out_fields = OutFieldSet::new_with_zero();
206
207        self.interface
208            .dispatch_command(
209                self.address,
210                0,
211                &[],
212                OutFieldSet::SIZE_BITS,
213                out_fields.get_inner_buffer_mut(),
214            )
215            .await?;
216
217        Ok(out_fields)
218    }
219}
220
221/// Input and output async
222impl<Interface, AddressType: Copy, InFieldSet: FieldSet, OutFieldSet: FieldSet>
223    CommandOperation<'_, Interface, AddressType, InFieldSet, OutFieldSet>
224where
225    Interface: AsyncCommandInterface<AddressType = AddressType>,
226{
227    /// Dispatch the command to the device
228    pub async fn dispatch_async(
229        self,
230        f: impl FnOnce(&mut InFieldSet),
231    ) -> Result<OutFieldSet, Interface::Error> {
232        let mut in_fields = InFieldSet::new_with_zero();
233        f(&mut in_fields);
234
235        let mut out_fields = OutFieldSet::new_with_zero();
236
237        self.interface
238            .dispatch_command(
239                self.address,
240                InFieldSet::SIZE_BITS,
241                in_fields.get_inner_buffer(),
242                OutFieldSet::SIZE_BITS,
243                out_fields.get_inner_buffer_mut(),
244            )
245            .await?;
246
247        Ok(out_fields)
248    }
249}