/*
Modificació joy2key (joanillo). És una modificació de joy2key per tal de solventar tot el que a mi no m'ha funcionat de joy2key. Tinc un joystick que és HID USB (V-USB). No he aconseguit fer funcionar algun dels exemples que es troben amb libusb, i per això opto per la solució de joy2key. Tanmateix, sendkeys és una mala solució i és millor implementar una solució que sigui independent de la finestra que selecciono, és a dir, una solució de baix nivell que treballi directament sobre el kernel. Això s'aconsegueix amb uinput.

joy2key_joanillo-0.0.2.c: començo a fer modificacions sobre joy2key.c. Detecta els botons i eixos i simplifico tot el que puc

gcc -DHAVE_CONFIG_H -I. -g -O2 -MT joy2key.o -MD -MP -MF .deps/joy2key.Tpo -c -o joy2key_joanillo.o joy2key_joanillo-0.0.2.c
gcc -g -O2 -o joy2key_joanillo joy2key_joanillo.o
*/

#define DEFAULT_DEVICE	"/dev/input/js0"
#define XK_MISCELLANY	1
#define XK_LATIN1			1

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#include <ctype.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <linux/joystick.h>

char *device=DEFAULT_DEVICE;
int jsfd=-1;
char button_repeat_flags[8];	//8 botons
char axis_hold_flags[4]; 		//2 eixos, que són 4 botons
int unsigned button_actions[8]; //és el mapejat dels botons amb les tecles que s'ha de pitjar
int unsigned axis_actions[2][2];
struct itimerval repeat_time;

int check_device(int argc, char **argv);
void test_eixos();
void cleanup(int s);
void repeat_handler(int s);

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

	char string[255];
	char numaxes, numbuttons;

	struct js_event js;
    struct timeval tv;
	
	//aquí va la info del programa, copyright i crèdits

	//***** MAPEJAT ***********
	button_actions[0] = 49; //ascii 49='1'
	button_actions[1] = 50; //ascii 50='2'
	button_actions[2] = 51; //ascii 51='3'
	button_actions[3] = 52; //ascii 52='4'
	button_actions[4] = 53; //ascii 53='5'
	button_actions[5] = 54; //ascii 54='6'
	button_actions[6] = 55; //ascii 55='7'
	button_actions[7] = 56; //ascii 56='8'

	axis_actions[0][0] = 76; //ascii 76='L'
	axis_actions[0][1] = 82; //ascii 82='R'
	axis_actions[1][0] = 85; //ascii 85='U'
	axis_actions[1][1] = 68; //ascii 68='D'

	//**************************

    memset(button_repeat_flags, 0, sizeof(button_repeat_flags));
    memset(axis_hold_flags, 0, sizeof(axis_hold_flags));
    repeat_time.it_interval.tv_sec=0;
    repeat_time.it_interval.tv_usec=0;
    repeat_time.it_value.tv_sec=0;
    repeat_time.it_value.tv_usec=0;

    if((jsfd=open(device,O_RDONLY))==-1)
    {
		printf("Error opening %s!\n", device);
		puts("Are you sure you have joystick support in your kernel?");
		return 1;
    }

    if((jsfd=open(device,O_RDONLY))==-1)
    {
		printf("Error opening %s!\n", device);
		puts("Are you sure you have joystick support in your kernel?");
		return 1;
    }

    if (ioctl(jsfd, JSIOCGAXES, &numaxes)) {
	/* acording to the American Heritage Dictionary of the English Language 'axes' *IS* the correct pluralization of 'axis' */
		perror("joy2key: error getting axes"); 
		return 1;
    }
    if (ioctl(jsfd, JSIOCGBUTTONS, &numbuttons)) {
		perror("joy2key: error getting buttons");
		return 1;
    }

	//printf("%d\n", numaxes);
	//printf("%d\n", numbuttons);

	//test_eixos();

    memset(&js, 0, sizeof(struct js_event)); //posem 0's

    signal(SIGINT, cleanup);
    signal(SIGTERM, cleanup);
    if(repeat_time.it_interval.tv_usec)
    {
		signal(SIGALRM, repeat_handler);
		repeat_time.it_value.tv_usec=repeat_time.it_interval.tv_usec;
		setitimer(ITIMER_REAL, &repeat_time, NULL);
    }

	/* Main Loop */
	for(;;)
	{
		memset(&js, 0, sizeof(struct js_event));
		read(jsfd, &js, sizeof(struct js_event));
//printf("type:%d number:%d value:%d\n", js.type, js.number, js.value);
		switch(js.type)
		{
//printf("%d %d\n", js.number, js.value); //value: 1=press; 0=release
//fflush(stdout);
		case JS_EVENT_BUTTON: /* buttons */
			if(button_actions[js.number])
			{
				//button_repeat_flags[js.number]=js.value;
				//enviem la tecla				
				//sendkey(button_actions[js.number], js.value ? PRESS : RELEASE, button_upper[js.number]);
				//printf("%d %d\n", js.number, js.value); //value: 1=press; 0=release
				if (js.value > 0) printf("%d %c\n", button_actions[js.number], button_actions[js.number]);
				fflush(stdout);
			}
			break;
		case JS_EVENT_AXIS: /* axis */
			if(axis_actions[js.number][0] || axis_actions[js.number][1])
			{
				//axis_hold_flags[js.number]=js.value;
				//enviem la tecla				
				//sendkey(button_actions[js.number], js.value ? PRESS : RELEASE, button_upper[js.number]);
				//printf("%d %d\n", js.number, js.value); //value: 1=press; 0=release
				if (js.value < 0) {
					printf("%d %c\n", axis_actions[js.number][0], axis_actions[js.number][0]);
				} else if (js.value > 0) {
					printf("%d %c\n", axis_actions[js.number][1], axis_actions[js.number][1]);
				}

				fflush(stdout);
			}
			break;
		} //switch

	} //main loop for
}

void test_eixos()
{
    struct js_event js;
    int joymid=0;

    printf("\nAnem a capturar events\n");
    fflush(stdout);
    do
    {
		read(jsfd, &js, sizeof(struct js_event));
		if(js.type==JS_EVENT_AXIS) 
		{
			printf("axis number: %d value:%d\n", js.number, js.value);
			fflush(stdout);
		}	
    } while(js.type!=JS_EVENT_BUTTON || (js.type==JS_EVENT_BUTTON && js.value==0));
}

void cleanup(int s) //cal??
{
    printf("\n%s caught, cleaning up & quitting.\n", 
		   s==SIGINT ? "SIGINT" : 
		   (s==SIGTERM ? "SIGTERM" : ((s == 0) ? "Window die" : "Unknown")));
    exit(0);
}

//funció per gestionar quan deixo apretat el botó o l'eix
void repeat_handler(int s)
{
    int i;
/*
    signal(SIGALRM, SIG_IGN);

    for(i=0; i<button_act_counter; i++)
    {
		if(button_repeat_flags[i])
		{
			sendkey(button_actions[i], RELEASE, button_upper[i]);
			sendkey(button_actions[i], PRESS, button_upper[i]);
		}
    }
    signal(SIGALRM, repeat_handler);
*/
}

