diff options
author | 3gg <3gg@shellblade.net> | 2025-08-30 16:53:58 -0700 |
---|---|---|
committer | 3gg <3gg@shellblade.net> | 2025-08-30 16:53:58 -0700 |
commit | 6aaedb813fa11ba0679c3051bc2eb28646b9506c (patch) | |
tree | 34acbfc9840e02cb4753e6306ea7ce978bf8b58e /src/contrib/SDL-3.2.20/test/testevdev.c | |
parent | 8f228ade99dd3d4c8da9b78ade1815c9adf85c8f (diff) |
Update to SDL3
Diffstat (limited to 'src/contrib/SDL-3.2.20/test/testevdev.c')
-rw-r--r-- | src/contrib/SDL-3.2.20/test/testevdev.c | 2249 |
1 files changed, 2249 insertions, 0 deletions
diff --git a/src/contrib/SDL-3.2.20/test/testevdev.c b/src/contrib/SDL-3.2.20/test/testevdev.c new file mode 100644 index 0000000..cdb16a9 --- /dev/null +++ b/src/contrib/SDL-3.2.20/test/testevdev.c | |||
@@ -0,0 +1,2249 @@ | |||
1 | /* | ||
2 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
3 | Copyright (C) 2020-2022 Collabora Ltd. | ||
4 | |||
5 | This software is provided 'as-is', without any express or implied | ||
6 | warranty. In no event will the authors be held liable for any damages | ||
7 | arising from the use of this software. | ||
8 | |||
9 | Permission is granted to anyone to use this software for any purpose, | ||
10 | including commercial applications, and to alter it and redistribute it | ||
11 | freely. | ||
12 | */ | ||
13 | |||
14 | /* Hack #1: avoid inclusion of SDL_main.h by SDL_internal.h */ | ||
15 | #define SDL_main_h_ | ||
16 | |||
17 | /* Hack #2: avoid dynapi renaming (must be done before #include <SDL3/SDL.h>) */ | ||
18 | #include "../src/dynapi/SDL_dynapi.h" | ||
19 | #ifdef SDL_DYNAMIC_API | ||
20 | #undef SDL_DYNAMIC_API | ||
21 | #endif | ||
22 | #define SDL_DYNAMIC_API 0 | ||
23 | |||
24 | #ifdef HAVE_BUILD_CONFIG | ||
25 | #include "../src/SDL_internal.h" | ||
26 | #endif | ||
27 | |||
28 | /* Hack #3: undo Hack #1 */ | ||
29 | #ifdef SDL_main_h_ | ||
30 | #undef SDL_main_h_ | ||
31 | #endif | ||
32 | #ifdef SDL_MAIN_NOIMPL | ||
33 | #undef SDL_MAIN_NOIMPL | ||
34 | #endif | ||
35 | |||
36 | #include <SDL3/SDL.h> | ||
37 | #include <SDL3/SDL_main.h> | ||
38 | #include <SDL3/SDL_test.h> | ||
39 | |||
40 | #include <stdio.h> | ||
41 | #include <string.h> | ||
42 | |||
43 | static int run_test(void); | ||
44 | |||
45 | /* FIXME: Need CMake tests for this */ | ||
46 | #if (defined(HAVE_LIBUDEV_H) || defined(SDL_JOYSTICK_LINUX)) && defined(HAVE_LINUX_INPUT_H) | ||
47 | |||
48 | #include <stdint.h> | ||
49 | |||
50 | #include "../src/core/linux/SDL_evdev_capabilities.h" | ||
51 | #include "../src/core/linux/SDL_evdev_capabilities.c" | ||
52 | |||
53 | static const struct | ||
54 | { | ||
55 | int code; | ||
56 | const char *name; | ||
57 | } device_classes[] = { | ||
58 | #define CLS(x) \ | ||
59 | { \ | ||
60 | SDL_UDEV_DEVICE_##x, #x \ | ||
61 | } | ||
62 | CLS(MOUSE), | ||
63 | CLS(KEYBOARD), | ||
64 | CLS(HAS_KEYS), | ||
65 | CLS(JOYSTICK), | ||
66 | CLS(SOUND), | ||
67 | CLS(TOUCHSCREEN), | ||
68 | CLS(ACCELEROMETER), | ||
69 | CLS(TOUCHPAD), | ||
70 | #undef CLS | ||
71 | { 0, NULL } | ||
72 | }; | ||
73 | |||
74 | typedef struct | ||
75 | { | ||
76 | const char *name; | ||
77 | const char *eviocgname; | ||
78 | const char *usb_vendor_name; | ||
79 | const char *usb_product_name; | ||
80 | uint16_t bus_type; | ||
81 | uint16_t vendor_id; | ||
82 | uint16_t product_id; | ||
83 | uint16_t version; | ||
84 | uint16_t usb_device_version; | ||
85 | uint8_t ev[(EV_MAX + 1) / 8]; | ||
86 | uint8_t keys[(KEY_MAX + 1) / 8]; | ||
87 | uint8_t abs[(ABS_MAX + 1) / 8]; | ||
88 | uint8_t rel[(REL_MAX + 1) / 8]; | ||
89 | uint8_t ff[(FF_MAX + 1) / 8]; | ||
90 | uint8_t props[(INPUT_PROP_MAX + 1) / 8]; | ||
91 | int expected; | ||
92 | const char *todo; | ||
93 | size_t hid_report_descriptor_length; | ||
94 | const unsigned char *hid_report_descriptor; | ||
95 | } GuessTest; | ||
96 | |||
97 | /* | ||
98 | * Test-cases for guessing a device type from its capabilities. | ||
99 | * | ||
100 | * The bytes in ev, etc. are in little-endian byte order | ||
101 | * Trailing zeroes can be omitted. | ||
102 | * | ||
103 | * The evemu-describe tool is a convenient way to add a test-case for | ||
104 | * a physically available device. To contribute new test-cases, see: | ||
105 | * https://github.com/libsdl-org/SDL/issues/7801#issuecomment-1589114910 | ||
106 | */ | ||
107 | #define ZEROx4 0, 0, 0, 0 | ||
108 | #define ZEROx8 ZEROx4, ZEROx4 | ||
109 | #define FFx4 0xff, 0xff, 0xff, 0xff | ||
110 | #define FFx8 FFx4, FFx4 | ||
111 | |||
112 | static unsigned char xbox_one_elite_2_hid_report_descriptor[] = | ||
113 | { | ||
114 | /* Generic Desktop / Game Pad, Generic Desktop / Keyboard */ | ||
115 | 0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x01, | ||
116 | 0x09, 0x01, 0xa1, 0x00, 0x09, 0x30, 0x09, 0x31, | ||
117 | 0x15, 0x00, 0x27, 0xff, 0xff, 0x00, 0x00, 0x95, | ||
118 | 0x02, 0x75, 0x10, 0x81, 0x02, 0xc0, 0x09, 0x01, | ||
119 | 0xa1, 0x00, 0x09, 0x32, 0x09, 0x35, 0x15, 0x00, | ||
120 | 0x27, 0xff, 0xff, 0x00, 0x00, 0x95, 0x02, 0x75, | ||
121 | 0x10, 0x81, 0x02, 0xc0, 0x05, 0x02, 0x09, 0xc5, | ||
122 | 0x15, 0x00, 0x26, 0xff, 0x03, 0x95, 0x01, 0x75, | ||
123 | 0x0a, 0x81, 0x02, 0x15, 0x00, 0x25, 0x00, 0x75, | ||
124 | 0x06, 0x95, 0x01, 0x81, 0x03, 0x05, 0x02, 0x09, | ||
125 | 0xc4, 0x15, 0x00, 0x26, 0xff, 0x03, 0x95, 0x01, | ||
126 | 0x75, 0x0a, 0x81, 0x02, 0x15, 0x00, 0x25, 0x00, | ||
127 | 0x75, 0x06, 0x95, 0x01, 0x81, 0x03, 0x05, 0x01, | ||
128 | 0x09, 0x39, 0x15, 0x01, 0x25, 0x08, 0x35, 0x00, | ||
129 | 0x46, 0x3b, 0x01, 0x66, 0x14, 0x00, 0x75, 0x04, | ||
130 | 0x95, 0x01, 0x81, 0x42, 0x75, 0x04, 0x95, 0x01, | ||
131 | 0x15, 0x00, 0x25, 0x00, 0x35, 0x00, 0x45, 0x00, | ||
132 | 0x65, 0x00, 0x81, 0x03, 0x05, 0x09, 0x19, 0x01, | ||
133 | 0x29, 0x0f, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, | ||
134 | 0x95, 0x0f, 0x81, 0x02, 0x15, 0x00, 0x25, 0x00, | ||
135 | 0x75, 0x01, 0x95, 0x01, 0x81, 0x03, 0x05, 0x0c, | ||
136 | 0x0a, 0xb2, 0x00, 0x15, 0x00, 0x25, 0x01, 0x95, | ||
137 | 0x01, 0x75, 0x01, 0x81, 0x02, 0x15, 0x00, 0x25, | ||
138 | 0x00, 0x75, 0x07, 0x95, 0x01, 0x81, 0x03, 0x05, | ||
139 | 0x0c, 0x09, 0x01, 0xa1, 0x01, 0x0a, 0x85, 0x00, | ||
140 | 0x15, 0x00, 0x26, 0xff, 0x00, 0x95, 0x01, 0x75, | ||
141 | 0x08, 0x81, 0x02, 0x0a, 0x99, 0x00, 0x15, 0x00, | ||
142 | 0x26, 0xff, 0x00, 0x95, 0x01, 0x75, 0x04, 0x81, | ||
143 | 0x02, 0x15, 0x00, 0x25, 0x00, 0x95, 0x01, 0x75, | ||
144 | 0x04, 0x81, 0x03, 0x0a, 0x81, 0x00, 0x15, 0x00, | ||
145 | 0x26, 0xff, 0x00, 0x95, 0x01, 0x75, 0x04, 0x81, | ||
146 | 0x02, 0x15, 0x00, 0x25, 0x00, 0x95, 0x01, 0x75, | ||
147 | 0x04, 0x81, 0x03, 0xc0, 0x05, 0x0f, 0x09, 0x21, | ||
148 | 0x85, 0x03, 0xa1, 0x02, 0x09, 0x97, 0x15, 0x00, | ||
149 | 0x25, 0x01, 0x75, 0x04, 0x95, 0x01, 0x91, 0x02, | ||
150 | 0x15, 0x00, 0x25, 0x00, 0x75, 0x04, 0x95, 0x01, | ||
151 | 0x91, 0x03, 0x09, 0x70, 0x15, 0x00, 0x25, 0x64, | ||
152 | 0x75, 0x08, 0x95, 0x04, 0x91, 0x02, 0x09, 0x50, | ||
153 | 0x66, 0x01, 0x10, 0x55, 0x0e, 0x15, 0x00, 0x26, | ||
154 | 0xff, 0x00, 0x75, 0x08, 0x95, 0x01, 0x91, 0x02, | ||
155 | 0x09, 0xa7, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, | ||
156 | 0x08, 0x95, 0x01, 0x91, 0x02, 0x65, 0x00, 0x55, | ||
157 | 0x00, 0x09, 0x7c, 0x15, 0x00, 0x26, 0xff, 0x00, | ||
158 | 0x75, 0x08, 0x95, 0x01, 0x91, 0x02, 0xc0, 0x05, | ||
159 | 0x0c, 0x09, 0x01, 0x85, 0x0c, 0xa1, 0x01, 0x0a, | ||
160 | 0x9e, 0x00, 0x15, 0x00, 0x26, 0xff, 0x00, 0x95, | ||
161 | 0x01, 0x75, 0x08, 0x81, 0x02, 0x0a, 0xa1, 0x00, | ||
162 | 0x15, 0x00, 0x26, 0xff, 0x00, 0x95, 0x01, 0x75, | ||
163 | 0x08, 0x81, 0x02, 0x0a, 0xa2, 0x00, 0x15, 0x00, | ||
164 | 0x26, 0xff, 0x00, 0x95, 0x01, 0x75, 0x08, 0x81, | ||
165 | 0x02, 0x0a, 0xa3, 0x00, 0x15, 0x00, 0x26, 0xff, | ||
166 | 0x00, 0x95, 0x01, 0x75, 0x08, 0x81, 0x02, 0xc0, | ||
167 | 0xc0, 0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x85, | ||
168 | 0x05, 0x05, 0x07, 0x19, 0xe0, 0x29, 0xe7, 0x15, | ||
169 | 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, | ||
170 | 0x02, 0x95, 0x01, 0x75, 0x08, 0x81, 0x03, 0x95, | ||
171 | 0x06, 0x75, 0x08, 0x15, 0x00, 0x25, 0x65, 0x05, | ||
172 | 0x07, 0x19, 0x00, 0x29, 0x65, 0x81, 0x00, 0xc0, | ||
173 | }; | ||
174 | SDL_COMPILE_TIME_ASSERT (xbox_one_elite_2, sizeof (xbox_one_elite_2_hid_report_descriptor) == 0720); | ||
175 | |||
176 | static unsigned char ps3_hid_report_descriptor[] = | ||
177 | { | ||
178 | /* Generic Desktop / Joystick */ | ||
179 | 0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0xa1, 0x02, | ||
180 | 0x85, 0x01, 0x75, 0x08, 0x95, 0x01, 0x15, 0x00, | ||
181 | 0x26, 0xff, 0x00, 0x81, 0x03, 0x75, 0x01, 0x95, | ||
182 | 0x13, 0x15, 0x00, 0x25, 0x01, 0x35, 0x00, 0x45, | ||
183 | 0x01, 0x05, 0x09, 0x19, 0x01, 0x29, 0x13, 0x81, | ||
184 | 0x02, 0x75, 0x01, 0x95, 0x0d, 0x06, 0x00, 0xff, | ||
185 | 0x81, 0x03, 0x15, 0x00, 0x26, 0xff, 0x00, 0x05, | ||
186 | 0x01, 0x09, 0x01, 0xa1, 0x00, 0x75, 0x08, 0x95, | ||
187 | 0x04, 0x35, 0x00, 0x46, 0xff, 0x00, 0x09, 0x30, | ||
188 | 0x09, 0x31, 0x09, 0x32, 0x09, 0x35, 0x81, 0x02, | ||
189 | 0xc0, 0x05, 0x01, 0x75, 0x08, 0x95, 0x27, 0x09, | ||
190 | 0x01, 0x81, 0x02, 0x75, 0x08, 0x95, 0x30, 0x09, | ||
191 | 0x01, 0x91, 0x02, 0x75, 0x08, 0x95, 0x30, 0x09, | ||
192 | 0x01, 0xb1, 0x02, 0xc0, 0xa1, 0x02, 0x85, 0x02, | ||
193 | 0x75, 0x08, 0x95, 0x30, 0x09, 0x01, 0xb1, 0x02, | ||
194 | 0xc0, 0xa1, 0x02, 0x85, 0xee, 0x75, 0x08, 0x95, | ||
195 | 0x30, 0x09, 0x01, 0xb1, 0x02, 0xc0, 0xa1, 0x02, | ||
196 | 0x85, 0xef, 0x75, 0x08, 0x95, 0x30, 0x09, 0x01, | ||
197 | 0xb1, 0x02, 0xc0, 0xc0, 0x00, | ||
198 | }; | ||
199 | SDL_COMPILE_TIME_ASSERT (ps3, sizeof (ps3_hid_report_descriptor) == 149); | ||
200 | |||
201 | /* Same for Steam Deck LCD (jupiter) and OLED (galileo) */ | ||
202 | static unsigned char steam_deck_mouse_hid_report_descriptor[] = | ||
203 | { | ||
204 | 0x05, 0x01, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x01, | ||
205 | 0xa1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x02, | ||
206 | 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x02, | ||
207 | 0x81, 0x02, 0x75, 0x06, 0x95, 0x01, 0x81, 0x01, | ||
208 | 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x15, 0x81, | ||
209 | 0x25, 0x7f, 0x75, 0x08, 0x95, 0x02, 0x81, 0x06, | ||
210 | 0x95, 0x01, 0x09, 0x38, 0x81, 0x06, 0x05, 0x0c, | ||
211 | 0x0a, 0x38, 0x02, 0x95, 0x01, 0x81, 0x06, 0xc0, | ||
212 | 0xc0, | ||
213 | }; | ||
214 | SDL_COMPILE_TIME_ASSERT (steam_deck_mouse, | ||
215 | sizeof (steam_deck_mouse_hid_report_descriptor) == 65); | ||
216 | |||
217 | /* Same for Steam Deck LCD (jupiter) and OLED (galileo) */ | ||
218 | static unsigned char steam_deck_kb_hid_report_descriptor[] = | ||
219 | { | ||
220 | 0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07, | ||
221 | 0x19, 0xe0, 0x29, 0xe7, 0x15, 0x00, 0x25, 0x01, | ||
222 | 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x81, 0x01, | ||
223 | 0x19, 0x00, 0x29, 0x65, 0x15, 0x00, 0x25, 0x65, | ||
224 | 0x75, 0x08, 0x95, 0x06, 0x81, 0x00, 0xc0, | ||
225 | }; | ||
226 | SDL_COMPILE_TIME_ASSERT (steam_deck_oled_kb, | ||
227 | sizeof (steam_deck_kb_hid_report_descriptor) == 39); | ||
228 | |||
229 | static unsigned char steam_deck_lcd_js_hid_report_descriptor[] = | ||
230 | { | ||
231 | 0x06, 0xff, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x15, | ||
232 | 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x40, | ||
233 | 0x09, 0x01, 0x81, 0x02, 0x09, 0x01, 0xb1, 0x02, | ||
234 | 0xc0, | ||
235 | }; | ||
236 | SDL_COMPILE_TIME_ASSERT (steam_deck_lcd_js, | ||
237 | sizeof (steam_deck_lcd_js_hid_report_descriptor) == 25); | ||
238 | |||
239 | static unsigned char steam_deck_oled_js_hid_report_descriptor[] = | ||
240 | { | ||
241 | 0x06, 0xff, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x09, | ||
242 | 0x02, 0x09, 0x03, 0x15, 0x00, 0x26, 0xff, 0x00, | ||
243 | 0x75, 0x08, 0x95, 0x40, 0x81, 0x02, 0x09, 0x06, | ||
244 | 0x09, 0x07, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, | ||
245 | 0x08, 0x95, 0x40, 0xb1, 0x02, 0xc0, | ||
246 | }; | ||
247 | SDL_COMPILE_TIME_ASSERT (steam_deck_oled_js, | ||
248 | sizeof (steam_deck_oled_js_hid_report_descriptor) == 38); | ||
249 | |||
250 | static unsigned char vrs_pedals_hid_report_descriptor[] = | ||
251 | { | ||
252 | /* Generic Desktop / Joystick */ | ||
253 | 0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0x05, 0x01, | ||
254 | 0xa1, 0x02, 0x85, 0x01, 0x09, 0x30, 0x09, 0x31, | ||
255 | 0x09, 0x32, 0x15, 0x00, 0x27, 0xff, 0xff, 0x00, | ||
256 | 0x00, 0x35, 0x00, 0x47, 0xff, 0xff, 0x00, 0x00, | ||
257 | 0x75, 0x10, 0x95, 0x03, 0x81, 0x02, 0x06, 0x00, | ||
258 | 0xff, 0x09, 0x01, 0x95, 0x39, 0x75, 0x08, 0x26, | ||
259 | 0xff, 0x00, 0x15, 0x00, 0x81, 0x02, 0xc0, 0x06, | ||
260 | 0x00, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x85, 0x64, | ||
261 | 0x95, 0x3f, 0x75, 0x08, 0x26, 0xff, 0x00, 0x15, | ||
262 | 0x00, 0x09, 0x01, 0x91, 0x02, 0x85, 0x65, 0x95, | ||
263 | 0x3f, 0x75, 0x08, 0x26, 0xff, 0x00, 0x15, 0x00, | ||
264 | 0x09, 0x01, 0x81, 0x02, 0xc0, 0xc0, | ||
265 | }; | ||
266 | SDL_COMPILE_TIME_ASSERT (vrs_pedals, sizeof (vrs_pedals_hid_report_descriptor) == 0136); | ||
267 | |||
268 | static unsigned char thinkpad_usb_keyboard_hid_report_descriptor[] = | ||
269 | { | ||
270 | /* Generic Desktop / Keyboard */ | ||
271 | 0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07, | ||
272 | 0x19, 0xe0, 0x29, 0xe7, 0x15, 0x00, 0x25, 0x01, | ||
273 | 0x95, 0x08, 0x75, 0x01, 0x81, 0x02, 0x95, 0x08, | ||
274 | 0x75, 0x01, 0x81, 0x01, 0x05, 0x08, 0x19, 0x01, | ||
275 | 0x29, 0x03, 0x95, 0x03, 0x75, 0x01, 0x91, 0x02, | ||
276 | 0x95, 0x01, 0x75, 0x05, 0x91, 0x01, 0x05, 0x07, | ||
277 | 0x19, 0x00, 0x2a, 0xff, 0x00, 0x15, 0x00, 0x26, | ||
278 | 0xff, 0x00, 0x95, 0x06, 0x75, 0x08, 0x81, 0x00, | ||
279 | 0xc0, | ||
280 | }; | ||
281 | SDL_COMPILE_TIME_ASSERT (thinkpad_usb_keyboard, sizeof (thinkpad_usb_keyboard_hid_report_descriptor) == 65); | ||
282 | |||
283 | static unsigned char thinkpad_usb_trackpoint_hid_report_descriptor[] = | ||
284 | { | ||
285 | /* Generic Desktop / Mouse, Generic Desktop / System Control, | ||
286 | * Consumer Devices / Consumer Control */ | ||
287 | 0x05, 0x01, 0x09, 0x02, 0xa1, 0x01, 0x85, 0x01, | ||
288 | 0x09, 0x01, 0xa1, 0x00, 0x05, 0x09, 0x19, 0x01, | ||
289 | 0x29, 0x03, 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, | ||
290 | 0x75, 0x01, 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, | ||
291 | 0x81, 0x01, 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, | ||
292 | 0x15, 0x81, 0x25, 0x7f, 0x95, 0x02, 0x75, 0x08, | ||
293 | 0x81, 0x06, 0xc0, 0xc0, 0x05, 0x01, 0x09, 0x80, | ||
294 | 0xa1, 0x01, 0x85, 0x02, 0x05, 0x01, 0x15, 0x00, | ||
295 | 0x25, 0x01, 0x95, 0x08, 0x75, 0x01, 0x19, 0x81, | ||
296 | 0x29, 0x88, 0x81, 0x02, 0xc0, 0x05, 0x0c, 0x09, | ||
297 | 0x01, 0xa1, 0x01, 0x85, 0x03, 0x95, 0x08, 0x75, | ||
298 | 0x01, 0x15, 0x00, 0x25, 0x01, 0x09, 0xe9, 0x09, | ||
299 | 0xea, 0x09, 0xe2, 0x09, 0xb7, 0x09, 0xcd, 0x09, | ||
300 | 0xb5, 0x09, 0xb6, 0x0a, 0x94, 0x01, 0x81, 0x02, | ||
301 | 0x09, 0x03, 0xa1, 0x02, 0x05, 0x09, 0x19, 0x10, | ||
302 | 0x29, 0x17, 0x81, 0x02, 0x05, 0x09, 0x19, 0x18, | ||
303 | 0x29, 0x1f, 0x81, 0x02, 0xc0, 0x05, 0x08, 0x95, | ||
304 | 0x02, 0x09, 0x09, 0x09, 0x21, 0x91, 0x02, 0x95, | ||
305 | 0x01, 0x75, 0x06, 0x91, 0x03, 0xc0, 0x06, 0x01, | ||
306 | 0xff, 0x09, 0x01, 0xa1, 0x01, 0x85, 0x04, 0x95, | ||
307 | 0x01, 0x75, 0x08, 0x15, 0x00, 0x26, 0xff, 0x00, | ||
308 | 0x09, 0x20, 0xb1, 0x03, 0x09, 0x21, 0xb1, 0x03, | ||
309 | 0x09, 0x22, 0xb1, 0x03, 0x09, 0x23, 0xb1, 0x03, | ||
310 | 0xc0, | ||
311 | }; | ||
312 | SDL_COMPILE_TIME_ASSERT (thinkpad_usb_trackpoint, sizeof (thinkpad_usb_trackpoint_hid_report_descriptor) == 185); | ||
313 | |||
314 | static unsigned char heusinkveld_pedals_hid_report_descriptor[] = | ||
315 | { | ||
316 | /* Generic Desktop / Joystick */ | ||
317 | 0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0x09, 0x33, | ||
318 | 0x09, 0x34, 0x09, 0x35, 0x15, 0x00, 0x26, 0xff, | ||
319 | 0x0f, 0x85, 0x01, 0x75, 0x10, 0x95, 0x03, 0x81, | ||
320 | 0x02, 0x09, 0x00, 0x75, 0x10, 0x95, 0x06, 0x82, | ||
321 | 0x01, 0x01, 0x85, 0x02, 0x75, 0x10, 0x95, 0x03, | ||
322 | 0x09, 0x00, 0x09, 0x00, 0xb1, 0x02, 0x85, 0x03, | ||
323 | 0x75, 0x08, 0x95, 0x03, 0x09, 0x00, 0x82, 0x01, | ||
324 | 0x01, 0xc0, | ||
325 | }; | ||
326 | SDL_COMPILE_TIME_ASSERT (heusinkveld_pedals, sizeof (heusinkveld_pedals_hid_report_descriptor) == 072); | ||
327 | |||
328 | static unsigned char fanatec_handbrake_hid_report_descriptor[] = | ||
329 | { | ||
330 | /* Generic Desktop / Joystick */ | ||
331 | 0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0x15, 0x00, | ||
332 | 0x26, 0xff, 0x00, 0x95, 0x01, 0x75, 0x08, 0x09, | ||
333 | 0x30, 0x81, 0x02, 0x06, 0x00, 0xff, 0x09, 0x01, | ||
334 | 0x95, 0x03, 0x81, 0x02, 0x06, 0x00, 0xff, 0x09, | ||
335 | 0x01, 0x95, 0x02, 0x91, 0x02, 0xc0, | ||
336 | }; | ||
337 | SDL_COMPILE_TIME_ASSERT (fanatec_handbrake, sizeof (fanatec_handbrake_hid_report_descriptor) == 046); | ||
338 | |||
339 | static unsigned char xpadneo09_xb1s_hid_report_descriptor[] = | ||
340 | { | ||
341 | 0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x01, | ||
342 | 0x09, 0x01, 0xa1, 0x00, 0x09, 0x30, 0x09, 0x31, | ||
343 | 0x15, 0x00, 0x27, 0xff, 0xff, 0x00, 0x00, 0x95, | ||
344 | 0x02, 0x75, 0x10, 0x81, 0x02, 0xc0, 0x09, 0x01, | ||
345 | 0xa1, 0x00, 0x09, 0x33, 0x09, 0x34, 0x15, 0x00, | ||
346 | 0x27, 0xff, 0xff, 0x00, 0x00, 0x95, 0x02, 0x75, | ||
347 | 0x10, 0x81, 0x02, 0xc0, 0x05, 0x01, 0x09, 0x32, | ||
348 | 0x15, 0x00, 0x26, 0xff, 0x03, 0x95, 0x01, 0x75, | ||
349 | 0x0a, 0x81, 0x02, 0x15, 0x00, 0x25, 0x00, 0x75, | ||
350 | 0x06, 0x95, 0x01, 0x81, 0x03, 0x05, 0x01, 0x09, | ||
351 | 0x35, 0x15, 0x00, 0x26, 0xff, 0x03, 0x95, 0x01, | ||
352 | 0x75, 0x0a, 0x81, 0x02, 0x15, 0x00, 0x25, 0x00, | ||
353 | 0x75, 0x06, 0x95, 0x01, 0x81, 0x03, 0x05, 0x01, | ||
354 | 0x09, 0x39, 0x15, 0x01, 0x25, 0x08, 0x35, 0x00, | ||
355 | 0x46, 0x3b, 0x01, 0x66, 0x14, 0x00, 0x75, 0x04, | ||
356 | 0x95, 0x01, 0x81, 0x42, 0x75, 0x04, 0x95, 0x01, | ||
357 | 0x15, 0x00, 0x25, 0x00, 0x35, 0x00, 0x45, 0x00, | ||
358 | 0x65, 0x00, 0x81, 0x03, 0x05, 0x09, 0x19, 0x01, | ||
359 | 0x29, 0x0c, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, | ||
360 | 0x95, 0x0c, 0x81, 0x02, 0x15, 0x00, 0x25, 0x00, | ||
361 | 0x75, 0x01, 0x95, 0x04, 0x81, 0x03, 0x05, 0x0c, | ||
362 | 0x0a, 0xb2, 0x00, 0x15, 0x00, 0x25, 0x01, 0x95, | ||
363 | 0x01, 0x75, 0x01, 0x81, 0x02, 0x15, 0x00, 0x25, | ||
364 | 0x00, 0x75, 0x07, 0x95, 0x01, 0x81, 0x03, 0x05, | ||
365 | 0x0f, 0x09, 0x21, 0x85, 0x03, 0xa1, 0x02, 0x09, | ||
366 | 0x97, 0x15, 0x00, 0x25, 0x01, 0x75, 0x04, 0x95, | ||
367 | 0x01, 0x91, 0x02, 0x15, 0x00, 0x25, 0x00, 0x75, | ||
368 | 0x04, 0x95, 0x01, 0x91, 0x03, 0x09, 0x70, 0x15, | ||
369 | 0x00, 0x25, 0x64, 0x75, 0x08, 0x95, 0x04, 0x91, | ||
370 | 0x02, 0x09, 0x50, 0x66, 0x01, 0x10, 0x55, 0x0e, | ||
371 | 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, | ||
372 | 0x01, 0x91, 0x02, 0x09, 0xa7, 0x15, 0x00, 0x26, | ||
373 | 0xff, 0x00, 0x75, 0x08, 0x95, 0x01, 0x91, 0x02, | ||
374 | 0x65, 0x00, 0x55, 0x00, 0x09, 0x7c, 0x15, 0x00, | ||
375 | 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x01, 0x91, | ||
376 | 0x02, 0xc0, 0xc0, | ||
377 | }; | ||
378 | SDL_COMPILE_TIME_ASSERT (xpadneo09_xb1s, sizeof (xpadneo09_xb1s_hid_report_descriptor) == 283); | ||
379 | |||
380 | /* Test-cases derived from real devices or from Linux kernel source */ | ||
381 | /* *INDENT-OFF* */ /* clang-format off */ | ||
382 | static const GuessTest guess_tests[] = | ||
383 | { | ||
384 | { | ||
385 | .name = "Xbox 360 wired USB controller", | ||
386 | .eviocgname = "Microsoft X-Box 360 pad", | ||
387 | .usb_vendor_name = "©Microsoft Corporation", | ||
388 | .usb_product_name = "Controller", | ||
389 | /* 8BitDo N30 Pro 2 v0114 via USB-C (with the xpad driver) is | ||
390 | * reported as 0003:045e:028e v0114, and is functionally equivalent */ | ||
391 | .bus_type = 0x0003, | ||
392 | .vendor_id = 0x045e, | ||
393 | .product_id = 0x028e, | ||
394 | .version = 0x0114, | ||
395 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
396 | /* SYN, KEY, ABS, FF */ | ||
397 | .ev = { 0x0b, 0x00, 0x20 }, | ||
398 | /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */ | ||
399 | .abs = { 0x3f, 0x00, 0x03 }, | ||
400 | .keys = { | ||
401 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
402 | /* A, B, X, Y, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */ | ||
403 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c, | ||
404 | }, | ||
405 | }, | ||
406 | { | ||
407 | .name = "X-Box One Elite", | ||
408 | .bus_type = 0x0003, | ||
409 | .vendor_id = 0x045e, | ||
410 | .product_id = 0x02e3, | ||
411 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
412 | /* SYN, KEY, ABS */ | ||
413 | .ev = { 0x0b }, | ||
414 | /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */ | ||
415 | .abs = { 0x3f, 0x00, 0x03 }, | ||
416 | .keys = { | ||
417 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
418 | /* A, B, X, Y, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */ | ||
419 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c, | ||
420 | }, | ||
421 | }, | ||
422 | { /* Reference: https://github.com/libsdl-org/SDL/issues/7814 */ | ||
423 | .name = "X-Box One Elite 2 via USB", | ||
424 | /* The same physical device via Bluetooth, 0005:045e:0b22 v0517, | ||
425 | * is reported differently (below). */ | ||
426 | /* Version 0407 is functionally equivalent. */ | ||
427 | .bus_type = 0x0003, | ||
428 | .vendor_id = 0x045e, | ||
429 | .product_id = 0x0b00, | ||
430 | .version = 0x0511, | ||
431 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
432 | /* SYN, KEY, ABS, FF */ | ||
433 | .ev = { 0x0b, 0x00, 0x20 }, | ||
434 | /* XY (left stick), RX/RY (right stick), Z/RZ (triggers), HAT0 (dpad) */ | ||
435 | .abs = { 0x3f, 0x00, 0x03 }, | ||
436 | .keys = { | ||
437 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
438 | /* A, B, X, Y, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */ | ||
439 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c, | ||
440 | /* 0x140 */ ZEROx8, | ||
441 | /* 0x180 */ ZEROx8, | ||
442 | /* 0x1c0 */ ZEROx8, | ||
443 | /* 0x200 */ ZEROx8, | ||
444 | /* 0x240 */ ZEROx8, | ||
445 | /* 0x280 */ ZEROx8, | ||
446 | /* BTN_TRIGGER_HAPPY5 up to BTN_TRIGGER_HAPPY8 inclusive are the | ||
447 | * back buttons (paddles) */ | ||
448 | /* 0x2c0 */ 0xf0, | ||
449 | }, | ||
450 | }, | ||
451 | { /* Reference: https://github.com/libsdl-org/SDL/issues/7814 */ | ||
452 | .name = "X-Box One Elite 2 via Bluetooth", | ||
453 | /* The same physical device via USB, 0003:045e:0b00 v0511, | ||
454 | * is reported differently (above). */ | ||
455 | .bus_type = 0x0003, | ||
456 | .vendor_id = 0x045e, | ||
457 | .product_id = 0x0b22, | ||
458 | .version = 0x0517, | ||
459 | .expected = SDL_UDEV_DEVICE_JOYSTICK | SDL_UDEV_DEVICE_HAS_KEYS, | ||
460 | /* SYN, KEY, ABS, FF */ | ||
461 | .ev = { 0x0b, 0x00, 0x20 }, | ||
462 | /* Android-style mapping: | ||
463 | * XY (left stick), Z/RZ (right stick), GAS/BRAKE (triggers), HAT0 (dpad) */ | ||
464 | .abs = { 0x27, 0x06, 0x03 }, | ||
465 | .keys = { | ||
466 | /* 0x00 */ ZEROx8, | ||
467 | /* 0x40 */ ZEROx8, | ||
468 | /* KEY_RECORD is advertised but isn't generated in practice */ | ||
469 | /* 0x80 */ ZEROx4, 0x80, 0x00, 0x00, 0x00, | ||
470 | /* KEY_UNKNOWN (240) is reported for the profile selector and all | ||
471 | * four back buttons (paddles) */ | ||
472 | /* 0xc0 */ ZEROx4, 0x00, 0x00, 0x01, 0x00, | ||
473 | /* ABXY, TL, TR, TL2, TR2, SELECT, START, MODE, THUMBL, | ||
474 | * THUMBR have their obvious meanings; C and Z are also | ||
475 | * advertised, but are not generated in practice. */ | ||
476 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0x7f, | ||
477 | }, | ||
478 | .hid_report_descriptor_length = sizeof (xbox_one_elite_2_hid_report_descriptor), | ||
479 | .hid_report_descriptor = &xbox_one_elite_2_hid_report_descriptor[0], | ||
480 | }, | ||
481 | { | ||
482 | .name = "X-Box One S via Bluetooth", | ||
483 | .bus_type = 0x0005, | ||
484 | .vendor_id = 0x045e, | ||
485 | .product_id = 0x02e0, | ||
486 | .version = 0x1130, | ||
487 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
488 | /* SYN, KEY, ABS */ | ||
489 | .ev = { 0x0b }, | ||
490 | /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */ | ||
491 | .abs = { 0x3f, 0x00, 0x03 }, | ||
492 | .keys = { | ||
493 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
494 | /* A, B, X, Y, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */ | ||
495 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c, | ||
496 | }, | ||
497 | }, | ||
498 | { | ||
499 | .name = "X-Box One S wired", | ||
500 | .bus_type = 0x0003, | ||
501 | .vendor_id = 0x045e, | ||
502 | .product_id = 0x02ea, | ||
503 | .version = 0x0301, | ||
504 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
505 | /* SYN, KEY, ABS */ | ||
506 | .ev = { 0x0b }, | ||
507 | /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */ | ||
508 | .abs = { 0x3f, 0x00, 0x03 }, | ||
509 | .keys = { | ||
510 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
511 | /* A, B, X, Y, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */ | ||
512 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c, | ||
513 | }, | ||
514 | }, | ||
515 | { | ||
516 | .name = "X-Box One S via xpadneo 0.9.x", | ||
517 | /* Reference: https://github.com/libsdl-org/SDL/issues/7823 */ | ||
518 | .eviocgname = "Xbox Wireless Controller", | ||
519 | .bus_type = 0x0005, | ||
520 | .vendor_id = 0x045e, | ||
521 | .product_id = 0x028e, | ||
522 | .version = 0x1130, | ||
523 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
524 | /* SYN, KEY, ABS, MSC, FF */ | ||
525 | .ev = { 0x1b }, | ||
526 | /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y | ||
527 | * plus MISC as a deprecated axis reporting (rz - z) */ | ||
528 | .abs = { 0x3f, 0x00, 0x03, 0x00, 0x00, 0x01 }, | ||
529 | .keys = { | ||
530 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
531 | /* A, B, X, Y, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */ | ||
532 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c, | ||
533 | /* 0x140 */ ZEROx8, | ||
534 | /* 0x180 */ ZEROx8, | ||
535 | /* 0x1c0 */ ZEROx8, | ||
536 | /* 0x200 */ ZEROx8, | ||
537 | /* 0x240 */ ZEROx8, | ||
538 | /* 0x280 */ ZEROx8, | ||
539 | /* BTN_TRIGGER_HAPPY33 up to BTN_TRIGGER_HAPPY36 inclusive: | ||
540 | * used to represent the current profile */ | ||
541 | /* 0x2c0 */ ZEROx4, 0xf0, | ||
542 | }, | ||
543 | .hid_report_descriptor_length = sizeof (xpadneo09_xb1s_hid_report_descriptor), | ||
544 | .hid_report_descriptor = &xpadneo09_xb1s_hid_report_descriptor[0], | ||
545 | }, | ||
546 | { | ||
547 | .name = "DualSense (PS5) - gamepad", | ||
548 | .bus_type = 0x0003, | ||
549 | .vendor_id = 0x054c, | ||
550 | .product_id = 0x0ce6, | ||
551 | .version = 0x111, | ||
552 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
553 | /* SYN, KEY, ABS */ | ||
554 | .ev = { 0x0b }, | ||
555 | /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */ | ||
556 | .abs = { 0x3f, 0x00, 0x03 }, | ||
557 | .keys = { | ||
558 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
559 | /* ABC, XYZ, TL, TR, TL2, TR2, select, start, mode, thumbl, | ||
560 | * thumbr; note that C and Z don't physically exist */ | ||
561 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0x7f, | ||
562 | }, | ||
563 | }, | ||
564 | { | ||
565 | .name = "DualSense (PS5) v8111 - gamepad", | ||
566 | .eviocgname = "Sony Interactive Entertainment Wireless Controller", | ||
567 | .usb_vendor_name = "Sony Interactive Entertainment", | ||
568 | .usb_product_name = "Wireless Controller", | ||
569 | /* Same physical device via Bluetooth is 0005:054c:0ce6 v8100 | ||
570 | * and EVIOCGNAME is just "Wireless Controller", otherwise equivalent */ | ||
571 | .bus_type = 0x0003, | ||
572 | .vendor_id = 0x054c, | ||
573 | .product_id = 0x0ce6, | ||
574 | .version = 0x8111, | ||
575 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
576 | /* SYN, KEY, ABS */ | ||
577 | .ev = { 0x0b }, | ||
578 | /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */ | ||
579 | .abs = { 0x3f, 0x00, 0x03 }, | ||
580 | .keys = { | ||
581 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
582 | /* A, B, X, Y, TL, TR, TL2, TR2, SELECT, START, MODE, | ||
583 | * THUMBL, THUMBR */ | ||
584 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7f, | ||
585 | }, | ||
586 | }, | ||
587 | { | ||
588 | .name = "DualShock 4 - gamepad", | ||
589 | /* EVIOCGNAME is just "Wireless Controller" when seen via Bluetooth */ | ||
590 | .eviocgname = "Sony Interactive Entertainment Wireless Controller", | ||
591 | .usb_vendor_name = "Sony Interactive Entertainment", | ||
592 | .usb_product_name = "Wireless Controller", | ||
593 | /* Same physical device via Bluetooth is 0005:054c:09cc v8100, | ||
594 | * but otherwise equivalent */ | ||
595 | .bus_type = 0x0003, | ||
596 | .vendor_id = 0x054c, | ||
597 | .product_id = 0x09cc, | ||
598 | .version = 0x8111, | ||
599 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
600 | /* SYN, KEY, ABS, MSC, FF */ | ||
601 | /* Some versions only have 0x0b, SYN, KEY, ABS, like the | ||
602 | * Bluetooth example below */ | ||
603 | .ev = { 0x1b, 0x00, 0x20 }, | ||
604 | /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */ | ||
605 | .abs = { 0x3f, 0x00, 0x03 }, | ||
606 | .keys = { | ||
607 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
608 | /* A, B, X, Y, TL, TR, TL2, TR2, SELECT, START, MODE, | ||
609 | * THUMBL, THUMBR */ | ||
610 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7f, | ||
611 | }, | ||
612 | }, | ||
613 | { | ||
614 | .name = "DualShock 4 - gamepad via Bluetooth (unknown version)", | ||
615 | .bus_type = 0x0005, | ||
616 | .vendor_id = 0x054c, | ||
617 | .product_id = 0x09cc, | ||
618 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
619 | /* SYN, KEY, ABS */ | ||
620 | .ev = { 0x0b }, | ||
621 | /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */ | ||
622 | .abs = { 0x3f, 0x00, 0x03 }, | ||
623 | .keys = { | ||
624 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
625 | /* A, B, X, Y, TL, TR, TL2, TR2, SELECT, START, MODE, | ||
626 | * THUMBL, THUMBR */ | ||
627 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7f, | ||
628 | }, | ||
629 | }, | ||
630 | { | ||
631 | .name = "DualShock 4 - touchpad", | ||
632 | /* EVIOCGNAME is just "Wireless Controller Touchpad" when seen via Bluetooth */ | ||
633 | .eviocgname = "Sony Interactive Entertainment Wireless Controller Touchpad", | ||
634 | .usb_vendor_name = "Sony Interactive Entertainment", | ||
635 | .usb_product_name = "Wireless Controller", | ||
636 | /* Same physical device via Bluetooth is 0005:054c:09cc v8100 and is | ||
637 | * functionally equivalent. */ | ||
638 | /* DualSense (PS5), 0003:054c:0ce6 v8111, is functionally equivalent. | ||
639 | * Same physical device via Bluetooth is 0005:054c:0ce6 v8100 and also | ||
640 | * functionally equivalent. */ | ||
641 | .bus_type = 0x0003, | ||
642 | .vendor_id = 0x054c, | ||
643 | .product_id = 0x09cc, | ||
644 | .version = 0x8111, | ||
645 | .expected = SDL_UDEV_DEVICE_TOUCHPAD, | ||
646 | /* SYN, KEY, ABS */ | ||
647 | .ev = { 0x0b }, | ||
648 | /* X, Y, multitouch */ | ||
649 | .abs = { 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x02 }, | ||
650 | .keys = { | ||
651 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
652 | /* Left mouse button */ | ||
653 | /* 0x100 */ 0x00, 0x00, 0x01, 0x00, ZEROx4, | ||
654 | /* BTN_TOOL_FINGER and some multitouch stuff */ | ||
655 | /* 0x140 */ 0x20, 0x24, 0x00, 0x00 | ||
656 | }, | ||
657 | /* POINTER, BUTTONPAD */ | ||
658 | .props = { 0x05 }, | ||
659 | }, | ||
660 | { | ||
661 | .name = "DualShock 4 - accelerometer", | ||
662 | /* EVIOCGNAME is just "Wireless Controller Motion Sensors" when seen via Bluetooth */ | ||
663 | .eviocgname = "Sony Interactive Entertainment Wireless Controller Motion Sensors", | ||
664 | .usb_vendor_name = "Sony Interactive Entertainment", | ||
665 | .usb_product_name = "Wireless Controller", | ||
666 | /* Same physical device via Bluetooth is 0005:054c:09cc v8100 and is | ||
667 | * functionally equivalent. */ | ||
668 | /* DualSense (PS5), 0003:054c:0ce6 v8111, is functionally equivalent. | ||
669 | * Same physical device via Bluetooth is 0005:054c:0ce6 v8100 and also | ||
670 | * functionally equivalent. */ | ||
671 | .bus_type = 0x0003, | ||
672 | .vendor_id = 0x054c, | ||
673 | .product_id = 0x09cc, | ||
674 | .version = 0x8111, | ||
675 | .expected = SDL_UDEV_DEVICE_ACCELEROMETER, | ||
676 | /* SYN, ABS, MSC */ | ||
677 | .ev = { 0x19 }, | ||
678 | /* X, Y, Z, RX, RY, RZ */ | ||
679 | .abs = { 0x3f }, | ||
680 | /* ACCELEROMETER */ | ||
681 | .props = { 0x40 }, | ||
682 | }, | ||
683 | { | ||
684 | .name = "DualShock 4 via USB dongle", | ||
685 | .bus_type = 0x0003, | ||
686 | .vendor_id = 0x054c, | ||
687 | .product_id = 0x0ba0, | ||
688 | .version = 0x8111, | ||
689 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
690 | /* SYN, ABS, KEY */ | ||
691 | .ev = { 0x0b }, | ||
692 | /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */ | ||
693 | .abs = { 0x3f, 0x00, 0x03 }, | ||
694 | .keys = { | ||
695 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
696 | /* A, B, X, Y, TL, TR, TL2, TR2, SELECT, START, MODE, | ||
697 | * THUMBL, THUMBR */ | ||
698 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7f, | ||
699 | }, | ||
700 | }, | ||
701 | { | ||
702 | .name = "DualShock 3 - gamepad", | ||
703 | .eviocgname = "Sony PLAYSTATION(R)3 Controller", | ||
704 | .usb_vendor_name = "Sony", | ||
705 | .usb_product_name = "PLAYSTATION(R)3 Controller", | ||
706 | .bus_type = 0x0003, | ||
707 | .vendor_id = 0x054c, | ||
708 | .product_id = 0x0268, | ||
709 | .version = 0x8111, | ||
710 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
711 | /* SYN, KEY, ABS, MSC, FF */ | ||
712 | .ev = { 0x1b, 0x00, 0x20 }, | ||
713 | /* X, Y, Z, RX, RY, RZ */ | ||
714 | .abs = { 0x3f }, | ||
715 | .keys = { | ||
716 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
717 | /* A, B, X, Y, TL, TR, TL2, TR2, SELECT, START, MODE, | ||
718 | * THUMBL, THUMBR */ | ||
719 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7f, | ||
720 | /* 0x140 */ ZEROx8, | ||
721 | /* 0x180 */ ZEROx8, | ||
722 | /* 0x1c0 */ ZEROx8, | ||
723 | /* Digital dpad */ | ||
724 | /* 0x200 */ ZEROx4, 0x0f, 0x00, 0x00, 0x00, | ||
725 | }, | ||
726 | .hid_report_descriptor_length = sizeof (ps3_hid_report_descriptor), | ||
727 | .hid_report_descriptor = &ps3_hid_report_descriptor[0], | ||
728 | }, | ||
729 | { | ||
730 | .name = "DualShock 3 - accelerometer", | ||
731 | .eviocgname = "Sony PLAYSTATION(R)3 Controller Motion Sensors", | ||
732 | .usb_vendor_name = "Sony", | ||
733 | .usb_product_name = "PLAYSTATION(R)3 Controller", | ||
734 | .bus_type = 0x0003, | ||
735 | .vendor_id = 0x054c, | ||
736 | .product_id = 0x0268, | ||
737 | .expected = SDL_UDEV_DEVICE_ACCELEROMETER, | ||
738 | /* SYN, ABS */ | ||
739 | .ev = { 0x09 }, | ||
740 | /* X, Y, Z */ | ||
741 | .abs = { 0x07 }, | ||
742 | /* ACCELEROMETER */ | ||
743 | .props = { 0x40 }, | ||
744 | .hid_report_descriptor_length = sizeof (ps3_hid_report_descriptor), | ||
745 | .hid_report_descriptor = &ps3_hid_report_descriptor[0], | ||
746 | }, | ||
747 | { | ||
748 | .name = "Steam Controller - gamepad", | ||
749 | .bus_type = 0x0003, | ||
750 | .vendor_id = 0x28de, | ||
751 | .product_id = 0x1142, | ||
752 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
753 | /* SYN, KEY, ABS */ | ||
754 | .ev = { 0x0b }, | ||
755 | /* X, Y, RX, RY, HAT0X, HAT0Y, HAT2X, HAT2Y */ | ||
756 | .abs = { 0x1b, 0x00, 0x33 }, | ||
757 | .keys = { | ||
758 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
759 | /* A, B, X, Y, TL, TR, TL2, TR2, SELECT, START, MODE, | ||
760 | * THUMBL, THUMBR, joystick THUMB, joystick THUMB2 */ | ||
761 | /* 0x100 */ ZEROx4, 0x06, 0x00, 0xdb, 0x7f, | ||
762 | /* GEAR_DOWN, GEAR_UP */ | ||
763 | /* 0x140 */ 0x00, 0x00, 0x03, 0x00, ZEROx4, | ||
764 | /* 0x180 */ ZEROx8, | ||
765 | /* 0x1c0 */ ZEROx8, | ||
766 | /* Digital dpad */ | ||
767 | /* 0x200 */ ZEROx4, 0x0f, 0x00, 0x00, 0x00, | ||
768 | }, | ||
769 | }, | ||
770 | { | ||
771 | /* Present to support lizard mode, even if no Steam Controller | ||
772 | * is connected */ | ||
773 | .name = "Steam Controller - dongle", | ||
774 | .bus_type = 0x0003, | ||
775 | .vendor_id = 0x28de, | ||
776 | .product_id = 0x1142, | ||
777 | .expected = (SDL_UDEV_DEVICE_HAS_KEYS | ||
778 | | SDL_UDEV_DEVICE_KEYBOARD | ||
779 | | SDL_UDEV_DEVICE_MOUSE), | ||
780 | /* SYN, KEY, REL, MSC, LED, REP */ | ||
781 | .ev = { 0x17, 0x00, 0x12 }, | ||
782 | /* X, Y, mouse wheel, high-res mouse wheel */ | ||
783 | .rel = { 0x03, 0x09 }, | ||
784 | .keys = { | ||
785 | /* 0x00 */ 0xfe, 0xff, 0xff, 0xff, FFx4, | ||
786 | /* 0x40 */ 0xff, 0xff, 0xcf, 0x01, 0xdf, 0xff, 0x80, 0xe0, | ||
787 | /* 0x80 */ ZEROx8, | ||
788 | /* 0xc0 */ ZEROx8, | ||
789 | /* 0x100 */ 0x00, 0x00, 0x1f, 0x00, ZEROx4, | ||
790 | }, | ||
791 | }, | ||
792 | { | ||
793 | .name = "Steam Deck - mouse", | ||
794 | /* This is the LCD model (jupiter). | ||
795 | * Steam Deck OLED (galileo, possibly pre-production) has | ||
796 | * .eviocgname = "Valve Software Steam Controller" | ||
797 | * .version = 0x0110 | ||
798 | * .usb_device_version = 0x0300 | ||
799 | * but is otherwise equivalent. | ||
800 | */ | ||
801 | .eviocgname = "Valve Software Steam Deck Controller", | ||
802 | .usb_vendor_name = "Valve Software", | ||
803 | .usb_product_name = "Steam Deck Controller", | ||
804 | .bus_type = 0x0003, | ||
805 | .vendor_id = 0x28de, | ||
806 | .product_id = 0x1205, | ||
807 | .version = 0x011, | ||
808 | .usb_device_version = 0x0200, | ||
809 | /* SYN, KEY, REL, MSC */ | ||
810 | .ev = { 0x17 }, | ||
811 | /* X, Y, mouse wheel v/h, high-res mouse wheel v/h */ | ||
812 | .rel = { 0x43, 0x19 }, | ||
813 | .keys = { | ||
814 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
815 | /* left/right mouse button */ | ||
816 | /* 0x100 */ 0x00, 0x00, 0x03, 0x00, ZEROx4, | ||
817 | }, | ||
818 | .expected = SDL_UDEV_DEVICE_MOUSE, | ||
819 | .hid_report_descriptor_length = sizeof (steam_deck_mouse_hid_report_descriptor), | ||
820 | .hid_report_descriptor = &steam_deck_mouse_hid_report_descriptor[0], | ||
821 | }, | ||
822 | { | ||
823 | .name = "Steam Deck - keyboard", | ||
824 | /* This is the LCD model (jupiter). | ||
825 | * Steam Deck OLED (galileo, possibly pre-production) has | ||
826 | * .eviocgname = "Valve Software Steam Controller" | ||
827 | * .version = 0x0110 | ||
828 | * .usb_device_version = 0x0300 | ||
829 | * but is otherwise equivalent. | ||
830 | */ | ||
831 | .eviocgname = "Valve Software Steam Deck Controller", | ||
832 | .usb_vendor_name = "Valve Software", | ||
833 | .usb_product_name = "Steam Deck Controller", | ||
834 | .bus_type = 0x0003, | ||
835 | .vendor_id = 0x28de, | ||
836 | .product_id = 0x1205, | ||
837 | .version = 0x0110, | ||
838 | .usb_device_version = 0x0300, | ||
839 | /* SYN, KEY, MSC, REP */ | ||
840 | .ev = { 0x13, 0x00, 0x10 }, | ||
841 | .keys = { | ||
842 | /* 0x00 */ 0xfe, 0xff, 0xff, 0xff, FFx4, | ||
843 | /* 0x40 */ 0xff, 0xff, 0xcf, 0x01, 0xdf, 0xff, 0x80, 0xe0, | ||
844 | }, | ||
845 | .expected = SDL_UDEV_DEVICE_KEYBOARD | SDL_UDEV_DEVICE_HAS_KEYS, | ||
846 | .hid_report_descriptor_length = sizeof (steam_deck_kb_hid_report_descriptor), | ||
847 | .hid_report_descriptor = &steam_deck_kb_hid_report_descriptor[0], | ||
848 | }, | ||
849 | { | ||
850 | .name = "Steam Deck LCD - gamepad", | ||
851 | .eviocgname = "Valve Software Steam Deck Controller", | ||
852 | .usb_vendor_name = "Valve Software", | ||
853 | .usb_product_name = "Steam Deck Controller", | ||
854 | .bus_type = 0x0003, | ||
855 | .vendor_id = 0x28de, | ||
856 | .product_id = 0x1205, | ||
857 | .version = 0x0111, | ||
858 | .usb_device_version = 0x0200, | ||
859 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
860 | /* TODO: The data I have for Steam Deck LCD didn't seem to have | ||
861 | * an evdev device available, so this is extrapolated from | ||
862 | * kernel source code as being the same as the OLED model | ||
863 | * (the kernel driver doesn't distinguish). */ | ||
864 | /* SYN, KEY, ABS */ | ||
865 | .ev = { 0x0b }, | ||
866 | /* X, Y, RX, RY, hat 0-2 x/y */ | ||
867 | .abs = { 0x1b, 0x00, 0x3f }, | ||
868 | .keys = { | ||
869 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
870 | /* 0x120 0x46: joystick THUMB, THUMB2, BASE */ | ||
871 | /* 0x130 0xdb: gamepad ABXY, TL/TR */ | ||
872 | /* 0x138 0x7f: gamepad TL2/TR2, SELECT/START, MODE, THUMBL/R */ | ||
873 | /* 0x100 */ ZEROx4, 0x46, 0x00, 0xdb, 0x7f, | ||
874 | /* 0x140 */ ZEROx8, | ||
875 | /* 0x180 */ ZEROx8, | ||
876 | /* 0x1c0 */ ZEROx8, | ||
877 | /* 0x220 0x0f: dpad up/down/left/right */ | ||
878 | /* 0x200 */ ZEROx4, 0x0f, 0x00, 0x00, 0x00, | ||
879 | /* 0x240 */ ZEROx8, | ||
880 | /* 0x280 */ ZEROx8, | ||
881 | /* 0x2c0 0x0f: joystick TRIGGER_HAPPY1..TRIGGER_HAPPY4 */ | ||
882 | /* 0x2c0 */ 0x0f, | ||
883 | }, | ||
884 | .hid_report_descriptor_length = sizeof (steam_deck_lcd_js_hid_report_descriptor), | ||
885 | .hid_report_descriptor = &steam_deck_lcd_js_hid_report_descriptor[0], | ||
886 | }, | ||
887 | { | ||
888 | .name = "Steam Deck OLED - gamepad", | ||
889 | .eviocgname = "Valve Software Steam Controller", | ||
890 | .usb_vendor_name = "Valve Software", | ||
891 | .usb_product_name = "Steam Controller", | ||
892 | .bus_type = 0x0003, | ||
893 | .vendor_id = 0x28de, | ||
894 | .product_id = 0x1205, | ||
895 | .version = 0x0110, | ||
896 | .usb_device_version = 0x0300, | ||
897 | /* SYN, KEY, ABS */ | ||
898 | .ev = { 0x0b }, | ||
899 | /* X, Y, RX, RY, hat 0-2 x/y */ | ||
900 | .abs = { 0x1b, 0x00, 0x3f }, | ||
901 | .keys = { | ||
902 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
903 | /* 0x120 0x46: joystick THUMB, THUMB2, BASE */ | ||
904 | /* 0x130 0xdb: gamepad ABXY, TL/TR */ | ||
905 | /* 0x138 0x7f: gamepad TL2/TR2, SELECT/START, MODE, THUMBL/R */ | ||
906 | /* 0x100 */ ZEROx4, 0x46, 0x00, 0xdb, 0x7f, | ||
907 | /* 0x140 */ ZEROx8, | ||
908 | /* 0x180 */ ZEROx8, | ||
909 | /* 0x1c0 */ ZEROx8, | ||
910 | /* 0x220 0x0f: dpad up/down/left/right */ | ||
911 | /* 0x200 */ ZEROx4, 0x0f, 0x00, 0x00, 0x00, | ||
912 | /* 0x240 */ ZEROx8, | ||
913 | /* 0x280 */ ZEROx8, | ||
914 | /* 0x2c0 0x0f: joystick TRIGGER_HAPPY1..TRIGGER_HAPPY4 */ | ||
915 | /* 0x2c0 */ 0x0f, | ||
916 | }, | ||
917 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
918 | .hid_report_descriptor_length = sizeof (steam_deck_oled_js_hid_report_descriptor), | ||
919 | .hid_report_descriptor = &steam_deck_oled_js_hid_report_descriptor[0], | ||
920 | }, | ||
921 | { | ||
922 | .name = "Steam Input virtual controller", | ||
923 | .eviocgname = "Microsoft X-Box 360 pad 0", | ||
924 | .bus_type = 0x0003, | ||
925 | .vendor_id = 0x28de, | ||
926 | .product_id = 0x11ff, | ||
927 | .version = 0x0001, | ||
928 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
929 | /* SYN, KEY, ABS, FF */ | ||
930 | .ev = { 0x0b, 0x00, 0x20 }, | ||
931 | /* XYZ, RXYZ, hat 0 */ | ||
932 | .abs = { 0x3f, 0x00, 0x03 }, | ||
933 | .keys = { | ||
934 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
935 | /* 0x130 0xdb: gamepad ABXY, TL/TR */ | ||
936 | /* 0x138 0x7f: gamepad SELECT/START, MODE, THUMBL/R */ | ||
937 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c, | ||
938 | }, | ||
939 | }, | ||
940 | { | ||
941 | .name = "Guitar Hero for PS3", | ||
942 | /* SWITCH CO.,LTD. Controller (Dinput) off-brand N64-style USB controller | ||
943 | * 0003:2563:0575 v0111 is functionally equivalent. | ||
944 | * https://linux-hardware.org/?id=usb:2563-0575 reports the same IDs as | ||
945 | * ShenZhen ShanWan Technology ZD-V+ Wired Gaming Controller */ | ||
946 | .bus_type = 0x0003, | ||
947 | .vendor_id = 0x12ba, | ||
948 | .product_id = 0x0100, | ||
949 | .version = 0x0110, | ||
950 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
951 | /* SYN, KEY, ABS */ | ||
952 | .ev = { 0x0b }, | ||
953 | /* X, Y, Z, RZ, HAT0X, HAT0Y */ | ||
954 | .abs = { 0x27, 0x00, 0x03 }, | ||
955 | .keys = { | ||
956 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
957 | /* ABC, XYZ, TL, TR, TL2, TR2, SELECT, START, MODE */ | ||
958 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0x1f, | ||
959 | }, | ||
960 | }, | ||
961 | { | ||
962 | .name = "G27 Racing Wheel, 0003:046d:c29b v0111", | ||
963 | .bus_type = 0x0003, | ||
964 | .vendor_id = 0x046d, | ||
965 | .product_id = 0xc29b, | ||
966 | .version = 0x0111, | ||
967 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
968 | /* SYN, KEY, ABS */ | ||
969 | .ev = { 0x0b }, | ||
970 | /* X, Y, Z, RZ, HAT0X, HAT0Y */ | ||
971 | .abs = { 0x27, 0x00, 0x03 }, | ||
972 | .keys = { | ||
973 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
974 | /* 16 buttons: TRIGGER, THUMB, THUMB2, TOP, TOP2, PINKIE, BASE, | ||
975 | * BASE2..BASE6, unregistered event codes 0x12c-0x12e, DEAD */ | ||
976 | /* 0x100 */ ZEROx4, 0xff, 0xff, 0x00, 0x00, | ||
977 | /* 0x140 */ ZEROx8, | ||
978 | /* 0x180 */ ZEROx8, | ||
979 | /* 0x1c0 */ ZEROx8, | ||
980 | /* 0x200 */ ZEROx8, | ||
981 | /* 0x240 */ ZEROx8, | ||
982 | /* 0x280 */ ZEROx8, | ||
983 | /* TRIGGER_HAPPY1..TRIGGER_HAPPY7 */ | ||
984 | /* 0x2c0 */ 0x7f, | ||
985 | }, | ||
986 | }, | ||
987 | { | ||
988 | .name = "Logitech Driving Force, 0003:046d:c294 v0100", | ||
989 | .bus_type = 0x0003, | ||
990 | .vendor_id = 0x046d, | ||
991 | .product_id = 0xc294, | ||
992 | .version = 0x0100, | ||
993 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
994 | /* SYN, KEY, ABS */ | ||
995 | .ev = { 0x0b }, | ||
996 | /* X, Y, RZ, HAT0X, HAT0Y */ | ||
997 | .abs = { 0x23, 0x00, 0x03 }, | ||
998 | .keys = { | ||
999 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1000 | /* 12 buttons: TRIGGER, THUMB, THUMB2, TOP, TOP2, PINKIE, BASE, | ||
1001 | * BASE2..BASE6 */ | ||
1002 | /* 0x100 */ ZEROx4, 0xff, 0x0f, 0x00, 0x00, | ||
1003 | }, | ||
1004 | }, | ||
1005 | { | ||
1006 | .name = "Logitech Dual Action", | ||
1007 | .bus_type = 0x0003, | ||
1008 | .vendor_id = 0x046d, | ||
1009 | .product_id = 0xc216, | ||
1010 | .version = 0x0110, | ||
1011 | /* Logitech RumblePad 2 USB, 0003:046d:c218 v0110, is the same | ||
1012 | * except for having force feedback, which we don't use in our | ||
1013 | * heuristic */ | ||
1014 | /* Jess Tech GGE909 PC Recoil Pad, 0003:0f30:010b v0110, is the same */ | ||
1015 | /* 8BitDo SNES30 via USB, 0003:2dc8:ab20 v0110, is the same; | ||
1016 | * see below for the same physical device via Bluetooth, | ||
1017 | * 0005:2dc8:2840 v0100 */ | ||
1018 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
1019 | /* SYN, KEY, ABS */ | ||
1020 | .ev = { 0x0b }, | ||
1021 | /* X, Y, Z, RZ, HAT0X, HAT0Y */ | ||
1022 | .abs = { 0x27, 0x00, 0x03 }, | ||
1023 | .keys = { | ||
1024 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1025 | /* 12 buttons: TRIGGER, THUMB, THUMB2, TOP, TOP2, PINKIE, BASE, | ||
1026 | * BASE2..BASE6 */ | ||
1027 | /* 0x100 */ ZEROx4, 0xff, 0x0f, 0x00, 0x00, | ||
1028 | }, | ||
1029 | }, | ||
1030 | { | ||
1031 | .name = "8BitDo SNES30 v0100 via Bluetooth", | ||
1032 | .eviocgname = "8Bitdo SNES30 GamePad", | ||
1033 | /* The same physical device via USB, 0003:2dc8:ab20 v0110, | ||
1034 | * is reported differently (above). */ | ||
1035 | /* 8BitDo NES30 Pro (aka N30 Pro) via Bluetooth, 0005:2dc8:3820 v0100, | ||
1036 | * is functionally equivalent; but the same physical device via USB, | ||
1037 | * 0003:2dc8:9001 v0111, matches N30 Pro 2 v0111. */ | ||
1038 | .bus_type = 0x0005, | ||
1039 | .vendor_id = 0x2dc8, | ||
1040 | .product_id = 0x2840, | ||
1041 | .version = 0x0100, | ||
1042 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
1043 | /* SYN, KEY, ABS, MSC */ | ||
1044 | .ev = { 0x1b }, | ||
1045 | /* XYZ, RZ, GAS, BRAKE, HAT0X, HAT0Y */ | ||
1046 | .abs = { 0x27, 0x06, 0x03 }, | ||
1047 | .keys = { | ||
1048 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1049 | /* ABC, XYZ, TL, TR, TL2, TR2, SELECT, START, MODE, THUMBL, THUMBR, | ||
1050 | * and an unassigned button code */ | ||
1051 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0xff, | ||
1052 | }, | ||
1053 | }, | ||
1054 | { | ||
1055 | .name = "Saitek ST290 Pro flight stick", | ||
1056 | .bus_type = 0x0003, | ||
1057 | .vendor_id = 0x06a3, | ||
1058 | .product_id = 0x0160, /* 0x0460 seems to be the same */ | ||
1059 | .version = 0x0100, | ||
1060 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
1061 | /* SYN, KEY, ABS, MSC */ | ||
1062 | .ev = { 0x1b }, | ||
1063 | /* X, Y, Z, RZ, HAT0X, HAT0Y */ | ||
1064 | .abs = { 0x27, 0x00, 0x03 }, | ||
1065 | .keys = { | ||
1066 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1067 | /* TRIGGER, THUMB, THUMB2, TOP, TOP2, PINKIE */ | ||
1068 | /* 0x100 */ ZEROx4, 0x3f, 0x00, 0x00, 0x00, | ||
1069 | }, | ||
1070 | }, | ||
1071 | { | ||
1072 | .name = "Saitek X52 Pro Flight Control System", | ||
1073 | .bus_type = 0x0003, | ||
1074 | .vendor_id = 0x06a3, | ||
1075 | .product_id = 0x0762, | ||
1076 | .version = 0x0111, | ||
1077 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
1078 | .ev = { 0x0b }, | ||
1079 | /* XYZ, RXYZ, throttle, hat0, MISC, unregistered event code 0x29 */ | ||
1080 | .abs = { 0x7f, 0x00, 0x03, 0x00, 0x00, 0x03 }, | ||
1081 | .keys = { | ||
1082 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1083 | /* 16 buttons: TRIGGER, THUMB, THUMB2, TOP, TOP2, PINKIE, BASE, | ||
1084 | * BASE2..BASE6, unregistered event codes 0x12c-0x12e, DEAD */ | ||
1085 | /* 0x100 */ ZEROx4, 0xff, 0xff, 0x00, 0x00, | ||
1086 | /* 0x140 */ ZEROx8, | ||
1087 | /* 0x180 */ ZEROx8, | ||
1088 | /* 0x1c0 */ ZEROx8, | ||
1089 | /* 0x200 */ ZEROx8, | ||
1090 | /* 0x240 */ ZEROx8, | ||
1091 | /* 0x280 */ ZEROx8, | ||
1092 | /* TRIGGER_HAPPY1..TRIGGER_HAPPY23 */ | ||
1093 | /* 0x2c0 */ 0xff, 0xff, 0x7f, | ||
1094 | }, | ||
1095 | }, | ||
1096 | { | ||
1097 | .name = "Logitech Extreme 3D", | ||
1098 | .bus_type = 0x0003, | ||
1099 | .vendor_id = 0x046d, | ||
1100 | .product_id = 0xc215, | ||
1101 | .version = 0x0110, | ||
1102 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
1103 | /* SYN, KEY, ABS, MSC */ | ||
1104 | .ev = { 0x0b }, | ||
1105 | /* X, Y, RZ, throttle, hat 0 */ | ||
1106 | .abs = { 0x63, 0x00, 0x03 }, | ||
1107 | .keys = { | ||
1108 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1109 | /* 12 buttons: TRIGGER, THUMB, THUMB2, TOP, TOP2, PINKIE, BASE, | ||
1110 | * BASE2..BASE6 */ | ||
1111 | /* 0x100 */ ZEROx4, 0xff, 0x0f, 0x00, 0x00, | ||
1112 | }, | ||
1113 | }, | ||
1114 | { | ||
1115 | .name = "Hori Real Arcade Pro VX-SA", | ||
1116 | .bus_type = 0x0003, | ||
1117 | .vendor_id = 0x24c6, | ||
1118 | .product_id = 0x5501, | ||
1119 | .version = 0x0533, | ||
1120 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
1121 | /* SYN, KEY, ABS */ | ||
1122 | .ev = { 0x0b }, | ||
1123 | /* X, Y, Z, RX, RY, RZ, hat 0 */ | ||
1124 | .abs = { 0x3f, 0x00, 0x03 }, | ||
1125 | .keys = { | ||
1126 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1127 | /* A, B, X, Y, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */ | ||
1128 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c, | ||
1129 | }, | ||
1130 | }, | ||
1131 | { | ||
1132 | /* https://github.com/ValveSoftware/steam-devices/pull/42 | ||
1133 | * PS4 mode is functionally equivalent, but with product ID 0x011c | ||
1134 | * and version 0x1101. */ | ||
1135 | .name = "Hori Fighting Stick Alpha - PS5 mode", | ||
1136 | .bus_type = 0x0003, /* USB */ | ||
1137 | .vendor_id = 0x0f0d, /* Hori Co., Ltd. */ | ||
1138 | .product_id = 0x0184, /* HORI FIGHTING STICK α (PS5 mode) */ | ||
1139 | .version = 0x0111, | ||
1140 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
1141 | /* SYN, KEY, ABS, MSC */ | ||
1142 | .ev = { 0x1b }, | ||
1143 | /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */ | ||
1144 | .abs = { 0x3f, 0x00, 0x03 }, | ||
1145 | .keys = { | ||
1146 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1147 | /* ABC, XYZ, TL, TR, TL2, TR2, SELECT, START, MODE, | ||
1148 | * THUMBL */ | ||
1149 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0x3f, | ||
1150 | }, | ||
1151 | }, | ||
1152 | { /* https://github.com/ValveSoftware/steam-devices/pull/42 */ | ||
1153 | .name = "Hori Fighting Stick Alpha - PC mode", | ||
1154 | .bus_type = 0x0003, /* USB */ | ||
1155 | .vendor_id = 0x0f0d, /* Hori Co., Ltd. */ | ||
1156 | .product_id = 0x011e, /* HORI FIGHTING STICK α (PC mode) */ | ||
1157 | .version = 0x0116, | ||
1158 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
1159 | /* SYN, KEY, ABS, FF */ | ||
1160 | .ev = { 0x0b, 0x00, 0x20 }, | ||
1161 | /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */ | ||
1162 | .abs = { 0x3f, 0x00, 0x03 }, | ||
1163 | .keys = { | ||
1164 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1165 | /* A, B, X, Y, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */ | ||
1166 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c, | ||
1167 | }, | ||
1168 | }, | ||
1169 | { /* https://github.com/ValveSoftware/steam-devices/issues/29 */ | ||
1170 | .name = "HORIPAD S for Nintendo", | ||
1171 | .bus_type = 0x0003, /* USB */ | ||
1172 | .vendor_id = 0x0f0d, /* Hori Co., Ltd. */ | ||
1173 | .product_id = 0x00dc, /* HORIPAD S */ | ||
1174 | .version = 0x0112, | ||
1175 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
1176 | /* SYN, KEY, ABS, FF */ | ||
1177 | .ev = { 0x0b, 0x00, 0x20 }, | ||
1178 | /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */ | ||
1179 | .abs = { 0x3f, 0x00, 0x03 }, | ||
1180 | .keys = { | ||
1181 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1182 | /* A, B, X, Y, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */ | ||
1183 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c, | ||
1184 | }, | ||
1185 | }, | ||
1186 | { | ||
1187 | .name = "Switch Pro Controller via Bluetooth", | ||
1188 | .bus_type = 0x0005, | ||
1189 | .vendor_id = 0x057e, | ||
1190 | .product_id = 0x2009, | ||
1191 | .version = 0x0001, | ||
1192 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
1193 | /* SYN, KEY, ABS */ | ||
1194 | .ev = { 0x0b }, | ||
1195 | /* X, Y, RX, RY, hat 0 */ | ||
1196 | .abs = { 0x1b, 0x00, 0x03 }, | ||
1197 | .keys = { | ||
1198 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1199 | /* 16 buttons: TRIGGER, THUMB, THUMB2, TOP, TOP2, PINKIE, BASE, | ||
1200 | * BASE2..BASE6, unregistered event codes 0x12c-0x12e, DEAD */ | ||
1201 | /* 0x100 */ ZEROx4, 0xff, 0xff, 0x00, 0x00, | ||
1202 | /* 0x140 */ ZEROx8, | ||
1203 | /* 0x180 */ ZEROx8, | ||
1204 | /* 0x1c0 */ ZEROx8, | ||
1205 | /* 0x200 */ ZEROx8, | ||
1206 | /* 0x240 */ ZEROx8, | ||
1207 | /* 0x280 */ ZEROx8, | ||
1208 | /* TRIGGER_HAPPY1..TRIGGER_HAPPY2 */ | ||
1209 | /* 0x2c0 */ 0x03, | ||
1210 | }, | ||
1211 | }, | ||
1212 | { | ||
1213 | .name = "Switch Pro Controller via Bluetooth (Linux 6.2.11)", | ||
1214 | .eviocgname = "Pro Controller", | ||
1215 | .bus_type = 0x0005, | ||
1216 | .vendor_id = 0x057e, | ||
1217 | .product_id = 0x2009, | ||
1218 | .version = 0x0001, | ||
1219 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
1220 | /* SYN, KEY, ABS */ | ||
1221 | .ev = { 0x0b }, | ||
1222 | /* X, Y, RX, RY, hat 0 */ | ||
1223 | .abs = { 0x1b, 0x00, 0x03 }, | ||
1224 | .keys = { | ||
1225 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1226 | /* ABC, XYZ, TL, TR, TL2, TR2, SELECT, START, MODE, THUMBL, THUMBR, | ||
1227 | * and an unassigned button code */ | ||
1228 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0xff, | ||
1229 | }, | ||
1230 | }, | ||
1231 | { | ||
1232 | .name = "Switch Pro Controller via USB", | ||
1233 | .eviocgname = "Nintendo Co., Ltd. Pro Controller", | ||
1234 | .usb_vendor_name = "Nintendo Co., Ltd.", | ||
1235 | .usb_product_name = "Pro Controller", | ||
1236 | .bus_type = 0x0003, | ||
1237 | .vendor_id = 0x057e, | ||
1238 | .product_id = 0x2009, | ||
1239 | .version = 0x0111, | ||
1240 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
1241 | /* SYN, KEY, ABS */ | ||
1242 | .ev = { 0x0b }, | ||
1243 | /* X, Y, Z, RZ, HAT0X, HAT0Y */ | ||
1244 | .abs = { 0x27, 0x00, 0x03 }, | ||
1245 | .keys = { | ||
1246 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1247 | /* 16 buttons: TRIGGER, THUMB, THUMB2, TOP, TOP2, PINKIE, BASE, | ||
1248 | * BASE2..BASE6, unregistered event codes 0x12c-0x12e, DEAD */ | ||
1249 | /* 0x100 */ ZEROx4, 0xff, 0xff, 0x00, 0x00, | ||
1250 | /* 0x140 */ ZEROx8, | ||
1251 | /* 0x180 */ ZEROx8, | ||
1252 | /* 0x1c0 */ ZEROx8, | ||
1253 | /* 0x200 */ ZEROx8, | ||
1254 | /* 0x240 */ ZEROx8, | ||
1255 | /* 0x280 */ ZEROx8, | ||
1256 | /* TRIGGER_HAPPY1..TRIGGER_HAPPY2 */ | ||
1257 | /* 0x2c0 */ 0x03, | ||
1258 | }, | ||
1259 | }, | ||
1260 | { /* https://github.com/ValveSoftware/steam-devices/pull/40 */ | ||
1261 | .name = "PDP wired Pro Controller for Switch", | ||
1262 | /* 0003:0e6f:0184 "Performance Designed Products" / | ||
1263 | * "Faceoff Deluxe+ Audio Wired Controller for Nintendo Switch" appears | ||
1264 | * to be functionally equivalent */ | ||
1265 | .eviocgname = "PDP CO.,LTD. Faceoff Wired Pro Controller for Nintendo Switch", | ||
1266 | .usb_vendor_name = "PDP CO.,LTD.", | ||
1267 | .usb_product_name = "Faceoff Wired Pro Controller for Nintendo Switch", | ||
1268 | .bus_type = 0x0003, | ||
1269 | .vendor_id = 0x0e6f, | ||
1270 | .product_id = 0x0180, | ||
1271 | .version = 0x0111, | ||
1272 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
1273 | /* SYN, KEY, ABS, MSC */ | ||
1274 | .ev = { 0x1b }, | ||
1275 | /* X, Y, Z, RZ, HAT0X, HAT0Y */ | ||
1276 | .abs = { 0x27, 0x00, 0x03 }, | ||
1277 | .keys = { | ||
1278 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1279 | /* ABC, XYZ, TL, TR, TL2, TR2, SELECT, START, MODE, | ||
1280 | * THUMBL */ | ||
1281 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0x3f, | ||
1282 | }, | ||
1283 | }, | ||
1284 | { | ||
1285 | .name = "NES Controller (R) NES-style Joycon from Nintendo Online", | ||
1286 | .eviocgname = "NES Controller (R)", | ||
1287 | /* Joy-Con (L), 0005:057e:2006 v0001, is functionally equivalent. | ||
1288 | * Ordinary Joy-Con (R) and NES-style Joy-Con (L) are assumed to be | ||
1289 | * functionally equivalent as well. */ | ||
1290 | .bus_type = 0x0005, /* Bluetooth-only */ | ||
1291 | .vendor_id = 0x057e, | ||
1292 | .product_id = 0x2007, | ||
1293 | .version = 0x0001, | ||
1294 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
1295 | /* SYN, KEY, ABS */ | ||
1296 | .ev = { 0x0b }, | ||
1297 | /* X, Y, RX, RY, hat 0 */ | ||
1298 | .abs = { 0x1b, 0x00, 0x03 }, | ||
1299 | .keys = { | ||
1300 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1301 | /* ABC, XYZ, TL, TR, TL2, TR2, SELECT, START, MODE, THUMBL, THUMBR, | ||
1302 | * and an unassigned button code */ | ||
1303 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0xff, | ||
1304 | }, | ||
1305 | }, | ||
1306 | { | ||
1307 | .name = "Thrustmaster Racing Wheel FFB", | ||
1308 | /* Several devices intended for PS4 are functionally equivalent to this: | ||
1309 | * https://github.com/ValveSoftware/steam-devices/pull/34 | ||
1310 | * Mad Catz FightStick TE S+ PS4, 0003:0738:8384:0111 v0111 | ||
1311 | * (aka Street Fighter V Arcade FightStick TES+) | ||
1312 | * Mad Catz FightStick TE2+ PS4, 0003:0738:8481 v0100 | ||
1313 | * (aka Street Fighter V Arcade FightStick TE2+) | ||
1314 | * Bigben Interactive DAIJA Arcade Stick, 0003:146b:0d09 v0111 | ||
1315 | * (aka Nacon Daija PS4 Arcade Stick) | ||
1316 | * Razer Razer Raiju Ultimate Wired, 0003:1532:1009 v0000 | ||
1317 | * Razer Razer Raiju Ultimate (Bluetooth), 0005:1532:1009 v0001 | ||
1318 | */ | ||
1319 | .bus_type = 0x0003, | ||
1320 | .vendor_id = 0x044f, | ||
1321 | .product_id = 0xb66d, | ||
1322 | .version = 0x0110, | ||
1323 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
1324 | .ev = { 0x0b }, | ||
1325 | /* XYZ, RXYZ, hat 0 */ | ||
1326 | .abs = { 0x3f, 0x00, 0x03 }, | ||
1327 | .keys = { | ||
1328 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1329 | /* ABC, XYZ, TL, TR, TL2, TR2, SELECT, START, MODE, | ||
1330 | * THUMBL */ | ||
1331 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0x3f, | ||
1332 | }, | ||
1333 | }, | ||
1334 | { | ||
1335 | .name = "Thrustmaster T.Flight Hotas X", | ||
1336 | .bus_type = 0x0003, | ||
1337 | .vendor_id = 0x044f, | ||
1338 | .product_id = 0xb108, | ||
1339 | .version = 0x0100, | ||
1340 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
1341 | .ev = { 0x0b }, | ||
1342 | /* XYZ, RZ, throttle, hat 0 */ | ||
1343 | .abs = { 0x67, 0x00, 0x03 }, | ||
1344 | .keys = { | ||
1345 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1346 | /* trigger, thumb, thumb2, top, top2, pinkie, base, | ||
1347 | * base2..base6 */ | ||
1348 | /* 0x100 */ ZEROx4, 0xff, 0x0f | ||
1349 | }, | ||
1350 | }, | ||
1351 | { | ||
1352 | .name = "8BitDo N30 Pro via Bluetooth", | ||
1353 | /* This device has also been seen reported with an additional | ||
1354 | * unassigned button code, the same as the SNES30 v0100 via Bluetooth */ | ||
1355 | .bus_type = 0x0005, | ||
1356 | .vendor_id = 0x2dc8, | ||
1357 | .product_id = 0x3820, | ||
1358 | .version = 0x0100, | ||
1359 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
1360 | /* SYN, KEY, ABS, MSC */ | ||
1361 | .ev = { 0x1b }, | ||
1362 | /* XYZ, RZ, gas, brake, hat0 */ | ||
1363 | .abs = { 0x27, 0x06, 0x03 }, | ||
1364 | .keys = { | ||
1365 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1366 | /* ABC, XYZ, TL, TR, TL2, TR2, select, start, mode, thumbl, | ||
1367 | * thumbr */ | ||
1368 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0x7f, | ||
1369 | }, | ||
1370 | }, | ||
1371 | { | ||
1372 | .name = "8BitDo N30 Pro 2 v0111", | ||
1373 | .bus_type = 0x0003, | ||
1374 | .vendor_id = 0x2dc8, | ||
1375 | .product_id = 0x9015, | ||
1376 | .version = 0x0111, | ||
1377 | /* 8BitDo NES30 Pro via USB, 0003:2dc8:9001 v0111, is the same; | ||
1378 | * but the same physical device via Bluetooth, 0005:2dc8:3820 v0100, | ||
1379 | * matches 8BitDo SNES30 v0100 via Bluetooth instead (see above). */ | ||
1380 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
1381 | .ev = { 0x0b }, | ||
1382 | /* XYZ, RZ, gas, brake, hat0 */ | ||
1383 | .abs = { 0x27, 0x06, 0x03 }, | ||
1384 | .keys = { | ||
1385 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1386 | /* ABC, XYZ, TL, TR, TL2, TR2, select, start, mode, thumbl, | ||
1387 | * thumbr */ | ||
1388 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0x7f, | ||
1389 | }, | ||
1390 | }, | ||
1391 | { | ||
1392 | .name = "8BitDo N30 Pro 2 via Bluetooth", | ||
1393 | /* Physically the same device as the one that mimics an Xbox 360 | ||
1394 | * USB controller when wired */ | ||
1395 | .bus_type = 0x0005, | ||
1396 | .vendor_id = 0x045e, | ||
1397 | .product_id = 0x02e0, | ||
1398 | .version = 0x0903, | ||
1399 | .expected = SDL_UDEV_DEVICE_JOYSTICK | SDL_UDEV_DEVICE_HAS_KEYS, | ||
1400 | /* SYN, KEY, ABS, MSC, FF */ | ||
1401 | .ev = { 0x1b, 0x00, 0x20 }, | ||
1402 | /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */ | ||
1403 | .abs = { 0x3f, 0x00, 0x03 }, | ||
1404 | .keys = { | ||
1405 | /* 0x00 */ ZEROx8, | ||
1406 | /* 0x40 */ ZEROx8, | ||
1407 | /* KEY_MENU */ | ||
1408 | /* 0x80 */ 0x00, 0x08, 0x00, 0x00, ZEROx4, | ||
1409 | /* 0xc0 */ ZEROx8, | ||
1410 | /* ABC, XYZ, TL, TR, TL2, TR2 */ | ||
1411 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0x03, | ||
1412 | }, | ||
1413 | }, | ||
1414 | { | ||
1415 | .name = "Retro Power SNES-style controller, 0003:0079:0011 v0110", | ||
1416 | .bus_type = 0x0003, | ||
1417 | .vendor_id = 0x0079, | ||
1418 | .product_id = 0x0011, | ||
1419 | .version = 0x0110, | ||
1420 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
1421 | .ev = { 0x0b }, | ||
1422 | /* X, Y */ | ||
1423 | .abs = { 0x03 }, | ||
1424 | .keys = { | ||
1425 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1426 | /* trigger, thumb, thumb2, top, top2, pinkie, base, | ||
1427 | * base2..base4 */ | ||
1428 | /* 0x100 */ ZEROx4, 0xff, 0x03, 0x00, 0x00, | ||
1429 | }, | ||
1430 | }, | ||
1431 | { | ||
1432 | .name = "Google Stadia Controller rev.A", | ||
1433 | .eviocgname = "Google LLC Stadia Controller rev. A", | ||
1434 | .usb_vendor_name = "Google LLC", | ||
1435 | .usb_product_name = "Stadia Controller rev. A", | ||
1436 | /* This data is with USB-C, but the same physical device via Bluetooth, | ||
1437 | * 0005:18d1:9400 v0000, is functionally equivalent other than having | ||
1438 | * EVIOCGNAME = StadiaXXXX-YYYY where XXXX is the last 4 digits of | ||
1439 | * the serial number and YYYY is some other mystery number */ | ||
1440 | .bus_type = 0x0003, | ||
1441 | .vendor_id = 0x18d1, | ||
1442 | .product_id = 0x9400, | ||
1443 | .version = 0x0100, | ||
1444 | .expected = SDL_UDEV_DEVICE_JOYSTICK | SDL_UDEV_DEVICE_HAS_KEYS, | ||
1445 | .ev = { 0x0b }, | ||
1446 | /* XYZ, RZ, gas, brake, hat0 */ | ||
1447 | .abs = { 0x27, 0x06, 0x03 }, | ||
1448 | .keys = { | ||
1449 | /* 0x00 */ ZEROx8, | ||
1450 | /* Volume up/down */ | ||
1451 | /* 0x40 */ ZEROx4, 0x00, 0x00, 0x0c, 0x00, | ||
1452 | /* Media play/pause */ | ||
1453 | /* 0x80 */ ZEROx4, 0x10, 0x00, 0x00, 0x00, | ||
1454 | /* 0xc0 */ ZEROx8, | ||
1455 | /* ABXY, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */ | ||
1456 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c, | ||
1457 | /* 0x140 */ ZEROx8, | ||
1458 | /* 0x180 */ ZEROx8, | ||
1459 | /* 0x1c0 */ ZEROx8, | ||
1460 | /* 0x200 */ ZEROx8, | ||
1461 | /* 0x240 */ ZEROx8, | ||
1462 | /* 0x280 */ ZEROx8, | ||
1463 | /* TRIGGER_HAPPY 1-4 */ | ||
1464 | /* 0x2c0 */ 0x0f, 0x00, 0x00, 0x00, ZEROx4, | ||
1465 | }, | ||
1466 | }, | ||
1467 | { | ||
1468 | .name = "Microsoft Xbox Series S|X Controller (model 1914) via USB", | ||
1469 | .eviocgname = "Microsoft Xbox Series S|X Controller", | ||
1470 | .usb_vendor_name = "Microsoft", | ||
1471 | .usb_product_name = "Controller", | ||
1472 | /* Physically the same device as 0003:045e:0b13 v0515 below, | ||
1473 | * but some functionality is mapped differently */ | ||
1474 | .bus_type = 0x0003, | ||
1475 | .vendor_id = 0x045e, | ||
1476 | .product_id = 0x0b12, | ||
1477 | .version = 0x050f, | ||
1478 | .expected = SDL_UDEV_DEVICE_JOYSTICK | SDL_UDEV_DEVICE_HAS_KEYS, | ||
1479 | .ev = { 0x0b }, | ||
1480 | /* X, Y, Z, RX, RY, RZ, hat 0 */ | ||
1481 | .abs = { 0x3f, 0x00, 0x03 }, | ||
1482 | .keys = { | ||
1483 | /* 0x00 */ ZEROx8, | ||
1484 | /* 0x40 */ ZEROx8, | ||
1485 | /* Record */ | ||
1486 | /* 0x80 */ ZEROx4, 0x80, 0x00, 0x00, 0x00, | ||
1487 | /* 0xc0 */ ZEROx8, | ||
1488 | /* ABXY, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */ | ||
1489 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c, | ||
1490 | }, | ||
1491 | }, | ||
1492 | { | ||
1493 | .name = "Microsoft Xbox Series S|X Controller (model 1914) via Bluetooth", | ||
1494 | .eviocgname = "Xbox Wireless Controller", | ||
1495 | /* Physically the same device as 0003:045e:0b12 v050f above, | ||
1496 | * but some functionality is mapped differently */ | ||
1497 | .bus_type = 0x0005, | ||
1498 | .vendor_id = 0x045e, | ||
1499 | .product_id = 0x0b13, | ||
1500 | .version = 0x0515, | ||
1501 | .expected = SDL_UDEV_DEVICE_JOYSTICK | SDL_UDEV_DEVICE_HAS_KEYS, | ||
1502 | .ev = { 0x0b }, | ||
1503 | /* XYZ, RZ, gas, brake, hat0 */ | ||
1504 | .abs = { 0x27, 0x06, 0x03 }, | ||
1505 | .keys = { | ||
1506 | /* 0x00 */ ZEROx8, | ||
1507 | /* 0x40 */ ZEROx8, | ||
1508 | /* Record */ | ||
1509 | /* 0x80 */ ZEROx4, 0x80, 0x00, 0x00, 0x00, | ||
1510 | /* 0xc0 */ ZEROx8, | ||
1511 | /* ABC, XYZ, TL, TR, TL2, TR2, select, start, mode, thumbl, | ||
1512 | * thumbr */ | ||
1513 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0x7f, | ||
1514 | }, | ||
1515 | }, | ||
1516 | { | ||
1517 | .name = "Wiimote - buttons", | ||
1518 | .eviocgname = "Nintendo Wii Remote", | ||
1519 | .bus_type = 0x0005, | ||
1520 | .vendor_id = 0x057e, | ||
1521 | .product_id = 0x0306, | ||
1522 | .version = 0x0600, | ||
1523 | /* This one is a bit weird because some of the buttons are mapped | ||
1524 | * to the arrow, page up and page down keys, so it's a joystick | ||
1525 | * with a subset of a keyboard attached. */ | ||
1526 | /* TODO: Should this be JOYSTICK, or even JOYSTICK|HAS_KEYS? */ | ||
1527 | .expected = SDL_UDEV_DEVICE_HAS_KEYS, | ||
1528 | /* SYN, KEY, FF */ | ||
1529 | .ev = { 0x03, 0x00, 0x20 }, | ||
1530 | .keys = { | ||
1531 | /* 0x00 */ ZEROx8, | ||
1532 | /* left, right, up down */ | ||
1533 | /* 0x40 */ ZEROx4, 0x80, 0x16, 0x00, 0x00, | ||
1534 | /* 0x80 */ ZEROx8, | ||
1535 | /* 0xc0 */ ZEROx8, | ||
1536 | /* BTN_1, BTN_2, BTN_A, BTN_B, BTN_MODE */ | ||
1537 | /* 0x100 */ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x10, | ||
1538 | /* 0x140 */ ZEROx8, | ||
1539 | /* next (keyboard page down), previous (keyboard page up) */ | ||
1540 | /* 0x180 */ 0x00, 0x00, 0x80, 0x10, ZEROx4, | ||
1541 | }, | ||
1542 | }, | ||
1543 | { | ||
1544 | .name = "Wiimote - accelerometer", | ||
1545 | .eviocgname = "Nintendo Wii Remote Accelerometer", | ||
1546 | .bus_type = 0x0005, | ||
1547 | .vendor_id = 0x057e, | ||
1548 | .product_id = 0x0306, | ||
1549 | .version = 0x0600, | ||
1550 | .expected = SDL_UDEV_DEVICE_ACCELEROMETER, | ||
1551 | /* SYN, ABS */ | ||
1552 | .ev = { 0x09 }, | ||
1553 | /* RX, RY, RZ - even though it would more conventionally be X, Y, Z */ | ||
1554 | .abs = { 0x38 }, | ||
1555 | }, | ||
1556 | { | ||
1557 | .name = "Wiimote - Motion Plus gyroscope", | ||
1558 | .eviocgname = "Nintendo Wii Remote Motion Plus", | ||
1559 | /* Note that if we only look at the bus type, vendor, product, version | ||
1560 | * and axes, this is indistinguishable from the accelerometer */ | ||
1561 | .bus_type = 0x0005, | ||
1562 | .vendor_id = 0x057e, | ||
1563 | .product_id = 0x0306, | ||
1564 | .version = 0x0600, | ||
1565 | .expected = SDL_UDEV_DEVICE_ACCELEROMETER, | ||
1566 | /* SYN, ABS */ | ||
1567 | .ev = { 0x09 }, | ||
1568 | /* RX, RY, RZ */ | ||
1569 | .abs = { 0x38 }, | ||
1570 | }, | ||
1571 | { | ||
1572 | .name = "Wiimote - IR positioning", | ||
1573 | .eviocgname = "Nintendo Wii Remote IR", | ||
1574 | .bus_type = 0x0005, | ||
1575 | .vendor_id = 0x057e, | ||
1576 | .product_id = 0x0306, | ||
1577 | .version = 0x0600, | ||
1578 | .expected = SDL_UDEV_DEVICE_UNKNOWN, | ||
1579 | /* SYN, ABS */ | ||
1580 | .ev = { 0x09 }, | ||
1581 | /* HAT0X, Y to HAT3X, Y */ | ||
1582 | .abs = { 0x00, 0x00, 0xff }, | ||
1583 | }, | ||
1584 | { | ||
1585 | .name = "Wiimote - Nunchuck", | ||
1586 | .eviocgname = "Nintendo Wii Remote Nunchuk", | ||
1587 | .bus_type = 0x0005, | ||
1588 | .vendor_id = 0x057e, | ||
1589 | .product_id = 0x0306, | ||
1590 | .version = 0x0600, | ||
1591 | /* TODO: Should this be JOYSTICK? It has one stick and two buttons */ | ||
1592 | .expected = SDL_UDEV_DEVICE_UNKNOWN, | ||
1593 | /* SYN, KEY, ABS */ | ||
1594 | .ev = { 0x0b }, | ||
1595 | /* RX, RY, RZ, hat 0 - even though this is an accelerometer, which | ||
1596 | * would more conventionally be X, Y, Z, and a left joystick, which | ||
1597 | * would more conventionally be X, Y */ | ||
1598 | .abs = { 0x38, 0x00, 0x03 }, | ||
1599 | .keys = { | ||
1600 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1601 | /* C and Z buttons */ | ||
1602 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0x24, 0x00, | ||
1603 | }, | ||
1604 | }, | ||
1605 | { | ||
1606 | .name = "Wiimote - Classic Controller", | ||
1607 | .eviocgname = "Nintendo Wii Remote Classic Controller", | ||
1608 | .bus_type = 0x0005, | ||
1609 | .vendor_id = 0x057e, | ||
1610 | .product_id = 0x0306, | ||
1611 | .version = 0x0600, | ||
1612 | /* TODO: Should this be JOYSTICK, or maybe JOYSTICK|HAS_KEYS? | ||
1613 | * It's unusual in the same ways as the Wiimote */ | ||
1614 | .expected = SDL_UDEV_DEVICE_HAS_KEYS, | ||
1615 | /* SYN, KEY, ABS */ | ||
1616 | .ev = { 0x0b }, | ||
1617 | /* Hat 1-3 X and Y */ | ||
1618 | .abs = { 0x00, 0x00, 0xfc }, | ||
1619 | .keys = { | ||
1620 | /* 0x00 */ ZEROx8, | ||
1621 | /* left, right, up down */ | ||
1622 | /* 0x40 */ ZEROx4, 0x80, 0x16, 0x00, 0x00, | ||
1623 | /* 0x80 */ ZEROx8, | ||
1624 | /* 0xc0 */ ZEROx8, | ||
1625 | /* A, B, X, Y, MODE, TL, TL2, TR, TR2 */ | ||
1626 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x13, | ||
1627 | /* 0x140 */ ZEROx8, | ||
1628 | /* next (keyboard page down), previous (keyboard page up) */ | ||
1629 | /* 0x180 */ 0x00, 0x00, 0x80, 0x10, ZEROx4, | ||
1630 | }, | ||
1631 | }, | ||
1632 | { | ||
1633 | /* Flags guessed from kernel source code, not confirmed with real | ||
1634 | * hardware */ | ||
1635 | .name = "Wiimote - Balance Board", | ||
1636 | /* TODO: Should this be JOYSTICK? */ | ||
1637 | .expected = SDL_UDEV_DEVICE_UNKNOWN, | ||
1638 | /* SYN, KEY, ABS */ | ||
1639 | .ev = { 0x0b }, | ||
1640 | /* Hat 0-1 */ | ||
1641 | .abs = { 0x00, 0x00, 0x0f }, | ||
1642 | .keys = { | ||
1643 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1644 | /* BTN_A */ | ||
1645 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0x01, 0x00, | ||
1646 | }, | ||
1647 | }, | ||
1648 | { | ||
1649 | /* Flags guessed from kernel source code, not confirmed with real | ||
1650 | * hardware */ | ||
1651 | .name = "Wiimote - Wii U Pro Controller", | ||
1652 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
1653 | /* SYN, KEY, ABS */ | ||
1654 | .ev = { 0x0b }, | ||
1655 | /* X, Y, RX, RY */ | ||
1656 | .abs = { 0x1b }, | ||
1657 | .keys = { | ||
1658 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1659 | /* A, B, X, Y, TL, TR, TL2, TR2, SELECT, START, MODE, | ||
1660 | * THUMBL, THUMBR */ | ||
1661 | /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7f, | ||
1662 | /* 0x140 */ ZEROx8, | ||
1663 | /* 0x180 */ ZEROx8, | ||
1664 | /* 0x1c0 */ ZEROx8, | ||
1665 | /* Digital dpad */ | ||
1666 | /* 0x200 */ ZEROx4, 0x0f, 0x00, 0x00, 0x00, | ||
1667 | }, | ||
1668 | }, | ||
1669 | { | ||
1670 | .name = "Synaptics TM3381-002 (Thinkpad X280 trackpad)", | ||
1671 | .eviocgname = "Synaptics TM3381-002", | ||
1672 | .bus_type = 0x001d, /* BUS_RMI */ | ||
1673 | .vendor_id = 0x06cb, | ||
1674 | .product_id = 0x0000, | ||
1675 | .version = 0x0000, | ||
1676 | .expected = SDL_UDEV_DEVICE_TOUCHPAD, | ||
1677 | /* SYN, KEY, ABS */ | ||
1678 | .ev = { 0x0b }, | ||
1679 | /* X, Y, pressure, multitouch */ | ||
1680 | .abs = { 0x03, 0x00, 0x00, 0x01, 0x00, 0x80, 0xf3, 0x06 }, | ||
1681 | .keys = { | ||
1682 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1683 | /* Left mouse button */ | ||
1684 | /* 0x100 */ 0x00, 0x00, 0x01, 0x00, ZEROx4, | ||
1685 | /* BTN_TOOL_FINGER and some multitouch gestures */ | ||
1686 | /* 0x140 */ 0x20, 0xe5 | ||
1687 | }, | ||
1688 | /* POINTER, BUTTONPAD */ | ||
1689 | .props = { 0x05 }, | ||
1690 | }, | ||
1691 | { | ||
1692 | .name = "DELL08AF:00 (Dell XPS laptop touchpad)", | ||
1693 | .bus_type = 0x18, | ||
1694 | .vendor_id = 0x6cb, | ||
1695 | .product_id = 0x76af, | ||
1696 | .version = 0x100, | ||
1697 | .ev = { 0x0b }, | ||
1698 | .expected = SDL_UDEV_DEVICE_TOUCHPAD, | ||
1699 | /* X, Y, multitouch */ | ||
1700 | .abs = { 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0x02 }, | ||
1701 | .keys = { | ||
1702 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1703 | /* Left mouse button */ | ||
1704 | /* 0x100 */ 0x00, 0x00, 0x01, 0x00, ZEROx4, | ||
1705 | /* BTN_TOOL_FINGER and some multitouch gestures */ | ||
1706 | /* 0x140 */ 0x20, 0xe5 | ||
1707 | }, | ||
1708 | /* POINTER, BUTTONPAD */ | ||
1709 | .props = { 0x05 }, | ||
1710 | }, | ||
1711 | { | ||
1712 | .name = "TPPS/2 Elan TrackPoint (Thinkpad X280)", | ||
1713 | .eviocgname = "TPPS/2 Elan TrackPoint", | ||
1714 | .bus_type = 0x0011, /* BUS_I8042 */ | ||
1715 | .vendor_id = 0x0002, | ||
1716 | .product_id = 0x000a, | ||
1717 | .version = 0x0000, | ||
1718 | .expected = SDL_UDEV_DEVICE_MOUSE, | ||
1719 | /* SYN, KEY, REL */ | ||
1720 | .ev = { 0x07 }, | ||
1721 | /* X, Y */ | ||
1722 | .rel = { 0x03 }, | ||
1723 | .keys = { | ||
1724 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
1725 | /* Left, middle, right mouse buttons */ | ||
1726 | /* 0x100 */ 0x00, 0x00, 0x07, | ||
1727 | }, | ||
1728 | /* POINTER, POINTING_STICK */ | ||
1729 | .props = { 0x21 }, | ||
1730 | }, | ||
1731 | { | ||
1732 | .name = "Thinkpad ACPI buttons", | ||
1733 | .eviocgname = "ThinkPad Extra Buttons", | ||
1734 | .bus_type = 0x0019, | ||
1735 | .vendor_id = 0x17aa, | ||
1736 | .product_id = 0x5054, | ||
1737 | .version = 0x4101, | ||
1738 | .expected = SDL_UDEV_DEVICE_HAS_KEYS, | ||
1739 | /* SYN, KEY, MSC, SW */ | ||
1740 | .ev = { 0x33 }, | ||
1741 | .keys = { | ||
1742 | /* 0x00 */ ZEROx8, | ||
1743 | /* 0x40 */ ZEROx4, 0x00, 0x00, 0x0e, 0x01, | ||
1744 | /* 0x80 */ 0x00, 0x50, 0x11, 0x51, 0x00, 0x28, 0x00, 0xc0, | ||
1745 | /* 0xc0 */ 0x04, 0x20, 0x10, 0x02, 0x1b, 0x70, 0x01, 0x00, | ||
1746 | /* 0x100 */ ZEROx8, | ||
1747 | /* 0x140 */ ZEROx4, 0x00, 0x00, 0x50, 0x00, | ||
1748 | /* 0x180 */ ZEROx8, | ||
1749 | /* 0x1c0 */ 0x00, 0x00, 0x04, 0x18, ZEROx4, | ||
1750 | /* 0x200 */ ZEROx8, | ||
1751 | /* 0x240 */ 0x40, 0x00, 0x01, 0x00, ZEROx4, | ||
1752 | }, | ||
1753 | }, | ||
1754 | { | ||
1755 | .name = "Thinkpad ACPI buttons (Linux 6.1)", | ||
1756 | .eviocgname = "ThinkPad Extra Buttons", | ||
1757 | .bus_type = 0x0019, | ||
1758 | .vendor_id = 0x17aa, | ||
1759 | .product_id = 0x5054, | ||
1760 | .version = 0x4101, | ||
1761 | .expected = SDL_UDEV_DEVICE_HAS_KEYS, | ||
1762 | /* SYN, KEY, MSC, SW */ | ||
1763 | .ev = { 0x33 }, | ||
1764 | .keys = { | ||
1765 | /* 0x00 */ ZEROx8, | ||
1766 | /* 0x40 */ ZEROx4, 0x00, 0x00, 0x0e, 0x01, | ||
1767 | /* 0x80 */ 0x00, 0x50, 0x11, 0x51, 0x00, 0x28, 0x00, 0xc0, | ||
1768 | /* 0xc0 */ 0x04, 0x20, 0x10, 0x02, 0x1b, 0x70, 0x01, 0x00, | ||
1769 | /* 0x100 */ ZEROx8, | ||
1770 | /* 0x140 */ ZEROx4, 0x00, 0x00, 0x50, 0x00, | ||
1771 | /* 0x180 */ ZEROx4, 0x00, 0x00, 0x00, 0x70, | ||
1772 | /* 0x1c0 */ 0x00, 0x00, 0x04, 0x18, 0x20, 0x00, 0x00, 0x00, | ||
1773 | /* 0x200 */ ZEROx8, | ||
1774 | /* 0x240 */ ZEROx8, | ||
1775 | }, | ||
1776 | }, | ||
1777 | { | ||
1778 | .name = "PC speaker", | ||
1779 | .eviocgname = "PC Speaker", | ||
1780 | .bus_type = 0x0010, /* BUS_ISA */ | ||
1781 | .vendor_id = 0x001f, | ||
1782 | .product_id = 0x0001, | ||
1783 | .version = 0x0100, | ||
1784 | .expected = SDL_UDEV_DEVICE_UNKNOWN, | ||
1785 | /* SYN, SND */ | ||
1786 | .ev = { 0x01, 0x00, 0x04 }, | ||
1787 | }, | ||
1788 | { | ||
1789 | .name = "HDA Digital PCBeep", | ||
1790 | .eviocgname = "HDA Digital PCBeep", | ||
1791 | .bus_type = 0x0001, | ||
1792 | .vendor_id = 0x10ec, | ||
1793 | .product_id = 0x0257, | ||
1794 | .version = 0x0001, | ||
1795 | .expected = SDL_UDEV_DEVICE_UNKNOWN, | ||
1796 | /* SYN, SND */ | ||
1797 | .ev = { 0x01, 0x00, 0x04 }, | ||
1798 | }, | ||
1799 | { | ||
1800 | .name = "ALSA headphone detection, etc.", | ||
1801 | .eviocgname = "HDA Intel PCH Mic", | ||
1802 | /* HDA Intel PCH Headphone is functionally equivalent */ | ||
1803 | /* HDA Intel PCH HDMI/DP,pcm=3 is functionally equivalent */ | ||
1804 | /* HDA Intel PCH HDMI/DP,pcm=7 is functionally equivalent */ | ||
1805 | /* HDA Intel PCH HDMI/DP,pcm=8 is functionally equivalent */ | ||
1806 | .bus_type = 0x0000, | ||
1807 | .vendor_id = 0x0000, | ||
1808 | .product_id = 0x0000, | ||
1809 | .version = 0x0000, | ||
1810 | .expected = SDL_UDEV_DEVICE_UNKNOWN, | ||
1811 | /* SYN, SW */ | ||
1812 | .ev = { 0x21 }, | ||
1813 | }, | ||
1814 | { | ||
1815 | /* Assumed to be a reasonably typical i8042 (PC AT) keyboard */ | ||
1816 | .name = "Thinkpad T520 and X280 keyboards", | ||
1817 | /* Steam Deck LCD/OLED keyboard interface is version 0xab83 but | ||
1818 | * otherwise equivalent */ | ||
1819 | .eviocgname = "AT Translated Set 2 keyboard", | ||
1820 | .bus_type = 0x0011, /* BUS_I8042 */ | ||
1821 | .vendor_id = 0x0001, | ||
1822 | .product_id = 0x0001, | ||
1823 | .version = 0xab54, | ||
1824 | .expected = SDL_UDEV_DEVICE_HAS_KEYS | SDL_UDEV_DEVICE_KEYBOARD, | ||
1825 | /* SYN, KEY, MSC, LED, REP */ | ||
1826 | .ev = { 0x13, 0x00, 0x12 }, | ||
1827 | .keys = { | ||
1828 | /* 0x00 */ 0xfe, 0xff, 0xff, 0xff, FFx4, | ||
1829 | /* 0x40 */ 0xff, 0xff, 0xef, 0xff, 0xdf, 0xff, 0xff, 0xfe, | ||
1830 | /* 0x80 */ 0x01, 0xd0, 0x00, 0xf8, 0x78, 0x30, 0x80, 0x03, | ||
1831 | /* 0xc0 */ 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, | ||
1832 | }, | ||
1833 | }, | ||
1834 | { | ||
1835 | .name = "Thinkpad X280 sleep button", | ||
1836 | .eviocgname = "Sleep Button", | ||
1837 | .bus_type = 0x0019, /* BUS_HOST */ | ||
1838 | .vendor_id = 0x0000, | ||
1839 | .product_id = 0x0003, | ||
1840 | .version = 0x0000, | ||
1841 | .expected = SDL_UDEV_DEVICE_HAS_KEYS, | ||
1842 | /* SYN, KEY */ | ||
1843 | .ev = { 0x03 }, | ||
1844 | .keys = { | ||
1845 | /* 0x00 */ ZEROx8, | ||
1846 | /* 0x40 */ ZEROx8, | ||
1847 | /* KEY_SLEEP */ | ||
1848 | /* 0x80 */ 0x00, 0x40, | ||
1849 | }, | ||
1850 | }, | ||
1851 | { | ||
1852 | /* As seen on Thinkpad X280, Steam Deck LCD, Steam Deck OLED */ | ||
1853 | .name = "ACPI lid switch", | ||
1854 | .eviocgname = "Lid Switch", | ||
1855 | .bus_type = 0x0019, /* BUS_HOST */ | ||
1856 | .vendor_id = 0x0000, | ||
1857 | .product_id = 0x0005, | ||
1858 | .version = 0x0000, | ||
1859 | .expected = SDL_UDEV_DEVICE_UNKNOWN, | ||
1860 | /* SYN, SW */ | ||
1861 | .ev = { 0x21 }, | ||
1862 | }, | ||
1863 | { | ||
1864 | /* As seen on Thinkpad X280, Steam Deck LCD, Steam Deck OLED */ | ||
1865 | .name = "ACPI power button", | ||
1866 | .eviocgname = "Power Button", | ||
1867 | .bus_type = 0x0019, /* BUS_HOST */ | ||
1868 | .vendor_id = 0x0000, | ||
1869 | .product_id = 0x0001, | ||
1870 | .version = 0x0000, | ||
1871 | .expected = SDL_UDEV_DEVICE_HAS_KEYS, | ||
1872 | /* SYN, KEY */ | ||
1873 | .ev = { 0x03 }, | ||
1874 | .keys = { | ||
1875 | /* 0x00 */ ZEROx8, | ||
1876 | /* KEY_POWER */ | ||
1877 | /* 0x40 */ ZEROx4, 0x00, 0x00, 0x10, 0x00, | ||
1878 | }, | ||
1879 | }, | ||
1880 | { | ||
1881 | /* As seen on Thinkpad X280, Steam Deck LCD, Steam Deck OLED */ | ||
1882 | .name = "ACPI video bus", | ||
1883 | .eviocgname = "Video Bus", | ||
1884 | .bus_type = 0x0019, /* BUS_HOST */ | ||
1885 | .vendor_id = 0x0000, | ||
1886 | .product_id = 0x0006, | ||
1887 | .version = 0x0000, | ||
1888 | .expected = SDL_UDEV_DEVICE_HAS_KEYS, | ||
1889 | /* SYN, KEY */ | ||
1890 | .ev = { 0x03 }, | ||
1891 | .keys = { | ||
1892 | /* 0x00 */ ZEROx8, | ||
1893 | /* 0x40 */ ZEROx8, | ||
1894 | /* 0x80 */ ZEROx8, | ||
1895 | /* brightness control, video mode, display off */ | ||
1896 | /* 0xc0 */ ZEROx4, 0x0b, 0x00, 0x3e, 0x00, | ||
1897 | }, | ||
1898 | }, | ||
1899 | { | ||
1900 | .name = "Thinkpad X280 webcam", | ||
1901 | .eviocgname = "Integrated Camera: Integrated C", | ||
1902 | .usb_vendor_name = "Chicony Electronics Co.,Ltd.", | ||
1903 | .usb_product_name = "Integrated Camera", | ||
1904 | .bus_type = 0x0003, | ||
1905 | .vendor_id = 0x04f2, | ||
1906 | .product_id = 0xb604, | ||
1907 | .version = 0x0027, | ||
1908 | .expected = SDL_UDEV_DEVICE_HAS_KEYS, | ||
1909 | /* SYN, KEY */ | ||
1910 | .ev = { 0x03 }, | ||
1911 | .keys = { | ||
1912 | /* 0x00 */ ZEROx8, | ||
1913 | /* 0x40 */ ZEROx8, | ||
1914 | /* 0x80 */ ZEROx8, | ||
1915 | /* KEY_CAMERA */ | ||
1916 | /* 0xc0 */ 0x00, 0x00, 0x10, 0x00, ZEROx4, | ||
1917 | }, | ||
1918 | }, | ||
1919 | { | ||
1920 | .name = "Thinkpad X280 extra buttons", | ||
1921 | .bus_type = 0x0019, /* BUS_HOST */ | ||
1922 | .vendor_id = 0x17aa, | ||
1923 | .product_id = 0x5054, | ||
1924 | .version = 0x4101, | ||
1925 | .expected = SDL_UDEV_DEVICE_HAS_KEYS, | ||
1926 | /* SYN, KEY */ | ||
1927 | .ev = { 0x03 }, | ||
1928 | .keys = { | ||
1929 | /* 0x00 */ ZEROx8, | ||
1930 | /* 0x40 */ ZEROx4, 0x00, 0x00, 0x0e, 0x01, | ||
1931 | /* 0x80 */ 0x00, 0x50, 0x11, 0x51, 0x00, 0x28, 0x00, 0xc0, | ||
1932 | /* 0xc0 */ 0x04, 0x20, 0x10, 0x02, 0x1b, 0x70, 0x01, 0x00, | ||
1933 | /* 0x100 */ ZEROx8, | ||
1934 | /* 0x140 */ ZEROx4, 0x00, 0x00, 0x50, 0x00, | ||
1935 | /* 0x180 */ ZEROx8, | ||
1936 | /* 0x1c0 */ 0x00, 0x00, 0x04, 0x18, ZEROx4, | ||
1937 | /* 0x200 */ ZEROx8, | ||
1938 | /* 0x240 */ 0x40, 0x00, 0x01, 0x00, ZEROx4, | ||
1939 | }, | ||
1940 | }, | ||
1941 | { | ||
1942 | .name = "Thinkpad USB keyboard with Trackpoint - keyboard", | ||
1943 | .eviocgname = "Lite-On Technology Corp. ThinkPad USB Keyboard with TrackPoint", | ||
1944 | .usb_vendor_name = "Lite-On Technology Corp.", | ||
1945 | .usb_product_name = "ThinkPad USB Keyboard with TrackPoint", | ||
1946 | .bus_type = 0x0003, | ||
1947 | .vendor_id = 0x17ef, | ||
1948 | .product_id = 0x6009, | ||
1949 | .expected = SDL_UDEV_DEVICE_HAS_KEYS | SDL_UDEV_DEVICE_KEYBOARD, | ||
1950 | /* SYN, KEY, MSC, LED, REP */ | ||
1951 | .ev = { 0x13, 0x00, 0x12 }, | ||
1952 | .keys = { | ||
1953 | /* 0x00 */ 0xfe, 0xff, 0xff, 0xff, FFx4, | ||
1954 | /* 0x40 */ 0xff, 0xff, 0xef, 0xff, 0xdf, 0xff, 0xbe, 0xfe, | ||
1955 | /* 0x80 */ 0xff, 0x57, 0x40, 0xc1, 0x7a, 0x20, 0x9f, 0xff, | ||
1956 | /* 0xc0 */ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, | ||
1957 | }, | ||
1958 | .hid_report_descriptor_length = sizeof (thinkpad_usb_keyboard_hid_report_descriptor), | ||
1959 | .hid_report_descriptor = &thinkpad_usb_keyboard_hid_report_descriptor[0], | ||
1960 | }, | ||
1961 | { | ||
1962 | .name = "Thinkpad USB keyboard with Trackpoint - Trackpoint", | ||
1963 | .eviocgname = "Lite-On Technology Corp. ThinkPad USB Keyboard with TrackPoint", | ||
1964 | .usb_vendor_name = "Lite-On Technology Corp.", | ||
1965 | .usb_product_name = "ThinkPad USB Keyboard with TrackPoint", | ||
1966 | .bus_type = 0x0003, | ||
1967 | .vendor_id = 0x17ef, | ||
1968 | .product_id = 0x6009, | ||
1969 | .version = 0x0110, | ||
1970 | /* For some reason the special keys like mute and wlan toggle | ||
1971 | * show up here instead of, or in addition to, as part of | ||
1972 | * the keyboard - so both udev and SDL report this as having keys too. */ | ||
1973 | .expected = SDL_UDEV_DEVICE_MOUSE | SDL_UDEV_DEVICE_HAS_KEYS, | ||
1974 | /* SYN, KEY, REL, MSC, LED */ | ||
1975 | .ev = { 0x17, 0x00, 0x02 }, | ||
1976 | /* X, Y */ | ||
1977 | .rel = { 0x03 }, | ||
1978 | .keys = { | ||
1979 | /* 0x00 */ ZEROx8, | ||
1980 | /* 0x40 */ ZEROx4, 0x00, 0x00, 0x1e, 0x00, | ||
1981 | /* 0x80 */ 0x00, 0xcc, 0x11, 0x01, 0x78, 0x40, 0x00, 0xc0, | ||
1982 | /* 0xc0 */ 0x00, 0x20, 0x10, 0x00, 0x0b, 0x50, 0x00, 0x00, | ||
1983 | /* Mouse buttons: left, right, middle, "task" */ | ||
1984 | /* 0x100 */ 0x00, 0x00, 0x87, 0x68, ZEROx4, | ||
1985 | /* 0x140 */ ZEROx4, 0x00, 0x00, 0x10, 0x00, | ||
1986 | /* 0x180 */ ZEROx4, 0x00, 0x00, 0x40, 0x00, | ||
1987 | }, | ||
1988 | .hid_report_descriptor_length = sizeof (thinkpad_usb_trackpoint_hid_report_descriptor), | ||
1989 | .hid_report_descriptor = &thinkpad_usb_trackpoint_hid_report_descriptor[0], | ||
1990 | }, | ||
1991 | { /* https://github.com/ValveSoftware/Proton/issues/5126 */ | ||
1992 | .name = "Smarty Co. VRS DirectForce Pro Pedals", | ||
1993 | .bus_type = 0x0003, | ||
1994 | .vendor_id = 0x0483, /* STMicroelectronics */ | ||
1995 | .product_id = 0xa3be, /* VRS DirectForce Pro Pedals */ | ||
1996 | .version = 0x0111, | ||
1997 | /* TODO: Ideally we would identify this as a joystick, but there | ||
1998 | * isn't currently enough information to do that without a table | ||
1999 | * of known devices. */ | ||
2000 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
2001 | .todo = "https://github.com/ValveSoftware/Proton/issues/5126", | ||
2002 | /* SYN, ABS */ | ||
2003 | .ev = { 0x09 }, | ||
2004 | /* X, Y, Z */ | ||
2005 | .abs = { 0x07 }, | ||
2006 | .hid_report_descriptor_length = sizeof (vrs_pedals_hid_report_descriptor), | ||
2007 | .hid_report_descriptor = &vrs_pedals_hid_report_descriptor[0], | ||
2008 | }, | ||
2009 | { /* https://github.com/ValveSoftware/Proton/issues/5126 */ | ||
2010 | .name = "Heusinkveld Heusinkveld Sim Pedals Ultimate", | ||
2011 | .bus_type = 0x0003, | ||
2012 | .vendor_id = 0x30b7, /* Heusinkveld Engineering */ | ||
2013 | .product_id = 0x1003, /* Heusinkveld Sim Pedals Ultimate */ | ||
2014 | .version = 0x0000, | ||
2015 | /* TODO: Ideally we would identify this as a joystick, but there | ||
2016 | * isn't currently enough information to do that without a table | ||
2017 | * of known devices. */ | ||
2018 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
2019 | .todo = "https://github.com/ValveSoftware/Proton/issues/5126", | ||
2020 | /* SYN, ABS */ | ||
2021 | .ev = { 0x09 }, | ||
2022 | /* RX, RY, RZ */ | ||
2023 | .abs = { 0x38 }, | ||
2024 | .hid_report_descriptor_length = sizeof (heusinkveld_pedals_hid_report_descriptor), | ||
2025 | .hid_report_descriptor = &heusinkveld_pedals_hid_report_descriptor[0], | ||
2026 | }, | ||
2027 | { /* https://github.com/ValveSoftware/Proton/issues/5126 */ | ||
2028 | .name = "Vitaly [mega_mozg] Naidentsev ODDOR-handbrake", | ||
2029 | .bus_type = 0x0003, | ||
2030 | .vendor_id = 0x0000, | ||
2031 | .product_id = 0x0000, | ||
2032 | .version = 0x0001, | ||
2033 | /* TODO: Ideally we would identify this as a joystick by it having | ||
2034 | * the joystick-specific THROTTLE axis and TRIGGER/THUMB buttons */ | ||
2035 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
2036 | .todo = "https://github.com/ValveSoftware/Proton/issues/5126", | ||
2037 | /* SYN, KEY, ABS, MSC */ | ||
2038 | .ev = { 0x1b }, | ||
2039 | /* THROTTLE only */ | ||
2040 | .abs = { 0x40 }, | ||
2041 | .keys = { | ||
2042 | /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8, | ||
2043 | /* TRIGGER = 0x120, THUMB = 0x121 */ | ||
2044 | /* 0x100 */ ZEROx4, 0x03, 0x00, 0x00, 0x00, | ||
2045 | }, | ||
2046 | }, | ||
2047 | { /* https://github.com/ValveSoftware/Proton/issues/5126 */ | ||
2048 | .name = "Leo Bodnar Logitech® G25 Pedals", | ||
2049 | .bus_type = 0x0003, | ||
2050 | .vendor_id = 0x1dd2, /* Leo Bodnar Electronics Ltd */ | ||
2051 | .product_id = 0x100c, | ||
2052 | .version = 0x0110, | ||
2053 | /* TODO: Ideally we would identify this as a joystick, but there | ||
2054 | * isn't currently enough information to do that without a table | ||
2055 | * of known devices. */ | ||
2056 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
2057 | .todo = "https://github.com/ValveSoftware/Proton/issues/5126", | ||
2058 | /* SYN, ABS */ | ||
2059 | .ev = { 0x09 }, | ||
2060 | /* RX, RY, RZ */ | ||
2061 | .abs = { 0x38 }, | ||
2062 | }, | ||
2063 | { /* https://github.com/ValveSoftware/Proton/issues/5126 */ | ||
2064 | .name = "FANATEC ClubSport USB Handbrake", | ||
2065 | .bus_type = 0x0003, | ||
2066 | .vendor_id = 0x0eb7, | ||
2067 | .product_id = 0x1a93, | ||
2068 | .version = 0x0111, | ||
2069 | /* TODO: Ideally we would identify this as a joystick, but there | ||
2070 | * isn't currently enough information to do that without a table | ||
2071 | * of known devices. */ | ||
2072 | .expected = SDL_UDEV_DEVICE_JOYSTICK, | ||
2073 | .todo = "https://github.com/ValveSoftware/Proton/issues/5126", | ||
2074 | /* SYN, ABS */ | ||
2075 | .ev = { 0x09 }, | ||
2076 | /* X only */ | ||
2077 | .abs = { 0x01 }, | ||
2078 | .hid_report_descriptor_length = sizeof (fanatec_handbrake_hid_report_descriptor), | ||
2079 | .hid_report_descriptor = &fanatec_handbrake_hid_report_descriptor[0], | ||
2080 | }, | ||
2081 | { /* Artificial test data, not a real device */ | ||
2082 | .name = "Fake accelerometer with fewer than usual axes reported", | ||
2083 | .expected = SDL_UDEV_DEVICE_ACCELEROMETER, | ||
2084 | /* SYN, ABS */ | ||
2085 | .ev = { 0x09 }, | ||
2086 | /* X only */ | ||
2087 | .abs = { 0x01 }, | ||
2088 | /* ACCELEROMETER */ | ||
2089 | .props = { 0x40 }, | ||
2090 | }, | ||
2091 | { /* Artificial test data, not a real device */ | ||
2092 | .name = "Fake pointing stick with no buttons", | ||
2093 | .expected = SDL_UDEV_DEVICE_MOUSE, | ||
2094 | /* SYN, REL */ | ||
2095 | .ev = { 0x05 }, | ||
2096 | /* X,Y */ | ||
2097 | .rel = { 0x03 }, | ||
2098 | /* POINTER, POINTING_STICK */ | ||
2099 | .props = { 0x21 }, | ||
2100 | }, | ||
2101 | { /* Artificial test data, not a real device */ | ||
2102 | .name = "Fake buttonpad", | ||
2103 | .expected = SDL_UDEV_DEVICE_TOUCHPAD, | ||
2104 | /* SYN, ABS */ | ||
2105 | .ev = { 0x09 }, | ||
2106 | /* X,Y */ | ||
2107 | .abs = { 0x03 }, | ||
2108 | /* POINTER, BUTTONPAD */ | ||
2109 | .props = { 0x05 }, | ||
2110 | }, | ||
2111 | { | ||
2112 | .name = "No information", | ||
2113 | .expected = SDL_UDEV_DEVICE_UNKNOWN, | ||
2114 | } | ||
2115 | }; | ||
2116 | /* *INDENT-ON* */ /* clang-format on */ | ||
2117 | |||
2118 | /* The Linux kernel provides capability info in EVIOCGBIT and in /sys | ||
2119 | * as an array of unsigned long in native byte order, rather than an array | ||
2120 | * of bytes, an array of native-endian 32-bit words or an array of | ||
2121 | * native-endian 64-bit words like you might have reasonably expected. | ||
2122 | * The order of words in the array is always lowest-valued first: for | ||
2123 | * instance, the first unsigned long in abs[] contains the bit representing | ||
2124 | * absolute axis 0 (ABS_X). | ||
2125 | * | ||
2126 | * The constant arrays above provide test data in little-endian, because | ||
2127 | * that's the easiest representation for hard-coding into a test like this. | ||
2128 | * On a big-endian platform we need to byteswap it, one unsigned long at a | ||
2129 | * time, to match what the kernel would produce. This requires us to choose | ||
2130 | * an appropriate byteswapping function for the architecture's word size. */ | ||
2131 | SDL_COMPILE_TIME_ASSERT(sizeof_long, sizeof(unsigned long) == 4 || sizeof(unsigned long) == 8); | ||
2132 | #define SwapLongLE(X) \ | ||
2133 | ((sizeof(unsigned long) == 4) ? SDL_Swap32LE(X) : SDL_Swap64LE(X)) | ||
2134 | |||
2135 | static int | ||
2136 | run_test(void) | ||
2137 | { | ||
2138 | int success = 1; | ||
2139 | size_t i; | ||
2140 | |||
2141 | for (i = 0; i < SDL_arraysize(guess_tests); i++) { | ||
2142 | const GuessTest *t = &guess_tests[i]; | ||
2143 | size_t j; | ||
2144 | int actual; | ||
2145 | struct | ||
2146 | { | ||
2147 | unsigned long props[NBITS(INPUT_PROP_MAX)]; | ||
2148 | unsigned long ev[NBITS(EV_MAX)]; | ||
2149 | unsigned long abs[NBITS(ABS_MAX)]; | ||
2150 | unsigned long keys[NBITS(KEY_MAX)]; | ||
2151 | unsigned long rel[NBITS(REL_MAX)]; | ||
2152 | } caps; | ||
2153 | |||
2154 | printf("%s...\n", t->name); | ||
2155 | |||
2156 | SDL_memset(&caps, '\0', sizeof(caps)); | ||
2157 | SDL_memcpy(caps.props, t->props, sizeof(t->props)); | ||
2158 | SDL_memcpy(caps.ev, t->ev, sizeof(t->ev)); | ||
2159 | SDL_memcpy(caps.keys, t->keys, sizeof(t->keys)); | ||
2160 | SDL_memcpy(caps.abs, t->abs, sizeof(t->abs)); | ||
2161 | SDL_memcpy(caps.rel, t->rel, sizeof(t->rel)); | ||
2162 | |||
2163 | for (j = 0; j < SDL_arraysize(caps.props); j++) { | ||
2164 | caps.props[j] = SwapLongLE(caps.props[j]); | ||
2165 | } | ||
2166 | |||
2167 | for (j = 0; j < SDL_arraysize(caps.ev); j++) { | ||
2168 | caps.ev[j] = SwapLongLE(caps.ev[j]); | ||
2169 | } | ||
2170 | |||
2171 | for (j = 0; j < SDL_arraysize(caps.keys); j++) { | ||
2172 | caps.keys[j] = SwapLongLE(caps.keys[j]); | ||
2173 | } | ||
2174 | |||
2175 | for (j = 0; j < SDL_arraysize(caps.abs); j++) { | ||
2176 | caps.abs[j] = SwapLongLE(caps.abs[j]); | ||
2177 | } | ||
2178 | |||
2179 | for (j = 0; j < SDL_arraysize(caps.rel); j++) { | ||
2180 | caps.rel[j] = SwapLongLE(caps.rel[j]); | ||
2181 | } | ||
2182 | |||
2183 | actual = SDL_EVDEV_GuessDeviceClass(caps.props, caps.ev, caps.abs, | ||
2184 | caps.keys, caps.rel); | ||
2185 | |||
2186 | if (actual == t->expected) { | ||
2187 | printf("\tOK\n"); | ||
2188 | } else { | ||
2189 | printf("\tExpected 0x%08x\n", t->expected); | ||
2190 | |||
2191 | for (j = 0; device_classes[j].code != 0; j++) { | ||
2192 | if (t->expected & device_classes[j].code) { | ||
2193 | printf("\t\t%s\n", device_classes[j].name); | ||
2194 | } | ||
2195 | } | ||
2196 | |||
2197 | printf("\tGot 0x%08x\n", actual); | ||
2198 | |||
2199 | for (j = 0; device_classes[j].code != 0; j++) { | ||
2200 | if (actual & device_classes[j].code) { | ||
2201 | printf("\t\t%s\n", device_classes[j].name); | ||
2202 | } | ||
2203 | } | ||
2204 | |||
2205 | if (t->todo) { | ||
2206 | printf("\tKnown issue, ignoring: %s\n", t->todo); | ||
2207 | } else { | ||
2208 | printf("\tFailed\n"); | ||
2209 | success = 0; | ||
2210 | } | ||
2211 | } | ||
2212 | } | ||
2213 | |||
2214 | return success; | ||
2215 | } | ||
2216 | |||
2217 | #else /* !(HAVE_LIBUDEV_H || defined(SDL_JOYSTICK_LINUX)) */ | ||
2218 | |||
2219 | static int | ||
2220 | run_test(void) | ||
2221 | { | ||
2222 | printf("SDL compiled without evdev capability check.\n"); | ||
2223 | return 1; | ||
2224 | } | ||
2225 | |||
2226 | #endif | ||
2227 | |||
2228 | int main(int argc, char *argv[]) | ||
2229 | { | ||
2230 | int result; | ||
2231 | SDLTest_CommonState *state; | ||
2232 | |||
2233 | /* Initialize test framework */ | ||
2234 | state = SDLTest_CommonCreateState(argv, 0); | ||
2235 | if (!state) { | ||
2236 | return 1; | ||
2237 | } | ||
2238 | |||
2239 | /* Parse commandline */ | ||
2240 | if (!SDLTest_CommonDefaultArgs(state, argc, argv)) { | ||
2241 | return 1; | ||
2242 | } | ||
2243 | |||
2244 | result = run_test() ? 0 : 1; | ||
2245 | |||
2246 | SDL_Quit(); | ||
2247 | SDLTest_CommonDestroyState(state); | ||
2248 | return result; | ||
2249 | } | ||