SDL

Форк
0
/
testevdev.c 
2249 строк · 81.1 Кб
1
/*
2
  Copyright (C) 1997-2024 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
#ifndef NO_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
}
2250

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.