@@ -22,13 +22,8 @@ pub trait SpiDevice: ErrorType {
2222 where
2323 Self : ' a ,
2424 R : ' a ,
25- F : FnOnce ( & ' a mut Self :: Bus ) -> Fut + ' a ,
26- Fut : Future <
27- Output = (
28- & ' a mut Self :: Bus ,
29- Result < R , <Self :: Bus as ErrorType >:: Error > ,
30- ) ,
31- > + ' a ;
25+ F : FnOnce ( * mut Self :: Bus ) -> Fut + ' a ,
26+ Fut : Future < Output = Result < R , <Self :: Bus as ErrorType >:: Error > > + ' a ;
3227
3328 /// Perform a transaction against the device.
3429 ///
@@ -42,15 +37,14 @@ pub trait SpiDevice: ErrorType {
4237 /// The locking mechanism is implementation-defined. The only requirement is it must prevent two
4338 /// transactions from executing concurrently against the same bus. Examples of implementations are:
4439 /// critical sections, blocking mutexes, async mutexes, returning an error or panicking if the bus is already busy.
40+ ///
41+ /// The current state of the Rust typechecker doesn't allow expressing the necessary lifetime constraints, so
42+ /// the `f` closure receives a lifetime-less `*mut Bus` raw pointer instead. The pointer is guaranteed
43+ /// to be valid for the entire duration the closure is running, so dereferencing it is safe.
4544 fn transaction < ' a , R , F , Fut > ( & ' a mut self , f : F ) -> Self :: TransactionFuture < ' a , R , F , Fut >
4645 where
47- F : FnOnce ( & ' a mut Self :: Bus ) -> Fut + ' a ,
48- Fut : Future <
49- Output = (
50- & ' a mut Self :: Bus ,
51- Result < R , <Self :: Bus as ErrorType >:: Error > ,
52- ) ,
53- > + ' a ;
46+ F : FnOnce ( * mut Self :: Bus ) -> Fut + ' a ,
47+ Fut : Future < Output = Result < R , <Self :: Bus as ErrorType >:: Error > > + ' a ;
5448}
5549
5650/// Helper methods for SpiDevice.
@@ -147,8 +141,9 @@ impl<T: SpiDevice> SpiDeviceExt for T {
147141 Word : Copy + ' static ,
148142 {
149143 self . transaction ( move |bus| async move {
150- let res = bus. read ( buf) . await ;
151- ( bus, res)
144+ // safety: `bus` is a valid pointer we're allowed to use for the duration of the closure.
145+ let bus = unsafe { & mut * bus } ;
146+ bus. read ( buf) . await
152147 } )
153148 }
154149
@@ -164,8 +159,9 @@ impl<T: SpiDevice> SpiDeviceExt for T {
164159 Word : Copy + ' static ,
165160 {
166161 self . transaction ( move |bus| async move {
167- let res = bus. write ( buf) . await ;
168- ( bus, res)
162+ // safety: `bus` is a valid pointer we're allowed to use for the duration of the closure.
163+ let bus = unsafe { & mut * bus } ;
164+ bus. write ( buf) . await
169165 } )
170166 }
171167
@@ -185,8 +181,9 @@ impl<T: SpiDevice> SpiDeviceExt for T {
185181 Word : Copy + ' static ,
186182 {
187183 self . transaction ( move |bus| async move {
188- let res = bus. transfer ( read, write) . await ;
189- ( bus, res)
184+ // safety: `bus` is a valid pointer we're allowed to use for the duration of the closure.
185+ let bus = unsafe { & mut * bus } ;
186+ bus. transfer ( read, write) . await
190187 } )
191188 }
192189
@@ -205,8 +202,9 @@ impl<T: SpiDevice> SpiDeviceExt for T {
205202 Word : Copy + ' static ,
206203 {
207204 self . transaction ( move |bus| async move {
208- let res = bus. transfer_in_place ( buf) . await ;
209- ( bus, res)
205+ // safety: `bus` is a valid pointer we're allowed to use for the duration of the closure.
206+ let bus = unsafe { & mut * bus } ;
207+ bus. transfer_in_place ( buf) . await
210208 } )
211209 }
212210}
@@ -216,18 +214,13 @@ impl<T: SpiDevice> SpiDevice for &mut T {
216214
217215 type TransactionFuture < ' a , R , F , Fut > = T :: TransactionFuture < ' a , R , F , Fut >
218216 where
219- Self : ' a , R : ' a , F : FnOnce ( & ' a mut Self :: Bus ) -> Fut + ' a ,
220- Fut : Future < Output = ( & ' a mut Self :: Bus , Result < R , <Self :: Bus as ErrorType >:: Error > ) > + ' a ;
217+ Self : ' a , R : ' a , F : FnOnce ( * mut Self :: Bus ) -> Fut + ' a ,
218+ Fut : Future < Output = Result < R , <Self :: Bus as ErrorType >:: Error > > + ' a ;
221219
222220 fn transaction < ' a , R , F , Fut > ( & ' a mut self , f : F ) -> Self :: TransactionFuture < ' a , R , F , Fut >
223221 where
224- F : FnOnce ( & ' a mut Self :: Bus ) -> Fut + ' a ,
225- Fut : Future <
226- Output = (
227- & ' a mut Self :: Bus ,
228- Result < R , <Self :: Bus as ErrorType >:: Error > ,
229- ) ,
230- > + ' a ,
222+ F : FnOnce ( * mut Self :: Bus ) -> Fut + ' a ,
223+ Fut : Future < Output = Result < R , <Self :: Bus as ErrorType >:: Error > > + ' a ,
231224 {
232225 T :: transaction ( self , f)
233226 }
@@ -449,27 +442,22 @@ where
449442
450443 type TransactionFuture < ' a , R , F , Fut > = impl Future < Output = Result < R , Self :: Error > > + ' a
451444 where
452- Self : ' a , R : ' a , F : FnOnce ( & ' a mut Self :: Bus ) -> Fut + ' a ,
453- Fut : Future < Output = ( & ' a mut Self :: Bus , Result < R , <Self :: Bus as ErrorType >:: Error > ) > + ' a ;
445+ Self : ' a , R : ' a , F : FnOnce ( * mut Self :: Bus ) -> Fut + ' a ,
446+ Fut : Future < Output = Result < R , <Self :: Bus as ErrorType >:: Error > > + ' a ;
454447
455448 fn transaction < ' a , R , F , Fut > ( & ' a mut self , f : F ) -> Self :: TransactionFuture < ' a , R , F , Fut >
456449 where
457450 R : ' a ,
458- F : FnOnce ( & ' a mut Self :: Bus ) -> Fut + ' a ,
459- Fut : Future <
460- Output = (
461- & ' a mut Self :: Bus ,
462- Result < R , <Self :: Bus as ErrorType >:: Error > ,
463- ) ,
464- > + ' a ,
451+ F : FnOnce ( * mut Self :: Bus ) -> Fut + ' a ,
452+ Fut : Future < Output = Result < R , <Self :: Bus as ErrorType >:: Error > > + ' a ,
465453 {
466454 async move {
467455 self . cs . set_low ( ) . map_err ( ExclusiveDeviceError :: Cs ) ?;
468456
469- let ( bus , f_res) = f ( & mut self . bus ) . await ;
457+ let f_res = f ( & mut self . bus ) . await ;
470458
471459 // On failure, it's important to still flush and deassert CS.
472- let flush_res = bus. flush ( ) . await ;
460+ let flush_res = self . bus . flush ( ) . await ;
473461 let cs_res = self . cs . set_high ( ) ;
474462
475463 let f_res = f_res. map_err ( ExclusiveDeviceError :: Spi ) ?;
0 commit comments