# power button handling with acpid

## mb

hi,

these 2 small scripts will handle the power button and display the kde shutdown dialog (if kde is running) or simply call init 0.

You need:

- Kernel with recent acpi support

- button support (CONFIG_ACPI_BUTTON=y or m)

- acpid

```

# /etc/acpid/events/powerbtn

# This is called when the user presses the power button and calls

# /etc/acpid/powerbtn.sh for further processing.

# Optionally you can specify the placeholder %e. It will pass

# through the whole kernel event message to the program you've

# specified.

# We need to react on "button power.*" and "button/power.*" because

# of kernel changes.

event=button[ /]power

action=/etc/acpi/powerbtn.sh

```

```

#!/bin/sh

# /etc/acpi/powerbtn.sh

# Initiates a shutdown when the power putton has been

# pressed.

if ps -Af | grep -q '[k]desktop' && test -f $KDEDIR/bin/dcop

then

    dcop --all-users ksmserver ksmserver logout 1 2 0 && exit 0

else

    /sbin/init 0

fi

```

remember to chmod 755 powerbtn.sh

note: taken from an unkown source and modified

todo:

- lid open/close -> xset dpms force on/off

- ac-adapter -> dont know

- gnome, other wm support

#mb

----------

## 870Fragmaster

to get this to work for me, in powerbtn.sh, i had to change it to --all-sessions. example bellow:

```
#!/bin/sh 

# /etc/acpi/powerbtn.sh 

# Initiates a shutdown when the power putton has been 

# pressed. 

 

if ps -Af | grep -q '[k]desktop' && test -f $KDEDIR/bin/dcop 

then 

    dcop --all-sessions ksmserver ksmserver logout 1 2 0 && exit 0 

else 

    /sbin/init 0 

fi 

```

----------

## nalin

heres an ac adaptor in and out events that ajust monitor brightness and time till dpms kicks in for slight power saving:

```

bash-2.05b$ cat /etc/acpi/events/ac_adaptor_in

event=ac_adapter.ACAD.00000080.00000001

action=`/usr/bin/X11/xgamma -d 0:0 -gamma 1.000;/usr/bin/X11/xset -d 0:0 dpms 0 0 300`

bash-2.05b$ cat /etc/acpi/events/ac_adaptor_out

event=ac_adapter.ACAD.00000080.00000000

action=`/usr/bin/X11/xgamma -d 0:0 -gamma 0.666; /usr/bin/X11/xset -d 0:0 dpms 0 0 120`

```

Im not sure whether the event codes are specific to me, i got em by tailing /var/log/acpid, and i think one needs xhost in their startup scripts

----------

## gkmac

If you prefer KDE to shut down immediately as opposed to displaying the shutdown dialog, in /etc/acpi/powerbtn.sh change the line...

```
dcop --all-users ksmserver ksmserver logout 1 2 0 && exit 0
```

 to 

```
dcop --all-users ksmserver ksmserver logout 0 2 0 && exit 0
```

----------

## ksuther

Great tip, thanks! I was getting tired of accidentally punching the power button and having it force power-off with apm. One thing people might want to remember when tinkering with their powerbtn.sh script is to restart acpid after each change by doing:

/etc/init.d/acpid stop ; /etc/init.d/acpid start

Took me a few minutes to figure out why my changes weren't happening  :Wink: 

----------

## handsomepete

Just replying to bookmark.  Ignore me.

----------

## nalin

Appended p4 throttling to my apcid ac_adaptor * scripts

Depending on your hardware you may or may not have the ability to do this.  I am not sure what kernels support it, I am using the ac-sources because I am told they have excellent acpi support, and I get lockups on boot with acpi and the gentoo sources.  

I have all the acpi stuff save that which is machine specific compiled in as well as the cpu-freq stuff specific to my machine.  The latter may not be necessary, from its documentation I believe it needs 2.5+ series kernels or something patched with sysfs in order to be used...waiting till next compile to remove it and test without it

