#!/bin/sh

###############################################################################
# x31.sh - IBM ThinkPad X31 ACPI event handler script
#
# Copyright (C) 2004-2005 by Henrik Brix Andersen <brix@gentoo.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
###############################################################################

###############################################################################
# Required software:
#
# * Linux kernel with CONFIG_ACPI support
# * acpid (http://acpid.sf.net/)
# * ibm-acpi kernel module (either in-kernel or from http://ibm-acpi.sf.net/)
# * radeontool (http://fdd.com/software/radeon/)
# * hibernate-script (http://www.suspend2.net/)
#
###############################################################################

###############################################################################
# ChangeLog:
#
# 2005-12-31: Remove xosd support, remove bashisms
#
# 2005-06-06: Turn off LCD when closing lid to save even more power
#
# 2005-05-20: Add new hotkey event handlers for BIOS version 2.15
#
# 2005-04-30: Execute hibernate-ram for suspend-to-ram
#
# 2005-01-20: added (untested) Ultrabay support, made if conditionals safer
#
# 2005-01-16: added xosd support, removed support for non
#             hibernate-script activated suspend, added processor event hook
#
# 2005-01-05: do not hardcode path to binaries
#
# 2004-11-25: use /usr/sbin/hibernate-sleep symlink for suspend-to-ram
#
# 2004-11-19: use the hibernate-script for both suspend-to-ram and
#             suspend-to-disk (if available)
#
# 2004-11-10: updated to work with ipw2100-0.61
#
# 2004-11-08: updated to work with software-suspend-2.1.3, use hibernate-script
#             if available
#
# 2004-10-22: enable pressing ESC to abort suspend when using swsusp2
#
# 2004-10-21: use swsusp2 if available
#
# 2004-10-18: updated to use the experimental features of ibm-acpi-0.5
#
# 2004-10-02: updated path to ipw2100 state file to work with ipw2100-0.55
#
# 2004-09-11: simplified remaining conditionals
#
# 2004-09-10: return to previous VT upon resume,
#             added docking support (not tested),
#             removed awk dependency,
#             use full path for external programs,
#             cleaned up conditionals,
#             change to VT 1 before shutdown
#
# 2004-09-08: added calls to hwclock when suspending
#
###############################################################################

###############################################################################
# Should the script prefer generic ACPI events over the events
# generated by the ibm-acpi module (yes/no)
###############################################################################
PREFER_GENERIC_ACPI=yes

###############################################################################
# Report events to system log (yes/no)
###############################################################################
USE_SYSLOG=yes

###############################################################################
# uncomment the following line for debug information in syslog
###############################################################################
# logger -t "Event" $*

###############################################################################
# Fn+F1 event
# No arguments
###############################################################################
f1() {
    log "Fn+F1 pressed"
}

###############################################################################
# Fn+F2 event
# No arguments
###############################################################################
f2() {
    log "Fn+F2 pressed"
}

###############################################################################
# Fn+F3 event (Display on/off)
# No arguments
###############################################################################
f3() {
    if radeontool light | grep "looks on"; then
        log "LCD off"
        radeontool light off
    else
        log "LCD on"
        radeontool light on
    fi
}

###############################################################################
# Fn+F4 event (Sleep)
# No arguments
###############################################################################
f4() {
    if [ -x /usr/sbin/hibernate-ram ]; then
        /usr/sbin/hibernate-ram
    fi
}

###############################################################################
# Fn+F5 event (Radio)
# No arguments
###############################################################################
f5() {
    if egrep [13] /sys/class/net/eth1/device/rf_kill || \
        grep disabled /sys/class/net/eth1/device/rf_kill; then
        log "Wireless network enabled"
        echo 0 > /sys/class/net/eth1/device/rf_kill
    else
        log "Wireless network disabled"
        echo 1 > /sys/class/net/eth1/device/rf_kill
    fi
}

###############################################################################
# Fn+F6 event
# No arguments
###############################################################################
f6() {
    log "Fn+F6 pressed"
}

###############################################################################
# Fn+F7 event (External display)
# No arguments
###############################################################################
f7() {
    echo video_switch > /proc/acpi/ibm/video

    # Use the following if the above doesn't work for you
    # See https://bugs.freedesktop.org/show_bug.cgi?id=2000 for more info

#    if radeontool dac | grep "looks on"; then
#        log "External monitor enabled"
#        radeontool dac off
#    else
#        log "External monitor disabled"
#        radeontool dac on
#    fi
}

