capsules_extra/
humidity.rs
1use core::cell::Cell;
55
56use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount};
57use kernel::hil;
58use kernel::syscall::{CommandReturn, SyscallDriver};
59use kernel::{ErrorCode, ProcessId};
60
61use capsules_core::driver;
63pub const DRIVER_NUM: usize = driver::NUM::Humidity as usize;
64
65#[derive(Clone, Copy, PartialEq)]
66pub enum HumidityCommand {
67 Exists,
68 ReadHumidity,
69}
70
71#[derive(Default)]
72pub struct App {
73 subscribed: bool,
74}
75
76pub struct HumiditySensor<'a, H: hil::sensors::HumidityDriver<'a>> {
77 driver: &'a H,
78 apps: Grant<App, UpcallCount<1>, AllowRoCount<0>, AllowRwCount<0>>,
79 busy: Cell<bool>,
80}
81
82impl<'a, H: hil::sensors::HumidityDriver<'a>> HumiditySensor<'a, H> {
83 pub fn new(
84 driver: &'a H,
85 grant: Grant<App, UpcallCount<1>, AllowRoCount<0>, AllowRwCount<0>>,
86 ) -> HumiditySensor<'a, H> {
87 HumiditySensor {
88 driver,
89 apps: grant,
90 busy: Cell::new(false),
91 }
92 }
93
94 fn enqueue_command(
95 &self,
96 command: HumidityCommand,
97 arg1: usize,
98 processid: ProcessId,
99 ) -> CommandReturn {
100 self.apps
101 .enter(processid, |app, _| {
102 app.subscribed = true;
103
104 if !self.busy.get() {
105 self.busy.set(true);
106 self.call_driver(command, arg1)
107 } else {
108 CommandReturn::success()
109 }
110 })
111 .unwrap_or_else(|err| CommandReturn::failure(err.into()))
112 }
113
114 fn call_driver(&self, command: HumidityCommand, _: usize) -> CommandReturn {
115 match command {
116 HumidityCommand::ReadHumidity => self.driver.read_humidity().into(),
117 _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
118 }
119 }
120}
121
122impl<'a, H: hil::sensors::HumidityDriver<'a>> hil::sensors::HumidityClient
123 for HumiditySensor<'a, H>
124{
125 fn callback(&self, humidity_val: usize) {
126 self.busy.set(false);
127
128 for cntr in self.apps.iter() {
129 cntr.enter(|app, upcalls| {
130 if app.subscribed {
131 app.subscribed = false;
132 upcalls.schedule_upcall(0, (humidity_val, 0, 0)).ok();
133 }
134 });
135 }
136 }
137}
138
139impl<'a, H: hil::sensors::HumidityDriver<'a>> SyscallDriver for HumiditySensor<'a, H> {
140 fn command(
141 &self,
142 command_num: usize,
143 arg1: usize,
144 _: usize,
145 processid: ProcessId,
146 ) -> CommandReturn {
147 match command_num {
148 0 => CommandReturn::success(),
150
151 1 => self.enqueue_command(HumidityCommand::ReadHumidity, arg1, processid),
153
154 _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
155 }
156 }
157
158 fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> {
159 self.apps.enter(processid, |_, _| {})
160 }
161}