If you compile in the acpi stuff reboot and have a  /proc/acpi/processor/CPU0/throttling file then you can try these

ac_adaptor_in

```

event=ac_adapter.ACAD.00000080.00000001

action=/usr/bin/X11/xgamma -d 0:0 -gamma 1.000; /usr/bin/X11/xset -d 0:0 dpms 0 0 300; echo -n 0 > /proc/acpi/processor/CPU0/throttling

```

ac_adaptor_out

```

event=ac_adapter.ACAD.00000080.00000000

action=/usr/bin/X11/xgamma -d 0:0 -gamma 0.666; /usr/bin/X11/xset -d 0:0 dpms 0 0 120; echo -n 6 > /proc/acpi/processor/CPU0/throttling

```

There are other /proc/acpi/processor tweaks documented here, this was the only one which did not freeze my machine...the states can be examined by cat'ing the aforementioned file, the %'s are the percent of cpu power loss, thus 0% is full power

----------

## TinheadNed

Actually as I understand it, throttling isn't power saving, it's the percentage of time NOPs are sent to the CPU in an attempt to reduce power consumption and heat.  It's not guaranteed to have any effect.  The performance file contains true power management.

Check acpi.sourceforge.net for more information.  I can't remember how to embed links off the top of my head

----------

## hulk2nd

hi there,

i need a little help and it would be great if somebody knows how to write my problem into a little script cause im absolute noob at that:

what i want:

if ac_adaptor is plugged in, then spicctrl -b 255

if ac_adaptor isnt plugged in, then spicctrl -b 0

this sets the brightness to maximum if the ac adaptor is plugged in and sets the brightness to minimum if ac adaptor isnt plugged in using the utility spicctrl.

is it possible to integrate that somehow into acpid?

Edit

ahh, got it already. just changed the ac_adaptor_in and the ac_adaptor_out files according to my needs. but there is still one question i have: if i boot without ac adapter, i just  have to plugin the cable and then unplug it again to change the brightness. isn't it possible that it will change these settings already at boot?

what im trying to say is, that these ac scripts only works after acpid has been started and they don't look immediatly after the state of the ac adapter. they only change something if the state changes.

Edit

thanks and greetz,

hulk

----------

## fishhead

Here's a script I use when AC is removed. If the batery gets to the warning level, it'll beep three times. If the battery is criticaly low, it will do a shutdown. Perl is required. You might need to do a few modifications to get this to work, and making it more flexable (i.e. reading a config file) would be nice.

The event handler:

```
#!/usr/bin/perl

if ($#ARGV != 3) { die("Too few arguments - " . $#ARGV  .  "\n") }

if ($ARGV[3] eq "00000000")

{

   print "AC removed. Starting battery monitor.\n";

   my $status = fork;

   if ($status eq "undef")

   {

      print "Fork unsucessful!\n";

   }

   elsif ($status == 0) # child

   {

      close STDOUT; 

      close STDERR;

      close STDIN;

      open(STDOUT,'>',"/dev/null");

      open(STDERR,'>',"/dev/null");

      open(STDIN,'<',"/dev/null");

      exec("/sbin/powermond");

   }

   else

   {

      print "Fork sucessful. Child pid is " . $status . "\n";

   }

   

}

elsif ($ARGV[3] eq "00000001")

{

   print "AC is back. Killing battery monitor.\n";

   `killall -KILL powermond`; 

}

exit(0);

```

/sbin/powermond:

