1use core::fmt::Debug;
4use core::marker::PhantomData;
5use core::time::Duration;
6use core::{ffi, mem, ptr, slice};
7
8extern crate alloc;
9use alloc::boxed::Box;
10use alloc::sync::{Arc, Weak};
11
12use embedded_svc::channel;
13
14use ::log::*;
15
16use crate::hal::cpu::Core;
17use crate::hal::delay;
18use crate::hal::interrupt;
19
20use crate::sys::*;
21
22use crate::handle::RawHandle;
23use crate::private::cstr::RawCstrs;
24use crate::private::mutex;
25use crate::private::waitable::Waitable;
26use crate::private::zerocopy::{Channel, QuitOnDrop, Receiver};
27
28#[cfg(all(feature = "alloc", esp_idf_comp_esp_timer_enabled))]
29pub use async_wait::*;
30
31pub type EspSystemSubscription<'a> = EspSubscription<'a, System>;
32pub type EspBackgroundSubscription<'a> = EspSubscription<'a, User<Background>>;
33pub type EspExplicitSubscription<'a> = EspSubscription<'a, User<Explicit>>;
34
35pub type EspSystemAsyncSubscription<P> = EspAsyncSubscription<P, System>;
36pub type EspBackgroundAsyncSubscription<P> = EspAsyncSubscription<P, User<Background>>;
37pub type EspExplicitAsyncSubscription<P> = EspAsyncSubscription<P, User<Explicit>>;
38
39pub type EspSystemEventLoop = EspEventLoop<System>;
40pub type EspBackgroundEventLoop = EspEventLoop<User<Background>>;
41pub type EspExplicitEventLoop = EspEventLoop<User<Explicit>>;
42
43#[derive(Debug)]
44pub struct BackgroundLoopConfiguration<'a> {
45 pub queue_size: usize,
46 pub task_name: &'a str,
47 pub task_priority: u8,
48 pub task_stack_size: usize,
49 pub task_pin_to_core: Core,
50}
51
52impl Default for BackgroundLoopConfiguration<'_> {
53 fn default() -> Self {
54 Self {
55 queue_size: 64,
56 task_name: "EventLoop",
57 task_priority: 0,
58 task_stack_size: 3072,
59 task_pin_to_core: Core::Core0,
60 }
61 }
62}
63
64impl<'a> TryFrom<&BackgroundLoopConfiguration<'a>> for (esp_event_loop_args_t, RawCstrs) {
65 type Error = EspError;
66
67 fn try_from(conf: &BackgroundLoopConfiguration<'a>) -> Result<Self, Self::Error> {
68 let mut rcs = RawCstrs::new();
69
70 let ela = esp_event_loop_args_t {
71 queue_size: conf.queue_size as _,
72 task_name: rcs.as_ptr(conf.task_name)?,
73 task_priority: conf.task_priority as _,
74 task_stack_size: conf.task_stack_size as _,
75 task_core_id: conf.task_pin_to_core as _,
76 };
77
78 Ok((ela, rcs))
79 }
80}
81
82#[derive(Debug)]
83pub struct ExplicitLoopConfiguration {
84 pub queue_size: usize,
85}
86
87impl Default for ExplicitLoopConfiguration {
88 fn default() -> Self {
89 Self { queue_size: 8192 }
90 }
91}
92
93impl From<&ExplicitLoopConfiguration> for esp_event_loop_args_t {
94 fn from(conf: &ExplicitLoopConfiguration) -> Self {
95 esp_event_loop_args_t {
96 queue_size: conf.queue_size as _,
97 ..Default::default()
98 }
99 }
100}
101
102static TAKEN: mutex::Mutex<bool> = mutex::Mutex::new(false);
103
104#[derive(Clone, Debug)]
105pub struct System;
106#[derive(Clone, Debug)]
107pub struct User<T>(esp_event_loop_handle_t, PhantomData<fn() -> T>);
108#[derive(Clone, Debug)]
109pub struct Background;
110#[derive(Clone, Debug)]
111pub struct Explicit;
112
113unsafe impl Send for User<Background> {}
114unsafe impl Sync for User<Background> {}
115
116unsafe impl Send for User<Explicit> {}
117unsafe impl Sync for User<Explicit> {}
118
119pub trait EspEventLoopType {
120 fn is_system() -> bool;
121}
122
123impl EspEventLoopType for System {
124 fn is_system() -> bool {
125 true
126 }
127}
128
129impl<T> EspEventLoopType for User<T> {
130 fn is_system() -> bool {
131 false
132 }
133}
134
135pub unsafe trait EspEventSource {
147 fn source() -> Option<&'static ffi::CStr>;
148
149 fn event_id() -> Option<i32> {
150 None
151 }
152}
153
154pub trait EspEventSerializer: EspEventSource {
155 type Data<'a>;
156
157 fn serialize<F, R>(data: &Self::Data<'_>, f: F) -> R
158 where
159 F: FnOnce(&EspEventPostData) -> R;
160}
161
162pub trait EspEventDeserializer: EspEventSource {
163 type Data<'a>;
164
165 fn deserialize<'a>(data: &EspEvent<'a>) -> Self::Data<'a>;
166}
167
168#[derive(Debug, Clone)]
169pub struct EspEventPostData<'a> {
170 source: &'static ffi::CStr,
171 event_id: i32,
172 payload: &'a ffi::c_void,
173 payload_len: usize,
174}
175
176impl<'a> EspEventPostData<'a> {
177 pub unsafe fn new<P: Copy + Send + 'static>(
182 source: &'static ffi::CStr,
183 event_id: Option<i32>,
184 payload: &'a P,
185 ) -> Self {
186 Self {
187 source,
188 event_id: event_id.unwrap_or(0),
189 payload: unsafe {
190 (payload as *const _ as *const ffi::c_void)
191 .as_ref()
192 .unwrap()
193 },
194 payload_len: mem::size_of::<P>(),
195 }
196 }
197
198 pub unsafe fn new_raw(
203 source: &'static ffi::CStr,
204 event_id: Option<i32>,
205 payload: &'a [u8],
206 ) -> Self {
207 Self {
208 source,
209 event_id: event_id.unwrap_or(0),
210 payload: unsafe {
211 (payload.as_ptr() as *const _ as *const ffi::c_void)
212 .as_ref()
213 .unwrap()
214 },
215 payload_len: payload.len(),
216 }
217 }
218}
219
220unsafe impl EspEventSource for EspEventPostData<'_> {
221 fn source() -> Option<&'static ffi::CStr> {
222 None
223 }
224}
225
226impl EspEventSerializer for EspEventPostData<'_> {
227 type Data<'d> = EspEventPostData<'d>;
228
229 fn serialize<F, R>(data: &Self::Data<'_>, f: F) -> R
230 where
231 F: FnOnce(&EspEventPostData) -> R,
232 {
233 f(data)
234 }
235}
236
237#[derive(Debug, Clone)]
238pub struct EspEvent<'a> {
239 pub source: &'static ffi::CStr,
240 pub event_id: i32,
241 pub payload: Option<&'a ffi::c_void>,
242}
243
244impl<'a> EspEvent<'a> {
245 pub unsafe fn as_payload<P: Copy + Send + 'static>(&self) -> &'a P {
250 let payload: &P = if mem::size_of::<P>() > 0 {
251 self.payload.unwrap() as *const _ as *const P
252 } else {
253 ptr::NonNull::dangling().as_ptr() as *const P
254 }
255 .as_ref()
256 .unwrap();
257
258 payload
259 }
260
261 pub unsafe fn as_raw_payload(&self, len: usize) -> Option<&[u8]> {
266 self.payload
267 .map(|payload| slice::from_raw_parts(payload as *const _ as *const _, len))
268 }
269}
270
271unsafe impl EspEventSource for EspEvent<'_> {
272 fn source() -> Option<&'static ffi::CStr> {
273 None
274 }
275}
276
277impl EspEventDeserializer for EspEvent<'_> {
278 type Data<'d> = EspEvent<'d>;
279
280 fn deserialize<'d>(data: &EspEvent<'d>) -> Self::Data<'d> {
281 data.clone()
282 }
283}
284
285struct UnsafeCallback<'a>(*mut Box<dyn FnMut(EspEvent) + Send + 'a>);
286
287impl<'a> UnsafeCallback<'a> {
288 #[allow(clippy::type_complexity)]
289 fn from(boxed: &mut Box<Box<dyn FnMut(EspEvent) + Send + 'a>>) -> Self {
290 Self(boxed.as_mut())
291 }
292
293 unsafe fn from_ptr(ptr: *mut ffi::c_void) -> Self {
294 Self(ptr as *mut _)
295 }
296
297 fn as_ptr(&self) -> *mut ffi::c_void {
298 self.0 as *mut _
299 }
300
301 unsafe fn call(&self, data: EspEvent) {
302 let reference = self.0.as_mut().unwrap();
303
304 (reference)(data);
305 }
306}
307
308enum EventLoopHandleRef<T>
309where
310 T: EspEventLoopType,
311{
312 Strong(Arc<EventLoopHandle<T>>),
313 Weak(Weak<EventLoopHandle<T>>),
314}
315
316impl<T> EventLoopHandleRef<T>
317where
318 T: EspEventLoopType,
319{
320 fn make_weak(&mut self) {
321 if matches!(self, Self::Strong(_)) {
322 *self = Self::Weak(Arc::downgrade(&self.upgrade().unwrap()))
323 }
324 }
325
326 fn upgrade(&self) -> Option<Arc<EventLoopHandle<T>>> {
327 match self {
328 Self::Strong(handle) => Some(handle.clone()),
329 Self::Weak(handle) => handle.upgrade(),
330 }
331 }
332}
333
334pub struct EspSubscription<'a, T>
335where
336 T: EspEventLoopType,
337{
338 event_loop_handle: EventLoopHandleRef<T>,
339 handler_instance: esp_event_handler_instance_t,
340 source: Option<&'static ffi::CStr>,
341 event_id: i32,
342 #[allow(clippy::type_complexity)]
343 _callback: Box<Box<dyn FnMut(EspEvent) + Send + 'a>>,
344}
345
346impl<T> EspSubscription<'_, T>
347where
348 T: EspEventLoopType,
349{
350 pub fn make_weak(&mut self) {
351 self.event_loop_handle.make_weak();
352 }
353
354 extern "C" fn handle(
355 event_handler_arg: *mut ffi::c_void,
356 event_base: esp_event_base_t,
357 event_id: i32,
358 event_data: *mut ffi::c_void,
359 ) {
360 let data = EspEvent {
361 source: unsafe { ffi::CStr::from_ptr(event_base) },
362 event_id,
363 payload: unsafe { (event_data as *const ffi::c_void).as_ref() },
364 };
365
366 unsafe {
367 UnsafeCallback::from_ptr(event_handler_arg).call(data);
368 }
369 }
370}
371
372unsafe impl<T> Send for EspSubscription<'_, T> where T: EspEventLoopType {}
373
374impl<T> Drop for EspSubscription<'_, T>
375where
376 T: EspEventLoopType,
377{
378 fn drop(&mut self) {
379 #[allow(clippy::unwrap_or_default)]
380 if let Some(handle) = self.event_loop_handle.upgrade() {
381 if T::is_system() {
382 unsafe {
383 esp!(esp_event_handler_instance_unregister(
384 self.source
385 .map(ffi::CStr::as_ptr)
386 .unwrap_or(core::ptr::null()),
387 self.event_id,
388 self.handler_instance
389 ))
390 .unwrap();
391 }
392 } else {
393 unsafe {
394 let handle: &T = &handle.0;
395 let user: &User<Background> = mem::transmute(handle);
396
397 esp!(esp_event_handler_instance_unregister_with(
398 user.0,
399 self.source
400 .map(ffi::CStr::as_ptr)
401 .unwrap_or(core::ptr::null()),
402 self.event_id,
403 self.handler_instance
404 ))
405 .unwrap();
406 }
407 }
408 }
409 }
410}
411
412impl<T> RawHandle for EspSubscription<'_, User<T>>
413where
414 T: EspEventLoopType,
415{
416 type Handle = esp_event_handler_instance_t;
417
418 fn handle(&self) -> Self::Handle {
419 self.handler_instance
420 }
421}
422
423pub struct EspAsyncSubscription<D, T>
424where
425 D: EspEventDeserializer,
426 T: EspEventLoopType,
427{
428 receiver: Receiver<EspEvent<'static>>,
429 subscription: EspSubscription<'static, T>,
430 given: bool,
431 _deserializer: PhantomData<fn() -> D>,
432}
433
434impl<D, T> EspAsyncSubscription<D, T>
435where
436 D: EspEventDeserializer,
437 T: EspEventLoopType,
438{
439 pub fn make_weak(&mut self) {
440 self.subscription.make_weak();
441 }
442
443 pub async fn recv(&mut self) -> Result<D::Data<'_>, EspError> {
444 if self.given {
445 self.receiver.done();
446 self.given = false;
447 }
448
449 while let Some(data) = self.receiver.get_shared_async().await {
450 if Some(data.source) != D::source() {
451 self.receiver.done();
452 continue;
453 }
454 self.given = true;
455 return Ok(D::deserialize(data));
456 }
457
458 Err(EspError::from_infallible::<ESP_ERR_INVALID_STATE>())
459 }
460}
461
462impl<D, T> RawHandle for EspAsyncSubscription<D, User<T>>
463where
464 D: EspEventDeserializer,
465 T: EspEventLoopType,
466{
467 type Handle = esp_event_handler_instance_t;
468
469 fn handle(&self) -> Self::Handle {
470 self.subscription.handle()
471 }
472}
473
474impl<D, T> channel::ErrorType for EspAsyncSubscription<D, T>
475where
476 D: EspEventDeserializer,
477 T: EspEventLoopType,
478{
479 type Error = EspError;
480}
481
482impl<D, T> channel::asynch::Receiver for EspAsyncSubscription<D, T>
483where
484 D: EspEventDeserializer + 'static,
485 T: EspEventLoopType + 'static,
486{
487 type Data<'a> = D::Data<'a>;
488
489 async fn recv(&mut self) -> Result<Self::Data<'_>, Self::Error> {
490 EspAsyncSubscription::recv(self).await
491 }
492}
493
494#[derive(Debug)]
495struct EventLoopHandle<T>(T)
496where
497 T: EspEventLoopType;
498
499impl EventLoopHandle<System> {
500 fn new() -> Result<Self, EspError> {
501 let mut taken = TAKEN.lock();
502
503 if *taken {
504 return Err(EspError::from_infallible::<ESP_ERR_INVALID_STATE>());
505 }
506
507 esp!(unsafe { esp_event_loop_create_default() })?;
508
509 *taken = true;
510
511 Ok(Self(System))
512 }
513}
514
515impl<T> EventLoopHandle<User<T>> {
516 fn new_internal(conf: &esp_event_loop_args_t) -> Result<Self, EspError> {
517 let mut handle: esp_event_loop_handle_t = ptr::null_mut();
518
519 esp!(unsafe { esp_event_loop_create(conf as *const _, &mut handle as _) })?;
520
521 Ok(Self(User(handle, PhantomData)))
522 }
523}
524
525impl EventLoopHandle<User<Background>> {
526 fn new(conf: &BackgroundLoopConfiguration) -> Result<Self, EspError> {
527 let (nconf, _rcs) = conf.try_into()?;
528
529 Self::new_internal(&nconf)
530 }
531}
532
533impl EventLoopHandle<User<Explicit>> {
534 fn new(conf: &ExplicitLoopConfiguration) -> Result<Self, EspError> {
535 Self::new_internal(&conf.into())
536 }
537}
538
539impl<T> Drop for EventLoopHandle<T>
540where
541 T: EspEventLoopType,
542{
543 fn drop(&mut self) {
544 if T::is_system() {
545 let mut taken = TAKEN.lock();
546
547 unsafe {
548 esp!(esp_event_loop_delete_default()).unwrap();
549 }
550
551 *taken = false;
552
553 info!("System event loop dropped");
554 } else {
555 unsafe {
556 let handle: &T = &self.0;
557 let user: &User<Background> = mem::transmute(handle);
558
559 esp!(esp_event_loop_delete(user.0)).unwrap();
560 }
561
562 info!("Event loop dropped");
563 }
564 }
565}
566
567#[derive(Debug)]
568pub struct EspEventLoop<T>(Arc<EventLoopHandle<T>>)
569where
570 T: EspEventLoopType;
571
572impl<T> EspEventLoop<T>
573where
574 T: EspEventLoopType,
575{
576 pub fn subscribe_async<D>(&self) -> Result<EspAsyncSubscription<D, T>, EspError>
577 where
578 D: EspEventDeserializer,
579 {
580 let (channel, receiver) = Channel::new();
581
582 let sender = QuitOnDrop::new(channel);
583
584 let subscription = self.subscribe::<EspEvent, _>(move |event| {
585 let mut event = unsafe { mem::transmute::<EspEvent<'_>, EspEvent<'_>>(event) };
586
587 sender.channel().share(&mut event);
588 })?;
589
590 Ok(EspAsyncSubscription {
591 receiver,
592 subscription,
593 given: false,
594 _deserializer: PhantomData,
595 })
596 }
597
598 pub fn subscribe<D, F>(&self, mut callback: F) -> Result<EspSubscription<'static, T>, EspError>
599 where
600 D: EspEventDeserializer,
601 F: for<'a> FnMut(D::Data<'a>) + Send + 'static,
602 {
603 self.subscribe_raw::<D, _>(move |event| callback(D::deserialize(&event)))
604 }
605
606 pub unsafe fn subscribe_nonstatic<'a, D, F>(
630 &self,
631 mut callback: F,
632 ) -> Result<EspSubscription<'a, T>, EspError>
633 where
634 D: EspEventDeserializer,
635 F: for<'d> FnMut(D::Data<'d>) + Send + 'a,
636 {
637 self.subscribe_raw::<D, _>(move |event| callback(D::deserialize(&event)))
638 }
639
640 pub async fn post_async<S>(&self, payload: &S::Data<'_>) -> Result<(), EspError>
641 where
642 S: EspEventSerializer,
643 {
644 loop {
645 if self.post::<S>(payload, delay::NON_BLOCK)? {
646 break Ok(());
647 }
648
649 crate::hal::task::yield_now().await;
650 }
651 }
652
653 pub fn post<S>(&self, payload: &S::Data<'_>, timeout: TickType_t) -> Result<bool, EspError>
654 where
655 S: EspEventSerializer,
656 {
657 if interrupt::active() {
658 #[cfg(not(esp_idf_esp_event_post_from_isr))]
659 panic!("Trying to post from an ISR handler. Enable `CONFIG_ESP_EVENT_POST_FROM_ISR` in `sdkconfig.defaults`");
660
661 #[cfg(esp_idf_esp_event_post_from_isr)]
662 S::serialize(payload, |event| self.isr_post_raw(event))
663 } else {
664 S::serialize(payload, |event| self.post_raw(event, timeout))
665 }
666 }
667
668 fn subscribe_raw<'a, S, F>(&self, callback: F) -> Result<EspSubscription<'a, T>, EspError>
669 where
670 S: EspEventSource,
671 F: FnMut(EspEvent) + Send + 'a,
672 {
673 let mut handler_instance: esp_event_handler_instance_t = ptr::null_mut();
674
675 let callback: Box<dyn FnMut(EspEvent) + Send + 'a> = Box::new(callback);
676 let mut callback = Box::new(callback);
677
678 let unsafe_callback = UnsafeCallback::from(&mut callback);
679
680 if T::is_system() {
681 esp!(unsafe {
682 esp_event_handler_instance_register(
683 S::source().map(ffi::CStr::as_ptr).unwrap_or(ptr::null()),
684 S::event_id().unwrap_or(ESP_EVENT_ANY_ID),
685 Some(EspSubscription::<System>::handle),
686 unsafe_callback.as_ptr(),
687 &mut handler_instance as *mut _,
688 )
689 })?;
690 } else {
691 esp!(unsafe {
692 let handle: &T = &self.0 .0;
693 let user: &User<Background> = mem::transmute(handle);
694
695 esp_event_handler_instance_register_with(
696 user.0,
697 S::source().map(ffi::CStr::as_ptr).unwrap_or(ptr::null()),
698 S::event_id().unwrap_or(ESP_EVENT_ANY_ID),
699 Some(EspSubscription::<User<T>>::handle),
700 unsafe_callback.as_ptr(),
701 &mut handler_instance as *mut _,
702 )
703 })?;
704 }
705
706 Ok(EspSubscription {
707 event_loop_handle: EventLoopHandleRef::Strong(self.0.clone()),
708 handler_instance,
709 source: S::source(),
710 event_id: S::event_id().unwrap_or(ESP_EVENT_ANY_ID),
711 _callback: callback,
712 })
713 }
714
715 fn post_raw(&self, data: &EspEventPostData, timeout: TickType_t) -> Result<bool, EspError> {
716 let result = if T::is_system() {
717 unsafe {
718 esp_event_post(
719 data.source.as_ptr(),
720 data.event_id,
721 data.payload as *const _ as *mut _,
722 data.payload_len as _,
723 timeout,
724 )
725 }
726 } else {
727 unsafe {
728 let handle: &T = &self.0 .0;
729 let user: &User<Background> = mem::transmute(handle);
730
731 esp_event_post_to(
732 user.0,
733 data.source.as_ptr(),
734 data.event_id,
735 data.payload as *const _ as *mut _,
736 data.payload_len as _,
737 timeout,
738 )
739 }
740 };
741
742 if result == ESP_ERR_TIMEOUT {
743 Ok(false)
744 } else {
745 esp_result!(result, true)
746 }
747 }
748
749 #[cfg(esp_idf_esp_event_post_from_isr)]
750 fn isr_post_raw(&self, data: &EspEventPostData) -> Result<bool, EspError> {
751 let mut higher_prio_task_woken: BaseType_t = Default::default();
752
753 let result = if T::is_system() {
754 unsafe {
755 esp_event_isr_post(
756 data.source.as_ptr(),
757 data.event_id,
758 data.payload as *const _ as *mut _,
759 data.payload_len as _,
760 &mut higher_prio_task_woken as *mut _,
761 )
762 }
763 } else {
764 unsafe {
765 let handle: &T = &self.0 .0;
766 let user: &User<Background> = mem::transmute(handle);
767
768 esp_event_isr_post_to(
769 user.0,
770 data.source.as_ptr(),
771 data.event_id,
772 data.payload as *const _ as *mut _,
773 data.payload_len as _,
774 &mut higher_prio_task_woken as *mut _,
775 )
776 }
777 };
778
779 if higher_prio_task_woken != 0 {
780 crate::hal::task::do_yield();
781 }
782
783 if result == ESP_FAIL {
784 Ok(false)
785 } else {
786 esp!(result)?;
787
788 Ok(true)
789 }
790 }
791}
792
793impl<T> EspEventLoop<User<T>> {
794 pub fn spin(&mut self, timeout: TickType_t) -> Result<(), EspError> {
795 esp!(unsafe { esp_event_loop_run(self.0 .0 .0, timeout) })
796 }
797}
798
799impl<T> RawHandle for EspEventLoop<User<T>> {
800 type Handle = esp_event_loop_handle_t;
801
802 fn handle(&self) -> Self::Handle {
803 self.0 .0 .0
804 }
805}
806
807impl EspEventLoop<System> {
808 pub fn take() -> Result<Self, EspError> {
809 Ok(Self(Arc::new(EventLoopHandle::<System>::new()?)))
810 }
811}
812
813impl EspEventLoop<User<Background>> {
814 pub fn new(conf: &BackgroundLoopConfiguration) -> Result<Self, EspError> {
815 Ok(Self(Arc::new(EventLoopHandle::<User<Background>>::new(
816 conf,
817 )?)))
818 }
819}
820
821impl EspEventLoop<User<Explicit>> {
822 pub fn new(conf: &ExplicitLoopConfiguration) -> Result<Self, EspError> {
823 Ok(Self(Arc::new(EventLoopHandle::<User<Explicit>>::new(
824 conf,
825 )?)))
826 }
827}
828
829impl<T> Clone for EspEventLoop<T>
830where
831 T: EspEventLoopType,
832{
833 fn clone(&self) -> Self {
834 Self(self.0.clone())
835 }
836}
837
838unsafe impl<T> Send for EspEventLoop<T> where T: EspEventLoopType + Send {}
839unsafe impl<T> Sync for EspEventLoop<T> where T: EspEventLoopType + Sync {}
840
841pub struct Wait<T>
842where
843 T: EspEventLoopType,
844{
845 waitable: Arc<Waitable<()>>,
846 _subscription: EspSubscription<'static, T>,
847}
848
849impl<T> Wait<T>
850where
851 T: EspEventLoopType,
852{
853 pub fn new<S>(event_loop: &EspEventLoop<T>) -> Result<Self, EspError>
854 where
855 S: EspEventSource,
856 {
857 let waitable: Arc<Waitable<()>> = Arc::new(Waitable::new(()));
858
859 let s_waitable = waitable.clone();
860 let subscription = event_loop.subscribe_raw::<S, _>(move |_| {
861 s_waitable.cvar.notify_all();
862 })?;
863
864 Ok(Self {
865 waitable,
866 _subscription: subscription,
867 })
868 }
869
870 pub fn wait_while<F: FnMut() -> Result<bool, EspError>>(
871 &self,
872 mut matcher: F,
873 duration: Option<Duration>,
874 ) -> Result<(), EspError> {
875 if let Some(duration) = duration {
876 debug!("About to wait for duration {duration:?}");
877
878 let (timeout, _) =
879 self.waitable
880 .wait_timeout_while_and_get(duration, |_| matcher(), |_| ())?;
881
882 if !timeout {
883 debug!("Waiting done - success");
884 Ok(())
885 } else {
886 debug!("Timeout while waiting");
887 esp!(ESP_ERR_TIMEOUT)
888 }
889 } else {
890 debug!("About to wait");
891
892 self.waitable.wait_while(|_| matcher())?;
893
894 debug!("Waiting done - success");
895
896 Ok(())
897 }
898 }
899}
900
901#[cfg(all(feature = "alloc", esp_idf_comp_esp_timer_enabled))]
902mod async_wait {
903 use core::marker::PhantomData;
904 use core::pin::pin;
905 use core::time::Duration;
906
907 extern crate alloc;
908 use alloc::sync::Arc;
909
910 use esp_idf_hal::task::asynch::Notification;
911
912 use ::log::debug;
913
914 use super::{EspEventDeserializer, EspEventLoop, EspEventLoopType, EspSubscription};
915 use crate::sys::{esp, EspError, ESP_ERR_TIMEOUT};
916 use crate::timer::{EspAsyncTimer, EspTimerService, Task};
917
918 pub struct AsyncWait<D, T>
919 where
920 D: EspEventDeserializer,
921 T: EspEventLoopType,
922 {
923 notification: Arc<Notification>,
924 timer: EspAsyncTimer,
925 _subscription: EspSubscription<'static, T>,
926 _deserializer: PhantomData<fn() -> D>,
927 }
928
929 impl<D, T> AsyncWait<D, T>
930 where
931 D: EspEventDeserializer,
932 T: EspEventLoopType + Send,
933 {
934 pub fn new(
935 event_loop: &EspEventLoop<T>,
936 timer_service: &EspTimerService<Task>,
937 ) -> Result<Self, EspError> {
938 let notification = Arc::new(Notification::new());
939
940 Ok(Self {
941 _subscription: {
942 let notification = notification.clone();
943 event_loop.subscribe::<D, _>(move |_| {
944 notification.notify_lsb();
945 })?
946 },
947 notification,
948 timer: timer_service.timer_async()?,
949 _deserializer: PhantomData,
950 })
951 }
952
953 pub async fn wait_while<F: FnMut() -> Result<bool, EspError>>(
954 &mut self,
955 mut matcher: F,
956 duration: Option<Duration>,
957 ) -> Result<(), EspError> {
958 let notification = &self.notification;
959
960 let subscription_wait = pin!(async move {
961 while matcher()? {
962 notification.wait().await;
963 }
964
965 Result::<(), EspError>::Ok(())
966 });
967
968 if let Some(duration) = duration {
969 debug!("About to wait for duration {duration:?}");
970
971 let timer_wait = self.timer.after(duration);
972
973 match embassy_futures::select::select(subscription_wait, timer_wait).await {
974 embassy_futures::select::Either::First(_) => {
975 debug!("Waiting done - success");
976 Ok(())
977 }
978 embassy_futures::select::Either::Second(_) => {
979 debug!("Timeout while waiting");
980 esp!(ESP_ERR_TIMEOUT)
981 }
982 }
983 } else {
984 debug!("About to wait");
985
986 subscription_wait.await?;
987
988 debug!("Waiting done - success");
989
990 Ok(())
991 }
992 }
993 }
994}