web-dev-qa-db-fra.com

Comment passer automatiquement de Suspend into Hibernate?

Est-il possible de faire passer Ubuntu à l'état Hibernate à partir de Suspend, alias "Suspend Sedation"?

Ce que je cherche, c'est ceci:
Lorsque je ferme le couvercle, l'ordinateur portable est mis en suspension. Puis, après un temps prédéterminé (même si la batterie est trop puissante), si je ne l’utilise toujours pas, il faut se mettre en veille prolongée pour économiser la batterie.

Par exemple, mon ordinateur portable est configuré pour passer en mode suspension lorsque je ferme le couvercle. Si je ne l'utilise pas pendant toute la journée, la batterie se décharge complètement, car même en mode veille, le matériel continue de consommer une petite quantité d'énergie et la batterie se décharge éventuellement. Ce que je veux, c'est pouvoir dire à Ubuntu que même si elle est suspendue, elle doit quand même entrer dans Hibernate après quelques heures d'inactivité.

Windows peut le faire. Ubuntu peut être programmé pour passer en veille o Hibernate sur timer, mais pas les deux.

51
Sergey Stadnik

Dans Ubuntu 18.04 c'est beaucoup plus facile. Dans , systemd est disponible, un nouveau mode suspend-then-hibernate . Pour commencer à utiliser cette fonction, vous devez créer n fichier /etc/systemd/sleep.conf avec le contenu suivant:

[Sleep]
HibernateDelaySec=3600

Ensuite, vous pouvez le tester avec la commande suivante:

Sudo systemctl suspend-then-hibernate

vous pouvez modifier HibernateDelaySec pour réduire le délai de mise en veille prolongée.


Si tout fonctionne bien, vous pouvez modifier l'action Fermer le couvercle. Pour ce faire, vous devez modifier le fichier /etc/systemd/logind.conf .

Vous devez rechercher l'option HandleLidSwitch=, la décommenter et la remplacer par HandleLidSwitch=suspend-then-hibernate. Ensuite, vous devez redémarrer le service systemd-logind (attention! Votre session utilisateur sera redémarrée) avec la commande suivante:

Sudo systemctl restart systemd-logind.service

C'est tout! Maintenant, vous pouvez utiliser cette fonction Nice.

16
PRIHLOP

La solution à cela est simple. Tout d’abord, lors de la suspension et de la reprise, le programme pm-suspend exécute une série de scripts dans /etc/pm/sleep.d et /usr/lib/pm-utils/sleep.d. Ma solution consiste donc à ajouter un script qui effectue les tâches suivantes:

  1. Lors de la suspension, enregistrez l'heure actuelle et enregistrez un événement de réveil à l'aide de rtcwake.
  2. À la reprise, comparez l’heure actuelle à l’heure enregistrée ci-dessus. Si suffisamment de temps s'est écoulé, nous nous sommes probablement réveillés en raison de l'événement de minuterie rtc. Sinon, nous nous sommes réveillés tôt à cause d'un événement de l'utilisateur (comme l'ouverture de l'écran du portable).
  3. Si nous nous sommes réveillés à cause du minuteur rtc, émettons immédiatement une commande "pm-hibernate" pour passer en veille prolongée.

