#! /usr/bin/env python

# Copyright (C) 2014, Arnaud EBALARD <arno@natisbad.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.

# Some notes/doc:
#
# This simple script just define dummy handlers (they simply print
# something on standard output; replace their content w/ a
# custom action) and associates those with the events generated
# by power, backup and copy buttons (respectively KEY_POWER,
# KEY_RESTART and KEY_COPY input events). The main loop monitors
# input events (i.e. /dev/input/event0) and calls the associated
# handler. Note that the handler is called when the associated key
# is released. Logic can easily be changed to act when the button
# is pressed or when the button is pressed twice in a given
# timeframe. When launched, the script does a double fork, i.e.
# you can use it as a basis for some init^Wsystemd script.
#
# The script was tested on NETGEAR ReadyNAS 102 and Duo v2 but
# should work with all NV+ v2, RN104 and RN2120 (RN2120 does not
# have a backup button).

import struct, os, sys

# Keyboard event type
EV_KEY = 1

# Keyboard event value
KEY_PRESSED = 0
KEY_RELEASED = 1

# Keyboard events we monitor
KEY_POWER = 116
KEY_RESTART = 408
KEY_COPY = 133

# Define one handler function for each interesting event
# The function must be able to handle being called multiple
# time simultaneously (i.e. you'll need to add some locking).

def power_handler():
    print "Shutdown!"

def reset_handler():
    print "Reboot!"

def backup_handler():
    print "Backup!"

ev_handlers = {KEY_POWER:   power_handler,
               KEY_RESTART: reset_handler,
               KEY_COPY:    backup_handler}

def main_loop():
    ev_fmt = "llHHI"
    ev_size = struct.calcsize(ev_fmt)

    fd = open("/dev/input/event0")

    while True:
        event = fd.read(ev_size)
        if len(event) != ev_size:
            sys.exit(1)

        tmp = struct.unpack(ev_fmt, event)
        sec, usec, ev_type, ev_code, ev_val = tmp

        # We will act on key release events
        if (ev_type, ev_val) != (EV_KEY, KEY_RELEASED):
            continue

        # Call asscoiated event handler
        if ev_code in ev_handlers:
            ev_handlers[ev_code]()

if __name__ == "__main__":
    # Let's double fork
    pid = os.fork()
    if pid != 0:
        os.waitpid(pid, 0)
    else:
        pid = os.fork()
        if pid != 0:
            sys.exit()
        else:
            main_loop()
            sys.exit(0)
