162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 1999-2004 Vojtech Pavlik <vojtech@suse.cz> 662306a36Sopenharmony_ci * Copyright (c) 2004 Peter Nelson <rufus-kernel@hackish.org> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Based on the work of: 962306a36Sopenharmony_ci * Andree Borrmann John Dahlstrom 1062306a36Sopenharmony_ci * David Kuder Nathan Hand 1162306a36Sopenharmony_ci * Raphael Assenat 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include <linux/kernel.h> 1762306a36Sopenharmony_ci#include <linux/delay.h> 1862306a36Sopenharmony_ci#include <linux/module.h> 1962306a36Sopenharmony_ci#include <linux/init.h> 2062306a36Sopenharmony_ci#include <linux/parport.h> 2162306a36Sopenharmony_ci#include <linux/input.h> 2262306a36Sopenharmony_ci#include <linux/mutex.h> 2362306a36Sopenharmony_ci#include <linux/slab.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ciMODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 2662306a36Sopenharmony_ciMODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver"); 2762306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#define GC_MAX_PORTS 3 3062306a36Sopenharmony_ci#define GC_MAX_DEVICES 5 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistruct gc_config { 3362306a36Sopenharmony_ci int args[GC_MAX_DEVICES + 1]; 3462306a36Sopenharmony_ci unsigned int nargs; 3562306a36Sopenharmony_ci}; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic struct gc_config gc_cfg[GC_MAX_PORTS]; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cimodule_param_array_named(map, gc_cfg[0].args, int, &gc_cfg[0].nargs, 0); 4062306a36Sopenharmony_ciMODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)"); 4162306a36Sopenharmony_cimodule_param_array_named(map2, gc_cfg[1].args, int, &gc_cfg[1].nargs, 0); 4262306a36Sopenharmony_ciMODULE_PARM_DESC(map2, "Describes second set of devices"); 4362306a36Sopenharmony_cimodule_param_array_named(map3, gc_cfg[2].args, int, &gc_cfg[2].nargs, 0); 4462306a36Sopenharmony_ciMODULE_PARM_DESC(map3, "Describes third set of devices"); 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* see also gs_psx_delay parameter in PSX support section */ 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cienum gc_type { 4962306a36Sopenharmony_ci GC_NONE = 0, 5062306a36Sopenharmony_ci GC_SNES, 5162306a36Sopenharmony_ci GC_NES, 5262306a36Sopenharmony_ci GC_NES4, 5362306a36Sopenharmony_ci GC_MULTI, 5462306a36Sopenharmony_ci GC_MULTI2, 5562306a36Sopenharmony_ci GC_N64, 5662306a36Sopenharmony_ci GC_PSX, 5762306a36Sopenharmony_ci GC_DDR, 5862306a36Sopenharmony_ci GC_SNESMOUSE, 5962306a36Sopenharmony_ci GC_MAX 6062306a36Sopenharmony_ci}; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#define GC_REFRESH_TIME HZ/100 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistruct gc_pad { 6562306a36Sopenharmony_ci struct input_dev *dev; 6662306a36Sopenharmony_ci enum gc_type type; 6762306a36Sopenharmony_ci char phys[32]; 6862306a36Sopenharmony_ci}; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistruct gc { 7162306a36Sopenharmony_ci struct pardevice *pd; 7262306a36Sopenharmony_ci struct gc_pad pads[GC_MAX_DEVICES]; 7362306a36Sopenharmony_ci struct timer_list timer; 7462306a36Sopenharmony_ci int pad_count[GC_MAX]; 7562306a36Sopenharmony_ci int used; 7662306a36Sopenharmony_ci int parportno; 7762306a36Sopenharmony_ci struct mutex mutex; 7862306a36Sopenharmony_ci}; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistruct gc_subdev { 8162306a36Sopenharmony_ci unsigned int idx; 8262306a36Sopenharmony_ci}; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistatic struct gc *gc_base[3]; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic const int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 }; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic const char *gc_names[] = { 8962306a36Sopenharmony_ci NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick", 9062306a36Sopenharmony_ci "Multisystem 2-button joystick", "N64 controller", "PSX controller", 9162306a36Sopenharmony_ci "PSX DDR controller", "SNES mouse" 9262306a36Sopenharmony_ci}; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci/* 9562306a36Sopenharmony_ci * N64 support. 9662306a36Sopenharmony_ci */ 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_cistatic const unsigned char gc_n64_bytes[] = { 0, 1, 13, 15, 14, 12, 10, 11, 2, 3 }; 9962306a36Sopenharmony_cistatic const short gc_n64_btn[] = { 10062306a36Sopenharmony_ci BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, 10162306a36Sopenharmony_ci BTN_TL, BTN_TR, BTN_TRIGGER, BTN_START 10262306a36Sopenharmony_ci}; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci#define GC_N64_LENGTH 32 /* N64 bit length, not including stop bit */ 10562306a36Sopenharmony_ci#define GC_N64_STOP_LENGTH 5 /* Length of encoded stop bit */ 10662306a36Sopenharmony_ci#define GC_N64_CMD_00 0x11111111UL 10762306a36Sopenharmony_ci#define GC_N64_CMD_01 0xd1111111UL 10862306a36Sopenharmony_ci#define GC_N64_CMD_03 0xdd111111UL 10962306a36Sopenharmony_ci#define GC_N64_CMD_1b 0xdd1dd111UL 11062306a36Sopenharmony_ci#define GC_N64_CMD_c0 0x111111ddUL 11162306a36Sopenharmony_ci#define GC_N64_CMD_80 0x1111111dUL 11262306a36Sopenharmony_ci#define GC_N64_STOP_BIT 0x1d /* Encoded stop bit */ 11362306a36Sopenharmony_ci#define GC_N64_REQUEST_DATA GC_N64_CMD_01 /* the request data command */ 11462306a36Sopenharmony_ci#define GC_N64_DELAY 133 /* delay between transmit request, and response ready (us) */ 11562306a36Sopenharmony_ci#define GC_N64_DWS 3 /* delay between write segments (required for sound playback because of ISA DMA) */ 11662306a36Sopenharmony_ci /* GC_N64_DWS > 24 is known to fail */ 11762306a36Sopenharmony_ci#define GC_N64_POWER_W 0xe2 /* power during write (transmit request) */ 11862306a36Sopenharmony_ci#define GC_N64_POWER_R 0xfd /* power during read */ 11962306a36Sopenharmony_ci#define GC_N64_OUT 0x1d /* output bits to the 4 pads */ 12062306a36Sopenharmony_ci /* Reading the main axes of any N64 pad is known to fail if the corresponding bit */ 12162306a36Sopenharmony_ci /* in GC_N64_OUT is pulled low on the output port (by any routine) for more */ 12262306a36Sopenharmony_ci /* than 123 us */ 12362306a36Sopenharmony_ci#define GC_N64_CLOCK 0x02 /* clock bits for read */ 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci/* 12662306a36Sopenharmony_ci * Used for rumble code. 12762306a36Sopenharmony_ci */ 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci/* Send encoded command */ 13062306a36Sopenharmony_cistatic void gc_n64_send_command(struct gc *gc, unsigned long cmd, 13162306a36Sopenharmony_ci unsigned char target) 13262306a36Sopenharmony_ci{ 13362306a36Sopenharmony_ci struct parport *port = gc->pd->port; 13462306a36Sopenharmony_ci int i; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci for (i = 0; i < GC_N64_LENGTH; i++) { 13762306a36Sopenharmony_ci unsigned char data = (cmd >> i) & 1 ? target : 0; 13862306a36Sopenharmony_ci parport_write_data(port, GC_N64_POWER_W | data); 13962306a36Sopenharmony_ci udelay(GC_N64_DWS); 14062306a36Sopenharmony_ci } 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci/* Send stop bit */ 14462306a36Sopenharmony_cistatic void gc_n64_send_stop_bit(struct gc *gc, unsigned char target) 14562306a36Sopenharmony_ci{ 14662306a36Sopenharmony_ci struct parport *port = gc->pd->port; 14762306a36Sopenharmony_ci int i; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci for (i = 0; i < GC_N64_STOP_LENGTH; i++) { 15062306a36Sopenharmony_ci unsigned char data = (GC_N64_STOP_BIT >> i) & 1 ? target : 0; 15162306a36Sopenharmony_ci parport_write_data(port, GC_N64_POWER_W | data); 15262306a36Sopenharmony_ci udelay(GC_N64_DWS); 15362306a36Sopenharmony_ci } 15462306a36Sopenharmony_ci} 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci/* 15762306a36Sopenharmony_ci * gc_n64_read_packet() reads an N64 packet. 15862306a36Sopenharmony_ci * Each pad uses one bit per byte. So all pads connected to this port 15962306a36Sopenharmony_ci * are read in parallel. 16062306a36Sopenharmony_ci */ 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_cistatic void gc_n64_read_packet(struct gc *gc, unsigned char *data) 16362306a36Sopenharmony_ci{ 16462306a36Sopenharmony_ci int i; 16562306a36Sopenharmony_ci unsigned long flags; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci/* 16862306a36Sopenharmony_ci * Request the pad to transmit data 16962306a36Sopenharmony_ci */ 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci local_irq_save(flags); 17262306a36Sopenharmony_ci gc_n64_send_command(gc, GC_N64_REQUEST_DATA, GC_N64_OUT); 17362306a36Sopenharmony_ci gc_n64_send_stop_bit(gc, GC_N64_OUT); 17462306a36Sopenharmony_ci local_irq_restore(flags); 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci/* 17762306a36Sopenharmony_ci * Wait for the pad response to be loaded into the 33-bit register 17862306a36Sopenharmony_ci * of the adapter. 17962306a36Sopenharmony_ci */ 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci udelay(GC_N64_DELAY); 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci/* 18462306a36Sopenharmony_ci * Grab data (ignoring the last bit, which is a stop bit) 18562306a36Sopenharmony_ci */ 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci for (i = 0; i < GC_N64_LENGTH; i++) { 18862306a36Sopenharmony_ci parport_write_data(gc->pd->port, GC_N64_POWER_R); 18962306a36Sopenharmony_ci udelay(2); 19062306a36Sopenharmony_ci data[i] = parport_read_status(gc->pd->port); 19162306a36Sopenharmony_ci parport_write_data(gc->pd->port, GC_N64_POWER_R | GC_N64_CLOCK); 19262306a36Sopenharmony_ci } 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci/* 19562306a36Sopenharmony_ci * We must wait 200 ms here for the controller to reinitialize before 19662306a36Sopenharmony_ci * the next read request. No worries as long as gc_read is polled less 19762306a36Sopenharmony_ci * frequently than this. 19862306a36Sopenharmony_ci */ 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci} 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_cistatic void gc_n64_process_packet(struct gc *gc) 20362306a36Sopenharmony_ci{ 20462306a36Sopenharmony_ci unsigned char data[GC_N64_LENGTH]; 20562306a36Sopenharmony_ci struct input_dev *dev; 20662306a36Sopenharmony_ci int i, j, s; 20762306a36Sopenharmony_ci signed char x, y; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci gc_n64_read_packet(gc, data); 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci for (i = 0; i < GC_MAX_DEVICES; i++) { 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci if (gc->pads[i].type != GC_N64) 21462306a36Sopenharmony_ci continue; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci dev = gc->pads[i].dev; 21762306a36Sopenharmony_ci s = gc_status_bit[i]; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci if (s & ~(data[8] | data[9])) { 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci x = y = 0; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci for (j = 0; j < 8; j++) { 22462306a36Sopenharmony_ci if (data[23 - j] & s) 22562306a36Sopenharmony_ci x |= 1 << j; 22662306a36Sopenharmony_ci if (data[31 - j] & s) 22762306a36Sopenharmony_ci y |= 1 << j; 22862306a36Sopenharmony_ci } 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci input_report_abs(dev, ABS_X, x); 23162306a36Sopenharmony_ci input_report_abs(dev, ABS_Y, -y); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci input_report_abs(dev, ABS_HAT0X, 23462306a36Sopenharmony_ci !(s & data[6]) - !(s & data[7])); 23562306a36Sopenharmony_ci input_report_abs(dev, ABS_HAT0Y, 23662306a36Sopenharmony_ci !(s & data[4]) - !(s & data[5])); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci for (j = 0; j < 10; j++) 23962306a36Sopenharmony_ci input_report_key(dev, gc_n64_btn[j], 24062306a36Sopenharmony_ci s & data[gc_n64_bytes[j]]); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci input_sync(dev); 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci} 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cistatic int gc_n64_play_effect(struct input_dev *dev, void *data, 24862306a36Sopenharmony_ci struct ff_effect *effect) 24962306a36Sopenharmony_ci{ 25062306a36Sopenharmony_ci int i; 25162306a36Sopenharmony_ci unsigned long flags; 25262306a36Sopenharmony_ci struct gc *gc = input_get_drvdata(dev); 25362306a36Sopenharmony_ci struct gc_subdev *sdev = data; 25462306a36Sopenharmony_ci unsigned char target = 1 << sdev->idx; /* select desired pin */ 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci if (effect->type == FF_RUMBLE) { 25762306a36Sopenharmony_ci struct ff_rumble_effect *rumble = &effect->u.rumble; 25862306a36Sopenharmony_ci unsigned int cmd = 25962306a36Sopenharmony_ci rumble->strong_magnitude || rumble->weak_magnitude ? 26062306a36Sopenharmony_ci GC_N64_CMD_01 : GC_N64_CMD_00; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci local_irq_save(flags); 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci /* Init Rumble - 0x03, 0x80, 0x01, (34)0x80 */ 26562306a36Sopenharmony_ci gc_n64_send_command(gc, GC_N64_CMD_03, target); 26662306a36Sopenharmony_ci gc_n64_send_command(gc, GC_N64_CMD_80, target); 26762306a36Sopenharmony_ci gc_n64_send_command(gc, GC_N64_CMD_01, target); 26862306a36Sopenharmony_ci for (i = 0; i < 32; i++) 26962306a36Sopenharmony_ci gc_n64_send_command(gc, GC_N64_CMD_80, target); 27062306a36Sopenharmony_ci gc_n64_send_stop_bit(gc, target); 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci udelay(GC_N64_DELAY); 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci /* Now start or stop it - 0x03, 0xc0, 0zx1b, (32)0x01/0x00 */ 27562306a36Sopenharmony_ci gc_n64_send_command(gc, GC_N64_CMD_03, target); 27662306a36Sopenharmony_ci gc_n64_send_command(gc, GC_N64_CMD_c0, target); 27762306a36Sopenharmony_ci gc_n64_send_command(gc, GC_N64_CMD_1b, target); 27862306a36Sopenharmony_ci for (i = 0; i < 32; i++) 27962306a36Sopenharmony_ci gc_n64_send_command(gc, cmd, target); 28062306a36Sopenharmony_ci gc_n64_send_stop_bit(gc, target); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci local_irq_restore(flags); 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci return 0; 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_cistatic int gc_n64_init_ff(struct input_dev *dev, int i) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci struct gc_subdev *sdev; 29262306a36Sopenharmony_ci int err; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci sdev = kmalloc(sizeof(*sdev), GFP_KERNEL); 29562306a36Sopenharmony_ci if (!sdev) 29662306a36Sopenharmony_ci return -ENOMEM; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci sdev->idx = i; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci input_set_capability(dev, EV_FF, FF_RUMBLE); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci err = input_ff_create_memless(dev, sdev, gc_n64_play_effect); 30362306a36Sopenharmony_ci if (err) { 30462306a36Sopenharmony_ci kfree(sdev); 30562306a36Sopenharmony_ci return err; 30662306a36Sopenharmony_ci } 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci return 0; 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci/* 31262306a36Sopenharmony_ci * NES/SNES support. 31362306a36Sopenharmony_ci */ 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci#define GC_NES_DELAY 6 /* Delay between bits - 6us */ 31662306a36Sopenharmony_ci#define GC_NES_LENGTH 8 /* The NES pads use 8 bits of data */ 31762306a36Sopenharmony_ci#define GC_SNES_LENGTH 12 /* The SNES true length is 16, but the 31862306a36Sopenharmony_ci last 4 bits are unused */ 31962306a36Sopenharmony_ci#define GC_SNESMOUSE_LENGTH 32 /* The SNES mouse uses 32 bits, the first 32062306a36Sopenharmony_ci 16 bits are equivalent to a gamepad */ 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci#define GC_NES_POWER 0xfc 32362306a36Sopenharmony_ci#define GC_NES_CLOCK 0x01 32462306a36Sopenharmony_ci#define GC_NES_LATCH 0x02 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_cistatic const unsigned char gc_nes_bytes[] = { 0, 1, 2, 3 }; 32762306a36Sopenharmony_cistatic const unsigned char gc_snes_bytes[] = { 8, 0, 2, 3, 9, 1, 10, 11 }; 32862306a36Sopenharmony_cistatic const short gc_snes_btn[] = { 32962306a36Sopenharmony_ci BTN_A, BTN_B, BTN_SELECT, BTN_START, BTN_X, BTN_Y, BTN_TL, BTN_TR 33062306a36Sopenharmony_ci}; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci/* 33362306a36Sopenharmony_ci * gc_nes_read_packet() reads a NES/SNES packet. 33462306a36Sopenharmony_ci * Each pad uses one bit per byte. So all pads connected to 33562306a36Sopenharmony_ci * this port are read in parallel. 33662306a36Sopenharmony_ci */ 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_cistatic void gc_nes_read_packet(struct gc *gc, int length, unsigned char *data) 33962306a36Sopenharmony_ci{ 34062306a36Sopenharmony_ci int i; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK | GC_NES_LATCH); 34362306a36Sopenharmony_ci udelay(GC_NES_DELAY * 2); 34462306a36Sopenharmony_ci parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci for (i = 0; i < length; i++) { 34762306a36Sopenharmony_ci udelay(GC_NES_DELAY); 34862306a36Sopenharmony_ci parport_write_data(gc->pd->port, GC_NES_POWER); 34962306a36Sopenharmony_ci data[i] = parport_read_status(gc->pd->port) ^ 0x7f; 35062306a36Sopenharmony_ci udelay(GC_NES_DELAY); 35162306a36Sopenharmony_ci parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK); 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci} 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_cistatic void gc_nes_process_packet(struct gc *gc) 35662306a36Sopenharmony_ci{ 35762306a36Sopenharmony_ci unsigned char data[GC_SNESMOUSE_LENGTH]; 35862306a36Sopenharmony_ci struct gc_pad *pad; 35962306a36Sopenharmony_ci struct input_dev *dev; 36062306a36Sopenharmony_ci int i, j, s, len; 36162306a36Sopenharmony_ci char x_rel, y_rel; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci len = gc->pad_count[GC_SNESMOUSE] ? GC_SNESMOUSE_LENGTH : 36462306a36Sopenharmony_ci (gc->pad_count[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci gc_nes_read_packet(gc, len, data); 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci for (i = 0; i < GC_MAX_DEVICES; i++) { 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci pad = &gc->pads[i]; 37162306a36Sopenharmony_ci dev = pad->dev; 37262306a36Sopenharmony_ci s = gc_status_bit[i]; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci switch (pad->type) { 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci case GC_NES: 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci input_report_abs(dev, ABS_X, !(s & data[6]) - !(s & data[7])); 37962306a36Sopenharmony_ci input_report_abs(dev, ABS_Y, !(s & data[4]) - !(s & data[5])); 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci for (j = 0; j < 4; j++) 38262306a36Sopenharmony_ci input_report_key(dev, gc_snes_btn[j], 38362306a36Sopenharmony_ci s & data[gc_nes_bytes[j]]); 38462306a36Sopenharmony_ci input_sync(dev); 38562306a36Sopenharmony_ci break; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci case GC_SNES: 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci input_report_abs(dev, ABS_X, !(s & data[6]) - !(s & data[7])); 39062306a36Sopenharmony_ci input_report_abs(dev, ABS_Y, !(s & data[4]) - !(s & data[5])); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci for (j = 0; j < 8; j++) 39362306a36Sopenharmony_ci input_report_key(dev, gc_snes_btn[j], 39462306a36Sopenharmony_ci s & data[gc_snes_bytes[j]]); 39562306a36Sopenharmony_ci input_sync(dev); 39662306a36Sopenharmony_ci break; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci case GC_SNESMOUSE: 39962306a36Sopenharmony_ci /* 40062306a36Sopenharmony_ci * The 4 unused bits from SNES controllers appear 40162306a36Sopenharmony_ci * to be ID bits so use them to make sure we are 40262306a36Sopenharmony_ci * dealing with a mouse. 40362306a36Sopenharmony_ci * gamepad is connected. This is important since 40462306a36Sopenharmony_ci * my SNES gamepad sends 1's for bits 16-31, which 40562306a36Sopenharmony_ci * cause the mouse pointer to quickly move to the 40662306a36Sopenharmony_ci * upper left corner of the screen. 40762306a36Sopenharmony_ci */ 40862306a36Sopenharmony_ci if (!(s & data[12]) && !(s & data[13]) && 40962306a36Sopenharmony_ci !(s & data[14]) && (s & data[15])) { 41062306a36Sopenharmony_ci input_report_key(dev, BTN_LEFT, s & data[9]); 41162306a36Sopenharmony_ci input_report_key(dev, BTN_RIGHT, s & data[8]); 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci x_rel = y_rel = 0; 41462306a36Sopenharmony_ci for (j = 0; j < 7; j++) { 41562306a36Sopenharmony_ci x_rel <<= 1; 41662306a36Sopenharmony_ci if (data[25 + j] & s) 41762306a36Sopenharmony_ci x_rel |= 1; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci y_rel <<= 1; 42062306a36Sopenharmony_ci if (data[17 + j] & s) 42162306a36Sopenharmony_ci y_rel |= 1; 42262306a36Sopenharmony_ci } 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci if (x_rel) { 42562306a36Sopenharmony_ci if (data[24] & s) 42662306a36Sopenharmony_ci x_rel = -x_rel; 42762306a36Sopenharmony_ci input_report_rel(dev, REL_X, x_rel); 42862306a36Sopenharmony_ci } 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci if (y_rel) { 43162306a36Sopenharmony_ci if (data[16] & s) 43262306a36Sopenharmony_ci y_rel = -y_rel; 43362306a36Sopenharmony_ci input_report_rel(dev, REL_Y, y_rel); 43462306a36Sopenharmony_ci } 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci input_sync(dev); 43762306a36Sopenharmony_ci } 43862306a36Sopenharmony_ci break; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci default: 44162306a36Sopenharmony_ci break; 44262306a36Sopenharmony_ci } 44362306a36Sopenharmony_ci } 44462306a36Sopenharmony_ci} 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci/* 44762306a36Sopenharmony_ci * Multisystem joystick support 44862306a36Sopenharmony_ci */ 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci#define GC_MULTI_LENGTH 5 /* Multi system joystick packet length is 5 */ 45162306a36Sopenharmony_ci#define GC_MULTI2_LENGTH 6 /* One more bit for one more button */ 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci/* 45462306a36Sopenharmony_ci * gc_multi_read_packet() reads a Multisystem joystick packet. 45562306a36Sopenharmony_ci */ 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_cistatic void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data) 45862306a36Sopenharmony_ci{ 45962306a36Sopenharmony_ci int i; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci for (i = 0; i < length; i++) { 46262306a36Sopenharmony_ci parport_write_data(gc->pd->port, ~(1 << i)); 46362306a36Sopenharmony_ci data[i] = parport_read_status(gc->pd->port) ^ 0x7f; 46462306a36Sopenharmony_ci } 46562306a36Sopenharmony_ci} 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_cistatic void gc_multi_process_packet(struct gc *gc) 46862306a36Sopenharmony_ci{ 46962306a36Sopenharmony_ci unsigned char data[GC_MULTI2_LENGTH]; 47062306a36Sopenharmony_ci int data_len = gc->pad_count[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH; 47162306a36Sopenharmony_ci struct gc_pad *pad; 47262306a36Sopenharmony_ci struct input_dev *dev; 47362306a36Sopenharmony_ci int i, s; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci gc_multi_read_packet(gc, data_len, data); 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci for (i = 0; i < GC_MAX_DEVICES; i++) { 47862306a36Sopenharmony_ci pad = &gc->pads[i]; 47962306a36Sopenharmony_ci dev = pad->dev; 48062306a36Sopenharmony_ci s = gc_status_bit[i]; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci switch (pad->type) { 48362306a36Sopenharmony_ci case GC_MULTI2: 48462306a36Sopenharmony_ci input_report_key(dev, BTN_THUMB, s & data[5]); 48562306a36Sopenharmony_ci fallthrough; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci case GC_MULTI: 48862306a36Sopenharmony_ci input_report_abs(dev, ABS_X, 48962306a36Sopenharmony_ci !(s & data[2]) - !(s & data[3])); 49062306a36Sopenharmony_ci input_report_abs(dev, ABS_Y, 49162306a36Sopenharmony_ci !(s & data[0]) - !(s & data[1])); 49262306a36Sopenharmony_ci input_report_key(dev, BTN_TRIGGER, s & data[4]); 49362306a36Sopenharmony_ci input_sync(dev); 49462306a36Sopenharmony_ci break; 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci default: 49762306a36Sopenharmony_ci break; 49862306a36Sopenharmony_ci } 49962306a36Sopenharmony_ci } 50062306a36Sopenharmony_ci} 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci/* 50362306a36Sopenharmony_ci * PSX support 50462306a36Sopenharmony_ci * 50562306a36Sopenharmony_ci * See documentation at: 50662306a36Sopenharmony_ci * http://www.geocities.co.jp/Playtown/2004/psx/ps_eng.txt 50762306a36Sopenharmony_ci * http://www.gamesx.com/controldata/psxcont/psxcont.htm 50862306a36Sopenharmony_ci * 50962306a36Sopenharmony_ci */ 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci#define GC_PSX_DELAY 25 /* 25 usec */ 51262306a36Sopenharmony_ci#define GC_PSX_LENGTH 8 /* talk to the controller in bits */ 51362306a36Sopenharmony_ci#define GC_PSX_BYTES 6 /* the maximum number of bytes to read off the controller */ 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci#define GC_PSX_MOUSE 1 /* Mouse */ 51662306a36Sopenharmony_ci#define GC_PSX_NEGCON 2 /* NegCon */ 51762306a36Sopenharmony_ci#define GC_PSX_NORMAL 4 /* Digital / Analog or Rumble in Digital mode */ 51862306a36Sopenharmony_ci#define GC_PSX_ANALOG 5 /* Analog in Analog mode / Rumble in Green mode */ 51962306a36Sopenharmony_ci#define GC_PSX_RUMBLE 7 /* Rumble in Red mode */ 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci#define GC_PSX_CLOCK 0x04 /* Pin 4 */ 52262306a36Sopenharmony_ci#define GC_PSX_COMMAND 0x01 /* Pin 2 */ 52362306a36Sopenharmony_ci#define GC_PSX_POWER 0xf8 /* Pins 5-9 */ 52462306a36Sopenharmony_ci#define GC_PSX_SELECT 0x02 /* Pin 3 */ 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci#define GC_PSX_ID(x) ((x) >> 4) /* High nibble is device type */ 52762306a36Sopenharmony_ci#define GC_PSX_LEN(x) (((x) & 0xf) << 1) /* Low nibble is length in bytes/2 */ 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_cistatic int gc_psx_delay = GC_PSX_DELAY; 53062306a36Sopenharmony_cimodule_param_named(psx_delay, gc_psx_delay, uint, 0); 53162306a36Sopenharmony_ciMODULE_PARM_DESC(psx_delay, "Delay when accessing Sony PSX controller (usecs)"); 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_cistatic const short gc_psx_abs[] = { 53462306a36Sopenharmony_ci ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y 53562306a36Sopenharmony_ci}; 53662306a36Sopenharmony_cistatic const short gc_psx_btn[] = { 53762306a36Sopenharmony_ci BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y, 53862306a36Sopenharmony_ci BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR 53962306a36Sopenharmony_ci}; 54062306a36Sopenharmony_cistatic const short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 }; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci/* 54362306a36Sopenharmony_ci * gc_psx_command() writes 8bit command and reads 8bit data from 54462306a36Sopenharmony_ci * the psx pad. 54562306a36Sopenharmony_ci */ 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_cistatic void gc_psx_command(struct gc *gc, int b, unsigned char *data) 54862306a36Sopenharmony_ci{ 54962306a36Sopenharmony_ci struct parport *port = gc->pd->port; 55062306a36Sopenharmony_ci int i, j, cmd, read; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci memset(data, 0, GC_MAX_DEVICES); 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci for (i = 0; i < GC_PSX_LENGTH; i++, b >>= 1) { 55562306a36Sopenharmony_ci cmd = (b & 1) ? GC_PSX_COMMAND : 0; 55662306a36Sopenharmony_ci parport_write_data(port, cmd | GC_PSX_POWER); 55762306a36Sopenharmony_ci udelay(gc_psx_delay); 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci read = parport_read_status(port) ^ 0x80; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci for (j = 0; j < GC_MAX_DEVICES; j++) { 56262306a36Sopenharmony_ci struct gc_pad *pad = &gc->pads[j]; 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci if (pad->type == GC_PSX || pad->type == GC_DDR) 56562306a36Sopenharmony_ci data[j] |= (read & gc_status_bit[j]) ? (1 << i) : 0; 56662306a36Sopenharmony_ci } 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER); 56962306a36Sopenharmony_ci udelay(gc_psx_delay); 57062306a36Sopenharmony_ci } 57162306a36Sopenharmony_ci} 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci/* 57462306a36Sopenharmony_ci * gc_psx_read_packet() reads a whole psx packet and returns 57562306a36Sopenharmony_ci * device identifier code. 57662306a36Sopenharmony_ci */ 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_cistatic void gc_psx_read_packet(struct gc *gc, 57962306a36Sopenharmony_ci unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES], 58062306a36Sopenharmony_ci unsigned char id[GC_MAX_DEVICES]) 58162306a36Sopenharmony_ci{ 58262306a36Sopenharmony_ci int i, j, max_len = 0; 58362306a36Sopenharmony_ci unsigned long flags; 58462306a36Sopenharmony_ci unsigned char data2[GC_MAX_DEVICES]; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci /* Select pad */ 58762306a36Sopenharmony_ci parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); 58862306a36Sopenharmony_ci udelay(gc_psx_delay); 58962306a36Sopenharmony_ci /* Deselect, begin command */ 59062306a36Sopenharmony_ci parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_POWER); 59162306a36Sopenharmony_ci udelay(gc_psx_delay); 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci local_irq_save(flags); 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci gc_psx_command(gc, 0x01, data2); /* Access pad */ 59662306a36Sopenharmony_ci gc_psx_command(gc, 0x42, id); /* Get device ids */ 59762306a36Sopenharmony_ci gc_psx_command(gc, 0, data2); /* Dump status */ 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci /* Find the longest pad */ 60062306a36Sopenharmony_ci for (i = 0; i < GC_MAX_DEVICES; i++) { 60162306a36Sopenharmony_ci struct gc_pad *pad = &gc->pads[i]; 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci if ((pad->type == GC_PSX || pad->type == GC_DDR) && 60462306a36Sopenharmony_ci GC_PSX_LEN(id[i]) > max_len && 60562306a36Sopenharmony_ci GC_PSX_LEN(id[i]) <= GC_PSX_BYTES) { 60662306a36Sopenharmony_ci max_len = GC_PSX_LEN(id[i]); 60762306a36Sopenharmony_ci } 60862306a36Sopenharmony_ci } 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci /* Read in all the data */ 61162306a36Sopenharmony_ci for (i = 0; i < max_len; i++) { 61262306a36Sopenharmony_ci gc_psx_command(gc, 0, data2); 61362306a36Sopenharmony_ci for (j = 0; j < GC_MAX_DEVICES; j++) 61462306a36Sopenharmony_ci data[j][i] = data2[j]; 61562306a36Sopenharmony_ci } 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci local_irq_restore(flags); 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci /* Set id's to the real value */ 62262306a36Sopenharmony_ci for (i = 0; i < GC_MAX_DEVICES; i++) 62362306a36Sopenharmony_ci id[i] = GC_PSX_ID(id[i]); 62462306a36Sopenharmony_ci} 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_cistatic void gc_psx_report_one(struct gc_pad *pad, unsigned char psx_type, 62762306a36Sopenharmony_ci unsigned char *data) 62862306a36Sopenharmony_ci{ 62962306a36Sopenharmony_ci struct input_dev *dev = pad->dev; 63062306a36Sopenharmony_ci int i; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci switch (psx_type) { 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci case GC_PSX_RUMBLE: 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci input_report_key(dev, BTN_THUMBL, ~data[0] & 0x04); 63762306a36Sopenharmony_ci input_report_key(dev, BTN_THUMBR, ~data[0] & 0x02); 63862306a36Sopenharmony_ci fallthrough; 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci case GC_PSX_NEGCON: 64162306a36Sopenharmony_ci case GC_PSX_ANALOG: 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci if (pad->type == GC_DDR) { 64462306a36Sopenharmony_ci for (i = 0; i < 4; i++) 64562306a36Sopenharmony_ci input_report_key(dev, gc_psx_ddr_btn[i], 64662306a36Sopenharmony_ci ~data[0] & (0x10 << i)); 64762306a36Sopenharmony_ci } else { 64862306a36Sopenharmony_ci for (i = 0; i < 4; i++) 64962306a36Sopenharmony_ci input_report_abs(dev, gc_psx_abs[i + 2], 65062306a36Sopenharmony_ci data[i + 2]); 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci input_report_abs(dev, ABS_X, 65362306a36Sopenharmony_ci !!(data[0] & 0x80) * 128 + !(data[0] & 0x20) * 127); 65462306a36Sopenharmony_ci input_report_abs(dev, ABS_Y, 65562306a36Sopenharmony_ci !!(data[0] & 0x10) * 128 + !(data[0] & 0x40) * 127); 65662306a36Sopenharmony_ci } 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci for (i = 0; i < 8; i++) 65962306a36Sopenharmony_ci input_report_key(dev, gc_psx_btn[i], ~data[1] & (1 << i)); 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci input_report_key(dev, BTN_START, ~data[0] & 0x08); 66262306a36Sopenharmony_ci input_report_key(dev, BTN_SELECT, ~data[0] & 0x01); 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci input_sync(dev); 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci break; 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci case GC_PSX_NORMAL: 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci if (pad->type == GC_DDR) { 67162306a36Sopenharmony_ci for (i = 0; i < 4; i++) 67262306a36Sopenharmony_ci input_report_key(dev, gc_psx_ddr_btn[i], 67362306a36Sopenharmony_ci ~data[0] & (0x10 << i)); 67462306a36Sopenharmony_ci } else { 67562306a36Sopenharmony_ci input_report_abs(dev, ABS_X, 67662306a36Sopenharmony_ci !!(data[0] & 0x80) * 128 + !(data[0] & 0x20) * 127); 67762306a36Sopenharmony_ci input_report_abs(dev, ABS_Y, 67862306a36Sopenharmony_ci !!(data[0] & 0x10) * 128 + !(data[0] & 0x40) * 127); 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci /* 68162306a36Sopenharmony_ci * For some reason if the extra axes are left unset 68262306a36Sopenharmony_ci * they drift. 68362306a36Sopenharmony_ci * for (i = 0; i < 4; i++) 68462306a36Sopenharmony_ci input_report_abs(dev, gc_psx_abs[i + 2], 128); 68562306a36Sopenharmony_ci * This needs to be debugged properly, 68662306a36Sopenharmony_ci * maybe fuzz processing needs to be done 68762306a36Sopenharmony_ci * in input_sync() 68862306a36Sopenharmony_ci * --vojtech 68962306a36Sopenharmony_ci */ 69062306a36Sopenharmony_ci } 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci for (i = 0; i < 8; i++) 69362306a36Sopenharmony_ci input_report_key(dev, gc_psx_btn[i], ~data[1] & (1 << i)); 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci input_report_key(dev, BTN_START, ~data[0] & 0x08); 69662306a36Sopenharmony_ci input_report_key(dev, BTN_SELECT, ~data[0] & 0x01); 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci input_sync(dev); 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci break; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci default: /* not a pad, ignore */ 70362306a36Sopenharmony_ci break; 70462306a36Sopenharmony_ci } 70562306a36Sopenharmony_ci} 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_cistatic void gc_psx_process_packet(struct gc *gc) 70862306a36Sopenharmony_ci{ 70962306a36Sopenharmony_ci unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES]; 71062306a36Sopenharmony_ci unsigned char id[GC_MAX_DEVICES]; 71162306a36Sopenharmony_ci struct gc_pad *pad; 71262306a36Sopenharmony_ci int i; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci gc_psx_read_packet(gc, data, id); 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci for (i = 0; i < GC_MAX_DEVICES; i++) { 71762306a36Sopenharmony_ci pad = &gc->pads[i]; 71862306a36Sopenharmony_ci if (pad->type == GC_PSX || pad->type == GC_DDR) 71962306a36Sopenharmony_ci gc_psx_report_one(pad, id[i], data[i]); 72062306a36Sopenharmony_ci } 72162306a36Sopenharmony_ci} 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci/* 72462306a36Sopenharmony_ci * gc_timer() initiates reads of console pads data. 72562306a36Sopenharmony_ci */ 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_cistatic void gc_timer(struct timer_list *t) 72862306a36Sopenharmony_ci{ 72962306a36Sopenharmony_ci struct gc *gc = from_timer(gc, t, timer); 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci/* 73262306a36Sopenharmony_ci * N64 pads - must be read first, any read confuses them for 200 us 73362306a36Sopenharmony_ci */ 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci if (gc->pad_count[GC_N64]) 73662306a36Sopenharmony_ci gc_n64_process_packet(gc); 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci/* 73962306a36Sopenharmony_ci * NES and SNES pads or mouse 74062306a36Sopenharmony_ci */ 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci if (gc->pad_count[GC_NES] || 74362306a36Sopenharmony_ci gc->pad_count[GC_SNES] || 74462306a36Sopenharmony_ci gc->pad_count[GC_SNESMOUSE]) { 74562306a36Sopenharmony_ci gc_nes_process_packet(gc); 74662306a36Sopenharmony_ci } 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci/* 74962306a36Sopenharmony_ci * Multi and Multi2 joysticks 75062306a36Sopenharmony_ci */ 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci if (gc->pad_count[GC_MULTI] || gc->pad_count[GC_MULTI2]) 75362306a36Sopenharmony_ci gc_multi_process_packet(gc); 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci/* 75662306a36Sopenharmony_ci * PSX controllers 75762306a36Sopenharmony_ci */ 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci if (gc->pad_count[GC_PSX] || gc->pad_count[GC_DDR]) 76062306a36Sopenharmony_ci gc_psx_process_packet(gc); 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); 76362306a36Sopenharmony_ci} 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_cistatic int gc_open(struct input_dev *dev) 76662306a36Sopenharmony_ci{ 76762306a36Sopenharmony_ci struct gc *gc = input_get_drvdata(dev); 76862306a36Sopenharmony_ci int err; 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci err = mutex_lock_interruptible(&gc->mutex); 77162306a36Sopenharmony_ci if (err) 77262306a36Sopenharmony_ci return err; 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci if (!gc->used++) { 77562306a36Sopenharmony_ci parport_claim(gc->pd); 77662306a36Sopenharmony_ci parport_write_control(gc->pd->port, 0x04); 77762306a36Sopenharmony_ci mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); 77862306a36Sopenharmony_ci } 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci mutex_unlock(&gc->mutex); 78162306a36Sopenharmony_ci return 0; 78262306a36Sopenharmony_ci} 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_cistatic void gc_close(struct input_dev *dev) 78562306a36Sopenharmony_ci{ 78662306a36Sopenharmony_ci struct gc *gc = input_get_drvdata(dev); 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci mutex_lock(&gc->mutex); 78962306a36Sopenharmony_ci if (!--gc->used) { 79062306a36Sopenharmony_ci del_timer_sync(&gc->timer); 79162306a36Sopenharmony_ci parport_write_control(gc->pd->port, 0x00); 79262306a36Sopenharmony_ci parport_release(gc->pd); 79362306a36Sopenharmony_ci } 79462306a36Sopenharmony_ci mutex_unlock(&gc->mutex); 79562306a36Sopenharmony_ci} 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_cistatic int gc_setup_pad(struct gc *gc, int idx, int pad_type) 79862306a36Sopenharmony_ci{ 79962306a36Sopenharmony_ci struct gc_pad *pad = &gc->pads[idx]; 80062306a36Sopenharmony_ci struct input_dev *input_dev; 80162306a36Sopenharmony_ci int i; 80262306a36Sopenharmony_ci int err; 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci if (pad_type < 1 || pad_type >= GC_MAX) { 80562306a36Sopenharmony_ci pr_err("Pad type %d unknown\n", pad_type); 80662306a36Sopenharmony_ci return -EINVAL; 80762306a36Sopenharmony_ci } 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci pad->dev = input_dev = input_allocate_device(); 81062306a36Sopenharmony_ci if (!input_dev) { 81162306a36Sopenharmony_ci pr_err("Not enough memory for input device\n"); 81262306a36Sopenharmony_ci return -ENOMEM; 81362306a36Sopenharmony_ci } 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci pad->type = pad_type; 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci snprintf(pad->phys, sizeof(pad->phys), 81862306a36Sopenharmony_ci "%s/input%d", gc->pd->port->name, idx); 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci input_dev->name = gc_names[pad_type]; 82162306a36Sopenharmony_ci input_dev->phys = pad->phys; 82262306a36Sopenharmony_ci input_dev->id.bustype = BUS_PARPORT; 82362306a36Sopenharmony_ci input_dev->id.vendor = 0x0001; 82462306a36Sopenharmony_ci input_dev->id.product = pad_type; 82562306a36Sopenharmony_ci input_dev->id.version = 0x0100; 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci input_set_drvdata(input_dev, gc); 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci input_dev->open = gc_open; 83062306a36Sopenharmony_ci input_dev->close = gc_close; 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ci if (pad_type != GC_SNESMOUSE) { 83362306a36Sopenharmony_ci input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci for (i = 0; i < 2; i++) 83662306a36Sopenharmony_ci input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0); 83762306a36Sopenharmony_ci } else 83862306a36Sopenharmony_ci input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci gc->pad_count[pad_type]++; 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci switch (pad_type) { 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci case GC_N64: 84562306a36Sopenharmony_ci for (i = 0; i < 10; i++) 84662306a36Sopenharmony_ci input_set_capability(input_dev, EV_KEY, gc_n64_btn[i]); 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci for (i = 0; i < 2; i++) { 84962306a36Sopenharmony_ci input_set_abs_params(input_dev, ABS_X + i, -127, 126, 0, 2); 85062306a36Sopenharmony_ci input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0); 85162306a36Sopenharmony_ci } 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci err = gc_n64_init_ff(input_dev, idx); 85462306a36Sopenharmony_ci if (err) { 85562306a36Sopenharmony_ci pr_warn("Failed to initiate rumble for N64 device %d\n", 85662306a36Sopenharmony_ci idx); 85762306a36Sopenharmony_ci goto err_free_dev; 85862306a36Sopenharmony_ci } 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci break; 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci case GC_SNESMOUSE: 86362306a36Sopenharmony_ci input_set_capability(input_dev, EV_KEY, BTN_LEFT); 86462306a36Sopenharmony_ci input_set_capability(input_dev, EV_KEY, BTN_RIGHT); 86562306a36Sopenharmony_ci input_set_capability(input_dev, EV_REL, REL_X); 86662306a36Sopenharmony_ci input_set_capability(input_dev, EV_REL, REL_Y); 86762306a36Sopenharmony_ci break; 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci case GC_SNES: 87062306a36Sopenharmony_ci for (i = 4; i < 8; i++) 87162306a36Sopenharmony_ci input_set_capability(input_dev, EV_KEY, gc_snes_btn[i]); 87262306a36Sopenharmony_ci fallthrough; 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci case GC_NES: 87562306a36Sopenharmony_ci for (i = 0; i < 4; i++) 87662306a36Sopenharmony_ci input_set_capability(input_dev, EV_KEY, gc_snes_btn[i]); 87762306a36Sopenharmony_ci break; 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci case GC_MULTI2: 88062306a36Sopenharmony_ci input_set_capability(input_dev, EV_KEY, BTN_THUMB); 88162306a36Sopenharmony_ci fallthrough; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci case GC_MULTI: 88462306a36Sopenharmony_ci input_set_capability(input_dev, EV_KEY, BTN_TRIGGER); 88562306a36Sopenharmony_ci break; 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci case GC_PSX: 88862306a36Sopenharmony_ci for (i = 0; i < 6; i++) 88962306a36Sopenharmony_ci input_set_abs_params(input_dev, 89062306a36Sopenharmony_ci gc_psx_abs[i], 4, 252, 0, 2); 89162306a36Sopenharmony_ci for (i = 0; i < 12; i++) 89262306a36Sopenharmony_ci input_set_capability(input_dev, EV_KEY, gc_psx_btn[i]); 89362306a36Sopenharmony_ci break; 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci break; 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci case GC_DDR: 89862306a36Sopenharmony_ci for (i = 0; i < 4; i++) 89962306a36Sopenharmony_ci input_set_capability(input_dev, EV_KEY, 90062306a36Sopenharmony_ci gc_psx_ddr_btn[i]); 90162306a36Sopenharmony_ci for (i = 0; i < 12; i++) 90262306a36Sopenharmony_ci input_set_capability(input_dev, EV_KEY, gc_psx_btn[i]); 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci break; 90562306a36Sopenharmony_ci } 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci err = input_register_device(pad->dev); 90862306a36Sopenharmony_ci if (err) 90962306a36Sopenharmony_ci goto err_free_dev; 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci return 0; 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_cierr_free_dev: 91462306a36Sopenharmony_ci input_free_device(pad->dev); 91562306a36Sopenharmony_ci pad->dev = NULL; 91662306a36Sopenharmony_ci return err; 91762306a36Sopenharmony_ci} 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_cistatic void gc_attach(struct parport *pp) 92062306a36Sopenharmony_ci{ 92162306a36Sopenharmony_ci struct gc *gc; 92262306a36Sopenharmony_ci struct pardevice *pd; 92362306a36Sopenharmony_ci int i, port_idx; 92462306a36Sopenharmony_ci int count = 0; 92562306a36Sopenharmony_ci int *pads, n_pads; 92662306a36Sopenharmony_ci struct pardev_cb gc_parport_cb; 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci for (port_idx = 0; port_idx < GC_MAX_PORTS; port_idx++) { 92962306a36Sopenharmony_ci if (gc_cfg[port_idx].nargs == 0 || gc_cfg[port_idx].args[0] < 0) 93062306a36Sopenharmony_ci continue; 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_ci if (gc_cfg[port_idx].args[0] == pp->number) 93362306a36Sopenharmony_ci break; 93462306a36Sopenharmony_ci } 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci if (port_idx == GC_MAX_PORTS) { 93762306a36Sopenharmony_ci pr_debug("Not using parport%d.\n", pp->number); 93862306a36Sopenharmony_ci return; 93962306a36Sopenharmony_ci } 94062306a36Sopenharmony_ci pads = gc_cfg[port_idx].args + 1; 94162306a36Sopenharmony_ci n_pads = gc_cfg[port_idx].nargs - 1; 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci memset(&gc_parport_cb, 0, sizeof(gc_parport_cb)); 94462306a36Sopenharmony_ci gc_parport_cb.flags = PARPORT_FLAG_EXCL; 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci pd = parport_register_dev_model(pp, "gamecon", &gc_parport_cb, 94762306a36Sopenharmony_ci port_idx); 94862306a36Sopenharmony_ci if (!pd) { 94962306a36Sopenharmony_ci pr_err("parport busy already - lp.o loaded?\n"); 95062306a36Sopenharmony_ci return; 95162306a36Sopenharmony_ci } 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_ci gc = kzalloc(sizeof(struct gc), GFP_KERNEL); 95462306a36Sopenharmony_ci if (!gc) { 95562306a36Sopenharmony_ci pr_err("Not enough memory\n"); 95662306a36Sopenharmony_ci goto err_unreg_pardev; 95762306a36Sopenharmony_ci } 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci mutex_init(&gc->mutex); 96062306a36Sopenharmony_ci gc->pd = pd; 96162306a36Sopenharmony_ci gc->parportno = pp->number; 96262306a36Sopenharmony_ci timer_setup(&gc->timer, gc_timer, 0); 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci for (i = 0; i < n_pads && i < GC_MAX_DEVICES; i++) { 96562306a36Sopenharmony_ci if (!pads[i]) 96662306a36Sopenharmony_ci continue; 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ci if (gc_setup_pad(gc, i, pads[i])) 96962306a36Sopenharmony_ci goto err_unreg_devs; 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci count++; 97262306a36Sopenharmony_ci } 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci if (count == 0) { 97562306a36Sopenharmony_ci pr_err("No valid devices specified\n"); 97662306a36Sopenharmony_ci goto err_free_gc; 97762306a36Sopenharmony_ci } 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci gc_base[port_idx] = gc; 98062306a36Sopenharmony_ci return; 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci err_unreg_devs: 98362306a36Sopenharmony_ci while (--i >= 0) 98462306a36Sopenharmony_ci if (gc->pads[i].dev) 98562306a36Sopenharmony_ci input_unregister_device(gc->pads[i].dev); 98662306a36Sopenharmony_ci err_free_gc: 98762306a36Sopenharmony_ci kfree(gc); 98862306a36Sopenharmony_ci err_unreg_pardev: 98962306a36Sopenharmony_ci parport_unregister_device(pd); 99062306a36Sopenharmony_ci} 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_cistatic void gc_detach(struct parport *port) 99362306a36Sopenharmony_ci{ 99462306a36Sopenharmony_ci int i; 99562306a36Sopenharmony_ci struct gc *gc; 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_ci for (i = 0; i < GC_MAX_PORTS; i++) { 99862306a36Sopenharmony_ci if (gc_base[i] && gc_base[i]->parportno == port->number) 99962306a36Sopenharmony_ci break; 100062306a36Sopenharmony_ci } 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci if (i == GC_MAX_PORTS) 100362306a36Sopenharmony_ci return; 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_ci gc = gc_base[i]; 100662306a36Sopenharmony_ci gc_base[i] = NULL; 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_ci for (i = 0; i < GC_MAX_DEVICES; i++) 100962306a36Sopenharmony_ci if (gc->pads[i].dev) 101062306a36Sopenharmony_ci input_unregister_device(gc->pads[i].dev); 101162306a36Sopenharmony_ci parport_unregister_device(gc->pd); 101262306a36Sopenharmony_ci kfree(gc); 101362306a36Sopenharmony_ci} 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_cistatic struct parport_driver gc_parport_driver = { 101662306a36Sopenharmony_ci .name = "gamecon", 101762306a36Sopenharmony_ci .match_port = gc_attach, 101862306a36Sopenharmony_ci .detach = gc_detach, 101962306a36Sopenharmony_ci .devmodel = true, 102062306a36Sopenharmony_ci}; 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_cistatic int __init gc_init(void) 102362306a36Sopenharmony_ci{ 102462306a36Sopenharmony_ci int i; 102562306a36Sopenharmony_ci int have_dev = 0; 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci for (i = 0; i < GC_MAX_PORTS; i++) { 102862306a36Sopenharmony_ci if (gc_cfg[i].nargs == 0 || gc_cfg[i].args[0] < 0) 102962306a36Sopenharmony_ci continue; 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci if (gc_cfg[i].nargs < 2) { 103262306a36Sopenharmony_ci pr_err("at least one device must be specified\n"); 103362306a36Sopenharmony_ci return -EINVAL; 103462306a36Sopenharmony_ci } 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci have_dev = 1; 103762306a36Sopenharmony_ci } 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci if (!have_dev) 104062306a36Sopenharmony_ci return -ENODEV; 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci return parport_register_driver(&gc_parport_driver); 104362306a36Sopenharmony_ci} 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_cistatic void __exit gc_exit(void) 104662306a36Sopenharmony_ci{ 104762306a36Sopenharmony_ci parport_unregister_driver(&gc_parport_driver); 104862306a36Sopenharmony_ci} 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_cimodule_init(gc_init); 105162306a36Sopenharmony_cimodule_exit(gc_exit); 1052