#include #include #include #include #include #include #include #ifndef GPIO #define GPIO 4 #endif #define STRINGIFY(a) #a #define STRINGIFY_HARDER(a) STRINGIFY(a) #define GPIO_STR STRINGIFY_HARDER(GPIO) char *names[KEY_MAX + 1] = { "", "", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=", "", "\t", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "[", "]", "", "", "a", "s", "d", "f", "g", "h", "j", "k", "l", ";", "'", "`", "", "\\", "z", "x", "c", "v", "b", "n", "m", ",", ".", "/" }; static char * strcasestr (const char *haystack, const char *needle) { size_t len = strlen (needle); for (; *haystack; haystack++) { if (!strncasecmp (haystack, needle, len)) return (char *) haystack; } return NULL; } static int squirt (const char *fn, const char *content) { size_t len = strlen (content); int fd = open (fn, O_WRONLY); int ret = -1; if (fd < 0) return ret; if (write (fd, content, len) == len) ret = 0; close (fd); return ret; } int open_ykhid (void) { #define MAX_DEV 64 char name[128]; unsigned i; int fd; for (i = 0; i < MAX_DEV; ++i) { sprintf (name, "/dev/input/event%d", i); fd = open (name, O_RDWR); if (fd < 0) continue; ioctl (fd, EVIOCGNAME (sizeof (name)), name); name[sizeof (name) - 1] = 0; if (strcasestr (name, "yubikey")) return fd; close (fd); } return -1; } static int get_string_with_timeout (int fd, struct timeval *tv, char *buf, size_t buf_len) { fd_set rfds; struct input_event ev; if (buf_len) buf_len--; FD_ZERO (&rfds); for (;;) { FD_SET (fd, &rfds); if (select (fd + 1, &rfds, NULL, NULL, tv) < 1) break; if (read (fd, &ev, sizeof (struct input_event)) != sizeof (struct input_event)) continue; if (ev.type != EV_KEY) continue; if (buf_len && ev.code == KEY_ENTER && !ev.value) return 0; if (!ev.value) continue; // printf("code %d (%s)\n",ev.code,names[ev.code]); if (buf_len && names[ev.code][0]) { *(buf++) = names[ev.code][0]; *buf = 0; buf_len--; } } return -1; } int main (int argc, char *argv[]) { int fd = open_ykhid (); struct timeval tv; char ret[128]; squirt ("/sys/class/gpio/export", GPIO_STR); squirt ("/sys/class/gpio/gpio" GPIO_STR "/direction", "out"); squirt ("/sys/class/gpio/gpio" GPIO_STR "/value", "0"); tv.tv_sec = 0; tv.tv_usec = 100; get_string_with_timeout (fd, &tv, NULL, 0); squirt ("/sys/class/gpio/gpio" GPIO_STR "/value", "1"); tv.tv_sec = 2; tv.tv_usec = 0; get_string_with_timeout (fd, &tv, ret, sizeof (ret)); squirt ("/sys/class/gpio/gpio" GPIO_STR "/value", "0"); printf ("Access-Control-Allow-Origin: *\n"); printf ("Content-Type: text/plain\n\n%s\n", ret); return 0; }