mirror of
				https://github.com/libsdl-org/SDL.git
				synced 2025-10-26 12:27:44 +00:00 
			
		
		
		
	Added support for /dev/input/js* on Linux
Added the hint SDL_HINT_LINUX_JOYSTICK_CLASSIC to control whether /dev/input/js* or /dev/input/event* are used as joystick devices Added the hint SDL_HINT_JOYSTICK_DEVICE to allow the user to specify devices t hat will be opened in addition to the normal joystick detection Fixes https://github.com/libsdl-org/SDL/issues/1314 Fixes https://github.com/libsdl-org/SDL/issues/1727 Fixes https://github.com/libsdl-org/SDL/issues/1981 Closes https://github.com/libsdl-org/SDL/pull/4727
This commit is contained in:
		| @@ -5,6 +5,10 @@ This is a list of major changes in SDL's version history. | |||||||
| 2.0.18: | 2.0.18: | ||||||
| --------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | Linux: | ||||||
|  | * Added the hint SDL_HINT_LINUX_JOYSTICK_CLASSIC to control whether /dev/input/js* or /dev/input/event* are used as joystick devices | ||||||
|  | * Added the hint SDL_HINT_JOYSTICK_DEVICE to allow the user to specify devices that will be opened in addition to the normal joystick detection | ||||||
|  |  | ||||||
| Android: | Android: | ||||||
| * Added support for audio output and capture using AAudio on Android 8.1 and newer | * Added support for audio output and capture using AAudio on Android 8.1 and newer | ||||||
|  |  | ||||||
|   | |||||||
| @@ -816,6 +816,24 @@ extern "C" { | |||||||
|  */ |  */ | ||||||
| #define SDL_HINT_KMSDRM_REQUIRE_DRM_MASTER      "SDL_KMSDRM_REQUIRE_DRM_MASTER" | #define SDL_HINT_KMSDRM_REQUIRE_DRM_MASTER      "SDL_KMSDRM_REQUIRE_DRM_MASTER" | ||||||
|  |  | ||||||
|  |  /** | ||||||
|  |   *  \brief  A comma separated list of devices to open as joysticks | ||||||
|  |   * | ||||||
|  |   *  This variable is currently only used by the Linux joystick driver. | ||||||
|  |   */ | ||||||
|  | #define SDL_HINT_JOYSTICK_DEVICE "SDL_JOYSTICK_DEVICE" | ||||||
|  |  | ||||||
|  |  /** | ||||||
|  |   *  \brief  A variable controlling whether to use the classic /dev/input/js* joystick interface or the newer /dev/input/event* joystick interface on Linux | ||||||
|  |   * | ||||||
|  |   *  This variable can be set to the following values: | ||||||
|  |   *    "0"       - Use /dev/input/event* | ||||||
|  |   *    "1"       - Use /dev/input/js* | ||||||
|  |   * | ||||||
|  |   *  By default the /dev/input/event* interfaces are used | ||||||
|  |   */ | ||||||
|  | #define SDL_HINT_LINUX_JOYSTICK_CLASSIC "SDL_LINUX_JOYSTICK_CLASSIC" | ||||||
|  |  | ||||||
|  /** |  /** | ||||||
|   *  \brief  A variable controlling whether joysticks on Linux adhere to their HID-defined deadzones or return unfiltered values. |   *  \brief  A variable controlling whether joysticks on Linux adhere to their HID-defined deadzones or return unfiltered values. | ||||||
|   * |   * | ||||||
|   | |||||||
| @@ -85,6 +85,7 @@ typedef enum | |||||||
|  |  | ||||||
| static EnumerationMethod enumeration_method = ENUMERATION_UNSET; | static EnumerationMethod enumeration_method = ENUMERATION_UNSET; | ||||||
|  |  | ||||||
|  | static SDL_bool IsJoystickDeviceNode(const char *node); | ||||||
| static int MaybeAddDevice(const char *path); | static int MaybeAddDevice(const char *path); | ||||||
| static int MaybeRemoveDevice(const char *path); | static int MaybeRemoveDevice(const char *path); | ||||||
|  |  | ||||||
| @@ -105,6 +106,7 @@ typedef struct SDL_joylist_item | |||||||
|     SDL_GamepadMapping *mapping; |     SDL_GamepadMapping *mapping; | ||||||
| } SDL_joylist_item; | } SDL_joylist_item; | ||||||
|  |  | ||||||
|  | static SDL_bool SDL_classic_joysticks = SDL_TRUE; | ||||||
| static SDL_joylist_item *SDL_joylist = NULL; | static SDL_joylist_item *SDL_joylist = NULL; | ||||||
| static SDL_joylist_item *SDL_joylist_tail = NULL; | static SDL_joylist_item *SDL_joylist_tail = NULL; | ||||||
| static int numjoysticks = 0; | static int numjoysticks = 0; | ||||||
| @@ -183,6 +185,10 @@ IsJoystick(int fd, char **name_return, SDL_JoystickGUID *guid) | |||||||
|     char *name; |     char *name; | ||||||
|     char product_string[128]; |     char product_string[128]; | ||||||
|  |  | ||||||
|  |     if (ioctl(fd, JSIOCGNAME(sizeof(product_string)), product_string) >= 0) { | ||||||
|  |         inpid.vendor = 0; | ||||||
|  |         inpid.product = 0; | ||||||
|  |     } else { | ||||||
|         /* When udev is enabled we only get joystick devices here, so there's no need to test them */ |         /* When udev is enabled we only get joystick devices here, so there's no need to test them */ | ||||||
|         if (enumeration_method != ENUMERATION_LIBUDEV && !GuessIsJoystick(fd)) { |         if (enumeration_method != ENUMERATION_LIBUDEV && !GuessIsJoystick(fd)) { | ||||||
|             return 0; |             return 0; | ||||||
| @@ -195,6 +201,7 @@ IsJoystick(int fd, char **name_return, SDL_JoystickGUID *guid) | |||||||
|         if (ioctl(fd, EVIOCGNAME(sizeof(product_string)), product_string) < 0) { |         if (ioctl(fd, EVIOCGNAME(sizeof(product_string)), product_string) < 0) { | ||||||
|             return 0; |             return 0; | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     name = SDL_CreateJoystickName(inpid.vendor, inpid.product, NULL, product_string); |     name = SDL_CreateJoystickName(inpid.vendor, inpid.product, NULL, product_string); | ||||||
|     if (!name) { |     if (!name) { | ||||||
| @@ -213,7 +220,7 @@ IsJoystick(int fd, char **name_return, SDL_JoystickGUID *guid) | |||||||
|     FixupDeviceInfoForMapping(fd, &inpid); |     FixupDeviceInfoForMapping(fd, &inpid); | ||||||
|  |  | ||||||
| #ifdef DEBUG_JOYSTICK | #ifdef DEBUG_JOYSTICK | ||||||
|     printf("Joystick: %s, bustype = %d, vendor = 0x%.4x, product = 0x%.4x, version = %d\n", name, inpid.bustype, inpid.vendor, inpid.product, inpid.version); |     SDL_Log("Joystick: %s, bustype = %d, vendor = 0x%.4x, product = 0x%.4x, version = %d\n", name, inpid.bustype, inpid.vendor, inpid.product, inpid.version); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|     SDL_memset(guid->data, 0, sizeof(guid->data)); |     SDL_memset(guid->data, 0, sizeof(guid->data)); | ||||||
| @@ -254,6 +261,9 @@ static void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_clas | |||||||
|             if (!(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) { |             if (!(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |             if (SDL_classic_joysticks && !IsJoystickDeviceNode(devpath)) { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|             MaybeAddDevice(devpath); |             MaybeAddDevice(devpath); | ||||||
|             break; |             break; | ||||||
|              |              | ||||||
| @@ -308,7 +318,7 @@ MaybeAddDevice(const char *path) | |||||||
|     } |     } | ||||||
|  |  | ||||||
| #ifdef DEBUG_INPUT_EVENTS | #ifdef DEBUG_INPUT_EVENTS | ||||||
|     printf("Checking %s\n", path); |     SDL_Log("Checking %s\n", path); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|     isstick = IsJoystick(fd, &name, &guid); |     isstick = IsJoystick(fd, &name, &guid); | ||||||
| @@ -507,6 +517,20 @@ StrIsInteger(const char *string) | |||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static SDL_bool | ||||||
|  | IsJoystickDeviceNode(const char *node) | ||||||
|  | { | ||||||
|  |     const char *last_slash = SDL_strrchr(node, '/'); | ||||||
|  |     if (last_slash) { | ||||||
|  |         node = last_slash + 1; | ||||||
|  |     } | ||||||
|  |     if (SDL_classic_joysticks) { | ||||||
|  |         return (StrHasPrefix(node, "js") && StrIsInteger(node + 2)); | ||||||
|  |     } else { | ||||||
|  |         return (StrHasPrefix(node, "event") && StrIsInteger(node + 5)); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| static void | static void | ||||||
| LINUX_InotifyJoystickDetect(void) | LINUX_InotifyJoystickDetect(void) | ||||||
| { | { | ||||||
| @@ -519,6 +543,7 @@ LINUX_InotifyJoystickDetect(void) | |||||||
|     ssize_t bytes; |     ssize_t bytes; | ||||||
|     size_t remain = 0; |     size_t remain = 0; | ||||||
|     size_t len; |     size_t len; | ||||||
|  |     char path[PATH_MAX]; | ||||||
|  |  | ||||||
|     bytes = read(inotify_fd, &buf, sizeof (buf)); |     bytes = read(inotify_fd, &buf, sizeof (buf)); | ||||||
|  |  | ||||||
| @@ -528,10 +553,7 @@ LINUX_InotifyJoystickDetect(void) | |||||||
|  |  | ||||||
|     while (remain > 0) { |     while (remain > 0) { | ||||||
|         if (buf.event.len > 0) { |         if (buf.event.len > 0) { | ||||||
|             if (StrHasPrefix(buf.event.name, "event") && |             if (IsJoystickDeviceNode(buf.event.name)) { | ||||||
|                 StrIsInteger(buf.event.name + SDL_strlen ("event"))) { |  | ||||||
|                 char path[PATH_MAX]; |  | ||||||
|  |  | ||||||
|                 SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", buf.event.name); |                 SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", buf.event.name); | ||||||
|  |  | ||||||
|                 if (buf.event.mask & (IN_CREATE | IN_MOVED_TO | IN_ATTRIB)) { |                 if (buf.event.mask & (IN_CREATE | IN_MOVED_TO | IN_ATTRIB)) { | ||||||
| @@ -560,7 +582,7 @@ LINUX_InotifyJoystickDetect(void) | |||||||
| static int | static int | ||||||
| filter_entries(const struct dirent *entry) | filter_entries(const struct dirent *entry) | ||||||
| { | { | ||||||
|     return (SDL_strlen(entry->d_name) > 5 && SDL_strncmp(entry->d_name, "event", 5) == 0); |     return IsJoystickDeviceNode(entry->d_name); | ||||||
| } | } | ||||||
| static int | static int | ||||||
| sort_entries(const struct dirent **a, const struct dirent **b) | sort_entries(const struct dirent **a, const struct dirent **b) | ||||||
| @@ -627,7 +649,9 @@ LINUX_JoystickDetect(void) | |||||||
| static int | static int | ||||||
| LINUX_JoystickInit(void) | LINUX_JoystickInit(void) | ||||||
| { | { | ||||||
|     const char *devices = SDL_GetHint("SDL_JOYSTICK_DEVICE"); |     const char *devices = SDL_GetHint(SDL_HINT_JOYSTICK_DEVICE); | ||||||
|  |  | ||||||
|  |     SDL_classic_joysticks = SDL_GetHintBoolean(SDL_HINT_LINUX_JOYSTICK_CLASSIC, SDL_FALSE); | ||||||
|  |  | ||||||
| #if SDL_USE_LIBUDEV | #if SDL_USE_LIBUDEV | ||||||
|     if (enumeration_method == ENUMERATION_UNSET) { |     if (enumeration_method == ENUMERATION_UNSET) { | ||||||
| @@ -824,6 +848,7 @@ ConfigJoystick(SDL_Joystick *joystick, int fd) | |||||||
|     unsigned long absbit[NBITS(ABS_MAX)] = { 0 }; |     unsigned long absbit[NBITS(ABS_MAX)] = { 0 }; | ||||||
|     unsigned long relbit[NBITS(REL_MAX)] = { 0 }; |     unsigned long relbit[NBITS(REL_MAX)] = { 0 }; | ||||||
|     unsigned long ffbit[NBITS(FF_MAX)] = { 0 }; |     unsigned long ffbit[NBITS(FF_MAX)] = { 0 }; | ||||||
|  |     Uint8 key_pam_size, abs_pam_size; | ||||||
|     SDL_bool use_deadzones = SDL_GetHintBoolean(SDL_HINT_LINUX_JOYSTICK_DEADZONES, SDL_FALSE); |     SDL_bool use_deadzones = SDL_GetHintBoolean(SDL_HINT_LINUX_JOYSTICK_DEADZONES, SDL_FALSE); | ||||||
|  |  | ||||||
|     /* See if this device uses the new unified event API */ |     /* See if this device uses the new unified event API */ | ||||||
| @@ -835,7 +860,7 @@ ConfigJoystick(SDL_Joystick *joystick, int fd) | |||||||
|         for (i = BTN_JOYSTICK; i < KEY_MAX; ++i) { |         for (i = BTN_JOYSTICK; i < KEY_MAX; ++i) { | ||||||
|             if (test_bit(i, keybit)) { |             if (test_bit(i, keybit)) { | ||||||
| #ifdef DEBUG_INPUT_EVENTS | #ifdef DEBUG_INPUT_EVENTS | ||||||
|                 printf("Joystick has button: 0x%x\n", i); |                 SDL_Log("Joystick has button: 0x%x\n", i); | ||||||
| #endif | #endif | ||||||
|                 joystick->hwdata->key_map[i] = joystick->nbuttons; |                 joystick->hwdata->key_map[i] = joystick->nbuttons; | ||||||
|                 joystick->hwdata->has_key[i] = SDL_TRUE; |                 joystick->hwdata->has_key[i] = SDL_TRUE; | ||||||
| @@ -845,7 +870,7 @@ ConfigJoystick(SDL_Joystick *joystick, int fd) | |||||||
|         for (i = 0; i < BTN_JOYSTICK; ++i) { |         for (i = 0; i < BTN_JOYSTICK; ++i) { | ||||||
|             if (test_bit(i, keybit)) { |             if (test_bit(i, keybit)) { | ||||||
| #ifdef DEBUG_INPUT_EVENTS | #ifdef DEBUG_INPUT_EVENTS | ||||||
|                 printf("Joystick has button: 0x%x\n", i); |                 SDL_Log("Joystick has button: 0x%x\n", i); | ||||||
| #endif | #endif | ||||||
|                 joystick->hwdata->key_map[i] = joystick->nbuttons; |                 joystick->hwdata->key_map[i] = joystick->nbuttons; | ||||||
|                 joystick->hwdata->has_key[i] = SDL_TRUE; |                 joystick->hwdata->has_key[i] = SDL_TRUE; | ||||||
| @@ -866,8 +891,8 @@ ConfigJoystick(SDL_Joystick *joystick, int fd) | |||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
| #ifdef DEBUG_INPUT_EVENTS | #ifdef DEBUG_INPUT_EVENTS | ||||||
|                 printf("Joystick has absolute axis: 0x%.2x\n", i); |                 SDL_Log("Joystick has absolute axis: 0x%.2x\n", i); | ||||||
|                 printf("Values = { %d, %d, %d, %d, %d }\n", |                 SDL_Log("Values = { %d, %d, %d, %d, %d }\n", | ||||||
|                         absinfo.value, absinfo.minimum, absinfo.maximum, |                         absinfo.value, absinfo.minimum, absinfo.maximum, | ||||||
|                         absinfo.fuzz, absinfo.flat); |                         absinfo.fuzz, absinfo.flat); | ||||||
| #endif /* DEBUG_INPUT_EVENTS */ | #endif /* DEBUG_INPUT_EVENTS */ | ||||||
| @@ -906,8 +931,8 @@ ConfigJoystick(SDL_Joystick *joystick, int fd) | |||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
| #ifdef DEBUG_INPUT_EVENTS | #ifdef DEBUG_INPUT_EVENTS | ||||||
|                 printf("Joystick has hat %d\n", hat_index); |                 SDL_Log("Joystick has hat %d\n", hat_index); | ||||||
|                 printf("Values = { %d, %d, %d, %d, %d }\n", |                 SDL_Log("Values = { %d, %d, %d, %d, %d }\n", | ||||||
|                         absinfo.value, absinfo.minimum, absinfo.maximum, |                         absinfo.value, absinfo.minimum, absinfo.maximum, | ||||||
|                         absinfo.fuzz, absinfo.flat); |                         absinfo.fuzz, absinfo.flat); | ||||||
| #endif /* DEBUG_INPUT_EVENTS */ | #endif /* DEBUG_INPUT_EVENTS */ | ||||||
| @@ -919,6 +944,63 @@ ConfigJoystick(SDL_Joystick *joystick, int fd) | |||||||
|             ++joystick->nballs; |             ++joystick->nballs; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |     } else if ((ioctl(fd, JSIOCGBUTTONS, &key_pam_size, sizeof(key_pam_size)) >= 0) && | ||||||
|  |                (ioctl(fd, JSIOCGAXES, &abs_pam_size, sizeof(abs_pam_size)) >= 0)) { | ||||||
|  |         size_t len; | ||||||
|  |  | ||||||
|  |         joystick->hwdata->classic = SDL_TRUE; | ||||||
|  |  | ||||||
|  |         len = (KEY_MAX - BTN_MISC + 1) * sizeof(*joystick->hwdata->key_pam); | ||||||
|  |         joystick->hwdata->key_pam = (Uint16 *)SDL_calloc(1, len); | ||||||
|  |         if (joystick->hwdata->key_pam) { | ||||||
|  |             if (ioctl(fd, JSIOCGBTNMAP, joystick->hwdata->key_pam, len) < 0) { | ||||||
|  |                 SDL_free(joystick->hwdata->key_pam); | ||||||
|  |                 joystick->hwdata->key_pam = NULL; | ||||||
|  |                 key_pam_size = 0; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         for (i = 0; i < key_pam_size; ++i) { | ||||||
|  |             Uint16 code = joystick->hwdata->key_pam[i]; | ||||||
|  | #ifdef DEBUG_INPUT_EVENTS | ||||||
|  |             SDL_Log("Joystick has button: 0x%x\n", code); | ||||||
|  | #endif | ||||||
|  |             joystick->hwdata->key_map[code] = joystick->nbuttons; | ||||||
|  |             joystick->hwdata->has_key[code] = SDL_TRUE; | ||||||
|  |             ++joystick->nbuttons; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         len = ABS_CNT * sizeof(*joystick->hwdata->abs_pam); | ||||||
|  |         joystick->hwdata->abs_pam = (Uint8 *)SDL_calloc(1, len); | ||||||
|  |         if (joystick->hwdata->abs_pam) { | ||||||
|  |             if (ioctl(fd, JSIOCGAXMAP, joystick->hwdata->abs_pam, len) < 0) { | ||||||
|  |                 SDL_free(joystick->hwdata->abs_pam); | ||||||
|  |                 joystick->hwdata->abs_pam = NULL; | ||||||
|  |                 abs_pam_size = 0; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         for (i = 0; i < abs_pam_size; ++i) { | ||||||
|  |             Uint8 code = joystick->hwdata->abs_pam[i]; | ||||||
|  |  | ||||||
|  |             if (code >= ABS_HAT0X && code <= ABS_HAT3Y) { | ||||||
|  |                 int hat_index = (code - ABS_HAT0X) / 2; | ||||||
|  |                 if (!joystick->hwdata->has_hat[hat_index]) { | ||||||
|  | #ifdef DEBUG_INPUT_EVENTS | ||||||
|  |                     SDL_Log("Joystick has hat %d\n", hat_index); | ||||||
|  | #endif | ||||||
|  |                     joystick->hwdata->hats_indices[hat_index] = joystick->nhats++; | ||||||
|  |                     joystick->hwdata->has_hat[hat_index] = SDL_TRUE; | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  | #ifdef DEBUG_INPUT_EVENTS | ||||||
|  |                 SDL_Log("Joystick has absolute axis: 0x%.2x\n", code); | ||||||
|  | #endif | ||||||
|  |                 joystick->hwdata->abs_map[code] = joystick->naxes; | ||||||
|  |                 joystick->hwdata->has_abs[code] = SDL_TRUE; | ||||||
|  |                 ++joystick->naxes; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /* Allocate data to keep track of these thingamajigs */ |     /* Allocate data to keep track of these thingamajigs */ | ||||||
|     if (joystick->nhats > 0) { |     if (joystick->nhats > 0) { | ||||||
|         if (allocate_hatdata(joystick) < 0) { |         if (allocate_hatdata(joystick) < 0) { | ||||||
| @@ -930,7 +1012,6 @@ ConfigJoystick(SDL_Joystick *joystick, int fd) | |||||||
|             joystick->nballs = 0; |             joystick->nballs = 0; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (ioctl(fd, EVIOCGBIT(EV_FF, sizeof(ffbit)), ffbit) >= 0) { |     if (ioctl(fd, EVIOCGBIT(EV_FF, sizeof(ffbit)), ffbit) >= 0) { | ||||||
|         if (test_bit(FF_RUMBLE, ffbit)) { |         if (test_bit(FF_RUMBLE, ffbit)) { | ||||||
| @@ -955,6 +1036,7 @@ PrepareJoystickHwdata(SDL_Joystick *joystick, SDL_joylist_item *item) | |||||||
|     joystick->hwdata->guid = item->guid; |     joystick->hwdata->guid = item->guid; | ||||||
|     joystick->hwdata->effect.id = -1; |     joystick->hwdata->effect.id = -1; | ||||||
|     joystick->hwdata->m_bSteamController = item->m_bSteamController; |     joystick->hwdata->m_bSteamController = item->m_bSteamController; | ||||||
|  |     SDL_memset(joystick->hwdata->key_map, 0xFF, sizeof(joystick->hwdata->key_map)); | ||||||
|     SDL_memset(joystick->hwdata->abs_map, 0xFF, sizeof(joystick->hwdata->abs_map)); |     SDL_memset(joystick->hwdata->abs_map, 0xFF, sizeof(joystick->hwdata->abs_map)); | ||||||
|  |  | ||||||
|     if (item->m_bSteamController) { |     if (item->m_bSteamController) { | ||||||
| @@ -1098,7 +1180,7 @@ LINUX_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled) | |||||||
|     return SDL_Unsupported(); |     return SDL_Unsupported(); | ||||||
| } | } | ||||||
|  |  | ||||||
| static SDL_INLINE void | static void | ||||||
| HandleHat(SDL_Joystick *stick, Uint8 hat, int axis, int value) | HandleHat(SDL_Joystick *stick, Uint8 hat, int axis, int value) | ||||||
| { | { | ||||||
|     struct hwdata_hat *the_hat; |     struct hwdata_hat *the_hat; | ||||||
| @@ -1123,14 +1205,14 @@ HandleHat(SDL_Joystick *stick, Uint8 hat, int axis, int value) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static SDL_INLINE void | static void | ||||||
| HandleBall(SDL_Joystick *stick, Uint8 ball, int axis, int value) | HandleBall(SDL_Joystick *stick, Uint8 ball, int axis, int value) | ||||||
| { | { | ||||||
|     stick->hwdata->balls[ball].axis[axis] += value; |     stick->hwdata->balls[ball].axis[axis] += value; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| static SDL_INLINE int | static int | ||||||
| AxisCorrect(SDL_Joystick *joystick, int which, int value) | AxisCorrect(SDL_Joystick *joystick, int which, int value) | ||||||
| { | { | ||||||
|     struct axis_correct *correct; |     struct axis_correct *correct; | ||||||
| @@ -1164,7 +1246,7 @@ AxisCorrect(SDL_Joystick *joystick, int which, int value) | |||||||
|     return value; |     return value; | ||||||
| } | } | ||||||
|  |  | ||||||
| static SDL_INLINE void | static void | ||||||
| PollAllValues(SDL_Joystick *joystick) | PollAllValues(SDL_Joystick *joystick) | ||||||
| { | { | ||||||
|     struct input_absinfo absinfo; |     struct input_absinfo absinfo; | ||||||
| @@ -1182,7 +1264,7 @@ PollAllValues(SDL_Joystick *joystick) | |||||||
|                 absinfo.value = AxisCorrect(joystick, i, absinfo.value); |                 absinfo.value = AxisCorrect(joystick, i, absinfo.value); | ||||||
|  |  | ||||||
| #ifdef DEBUG_INPUT_EVENTS | #ifdef DEBUG_INPUT_EVENTS | ||||||
|                 printf("Joystick : Re-read Axis %d (%d) val= %d\n", |                 SDL_Log("Joystick : Re-read Axis %d (%d) val= %d\n", | ||||||
|                     joystick->hwdata->abs_map[i], i, absinfo.value); |                     joystick->hwdata->abs_map[i], i, absinfo.value); | ||||||
| #endif | #endif | ||||||
|                 SDL_PrivateJoystickAxis(joystick, |                 SDL_PrivateJoystickAxis(joystick, | ||||||
| @@ -1212,7 +1294,7 @@ PollAllValues(SDL_Joystick *joystick) | |||||||
|             if (joystick->hwdata->has_key[i]) { |             if (joystick->hwdata->has_key[i]) { | ||||||
|                 const Uint8 value = test_bit(i, keyinfo) ? SDL_PRESSED : SDL_RELEASED; |                 const Uint8 value = test_bit(i, keyinfo) ? SDL_PRESSED : SDL_RELEASED; | ||||||
| #ifdef DEBUG_INPUT_EVENTS | #ifdef DEBUG_INPUT_EVENTS | ||||||
|                 printf("Joystick : Re-read Button %d (%d) val= %d\n", |                 SDL_Log("Joystick : Re-read Button %d (%d) val= %d\n", | ||||||
|                     joystick->hwdata->key_map[i], i, value); |                     joystick->hwdata->key_map[i], i, value); | ||||||
| #endif | #endif | ||||||
|                 SDL_PrivateJoystickButton(joystick, |                 SDL_PrivateJoystickButton(joystick, | ||||||
| @@ -1224,12 +1306,11 @@ PollAllValues(SDL_Joystick *joystick) | |||||||
|     /* Joyballs are relative input, so there's no poll state. Events only! */ |     /* Joyballs are relative input, so there's no poll state. Events only! */ | ||||||
| } | } | ||||||
|  |  | ||||||
| static SDL_INLINE void | static void | ||||||
| HandleInputEvents(SDL_Joystick *joystick) | HandleInputEvents(SDL_Joystick *joystick) | ||||||
| { | { | ||||||
|     struct input_event events[32]; |     struct input_event events[32]; | ||||||
|     int i, len; |     int i, len, code; | ||||||
|     int code; |  | ||||||
|  |  | ||||||
|     if (joystick->hwdata->fresh) { |     if (joystick->hwdata->fresh) { | ||||||
|         PollAllValues(joystick); |         PollAllValues(joystick); | ||||||
| @@ -1268,13 +1349,10 @@ HandleInputEvents(SDL_Joystick *joystick) | |||||||
|                     HandleHat(joystick, joystick->hwdata->hats_indices[code / 2], code % 2, events[i].value); |                     HandleHat(joystick, joystick->hwdata->hats_indices[code / 2], code % 2, events[i].value); | ||||||
|                     break; |                     break; | ||||||
|                 default: |                 default: | ||||||
|                     if (joystick->hwdata->abs_map[code] != 0xFF) { |                     events[i].value = AxisCorrect(joystick, code, events[i].value); | ||||||
|                         events[i].value = |  | ||||||
|                             AxisCorrect(joystick, code, events[i].value); |  | ||||||
|                     SDL_PrivateJoystickAxis(joystick, |                     SDL_PrivateJoystickAxis(joystick, | ||||||
|                                             joystick->hwdata->abs_map[code], |                                             joystick->hwdata->abs_map[code], | ||||||
|                                             events[i].value); |                                             events[i].value); | ||||||
|                     } |  | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|                 break; |                 break; | ||||||
| @@ -1293,7 +1371,7 @@ HandleInputEvents(SDL_Joystick *joystick) | |||||||
|                 switch (code) { |                 switch (code) { | ||||||
|                 case SYN_DROPPED : |                 case SYN_DROPPED : | ||||||
| #ifdef DEBUG_INPUT_EVENTS | #ifdef DEBUG_INPUT_EVENTS | ||||||
|                     printf("Event SYN_DROPPED detected\n"); |                     SDL_Log("Event SYN_DROPPED detected\n"); | ||||||
| #endif | #endif | ||||||
|                     joystick->hwdata->recovering_from_dropped = SDL_TRUE; |                     joystick->hwdata->recovering_from_dropped = SDL_TRUE; | ||||||
|                     break; |                     break; | ||||||
| @@ -1318,6 +1396,48 @@ HandleInputEvents(SDL_Joystick *joystick) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | HandleClassicEvents(SDL_Joystick *joystick) | ||||||
|  | { | ||||||
|  |     struct js_event events[32]; | ||||||
|  |     int i, len, code; | ||||||
|  |  | ||||||
|  |     joystick->hwdata->fresh = SDL_FALSE; | ||||||
|  |     while ((len = read(joystick->hwdata->fd, events, (sizeof events))) > 0) { | ||||||
|  |         len /= sizeof(events[0]); | ||||||
|  |         for (i = 0; i < len; ++i) { | ||||||
|  |             switch (events[i].type) { | ||||||
|  |             case JS_EVENT_BUTTON: | ||||||
|  |                 code = joystick->hwdata->key_pam[events[i].number]; | ||||||
|  |                 SDL_PrivateJoystickButton(joystick, | ||||||
|  |                                           joystick->hwdata->key_map[code], | ||||||
|  |                                           events[i].value); | ||||||
|  |                 break; | ||||||
|  |             case JS_EVENT_AXIS: | ||||||
|  |                 code = joystick->hwdata->abs_pam[events[i].number]; | ||||||
|  |                 switch (code) { | ||||||
|  |                 case ABS_HAT0X: | ||||||
|  |                 case ABS_HAT0Y: | ||||||
|  |                 case ABS_HAT1X: | ||||||
|  |                 case ABS_HAT1Y: | ||||||
|  |                 case ABS_HAT2X: | ||||||
|  |                 case ABS_HAT2Y: | ||||||
|  |                 case ABS_HAT3X: | ||||||
|  |                 case ABS_HAT3Y: | ||||||
|  |                     code -= ABS_HAT0X; | ||||||
|  |                     HandleHat(joystick, joystick->hwdata->hats_indices[code / 2], code % 2, events[i].value); | ||||||
|  |                     break; | ||||||
|  |                 default: | ||||||
|  |                     SDL_PrivateJoystickAxis(joystick, | ||||||
|  |                                             joystick->hwdata->abs_map[code], | ||||||
|  |                                             events[i].value); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| static void | static void | ||||||
| LINUX_JoystickUpdate(SDL_Joystick *joystick) | LINUX_JoystickUpdate(SDL_Joystick *joystick) | ||||||
| { | { | ||||||
| @@ -1328,7 +1448,11 @@ LINUX_JoystickUpdate(SDL_Joystick *joystick) | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (joystick->hwdata->classic) { | ||||||
|  |         HandleClassicEvents(joystick); | ||||||
|  |     } else { | ||||||
|         HandleInputEvents(joystick); |         HandleInputEvents(joystick); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /* Deliver ball motion updates */ |     /* Deliver ball motion updates */ | ||||||
|     for (i = 0; i < joystick->nballs; ++i) { |     for (i = 0; i < joystick->nballs; ++i) { | ||||||
| @@ -1359,6 +1483,8 @@ LINUX_JoystickClose(SDL_Joystick *joystick) | |||||||
|         if (joystick->hwdata->item) { |         if (joystick->hwdata->item) { | ||||||
|             joystick->hwdata->item->hwdata = NULL; |             joystick->hwdata->item->hwdata = NULL; | ||||||
|         } |         } | ||||||
|  |         SDL_free(joystick->hwdata->key_pam); | ||||||
|  |         SDL_free(joystick->hwdata->abs_pam); | ||||||
|         SDL_free(joystick->hwdata->hats); |         SDL_free(joystick->hwdata->hats); | ||||||
|         SDL_free(joystick->hwdata->balls); |         SDL_free(joystick->hwdata->balls); | ||||||
|         SDL_free(joystick->hwdata->fname); |         SDL_free(joystick->hwdata->fname); | ||||||
| @@ -1525,20 +1651,20 @@ LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out) | |||||||
|         out->lefttrigger.target = hat | 0x4; |         out->lefttrigger.target = hat | 0x4; | ||||||
|         out->righttrigger.target = hat | 0x2; |         out->righttrigger.target = hat | 0x2; | ||||||
|     } else { |     } else { | ||||||
|         if (joystick->hwdata->has_key[BTN_TL2]) { |         if (joystick->hwdata->has_abs[ABS_Z]) { | ||||||
|             out->lefttrigger.kind = EMappingKind_Button; |  | ||||||
|             out->lefttrigger.target = joystick->hwdata->key_map[BTN_TL2]; |  | ||||||
|         } else if (joystick->hwdata->has_abs[ABS_Z]) { |  | ||||||
|             out->lefttrigger.kind = EMappingKind_Axis; |             out->lefttrigger.kind = EMappingKind_Axis; | ||||||
|             out->lefttrigger.target = joystick->hwdata->abs_map[ABS_Z]; |             out->lefttrigger.target = joystick->hwdata->abs_map[ABS_Z]; | ||||||
|  |         } else if (joystick->hwdata->has_key[BTN_TL2]) { | ||||||
|  |             out->lefttrigger.kind = EMappingKind_Button; | ||||||
|  |             out->lefttrigger.target = joystick->hwdata->key_map[BTN_TL2]; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (joystick->hwdata->has_key[BTN_TR2]) { |         if (joystick->hwdata->has_abs[ABS_RZ]) { | ||||||
|             out->righttrigger.kind = EMappingKind_Button; |  | ||||||
|             out->righttrigger.target = joystick->hwdata->key_map[BTN_TR2]; |  | ||||||
|         } else if (joystick->hwdata->has_abs[ABS_RZ]) { |  | ||||||
|             out->righttrigger.kind = EMappingKind_Axis; |             out->righttrigger.kind = EMappingKind_Axis; | ||||||
|             out->righttrigger.target = joystick->hwdata->abs_map[ABS_RZ]; |             out->righttrigger.target = joystick->hwdata->abs_map[ABS_RZ]; | ||||||
|  |         } else if (joystick->hwdata->has_key[BTN_TR2]) { | ||||||
|  |             out->righttrigger.kind = EMappingKind_Button; | ||||||
|  |             out->righttrigger.target = joystick->hwdata->key_map[BTN_TR2]; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -56,6 +56,11 @@ struct joystick_hwdata | |||||||
|     SDL_bool has_key[KEY_MAX]; |     SDL_bool has_key[KEY_MAX]; | ||||||
|     SDL_bool has_abs[ABS_MAX]; |     SDL_bool has_abs[ABS_MAX]; | ||||||
|  |  | ||||||
|  |     /* Support for the classic joystick interface */ | ||||||
|  |     SDL_bool classic; | ||||||
|  |     Uint16 *key_pam; | ||||||
|  |     Uint8 *abs_pam; | ||||||
|  |  | ||||||
|     struct axis_correct |     struct axis_correct | ||||||
|     { |     { | ||||||
|         SDL_bool use_deadzones; |         SDL_bool use_deadzones; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Sam Lantinga
					Sam Lantinga