diff options
| -rw-r--r-- | drivers/hid/hid-sony.c | 55 |
1 files changed, 35 insertions, 20 deletions
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index edffe2c47cf9..9013005a9f35 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c | |||
| @@ -298,6 +298,7 @@ static const unsigned int buzz_keymap[] = { | |||
| 298 | struct sony_sc { | 298 | struct sony_sc { |
| 299 | struct hid_device *hdev; | 299 | struct hid_device *hdev; |
| 300 | struct led_classdev *leds[MAX_LEDS]; | 300 | struct led_classdev *leds[MAX_LEDS]; |
| 301 | struct hid_report *output_report; | ||
| 301 | unsigned long quirks; | 302 | unsigned long quirks; |
| 302 | struct work_struct state_worker; | 303 | struct work_struct state_worker; |
| 303 | 304 | ||
| @@ -743,26 +744,9 @@ static void dualshock4_state_worker(struct work_struct *work) | |||
| 743 | { | 744 | { |
| 744 | struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); | 745 | struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); |
| 745 | struct hid_device *hdev = sc->hdev; | 746 | struct hid_device *hdev = sc->hdev; |
| 746 | struct list_head *head, *list; | 747 | struct hid_report *report = sc->output_report; |
| 747 | struct hid_report *report; | 748 | __s32 *value = report->field[0]->value; |
| 748 | __s32 *value; | ||
| 749 | |||
| 750 | list = &hdev->report_enum[HID_OUTPUT_REPORT].report_list; | ||
| 751 | |||
| 752 | list_for_each(head, list) { | ||
| 753 | report = list_entry(head, struct hid_report, list); | ||
| 754 | |||
| 755 | /* Report 5 is used to send data to the controller via USB */ | ||
| 756 | if ((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && report->id == 5) | ||
| 757 | break; | ||
| 758 | } | ||
| 759 | |||
| 760 | if (head == list) { | ||
| 761 | hid_err(hdev, "Dualshock 4 output report not found\n"); | ||
| 762 | return; | ||
| 763 | } | ||
| 764 | 749 | ||
| 765 | value = report->field[0]->value; | ||
| 766 | value[0] = 0x03; | 750 | value[0] = 0x03; |
| 767 | 751 | ||
| 768 | #ifdef CONFIG_SONY_FF | 752 | #ifdef CONFIG_SONY_FF |
| @@ -822,6 +806,33 @@ static void sony_destroy_ff(struct hid_device *hdev) | |||
| 822 | } | 806 | } |
| 823 | #endif | 807 | #endif |
| 824 | 808 | ||
| 809 | static int sony_set_output_report(struct sony_sc *sc, int req_id, int req_size) | ||
| 810 | { | ||
| 811 | struct list_head *head, *list; | ||
| 812 | struct hid_report *report; | ||
| 813 | struct hid_device *hdev = sc->hdev; | ||
| 814 | |||
| 815 | list = &hdev->report_enum[HID_OUTPUT_REPORT].report_list; | ||
| 816 | |||
| 817 | list_for_each(head, list) { | ||
| 818 | report = list_entry(head, struct hid_report, list); | ||
| 819 | |||
| 820 | if (report->id == req_id) { | ||
| 821 | if (report->size < req_size) { | ||
| 822 | hid_err(hdev, "Output report 0x%02x (%i bits) is smaller than requested size (%i bits)\n", | ||
| 823 | req_id, report->size, req_size); | ||
| 824 | return -EINVAL; | ||
| 825 | } | ||
| 826 | sc->output_report = report; | ||
| 827 | return 0; | ||
| 828 | } | ||
| 829 | } | ||
| 830 | |||
| 831 | hid_err(hdev, "Unable to locate output report 0x%02x\n", req_id); | ||
| 832 | |||
| 833 | return -EINVAL; | ||
| 834 | } | ||
| 835 | |||
| 825 | static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | 836 | static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) |
| 826 | { | 837 | { |
| 827 | int ret; | 838 | int ret; |
| @@ -866,7 +877,11 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 866 | else if (sc->quirks & SIXAXIS_CONTROLLER_BT) | 877 | else if (sc->quirks & SIXAXIS_CONTROLLER_BT) |
| 867 | ret = sixaxis_set_operational_bt(hdev); | 878 | ret = sixaxis_set_operational_bt(hdev); |
| 868 | else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { | 879 | else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { |
| 869 | ret = 0; | 880 | /* Report 5 (31 bytes) is used to send data to the controller via USB */ |
| 881 | ret = sony_set_output_report(sc, 0x05, 248); | ||
| 882 | if (ret < 0) | ||
| 883 | goto err_stop; | ||
| 884 | |||
| 870 | INIT_WORK(&sc->state_worker, dualshock4_state_worker); | 885 | INIT_WORK(&sc->state_worker, dualshock4_state_worker); |
| 871 | } else { | 886 | } else { |
| 872 | ret = 0; | 887 | ret = 0; |
