---------------------------------------------------------
  Linux Powerswitch Driver

  Version 1.5, Feb 2003
  Joris van Rantwijk
---------------------------------------------------------


What is it ?
------------

The powerswitch driver makes it possible to use the ATX power button
on your computer to shutdown Linux. You simply press the power button,
and the driver shuts down Linux and powers off the machine, just like
the shutdown command does.


Why is it useful ?
------------------

It isn't.
But it is cool to have it.
And it was cool to make it.
And I could imagine it being useful in case you have a Linux server running
without a keyboard or monitor attached. It would then make sense to have
a way of shutting down the system without having to plug in a keyboard.


How does it work ?
------------------

On most ATX PC motherboards, it is possible to configure the power button
so that it generates an APM suspend request instead of immediately powering
off the machine. For example: my power button works as suspend button
when pressed for a short time, and it switches off the power when I press
it for more than 3 seconds.

Suspend requests are intercepted by the powerswitch driver, which then
executes "/sbin/shutdown -h now" to shutdown the system. To make this work,
the powerswitch driver should be loaded as a kernel module at system boot
time. Unfortunately, you will loose the possibility to do normal APM suspends
on your computer (since all APM suspend requests are interpreted as
poweroff requests). This is normally not a problem.


Requirements
------------

- Linux 2.2.x - 2.6.x kernel, with APM support enabled.
- ATX motherboard with APM support and APM suspend button support.
- Linux kernel header files for your kernel version installed
  in /usr/src/linux/include.


Installation
------------

- Compile the powerswitch module by giving the command "make".
  This should result in the kernel module "powerswitch.o".

  The source contains support for two different interfaces to the Linux
  powermanagement system: the old apm_bios interface for Linux 2.2.x and
  the new pm interface for Linux 2.4.x and later. Only one of these
  interfaces is compiled into the module; the right one should automatically
  be selected based on the kernel version.

  It is possible to use the old apm_bios interface for 2.4.x kernels with
  APM support, but the pm interface is a bit more elegant and should also
  work with ACPI (not tested). You can force the old interface by defining
  the -DUSE_APMDEV flag in the Makefile.

- Change your computer's BIOS setup to make the power button act as suspend
  button. Also make sure to disable automatic suspend-on-idle options (or
  your computer will shut down when it becomes idle).

- Enable APM support and APM power off support in the Linux kernel
  (recompile if necessary).

- Test the functionality of the suspend button: press it to suspend the
  system, press it again to resume.

- Install the powerswitch module in the kernel:
    insmod powerswitch.o

- Test the powerswitch driver: press the suspend button and the system
  should shut down immediately.

- Configure your system to load the powerswitch module automatically at
  system startup. Copy powerswitch.o to an appropriate directory (such
  as /lib/modules/2.4.18/misc) and change startup scripts if necessary.
  On Debian systems, you can make the module load at boot time by adding
  the line "powerswitch" to the file /etc/modules.

- You can unload the module with the command: "rmmod powerswitch".
  The Linux 2.2.x version of the module cannot be unloaded as long as the
  APM monitor thread is still running. Kill the thread first with
  "killall -KILL powerswitch".


Problem solving
---------------

If the module fails to load or doesn't work properly, try the command
"dmesg" to see any kernel messages about the module.

P: The module gives errors when compiling.
P: Loading the module gives errors about version incompatibility.
S: Make sure you have the kernel headers for your _current_ kernel version
   installed in /usr/src/linux/include. Most distributions have a package
   called "kernel-source" or "kernel-headers" for this. The kernel tree
   must also be configured exactly like your current kernel. If you have the
   kernel headers in a different location, you may use the KERNELDIR option
   to the makefile like: "make KERNELDIR=/usr/src/kernel-source-2.4.18"

P: Loading the module results in a warning about tainting the kernel
   because there is no license in the module file.
S: This message appears because there is no explicit license statement in
   the powerswitch module code. I refuse to put a license statement in the
   module because I don't believe in this automated license checking
   business. But don't worry: tainting the kernel is completely harmless,
   and powerswitch _is_ free software.

