capsules_extra/
analog_comparator.rs
1use capsules_core::driver;
42pub const DRIVER_NUM: usize = driver::NUM::AnalogComparator as usize;
43
44use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount};
45use kernel::hil;
46use kernel::syscall::{CommandReturn, SyscallDriver};
47use kernel::utilities::cells::OptionalCell;
48use kernel::{ErrorCode, ProcessId};
49
50pub struct AnalogComparator<'a, A: hil::analog_comparator::AnalogComparator<'a> + 'a> {
51 analog_comparator: &'a A,
53 channels: &'a [&'a <A as hil::analog_comparator::AnalogComparator<'a>>::Channel],
54
55 grants: Grant<App, UpcallCount<1>, AllowRoCount<0>, AllowRwCount<0>>,
56 current_process: OptionalCell<ProcessId>,
57}
58
59#[derive(Default)]
60pub struct App {}
61
62impl<'a, A: hil::analog_comparator::AnalogComparator<'a>> AnalogComparator<'a, A> {
63 pub fn new(
64 analog_comparator: &'a A,
65 channels: &'a [&'a <A as hil::analog_comparator::AnalogComparator<'a>>::Channel],
66 grant: Grant<App, UpcallCount<1>, AllowRoCount<0>, AllowRwCount<0>>,
67 ) -> AnalogComparator<'a, A> {
68 AnalogComparator {
69 analog_comparator,
71 channels,
72 grants: grant,
73 current_process: OptionalCell::empty(),
74 }
75 }
76
77 fn comparison(&self, channel: usize) -> Result<bool, ErrorCode> {
79 if channel >= self.channels.len() {
80 return Err(ErrorCode::INVAL);
81 }
82 let chan = self.channels[channel];
84 let result = self.analog_comparator.comparison(chan);
85
86 Ok(result)
87 }
88
89 fn start_comparing(&self, channel: usize) -> Result<(), ErrorCode> {
91 if channel >= self.channels.len() {
92 return Err(ErrorCode::INVAL);
93 }
94 let chan = self.channels[channel];
96
97 self.analog_comparator.start_comparing(chan)
98 }
99
100 fn stop_comparing(&self, channel: usize) -> Result<(), ErrorCode> {
102 if channel >= self.channels.len() {
103 return Err(ErrorCode::INVAL);
104 }
105 let chan = self.channels[channel];
107
108 self.analog_comparator.stop_comparing(chan)
109 }
110}
111
112impl<'a, A: hil::analog_comparator::AnalogComparator<'a>> SyscallDriver
113 for AnalogComparator<'a, A>
114{
115 fn command(
128 &self,
129 command_num: usize,
130 channel: usize,
131 _: usize,
132 processid: ProcessId,
133 ) -> CommandReturn {
134 if command_num == 0 {
135 return CommandReturn::success();
137 }
138
139 let match_or_empty_or_nonexistant = self.current_process.map_or(true, |current_process| {
141 self.grants
142 .enter(current_process, |_, _| current_process == processid)
143 .unwrap_or(true)
144 });
145 if match_or_empty_or_nonexistant {
146 self.current_process.set(processid);
147 } else {
148 return CommandReturn::failure(ErrorCode::NOMEM);
149 }
150
151 match command_num {
152 0 => CommandReturn::success_u32(self.channels.len() as u32),
153
154 1 => match self.comparison(channel) {
155 Ok(b) => CommandReturn::success_u32(b as u32),
156 Err(e) => CommandReturn::failure(e),
157 },
158
159 2 => self.start_comparing(channel).into(),
160
161 3 => self.stop_comparing(channel).into(),
162
163 4 => CommandReturn::success_u32(self.channels.len() as u32),
164
165 _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
166 }
167 }
168
169 fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> {
170 self.grants.enter(processid, |_, _| {})
171 }
172}
173
174impl<'a, A: hil::analog_comparator::AnalogComparator<'a>> hil::analog_comparator::Client
175 for AnalogComparator<'a, A>
176{
177 fn fired(&self, channel: usize) {
179 self.current_process.map(|processid| {
180 let _ = self.grants.enter(processid, |_app, upcalls| {
181 upcalls.schedule_upcall(0, (channel, 0, 0)).ok();
182 });
183 });
184 }
185}