diff options
-rw-r--r-- | drivers/input/joystick/a3d.c | 88 |
1 files changed, 46 insertions, 42 deletions
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c index 4571ea3a4b92..4612d13ea756 100644 --- a/drivers/input/joystick/a3d.c +++ b/drivers/input/joystick/a3d.c | |||
@@ -57,7 +57,7 @@ static char *a3d_names[] = { NULL, "FP-Gaming Assassin 3D", "MadCatz Panther", " | |||
57 | struct a3d { | 57 | struct a3d { |
58 | struct gameport *gameport; | 58 | struct gameport *gameport; |
59 | struct gameport *adc; | 59 | struct gameport *adc; |
60 | struct input_dev dev; | 60 | struct input_dev *dev; |
61 | int axes[4]; | 61 | int axes[4]; |
62 | int buttons; | 62 | int buttons; |
63 | int mode; | 63 | int mode; |
@@ -115,7 +115,7 @@ static int a3d_csum(char *data, int count) | |||
115 | 115 | ||
116 | static void a3d_read(struct a3d *a3d, unsigned char *data) | 116 | static void a3d_read(struct a3d *a3d, unsigned char *data) |
117 | { | 117 | { |
118 | struct input_dev *dev = &a3d->dev; | 118 | struct input_dev *dev = a3d->dev; |
119 | 119 | ||
120 | switch (a3d->mode) { | 120 | switch (a3d->mode) { |
121 | 121 | ||
@@ -265,14 +265,20 @@ static void a3d_close(struct input_dev *dev) | |||
265 | static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv) | 265 | static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv) |
266 | { | 266 | { |
267 | struct a3d *a3d; | 267 | struct a3d *a3d; |
268 | struct input_dev *input_dev; | ||
268 | struct gameport *adc; | 269 | struct gameport *adc; |
269 | unsigned char data[A3D_MAX_LENGTH]; | 270 | unsigned char data[A3D_MAX_LENGTH]; |
270 | int i; | 271 | int i; |
271 | int err; | 272 | int err; |
272 | 273 | ||
273 | if (!(a3d = kzalloc(sizeof(struct a3d), GFP_KERNEL))) | 274 | a3d = kzalloc(sizeof(struct a3d), GFP_KERNEL); |
274 | return -ENOMEM; | 275 | input_dev = input_allocate_device(); |
276 | if (!a3d || !input_dev) { | ||
277 | err = -ENOMEM; | ||
278 | goto fail1; | ||
279 | } | ||
275 | 280 | ||
281 | a3d->dev = input_dev; | ||
276 | a3d->gameport = gameport; | 282 | a3d->gameport = gameport; |
277 | 283 | ||
278 | gameport_set_drvdata(gameport, a3d); | 284 | gameport_set_drvdata(gameport, a3d); |
@@ -302,42 +308,48 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
302 | 308 | ||
303 | sprintf(a3d->phys, "%s/input0", gameport->phys); | 309 | sprintf(a3d->phys, "%s/input0", gameport->phys); |
304 | 310 | ||
311 | input_dev->name = a3d_names[a3d->mode]; | ||
312 | input_dev->phys = a3d->phys; | ||
313 | input_dev->id.bustype = BUS_GAMEPORT; | ||
314 | input_dev->id.vendor = GAMEPORT_ID_VENDOR_MADCATZ; | ||
315 | input_dev->id.product = a3d->mode; | ||
316 | input_dev->id.version = 0x0100; | ||
317 | input_dev->cdev.dev = &gameport->dev; | ||
318 | input_dev->private = a3d; | ||
319 | input_dev->open = a3d_open; | ||
320 | input_dev->close = a3d_close; | ||
321 | |||
305 | if (a3d->mode == A3D_MODE_PXL) { | 322 | if (a3d->mode == A3D_MODE_PXL) { |
306 | 323 | ||
307 | int axes[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER }; | 324 | int axes[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER }; |
308 | 325 | ||
309 | a3d->length = 33; | 326 | a3d->length = 33; |
310 | 327 | ||
311 | init_input_dev(&a3d->dev); | 328 | input_dev->evbit[0] |= BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL); |
312 | 329 | input_dev->relbit[0] |= BIT(REL_X) | BIT(REL_Y); | |
313 | a3d->dev.evbit[0] |= BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL); | 330 | input_dev->absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_RUDDER) |
314 | a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y); | 331 | | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y) | BIT(ABS_HAT1X) | BIT(ABS_HAT1Y); |
315 | a3d->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_RUDDER) | 332 | input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE) |
316 | | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y) | BIT(ABS_HAT1X) | BIT(ABS_HAT1Y); | 333 | | BIT(BTN_SIDE) | BIT(BTN_EXTRA); |
317 | 334 | input_dev->keybit[LONG(BTN_JOYSTICK)] |= BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | |
318 | a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | 335 | | BIT(BTN_PINKIE); |
319 | | BIT(BTN_SIDE) | BIT(BTN_EXTRA); | ||
320 | |||
321 | a3d->dev.keybit[LONG(BTN_JOYSTICK)] |= BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_PINKIE); | ||
322 | 336 | ||
323 | a3d_read(a3d, data); | 337 | a3d_read(a3d, data); |
324 | 338 | ||
325 | for (i = 0; i < 4; i++) { | 339 | for (i = 0; i < 4; i++) { |
326 | if (i < 2) | 340 | if (i < 2) |
327 | input_set_abs_params(&a3d->dev, axes[i], 48, a3d->dev.abs[axes[i]] * 2 - 48, 0, 8); | 341 | input_set_abs_params(input_dev, axes[i], 48, input_dev->abs[axes[i]] * 2 - 48, 0, 8); |
328 | else | 342 | else |
329 | input_set_abs_params(&a3d->dev, axes[i], 2, 253, 0, 0); | 343 | input_set_abs_params(input_dev, axes[i], 2, 253, 0, 0); |
330 | input_set_abs_params(&a3d->dev, ABS_HAT0X + i, -1, 1, 0, 0); | 344 | input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0); |
331 | } | 345 | } |
332 | 346 | ||
333 | } else { | 347 | } else { |
334 | a3d->length = 29; | 348 | a3d->length = 29; |
335 | 349 | ||
336 | init_input_dev(&a3d->dev); | 350 | input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_REL); |
337 | 351 | input_dev->relbit[0] |= BIT(REL_X) | BIT(REL_Y); | |
338 | a3d->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_REL); | 352 | input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE); |
339 | a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y); | ||
340 | a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE); | ||
341 | 353 | ||
342 | a3d_read(a3d, data); | 354 | a3d_read(a3d, data); |
343 | 355 | ||
@@ -358,24 +370,17 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
358 | } | 370 | } |
359 | } | 371 | } |
360 | 372 | ||
361 | a3d->dev.private = a3d; | 373 | err = input_register_device(a3d->dev); |
362 | a3d->dev.open = a3d_open; | 374 | if (err) |
363 | a3d->dev.close = a3d_close; | 375 | goto fail3; |
364 | |||
365 | a3d->dev.name = a3d_names[a3d->mode]; | ||
366 | a3d->dev.phys = a3d->phys; | ||
367 | a3d->dev.id.bustype = BUS_GAMEPORT; | ||
368 | a3d->dev.id.vendor = GAMEPORT_ID_VENDOR_MADCATZ; | ||
369 | a3d->dev.id.product = a3d->mode; | ||
370 | a3d->dev.id.version = 0x0100; | ||
371 | |||
372 | input_register_device(&a3d->dev); | ||
373 | printk(KERN_INFO "input: %s on %s\n", a3d_names[a3d->mode], a3d->phys); | ||
374 | 376 | ||
375 | return 0; | 377 | return 0; |
376 | 378 | ||
377 | fail2: gameport_close(gameport); | 379 | fail3: if (a3d->adc) |
378 | fail1: gameport_set_drvdata(gameport, NULL); | 380 | gameport_unregister_port(a3d->adc); |
381 | fail2: gameport_close(gameport); | ||
382 | fail1: gameport_set_drvdata(gameport, NULL); | ||
383 | input_free_device(input_dev); | ||
379 | kfree(a3d); | 384 | kfree(a3d); |
380 | return err; | 385 | return err; |
381 | } | 386 | } |
@@ -384,11 +389,9 @@ static void a3d_disconnect(struct gameport *gameport) | |||
384 | { | 389 | { |
385 | struct a3d *a3d = gameport_get_drvdata(gameport); | 390 | struct a3d *a3d = gameport_get_drvdata(gameport); |
386 | 391 | ||
387 | input_unregister_device(&a3d->dev); | 392 | input_unregister_device(a3d->dev); |
388 | if (a3d->adc) { | 393 | if (a3d->adc) |
389 | gameport_unregister_port(a3d->adc); | 394 | gameport_unregister_port(a3d->adc); |
390 | a3d->adc = NULL; | ||
391 | } | ||
392 | gameport_close(gameport); | 395 | gameport_close(gameport); |
393 | gameport_set_drvdata(gameport, NULL); | 396 | gameport_set_drvdata(gameport, NULL); |
394 | kfree(a3d); | 397 | kfree(a3d); |
@@ -397,6 +400,7 @@ static void a3d_disconnect(struct gameport *gameport) | |||
397 | static struct gameport_driver a3d_drv = { | 400 | static struct gameport_driver a3d_drv = { |
398 | .driver = { | 401 | .driver = { |
399 | .name = "adc", | 402 | .name = "adc", |
403 | .owner = THIS_MODULE, | ||
400 | }, | 404 | }, |
401 | .description = DRIVER_DESC, | 405 | .description = DRIVER_DESC, |
402 | .connect = a3d_connect, | 406 | .connect = a3d_connect, |