END_TEST START_TEST(test_empty_sync) { struct uinput_device* uidev; struct libevdev *dev; int rc; struct input_event ev; rc = test_create_device(&uidev, &dev, EV_SYN, SYN_REPORT, EV_SYN, SYN_DROPPED, EV_KEY, BTN_LEFT, EV_KEY, BTN_MIDDLE, EV_KEY, BTN_RIGHT, -1); ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc)); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_FORCE_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, -EAGAIN); uinput_device_free(uidev); libevdev_free(dev); }
END_TEST START_TEST(test_incomplete_sync) { struct uinput_device* uidev; struct libevdev *dev; int rc; struct input_event ev; struct input_absinfo abs[2]; memset(abs, 0, sizeof(abs)); abs[0].value = ABS_X; abs[0].maximum = 1000; abs[1].value = ABS_Y; abs[1].maximum = 1000; rc = test_create_abs_device(&uidev, &dev, 2, abs, EV_SYN, SYN_REPORT, EV_SYN, SYN_DROPPED, EV_KEY, BTN_LEFT, EV_KEY, BTN_MIDDLE, EV_KEY, BTN_RIGHT, -1); ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc)); uinput_device_event(uidev, EV_KEY, BTN_LEFT, 1); uinput_device_event(uidev, EV_ABS, ABS_X, 100); uinput_device_event(uidev, EV_ABS, ABS_Y, 500); uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_FORCE_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); ck_assert_int_eq(ev.type, EV_KEY); ck_assert_int_eq(ev.code, BTN_LEFT); ck_assert_int_eq(ev.value, 1); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); ck_assert_int_eq(rc, -EAGAIN); ck_assert_int_eq(libevdev_get_event_value(dev, EV_KEY, BTN_LEFT), 1); ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_X), 100); ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_Y), 500); uinput_device_free(uidev); libevdev_free(dev); }
void evdevDevice::UpdateInput() { // Run through all evdev events // libevdev will keep track of the actual controller state internally which can be queried // later with libevdev_fetch_event_value() input_event ev; int rc = LIBEVDEV_READ_STATUS_SUCCESS; do { if (rc == LIBEVDEV_READ_STATUS_SYNC) rc = libevdev_next_event(m_dev, LIBEVDEV_READ_FLAG_SYNC, &ev); else rc = libevdev_next_event(m_dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); } while (rc >= 0); }
END_TEST START_TEST(test_event_code_filtered) { struct uinput_device* uidev; struct libevdev *dev; int rc; struct input_event ev; rc = test_create_device(&uidev, &dev, EV_REL, REL_X, EV_REL, REL_Y, EV_KEY, BTN_LEFT, -1); ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc)); libevdev_disable_event_code(dev, EV_REL, REL_X); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); ck_assert_int_eq(rc, -EAGAIN); uinput_device_event(uidev, EV_REL, REL_X, 1); uinput_device_event(uidev, EV_REL, REL_Y, 1); uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS); ck_assert_int_eq(ev.type, EV_REL); ck_assert_int_eq(ev.code, REL_Y); ck_assert_int_eq(ev.value, 1); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS); ck_assert_int_eq(ev.type, EV_SYN); ck_assert_int_eq(ev.code, SYN_REPORT); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); ck_assert_int_eq(rc, -EAGAIN); libevdev_free(dev); uinput_device_free(uidev); }
END_TEST START_TEST(test_has_event_pending) { struct uinput_device* uidev; struct libevdev *dev; int rc; struct input_event ev; rc = test_create_device(&uidev, &dev, EV_REL, REL_X, EV_REL, REL_Y, EV_KEY, BTN_LEFT, -1); ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc)); ck_assert_int_eq(libevdev_has_event_pending(dev), 0); uinput_device_event(uidev, EV_REL, REL_X, 1); uinput_device_event(uidev, EV_REL, REL_Y, 1); uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0); ck_assert_int_eq(libevdev_has_event_pending(dev), 1); libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); ck_assert_int_eq(libevdev_has_event_pending(dev), 1); while ((rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev)) != -EAGAIN) ; ck_assert_int_eq(libevdev_has_event_pending(dev), 0); libevdev_change_fd(dev, -1); ck_assert_int_eq(libevdev_has_event_pending(dev), -EBADF); libevdev_free(dev); uinput_device_free(uidev); }
END_TEST START_TEST(test_syn_delta_button) { struct uinput_device* uidev; struct libevdev *dev; int rc; struct input_event ev; rc = test_create_device(&uidev, &dev, EV_SYN, SYN_REPORT, EV_SYN, SYN_DROPPED, EV_REL, REL_X, EV_REL, REL_Y, EV_KEY, BTN_LEFT, EV_KEY, BTN_MIDDLE, EV_KEY, BTN_RIGHT, EV_KEY, KEY_MAX, -1); ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc)); uinput_device_event(uidev, EV_KEY, BTN_LEFT, 1); uinput_device_event(uidev, EV_KEY, BTN_RIGHT, 1); uinput_device_event(uidev, EV_KEY, KEY_MAX, 1); uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_FORCE_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); ck_assert_int_eq(ev.type, EV_KEY); ck_assert_int_eq(ev.code, BTN_LEFT); ck_assert_int_eq(ev.value, 1); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); ck_assert_int_eq(ev.type, EV_KEY); ck_assert_int_eq(ev.code, BTN_RIGHT); ck_assert_int_eq(ev.value, 1); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); ck_assert_int_eq(ev.type, EV_KEY); ck_assert_int_eq(ev.code, KEY_MAX); ck_assert_int_eq(ev.value, 1); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); ck_assert_int_eq(ev.type, EV_SYN); ck_assert_int_eq(ev.code, SYN_REPORT); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, -EAGAIN); ck_assert(libevdev_get_event_value(dev, EV_KEY, BTN_LEFT)); ck_assert(libevdev_get_event_value(dev, EV_KEY, BTN_RIGHT)); ck_assert(!libevdev_get_event_value(dev, EV_KEY, BTN_MIDDLE)); ck_assert(libevdev_get_event_value(dev, EV_KEY, KEY_MAX)); uinput_device_free(uidev); libevdev_free(dev); }
END_TEST START_TEST(test_syn_delta_sw) { struct uinput_device* uidev; struct libevdev *dev; int rc; struct input_event ev; rc = test_create_device(&uidev, &dev, EV_SYN, SYN_REPORT, EV_SYN, SYN_DROPPED, EV_SW, SW_LID, EV_SW, SW_MICROPHONE_INSERT, EV_SW, SW_MAX, -1); ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc)); uinput_device_event(uidev, EV_SW, SW_LID, 1); uinput_device_event(uidev, EV_SW, SW_MICROPHONE_INSERT, 1); uinput_device_event(uidev, EV_SW, SW_MAX, 1); uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_FORCE_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); ck_assert_int_eq(ev.type, EV_SW); ck_assert_int_eq(ev.code, SW_LID); ck_assert_int_eq(ev.value, 1); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); ck_assert_int_eq(ev.type, EV_SW); ck_assert_int_eq(ev.code, SW_MICROPHONE_INSERT); ck_assert_int_eq(ev.value, 1); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); ck_assert_int_eq(ev.type, EV_SW); ck_assert_int_eq(ev.code, SW_MAX); ck_assert_int_eq(ev.value, 1); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); ck_assert_int_eq(ev.type, EV_SYN); ck_assert_int_eq(ev.code, SYN_REPORT); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, -EAGAIN); ck_assert_int_eq(libevdev_get_event_value(dev, EV_SW, SW_LID), 1); ck_assert_int_eq(libevdev_get_event_value(dev, EV_SW, SW_MICROPHONE_INSERT), 1); ck_assert_int_eq(libevdev_get_event_value(dev, EV_SW, SW_MAX), 1); uinput_device_free(uidev); libevdev_free(dev); }
int intercept(struct libevdev_uinput *uidev, struct libevdev *dev){ int ret; struct input_event ev; struct chord state; chord_reset(&state); lookup_init("dat/test-keymap-minimal.dat"); do { ret = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL|LIBEVDEV_READ_FLAG_BLOCKING, &ev); if (ret == LIBEVDEV_READ_STATUS_SUCCESS){ //forward key down and key up events if(ev.type == EV_KEY && (ev.value == 1 || ev.value == 0)) forward_event(uidev, &ev, &state); } } while (ret == LIBEVDEV_READ_STATUS_SYNC || ret == LIBEVDEV_READ_STATUS_SUCCESS || ret == -EAGAIN); if (ret != LIBEVDEV_READ_STATUS_SUCCESS && ret != -EAGAIN) fprintf(stderr, "Failed to handle events: %s\n", strerror(-ret)); return 0;}
int next_event_wrapper(struct adhoc *adhoc, struct input_event *event) { int r = libevdev_next_event(adhoc->dev, LIBEVDEV_READ_FLAG_NORMAL | LIBEVDEV_READ_FLAG_BLOCKING, event); if (r < 0) { error(0, -r, "libevdev_next_event failed"); return r; } if (r == LIBEVDEV_READ_STATUS_SYNC) { fprintf(stderr, "libevdev_next_event returned LIBEVDEV_READ_STATUS_SYNC, handling not implemented!\n"); return 0; } #ifdef DEBUG fprintf(stderr, "event [type: %s, code: %s, value: %d]\n", libevdev_event_type_get_name(event->type), libevdev_event_code_get_name(event->type, event->code), event->value); #endif return 0; }
static int mainloop(struct libevdev *dev, struct measurements *m) { struct pollfd fds[2]; sigset_t mask; fds[0].fd = libevdev_get_fd(dev); fds[0].events = POLLIN; sigemptyset(&mask); sigaddset(&mask, SIGINT); fds[1].fd = signalfd(-1, &mask, SFD_NONBLOCK); fds[1].events = POLLIN; sigprocmask(SIG_BLOCK, &mask, NULL); while (poll(fds, 2, -1)) { struct input_event ev; int rc; if (fds[1].revents) break; do { rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); if (rc == LIBEVDEV_READ_STATUS_SYNC) { fprintf(stderr, "Error: cannot keep up\n"); return 1; } else if (rc != -EAGAIN && rc < 0) { fprintf(stderr, "Error: %s\n", strerror(-rc)); return 1; } else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) { handle_event(m, &ev); } } while (rc != -EAGAIN); } return 0; }
static int evdev_handle(int fd) { for (int i=0;i<numDevices;i++) { if (devices[i].fd = fd) { int rc; struct input_event ev; while ((rc = libevdev_next_event(devices[i].dev, LIBEVDEV_READ_FLAG_NORMAL, &ev)) >= 0) { if (rc == LIBEVDEV_READ_STATUS_SYNC) fprintf(stderr, "Error: cannot keep up\n"); else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) { if (!handler(&ev, &devices[i])) return LOOP_RETURN; } } if (rc == -ENODEV) { evdev_remove(i); } else if (rc != -EAGAIN && rc < 0) { fprintf(stderr, "Error: %s\n", strerror(-rc)); exit(EXIT_FAILURE); } } } return LOOP_OK; }
static void evdev_drain(void) { for (int i = 0; i < numDevices; i++) { struct input_event ev; while (libevdev_next_event(devices[i].dev, LIBEVDEV_READ_FLAG_NORMAL, &ev) >= 0); } }
uint32_t joystick_linux::process_joysticks(uint32_t p_event_id) { if (joy_mutex->try_lock() != OK) { return p_event_id; } for (int i=0; i<JOYSTICKS_MAX; i++) { if (joysticks[i].fd == -1) continue; input_event ev; Joystick* joy = &joysticks[i]; libevdev* dev = joy->dev; int rc = 1; rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); if (rc < 0 && rc != -EAGAIN) { continue; } while (rc == LIBEVDEV_READ_STATUS_SYNC || rc == LIBEVDEV_READ_STATUS_SUCCESS) { switch (ev.type) { case EV_KEY: p_event_id = input->joy_button(p_event_id, i, joy->key_map[ev.code], ev.value); break; case EV_ABS: switch (ev.code) { case ABS_HAT0X: if (ev.value != 0) { if (ev.value < 0) joy->dpad |= InputDefault::HAT_MASK_LEFT; else joy->dpad |= InputDefault::HAT_MASK_RIGHT; } else joy->dpad &= ~(InputDefault::HAT_MASK_LEFT | InputDefault::HAT_MASK_RIGHT); p_event_id = input->joy_hat(p_event_id, i, joy->dpad); break; case ABS_HAT0Y: if (ev.value != 0) { if (ev.value < 0) joy->dpad |= InputDefault::HAT_MASK_UP; else joy->dpad |= InputDefault::HAT_MASK_DOWN; } else joy->dpad &= ~(InputDefault::HAT_MASK_UP | InputDefault::HAT_MASK_DOWN); p_event_id = input->joy_hat(p_event_id, i, joy->dpad); break; default: if (joy->abs_map[ev.code] != -1) { InputDefault::JoyAxis value = axis_correct(libevdev_get_abs_info(dev, ev.code), ev.value); joy->curr_axis[joy->abs_map[ev.code]] = value; } break; } break; } rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); } for (int j = 0; j < MAX_ABS; j++) { int index = joy->abs_map[j]; if (index != -1) { p_event_id = input->joy_axis(p_event_id, i, index, joy->curr_axis[index]); } } } joy_mutex->unlock(); return p_event_id; }
END_TEST START_TEST(test_syn_delta_mt) { struct uinput_device* uidev; struct libevdev *dev; int rc; struct input_event ev; struct input_absinfo abs[6]; memset(abs, 0, sizeof(abs)); abs[0].value = ABS_X; abs[0].maximum = 1000; abs[1].value = ABS_MT_POSITION_X; abs[1].maximum = 1000; abs[2].value = ABS_Y; abs[2].maximum = 1000; abs[3].value = ABS_MT_POSITION_Y; abs[3].maximum = 1000; abs[4].value = ABS_MT_SLOT; abs[4].maximum = 1; abs[5].value = ABS_MT_TRACKING_ID; abs[5].minimum = -1; abs[5].maximum = 2; rc = test_create_abs_device(&uidev, &dev, 6, abs, EV_SYN, SYN_REPORT, -1); ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc)); uinput_device_event(uidev, EV_ABS, ABS_MT_SLOT, 0); uinput_device_event(uidev, EV_ABS, ABS_X, 100); uinput_device_event(uidev, EV_ABS, ABS_Y, 500); uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_X, 100); uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_Y, 500); uinput_device_event(uidev, EV_ABS, ABS_MT_TRACKING_ID, 1); uinput_device_event(uidev, EV_ABS, ABS_MT_SLOT, 1); uinput_device_event(uidev, EV_ABS, ABS_X, 1); uinput_device_event(uidev, EV_ABS, ABS_Y, 5); uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_X, 1); uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_Y, 5); uinput_device_event(uidev, EV_ABS, ABS_MT_TRACKING_ID, 2); uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_FORCE_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); ck_assert_int_eq(ev.type, EV_ABS); ck_assert_int_eq(ev.code, ABS_X); ck_assert_int_eq(ev.value, 1); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); ck_assert_int_eq(ev.type, EV_ABS); ck_assert_int_eq(ev.code, ABS_Y); ck_assert_int_eq(ev.value, 5); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); ck_assert_int_eq(ev.type, EV_ABS); ck_assert_int_eq(ev.code, ABS_MT_SLOT); ck_assert_int_eq(ev.value, 0); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); ck_assert_int_eq(ev.type, EV_ABS); ck_assert_int_eq(ev.code, ABS_MT_POSITION_X); ck_assert_int_eq(ev.value, 100); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); ck_assert_int_eq(ev.type, EV_ABS); ck_assert_int_eq(ev.code, ABS_MT_POSITION_Y); ck_assert_int_eq(ev.value, 500); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); ck_assert_int_eq(ev.type, EV_ABS); ck_assert_int_eq(ev.code, ABS_MT_TRACKING_ID); ck_assert_int_eq(ev.value, 1); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); ck_assert_int_eq(ev.type, EV_ABS); ck_assert_int_eq(ev.code, ABS_MT_SLOT); ck_assert_int_eq(ev.value, 1); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); ck_assert_int_eq(ev.type, EV_ABS); ck_assert_int_eq(ev.code, ABS_MT_POSITION_X); ck_assert_int_eq(ev.value, 1); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); ck_assert_int_eq(ev.type, EV_ABS); ck_assert_int_eq(ev.code, ABS_MT_POSITION_Y); ck_assert_int_eq(ev.value, 5); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); ck_assert_int_eq(ev.type, EV_ABS); ck_assert_int_eq(ev.code, ABS_MT_TRACKING_ID); ck_assert_int_eq(ev.value, 2); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); ck_assert_int_eq(ev.type, EV_SYN); ck_assert_int_eq(ev.code, SYN_REPORT); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); ck_assert_int_eq(rc, -EAGAIN); uinput_device_free(uidev); libevdev_free(dev); }
END_TEST START_TEST(test_syn_event) { struct uinput_device* uidev; struct libevdev *dev; int rc; struct input_event ev; int pipefd[2]; rc = test_create_device(&uidev, &dev, EV_SYN, SYN_REPORT, EV_SYN, SYN_DROPPED, EV_REL, REL_X, EV_REL, REL_Y, EV_KEY, BTN_LEFT, -1); ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc)); /* This is a bid complicated: we can't get SYN_DROPPED through uinput, so we push two events down uinput, and fetch one off libevdev (reading in the other one on the way). Then write a SYN_DROPPED on a pipe, switch the fd and read one event off the wire (but returning the second event from before). Switch back, so that when we do read off the SYN_DROPPED we have the fd back on the device and the ioctls work. */ uinput_device_event(uidev, EV_KEY, BTN_LEFT, 1); uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS); ck_assert_int_eq(ev.type, EV_KEY); ck_assert_int_eq(ev.code, BTN_LEFT); rc = pipe2(pipefd, O_NONBLOCK); ck_assert_int_eq(rc, 0); libevdev_change_fd(dev, pipefd[0]); ev.type = EV_SYN; ev.code = SYN_DROPPED; ev.value = 0; rc = write(pipefd[1], &ev, sizeof(ev)); ck_assert_int_eq(rc, sizeof(ev)); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); libevdev_change_fd(dev, uinput_device_get_fd(uidev)); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS); ck_assert_int_eq(ev.type, EV_SYN); ck_assert_int_eq(ev.code, SYN_REPORT); rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC); /* only check for the rc, nothing actually changed on the device */ libevdev_free(dev); uinput_device_free(uidev); close(pipefd[0]); close(pipefd[1]); }
static bool input_poll(bool (*handler) (struct input_event*, struct input_device*)) { // Block signals that are handled gracefully by the input polling code. This // is done at the last moment to allow Ctrl+C to work until everything // is ready to go. sigset_t sigset; sigemptyset(&sigset); sigaddset(&sigset, SIGHUP); sigaddset(&sigset, SIGTERM); sigaddset(&sigset, SIGINT); sigaddset(&sigset, SIGQUIT); sigprocmask(SIG_BLOCK, &sigset, NULL); fds[sig_fdindex].fd = signalfd(-1, &sigset, 0); fds[sig_fdindex].events = POLLIN | POLLERR | POLLHUP; while (poll(fds, numFds, -1)) { if (fds[udev_fdindex].revents > 0) { struct udev_device *dev = udev_monitor_receive_device(udev_mon); const char *action = udev_device_get_action(dev); if (action != NULL) { if (autoadd && strcmp("add", action) == 0) { const char *devnode = udev_device_get_devnode(dev); int id; if (devnode != NULL && sscanf(devnode, "/dev/input/event%d", &id) == 1) { input_create(devnode, defaultMapfile); } } udev_device_unref(dev); } } else if (fds[sig_fdindex].revents > 0) { struct signalfd_siginfo info; read(fds[sig_fdindex].fd, &info, sizeof(info)); switch (info.ssi_signo) { case SIGINT: case SIGTERM: case SIGQUIT: case SIGHUP: return false; } } for (int i=0;i<numDevices;i++) { if (fds[devices[i].fdindex].revents > 0) { int rc; struct input_event ev; while ((rc = libevdev_next_event(devices[i].dev, LIBEVDEV_READ_FLAG_NORMAL, &ev)) >= 0) { if (rc == LIBEVDEV_READ_STATUS_SYNC) fprintf(stderr, "Error: cannot keep up\n"); else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) { if (!handler(&ev, &devices[i])) return true; } } if (rc == -ENODEV) { input_remove(i); } else if (rc != -EAGAIN && rc < 0) { fprintf(stderr, "Error: %s\n", strerror(-rc)); exit(EXIT_FAILURE); } } } } return false; }
END_TEST START_TEST(test_mt_event_values) { struct uinput_device* uidev; struct libevdev *dev; int rc; struct input_event ev; struct input_absinfo abs[5]; int value; memset(abs, 0, sizeof(abs)); abs[0].value = ABS_X; abs[0].maximum = 1000; abs[1].value = ABS_MT_POSITION_X; abs[1].maximum = 1000; abs[2].value = ABS_Y; abs[2].maximum = 1000; abs[3].value = ABS_MT_POSITION_Y; abs[3].maximum = 1000; abs[4].value = ABS_MT_SLOT; abs[4].maximum = 2; rc = test_create_abs_device(&uidev, &dev, 5, abs, EV_SYN, SYN_REPORT, -1); ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc)); uinput_device_event(uidev, EV_ABS, ABS_MT_SLOT, 0); uinput_device_event(uidev, EV_ABS, ABS_X, 100); uinput_device_event(uidev, EV_ABS, ABS_Y, 500); uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_X, 100); uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_Y, 500); uinput_device_event(uidev, EV_ABS, ABS_MT_SLOT, 1); uinput_device_event(uidev, EV_ABS, ABS_X, 1); uinput_device_event(uidev, EV_ABS, ABS_Y, 5); uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_X, 1); uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_Y, 5); uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0); /* must still be on old values */ ck_assert_int_eq(libevdev_get_current_slot(dev), 0); ck_assert_int_eq(libevdev_get_slot_value(dev, 0, ABS_MT_POSITION_X), 0); ck_assert_int_eq(libevdev_get_slot_value(dev, 0, ABS_MT_POSITION_Y), 0); ck_assert_int_eq(libevdev_get_slot_value(dev, 1, ABS_MT_POSITION_X), 0); ck_assert_int_eq(libevdev_get_slot_value(dev, 1, ABS_MT_POSITION_Y), 0); do { rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); } while (rc == LIBEVDEV_READ_STATUS_SUCCESS); ck_assert_int_eq(rc, -EAGAIN); ck_assert_int_eq(libevdev_get_current_slot(dev), 1); ck_assert_int_eq(libevdev_get_slot_value(dev, 0, ABS_MT_POSITION_X), 100); ck_assert_int_eq(libevdev_get_slot_value(dev, 0, ABS_MT_POSITION_Y), 500); ck_assert_int_eq(libevdev_get_slot_value(dev, 1, ABS_MT_POSITION_X), 1); ck_assert_int_eq(libevdev_get_slot_value(dev, 1, ABS_MT_POSITION_Y), 5); ck_assert_int_eq(libevdev_fetch_slot_value(dev, 0, ABS_MT_POSITION_X, &value), 1); ck_assert_int_eq(value, 100); ck_assert_int_eq(libevdev_fetch_slot_value(dev, 0, ABS_MT_POSITION_Y, &value), 1); ck_assert_int_eq(value, 500); ck_assert_int_eq(libevdev_fetch_slot_value(dev, 1, ABS_MT_POSITION_X, &value), 1); ck_assert_int_eq(value, 1); ck_assert_int_eq(libevdev_fetch_slot_value(dev, 1, ABS_MT_POSITION_Y, &value), 1); ck_assert_int_eq(value, 5); uinput_device_free(uidev); libevdev_free(dev); }
END_TEST START_TEST(test_event_values) { struct uinput_device* uidev; struct libevdev *dev; int rc; struct input_event ev; struct input_absinfo abs[2]; int value; memset(abs, 0, sizeof(abs)); abs[0].value = ABS_X; abs[0].maximum = 1000; abs[1].value = ABS_Y; abs[1].maximum = 1000; rc = test_create_abs_device(&uidev, &dev, 2, abs, EV_SYN, SYN_REPORT, EV_SYN, SYN_DROPPED, EV_REL, REL_X, EV_REL, REL_Y, EV_KEY, BTN_LEFT, EV_KEY, BTN_MIDDLE, EV_KEY, BTN_RIGHT, -1); ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc)); uinput_device_event(uidev, EV_KEY, BTN_LEFT, 1); uinput_device_event(uidev, EV_ABS, ABS_X, 100); uinput_device_event(uidev, EV_ABS, ABS_Y, 500); uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0); /* must still be on old values */ ck_assert_int_eq(libevdev_get_event_value(dev, EV_KEY, BTN_LEFT), 0); ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_X), 0); ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_Y), 0); ck_assert_int_eq(libevdev_get_event_value(dev, EV_REL, REL_X), 0); ck_assert_int_eq(libevdev_get_event_value(dev, EV_REL, REL_Y), 0); ck_assert_int_eq(libevdev_fetch_event_value(dev, EV_KEY, BTN_LEFT, &value), 1); ck_assert_int_eq(value, 0); do { rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); } while (rc == 0); ck_assert_int_eq(rc, -EAGAIN); ck_assert_int_eq(libevdev_get_event_value(dev, EV_KEY, BTN_LEFT), 1); ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_X), 100); ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_Y), 500); /* always 0 */ ck_assert_int_eq(libevdev_get_event_value(dev, EV_REL, REL_X), 0); ck_assert_int_eq(libevdev_get_event_value(dev, EV_REL, REL_Y), 0); ck_assert_int_eq(libevdev_fetch_event_value(dev, EV_KEY, BTN_LEFT, &value), 1); ck_assert_int_eq(value, 1); ck_assert_int_eq(libevdev_fetch_event_value(dev, EV_ABS, ABS_X, &value), 1); ck_assert_int_eq(value, 100); ck_assert_int_eq(libevdev_fetch_event_value(dev, EV_ABS, ABS_Y, &value), 1); ck_assert_int_eq(value, 500); uinput_device_free(uidev); libevdev_free(dev); }
int main(int argc, char const *argv[]) { if (argc < 5) { printf("Usage: evmpd HOSTNAME PORT DEVICE HALT_COMMAND\n"); return EXIT_FAILURE; } struct mpd_connection *client = connect(argv[1], strtol(argv[2], NULL, 10)); struct libevdev *dev = NULL; int fd; int rc = 1; fd = open(argv[3], O_RDONLY | O_NONBLOCK); rc = libevdev_new_from_fd(fd, &dev); if (rc < 0) { fprintf(stderr, "Failed to init libevdev (%d)\n", strerror(-rc)); return EXIT_FAILURE; } printf("Input device name: \"%s\"\n", libevdev_get_name(dev)); printf("Input device ID: bus %#x vendor %#x product %#x\n", libevdev_get_id_bustype(dev), libevdev_get_id_vendor(dev), libevdev_get_id_product(dev)); do { struct input_event ev; rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); if (rc == 0 && ev.value == 0) { if (libevdev_event_is_code(&ev, EV_KEY, KEY_F4)) { system(argv[4]); printf("shutdown\n"); } else if (libevdev_event_is_code(&ev, EV_KEY, KEY_PLAYPAUSE)) { struct mpd_status *status = mpd_run_status(client); enum mpd_state state = mpd_status_get_state(status); if (state != MPD_STATE_PLAY && state != MPD_STATE_PAUSE) { mpd_run_play(client); printf("play\n"); } else { mpd_run_toggle_pause(client); printf("toggle-pause\n"); } } else if (libevdev_event_is_code(&ev, EV_KEY, KEY_STOPCD)) { mpd_run_stop(client); printf("stop\n"); } else if (libevdev_event_is_code(&ev, EV_KEY, KEY_PREVIOUSSONG)) { mpd_run_previous(client); printf("previous\n"); } else if (libevdev_event_is_code(&ev, EV_KEY, KEY_NEXTSONG)) { mpd_run_next(client); printf("next\n"); } else if (libevdev_event_is_code(&ev, EV_KEY, KEY_VOLUMEUP)) { struct mpd_status *status = mpd_run_status(client); int volume = mpd_status_get_volume(status); volume += 5; if (volume > 100) { volume = 100; } mpd_run_set_volume(client, volume); printf("set-volume %d\n", volume); } else if (libevdev_event_is_code(&ev, EV_KEY, KEY_VOLUMEDOWN)) { struct mpd_status *status = mpd_run_status(client); int volume = mpd_status_get_volume(status); volume -= 5; if (volume < 0) { volume = 0; } mpd_run_set_volume(client, volume); printf("set-volume %d\n", volume); } else { printf("Event: %s %s %d\n", libevdev_event_type_get_name(ev.type), libevdev_event_code_get_name(ev.type, ev.code), ev.value); } } } while (rc == LIBEVDEV_READ_STATUS_SUCCESS || rc == LIBEVDEV_READ_STATUS_SYNC || rc == -EAGAIN); printf("rc: %d\n", rc); if (client != NULL) { mpd_connection_free(client); } return EXIT_SUCCESS; }