📄 gamecon.c
字号:
axes[0] = axes[1] = 0; for (j = 0; j < 8; j++) { if (data[23 - j] & s) axes[0] |= 1 << j; if (data[31 - j] & s) axes[1] |= 1 << j; } input_report_abs(dev + i, ABS_X, axes[0]); input_report_abs(dev + i, ABS_Y, -axes[1]); input_report_abs(dev + i, ABS_HAT0X, !(s & data[6]) - !(s & data[7])); input_report_abs(dev + i, ABS_HAT0Y, !(s & data[4]) - !(s & data[5])); for (j = 0; j < 10; j++) input_report_key(dev + i, gc_n64_btn[j], s & data[gc_n64_bytes[j]]); input_sync(dev + i); } } }/* * 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(dev + i, ABS_X, !(s & data[6]) - !(s & data[7])); input_report_abs(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(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(dev + i, gc_snes_btn[j], s & data[gc_snes_bytes[j]]); input_sync(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(dev + i, ABS_X, !(s & data[2]) - !(s & data[3])); input_report_abs(dev + i, ABS_Y, !(s & data[0]) - !(s & data[1])); input_report_key(dev + i, BTN_TRIGGER, s & data[4]); } if (s & gc->pads[GC_MULTI2]) input_report_key(dev + i, BTN_THUMB, s & data[5]); input_sync(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(dev + i, BTN_THUMBL, ~data_psx[i][0] & 0x04); input_report_key(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(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j)); } else { for (j = 0; j < 4; j++) input_report_abs(dev + i, gc_psx_abs[j+2], data_psx[i][j + 2]); input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128); input_report_abs(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(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j)); input_report_key(dev + i, BTN_START, ~data_psx[i][0] & 0x08); input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01); input_sync(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(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j)); } else { input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128); input_report_abs(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(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(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j)); input_report_key(dev + i, BTN_START, ~data_psx[i][0] & 0x08); input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01); input_sync(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; if (!gc->used++) { parport_claim(gc->pd); parport_write_control(gc->pd->port, 0x04); mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); } return 0;}static void gc_close(struct input_dev *dev){ struct gc *gc = dev->private; if (!--gc->used) { del_timer(&gc->timer); parport_write_control(gc->pd->port, 0x00); parport_release(gc->pd); }}static struct gc __init *gc_probe(int *config, int nargs){ struct gc *gc; struct parport *pp; int i, j; if (config[0] < 0) return NULL; if (nargs < 2) { printk(KERN_ERR "gamecon.c: at least one device must be specified\n"); return NULL; } pp = parport_find_number(config[0]); if (!pp) { printk(KERN_ERR "gamecon.c: no such parport\n"); return NULL; } if (!(gc = kmalloc(sizeof(struct gc), GFP_KERNEL))) { parport_put_port(pp); return NULL; } memset(gc, 0, sizeof(struct gc)); gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); parport_put_port(pp); if (!gc->pd) { printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n"); kfree(gc); return NULL; } parport_claim(gc->pd); init_timer(&gc->timer); gc->timer.data = (long) gc; gc->timer.function = gc_timer; for (i = 0; i < nargs - 1; i++) { if (!config[i + 1]) continue; if (config[i + 1] < 1 || config[i + 1] > GC_MAX) { printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", config[i + 1]); continue; } gc->dev[i].private = gc; gc->dev[i].open = gc_open; gc->dev[i].close = gc_close; gc->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); for (j = 0; j < 2; j++) { set_bit(ABS_X + j, gc->dev[i].absbit); gc->dev[i].absmin[ABS_X + j] = -1; gc->dev[i].absmax[ABS_X + j] = 1; } gc->pads[0] |= gc_status_bit[i]; gc->pads[config[i + 1]] |= gc_status_bit[i]; switch(config[i + 1]) { case GC_N64: for (j = 0; j < 10; j++) set_bit(gc_n64_btn[j], gc->dev[i].keybit); for (j = 0; j < 2; j++) { set_bit(ABS_X + j, gc->dev[i].absbit); gc->dev[i].absmin[ABS_X + j] = -127; gc->dev[i].absmax[ABS_X + j] = 126; gc->dev[i].absflat[ABS_X + j] = 2; set_bit(ABS_HAT0X + j, gc->dev[i].absbit); gc->dev[i].absmin[ABS_HAT0X + j] = -1; gc->dev[i].absmax[ABS_HAT0X + j] = 1; } break; case GC_SNES: for (j = 4; j < 8; j++) set_bit(gc_snes_btn[j], gc->dev[i].keybit); case GC_NES: for (j = 0; j < 4; j++) set_bit(gc_snes_btn[j], gc->dev[i].keybit); break; case GC_MULTI2: set_bit(BTN_THUMB, gc->dev[i].keybit); case GC_MULTI: set_bit(BTN_TRIGGER, gc->dev[i].keybit); break; case GC_PSX: case GC_DDR: if(config[i + 1] == GC_DDR) { for (j = 0; j < 4; j++) set_bit(gc_psx_ddr_btn[j], gc->dev[i].keybit); } else { for (j = 0; j < 6; j++) { set_bit(gc_psx_abs[j], gc->dev[i].absbit); gc->dev[i].absmin[gc_psx_abs[j]] = 4; gc->dev[i].absmax[gc_psx_abs[j]] = 252; gc->dev[i].absflat[gc_psx_abs[j]] = 2; } } for (j = 0; j < 12; j++) set_bit(gc_psx_btn[j], gc->dev[i].keybit); break; } sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i); gc->dev[i].name = gc_names[config[i + 1]]; gc->dev[i].phys = gc->phys[i]; gc->dev[i].id.bustype = BUS_PARPORT; gc->dev[i].id.vendor = 0x0001; gc->dev[i].id.product = config[i + 1]; gc->dev[i].id.version = 0x0100; } parport_release(gc->pd); if (!gc->pads[0]) { parport_unregister_device(gc->pd); kfree(gc); return NULL; } for (i = 0; i < 5; i++) if (gc->pads[0] & gc_status_bit[i]) { input_register_device(gc->dev + i); printk(KERN_INFO "input: %s on %s\n", gc->dev[i].name, gc->pd->port->name); } return gc;}int __init gc_init(void){ gc_base[0] = gc_probe(gc, gc_nargs); gc_base[1] = gc_probe(gc_2, gc_nargs_2); gc_base[2] = gc_probe(gc_3, gc_nargs_3); if (gc_base[0] || gc_base[1] || gc_base[2]) return 0; return -ENODEV;}void __exit gc_exit(void){ int i, j; for (i = 0; i < 3; i++) if (gc_base[i]) { for (j = 0; j < 5; j++) if (gc_base[i]->pads[0] & gc_status_bit[j]) input_unregister_device(gc_base[i]->dev + j); parport_unregister_device(gc_base[i]->pd); }}module_init(gc_init);module_exit(gc_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -