Skip to content

Commit e556b6a

Browse files
authored
Tweak RTC alarm disable (koreader#1106)
Do it like busybox & Nickel The other approach would be a WKALM_RD + WKALM_SET. I'm not *quite* sure what the previous behavior was actually doing (No idea what an epoch set to -1 actually does in practice?)
1 parent 35ce048 commit e556b6a

File tree

3 files changed

+53
-1
lines changed

3 files changed

+53
-1
lines changed

ffi-cdecl/rtc_cdecl.c

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
cdecl_struct(rtc_time)
88
cdecl_struct(rtc_wkalrm)
99

10+
cdecl_const(RTC_AIE_ON)
11+
cdecl_const(RTC_AIE_OFF)
1012
cdecl_const(RTC_WKALM_SET)
1113
cdecl_const(RTC_WKALM_RD)
1214

ffi/rtc.lua

+49-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,52 @@ function RTC:secondsFromNowToEpoch(seconds_from_now)
3737
return epoch
3838
end
3939

40+
41+
--[[--
42+
Enable/Disable the alarm interrupt.
43+
The use of RTC_WKALM_SET allows us to bypass the need for RTC_AIE_* calls,
44+
thanks to the enabled field in the rtc_wkalrm struct.
45+
Busybox rtcwake still does an RTC_AIE_OFF when resuming from an alarm wakeup,
46+
as does Nickel when powering off.
47+
In this scenario, the modern util-linux rtcwake, which never uses legacy RTC_ALM_SET calls,
48+
instead uses RTC_WKALM_SET filled from RTC_WKALM_RD but with enabled set to 0.
49+
50+
@enabled bool Whether the call enables or disables the alarm interrupt. Defaults to true.
51+
52+
@treturn bool Success.
53+
@treturn re Error code (if any).
54+
@treturn err Error string (if any).
55+
--]]
56+
function RTC:toggleAlarmInterrupt(enabled)
57+
enabled = (enabled ~= nil) and enabled or true
58+
59+
local err
60+
local rtc0 = C.open("/dev/rtc0", bor(bor(C.O_RDONLY, C.O_NONBLOCK), C.O_CLOEXEC))
61+
if rtc0 == -1 then
62+
err = ffi.string(C.strerror(ffi.errno()))
63+
print("toggleAlarmInterrupt open /dev/rtc0", rtc0, err)
64+
return nil, rtc0, err
65+
end
66+
local re = C.ioctl(rtc0, enabled and C.RTC_AIE_ON or C.RTC_AIE_OFF, 0)
67+
if re == -1 then
68+
err = ffi.string(C.strerror(ffi.errno()))
69+
if enabled then
70+
print("toggleAlarmInterrupt ioctl RTC_AIE_ON", re, err)
71+
else
72+
print("toggleAlarmInterrupt ioctl RTC_AIE_OFF", re, err)
73+
end
74+
return nil, re, err
75+
end
76+
re = C.close(rtc0)
77+
if re == -1 then
78+
err = ffi.string(C.strerror(ffi.errno()))
79+
print("toggleAlarmInterrupt close /dev/rtc0", re, err)
80+
return nil, re, err
81+
end
82+
83+
return true
84+
end
85+
4086
--[[--
4187
Set wakeup alarm.
4288
@@ -103,7 +149,9 @@ end
103149
Unset wakeup alarm.
104150
--]]
105151
function RTC:unsetWakeupAlarm()
106-
self:setWakeupAlarm(-1, false)
152+
-- NOTE: Both util-linux & busybox rtcwake leave the current alarm as-is, and just disable the alarm interrupt.
153+
-- c.f., toggleAlarmInterrupt for details.
154+
self:toggleAlarmInterrupt(false)
107155
self._wakeup_scheduled = false
108156
self._wakeup_scheduled_ptm = nil
109157
end

ffi/rtc_h.lua

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ struct rtc_wkalrm {
1717
unsigned char pending;
1818
struct rtc_time time;
1919
};
20+
static const int RTC_AIE_ON = 28673;
21+
static const int RTC_AIE_OFF = 28674;
2022
static const int RTC_WKALM_SET = 1076391951;
2123
static const int RTC_WKALM_RD = 2150133776;
2224
typedef long int time_t;

0 commit comments

Comments
 (0)