The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Linux::RTC::Ioctl - Real Time Clock access using the Linux driver ioctl interface.

VERSION

Version 0.08

SYNOPSIS

Provides access to the Linux RTC driver (Real Time Clock), using one of the RTC device files in a Linux system:

    - /dev/rtc
    - /dev/rtc0
    - /dev/rtc1
    - ...

Note /dev/rtc is now usually a symlink to /dev/rtc0.

Usage:

    use Linux::RTC::Ioctl;

    my $rtc = Linux::RTC::Ioctl->new($device) // die "Error: $!";

    $sec, $min, $hour, $mday, $mon, $year = $rtc->read_time;

    # or:
    $rtc->read_time // die "Failed to read RTC device: $!";
    $sec, $min, $hour = $rtc->{sec}, $rtc->{min}, $rtc->{hour};

    $rtc->{year} += 1;
    $rtc->set_time;     # Set RTC time one year in the future
    $rtc->set_time($sec, $min, $hour, $mday, $mon, $year+1);

    $enable = !0;

    $rtc->update_interrupt($enable);

    $freq = 20;
    $rtc->periodic_frequency($freq) // die "Access to RTC device failed: $!";
    $freq = $rtc->periodic_frequency;
    $rtc->periodic_interrupt($enable);

    $rtc->read_alarm // die "Access to RTC device ${\$rtc->nodename} failed: $!";
    $rtc->set_alarm($sec, $min, $hour, $mday, $mon, $year);
    $rtc->read_wakup_alarm
    $rtc->set_wakeup_alarm($sec, $min, $hour, $mday, $mon, $year);
    $rtc->alarm_interrupt($enable);

DESCRIPTION

$device can be an open file handle, a device file name, a device number (0, 1, 2..) or empty (undef), in which case /dev/rtc is used.

The Linux driver has built-in locking so that only one process can have the /dev/rtc interface open at a time. You must be root or must have permissions to access the device file, according to the usual file owner and group. User processes than can access the device, still need to have the CAP_SYS_TIME capability in order to use the $rtc->set_time method.

Beware the RTC time runs in the RTC time zone, which is not the same as the local time zone of the system, as it can also be GMT. To prevent problems with the transition to and from DST (daylight saving time), the RTC should run in the GMT time zone, which is usually the default for the Linux setup. Note there is no why to retrieve this time zone from the RTC device, the system stores this information elsewhere (see the manual page for the `hwclock` command for more details). Even if you know the RTC time zone, the RTC time will not accurately match the system time. Linux OS learns how fast the RTC time is running compared to real time, and if it is not accurate, Linux will constantly adjust the RTC (every 11 min) to keep it close to the real time.

Any functionality described here is present only when supported by the RTC hardware. Methods that access the device return undef in case of error, in which case you can read the system error variable $!. Methods are defined only if the corresponding ioctl request is defined for the platform, you can check for example defined \&Linux::RTC::Ioctl::set_wakeup_alarm.

All methods can take the date-time components from:

  • the argument list (if arguments are passed)

  • the $rtc object fields (empty arguments list)

All methods can return the date-time components as:

  • function result (if called in list context)

  • the $rtc object fields (in scalar or void context)

All information here is taken from:

See your platform documentation for more information.

METHODS

my $rtc = Linux::RTC::Ioctl->new($device)

Creates an RTC object from given open file handle, device file name, device index, or /dev/rtc by default.

If an open file handle is given, it must represent a device file on the platform, that supportes the RTC ioctl requests. Binary mode will be turned on for the open handle

Only one process can open the same RTC device at a time. Returns undef if opening fails, in which case you can read the $! variable.

$rtc->nodename

The name of the device file that is used by this $rtc object. This is given (or implied) by the argument passed to the new() constructor.

If the new() constructor is given an open file handle (no file name), the nodename will be undef, unless (on most Linux platforms) the file name can still be found using procfs at a path of the form: /proc/<PID>/fd/<fd>.

Might be usefull to show error messages when $rtc methods fail.

$rtc->device

An open file handle for the RTC device file represented by this $rtc object. This is a read-only character device that will block on read until the next timer event occurs (either a time update interrupt, a periodic timer interrupt, or an alarm interrupt; timers use IRQ 8). Usually you need to enable the timer interrupts before you can read from this file.

When the event occurs, a block of fixed size (given by RTC_RECORD_SIZE, which is the size of an unsigned long on the native platform) can be read, of which the low order byte is a bitmask of flags choosen from RTC_PF (for periodic interrupt), RTC_UF (time update interrupt) and RTC_AF (alarm interrupt), and the remaining bytes are a count of interrupts that occurred since the last read.

You can also use the file handle in calls to select() to avoid blocking the current thread on the RTC device only.

