acpi-apm V2.0a
What is this?
acpi-apm is a Linux kernel module that simulates the
output from
/proc/apm on systems that
have ACPI, not APM, for power
management. Why is this useful? A great deal of software uses
/proc/apm to determine the
power and battery status, including the Gnome
and KDE applets that display battery status. Modern PCs, particularly
laptops, are increasingly using ACPI for power management, and don't
support APM very well. To use one of these systems you need to compile
ACPI support into the kernel, and disable APM. You therefore lose /proc/apm. There are
equivalent power monitoring utilities for ACPI, but they never seem to
work very well. With this module, it appears to applications like
Gnome that APM is available.
Please note that acpi-apm does not
simulate the control features of
APM, only the monitoring. You won't be able to use this module to give
you a suspend-to-RAM feature if your kernel doesn't support it
through ACPI. What's more, it does not provide an interface to /dev/apm_bios (not yet; maybe
never). A small number of power monitoring utilities interact with apm_bios directly, so this
module won't help them. Among that small number, annoyingly, is the
standard `apm' utility supplied with most Linux utilities.
acpi-apm works by intercepting reads made on
/proc/apm, determining the
power status from ACPI, then simulating the APM values based on the
ACPI values. You need to have ACPI support compiled into your
kernel and working before using this module. If you already have APM
support in your Linux kernel, you don't need this module, and it will
not load.
What APM utilities does acpi-apm work with?
acpi-apm should work with
any utility that reads /proc/apm.
It works (which is to say, it has been reported to
work by at least one person) with xapm,
battstat-applet (versions
supplied with RedHat Linux from 7.2-9),
and power-applet v0.5.
What kernel versions does it work with?
V2.0a of this module is radically different from
earlier versions. In particular, the method it uses to get access to
the battery status from ACPI is extremely ugly, but ought to work with
most modern kernels, and most versions of the ACPI patches that are
currently in circulation.
Previous versions attempted to
get to the ACPI data through ACPI API calls embedded in
the kernel. These calls are not well documented, and prone to change.
As a result, I had to tweak the module for every trivial change in the
ACPI patches. Then after
kernel version 2.4.17 I couldn't get the previous version to work at
all, with any amount of tweaking. This version works with 2.4.23, and
ought
to work with other kernels as well. If you find it compiles, but does
not produce credible output from /proc/apm,
please let me know.
Do I need to recompile the kernel to use acpi-apm?
No. No part of the kernel needs to be recompiled, and this module will
not interfere with any other part of the kernel (as far as I know).
However, you will need to have ACPI support working and, at the time of
writing, no standard Linux distribution had ACPI support. So you would
have had to recompile the kernel to get ACPI to work in the first place.
Compiling and installing
You will need to compile this. Please don't ask me for binaries, as
it's too much hassle to generate them. Compiling should not be
difficult, but you will need to have kernel headers installed, as well
as the compiler itself. To compile, unpack the archive and run
% make
in the source directory.
If it doesn't
compile, and you have all the prerequisites, e-mail me. The compilation
should generate the
file acpi-apm.o. Install the module by doing
# make install
Load this module into the kernel
by doing
# modprobe acpi-apm [jiffies_delay=NNNNN]
See below for a description of the jiffies_delay parameter. Run
% dmesg
and ensure there are no error messages from the module.
That's it.
If you do a cat /proc/apm you should see some
numbers in decimal and hex. If you get a segmentation fault,
e-mail me. How you get the module loaded at boot time is
up to you: rc script or whatever.
Configuration
This module takes one initialization parameter: jiffies_delay. This is minimum
amount of time the module will allow between real access to the ACPI
subsystem. If /proc/apm
is read more frequently than that, then the reader will get the last
value, which the module keeps in a cache. This is very important,
because ACPI access is much, much slower than APM on Linux systems
(perhaps on all systems). So utilities that were designed with APM in
mind hammer the /proc/apm
file ferociously. The Gnome battstat-applet,
for example, reads several times per second. This frequency of access
would bring most systems to a crashing halt. Of course, frequent
polling of /proc/apm
allows the display to update rapidly if, for example, the power cable
comes uplugged. This is handy but, in most circumstances, updating a
couple of times a minute should be enough. Since a `jiffy' is 1/100th
of a second, to load acpi-apm with a 30 second update time, do
this:
# modprobe acpi-apm jiffies_delay=3000
Bugs and limitations
This module is extremely simply, and has its own limitations. There are
also limitations with ACPI itself. You should bear in mind the
following if the module does not work as expected
- The module attempts to work out how long the battery will
continue
to run the machine. If the battery is on charge, the result will
generally be nonsense because ACPI reports the current
drawn from the battery, not the current drawn by the hardware. Of
course, off charge
these two figures are the same. On charge, the current drawn
by the battery is a nonsense figure. The only way to fix this
problem would be for the module to record the discharge figures
whenever the battery is off charge, and try to interpolate when
on charge. This just seems like too much of a chore. When the battery
is charging, the module reports the battery life as `-1 sec', which
causes most client utilities to report that the battery life as
unknown, which is correct.
- Only one battery is monitored, even though some systems support
more than one battery. I think that it won't fall over
completely
with more than one battery, and it may even produce valid results
if the batteries charge and discharge together. But it won't
be perfect. Again, it was just too much of a chore to write the code
to add up the charges, average the discharge rates, etc.
- The module assumes that the files /proc/acpi/battery/BAT1/state
and /proc/acpi/battery/BAT1/info
exist. In some earlier ACPI implementations, the state file was called
`status'. If that's what you've got, you'll need to modify the code to
that effect.
- To reduce the number of ACPI calls, the software does not
interrogate ACPI for the mains power status. Instead, it assumes
that there is mains power if (a) there is no battery reported, or
(b) a battery is reported as charging. It seems to me that this
is a not quite an infallible algorithm. I think it's
safe to assume that if there is neither mains power
nor a battery, then you won't have a running machine. But isn't
necessarily true that if there is
mains power then the battery must be charging. Where it will fall
down is if your BIOS shows the battery in the `ok' state rather
than the `charging' state when it is fully charged on mains power.
Then it will look like the mains has been switched off. However,
it works correctly on my laptop, which is good enough for me :)
- One of the values output from /proc/apm is called
`battery_flag'.
It's never been clear to me what this is for. This module sets
-1 to this field which does not appear to be a problem. I guess that
means that the client software doesn't read it.
- This module does parse the contents of files in the /proc/acpi directory. The
contents of these files have been stable for a while now, but there's
no guarantee that this will remain the case. It should be relatively
straightforward to hack the code to deal with minor changes in the
files.
Technical notes
This module works by reading an parsing the contents of /proc/acpi/battery/BAT1/state
and /proc/acpi/battery/BAT1/info.
It takes the data from these files, does a bit of arithmetic, and
generates a simulation of the contents of /proc/apm. acpi-apm does not read the
files in the sense that an application program would read them; that
is, it does not generate a system call into the kernel's VFS layer (we
are in the kernel already). Instead it finds the location in the
kernel's address space of the function that ultimately has to be
invoked when these files are read, and calls that function directly. It
finds the function by getting a struct
file object for the file using filp_open, and navigating down to
the read() function in
the file_operations
structure. I suppose that ideally the module should try to find a
cached dentry for the files before doing filp_open(), but since all
operations on /proc are
done in memory, I don't think it would make much difference to the
speed of response. The module allocates exactly one page of kernel
memory, so if there ever comes a time when the files in /proc/acpi are
more than 1 kB long, we'll be in trouble. I can't guarantee that there
aren't error conditions that will cause a buffer to overflow in the
module, and crash the machine. I've tried to trap most of the obvious
problems, but the module does rely to a certain extent on the ACPI
subsystem outputting meaningful data.
Author and legal
This kernel module was written by Kevin Boone and is (c)2002-2004. You
may do whatever you like with the source code, provided that you
continue to acknowledge the author in any distribution of it, and of
any distribution of code substantially derived from it; and that you
make the original source code
available. Needless to say, there is no warranty of any kind, and
you use this at your own risk. Please report bugs, etc., to
kb@kevinboone.com.