```
#!/usr/bin/perl 

# Battery stuff ... made more readable

%battery = ();

# Ac stuff

%ac_adapter = ();

sub make_list

{

   my $list = $_[0];

   for(my $c = 0; $c < @{$list}; $c++) 

   { 

      chomp(${$list}[$c]);

      my @tmp = split(/:/,${$list}[$c]);

      ${$list}[$c] = \@tmp;

   }

}

sub make_hash

{

   my $hash = $_[0];

   my $list = $_[1];

   for( my $c = 0; $c < @{$list}; $c++)

   {

      $$$hash{${$list}[$c][0]} = ${$list}[$c][1];

   }

}

sub set_info

{

 my $battery = $_[0];

 my $ac = $_[1];

 #Get needed info ...

 #Adapter pugged in?

 my @ac_state = `cat /proc/acpi/ac_adapter/ACAD/state | sed -e 's/: */:/g'`;

 #Needed info about battery

 my @battery_info = `cat /proc/acpi/battery/BAT1/info | sed -e 's/: */:/g 

                         s/mAh//g

                        s/mA//g

                        s/mV//g'`;

 #Status of battery

 my @battery_state = `cat /proc/acpi/battery/BAT1/state | sed -e 's/: */:/g

                           s/mAh//g

                           s/mA//g

                           s/mV//g'`;

 make_list( \@ac_state );

 make_list( \@battery_info );

 make_list( \@battery_state );

 make_hash( \$ac , \@ac_state );

 make_hash( \$battery, \@battery_info );

 make_hash( \$battery, \@battery_state );

}

sub batt_left

{

   my $capacity = $_[0];

   my $rate = $_[1];

   my @list;

   if ($rate == 0)

   {

      $list[0] = 8;

      $list[1] = 0;

      return @list;

   }

   $list[0] = int($capacity / $rate);

   $list[1] = int($capacity * 60 / $rate) % 60; 

   return @list;

}

sub do_sleep

{

   my $hours = $_[0];

   my $minutes = $_[1];

   if ($hours >= 1)

   {

      sleep(600);

   }

   elsif ($minutes > 30)

   {

      sleep(300);

   }

   elsif ($minutes > 20)

   {

      sleep(120);

   }

   else

   {

      sleep(10);

   }

   

}

# ac_adapter event on unplug and plug  -  battery events all the time UNLESS

# the power was battery to begin with.

# ac_adapter gives 00000000 on removal and 00000001 on insertion

# vars in each hash

#

# ac_adapter: state

#

# battery: present, design capacity (mAh),last full capacity (mAh), battery technology, design voltage (mV), 

# design capacity warning(mAh), design capacity low(mAh), capacity granularity 1(mAh), 

# capacity granularity 2(mAh) , model number, serial number, battery type, OEM info, 

# present, capacity state, charging state, present rate (mA), remaining capacity (mAh), present voltage (mV)

my $warning = "false";

while(1)

{

   set_info( \%battery , \%ac_adapter );

   # Ok, so we should have been called either at startup or by an ac_adapter event

   # so if an adapter is present, exit

   if ($ac_adapter{"state"} eq "on-line")

   {

      exit(0);

   }

   

   # We're on battery power. Should we warn or shutdown?

   if (($battery{"remaining capacity"} <= $battery{"design capacity warning"}) and ($warning eq "false"))

   {

      $warning = "true";

      `aumix -v90 -p90`;

      `beep -r 3`;

      `aumix -p0`;

   }

   elsif ($battery{"remaining capacity"} <= $battery{"design capacity low"})

   {

      `aumix -v90 -p90`;

      `beep -r 5`;

      `aumix -p0`;

      `shutdown -h now`;

      exit(0);      

   }

   #Ok, we still have time left, let's see how much ...

   @time_left = batt_left( $battery{"remaining capacity"}, $battery{"present rate"} ); # [ h, m] form

   

   #Now we'll sleep based on the time remaining

   do_sleep( @time_left );

   

}

```

Most of the subroutines could be useful for other things too.....

I the owner is root.root for both and they both have permissions of 700.

If anyone wants to modify this, put stuff in a library, ect. Feel free. I'm eventualy going to post this on my website ...

----------

## nalin

 *hulk2nd wrote:*   

> 
> 
> what im trying to say is, that these ac scripts only works after acpid has been started and they don't look immediatly after the state of the ac adapter. they only change something if the state changes.
> 
> 

 

If you write external scripts, you can explicitly call them at boot, though my example kinda sucks here...

With the ac_adapter, lets say your events has an entry that catchs ac_adaptor.* and calls /etc/acpi/script/ac_adaptor.sh

ac_adaptor.sh looks like this

```

