/* * tegra_gte_mon - monitor GPIO line events from userspace and hardware * timestamp. * * Copyright (C) 2020 Dipen Patel * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. * * Example Usage: * tegra_gte_mon -d -g -r -f */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include int monitor_device(const char *device_name, unsigned int gnum, unsigned int eventflags, unsigned int loops) { struct tegra_gte_hts_event_req req = {0}; struct tegra_gte_hts_event_data event; char *chrdev_name; int fd; int ret; int i = 0; ret = asprintf(&chrdev_name, "/dev/%s", device_name); if (ret < 0) return -ENOMEM; fd = open(chrdev_name, 0); if (fd == -1) { ret = -errno; perror("Error: "); goto exit_close_error; } req.global_gpio_pin = gnum; req.eventflags = eventflags; ret = ioctl(fd, TEGRA_GTE_HTS_CREATE_GPIO_EV_IOCTL, &req); if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue GET EVENT " "IOCTL (%d)\n", ret); goto exit_close_error; } fprintf(stdout, "Monitoring line %d on %s\n", gnum, device_name); while (1) { ret = read(req.fd, &event, sizeof(event)); if (ret == -1) { if (errno == -EAGAIN) { fprintf(stderr, "nothing available\n"); continue; } else { ret = -errno; fprintf(stderr, "Failed to read event (%d)\n", ret); break; } } if (ret != sizeof(event)) { fprintf(stderr, "Reading event failed\n"); ret = -EIO; break; } fprintf(stdout, "HW timestamp GPIO EVENT %" PRIu64 "\n", event.timestamp); i++; if (i == loops) break; } exit_close_error: if (close(fd) == -1) perror("Failed to close GPIO character device file"); free(chrdev_name); return ret; } void print_usage(char *bin_name) { fprintf(stderr, "Usage: %s [options]...\n" "Listen to events on GPIO lines, 0->1 1->0\n" " -d Listen using named HW ts engine device\n" " -g GPIO global id\n" " -r Listen for rising edges\n" " -f Listen for falling edges\n" " [-c ] Do loops (optional, infinite loop if not stated)\n" " -h This helptext\n" "\n" "Example:\n" "%s -d gtechip0 -g 257 -r -f\n" "(means GPIO 257 rising and falling edge monitoring)\n", bin_name, bin_name ); } int main(int argc, char **argv) { const char *device_name = NULL; unsigned int gnum = -1; unsigned int loops = 0; unsigned int eventflags = 0; int c; while ((c = getopt(argc, argv, "c:g:d:rfh")) != -1) { switch (c) { case 'c': loops = strtoul(optarg, NULL, 10); break; case 'd': device_name = optarg; break; case 'g': gnum = strtoul(optarg, NULL, 10); break; case 'r': eventflags |= TEGRA_GTE_EVENT_RISING_EDGE; break; case 'f': eventflags |= TEGRA_GTE_EVENT_FALLING_EDGE; break; case 'h': print_usage(argv[0]); return 1; } } if (!device_name || gnum == -1) { print_usage(argv[0]); return 1; } if (!eventflags) { printf("No flags specified, listening on both rising and " "falling edges\n"); eventflags = TEGRA_GTE_EVENT_REQ_BOTH_EDGES; } return monitor_device(device_name, gnum, eventflags, loops); }