1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use core::cell::Cell;
use kernel::{AppId, Callback, Driver, Grant, ReturnCode};
use kernel::hil;
pub const DRIVER_NUM: usize = 0x60002;
#[derive(Default)]
pub struct App {
callback: Option<Callback>,
pending: bool,
}
pub struct AmbientLight<'a> {
sensor: &'a hil::sensors::AmbientLight,
command_pending: Cell<bool>,
apps: Grant<App>,
}
impl<'a> AmbientLight<'a> {
pub fn new(sensor: &'a hil::sensors::AmbientLight, grant: Grant<App>) -> AmbientLight {
AmbientLight {
sensor: sensor,
command_pending: Cell::new(false),
apps: grant,
}
}
fn enqueue_sensor_reading(&self, appid: AppId) -> ReturnCode {
self.apps
.enter(appid, |app, _| {
if app.pending {
ReturnCode::ENOMEM
} else {
app.pending = true;
if !self.command_pending.get() {
self.command_pending.set(true);
self.sensor.read_light_intensity();
}
ReturnCode::SUCCESS
}
})
.unwrap_or_else(|err| err.into())
}
}
impl<'a> Driver for AmbientLight<'a> {
fn subscribe(&self, subscribe_num: usize, callback: Callback) -> ReturnCode {
match subscribe_num {
0 => self.apps
.enter(callback.app_id(), |app, _| {
app.callback = Some(callback);
ReturnCode::SUCCESS
})
.unwrap_or_else(|err| err.into()),
_ => ReturnCode::ENOSUPPORT,
}
}
fn command(&self, command_num: usize, _arg1: usize, _: usize, appid: AppId) -> ReturnCode {
match command_num {
0 => ReturnCode::SUCCESS,
1 => {
self.enqueue_sensor_reading(appid);
ReturnCode::SUCCESS
}
_ => ReturnCode::ENOSUPPORT,
}
}
}
impl<'a> hil::sensors::AmbientLightClient for AmbientLight<'a> {
fn callback(&self, lux: usize) {
self.command_pending.set(false);
self.apps.each(|app| {
if app.pending {
app.pending = false;
if let Some(mut callback) = app.callback {
callback.schedule(lux, 0, 0);
}
}
});
}
}