Example for reading the device file:

    my $rtc_record = pack 'L!', 0;
    my $record_size = length $rtc_record;   # length also given as the package constant RTC_RECORD_SIZE
    my $size = sysread $rtc->device, $rtc_record, $record_size; # blocks until next timer event occurs

    defined $size or die("Access to real time clock device failed: $!");
    $size == $record_size or die("Unexpected end of file reading RTC device.");

    $rtc_record = unpack 'L!', $rtc_record;

    # Event flags and the interrupt count are now available
    $timer_flags = $rtc_record & 0xFF;
    $timer_count = $rtc_record >> 8;

Or you can use the $rtc->wait_for_timer() method, which natively does about the same as the above.

$rtc->rtctime

    $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst = $rtc->rtctime
    $rtc->rtctime($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst)

Similar to localtime and gmtime, $rtc->rtctime returns a list of the the broken-down time components stored in the $rtc object. You can also pass such a list to this method, to populate the $rtc object.

There is no calendar time alternative to these components, measured as seconds from the begining of the Unix epoch. To build one you would need to know the RTC time zone (either GMT or the local time zone), which the RTC device does not.

The time components stored in the $rtc object are used by the set_time, set_alarm and set_wakeup_alarm methods when they are called without any arguments. The time components are also populated by the read_time, read_alarm and read_wakeup_alarm methods when they are called in void or scalar context. When such methods are called in list context, the time components are returned as usual and are NOT stored in the $rtc object.

Note the RTC device does not use the last 3 time components: $wday, $yday, $isdst. They are included here to match the platform C-language API, but it f needed please exclude them with a sublist like @{[ $rtc->rtctime ]}[0..5].

$rtc->wait_for_timer

    $event_flags, $event_count = $rtc->wait_for_timer();

Wait for the next timer event.

Will issue a read from this RTC device. Blocks the current thread, so only use if you set up the alarm or timer events, and/or you know it is going to ring soon enough. To avoid blocking the thread for just the RTC device, you can use the $rtc->device in a call to select().

Returns a bitmask of flags indicating what timer events have occurred, and a count of all the events since the last read. See the RTC_PF, RTC_UP, RTC_AF, RTC_IRQF falgs. If read failes returns undef, in which case you can read the $! variable.

$rtc->periodic_frequency

    $rtc->periodic_frequency($frequncy);
    $frequency = $rtc->periodic_frequency;

Sets up the the requency for periodic RTC events (interrupts). The frequency must be a power of 2 between 2 and RTC_MAX_FREQ. After setting the frequency you should also enable the periodic interrupt. Maximum frequency for a non-root user (usually 64) can be read from file /sys/class/rtc/rtc0/max-user-freq. Returns undef if the underlaying ioctl call failes, in which case you can read the $! variable.

$rtc->periodic_interrupt($enable)

Sets up the RTC device to emit or not periodic (frequncy) timer events (IRQ 8 interrupts). Enable or disable the periodic interrupts. Returns undef on failure from the underlaying ioctl call, read $! variable.

$rtc->update_interrupt($enable)

Sets up the RTC device to emit or not update timer events (whenever the current time changes). Enable or disable the update interrupts. Returns undef on failure from the underlaying ioctl call, read $! variable.

$rtc->alarm_interrupt($enable)

Sets up the RTC device to emit or not timer events (IRQ 8 interrupts). Enable or disable the alarm interrupts. Returns undef on failure from the underlaying ioctl call, read $! variable.

$rtc->read_time

$rtc->set_time

    $rtc->read_time;
    $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst = $rtc->read_time;
    
    $rtc->set_time;
    $rtc->set_time($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);

Sets or reads the RTC date and time in the RTC time zone. Uses the members in $rtc: $rtc->{sec}, $rtc->{min} $rtc->{hour}, $rtc->{mday}, $rtc->{mon}, $rtc->year, $rtc->{wday} (not used), $rtc->{yday} (not used), $rtc->isdst (not used). These fields are similar to the components return from gmtime or localtime: mon begins with 0 for january, year begins with 0 for 1900. For non-root users, even if you can read the device, you still need CAP_SYS_TIME capability to set the real time clock. Returns undef on error, when you can read the $! variable.

$rtc->read_alarm

$rtc->set_alarm

    $rtc->read_alarm;
    $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst = $rtc->read_alarm;
    
    $rtc->set_alarm;
    $rtc->set_alarm($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);

Sets or reads the RTC alarm time in the RTC time zone. Can use the members in $rtc: $rtc->{sec}, $rtc->{min} $rtc->{hour}, $rtc->{mday}, $rtc->{mon}, $rtc->year, $rtc->{wday} (not used), $rtc->{yday} (not used), $rtc->isdst (not used). The Linux documentation describes only the time components (sec, min, hour) as being used here, and not the date components. These fields are similar to the components returned from gmtime or localtime. Returns undef on error, when you can read the $! variable.