Voici un script qui fait cela. Nommez-le 0000rtchibernate et placez-le dans le répertoire /etc/pm/sleep.d (le code 0000 est important pour que le script s'exécute en premier lors de la suspension et en dernier lieu de la reprise).

#!/bin/bash
# Script name: /etc/pm/sleep.d/0000rtchibernate
# Purpose: Auto hibernates after a period of sleep
# Edit the "autohibernate" variable below to set the number of seconds to sleep.
curtime=$(date +%s)
autohibernate=7200
echo "$curtime $1" >>/tmp/autohibernate.log
if [ "$1" = "suspend" ]
then
    # Suspending.  Record current time, and set a wake up timer.
    echo "$curtime" >/var/run/pm-utils/locks/rtchibernate.lock
    rtcwake -m no -s $autohibernate
fi

if [ "$1" = "resume" ]
then
    # Coming out of sleep
    sustime=$(cat /var/run/pm-utils/locks/rtchibernate.lock)
    rm /var/run/pm-utils/locks/rtchibernate.lock
    # Did we wake up due to the rtc timer above?
    if [ $(($curtime - $sustime)) -ge $autohibernate ]
    then
        # Then hibernate
        rm /var/run/pm-utils/locks/pm-suspend.lock
        /usr/sbin/pm-hibernate
    else
        # Otherwise cancel the rtc timer and wake up normally.
        rtcwake -m no -s 1
    fi
fi

Espérons que ce code passe sur ce forum (ceci est mon premier post ici).

Modifiez la valeur du délai d'attente autohibernate=7200 en haut, quel que soit le nombre de secondes qu'il vous faut avant de passer en veille prolongée. La valeur actuelle ci-dessus est 2 heures. Notez que votre ordinateur portable va se réveiller à cette heure pendant quelques secondes, alors qu'il exécute la fonction de veille prolongée.

Donc, si vous envisagez de mettre votre ordinateur portable dans une affaire, ne suspendez pas, mais hibernez à la place. Sinon, votre ordinateur portable pourrait surchauffer dans esp. si c'est dans un étui bien ajusté (bien qu'il ne soit allumé que quelques secondes à une minute).

J'utilise cette méthode depuis quelques jours, jusqu'à présent, elle a été un succès (et m'a sauvé d'une batterie morte cet après-midi). Prendre plaisir.

Pour les autres distributions Linux qui utilisent systemd et les versions plus récentes d'Ubuntu, cela devrait toujours fonctionner si vous placez le script dans /usr/lib/systemd/system-sleep au lieu de /etc/pm/sleep.d. Remplacez également la commande /usr/sbin/pm-hibernate par systemctl hibernate.

35
Derek Pressnall

Pour expliquer comment cela fonctionne (cela ressemble à Windows) en des mots simples: la machine ne se réveille pas lorsque la batterie devient faible pour pouvoir enregistrer l'état de la machine sur la partition de swap, elle enregistre immédiatement tout sur la partition de swap. en attente, et lorsque la batterie est épuisée, elle récupère l'état en chargeant l'état à partir de la partition d'échange (comme cela se produirait si vous étiez en veille prolongée).

Autant que je sache, linux utilisera/devrait utiliser un mode veille/veille prolongée hybride au lieu du mode veille "normal" s'il sait que cela fonctionne pour votre matériel. Il est également possible que cette option soit désactivée actuellement à cause d'un trop grand nombre de bugs ou quelque chose comme ça ...;)

Si vous aimez expérimenter, vous pouvez peut-être voir si vous pouvez obtenir de bons résultats avec pm-suspend-hybrid .

Si ce qui suit indique que vous avez de la chance, alors, en théorie, la suspension hybride est prise en charge sur votre système:

pm-is-supported --suspend-hybrid && echo "you're lucky"
12
JanC

Vous pouvez être intéressé par s2both . Il est fourni par le paquetage uswsusp dans Ubuntu 10.10. Il suspend sur le disque, mais au lieu d'arrêter le système, il le place en S3, qui est le mode d'alimentation généralement associé à l'option "Suspendre" dans Ubuntu. pm-suspend-hybrid est un autre outil censé faire la même chose.

Pour automatiser la fermeture du couvercle, consultez le guide suivant, qui vous permet d'exécuter un script arbitraire lorsqu'un événement de couvercle est intercepté:

http://ubuntuforums.org/showthread.php?t=1076486

Si vous possédez un ThinkPad, la page de manuel de tpctl fait référence à un argument, --pm-sedation-hibernate-from-suspend-timer, qui semble fournir la fonctionnalité que vous recherchez. Je vous prie de ne pas essayer ceci avec du matériel autre que ThinkPad.

Pour référence, j'ai parcouru la page de manuel pour hibernate.conf ; il ne semblait pas y avoir d’options pertinentes, mais méritait peut-être une seconde lecture.

6
ayan4m1

Ubuntu 16.04 - de suspendre/dormir en veille prolongée après un temps prédéterminé

