#include <string.h>
#include <unistd.h>
#include <stdarg.h>
+#include <stdbool.h>
#include "libevdev.h"
#include "libevdev-int.h"
prefix = "libevdev debug";
break;
default:
+ prefix = "libevdev INVALID LOG PRIORITY";
break;
}
/* default logging format:
va_end(args);
}
+static void
+libevdev_reset(struct libevdev *dev)
+{
+ memset(dev, 0, sizeof(*dev));
+ dev->fd = -1;
+ dev->initialized = false;
+ dev->num_slots = -1;
+ dev->current_slot = -1;
+ dev->grabbed = LIBEVDEV_UNGRAB;
+ dev->sync_state = SYNC_NONE;
+ libevdev_enable_event_type(dev, EV_SYN);
+}
+
LIBEVDEV_EXPORT struct libevdev*
libevdev_new(void)
{
struct libevdev *dev;
- dev = calloc(1, sizeof(*dev));
+ dev = malloc(sizeof(*dev));
if (!dev)
return NULL;
- dev->fd = -1;
- dev->num_slots = -1;
- dev->current_slot = -1;
- dev->grabbed = LIBEVDEV_UNGRAB;
- dev->sync_state = SYNC_NONE;
+
+ libevdev_reset(dev);
return dev;
}
free(dev);
}
-/* DEPRECATED */
-LIBEVDEV_EXPORT void
-libevdev_set_log_handler(struct libevdev *dev, libevdev_log_func_t logfunc)
-{
- /* Can't be backwards compatible to this yet, so don't even try */
- fprintf(stderr, "libevdev: ABI change. Log function will not be honored.\n");
-}
-
LIBEVDEV_EXPORT void
libevdev_set_log_function(libevdev_log_func_t logfunc, void *data)
{
LIBEVDEV_EXPORT int
libevdev_change_fd(struct libevdev *dev, int fd)
{
- if (dev->fd == -1) {
+ if (!dev->initialized) {
log_bug("device not initialized. call libevdev_set_fd() first\n");
return -1;
}
int i;
char buf[256];
- if (dev->fd != -1) {
+ if (dev->initialized) {
log_bug("device already initialized.\n");
return -EBADF;
- }
+ } else if (fd < 0)
+ return -EBADF;
+
+ libevdev_reset(dev);
rc = ioctl(fd, EVIOCGBIT(0, sizeof(dev->bits)), dev->bits);
if (rc < 0)
if (rc < 0)
goto out;
+ /* Built on a kernel with props, running against a kernel without property
+ support. This should not be a fatal case, we'll be missing properties but other
+ than that everything is as expected.
+ */
rc = ioctl(fd, EVIOCGPROP(sizeof(dev->props)), dev->props);
- if (rc < 0)
+ if (rc < 0 && errno != EINVAL)
goto out;
rc = ioctl(fd, EVIOCGBIT(EV_REL, sizeof(dev->rel_bits)), dev->rel_bits);
* Same with the valuators, really, but they may not change.
*/
+ dev->initialized = true;
out:
+ if (rc)
+ libevdev_reset(dev);
return rc ? -errno : 0;
}
{
int rc;
int i;
+ int ioctl_success = 0;
struct mt_state {
int code;
int val[MAX_SLOTS];
} mt_state[ABS_MT_CNT];
+ memset(&mt_state, 0, sizeof(mt_state));
+
for (i = ABS_MT_MIN; i <= ABS_MT_MAX; i++) {
int idx;
if (i == ABS_MT_SLOT)
idx = i - ABS_MT_MIN;
mt_state[idx].code = i;
rc = ioctl(dev->fd, EVIOCGMTSLOTS(sizeof(struct mt_state)), &mt_state[idx]);
- if (rc < 0)
- goto out;
+ if (rc < 0) {
+ /* if the first ioctl fails with -EINVAL, chances are the kernel
+ doesn't support the ioctl. Simply continue */
+ if (errno == -EINVAL && !ioctl_success) {
+ rc = 0;
+ } else /* if the second, ... ioctl fails, really fail */
+ goto out;
+ } else if (ioctl_success == 0)
+ ioctl_success = 1;
}
for (i = 0; i < dev->num_slots; i++) {
{
int rc = LIBEVDEV_READ_STATUS_SUCCESS;
- if (dev->fd < 0) {
+ if (!dev->initialized) {
log_bug("device not initialized. call libevdev_set_fd() first\n");
return -EBADF;
- }
+ } else if (dev->fd < 0)
+ return -EBADF;
- if (!(flags & (LIBEVDEV_READ_NORMAL|LIBEVDEV_READ_SYNC|LIBEVDEV_FORCE_SYNC))) {
+ if (!(flags & (LIBEVDEV_READ_FLAG_NORMAL|LIBEVDEV_READ_FLAG_SYNC|LIBEVDEV_READ_FLAG_FORCE_SYNC))) {
log_bug("invalid flags %#x\n.\n", flags);
return -EINVAL;
}
- if (flags & LIBEVDEV_READ_SYNC) {
+ if (flags & LIBEVDEV_READ_FLAG_SYNC) {
if (dev->sync_state == SYNC_NEEDED) {
rc = sync_state(dev);
if (rc != 0)
read in any more.
*/
do {
- if (!(flags & LIBEVDEV_READ_BLOCKING) ||
+ if (!(flags & LIBEVDEV_READ_FLAG_BLOCKING) ||
queue_num_elements(dev) == 0) {
rc = read_more_events(dev);
if (rc < 0 && rc != -EAGAIN)
goto out;
}
- if (flags & LIBEVDEV_FORCE_SYNC) {
+ if (flags & LIBEVDEV_READ_FLAG_FORCE_SYNC) {
dev->sync_state = SYNC_NEEDED;
rc = LIBEVDEV_READ_STATUS_SYNC;
goto out;
rc = LIBEVDEV_READ_STATUS_SYNC;
}
- if (flags & LIBEVDEV_READ_SYNC && dev->queue_nsync > 0) {
+ if (flags & LIBEVDEV_READ_FLAG_SYNC && dev->queue_nsync > 0) {
dev->queue_nsync--;
rc = LIBEVDEV_READ_STATUS_SYNC;
if (dev->queue_nsync == 0)
struct pollfd fds = { dev->fd, POLLIN, 0 };
int rc;
- if (dev->fd < 0) {
+ if (!dev->initialized) {
log_bug("device not initialized. call libevdev_set_fd() first\n");
return -EBADF;
- }
+ } else if (dev->fd < 0)
+ return -EBADF;
if (queue_num_elements(dev) != 0)
return 1;
dev->field = strdup(field); \
}
-STRING_SETTER(name);
-STRING_SETTER(phys);
-STRING_SETTER(uniq);
+STRING_SETTER(name)
+STRING_SETTER(phys)
+STRING_SETTER(uniq)
#define PRODUCT_GETTER(name) \
return dev->ids.name; \
}
-PRODUCT_GETTER(product);
-PRODUCT_GETTER(vendor);
-PRODUCT_GETTER(bustype);
-PRODUCT_GETTER(version);
+PRODUCT_GETTER(product)
+PRODUCT_GETTER(vendor)
+PRODUCT_GETTER(bustype)
+PRODUCT_GETTER(version)
#define PRODUCT_SETTER(field) \
LIBEVDEV_EXPORT void libevdev_set_id_##field(struct libevdev *dev, int field) \
dev->ids.field = field;\
}
-PRODUCT_SETTER(product);
-PRODUCT_SETTER(vendor);
-PRODUCT_SETTER(bustype);
-PRODUCT_SETTER(version);
+PRODUCT_SETTER(product)
+PRODUCT_SETTER(vendor)
+PRODUCT_SETTER(bustype)
+PRODUCT_SETTER(version)
LIBEVDEV_EXPORT int
libevdev_get_driver_version(const struct libevdev *dev)
LIBEVDEV_EXPORT int
libevdev_has_event_type(const struct libevdev *dev, unsigned int type)
{
- return (type <= EV_MAX) && bit_is_set(dev->bits, type);
+ return type == EV_SYN ||(type <= EV_MAX && bit_is_set(dev->bits, type));
}
LIBEVDEV_EXPORT int
case EV_KEY: value = bit_is_set(dev->key_values, code); break;
case EV_LED: value = bit_is_set(dev->led_values, code); break;
case EV_SW: value = bit_is_set(dev->sw_values, code); break;
+ case EV_REP:
+ switch(code) {
+ case REP_DELAY:
+ libevdev_get_repeat(dev, &value, NULL);
+ break;
+ case REP_PERIOD:
+ libevdev_get_repeat(dev, NULL, &value);
+ break;
+ default:
+ value = 0;
+ break;
+ }
+ break;
default:
value = 0;
break;
return absinfo ? absinfo->name : 0; \
}
-ABS_GETTER(maximum);
-ABS_GETTER(minimum);
-ABS_GETTER(fuzz);
-ABS_GETTER(flat);
-ABS_GETTER(resolution);
+ABS_GETTER(maximum)
+ABS_GETTER(minimum)
+ABS_GETTER(fuzz)
+ABS_GETTER(flat)
+ABS_GETTER(resolution)
#define ABS_SETTER(field) \
LIBEVDEV_EXPORT void libevdev_set_abs_##field(struct libevdev *dev, unsigned int code, int val) \
LIBEVDEV_EXPORT int
libevdev_enable_event_type(struct libevdev *dev, unsigned int type)
{
+ int max;
+
if (type > EV_MAX)
return -1;
if (libevdev_has_event_type(dev, type))
return 0;
+ max = libevdev_event_type_get_max(type);
+ if (max == -1)
+ return -1;
+
set_bit(dev->bits, type);
if (type == EV_REP) {
LIBEVDEV_EXPORT int
libevdev_disable_event_type(struct libevdev *dev, unsigned int type)
{
+ int max;
+
if (type > EV_MAX || type == EV_SYN)
return -1;
+ max = libevdev_event_type_get_max(type);
+ if (max == -1)
+ return -1;
+
clear_bit(dev->bits, type);
return 0;
max = type_to_mask(dev, type, &mask);
- if (code > max)
+ if (code > max || (int)max == -1)
return -1;
set_bit(mask, code);
unsigned int max;
unsigned long *mask = NULL;
- if (type > EV_MAX)
+ if (type > EV_MAX || type == EV_SYN)
return -1;
max = type_to_mask(dev, type, &mask);
- if (code > max)
+ if (code > max || (int)max == -1)
return -1;
clear_bit(mask, code);
}
LIBEVDEV_EXPORT int
-libevdev_kernel_set_abs_value(struct libevdev *dev, unsigned int code, const struct input_absinfo *abs)
-{
- return libevdev_kernel_set_abs_info(dev, code, abs);
-}
-
-LIBEVDEV_EXPORT int
libevdev_kernel_set_abs_info(struct libevdev *dev, unsigned int code, const struct input_absinfo *abs)
{
int rc;
- if (dev->fd < 0) {
+ if (!dev->initialized) {
log_bug("device not initialized. call libevdev_set_fd() first\n");
return -EBADF;
- }
+ } else if (dev->fd < 0)
+ return -EBADF;
if (code > ABS_MAX)
return -EINVAL;
{
int rc = 0;
- if (dev->fd < 0) {
+ if (!dev->initialized) {
log_bug("device not initialized. call libevdev_set_fd() first\n");
return -EBADF;
- }
+ } else if (dev->fd < 0)
+ return -EBADF;
if (grab != LIBEVDEV_GRAB && grab != LIBEVDEV_UNGRAB) {
log_bug("invalid grab parameter %#x\n", grab);
return rc < 0 ? -errno : 0;
}
-/* DEPRECATED */
-LIBEVDEV_EXPORT int
-libevdev_is_event_type(const struct input_event *ev, unsigned int type)
-ALIAS(libevdev_event_is_type);
-
LIBEVDEV_EXPORT int
libevdev_event_is_type(const struct input_event *ev, unsigned int type)
{
return type < EV_CNT && ev->type == type;
}
-/* DEPRECATED */
-LIBEVDEV_EXPORT int
-libevdev_is_event_code(const struct input_event *ev, unsigned int type, unsigned int code)
-ALIAS(libevdev_event_is_code);
-
LIBEVDEV_EXPORT int
libevdev_event_is_code(const struct input_event *ev, unsigned int type, unsigned int code)
{
return (max > -1 && code <= (unsigned int)max && ev->code == code);
}
-/* DEPRECATED */
-LIBEVDEV_EXPORT const char*
-libevdev_get_event_type_name(unsigned int type)
-ALIAS(libevdev_event_type_get_name);
-
LIBEVDEV_EXPORT const char*
libevdev_event_type_get_name(unsigned int type)
{
return ev_map[type];
}
-/* DEPRECATED */
-LIBEVDEV_EXPORT const char*
-libevdev_get_event_code_name(unsigned int type, unsigned int code)
-ALIAS(libevdev_event_code_get_name);
-
LIBEVDEV_EXPORT const char*
libevdev_event_code_get_name(unsigned int type, unsigned int code)
{
return event_type_map[type][code];
}
-/* DEPRECATED */
-LIBEVDEV_EXPORT const char*
-libevdev_get_input_prop_name(unsigned int prop)
-ALIAS(libevdev_property_get_name);
-
-/* DEPRECATED */
-LIBEVDEV_EXPORT const char*
-libevdev_get_property_name(unsigned int prop)
-ALIAS(libevdev_property_get_name);
-
LIBEVDEV_EXPORT const char*
libevdev_property_get_name(unsigned int prop)
{
return input_prop_map[prop];
}
-/* DEPRECATED */
-LIBEVDEV_EXPORT int
-libevdev_get_event_type_max(unsigned int type)
-ALIAS(libevdev_event_type_get_max);
-
LIBEVDEV_EXPORT int
libevdev_event_type_get_max(unsigned int type)
{
}
LIBEVDEV_EXPORT int
-libevdev_get_repeat(struct libevdev *dev, int *delay, int *period)
+libevdev_get_repeat(const struct libevdev *dev, int *delay, int *period)
{
if (!libevdev_has_event_type(dev, EV_REP))
return -1;
int rc = 0;
size_t nleds = 0;
- if (dev->fd < 0) {
+ if (!dev->initialized) {
log_bug("device not initialized. call libevdev_set_fd() first\n");
return -EBADF;
- }
+ } else if (dev->fd < 0)
+ return -EBADF;
memset(ev, 0, sizeof(ev));
return rc;
}
+
+LIBEVDEV_EXPORT int
+libevdev_set_clock_id(struct libevdev *dev, int clockid)
+{
+ if (!dev->initialized) {
+ log_bug("device not initialized. call libevdev_set_fd() first\n");
+ return -EBADF;
+ } else if (dev->fd < 0)
+ return -EBADF;
+
+ return ioctl(dev->fd, EVIOCSCLOCKID, &clockid) ? -errno : 0;
+}