###############################################################################
# Fn+F8 event (Screen expansion)
# No arguments
###############################################################################
f8() {
#    echo expand_toggle > /proc/acpi/ibm/video
    log "Restarting eth1"
    /etc/init.d/net.eth1 restart
}

###############################################################################
# Fn+F9 event (Dock eject)
# No arguments
###############################################################################
f9() {
#    dock_eject
    log "Restarting fetchmail"
    /etc/init.d/fetchmail restart
}

###############################################################################
# Fn+F10 event
# No arguments
###############################################################################
f10() {
    log "Fn+F10 pressed"
}

###############################################################################
# Fn+F11 event
# No arguments
###############################################################################
f11() {
    log "Fn+F11 pressed"
}

###############################################################################
# Fn+F12 event (Hibernate)
# No arguments
###############################################################################
f12() {
    if [ -x /usr/sbin/hibernate ]; then
        /usr/sbin/hibernate
    fi
}

###############################################################################
# Fn+Backspace event
# No arguments
###############################################################################
backspace() {
    log "Fn+Backspace pressed"
}

###############################################################################
# Fn+Insert event
# No arguments
###############################################################################
insert() {
    log "Fn+Insert pressed"
}

###############################################################################
# Fn+Delete event
# No arguments
###############################################################################
delete() {
    log "Fn+Delete pressed"
}

###############################################################################
# Fn+Home event
# No arguments
###############################################################################
home() {
    log "Fn+Home pressed"
}

###############################################################################
# Lid event
# $1: opened, closed
###############################################################################
lid() {
    if [ "${1}" = "closed" ]; then
	log "Lid closed"
	radeontool light off
    else
	log "Lid opened"
	radeontool light on
    fi
}

###############################################################################
# Power button event
# No arguments
###############################################################################
power() {
    log "Initiating shutdown"

    echo 0 blink > /proc/acpi/ibm/led

    chvt 1
    shutdown -h now

    echo 0 on > /proc/acpi/ibm/led
}

###############################################################################
# cpu event
# $1: performanc, power
###############################################################################
cpu() {
    case $1 in
	performance)
	    log "CPU performance changed"
	    ;;

	power)
	    log "CPU power changed"
	    ;;
    esac
}

###############################################################################
# AC adapter event
# $1: connected, disconnected
###############################################################################
ac() {
    if [ "$1" = "connected" ]; then
        log "AC adapter connected"
    else
        log "AC adapter disconnected"
    fi
}

###############################################################################
# Battery event
# $1: connected, disconnected
# $2: BAT0, BAT1, ...
###############################################################################
battery() {
    case $1 in
        connected)
            log "Battery connected ($2)"
            ;;

        disconnected)
            log "Battery disconnected ($2)"
            ;;

        state)
            log "Battery status changed ($2)"
            ;;
    esac
}

###############################################################################
# Docking station eject request event
# No arguments
###############################################################################
dock_eject() {
    sync
    idectl 1 off

    echo undock > /proc/acpi/ibm/dock

    log "Laptop ready for undocking"
}

###############################################################################
# Docking station undocked event
# No arguments
###############################################################################
dock_undocked() {
    log "Laptop undocked"
}

###############################################################################
# Docking station docked event
# No arguments
###############################################################################
dock_docked() {
    sync
    echo dock > /proc/acpi/ibm/dock

    idectl 1 on
    idectl 1 rescan

    log "Laptop docked"
}

###############################################################################
# Bay eject request event
# No arguments
###############################################################################
bay_eject() {
    sync
    idectl 1 off

    echo eject > /proc/acpi/ibm/bay

    log "Ultrabay ready for detach"
}

###############################################################################
# Bay docked event
# No arguments
###############################################################################
bay_docked() {
    sync
    idectl 1 on
    idectl 1 rescan

    log "Ultrabay attached"
}

###############################################################################
# Unhandled event, called for all events not handled by the above functions
# $*: the entire ACPI event string
###############################################################################
unhandled() {
    log "Unhandled event: $*"
}



###############################################################################
#
# GENERALLY NO NEED TO CHANGE ANYTHING BELOW THIS LINE
#
###############################################################################


###############################################################################
#
# idectl function
#
###############################################################################
idectl() {
    if [ -x /sbin/idectl-ibm-acpi ]; then
	/sbin/idectl-ibm-acpi $@
    elif [ -x /sbin/idectl ]; then
	/sbin/idectl $@
    else
	log "/sbin/idectl not found"
    fi
}

