* Based on the work of:
* Andree Borrmann John Dahlstrom
* David Kuder Nathan Hand
- * Raphael Assenat
*/
/*
#include <linux/init.h>
#include <linux/parport.h>
#include <linux/input.h>
-#include <linux/mutex.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver");
#define GC_N64 6
#define GC_PSX 7
#define GC_DDR 8
-#define GC_SNESMOUSE 9
-#define GC_MAX 9
+#define GC_MAX 8
#define GC_REFRESH_TIME HZ/100
struct timer_list timer;
unsigned char pads[GC_MAX + 1];
int used;
- struct mutex mutex;
+ struct semaphore sem;
char phys[GC_MAX_DEVICES][32];
};
static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick",
"Multisystem 2-button joystick", "N64 controller", "PSX controller",
- "PSX DDR controller", "SNES mouse" };
+ "PSX DDR controller" };
/*
* N64 support.
*/
* NES/SNES support.
*/
-#define GC_NES_DELAY 6 /* Delay between bits - 6us */
-#define GC_NES_LENGTH 8 /* The NES pads use 8 bits of data */
-#define GC_SNES_LENGTH 12 /* The SNES true length is 16, but the
- last 4 bits are unused */
-#define GC_SNESMOUSE_LENGTH 32 /* The SNES mouse uses 32 bits, the first
- 16 bits are equivalent to a gamepad */
+#define GC_NES_DELAY 6 /* Delay between bits - 6us */
+#define GC_NES_LENGTH 8 /* The NES pads use 8 bits of data */
+#define GC_SNES_LENGTH 12 /* The SNES true length is 16, but the last 4 bits are unused */
#define GC_NES_POWER 0xfc
#define GC_NES_CLOCK 0x01
static void gc_nes_process_packet(struct gc *gc)
{
- unsigned char data[GC_SNESMOUSE_LENGTH];
+ unsigned char data[GC_SNES_LENGTH];
struct input_dev *dev;
- int i, j, s, len;
- char x_rel, y_rel;
-
- len = gc->pads[GC_SNESMOUSE] ? GC_SNESMOUSE_LENGTH :
- (gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH);
+ int i, j, s;
- gc_nes_read_packet(gc, len, data);
+ gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data);
for (i = 0; i < GC_MAX_DEVICES; i++) {
for (j = 0; j < 8; j++)
input_report_key(dev, gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
- if (s & gc->pads[GC_SNESMOUSE]) {
- /*
- * The 4 unused bits from SNES controllers appear to be ID bits
- * so use them to make sure iwe are dealing with a mouse.
- * gamepad is connected. This is important since
- * my SNES gamepad sends 1's for bits 16-31, which
- * cause the mouse pointer to quickly move to the
- * upper left corner of the screen.
- */
- if (!(s & data[12]) && !(s & data[13]) &&
- !(s & data[14]) && (s & data[15])) {
- input_report_key(dev, BTN_LEFT, s & data[9]);
- input_report_key(dev, BTN_RIGHT, s & data[8]);
-
- x_rel = y_rel = 0;
- for (j = 0; j < 7; j++) {
- x_rel <<= 1;
- if (data[25 + j] & s)
- x_rel |= 1;
-
- y_rel <<= 1;
- if (data[17 + j] & s)
- y_rel |= 1;
- }
-
- if (x_rel) {
- if (data[24] & s)
- x_rel = -x_rel;
- input_report_rel(dev, REL_X, x_rel);
- }
-
- if (y_rel) {
- if (data[16] & s)
- y_rel = -y_rel;
- input_report_rel(dev, REL_Y, y_rel);
- }
- }
- }
input_sync(dev);
}
}
gc_n64_process_packet(gc);
/*
- * NES and SNES pads or mouse
+ * NES and SNES pads
*/
- if (gc->pads[GC_NES] || gc->pads[GC_SNES] || gc->pads[GC_SNESMOUSE])
+ if (gc->pads[GC_NES] || gc->pads[GC_SNES])
gc_nes_process_packet(gc);
/*
struct gc *gc = dev->private;
int err;
- err = mutex_lock_interruptible(&gc->mutex);
+ err = down_interruptible(&gc->sem);
if (err)
return err;
mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
}
- mutex_unlock(&gc->mutex);
+ up(&gc->sem);
return 0;
}
{
struct gc *gc = dev->private;
- mutex_lock(&gc->mutex);
+ down(&gc->sem);
if (!--gc->used) {
del_timer_sync(&gc->timer);
parport_write_control(gc->pd->port, 0x00);
parport_release(gc->pd);
}
- mutex_unlock(&gc->mutex);
+ up(&gc->sem);
}
static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
input_dev->open = gc_open;
input_dev->close = gc_close;
- if (pad_type != GC_SNESMOUSE) {
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ 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);
- } else
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ 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];
break;
- case GC_SNESMOUSE:
- set_bit(BTN_LEFT, input_dev->keybit);
- set_bit(BTN_RIGHT, input_dev->keybit);
- set_bit(REL_X, input_dev->relbit);
- set_bit(REL_Y, input_dev->relbit);
- break;
-
case GC_SNES:
for (i = 4; i < 8; i++)
set_bit(gc_snes_btn[i], input_dev->keybit);
goto err_unreg_pardev;
}
- mutex_init(&gc->mutex);
+ init_MUTEX(&gc->sem);
gc->pd = pd;
init_timer(&gc->timer);
gc->timer.data = (long) gc;
if (!pads[i])
continue;
- snprintf(gc->phys[i], sizeof(gc->phys[i]),
- "%s/input%d", gc->pd->port->name, i);
+ sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i);
err = gc_setup_pad(gc, i, pads[i]);
if (err)
goto err_unreg_devs;