playdate_device/device/
methods.rs

1use crate::retry::{IterTime, Retries};
2use crate::usb::mode::Mode;
3use crate::error::Error;
4
5use super::Device;
6
7
8type Result<T = (), E = Error> = std::result::Result<T, E>;
9
10
11pub async fn wait_mode_storage<T>(dev: Device, retry: Retries<T>) -> Result<Device>
12	where T: IterTime {
13	wait_mode_change(dev, Mode::Storage, retry).await
14}
15
16pub async fn wait_mode_data<T>(dev: Device, retry: Retries<T>) -> Result<Device>
17	where T: IterTime {
18	wait_mode_change(dev, Mode::Data, retry).await
19}
20
21
22#[cfg_attr(feature = "tracing", tracing::instrument(skip(dev, retry), fields(dev = dev.info().serial_number())))]
23pub async fn wait_mode_change(mut dev: Device, to: Mode, retry: Retries<impl IterTime>) -> Result<Device> {
24	let total = &retry.total;
25	let iter_ms = retry.iters.interval(total);
26	let retries_num = total.as_millis() / iter_ms.as_millis();
27	debug!("retries: {retries_num} * {iter_ms:?} ≈ {total:?}.");
28
29	let mut counter = retries_num;
30	#[cfg(all(feature = "tokio", not(feature = "async-std")))]
31	let mut interval = tokio::time::interval(iter_ms);
32
33	while {
34		counter -= 1;
35		counter
36	} != 0
37	{
38		#[cfg(all(not(feature = "async-std"), feature = "tokio"))]
39		interval.tick().await;
40		#[cfg(feature = "async-std")]
41		async_std::task::sleep(iter_ms).await;
42		#[cfg(all(not(feature = "tokio"), not(feature = "async-std")))]
43		std::thread::sleep(iter_ms);
44
45		let mode = dev.mode_cached();
46		trace!(
47		       "{dev}: waiting mode {to}, current: {mode}, try: {}/{retries_num}",
48		       retries_num - counter
49		);
50
51		if mode == to {
52			trace!("{dev} is in {to} mode.");
53			return Ok(dev);
54		}
55
56		if dev.refresh()? {
57			if dev.mode_cached() == to {
58				return Ok(dev);
59			} else {
60				trace!("refreshed to {mode} mode, waiting...")
61			}
62		}
63	}
64
65	Err(Error::usb_timeout(dev))
66}