view uinput.c @ 5:c0223d75444d

Fill the .hgignore with compiled files.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Mon, 23 Feb 2015 00:27:48 +0100
parents 73c20831be0a
children eafcd170dc6d
line wrap: on
line source

#include "uinput.h"
#include "ds.h"
#include "service.h"

#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdbool.h>


#define DS_NAME     "Nintendo 3DS"

/* Not found these values... but it's not important! */
#define DS_VENDOR   0xdead
#define DS_PRODUCT  0xbeef
#define DS_VERSION  0x00



/*
    Create a new uinput device
    Returns: file descriptor (-1 if error)
 */
int init_uinput_device(void){
    struct uinput_user_dev dev;
    int fd = -1;

    if(uinput_dev == NULL){
        fd = open("/dev/uinput", O_RDWR);

        if(fd < 0)
            fd = open("/dev/misc/uinput", O_RDWR);

        if(fd < 0)
            fd = open("/dev/input/uinput", O_RDWR);
    }
    else fd = open(uinput_dev, O_RDWR); //from xml

    if(fd < 0){
        fprintf(stderr, " [%d]  Unable to open uinput device ; hint: 'modprobe uinput' ?!\n", curdev);
        return -1;
    }



    memset(&dev, 0, sizeof(dev));
    strncpy(dev.name, DS_NAME, UINPUT_MAX_NAME_SIZE);
    dev.id.bustype = 0;
    dev.id.vendor  = DS_VENDOR;
    dev.id.product = DS_PRODUCT;
    dev.id.version = DS_VERSION;

    dev.absmax[ABS_X]  = DS_MAX_X;
    dev.absmin[ABS_X]  = DS_MIN_X;
    dev.absfuzz[ABS_X] = 4;
    dev.absflat[ABS_X] = 2;

    dev.absmax[ABS_Y]  = DS_MAX_Y;
    dev.absmin[ABS_Y]  = DS_MIN_Y;
    dev.absfuzz[ABS_Y] = 4;
    dev.absflat[ABS_Y] = 2;


    if(write(fd, &dev, sizeof(dev)) < (ssize_t)sizeof(dev)){
        fprintf(stderr, " [%d]  Registering device at uinput failed\n", curdev);
        return -1;
    }

    /* Keys [01] (found in <linux/input.h>) */
    if( ioctl(fd, UI_SET_EVBIT,  EV_KEY)    ) return -1;
    if( ioctl(fd, UI_SET_KEYBIT, BTN_A)     ) return -1;
    if( ioctl(fd, UI_SET_KEYBIT, BTN_B)     ) return -1;
    if( ioctl(fd, UI_SET_KEYBIT, BTN_X)     ) return -1;
    if( ioctl(fd, UI_SET_KEYBIT, BTN_Y)     ) return -1;
    if( ioctl(fd, UI_SET_KEYBIT, BTN_TL)    ) return -1;
    if( ioctl(fd, UI_SET_KEYBIT, BTN_TR)    ) return -1;
    if( ioctl(fd, UI_SET_KEYBIT, BTN_TL2)   ) return -1;
    if( ioctl(fd, UI_SET_KEYBIT, BTN_TR2)   ) return -1;
    if( ioctl(fd, UI_SET_KEYBIT, BTN_START) ) return -1;
    if( ioctl(fd, UI_SET_KEYBIT, BTN_SELECT)) return -1;
    if( ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_UP)) return -1;
    if( ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_DOWN)) return -1;
    if( ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_LEFT)) return -1;
    if( ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_RIGHT)) return -1;

    /* D-Pad [-0xFFFF - 0xFFFF] */
    if( ioctl(fd, UI_SET_EVBIT,  EV_ABS)    ) return -1;
    if( ioctl(fd, UI_SET_ABSBIT, ABS_X)     ) return -1;
    if( ioctl(fd, UI_SET_ABSBIT, ABS_Y)     ) return -1;


    /* Register device */
    if( ioctl(fd, UI_DEV_CREATE)            ) return -1;

    return fd;
}


/*
    Send an event into the uinput device
    Returns: TRUE, FALSE
*/
int do_uinput(int fd, unsigned short key, int pressed, unsigned short event_type){
    struct input_event event;
    memset(&event, 0 , sizeof(event));

    event.type = event_type;
    event.code = key;
    event.value = pressed;

    if(write(fd,&event,sizeof(event)) != sizeof(event)){
        fprintf(stderr, "  [%d] Writing event to uinput driver failed ; Aborting\n", curdev);
        return false;
    }
    return true;
}


/*
    Synchonize events
*/
void flush_uinput(int fd){
    struct input_event event;
    memset(&event, 0 , sizeof(event));

    event.type = EV_SYN;
    event.code = SYN_REPORT;

    if(fd){
        if(write(fd, &event, sizeof(event) != sizeof(event)))
            fprintf(stderr, "  [%d] Flushing uinput failed\n", curdev);
    }
}