###############################################################################
#
# log function
#
###############################################################################
log() {
    if [ "$USE_SYSLOG" = "yes" ]; then
	logger -t ACPI -- "$@"
    fi
}

###############################################################################
#
# use more descriptive names for the script arguments
#
###############################################################################
class=$1
bus=$2
type=$3
data=$4

###############################################################################
#
# case statements below to figure out which event was recieved
#
###############################################################################

case $class in
    processor)
	# generic ACPI processor event
	case $type in
	    00000080)
		# processor performance changed
		cpu performance
		;;

	    00000081)
		# processor power changed
		cpu power
		;;

	    *)
		# unknown processor event
		unhandled $*
		;;
	esac
	;;

    ac_adapter)
        # generic ACPI AC adapter event
        case $data in
            00000000)
                # AC adapter was disconnected
                ac disconnected
                ;;

            00000001)
                # AC adapter was connected
                ac connected
                ;;

            *)
                # unknown AC adapter event
                unhandled $*
                ;;
        esac
        ;;

    battery)
        # generic ACPI battery event
        case $type in
            00000080)
                case $data in
                    00000000)
                        battery state $bus
                        ;;

                    00000001)
                        battery state $bus
                        ;;

                    *)
                        unhandled $*
                        ;;
                    esac
                ;;

            00000081)
                # battery connect/disconnect event
                case $data in
                    00000000)
                        battery inserted $bus
                        ;;

                    00000001)
                        battery removed $bus
                        ;;
                    *)
                        unhandled $*
                        ;;
                esac

                ;;
            *)
                # unknown battery event
                unhandled $*
                ;;
        esac
        ;;

    button/power)
        # generic ACPI power button event
        power
        ;;

    button/sleep)
        # generic ACPI sleep button event
        f4
        ;;

    button/lid)
        # generic ACPI lid event
        if [[ $PREFER_GENERIC_ACPI == "yes" ]]; then
            # check the state of the lid
            if grep open /proc/acpi/button/lid/LID/state; then
                lid opened
            else
                lid closed
            fi
        fi
	;;

    ibm/hotkey)
        # ibm-acpi kernel module hotkey event
        case $data in
            00001001)
                # Fn+F1 hotkey pressed
                f1
                ;;

            00001002)
                # Fn+F2 hotkey pressed
                f2
                ;;

            00001003)
                # Fn+F3 hotkey pressed
                f3
                ;;

            00001004)
                # Fn+F4 hotkey pressed
                f4
                ;;

            00001005)
                # Fn+F5 hotkey pressed
                f5
                ;;

            00001006)
                # Fn+F6 hotkey pressed
                f6
                ;;

            00001007)
                # Fn+F7 hotkey pressed
                f7
                ;;

            00001008)
                # Fn+F8 hotkey pressed
                f8
                ;;

            00001009)
                # Fn+F9 hotkey pressed
                f9
                ;;

            0000100a)
                # Fn+F10 hotkey pressed
                f10
                ;;

            0000100b)
                # Fn+F11 hotkey pressed
                f11
                ;;

            0000100c)
                # Fn+F12 hotkey pressed
                f12
                ;;

            0000100d)
                # Fn+Backspace hotkey pressed
                backspace
                ;;

            0000100e)
                # Fn+Insert hotkey pressed
                insert
                ;;

            0000100f)
                # Fn+Delete hotkey pressed
                delete
                ;;

            00001010)
                # Fn+Home hotkey pressed
                home
                ;;

            00005001)
                # Lid closed
                if [ $PREFER_GENERIC_ACPI == "no" ]; then
                    lid closed
                fi
                ;;

            00005002)
                # Lid opened
                if [ $PREFER_GENERIC_ACPI == "no" ]; then
                    lid opened
                fi
                ;;

            *)
                # unknown ibm-acpi hotkey event
                unhandled $*
        esac
        ;;

    ibm/dock)
        # ibm-acpi kernel module dock event
        case $data in
            00000001)
                # dock eject request
                dock_eject
                ;;

            00000002)
                # undocked
                dock_undocked
                ;;

            00000003)
                # docked
                dock_docked
                ;;

            *)
                # unknown ibm-acpi dock event
                unhandled $*
        esac
        ;;

    ibm/bay)
	# ibm-acpi kernel module bay event
	case $type in
	    00000003)
		# bay eject request
		bay_eject
		;;

	    00000001)
		# bay inserted
		bay_dock
		;;

	    *)
                # unknown ibm-acpi bay event
                unhandled $*
	esac
	;;

    *)
        # unknown ACPI event
        unhandled $*
        ;;
esac