#!/bin/bash

#test for ac

grep 'on-line' /proc/acpi/ac_adapter/ACAD/state > /dev/null

if [ $? = 0 ]; then

        #ac on vars

        GAMMA=1.000

        DPMS=600

        THROTTLE=0

        FREQ_MIN=66

        FREQ_MAX=100

        FREQ_NAME="performance"

else

        #ac off vars

        GAMMA=.666

        DPMS=240

        THROTTLE=1

        FREQ_MIN=0

        FREQ_MAX=0

        FREQ_NAME="powersave"

fi

#check for X server

ps -A | grep X

if [ $? = 0 ]; then

        #do display stuff

        /usr/bin/X11/xgamma -d 0:0 -gamma $GAMMA

        /usr/bin/X11/xset -d 0:0 dpms 0 0 $DPMS

fi

#check for root (does not work for acpid thus the comments)

#if [ $USER = root ]; then

        #do root  stuff

        echo -n $THROTTLE > /proc/acpi/processor/CPU0/throttling

        echo -n "0%$FREQ_MIN%$FREQ_MAX%$FREQ_NAME" > /proc/cpufreq

#fi

```

It works fine with acpid but at boot it gets kinda ugly!  The problem is that (with my example) you need to call it with a privledged user after x has started, which rules out /etc/conf.d/local.start etc/X11/xinit/xinitrc and .kde/Autostart

One could execute it within local.start and link to it within the Autostart directory and enable all functionality but thats rather unelegant.  You could also break up the individual parts in my example into 2 or more files executed at two or more times, but then you have twice as much to maintain when you change anything...in any case im not sure you need x or root stuff so...

 *TinheadNed wrote:*   

> Actually as I understand it, throttling isn't power saving, it's the percentage of time NOPs are sent to the CPU in an attempt to reduce power consumption and heat.  It's not guaranteed to have any effect.  The performance file contains true power management.
> 
> Check acpi.sourceforge.net for more information.  I can't remember how to embed links off the top of my head

 

Thanks ned, I have problems with the performance entries in that using the 2.4 series ac kernels info says that I have them and the files are there but echoing to them gives me no change and debug messages.  With the 2.6 series (tested with and without ac-patch), info lists that I do not have performance capibilities.  In any case, I have compiled in the cpu-freq stuff as a viable alternative to the cpu/performance modifications (incedentally, my limit functions correctly only when I set throttling and leave performance unchanged, I think this is related to the performance errors).

For those who are interested in using cpu-freq in 2.4 series, the commands necessary are given above (the kernel docs cover writing only via the sys fs, and if i am correct, the sys fs cannot be compiled into a ac-source kernel), the commands seem to be squeemish about the values, [0-100] and do better with two distinct values, or perhaps it is my bios alone!

I noticed that severely throttling (>3 mabye) and setting cpu-fre	q severly degrades proformance compared to setting cpu-freq alone, for instance at 12% and throttle of two (processor running ~400mhz)  I get a subtle but noticable slowdown, for 12% and throttle of six I get a pentium 90 16mb of ram (I have one with half the ram and thus I am able to mentally benchmark)!

----------

## hulk2nd

@nalin

big thanks for your help, that works great!

if i have time im gonna change it a little bit, but until now it is even cool!

 *Quote:*   

> and display the kde shutdown dialog (if kde is running)

 

is it possible to do this with gnome and how do i have to change the powerbtn.sh according to my needs?

big thanks and greetz,

hulk

----------

## water

 *hulk2nd wrote:*   

> @nalin
> 
> big thanks for your help, that works great!
> 
> if i have time im gonna change it a little bit, but until now it is even cool!
> ...

 

Almost same question for me. My login manager is gwm, but my desktop is KDE. So if anyone knows how to?

----------

## olias2

Thanks mb. This worked great for me on a nforce2 board. Now I just need to figure out how to get acpid to look at my keyboard power button so I don't have to reach down to my case button.  :Wink: 

Cheers, Olias

----------

## OdinsDream

 *olias2 wrote:*   

> Thanks mb. This worked great for me on a nforce2 board. Now I just need to figure out how to get acpid to look at my keyboard power button so I don't have to reach down to my case button. 
> 
> Cheers, Olias

 

Have a look at man xbindkeys, it might be just what you need. You can bind a keypress to any command. Included in the man page is information on capturing the keycodes for any key.

----------

## olias2

Thanks OdinsDream. I emerged xbindkeys and found out that the kb power button was c:222 

```
"NoCommand"

    m:0x10 + c:222

    Mod2 + NoSymbol

