embedded_fans_async/
lib.rs

1//! Async Fan API
2//!
3//! This API provides generic methods for interfacing with fans.
4//!
5//! # For HAL authors
6//!
7//! Here is an example of an embedded-fans implementation of the Fan and RpmSense traits.
8//!
9//! ```
10//! use embedded_fans_async::{self, Fan, RpmSense};
11//!
12//! // A struct representing a fan device.
13//! pub struct MyFan {
14//!     // ...
15//! }
16//!
17//! #[derive(Clone, Copy, Debug)]
18//! pub enum Error {
19//!     // ...
20//! }
21//!
22//! impl embedded_fans_async::Error for Error {
23//!     fn kind(&self) -> embedded_fans::ErrorKind {
24//!         match *self {
25//!             // ...
26//!         }
27//!     }
28//! }
29//!
30//! impl embedded_fans_async::ErrorType for MyFan {
31//!     type Error = Error;
32//! }
33//!
34//! impl Fan for MyFan {
35//!     fn max_rpm(&self) -> u16 {
36//!         3150
37//!     }
38//!
39//!     fn min_rpm(&self) -> u16 {
40//!         0
41//!     }
42//!
43//!     fn min_start_rpm(&self) -> u16 {
44//!         1120
45//!     }
46//!
47//!     async fn set_speed_rpm(&mut self, rpm: u16) -> Result<u16, Self::Error> {
48//!         // ...
49//!         Ok(rpm)
50//!     }
51//! }
52//!
53//! impl RpmSense for MyFan {
54//!     async fn rpm(&mut self) -> Result<u16, Self::Error> {
55//!         // ...
56//!         Ok(42)
57//!     }
58//! }
59//! ```
60
61#![doc = include_str!("../README.md")]
62#![forbid(missing_docs)]
63#![forbid(unsafe_code)]
64#![no_std]
65#![allow(async_fn_in_trait)]
66
67pub use embedded_fans::{Error, ErrorKind, ErrorType};
68
69/// Async fan methods
70pub trait Fan: ErrorType {
71    /// Returns the maximum RPM the fan is capable of running at.
72    fn max_rpm(&self) -> u16;
73
74    /// Returns the minimum RPM the fan is capable of running at.
75    fn min_rpm(&self) -> u16;
76
77    /// Returns the minimum RPM needed for the fan to begin running from a dead stop
78    /// (which may be the same as the minimum running speed).
79    fn min_start_rpm(&self) -> u16;
80
81    /// Sets the fan's speed in terms of absolute RPM.
82    /// Returns the actual RPM set on success.
83    async fn set_speed_rpm(&mut self, rpm: u16) -> Result<u16, Self::Error>;
84
85    /// Sets the fan's speed in terms of percent of maximum RPM.
86    /// Returns the actual RPM set on success.
87    #[inline]
88    async fn set_speed_percent(&mut self, percent: u8) -> Result<u16, Self::Error> {
89        debug_assert!((0..=100).contains(&percent));
90
91        // Cast operands to u32 to prevent overflow during multiplication
92        self.set_speed_rpm(((u32::from(self.max_rpm()) * u32::from(percent)) / 100) as u16)
93            .await
94    }
95
96    /// Sets the fan's speed to the maximum RPM it's capable of running at.
97    #[inline]
98    async fn set_speed_max(&mut self) -> Result<(), Self::Error> {
99        self.set_speed_rpm(self.max_rpm()).await?;
100        Ok(())
101    }
102
103    /// Starts the fan at its minimum RPM needed to begin from a dead stop.
104    #[inline]
105    async fn start(&mut self) -> Result<(), Self::Error> {
106        self.set_speed_rpm(self.min_start_rpm()).await?;
107        Ok(())
108    }
109
110    /// Stops the fan completely.
111    #[inline]
112    async fn stop(&mut self) -> Result<(), Self::Error> {
113        self.set_speed_rpm(0).await?;
114        Ok(())
115    }
116}
117
118impl<T: Fan + ?Sized> Fan for &mut T {
119    #[inline]
120    fn max_rpm(&self) -> u16 {
121        T::max_rpm(self)
122    }
123
124    #[inline]
125    fn min_rpm(&self) -> u16 {
126        T::min_rpm(self)
127    }
128
129    #[inline]
130    fn min_start_rpm(&self) -> u16 {
131        T::min_start_rpm(self)
132    }
133
134    #[inline]
135    async fn set_speed_rpm(&mut self, rpm: u16) -> Result<u16, Self::Error> {
136        T::set_speed_rpm(self, rpm).await
137    }
138
139    #[inline]
140    async fn set_speed_percent(&mut self, percent: u8) -> Result<u16, Self::Error> {
141        T::set_speed_percent(self, percent).await
142    }
143
144    #[inline]
145    async fn set_speed_max(&mut self) -> Result<(), Self::Error> {
146        T::set_speed_max(self).await
147    }
148
149    #[inline]
150    async fn stop(&mut self) -> Result<(), Self::Error> {
151        T::stop(self).await
152    }
153}
154
155/// Async RPM sensing (tachometer) methods
156pub trait RpmSense: ErrorType {
157    /// Returns the fan's currently measured RPM.
158    async fn rpm(&mut self) -> Result<u16, Self::Error>;
159}
160
161impl<T: RpmSense + ?Sized> RpmSense for &mut T {
162    #[inline]
163    async fn rpm(&mut self) -> Result<u16, Self::Error> {
164        T::rpm(self).await
165    }
166}