⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sidewinder.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
			return 0;	}	return -1;}/* * sw_read() reads SideWinder joystick data, and reinitializes * the joystick in case of persistent problems. This is the function that is * called from the generic code to poll the joystick. */static int sw_read(struct sw *sw){	unsigned char buf[SW_LENGTH];	int i;	i = sw_read_packet(sw->gameport, buf, sw->length, 0);	if (sw->type == SW_ID_3DP && sw->length == 66 && i != 66) {		/* Broken packet, try to fix */		if (i == 64 && !sw_check(sw_get_bits(buf,0,64,1))) {		/* Last init failed, 1 bit mode */			printk(KERN_WARNING "sidewinder.c: Joystick in wrong mode on %s"				" - going to reinitialize.\n", sw->gameport->phys);			sw->fail = SW_FAIL;					/* Reinitialize */			i = 128;						/* Bogus value */		}		if (i < 66 && GB(0,64) == GB(i*3-66,64))			/* 1 == 3 */			i = 66;							/* Everything is fine */		if (i < 66 && GB(0,64) == GB(66,64))				/* 1 == 2 */			i = 66;							/* Everything is fine */		if (i < 66 && GB(i*3-132,64) == GB(i*3-66,64)) {		/* 2 == 3 */			memmove(buf, buf + i - 22, 22);				/* Move data */			i = 66;							/* Carry on */		}	}	if (i == sw->length && !sw_parse(buf, sw)) {				/* Parse data */		sw->fail = 0;		sw->ok++;		if (sw->type == SW_ID_3DP && sw->length == 66			/* Many packets OK */			&& sw->ok > SW_OK) {			printk(KERN_INFO "sidewinder.c: No more trouble on %s"				" - enabling optimization again.\n", sw->gameport->phys);			sw->length = 22;		}		return 0;	}	sw->ok = 0;	sw->fail++;	if (sw->type == SW_ID_3DP && sw->length == 22 && sw->fail > SW_BAD) {	/* Consecutive bad packets */		printk(KERN_INFO "sidewinder.c: Many bit errors on %s"			" - disabling optimization.\n", sw->gameport->phys);		sw->length = 66;	}	if (sw->fail < SW_FAIL)		return -1;							/* Not enough, don't reinitialize yet */	printk(KERN_WARNING "sidewinder.c: Too many bit errors on %s"		" - reinitializing joystick.\n", sw->gameport->phys);	if (!i && sw->type == SW_ID_3DP) {					/* 3D Pro can be in analog mode */		mdelay(3 * SW_TIMEOUT);		sw_init_digital(sw->gameport);	}	mdelay(SW_TIMEOUT);	i = sw_read_packet(sw->gameport, buf, SW_LENGTH, 0);			/* Read normal data packet */	mdelay(SW_TIMEOUT);	sw_read_packet(sw->gameport, buf, SW_LENGTH, i);			/* Read ID packet, this initializes the stick */	sw->fail = SW_FAIL;	return -1;}static void sw_poll(struct gameport *gameport){	struct sw *sw = gameport_get_drvdata(gameport);	sw->reads++;	if (sw_read(sw))		sw->bads++;}static int sw_open(struct input_dev *dev){	struct sw *sw = dev->private;	gameport_start_polling(sw->gameport);	return 0;}static void sw_close(struct input_dev *dev){	struct sw *sw = dev->private;	gameport_stop_polling(sw->gameport);}/* * sw_print_packet() prints the contents of a SideWinder packet. */static void sw_print_packet(char *name, int length, unsigned char *buf, char bits){	int i;	printk(KERN_INFO "sidewinder.c: %s packet, %d bits. [", name, length);	for (i = (((length + 3) >> 2) - 1); i >= 0; i--)		printk("%x", (int)sw_get_bits(buf, i << 2, 4, bits));	printk("]\n");}/* * sw_3dp_id() translates the 3DP id into a human legible string. * Unfortunately I don't know how to do this for the other SW types. */static void sw_3dp_id(unsigned char *buf, char *comment){	int i;	char pnp[8], rev[9];	for (i = 0; i < 7; i++)						/* ASCII PnP ID */		pnp[i] = sw_get_bits(buf, 24+8*i, 8, 1);	for (i = 0; i < 8; i++)						/* ASCII firmware revision */		rev[i] = sw_get_bits(buf, 88+8*i, 8, 1);	pnp[7] = rev[8] = 0;	sprintf(comment, " [PnP %d.%02d id %s rev %s]",		(int) ((sw_get_bits(buf, 8, 6, 1) << 6) |		/* Two 6-bit values */			sw_get_bits(buf, 16, 6, 1)) / 100,		(int) ((sw_get_bits(buf, 8, 6, 1) << 6) |			sw_get_bits(buf, 16, 6, 1)) % 100,		 pnp, rev);}/* * sw_guess_mode() checks the upper two button bits for toggling - * indication of that the joystick is in 3-bit mode. This is documented * behavior for 3DP ID packet, and for example the FSP does this in * normal packets instead. Fun ... */static int sw_guess_mode(unsigned char *buf, int len){	int i;	unsigned char xor = 0;	for (i = 1; i < len; i++)		xor |= (buf[i - 1] ^ buf[i]) & 6;	return !!xor * 2 + 1;}/* * sw_connect() probes for SideWinder type joysticks. */static int sw_connect(struct gameport *gameport, struct gameport_driver *drv){	struct sw *sw;	struct input_dev *input_dev;	int i, j, k, l;	int err;	unsigned char *buf = NULL;	/* [SW_LENGTH] */	unsigned char *idbuf = NULL;	/* [SW_LENGTH] */	unsigned char m = 1;	char comment[40];	comment[0] = 0;	sw = kzalloc(sizeof(struct sw), GFP_KERNEL);	buf = kmalloc(SW_LENGTH, GFP_KERNEL);	idbuf = kmalloc(SW_LENGTH, GFP_KERNEL);	if (!sw || !buf || !idbuf) {		err = -ENOMEM;		goto fail1;	}	sw->gameport = gameport;	gameport_set_drvdata(gameport, sw);	err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);	if (err)		goto fail1;	dbg("Init 0: Opened %s, io %#x, speed %d",		gameport->phys, gameport->io, gameport->speed);	i = sw_read_packet(gameport, buf, SW_LENGTH, 0);		/* Read normal packet */	msleep(SW_TIMEOUT);	dbg("Init 1: Mode %d. Length %d.", m , i);	if (!i) {							/* No data. 3d Pro analog mode? */		sw_init_digital(gameport);				/* Switch to digital */		msleep(SW_TIMEOUT);		i = sw_read_packet(gameport, buf, SW_LENGTH, 0);	/* Retry reading packet */		msleep(SW_TIMEOUT);		dbg("Init 1b: Length %d.", i);		if (!i) {						/* No data -> FAIL */			err = -ENODEV;			goto fail2;		}	}	j = sw_read_packet(gameport, idbuf, SW_LENGTH, i);		/* Read ID. This initializes the stick */	m |= sw_guess_mode(idbuf, j);					/* ID packet should carry mode info [3DP] */	dbg("Init 2: Mode %d. ID Length %d.", m, j);	if (j <= 0) {							/* Read ID failed. Happens in 1-bit mode on PP */		msleep(SW_TIMEOUT);		i = sw_read_packet(gameport, buf, SW_LENGTH, 0);	/* Retry reading packet */		m |= sw_guess_mode(buf, i);		dbg("Init 2b: Mode %d. Length %d.", m, i);		if (!i) {			err = -ENODEV;			goto fail2;		}		msleep(SW_TIMEOUT);		j = sw_read_packet(gameport, idbuf, SW_LENGTH, i);	/* Retry reading ID */		dbg("Init 2c: ID Length %d.", j);	}	sw->type = -1;	k = SW_FAIL;							/* Try SW_FAIL times */	l = 0;	do {		k--;		msleep(SW_TIMEOUT);		i = sw_read_packet(gameport, buf, SW_LENGTH, 0);	/* Read data packet */		dbg("Init 3: Mode %d. Length %d. Last %d. Tries %d.", m, i, l, k);		if (i > l) {						/* Longer? As we can only lose bits, it makes */									/* no sense to try detection for a packet shorter */			l = i;						/* than the previous one */			sw->number = 1;			sw->gameport = gameport;			sw->length = i;			sw->bits = m;			dbg("Init 3a: Case %d.\n", i * m);			switch (i * m) {				case 60:					sw->number++;				case 45:				/* Ambiguous packet length */					if (j <= 40) {			/* ID length less or eq 40 -> FSP */				case 43:						sw->type = SW_ID_FSP;						break;					}					sw->number++;				case 30:					sw->number++;				case 15:					sw->type = SW_ID_GP;					break;				case 33:				case 31:					sw->type = SW_ID_FFW;					break;				case 48:				/* Ambiguous */					if (j == 14) {			/* ID length 14*3 -> FFP */						sw->type = SW_ID_FFP;						sprintf(comment, " [AC %s]", sw_get_bits(idbuf,38,1,3) ? "off" : "on");					} else					sw->type = SW_ID_PP;					break;				case 66:					sw->bits = 3;				case 198:					sw->length = 22;				case 64:					sw->type = SW_ID_3DP;					if (j == 160) sw_3dp_id(idbuf, comment);					break;			}		}	} while (k && sw->type == -1);	if (sw->type == -1) {		printk(KERN_WARNING "sidewinder.c: unknown joystick device detected "			"on %s, contact <vojtech@ucw.cz>\n", gameport->phys);		sw_print_packet("ID", j * 3, idbuf, 3);		sw_print_packet("Data", i * m, buf, m);		err = -ENODEV;		goto fail2;	}#ifdef SW_DEBUG	sw_print_packet("ID", j * 3, idbuf, 3);	sw_print_packet("Data", i * m, buf, m);#endif	gameport_set_poll_handler(gameport, sw_poll);	gameport_set_poll_interval(gameport, 20);	k = i;	l = j;	for (i = 0; i < sw->number; i++) {		int bits, code;		sprintf(sw->name, "Microsoft SideWinder %s", sw_name[sw->type]);		sprintf(sw->phys[i], "%s/input%d", gameport->phys, i);		sw->dev[i] = input_dev = input_allocate_device();		if (!input_dev) {			err = -ENOMEM;			goto fail3;		}		input_dev->name = sw->name;		input_dev->phys = sw->phys[i];		input_dev->id.bustype = BUS_GAMEPORT;		input_dev->id.vendor = GAMEPORT_ID_VENDOR_MICROSOFT;		input_dev->id.product = sw->type;		input_dev->id.version = 0x0100;		input_dev->cdev.dev = &gameport->dev;		input_dev->private = sw;		input_dev->open = sw_open;		input_dev->close = sw_close;		input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);		for (j = 0; (bits = sw_bit[sw->type][j]); j++) {			code = sw_abs[sw->type][j];			set_bit(code, input_dev->absbit);			input_dev->absmax[code] = (1 << bits) - 1;			input_dev->absmin[code] = (bits == 1) ? -1 : 0;			input_dev->absfuzz[code] = ((bits >> 1) >= 2) ? (1 << ((bits >> 1) - 2)) : 0;			if (code != ABS_THROTTLE)				input_dev->absflat[code] = (bits >= 5) ? (1 << (bits - 5)) : 0;		}		for (j = 0; (code = sw_btn[sw->type][j]); j++)			set_bit(code, input_dev->keybit);		dbg("%s%s [%d-bit id %d data %d]\n", sw->name, comment, m, l, k);		input_register_device(sw->dev[i]);	}	return 0; fail3: while (--i >= 0)		input_unregister_device(sw->dev[i]); fail2:	gameport_close(gameport); fail1:	gameport_set_drvdata(gameport, NULL);	kfree(sw);	kfree(buf);	kfree(idbuf);	return err;}static void sw_disconnect(struct gameport *gameport){	struct sw *sw = gameport_get_drvdata(gameport);	int i;	for (i = 0; i < sw->number; i++)		input_unregister_device(sw->dev[i]);	gameport_close(gameport);	gameport_set_drvdata(gameport, NULL);	kfree(sw);}static struct gameport_driver sw_drv = {	.driver		= {		.name	= "sidewinder",	},	.description	= DRIVER_DESC,	.connect	= sw_connect,	.disconnect	= sw_disconnect,};static int __init sw_init(void){	gameport_register_driver(&sw_drv);	return 0;}static void __exit sw_exit(void){	gameport_unregister_driver(&sw_drv);}module_init(sw_init);module_exit(sw_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -