From 877d58a42fdfa4d1f7eddcc0b888b629f5a7de5e Mon Sep 17 00:00:00 2001 From: JosePereira Date: Sun, 6 May 2012 20:13:15 +0100 Subject: [PATCH] moved suinput --- jni/vnc/suinput/suinput.c | 225 ++++++++++++++++++++++++++++++++++++++ jni/vnc/suinput/suinput.h | 96 ++++++++++++++++ 2 files changed, 321 insertions(+) create mode 100755 jni/vnc/suinput/suinput.c create mode 100755 jni/vnc/suinput/suinput.h diff --git a/jni/vnc/suinput/suinput.c b/jni/vnc/suinput/suinput.c new file mode 100755 index 0000000..3f7f18d --- /dev/null +++ b/jni/vnc/suinput/suinput.c @@ -0,0 +1,225 @@ +/* +suinput - Simple C-API to the Linux uinput-system. +Copyright (C) 2009 Tuomas Räsänen + +This library 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 3 of the License, or (at your option) any later version. + +This library 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 this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include +#include +#include +#include +#include "suinput.h" + +char* UINPUT_FILEPATHS[] = { + "/android/dev/uinput", + "/dev/uinput", + "/dev/input/uinput", + "/dev/misc/uinput", +}; +#define UINPUT_FILEPATHS_COUNT (sizeof(UINPUT_FILEPATHS) / sizeof(char*)) + +int suinput_write(int uinput_fd, + uint16_t type, uint16_t code, int32_t value) +{ + struct input_event event; + memset(&event, 0, sizeof(event)); + gettimeofday(&event.time, 0); /* This should not be able to fail ever.. */ + event.type = type; + event.code = code; + event.value = value; + if (write(uinput_fd, &event, sizeof(event)) != sizeof(event)) + return -1; + return 0; +} + +int suinput_write_syn(int uinput_fd, + uint16_t type, uint16_t code, int32_t value) +{ + if (suinput_write(uinput_fd, type, code, value)) + return -1; + return suinput_write(uinput_fd, EV_SYN, SYN_REPORT, 0); +} + +int suinput_open(const char* device_name, const struct input_id* id) +{ + int original_errno = 0; + int uinput_fd = -1; + struct uinput_user_dev user_dev; + int i; + + for (i = 0; i < UINPUT_FILEPATHS_COUNT; ++i) { + uinput_fd = open(UINPUT_FILEPATHS[i], O_WRONLY | O_NONBLOCK); + if (uinput_fd != -1) + break; + } + + if (uinput_fd == -1) + return -1; + + + + /* Set device to handle following types of events: */ + + /* Key and button events */ + if (ioctl(uinput_fd, UI_SET_EVBIT, EV_KEY) == -1) + goto err; +// +// /* Key and button repetition events */ + if (ioctl(uinput_fd, UI_SET_EVBIT, EV_REP) == -1) + goto err; +// +// /* Relative pointer motions */ +// if (ioctl(uinput_fd, UI_SET_EVBIT, EV_REL) == -1) +// goto err; + + /* Absolute pointer motions */ + + if (ioctl(uinput_fd, UI_SET_EVBIT, EV_ABS) == -1) + goto err; + + /* Synchronization events, this is probably set implicitely too. */ + if (ioctl(uinput_fd, UI_SET_EVBIT, EV_SYN) == -1) + goto err; + + + + /* Configure device to handle relative x and y axis. */ +// if (ioctl(uinput_fd, UI_SET_RELBIT, REL_X) == -1) +// goto err; +// if (ioctl(uinput_fd, UI_SET_RELBIT, REL_Y) == -1) +// goto err; + + /* Configure device to handle absolute x and y axis. */ + if (ioctl(uinput_fd, UI_SET_ABSBIT, ABS_X) == -1) + goto err; + if (ioctl(uinput_fd, UI_SET_ABSBIT, ABS_Y) == -1) + goto err; + + + + /* Configure device to handle all keys, see linux/input.h. */ + for (i = 0; i < KEY_MAX; i++) { + if (ioctl(uinput_fd, UI_SET_KEYBIT, i) == -1) + goto err; + } + + /* Set device-specific information. */ + memset(&user_dev, 0, sizeof(user_dev)); + strncpy(user_dev.name, device_name, UINPUT_MAX_NAME_SIZE); + user_dev.id.bustype = id->bustype; + user_dev.id.vendor = id->vendor; + user_dev.id.product = id->product; + user_dev.id.version = id->version; + + //minor tweak to support ABSolute events + user_dev.absmin[ABS_X] = -2047; + user_dev.absmax[ABS_X] = 2048; + user_dev.absfuzz[ABS_X] = 0; + user_dev.absflat[ABS_X] = 0; + + user_dev.absmin[ABS_Y] = -2047; + user_dev.absmax[ABS_Y] = 2048; + user_dev.absfuzz[ABS_Y] = 0; + user_dev.absflat[ABS_Y] = 0; + + if (write(uinput_fd, &user_dev, sizeof(user_dev)) != sizeof(user_dev)) + goto err; + + + if (ioctl(uinput_fd, UI_DEV_CREATE) == -1) + goto err; + + /* + The reason for generating a small delay is that creating succesfully + an uinput device does not guarantee that the device is ready to process + input events. It's probably due the asynchronous nature of the udev. + However, my experiments show that the device is not ready to process input + events even after a device creation event is received from udev. + */ + + //sleep(2); + + return uinput_fd; + + err: + + /* + At this point, errno is set for some reason. However, cleanup-actions + can also fail and reset errno, therefore we store the original one + and reset it before returning. + */ + original_errno = errno; + + /* Cleanup. */ + close(uinput_fd); /* Might fail, but we don't care anymore at this point. */ + + errno = original_errno; + return -1; +} + +int suinput_close(int uinput_fd) +{ + /* + Sleep before destroying the device because there still can be some + unprocessed events. This is not the right way, but I am still + looking for better ways. The question is: how to know whether there + are any unprocessed uinput events? + */ + sleep(2); + + if (ioctl(uinput_fd, UI_DEV_DESTROY) == -1) { + close(uinput_fd); + return -1; + } + + if (close(uinput_fd) == -1) + return -1; + + return 0; +} + +int suinput_move_pointer(int uinput_fd, int32_t x, int32_t y) +{ + if (suinput_write(uinput_fd, EV_REL, REL_X, x)) + return -1; + return suinput_write_syn(uinput_fd, EV_REL, REL_Y, y); +} + +int suinput_set_pointer(int uinput_fd, int32_t x, int32_t y) +{ + if (suinput_write(uinput_fd, EV_ABS, ABS_X, x)) + return -1; + return suinput_write_syn(uinput_fd, EV_ABS, ABS_Y, y); +} + +int suinput_press(int uinput_fd, uint16_t code) +{ + return suinput_write(uinput_fd, EV_KEY, code, 1); +} + +int suinput_release(int uinput_fd, uint16_t code) +{ + return suinput_write(uinput_fd, EV_KEY, code, 0); +} + +int suinput_click(int uinput_fd, uint16_t code) +{ + if (suinput_press(uinput_fd, code)) + return -1; + return suinput_release(uinput_fd, code); +} diff --git a/jni/vnc/suinput/suinput.h b/jni/vnc/suinput/suinput.h new file mode 100755 index 0000000..14c2e66 --- /dev/null +++ b/jni/vnc/suinput/suinput.h @@ -0,0 +1,96 @@ +/* +suinput - Simple C-API to the Linux uinput-system. +Copyright (C) 2009 Tuomas Räsänen + +This library 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 3 of the License, or (at your option) any later version. + +This library 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 this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef SUINPUT_H +#define SUINPUT_H +#include + +#include +#include + +int suinput_write(int uinput_fd, + uint16_t type, uint16_t code, int32_t value); +/* + Creates and opens a connection to the event device. Returns an uinput file + descriptor on success. On error, -1 is returned, and errno is set + appropriately. +*/ +int suinput_open(const char* device_name, const struct input_id* id); + +/* + Destroys and closes a connection to the event device. Returns 0 on success. + On error, -1 is returned, and errno is set appropriately. + + Behaviour is undefined when passed a file descriptor not returned by + suinput_open(). +*/ +int suinput_close(int uinput_fd); + +/* + Sends a relative pointer motion event to the event device. Values increase + towards right-bottom. Returns 0 on success. On error, -1 is returned, and + errno is set appropriately. + + Behaviour is undefined when passed a file descriptor not returned by + suinput_open(). +*/ +int suinput_move_pointer(int uinput_fd, int32_t x, int32_t y); +int suinput_set_pointer(int uinput_fd, int32_t x, int32_t y); + +/* + Sends a press event to the event device. Event is repeated after + a short delay until a release event is sent. Returns 0 on success. + On error, -1 is returned, and errno is set appropriately. + + Behaviour is undefined when passed a file descriptor not returned by + suinput_open(). + + All possible values of `code` are defined in linux/input.h prefixed + by KEY_ or BTN_. +*/ +int suinput_press(int uinput_fd, uint16_t code); + +/* + Sends a release event to the event device. Returns 0 on success. + On error, -1 is returned, and errno is set appropriately. + + Behaviour is undefined when passed a file descriptor not returned by + suinput_open(). + + All possible values of `code` are defined in linux/input.h prefixed + by KEY_ or BTN_. +*/ +int suinput_release(int uinput_fd, uint16_t code); + +/* + Sends a press and release events to the event device. Returns 0 on + success. On error, -1 is returned, and errno is set appropriately. + + Behaviour is undefined when passed a file descriptor not returned by + suinput_open(). + + All possible values of `code` are defined in linux/input.h prefixed + by KEY_ or BTN_. + + This function is provided as a convenience and has effectively the + same result as calling suinput_press() and suinput_release() sequentially. +*/ +int suinput_click(int uinput_fd, uint16_t code); + +#endif /* SUINPUT_H */