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,7 @@ 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
+ SDL_free (item -> driver );
425
448
SDL_free (item );
426
449
}
427
450
@@ -436,6 +459,7 @@ static void MaybeAddDevice(const char *path)
436
459
struct stat sb ;
437
460
int fd = -1 ;
438
461
char * name = NULL ;
462
+ char * driver = NULL ;
439
463
Uint16 vendor , product ;
440
464
SDL_GUID guid ;
441
465
SDL_joylist_item * item ;
@@ -473,7 +497,7 @@ static void MaybeAddDevice(const char *path)
473
497
SDL_Log ("Checking %s" , path );
474
498
#endif
475
499
476
- if (IsJoystick (path , & fd , & name , & vendor , & product , & guid )) {
500
+ if (IsJoystick (path , & fd , & name , & vendor , & product , & guid , & driver )) {
477
501
#ifdef DEBUG_INPUT_EVENTS
478
502
SDL_Log ("found joystick: %s" , path );
479
503
#endif
@@ -488,6 +512,7 @@ static void MaybeAddDevice(const char *path)
488
512
item -> path = SDL_strdup (path );
489
513
item -> name = name ;
490
514
item -> guid = guid ;
515
+ item -> driver = driver ;
491
516
492
517
if (vendor == USB_VENDOR_VALVE &&
493
518
product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD ) {
@@ -861,7 +886,7 @@ static void LINUX_ScanSteamVirtualGamepads(void)
861
886
// Opening input devices can generate synchronous device I/O, so avoid it if we can
862
887
class = 0 ;
863
888
SDL_zero (inpid );
864
- if (SDL_UDEV_GetProductInfo (path , & inpid . vendor , & inpid . product , & inpid . version , & class ) &&
889
+ if (SDL_UDEV_GetProductInfo (path , & inpid , & class , NULL ) &&
865
890
(inpid .vendor != USB_VENDOR_VALVE || inpid .product != USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD )) {
866
891
free (entries [i ]); // This should NOT be SDL_free()
867
892
continue ;
@@ -2244,6 +2269,12 @@ static bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping
2244
2269
MAPPED_DPAD_LEFT = 0x4 ,
2245
2270
MAPPED_DPAD_RIGHT = 0x8 ,
2246
2271
MAPPED_DPAD_ALL = 0xF ,
2272
+
2273
+ MAPPED_LEFT_PADDLE1 = 0x1 ,
2274
+ MAPPED_RIGHT_PADDLE1 = 0x2 ,
2275
+ MAPPED_LEFT_PADDLE2 = 0x4 ,
2276
+ MAPPED_RIGHT_PADDLE2 = 0x8 ,
2277
+ MAPPED_PADDLE_ALL = 0xF ,
2247
2278
};
2248
2279
unsigned int mapped ;
2249
2280
bool result = false;
@@ -2609,6 +2640,27 @@ static bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping
2609
2640
SDL_Log ("Mapped DPUP+DOWN to axis %d (ABS_HAT0Y)" , out -> dpup .target );
2610
2641
SDL_Log ("Mapped DPLEFT+RIGHT to axis %d (ABS_HAT0X)" , out -> dpleft .target );
2611
2642
#endif
2643
+ } else if (item -> driver && SDL_strcmp (item -> driver , "xpad" ) == 0 ) {
2644
+ // xpad will sometimes map the D-Pad as BTN_TRIGGER_HAPPY1 - BTN_TRIGGER_HAPPY4
2645
+ if (joystick -> hwdata -> has_key [BTN_TRIGGER_HAPPY1 ] &&
2646
+ joystick -> hwdata -> has_key [BTN_TRIGGER_HAPPY2 ] &&
2647
+ joystick -> hwdata -> has_key [BTN_TRIGGER_HAPPY3 ] &&
2648
+ joystick -> hwdata -> has_key [BTN_TRIGGER_HAPPY4 ]) {
2649
+ out -> dpleft .kind = EMappingKind_Button ;
2650
+ out -> dpright .kind = EMappingKind_Button ;
2651
+ out -> dpup .kind = EMappingKind_Button ;
2652
+ out -> dpdown .kind = EMappingKind_Button ;
2653
+ out -> dpleft .target = joystick -> hwdata -> key_map [BTN_TRIGGER_HAPPY1 ];
2654
+ out -> dpright .target = joystick -> hwdata -> key_map [BTN_TRIGGER_HAPPY2 ];
2655
+ out -> dpup .target = joystick -> hwdata -> key_map [BTN_TRIGGER_HAPPY3 ];
2656
+ out -> dpdown .target = joystick -> hwdata -> key_map [BTN_TRIGGER_HAPPY4 ];
2657
+ #ifdef DEBUG_GAMEPAD_MAPPING
2658
+ SDL_Log ("Mapped DPLEFT to button %d (BTN_TRIGGER_HAPPY1)" , out -> dpleft .target );
2659
+ SDL_Log ("Mapped DPRIGHT to button %d (BTN_TRIGGER_HAPPY2)" , out -> dpright .target );
2660
+ SDL_Log ("Mapped DPUP to button %d (BTN_TRIGGER_HAPPY3)" , out -> dpup .target );
2661
+ SDL_Log ("Mapped DPDOWN to button %d (BTN_TRIGGER_HAPPY4)" , out -> dpdown .target );
2662
+ #endif
2663
+ }
2612
2664
}
2613
2665
}
2614
2666
@@ -2653,8 +2705,44 @@ static bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping
2653
2705
#endif
2654
2706
}
2655
2707
2656
- if (SDL_GetJoystickVendor (joystick ) == USB_VENDOR_MICROSOFT ) {
2708
+ mapped = 0 ;
2709
+
2710
+ if (joystick -> hwdata -> has_key [BTN_GRIPR ]) {
2711
+ out -> right_paddle1 .kind = EMappingKind_Button ;
2712
+ out -> right_paddle1 .target = joystick -> hwdata -> key_map [BTN_GRIPR ];
2713
+ mapped |= MAPPED_RIGHT_PADDLE1 ;
2714
+ #ifdef DEBUG_GAMEPAD_MAPPING
2715
+ SDL_Log ("Mapped RIGHT_PADDLE1 to button %d (BTN_GRIPR)" , out -> right_paddle1 .target );
2716
+ #endif
2717
+ }
2718
+ if (joystick -> hwdata -> has_key [BTN_GRIPL ]) {
2719
+ out -> left_paddle1 .kind = EMappingKind_Button ;
2720
+ out -> left_paddle1 .target = joystick -> hwdata -> key_map [BTN_GRIPL ];
2721
+ mapped |= MAPPED_LEFT_PADDLE1 ;
2722
+ #ifdef DEBUG_GAMEPAD_MAPPING
2723
+ SDL_Log ("Mapped LEFT_PADDLE1 to button %d (BTN_GRIPL)" , out -> left_paddle1 .target );
2724
+ #endif
2725
+ }
2726
+ if (joystick -> hwdata -> has_key [BTN_GRIPR2 ]) {
2727
+ out -> right_paddle2 .kind = EMappingKind_Button ;
2728
+ out -> right_paddle2 .target = joystick -> hwdata -> key_map [BTN_GRIPR2 ];
2729
+ mapped |= MAPPED_RIGHT_PADDLE2 ;
2730
+ #ifdef DEBUG_GAMEPAD_MAPPING
2731
+ SDL_Log ("Mapped RIGHT_PADDLE2 to button %d (BTN_GRIPR)" , out -> right_paddle2 .target );
2732
+ #endif
2733
+ }
2734
+ if (joystick -> hwdata -> has_key [BTN_GRIPL2 ]) {
2735
+ out -> left_paddle2 .kind = EMappingKind_Button ;
2736
+ out -> left_paddle2 .target = joystick -> hwdata -> key_map [BTN_GRIPL2 ];
2737
+ mapped |= MAPPED_LEFT_PADDLE2 ;
2738
+ #ifdef DEBUG_GAMEPAD_MAPPING
2739
+ SDL_Log ("Mapped LEFT_PADDLE2 to button %d (BTN_GRIPL2)" , out -> left_paddle2 .target );
2740
+ #endif
2741
+ }
2742
+
2743
+ if (mapped != MAPPED_PADDLE_ALL && SDL_GetJoystickVendor (joystick ) == USB_VENDOR_MICROSOFT ) {
2657
2744
// The Xbox Elite controllers have the paddles as BTN_TRIGGER_HAPPY5 - BTN_TRIGGER_HAPPY8
2745
+ // in older drivers
2658
2746
if (joystick -> hwdata -> has_key [BTN_TRIGGER_HAPPY5 ] &&
2659
2747
joystick -> hwdata -> has_key [BTN_TRIGGER_HAPPY6 ] &&
2660
2748
joystick -> hwdata -> has_key [BTN_TRIGGER_HAPPY7 ] &&
@@ -2667,22 +2755,23 @@ static bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping
2667
2755
out -> right_paddle2 .target = joystick -> hwdata -> key_map [BTN_TRIGGER_HAPPY6 ];
2668
2756
out -> left_paddle2 .kind = EMappingKind_Button ;
2669
2757
out -> left_paddle2 .target = joystick -> hwdata -> key_map [BTN_TRIGGER_HAPPY8 ];
2758
+ mapped = MAPPED_PADDLE_ALL ;
2670
2759
#ifdef DEBUG_GAMEPAD_MAPPING
2671
2760
SDL_Log ("Mapped RIGHT_PADDLE1 to button %d (BTN_TRIGGER_HAPPY5)" , out -> right_paddle1 .target );
2672
2761
SDL_Log ("Mapped LEFT_PADDLE1 to button %d (BTN_TRIGGER_HAPPY7)" , out -> left_paddle1 .target );
2673
2762
SDL_Log ("Mapped RIGHT_PADDLE2 to button %d (BTN_TRIGGER_HAPPY6)" , out -> right_paddle2 .target );
2674
2763
SDL_Log ("Mapped LEFT_PADDLE2 to button %d (BTN_TRIGGER_HAPPY8)" , out -> left_paddle2 .target );
2675
2764
#endif
2676
2765
}
2766
+ }
2677
2767
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 ];
2768
+ // Xbox Series controllers have the Share button as KEY_RECORD
2769
+ if (joystick -> hwdata -> has_key [KEY_RECORD ]) {
2770
+ out -> misc1 .kind = EMappingKind_Button ;
2771
+ out -> misc1 .target = joystick -> hwdata -> key_map [KEY_RECORD ];
2682
2772
#ifdef DEBUG_GAMEPAD_MAPPING
2683
- SDL_Log ("Mapped MISC1 to button %d (KEY_RECORD)" , out -> misc1 .target );
2773
+ SDL_Log ("Mapped MISC1 to button %d (KEY_RECORD)" , out -> misc1 .target );
2684
2774
#endif
2685
- }
2686
2775
}
2687
2776
2688
2777
// Cache the mapping for later
0 commit comments