📄 gamecon.c
字号:
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[7]) - !!(s & data[6])); input_report_abs(dev + i, ABS_Y, !!(s & data[5]) - !!(s & data[4])); } 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]]); } }/* * 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[3]) - !!(s & data[2])); input_report_abs(dev + i, ABS_Y, !!(s & data[1]) - !!(s & data[0])); 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]); } }/* * PSX controllers */ if (gc->pads[GC_PSX]) { for (i = 0; i < 5; i++) if (gc->pads[GC_PSX] & gc_status_bit[i]) break; switch (gc_psx_read_packet(gc, 6, data)) { case GC_PSX_ANALOGG: for (j = 0; j < 4; j++) input_report_abs(dev + i, gc_psx_abs[j], data[j + 2]); input_report_abs(dev + i, ABS_HAT0X, !!(data[0]&0x20) - !!(data[0]&0x80)); input_report_abs(dev + i, ABS_HAT0Y, !!(data[0]&0x40) - !!(data[0]&0x10)); for (j = 0; j < 8; j++) input_report_key(dev + i, gc_psx_btn[j], ~data[1] & (1 << i)); input_report_key(dev + i, BTN_START, ~data[0] & 0x08); input_report_key(dev + i, BTN_SELECT, ~data[0] & 0x01); break; case GC_PSX_ANALOGR: input_report_key(dev + i, BTN_THUMB, ~data[0] & 0x04); input_report_key(dev + i, BTN_THUMB2, ~data[0] & 0x02); case GC_PSX_NORMAL: case GC_PSX_NEGCON: input_report_abs(dev + i, ABS_X, 128 + !!(data[0] & 0x20) * 127 - !!(data[0] & 0x80) * 128); input_report_abs(dev + i, ABS_Y, 128 + !!(data[0] & 0x40) * 127 - !!(data[0] & 0x10) * 128); for (j = 0; j < 8; j++) input_report_key(dev + i, gc_psx_btn[j], ~data[1] & (1 << i)); input_report_key(dev + i, BTN_START, ~data[0] & 0x08); input_report_key(dev + i, BTN_SELECT, ~data[0] & 0x01); 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){ struct gc *gc; struct parport *pp; int i, j, psx, pbtn; unsigned char data[2]; if (config[0] < 0) return NULL; for (pp = parport_enumerate(); pp && (config[0] > 0); pp = pp->next) config[0]--; if (!pp) { printk(KERN_ERR "gamecon.c: no such parport\n"); return NULL; } if (!(gc = kmalloc(sizeof(struct gc), GFP_KERNEL))) return NULL; memset(gc, 0, sizeof(struct gc)); gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); 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 < 5; 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: psx = gc_psx_read_packet(gc, 2, data); switch(psx) { case GC_PSX_NEGCON: config[i + 1] += 1; case GC_PSX_NORMAL: pbtn = 10; break; case GC_PSX_ANALOGG: case GC_PSX_ANALOGR: config[i + 1] += 2; pbtn = 12; for (j = 0; j < 6; j++) { psx = gc_psx_abs[j]; set_bit(psx, gc->dev[i].absbit); gc->dev[i].absmin[psx] = 4; gc->dev[i].absmax[psx] = 252; gc->dev[i].absflat[psx] = 2; } break; case -1: gc->pads[GC_PSX] &= ~gc_status_bit[i]; pbtn = 0; printk(KERN_ERR "gamecon.c: No PSX controller found.\n"); break; default: gc->pads[GC_PSX] &= ~gc_status_bit[i]; pbtn = 0; printk(KERN_WARNING "gamecon.c: Unsupported PSX controller %#x," " please report to <vojtech@suse.cz>.\n", psx); } for (j = 0; j < pbtn; j++) set_bit(gc_psx_btn[j], gc->dev[i].keybit); break; } gc->dev[i].name = gc_names[config[i + 1]]; gc->dev[i].idbus = BUS_PARPORT; gc->dev[i].idvendor = 0x0001; gc->dev[i].idproduct = config[i + 1]; gc->dev[i].idversion = 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%d: %s on %s\n", gc->dev[i].number, gc->dev[i].name, gc->pd->port->name); } return gc;}#ifndef MODULEint __init gc_setup(char *str){ int i, ints[7]; get_options(str, ARRAY_SIZE(ints), ints); for (i = 0; i <= ints[0] && i < 6; i++) gc[i] = ints[i + 1]; return 1;}int __init gc_setup_2(char *str){ int i, ints[7]; get_options(str, ARRAY_SIZE(ints), ints); for (i = 0; i <= ints[0] && i < 6; i++) gc_2[i] = ints[i + 1]; return 1;}int __init gc_setup_3(char *str){ int i, ints[7]; get_options(str, ARRAY_SIZE(ints), ints); for (i = 0; i <= ints[0] && i < 6; i++) gc_3[i] = ints[i + 1]; return 1;}__setup("gc=", gc_setup);__setup("gc_2=", gc_setup_2);__setup("gc_3=", gc_setup_3);#endifint __init gc_init(void){ gc_base[0] = gc_probe(gc); gc_base[1] = gc_probe(gc_2); gc_base[2] = gc_probe(gc_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 + -