75
75
#ifndef BTN_DPAD_RIGHT
76
76
#define BTN_DPAD_RIGHT 0x223
77
77
#endif
78
+ #ifndef BTN_GRIPL
79
+ #define BTN_GRIPL 0x224
80
+ #endif
81
+ #ifndef BTN_GRIPR
82
+ #define BTN_GRIPR 0x225
83
+ #endif
84
+ #ifndef BTN_GRIPL2
85
+ #define BTN_GRIPL2 0x226
86
+ #endif
87
+ #ifndef BTN_GRIPR2
88
+ #define BTN_GRIPR2 0x227
89
+ #endif
78
90
79
91
#ifndef BTN_TRIGGER_HAPPY
80
92
#define BTN_TRIGGER_HAPPY 0x2c0
@@ -151,6 +163,7 @@ typedef struct SDL_joylist_item
151
163
SDL_JoystickID device_instance ;
152
164
char * path ; // "/dev/input/event2" or whatever
153
165
char * name ; // "SideWinder 3D Pro" or whatever
166
+ char * driver ; // "xpad" or whatever
154
167
SDL_GUID guid ;
155
168
dev_t devnum ;
156
169
int steam_virtual_gamepad_slot ;
@@ -274,54 +287,54 @@ static bool GuessIsSensor(int fd)
274
287
return false;
275
288
}
276
289
277
- static bool IsJoystick (const char * path , int * fd , char * * name_return , Uint16 * vendor_return , Uint16 * product_return , SDL_GUID * guid )
290
+ static bool IsJoystick (const char * path , int * fd , char * * name_return , Uint16 * vendor_return , Uint16 * product_return , SDL_GUID * guid , char * * driver_return )
278
291
{
279
292
struct input_id inpid ;
280
- char * name ;
293
+ char * name = NULL ;
294
+ char * driver = NULL ;
281
295
char product_string [128 ];
282
296
int class = 0 ;
283
297
284
298
SDL_zero (inpid );
285
299
#ifdef SDL_USE_LIBUDEV
286
300
// Opening input devices can generate synchronous device I/O, so avoid it if we can
287
- if (SDL_UDEV_GetProductInfo (path , & inpid . vendor , & inpid . product , & inpid . version , & class ) &&
301
+ if (SDL_UDEV_GetProductInfo (path , & inpid , & class , & driver ) &&
288
302
!(class & SDL_UDEV_DEVICE_JOYSTICK )) {
289
- return false ;
303
+ goto error ;
290
304
}
291
305
#endif
292
306
293
307
if (fd && * fd < 0 ) {
294
308
* fd = open (path , O_RDONLY | O_CLOEXEC , 0 );
295
309
}
296
310
if (!fd || * fd < 0 ) {
297
- return false ;
311
+ goto error ;
298
312
}
299
313
300
314
if (ioctl (* fd , JSIOCGNAME (sizeof (product_string )), product_string ) <= 0 ) {
301
315
// When udev enumeration or classification, we only got joysticks here, so no need to test
302
316
if (enumeration_method != ENUMERATION_LIBUDEV && !class && !GuessIsJoystick (* fd )) {
303
- return false ;
317
+ goto error ;
304
318
}
305
319
306
320
// Could have vendor and product already from udev, but should agree with evdev
307
321
if (ioctl (* fd , EVIOCGID , & inpid ) < 0 ) {
308
- return false ;
322
+ goto error ;
309
323
}
310
324
311
325
if (ioctl (* fd , EVIOCGNAME (sizeof (product_string )), product_string ) < 0 ) {
312
- return false ;
326
+ goto error ;
313
327
}
314
328
}
315
329
316
330
name = SDL_CreateJoystickName (inpid .vendor , inpid .product , NULL , product_string );
317
331
if (!name ) {
318
- return false ;
332
+ goto error ;
319
333
}
320
334
321
335
if (!IsVirtualJoystick (inpid .vendor , inpid .product , inpid .version , name ) &&
322
336
SDL_JoystickHandledByAnotherDriver (& SDL_LINUX_JoystickDriver , inpid .vendor , inpid .product , inpid .version , name )) {
323
- SDL_free (name );
324
- return false;
337
+ goto error ;
325
338
}
326
339
327
340
FixupDeviceInfoForMapping (* fd , & inpid );
@@ -331,14 +344,23 @@ static bool IsJoystick(const char *path, int *fd, char **name_return, Uint16 *ve
331
344
#endif
332
345
333
346
if (SDL_ShouldIgnoreJoystick (inpid .vendor , inpid .product , inpid .version , name )) {
334
- SDL_free (name );
335
- return false;
347
+ goto error ;
336
348
}
337
349
* name_return = name ;
350
+ * driver_return = driver ;
338
351
* vendor_return = inpid .vendor ;
339
352
* product_return = inpid .product ;
340
353
* guid = SDL_CreateJoystickGUID (inpid .bustype , inpid .vendor , inpid .product , inpid .version , NULL , product_string , 0 , 0 );
341
354
return true;
355
+
356
+ error :
357
+ if (driver ) {
358
+ SDL_free (driver );
359
+ }
360
+ if (name ) {
361
+ SDL_free (name );
362
+ }
363
+ return false;
342
364
}
343
365
344
366
static bool IsSensor (const char * path , int * fd )
@@ -349,7 +371,7 @@ static bool IsSensor(const char *path, int *fd)
349
371
SDL_zero (inpid );
350
372
#ifdef SDL_USE_LIBUDEV
351
373
// Opening input devices can generate synchronous device I/O, so avoid it if we can
352
- if (SDL_UDEV_GetProductInfo (path , & inpid . vendor , & inpid . product , & inpid . version , & class ) &&
374
+ if (SDL_UDEV_GetProductInfo (path , & inpid , & class , NULL ) &&
353
375
!(class & SDL_UDEV_DEVICE_ACCELEROMETER )) {
354
376
return false;
355
377
}
@@ -422,6 +444,9 @@ static void FreeJoylistItem(SDL_joylist_item *item)
422
444
SDL_free (item -> mapping );
423
445
SDL_free (item -> path );
424
446
SDL_free (item -> name );
447
+ if (item -> driver ) {
448
+ SDL_free (item -> driver );
449
+ }
425
450
SDL_free (item );
426
451
}
427
452
@@ -436,6 +461,7 @@ static void MaybeAddDevice(const char *path)
436
461
struct stat sb ;
437
462
int fd = -1 ;
438
463
char * name = NULL ;
464
+ char * driver = NULL ;
439
465
Uint16 vendor , product ;
440
466
SDL_GUID guid ;
441
467
SDL_joylist_item * item ;
@@ -473,7 +499,7 @@ static void MaybeAddDevice(const char *path)
473
499
SDL_Log ("Checking %s" , path );
474
500
#endif
475
501
476
- if (IsJoystick (path , & fd , & name , & vendor , & product , & guid )) {
502
+ if (IsJoystick (path , & fd , & name , & vendor , & product , & guid , & driver )) {
477
503
#ifdef DEBUG_INPUT_EVENTS
478
504
SDL_Log ("found joystick: %s" , path );
479
505
#endif
@@ -488,6 +514,7 @@ static void MaybeAddDevice(const char *path)
488
514
item -> path = SDL_strdup (path );
489
515
item -> name = name ;
490
516
item -> guid = guid ;
517
+ item -> driver = driver ;
491
518
492
519
if (vendor == USB_VENDOR_VALVE &&
493
520
product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD ) {
@@ -861,7 +888,7 @@ static void LINUX_ScanSteamVirtualGamepads(void)
861
888
// Opening input devices can generate synchronous device I/O, so avoid it if we can
862
889
class = 0 ;
863
890
SDL_zero (inpid );
864
- if (SDL_UDEV_GetProductInfo (path , & inpid . vendor , & inpid . product , & inpid . version , & class ) &&
891
+ if (SDL_UDEV_GetProductInfo (path , & inpid , & class , NULL ) &&
865
892
(inpid .vendor != USB_VENDOR_VALVE || inpid .product != USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD )) {
866
893
free (entries [i ]); // This should NOT be SDL_free()
867
894
continue ;
@@ -2244,6 +2271,12 @@ static bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping
2244
2271
MAPPED_DPAD_LEFT = 0x4 ,
2245
2272
MAPPED_DPAD_RIGHT = 0x8 ,
2246
2273
MAPPED_DPAD_ALL = 0xF ,
2274
+
2275
+ MAPPED_LEFT_PADDLE1 = 0x1 ,
2276
+ MAPPED_RIGHT_PADDLE1 = 0x2 ,
2277
+ MAPPED_LEFT_PADDLE2 = 0x4 ,
2278
+ MAPPED_RIGHT_PADDLE2 = 0x8 ,
2279
+ MAPPED_PADDLE_ALL = 0xF ,
2247
2280
};
2248
2281
unsigned int mapped ;
2249
2282
bool result = false;
@@ -2609,6 +2642,27 @@ static bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping
2609
2642
SDL_Log ("Mapped DPUP+DOWN to axis %d (ABS_HAT0Y)" , out -> dpup .target );
2610
2643
SDL_Log ("Mapped DPLEFT+RIGHT to axis %d (ABS_HAT0X)" , out -> dpleft .target );
2611
2644
#endif
2645
+ } else if (item -> driver && SDL_strcmp (item -> driver , "xpad" ) == 0 ) {
2646
+ // xpad will sometimes map the D-Pad as BTN_TRIGGER_HAPPY1 - BTN_TRIGGER_HAPPY4
2647
+ if (joystick -> hwdata -> has_key [BTN_TRIGGER_HAPPY1 ] &&
2648
+ joystick -> hwdata -> has_key [BTN_TRIGGER_HAPPY2 ] &&
2649
+ joystick -> hwdata -> has_key [BTN_TRIGGER_HAPPY3 ] &&
2650
+ joystick -> hwdata -> has_key [BTN_TRIGGER_HAPPY4 ]) {
2651
+ out -> dpleft .kind = EMappingKind_Button ;
2652
+ out -> dpright .kind = EMappingKind_Button ;
2653
+ out -> dpup .kind = EMappingKind_Button ;
2654
+ out -> dpdown .kind = EMappingKind_Button ;
2655
+ out -> dpleft .target = joystick -> hwdata -> key_map [BTN_TRIGGER_HAPPY1 ];
2656
+ out -> dpright .target = joystick -> hwdata -> key_map [BTN_TRIGGER_HAPPY2 ];
2657
+ out -> dpup .target = joystick -> hwdata -> key_map [BTN_TRIGGER_HAPPY3 ];
2658
+ out -> dpdown .target = joystick -> hwdata -> key_map [BTN_TRIGGER_HAPPY4 ];
2659
+ #ifdef DEBUG_GAMEPAD_MAPPING
2660
+ SDL_Log ("Mapped DPLEFT to button %d (BTN_TRIGGER_HAPPY1)" , out -> dpleft .target );
2661
+ SDL_Log ("Mapped DPRIGHT to button %d (BTN_TRIGGER_HAPPY2)" , out -> dpright .target );
2662
+ SDL_Log ("Mapped DPUP to button %d (BTN_TRIGGER_HAPPY3)" , out -> dpup .target );
2663
+ SDL_Log ("Mapped DPDOWN to button %d (BTN_TRIGGER_HAPPY4)" , out -> dpdown .target );
2664
+ #endif
2665
+ }
2612
2666
}
2613
2667
}
2614
2668
@@ -2653,8 +2707,44 @@ static bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping
2653
2707
#endif
2654
2708
}
2655
2709
2656
- if (SDL_GetJoystickVendor (joystick ) == USB_VENDOR_MICROSOFT ) {
2710
+ mapped = 0 ;
2711
+
2712
+ if (joystick -> hwdata -> has_key [BTN_GRIPR ]) {
2713
+ out -> right_paddle1 .kind = EMappingKind_Button ;
2714
+ out -> right_paddle1 .target = joystick -> hwdata -> key_map [BTN_GRIPR ];
2715
+ mapped |= MAPPED_RIGHT_PADDLE1 ;
2716
+ #ifdef DEBUG_GAMEPAD_MAPPING
2717
+ SDL_Log ("Mapped RIGHT_PADDLE1 to button %d (BTN_GRIPR)" , out -> right_paddle1 .target );
2718
+ #endif
2719
+ }
2720
+ if (joystick -> hwdata -> has_key [BTN_GRIPL ]) {
2721
+ out -> left_paddle1 .kind = EMappingKind_Button ;
2722
+ out -> left_paddle1 .target = joystick -> hwdata -> key_map [BTN_GRIPL ];
2723
+ mapped |= MAPPED_LEFT_PADDLE1 ;
2724
+ #ifdef DEBUG_GAMEPAD_MAPPING
2725
+ SDL_Log ("Mapped LEFT_PADDLE1 to button %d (BTN_GRIPL)" , out -> left_paddle1 .target );
2726
+ #endif
2727
+ }
2728
+ if (joystick -> hwdata -> has_key [BTN_GRIPR2 ]) {
2729
+ out -> right_paddle2 .kind = EMappingKind_Button ;
2730
+ out -> right_paddle2 .target = joystick -> hwdata -> key_map [BTN_GRIPR2 ];
2731
+ mapped |= MAPPED_RIGHT_PADDLE2 ;
2732
+ #ifdef DEBUG_GAMEPAD_MAPPING
2733
+ SDL_Log ("Mapped RIGHT_PADDLE2 to button %d (BTN_GRIPR)" , out -> right_paddle2 .target );
2734
+ #endif
2735
+ }
2736
+ if (joystick -> hwdata -> has_key [BTN_GRIPL2 ]) {
2737
+ out -> left_paddle2 .kind = EMappingKind_Button ;
2738
+ out -> left_paddle2 .target = joystick -> hwdata -> key_map [BTN_GRIPL2 ];
2739
+ mapped |= MAPPED_LEFT_PADDLE2 ;
2740
+ #ifdef DEBUG_GAMEPAD_MAPPING
2741
+ SDL_Log ("Mapped LEFT_PADDLE2 to button %d (BTN_GRIPL2)" , out -> left_paddle2 .target );
2742
+ #endif
2743
+ }
2744
+
2745
+ if (mapped != MAPPED_PADDLE_ALL && SDL_GetJoystickVendor (joystick ) == USB_VENDOR_MICROSOFT ) {
2657
2746
// The Xbox Elite controllers have the paddles as BTN_TRIGGER_HAPPY5 - BTN_TRIGGER_HAPPY8
2747
+ // in older drivers
2658
2748
if (joystick -> hwdata -> has_key [BTN_TRIGGER_HAPPY5 ] &&
2659
2749
joystick -> hwdata -> has_key [BTN_TRIGGER_HAPPY6 ] &&
2660
2750
joystick -> hwdata -> has_key [BTN_TRIGGER_HAPPY7 ] &&
@@ -2667,22 +2757,23 @@ static bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping
2667
2757
out -> right_paddle2 .target = joystick -> hwdata -> key_map [BTN_TRIGGER_HAPPY6 ];
2668
2758
out -> left_paddle2 .kind = EMappingKind_Button ;
2669
2759
out -> left_paddle2 .target = joystick -> hwdata -> key_map [BTN_TRIGGER_HAPPY8 ];
2760
+ mapped = MAPPED_PADDLE_ALL ;
2670
2761
#ifdef DEBUG_GAMEPAD_MAPPING
2671
2762
SDL_Log ("Mapped RIGHT_PADDLE1 to button %d (BTN_TRIGGER_HAPPY5)" , out -> right_paddle1 .target );
2672
2763
SDL_Log ("Mapped LEFT_PADDLE1 to button %d (BTN_TRIGGER_HAPPY7)" , out -> left_paddle1 .target );
2673
2764
SDL_Log ("Mapped RIGHT_PADDLE2 to button %d (BTN_TRIGGER_HAPPY6)" , out -> right_paddle2 .target );
2674
2765
SDL_Log ("Mapped LEFT_PADDLE2 to button %d (BTN_TRIGGER_HAPPY8)" , out -> left_paddle2 .target );
2675
2766
#endif
2676
2767
}
2768
+ }
2677
2769
2678
- // The Xbox Series X controllers have the Share button as KEY_RECORD
2679
- if (joystick -> hwdata -> has_key [KEY_RECORD ]) {
2680
- out -> misc1 .kind = EMappingKind_Button ;
2681
- out -> misc1 .target = joystick -> hwdata -> key_map [KEY_RECORD ];
2770
+ // Xbox Series controllers have the Share button as KEY_RECORD
2771
+ if (joystick -> hwdata -> has_key [KEY_RECORD ]) {
2772
+ out -> misc1 .kind = EMappingKind_Button ;
2773
+ out -> misc1 .target = joystick -> hwdata -> key_map [KEY_RECORD ];
2682
2774
#ifdef DEBUG_GAMEPAD_MAPPING
2683
- SDL_Log ("Mapped MISC1 to button %d (KEY_RECORD)" , out -> misc1 .target );
2775
+ SDL_Log ("Mapped MISC1 to button %d (KEY_RECORD)" , out -> misc1 .target );
2684
2776
#endif
2685
- }
2686
2777
}
2687
2778
2688
2779
// Cache the mapping for later
0 commit comments