typedef struct managed_evdev managed_evdev;
struct idev_evdev {
- struct idev_element element;
+ idev_element element;
struct libevdev *evdev;
int fd;
sd_event_source *fd_src;
bool unsync : 1; /* not in-sync with kernel */
bool resync : 1; /* re-syncing with kernel */
+ bool running : 1;
};
struct unmanaged_evdev {
- struct idev_evdev evdev;
+ idev_evdev evdev;
char *devnode;
};
struct managed_evdev {
- struct idev_evdev evdev;
+ idev_evdev evdev;
dev_t devnum;
sd_bus_slot *slot_pause_device;
sprintf(out, "evdev/%u:%u", major(devnum), minor(devnum));
}
-static int idev_evdev_raise(idev_evdev *evdev, struct input_event *event) {
+static int idev_evdev_feed_resync(idev_evdev *evdev) {
+ idev_data data = {
+ .type = IDEV_DATA_RESYNC,
+ .resync = evdev->resync,
+ };
+
+ return idev_element_feed(&evdev->element, &data);
+}
+
+static int idev_evdev_feed_evdev(idev_evdev *evdev, struct input_event *event) {
idev_data data = {
.type = IDEV_DATA_EVDEV,
.resync = evdev->resync,
* case we cannot keep up with the kernel.
* TODO: Make sure libevdev always reports SYN_DROPPED to us, regardless
* whether any event was synced afterwards.
- * TODO: Forward SYN_DROPPED to attached devices.
*/
flags = LIBEVDEV_READ_FLAG_NORMAL;
} else if (r == LIBEVDEV_READ_STATUS_SYNC) {
if (evdev->resync) {
/* sync-event */
- r = idev_evdev_raise(evdev, &ev);
+ r = idev_evdev_feed_evdev(evdev, &ev);
if (r != 0) {
error = r;
break;
/* start of sync */
evdev->resync = true;
flags = LIBEVDEV_READ_FLAG_SYNC;
+ r = idev_evdev_feed_resync(evdev);
+ if (r != 0) {
+ error = r;
+ break;
+ }
}
} else {
/* normal event */
- r = idev_evdev_raise(evdev, &ev);
+ r = idev_evdev_feed_evdev(evdev, &ev);
if (r != 0) {
error = r;
break;
assert(evdev->fd_src);
assert(evdev->idle_src);
+ if (evdev->running)
+ return;
+ if (evdev->fd < 0 || evdev->element.n_open < 1 || !evdev->element.enabled)
+ return;
+
+ evdev->running = true;
sd_event_source_set_enabled(evdev->fd_src, SD_EVENT_ON);
sd_event_source_set_enabled(evdev->idle_src, SD_EVENT_ONESHOT);
}
assert(evdev->fd_src);
assert(evdev->idle_src);
+ if (!evdev->running)
+ return;
+
+ evdev->running = false;
+ idev_evdev_feed_resync(evdev);
sd_event_source_set_enabled(evdev->fd_src, SD_EVENT_OFF);
sd_event_source_set_enabled(evdev->idle_src, SD_EVENT_OFF);
}
if (fd < 0 || evdev->fd == fd) {
fd = -1;
- if (evdev->fd >= 0 && e->n_open > 0 && e->enabled)
- idev_evdev_enable(evdev);
-
+ idev_evdev_enable(evdev);
return 0;
}
flags = fcntl(fd, F_GETFL, 0);
if (flags < 0)
- return r;
+ return -errno;
flags &= O_ACCMODE;
if (flags == O_WRONLY)
return -EACCES;
evdev->element.readable = true;
- evdev->element.writable = true;
- if (flags == O_RDONLY)
- evdev->element.writable = false;
- else if (flags == O_WRONLY)
- evdev->element.readable = false;
+ evdev->element.writable = !(flags & O_RDONLY);
/*
* TODO: We *MUST* re-sync the device so we get a delta of the changed
return r;
}
- if (e->n_open < 1 || !e->enabled) {
- sd_event_source_set_enabled(evdev->fd_src, SD_EVENT_OFF);
- sd_event_source_set_enabled(evdev->idle_src, SD_EVENT_OFF);
- }
+ sd_event_source_set_enabled(evdev->fd_src, SD_EVENT_OFF);
+ sd_event_source_set_enabled(evdev->idle_src, SD_EVENT_OFF);
evdev->unsync = true;
evdev->fd = fd;
-
fd = -1;
+
+ idev_evdev_enable(evdev);
return 0;
}
log_debug("idev-evdev: %s/%s: pause", e->session->name, e->name);
+ idev_evdev_disable(evdev);
if (release) {
evdev->idle_src = sd_event_source_unref(evdev->idle_src);
evdev->fd_src = sd_event_source_unref(evdev->fd_src);
evdev->fd = safe_close(evdev->fd);
- } else {
- idev_evdev_disable(evdev);
}
}
int r;
assert_return(s, -EINVAL);
- assert_return(s->context->sysbus, -EINVAL);
assert_return(s->managed, -EINVAL);
assert_return(s->context->sysbus, -EINVAL);
assert_return(ud, -EINVAL);