P: Compiling and loading seems to work, but there are many weird bugs.
S: Make sure that the kernel and the powerswitch module are compiled
   with the same version of GCC. The 2.2.x kernels are sometimes compiled
   with an older version of GCC, often included in distributions as gcc272
   or kgcc. If your 2.2.x kernel was compiled with gcc272, then the module
   _must_ also be compiled with gcc272 or you'll get the weirdest bugs ever.
   Do "cat /proc/version" to see which version of GCC your kernel was
   compiled with, and "gcc -v" to show the system's GCC version.
S: Make sure that the kernel and powerswitch module are compiled with
   the same kernel configuration settings. For example: it would be a bad
   thing to load a uniprocessor module in an SMP kernel.

P: The module doesn't work with Linux 2.2.x and gives the log message
   "Cannot open /dev/apm_bios" when loading.
S: You need to create the device node /dev/apm_bios by giving the
   following command as root: "mknod /dev/apm_bios c 10 134"

P: The system immediately powers off when pushing the power button.
S: The power button is not properly configured as suspend button.
   Go to the BIOS setup and set the power button action to APM suspend.
   Some BIOSes have a power management master switch which must be
   enabled to make it work.

P: The system doesn't shut down when pushing the power button with
   the module loaded.
S: Look at the kernel messages. After pushing the button, powerswitch
   should say "Received suspend event". If this doesn't work, try pushing
   the button without the module loaded; the system should go to suspend
   mode. Make sure you are running a kernel with APM support (the file
   /proc/apm should exist).

P: My system doesn't suspend when pushing the power button _without_
   the module loaded.
S: Try what happens when pushing the power button before Linux starts
   (like in the bootloader screen). If the suspend button works before
   starting Linux, but not inside Linux, then you may have a driver loaded
   which blocks suspend events (some videocard/soundcard drivers). Also
   look for "suspend was vetoed" messages from the kernel.


Status
------

This is poorly tested beta software.
I'm not sure if the driver works correctly; it may crash your system or
cause kernel instability and other nasty things. I don't understand the
Linux kernel internals very well, so I used something like a trial-and-error
approach to minimize the number of kernel oopses. It seems to work fine now
on my system, but it may or may not work on your system.

powerswitch is copyright 2000-2003 by Joris van Rantwijk
This program is freeware; you may use, modify and/or distribute it
without restriction.


Version history
---------------

Version 0, Jan 2000
  - First try: combination of a kernel patch and a userspace daemon.
    See apm.c_2.2.12.patch and powerswitch-daemon.c

Version 1.0, Apr 2000
  - Reimplemented as a kernel module for Linux 2.2.x kernels.
  - This is still pretty much a kludge to work around the limitations
    in apm.c, things will get easier in 2.4.x.

Version 1.1, May 2000
  - Small cleanup of Linux 2.2.x module: thread now does exit_mm(),
    keep track of module usecount, use /sbin/shutdown instead of halt.
  - Added a seperate version for Linux 2.4.x kernels. I was wrong about it
    being easy; I've seen more than enough oopses by now.
  - First release.

Version 1.2, Jan 2001
  - Fixed the Makefile to make it work with the 2.4.0 kernel (added
    a -I/usr/include switch for gcc to fix weird posix_types.h problem).
  - Added a script for automatic version selection.

Version 1.3, May 2001
  - This driver now officially has a real user (other than myself).
  - Modified Makefile and version selection script to prefer the kernel
    headers files in /usr/src/linux/include above those in /usr/include.
    This eases compilation on systems with libc-supplied headers in
    /usr/include/{linux,asm} (like Debian).
    (contributed by Garric James)
  - Removed old files from the version 0 approach.
  - More pretty select_version script.
  - Documented GCC version problem.

Version 1.4, Aug 2001
  - Merged versions for Linux 2.2.x and 2.4.x into a single source file.
  - Should now also work on SMP kernels and on kernels with version
    information in the symbol names.
  - Use neat call_usermodehelper() interface on 2.4.x kernels.
  - Added install function to the Makefile.

Version 1.5, Feb 2003
  - Small changes to make it work with Linux 2.5.x
  - Updated documentation

----
