Skip to content

Commit d448d97

Browse files
authored
Merge pull request #30 from jedrzejboczar/suspend-wakeup
Support remote wakeup from suspend
2 parents c5260f9 + c6f7d12 commit d448d97

File tree

1 file changed

+40
-5
lines changed

1 file changed

+40
-5
lines changed

src/bus.rs

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,44 @@ impl<USB: UsbPeripheral> UsbBus<USB> {
7171
regs.cntr.modify(|_, w| w.pdwn().bit(pdwn));
7272
});
7373
}
74+
75+
/// Enter suspend low-power mode
76+
///
77+
/// This should be used when in suspend mode if low-power mode needs to be entered during
78+
/// suspend (bus-powered device). Application should call this when it is ready to decrease
79+
/// power consumption to meet power consumption requirements of the USB suspend condition
80+
/// (e.g. disable system clocks or reduce their frequency). When wake up event is received
81+
/// low power mode will be automatically disabled.
82+
///
83+
/// Will not enter low-power mode if not in suspend state. Returns `true` if entered.
84+
pub fn suspend_low_power_mode(&self) -> bool {
85+
interrupt::free(|cs| {
86+
let regs = self.regs.borrow(cs);
87+
if regs.cntr.read().fsusp().is_suspend() {
88+
regs.cntr.modify(|_, w| w.lpmode().set_bit());
89+
true
90+
} else {
91+
false
92+
}
93+
})
94+
}
95+
96+
/// Set/clear remote wakeup bit
97+
///
98+
/// Allows to modify CNTR.RESUME bit from device to perform remote wake up from suspend
99+
/// (e.g. on keyboard/mouse input). To perform remote wake up: when a condition is met
100+
/// during suspend mode, use this method with `true` to set the RESUME bit. Then, after
101+
/// waiting between 1-15 ms (see reference manual) call it again with `false` to clear
102+
/// the bit.
103+
///
104+
/// This method will not set the bit if device is not suspended because performing remote
105+
/// wake up in other mode is invalid and host will most likely disable such a device.
106+
pub fn remote_wakeup(&self, resume: bool) {
107+
interrupt::free(|cs| {
108+
self.regs.borrow(cs)
109+
.cntr.modify(|r, w| w.resume().bit(resume && r.fsusp().is_suspend()));
110+
})
111+
}
74112
}
75113

76114
impl<USB: UsbPeripheral> usb_device::bus::UsbBus for UsbBus<USB> {
@@ -218,10 +256,7 @@ impl<USB: UsbPeripheral> usb_device::bus::UsbBus for UsbBus<USB> {
218256

219257
if v.ctr_tx().bit_is_set() {
220258
ep_in_complete |= bit;
221-
222-
interrupt::free(|cs| {
223-
ep.clear_ctr_tx(cs);
224-
});
259+
ep.clear_ctr_tx(cs);
225260
}
226261

227262
bit <<= 1;
@@ -288,7 +323,7 @@ impl<USB: UsbPeripheral> usb_device::bus::UsbBus for UsbBus<USB> {
288323
self.regs
289324
.borrow(cs)
290325
.cntr
291-
.modify(|_, w| w.fsusp().set_bit().lpmode().set_bit());
326+
.modify(|_, w| w.fsusp().set_bit());
292327
});
293328
}
294329

0 commit comments

Comments
 (0)