Skip to content

Commit e19a267

Browse files
Roderick ColenbranderJiri Kosina
authored andcommitted
HID: sony: DS3 comply to Linux gamepad spec
The axis and button mapping for the DS3 is strange. This is mostly due to the device reporting many axes as for every digital button it also has an analog button. Due to amount of analog values it is even leaking well into the MT axes range. We felt it is best to remove the many analog buttons and just report digital and comply to the Linux gamepad spec. The analog buttons are rarely used on the official platform, let alone on Linux. This patch does remove motion sensor support (added back in another patch). Signed-off-by: Roderick Colenbrander <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent b9f7d24 commit e19a267

File tree

1 file changed

+81
-95
lines changed

1 file changed

+81
-95
lines changed

drivers/hid/hid-sony.c

Lines changed: 81 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -75,89 +75,6 @@
7575

7676
#define MAX_LEDS 4
7777

78-
/*
79-
* The Sixaxis reports both digital and analog values for each button on the
80-
* controller except for Start, Select and the PS button. The controller ends
81-
* up reporting 27 axes which causes them to spill over into the multi-touch
82-
* axis values. Additionally, the controller only has 20 actual, physical axes
83-
* so there are several unused axes in between the used ones.
84-
*/
85-
static u8 sixaxis_rdesc[] = {
86-
0x05, 0x01, /* Usage Page (Desktop), */
87-
0x09, 0x04, /* Usage (Joystick), */
88-
0xA1, 0x01, /* Collection (Application), */
89-
0xA1, 0x02, /* Collection (Logical), */
90-
0x85, 0x01, /* Report ID (1), */
91-
0x75, 0x08, /* Report Size (8), */
92-
0x95, 0x01, /* Report Count (1), */
93-
0x15, 0x00, /* Logical Minimum (0), */
94-
0x26, 0xFF, 0x00, /* Logical Maximum (255), */
95-
0x81, 0x03, /* Input (Constant, Variable), */
96-
0x75, 0x01, /* Report Size (1), */
97-
0x95, 0x13, /* Report Count (19), */
98-
0x15, 0x00, /* Logical Minimum (0), */
99-
0x25, 0x01, /* Logical Maximum (1), */
100-
0x35, 0x00, /* Physical Minimum (0), */
101-
0x45, 0x01, /* Physical Maximum (1), */
102-
0x05, 0x09, /* Usage Page (Button), */
103-
0x19, 0x01, /* Usage Minimum (01h), */
104-
0x29, 0x13, /* Usage Maximum (13h), */
105-
0x81, 0x02, /* Input (Variable), */
106-
0x75, 0x01, /* Report Size (1), */
107-
0x95, 0x0D, /* Report Count (13), */
108-
0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
109-
0x81, 0x03, /* Input (Constant, Variable), */
110-
0x15, 0x00, /* Logical Minimum (0), */
111-
0x26, 0xFF, 0x00, /* Logical Maximum (255), */
112-
0x05, 0x01, /* Usage Page (Desktop), */
113-
0x09, 0x01, /* Usage (Pointer), */
114-
0xA1, 0x00, /* Collection (Physical), */
115-
0x75, 0x08, /* Report Size (8), */
116-
0x95, 0x04, /* Report Count (4), */
117-
0x35, 0x00, /* Physical Minimum (0), */
118-
0x46, 0xFF, 0x00, /* Physical Maximum (255), */
119-
0x09, 0x30, /* Usage (X), */
120-
0x09, 0x31, /* Usage (Y), */
121-
0x09, 0x32, /* Usage (Z), */
122-
0x09, 0x35, /* Usage (Rz), */
123-
0x81, 0x02, /* Input (Variable), */
124-
0xC0, /* End Collection, */
125-
0x05, 0x01, /* Usage Page (Desktop), */
126-
0x95, 0x13, /* Report Count (19), */
127-
0x09, 0x01, /* Usage (Pointer), */
128-
0x81, 0x02, /* Input (Variable), */
129-
0x95, 0x0C, /* Report Count (12), */
130-
0x81, 0x01, /* Input (Constant), */
131-
0x75, 0x10, /* Report Size (16), */
132-
0x95, 0x04, /* Report Count (4), */
133-
0x26, 0xFF, 0x03, /* Logical Maximum (1023), */
134-
0x46, 0xFF, 0x03, /* Physical Maximum (1023), */
135-
0x09, 0x01, /* Usage (Pointer), */
136-
0x81, 0x02, /* Input (Variable), */
137-
0xC0, /* End Collection, */
138-
0xA1, 0x02, /* Collection (Logical), */
139-
0x85, 0x02, /* Report ID (2), */
140-
0x75, 0x08, /* Report Size (8), */
141-
0x95, 0x30, /* Report Count (48), */
142-
0x09, 0x01, /* Usage (Pointer), */
143-
0xB1, 0x02, /* Feature (Variable), */
144-
0xC0, /* End Collection, */
145-
0xA1, 0x02, /* Collection (Logical), */
146-
0x85, 0xEE, /* Report ID (238), */
147-
0x75, 0x08, /* Report Size (8), */
148-
0x95, 0x30, /* Report Count (48), */
149-
0x09, 0x01, /* Usage (Pointer), */
150-
0xB1, 0x02, /* Feature (Variable), */
151-
0xC0, /* End Collection, */
152-
0xA1, 0x02, /* Collection (Logical), */
153-
0x85, 0xEF, /* Report ID (239), */
154-
0x75, 0x08, /* Report Size (8), */
155-
0x95, 0x30, /* Report Count (48), */
156-
0x09, 0x01, /* Usage (Pointer), */
157-
0xB1, 0x02, /* Feature (Variable), */
158-
0xC0, /* End Collection, */
159-
0xC0 /* End Collection */
160-
};
16178

