|
@@ -78,7 +78,7 @@
|
|
|
#include "../../core/linux/SDL_evdev_capabilities.h"
|
|
|
#include "../../core/linux/SDL_udev.h"
|
|
|
|
|
|
-#if 0
|
|
|
+#if 1
|
|
|
#define DEBUG_INPUT_EVENTS 1
|
|
|
#endif
|
|
|
|
|
@@ -926,6 +926,33 @@ allocate_balldata(SDL_Joystick *joystick)
|
|
|
return (0);
|
|
|
}
|
|
|
|
|
|
+static SDL_bool
|
|
|
+GuessIfAxesAreDigitalHat(struct input_absinfo *absinfo_x, struct input_absinfo *absinfo_y)
|
|
|
+{
|
|
|
+ /* A "hat" is assumed to be a digital input with at most 9 possible states
|
|
|
+ * (3 per axis: negative/zero/positive), as opposed to a true "axis" which
|
|
|
+ * can report a continuous range of possible values. Unfortunately the Linux
|
|
|
+ * joystick interface makes no distinction between digital hat axes and any
|
|
|
+ * other continuous analog axis, so we have to guess. */
|
|
|
+
|
|
|
+ /* If both axes are missing, they're not anything. */
|
|
|
+ if (!absinfo_x && !absinfo_y)
|
|
|
+ return SDL_FALSE;
|
|
|
+
|
|
|
+ /* If both axes have ranges constrained between -1 and 1, they're definitely digital. */
|
|
|
+ if ((!absinfo_x || (absinfo_x->minimum == -1 && absinfo_x->maximum == 1)) &&
|
|
|
+ (!absinfo_y || (absinfo_y->minimum == -1 && absinfo_y->maximum == 1)))
|
|
|
+ return SDL_TRUE;
|
|
|
+
|
|
|
+ /* If both axes lack fuzz, flat, and resolution values, they're probably digital. */
|
|
|
+ if ((!absinfo_x || (!absinfo_x->fuzz && !absinfo_x->flat && !absinfo_x->resolution)) &&
|
|
|
+ (!absinfo_y || (!absinfo_y->fuzz && !absinfo_y->flat && !absinfo_y->resolution)))
|
|
|
+ return SDL_TRUE;
|
|
|
+
|
|
|
+ /* Otherwise, treat them as analog. */
|
|
|
+ return SDL_FALSE;
|
|
|
+}
|
|
|
+
|
|
|
static void
|
|
|
ConfigJoystick(SDL_Joystick *joystick, int fd)
|
|
|
{
|
|
@@ -963,10 +990,43 @@ ConfigJoystick(SDL_Joystick *joystick, int fd)
|
|
|
++joystick->nbuttons;
|
|
|
}
|
|
|
}
|
|
|
+ for (i = ABS_HAT0X; i <= ABS_HAT3Y; i += 2) {
|
|
|
+ int hat_x = -1;
|
|
|
+ int hat_y = -1;
|
|
|
+ struct input_absinfo absinfo_x;
|
|
|
+ struct input_absinfo absinfo_y;
|
|
|
+ if (test_bit(i, absbit))
|
|
|
+ hat_x = ioctl(fd, EVIOCGABS(i), &absinfo_x);
|
|
|
+ if (test_bit(i + 1, absbit))
|
|
|
+ hat_y = ioctl(fd, EVIOCGABS(i + 1), &absinfo_y);
|
|
|
+ if (GuessIfAxesAreDigitalHat((hat_x < 0 ? (void*)0 : &absinfo_x),
|
|
|
+ (hat_y < 0 ? (void*)0 : &absinfo_y))) {
|
|
|
+ const int hat_index = (i - ABS_HAT0X) / 2;
|
|
|
+#ifdef DEBUG_INPUT_EVENTS
|
|
|
+ SDL_Log("Joystick has digital hat: %d\n", hat_index);
|
|
|
+ if (hat_x >= 0) {
|
|
|
+ SDL_Log("X Values = { %d, %d, %d, %d, %d, %d }\n",
|
|
|
+ absinfo_x.value, absinfo_x.minimum, absinfo_x.maximum,
|
|
|
+ absinfo_x.fuzz, absinfo_x.flat, absinfo_x.resolution);
|
|
|
+ }
|
|
|
+ if (hat_y >= 0) {
|
|
|
+ SDL_Log("Y Values = { %d, %d, %d, %d, %d, %d }\n",
|
|
|
+ absinfo_y.value, absinfo_y.minimum, absinfo_y.maximum,
|
|
|
+ absinfo_y.fuzz, absinfo_y.flat, absinfo_y.resolution);
|
|
|
+ }
|
|
|
+#endif /* DEBUG_INPUT_EVENTS */
|
|
|
+ joystick->hwdata->hats_indices[hat_index] = joystick->nhats;
|
|
|
+ joystick->hwdata->has_hat[hat_index] = SDL_TRUE;
|
|
|
+ joystick->hwdata->hat_correct[hat_index].minimum[0] = (hat_x < 0) ? -1 : absinfo_x.minimum;
|
|
|
+ joystick->hwdata->hat_correct[hat_index].maximum[0] = (hat_x < 0) ? 1 : absinfo_x.maximum;
|
|
|
+ joystick->hwdata->hat_correct[hat_index].minimum[1] = (hat_y < 0) ? -1 : absinfo_y.minimum;
|
|
|
+ joystick->hwdata->hat_correct[hat_index].maximum[1] = (hat_y < 0) ? 1 : absinfo_y.maximum;
|
|
|
+ ++joystick->nhats;
|
|
|
+ }
|
|
|
+ }
|
|
|
for (i = 0; i < ABS_MAX; ++i) {
|
|
|
- /* Skip hats */
|
|
|
- if (i == ABS_HAT0X) {
|
|
|
- i = ABS_HAT3Y;
|
|
|
+ /* Skip digital hats */
|
|
|
+ if (joystick->hwdata->has_hat[(i - ABS_HAT0X) / 2]) {
|
|
|
continue;
|
|
|
}
|
|
|
if (test_bit(i, absbit)) {
|
|
@@ -978,9 +1038,9 @@ ConfigJoystick(SDL_Joystick *joystick, int fd)
|
|
|
}
|
|
|
#ifdef DEBUG_INPUT_EVENTS
|
|
|
SDL_Log("Joystick has absolute axis: 0x%.2x\n", i);
|
|
|
- SDL_Log("Values = { %d, %d, %d, %d, %d }\n",
|
|
|
+ SDL_Log("Values = { %d, %d, %d, %d, %d, %d }\n",
|
|
|
absinfo.value, absinfo.minimum, absinfo.maximum,
|
|
|
- absinfo.fuzz, absinfo.flat);
|
|
|
+ absinfo.fuzz, absinfo.flat, absinfo.resolution);
|
|
|
#endif /* DEBUG_INPUT_EVENTS */
|
|
|
joystick->hwdata->abs_map[i] = joystick->naxes;
|
|
|
joystick->hwdata->has_abs[i] = SDL_TRUE;
|
|
@@ -1008,24 +1068,6 @@ ConfigJoystick(SDL_Joystick *joystick, int fd)
|
|
|
++joystick->naxes;
|
|
|
}
|
|
|
}
|
|
|
- for (i = ABS_HAT0X; i <= ABS_HAT3Y; i += 2) {
|
|
|
- if (test_bit(i, absbit) || test_bit(i + 1, absbit)) {
|
|
|
- struct input_absinfo absinfo;
|
|
|
- int hat_index = (i - ABS_HAT0X) / 2;
|
|
|
-
|
|
|
- if (ioctl(fd, EVIOCGABS(i), &absinfo) < 0) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-#ifdef DEBUG_INPUT_EVENTS
|
|
|
- SDL_Log("Joystick has hat %d\n", hat_index);
|
|
|
- SDL_Log("Values = { %d, %d, %d, %d, %d }\n",
|
|
|
- absinfo.value, absinfo.minimum, absinfo.maximum,
|
|
|
- absinfo.fuzz, absinfo.flat);
|
|
|
-#endif /* DEBUG_INPUT_EVENTS */
|
|
|
- joystick->hwdata->hats_indices[hat_index] = joystick->nhats++;
|
|
|
- joystick->hwdata->has_hat[hat_index] = SDL_TRUE;
|
|
|
- }
|
|
|
- }
|
|
|
if (test_bit(REL_X, relbit) || test_bit(REL_Y, relbit)) {
|
|
|
++joystick->nballs;
|
|
|
}
|
|
@@ -1071,14 +1113,19 @@ ConfigJoystick(SDL_Joystick *joystick, int fd)
|
|
|
for (i = 0; i < abs_pam_size; ++i) {
|
|
|
Uint8 code = joystick->hwdata->abs_pam[i];
|
|
|
|
|
|
+ // TODO: is there any way to detect analog hats in advance via this API?
|
|
|
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);
|
|
|
+ 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;
|
|
|
+ joystick->hwdata->hat_correct[hat_index].minimum[0] = -1;
|
|
|
+ joystick->hwdata->hat_correct[hat_index].maximum[0] = 1;
|
|
|
+ joystick->hwdata->hat_correct[hat_index].minimum[1] = -1;
|
|
|
+ joystick->hwdata->hat_correct[hat_index].maximum[1] = 1;
|
|
|
}
|
|
|
} else {
|
|
|
#ifdef DEBUG_INPUT_EVENTS
|
|
@@ -1277,26 +1324,47 @@ LINUX_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
-HandleHat(SDL_Joystick *stick, Uint8 hat, int axis, int value)
|
|
|
+HandleHat(SDL_Joystick *stick, int hatidx, int axis, int value)
|
|
|
{
|
|
|
+ const int hatnum = stick->hwdata->hats_indices[hatidx];
|
|
|
struct hwdata_hat *the_hat;
|
|
|
+ struct hat_axis_correct *correct;
|
|
|
const Uint8 position_map[3][3] = {
|
|
|
{SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP},
|
|
|
{SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT},
|
|
|
{SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN}
|
|
|
};
|
|
|
|
|
|
- the_hat = &stick->hwdata->hats[hat];
|
|
|
+ the_hat = &stick->hwdata->hats[hatnum];
|
|
|
+ correct = &stick->hwdata->hat_correct[hatidx];
|
|
|
+ /* If we failed to detect that this hat's axes are analog,
|
|
|
+ * we can at least make the hat output usable by applying
|
|
|
+ * a deadzone of half of the observed min/max values. If
|
|
|
+ * the axes really are digital, this won't hurt. */
|
|
|
if (value < 0) {
|
|
|
- value = 0;
|
|
|
- } else if (value == 0) {
|
|
|
- value = 1;
|
|
|
+ if (value <= correct->minimum[axis]) {
|
|
|
+ correct->minimum[axis] = value;
|
|
|
+ value = 0;
|
|
|
+ } else if (value < correct->minimum[axis] / 2) {
|
|
|
+ value = 0;
|
|
|
+ } else {
|
|
|
+ value = 1;
|
|
|
+ }
|
|
|
} else if (value > 0) {
|
|
|
- value = 2;
|
|
|
+ if (value >= correct->maximum[axis]) {
|
|
|
+ correct->maximum[axis] = value;
|
|
|
+ value = 2;
|
|
|
+ } else if (value > correct->maximum[axis] / 2) {
|
|
|
+ value = 2;
|
|
|
+ } else {
|
|
|
+ value = 1;
|
|
|
+ }
|
|
|
+ } else { // value == 0
|
|
|
+ value = 1;
|
|
|
}
|
|
|
if (value != the_hat->axis[axis]) {
|
|
|
the_hat->axis[axis] = value;
|
|
|
- SDL_PrivateJoystickHat(stick, hat,
|
|
|
+ SDL_PrivateJoystickHat(stick, hatnum,
|
|
|
position_map[the_hat->axis[1]][the_hat->axis[0]]);
|
|
|
}
|
|
|
}
|
|
@@ -1351,10 +1419,7 @@ PollAllValues(SDL_Joystick *joystick)
|
|
|
|
|
|
/* Poll all axis */
|
|
|
for (i = ABS_X; i < ABS_MAX; i++) {
|
|
|
- if (i == ABS_HAT0X) { /* we handle hats in the next loop, skip them for now. */
|
|
|
- i = ABS_HAT3Y;
|
|
|
- continue;
|
|
|
- }
|
|
|
+ /* We don't need to test for digital hats here, they won't have has_abs[] set */
|
|
|
if (joystick->hwdata->has_abs[i]) {
|
|
|
if (ioctl(joystick->hwdata->fd, EVIOCGABS(i), &absinfo) >= 0) {
|
|
|
absinfo.value = AxisCorrect(joystick, i, absinfo.value);
|
|
@@ -1370,15 +1435,16 @@ PollAllValues(SDL_Joystick *joystick)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /* Poll all hats */
|
|
|
+ /* Poll all digital hats */
|
|
|
for (i = ABS_HAT0X; i <= ABS_HAT3Y; i++) {
|
|
|
const int baseaxis = i - ABS_HAT0X;
|
|
|
const int hatidx = baseaxis / 2;
|
|
|
SDL_assert(hatidx < SDL_arraysize(joystick->hwdata->has_hat));
|
|
|
+ /* We don't need to test for analog axes here, they won't have has_hat[] set */
|
|
|
if (joystick->hwdata->has_hat[hatidx]) {
|
|
|
if (ioctl(joystick->hwdata->fd, EVIOCGABS(i), &absinfo) >= 0) {
|
|
|
const int hataxis = baseaxis % 2;
|
|
|
- HandleHat(joystick, joystick->hwdata->hats_indices[hatidx], hataxis, absinfo.value);
|
|
|
+ HandleHat(joystick, hatidx, hataxis, absinfo.value);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -1406,7 +1472,7 @@ static void
|
|
|
HandleInputEvents(SDL_Joystick *joystick)
|
|
|
{
|
|
|
struct input_event events[32];
|
|
|
- int i, len, code;
|
|
|
+ int i, len, code, hat_index;
|
|
|
|
|
|
if (joystick->hwdata->fresh) {
|
|
|
PollAllValues(joystick);
|
|
@@ -1441,9 +1507,11 @@ HandleInputEvents(SDL_Joystick *joystick)
|
|
|
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;
|
|
|
+ hat_index = (code - ABS_HAT0X) / 2;
|
|
|
+ if (joystick->hwdata->has_hat[hat_index]) {
|
|
|
+ HandleHat(joystick, hat_index, code % 2, events[i].value);
|
|
|
+ break;
|
|
|
+ }
|
|
|
default:
|
|
|
events[i].value = AxisCorrect(joystick, code, events[i].value);
|
|
|
SDL_PrivateJoystickAxis(joystick,
|
|
@@ -1496,7 +1564,7 @@ static void
|
|
|
HandleClassicEvents(SDL_Joystick *joystick)
|
|
|
{
|
|
|
struct js_event events[32];
|
|
|
- int i, len, code;
|
|
|
+ int i, len, code, hat_index;
|
|
|
|
|
|
joystick->hwdata->fresh = SDL_FALSE;
|
|
|
while ((len = read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
|
|
@@ -1520,9 +1588,11 @@ HandleClassicEvents(SDL_Joystick *joystick)
|
|
|
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;
|
|
|
+ hat_index = (code - ABS_HAT0X) / 2;
|
|
|
+ if (joystick->hwdata->has_hat[hat_index]) {
|
|
|
+ HandleHat(joystick, hat_index, code % 2, events[i].value);
|
|
|
+ break;
|
|
|
+ }
|
|
|
default:
|
|
|
SDL_PrivateJoystickAxis(joystick,
|
|
|
joystick->hwdata->abs_map[code],
|
|
@@ -1628,6 +1698,7 @@ LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
|
|
|
{
|
|
|
SDL_Joystick *joystick;
|
|
|
SDL_joylist_item *item = JoystickByDevIndex(device_index);
|
|
|
+ unsigned int mapped;
|
|
|
|
|
|
if (item->checked_mapping) {
|
|
|
if (item->mapping) {
|
|
@@ -1739,84 +1810,136 @@ LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
|
|
|
can be digital, or analog, or both at the same time.
|
|
|
*/
|
|
|
|
|
|
- /* Prefer digital shoulder buttons, but settle for analog if missing. */
|
|
|
+ /* Prefer digital shoulder buttons, but settle for digital or analog hat. */
|
|
|
+ mapped = 0;
|
|
|
+
|
|
|
if (joystick->hwdata->has_key[BTN_TL]) {
|
|
|
out->leftshoulder.kind = EMappingKind_Button;
|
|
|
out->leftshoulder.target = joystick->hwdata->key_map[BTN_TL];
|
|
|
+ mapped |= 0x1;
|
|
|
}
|
|
|
|
|
|
if (joystick->hwdata->has_key[BTN_TR]) {
|
|
|
out->rightshoulder.kind = EMappingKind_Button;
|
|
|
out->rightshoulder.target = joystick->hwdata->key_map[BTN_TR];
|
|
|
+ mapped |= 0x2;
|
|
|
}
|
|
|
|
|
|
- if (joystick->hwdata->has_hat[1] && /* Check if ABS_HAT1{X, Y} is available. */
|
|
|
- (!joystick->hwdata->has_key[BTN_TL] || !joystick->hwdata->has_key[BTN_TR])) {
|
|
|
+ if (mapped != 0x3 && joystick->hwdata->has_hat[1]) {
|
|
|
int hat = joystick->hwdata->hats_indices[1] << 4;
|
|
|
out->leftshoulder.kind = EMappingKind_Hat;
|
|
|
out->rightshoulder.kind = EMappingKind_Hat;
|
|
|
out->leftshoulder.target = hat | 0x4;
|
|
|
out->rightshoulder.target = hat | 0x2;
|
|
|
+ mapped |= 0x3;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!(mapped & 0x1) && joystick->hwdata->has_abs[ABS_HAT1Y]) {
|
|
|
+ out->leftshoulder.kind = EMappingKind_Axis;
|
|
|
+ out->leftshoulder.target = joystick->hwdata->abs_map[ABS_HAT1Y];
|
|
|
+ mapped |= 0x1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!(mapped & 0x2) && joystick->hwdata->has_abs[ABS_HAT1X]) {
|
|
|
+ out->rightshoulder.kind = EMappingKind_Axis;
|
|
|
+ out->rightshoulder.target = joystick->hwdata->abs_map[ABS_HAT1X];
|
|
|
+ mapped |= 0x2;
|
|
|
}
|
|
|
|
|
|
- /* Prefer analog triggers, but settle for digital if missing. */
|
|
|
- if (joystick->hwdata->has_hat[2]) { /* Check if ABS_HAT2{X,Y} is available. */
|
|
|
+ /* Prefer analog triggers, but settle for digital hat or buttons. */
|
|
|
+ mapped = 0;
|
|
|
+
|
|
|
+ if (joystick->hwdata->has_abs[ABS_HAT2Y]) {
|
|
|
+ out->lefttrigger.kind = EMappingKind_Axis;
|
|
|
+ out->lefttrigger.target = joystick->hwdata->abs_map[ABS_HAT2Y];
|
|
|
+ mapped |= 0x1;
|
|
|
+ } else if (joystick->hwdata->has_abs[ABS_Z]) {
|
|
|
+ out->lefttrigger.kind = EMappingKind_Axis;
|
|
|
+ out->lefttrigger.target = joystick->hwdata->abs_map[ABS_Z];
|
|
|
+ mapped |= 0x1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (joystick->hwdata->has_abs[ABS_HAT2X]) {
|
|
|
+ out->righttrigger.kind = EMappingKind_Axis;
|
|
|
+ out->righttrigger.target = joystick->hwdata->abs_map[ABS_HAT2X];
|
|
|
+ mapped |= 0x2;
|
|
|
+ } else if (joystick->hwdata->has_abs[ABS_RZ]) {
|
|
|
+ out->righttrigger.kind = EMappingKind_Axis;
|
|
|
+ out->righttrigger.target = joystick->hwdata->abs_map[ABS_RZ];
|
|
|
+ mapped |= 0x2;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mapped != 0x3 && joystick->hwdata->has_hat[2]) {
|
|
|
int hat = joystick->hwdata->hats_indices[2] << 4;
|
|
|
out->lefttrigger.kind = EMappingKind_Hat;
|
|
|
out->righttrigger.kind = EMappingKind_Hat;
|
|
|
out->lefttrigger.target = hat | 0x4;
|
|
|
out->righttrigger.target = hat | 0x2;
|
|
|
- } else {
|
|
|
- if (joystick->hwdata->has_abs[ABS_Z]) {
|
|
|
- out->lefttrigger.kind = EMappingKind_Axis;
|
|
|
- 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];
|
|
|
- }
|
|
|
+ mapped |= 0x3;
|
|
|
+ }
|
|
|
|
|
|
- if (joystick->hwdata->has_abs[ABS_RZ]) {
|
|
|
- out->righttrigger.kind = EMappingKind_Axis;
|
|
|
- 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];
|
|
|
- }
|
|
|
+ if (!(mapped & 0x1) && joystick->hwdata->has_key[BTN_TL2]) {
|
|
|
+ out->lefttrigger.kind = EMappingKind_Button;
|
|
|
+ out->lefttrigger.target = joystick->hwdata->key_map[BTN_TL2];
|
|
|
+ mapped |= 0x1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!(mapped & 0x2) && joystick->hwdata->has_key[BTN_TR2]) {
|
|
|
+ out->righttrigger.kind = EMappingKind_Button;
|
|
|
+ out->righttrigger.target = joystick->hwdata->key_map[BTN_TR2];
|
|
|
+ mapped |= 0x2;
|
|
|
}
|
|
|
|
|
|
- /* Prefer digital D-Pad, but settle for analog if missing. */
|
|
|
+ /* Prefer digital D-Pad buttons, but settle for digital or analog hat. */
|
|
|
+ mapped = 0;
|
|
|
+
|
|
|
if (joystick->hwdata->has_key[BTN_DPAD_UP]) {
|
|
|
out->dpup.kind = EMappingKind_Button;
|
|
|
out->dpup.target = joystick->hwdata->key_map[BTN_DPAD_UP];
|
|
|
+ mapped |= 0x1;
|
|
|
}
|
|
|
|
|
|
if (joystick->hwdata->has_key[BTN_DPAD_DOWN]) {
|
|
|
out->dpdown.kind = EMappingKind_Button;
|
|
|
out->dpdown.target = joystick->hwdata->key_map[BTN_DPAD_DOWN];
|
|
|
+ mapped |= 0x2;
|
|
|
}
|
|
|
|
|
|
if (joystick->hwdata->has_key[BTN_DPAD_LEFT]) {
|
|
|
out->dpleft.kind = EMappingKind_Button;
|
|
|
out->dpleft.target = joystick->hwdata->key_map[BTN_DPAD_LEFT];
|
|
|
+ mapped |= 0x4;
|
|
|
}
|
|
|
|
|
|
if (joystick->hwdata->has_key[BTN_DPAD_RIGHT]) {
|
|
|
out->dpright.kind = EMappingKind_Button;
|
|
|
out->dpright.target = joystick->hwdata->key_map[BTN_DPAD_RIGHT];
|
|
|
- }
|
|
|
-
|
|
|
- if (joystick->hwdata->has_hat[0] && /* Check if ABS_HAT0{X,Y} is available. */
|
|
|
- (!joystick->hwdata->has_key[BTN_DPAD_LEFT] || !joystick->hwdata->has_key[BTN_DPAD_RIGHT] ||
|
|
|
- !joystick->hwdata->has_key[BTN_DPAD_UP] || !joystick->hwdata->has_key[BTN_DPAD_DOWN])) {
|
|
|
- int hat = joystick->hwdata->hats_indices[0] << 4;
|
|
|
- out->dpleft.kind = EMappingKind_Hat;
|
|
|
- out->dpright.kind = EMappingKind_Hat;
|
|
|
- out->dpup.kind = EMappingKind_Hat;
|
|
|
- out->dpdown.kind = EMappingKind_Hat;
|
|
|
- out->dpleft.target = hat | 0x8;
|
|
|
- out->dpright.target = hat | 0x2;
|
|
|
- out->dpup.target = hat | 0x1;
|
|
|
- out->dpdown.target = hat | 0x4;
|
|
|
+ mapped |= 0x8;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mapped != 0xF) {
|
|
|
+ if (joystick->hwdata->has_hat[0]) {
|
|
|
+ int hat = joystick->hwdata->hats_indices[0] << 4;
|
|
|
+ out->dpleft.kind = EMappingKind_Hat;
|
|
|
+ out->dpright.kind = EMappingKind_Hat;
|
|
|
+ out->dpup.kind = EMappingKind_Hat;
|
|
|
+ out->dpdown.kind = EMappingKind_Hat;
|
|
|
+ out->dpleft.target = hat | 0x8;
|
|
|
+ out->dpright.target = hat | 0x2;
|
|
|
+ out->dpup.target = hat | 0x1;
|
|
|
+ out->dpdown.target = hat | 0x4;
|
|
|
+ mapped |= 0xF;
|
|
|
+ } else if (joystick->hwdata->has_abs[ABS_HAT0X] && joystick->hwdata->has_abs[ABS_HAT0Y]) {
|
|
|
+ out->dpleft.kind = EMappingKind_Axis;
|
|
|
+ out->dpright.kind = EMappingKind_Axis;
|
|
|
+ out->dpup.kind = EMappingKind_Axis;
|
|
|
+ out->dpdown.kind = EMappingKind_Axis;
|
|
|
+ out->dpleft.target = joystick->hwdata->abs_map[ABS_HAT0X];
|
|
|
+ out->dpright.target = joystick->hwdata->abs_map[ABS_HAT0X];
|
|
|
+ out->dpup.target = joystick->hwdata->abs_map[ABS_HAT0Y];
|
|
|
+ out->dpdown.target = joystick->hwdata->abs_map[ABS_HAT0Y];
|
|
|
+ mapped |= 0xF;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (joystick->hwdata->has_abs[ABS_X] && joystick->hwdata->has_abs[ABS_Y]) {
|