Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tweak RTC alarm disable #1106

Merged
merged 1 commit into from
May 31, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ffi-cdecl/rtc_cdecl.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
cdecl_struct(rtc_time)
cdecl_struct(rtc_wkalrm)

cdecl_const(RTC_AIE_ON)
cdecl_const(RTC_AIE_OFF)
cdecl_const(RTC_WKALM_SET)
cdecl_const(RTC_WKALM_RD)

Expand Down
50 changes: 49 additions & 1 deletion ffi/rtc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,52 @@ function RTC:secondsFromNowToEpoch(seconds_from_now)
return epoch
end


--[[--
Enable/Disable the alarm interrupt.
The use of RTC_WKALM_SET allows us to bypass the need for RTC_AIE_* calls,
thanks to the enabled field in the rtc_wkalrm struct.
Busybox rtcwake still does an RTC_AIE_OFF when resuming from an alarm wakeup,
as does Nickel when powering off.
In this scenario, the modern util-linux rtcwake, which never uses legacy RTC_ALM_SET calls,
instead uses RTC_WKALM_SET filled from RTC_WKALM_RD but with enabled set to 0.

@enabled bool Whether the call enables or disables the alarm interrupt. Defaults to true.

@treturn bool Success.
@treturn re Error code (if any).
@treturn err Error string (if any).
--]]
function RTC:toggleAlarmInterrupt(enabled)
enabled = (enabled ~= nil) and enabled or true

local err
local rtc0 = C.open("/dev/rtc0", bor(bor(C.O_RDONLY, C.O_NONBLOCK), C.O_CLOEXEC))
if rtc0 == -1 then
err = ffi.string(C.strerror(ffi.errno()))
print("toggleAlarmInterrupt open /dev/rtc0", rtc0, err)
return nil, rtc0, err
end
local re = C.ioctl(rtc0, enabled and C.RTC_AIE_ON or C.RTC_AIE_OFF, 0)
if re == -1 then
err = ffi.string(C.strerror(ffi.errno()))
if enabled then
print("toggleAlarmInterrupt ioctl RTC_AIE_ON", re, err)
else
print("toggleAlarmInterrupt ioctl RTC_AIE_OFF", re, err)
end
return nil, re, err
end
re = C.close(rtc0)
if re == -1 then
err = ffi.string(C.strerror(ffi.errno()))
print("toggleAlarmInterrupt close /dev/rtc0", re, err)
return nil, re, err
end

return true
end

--[[--
Set wakeup alarm.

Expand Down Expand Up @@ -103,7 +149,9 @@ end
Unset wakeup alarm.
--]]
function RTC:unsetWakeupAlarm()
self:setWakeupAlarm(-1, false)
-- NOTE: Both util-linux & busybox rtcwake leave the current alarm as-is, and just disable the alarm interrupt.
-- c.f., toggleAlarmInterrupt for details.
self:toggleAlarmInterrupt(false)
self._wakeup_scheduled = false
self._wakeup_scheduled_ptm = nil
end
Expand Down
2 changes: 2 additions & 0 deletions ffi/rtc_h.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ struct rtc_wkalrm {
unsigned char pending;
struct rtc_time time;
};
static const int RTC_AIE_ON = 28673;
static const int RTC_AIE_OFF = 28674;
static const int RTC_WKALM_SET = 1076391951;
static const int RTC_WKALM_RD = 2150133776;
typedef long int time_t;
Expand Down