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