Il semble que sur Ubuntu 16.04, les choses soient un peu différentes, donc les étapes que j'ai prises pour que cela fonctionne sont les suivantes:

  1. Assurez-vous que le mode veille prolongée fonctionne comme prévu lors de l'exécution

    systemctl hibernate
    
  2. Copiez le fichier suspend.target d'origine:

    Sudo cp /lib/systemd/system/suspend.target /etc/systemd/system/suspend.target
    

    Puis éditez le fichier /etc/systemd/system/suspend.target et ajoutez la ligne:

    Requires=delayed-hibernation.service
    

    à la section [Unit] de ce fichier.

  3. Créez le fichier /etc/systemd/system/delayed-hibernation.service avec le contenu suivant:

 [Unité] 
 Description = Déclenchement d'hibernation retardée 
 Avant = suspendre.attaquer 
 Conflits = hibernate.tenir hybride- suspendre.tenir 
 StopWhenUnneeded = true 
 
 [Service] 
 Type = one shot 
 RemainAfterExit = yes 
 ExecStart =/usr/local/bin/delay-hibernation.sh pre suspendre 
 ExecStop =/usr/local/bin/delay-hibernation.sh post suspendre 
 
 [Installer] 
 WantedBy = sleep.target 
  1. Créez le fichier de configuration /etc/delayed-hibernation.conf pour le script avec le contenu suivant:
 # Fichier de configuration pour le script 'delay-hibernation.sh' 
 
 # Spécifiez le temps en secondes à passer en mode veille avant que l'ordinateur ne soit en veille 
 TIMEOUT = 1200 #en secondes, donne 20 minutes 
  1. Créez le script qui fera réellement le travail difficile.

    Créez le fichier /usr/local/bin/delayed-hibernation.sh avec le contenu:

 #!/bin/bash 
 # Nom du script: delay-hibernation.sh 
 # Objet: Hiberne automatiquement après une période de sommeil 
 # Modifiez le `TIMEOUT `variable dans le fichier` $ hibernation_conf` pour définir le nombre de secondes en veille. 
 
 hibernation_lock = '/ var/run/retard-hibernation.lock' 
 hibernation_fail = ' /var/run/delayed-hibernation.fail'
hibernation_conf='/etc/delayed-hibernation.conf'
.____.]# Vérification du fichier de configuration 
 if [ ! -f $ hibernation_conf]; then 
 echo "Fichier de configuration manquant ('$ hibernation_conf'), abandon." 
 exit 1 
 fi 
 hibernation_timeout = $ (grep "^ [^ #] "$ hibernation_conf | grep" TIMEOUT = "| awk -F '=' '{print $ 2}' | awk -F '#' '{print $ 1}' | tr -d '[[\ t]]') 
 if ["$ hibernation_timeout" = ""]; then 
 echo "Paramètre 'TIMEOUT' manquant dans le fichier de configuration ('$ hibernation_conf'), abandon." 
 exit 1 
 Elif [[! "$ hibernation_timeout" = ~ ^ [0-9] + $]]; then 
 echo "Mauvais paramètre" TIMEOUT "(" $ hibernation_timeout ") dans le fichier de configuration (" $ hibernation_conf "), nombre de secondes attendu, abandon." 
 exit 1 
 fi 
 
 # Traitement des paramètres donnés 
 If ["$ 2" = "suspendre"]; alors 
 curtime = $ (date +% s) 
 if ["$ 1" = "pre"]; alors 
 if [-f $ hibernation_fail]; then 
 echo "Échec de l'hibernation détectée, saute le réglage RTC le réveil." 
 else 
 echo "Suspension détectée. Durée d'enregistrement définie RTC timer "
 echo" $ curtime "> $ hibernation_lock 
 rtcwake -m no -s $ hibernation_timeout 
 fi 
 Elif [" $ 1 "=" post " ]; alors 
 if [-f $ hibernation_fail]; then 
 rm $ hibernation_fail 
 fi 
 if [-f $ hibernation_lock]; then 
 sustime = $ (cat $ hibernation_lock) 
 rm $ hibernation_lock 
 if [$ (($ curtime - $ sustime)) -ge $ hibernation_timeout]; then 
 echo "La reprise automatique de la suspension est détectée. Hibernation ..." 
 systemctl hibernate 
 si [$? -ne 0]; then 
 echo "Echec de l'hibernation automatique. Tentative de suspension à la place." 
 touch $ hibernation_fail 
 systemctl suspendre 
 si [$? -ne 0]; then 
 echo "Le basculement en mode hibernation et suspension automatique a échoué. Rien d'autre à essayer." 
 fi 
 fi 
 else 
 echo "Reprise manuelle de la suspension Effacement RTC minuterie "
 rtcwake -m désactiver 
 fi 
 sinon 
 echo" Le fichier '$ hibernation_lock' n'a pas été trouvé, rien faire "
 fi 
 else 
 echo" Premier paramètre non reconnu: '$ 1', attendu 'avant' ou 'après' "" 
 fi 
 else 
 echo "Ce script est destiné à être exécuté par systemctl delay-hibernation.service (second paramètre attendu: 'suspend')" "
 fi 
  1. Rendre le script exécutable:
 chmod 755 /usr/local/bin/delayed-hibernation.sh

