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

📄 analog.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	GET_TIME(t3);	local_irq_restore(flags);	port->speed = DELTA(t1, t2) - DELTA(t2, t3);	tx = ~0;	for (i = 0; i < 50; i++) {		local_irq_save(flags);		GET_TIME(t1);		for (t = 0; t < 50; t++) { gameport_read(gameport); GET_TIME(t2); }		GET_TIME(t3);		local_irq_restore(flags);		udelay(i);		t = DELTA(t1, t2) - DELTA(t2, t3);		if (t < tx) tx = t;	}        port->loop = tx / 50;}/* * analog_name() constructs a name for an analog joystick. */static void analog_name(struct analog *analog){	sprintf(analog->name, "Analog %d-axis %d-button",		hweight8(analog->mask & ANALOG_AXES_STD),		hweight8(analog->mask & ANALOG_BTNS_STD) + !!(analog->mask & ANALOG_BTNS_CHF) * 2 +		hweight16(analog->mask & ANALOG_BTNS_GAMEPAD) + !!(analog->mask & ANALOG_HBTN_CHF) * 4);	if (analog->mask & ANALOG_HATS_ALL)		sprintf(analog->name, "%s %d-hat",			analog->name, hweight16(analog->mask & ANALOG_HATS_ALL));	if (analog->mask & ANALOG_HAT_FCS)			strcat(analog->name, " FCS");	if (analog->mask & ANALOG_ANY_CHF)			strcat(analog->name, (analog->mask & ANALOG_SAITEK) ? " Saitek" : " CHF");	strcat(analog->name, (analog->mask & ANALOG_GAMEPAD) ? " gamepad": " joystick");}/* * analog_init_device() */static int analog_init_device(struct analog_port *port, struct analog *analog, int index){	struct input_dev *input_dev;	int i, j, t, v, w, x, y, z;	analog_name(analog);	sprintf(analog->phys, "%s/input%d", port->gameport->phys, index);	analog->buttons = (analog->mask & ANALOG_GAMEPAD) ? analog_pad_btn : analog_joy_btn;	analog->dev = input_dev = input_allocate_device();	if (!input_dev)		return -ENOMEM;	input_dev->name = analog->name;	input_dev->phys = analog->phys;	input_dev->id.bustype = BUS_GAMEPORT;	input_dev->id.vendor = GAMEPORT_ID_VENDOR_ANALOG;	input_dev->id.product = analog->mask >> 4;	input_dev->id.version = 0x0100;	input_dev->open = analog_open;	input_dev->close = analog_close;	input_dev->private = port;	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);	for (i = j = 0; i < 4; i++)		if (analog->mask & (1 << i)) {			t = analog_axes[j];			x = port->axes[i];			y = (port->axes[0] + port->axes[1]) >> 1;			z = y - port->axes[i];			z = z > 0 ? z : -z;			v = (x >> 3);			w = (x >> 3);			if ((i == 2 || i == 3) && (j == 2 || j == 3) && (z > (y >> 3)))				x = y;			if (analog->mask & ANALOG_SAITEK) {				if (i == 2) x = port->axes[i];				v = x - (x >> 2);				w = (x >> 4);			}			input_set_abs_params(input_dev, t, v, (x << 1) - v, port->fuzz, w);			j++;		}	for (i = j = 0; i < 3; i++)		if (analog->mask & analog_exts[i])			for (x = 0; x < 2; x++) {				t = analog_hats[j++];				input_set_abs_params(input_dev, t, -1, 1, 0, 0);			}	for (i = j = 0; i < 4; i++)		if (analog->mask & (0x10 << i))			set_bit(analog->buttons[j++], input_dev->keybit);	if (analog->mask & ANALOG_BTNS_CHF)		for (i = 0; i < 2; i++)			set_bit(analog->buttons[j++], input_dev->keybit);	if (analog->mask & ANALOG_HBTN_CHF)		for (i = 0; i < 4; i++)			set_bit(analog->buttons[j++], input_dev->keybit);	for (i = 0; i < 4; i++)		if (analog->mask & (ANALOG_BTN_TL << i))			set_bit(analog_pads[i], input_dev->keybit);	analog_decode(analog, port->axes, port->initial, port->buttons);	input_register_device(analog->dev);	return 0;}/* * analog_init_devices() sets up device-specific values and registers the input devices. */static int analog_init_masks(struct analog_port *port){	int i;	struct analog *analog = port->analog;	int max[4];	if (!port->mask)		return -1;	if ((port->mask & 3) != 3 && port->mask != 0xc) {		printk(KERN_WARNING "analog.c: Unknown joystick device found  "			"(data=%#x, %s), probably not analog joystick.\n",			port->mask, port->gameport->phys);		return -1;	}	i = analog_options[0]; /* FIXME !!! - need to specify options for different ports */	analog[0].mask = i & 0xfffff;	analog[0].mask &= ~(ANALOG_AXES_STD | ANALOG_HAT_FCS | ANALOG_BTNS_GAMEPAD)			| port->mask | ((port->mask << 8) & ANALOG_HAT_FCS)			| ((port->mask << 10) & ANALOG_BTNS_TLR) | ((port->mask << 12) & ANALOG_BTNS_TLR2);	analog[0].mask &= ~(ANALOG_HAT2_CHF)			| ((analog[0].mask & ANALOG_HBTN_CHF) ? 0 : ANALOG_HAT2_CHF);	analog[0].mask &= ~(ANALOG_THROTTLE | ANALOG_BTN_TR | ANALOG_BTN_TR2)			| ((~analog[0].mask & ANALOG_HAT_FCS) >> 8)			| ((~analog[0].mask & ANALOG_HAT_FCS) << 2)			| ((~analog[0].mask & ANALOG_HAT_FCS) << 4);	analog[0].mask &= ~(ANALOG_THROTTLE | ANALOG_RUDDER)			| (((~analog[0].mask & ANALOG_BTNS_TLR ) >> 10)			&  ((~analog[0].mask & ANALOG_BTNS_TLR2) >> 12));	analog[1].mask = ((i >> 20) & 0xff) | ((i >> 12) & 0xf0000);	analog[1].mask &= (analog[0].mask & ANALOG_EXTENSIONS) ? ANALOG_GAMEPAD			: (((ANALOG_BTNS_STD | port->mask) & ~analog[0].mask) | ANALOG_GAMEPAD);	if (port->cooked) {		for (i = 0; i < 4; i++) max[i] = port->axes[i] << 1;		if ((analog[0].mask & 0x7) == 0x7) max[2] = (max[0] + max[1]) >> 1;		if ((analog[0].mask & 0xb) == 0xb) max[3] = (max[0] + max[1]) >> 1;		if ((analog[0].mask & ANALOG_BTN_TL) && !(analog[0].mask & ANALOG_BTN_TL2)) max[2] >>= 1;		if ((analog[0].mask & ANALOG_BTN_TR) && !(analog[0].mask & ANALOG_BTN_TR2)) max[3] >>= 1;		if ((analog[0].mask & ANALOG_HAT_FCS)) max[3] >>= 1;		gameport_calibrate(port->gameport, port->axes, max);	}	for (i = 0; i < 4; i++)		port->initial[i] = port->axes[i];	return -!(analog[0].mask || analog[1].mask);}static int analog_init_port(struct gameport *gameport, struct gameport_driver *drv, struct analog_port *port){	int i, t, u, v;	port->gameport = gameport;	gameport_set_drvdata(gameport, port);	if (!gameport_open(gameport, drv, GAMEPORT_MODE_RAW)) {		analog_calibrate_timer(port);		gameport_trigger(gameport);		t = gameport_read(gameport);		msleep(ANALOG_MAX_TIME);		port->mask = (gameport_read(gameport) ^ t) & t & 0xf;		port->fuzz = (port->speed * ANALOG_FUZZ_MAGIC) / port->loop / 1000 + ANALOG_FUZZ_BITS;		for (i = 0; i < ANALOG_INIT_RETRIES; i++) {			if (!analog_cooked_read(port))				break;			msleep(ANALOG_MAX_TIME);		}		u = v = 0;		msleep(ANALOG_MAX_TIME);		t = gameport_time(gameport, ANALOG_MAX_TIME * 1000);		gameport_trigger(gameport);		while ((gameport_read(port->gameport) & port->mask) && (u < t))			u++;		udelay(ANALOG_SAITEK_DELAY);		t = gameport_time(gameport, ANALOG_SAITEK_TIME);		gameport_trigger(gameport);		while ((gameport_read(port->gameport) & port->mask) && (v < t))			v++;		if (v < (u >> 1)) { /* FIXME - more than one port */			analog_options[0] |= /* FIXME - more than one port */				ANALOG_SAITEK | ANALOG_BTNS_CHF | ANALOG_HBTN_CHF | ANALOG_HAT1_CHF;			return 0;		}		gameport_close(gameport);	}	if (!gameport_open(gameport, drv, GAMEPORT_MODE_COOKED)) {		for (i = 0; i < ANALOG_INIT_RETRIES; i++)			if (!gameport_cooked_read(gameport, port->axes, &port->buttons))				break;		for (i = 0; i < 4; i++)			if (port->axes[i] != -1)				port->mask |= 1 << i;		port->fuzz = gameport->fuzz;		port->cooked = 1;		return 0;	}	return gameport_open(gameport, drv, GAMEPORT_MODE_RAW);}static int analog_connect(struct gameport *gameport, struct gameport_driver *drv){	struct analog_port *port;	int i;	int err;	if (!(port = kzalloc(sizeof(struct analog_port), GFP_KERNEL)))		return - ENOMEM;	err = analog_init_port(gameport, drv, port);	if (err)		goto fail1;	err = analog_init_masks(port);	if (err)		goto fail2;	gameport_set_poll_handler(gameport, analog_poll);	gameport_set_poll_interval(gameport, 10);	for (i = 0; i < 2; i++)		if (port->analog[i].mask) {			err = analog_init_device(port, port->analog + i, i);			if (err)				goto fail3;		}	return 0; fail3: while (--i >= 0)		input_unregister_device(port->analog[i].dev); fail2:	gameport_close(gameport); fail1:	gameport_set_drvdata(gameport, NULL);	kfree(port);	return err;}static void analog_disconnect(struct gameport *gameport){	struct analog_port *port = gameport_get_drvdata(gameport);	int i;	for (i = 0; i < 2; i++)		if (port->analog[i].mask)			input_unregister_device(port->analog[i].dev);	gameport_close(gameport);	gameport_set_drvdata(gameport, NULL);	printk(KERN_INFO "analog.c: %d out of %d reads (%d%%) on %s failed\n",		port->bads, port->reads, port->reads ? (port->bads * 100 / port->reads) : 0,		port->gameport->phys);	kfree(port);}struct analog_types {	char *name;	int value;};static struct analog_types analog_types[] = {	{ "none",	0x00000000 },	{ "auto",	0x000000ff },	{ "2btn",	0x0000003f },	{ "y-joy",	0x0cc00033 },	{ "y-pad",	0x8cc80033 },	{ "fcs",	0x000008f7 },	{ "chf",	0x000002ff },	{ "fullchf",	0x000007ff },	{ "gamepad",	0x000830f3 },	{ "gamepad8",	0x0008f0f3 },	{ NULL, 0 }};static void analog_parse_options(void){	int i, j;	char *end;	for (i = 0; i < js_nargs; i++) {		for (j = 0; analog_types[j].name; j++)			if (!strcmp(analog_types[j].name, js[i])) {				analog_options[i] = analog_types[j].value;				break;			}		if (analog_types[j].name) continue;		analog_options[i] = simple_strtoul(js[i], &end, 0);		if (end != js[i]) continue;		analog_options[i] = 0xff;		if (!strlen(js[i])) continue;		printk(KERN_WARNING "analog.c: Bad config for port %d - \"%s\"\n", i, js[i]);	}	for (; i < ANALOG_PORTS; i++)		analog_options[i] = 0xff;}/* * The gameport device structure. */static struct gameport_driver analog_drv = {	.driver		= {		.name	= "analog",	},	.description	= DRIVER_DESC,	.connect	= analog_connect,	.disconnect	= analog_disconnect,};static int __init analog_init(void){	analog_parse_options();	gameport_register_driver(&analog_drv);	return 0;}static void __exit analog_exit(void){	gameport_unregister_driver(&analog_drv);}module_init(analog_init);module_exit(analog_exit);

⌨️ 快捷键说明

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