diff options
author | Frank Praznik <frank.praznik@oh.rr.com> | 2014-01-17 14:46:26 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2014-01-20 07:01:31 -0500 |
commit | c4e1ddf2680b357868deb3c7f5618d3d8ea500e2 (patch) | |
tree | 8474e0ef6d306d96f0ccd42f65461714fe450f11 | |
parent | ed19d8cf28b2b03ec05e75de9c1f73981b342978 (diff) |
HID: sony: Cache the output report for the Dualshock 4
Retrieve and cache the output report for the Dualshock 4 in sony_probe()
instead of repeatedly walking the report list in the worker function.
Signed-off-by: Frank Praznik <frank.praznik@oh.rr.com>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-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; |