Il m'a fallu beaucoup de temps avant d'écrire ce script à partir d'autres réponses de ce fil, des choses que j'ai trouvées sur Internet, telles que https://bbs.archlinux.org/viewtopic.php?pid=1554259

Ma version du script tente de résoudre de nombreux problèmes, tels que la mise en suspension à nouveau si le mode Veille prolongée échoue, mais ne vous réveillez pas à nouveau après l'heure prédéterminée.

  1. La dernière étape, je suppose, serait de simplement exécuter

    Sudo systemctl daemon-reload
    Sudo systemctl enable delayed-hibernation.service 
    

    pour vous assurer que les nouveaux services/configurations sont utilisés.

Pour consulter le journal de service, vous pouvez utiliser:

Sudo systemctl status delay-hibernation.service

ou pour un journal complet de l'utilisation du service:

Sudo journalctl -u delay-hibernation.service

Un journal normal que je reçois du service en cours d'exécution est:

 mile @ mile-ThinkPad: ~ $ Sudo systemctl status delay-hibernation.service 
 ● delay-hibernation.service - Déclencheur d'hibernation retardée 
 Loaded: Chargé (/ etc/systemd/system/delay-hibernation.service; activé; préréglage du fournisseur: activé) 
 actif: inactif (hors service) 
 
 9 juin 09 20h35:42 mile-ThinkPad systemd [1] : Démarrage du déclencheur d'hibernation retardée ... 
 9 juin 09:35:42 mile-ThinkPad delay-hibernation.sh [2933]: suspension détectée. Durée d'enregistrement, définissez RTC timer 
 9 juin 09 20:35:42 mile-ThinkPad delay-hibernation.sh [2933]: rtcwake: en supposant que RTC utilise UTC .. . 
 Juin 09 20:35:42 mile-ThinkPad retardant-hibernation.sh [2933]: rtcwake: réveil à l'aide de/dev/rtc0 au jeu. Juin 9 18:55:43 2016 
 Juin 09 20:55:44 mile-ThinkPad systemd [1]: démarrage du déclencheur d'hibernation retardée. 
 Juin 09 20:55:44 mile-ThinkPad systemd [1]: retard-hibernation.service: unité n'est plus nécessaire. Arrêt. 
 Juin 09 20:55:44 mile-ThinkPad systemd [1]: arrêt, retardement de l'hibernation ... 
 Juin 09 20:55:44 mile-ThinkPad delayhhibernation.sh [. 3093]: La reprise automatique de la suspension est détectée. Hibernation ... 
 9 juin 09 20:55:44 mile-ThinkPad systemd [1]: arrêt du déclenchement d'hibernation retardée. 
 Mile @ mile-ThinkPad: ~ $ 

J'espère donc que cela aidera vraiment quelqu'un puisque j'ai passé des jours à essayer de trouver la bonne combinaison de configurations et de versions de script pour que cette fonctionnalité pratique fonctionne.

5
mihai.ile

Juste au cas où quelque chose se passerait mal avec pm-hibernate, je préférerais mettre l'ordinateur en veille plutôt que de le laisser fonctionner. Pour que vous puissiez utiliser:

   ...
/usr/sbin/pm-hibernate || /usr/sbin/pm-suspend
   ...
4
iiegn

