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

sidewinder.c (20806B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  Copyright (c) 1998-2005 Vojtech Pavlik
      4 */
      5
      6/*
      7 * Microsoft SideWinder joystick family driver for Linux
      8 */
      9
     10/*
     11 */
     12
     13#include <linux/delay.h>
     14#include <linux/kernel.h>
     15#include <linux/module.h>
     16#include <linux/slab.h>
     17#include <linux/input.h>
     18#include <linux/gameport.h>
     19#include <linux/jiffies.h>
     20
     21#define DRIVER_DESC	"Microsoft SideWinder joystick family driver"
     22
     23MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
     24MODULE_DESCRIPTION(DRIVER_DESC);
     25MODULE_LICENSE("GPL");
     26
     27/*
     28 * These are really magic values. Changing them can make a problem go away,
     29 * as well as break everything.
     30 */
     31
     32#undef SW_DEBUG
     33#undef SW_DEBUG_DATA
     34
     35#define SW_START	600	/* The time we wait for the first bit [600 us] */
     36#define SW_STROBE	60	/* Max time per bit [60 us] */
     37#define SW_TIMEOUT	6	/* Wait for everything to settle [6 ms] */
     38#define SW_KICK		45	/* Wait after A0 fall till kick [45 us] */
     39#define SW_END		8	/* Number of bits before end of packet to kick */
     40#define SW_FAIL		16	/* Number of packet read errors to fail and reinitialize */
     41#define SW_BAD		2	/* Number of packet read errors to switch off 3d Pro optimization */
     42#define SW_OK		64	/* Number of packet read successes to switch optimization back on */
     43#define SW_LENGTH	512	/* Max number of bits in a packet */
     44
     45#ifdef SW_DEBUG
     46#define dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg)
     47#else
     48#define dbg(format, arg...) do {} while (0)
     49#endif
     50
     51/*
     52 * SideWinder joystick types ...
     53 */
     54
     55#define SW_ID_3DP	0
     56#define SW_ID_GP	1
     57#define SW_ID_PP	2
     58#define SW_ID_FFP	3
     59#define SW_ID_FSP	4
     60#define SW_ID_FFW	5
     61
     62/*
     63 * Names, buttons, axes ...
     64 */
     65
     66static char *sw_name[] = {	"3D Pro", "GamePad", "Precision Pro", "Force Feedback Pro", "FreeStyle Pro",
     67				"Force Feedback Wheel" };
     68
     69static char sw_abs[][7] = {
     70	{ ABS_X, ABS_Y, ABS_RZ, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y },
     71	{ ABS_X, ABS_Y },
     72	{ ABS_X, ABS_Y, ABS_RZ, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y },
     73	{ ABS_X, ABS_Y, ABS_RZ, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y },
     74	{ ABS_X, ABS_Y,         ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y },
     75	{ ABS_RX, ABS_RUDDER,   ABS_THROTTLE }};
     76
     77static char sw_bit[][7] = {
     78	{ 10, 10,  9, 10,  1,  1 },
     79	{  1,  1                 },
     80	{ 10, 10,  6,  7,  1,  1 },
     81	{ 10, 10,  6,  7,  1,  1 },
     82	{ 10, 10,  6,  1,  1     },
     83	{ 10,  7,  7,  1,  1     }};
     84
     85static short sw_btn[][12] = {
     86	{ BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_THUMB2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_MODE },
     87	{ BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE },
     88	{ BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_SELECT },
     89	{ BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_SELECT },
     90	{ BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT },
     91	{ BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_THUMB2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4 }};
     92
     93static struct {
     94	int x;
     95	int y;
     96} sw_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
     97
     98struct sw {
     99	struct gameport *gameport;
    100	struct input_dev *dev[4];
    101	char name[64];
    102	char phys[4][32];
    103	int length;
    104	int type;
    105	int bits;
    106	int number;
    107	int fail;
    108	int ok;
    109	int reads;
    110	int bads;
    111};
    112
    113/*
    114 * sw_read_packet() is a function which reads either a data packet, or an
    115 * identification packet from a SideWinder joystick. The protocol is very,
    116 * very, very braindamaged. Microsoft patented it in US patent #5628686.
    117 */
    118
    119static int sw_read_packet(struct gameport *gameport, unsigned char *buf, int length, int id)
    120{
    121	unsigned long flags;
    122	int timeout, bitout, sched, i, kick, start, strobe;
    123	unsigned char pending, u, v;
    124
    125	i = -id;						/* Don't care about data, only want ID */
    126	timeout = id ? gameport_time(gameport, SW_TIMEOUT * 1000) : 0; /* Set up global timeout for ID packet */
    127	kick = id ? gameport_time(gameport, SW_KICK) : 0;	/* Set up kick timeout for ID packet */
    128	start = gameport_time(gameport, SW_START);
    129	strobe = gameport_time(gameport, SW_STROBE);
    130	bitout = start;
    131	pending = 0;
    132	sched = 0;
    133
    134        local_irq_save(flags);					/* Quiet, please */
    135
    136	gameport_trigger(gameport);				/* Trigger */
    137	v = gameport_read(gameport);
    138
    139	do {
    140		bitout--;
    141		u = v;
    142		v = gameport_read(gameport);
    143	} while (!(~v & u & 0x10) && (bitout > 0));		/* Wait for first falling edge on clock */
    144
    145	if (bitout > 0)
    146		bitout = strobe;				/* Extend time if not timed out */
    147
    148	while ((timeout > 0 || bitout > 0) && (i < length)) {
    149
    150		timeout--;
    151		bitout--;					/* Decrement timers */
    152		sched--;
    153
    154		u = v;
    155		v = gameport_read(gameport);
    156
    157		if ((~u & v & 0x10) && (bitout > 0)) {		/* Rising edge on clock - data bit */
    158			if (i >= 0)				/* Want this data */
    159				buf[i] = v >> 5;		/* Store it */
    160			i++;					/* Advance index */
    161			bitout = strobe;			/* Extend timeout for next bit */
    162		}
    163
    164		if (kick && (~v & u & 0x01)) {			/* Falling edge on axis 0 */
    165			sched = kick;				/* Schedule second trigger */
    166			kick = 0;				/* Don't schedule next time on falling edge */
    167			pending = 1;				/* Mark schedule */
    168		}
    169
    170		if (pending && sched < 0 && (i > -SW_END)) {	/* Second trigger time */
    171			gameport_trigger(gameport);		/* Trigger */
    172			bitout = start;				/* Long bit timeout */
    173			pending = 0;				/* Unmark schedule */
    174			timeout = 0;				/* Switch from global to bit timeouts */
    175		}
    176	}
    177
    178	local_irq_restore(flags);					/* Done - relax */
    179
    180#ifdef SW_DEBUG_DATA
    181	{
    182		int j;
    183		printk(KERN_DEBUG "sidewinder.c: Read %d triplets. [", i);
    184		for (j = 0; j < i; j++) printk("%d", buf[j]);
    185		printk("]\n");
    186	}
    187#endif
    188
    189	return i;
    190}
    191
    192/*
    193 * sw_get_bits() and GB() compose bits from the triplet buffer into a __u64.
    194 * Parameter 'pos' is bit number inside packet where to start at, 'num' is number
    195 * of bits to be read, 'shift' is offset in the resulting __u64 to start at, bits
    196 * is number of bits per triplet.
    197 */
    198
    199#define GB(pos,num) sw_get_bits(buf, pos, num, sw->bits)
    200
    201static __u64 sw_get_bits(unsigned char *buf, int pos, int num, char bits)
    202{
    203	__u64 data = 0;
    204	int tri = pos % bits;						/* Start position */
    205	int i   = pos / bits;
    206	int bit = 0;
    207
    208	while (num--) {
    209		data |= (__u64)((buf[i] >> tri++) & 1) << bit++;	/* Transfer bit */
    210		if (tri == bits) {
    211			i++;						/* Next triplet */
    212			tri = 0;
    213		}
    214	}
    215
    216	return data;
    217}
    218
    219/*
    220 * sw_init_digital() initializes a SideWinder 3D Pro joystick
    221 * into digital mode.
    222 */
    223
    224static void sw_init_digital(struct gameport *gameport)
    225{
    226	static const int seq[] = { 140, 140+725, 140+300, 0 };
    227	unsigned long flags;
    228	int i, t;
    229
    230        local_irq_save(flags);
    231
    232	i = 0;
    233        do {
    234                gameport_trigger(gameport);			/* Trigger */
    235		t = gameport_time(gameport, SW_TIMEOUT * 1000);
    236		while ((gameport_read(gameport) & 1) && t) t--;	/* Wait for axis to fall back to 0 */
    237                udelay(seq[i]);					/* Delay magic time */
    238        } while (seq[++i]);
    239
    240	gameport_trigger(gameport);				/* Last trigger */
    241
    242	local_irq_restore(flags);
    243}
    244
    245/*
    246 * sw_parity() computes parity of __u64
    247 */
    248
    249static int sw_parity(__u64 t)
    250{
    251	int x = t ^ (t >> 32);
    252
    253	x ^= x >> 16;
    254	x ^= x >> 8;
    255	x ^= x >> 4;
    256	x ^= x >> 2;
    257	x ^= x >> 1;
    258	return x & 1;
    259}
    260
    261/*
    262 * sw_ccheck() checks synchronization bits and computes checksum of nibbles.
    263 */
    264
    265static int sw_check(__u64 t)
    266{
    267	unsigned char sum = 0;
    268
    269	if ((t & 0x8080808080808080ULL) ^ 0x80)			/* Sync */
    270		return -1;
    271
    272	while (t) {						/* Sum */
    273		sum += t & 0xf;
    274		t >>= 4;
    275	}
    276
    277	return sum & 0xf;
    278}
    279
    280/*
    281 * sw_parse() analyzes SideWinder joystick data, and writes the results into
    282 * the axes and buttons arrays.
    283 */
    284
    285static int sw_parse(unsigned char *buf, struct sw *sw)
    286{
    287	int hat, i, j;
    288	struct input_dev *dev;
    289
    290	switch (sw->type) {
    291
    292		case SW_ID_3DP:
    293
    294			if (sw_check(GB(0,64)) || (hat = (GB(6,1) << 3) | GB(60,3)) > 8)
    295				return -1;
    296
    297			dev = sw->dev[0];
    298
    299			input_report_abs(dev, ABS_X,        (GB( 3,3) << 7) | GB(16,7));
    300			input_report_abs(dev, ABS_Y,        (GB( 0,3) << 7) | GB(24,7));
    301			input_report_abs(dev, ABS_RZ,       (GB(35,2) << 7) | GB(40,7));
    302			input_report_abs(dev, ABS_THROTTLE, (GB(32,3) << 7) | GB(48,7));
    303
    304			input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x);
    305			input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y);
    306
    307			for (j = 0; j < 7; j++)
    308				input_report_key(dev, sw_btn[SW_ID_3DP][j], !GB(j+8,1));
    309
    310			input_report_key(dev, BTN_BASE4, !GB(38,1));
    311			input_report_key(dev, BTN_BASE5, !GB(37,1));
    312
    313			input_sync(dev);
    314
    315			return 0;
    316
    317		case SW_ID_GP:
    318
    319			for (i = 0; i < sw->number; i ++) {
    320
    321				if (sw_parity(GB(i*15,15)))
    322					return -1;
    323
    324				input_report_abs(sw->dev[i], ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
    325				input_report_abs(sw->dev[i], ABS_Y, GB(i*15+0,1) - GB(i*15+1,1));
    326
    327				for (j = 0; j < 10; j++)
    328					input_report_key(sw->dev[i], sw_btn[SW_ID_GP][j], !GB(i*15+j+4,1));
    329
    330				input_sync(sw->dev[i]);
    331			}
    332
    333			return 0;
    334
    335		case SW_ID_PP:
    336		case SW_ID_FFP:
    337
    338			if (!sw_parity(GB(0,48)) || (hat = GB(42,4)) > 8)
    339				return -1;
    340
    341			dev = sw->dev[0];
    342			input_report_abs(dev, ABS_X,        GB( 9,10));
    343			input_report_abs(dev, ABS_Y,        GB(19,10));
    344			input_report_abs(dev, ABS_RZ,       GB(36, 6));
    345			input_report_abs(dev, ABS_THROTTLE, GB(29, 7));
    346
    347			input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x);
    348			input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y);
    349
    350			for (j = 0; j < 9; j++)
    351				input_report_key(dev, sw_btn[SW_ID_PP][j], !GB(j,1));
    352
    353			input_sync(dev);
    354
    355			return 0;
    356
    357		case SW_ID_FSP:
    358
    359			if (!sw_parity(GB(0,43)) || (hat = GB(28,4)) > 8)
    360				return -1;
    361
    362			dev = sw->dev[0];
    363			input_report_abs(dev, ABS_X,        GB( 0,10));
    364			input_report_abs(dev, ABS_Y,        GB(16,10));
    365			input_report_abs(dev, ABS_THROTTLE, GB(32, 6));
    366
    367			input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x);
    368			input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y);
    369
    370			for (j = 0; j < 6; j++)
    371				input_report_key(dev, sw_btn[SW_ID_FSP][j], !GB(j+10,1));
    372
    373			input_report_key(dev, BTN_TR,     !GB(26,1));
    374			input_report_key(dev, BTN_START,  !GB(27,1));
    375			input_report_key(dev, BTN_MODE,   !GB(38,1));
    376			input_report_key(dev, BTN_SELECT, !GB(39,1));
    377
    378			input_sync(dev);
    379
    380			return 0;
    381
    382		case SW_ID_FFW:
    383
    384			if (!sw_parity(GB(0,33)))
    385				return -1;
    386
    387			dev = sw->dev[0];
    388			input_report_abs(dev, ABS_RX,       GB( 0,10));
    389			input_report_abs(dev, ABS_RUDDER,   GB(10, 6));
    390			input_report_abs(dev, ABS_THROTTLE, GB(16, 6));
    391
    392			for (j = 0; j < 8; j++)
    393				input_report_key(dev, sw_btn[SW_ID_FFW][j], !GB(j+22,1));
    394
    395			input_sync(dev);
    396
    397			return 0;
    398	}
    399
    400	return -1;
    401}
    402
    403/*
    404 * sw_read() reads SideWinder joystick data, and reinitializes
    405 * the joystick in case of persistent problems. This is the function that is
    406 * called from the generic code to poll the joystick.
    407 */
    408
    409static int sw_read(struct sw *sw)
    410{
    411	unsigned char buf[SW_LENGTH];
    412	int i;
    413
    414	i = sw_read_packet(sw->gameport, buf, sw->length, 0);
    415
    416	if (sw->type == SW_ID_3DP && sw->length == 66 && i != 66) {		/* Broken packet, try to fix */
    417
    418		if (i == 64 && !sw_check(sw_get_bits(buf,0,64,1))) {		/* Last init failed, 1 bit mode */
    419			printk(KERN_WARNING "sidewinder.c: Joystick in wrong mode on %s"
    420				" - going to reinitialize.\n", sw->gameport->phys);
    421			sw->fail = SW_FAIL;					/* Reinitialize */
    422			i = 128;						/* Bogus value */
    423		}
    424
    425		if (i < 66 && GB(0,64) == GB(i*3-66,64))			/* 1 == 3 */
    426			i = 66;							/* Everything is fine */
    427
    428		if (i < 66 && GB(0,64) == GB(66,64))				/* 1 == 2 */
    429			i = 66;							/* Everything is fine */
    430
    431		if (i < 66 && GB(i*3-132,64) == GB(i*3-66,64)) {		/* 2 == 3 */
    432			memmove(buf, buf + i - 22, 22);				/* Move data */
    433			i = 66;							/* Carry on */
    434		}
    435	}
    436
    437	if (i == sw->length && !sw_parse(buf, sw)) {				/* Parse data */
    438
    439		sw->fail = 0;
    440		sw->ok++;
    441
    442		if (sw->type == SW_ID_3DP && sw->length == 66			/* Many packets OK */
    443			&& sw->ok > SW_OK) {
    444
    445			printk(KERN_INFO "sidewinder.c: No more trouble on %s"
    446				" - enabling optimization again.\n", sw->gameport->phys);
    447			sw->length = 22;
    448		}
    449
    450		return 0;
    451	}
    452
    453	sw->ok = 0;
    454	sw->fail++;
    455
    456	if (sw->type == SW_ID_3DP && sw->length == 22 && sw->fail > SW_BAD) {	/* Consecutive bad packets */
    457
    458		printk(KERN_INFO "sidewinder.c: Many bit errors on %s"
    459			" - disabling optimization.\n", sw->gameport->phys);
    460		sw->length = 66;
    461	}
    462
    463	if (sw->fail < SW_FAIL)
    464		return -1;							/* Not enough, don't reinitialize yet */
    465
    466	printk(KERN_WARNING "sidewinder.c: Too many bit errors on %s"
    467		" - reinitializing joystick.\n", sw->gameport->phys);
    468
    469	if (!i && sw->type == SW_ID_3DP) {					/* 3D Pro can be in analog mode */
    470		mdelay(3 * SW_TIMEOUT);
    471		sw_init_digital(sw->gameport);
    472	}
    473
    474	mdelay(SW_TIMEOUT);
    475	i = sw_read_packet(sw->gameport, buf, SW_LENGTH, 0);			/* Read normal data packet */
    476	mdelay(SW_TIMEOUT);
    477	sw_read_packet(sw->gameport, buf, SW_LENGTH, i);			/* Read ID packet, this initializes the stick */
    478
    479	sw->fail = SW_FAIL;
    480
    481	return -1;
    482}
    483
    484static void sw_poll(struct gameport *gameport)
    485{
    486	struct sw *sw = gameport_get_drvdata(gameport);
    487
    488	sw->reads++;
    489	if (sw_read(sw))
    490		sw->bads++;
    491}
    492
    493static int sw_open(struct input_dev *dev)
    494{
    495	struct sw *sw = input_get_drvdata(dev);
    496
    497	gameport_start_polling(sw->gameport);
    498	return 0;
    499}
    500
    501static void sw_close(struct input_dev *dev)
    502{
    503	struct sw *sw = input_get_drvdata(dev);
    504
    505	gameport_stop_polling(sw->gameport);
    506}
    507
    508/*
    509 * sw_print_packet() prints the contents of a SideWinder packet.
    510 */
    511
    512static void sw_print_packet(char *name, int length, unsigned char *buf, char bits)
    513{
    514	int i;
    515
    516	printk(KERN_INFO "sidewinder.c: %s packet, %d bits. [", name, length);
    517	for (i = (((length + 3) >> 2) - 1); i >= 0; i--)
    518		printk("%x", (int)sw_get_bits(buf, i << 2, 4, bits));
    519	printk("]\n");
    520}
    521
    522/*
    523 * sw_3dp_id() translates the 3DP id into a human legible string.
    524 * Unfortunately I don't know how to do this for the other SW types.
    525 */
    526
    527static void sw_3dp_id(unsigned char *buf, char *comment, size_t size)
    528{
    529	int i;
    530	char pnp[8], rev[9];
    531
    532	for (i = 0; i < 7; i++)						/* ASCII PnP ID */
    533		pnp[i] = sw_get_bits(buf, 24+8*i, 8, 1);
    534
    535	for (i = 0; i < 8; i++)						/* ASCII firmware revision */
    536		rev[i] = sw_get_bits(buf, 88+8*i, 8, 1);
    537
    538	pnp[7] = rev[8] = 0;
    539
    540	snprintf(comment, size, " [PnP %d.%02d id %s rev %s]",
    541		(int) ((sw_get_bits(buf, 8, 6, 1) << 6) |		/* Two 6-bit values */
    542			sw_get_bits(buf, 16, 6, 1)) / 100,
    543		(int) ((sw_get_bits(buf, 8, 6, 1) << 6) |
    544			sw_get_bits(buf, 16, 6, 1)) % 100,
    545		 pnp, rev);
    546}
    547
    548/*
    549 * sw_guess_mode() checks the upper two button bits for toggling -
    550 * indication of that the joystick is in 3-bit mode. This is documented
    551 * behavior for 3DP ID packet, and for example the FSP does this in
    552 * normal packets instead. Fun ...
    553 */
    554
    555static int sw_guess_mode(unsigned char *buf, int len)
    556{
    557	int i;
    558	unsigned char xor = 0;
    559
    560	for (i = 1; i < len; i++)
    561		xor |= (buf[i - 1] ^ buf[i]) & 6;
    562
    563	return !!xor * 2 + 1;
    564}
    565
    566/*
    567 * sw_connect() probes for SideWinder type joysticks.
    568 */
    569
    570static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
    571{
    572	struct sw *sw;
    573	struct input_dev *input_dev;
    574	int i, j, k, l;
    575	int err = 0;
    576	unsigned char *buf = NULL;	/* [SW_LENGTH] */
    577	unsigned char *idbuf = NULL;	/* [SW_LENGTH] */
    578	unsigned char m = 1;
    579	char comment[40];
    580
    581	comment[0] = 0;
    582
    583	sw = kzalloc(sizeof(struct sw), GFP_KERNEL);
    584	buf = kmalloc(SW_LENGTH, GFP_KERNEL);
    585	idbuf = kmalloc(SW_LENGTH, GFP_KERNEL);
    586	if (!sw || !buf || !idbuf) {
    587		err = -ENOMEM;
    588		goto fail1;
    589	}
    590
    591	sw->gameport = gameport;
    592
    593	gameport_set_drvdata(gameport, sw);
    594
    595	err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
    596	if (err)
    597		goto fail1;
    598
    599	dbg("Init 0: Opened %s, io %#x, speed %d",
    600		gameport->phys, gameport->io, gameport->speed);
    601
    602	i = sw_read_packet(gameport, buf, SW_LENGTH, 0);		/* Read normal packet */
    603	msleep(SW_TIMEOUT);
    604	dbg("Init 1: Mode %d. Length %d.", m , i);
    605
    606	if (!i) {							/* No data. 3d Pro analog mode? */
    607		sw_init_digital(gameport);				/* Switch to digital */
    608		msleep(SW_TIMEOUT);
    609		i = sw_read_packet(gameport, buf, SW_LENGTH, 0);	/* Retry reading packet */
    610		msleep(SW_TIMEOUT);
    611		dbg("Init 1b: Length %d.", i);
    612		if (!i) {						/* No data -> FAIL */
    613			err = -ENODEV;
    614			goto fail2;
    615		}
    616	}
    617
    618	j = sw_read_packet(gameport, idbuf, SW_LENGTH, i);		/* Read ID. This initializes the stick */
    619	m |= sw_guess_mode(idbuf, j);					/* ID packet should carry mode info [3DP] */
    620	dbg("Init 2: Mode %d. ID Length %d.", m, j);
    621
    622	if (j <= 0) {							/* Read ID failed. Happens in 1-bit mode on PP */
    623		msleep(SW_TIMEOUT);
    624		i = sw_read_packet(gameport, buf, SW_LENGTH, 0);	/* Retry reading packet */
    625		m |= sw_guess_mode(buf, i);
    626		dbg("Init 2b: Mode %d. Length %d.", m, i);
    627		if (!i) {
    628			err = -ENODEV;
    629			goto fail2;
    630		}
    631		msleep(SW_TIMEOUT);
    632		j = sw_read_packet(gameport, idbuf, SW_LENGTH, i);	/* Retry reading ID */
    633		dbg("Init 2c: ID Length %d.", j);
    634	}
    635
    636	sw->type = -1;
    637	k = SW_FAIL;							/* Try SW_FAIL times */
    638	l = 0;
    639
    640	do {
    641		k--;
    642		msleep(SW_TIMEOUT);
    643		i = sw_read_packet(gameport, buf, SW_LENGTH, 0);	/* Read data packet */
    644		dbg("Init 3: Mode %d. Length %d. Last %d. Tries %d.", m, i, l, k);
    645
    646		if (i > l) {						/* Longer? As we can only lose bits, it makes */
    647									/* no sense to try detection for a packet shorter */
    648			l = i;						/* than the previous one */
    649
    650			sw->number = 1;
    651			sw->gameport = gameport;
    652			sw->length = i;
    653			sw->bits = m;
    654
    655			dbg("Init 3a: Case %d.\n", i * m);
    656
    657			switch (i * m) {
    658				case 60:
    659					sw->number++;
    660					fallthrough;
    661				case 45:				/* Ambiguous packet length */
    662					if (j <= 40) {			/* ID length less or eq 40 -> FSP */
    663					fallthrough;
    664				case 43:
    665						sw->type = SW_ID_FSP;
    666						break;
    667					}
    668					sw->number++;
    669					fallthrough;
    670				case 30:
    671					sw->number++;
    672					fallthrough;
    673				case 15:
    674					sw->type = SW_ID_GP;
    675					break;
    676				case 33:
    677				case 31:
    678					sw->type = SW_ID_FFW;
    679					break;
    680				case 48:				/* Ambiguous */
    681					if (j == 14) {			/* ID length 14*3 -> FFP */
    682						sw->type = SW_ID_FFP;
    683						sprintf(comment, " [AC %s]", sw_get_bits(idbuf,38,1,3) ? "off" : "on");
    684					} else
    685						sw->type = SW_ID_PP;
    686					break;
    687				case 66:
    688					sw->bits = 3;
    689					fallthrough;
    690				case 198:
    691					sw->length = 22;
    692					fallthrough;
    693				case 64:
    694					sw->type = SW_ID_3DP;
    695					if (j == 160)
    696						sw_3dp_id(idbuf, comment, sizeof(comment));
    697					break;
    698			}
    699		}
    700
    701	} while (k && sw->type == -1);
    702
    703	if (sw->type == -1) {
    704		printk(KERN_WARNING "sidewinder.c: unknown joystick device detected "
    705			"on %s, contact <vojtech@ucw.cz>\n", gameport->phys);
    706		sw_print_packet("ID", j * 3, idbuf, 3);
    707		sw_print_packet("Data", i * m, buf, m);
    708		err = -ENODEV;
    709		goto fail2;
    710	}
    711
    712#ifdef SW_DEBUG
    713	sw_print_packet("ID", j * 3, idbuf, 3);
    714	sw_print_packet("Data", i * m, buf, m);
    715#endif
    716
    717	gameport_set_poll_handler(gameport, sw_poll);
    718	gameport_set_poll_interval(gameport, 20);
    719
    720	k = i;
    721	l = j;
    722
    723	for (i = 0; i < sw->number; i++) {
    724		int bits, code;
    725
    726		snprintf(sw->name, sizeof(sw->name),
    727			 "Microsoft SideWinder %s", sw_name[sw->type]);
    728		snprintf(sw->phys[i], sizeof(sw->phys[i]),
    729			 "%s/input%d", gameport->phys, i);
    730
    731		sw->dev[i] = input_dev = input_allocate_device();
    732		if (!input_dev) {
    733			err = -ENOMEM;
    734			goto fail3;
    735		}
    736
    737		input_dev->name = sw->name;
    738		input_dev->phys = sw->phys[i];
    739		input_dev->id.bustype = BUS_GAMEPORT;
    740		input_dev->id.vendor = GAMEPORT_ID_VENDOR_MICROSOFT;
    741		input_dev->id.product = sw->type;
    742		input_dev->id.version = 0x0100;
    743		input_dev->dev.parent = &gameport->dev;
    744
    745		input_set_drvdata(input_dev, sw);
    746
    747		input_dev->open = sw_open;
    748		input_dev->close = sw_close;
    749
    750		input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
    751
    752		for (j = 0; (bits = sw_bit[sw->type][j]); j++) {
    753			int min, max, fuzz, flat;
    754
    755			code = sw_abs[sw->type][j];
    756			min = bits == 1 ? -1 : 0;
    757			max = (1 << bits) - 1;
    758			fuzz = (bits >> 1) >= 2 ? 1 << ((bits >> 1) - 2) : 0;
    759			flat = code == ABS_THROTTLE || bits < 5 ?
    760				0 : 1 << (bits - 5);
    761
    762			input_set_abs_params(input_dev, code,
    763					     min, max, fuzz, flat);
    764		}
    765
    766		for (j = 0; (code = sw_btn[sw->type][j]); j++)
    767			__set_bit(code, input_dev->keybit);
    768
    769		dbg("%s%s [%d-bit id %d data %d]\n", sw->name, comment, m, l, k);
    770
    771		err = input_register_device(sw->dev[i]);
    772		if (err)
    773			goto fail4;
    774	}
    775
    776 out:	kfree(buf);
    777	kfree(idbuf);
    778
    779	return err;
    780
    781 fail4:	input_free_device(sw->dev[i]);
    782 fail3:	while (--i >= 0)
    783		input_unregister_device(sw->dev[i]);
    784 fail2:	gameport_close(gameport);
    785 fail1:	gameport_set_drvdata(gameport, NULL);
    786	kfree(sw);
    787	goto out;
    788}
    789
    790static void sw_disconnect(struct gameport *gameport)
    791{
    792	struct sw *sw = gameport_get_drvdata(gameport);
    793	int i;
    794
    795	for (i = 0; i < sw->number; i++)
    796		input_unregister_device(sw->dev[i]);
    797	gameport_close(gameport);
    798	gameport_set_drvdata(gameport, NULL);
    799	kfree(sw);
    800}
    801
    802static struct gameport_driver sw_drv = {
    803	.driver		= {
    804		.name	= "sidewinder",
    805		.owner	= THIS_MODULE,
    806	},
    807	.description	= DRIVER_DESC,
    808	.connect	= sw_connect,
    809	.disconnect	= sw_disconnect,
    810};
    811
    812module_gameport_driver(sw_drv);