diff options
Diffstat (limited to 'drivers/input/joystick/adi.c')
-rw-r--r-- | drivers/input/joystick/adi.c | 93 |
1 files changed, 54 insertions, 39 deletions
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c index cf35ae638a0d..9d95459f4bcb 100644 --- a/drivers/input/joystick/adi.c +++ b/drivers/input/joystick/adi.c | |||
@@ -54,7 +54,7 @@ MODULE_LICENSE("GPL"); | |||
54 | #define ADI_MIN_LENGTH 8 | 54 | #define ADI_MIN_LENGTH 8 |
55 | #define ADI_MIN_LEN_LENGTH 10 | 55 | #define ADI_MIN_LEN_LENGTH 10 |
56 | #define ADI_MIN_ID_LENGTH 66 | 56 | #define ADI_MIN_ID_LENGTH 66 |
57 | #define ADI_MAX_NAME_LENGTH 48 | 57 | #define ADI_MAX_NAME_LENGTH 64 |
58 | #define ADI_MAX_CNAME_LENGTH 16 | 58 | #define ADI_MAX_CNAME_LENGTH 16 |
59 | #define ADI_MAX_PHYS_LENGTH 64 | 59 | #define ADI_MAX_PHYS_LENGTH 64 |
60 | 60 | ||
@@ -106,7 +106,7 @@ static struct { | |||
106 | */ | 106 | */ |
107 | 107 | ||
108 | struct adi { | 108 | struct adi { |
109 | struct input_dev dev; | 109 | struct input_dev *dev; |
110 | int length; | 110 | int length; |
111 | int ret; | 111 | int ret; |
112 | int idx; | 112 | int idx; |
@@ -215,7 +215,7 @@ static inline int adi_get_bits(struct adi *adi, int count) | |||
215 | 215 | ||
216 | static int adi_decode(struct adi *adi) | 216 | static int adi_decode(struct adi *adi) |
217 | { | 217 | { |
218 | struct input_dev *dev = &adi->dev; | 218 | struct input_dev *dev = adi->dev; |
219 | char *abs = adi->abs; | 219 | char *abs = adi->abs; |
220 | short *key = adi->key; | 220 | short *key = adi->key; |
221 | int i, t; | 221 | int i, t; |
@@ -318,7 +318,8 @@ static void adi_init_digital(struct gameport *gameport) | |||
318 | 318 | ||
319 | for (i = 0; seq[i]; i++) { | 319 | for (i = 0; seq[i]; i++) { |
320 | gameport_trigger(gameport); | 320 | gameport_trigger(gameport); |
321 | if (seq[i] > 0) msleep(seq[i]); | 321 | if (seq[i] > 0) |
322 | msleep(seq[i]); | ||
322 | if (seq[i] < 0) { | 323 | if (seq[i] < 0) { |
323 | mdelay(-seq[i]); | 324 | mdelay(-seq[i]); |
324 | udelay(-seq[i]*14); /* It looks like mdelay() is off by approx 1.4% */ | 325 | udelay(-seq[i]*14); /* It looks like mdelay() is off by approx 1.4% */ |
@@ -397,42 +398,46 @@ static void adi_id_decode(struct adi *adi, struct adi_port *port) | |||
397 | } | 398 | } |
398 | } | 399 | } |
399 | 400 | ||
400 | static void adi_init_input(struct adi *adi, struct adi_port *port, int half) | 401 | static int adi_init_input(struct adi *adi, struct adi_port *port, int half) |
401 | { | 402 | { |
402 | int i, t; | 403 | struct input_dev *input_dev; |
403 | char buf[ADI_MAX_NAME_LENGTH]; | 404 | char buf[ADI_MAX_NAME_LENGTH]; |
405 | int i, t; | ||
404 | 406 | ||
405 | if (!adi->length) return; | 407 | adi->dev = input_dev = input_allocate_device(); |
406 | 408 | if (!input_dev) | |
407 | init_input_dev(&adi->dev); | 409 | return -ENOMEM; |
408 | 410 | ||
409 | t = adi->id < ADI_ID_MAX ? adi->id : ADI_ID_MAX; | 411 | t = adi->id < ADI_ID_MAX ? adi->id : ADI_ID_MAX; |
410 | 412 | ||
411 | snprintf(buf, ADI_MAX_PHYS_LENGTH, adi_names[t], adi->id); | 413 | snprintf(buf, ADI_MAX_PHYS_LENGTH, adi_names[t], adi->id); |
412 | snprintf(adi->name, ADI_MAX_NAME_LENGTH, "Logitech %s", buf); | 414 | snprintf(adi->name, ADI_MAX_NAME_LENGTH, "Logitech %s [%s]", buf, adi->cname); |
413 | snprintf(adi->phys, ADI_MAX_PHYS_LENGTH, "%s/input%d", port->gameport->phys, half); | 415 | snprintf(adi->phys, ADI_MAX_PHYS_LENGTH, "%s/input%d", port->gameport->phys, half); |
414 | 416 | ||
415 | adi->abs = adi_abs[t]; | 417 | adi->abs = adi_abs[t]; |
416 | adi->key = adi_key[t]; | 418 | adi->key = adi_key[t]; |
417 | 419 | ||
418 | adi->dev.open = adi_open; | 420 | input_dev->name = adi->name; |
419 | adi->dev.close = adi_close; | 421 | input_dev->phys = adi->phys; |
422 | input_dev->id.bustype = BUS_GAMEPORT; | ||
423 | input_dev->id.vendor = GAMEPORT_ID_VENDOR_LOGITECH; | ||
424 | input_dev->id.product = adi->id; | ||
425 | input_dev->id.version = 0x0100; | ||
426 | input_dev->cdev.dev = &port->gameport->dev; | ||
427 | input_dev->private = port; | ||
420 | 428 | ||
421 | adi->dev.name = adi->name; | 429 | input_dev->open = adi_open; |
422 | adi->dev.phys = adi->phys; | 430 | input_dev->close = adi_close; |
423 | adi->dev.id.bustype = BUS_GAMEPORT; | ||
424 | adi->dev.id.vendor = GAMEPORT_ID_VENDOR_LOGITECH; | ||
425 | adi->dev.id.product = adi->id; | ||
426 | adi->dev.id.version = 0x0100; | ||
427 | 431 | ||
428 | adi->dev.private = port; | 432 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); |
429 | adi->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
430 | 433 | ||
431 | for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++) | 434 | for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++) |
432 | set_bit(adi->abs[i], adi->dev.absbit); | 435 | set_bit(adi->abs[i], input_dev->absbit); |
433 | 436 | ||
434 | for (i = 0; i < adi->buttons; i++) | 437 | for (i = 0; i < adi->buttons; i++) |
435 | set_bit(adi->key[i], adi->dev.keybit); | 438 | set_bit(adi->key[i], input_dev->keybit); |
439 | |||
440 | return 0; | ||
436 | } | 441 | } |
437 | 442 | ||
438 | static void adi_init_center(struct adi *adi) | 443 | static void adi_init_center(struct adi *adi) |
@@ -445,17 +450,17 @@ static void adi_init_center(struct adi *adi) | |||
445 | for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++) { | 450 | for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++) { |
446 | 451 | ||
447 | t = adi->abs[i]; | 452 | t = adi->abs[i]; |
448 | x = adi->dev.abs[t]; | 453 | x = adi->dev->abs[t]; |
449 | 454 | ||
450 | if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE) | 455 | if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE) |
451 | x = i < adi->axes10 ? 512 : 128; | 456 | x = i < adi->axes10 ? 512 : 128; |
452 | 457 | ||
453 | if (i < adi->axes10) | 458 | if (i < adi->axes10) |
454 | input_set_abs_params(&adi->dev, t, 64, x * 2 - 64, 2, 16); | 459 | input_set_abs_params(adi->dev, t, 64, x * 2 - 64, 2, 16); |
455 | else if (i < adi->axes10 + adi->axes8) | 460 | else if (i < adi->axes10 + adi->axes8) |
456 | input_set_abs_params(&adi->dev, t, 48, x * 2 - 48, 1, 16); | 461 | input_set_abs_params(adi->dev, t, 48, x * 2 - 48, 1, 16); |
457 | else | 462 | else |
458 | input_set_abs_params(&adi->dev, t, -1, 1, 0, 0); | 463 | input_set_abs_params(adi->dev, t, -1, 1, 0, 0); |
459 | } | 464 | } |
460 | } | 465 | } |
461 | 466 | ||
@@ -469,7 +474,8 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
469 | int i; | 474 | int i; |
470 | int err; | 475 | int err; |
471 | 476 | ||
472 | if (!(port = kzalloc(sizeof(struct adi_port), GFP_KERNEL))) | 477 | port = kzalloc(sizeof(struct adi_port), GFP_KERNEL); |
478 | if (!port) | ||
473 | return -ENOMEM; | 479 | return -ENOMEM; |
474 | 480 | ||
475 | port->gameport = gameport; | 481 | port->gameport = gameport; |
@@ -477,10 +483,8 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
477 | gameport_set_drvdata(gameport, port); | 483 | gameport_set_drvdata(gameport, port); |
478 | 484 | ||
479 | err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW); | 485 | err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW); |
480 | if (err) { | 486 | if (err) |
481 | kfree(port); | 487 | goto fail1; |
482 | return err; | ||
483 | } | ||
484 | 488 | ||
485 | adi_init_digital(gameport); | 489 | adi_init_digital(gameport); |
486 | adi_read_packet(port); | 490 | adi_read_packet(port); |
@@ -490,13 +494,18 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
490 | 494 | ||
491 | for (i = 0; i < 2; i++) { | 495 | for (i = 0; i < 2; i++) { |
492 | adi_id_decode(port->adi + i, port); | 496 | adi_id_decode(port->adi + i, port); |
493 | adi_init_input(port->adi + i, port, i); | 497 | |
498 | if (!port->adi[i].length) | ||
499 | continue; | ||
500 | |||
501 | err = adi_init_input(port->adi + i, port, i); | ||
502 | if (err) | ||
503 | goto fail2; | ||
494 | } | 504 | } |
495 | 505 | ||
496 | if (!port->adi[0].length && !port->adi[1].length) { | 506 | if (!port->adi[0].length && !port->adi[1].length) { |
497 | gameport_close(gameport); | 507 | err = -ENODEV; |
498 | kfree(port); | 508 | goto fail2; |
499 | return -ENODEV; | ||
500 | } | 509 | } |
501 | 510 | ||
502 | gameport_set_poll_handler(gameport, adi_poll); | 511 | gameport_set_poll_handler(gameport, adi_poll); |
@@ -511,12 +520,18 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
511 | for (i = 0; i < 2; i++) | 520 | for (i = 0; i < 2; i++) |
512 | if (port->adi[i].length > 0) { | 521 | if (port->adi[i].length > 0) { |
513 | adi_init_center(port->adi + i); | 522 | adi_init_center(port->adi + i); |
514 | input_register_device(&port->adi[i].dev); | 523 | input_register_device(port->adi[i].dev); |
515 | printk(KERN_INFO "input: %s [%s] on %s\n", | ||
516 | port->adi[i].name, port->adi[i].cname, gameport->phys); | ||
517 | } | 524 | } |
518 | 525 | ||
519 | return 0; | 526 | return 0; |
527 | |||
528 | fail2: for (i = 0; i < 2; i++) | ||
529 | if (port->adi[i].dev) | ||
530 | input_free_device(port->adi[i].dev); | ||
531 | gameport_close(gameport); | ||
532 | fail1: gameport_set_drvdata(gameport, NULL); | ||
533 | kfree(port); | ||
534 | return err; | ||
520 | } | 535 | } |
521 | 536 | ||
522 | static void adi_disconnect(struct gameport *gameport) | 537 | static void adi_disconnect(struct gameport *gameport) |
@@ -526,7 +541,7 @@ static void adi_disconnect(struct gameport *gameport) | |||
526 | 541 | ||
527 | for (i = 0; i < 2; i++) | 542 | for (i = 0; i < 2; i++) |
528 | if (port->adi[i].length > 0) | 543 | if (port->adi[i].length > 0) |
529 | input_unregister_device(&port->adi[i].dev); | 544 | input_unregister_device(port->adi[i].dev); |
530 | gameport_close(gameport); | 545 | gameport_close(gameport); |
531 | gameport_set_drvdata(gameport, NULL); | 546 | gameport_set_drvdata(gameport, NULL); |
532 | kfree(port); | 547 | kfree(port); |