$rtc->read_wakeup_alarm

$rtc->set_wakeup_alarm

    $rtc->read_wakup_alarm // die "Access to real time clock device ${\$rtc->nodename} failed: $!";
    $enabled, $pending, $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst = $rtc->read_wakeup_alarm;

    $rtc->set_wakeup_alarm // die "Access failed";
    $rtc->set_wakeup_alarm($enabled, $pending, $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) // die "Error";

Some RTCs support these methods as improved (and preferred) versions of $rtc->read_alarm and $rtc->set_alarm. The $enabled argument or return is used to enable or disable the alarm interrupt for this alarm, the $rtc->alarm_interrupt call is not used for this alarm. The $pending argument is used to report a pending interrupt, mostly for firmware, do not use it.

Both time and date components should work to set the wake-up alarm. Some hardware allows periodic alarms if you use special values for year, month, day, etc. On most hardware this alarm can kick the computer out of suspend / stand-by or power-off (might not work for laptops when running on battery power). You might read wakeup-enable status from /sys/class/rtc/rtc0/device/power/wakeup file.

If method arguments or results are not used, the time components can be found in the $rtc object fields, as well as the two additional fields $rtc->{enabled} and $rtc->{pending}.

$rtc->read_voltage_low_indicator

$rtc->clear_voltage_low_indicator

    $voltage_indicator = $rtc->read_voltage_low_indicator // die "Voltage Low indicator not supported $!."
    $rtc->clear_voltage_low_indicator // die "Voltage low indicator not supported $!."

Not directly documentated, presumably reads/resets RTC battery voltage low indicator for hardware that can report this.

$rtc->close

Closes the underlaying device in $rtc->device (like /dev/rtc). The $rtc object should no longer be used after calling this method.

EXPORT

Constants for use with the ioctl() call can be exported with:

    use Linux::RTC::Ioctl qw(:all)

or you can export individual constants by name if you so wish.

Exportable constants

Each of the following constants is exported only if the platform defines it.

ioctl requests:

The following constants are exposed from the system headers of the underlaying platofrm (see <linux/rtc.h>), and have been used to implement the methods above.

Enable/disable periodic interrupt. Can be used to generate a periodic signal with any power of 2 frequency between 2Hz and RTC_MAX_FREQ for root user (usually max 64Hz for non-root, see /sys/class/rtc/rtc0/max_user_freq). Using the maximum frequency is likely to consume CPU time resources on your target machine.

    RTC_PIE_OFF
    RTC_PIE_ON
    RTC_MAX_FREQ

Enable/disable timer interrupt on every time update. Since the RTC displays time in seconds, the interrupt will occur once per second (1Hz)

    RTC_UIE_ON
    RTC_UIE_OFF

Enable/disable timer interrupt when the alarm rings.

    RTC_AIE_ON
    RTC_AIE_OFF

Read and set current RTC date and time.

    RTC_RD_TIME
    RTC_SET_TIME

Read and set the RTC time since the RTC epoch. This is not the same as the Unix epoch normally used by the system.

    RTC_EPOCH_READ
    RTC_EPOCH_SET

Read or set the alarm time. Usually only hour, minutes and seconds are supported.

    RTC_ALM_READ
    RTC_ALM_SET

Read or set the wake-up alarm time. Supports both date and time. For most hardware this alarm can pull the computer out of suspend/sleep, and even out of hibrenate/poweroff.

    RTC_WKALM_RD
    RTC_WKALM_SET

Read / set periodic interrupt frequency:

    RTC_IRQP_READ
    RTC_IRQP_SET

Flags for records read from the RTC device file

Record size (records from RTC device files are fixed-length), always defined as the native size of an unsigned long:

    RTC_RECORD_SIZE

Flag indicating periodic interrupt has occurred:

    RTC_PF

Flag indicating an update interrupt has occurred (current RTC time has just changed):

    RTC_UF

Flag indicating an alarm interrupt occurrent (the alarm was set and just went off):

    RTC_AF

Flag indicating any of the above 3 flags is also set:

    RTC_IRQF

Other constants

These are not documented in the Linux kernel, but are exposed to C/C++ programs in the system headers.

Read / set PLL correction (like the RTC used in Q40/Q60 computers):

    RTC_PLL_GET
    RTC_PLL_SET

Read voltage low detector / clear voltage low information:

    RTC_VL_READ
    RTC_VL_CLR

constant

Internal method used to autoload the above constants.

AUTHOR

Timothy Madden, <terminatorul at gmail.com>

BUGS

Please report any bugs or feature requests to bug-linux-rtc-ioctl at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Linux-RTC-Ioctl. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Linux::RTC::Ioctl

You can also look for information at:

ACKNOWLEDGEMENTS

LICENSE AND COPYRIGHT

Copyright 2016 Timothy Madden.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.