16279
/* PS/3 Motion controller */
16380
static u8 motion_rdesc[] = {
@@ -508,6 +425,34 @@ static const unsigned int buzz_keymap[] = {
508425
[20] = BTN_TRIGGER_HAPPY20,
509426
};
510427

428+
static const unsigned int sixaxis_absmap[] = {
429+
[0x30] = ABS_X,
430+
[0x31] = ABS_Y,
431+
[0x32] = ABS_RX, /* right stick X */
432+
[0x35] = ABS_RY, /* right stick Y */
433+
};
434+
435+
static const unsigned int sixaxis_keymap[] = {
436+
[0x01] = BTN_SELECT, /* Select */
437+
[0x02] = BTN_THUMBL, /* L3 */
438+
[0x03] = BTN_THUMBR, /* R3 */
439+
[0x04] = BTN_START, /* Start */
440+
[0x05] = BTN_DPAD_UP, /* Up */
441+
[0x06] = BTN_DPAD_RIGHT, /* Right */
442+
[0x07] = BTN_DPAD_DOWN, /* Down */
443+
[0x08] = BTN_DPAD_LEFT, /* Left */
444+
[0x09] = BTN_TL2, /* L2 */
445+
[0x0a] = BTN_TR2, /* R2 */
446+
[0x0b] = BTN_TL, /* L1 */
447+
[0x0c] = BTN_TR, /* R1 */
448+
[0x0d] = BTN_NORTH, /* Triangle */
449+
[0x0e] = BTN_EAST, /* Circle */
450+
[0x0f] = BTN_SOUTH, /* Cross */
451+
[0x10] = BTN_WEST, /* Square */
452+
[0x11] = BTN_MODE, /* PS */
453+
};
454+
455+
511456
static const unsigned int ds4_absmap[] = {
512457
[0x30] = ABS_X,
513458
[0x31] = ABS_Y,
@@ -695,13 +640,6 @@ static inline void sony_schedule_work(struct sony_sc *sc,
695640
}
696641
}
697642

698-
static u8 *sixaxis_fixup(struct hid_device *hdev, u8 *rdesc,
699-
unsigned int *rsize)
700-
{
701-
*rsize = sizeof(sixaxis_rdesc);
702-
return sixaxis_rdesc;
703-
}
704-
705643
static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc,
706644
unsigned int *rsize)
707645
{
@@ -757,6 +695,54 @@ static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
757695
return 1;
758696
}
759697