```

As a test, I was able to to configure the button to open up kcalc so I know the button works. Problem is that I don't know how to use this to do a shutdown.  :Sad: 

I then got off on a tangent with XF86Config and did some setup there as well...

```
Section "InputDevice"

        Identifier  "Keyboard0"

        Driver      "keyboard"

        Option "XkbRules" "xfree86"

        Option "XkbModel" "ACPI Standard"

        Option "XkbLayout" "us"

EndSection
```

I'm feeling kind of divided now. Can you tell me which way to go.

Thanks, Olias

----------

## olias2

I got it. Thanks   :Laughing:  I just have c:222 run the /etc/acpi/powerbtn.sh script but I had to change the dcop line to get rid of the shutdown dialog. You guys are awsome.

----------

## OdinsDream

Glad to hear the solution. It'll come in handy with a laptop I've been working on for my sister.

----------

## olias2

Thanks again mb this worked great for me in KDE. I just recently switched to Gnome/gdm and I was wondering if you would know how to modify your powerbtn script to gracefully shutdown Gnome?

Olias *mb wrote:*   

> hi,
> 
> ```
> 
> #!/bin/sh
> ...

 

----------

## olias2

<shameless bump> ... are there any code masters in the house?  :Wink: 

----------

## Kitrik

I'll shamelessly bump this one again as well...

----------

## Kitrik

found this beauty that I'm testing out right now...

/usr/bin/gnome-session-save --kill --gui

/usr/bin/sleep 5

/sbin/poweroff

if you load those commands up in an event file for the acpid then it should shut the comp down nicely! Can't guarantee that it works yet as I'm building some kernels and stuff - will report back later on it...

Kitrik

----------

## dj_rigo

 *Kitrik wrote:*   

> found this beauty that I'm testing out right now...
> 
> /usr/bin/gnome-session-save --kill --gui
> 
> /usr/bin/sleep 5
> ...

 

gnome-session-save doesn't work for me... you must run it as the user that is executing gnome-session...

----------

## Remenic

Has anyone managed to figure out a proper solution for GNOME yet? It's quite annoying that GNOME seemingly lacks usability....  :Sad: 

----------

## silentbob

Thanks for the guide, I hope you don't mind but I've written it up and stuck it on my website. I noticed that there is a slight error in your original post. Instead of "/etc/acpid/events/powerbtn" it should be "/etc/acpi/events/powerbtn" and also with the latest acpi emerge the ebuild creates a default power button shutdown command that needs to be disabled in /etc/acpi/default.sh

HOWTO: http://www.slashdotdash.net/Articles/Linux/Gentoo/PowerManagement/

----------

## Jakub

What I've noticed is that I can't get it to work unless I issue:

```

/etc/init.d/acpid restart

```

after starting X. I've seen others have this problem too but never actually found an explanation why it is so and what is the proper way to make it work (there were some suggestions with xhost or something like that but I don't feel comfortable messing with that). Does anybody have an idea?

----------

## silentbob

 *Jakub wrote:*   

> What I've noticed is that I can't get it to work unless I issue:
> 
> ```
> /etc/init.d/acpid restart
> ```
> ...

 

I've just realised I have the same problem with my setup. I need to /etc/init.d/acpid restart once KDE is loaded to get this working, quite annoying. Anyone have any pointers?

----------

