diff options
author | Frank Praznik <frank.praznik@oh.rr.com> | 2015-05-05 20:47:30 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2015-05-07 04:41:35 -0400 |
commit | c5e0c1c4950f9126f7eb2fb1d3f8aa4080f05538 (patch) | |
tree | 89bbf962abc0b4cb9b1f9227f0a457c013e8b6d1 | |
parent | 7c886d098d6128438e706ca4c068b8920fdac42d (diff) |
HID: sony: Add support for the Sony Motion Controller
Add a fixed-up HID descriptor for the Sony motion controller and enable
controls for the LED light as well as force-feedback.
The LED is multi-colored (red, green, blue).
The motion controller has a single rumble motor so the higher of the left
and right values is used to set the speed.
Signed-off-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Frank Praznik <frank.praznik@oh.rr.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | drivers/hid/hid-sony.c | 138 |
1 files changed, 136 insertions, 2 deletions
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 4c521b2c6a82..d0b18a5779d7 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c | |||
@@ -46,14 +46,16 @@ | |||
46 | #define PS3REMOTE BIT(4) | 46 | #define PS3REMOTE BIT(4) |
47 | #define DUALSHOCK4_CONTROLLER_USB BIT(5) | 47 | #define DUALSHOCK4_CONTROLLER_USB BIT(5) |
48 | #define DUALSHOCK4_CONTROLLER_BT BIT(6) | 48 | #define DUALSHOCK4_CONTROLLER_BT BIT(6) |
49 | #define MOTION_CONTROLLER BIT(7) | ||
49 | 50 | ||
50 | #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT) | 51 | #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT) |
51 | #define DUALSHOCK4_CONTROLLER (DUALSHOCK4_CONTROLLER_USB |\ | 52 | #define DUALSHOCK4_CONTROLLER (DUALSHOCK4_CONTROLLER_USB |\ |
52 | DUALSHOCK4_CONTROLLER_BT) | 53 | DUALSHOCK4_CONTROLLER_BT) |
53 | #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\ | 54 | #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\ |
54 | DUALSHOCK4_CONTROLLER) | 55 | DUALSHOCK4_CONTROLLER | MOTION_CONTROLLER) |
55 | #define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER) | 56 | #define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER) |
56 | #define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER) | 57 | #define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\ |
58 | MOTION_CONTROLLER) | ||
57 | 59 | ||
58 | #define MAX_LEDS 4 | 60 | #define MAX_LEDS 4 |
59 | 61 | ||
@@ -134,6 +136,85 @@ static __u8 sixaxis_rdesc[] = { | |||
134 | 0xC0 /* End Collection */ | 136 | 0xC0 /* End Collection */ |
135 | }; | 137 | }; |
136 | 138 | ||
139 | /* PS/3 Motion controller */ | ||
140 | static __u8 motion_rdesc[] = { | ||
141 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
142 | 0x09, 0x04, /* Usage (Joystick), */ | ||
143 | 0xA1, 0x01, /* Collection (Application), */ | ||
144 | 0xA1, 0x02, /* Collection (Logical), */ | ||
145 | 0x85, 0x01, /* Report ID (1), */ | ||
146 | 0x75, 0x08, /* Report Size (8), */ | ||
147 | 0x95, 0x01, /* Report Count (1), */ | ||
148 | 0x15, 0x00, /* Logical Minimum (0), */ | ||
149 | 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ | ||
150 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
151 | 0x75, 0x01, /* Report Size (1), */ | ||
152 | 0x95, 0x13, /* Report Count (19), */ | ||
153 | 0x15, 0x00, /* Logical Minimum (0), */ | ||
154 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
155 | 0x35, 0x00, /* Physical Minimum (0), */ | ||
156 | 0x45, 0x01, /* Physical Maximum (1), */ | ||
157 | 0x05, 0x09, /* Usage Page (Button), */ | ||
158 | 0x19, 0x01, /* Usage Minimum (01h), */ | ||
159 | 0x29, 0x13, /* Usage Maximum (13h), */ | ||
160 | 0x81, 0x02, /* Input (Variable), */ | ||
161 | 0x75, 0x01, /* Report Size (1), */ | ||
162 | 0x95, 0x0D, /* Report Count (13), */ | ||
163 | 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ | ||
164 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
165 | 0x15, 0x00, /* Logical Minimum (0), */ | ||
166 | 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ | ||
167 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
168 | 0x09, 0x01, /* Usage (Pointer), */ | ||
169 | 0xA1, 0x00, /* Collection (Physical), */ | ||
170 | 0x75, 0x08, /* Report Size (8), */ | ||
171 | 0x95, 0x04, /* Report Count (4), */ | ||
172 | 0x35, 0x00, /* Physical Minimum (0), */ | ||
173 | 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ | ||
174 | 0x09, 0x30, /* Usage (X), */ | ||
175 | 0x09, 0x31, /* Usage (Y), */ | ||
176 | 0x09, 0x32, /* Usage (Z), */ | ||
177 | 0x09, 0x35, /* Usage (Rz), */ | ||
178 | 0x81, 0x02, /* Input (Variable), */ | ||
179 | 0xC0, /* End Collection, */ | ||
180 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
181 | 0x95, 0x13, /* Report Count (19), */ | ||
182 | 0x09, 0x01, /* Usage (Pointer), */ | ||
183 | 0x81, 0x02, /* Input (Variable), */ | ||
184 | 0x95, 0x0C, /* Report Count (12), */ | ||
185 | 0x81, 0x01, /* Input (Constant), */ | ||
186 | 0x75, 0x10, /* Report Size (16), */ | ||
187 | 0x95, 0x04, /* Report Count (4), */ | ||
188 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
189 | 0x46, 0xFF, 0x03, /* Physical Maximum (1023), */ | ||
190 | 0x09, 0x01, /* Usage (Pointer), */ | ||
191 | 0x81, 0x02, /* Input (Variable), */ | ||
192 | 0xC0, /* End Collection, */ | ||
193 | 0xA1, 0x02, /* Collection (Logical), */ | ||
194 | 0x85, 0x02, /* Report ID (2), */ | ||
195 | 0x75, 0x08, /* Report Size (8), */ | ||
196 | 0x95, 0x30, /* Report Count (48), */ | ||
197 | 0x09, 0x01, /* Usage (Pointer), */ | ||
198 | 0xB1, 0x02, /* Feature (Variable), */ | ||
199 | 0xC0, /* End Collection, */ | ||
200 | 0xA1, 0x02, /* Collection (Logical), */ | ||
201 | 0x85, 0xEE, /* Report ID (238), */ | ||
202 | 0x75, 0x08, /* Report Size (8), */ | ||
203 | 0x95, 0x30, /* Report Count (48), */ | ||
204 | 0x09, 0x01, /* Usage (Pointer), */ | ||
205 | 0xB1, 0x02, /* Feature (Variable), */ | ||
206 | 0xC0, /* End Collection, */ | ||
207 | 0xA1, 0x02, /* Collection (Logical), */ | ||
208 | 0x85, 0xEF, /* Report ID (239), */ | ||
209 | 0x75, 0x08, /* Report Size (8), */ | ||
210 | 0x95, 0x30, /* Report Count (48), */ | ||
211 | 0x09, 0x01, /* Usage (Pointer), */ | ||
212 | 0xB1, 0x02, /* Feature (Variable), */ | ||
213 | 0xC0, /* End Collection, */ | ||
214 | 0xC0 /* End Collection */ | ||
215 | }; | ||
216 | |||
217 | |||
137 | /* | 218 | /* |
138 | * The default descriptor doesn't provide mapping for the accelerometers | 219 | * The default descriptor doesn't provide mapping for the accelerometers |
139 | * or orientation sensors. This fixed descriptor maps the accelerometers | 220 | * or orientation sensors. This fixed descriptor maps the accelerometers |
@@ -798,6 +879,13 @@ union sixaxis_output_report_01 { | |||
798 | __u8 buf[36]; | 879 | __u8 buf[36]; |
799 | }; | 880 | }; |
800 | 881 | ||
882 | struct motion_output_report_02 { | ||
883 | u8 type, zero; | ||
884 | u8 r, g, b; | ||
885 | u8 zero2; | ||
886 | u8 rumble; | ||
887 | }; | ||
888 | |||
801 | #define DS4_REPORT_0x02_SIZE 37 | 889 | #define DS4_REPORT_0x02_SIZE 37 |
802 | #define DS4_REPORT_0x05_SIZE 32 | 890 | #define DS4_REPORT_0x05_SIZE 32 |
803 | #define DS4_REPORT_0x11_SIZE 78 | 891 | #define DS4_REPORT_0x11_SIZE 78 |
@@ -844,6 +932,13 @@ static __u8 *sixaxis_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
844 | return sixaxis_rdesc; | 932 | return sixaxis_rdesc; |
845 | } | 933 | } |
846 | 934 | ||
935 | static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc, | ||
936 | unsigned int *rsize) | ||
937 | { | ||
938 | *rsize = sizeof(motion_rdesc); | ||
939 | return motion_rdesc; | ||
940 | } | ||
941 | |||
847 | static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, | 942 | static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, |
848 | unsigned int *rsize) | 943 | unsigned int *rsize) |
849 | { | 944 | { |
@@ -924,6 +1019,9 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
924 | if (sc->quirks & SIXAXIS_CONTROLLER) | 1019 | if (sc->quirks & SIXAXIS_CONTROLLER) |
925 | return sixaxis_fixup(hdev, rdesc, rsize); | 1020 | return sixaxis_fixup(hdev, rdesc, rsize); |
926 | 1021 | ||
1022 | if (sc->quirks & MOTION_CONTROLLER) | ||
1023 | return motion_fixup(hdev, rdesc, rsize); | ||
1024 | |||
927 | if (sc->quirks & PS3REMOTE) | 1025 | if (sc->quirks & PS3REMOTE) |
928 | return ps3remote_fixup(hdev, rdesc, rsize); | 1026 | return ps3remote_fixup(hdev, rdesc, rsize); |
929 | 1027 | ||
@@ -1454,6 +1552,12 @@ static int sony_leds_init(struct sony_sc *sc) | |||
1454 | use_ds4_names = 1; | 1552 | use_ds4_names = 1; |
1455 | name_len = 0; | 1553 | name_len = 0; |
1456 | name_fmt = "%s:%s"; | 1554 | name_fmt = "%s:%s"; |
1555 | } else if (sc->quirks & MOTION_CONTROLLER) { | ||
1556 | sc->led_count = 3; | ||
1557 | memset(max_brightness, 255, 3); | ||
1558 | use_ds4_names = 1; | ||
1559 | name_len = 0; | ||
1560 | name_fmt = "%s:%s"; | ||
1457 | } else { | 1561 | } else { |
1458 | sixaxis_set_leds_from_id(sc->device_id, initial_values); | 1562 | sixaxis_set_leds_from_id(sc->device_id, initial_values); |
1459 | sc->led_count = 4; | 1563 | sc->led_count = 4; |
@@ -1622,6 +1726,28 @@ static void dualshock4_state_worker(struct work_struct *work) | |||
1622 | HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); | 1726 | HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); |
1623 | } | 1727 | } |
1624 | 1728 | ||
1729 | static void motion_state_worker(struct work_struct *work) | ||
1730 | { | ||
1731 | struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); | ||
1732 | struct hid_device *hdev = sc->hdev; | ||
1733 | struct motion_output_report_02 *report = | ||
1734 | (struct motion_output_report_02 *)sc->output_report_dmabuf; | ||
1735 | |||
1736 | memset(report, 0, sizeof(struct motion_output_report_02)); | ||
1737 | |||
1738 | report->type = 0x02; /* set leds */ | ||
1739 | report->r = sc->led_state[0]; | ||
1740 | report->g = sc->led_state[1]; | ||
1741 | report->b = sc->led_state[2]; | ||
1742 | |||
1743 | #ifdef CONFIG_SONY_FF | ||
1744 | report->rumble = max(sc->right, sc->left); | ||
1745 | #endif | ||
1746 | |||
1747 | hid_hw_output_report(hdev, (__u8 *)report, | ||
1748 | sizeof(struct motion_output_report_02)); | ||
1749 | } | ||
1750 | |||
1625 | static int sony_allocate_output_report(struct sony_sc *sc) | 1751 | static int sony_allocate_output_report(struct sony_sc *sc) |
1626 | { | 1752 | { |
1627 | if (sc->quirks & SIXAXIS_CONTROLLER) | 1753 | if (sc->quirks & SIXAXIS_CONTROLLER) |
@@ -1634,6 +1760,10 @@ static int sony_allocate_output_report(struct sony_sc *sc) | |||
1634 | else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) | 1760 | else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) |
1635 | sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x05_SIZE, | 1761 | sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x05_SIZE, |
1636 | GFP_KERNEL); | 1762 | GFP_KERNEL); |
1763 | else if (sc->quirks & MOTION_CONTROLLER) | ||
1764 | sc->output_report_dmabuf = | ||
1765 | kmalloc(sizeof(struct motion_output_report_02), | ||
1766 | GFP_KERNEL); | ||
1637 | else | 1767 | else |
1638 | return 0; | 1768 | return 0; |
1639 | 1769 | ||
@@ -2043,6 +2173,8 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
2043 | } | 2173 | } |
2044 | 2174 | ||
2045 | sony_init_work(sc, dualshock4_state_worker); | 2175 | sony_init_work(sc, dualshock4_state_worker); |
2176 | } else if (sc->quirks & MOTION_CONTROLLER) { | ||
2177 | sony_init_work(sc, motion_state_worker); | ||
2046 | } else { | 2178 | } else { |
2047 | ret = 0; | 2179 | ret = 0; |
2048 | } | 2180 | } |
@@ -2123,6 +2255,8 @@ static const struct hid_device_id sony_devices[] = { | |||
2123 | .driver_data = SIXAXIS_CONTROLLER_USB }, | 2255 | .driver_data = SIXAXIS_CONTROLLER_USB }, |
2124 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), | 2256 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), |
2125 | .driver_data = SIXAXIS_CONTROLLER_USB }, | 2257 | .driver_data = SIXAXIS_CONTROLLER_USB }, |
2258 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER), | ||
2259 | .driver_data = MOTION_CONTROLLER }, | ||
2126 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), | 2260 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), |
2127 | .driver_data = SIXAXIS_CONTROLLER_BT }, | 2261 | .driver_data = SIXAXIS_CONTROLLER_BT }, |
2128 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), | 2262 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), |