Voici une version mise à jour de réponse de Derek Pressnall qui fonctionne avec systemd et inclut suggestion d'Eliah Kagan , il suffit de l'insérer dans /usr/lib/systemd/system-sleep/delay_hibernation.sh et rendez-le exécutable:

#!/bin/bash

hibernation_timeout=1800  #30 minutes

if [ "$2" = "suspend" ]; then
    curtime=$(date +%s)
    if [ "$1" = "pre" ]; then
        echo -e "[($curtime) $@]\nExecuting pre-suspend hook..." >> /tmp/delayed_hibernation.log
        echo "$curtime" > /var/run/delayed_hibernation.lock
        rtcwake -m no -s $hibernation_timeout
    Elif [ "$1" = "post" ]; then
        echo -e "[($curtime) $@]\nExecuting post-suspend hook..." >> /tmp/delayed_hibernation.log
        sustime=$(cat /var/run/delayed_hibernation.lock)
        if [ $(($curtime - $sustime)) -ge $hibernation_timeout ]; then
            echo -e "Automatic resume detected, hibernating.\n" >> /tmp/delayed_hibernation.log
            systemctl hibernate || systemctl suspend
        else
            echo -e "Manual resume detected, clearing RTC alarm.\n" >> /tmp/delayed_hibernation.log
            rtcwake -m no -s 1
        fi
        rm /var/run/delayed_hibernation.lock
    fi
fi
3
Niccolò Maggioni

Voici ma recette (testée sur deux ordinateurs portables Ubuntu 16.04):

Mettez ce script où vous voulez (je le mets à la racine, /syspend.sh) et rendez-le exécutable (chmod +x /suspend.sh)

TIMELOG=/tmp/autohibernate.log
ALARM=$(tail -n 1 $TIMELOG)
SLEEPTIME=5000 #edit this line to change timer, e.g. 2 hours "$((2*60*60))"
if [[ $1 == "resume" ]]
then
    if [[ $(date +%s) -ge $(( $ALARM + $SLEEPTIME )) ]]
    then
        echo "hibernate triggered $(date +%H:%M:%S)">>$TIMELOG
        systemctl hibernate 2>> $TIMELOG
    else
        echo "normal wakeup $(date +%H:%M:%S)">>$TIMELOG
    fi
Elif [[ $1 == "suspend" ]]
then
    echo "$(date +%s)" >> $TIMELOG
    rtcwake -m no -s $SLEEPTIME
fi

Créez ensuite la cible systemd: # touch /etc/systemd/system/suspend-to-sleep.target Collez ce contenu:

#/etc/systemd/system/suspend-to-hibernate.service
[Unit]
Description=Delayed hibernation trigger
Before=suspend.target
Conflicts=hibernate.target hybrid-suspend.target
StopWhenUnneeded=true

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/bash /suspend.sh suspend
ExecStop=/bin/bash /suspend.sh wakeup

[Install]
WantedBy=sleep.target
RequiredBy=suspend.target

Puis activez-le # systemctl enable suspend-to-sleep.target.

J'ai eu un problème avec celui des ordinateurs portables: la fermeture du couvercle n'a pas déclenché cette cible. Cela était dû à xfce4-power-manager. Il existe deux manières de contourner ce problème. La première consiste à éditer le fichier /etc/systemd/logind.conf et à remplacer HandleLidSwitch=ignore par HandleLidSwitch=suspend. Mais ce sera à l'échelle du système, alors je viens d'ajouter un lien symbolique à mon script # ln -s /suspend.sh /etc/pm/sleep.d/0000rtchibernate

2
yanpas

Une autre solution de contournement plus courante consiste à utiliser hybrid-sleep (comme le fait Mac OS). Si votre ordinateur prend en charge l'hibernation, vous pouvez utiliser cette fonctionnalité:

systemctl hybrid-sleep

Cette commande devrait suspendre et envoyer sur le disque (veille prolongée) l'ordinateur. Après un certain temps, l’ordinateur s’éteindra (il utilisera les fichiers de veille prolongée pour s’activer).

p.s .: Je sais que ce n'est pas exactement ce que le PO a posté, mais c'est assez proche

1
morhook

N'oubliez pas de chmod + x ce fichier, rendez-le exécutable.

