18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 1996-2001 Vojtech Pavlik 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci/* 78c2ecf20Sopenharmony_ci * This is just a very simple driver that can dump the data 88c2ecf20Sopenharmony_ci * out of the joystick port into the syslog ... 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci/* 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/module.h> 158c2ecf20Sopenharmony_ci#include <linux/gameport.h> 168c2ecf20Sopenharmony_ci#include <linux/kernel.h> 178c2ecf20Sopenharmony_ci#include <linux/delay.h> 188c2ecf20Sopenharmony_ci#include <linux/slab.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#define DRIVER_DESC "Gameport data dumper module" 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ciMODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 238c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(DRIVER_DESC); 248c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define BUF_SIZE 256 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistruct joydump { 298c2ecf20Sopenharmony_ci unsigned int time; 308c2ecf20Sopenharmony_ci unsigned char data; 318c2ecf20Sopenharmony_ci}; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic int joydump_connect(struct gameport *gameport, struct gameport_driver *drv) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci struct joydump *buf; /* all entries */ 368c2ecf20Sopenharmony_ci struct joydump *dump, *prev; /* one entry each */ 378c2ecf20Sopenharmony_ci int axes[4], buttons; 388c2ecf20Sopenharmony_ci int i, j, t, timeout; 398c2ecf20Sopenharmony_ci unsigned long flags; 408c2ecf20Sopenharmony_ci unsigned char u; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci printk(KERN_INFO "joydump: ,------------------ START ----------------.\n"); 438c2ecf20Sopenharmony_ci printk(KERN_INFO "joydump: | Dumping: %30s |\n", gameport->phys); 448c2ecf20Sopenharmony_ci printk(KERN_INFO "joydump: | Speed: %28d kHz |\n", gameport->speed); 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW)) { 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci printk(KERN_INFO "joydump: | Raw mode not available - trying cooked. |\n"); 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci if (gameport_open(gameport, drv, GAMEPORT_MODE_COOKED)) { 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci printk(KERN_INFO "joydump: | Cooked not available either. Failing. |\n"); 538c2ecf20Sopenharmony_ci printk(KERN_INFO "joydump: `------------------- END -----------------'\n"); 548c2ecf20Sopenharmony_ci return -ENODEV; 558c2ecf20Sopenharmony_ci } 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci gameport_cooked_read(gameport, axes, &buttons); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 608c2ecf20Sopenharmony_ci printk(KERN_INFO "joydump: | Axis %d: %4d. |\n", i, axes[i]); 618c2ecf20Sopenharmony_ci printk(KERN_INFO "joydump: | Buttons %02x. |\n", buttons); 628c2ecf20Sopenharmony_ci printk(KERN_INFO "joydump: `------------------- END -----------------'\n"); 638c2ecf20Sopenharmony_ci } 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci timeout = gameport_time(gameport, 10000); /* 10 ms */ 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci buf = kmalloc_array(BUF_SIZE, sizeof(struct joydump), GFP_KERNEL); 688c2ecf20Sopenharmony_ci if (!buf) { 698c2ecf20Sopenharmony_ci printk(KERN_INFO "joydump: no memory for testing\n"); 708c2ecf20Sopenharmony_ci goto jd_end; 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci dump = buf; 738c2ecf20Sopenharmony_ci t = 0; 748c2ecf20Sopenharmony_ci i = 1; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci local_irq_save(flags); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci u = gameport_read(gameport); 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci dump->data = u; 818c2ecf20Sopenharmony_ci dump->time = t; 828c2ecf20Sopenharmony_ci dump++; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci gameport_trigger(gameport); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci while (i < BUF_SIZE && t < timeout) { 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci dump->data = gameport_read(gameport); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci if (dump->data ^ u) { 918c2ecf20Sopenharmony_ci u = dump->data; 928c2ecf20Sopenharmony_ci dump->time = t; 938c2ecf20Sopenharmony_ci i++; 948c2ecf20Sopenharmony_ci dump++; 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci t++; 978c2ecf20Sopenharmony_ci } 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci local_irq_restore(flags); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci/* 1028c2ecf20Sopenharmony_ci * Dump data. 1038c2ecf20Sopenharmony_ci */ 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci t = i; 1068c2ecf20Sopenharmony_ci dump = buf; 1078c2ecf20Sopenharmony_ci prev = dump; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci printk(KERN_INFO "joydump: >------------------ DATA -----------------<\n"); 1108c2ecf20Sopenharmony_ci printk(KERN_INFO "joydump: | index: %3d delta: %3d us data: ", 0, 0); 1118c2ecf20Sopenharmony_ci for (j = 7; j >= 0; j--) 1128c2ecf20Sopenharmony_ci printk("%d", (dump->data >> j) & 1); 1138c2ecf20Sopenharmony_ci printk(" |\n"); 1148c2ecf20Sopenharmony_ci dump++; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci for (i = 1; i < t; i++, dump++, prev++) { 1178c2ecf20Sopenharmony_ci printk(KERN_INFO "joydump: | index: %3d delta: %3d us data: ", 1188c2ecf20Sopenharmony_ci i, dump->time - prev->time); 1198c2ecf20Sopenharmony_ci for (j = 7; j >= 0; j--) 1208c2ecf20Sopenharmony_ci printk("%d", (dump->data >> j) & 1); 1218c2ecf20Sopenharmony_ci printk(" |\n"); 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci kfree(buf); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cijd_end: 1268c2ecf20Sopenharmony_ci printk(KERN_INFO "joydump: `------------------- END -----------------'\n"); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci return 0; 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistatic void joydump_disconnect(struct gameport *gameport) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci gameport_close(gameport); 1348c2ecf20Sopenharmony_ci} 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic struct gameport_driver joydump_drv = { 1378c2ecf20Sopenharmony_ci .driver = { 1388c2ecf20Sopenharmony_ci .name = "joydump", 1398c2ecf20Sopenharmony_ci }, 1408c2ecf20Sopenharmony_ci .description = DRIVER_DESC, 1418c2ecf20Sopenharmony_ci .connect = joydump_connect, 1428c2ecf20Sopenharmony_ci .disconnect = joydump_disconnect, 1438c2ecf20Sopenharmony_ci}; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cimodule_gameport_driver(joydump_drv); 146