698+
static int sixaxis_mapping(struct hid_device *hdev, struct hid_input *hi,
699+
struct hid_field *field, struct hid_usage *usage,
700+
unsigned long **bit, int *max)
701+
{
702+
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
703+
unsigned int key = usage->hid & HID_USAGE;
704+
705+
if (key >= ARRAY_SIZE(sixaxis_keymap))
706+
return -1;
707+
708+
key = sixaxis_keymap[key];
709+
hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
710+
return 1;
711+
} else if (usage->hid == HID_GD_POINTER) {
712+
/* The DS3 provides analog values for most buttons and even
713+
* for HAT axes through GD Pointer. L2 and R2 are reported
714+
* among these as well instead of as GD Z / RZ. Remap L2
715+
* and R2 and ignore other analog 'button axes' as there is
716+
* no good way for reporting them.
717+
*/
718+
switch (usage->usage_index) {
719+
case 8: /* L2 */
720+
usage->hid = HID_GD_Z;
721+
break;
722+
case 9: /* R2 */
723+
usage->hid = HID_GD_RZ;
724+
break;
725+
default:
726+
return -1;
727+
}
728+
729+
hid_map_usage_clear(hi, usage, bit, max, EV_ABS, usage->hid & 0xf);
730+
return 1;
731+
} else if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK) {
732+
unsigned int abs = usage->hid & HID_USAGE;
733+
734+
if (abs >= ARRAY_SIZE(sixaxis_absmap))
735+
return -1;
736+
737+
abs = sixaxis_absmap[abs];
738+
739+
hid_map_usage_clear(hi, usage, bit, max, EV_ABS, abs);
740+
return 1;
741+
}
742+
743+
return -1;
744+
}
745+
760746
static int ds4_mapping(struct hid_device *hdev, struct hid_input *hi,
761747
struct hid_field *field, struct hid_usage *usage,
762748
unsigned long **bit, int *max)
@@ -812,9 +798,6 @@ static u8 *sony_report_fixup(struct hid_device *hdev, u8 *rdesc,
812798
rdesc[55] = 0x06;
813799
}
814800

815-
if (sc->quirks & SIXAXIS_CONTROLLER)
816-
return sixaxis_fixup(hdev, rdesc, rsize);
817-
818801
if (sc->quirks & MOTION_CONTROLLER)
819802
return motion_fixup(hdev, rdesc, rsize);
820803

@@ -1196,10 +1179,13 @@ static int sony_mapping(struct hid_device *hdev, struct hid_input *hi,
11961179
if (sc->quirks & PS3REMOTE)
11971180
return ps3remote_mapping(hdev, hi, field, usage, bit, max);
11981181

1182+
if (sc->quirks & SIXAXIS_CONTROLLER)
1183+
return sixaxis_mapping(hdev, hi, field, usage, bit, max);
11991184

12001185
if (sc->quirks & DUALSHOCK4_CONTROLLER)
12011186
return ds4_mapping(hdev, hi, field, usage, bit, max);
12021187

1188+
12031189
/* Let hid-core decide for the others */
12041190
return 0;
12051191
}
@@ -2613,13 +2599,13 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
26132599
else if (sc->quirks & SIXAXIS_CONTROLLER)
26142600
connect_mask |= HID_CONNECT_HIDDEV_FORCE;
26152601

2616-
/* Patch the hw version on DS4 compatible devices, so applications can
2602+
/* Patch the hw version on DS3/4 compatible devices, so applications can
26172603
* distinguish between the default HID mappings and the mappings defined
26182604
* by the Linux game controller spec. This is important for the SDL2
26192605
* library, which has a game controller database, which uses device ids
26202606
* in combination with version as a key.
26212607
*/
2622-
if (sc->quirks & DUALSHOCK4_CONTROLLER)
2608+
if (sc->quirks & (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER))
26232609
hdev->version |= 0x8000;
26242610

26252611
ret = hid_hw_start(hdev, connect_mask);

0 commit comments

Comments
 (0)