You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
2.6 KiB

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2015 Cedric Hnyda <chnyda@suse.com>
* Copyright (c) 2019 Cyril Hrubis <chrubis@suse.cz>
*/
#include <linux/input.h>
#include <linux/uinput.h>
#include <stdio.h>
#include <string.h>
#define TST_NO_DEFAULT_MAIN
#include "tst_test.h"
#include "tst_uinput.h"
#define VIRTUAL_DEVICE "virtual-device-ltp"
static const char *uinput_paths[] = {
"/dev/input/uinput",
"/dev/uinput",
};
int open_uinput(void)
{
unsigned int i;
int fd;
for (i = 0; i < ARRAY_SIZE(uinput_paths); i++) {
fd = open(uinput_paths[i], O_WRONLY | O_NONBLOCK);
if (fd > 0) {
tst_res(TINFO, "Found uinput dev at %s", uinput_paths[i]);
return fd;
}
if (fd < 0 && errno != ENOENT) {
tst_brk(TBROK | TERRNO, "open(%s)", uinput_paths[i]);
}
}
return -1;
}
#define SYSFS_PREFIX "Sysfs="
#define HANDLERS_PREFIX "Handlers="
static char *parse_field(char *line, char field)
{
char *value;
switch (field) {
case 'H':
value = strstr(line, HANDLERS_PREFIX) + sizeof(HANDLERS_PREFIX) - 1;
break;
case 'S':
value = strstr(line, SYSFS_PREFIX) + sizeof(SYSFS_PREFIX) - 1;
break;
default:
return NULL;
}
value[strlen(value) - 1] = 0;
return strdup(value);
}
char *get_input_field_value(char field)
{
FILE *file;
char line[1024];
int flag = 0;
file = fopen("/proc/bus/input/devices", "r");
if (!file)
return NULL;
while (fgets(line, sizeof(line), file)) {
if (strstr(line, "N: Name=\""VIRTUAL_DEVICE"\""))
flag = 1;
if (flag) {
if (line[0] == field)
return parse_field(line, field);
if (line[0] == '\n')
flag = 0;
}
}
fclose(file);
return NULL;
}
static int check_device(void)
{
FILE *file;
char line[256];
file = fopen("/proc/bus/input/devices", "r");
if (!file)
return 0;
while (fgets(line, sizeof(line), file)) {
if (strstr(line, "Name=\""VIRTUAL_DEVICE"\""))
return 1;
}
fclose(file);
return 0;
}
void setup_mouse_events(int fd)
{
SAFE_IOCTL(fd, UI_SET_EVBIT, EV_KEY);
SAFE_IOCTL(fd, UI_SET_KEYBIT, BTN_LEFT);
SAFE_IOCTL(fd, UI_SET_EVBIT, EV_REL);
SAFE_IOCTL(fd, UI_SET_RELBIT, REL_X);
SAFE_IOCTL(fd, UI_SET_RELBIT, REL_Y);
}
void destroy_input_device(int fd)
{
SAFE_IOCTL(fd, UI_DEV_DESTROY, NULL);
SAFE_CLOSE(fd);
}
void create_input_device(int fd)
{
int nb;
struct uinput_user_dev uidev = {
.name = VIRTUAL_DEVICE,
.id = {
.bustype = BUS_USB,
.vendor = 0x1,
.product = 0x1,
.version = 1,
}
};
SAFE_WRITE(1, fd, &uidev, sizeof(uidev));
SAFE_IOCTL(fd, UI_DEV_CREATE, NULL);
for (nb = 100; nb > 0; nb--) {
if (check_device())
return;
usleep(10000);
}
destroy_input_device(fd);
tst_brk(TBROK, "Failed to create device");
}