Michel-FK e2b637f3bd add compatibilty with kernel with dates on 32 bits
Signed-off-by: Michel-FK <michel.stempin@funkey-project.com>
2020-12-21 21:38:38 +01:00

264 lines
5.9 KiB
C
Executable File

/**** uinput.c *****************************/
/* M. Moller 2013-01-16 */
/* Universal RPi GPIO keyboard daemon */
/*******************************************/
/*
Copyright (C) 2013 Michael Moller.
This file is part of the Universal Raspberry Pi GPIO keyboard daemon.
This is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The software 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
//#include <linux/uinput.h>
#include "uinput_linux.h"
//#include "config.h"
//include "daemon.h"
#include "uinput.h"
#include <time.h>
/****************************************************************
* Defines
****************************************************************/
#define DEBUG_UINPUT_PRINTF (0)
#if DEBUG_UINPUT_PRINTF
#define UINPUT_PRINTF(...) printf(__VA_ARGS__);
#else
#define UINPUT_PRINTF(...)
#endif
//#define SLEEP_TIME_SEND_STOP_KEY_US 20*1000
#define SLEEP_TIME_SEND_STOP_KEY_US 200*1000
#define die(str, args...) do { \
perror(str); \
return(EXIT_FAILURE); \
} while(0)
// For compatibility with kernels having dates on 32 bits
struct timeval_compat
{
unsigned int tv_sec;
long int tv_usec;
};
struct input_event_compat {
struct timeval_compat time;
unsigned short type;
unsigned short code;
unsigned int value;
};
/****************************************************************
* Static functions declaration
****************************************************************/
static int sendRel(int dx, int dy);
static int sendSync(void);
/****************************************************************
* Static variables
****************************************************************/
static struct input_event uidev_ev;
static int uidev_fd;
/*static keyinfo_s lastkey;*/
/****************************************************************
* Functions Implementation
****************************************************************/
int init_uinput(void)
{
int fd;
struct uinput_user_dev uidev;
int i;
fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
if(fd < 0)
die("/dev/uinput");
if(ioctl(fd, UI_SET_EVBIT, EV_KEY) < 0)
die("error: ioctl");
if(ioctl(fd, UI_SET_EVBIT, EV_REP) < 0)
die("error: ioctl");
if(ioctl(fd, UI_SET_KEYBIT, BTN_LEFT) < 0)
die("error: ioctl");
if(ioctl(fd, UI_SET_EVBIT, EV_REL) < 0)
die("error: ioctl");
if(ioctl(fd, UI_SET_RELBIT, REL_X) < 0)
die("error: ioctl");
if(ioctl(fd, UI_SET_RELBIT, REL_Y) < 0)
die("error: ioctl");
/* don't forget to add all the keys! */
for(i=0; i<256; i++){
if(ioctl(fd, UI_SET_KEYBIT, i) < 0)
die("error: ioctl");
}
memset(&uidev, 0, sizeof(uidev));
snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-sample");
uidev.id.bustype = BUS_USB;
uidev.id.vendor = 0x1;
uidev.id.product = 0x1;
uidev.id.version = 1;
/*if(write(fd, &uidev, sizeof(uidev)) < 0)
die("error: write");*/
if(ioctl(fd, UI_DEV_SETUP, &uidev) < 0)
die("error: ioctl");
if(ioctl(fd, UI_DEV_CREATE) < 0)
die("error: ioctl");
uidev_fd = fd;
sleep(1);
return 0;
}
int test_uinput(void)
{
int dx, dy;
int i,k;
//srand(time(NULL));
int op = 1;
while(1) {
//switch(rand() % 4) {
switch(op) {
case 0:
dx = -10;
dy = -1;
break;
case 1:
dx = 10;
dy = 1;
break;
case 2:
dx = -1;
dy = 10;
break;
case 3:
dx = 1;
dy = -10;
break;
}
/*k = send_gpio_keys(21, 1);
sendKey(k, 0);*/
sendKey(KEY_D, 0);
for(i = 0; i < 20; i++) {
//sendKey(KEY_D, 1);
//sendKey(KEY_D, 0);
sendRel(dx, dy);
usleep(15000);
}
sleep(10);
}
}
int close_uinput(void)
{
sleep(2);
if(ioctl(uidev_fd, UI_DEV_DESTROY) < 0)
die("error: ioctl");
close(uidev_fd);
return 0;
}
int sendKey(int key, int value)
{
struct input_event_compat ie;
//memset(&uidev_ev, 0, sizeof(struct input_event));
//gettimeofday(&uidev_ev.time, NULL);
ie.type = EV_KEY;
ie.code = key;
ie.value = value;
ie.time.tv_sec = 0;
ie.time.tv_usec = 0;
UINPUT_PRINTF("sendKey: %d = %d\n", key, value);
if(write(uidev_fd, &ie, sizeof(struct input_event_compat)) < 0)
die("error: write");
sendSync();
return 0;
}
int sendKeyAndStopKey(int key)
{
sendKey(key, 1);
usleep(SLEEP_TIME_SEND_STOP_KEY_US);
sendKey(key, 0);
return 0;
}
static int sendRel(int dx, int dy)
{
memset(&uidev_ev, 0, sizeof(struct input_event));
uidev_ev.type = EV_REL;
uidev_ev.code = REL_X;
uidev_ev.value = dx;
if(write(uidev_fd, &uidev_ev, sizeof(struct input_event)) < 0)
die("error: write");
memset(&uidev_ev, 0, sizeof(struct input_event));
uidev_ev.type = EV_REL;
uidev_ev.code = REL_Y;
uidev_ev.value = dy;
if(write(uidev_fd, &uidev_ev, sizeof(struct input_event)) < 0)
die("error: write");
sendSync();
return 0;
}
static int sendSync(void)
{
UINPUT_PRINTF("sendSync\n");
//memset(&uidev_ev, 0, sizeof(struct input_event));
struct input_event ie;
ie.type = EV_SYN;
ie.code = SYN_REPORT;
ie.value = 0;
ie.time.tv_sec = 0;
ie.time.tv_usec = 0;
if(write(uidev_fd, &ie, sizeof(struct input_event)) < 0)
die("error: sendSync - write");
return 0;
}