Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
Dell latitude C610: doubled Suspend signal
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Kernel & Hardware
View previous topic :: View next topic  
Author Message
.yankee
Apprentice
Apprentice


Joined: 24 Feb 2008
Posts: 194
Location: Polska

PostPosted: Mon Feb 25, 2008 1:42 am    Post subject: Dell latitude C610: doubled Suspend signal Reply with quote

Hi, all!

I have a problem in using the suspend button on my laptop (the Fn+Esc combination).
ACPI receives a signal on both pressing and releasing the button:

Code:

Feb 25 02:03:43 jan acpid: received event "button/sleep SBTN 00000080 00000134"
Feb 25 02:03:43 jan acpid: notifying client 4567[103:443]
Feb 25 02:03:43 jan acpid: executing action "/etc/acpi/default.sh button/sleep SBTN 00000080 00000134"
Feb 25 02:03:43 jan logger: ACPI event unhandled: button/sleep SBTN 00000080 00000134
Feb 25 02:03:43 jan acpid: action exited with status 0
Feb 25 02:03:43 jan acpid: completed event "button/sleep SBTN 00000080 00000134"

Feb 25 02:03:43 jan acpid: received event "button/sleep SBTN 00000080 00000135"
Feb 25 02:03:43 jan acpid: notifying client 4567[103:443]
Feb 25 02:03:43 jan acpid: executing action "/etc/acpi/default.sh button/sleep SBTN 00000080 00000135"
Feb 25 02:03:43 jan logger: ACPI event unhandled: button/sleep SBTN 00000080 00000135
Feb 25 02:03:43 jan acpid: action exited with status 0
Feb 25 02:03:43 jan acpid: completed event "button/sleep SBTN 00000080 00000135"

(This was the case, when the script /etc/acpi/default.sh had no section for action "sleep" - and it was treated as unhandled)

The problem is, that I need to receive only one signal - could be the release of the key - because, in other case, the acpi preforms hibernation twice (the laptop hibernates again immediately after being woken up).
As you can see from the code, the value passed with "sleep" action is just incremental - it does not indicate, whether the button is sunk, or released.
I could, of course send only one signal, by:
- pressing Fn
- pressing Esc (Suspend)
- releasing Fn
- releasing Esc (NOT interpreted as "Suspend" this time)
but this is rather unnatural, ane if I forget to do it that way, the double-hibernation problem would again occur.

So, I temporarily came up with such a solution:
/etc/acpi/default.sh (fragment)
Code:

                        sleep)
                                logger "====== Value: $value ======"
                                if [ -f /tmp/.acpi_suspend_lock ]
                                then
                                        rm /tmp/.acpi_suspend_lock
                                        logger "######### THE SIGNAL! #########"
                                        /usr/sbin/hibernate
                                else
                                        echo $value > /tmp/.acpi_suspend_lock
                                        logger "####### THE LOCK IS SET #######"
                                fi
                                ;;


Which makes the hibernate script be called every other time the "sleep" signal occurs. Still, this is neither neat nor safe solution (for example, the tmp/.acpi_suspend_lock file could be created by someone else and therefore inaccessible for acpid).

My question here is:
How should it be done in a nicer way?

Thanks in advance for any tips.

P.S. here's my full /etc/acpi/default.sh just in case someone got confused:
Code:

#!/bin/sh
# /etc/acpi/default.sh
# Default acpi script that takes an entry for all actions

set $*

group=${1%%/*}
action=${1#*/}
device=$2
id=$3
value=$4
log_unhandled() {
        logger "ACPI event unhandled: $*"
}

case "$group" in
        button)
                case "$action" in
                        power)
                                /sbin/init 0
                                ;;

                        # if your laptop doesnt turn on/off the display via hardware
                        # switch and instead just generates an acpi event, you can force
                        # X to turn off the display via dpms.  note you will have to run
                        # 'xhost +local:0' so root can access the X DISPLAY.
                        #lid)
                        #       xset dpms force off
                        #       ;;

                        sleep)
                                logger "====== Value: $value ======"
                                if [ -f /tmp/.acpi_suspend_lock ]
                                then
                                        rm /tmp/.acpi_suspend_lock
                                        logger "######### THE SIGNAL! #########"
                                        /usr/sbin/hibernate
                                else
                                        echo $value > /tmp/.acpi_suspend_lock
                                        logger "####### THE LOCK IS SET #######"
                                fi
                                ;;

                        *)      log_unhandled $* ;;
                esac
                ;;

        ac_adapter)
                case "$value" in
                        # Add code here to handle when the system is unplugged
                        # (maybe change cpu scaling to powersave mode).  For
                        # multicore systems, make sure you set powersave mode
                        # for each core!
                        #*0)
                        #       cpufreq-set -g powersave
                        #       ;;

                        # Add code here to handle when the system is plugged in
                        # (maybe change cpu scaling to performance mode).  For
                        # multicore systems, make sure you set performance mode
                        # for each core!
                        #*1)
                        #       cpufreq-set -g performance
                        #       ;;

                        *)      log_unhandled $* ;;
                esac
                ;;

        *)      log_unhandled $* ;;
