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

📄 gamecon.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * NES and SNES pads */	if (gc->pads[GC_NES] || gc->pads[GC_SNES]) {		gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data);		for (i = 0; i < 5; i++) {			s = gc_status_bit[i];			if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) {				input_report_abs(gc->dev[i], ABS_X, !(s & data[6]) - !(s & data[7]));				input_report_abs(gc->dev[i], ABS_Y, !(s & data[4]) - !(s & data[5]));			}			if (s & gc->pads[GC_NES])				for (j = 0; j < 4; j++)					input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_nes_bytes[j]]);			if (s & gc->pads[GC_SNES])				for (j = 0; j < 8; j++)					input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_snes_bytes[j]]);			input_sync(gc->dev[i]);		}	}/* * Multi and Multi2 joysticks */	if (gc->pads[GC_MULTI] || gc->pads[GC_MULTI2]) {		gc_multi_read_packet(gc, gc->pads[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH, data);		for (i = 0; i < 5; i++) {			s = gc_status_bit[i];			if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) {				input_report_abs(gc->dev[i], ABS_X,  !(s & data[2]) - !(s & data[3]));				input_report_abs(gc->dev[i], ABS_Y,  !(s & data[0]) - !(s & data[1]));				input_report_key(gc->dev[i], BTN_TRIGGER, s & data[4]);			}			if (s & gc->pads[GC_MULTI2])				input_report_key(gc->dev[i], BTN_THUMB, s & data[5]);			input_sync(gc->dev[i]);		}	}/* * PSX controllers */	if (gc->pads[GC_PSX] || gc->pads[GC_DDR]) {		gc_psx_read_packet(gc, data_psx, data);		for (i = 0; i < 5; i++) {			switch (data[i]) {				case GC_PSX_RUMBLE:					input_report_key(gc->dev[i], BTN_THUMBL, ~data_psx[i][0] & 0x04);					input_report_key(gc->dev[i], BTN_THUMBR, ~data_psx[i][0] & 0x02);				case GC_PSX_NEGCON:				case GC_PSX_ANALOG:					if (gc->pads[GC_DDR] & gc_status_bit[i]) {						for(j = 0; j < 4; j++)							input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));					} else {						for (j = 0; j < 4; j++)							input_report_abs(gc->dev[i], gc_psx_abs[j+2], data_psx[i][j + 2]);						input_report_abs(gc->dev[i], ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);						input_report_abs(gc->dev[i], ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);					}					for (j = 0; j < 8; j++)						input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j));					input_report_key(gc->dev[i], BTN_START,  ~data_psx[i][0] & 0x08);					input_report_key(gc->dev[i], BTN_SELECT, ~data_psx[i][0] & 0x01);					input_sync(gc->dev[i]);					break;				case GC_PSX_NORMAL:					if (gc->pads[GC_DDR] & gc_status_bit[i]) {						for(j = 0; j < 4; j++)							input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));					} else {						input_report_abs(gc->dev[i], ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);						input_report_abs(gc->dev[i], ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);						/* for some reason if the extra axes are left unset they drift */						/* for (j = 0; j < 4; j++)							input_report_abs(gc->dev[i], gc_psx_abs[j+2], 128);						 * This needs to be debugged properly,						 * maybe fuzz processing needs to be done in input_sync()						 *				 --vojtech						 */					}					for (j = 0; j < 8; j++)						input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j));					input_report_key(gc->dev[i], BTN_START,  ~data_psx[i][0] & 0x08);					input_report_key(gc->dev[i], BTN_SELECT, ~data_psx[i][0] & 0x01);					input_sync(gc->dev[i]);					break;				case 0: /* not a pad, ignore */					break;			}		}	}	mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);}static int gc_open(struct input_dev *dev){	struct gc *gc = dev->private;	int err;	err = down_interruptible(&gc->sem);	if (err)		return err;	if (!gc->used++) {		parport_claim(gc->pd);		parport_write_control(gc->pd->port, 0x04);		mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);	}	up(&gc->sem);	return 0;}static void gc_close(struct input_dev *dev){	struct gc *gc = dev->private;	down(&gc->sem);	if (!--gc->used) {		del_timer_sync(&gc->timer);		parport_write_control(gc->pd->port, 0x00);		parport_release(gc->pd);	}	up(&gc->sem);}static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type){	struct input_dev *input_dev;	int i;	if (!pad_type)		return 0;	if (pad_type < 1 || pad_type > GC_MAX) {		printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", pad_type);		return -EINVAL;	}	gc->dev[idx] = input_dev = input_allocate_device();	if (!input_dev) {		printk(KERN_ERR "gamecon.c: Not enough memory for input device\n");		return -ENOMEM;	}	input_dev->name = gc_names[pad_type];	input_dev->phys = gc->phys[idx];	input_dev->id.bustype = BUS_PARPORT;	input_dev->id.vendor = 0x0001;	input_dev->id.product = pad_type;	input_dev->id.version = 0x0100;	input_dev->private = gc;	input_dev->open = gc_open;	input_dev->close = gc_close;	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);	for (i = 0; i < 2; i++)		input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0);	gc->pads[0] |= gc_status_bit[idx];	gc->pads[pad_type] |= gc_status_bit[idx];	switch (pad_type) {		case GC_N64:			for (i = 0; i < 10; i++)				set_bit(gc_n64_btn[i], input_dev->keybit);			for (i = 0; i < 2; i++) {				input_set_abs_params(input_dev, ABS_X + i, -127, 126, 0, 2);				input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0);			}			break;		case GC_SNES:			for (i = 4; i < 8; i++)				set_bit(gc_snes_btn[i], input_dev->keybit);		case GC_NES:			for (i = 0; i < 4; i++)				set_bit(gc_snes_btn[i], input_dev->keybit);			break;		case GC_MULTI2:			set_bit(BTN_THUMB, input_dev->keybit);		case GC_MULTI:			set_bit(BTN_TRIGGER, input_dev->keybit);			break;		case GC_PSX:			for (i = 0; i < 6; i++)				input_set_abs_params(input_dev, gc_psx_abs[i], 4, 252, 0, 2);			for (i = 0; i < 12; i++)				set_bit(gc_psx_btn[i], input_dev->keybit);			break;		case GC_DDR:			for (i = 0; i < 4; i++)				set_bit(gc_psx_ddr_btn[i], input_dev->keybit);			for (i = 0; i < 12; i++)				set_bit(gc_psx_btn[i], input_dev->keybit);			break;	}	return 0;}static struct gc __init *gc_probe(int parport, int *pads, int n_pads){	struct gc *gc;	struct parport *pp;	struct pardevice *pd;	int i;	int err;	pp = parport_find_number(parport);	if (!pp) {		printk(KERN_ERR "gamecon.c: no such parport\n");		err = -EINVAL;		goto err_out;	}	pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);	if (!pd) {		printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n");		err = -EBUSY;		goto err_put_pp;	}	gc = kzalloc(sizeof(struct gc), GFP_KERNEL);	if (!gc) {		printk(KERN_ERR "gamecon.c: Not enough memory\n");		err = -ENOMEM;		goto err_unreg_pardev;	}	init_MUTEX(&gc->sem);	gc->pd = pd;	init_timer(&gc->timer);	gc->timer.data = (long) gc;	gc->timer.function = gc_timer;	for (i = 0; i < n_pads; i++) {		if (!pads[i])			continue;		sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i);		err = gc_setup_pad(gc, i, pads[i]);		if (err)			goto err_free_devs;		input_register_device(gc->dev[i]);	}	if (!gc->pads[0]) {		printk(KERN_ERR "gamecon.c: No valid devices specified\n");		err = -EINVAL;		goto err_free_gc;	}	parport_put_port(pp);	return gc; err_free_devs:	while (--i >= 0)		input_unregister_device(gc->dev[i]); err_free_gc:	kfree(gc); err_unreg_pardev:	parport_unregister_device(pd); err_put_pp:	parport_put_port(pp); err_out:	return ERR_PTR(err);}static void __exit gc_remove(struct gc *gc){	int i;	for (i = 0; i < GC_MAX_DEVICES; i++)		if (gc->dev[i])			input_unregister_device(gc->dev[i]);	parport_unregister_device(gc->pd);	kfree(gc);}static int __init gc_init(void){	int i;	int have_dev = 0;	int err = 0;	for (i = 0; i < GC_MAX_PORTS; i++) {		if (gc[i].nargs == 0 || gc[i].args[0] < 0)			continue;		if (gc[i].nargs < 2) {			printk(KERN_ERR "gamecon.c: at least one device must be specified\n");			err = -EINVAL;			break;		}		gc_base[i] = gc_probe(gc[i].args[0], gc[i].args + 1, gc[i].nargs - 1);		if (IS_ERR(gc_base[i])) {			err = PTR_ERR(gc_base[i]);			break;		}		have_dev = 1;	}	if (err) {		while (--i >= 0)			gc_remove(gc_base[i]);		return err;	}	return have_dev ? 0 : -ENODEV;}static void __exit gc_exit(void){	int i;	for (i = 0; i < GC_MAX_PORTS; i++)		if (gc_base[i])			gc_remove(gc_base[i]);}module_init(gc_init);module_exit(gc_exit);

⌨️ 快捷键说明

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