/*
 *
 * Sony Programmable I/O Control Device driver for VAIO. 
 * Userspace X11 Daemon Utility
 *
 * Copyright 2001 Stelian Pop, Alcove
 *
 * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

#include <X11/Xlib.h>
#include <X11/extensions/XTest.h>


#include <linux/sonypi.h>

/* Added event definitions (Adi Kriegisch) */

#define FN_ESC ""
#define FN_F1 ""
#define FN_F2 ""
#define FN_F3 "/usr/bin/aumix -v 0 &"             // disable speakers
#define FN_F4 "/usr/bin/aumix -v +10 &"           // enable speakers (in 10% steps...)
#define FN_F5 "/usr/local/bin/spicctrl -b 250 &"  // set maximum brightness
#define FN_F6 "/usr/local/bin/spicctrl -b 0 &"    // set minimum brightness
#define FN_F7 "/usr/bin/vga.sh &"                 // set LCD and CRT active
#define FN_F8 "/usr/bin/tv.sh &"                  // set TV-OUT active (therefor resolution needs to bechanged to 800x600)
#define FN_F9 ""
#define FN_F10 ""
#define FN_F11 ""
#define FN_F12 ""
#define FN_E "/opt/kde3/bin/kate &"
#define FN_S "/opt/kde3/bin/kdesktop_lock --force_lock &"
#define FN_D ""
#define FN_F ""
#define FN_B ""
#define FN_1 ""
#define FN_2 ""
#define P1 "/opt/kde3/bin/konqueror --profile webbrowsing &"
#define P2 "/opt/kde3/bin/kmail --composer &"
#define P3 "/opt/kde3/bin/konsole &"
#define LID_CLOSED ""
#define LID_OPEN ""

static void inline simulateKeyPress(Display *disp, char *keyname) {
	KeyCode keycode = 0;
	keycode = XKeysymToKeycode(disp, XStringToKeysym(keyname));
	XTestGrabControl(disp, True);
	XTestFakeKeyEvent(disp, keycode, True, 0);
	XSync(disp, False);
	XTestGrabControl(disp, False);
}

static void inline simulateKeyRelease(Display *disp, char *keyname) {
	KeyCode keycode = 0;
	keycode = XKeysymToKeycode(disp, XStringToKeysym(keyname));
	XTestGrabControl(disp, True);
	XTestFakeKeyEvent(disp, keycode, False, 0);
	XSync(disp, False);
	XTestGrabControl(disp, False);
}

static void inline simulateButton(Display *disp, int button) {
	XTestGrabControl(disp, True);
	XTestFakeButtonEvent(disp, button, True, 0);
	XTestFakeButtonEvent(disp, button, False, 0);
	XSync(disp, False);
	XTestGrabControl(disp, False);
}

static void inline verboseEvent(char *event) {
	fprintf(stderr, "Event: %s\n", event);
}

/*
 * Main function.
 */