esac
Back to top
View user's profile Send private message
BradN
Advocate
Advocate


Joined: 19 Apr 2002
Posts: 2391
Location: Wisconsin (USA)

PostPosted: Mon Feb 25, 2008 6:16 am    Post subject: Reply with quote

Realistically, I don't think someone's going to attempt a "hibernation DOS" attack on your machine, and I suppose the only other logical approach I can think of would be making a script parse the event numbers and ignore the (even|odd) numbered events.

If you're worried about the lock file being accessed improperly, just change the location and set the permissions accordingly. Otherwise it sounds like you've found a decent solution to an irritating problem :)
Back to top
View user's profile Send private message
.yankee
Apprentice
Apprentice


Joined: 24 Feb 2008
Posts: 194
Location: Polska

PostPosted: Mon Feb 25, 2008 8:15 pm    Post subject: Reply with quote

Thanks for your kind word :)

But I'm a rather stubborn bastard :twisted: and I still think my way is not good enough.

I didn't actually mean hibernation DOS attack - one could do something more nasty. For instance, they could create the /tmp/.acpi_suspend_lock to be a link to some important system configuration file. This one would be then overwritten by the "echo $value > /tmp/.acpi_suspend_lock" command. I could of course use "touch /tmp/.acpi_suspend_lock" instead - but would that be enough..?

Anyway - I at first thought about the same thing as you mentioned - watching for odd/even values of $value. The problem is that I am too poor at shell programming to do that (I'm not asking for a howto on that though - I'm sure any online shell tutorial would help me out). This is a bit better, I believe, because it does not operate on files.

Still, the two approaches have one more drawback: If I press the button for too long, multiple signals would be sent. So the ideal solution would be one that would trigger an action only on release of the button. But I don't know where I could get the information on whether a key is down or up - I guess that would need some editing of keyboard driver/module code? Kernel-programming? I guess that would be a nice point for me to start kernel hacking :)

Yes, I'm a problem-inventor. That's my hobby 8)
It makes me learn and gain satisfaction.
Back to top
View user's profile Send private message
BradN
Advocate
Advocate


Joined: 19 Apr 2002
Posts: 2391
Location: Wisconsin (USA)

PostPosted: Tue Feb 26, 2008 12:07 am    Post subject: Reply with quote

Well, I don't think standard keyboard rules apply here, since the event is being delivered via ACPI and not the keyboard (most laptops won't even report the fn key or some special combinations, for example). Probably you would have to alter the system ACPI code to change this behavior, so I don't think there's many better ways to go about this than what you've done.

Perhaps a time delay to ignore suspend signals after getting one rather than ignoring alternating events might work too. I don't know how easy that would be to implement if the system suspends during the delay and then comes back with the clock that much farther along. Perhaps a series of short delays would work better (since a clock advance would only affect one of them).
Back to top
View user's profile Send private message
.yankee
Apprentice
Apprentice


Joined: 24 Feb 2008
Posts: 194
Location: Polska

PostPosted: Tue Feb 26, 2008 5:05 pm    Post subject: Reply with quote

I thought of time delay as well... Maybe I'll do it next.
It turned out, that my idea to act only on button release was not good; running showkey revealed, that each press-and-release of the button (Fn+Esc that is), sends a sequence of pressed-released-pressed-released. So this won't do.

Anyways, I dug a little in kernel sources (2.6.21-suspend2-r7), and found the code responsible for sending the acpi sleep-button signals in drivers/acpi/button.c. After a few tries, I got a solution, which suits me better, then the earlier script. Here's a patch:

Code:

--- /usr/src/linux/drivers/acpi/button-orig.c   2008-02-26 03:42:43.000000000 +0000
+++ /usr/src/linux/drivers/acpi/button.c        2008-02-26 05:39:29.000000000 +0000
@@ -274,8 +274,12 @@
                }
                input_sync(input);
 
-               acpi_bus_generate_event(button->device, event,
-                                       ++button->pushed);
+               if ( !((button->type == ACPI_BUTTON_TYPE_SLEEP) // is NOT the sleep btn
+                  || (button->type == ACPI_BUTTON_TYPE_SLEEPF))
+                  || (button->pushed %2))      // or (if is), is pressed twice (?)
+                       acpi_bus_generate_event(button->device, event, ++button->pushed);
+               else ++button->pushed;
+
                break;
        default:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,


This works fine so far, but I'm not sure, whether I didn't mess up anything with that modification. Can some dev give an opinion on my patch?...
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Kernel & Hardware All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum