示例#1
0
static int
keyboard_new(struct dirent *ent, struct xkb_keymap *keymap,
             struct keyboard **out)
{
    int ret;
    char *path;
    int fd;
    struct xkb_state *state;
    struct keyboard *kbd;

    ret = asprintf(&path, "/dev/input/%s", ent->d_name);
    if (ret < 0)
        return -ENOMEM;

    fd = open(path, O_NONBLOCK | O_CLOEXEC | O_RDONLY);
    if (fd < 0) {
        ret = -errno;
        goto err_path;
    }

    if (!is_keyboard(fd)) {
        /* Dummy "skip this device" value. */
        ret = -ENOTSUP;
        goto err_fd;
    }

    state = xkb_state_new(keymap);
    if (!state) {
        fprintf(stderr, "Couldn't create xkb state for %s\n", path);
        ret = -EFAULT;
        goto err_fd;
    }

    kbd = calloc(1, sizeof(*kbd));
    if (!kbd) {
        ret = -ENOMEM;
        goto err_state;
    }

    kbd->path = path;
    kbd->fd = fd;
    kbd->state = state;
    *out = kbd;
    return 0;

err_state:
    xkb_state_unref(state);
err_fd:
    close(fd);
err_path:
    free(path);
    return ret;
}
示例#2
0
int main(int argc, char **argv)
{
	struct option long_options[] = {
		{"keyboard", required_argument, NULL, 'k'},
		{"mouse", required_argument, NULL, 'm'},
		{"help", no_argument, NULL, 'h'},
	};
	char *keyboard_cmd = NULL;
	char *mouse_cmd = NULL;
	struct udev *udev;
	struct udev_monitor *monitor;
	struct pollfd pollfd;
	int status = EXIT_FAILURE;
	int ret;

	if (argc > 0)
		progname = argv[0];

	for (;;) {
		int c;

		c = getopt_long(argc, argv, "kmh", long_options, NULL);
		if (c == -1)
			break;

		switch (c) {
		case 'k':
			keyboard_cmd = strdup(optarg);
			if (!keyboard_cmd) {
				perror("strdup");
				goto out;
			}
			break;
		case 'm':
			mouse_cmd = strdup(optarg);
			if (!mouse_cmd) {
				perror("strdup");
				goto out;
			}
			break;
		case 'h':
			free(keyboard_cmd);
			free(mouse_cmd);
			usage(false);
		default:
			free(keyboard_cmd);
			free(mouse_cmd);
			usage(true);
		}
	}
	if (optind != argc || (!keyboard_cmd && !mouse_cmd))
		usage(true);

	if (keyboard_cmd)
		run_cmd(keyboard_cmd, "keyboard");
	if (mouse_cmd)
		run_cmd(mouse_cmd, "mouse");

	udev = udev_new();
	if (!udev) {
		fprintf(stderr, "failed to allocate a new udev context\n");
		goto out;
	}

	monitor = udev_monitor_new_from_netlink(udev, "udev");
	if (!monitor) {
		fprintf(stderr, "failed to allocate udev monitor\n");
		goto out_udev;
	}

	ret = udev_monitor_filter_add_match_subsystem_devtype(monitor, "input", NULL);
	if (ret != 0) {
		fprintf(stderr, "failed to add udev subsystem filter\n");
		goto out_udev_monitor;
	}

	ret = udev_monitor_enable_receiving(monitor);
	if (ret != 0) {
		fprintf(stderr, "failed to enable udev monitor\n");
		goto out_udev_monitor;
	}

	pollfd.fd = udev_monitor_get_fd(monitor);
	pollfd.events = POLLIN;
	for (;;) {
		struct udev_device *device;
		bool run_keyboard = false;
		bool run_mouse = false;

		pollfd.revents = 0;
		ret = poll(&pollfd, 1, -1);
		if (ret == -1) {
			perror("poll");
			goto out_udev_monitor;
		}

		if (!(pollfd.revents & POLLIN))
			continue;

		while ((device = udev_monitor_receive_device(monitor))) {
			if (strcmp(udev_device_get_action(device), "add") == 0) {
				if (is_keyboard(device))
					run_keyboard = true;
				if (is_mouse(device))
					run_mouse = true;
			}
			udev_device_unref(device);
		}

		if (run_keyboard && keyboard_cmd)
			run_cmd(keyboard_cmd, "keyboard");
		if (run_mouse && mouse_cmd)
			run_cmd(mouse_cmd, "mouse");
	}

	status = EXIT_SUCCESS;
out_udev_monitor:
	udev_monitor_unref(monitor);
out_udev:
	udev_unref(udev);
out:
	free(keyboard_cmd);
	free(mouse_cmd);
	return status;
}
示例#3
0
int main()
{
    struct termios old_term, new_term;
    int kb = -1; /* keyboard file descriptor */
    char *files_to_try[] = {"/dev/tty", "/dev/console", NULL};
    int old_mode = -1;
    int i;

    /* First we need to find a file descriptor that represents the
       system's keyboard. This should be /dev/tty, /dev/console, stdin,
       stdout, or stderr. We'll try them in that order. If none are
       acceptable, we're probably not being run from a VT. */
    for (i = 0; files_to_try[i] != NULL; i++) {

	/* Try to open the file. */
	kb = open(files_to_try[i], O_RDONLY);
	if (kb < 0) continue;

	/* See if this is valid for our purposes. */
	if (is_keyboard(kb)) {
	    printf("Using keyboard on %s.\n", files_to_try[i]);
	    break;
	}
		
	close(kb);
    }

    /* If those didn't work, not all is lost. We can try the 3 standard
       file descriptors, in hopes that one of them might point to a
       console. This is not especially likely. */
    if (files_to_try[i] == NULL) {
		
	for (kb = 0; kb < 3; kb++) {
	    if (is_keyboard(i)) break;
	}

	printf("Unable to find a file descriptor associated with the "\
	       "keyboard.\n" \
	       "Perhaps you're not using a virtual terminal?\n");
	return 1;

    }

    /* Find the keyboard's current mode so we can restore it later. */
    if (ioctl(kb, KDGKBMODE, &old_mode) != 0) {
	printf("Unable to query keyboard mode.\n");
	goto error;
    }

    /* Adjust the terminal's settings. In particular, disable echoing,
       signal generation, and line buffering. Any of these could cause
       trouble. Save the old settings first. */
    if (tcgetattr(kb, &old_term) != 0) {
	printf("Unable to query terminal settings.\n");
	goto error;
    }

    new_term = old_term;
    new_term.c_iflag = 0;
    new_term.c_lflag &= ~(ECHO | ICANON | ISIG);

    /* TCSAFLUSH discards unread input before making the change.
       A good idea. */
    if (tcsetattr(kb, TCSAFLUSH, &new_term) != 0) {
	printf("Unable to change terminal settings.\n");
    }

    /* Put the keyboard in mediumraw mode. */
    if (ioctl(kb, KDSKBMODE, K_MEDIUMRAW) != 0) {
	printf("Unable to set mediumraw mode.\n");
	goto error;
    }

    printf("Reading keycodes. Press Escape (keycode 1) to exit.\n");

    for (;;) {
	unsigned char data;

	if (read(kb, &data, 1) < 1) {
	    printf("Unable to read data. Trying to exit nicely.\n");
	    goto error;
	}

	/* Print the keycode. The top bit is the pressed/released flag,
	   and the lower seven are the keycode. */
	printf("%s: %2Xh (%i)\n",
	       (data & 0x80) ? "Released" : " Pressed",
	       (unsigned int)data & 0x7F,
	       (unsigned int)data & 0x7F);

	if ((data & 0x7F) == 1) {
	    printf("Escape pressed.\n");
	    break;
	}
    }

    /* Shut down nicely. */
    printf("Exiting normally.\n");

    ioctl(kb, KDSKBMODE, old_mode);
    tcsetattr(kb, 0, &old_term);

    if (kb > 3)
	close(kb);

    return 0;

 error:
    printf("Cleaning up.\n");
    fflush(stdout);

    /* Restore the previous mode. Users hate it when they can't
       use the keyboard. */
    if (old_mode != -1) {
	ioctl(kb, KDSKBMODE, old_mode);
	tcsetattr(kb, 0, &old_term);
    }

    /* Only bother closing the keyboard fd if it's not stdin, stdout,
       or stderr. */
    if (kb > 3)
	close(kb);
		
    return 1;
}