capsules_extra/
analog_comparator.rs1use 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 let result = self.analog_comparator.start_comparing(chan);
97
98 result
99 }
100
101 fn stop_comparing(&self, channel: usize) -> Result<(), ErrorCode> {
103 if channel >= self.channels.len() {
104 return Err(ErrorCode::INVAL);
105 }
106 let chan = self.channels[channel];
108 let result = self.analog_comparator.stop_comparing(chan);
109
110 result
111 }
112}
113
114impl<'a, A: hil::analog_comparator::AnalogComparator<'a>> SyscallDriver
115 for AnalogComparator<'a, A>
116{
117 fn command(
130 &self,
131 command_num: usize,
132 channel: usize,
133 _: usize,
134 processid: ProcessId,
135 ) -> CommandReturn {
136 if command_num == 0 {
137 return CommandReturn::success();
139 }
140
141 let match_or_empty_or_nonexistant = self.current_process.map_or(true, |current_process| {
143 self.grants
144 .enter(current_process, |_, _| current_process == processid)
145 .unwrap_or(true)
146 });
147 if match_or_empty_or_nonexistant {
148 self.current_process.set(processid);
149 } else {
150 return CommandReturn::failure(ErrorCode::NOMEM);
151 }
152
153 match command_num {
154 0 => CommandReturn::success_u32(self.channels.len() as u32),
155
156 1 => match self.comparison(channel) {
157 Ok(b) => CommandReturn::success_u32(b as u32),
158 Err(e) => CommandReturn::failure(e),
159 },
160
161 2 => self.start_comparing(channel).into(),
162
163 3 => self.stop_comparing(channel).into(),
164
165 4 => CommandReturn::success_u32(self.channels.len() as u32),
166
167 _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
168 }
169 }
170
171 fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> {
172 self.grants.enter(processid, |_, _| {})
173 }
174}
175
176impl<'a, A: hil::analog_comparator::AnalogComparator<'a>> hil::analog_comparator::Client
177 for AnalogComparator<'a, A>
178{
179 fn fired(&self, channel: usize) {
181 self.current_process.map(|processid| {
182 let _ = self.grants.enter(processid, |_app, upcalls| {
183 upcalls.schedule_upcall(0, (channel, 0, 0)).ok();
184 });
185 });
186 }
187}