// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2001 Arndt Schoenewald * Copyright (c) 2000-2001 Vojtech Pavlik * Copyright (c) 2000 Mark Fletcher * * Sponsored by Quelltext AG (http://www.quelltext-ag.de), Dortmund, Germany */ /* * Driver to use Handykey's Twiddler (the first edition, i.e. the one with * the RS232 interface) as a joystick under Linux * * The Twiddler is a one-handed chording keyboard featuring twelve buttons on * the front, six buttons on the top, and a built-in tilt sensor. The buttons * on the front, which are grouped as four rows of three buttons, are pressed * by the four fingers (this implies only one button per row can be held down * at the same time) and the buttons on the top are for the thumb. The tilt * sensor delivers X and Y axis data depending on how the Twiddler is held. * Additional information can be found at http://www.handykey.com. * * This driver does not use the Twiddler for its intended purpose, i.e. as * a chording keyboard, but as a joystick: pressing and releasing a button * immediately sends a corresponding button event, and tilting it generates * corresponding ABS_X and ABS_Y events. This turns the Twiddler into a game * controller with amazing 18 buttons :-) * * Note: The Twiddler2 (the successor of the Twiddler that connects directly * to the PS/2 keyboard and mouse ports) is NOT supported by this driver! * * For questions or feedback regarding this driver module please contact: * Arndt Schoenewald <[email protected]> */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> #define DRIVER_DESC … MODULE_DESCRIPTION(…); MODULE_LICENSE(…) …; /* * Constants. */ #define TWIDJOY_MAX_LENGTH … static struct twidjoy_button_spec { … } twidjoy_buttons[] = …; /* * Per-Twiddler data. */ struct twidjoy { … }; /* * twidjoy_process_packet() decodes packets the driver receives from the * Twiddler. It updates the data accordingly. */ static void twidjoy_process_packet(struct twidjoy *twidjoy) { … } /* * twidjoy_interrupt() is called by the low level driver when characters * are ready for us. We then buffer them for further processing, or call the * packet processing routine. */ static irqreturn_t twidjoy_interrupt(struct serio *serio, unsigned char data, unsigned int flags) { … } /* * twidjoy_disconnect() is the opposite of twidjoy_connect() */ static void twidjoy_disconnect(struct serio *serio) { … } /* * twidjoy_connect() is the routine that is called when someone adds a * new serio device. It looks for the Twiddler, and if found, registers * it as an input device. */ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv) { … } /* * The serio driver structure. */ static const struct serio_device_id twidjoy_serio_ids[] = …; MODULE_DEVICE_TABLE(serio, twidjoy_serio_ids); static struct serio_driver twidjoy_drv = …; module_serio_driver(…) …;