Il existe une autre solution sans rtcwake, en utilisant wakealarm dans/sys/class/rtc/rtc0. Utilisez du code obsolète dans pm-functions (/ usr/lib/pm-utils) après les commentaires # depuis que le noyau ne supporte pas directement ..., (car le noyau actuel (quelque chose après la version 3.6) le supporte directement). Retournez ce code et insérez la partie do_suspend () à la place de do_suspend_hybrid ().

Code obsolète (suspendre puis hiberner lorsque susp_hybrid est appelé):

# since the kernel does not directly support hybrid sleep, we do
# something else -- suspend and schedule an alarm to go into
# hibernate if we have slept long enough.
# Only do this if we do not need to do any special video hackery on resume
# from hibernate, though.
if [ -z "$SUSPEND_HYBRID_MODULE" -a -w "$PM_RTC/wakealarm" ] && \
    check_suspend && check_hibernate && ! is_set $HIBERNATE_RESUME_POST_VIDEO; \
    then
    SUSPEND_HYBRID_MODULE="kernel"
    do_suspend_hybrid() {
    WAKETIME=$(( $(cat "$PM_RTC/since_Epoch") + PM_HIBERNATE_DELAY))
    echo >"$PM_RTC/wakealarm"
    echo $WAKETIME > "$PM_RTC/wakealarm"
    if do_suspend; then
        NOW=$(cat "$PM_RTC/since_Epoch")
        if [ "$NOW" -ge "$WAKETIME" -a "$NOW" -lt $((WAKETIME + 30)) ]; then
        log "Woken by RTC alarm, hibernating."
        # if hibernate fails for any reason, go back to suspend.
        do_hibernate || do_suspend
        else
        echo > "$PM_RTC/wakealarm"
        fi
    else
        # if we cannot suspend, just try to hibernate.
        do_hibernate
    fi
    }
fi

Conseillé. Même plus facile à utiliser, uswsusp tout en maximisant les avantages de s2 à la fois s2 et la suspension Placez le code inversé dans la partie do_suspend () du module uswsusp (/usr/lib/pm-utils/module.d).

Code inversé (suspend_hybrid lorsque la suspension est appelée):

WAKETIME=$(( $(cat "$PM_RTC/since_Epoch") + PM_HIBERNATE_DELAY))
echo >"$PM_RTC/wakealarm"
echo $WAKETIME > "$PM_RTC/wakealarm"
if do_suspend_hybrid; then
    NOW=$(cat "$PM_RTC/since_Epoch")
    if [ "$NOW" -ge "$WAKETIME" -a "$NOW" -lt $((WAKETIME + 30)) ];             then
    log "Woken by RTC alarm, hibernating."
    # if hibernate fails for any reason, go back to suspend_hybrid.
    do_hibernate || do_suspend_hybrid
    else
    echo > "$PM_RTC/wakealarm"
    fi
else
    # when do_suspend is being called, convert to suspend_hybrid.
    do_suspend_hybrid
fi      

Avec uswsusp, nous pouvons voir la progression de la suspension/veille prolongée et le processus inverse affichés en texte, même si nous pouvons l’abandonner en appuyant sur la touche retour arrière. Sans uswsusp, suspend/hibernate semble juste disparaître de manière ennuyeuse, en particulier lorsque wakealarm est déclenché et exécuter hibernate (s2disk in uswsusp). Définissez la période de veille avant l'hibernation à l'emplacement habituel du fichier pm-functions.

# variables to handle hibernate after suspend support
PM_HIBERNATE_DELAY=900  # 15 minutes
PM_RTC=/sys/class/rtc/rtc0

Voici le mod uswsusp: (rappelez-vous, ce module est appelé depuis pm-functions, donc les variables insérées sont les mêmes)

#!/bin/sh

# disable processing of 90chvt and 99video.
# s2ram and s2disk handle all this stuff internally.
uswsusp_hooks()
{
    disablehook 99video "disabled by uswsusp"
}

