aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Eckelmann <sven@narfation.org>2013-11-19 14:26:32 -0500
committerJiri Kosina <jkosina@suse.cz>2013-11-20 03:59:19 -0500
commit0a286ef278529f2bc4f4bb27c4cf99c05999c818 (patch)
treeb3fc8a9ad60e6d362a60e95dd0c20153c642acb6
parent2251b85f3dfd7be140e2d6a1f9d1e78287367a4f (diff)
HID: sony: Add LED support for Sixaxis/Dualshock3 USB
The PS3 Sixaxis controller has 4 LEDs which can be controlled using the same command as the rumble functionality. It seems not to be possible to only change the LED without modifying the rumble motor state. Thus both have to be stored on the host and retransmitted when either the LED or rumble state is changed. Third party controllers may not support to disable all LEDs at once. These controllers automatically switch to blinking of all LEDs when no LED is active anymore. Signed-off-by: Sven Eckelmann <sven@narfation.org> Tested-by: Simon Wood <simon@mungewell.org> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/hid-sony.c120
1 files changed, 72 insertions, 48 deletions
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 2f93aab11056..b60bc38903db 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -39,6 +39,8 @@
39#define BUZZ_CONTROLLER BIT(3) 39#define BUZZ_CONTROLLER BIT(3)
40#define PS3REMOTE BIT(4) 40#define PS3REMOTE BIT(4)
41 41
42#define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER_USB | BUZZ_CONTROLLER)
43
42static const u8 sixaxis_rdesc_fixup[] = { 44static const u8 sixaxis_rdesc_fixup[] = {
43 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C, 45 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C,
44 0x81, 0x01, 0x75, 0x10, 0x95, 0x04, 0x26, 0xFF, 46 0x81, 0x01, 0x75, 0x10, 0x95, 0x04, 0x26, 0xFF,
@@ -223,12 +225,12 @@ static const unsigned int buzz_keymap[] = {
223}; 225};
224 226
225struct sony_sc { 227struct sony_sc {
228 struct hid_device *hdev;
226 struct led_classdev *leds[4]; 229 struct led_classdev *leds[4];
227 unsigned long quirks; 230 unsigned long quirks;
231 struct work_struct state_worker;
228 232
229#ifdef CONFIG_SONY_FF 233#ifdef CONFIG_SONY_FF
230 struct work_struct state_worker;
231 struct hid_device *hdev;
232 __u8 left; 234 __u8 left;
233 __u8 right; 235 __u8 right;
234#endif 236#endif
@@ -462,6 +464,18 @@ static void buzz_set_leds(struct hid_device *hdev, int leds)
462 hid_hw_request(hdev, report, HID_REQ_SET_REPORT); 464 hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
463} 465}
464 466
467static void sony_set_leds(struct hid_device *hdev, __u8 leds)
468{
469 struct sony_sc *drv_data = hid_get_drvdata(hdev);
470
471 if (drv_data->quirks & BUZZ_CONTROLLER) {
472 buzz_set_leds(hdev, leds);
473 } else if (drv_data->quirks & SIXAXIS_CONTROLLER_USB) {
474 drv_data->led_state = leds;
475 schedule_work(&drv_data->state_worker);
476 }
477}
478
465static void sony_led_set_brightness(struct led_classdev *led, 479static void sony_led_set_brightness(struct led_classdev *led,
466 enum led_brightness value) 480 enum led_brightness value)
467{ 481{
@@ -482,10 +496,10 @@ static void sony_led_set_brightness(struct led_classdev *led,
482 int on = !!(drv_data->led_state & (1 << n)); 496 int on = !!(drv_data->led_state & (1 << n));
483 if (value == LED_OFF && on) { 497 if (value == LED_OFF && on) {
484 drv_data->led_state &= ~(1 << n); 498 drv_data->led_state &= ~(1 << n);
485 buzz_set_leds(hdev, drv_data->led_state); 499 sony_set_leds(hdev, drv_data->led_state);
486 } else if (value != LED_OFF && !on) { 500 } else if (value != LED_OFF && !on) {
487 drv_data->led_state |= (1 << n); 501 drv_data->led_state |= (1 << n);
488 buzz_set_leds(hdev, drv_data->led_state); 502 sony_set_leds(hdev, drv_data->led_state);
489 } 503 }
490 break; 504 break;
491 } 505 }
@@ -517,6 +531,25 @@ static enum led_brightness sony_led_get_brightness(struct led_classdev *led)
517 return on ? LED_FULL : LED_OFF; 531 return on ? LED_FULL : LED_OFF;
518} 532}
519 533
534static void sony_leds_remove(struct hid_device *hdev)
535{
536 struct sony_sc *drv_data;
537 struct led_classdev *led;
538 int n;
539
540 drv_data = hid_get_drvdata(hdev);
541 BUG_ON(!(drv_data->quirks & SONY_LED_SUPPORT));
542
543 for (n = 0; n < 4; n++) {
544 led = drv_data->leds[n];
545 drv_data->leds[n] = NULL;
546 if (!led)
547 continue;
548 led_classdev_unregister(led);
549 kfree(led);
550 }
551}
552
520static int sony_leds_init(struct hid_device *hdev) 553static int sony_leds_init(struct hid_device *hdev)
521{ 554{
522 struct sony_sc *drv_data; 555 struct sony_sc *drv_data;
@@ -524,20 +557,29 @@ static int sony_leds_init(struct hid_device *hdev)
524 struct led_classdev *led; 557 struct led_classdev *led;
525 size_t name_sz; 558 size_t name_sz;
526 char *name; 559 char *name;
560 size_t name_len;
561 const char *name_fmt;
527 562
528 drv_data = hid_get_drvdata(hdev); 563 drv_data = hid_get_drvdata(hdev);
529 BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER)); 564 BUG_ON(!(drv_data->quirks & SONY_LED_SUPPORT));
530 565
531 /* Validate expected report characteristics. */ 566 if (drv_data->quirks & BUZZ_CONTROLLER) {
532 if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7)) 567 name_len = strlen("::buzz#");
533 return -ENODEV; 568 name_fmt = "%s::buzz%d";
569 /* Validate expected report characteristics. */
570 if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7))
571 return -ENODEV;
572 } else {
573 name_len = strlen("::sony#");
574 name_fmt = "%s::sony%d";
575 }
534 576
535 /* Clear LEDs as we have no way of reading their initial state. This is 577 /* Clear LEDs as we have no way of reading their initial state. This is
536 * only relevant if the driver is loaded after somebody actively set the 578 * only relevant if the driver is loaded after somebody actively set the
537 * LEDs to on */ 579 * LEDs to on */
538 buzz_set_leds(hdev, 0x00); 580 sony_set_leds(hdev, 0x00);
539 581
540 name_sz = strlen(dev_name(&hdev->dev)) + strlen("::buzz#") + 1; 582 name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1;
541 583
542 for (n = 0; n < 4; n++) { 584 for (n = 0; n < 4; n++) {
543 led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL); 585 led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL);
@@ -547,7 +589,7 @@ static int sony_leds_init(struct hid_device *hdev)
547 } 589 }
548 590
549 name = (void *)(&led[1]); 591 name = (void *)(&led[1]);
550 snprintf(name, name_sz, "%s::buzz%d", dev_name(&hdev->dev), n + 1); 592 snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1);
551 led->name = name; 593 led->name = name;
552 led->brightness = 0; 594 led->brightness = 0;
553 led->max_brightness = 1; 595 led->max_brightness = 1;
@@ -566,45 +608,18 @@ static int sony_leds_init(struct hid_device *hdev)
566 return ret; 608 return ret;
567 609
568error_leds: 610error_leds:
569 for (n = 0; n < 4; n++) { 611 sony_leds_remove(hdev);
570 led = drv_data->leds[n];
571 drv_data->leds[n] = NULL;
572 if (!led)
573 continue;
574 led_classdev_unregister(led);
575 kfree(led);
576 }
577 612
578 return ret; 613 return ret;
579} 614}
580 615
581static void sony_leds_remove(struct hid_device *hdev)
582{
583 struct sony_sc *drv_data;
584 struct led_classdev *led;
585 int n;
586
587 drv_data = hid_get_drvdata(hdev);
588 BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER));
589
590 for (n = 0; n < 4; n++) {
591 led = drv_data->leds[n];
592 drv_data->leds[n] = NULL;
593 if (!led)
594 continue;
595 led_classdev_unregister(led);
596 kfree(led);
597 }
598}
599
600#ifdef CONFIG_SONY_FF
601static void sony_state_worker(struct work_struct *work) 616static void sony_state_worker(struct work_struct *work)
602{ 617{
603 struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); 618 struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
604 unsigned char buf[] = { 619 unsigned char buf[] = {
605 0x01, 620 0x01,
606 0x00, 0xff, 0x00, 0xff, 0x00, 621 0x00, 0xff, 0x00, 0xff, 0x00,
607 0x00, 0x00, 0x00, 0x00, 0x03, 622 0x00, 0x00, 0x00, 0x00, 0x00,
608 0xff, 0x27, 0x10, 0x00, 0x32, 623 0xff, 0x27, 0x10, 0x00, 0x32,
609 0xff, 0x27, 0x10, 0x00, 0x32, 624 0xff, 0x27, 0x10, 0x00, 0x32,
610 0xff, 0x27, 0x10, 0x00, 0x32, 625 0xff, 0x27, 0x10, 0x00, 0x32,
@@ -612,13 +627,18 @@ static void sony_state_worker(struct work_struct *work)
612 0x00, 0x00, 0x00, 0x00, 0x00 627 0x00, 0x00, 0x00, 0x00, 0x00
613 }; 628 };
614 629
630#ifdef CONFIG_SONY_FF
615 buf[3] = sc->right; 631 buf[3] = sc->right;
616 buf[5] = sc->left; 632 buf[5] = sc->left;
633#endif
634
635 buf[10] |= (sc->led_state & 0xf) << 1;
617 636
618 sc->hdev->hid_output_raw_report(sc->hdev, buf, sizeof(buf), 637 sc->hdev->hid_output_raw_report(sc->hdev, buf, sizeof(buf),
619 HID_OUTPUT_REPORT); 638 HID_OUTPUT_REPORT);
620} 639}
621 640
641#ifdef CONFIG_SONY_FF
622static int sony_play_effect(struct input_dev *dev, void *data, 642static int sony_play_effect(struct input_dev *dev, void *data,
623 struct ff_effect *effect) 643 struct ff_effect *effect)
624{ 644{
@@ -640,10 +660,6 @@ static int sony_init_ff(struct hid_device *hdev)
640 struct hid_input *hidinput = list_entry(hdev->inputs.next, 660 struct hid_input *hidinput = list_entry(hdev->inputs.next,
641 struct hid_input, list); 661 struct hid_input, list);
642 struct input_dev *input_dev = hidinput->input; 662 struct input_dev *input_dev = hidinput->input;
643 struct sony_sc *sc = hid_get_drvdata(hdev);
644
645 sc->hdev = hdev;
646 INIT_WORK(&sc->state_worker, sony_state_worker);
647 663
648 input_set_capability(input_dev, EV_FF, FF_RUMBLE); 664 input_set_capability(input_dev, EV_FF, FF_RUMBLE);
649 return input_ff_create_memless(input_dev, NULL, sony_play_effect); 665 return input_ff_create_memless(input_dev, NULL, sony_play_effect);
@@ -682,6 +698,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
682 698
683 sc->quirks = quirks; 699 sc->quirks = quirks;
684 hid_set_drvdata(hdev, sc); 700 hid_set_drvdata(hdev, sc);
701 sc->hdev = hdev;
685 702
686 ret = hid_parse(hdev); 703 ret = hid_parse(hdev);
687 if (ret) { 704 if (ret) {
@@ -705,23 +722,30 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
705 if (sc->quirks & SIXAXIS_CONTROLLER_USB) { 722 if (sc->quirks & SIXAXIS_CONTROLLER_USB) {
706 hdev->hid_output_raw_report = sixaxis_usb_output_raw_report; 723 hdev->hid_output_raw_report = sixaxis_usb_output_raw_report;
707 ret = sixaxis_set_operational_usb(hdev); 724 ret = sixaxis_set_operational_usb(hdev);
725 INIT_WORK(&sc->state_worker, sony_state_worker);
708 } 726 }
709 else if (sc->quirks & SIXAXIS_CONTROLLER_BT) 727 else if (sc->quirks & SIXAXIS_CONTROLLER_BT)
710 ret = sixaxis_set_operational_bt(hdev); 728 ret = sixaxis_set_operational_bt(hdev);
711 else if (sc->quirks & BUZZ_CONTROLLER)
712 ret = sony_leds_init(hdev);
713 else 729 else
714 ret = 0; 730 ret = 0;
715 731
716 if (ret < 0) 732 if (ret < 0)
717 goto err_stop; 733 goto err_stop;
718 734
735 if (sc->quirks & SONY_LED_SUPPORT) {
736 ret = sony_leds_init(hdev);
737 if (ret < 0)
738 goto err_stop;
739 }
740
719 ret = sony_init_ff(hdev); 741 ret = sony_init_ff(hdev);
720 if (ret < 0) 742 if (ret < 0)
721 goto err_stop; 743 goto err_stop;
722 744
723 return 0; 745 return 0;
724err_stop: 746err_stop:
747 if (sc->quirks & SONY_LED_SUPPORT)
748 sony_leds_remove(hdev);
725 hid_hw_stop(hdev); 749 hid_hw_stop(hdev);
726 return ret; 750 return ret;
727} 751}
@@ -730,7 +754,7 @@ static void sony_remove(struct hid_device *hdev)
730{ 754{
731 struct sony_sc *sc = hid_get_drvdata(hdev); 755 struct sony_sc *sc = hid_get_drvdata(hdev);
732 756
733 if (sc->quirks & BUZZ_CONTROLLER) 757 if (sc->quirks & SONY_LED_SUPPORT)
734 sony_leds_remove(hdev); 758 sony_leds_remove(hdev);
735 759
736 sony_destroy_ff(hdev); 760 sony_destroy_ff(hdev);