int main(int argc, char *argv[]) {
	int fd;
	fd_set rfds;
	int retval;
	unsigned char event;
	Display *disp = NULL;

	disp = XOpenDisplay(NULL);
	if (!disp) {
		fprintf(stderr, "Failed to open display\n");
#ifdef FORCE_X
		return -1;
#endif
	}
	if ( (fd = open("/dev/sonypi", O_RDONLY)) == -1) {
		fprintf(stderr, "Failed to open /dev/sonypi: %s\n", 
			strerror(errno));
		return -1;
	}
again:
	FD_ZERO(&rfds);
	FD_SET(fd, &rfds);

	retval = select(fd + 1, &rfds, NULL, NULL, NULL);

	if (retval == -1) {
		fprintf(stderr, "select failed: %s\n", strerror(errno));
		return -1;
	}

	if (FD_ISSET(fd, &rfds)) {
		if (read(fd, &event, sizeof(event)) != sizeof(event)) {
			fprintf(stderr, "read failed: %s\n", strerror(errno));
			return -1;
		}
		switch (event) {
			case SONYPI_EVENT_JOGDIAL_DOWN:
				if( disp ) {
					simulateButton(disp, 5);
				};
				verboseEvent("Jogdial Down");
				break;
			case SONYPI_EVENT_JOGDIAL_UP:
				if( disp ) {
					simulateButton(disp, 4);
				};
				verboseEvent("Jogdial Up");
				break;
			case SONYPI_EVENT_JOGDIAL_DOWN_PRESSED:
				verboseEvent("Jogdial Down & Pressed");
				break;
			case SONYPI_EVENT_JOGDIAL_UP_PRESSED:
				verboseEvent("Jogdial Up & Pressed");
				break;
			case SONYPI_EVENT_JOGDIAL_PRESSED:
				if( disp ) {
					simulateKeyPress(disp, "Return");
				};
				verboseEvent("Jogdial Pressed");
				break;
			case SONYPI_EVENT_JOGDIAL_RELEASED:
				if( disp ) {
					simulateKeyRelease(disp, "Return");
				};
				verboseEvent("Jogdial Released");
				break;
			case SONYPI_EVENT_CAPTURE_PRESSED:
				if (!fork()) {
					execlp("xterm", "xterm", 0);
					exit(0);
				}
				verboseEvent("Capture Pressed");
				break;
			case SONYPI_EVENT_CAPTURE_RELEASED:
				verboseEvent("Capture Released");
				break;
			case SONYPI_EVENT_CAPTURE_PARTIALPRESSED:
				verboseEvent("Capture Partial Pressed");
				break;
			case SONYPI_EVENT_CAPTURE_PARTIALRELEASED:
				verboseEvent("Capture Partial Released");
				break;
/* EVENTS START HERE... */                                
			case SONYPI_EVENT_FNKEY_ESC:
                        	system(FN_ESC);
				verboseEvent("Fn-Esc Pressed");
				break;
			case SONYPI_EVENT_FNKEY_F1:
                        	system(FN_F1);
				verboseEvent("Fn-F1 Pressed");
				break;
			case SONYPI_EVENT_FNKEY_F2:
                        	system(FN_F2);
				verboseEvent("Fn-F2 Pressed");
				break;
			case SONYPI_EVENT_FNKEY_F3:
                        	system(FN_F3);
				verboseEvent("Fn-F3 Pressed");
				break;
			case SONYPI_EVENT_FNKEY_F4:
                        	system(FN_F4);
				verboseEvent("Fn-F4 Pressed");
				break;
			case SONYPI_EVENT_FNKEY_F5:
                        	system(FN_F5);
				verboseEvent("Fn-F5 Pressed");
				break;
			case SONYPI_EVENT_FNKEY_F6:
                        	system(FN_F6);
				verboseEvent("Fn-F6 Pressed");
				break;
			case SONYPI_EVENT_FNKEY_F7:
                        	system(FN_F7);
				verboseEvent("Fn-F7 Pressed");
				break;
			case SONYPI_EVENT_FNKEY_F8:
                        	system(FN_F8);
				verboseEvent("Fn-F8 Pressed");
				break;
			case SONYPI_EVENT_FNKEY_F9:
                        	system(FN_F9);
				verboseEvent("Fn-F9 Pressed");
				break;
			case SONYPI_EVENT_FNKEY_F10:
                        	system(FN_F10);
				verboseEvent("Fn-F10 Pressed");
				break;
			case SONYPI_EVENT_FNKEY_F11:
                        	system(FN_F11);
				verboseEvent("Fn-F11 Pressed");
				break;
			case SONYPI_EVENT_FNKEY_F12:
                        	system(FN_F12);
				verboseEvent("Fn-F12 Pressed");
				break;
			case SONYPI_EVENT_FNKEY_1:
                        	system(FN_1);
				verboseEvent("Fn-1 Pressed");
				break;
			case SONYPI_EVENT_FNKEY_2:
                        	system(FN_2);
				verboseEvent("Fn-2 Pressed");
				break;
			case SONYPI_EVENT_FNKEY_D:
                        	system(FN_D);
				verboseEvent("Fn-D Pressed");
				break;
			case SONYPI_EVENT_FNKEY_E:
                        	system(FN_E);
				verboseEvent("Fn-E Pressed");
				break;
			case SONYPI_EVENT_FNKEY_F:
                        	system(FN_F);
				verboseEvent("Fn-F Pressed");
				break;
			case SONYPI_EVENT_FNKEY_S:
                        	system(FN_S);
				verboseEvent("Fn-S Pressed");
				break;
			case SONYPI_EVENT_FNKEY_B:
                        	system(FN_B);
				verboseEvent("Fn-B Pressed");
				break;
			case SONYPI_EVENT_BLUETOOTH_PRESSED:
				verboseEvent("Bluetooth Button Pressed");
				break;
#ifdef SONYPI_EVENT_PKEY_P1
			case SONYPI_EVENT_PKEY_P1:
				system(P1);
                                verboseEvent("P1 Pressed");
				break;
#endif
#ifdef SONYPI_EVENT_PKEY_P2
			case SONYPI_EVENT_PKEY_P2:
                        	system(P2);
				verboseEvent("P2 Pressed");
				break;
#endif
#ifdef SONYPI_EVENT_PKEY_P3
			case SONYPI_EVENT_PKEY_P3:
				system(P3);
                                verboseEvent("P3 Pressed");
				break;
#endif
#ifdef SONYPI_EVENT_BACK_PRESSED
			case SONYPI_EVENT_BACK_PRESSED:
				verboseEvent("Back Button Pressed");
				break;
#endif
#ifdef SONYPI_EVENT_LID_OPENED
			case SONYPI_EVENT_LID_OPENED:
                        	system(LID_OPEN);
				verboseEvent("Lid Opened");
				break;
#endif
#ifdef SONYPI_EVENT_LID_CLOSED
			case SONYPI_EVENT_LID_CLOSED:
                        	system(LID_CLOSED);
				verboseEvent("Lid Closed");
				break;
#endif
#ifdef SONYPI_EVENT_BLUETOOTH_ON
			case SONYPI_EVENT_BLUETOOTH_ON:
				verboseEvent("Bluetooth set to on");
				break;
#endif
#ifdef SONYPI_EVENT_BLUETOOTH_OFF
			case SONYPI_EVENT_BLUETOOTH_OFF:
				verboseEvent("Bluetooth set to off");
				break;
#endif
#ifdef SONYPI_EVENT_HELP_PRESSED
			case SONYPI_EVENT_HELP_PRESSED:
				verboseEvent("Help button pressed");
				break;
#endif
			default:
				verboseEvent("Event unknown!");
		}
	}

	goto again;

	close(fd);
	return 0;
}


