cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

grip_mp.c (17059B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  Driver for the Gravis Grip Multiport, a gamepad "hub" that
      4 *  connects up to four 9-pin digital gamepads/joysticks.
      5 *  Driver tested on SMP and UP kernel versions 2.4.18-4 and 2.4.18-5.
      6 *
      7 *  Thanks to Chris Gassib for helpful advice.
      8 *
      9 *  Copyright (c)      2002 Brian Bonnlander, Bill Soudan
     10 *  Copyright (c) 1998-2000 Vojtech Pavlik
     11 */
     12
     13#include <linux/kernel.h>
     14#include <linux/module.h>
     15#include <linux/slab.h>
     16#include <linux/gameport.h>
     17#include <linux/input.h>
     18#include <linux/delay.h>
     19#include <linux/proc_fs.h>
     20#include <linux/jiffies.h>
     21
     22#define DRIVER_DESC	"Gravis Grip Multiport driver"
     23
     24MODULE_AUTHOR("Brian Bonnlander");
     25MODULE_DESCRIPTION(DRIVER_DESC);
     26MODULE_LICENSE("GPL");
     27
     28#ifdef GRIP_DEBUG
     29#define dbg(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" , ## arg)
     30#else
     31#define dbg(format, arg...) do {} while (0)
     32#endif
     33
     34#define GRIP_MAX_PORTS	4
     35/*
     36 * Grip multiport state
     37 */
     38
     39struct grip_port {
     40	struct input_dev *dev;
     41	int mode;
     42	int registered;
     43
     44	/* individual gamepad states */
     45	int buttons;
     46	int xaxes;
     47	int yaxes;
     48	int dirty;     /* has the state been updated? */
     49};
     50
     51struct grip_mp {
     52	struct gameport *gameport;
     53	struct grip_port *port[GRIP_MAX_PORTS];
     54	int reads;
     55	int bads;
     56};
     57
     58/*
     59 * Multiport packet interpretation
     60 */
     61
     62#define PACKET_FULL          0x80000000       /* packet is full                        */
     63#define PACKET_IO_FAST       0x40000000       /* 3 bits per gameport read              */
     64#define PACKET_IO_SLOW       0x20000000       /* 1 bit per gameport read               */
     65#define PACKET_MP_MORE       0x04000000       /* multiport wants to send more          */
     66#define PACKET_MP_DONE       0x02000000       /* multiport done sending                */
     67
     68/*
     69 * Packet status code interpretation
     70 */
     71
     72#define IO_GOT_PACKET        0x0100           /* Got a packet                           */
     73#define IO_MODE_FAST         0x0200           /* Used 3 data bits per gameport read     */
     74#define IO_SLOT_CHANGE       0x0800           /* Multiport physical slot status changed */
     75#define IO_DONE              0x1000           /* Multiport is done sending packets      */
     76#define IO_RETRY             0x4000           /* Try again later to get packet          */
     77#define IO_RESET             0x8000           /* Force multiport to resend all packets  */
     78
     79/*
     80 * Gamepad configuration data.  Other 9-pin digital joystick devices
     81 * may work with the multiport, so this may not be an exhaustive list!
     82 * Commodore 64 joystick remains untested.
     83 */
     84
     85#define GRIP_INIT_DELAY         2000          /*  2 ms */
     86
     87#define GRIP_MODE_NONE		0
     88#define GRIP_MODE_RESET         1
     89#define GRIP_MODE_GP		2
     90#define GRIP_MODE_C64		3
     91
     92static const int grip_btn_gp[]  = { BTN_TR, BTN_TL, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, -1 };
     93static const int grip_btn_c64[] = { BTN_JOYSTICK, -1 };
     94
     95static const int grip_abs_gp[]  = { ABS_X, ABS_Y, -1 };
     96static const int grip_abs_c64[] = { ABS_X, ABS_Y, -1 };
     97
     98static const int *grip_abs[] = { NULL, NULL, grip_abs_gp, grip_abs_c64 };
     99static const int *grip_btn[] = { NULL, NULL, grip_btn_gp, grip_btn_c64 };
    100
    101static const char *grip_name[] = { NULL, NULL, "Gravis Grip Pad", "Commodore 64 Joystick" };
    102
    103static const int init_seq[] = {
    104	1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1,
    105	1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1,
    106	1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1,
    107	0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1 };
    108
    109/* Maps multiport directional values to X,Y axis values (each axis encoded in 3 bits) */
    110
    111static const int axis_map[] = { 5, 9, 1, 5, 6, 10, 2, 6, 4, 8, 0, 4, 5, 9, 1, 5 };
    112
    113static int register_slot(int i, struct grip_mp *grip);
    114
    115/*
    116 * Returns whether an odd or even number of bits are on in pkt.
    117 */
    118
    119static int bit_parity(u32 pkt)
    120{
    121	int x = pkt ^ (pkt >> 16);
    122	x ^= x >> 8;
    123	x ^= x >> 4;
    124	x ^= x >> 2;
    125	x ^= x >> 1;
    126	return x & 1;
    127}
    128
    129/*
    130 * Poll gameport; return true if all bits set in 'onbits' are on and
    131 * all bits set in 'offbits' are off.
    132 */
    133
    134static inline int poll_until(u8 onbits, u8 offbits, int u_sec, struct gameport* gp, u8 *data)
    135{
    136	int i, nloops;
    137
    138	nloops = gameport_time(gp, u_sec);
    139	for (i = 0; i < nloops; i++) {
    140		*data = gameport_read(gp);
    141		if ((*data & onbits) == onbits &&
    142		    (~(*data) & offbits) == offbits)
    143			return 1;
    144	}
    145	dbg("gameport timed out after %d microseconds.\n", u_sec);
    146	return 0;
    147}
    148
    149/*
    150 * Gets a 28-bit packet from the multiport.
    151 *
    152 * After getting a packet successfully, commands encoded by sendcode may
    153 * be sent to the multiport.
    154 *
    155 * The multiport clock value is reflected in gameport bit B4.
    156 *
    157 * Returns a packet status code indicating whether packet is valid, the transfer
    158 * mode, and any error conditions.
    159 *
    160 * sendflags:      current I/O status
    161 * sendcode:   data to send to the multiport if sendflags is nonzero
    162 */
    163
    164static int mp_io(struct gameport* gameport, int sendflags, int sendcode, u32 *packet)
    165{
    166	u8  raw_data;            /* raw data from gameport */
    167	u8  data_mask;           /* packet data bits from raw_data */
    168	u32 pkt;                 /* packet temporary storage */
    169	int bits_per_read;       /* num packet bits per gameport read */
    170	int portvals = 0;        /* used for port value sanity check */
    171	int i;
    172
    173	/* Gameport bits B0, B4, B5 should first be off, then B4 should come on. */
    174
    175	*packet = 0;
    176	raw_data = gameport_read(gameport);
    177	if (raw_data & 1)
    178		return IO_RETRY;
    179
    180	for (i = 0; i < 64; i++) {
    181		raw_data = gameport_read(gameport);
    182		portvals |= 1 << ((raw_data >> 4) & 3); /* Demux B4, B5 */
    183	}
    184
    185	if (portvals == 1) {                            /* B4, B5 off */
    186		raw_data = gameport_read(gameport);
    187		portvals = raw_data & 0xf0;
    188
    189		if (raw_data & 0x31)
    190			return IO_RESET;
    191		gameport_trigger(gameport);
    192
    193		if (!poll_until(0x10, 0, 308, gameport, &raw_data))
    194			return IO_RESET;
    195	} else
    196		return IO_RETRY;
    197
    198	/* Determine packet transfer mode and prepare for packet construction. */
    199
    200	if (raw_data & 0x20) {                 /* 3 data bits/read */
    201		portvals |= raw_data >> 4;     /* Compare B4-B7 before & after trigger */
    202
    203		if (portvals != 0xb)
    204			return 0;
    205		data_mask = 7;
    206		bits_per_read = 3;
    207		pkt = (PACKET_FULL | PACKET_IO_FAST) >> 28;
    208	} else {                                 /* 1 data bit/read */
    209		data_mask = 1;
    210		bits_per_read = 1;
    211		pkt = (PACKET_FULL | PACKET_IO_SLOW) >> 28;
    212	}
    213
    214	/* Construct a packet.  Final data bits must be zero. */
    215
    216	while (1) {
    217		if (!poll_until(0, 0x10, 77, gameport, &raw_data))
    218			return IO_RESET;
    219		raw_data = (raw_data >> 5) & data_mask;
    220
    221		if (pkt & PACKET_FULL)
    222			break;
    223		pkt = (pkt << bits_per_read) | raw_data;
    224
    225		if (!poll_until(0x10, 0, 77, gameport, &raw_data))
    226			return IO_RESET;
    227	}
    228
    229	if (raw_data)
    230		return IO_RESET;
    231
    232	/* If 3 bits/read used, drop from 30 bits to 28. */
    233
    234	if (bits_per_read == 3) {
    235		pkt = (pkt & 0xffff0000) | ((pkt << 1) & 0xffff);
    236		pkt = (pkt >> 2) | 0xf0000000;
    237	}
    238
    239	if (bit_parity(pkt) == 1)
    240		return IO_RESET;
    241
    242	/* Acknowledge packet receipt */
    243
    244	if (!poll_until(0x30, 0, 77, gameport, &raw_data))
    245		return IO_RESET;
    246
    247	raw_data = gameport_read(gameport);
    248
    249	if (raw_data & 1)
    250		return IO_RESET;
    251
    252	gameport_trigger(gameport);
    253
    254	if (!poll_until(0, 0x20, 77, gameport, &raw_data))
    255		return IO_RESET;
    256
    257        /* Return if we just wanted the packet or multiport wants to send more */
    258
    259	*packet = pkt;
    260	if ((sendflags == 0) || ((sendflags & IO_RETRY) && !(pkt & PACKET_MP_DONE)))
    261		return IO_GOT_PACKET;
    262
    263	if (pkt & PACKET_MP_MORE)
    264		return IO_GOT_PACKET | IO_RETRY;
    265
    266	/* Multiport is done sending packets and is ready to receive data */
    267
    268	if (!poll_until(0x20, 0, 77, gameport, &raw_data))
    269		return IO_GOT_PACKET | IO_RESET;
    270
    271	raw_data = gameport_read(gameport);
    272	if (raw_data & 1)
    273		return IO_GOT_PACKET | IO_RESET;
    274
    275	/* Trigger gameport based on bits in sendcode */
    276
    277	gameport_trigger(gameport);
    278	do {
    279		if (!poll_until(0x20, 0x10, 116, gameport, &raw_data))
    280			return IO_GOT_PACKET | IO_RESET;
    281
    282		if (!poll_until(0x30, 0, 193, gameport, &raw_data))
    283			return IO_GOT_PACKET | IO_RESET;
    284
    285		if (raw_data & 1)
    286			return IO_GOT_PACKET | IO_RESET;
    287
    288		if (sendcode & 1)
    289			gameport_trigger(gameport);
    290
    291		sendcode >>= 1;
    292	} while (sendcode);
    293
    294	return IO_GOT_PACKET | IO_MODE_FAST;
    295}
    296
    297/*
    298 * Disables and restores interrupts for mp_io(), which does the actual I/O.
    299 */
    300
    301static int multiport_io(struct gameport* gameport, int sendflags, int sendcode, u32 *packet)
    302{
    303	int status;
    304	unsigned long flags;
    305
    306	local_irq_save(flags);
    307	status = mp_io(gameport, sendflags, sendcode, packet);
    308	local_irq_restore(flags);
    309
    310	return status;
    311}
    312
    313/*
    314 * Puts multiport into digital mode.  Multiport LED turns green.
    315 *
    316 * Returns true if a valid digital packet was received, false otherwise.
    317 */
    318
    319static int dig_mode_start(struct gameport *gameport, u32 *packet)
    320{
    321	int i;
    322	int flags, tries = 0, bads = 0;
    323
    324	for (i = 0; i < ARRAY_SIZE(init_seq); i++) {     /* Send magic sequence */
    325		if (init_seq[i])
    326			gameport_trigger(gameport);
    327		udelay(GRIP_INIT_DELAY);
    328	}
    329
    330	for (i = 0; i < 16; i++)            /* Wait for multiport to settle */
    331		udelay(GRIP_INIT_DELAY);
    332
    333	while (tries < 64 && bads < 8) {    /* Reset multiport and try getting a packet */
    334
    335		flags = multiport_io(gameport, IO_RESET, 0x27, packet);
    336
    337		if (flags & IO_MODE_FAST)
    338			return 1;
    339
    340		if (flags & IO_RETRY)
    341			tries++;
    342		else
    343			bads++;
    344	}
    345	return 0;
    346}
    347
    348/*
    349 * Packet structure: B0-B15   => gamepad state
    350 *                   B16-B20  => gamepad device type
    351 *                   B21-B24  => multiport slot index (1-4)
    352 *
    353 * Known device types: 0x1f (grip pad), 0x0 (no device).  Others may exist.
    354 *
    355 * Returns the packet status.
    356 */
    357
    358static int get_and_decode_packet(struct grip_mp *grip, int flags)
    359{
    360	struct grip_port *port;
    361	u32 packet;
    362	int joytype = 0;
    363	int slot;
    364
    365	/* Get a packet and check for validity */
    366
    367	flags &= IO_RESET | IO_RETRY;
    368	flags = multiport_io(grip->gameport, flags, 0, &packet);
    369	grip->reads++;
    370
    371	if (packet & PACKET_MP_DONE)
    372		flags |= IO_DONE;
    373
    374	if (flags && !(flags & IO_GOT_PACKET)) {
    375		grip->bads++;
    376		return flags;
    377	}
    378
    379	/* Ignore non-gamepad packets, e.g. multiport hardware version */
    380
    381	slot = ((packet >> 21) & 0xf) - 1;
    382	if ((slot < 0) || (slot > 3))
    383		return flags;
    384
    385	port = grip->port[slot];
    386
    387	/*
    388	 * Handle "reset" packets, which occur at startup, and when gamepads
    389	 * are removed or plugged in.  May contain configuration of a new gamepad.
    390	 */
    391
    392	joytype = (packet >> 16) & 0x1f;
    393	if (!joytype) {
    394
    395		if (port->registered) {
    396			printk(KERN_INFO "grip_mp: removing %s, slot %d\n",
    397			       grip_name[port->mode], slot);
    398			input_unregister_device(port->dev);
    399			port->registered = 0;
    400		}
    401		dbg("Reset: grip multiport slot %d\n", slot);
    402		port->mode = GRIP_MODE_RESET;
    403		flags |= IO_SLOT_CHANGE;
    404		return flags;
    405	}
    406
    407	/* Interpret a grip pad packet */
    408
    409	if (joytype == 0x1f) {
    410
    411		int dir = (packet >> 8) & 0xf;          /* eight way directional value */
    412		port->buttons = (~packet) & 0xff;
    413		port->yaxes = ((axis_map[dir] >> 2) & 3) - 1;
    414		port->xaxes = (axis_map[dir] & 3) - 1;
    415		port->dirty = 1;
    416
    417		if (port->mode == GRIP_MODE_RESET)
    418			flags |= IO_SLOT_CHANGE;
    419
    420		port->mode = GRIP_MODE_GP;
    421
    422		if (!port->registered) {
    423			dbg("New Grip pad in multiport slot %d.\n", slot);
    424			if (register_slot(slot, grip)) {
    425				port->mode = GRIP_MODE_RESET;
    426				port->dirty = 0;
    427			}
    428		}
    429		return flags;
    430	}
    431
    432	/* Handle non-grip device codes.  For now, just print diagnostics. */
    433
    434	{
    435		static int strange_code = 0;
    436		if (strange_code != joytype) {
    437			printk(KERN_INFO "Possible non-grip pad/joystick detected.\n");
    438			printk(KERN_INFO "Got joy type 0x%x and packet 0x%x.\n", joytype, packet);
    439			strange_code = joytype;
    440		}
    441	}
    442	return flags;
    443}
    444
    445/*
    446 * Returns true if all multiport slot states appear valid.
    447 */
    448
    449static int slots_valid(struct grip_mp *grip)
    450{
    451	int flags, slot, invalid = 0, active = 0;
    452
    453	flags = get_and_decode_packet(grip, 0);
    454	if (!(flags & IO_GOT_PACKET))
    455		return 0;
    456
    457	for (slot = 0; slot < 4; slot++) {
    458		if (grip->port[slot]->mode == GRIP_MODE_RESET)
    459			invalid = 1;
    460		if (grip->port[slot]->mode != GRIP_MODE_NONE)
    461			active = 1;
    462	}
    463
    464	/* Return true if no active slot but multiport sent all its data */
    465	if (!active)
    466		return (flags & IO_DONE) ? 1 : 0;
    467
    468	/* Return false if invalid device code received */
    469	return invalid ? 0 : 1;
    470}
    471
    472/*
    473 * Returns whether the multiport was placed into digital mode and
    474 * able to communicate its state successfully.
    475 */
    476
    477static int multiport_init(struct grip_mp *grip)
    478{
    479	int dig_mode, initialized = 0, tries = 0;
    480	u32 packet;
    481
    482	dig_mode = dig_mode_start(grip->gameport, &packet);
    483	while (!dig_mode && tries < 4) {
    484		dig_mode = dig_mode_start(grip->gameport, &packet);
    485		tries++;
    486	}
    487
    488	if (dig_mode)
    489		dbg("multiport_init(): digital mode activated.\n");
    490	else {
    491		dbg("multiport_init(): unable to activate digital mode.\n");
    492		return 0;
    493	}
    494
    495	/* Get packets, store multiport state, and check state's validity */
    496	for (tries = 0; tries < 4096; tries++) {
    497		if (slots_valid(grip)) {
    498			initialized = 1;
    499			break;
    500		}
    501	}
    502	dbg("multiport_init(): initialized == %d\n", initialized);
    503	return initialized;
    504}
    505
    506/*
    507 * Reports joystick state to the linux input layer.
    508 */
    509
    510static void report_slot(struct grip_mp *grip, int slot)
    511{
    512	struct grip_port *port = grip->port[slot];
    513	int i;
    514
    515	/* Store button states with linux input driver */
    516
    517	for (i = 0; i < 8; i++)
    518		input_report_key(port->dev, grip_btn_gp[i], (port->buttons >> i) & 1);
    519
    520	/* Store axis states with linux driver */
    521
    522	input_report_abs(port->dev, ABS_X, port->xaxes);
    523	input_report_abs(port->dev, ABS_Y, port->yaxes);
    524
    525	/* Tell the receiver of the events to process them */
    526
    527	input_sync(port->dev);
    528
    529	port->dirty = 0;
    530}
    531
    532/*
    533 * Get the multiport state.
    534 */
    535
    536static void grip_poll(struct gameport *gameport)
    537{
    538	struct grip_mp *grip = gameport_get_drvdata(gameport);
    539	int i, npkts, flags;
    540
    541	for (npkts = 0; npkts < 4; npkts++) {
    542		flags = IO_RETRY;
    543		for (i = 0; i < 32; i++) {
    544			flags = get_and_decode_packet(grip, flags);
    545			if ((flags & IO_GOT_PACKET) || !(flags & IO_RETRY))
    546				break;
    547		}
    548		if (flags & IO_DONE)
    549			break;
    550	}
    551
    552	for (i = 0; i < 4; i++)
    553		if (grip->port[i]->dirty)
    554			report_slot(grip, i);
    555}
    556
    557/*
    558 * Called when a joystick device file is opened
    559 */
    560
    561static int grip_open(struct input_dev *dev)
    562{
    563	struct grip_mp *grip = input_get_drvdata(dev);
    564
    565	gameport_start_polling(grip->gameport);
    566	return 0;
    567}
    568
    569/*
    570 * Called when a joystick device file is closed
    571 */
    572
    573static void grip_close(struct input_dev *dev)
    574{
    575	struct grip_mp *grip = input_get_drvdata(dev);
    576
    577	gameport_stop_polling(grip->gameport);
    578}
    579
    580/*
    581 * Tell the linux input layer about a newly plugged-in gamepad.
    582 */
    583
    584static int register_slot(int slot, struct grip_mp *grip)
    585{
    586	struct grip_port *port = grip->port[slot];
    587	struct input_dev *input_dev;
    588	int j, t;
    589	int err;
    590
    591	port->dev = input_dev = input_allocate_device();
    592	if (!input_dev)
    593		return -ENOMEM;
    594
    595	input_dev->name = grip_name[port->mode];
    596	input_dev->id.bustype = BUS_GAMEPORT;
    597	input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
    598	input_dev->id.product = 0x0100 + port->mode;
    599	input_dev->id.version = 0x0100;
    600	input_dev->dev.parent = &grip->gameport->dev;
    601
    602	input_set_drvdata(input_dev, grip);
    603
    604	input_dev->open = grip_open;
    605	input_dev->close = grip_close;
    606
    607	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
    608
    609	for (j = 0; (t = grip_abs[port->mode][j]) >= 0; j++)
    610		input_set_abs_params(input_dev, t, -1, 1, 0, 0);
    611
    612	for (j = 0; (t = grip_btn[port->mode][j]) >= 0; j++)
    613		if (t > 0)
    614			set_bit(t, input_dev->keybit);
    615
    616	err = input_register_device(port->dev);
    617	if (err) {
    618		input_free_device(port->dev);
    619		return err;
    620	}
    621
    622	port->registered = 1;
    623
    624	if (port->dirty)	            /* report initial state, if any */
    625		report_slot(grip, slot);
    626
    627	return 0;
    628}
    629
    630static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
    631{
    632	struct grip_mp *grip;
    633	int err;
    634
    635	if (!(grip = kzalloc(sizeof(struct grip_mp), GFP_KERNEL)))
    636		return -ENOMEM;
    637
    638	grip->gameport = gameport;
    639
    640	gameport_set_drvdata(gameport, grip);
    641
    642	err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
    643	if (err)
    644		goto fail1;
    645
    646	gameport_set_poll_handler(gameport, grip_poll);
    647	gameport_set_poll_interval(gameport, 20);
    648
    649	if (!multiport_init(grip)) {
    650		err = -ENODEV;
    651		goto fail2;
    652	}
    653
    654	if (!grip->port[0]->mode && !grip->port[1]->mode && !grip->port[2]->mode && !grip->port[3]->mode) {
    655		/* nothing plugged in */
    656		err = -ENODEV;
    657		goto fail2;
    658	}
    659
    660	return 0;
    661
    662fail2:	gameport_close(gameport);
    663fail1:	gameport_set_drvdata(gameport, NULL);
    664	kfree(grip);
    665	return err;
    666}
    667
    668static void grip_disconnect(struct gameport *gameport)
    669{
    670	struct grip_mp *grip = gameport_get_drvdata(gameport);
    671	int i;
    672
    673	for (i = 0; i < 4; i++)
    674		if (grip->port[i]->registered)
    675			input_unregister_device(grip->port[i]->dev);
    676	gameport_close(gameport);
    677	gameport_set_drvdata(gameport, NULL);
    678	kfree(grip);
    679}
    680
    681static struct gameport_driver grip_drv = {
    682	.driver		= {
    683		.name	= "grip_mp",
    684	},
    685	.description	= DRIVER_DESC,
    686	.connect	= grip_connect,
    687	.disconnect	= grip_disconnect,
    688};
    689
    690module_gameport_driver(grip_drv);