Skip to content
Permalink
master
Go to file
 
 
Cannot retrieve contributors at this time
198 lines (179 sloc) 5.19 KB
/*
*The MIT License (MIT)
*
*Copyright (c) 2014 Raphael Sousa Santos, http://raphaelss.com
*
*Permission is hereby granted, free of charge, to any person obtaining a copy
*of this software and associated documentation files (the "Software"), to deal
*in the Software without restriction, including without limitation the rights
*to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
*copies of the Software, and to permit persons to whom the Software is
*furnished to do so, subject to the following conditions:
*
*The above copyright notice and this permission notice shall be included in all
*copies or substantial portions of the Software.
*
*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
*IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
*FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
*AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
*LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
*OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
*SOFTWARE.
*/
#ifndef EVTABLET_HPP_INCLUDED
#define EVTABLET_HPP_INCLUDED
#include <memory>
#include <cstring>
#include <libevdev/libevdev.h>
#include <fcntl.h>
namespace ev {
namespace impl {
struct evdev_deleter {
void operator()(libevdev *ptr)
{
libevdev_free(ptr);
}
};
}
template <class T>
struct Tablet {
Tablet(): good(false) {}
bool open(const char *path)
{
libevdev *tmp;
int fd = ::open(path, O_RDONLY | O_NONBLOCK);
if (fd < 0) {
std::fputs("Failed to open device\n", stderr);
dev.reset();
good = false;
return false;
}
int rc = libevdev_new_from_fd(fd, &tmp);
if (rc < 0) {
std::fprintf(stderr,"Failed to init libevdev (%s)\n", std::strerror(-rc));
dev.reset();
good = false;
return false;
}
dev.reset(tmp);
good = true;
return true;
}
void close()
{
dev.reset();
good = false;
}
bool process_events()
{
input_event ev;
T *derived = static_cast<T*>(this);
int rc;
do {
rc = libevdev_next_event(dev.get(), LIBEVDEV_READ_FLAG_NORMAL, &ev);
if (rc == LIBEVDEV_READ_STATUS_SYNC) {
derived->event_sync(ev.code != SYN_DROPPED);
while (rc == LIBEVDEV_READ_STATUS_SYNC) {
rc = libevdev_next_event(dev.get(), LIBEVDEV_READ_FLAG_SYNC, &ev);
}
} else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) {
switch(ev.type) {
case EV_SYN:
derived->event_sync(ev.code != SYN_DROPPED);
break;
case EV_ABS:
switch(ev.code) {
case ABS_X:
derived->event_x(ev.value);
break;
case ABS_Y:
derived->event_y(ev.value);
break;
case ABS_PRESSURE:
derived->event_pressure(ev.value);
break;
case ABS_DISTANCE:
derived->event_distance(ev.value);
break;
}
case EV_KEY:
switch(ev.code) {
case BTN_TOOL_PEN:
derived->event_in_range(ev.value);
break;
case BTN_TOOL_RUBBER:
derived->event_rubber_in_range(ev.value);
break;
case BTN_TOUCH:
derived->event_stylus_contact(ev.value);
break;
case BTN_STYLUS:
derived->event_stylus_button1(ev.value);
break;
case BTN_STYLUS2:
derived->event_stylus_button2(ev.value);
break;
}
}
}
} while(rc == LIBEVDEV_READ_STATUS_SYNC
|| rc == LIBEVDEV_READ_STATUS_SUCCESS);
if (rc != LIBEVDEV_READ_STATUS_SUCCESS && rc != -EAGAIN) {
std::fprintf(stderr, "Failed to handle events: %s\n", std::strerror(rc));
good = false;
return false;
}
return true;
}
const input_absinfo *query_properties(int axis)
{
return libevdev_get_abs_info(dev.get(), axis);
}
unsigned x_min() const
{
return libevdev_get_abs_info(dev.get(), ABS_X)->minimum;
}
unsigned x_max() const
{
return libevdev_get_abs_info(dev.get(), ABS_X)->maximum;
}
unsigned y_min() const
{
return libevdev_get_abs_info(dev.get(), ABS_Y)->minimum;
}
unsigned y_max() const
{
return libevdev_get_abs_info(dev.get(), ABS_Y)->maximum;
}
unsigned pressure_min() const
{
return libevdev_get_abs_info(dev.get(), ABS_PRESSURE)->minimum;
}
unsigned pressure_max() const
{
return libevdev_get_abs_info(dev.get(), ABS_PRESSURE)->maximum;
}
unsigned distance_min() const
{
return libevdev_get_abs_info(dev.get(), ABS_DISTANCE)->minimum;
}
unsigned distance_max() const
{
return libevdev_get_abs_info(dev.get(), ABS_DISTANCE)->maximum;
}
void event_sync(bool report) {}
void event_x(unsigned x) {}
void event_y(unsigned x) {}
void event_pressure(unsigned x) {}
void event_distance(unsigned x) {}
void event_in_range(bool x) {}
void event_rubber_in_range(bool x) {}
void event_stylus_contact(bool x) {}
void event_stylus_button1(bool x) {}
void event_stylus_button2(bool x) {}
bool good;
std::unique_ptr<libevdev, impl::evdev_deleter> dev;
};
}
#endif