1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 1996-2001 Vojtech Pavlik 4 */ 5 6 /* 7 * This is just a very simple driver that can dump the data 8 * out of the joystick port into the syslog ... 9 */ 10 11 /* 12 */ 13 14 #include <linux/module.h> 15 #include <linux/gameport.h> 16 #include <linux/kernel.h> 17 #include <linux/delay.h> 18 #include <linux/slab.h> 19 20 #define DRIVER_DESC "Gameport data dumper module" 21 22 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 23 MODULE_DESCRIPTION(DRIVER_DESC); 24 MODULE_LICENSE("GPL"); 25 26 #define BUF_SIZE 256 27 28 struct joydump { 29 unsigned int time; 30 unsigned char data; 31 }; 32 33 static int joydump_connect(struct gameport *gameport, struct gameport_driver *drv) 34 { 35 struct joydump *buf; /* all entries */ 36 struct joydump *dump, *prev; /* one entry each */ 37 int axes[4], buttons; 38 int i, j, t, timeout; 39 unsigned long flags; 40 unsigned char u; 41 42 printk(KERN_INFO "joydump: ,------------------ START ----------------.\n"); 43 printk(KERN_INFO "joydump: | Dumping: %30s |\n", gameport->phys); 44 printk(KERN_INFO "joydump: | Speed: %28d kHz |\n", gameport->speed); 45 46 if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW)) { 47 48 printk(KERN_INFO "joydump: | Raw mode not available - trying cooked. |\n"); 49 50 if (gameport_open(gameport, drv, GAMEPORT_MODE_COOKED)) { 51 52 printk(KERN_INFO "joydump: | Cooked not available either. Failing. |\n"); 53 printk(KERN_INFO "joydump: `------------------- END -----------------'\n"); 54 return -ENODEV; 55 } 56 57 gameport_cooked_read(gameport, axes, &buttons); 58 59 for (i = 0; i < 4; i++) 60 printk(KERN_INFO "joydump: | Axis %d: %4d. |\n", i, axes[i]); 61 printk(KERN_INFO "joydump: | Buttons %02x. |\n", buttons); 62 printk(KERN_INFO "joydump: `------------------- END -----------------'\n"); 63 } 64 65 timeout = gameport_time(gameport, 10000); /* 10 ms */ 66 67 buf = kmalloc_array(BUF_SIZE, sizeof(struct joydump), GFP_KERNEL); 68 if (!buf) { 69 printk(KERN_INFO "joydump: no memory for testing\n"); 70 goto jd_end; 71 } 72 dump = buf; 73 t = 0; 74 i = 1; 75 76 local_irq_save(flags); 77 78 u = gameport_read(gameport); 79 80 dump->data = u; 81 dump->time = t; 82 dump++; 83 84 gameport_trigger(gameport); 85 86 while (i < BUF_SIZE && t < timeout) { 87 88 dump->data = gameport_read(gameport); 89 90 if (dump->data ^ u) { 91 u = dump->data; 92 dump->time = t; 93 i++; 94 dump++; 95 } 96 t++; 97 } 98 99 local_irq_restore(flags); 100 101 /* 102 * Dump data. 103 */ 104 105 t = i; 106 dump = buf; 107 prev = dump; 108 109 printk(KERN_INFO "joydump: >------------------ DATA -----------------<\n"); 110 printk(KERN_INFO "joydump: | index: %3d delta: %3d us data: ", 0, 0); 111 for (j = 7; j >= 0; j--) 112 printk("%d", (dump->data >> j) & 1); 113 printk(" |\n"); 114 dump++; 115 116 for (i = 1; i < t; i++, dump++, prev++) { 117 printk(KERN_INFO "joydump: | index: %3d delta: %3d us data: ", 118 i, dump->time - prev->time); 119 for (j = 7; j >= 0; j--) 120 printk("%d", (dump->data >> j) & 1); 121 printk(" |\n"); 122 } 123 kfree(buf); 124 125 jd_end: 126 printk(KERN_INFO "joydump: `------------------- END -----------------'\n"); 127 128 return 0; 129 } 130 131 static void joydump_disconnect(struct gameport *gameport) 132 { 133 gameport_close(gameport); 134 } 135 136 static struct gameport_driver joydump_drv = { 137 .driver = { 138 .name = "joydump", 139 }, 140 .description = DRIVER_DESC, 141 .connect = joydump_connect, 142 .disconnect = joydump_disconnect, 143 }; 144 145 module_gameport_driver(joydump_drv); 146