# Since we disabled 99video, we need to take responsibility for proper
# quirk handling.  s2ram handles all common video quirks internally,
# so all we have to do is translate the HAL standard options to s2ram options.
uswsusp_get_quirks()
{
    OPTS=""
    ACPI_SLEEP=0
    for opt in $PM_CMDLINE; do
        case "${opt##--quirk-}" in # just quirks, please
            dpms-on)       ;; # no-op
            dpms-suspend)      ;; # no-op
            radeon-off)        OPTS="$OPTS --radeontool" ;;
            reset-brightness)  ;; # no-op
            s3-bios)       ACPI_SLEEP=$(($ACPI_SLEEP + 1)) ;;
            s3-mode)       ACPI_SLEEP=$(($ACPI_SLEEP + 2)) ;;
            vbe-post)      OPTS="$OPTS --vbe_post" ;;
            vbemode-restore)   OPTS="$OPTS --vbe_mode" ;;
            vbestate-restore)  OPTS="$OPTS --vbe_save" ;;
            vga-mode-3)        ;; # no-op
            save-pci)          OPTS="$OPTS --pci_save" ;;
            none)          QUIRK_NONE="true" ;;
            *) continue ;;
        esac
    done
    [ $ACPI_SLEEP -ne 0 ] && OPTS="$OPTS --acpi_sleep $ACPI_SLEEP"
    # if we were told to ignore quirks, do so.
    # This is arguably not the best way to do things, but...
    [ "$QUIRK_NONE" = "true" ] && OPTS=""
}

# Since we disabled 99video, we also need to handle displaying
# help info for the quirks we handle.
uswsusp_help()
{
    echo  # first echo makes it look nicer.
    echo "s2ram video quirk handler options:"
    echo
    echo "  --quirk-radeon-off"
    echo "  --quirk-s3-bios"
    echo "  --quirk-s3-mode"
    echo "  --quirk-vbe-post"
    echo "  --quirk-vbemode-restore"
    echo "  --quirk-vbestate-restore"
    echo "  --quirk-save-pci"
    echo "  --quirk-none"
}

# This idiom is used for all sleep methods.  Only declare the actual
# do_ method if:
# 1: some other sleep module has not already done so, and
# 2: this sleep method can actually work on this system.
#
# For suspend, if SUSPEND_MODULE is set then something else has already
# implemented do_suspend.  We could just check to see of do_suspend was
# already declared using command_exists, but using a dedicated environment
# variable makes it easier to debug when we have to know what sleep module
# ended up claiming ownership of a given sleep method.
if [ -z "$SUSPEND_MODULE" ] && command_exists s2ram && \
    ( grep -q mem /sys/power/state || \
        ( [ -c /dev/pmu ] && check_suspend_pmu; ); ); then
    SUSPEND_MODULE="uswsusp"
    do_suspend()
    {
        WAKETIME=$(( $(cat "$PM_RTC/since_Epoch") + PM_HIBERNATE_DELAY))
        echo >"$PM_RTC/wakealarm"
        echo $WAKETIME > "$PM_RTC/wakealarm"
        if do_suspend_hybrid; then
            NOW=$(cat "$PM_RTC/since_Epoch")
            if [ "$NOW" -ge "$WAKETIME" -a "$NOW" -lt $((WAKETIME + 30)) ];             then
            log "Woken by RTC alarm, hibernating."
            # if hibernate fails for any reason, go back to suspend_hybrid.
            do_hibernate || do_suspend_hybrid
            else
            echo > "$PM_RTC/wakealarm"
            fi
        else
            # when do_suspend is being called, convert to suspend_hybrid.
            do_suspend_hybrid
        fi      
    }
fi

if [ -z "$HIBERNATE_MODULE" ] && \
    [ -f /sys/power/disk ] && \
    grep -q disk /sys/power/state && \
    [ -c /dev/snapshot ] &&
    command_exists s2disk; then
    HIBERNATE_MODULE="uswsusp"
    do_hibernate()
    {
        s2disk
    }
fi

if [ -z "$SUSPEND_HYBRID_MODULE" ] && 
    grep -q mem /sys/power/state && \
    command_exists s2both && \
    check_hibernate; then
    SUSPEND_HYBRID_MODULE="uswsusp"
    do_suspend_hybrid()
    {   
        uswsusp_get_quirks
        s2both --force $OPTS 
    }
    if [ "$METHOD" = "suspend_hybrid" ]; then
        add_before_hooks uswsusp_hooks
        add_module_help uswsusp_help
    fi
fi  
0
mark