#!/usr/bin/env python
#
# Poll hotkeys of Libretto L1 series laptop and trigger appropriate events.
#
# Copyright (C) 2002 John Belmonte
#
# $Date: 2004/06/18 $
# $Change: 312 $
#
#
# TODO
#
#   cleanup pid file upon termination
#   support video out key
#
#
# NOTES
#
#   Supporting the video out key would require a way to reset the X server
#   if X were running.
#

import time
import re
import sys
import os


#
### config
#

polls_per_sec   = 4
proc_dir        = '/proc/acpi/toshiba/'
pid_filename    = '/var/run/%s.pid' % os.path.basename(sys.argv[0])
swsusp_filename = '/proc/sys/kernel/swsusp'
swsusp_value    = '1 0 0'


#
### key assignments
#

disk_suspend        = 0x013E    # F4 push
brightness_down     = 0x0140    # F6 push
brightness_up       = 0x0141    # F7 push
force_fan_toggle    = 0x0142    # F8 push


#
### general utils
#

# convert string to int, guessing number base
def toint(s):
    return int(s, 0)

# clamp x to range [a, b]
def clamp(x, a, b):
    if x < a: return a
    if x > b: return b
    return x

def error(msg):
    if msg: sys.exit('ERROR: ' + msg)
    else: sys.exit(1)


#
### app-specific funcs
#

def read_val(file, key):
    file_name = proc_dir + file
    file_h = open(file_name)
    text = file_h.read()
    file_h.close()
    match = re.search('%s:\s*(\S+)' % key, text)
    if not match:
        error('search for key "%s" in file "%s" failed.\nFile text was:\n%s' %
            (key, file, text))
    return match.group(1)

def write_val(file, key, val):
    file_name = proc_dir + file
    file = open(file_name, 'w')
    file.write('%s:%s' % (key, val))
    file.close()

def is_hotkey_ready():
    return toint(read_val('keys', 'hotkey_ready'))

def get_hotkey():
    code = toint(read_val('keys', 'hotkey'))
    write_val('keys', 'hotkey_ready', 0)
    return code


#
### main
#

# check version
assert(toint(read_val('version', 'proc_interface')) == 1)

# fork to background and write out pid file
pid = os.fork()
if pid != 0:
    file = open(pid_filename, 'w')
    file.write('%d\n' % pid)
    file.close()
    sys.exit(0)

# flush hotkey queue
while is_hotkey_ready():
    get_hotkey()

# polling loop
while 1:
    while is_hotkey_ready():
        code = get_hotkey()
        #print('0x%04x' % code)
        if code == force_fan_toggle:
            current_val = toint(read_val('fan', 'force_on'))
            write_val('fan', 'force_on', current_val ^ 1)
        elif code == brightness_down or code == brightness_up:
            num_levels = toint(read_val('lcd', 'brightness_levels'))
            current_level = toint(read_val('lcd', 'brightness'))
            increment = (code == brightness_down) and -1 or 1
            new_level = clamp(current_level + increment, 0, num_levels-1)
            write_val('lcd', 'brightness', new_level)
        elif code == disk_suspend:
            file = open(swsusp_filename, 'w')
            file.write(swsusp_value)
            file.close()
    time.sleep(1.0/polls_per_sec)
