7575#ifndef BTN_DPAD_RIGHT
7676#define BTN_DPAD_RIGHT 0x223
7777#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
7890
7991#ifndef BTN_TRIGGER_HAPPY
8092#define BTN_TRIGGER_HAPPY 0x2c0
@@ -151,6 +163,7 @@ typedef struct SDL_joylist_item
151163 SDL_JoystickID device_instance ;
152164 char * path ; // "/dev/input/event2" or whatever
153165 char * name ; // "SideWinder 3D Pro" or whatever
166+ char * driver ; // "xpad" or whatever
154167 SDL_GUID guid ;
155168 dev_t devnum ;
156169 int steam_virtual_gamepad_slot ;
@@ -274,54 +287,54 @@ static bool GuessIsSensor(int fd)
274287 return false;
275288}
276289
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 )
278291{
279292 struct input_id inpid ;
280- char * name ;
293+ char * name = NULL ;
294+ char * driver = NULL ;
281295 char product_string [128 ];
282296 int class = 0 ;
283297
284298 SDL_zero (inpid );
285299#ifdef SDL_USE_LIBUDEV
286300 // 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 ) &&
288302 !(class & SDL_UDEV_DEVICE_JOYSTICK )) {
289- return false ;
303+ goto error ;
290304 }
291305#endif
292306
293307 if (fd && * fd < 0 ) {
294308 * fd = open (path , O_RDONLY | O_CLOEXEC , 0 );
295309 }
296310 if (!fd || * fd < 0 ) {
297- return false ;
311+ goto error ;
298312 }
299313
300314 if (ioctl (* fd , JSIOCGNAME (sizeof (product_string )), product_string ) <= 0 ) {
301315 // When udev enumeration or classification, we only got joysticks here, so no need to test
302316 if (enumeration_method != ENUMERATION_LIBUDEV && !class && !GuessIsJoystick (* fd )) {
303- return false ;
317+ goto error ;
304318 }
305319
306320 // Could have vendor and product already from udev, but should agree with evdev
307321 if (ioctl (* fd , EVIOCGID , & inpid ) < 0 ) {
308- return false ;
322+ goto error ;
309323 }
310324
311325 if (ioctl (* fd , EVIOCGNAME (sizeof (product_string )), product_string ) < 0 ) {
312- return false ;
326+ goto error ;
313327 }
314328 }
315329
316330 name = SDL_CreateJoystickName (inpid .vendor , inpid .product , NULL , product_string );
317331 if (!name ) {
318- return false ;
332+ goto error ;
319333 }
320334
321335 if (!IsVirtualJoystick (inpid .vendor , inpid .product , inpid .version , name ) &&
322336 SDL_JoystickHandledByAnotherDriver (& SDL_LINUX_JoystickDriver , inpid .vendor , inpid .product , inpid .version , name )) {
323- SDL_free (name );
324- return false;
337+ goto error ;
325338 }
326339
327340 FixupDeviceInfoForMapping (* fd , & inpid );
@@ -331,14 +344,23 @@ static bool IsJoystick(const char *path, int *fd, char **name_return, Uint16 *ve
331344#endif
332345
333346 if (SDL_ShouldIgnoreJoystick (inpid .vendor , inpid .product , inpid .version , name )) {
334- SDL_free (name );
335- return false;
347+ goto error ;
336348 }
337349 * name_return = name ;
350+ * driver_return = driver ;
338351 * vendor_return = inpid .vendor ;
339352 * product_return = inpid .product ;
340353 * guid = SDL_CreateJoystickGUID (inpid .bustype , inpid .vendor , inpid .product , inpid .version , NULL , product_string , 0 , 0 );
341354 return true;
355+
356+ error :
357+ if (driver ) {
358+ SDL_free (driver );
359+ }
360+ if (name ) {
361+ SDL_free (name );
362+ }
363+ return false;
342364}
343365
344366static bool IsSensor (const char * path , int * fd )
@@ -349,7 +371,7 @@ static bool IsSensor(const char *path, int *fd)
349371 SDL_zero (inpid );
350372#ifdef SDL_USE_LIBUDEV
351373 // 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 ) &&
353375 !(class & SDL_UDEV_DEVICE_ACCELEROMETER )) {
354376 return false;
355377 }
@@ -422,6 +444,7 @@ static void FreeJoylistItem(SDL_joylist_item *item)
422444 SDL_free (item -> mapping );
423445 SDL_free (item -> path );
424446 SDL_free (item -> name );
447+ SDL_free (item -> driver );
425448 SDL_free (item );
426449}
427450
@@ -436,6 +459,7 @@ static void MaybeAddDevice(const char *path)
436459 struct stat sb ;
437460 int fd = -1 ;
438461 char * name = NULL ;
462+ char * driver = NULL ;
439463 Uint16 vendor , product ;
440464 SDL_GUID guid ;
441465 SDL_joylist_item * item ;
@@ -473,7 +497,7 @@ static void MaybeAddDevice(const char *path)
473497 SDL_Log ("Checking %s" , path );
474498#endif
475499
476- if (IsJoystick (path , & fd , & name , & vendor , & product , & guid )) {
500+ if (IsJoystick (path , & fd , & name , & vendor , & product , & guid , & driver )) {
477501#ifdef DEBUG_INPUT_EVENTS
478502 SDL_Log ("found joystick: %s" , path );
479503#endif
@@ -488,6 +512,7 @@ static void MaybeAddDevice(const char *path)
488512 item -> path = SDL_strdup (path );
489513 item -> name = name ;
490514 item -> guid = guid ;
515+ item -> driver = driver ;
491516
492517 if (vendor == USB_VENDOR_VALVE &&
493518 product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD ) {
@@ -861,7 +886,7 @@ static void LINUX_ScanSteamVirtualGamepads(void)
861886 // Opening input devices can generate synchronous device I/O, so avoid it if we can
862887 class = 0 ;
863888 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 ) &&
865890 (inpid .vendor != USB_VENDOR_VALVE || inpid .product != USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD )) {
866891 free (entries [i ]); // This should NOT be SDL_free()
867892 continue ;
@@ -2244,6 +2269,12 @@ static bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping
22442269 MAPPED_DPAD_LEFT = 0x4 ,
22452270 MAPPED_DPAD_RIGHT = 0x8 ,
22462271 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 ,
22472278 };
22482279 unsigned int mapped ;
22492280 bool result = false;
@@ -2609,6 +2640,27 @@ static bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping
26092640 SDL_Log ("Mapped DPUP+DOWN to axis %d (ABS_HAT0Y)" , out -> dpup .target );
26102641 SDL_Log ("Mapped DPLEFT+RIGHT to axis %d (ABS_HAT0X)" , out -> dpleft .target );
26112642#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+ }
26122664 }
26132665 }
26142666
@@ -2653,8 +2705,44 @@ static bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping
26532705#endif
26542706 }
26552707
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 ) {
26572744 // The Xbox Elite controllers have the paddles as BTN_TRIGGER_HAPPY5 - BTN_TRIGGER_HAPPY8
2745+ // in older drivers
26582746 if (joystick -> hwdata -> has_key [BTN_TRIGGER_HAPPY5 ] &&
26592747 joystick -> hwdata -> has_key [BTN_TRIGGER_HAPPY6 ] &&
26602748 joystick -> hwdata -> has_key [BTN_TRIGGER_HAPPY7 ] &&
@@ -2667,22 +2755,23 @@ static bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping
26672755 out -> right_paddle2 .target = joystick -> hwdata -> key_map [BTN_TRIGGER_HAPPY6 ];
26682756 out -> left_paddle2 .kind = EMappingKind_Button ;
26692757 out -> left_paddle2 .target = joystick -> hwdata -> key_map [BTN_TRIGGER_HAPPY8 ];
2758+ mapped = MAPPED_PADDLE_ALL ;
26702759#ifdef DEBUG_GAMEPAD_MAPPING
26712760 SDL_Log ("Mapped RIGHT_PADDLE1 to button %d (BTN_TRIGGER_HAPPY5)" , out -> right_paddle1 .target );
26722761 SDL_Log ("Mapped LEFT_PADDLE1 to button %d (BTN_TRIGGER_HAPPY7)" , out -> left_paddle1 .target );
26732762 SDL_Log ("Mapped RIGHT_PADDLE2 to button %d (BTN_TRIGGER_HAPPY6)" , out -> right_paddle2 .target );
26742763 SDL_Log ("Mapped LEFT_PADDLE2 to button %d (BTN_TRIGGER_HAPPY8)" , out -> left_paddle2 .target );
26752764#endif
26762765 }
2766+ }
26772767
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 ];
26822772#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 );
26842774#endif
2685- }
26862775 }
26872776
26882777 // Cache the mapping for later
0 commit comments