Commit d20e6336 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/dtor/input

parents fa3c791d 6dea9347
...@@ -57,7 +57,7 @@ static char *a3d_names[] = { NULL, "FP-Gaming Assassin 3D", "MadCatz Panther", " ...@@ -57,7 +57,7 @@ static char *a3d_names[] = { NULL, "FP-Gaming Assassin 3D", "MadCatz Panther", "
struct a3d { struct a3d {
struct gameport *gameport; struct gameport *gameport;
struct gameport *adc; struct gameport *adc;
struct input_dev dev; struct input_dev *dev;
int axes[4]; int axes[4];
int buttons; int buttons;
int mode; int mode;
...@@ -115,7 +115,7 @@ static int a3d_csum(char *data, int count) ...@@ -115,7 +115,7 @@ static int a3d_csum(char *data, int count)
static void a3d_read(struct a3d *a3d, unsigned char *data) static void a3d_read(struct a3d *a3d, unsigned char *data)
{ {
struct input_dev *dev = &a3d->dev; struct input_dev *dev = a3d->dev;
switch (a3d->mode) { switch (a3d->mode) {
...@@ -265,14 +265,20 @@ static void a3d_close(struct input_dev *dev) ...@@ -265,14 +265,20 @@ static void a3d_close(struct input_dev *dev)
static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv) static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
{ {
struct a3d *a3d; struct a3d *a3d;
struct input_dev *input_dev;
struct gameport *adc; struct gameport *adc;
unsigned char data[A3D_MAX_LENGTH]; unsigned char data[A3D_MAX_LENGTH];
int i; int i;
int err; int err;
if (!(a3d = kzalloc(sizeof(struct a3d), GFP_KERNEL))) a3d = kzalloc(sizeof(struct a3d), GFP_KERNEL);
return -ENOMEM; input_dev = input_allocate_device();
if (!a3d || !input_dev) {
err = -ENOMEM;
goto fail1;
}
a3d->dev = input_dev;
a3d->gameport = gameport; a3d->gameport = gameport;
gameport_set_drvdata(gameport, a3d); gameport_set_drvdata(gameport, a3d);
...@@ -302,42 +308,48 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv) ...@@ -302,42 +308,48 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
sprintf(a3d->phys, "%s/input0", gameport->phys); sprintf(a3d->phys, "%s/input0", gameport->phys);
input_dev->name = a3d_names[a3d->mode];
input_dev->phys = a3d->phys;
input_dev->id.bustype = BUS_GAMEPORT;
input_dev->id.vendor = GAMEPORT_ID_VENDOR_MADCATZ;
input_dev->id.product = a3d->mode;
input_dev->id.version = 0x0100;
input_dev->cdev.dev = &gameport->dev;
input_dev->private = a3d;
input_dev->open = a3d_open;
input_dev->close = a3d_close;
if (a3d->mode == A3D_MODE_PXL) { if (a3d->mode == A3D_MODE_PXL) {
int axes[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER }; int axes[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER };
a3d->length = 33; a3d->length = 33;
init_input_dev(&a3d->dev); input_dev->evbit[0] |= BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
input_dev->relbit[0] |= BIT(REL_X) | BIT(REL_Y);
a3d->dev.evbit[0] |= BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL); input_dev->absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_RUDDER)
a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y); | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y) | BIT(ABS_HAT1X) | BIT(ABS_HAT1Y);
a3d->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_RUDDER) input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE)
| BIT(ABS_HAT0X) | BIT(ABS_HAT0Y) | BIT(ABS_HAT1X) | BIT(ABS_HAT1Y); | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
input_dev->keybit[LONG(BTN_JOYSTICK)] |= BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP)
a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_PINKIE);
| BIT(BTN_SIDE) | BIT(BTN_EXTRA);
a3d->dev.keybit[LONG(BTN_JOYSTICK)] |= BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_PINKIE);
a3d_read(a3d, data); a3d_read(a3d, data);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
if (i < 2) if (i < 2)
input_set_abs_params(&a3d->dev, axes[i], 48, a3d->dev.abs[axes[i]] * 2 - 48, 0, 8); input_set_abs_params(input_dev, axes[i], 48, input_dev->abs[axes[i]] * 2 - 48, 0, 8);
else else
input_set_abs_params(&a3d->dev, axes[i], 2, 253, 0, 0); input_set_abs_params(input_dev, axes[i], 2, 253, 0, 0);
input_set_abs_params(&a3d->dev, ABS_HAT0X + i, -1, 1, 0, 0); input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0);
} }
} else { } else {
a3d->length = 29; a3d->length = 29;
init_input_dev(&a3d->dev); input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_REL);
input_dev->relbit[0] |= BIT(REL_X) | BIT(REL_Y);
a3d->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_REL); input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE);
a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y);
a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE);
a3d_read(a3d, data); a3d_read(a3d, data);
...@@ -358,24 +370,17 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv) ...@@ -358,24 +370,17 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
} }
} }
a3d->dev.private = a3d; err = input_register_device(a3d->dev);
a3d->dev.open = a3d_open; if (err)
a3d->dev.close = a3d_close; goto fail3;
a3d->dev.name = a3d_names[a3d->mode];
a3d->dev.phys = a3d->phys;
a3d->dev.id.bustype = BUS_GAMEPORT;
a3d->dev.id.vendor = GAMEPORT_ID_VENDOR_MADCATZ;
a3d->dev.id.product = a3d->mode;
a3d->dev.id.version = 0x0100;
input_register_device(&a3d->dev);
printk(KERN_INFO "input: %s on %s\n", a3d_names[a3d->mode], a3d->phys);
return 0; return 0;
fail2: gameport_close(gameport); fail3: if (a3d->adc)
fail1: gameport_set_drvdata(gameport, NULL); gameport_unregister_port(a3d->adc);
fail2: gameport_close(gameport);
fail1: gameport_set_drvdata(gameport, NULL);
input_free_device(input_dev);
kfree(a3d); kfree(a3d);
return err; return err;
} }
...@@ -384,11 +389,9 @@ static void a3d_disconnect(struct gameport *gameport) ...@@ -384,11 +389,9 @@ static void a3d_disconnect(struct gameport *gameport)
{ {
struct a3d *a3d = gameport_get_drvdata(gameport); struct a3d *a3d = gameport_get_drvdata(gameport);
input_unregister_device(&a3d->dev); input_unregister_device(a3d->dev);
if (a3d->adc) { if (a3d->adc)
gameport_unregister_port(a3d->adc); gameport_unregister_port(a3d->adc);
a3d->adc = NULL;
}
gameport_close(gameport); gameport_close(gameport);
gameport_set_drvdata(gameport, NULL); gameport_set_drvdata(gameport, NULL);
kfree(a3d); kfree(a3d);
...@@ -397,6 +400,7 @@ static void a3d_disconnect(struct gameport *gameport) ...@@ -397,6 +400,7 @@ static void a3d_disconnect(struct gameport *gameport)
static struct gameport_driver a3d_drv = { static struct gameport_driver a3d_drv = {
.driver = { .driver = {
.name = "adc", .name = "adc",
.owner = THIS_MODULE,
}, },
.description = DRIVER_DESC, .description = DRIVER_DESC,
.connect = a3d_connect, .connect = a3d_connect,
......
...@@ -275,68 +275,70 @@ static unsigned char db9_saturn_read_packet(struct parport *port, unsigned char ...@@ -275,68 +275,70 @@ static unsigned char db9_saturn_read_packet(struct parport *port, unsigned char
/* /*
* db9_saturn_report() analyzes packet and reports. * db9_saturn_report() analyzes packet and reports.
*/ */
static int db9_saturn_report(unsigned char id, unsigned char data[60], struct input_dev *dev, int n, int max_pads) static int db9_saturn_report(unsigned char id, unsigned char data[60], struct input_dev *devs[], int n, int max_pads)
{ {
struct input_dev *dev;
int tmp, i, j; int tmp, i, j;
tmp = (id == 0x41) ? 60 : 10; tmp = (id == 0x41) ? 60 : 10;
for (j = 0; (j < tmp) && (n < max_pads); j += 10, n++) { for (j = 0; j < tmp && n < max_pads; j += 10, n++) {
dev = devs[n];
switch (data[j]) { switch (data[j]) {
case 0x16: /* multi controller (analog 4 axis) */ case 0x16: /* multi controller (analog 4 axis) */
input_report_abs(dev + n, db9_abs[5], data[j + 6]); input_report_abs(dev, db9_abs[5], data[j + 6]);
case 0x15: /* mission stick (analog 3 axis) */ case 0x15: /* mission stick (analog 3 axis) */
input_report_abs(dev + n, db9_abs[3], data[j + 4]); input_report_abs(dev, db9_abs[3], data[j + 4]);
input_report_abs(dev + n, db9_abs[4], data[j + 5]); input_report_abs(dev, db9_abs[4], data[j + 5]);
case 0x13: /* racing controller (analog 1 axis) */ case 0x13: /* racing controller (analog 1 axis) */
input_report_abs(dev + n, db9_abs[2], data[j + 3]); input_report_abs(dev, db9_abs[2], data[j + 3]);
case 0x34: /* saturn keyboard (udlr ZXC ASD QE Esc) */ case 0x34: /* saturn keyboard (udlr ZXC ASD QE Esc) */
case 0x02: /* digital pad (digital 2 axis + buttons) */ case 0x02: /* digital pad (digital 2 axis + buttons) */
input_report_abs(dev + n, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64)); input_report_abs(dev, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
input_report_abs(dev + n, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16)); input_report_abs(dev, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16));
for (i = 0; i < 9; i++) for (i = 0; i < 9; i++)
input_report_key(dev + n, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]); input_report_key(dev, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]);
break; break;
case 0x19: /* mission stick x2 (analog 6 axis + buttons) */ case 0x19: /* mission stick x2 (analog 6 axis + buttons) */
input_report_abs(dev + n, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64)); input_report_abs(dev, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
input_report_abs(dev + n, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16)); input_report_abs(dev, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16));
for (i = 0; i < 9; i++) for (i = 0; i < 9; i++)
input_report_key(dev + n, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]); input_report_key(dev, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]);
input_report_abs(dev + n, db9_abs[2], data[j + 3]); input_report_abs(dev, db9_abs[2], data[j + 3]);
input_report_abs(dev + n, db9_abs[3], data[j + 4]); input_report_abs(dev, db9_abs[3], data[j + 4]);
input_report_abs(dev + n, db9_abs[4], data[j + 5]); input_report_abs(dev, db9_abs[4], data[j + 5]);
/* /*
input_report_abs(dev + n, db9_abs[8], (data[j + 6] & 128 ? 0 : 1) - (data[j + 6] & 64 ? 0 : 1)); input_report_abs(dev, db9_abs[8], (data[j + 6] & 128 ? 0 : 1) - (data[j + 6] & 64 ? 0 : 1));
input_report_abs(dev + n, db9_abs[9], (data[j + 6] & 32 ? 0 : 1) - (data[j + 6] & 16 ? 0 : 1)); input_report_abs(dev, db9_abs[9], (data[j + 6] & 32 ? 0 : 1) - (data[j + 6] & 16 ? 0 : 1));
*/ */
input_report_abs(dev + n, db9_abs[6], data[j + 7]); input_report_abs(dev, db9_abs[6], data[j + 7]);
input_report_abs(dev + n, db9_abs[7], data[j + 8]); input_report_abs(dev, db9_abs[7], data[j + 8]);
input_report_abs(dev + n, db9_abs[5], data[j + 9]); input_report_abs(dev, db9_abs[5], data[j + 9]);
break; break;
case 0xd3: /* sankyo ff (analog 1 axis + stop btn) */ case 0xd3: /* sankyo ff (analog 1 axis + stop btn) */
input_report_key(dev + n, BTN_A, data[j + 3] & 0x80); input_report_key(dev, BTN_A, data[j + 3] & 0x80);
input_report_abs(dev + n, db9_abs[2], data[j + 3] & 0x7f); input_report_abs(dev, db9_abs[2], data[j + 3] & 0x7f);
break; break;
case 0xe3: /* shuttle mouse (analog 2 axis + buttons. signed value) */ case 0xe3: /* shuttle mouse (analog 2 axis + buttons. signed value) */
input_report_key(dev + n, BTN_START, data[j + 1] & 0x08); input_report_key(dev, BTN_START, data[j + 1] & 0x08);
input_report_key(dev + n, BTN_A, data[j + 1] & 0x04); input_report_key(dev, BTN_A, data[j + 1] & 0x04);
input_report_key(dev + n, BTN_C, data[j + 1] & 0x02); input_report_key(dev, BTN_C, data[j + 1] & 0x02);
input_report_key(dev + n, BTN_B, data[j + 1] & 0x01); input_report_key(dev, BTN_B, data[j + 1] & 0x01);
input_report_abs(dev + n, db9_abs[2], data[j + 2] ^ 0x80); input_report_abs(dev, db9_abs[2], data[j + 2] ^ 0x80);
input_report_abs(dev + n, db9_abs[3], (0xff-(data[j + 3] ^ 0x80))+1); /* */ input_report_abs(dev, db9_abs[3], (0xff-(data[j + 3] ^ 0x80))+1); /* */
break; break;
case 0xff: case 0xff:
default: /* no pad */ default: /* no pad */
input_report_abs(dev + n, db9_abs[0], 0); input_report_abs(dev, db9_abs[0], 0);
input_report_abs(dev + n, db9_abs[1], 0); input_report_abs(dev, db9_abs[1], 0);
for (i = 0; i < 9; i++) for (i = 0; i < 9; i++)
input_report_key(dev + n, db9_cd32_btn[i], 0); input_report_key(dev, db9_cd32_btn[i], 0);
break; break;
} }
} }
return n; return n;
} }
static int db9_saturn(int mode, struct parport *port, struct input_dev *dev) static int db9_saturn(int mode, struct parport *port, struct input_dev *devs[])
{ {
unsigned char id, data[60]; unsigned char id, data[60];
int type, n, max_pads; int type, n, max_pads;
...@@ -361,7 +363,7 @@ static int db9_saturn(int mode, struct parport *port, struct input_dev *dev) ...@@ -361,7 +363,7 @@ static int db9_saturn(int mode, struct parport *port, struct input_dev *dev)
max_pads = min(db9_modes[mode].n_pads, DB9_MAX_DEVICES); max_pads = min(db9_modes[mode].n_pads, DB9_MAX_DEVICES);
for (tmp = 0, i = 0; i < n; i++) { for (tmp = 0, i = 0; i < n; i++) {
id = db9_saturn_read_packet(port, data, type + i, 1); id = db9_saturn_read_packet(port, data, type + i, 1);
tmp = db9_saturn_report(id, data, dev, tmp, max_pads); tmp = db9_saturn_report(id, data, devs, tmp, max_pads);
} }
return 0; return 0;
} }
...@@ -489,7 +491,7 @@ static void db9_timer(unsigned long private) ...@@ -489,7 +491,7 @@ static void db9_timer(unsigned long private)
case DB9_SATURN_DPP: case DB9_SATURN_DPP:
case DB9_SATURN_DPP_2: case DB9_SATURN_DPP_2:
db9_saturn(db9->mode, port, dev); db9_saturn(db9->mode, port, db9->dev);
break; break;
case DB9_CD32_PAD: case DB9_CD32_PAD:
...@@ -614,7 +616,7 @@ static struct db9 __init *db9_probe(int parport, int mode) ...@@ -614,7 +616,7 @@ static struct db9 __init *db9_probe(int parport, int mode)
if (!input_dev) { if (!input_dev) {
printk(KERN_ERR "db9.c: Not enough memory for input device\n"); printk(KERN_ERR "db9.c: Not enough memory for input device\n");
err = -ENOMEM; err = -ENOMEM;
goto err_free_devs; goto err_unreg_devs;
} }
sprintf(db9->phys[i], "%s/input%d", db9->pd->port->name, i); sprintf(db9->phys[i], "%s/input%d", db9->pd->port->name, i);
...@@ -640,13 +642,17 @@ static struct db9 __init *db9_probe(int parport, int mode) ...@@ -640,13 +642,17 @@ static struct db9 __init *db9_probe(int parport, int mode)
input_set_abs_params(input_dev, db9_abs[j], 1, 255, 0, 0); input_set_abs_params(input_dev, db9_abs[j], 1, 255, 0, 0);
} }
input_register_device(input_dev); err = input_register_device(input_dev);
if (err)
goto err_free_dev;
} }
parport_put_port(pp); parport_put_port(pp);
return db9; return db9;
err_free_devs: err_free_dev:
input_free_device(db9->dev[i]);
err_unreg_devs:
while (--i >= 0) while (--i >= 0)
input_unregister_device(db9->dev[i]); input_unregister_device(db9->dev[i]);
kfree(db9); kfree(db9);
...@@ -658,7 +664,7 @@ static struct db9 __init *db9_probe(int parport, int mode) ...@@ -658,7 +664,7 @@ static struct db9 __init *db9_probe(int parport, int mode)
return ERR_PTR(err); return ERR_PTR(err);
} }
static void __exit db9_remove(struct db9 *db9) static void db9_remove(struct db9 *db9)
{ {
int i; int i;
...@@ -696,7 +702,8 @@ static int __init db9_init(void) ...@@ -696,7 +702,8 @@ static int __init db9_init(void)
if (err) { if (err) {
while (--i >= 0) while (--i >= 0)
db9_remove(db9_base[i]); if (db9_base[i])
db9_remove(db9_base[i]);
return err; return err;
} }
......
...@@ -159,6 +159,48 @@ static void gc_n64_read_packet(struct gc *gc, unsigned char *data) ...@@ -159,6 +159,48 @@ static void gc_n64_read_packet(struct gc *gc, unsigned char *data)
} }
static void gc_n64_process_packet(struct gc *gc)
{
unsigned char data[GC_N64_LENGTH];
signed char axes[2];
struct input_dev *dev;
int i, j, s;
gc_n64_read_packet(gc, data);
for (i = 0; i < GC_MAX_DEVICES; i++) {
dev = gc->dev[i];
if (!dev)
continue;
s = gc_status_bit[i];
if (s & gc->pads[GC_N64] & ~(data[8] | data[9])) {
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, ABS_X, axes[0]);
input_report_abs(dev, ABS_Y, -axes[1]);
input_report_abs(dev, ABS_HAT0X, !(s & data[6]) - !(s & data[7]));
input_report_abs(dev, ABS_HAT0Y, !(s & data[4]) - !(s & data[5]));
for (j = 0; j < 10; j++)
input_report_key(dev, gc_n64_btn[j], s & data[gc_n64_bytes[j]]);
input_sync(dev);
}
}
}
/* /*
* NES/SNES support. * NES/SNES support.
*/ */
...@@ -198,6 +240,39 @@ static void gc_nes_read_packet(struct gc *gc, int length, unsigned char *data) ...@@ -198,6 +240,39 @@ static void gc_nes_read_packet(struct gc *gc, int length, unsigned char *data)
} }
} }
static void gc_nes_process_packet(struct gc *gc)
{
unsigned char data[GC_SNES_LENGTH];
struct input_dev *dev;
int i, j, s;
gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data);
for (i = 0; i < GC_MAX_DEVICES; i++) {
dev = gc->dev[i];
if (!dev)
continue;
s = gc_status_bit[i];
if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) {
input_report_abs(dev, ABS_X, !(s & data[6]) - !(s & data[7]));
input_report_abs(dev, ABS_Y, !(s & data[4]) - !(s & data[5]));
}
if (s & gc->pads[GC_NES])
for (j = 0; j < 4; j++)
input_report_key(dev, 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, gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
input_sync(dev);
}
}
/* /*
* Multisystem joystick support * Multisystem joystick support
*/ */
...@@ -219,6 +294,35 @@ static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data) ...@@ -219,6 +294,35 @@ static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data)
} }
} }
static void gc_multi_process_packet(struct gc *gc)
{
unsigned char data[GC_MULTI2_LENGTH];
struct input_dev *dev;
int i, s;
gc_multi_read_packet(gc, gc->pads[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH, data);
for (i = 0; i < GC_MAX_DEVICES; i++) {
dev = gc->dev[i];
if (!dev)
continue;
s = gc_status_bit[i];
if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) {
input_report_abs(dev, ABS_X, !(s & data[2]) - !(s & data[3]));
input_report_abs(dev, ABS_Y, !(s & data[0]) - !(s & data[1]));
input_report_key(dev, BTN_TRIGGER, s & data[4]);
}
if (s & gc->pads[GC_MULTI2])
input_report_key(dev, BTN_THUMB, s & data[5]);
input_sync(dev);
}
}
/* /*
* PSX support * PSX support
* *
...@@ -263,10 +367,11 @@ static short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 }; ...@@ -263,10 +367,11 @@ static short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 };
* the psx pad. * the psx pad.
*/ */
static void gc_psx_command(struct gc *gc, int b, unsigned char data[5]) static void gc_psx_command(struct gc *gc, int b, unsigned char data[GC_MAX_DEVICES])
{ {
int i, j, cmd, read; int i, j, cmd, read;
for (i = 0; i < 5; i++)
for (i = 0; i < GC_MAX_DEVICES; i++)
data[i] = 0; data[i] = 0;
for (i = 0; i < GC_PSX_LENGTH; i++, b >>= 1) { for (i = 0; i < GC_PSX_LENGTH; i++, b >>= 1) {
...@@ -274,7 +379,7 @@ static void gc_psx_command(struct gc *gc, int b, unsigned char data[5]) ...@@ -274,7 +379,7 @@ static void gc_psx_command(struct gc *gc, int b, unsigned char data[5])
parport_write_data(gc->pd->port, cmd | GC_PSX_POWER); parport_write_data(gc->pd->port, cmd | GC_PSX_POWER);
udelay(gc_psx_delay); udelay(gc_psx_delay);
read = parport_read_status(gc->pd->port) ^ 0x80; read = parport_read_status(gc->pd->port) ^ 0x80;
for (j = 0; j < 5; j++) for (j = 0; j < GC_MAX_DEVICES; j++)
data[j] |= (read & gc_status_bit[j] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) ? (1 << i) : 0; data[j] |= (read & gc_status_bit[j] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) ? (1 << i) : 0;
parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER); parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER);
udelay(gc_psx_delay); udelay(gc_psx_delay);
...@@ -286,11 +391,12 @@ static void gc_psx_command(struct gc *gc, int b, unsigned char data[5]) ...@@ -286,11 +391,12 @@ static void gc_psx_command(struct gc *gc, int b, unsigned char data[5])
* device identifier code. * device identifier code.
*/ */
static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES], unsigned char id[5]) static void gc_psx_read_packet(struct gc *gc, unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES],
unsigned char id[GC_MAX_DEVICES])
{ {
int i, j, max_len = 0; int i, j, max_len = 0;
unsigned long flags; unsigned long flags;
unsigned char data2[5]; unsigned char data2[GC_MAX_DEVICES];
parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); /* Select pad */ parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); /* Select pad */
udelay(gc_psx_delay); udelay(gc_psx_delay);
...@@ -303,7 +409,7 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES ...@@ -303,7 +409,7 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES
gc_psx_command(gc, 0x42, id); /* Get device ids */ gc_psx_command(gc, 0x42, id); /* Get device ids */
gc_psx_command(gc, 0, data2); /* Dump status */ gc_psx_command(gc, 0, data2); /* Dump status */
for (i =0; i < 5; i++) /* Find the longest pad */ for (i =0; i < GC_MAX_DEVICES; i++) /* Find the longest pad */
if((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) if((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR]))
&& (GC_PSX_LEN(id[i]) > max_len) && (GC_PSX_LEN(id[i]) > max_len)
&& (GC_PSX_LEN(id[i]) <= GC_PSX_BYTES)) && (GC_PSX_LEN(id[i]) <= GC_PSX_BYTES))
...@@ -311,7 +417,7 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES ...@@ -311,7 +417,7 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES
for (i = 0; i < max_len; i++) { /* Read in all the data */ for (i = 0; i < max_len; i++) { /* Read in all the data */
gc_psx_command(gc, 0, data2); gc_psx_command(gc, 0, data2);
for (j = 0; j < 5; j++) for (j = 0; j < GC_MAX_DEVICES; j++)
data[j][i] = data2[j]; data[j][i] = data2[j];
} }
...@@ -319,185 +425,124 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES ...@@ -319,185 +425,124 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES
parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);
for(i = 0; i < 5; i++) /* Set id's to the real value */ for(i = 0; i < GC_MAX_DEVICES; i++) /* Set id's to the real value */
id[i] = GC_PSX_ID(id[i]); id[i] = GC_PSX_ID(id[i]);
} }
/* static void gc_psx_process_packet(struct gc *gc)
* gc_timer() reads and analyzes console pads data. {
*/ unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES];
unsigned char id[GC_MAX_DEVICES];
struct input_dev *dev;
int i, j;
#define GC_MAX_LENGTH GC_N64_LENGTH gc_psx_read_packet(gc, data, id);
static void gc_timer(unsigned long private) for (i = 0; i < GC_MAX_DEVICES; i++) {
{
struct gc *gc = (void *) private;
unsigned char data[GC_MAX_LENGTH];
unsigned char data_psx[5][GC_PSX_BYTES];
int i, j, s;
/* dev = gc->dev[i];
* N64 pads - must be read first, any read confuses them for 200 us if (!dev)
*/ continue;
if (gc->pads[GC_N64]) { switch (id[i]) {
gc_n64_read_packet(gc, data); case GC_PSX_RUMBLE:
for (i = 0; i < 5; i++) { input_report_key(dev, BTN_THUMBL, ~data[i][0] & 0x04);
input_report_key(dev, BTN_THUMBR, ~data[i][0] & 0x02);
s = gc_status_bit[i]; case GC_PSX_NEGCON:
case GC_PSX_ANALOG:
if (s & gc->pads[GC_N64] & ~(data[8] | data[9])) { if (gc->pads[GC_DDR] & gc_status_bit[i]) {
for(j = 0; j < 4; j++)
input_report_key(dev, gc_psx_ddr_btn[j], ~data[i][0] & (0x10 << j));
} else {
for (j = 0; j < 4; j++)
input_report_abs(dev, gc_psx_abs[j + 2], data[i][j + 2]);
signed char axes[2]; input_report_abs(dev, ABS_X, 128 + !(data[i][0] & 0x20) * 127 - !(data[i][0] & 0x80) * 128);
axes[0] = axes[1] = 0; input_report_abs(dev, ABS_Y, 128 + !(data[i][0] & 0x40) * 127 - !(data[i][0] & 0x10) * 128);
}
for (j = 0; j < 8; j++) { for (j = 0; j < 8; j++)
if (data[23 - j] & s) axes[0] |= 1 << j; input_report_key(dev, gc_psx_btn[j], ~data[i][1] & (1 << j));
if (data[31 - j] & s) axes[1] |= 1 << j;
input_report_key(dev, BTN_START, ~data[i][0] & 0x08);
input_report_key(dev, BTN_SELECT, ~data[i][0] & 0x01);
input_sync(dev);
break;
case GC_PSX_NORMAL:
if (gc->pads[GC_DDR] & gc_status_bit[i]) {
for(j = 0; j < 4; j++)
input_report_key(dev, gc_psx_ddr_btn[j], ~data[i][0] & (0x10 << j));
} else {
input_report_abs(dev, ABS_X, 128 + !(data[i][0] & 0x20) * 127 - !(data[i][0] & 0x80) * 128);
input_report_abs(dev, ABS_Y, 128 + !(data[i][0] & 0x40) * 127 - !(data[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, gc_psx_abs[j + 2], 128);
* This needs to be debugged properly,
* maybe fuzz processing needs to be done in input_sync()
* --vojtech
*/
} }
input_report_abs(gc->dev[i], ABS_X, axes[0]); for (j = 0; j < 8; j++)
input_report_abs(gc->dev[i], ABS_Y, -axes[1]); input_report_key(dev, gc_psx_btn[j], ~data[i][1] & (1 << j));
input_report_key(dev, BTN_START, ~data[i][0] & 0x08);
input_report_key(dev, BTN_SELECT, ~data[i][0] & 0x01);
input_report_abs(gc->dev[i], ABS_HAT0X, !(s & data[6]) - !(s & data[7])); input_sync(dev);
input_report_abs(gc->dev[i], ABS_HAT0Y, !(s & data[4]) - !(s & data[5]));
for (j = 0; j < 10; j++) break;
input_report_key(gc->dev[i], gc_n64_btn[j], s & data[gc_n64_bytes[j]]);
input_sync(gc->dev[i]); case 0: /* not a pad, ignore */
} break;
} }
} }
}
/* /*
* NES and SNES pads * gc_timer() initiates reads of console pads data.
*/ */
if (gc->pads[GC_NES] || gc->pads[GC_SNES]) { static void gc_timer(unsigned long private)
{
gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data); struct gc *gc = (void *) private;
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])); * N64 pads - must be read first, any read confuses them for 200 us
input_report_abs(gc->dev[i], ABS_Y, !(s & data[4]) - !(s & data[5])); */
}
if (s & gc->pads[GC_NES]) if (gc->pads[GC_N64])
for (j = 0; j < 4; j++) gc_n64_process_packet(gc);
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++) * NES and SNES pads
input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_snes_bytes[j]]); */
input_sync(gc->dev[i]); if (gc->pads[GC_NES] || gc->pads[GC_SNES])
} gc_nes_process_packet(gc);
}
/* /*
* Multi and Multi2 joysticks * Multi and Multi2 joysticks
*/ */
if (gc->pads[GC_MULTI] || gc->pads[GC_MULTI2]) { if (gc->pads[GC_MULTI] || gc->pads[GC_MULTI2])
gc_multi_process_packet(gc);
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 * PSX controllers
*/ */
if (gc->pads[GC_PSX] || gc->pads[GC_DDR]) { if (gc->pads[GC_PSX] || gc->pads[GC_DDR])
gc_psx_process_packet(gc);
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); mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
} }
...@@ -654,16 +699,18 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) ...@@ -654,16 +699,18 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
gc->timer.data = (long) gc; gc->timer.data = (long) gc;
gc->timer.function = gc_timer; gc->timer.function = gc_timer;
for (i = 0; i < n_pads; i++) { for (i = 0; i < n_pads && i < GC_MAX_DEVICES; i++) {
if (!pads[i]) if (!pads[i])
continue; continue;
sprintf(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]); err = gc_setup_pad(gc, i, pads[i]);
if (err) if (err)
goto err_free_devs; goto err_unreg_devs;
input_register_device(gc->dev[i]); err = input_register_device(gc->dev[i]);
if (err)
goto err_free_dev;
} }
if (!gc->pads[0]) { if (!gc->pads[0]) {
...@@ -675,9 +722,12 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) ...@@ -675,9 +722,12 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
parport_put_port(pp); parport_put_port(pp);
return gc; return gc;
err_free_devs: err_free_dev:
input_free_device(gc->dev[i]);
err_unreg_devs:
while (--i >= 0) while (--i >= 0)
input_unregister_device(gc->dev[i]); if (gc->dev[i])
input_unregister_device(gc->dev[i]);
err_free_gc: err_free_gc:
kfree(gc); kfree(gc);
err_unreg_pardev: err_unreg_pardev:
...@@ -688,7 +738,7 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) ...@@ -688,7 +738,7 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
return ERR_PTR(err); return ERR_PTR(err);
} }
static void __exit gc_remove(struct gc *gc) static void gc_remove(struct gc *gc)
{ {
int i; int i;
...@@ -726,7 +776,8 @@ static int __init gc_init(void) ...@@ -726,7 +776,8 @@ static int __init gc_init(void)
if (err) { if (err) {
while (--i >= 0) while (--i >= 0)
gc_remove(gc_base[i]); if (gc_base[i])
gc_remove(gc_base[i]);
return err; return err;
} }
......
...@@ -192,6 +192,9 @@ static void grip_poll(struct gameport *gameport) ...@@ -192,6 +192,9 @@ static void grip_poll(struct gameport *gameport)
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
dev = grip->dev[i]; dev = grip->dev[i];
if (!dev)
continue;
grip->reads++; grip->reads++;
switch (grip->mode[i]) { switch (grip->mode[i]) {
...@@ -381,12 +384,15 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv) ...@@ -381,12 +384,15 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
if (t > 0) if (t > 0)
set_bit(t, input_dev->keybit); set_bit(t, input_dev->keybit);
input_register_device(grip->dev[i]); err = input_register_device(grip->dev[i]);
if (err)
goto fail4;
} }
return 0; return 0;
fail3: for (i = 0; i < 2; i++) fail4: input_free_device(grip->dev[i]);
fail3: while (--i >= 0)
if (grip->dev[i]) if (grip->dev[i])
input_unregister_device(grip->dev[i]); input_unregister_device(grip->dev[i]);
fail2: gameport_close(gameport); fail2: gameport_close(gameport);
...@@ -411,6 +417,7 @@ static void grip_disconnect(struct gameport *gameport) ...@@ -411,6 +417,7 @@ static void grip_disconnect(struct gameport *gameport)
static struct gameport_driver grip_drv = { static struct gameport_driver grip_drv = {
.driver = { .driver = {
.name = "grip", .name = "grip",
.owner = THIS_MODULE,
}, },
.description = DRIVER_DESC, .description = DRIVER_DESC,
.connect = grip_connect, .connect = grip_connect,
......
...@@ -345,7 +345,7 @@ int iforce_init_device(struct iforce *iforce) ...@@ -345,7 +345,7 @@ int iforce_init_device(struct iforce *iforce)
int i; int i;
input_dev = input_allocate_device(); input_dev = input_allocate_device();
if (input_dev) if (!input_dev)
return -ENOMEM; return -ENOMEM;
init_waitqueue_head(&iforce->wait); init_waitqueue_head(&iforce->wait);
......
...@@ -167,9 +167,9 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data, ...@@ -167,9 +167,9 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data,
iforce->expect_packet = 0; iforce->expect_packet = 0;
iforce->ecmd = cmd; iforce->ecmd = cmd;
memcpy(iforce->edata, data, IFORCE_MAX_LENGTH); memcpy(iforce->edata, data, IFORCE_MAX_LENGTH);
wake_up(&iforce->wait);
} }
#endif #endif
wake_up(&iforce->wait);
if (!iforce->type) { if (!iforce->type) {
being_used--; being_used--;
...@@ -264,7 +264,7 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet) ...@@ -264,7 +264,7 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
wait_event_interruptible_timeout(iforce->wait, wait_event_interruptible_timeout(iforce->wait,
iforce->ctrl->status != -EINPROGRESS, HZ); iforce->ctrl->status != -EINPROGRESS, HZ);
if (iforce->ctrl->status != -EINPROGRESS) { if (iforce->ctrl->status) {
usb_unlink_urb(iforce->ctrl); usb_unlink_urb(iforce->ctrl);
return -1; return -1;
} }
......
...@@ -95,7 +95,6 @@ static void iforce_usb_irq(struct urb *urb, struct pt_regs *regs) ...@@ -95,7 +95,6 @@ static void iforce_usb_irq(struct urb *urb, struct pt_regs *regs)
goto exit; goto exit;
} }
wake_up(&iforce->wait);
iforce_process_packet(iforce, iforce_process_packet(iforce,
(iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1, regs); (iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1, regs);
......
...@@ -736,7 +736,7 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) ...@@ -736,7 +736,7 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
sprintf(sw->name, "Microsoft SideWinder %s", sw_name[sw->type]); sprintf(sw->name, "Microsoft SideWinder %s", sw_name[sw->type]);
sprintf(sw->phys[i], "%s/input%d", gameport->phys, i); sprintf(sw->phys[i], "%s/input%d", gameport->phys, i);
input_dev = input_allocate_device(); sw->dev[i] = input_dev = input_allocate_device();
if (!input_dev) { if (!input_dev) {
err = -ENOMEM; err = -ENOMEM;
goto fail3; goto fail3;
...@@ -771,12 +771,15 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) ...@@ -771,12 +771,15 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
dbg("%s%s [%d-bit id %d data %d]\n", sw->name, comment, m, l, k); dbg("%s%s [%d-bit id %d data %d]\n", sw->name, comment, m, l, k);
input_register_device(sw->dev[i]); err = input_register_device(sw->dev[i]);
if (err)
goto fail4;
} }
return 0; return 0;
fail3: while (--i >= 0) fail4: input_free_device(sw->dev[i]);
fail3: while (--i >= 0)
input_unregister_device(sw->dev[i]); input_unregister_device(sw->dev[i]);
fail2: gameport_close(gameport); fail2: gameport_close(gameport);
fail1: gameport_set_drvdata(gameport, NULL); fail1: gameport_set_drvdata(gameport, NULL);
...@@ -801,6 +804,7 @@ static void sw_disconnect(struct gameport *gameport) ...@@ -801,6 +804,7 @@ static void sw_disconnect(struct gameport *gameport)
static struct gameport_driver sw_drv = { static struct gameport_driver sw_drv = {
.driver = { .driver = {
.name = "sidewinder", .name = "sidewinder",
.owner = THIS_MODULE,
}, },
.description = DRIVER_DESC, .description = DRIVER_DESC,
.connect = sw_connect, .connect = sw_connect,
......
...@@ -284,13 +284,13 @@ static int tmdc_setup_port(struct tmdc *tmdc, int idx, unsigned char *data) ...@@ -284,13 +284,13 @@ static int tmdc_setup_port(struct tmdc *tmdc, int idx, unsigned char *data)
struct tmdc_port *port; struct tmdc_port *port;
struct input_dev *input_dev; struct input_dev *input_dev;
int i, j, b = 0; int i, j, b = 0;
int err;
tmdc->port[idx] = port = kzalloc(sizeof (struct tmdc_port), GFP_KERNEL); tmdc->port[idx] = port = kzalloc(sizeof (struct tmdc_port), GFP_KERNEL);
input_dev = input_allocate_device(); input_dev = input_allocate_device();
if (!port || !input_dev) { if (!port || !input_dev) {
kfree(port); err = -ENOMEM;
input_free_device(input_dev); goto fail;
return -ENOMEM;
} }
port->mode = data[TMDC_BYTE_ID]; port->mode = data[TMDC_BYTE_ID];
...@@ -347,9 +347,15 @@ static int tmdc_setup_port(struct tmdc *tmdc, int idx, unsigned char *data) ...@@ -347,9 +347,15 @@ static int tmdc_setup_port(struct tmdc *tmdc, int idx, unsigned char *data)
b += port->btnc[i]; b += port->btnc[i];
} }
input_register_device(port->dev); err = input_register_device(port->dev);
if (err)
goto fail;
return 0; return 0;
fail: input_free_device(input_dev);
kfree(port);
return err;
} }
/* /*
...@@ -424,6 +430,7 @@ static void tmdc_disconnect(struct gameport *gameport) ...@@ -424,6 +430,7 @@ static void tmdc_disconnect(struct gameport *gameport)
static struct gameport_driver tmdc_drv = { static struct gameport_driver tmdc_drv = {
.driver = { .driver = {
.name = "tmdc", .name = "tmdc",
.owner = THIS_MODULE,
}, },
.description = DRIVER_DESC, .description = DRIVER_DESC,
.connect = tmdc_connect, .connect = tmdc_connect,
......
...@@ -204,14 +204,14 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) ...@@ -204,14 +204,14 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
if (n_buttons[i] > 6) { if (n_buttons[i] > 6) {
printk(KERN_ERR "turbografx.c: Invalid number of buttons %d\n", n_buttons[i]); printk(KERN_ERR "turbografx.c: Invalid number of buttons %d\n", n_buttons[i]);
err = -EINVAL; err = -EINVAL;
goto err_free_devs; goto err_unreg_devs;
} }
tgfx->dev[i] = input_dev = input_allocate_device(); tgfx->dev[i] = input_dev = input_allocate_device();
if (!input_dev) { if (!input_dev) {
printk(KERN_ERR "turbografx.c: Not enough memory for input device\n"); printk(KERN_ERR "turbografx.c: Not enough memory for input device\n");
err = -ENOMEM; err = -ENOMEM;
goto err_free_devs; goto err_unreg_devs;
} }
tgfx->sticks |= (1 << i); tgfx->sticks |= (1 << i);
...@@ -238,7 +238,9 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) ...@@ -238,7 +238,9 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
for (j = 0; j < n_buttons[i]; j++) for (j = 0; j < n_buttons[i]; j++)
set_bit(tgfx_buttons[j], input_dev->keybit); set_bit(tgfx_buttons[j], input_dev->keybit);
input_register_device(tgfx->dev[i]); err = input_register_device(tgfx->dev[i]);
if (err)
goto err_free_dev;
} }
if (!tgfx->sticks) { if (!tgfx->sticks) {
...@@ -249,9 +251,12 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) ...@@ -249,9 +251,12 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
return tgfx; return tgfx;
err_free_devs: err_free_dev:
input_free_device(tgfx->dev[i]);
err_unreg_devs:
while (--i >= 0) while (--i >= 0)
input_unregister_device(tgfx->dev[i]); if (tgfx->dev[i])
input_unregister_device(tgfx->dev[i]);
err_free_tgfx: err_free_tgfx:
kfree(tgfx); kfree(tgfx);
err_unreg_pardev: err_unreg_pardev:
...@@ -262,7 +267,7 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) ...@@ -262,7 +267,7 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
return ERR_PTR(err); return ERR_PTR(err);
} }
static void __exit tgfx_remove(struct tgfx *tgfx) static void tgfx_remove(struct tgfx *tgfx)
{ {
int i; int i;
...@@ -300,7 +305,8 @@ static int __init tgfx_init(void) ...@@ -300,7 +305,8 @@ static int __init tgfx_init(void)
if (err) { if (err) {
while (--i >= 0) while (--i >= 0)
tgfx_remove(tgfx_base[i]); if (tgfx_base[i])
tgfx_remove(tgfx_base[i]);
return err; return err;
} }
......
...@@ -265,13 +265,13 @@ static struct serio_driver twidjoy_drv = { ...@@ -265,13 +265,13 @@ static struct serio_driver twidjoy_drv = {
* The functions for inserting/removing us as a module. * The functions for inserting/removing us as a module.
*/ */
int __init twidjoy_init(void) static int __init twidjoy_init(void)
{ {
serio_register_driver(&twidjoy_drv); serio_register_driver(&twidjoy_drv);
return 0; return 0;
} }
void __exit twidjoy_exit(void) static void __exit twidjoy_exit(void)
{ {
serio_unregister_driver(&twidjoy_drv); serio_unregister_driver(&twidjoy_drv);
} }
......
...@@ -50,6 +50,18 @@ config INPUT_WISTRON_BTNS ...@@ -50,6 +50,18 @@ config INPUT_WISTRON_BTNS
To compile this driver as a module, choose M here: the module will To compile this driver as a module, choose M here: the module will
be called wistron_btns. be called wistron_btns.
config INPUT_IXP4XX_BEEPER
tristate "IXP4XX Beeper support"
depends on ARCH_IXP4XX
help
If you say yes here, you can connect a beeper to the
ixp4xx gpio pins. This is used by the LinkSys NSLU2.
If unsure, say Y.
To compile this driver as a module, choose M here: the
module will be called ixp4xx-beeper.
config INPUT_UINPUT config INPUT_UINPUT
tristate "User level driver support" tristate "User level driver support"
help help
......
...@@ -11,3 +11,4 @@ obj-$(CONFIG_INPUT_98SPKR) += 98spkr.o ...@@ -11,3 +11,4 @@ obj-$(CONFIG_INPUT_98SPKR) += 98spkr.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.o obj-$(CONFIG_INPUT_UINPUT) += uinput.o
obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o
obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o
/*
* Generic IXP4xx beeper driver
*
* Copyright (C) 2005 Tower Technologies
*
* based on nslu2-io.c
* Copyright (C) 2004 Karen Spearel
*
* Author: Alessandro Zummo <a.zummo@towertech.it>
* Maintainers: http://www.nslu2-linux.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/module.h>
#include <linux/input.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <asm/hardware.h>
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
MODULE_DESCRIPTION("ixp4xx beeper driver");
MODULE_LICENSE("GPL");
static DEFINE_SPINLOCK(beep_lock);
static void ixp4xx_spkr_control(unsigned int pin, unsigned int count)
{
unsigned long flags;
spin_lock_irqsave(&beep_lock, flags);
if (count) {
gpio_line_config(pin, IXP4XX_GPIO_OUT);
gpio_line_set(pin, IXP4XX_GPIO_LOW);
*IXP4XX_OSRT2 = (count & ~IXP4XX_OST_RELOAD_MASK) | IXP4XX_OST_ENABLE;
} else {
gpio_line_config(pin, IXP4XX_GPIO_IN);
gpio_line_set(pin, IXP4XX_GPIO_HIGH);
*IXP4XX_OSRT2 = 0;
}
spin_unlock_irqrestore(&beep_lock, flags);
}
static int ixp4xx_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
unsigned int pin = (unsigned int) dev->private;
unsigned int count = 0;
if (type != EV_SND)
return -1;
switch (code) {
case SND_BELL:
if (value)
value = 1000;
case SND_TONE:
break;
default:
return -1;
}
if (value > 20 && value < 32767)
#ifndef FREQ
count = (ixp4xx_get_board_tick_rate() / (value * 4)) - 1;
#else
count = (FREQ / (value * 4)) - 1;
#endif
ixp4xx_spkr_control(pin, count);
return 0;
}
static irqreturn_t ixp4xx_spkr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
/* clear interrupt */
*IXP4XX_OSST = IXP4XX_OSST_TIMER_2_PEND;
/* flip the beeper output */
*IXP4XX_GPIO_GPOUTR ^= (1 << (unsigned int) dev_id);
return IRQ_HANDLED;
}
static int __devinit ixp4xx_spkr_probe(struct platform_device *dev)
{
struct input_dev *input_dev;
int err;
input_dev = input_allocate_device();
if (!input_dev)
return -ENOMEM;
input_dev->private = (void *) dev->id;
input_dev->name = "ixp4xx beeper",
input_dev->phys = "ixp4xx/gpio";
input_dev->id.bustype = BUS_HOST;
input_dev->id.vendor = 0x001f;
input_dev->id.product = 0x0001;
input_dev->id.version = 0x0100;
input_dev->cdev.dev = &dev->dev;
input_dev->evbit[0] = BIT(EV_SND);
input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
input_dev->event = ixp4xx_spkr_event;
err = request_irq(IRQ_IXP4XX_TIMER2, &ixp4xx_spkr_interrupt,
SA_INTERRUPT | SA_TIMER, "ixp4xx-beeper", (void *) dev->id);
if (err)
goto err_free_device;
err = input_register_device(input_dev);
if (err)
goto err_free_irq;
platform_set_drvdata(dev, input_dev);
return 0;
err_free_irq:
free_irq(IRQ_IXP4XX_TIMER2, dev);
err_free_device:
input_free_device(input_dev);
return err;
}
static int __devexit ixp4xx_spkr_remove(struct platform_device *dev)
{
struct input_dev *input_dev = platform_get_drvdata(dev);
unsigned int pin = (unsigned int) input_dev->private;
input_unregister_device(input_dev);
platform_set_drvdata(dev, NULL);
/* turn the speaker off */
disable_irq(IRQ_IXP4XX_TIMER2);
ixp4xx_spkr_control(pin, 0);
free_irq(IRQ_IXP4XX_TIMER2, dev);
return 0;
}
static void ixp4xx_spkr_shutdown(struct platform_device *dev)
{
struct input_dev *input_dev = platform_get_drvdata(dev);
unsigned int pin = (unsigned int) input_dev->private;
/* turn off the speaker */
disable_irq(IRQ_IXP4XX_TIMER2);
ixp4xx_spkr_control(pin, 0);
}
static struct platform_driver ixp4xx_spkr_platform_driver = {
.driver = {
.name = "ixp4xx-beeper",
.owner = THIS_MODULE,
},
.probe = ixp4xx_spkr_probe,
.remove = __devexit_p(ixp4xx_spkr_remove),
.shutdown = ixp4xx_spkr_shutdown,
};
static int __init ixp4xx_spkr_init(void)
{
return platform_driver_register(&ixp4xx_spkr_platform_driver);
}
static void __exit ixp4xx_spkr_exit(void)
{
platform_driver_unregister(&ixp4xx_spkr_platform_driver);
}
module_init(ixp4xx_spkr_init);
module_exit(ixp4xx_spkr_exit);
...@@ -403,6 +403,7 @@ static int genius_detect(struct psmouse *psmouse, int set_properties) ...@@ -403,6 +403,7 @@ static int genius_detect(struct psmouse *psmouse, int set_properties)
set_bit(REL_WHEEL, psmouse->dev->relbit); set_bit(REL_WHEEL, psmouse->dev->relbit);
psmouse->vendor = "Genius"; psmouse->vendor = "Genius";
psmouse->name = "Mouse";
psmouse->pktsize = 4; psmouse->pktsize = 4;
} }
......
...@@ -356,7 +356,7 @@ static void mousedev_free(struct mousedev *mousedev) ...@@ -356,7 +356,7 @@ static void mousedev_free(struct mousedev *mousedev)
kfree(mousedev); kfree(mousedev);
} }
static int mixdev_release(void) static void mixdev_release(void)
{ {
struct input_handle *handle; struct input_handle *handle;
...@@ -370,8 +370,6 @@ static int mixdev_release(void) ...@@ -370,8 +370,6 @@ static int mixdev_release(void)
mousedev_free(mousedev); mousedev_free(mousedev);
} }
} }
return 0;
} }
static int mousedev_release(struct inode * inode, struct file * file) static int mousedev_release(struct inode * inode, struct file * file)
...@@ -384,9 +382,8 @@ static int mousedev_release(struct inode * inode, struct file * file) ...@@ -384,9 +382,8 @@ static int mousedev_release(struct inode * inode, struct file * file)
if (!--list->mousedev->open) { if (!--list->mousedev->open) {
if (list->mousedev->minor == MOUSEDEV_MIX) if (list->mousedev->minor == MOUSEDEV_MIX)
return mixdev_release(); mixdev_release();
else if (!mousedev_mix.open) {
if (!mousedev_mix.open) {
if (list->mousedev->exist) if (list->mousedev->exist)
input_close_device(&list->mousedev->handle); input_close_device(&list->mousedev->handle);
else else
......
...@@ -154,7 +154,7 @@ static void mk712_close(struct input_dev *dev) ...@@ -154,7 +154,7 @@ static void mk712_close(struct input_dev *dev)
spin_unlock_irqrestore(&mk712_lock, flags); spin_unlock_irqrestore(&mk712_lock, flags);
} }
int __init mk712_init(void) static int __init mk712_init(void)
{ {
int err; int err;
......
...@@ -631,7 +631,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -631,7 +631,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
(uref_multi->num_values > HID_MAX_MULTI_USAGES || (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
uref->usage_index + uref_multi->num_values >= field->report_count)) uref->usage_index + uref_multi->num_values > field->report_count))
goto inval; goto inval;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment