/*
asuskledd.c
ASUS Keyboard LED Daemon
Version 0.1 - initial release
Handles hotkeys for changing backlit keyboard brightness level

This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as published by
the Free Software Foundation.

Send bugs/patches to: allurgroceries@gmail.com
Newest version at: http://allurgroceries.com
 
Built with: 
 glib 2.24.0
 dbus-glib 0.86
 libdbus 1.2.24
 
Quick install dependencies on Debian/Ubuntu:
sudo apt-get update && sudo apt-get install build-essential \
libglib2.0-dev libdbus-glib-1-dev libdbus-1-dev
 
Build command line:
gcc -oasuskledd `pkg-config --libs --cflags dbus-1 glib-2.0 dbus-glib-1` asuskledd.c

*/

#include <glib.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

static DBusHandlerResult signal_filter 
      (DBusConnection *connection, DBusMessage *message, void *user_data);

int main (int argc, char **argv) {

  /* set up the glib main loop and initalize dbus */
  GMainLoop *loop;
  DBusConnection *bus;
  DBusError error;

  loop = g_main_loop_new (NULL, FALSE);

  dbus_error_init (&error);
  bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
  if (!bus) {
    g_warning ("Failed to connect to the D-BUS daemon: %s", error.message);
    dbus_error_free (&error);
    return 1;
  }
  dbus_connection_setup_with_g_main (bus, NULL);

  dbus_bus_add_match (bus,"type='signal',interface='org.freedesktop.Hal.Device'", &error);
  dbus_connection_add_filter (bus, signal_filter, loop, NULL);

  g_main_loop_run (loop);
  return 0;
}

static DBusHandlerResult signal_filter (DBusConnection *connection, DBusMessage *message,
					void *user_data) {

  FILE *keyboard; /* keyboard brightness file handle */
  char *f; /* first string returned by hal, throw away */
  char *s; /* second string, up or down */
  int current_value; /* current brightness level, 0-3 */
  DBusError error;  /* dbus error handler */
  GMainLoop *loop = user_data;  /* event loop we are running in */

   if (dbus_message_is_signal 
       (message, "org.freedesktop.Local", "Disconnected")) {
     g_main_loop_quit (loop);
     return DBUS_HANDLER_RESULT_HANDLED;
  }

  else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "Condition")) {

    dbus_error_init (&error);
    /* there are two strings that get returned, the first is garbage */
    if (dbus_message_get_args 
	(message, &error, DBUS_TYPE_STRING, &f, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID)) {

      /* open keyboard from sysfs */
      keyboard = fopen("/sys/devices/platform/asus_laptop/leds/asus::kbd_backlight/brightness",
		       "r+");

      if (keyboard == NULL) {
	  g_print("cannot open file, run as root or sudo\n");
	  exit(1);
      }

      /* get the current brightness */
      fscanf(keyboard, "%d", &current_value);

      /* valid levels to write are 0-3, read levels are 0-3 or 0,128 and 129-131 */
      if (current_value > 127) 
	current_value %= 128;

      if (!strcmp(s,"kbd-illum-up"))  {
	if (current_value < 3)
	  current_value++;
      }

      if (!strcmp(s,"kbd-illum-down")) {
	if (current_value > 0)
	  current_value--;
      }

      /* write the value to sysfs */
      fprintf(keyboard, "%d", current_value);

      /* close the sysfs file */
      fclose(keyboard);
     
    } else {
      g_print("Error: %s\n", error.message);
      dbus_error_free (&error);
    }

    return DBUS_HANDLER_RESULT_HANDLED;

  }

  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

}

