blob: b284f9ed69b8522a11b9b1ca787777a361279c93 [file] [log] [blame]
// Copyright 2016 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef USERSPACE_TOUCHPAD_UINPUTDEVICE_H_
#define USERSPACE_TOUCHPAD_UINPUTDEVICE_H_
#include <error.h>
#include <fcntl.h>
#include <linux/uinput.h>
#include <stdio.h>
#include <string>
#include <string.h>
#include <unistd.h>
#include "userspace_touchpad/syscallhandler.h"
#define UINPUT_CONTROL_FILENAME "/dev/uinput"
// When creating a new uinput device, you must specify these parameters like
// with an actual, physical device. These are sane, safe values.
#define GOOGLE_VENDOR_ID 0x18d1
#define DUMMY_PRODUCT_ID 0x00FF
#define VERSION_NUMBER 1
// Macros used for the bit manipulations required to interpret the results of
// ioctls when querying the capabilities of a device to duplicate with uinput.
#define BITS_PER_LONG (sizeof(int64_t) * 8)
#define NBITS(x) ((((x) - 1) / BITS_PER_LONG) + 1)
#define OFF(x) ((x) % BITS_PER_LONG)
#define BIT(x) (1UL << OFF(x))
#define LONG(x) ((x) / BITS_PER_LONG)
#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
// Define these structs and ioctls so this can compile against an old kernel
// that doesn't support these features yet. The kernel this code runs on
// must support it, but adding these here allows it to build elsewhere.
// Without these, uinput can't correctly support setting the axis ranges for
// absolute axes which is essential for simulated touch devices.
#ifndef UI_ABS_SETUP
#define UI_ABS_SETUP _IOW(UINPUT_IOCTL_BASE, 4, struct uinput_abs_setup)
struct uinput_abs_setup {
__u16 code; /* axis code */
/* __u16 filler; */
struct input_absinfo absinfo;
};
#endif
#ifndef UI_DEV_SETUP
#define UI_DEV_SETUP _IOW(UINPUT_IOCTL_BASE, 3, struct uinput_setup)
struct uinput_setup {
struct input_id id;
char name[UINPUT_MAX_NAME_SIZE];
__u32 ff_effects_max;
};
#endif
class UinputDevice {
/* A class to allow you to easily create uinput devices and generate events.
*
* This class can be used to create uinput devices, setup which events they
* are capable of generating, and actually sending them. The general flow is
* to instantiate a UinputDevice object and call CreateUinputFD() to get the
* process started. You can then use the various EnableXXXX() functions to
* enable the correct event types that you plan to generate. Once all the
* events are enabled, FinalizeUinputCreation() will tell the kernel create
* the device and SendEvent() can now be used.
*/
public:
UinputDevice() : syscall_handler_(&default_syscall_handler_),
uinput_fd_(-1) {}
explicit UinputDevice(SyscallHandler *syscall_handler) :
syscall_handler_(syscall_handler), uinput_fd_(-1) {
// This constructor allows you to pass in a SyscallHandler when unit
// testing this class. For real use, allow it to use the default value
// by using the constructor with no arguments.
if (syscall_handler_ == NULL) {
syscall_handler_ = &default_syscall_handler_;
}
}
~UinputDevice();
bool CreateUinputFD();
bool EnableEventType(int ev_type) const;
bool EnableKeyEvent(int ev_code) const;
bool EnableAbsEvent(int ev_code) const;
bool FinalizeUinputCreation(std::string const &device_name) const;
bool CopyABSOutputEvents(int source_evdev_fd, int width, int height) const;
bool SendEvent(int ev_type, int ev_code, int value) const;
int get_fd() const { return uinput_fd_; }
private:
SyscallHandler default_syscall_handler_;
SyscallHandler *syscall_handler_;
int uinput_fd_;
friend class UinputDeviceTest;
};
#endif // USERSPACE_TOUCHPAD_UINPUTDEVICE_H_