/***************************************************************************** * * evemu - Kernel device emulation * * Copyright (C) 2010-2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3 as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Copyright (C) 2010 Henrik Rydberg * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * ****************************************************************************/ #define _GNU_SOURCE #include "evemu.h" #include #include #include #include #include #include #include #include "find_event_devices.h" #define INFINITE -1 FILE *output; static int describe_device(int fd) { struct evemu_device *dev; int ret = -ENOMEM; dev = evemu_new(NULL); if (!dev) goto out; ret = evemu_extract(dev, fd); if (ret) goto out; evemu_write(dev, stdout); out: evemu_delete(dev); return ret; } static void handler (int sig __attribute__((unused))) { fflush(output); if (output != stdout) { fclose(output); output = stdout; } } enum mode { EVEMU_RECORD, EVEMU_DESCRIBE }; int main(int argc, char *argv[]) { enum mode mode = EVEMU_RECORD; int fd; struct sigaction act; char *prgm_name = program_invocation_short_name; char *device; if (prgm_name && (strcmp(prgm_name, "evemu-describe") == 0 || /* when run directly from the sources (not installed) */ strcmp(prgm_name, "lt-evemu-describe") == 0)) mode = EVEMU_DESCRIBE; device = (argc < 2) ? find_event_devices() : strdup(argv[1]); if (device == NULL) { fprintf(stderr, "Usage: %s [output file]\n", argv[0]); return -1; } fd = open(device, O_RDONLY | O_NONBLOCK); if (fd < 0) { fprintf(stderr, "error: could not open device\n"); return -1; } memset (&act, '\0', sizeof(act)); act.sa_handler = &handler; if (sigaction(SIGTERM, &act, NULL) < 0) { fprintf (stderr, "Could not attach TERM signal handler.\n"); return 1; } if (sigaction(SIGINT, &act, NULL) < 0) { fprintf (stderr, "Could not attach INT signal handler.\n"); return 1; } if (argc < 3) output = stdout; else { output = fopen(argv[2], "w"); if (!output) { fprintf(stderr, "error: could not open output file"); } } if (describe_device(fd)) { fprintf(stderr, "error: could not describe device\n"); goto out; } if (mode == EVEMU_RECORD) { #ifdef EVIOCSCLOCKID int clockid = CLOCK_MONOTONIC; ioctl(fd, EVIOCSCLOCKID, &clockid); #endif if (ioctl(fd, EVIOCGRAB, (void*)1) < 0) { fprintf(stderr, "error: this device is grabbed and I cannot record events\n"); fprintf(stderr, "see the evemu-record man page for more information\n"); return -1; } else ioctl(fd, EVIOCGRAB, (void*)0); fprintf(output, "################################\n"); fprintf(output, "# Waiting for events #\n"); fprintf(output, "################################\n"); if (evemu_record(output, fd, INFINITE)) fprintf(stderr, "error: could not describe device\n"); } out: free(device); close(fd); if (output != stdout) { fclose(output); output = stdout; } return 0; }