diff options
Diffstat (limited to 'drivers/hid/hid-sony.c')
-rw-r--r-- | drivers/hid/hid-sony.c | 132 |
1 files changed, 86 insertions, 46 deletions
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 2259eaa8b988..c372368e438c 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c | |||
@@ -56,32 +56,81 @@ | |||
56 | 56 | ||
57 | #define MAX_LEDS 4 | 57 | #define MAX_LEDS 4 |
58 | 58 | ||
59 | static const u8 sixaxis_rdesc_fixup[] = { | 59 | static __u8 sixaxis_rdesc[] = { |
60 | 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C, | 60 | 0x05, 0x01, /* Usage Page (Desktop), */ |
61 | 0x81, 0x01, 0x75, 0x10, 0x95, 0x04, 0x26, 0xFF, | 61 | 0x09, 0x04, /* Usage (Joystik), */ |
62 | 0x03, 0x46, 0xFF, 0x03, 0x09, 0x01, 0x81, 0x02 | 62 | 0xA1, 0x01, /* Collection (Application), */ |
63 | }; | 63 | 0xA1, 0x02, /* Collection (Logical), */ |
64 | 64 | 0x85, 0x01, /* Report ID (1), */ | |
65 | static const u8 sixaxis_rdesc_fixup2[] = { | 65 | 0x75, 0x08, /* Report Size (8), */ |
66 | 0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0xa1, 0x02, | 66 | 0x95, 0x01, /* Report Count (1), */ |
67 | 0x85, 0x01, 0x75, 0x08, 0x95, 0x01, 0x15, 0x00, | 67 | 0x15, 0x00, /* Logical Minimum (0), */ |
68 | 0x26, 0xff, 0x00, 0x81, 0x03, 0x75, 0x01, 0x95, | 68 | 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ |
69 | 0x13, 0x15, 0x00, 0x25, 0x01, 0x35, 0x00, 0x45, | 69 | 0x81, 0x03, /* Input (Constant, Variable), */ |
70 | 0x01, 0x05, 0x09, 0x19, 0x01, 0x29, 0x13, 0x81, | 70 | 0x75, 0x01, /* Report Size (1), */ |
71 | 0x02, 0x75, 0x01, 0x95, 0x0d, 0x06, 0x00, 0xff, | 71 | 0x95, 0x13, /* Report Count (19), */ |
72 | 0x81, 0x03, 0x15, 0x00, 0x26, 0xff, 0x00, 0x05, | 72 | 0x15, 0x00, /* Logical Minimum (0), */ |
73 | 0x01, 0x09, 0x01, 0xa1, 0x00, 0x75, 0x08, 0x95, | 73 | 0x25, 0x01, /* Logical Maximum (1), */ |
74 | 0x04, 0x35, 0x00, 0x46, 0xff, 0x00, 0x09, 0x30, | 74 | 0x35, 0x00, /* Physical Minimum (0), */ |
75 | 0x09, 0x31, 0x09, 0x32, 0x09, 0x35, 0x81, 0x02, | 75 | 0x45, 0x01, /* Physical Maximum (1), */ |
76 | 0xc0, 0x05, 0x01, 0x95, 0x13, 0x09, 0x01, 0x81, | 76 | 0x05, 0x09, /* Usage Page (Button), */ |
77 | 0x02, 0x95, 0x0c, 0x81, 0x01, 0x75, 0x10, 0x95, | 77 | 0x19, 0x01, /* Usage Minimum (01h), */ |
78 | 0x04, 0x26, 0xff, 0x03, 0x46, 0xff, 0x03, 0x09, | 78 | 0x29, 0x13, /* Usage Maximum (13h), */ |
79 | 0x01, 0x81, 0x02, 0xc0, 0xa1, 0x02, 0x85, 0x02, | 79 | 0x81, 0x02, /* Input (Variable), */ |
80 | 0x75, 0x08, 0x95, 0x30, 0x09, 0x01, 0xb1, 0x02, | 80 | 0x75, 0x01, /* Report Size (1), */ |
81 | 0xc0, 0xa1, 0x02, 0x85, 0xee, 0x75, 0x08, 0x95, | 81 | 0x95, 0x0D, /* Report Count (13), */ |
82 | 0x30, 0x09, 0x01, 0xb1, 0x02, 0xc0, 0xa1, 0x02, | 82 | 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ |
83 | 0x85, 0xef, 0x75, 0x08, 0x95, 0x30, 0x09, 0x01, | 83 | 0x81, 0x03, /* Input (Constant, Variable), */ |
84 | 0xb1, 0x02, 0xc0, 0xc0, | 84 | 0x15, 0x00, /* Logical Minimum (0), */ |
85 | 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ | ||
86 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
87 | 0x09, 0x01, /* Usage (Pointer), */ | ||
88 | 0xA1, 0x00, /* Collection (Physical), */ | ||
89 | 0x75, 0x08, /* Report Size (8), */ | ||
90 | 0x95, 0x04, /* Report Count (4), */ | ||
91 | 0x35, 0x00, /* Physical Minimum (0), */ | ||
92 | 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ | ||
93 | 0x09, 0x30, /* Usage (X), */ | ||
94 | 0x09, 0x31, /* Usage (Y), */ | ||
95 | 0x09, 0x32, /* Usage (Z), */ | ||
96 | 0x09, 0x35, /* Usage (Rz), */ | ||
97 | 0x81, 0x02, /* Input (Variable), */ | ||
98 | 0xC0, /* End Collection, */ | ||
99 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
100 | 0x95, 0x13, /* Report Count (19), */ | ||
101 | 0x09, 0x01, /* Usage (Pointer), */ | ||
102 | 0x81, 0x02, /* Input (Variable), */ | ||
103 | 0x95, 0x0C, /* Report Count (12), */ | ||
104 | 0x81, 0x01, /* Input (Constant), */ | ||
105 | 0x75, 0x10, /* Report Size (16), */ | ||
106 | 0x95, 0x04, /* Report Count (4), */ | ||
107 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
108 | 0x46, 0xFF, 0x03, /* Physical Maximum (1023), */ | ||
109 | 0x09, 0x01, /* Usage (Pointer), */ | ||
110 | 0x81, 0x02, /* Input (Variable), */ | ||
111 | 0xC0, /* End Collection, */ | ||
112 | 0xA1, 0x02, /* Collection (Logical), */ | ||
113 | 0x85, 0x02, /* Report ID (2), */ | ||
114 | 0x75, 0x08, /* Report Size (8), */ | ||
115 | 0x95, 0x30, /* Report Count (48), */ | ||
116 | 0x09, 0x01, /* Usage (Pointer), */ | ||
117 | 0xB1, 0x02, /* Feature (Variable), */ | ||
118 | 0xC0, /* End Collection, */ | ||
119 | 0xA1, 0x02, /* Collection (Logical), */ | ||
120 | 0x85, 0xEE, /* Report ID (238), */ | ||
121 | 0x75, 0x08, /* Report Size (8), */ | ||
122 | 0x95, 0x30, /* Report Count (48), */ | ||
123 | 0x09, 0x01, /* Usage (Pointer), */ | ||
124 | 0xB1, 0x02, /* Feature (Variable), */ | ||
125 | 0xC0, /* End Collection, */ | ||
126 | 0xA1, 0x02, /* Collection (Logical), */ | ||
127 | 0x85, 0xEF, /* Report ID (239), */ | ||
128 | 0x75, 0x08, /* Report Size (8), */ | ||
129 | 0x95, 0x30, /* Report Count (48), */ | ||
130 | 0x09, 0x01, /* Usage (Pointer), */ | ||
131 | 0xB1, 0x02, /* Feature (Variable), */ | ||
132 | 0xC0, /* End Collection, */ | ||
133 | 0xC0 /* End Collection */ | ||
85 | }; | 134 | }; |
86 | 135 | ||
87 | /* | 136 | /* |
@@ -778,6 +827,13 @@ struct sony_sc { | |||
778 | __u8 led_count; | 827 | __u8 led_count; |
779 | }; | 828 | }; |
780 | 829 | ||
830 | static __u8 *sixaxis_fixup(struct hid_device *hdev, __u8 *rdesc, | ||
831 | unsigned int *rsize) | ||
832 | { | ||
833 | *rsize = sizeof(sixaxis_rdesc); | ||
834 | return sixaxis_rdesc; | ||
835 | } | ||
836 | |||
781 | static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, | 837 | static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, |
782 | unsigned int *rsize) | 838 | unsigned int *rsize) |
783 | { | 839 | { |
@@ -819,8 +875,6 @@ static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
819 | return 1; | 875 | return 1; |
820 | } | 876 | } |
821 | 877 | ||
822 | |||
823 | /* Sony Vaio VGX has wrongly mouse pointer declared as constant */ | ||
824 | static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 878 | static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
825 | unsigned int *rsize) | 879 | unsigned int *rsize) |
826 | { | 880 | { |
@@ -857,20 +911,8 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
857 | *rsize = sizeof(dualshock4_bt_rdesc); | 911 | *rsize = sizeof(dualshock4_bt_rdesc); |
858 | } | 912 | } |
859 | 913 | ||
860 | /* The HID descriptor exposed over BT has a trailing zero byte */ | 914 | if (sc->quirks & SIXAXIS_CONTROLLER) |
861 | if ((((sc->quirks & SIXAXIS_CONTROLLER_USB) && *rsize == 148) || | 915 | return sixaxis_fixup(hdev, rdesc, rsize); |
862 | ((sc->quirks & SIXAXIS_CONTROLLER_BT) && *rsize == 149)) && | ||
863 | rdesc[83] == 0x75) { | ||
864 | hid_info(hdev, "Fixing up Sony Sixaxis report descriptor\n"); | ||
865 | memcpy((void *)&rdesc[83], (void *)&sixaxis_rdesc_fixup, | ||
866 | sizeof(sixaxis_rdesc_fixup)); | ||
867 | } else if (sc->quirks & SIXAXIS_CONTROLLER_USB && | ||
868 | *rsize > sizeof(sixaxis_rdesc_fixup2)) { | ||
869 | hid_info(hdev, "Sony Sixaxis clone detected. Using original report descriptor (size: %d clone; %d new)\n", | ||
870 | *rsize, (int)sizeof(sixaxis_rdesc_fixup2)); | ||
871 | *rsize = sizeof(sixaxis_rdesc_fixup2); | ||
872 | memcpy(rdesc, &sixaxis_rdesc_fixup2, *rsize); | ||
873 | } | ||
874 | 916 | ||
875 | if (sc->quirks & PS3REMOTE) | 917 | if (sc->quirks & PS3REMOTE) |
876 | return ps3remote_fixup(hdev, rdesc, rsize); | 918 | return ps3remote_fixup(hdev, rdesc, rsize); |
@@ -1307,7 +1349,7 @@ static int sony_leds_init(struct sony_sc *sc) | |||
1307 | static const char * const ds4_name_str[] = { "red", "green", "blue", | 1349 | static const char * const ds4_name_str[] = { "red", "green", "blue", |
1308 | "global" }; | 1350 | "global" }; |
1309 | __u8 initial_values[MAX_LEDS] = { 0 }; | 1351 | __u8 initial_values[MAX_LEDS] = { 0 }; |
1310 | __u8 max_brightness[MAX_LEDS] = { 1 }; | 1352 | __u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 }; |
1311 | __u8 use_hw_blink[MAX_LEDS] = { 0 }; | 1353 | __u8 use_hw_blink[MAX_LEDS] = { 0 }; |
1312 | 1354 | ||
1313 | BUG_ON(!(sc->quirks & SONY_LED_SUPPORT)); | 1355 | BUG_ON(!(sc->quirks & SONY_LED_SUPPORT)); |
@@ -1830,9 +1872,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
1830 | 1872 | ||
1831 | if (sc->quirks & VAIO_RDESC_CONSTANT) | 1873 | if (sc->quirks & VAIO_RDESC_CONSTANT) |
1832 | connect_mask |= HID_CONNECT_HIDDEV_FORCE; | 1874 | connect_mask |= HID_CONNECT_HIDDEV_FORCE; |
1833 | else if (sc->quirks & SIXAXIS_CONTROLLER_USB) | 1875 | else if (sc->quirks & SIXAXIS_CONTROLLER) |
1834 | connect_mask |= HID_CONNECT_HIDDEV_FORCE; | ||
1835 | else if (sc->quirks & SIXAXIS_CONTROLLER_BT) | ||
1836 | connect_mask |= HID_CONNECT_HIDDEV_FORCE; | 1876 | connect_mask |= HID_CONNECT_HIDDEV_FORCE; |
1837 | 1877 | ||
1838 | ret = hid_hw_start(hdev, connect_mask); | 1878 | ret = hid_hw_start(hdev, connect_mask); |