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