void test_create_device(struct uinput_device **uidev_return, struct libevdev **dev_return, ...) { int rc, fd; struct uinput_device *uidev; struct libevdev *dev; va_list args; va_start(args, dev_return); rc = uinput_device_new_with_events_v(&uidev, TEST_DEVICE_NAME, DEFAULT_IDS, args); va_end(args); ck_assert_msg(rc == 0, "Failed to create uinput device: %s", strerror(-rc)); fd = uinput_device_get_fd(uidev); rc = libevdev_new_from_fd(fd, &dev); ck_assert_msg(rc == 0, "Failed to init device device: %s", strerror(-rc)); rc = fcntl(fd, F_SETFL, O_NONBLOCK); ck_assert_msg(rc == 0, "fcntl failed: %s", strerror(errno)); *uidev_return = uidev; *dev_return = dev; }
struct adhoc* adhoc_init(int fd) { struct adhoc *adhoc = calloc(1, sizeof(struct adhoc)); int r = libevdev_new_from_fd(fd, &adhoc->dev); if (r) { error(0, -r, "libevdev_new_from_fd failed"); goto creation_error; } const char *name = libevdev_get_name(adhoc->dev); if (strcmp(name, "SMART SB680 Interactive Whiteboard") == 0) adhoc->internal_calls = internal_calls_sb680; else if (strcmp(name, "SMART SB885 Interactive Whiteboard") == 0) adhoc->internal_calls = internal_calls_sb885; else { fprintf(stderr, "unknown device: %s\n", name); goto device_error; } #ifdef DEBUG fprintf(stderr, "device: %s\n", name); #endif if (adhoc->internal_calls.init(adhoc)) goto device_error; return adhoc; device_error: libevdev_free(adhoc->dev); creation_error: free(adhoc); return NULL; }
int main (int argc, char **argv) { int rc; int fd; const char *path; struct libevdev *dev; struct measurements measurements = {0}; if (argc < 2) return usage(); path = argv[1]; if (path[0] == '-') return usage(); fd = open(path, O_RDONLY|O_NONBLOCK); if (fd < 0) { fprintf(stderr, "Error opening the device: %s\n", strerror(errno)); return 1; } rc = libevdev_new_from_fd(fd, &dev); if (rc != 0) { fprintf(stderr, "Error fetching the device info: %s\n", strerror(-rc)); return 1; } if (libevdev_grab(dev, LIBEVDEV_GRAB) != 0) { fprintf(stderr, "Error: cannot grab the device, something else is grabbing it.\n"); fprintf(stderr, "Use 'fuser -v %s' to find processes with an open fd\n", path); return 1; } libevdev_grab(dev, LIBEVDEV_UNGRAB); printf("Mouse %s on %s\n", libevdev_get_name(dev), path); printf("Move the device 250mm/10in or more along the x-axis.\n"); printf("Pause 3 seconds before movement to reset, Ctrl+C to exit.\n"); setbuf(stdout, NULL); rc = mainloop(dev, &measurements); printf("\n"); print_summary(&measurements); printf("\n"); printf("Entry for hwdb match (replace XXX with the resolution in DPI):\n" "mouse:%s:v%04xp%04x:name:%s:\n" " MOUSE_DPI=XXX@%d\n", bustype(libevdev_get_id_bustype(dev)), libevdev_get_id_vendor(dev), libevdev_get_id_product(dev), libevdev_get_name(dev), (int)measurements.max_frequency); libevdev_free(dev); close(fd); return rc; }
void joystick_linux::open_joystick(const char *p_path) { int joy_num = get_free_joy_slot(); int fd = open(p_path, O_RDONLY | O_NONBLOCK); if (fd != -1 && joy_num != -1) { int rc = libevdev_new_from_fd(fd, &joysticks[joy_num].dev); if (rc < 0) { fprintf(stderr, "Failed to init libevdev (%s)\n", strerror(-rc)); return; } libevdev *dev = joysticks[joy_num].dev; //check if the device supports basic gamepad events, prevents certain keyboards from //being detected as joysticks if (libevdev_has_event_type(dev, EV_ABS) && libevdev_has_event_type(dev, EV_KEY) && (libevdev_has_event_code(dev, EV_KEY, BTN_A) || libevdev_has_event_code(dev, EV_KEY, BTN_THUMBL) || libevdev_has_event_code(dev, EV_KEY, BTN_TOP))) { char uid[128]; String name = libevdev_get_name(dev); uint16_t bus = __bswap_16(libevdev_get_id_bustype(dev)); uint16_t vendor = __bswap_16(libevdev_get_id_vendor(dev)); uint16_t product = __bswap_16(libevdev_get_id_product(dev)); uint16_t version = __bswap_16(libevdev_get_id_version(dev)); joysticks[joy_num].reset(); Joystick &joy = joysticks[joy_num]; joy.fd = fd; joy.devpath = String(p_path); setup_joystick_properties(joy_num); sprintf(uid, "%04x%04x", bus, 0); if (vendor && product && version) { sprintf(uid + String(uid).length(), "%04x%04x%04x%04x%04x%04x", vendor,0,product,0,version,0); input->joy_connection_changed(joy_num, true, name, uid); } else { String uidname = uid; int uidlen = MIN(name.length(), 11); for (int i=0; i<uidlen; i++) { uidname = uidname + _hex_str(name[i]); } uidname += "00"; input->joy_connection_changed(joy_num, true, name, uidname); } } else { //device is not a gamepad, clean up libevdev_free(dev); close(fd); } } }
int _libevdev_new_from_fd(lua_State* const state) { libevdev* dev; lua::push(state, libevdev_new_from_fd( lua::get<int>(state, 1), &dev )); lua::push(state, dev); return 2; }
END_TEST START_TEST(test_uinput_create_device_from_fd) { struct libevdev *dev, *dev2; struct libevdev_uinput *uidev; int fd, fd2; unsigned int type, code; int rc; const char *devnode; dev = libevdev_new(); ck_assert(dev != NULL); libevdev_set_name(dev, TEST_DEVICE_NAME); libevdev_enable_event_type(dev, EV_SYN); libevdev_enable_event_type(dev, EV_REL); libevdev_enable_event_code(dev, EV_REL, REL_X, NULL); libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL); fd = open(UINPUT_NODE, O_RDWR); ck_assert_int_gt(fd, -1); rc = libevdev_uinput_create_from_device(dev, fd, &uidev); ck_assert_int_eq(rc, 0); ck_assert(uidev != NULL); ck_assert_int_eq(libevdev_uinput_get_fd(uidev), fd); devnode = libevdev_uinput_get_devnode(uidev); ck_assert(devnode != NULL); fd2 = open(devnode, O_RDONLY); ck_assert_int_gt(fd2, -1); rc = libevdev_new_from_fd(fd2, &dev2); ck_assert_int_eq(rc, 0); for (type = 0; type < EV_CNT; type++) { int max = libevdev_event_type_get_max(type); if (max == -1) continue; for (code = 0; code < max; code++) { ck_assert_int_eq(libevdev_has_event_code(dev, type, code), libevdev_has_event_code(dev2, type, code)); } } libevdev_free(dev); libevdev_free(dev2); libevdev_uinput_destroy(uidev); close(fd); close(fd2); }
int power_key_resume_handler_init(void) { const char *node_path; char *full_path; GDir *input_dir; int rc = 1; struct libevdev *dev = NULL; input_dir = g_dir_open("/dev/input", 0, NULL); if (!input_dir) { g_warning("Failed to reach /dev/input directory"); return -ENODEV; } while ((node_path = g_dir_read_name(input_dir)) != NULL) { full_path = g_strdup_printf("/dev/input/%s", node_path); if (g_file_test(node_path, G_FILE_TEST_IS_DIR)) continue; input_source_fd = open(full_path, O_RDONLY|O_NONBLOCK); g_free(full_path); if (input_source_fd < 0) continue; rc = libevdev_new_from_fd(input_source_fd, &dev); if (rc < 0) { fprintf(stderr, "Failed to init libevdev (%s)\n", strerror(-rc)); close(input_source_fd); input_source_fd = -1; continue; } if (libevdev_has_event_code(dev, EV_KEY, KEY_POWER)) { libevdev_free(dev); break; } libevdev_free(dev); close(input_source_fd); input_source_fd = -1; } if (input_source_fd < 0) return -ENODEV; channel = g_io_channel_unix_new(input_source_fd); g_io_channel_set_encoding(channel, NULL, NULL); readwatch = g_io_add_watch(channel, G_IO_IN | G_IO_HUP | G_IO_NVAL, _handle_input_event, NULL); return 0; }
evdevDevice::evdevDevice(const std::string& devnode) : m_devfile(devnode) { // The device file will be read on one of the main threads, so we open in non-blocking mode. m_fd = open(devnode.c_str(), O_RDWR | O_NONBLOCK); int ret = libevdev_new_from_fd(m_fd, &m_dev); if (ret != 0) { // This useally fails because the device node isn't an evdev device, such as /dev/input/js0 m_initialized = false; close(m_fd); return; } m_name = StripSpaces(libevdev_get_name(m_dev)); // Controller buttons (and keyboard keys) int num_buttons = 0; for (int key = 0; key < KEY_MAX; key++) if (libevdev_has_event_code(m_dev, EV_KEY, key)) AddInput(new Button(num_buttons++, key, m_dev)); // Absolute axis (thumbsticks) int num_axis = 0; for (int axis = 0; axis < 0x100; axis++) if (libevdev_has_event_code(m_dev, EV_ABS, axis)) { AddAnalogInputs(new Axis(num_axis, axis, false, m_dev), new Axis(num_axis, axis, true, m_dev)); num_axis++; } // Force feedback if (libevdev_has_event_code(m_dev, EV_FF, FF_PERIODIC)) { for (auto type : {FF_SINE, FF_SQUARE, FF_TRIANGLE, FF_SAW_UP, FF_SAW_DOWN}) if (libevdev_has_event_code(m_dev, EV_FF, type)) AddOutput(new ForceFeedback(type, m_dev)); } if (libevdev_has_event_code(m_dev, EV_FF, FF_RUMBLE)) { AddOutput(new ForceFeedback(FF_RUMBLE, m_dev)); } // TODO: Add leds as output devices m_initialized = true; m_interesting = num_axis >= 2 || num_buttons >= 8; }
bool evdevDevice::IsValid() const { int current_fd = libevdev_get_fd(m_dev); if (current_fd == -1) return false; libevdev* device; if (libevdev_new_from_fd(current_fd, &device) != 0) { close(current_fd); return false; } libevdev_free(device); return true; }
void test_create_abs_device(struct uinput_device **uidev_return, struct libevdev **dev_return, int nabs, const struct input_absinfo *abs, ...) { int rc, fd; struct uinput_device *uidev; struct libevdev *dev; va_list args; uidev = uinput_device_new(TEST_DEVICE_NAME); ck_assert(uidev != NULL); va_start(args, abs); rc = uinput_device_set_event_bits_v(uidev, args); va_end(args); while (--nabs >= 0) { int code; struct input_absinfo a; code = abs[nabs].value; a = abs[nabs]; a.value = 0; rc = uinput_device_set_abs_bit(uidev, code, &a); ck_assert_msg(rc == 0, "for abs field %d\n", nabs); } rc = uinput_device_create(uidev); ck_assert_msg(rc == 0, "Failed to create uinput device: %s", strerror(-rc)); fd = uinput_device_get_fd(uidev); rc = libevdev_new_from_fd(fd, &dev); ck_assert_msg(rc == 0, "Failed to init device device: %s", strerror(-rc)); rc = fcntl(fd, F_SETFL, O_NONBLOCK); ck_assert_msg(rc == 0, "fcntl failed: %s", strerror(errno)); *uidev_return = uidev; *dev_return = dev; }
END_TEST START_TEST(test_uinput_properties) { struct libevdev *dev, *dev2; struct libevdev_uinput *uidev; int fd; int rc; const char *devnode; dev = libevdev_new(); ck_assert(dev != NULL); libevdev_set_name(dev, TEST_DEVICE_NAME); libevdev_enable_event_type(dev, EV_SYN); libevdev_enable_event_type(dev, EV_REL); libevdev_enable_event_type(dev, EV_KEY); libevdev_enable_event_code(dev, EV_REL, REL_X, NULL); libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL); libevdev_enable_event_code(dev, EV_KEY, BTN_LEFT, NULL); libevdev_enable_property(dev, INPUT_PROP_BUTTONPAD); libevdev_enable_property(dev, INPUT_PROP_MAX); rc = libevdev_uinput_create_from_device(dev, LIBEVDEV_UINPUT_OPEN_MANAGED, &uidev); ck_assert_int_eq(rc, 0); ck_assert(uidev != NULL); devnode = libevdev_uinput_get_devnode(uidev); ck_assert(devnode != NULL); fd = open(devnode, O_RDONLY); ck_assert_int_gt(fd, -1); rc = libevdev_new_from_fd(fd, &dev2); ck_assert_int_eq(rc, 0); ck_assert(libevdev_has_property(dev2, INPUT_PROP_BUTTONPAD)); ck_assert(libevdev_has_property(dev2, INPUT_PROP_MAX)); libevdev_free(dev); libevdev_free(dev2); libevdev_uinput_destroy(uidev); close(fd); }
int main(int argc, char **argv) { struct libevdev *dev = NULL; struct libevdev_uinput *uidev = NULL; int fd, ret; if (argc < 2){ fprintf(stderr, "Usage: %s <event device>\n", argv[0]); return 1; } //open the event device file descriptor fd = open(argv[1], O_RDONLY); if (fd < 0) {perror("Failed to open device"); return fd;} //create a libevdev device from the event file descriptor ret = libevdev_new_from_fd(fd, &dev); if (ret < 0) {perror("Failed to create libevdev device"); return ret;} //create a device connected to the virtual device interface /dev/uinput ret = libevdev_uinput_create_from_device( dev, LIBEVDEV_UINPUT_OPEN_MANAGED, &uidev); if (ret < 0) {perror("Failed to create uinput device"); return ret;} sleep(1); //EVIOCGRAB the event, this means no other client will receive the events from the device, including your window manager. // "This is generally a bad idea. Don't do this." - libevdev documentation //We need to do this to avoid douplicate keyboard events. ret = libevdev_grab(dev, LIBEVDEV_GRAB); //start the interceptor and never return intercept(uidev, dev); libevdev_uinput_destroy(uidev); libevdev_grab(dev, LIBEVDEV_UNGRAB); libevdev_free(dev); return ret; }
int main(int argc, char **argv) { struct libevdev *dev = NULL; int fd = -1; int rc = EXIT_FAILURE; enum mode mode; const char *path; struct input_absinfo absinfo; int axis = -1; int led = -1; int led_state = -1; unsigned int changes = 0; /* bitmask of changes */ int xres = 0, yres = 0; mode = parse_options_mode(argc, argv); switch (mode) { case MODE_HELP: rc = EXIT_SUCCESS; /* fallthrough */ case MODE_NONE: usage(); goto out; case MODE_ABS: rc = parse_options_abs(argc, argv, &changes, &axis, &absinfo); break; case MODE_LED: rc = parse_options_led(argc, argv, &led, &led_state); break; case MODE_RESOLUTION: rc = parse_options_resolution(argc, argv, &xres, &yres); break; default: fprintf(stderr, "++?????++ Out of Cheese Error. Redo From Start.\n"); goto out; } if (rc != EXIT_SUCCESS) goto out; if (optind >= argc) { rc = EXIT_FAILURE; usage(); goto out; } path = argv[optind]; fd = open(path, O_RDWR); if (fd < 0) { rc = EXIT_FAILURE; perror("Failed to open device"); goto out; } rc = libevdev_new_from_fd(fd, &dev); if (rc < 0) { fprintf(stderr, "Failed to init libevdev (%s)\n", strerror(-rc)); goto out; } switch (mode) { case MODE_ABS: set_abs(dev, changes, axis, &absinfo); break; case MODE_LED: set_led(dev, led, led_state); break; case MODE_RESOLUTION: set_resolution(dev, xres, yres); break; default: break; } out: libevdev_free(dev); if (fd != -1) close(fd); return rc; }
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; }
static int consider_device(const char* devpath, internal_state_t* state) { int fd = -1; struct libevdev* evdev = NULL; if (!is_character_device(devpath)) { goto mismatch; } if ((fd = open(devpath, O_RDWR)) < 0) { perror("open"); fprintf(stderr, "Unable to open device %s for inspection", devpath); goto mismatch; } if (libevdev_new_from_fd(fd, &evdev) < 0) { fprintf(stderr, "Note: device %s is not supported by libevdev\n", devpath); goto mismatch; } if (!is_multitouch_device(evdev)) { goto mismatch; } int score = 10000; if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_TOOL_TYPE)) { int tool_min = libevdev_get_abs_minimum(evdev, ABS_MT_TOOL_TYPE); int tool_max = libevdev_get_abs_maximum(evdev, ABS_MT_TOOL_TYPE); if (tool_min > MT_TOOL_FINGER || tool_max < MT_TOOL_FINGER) { fprintf(stderr, "Note: device %s is a touch device, but doesn't" " support fingers\n", devpath); goto mismatch; } score -= tool_max - MT_TOOL_FINGER; } if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_SLOT)) { score += 1000; // Some devices, e.g. Blackberry PRIV (STV100) have more than one surface // you can touch. On the PRIV, the keypad also acts as a touch screen // that you can swipe and scroll with. The only differences between the // touch devices are that one is named "touch_display" and the other // "touch_keypad", the keypad only supports 3 contacts and the display // up to 9, and the keypad has a much lower resolution. Therefore // increasing the score by the number of contacts should be a relatively // safe bet, though we may also want to decrease the score by, say, 1, // if the device name contains "key" just in case they decide to start // supporting more contacts on both touch surfaces in the future. int num_slots = libevdev_get_abs_maximum(evdev, ABS_MT_SLOT); score += num_slots; } // For Blackberry devices, see above. const char* name = libevdev_get_name(evdev); if (strstr(name, "key") != NULL) { score -= 1; } // Alcatel OneTouch Idol 3 has an `input_mt_wrapper` device in addition // to direct input. It seems to be related to accessibility, as it shows // a touchpoint that you can move around, and then tap to activate whatever // is under the point. That wrapper device lacks the direct property. if (libevdev_has_property(evdev, INPUT_PROP_DIRECT)) { score += 10000; } // Some devices may have an additional screen. For example, Meizu Pro7 Plus // has a small screen on the back side of the device called sub_touch, while // the boring screen in the front is called main_touch. The resolution on // the sub_touch device is much much lower. It seems like a safe bet // to always prefer the larger device, as long as the score adjustment is // likely to be lower than the adjustment we do for INPUT_PROP_DIRECT. if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X)) { int x = libevdev_get_abs_maximum(evdev, ABS_MT_POSITION_X); int y = libevdev_get_abs_maximum(evdev, ABS_MT_POSITION_Y); score += sqrt(x * y); } if (state->evdev != NULL) { if (state->score >= score) { fprintf(stderr, "Note: device %s was outscored by %s (%d >= %d)\n", devpath, state->path, state->score, score); goto mismatch; } else { fprintf(stderr, "Note: device %s was outscored by %s (%d >= %d)\n", state->path, devpath, score, state->score); } } libevdev_free(state->evdev); state->fd = fd; state->score = score; strncpy(state->path, devpath, sizeof(state->path)); state->evdev = evdev; return 1; mismatch: libevdev_free(evdev); if (fd >= 0) { close(fd); } return 0; }