added hueristic to differentiate digital vs analog 'hat' input axes and expose the latter as regular axes; added automatic deadzones to hat outputs, in case analog axes are still mapped to digital hats; updated automatic gamepad control mapping to more completely follow the spec
parent
fbd230bb6c
commit
0b8e796e2c
|
@ -78,7 +78,7 @@
|
||||||
#include "../../core/linux/SDL_evdev_capabilities.h"
|
#include "../../core/linux/SDL_evdev_capabilities.h"
|
||||||
#include "../../core/linux/SDL_udev.h"
|
#include "../../core/linux/SDL_udev.h"
|
||||||
|
|
||||||
#if 0
|
#if 1
|
||||||
#define DEBUG_INPUT_EVENTS 1
|
#define DEBUG_INPUT_EVENTS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -926,6 +926,33 @@ allocate_balldata(SDL_Joystick *joystick)
|
||||||
return (0);
|
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
|
static void
|
||||||
ConfigJoystick(SDL_Joystick *joystick, int fd)
|
ConfigJoystick(SDL_Joystick *joystick, int fd)
|
||||||
{
|
{
|
||||||
|
@ -963,10 +990,43 @@ ConfigJoystick(SDL_Joystick *joystick, int fd)
|
||||||
++joystick->nbuttons;
|
++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) {
|
for (i = 0; i < ABS_MAX; ++i) {
|
||||||
/* Skip hats */
|
/* Skip digital hats */
|
||||||
if (i == ABS_HAT0X) {
|
if (joystick->hwdata->has_hat[(i - ABS_HAT0X) / 2]) {
|
||||||
i = ABS_HAT3Y;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (test_bit(i, absbit)) {
|
if (test_bit(i, absbit)) {
|
||||||
|
@ -978,9 +1038,9 @@ ConfigJoystick(SDL_Joystick *joystick, int fd)
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_INPUT_EVENTS
|
#ifdef DEBUG_INPUT_EVENTS
|
||||||
SDL_Log("Joystick has absolute axis: 0x%.2x\n", i);
|
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.value, absinfo.minimum, absinfo.maximum,
|
||||||
absinfo.fuzz, absinfo.flat);
|
absinfo.fuzz, absinfo.flat, absinfo.resolution);
|
||||||
#endif /* DEBUG_INPUT_EVENTS */
|
#endif /* DEBUG_INPUT_EVENTS */
|
||||||
joystick->hwdata->abs_map[i] = joystick->naxes;
|
joystick->hwdata->abs_map[i] = joystick->naxes;
|
||||||
joystick->hwdata->has_abs[i] = SDL_TRUE;
|
joystick->hwdata->has_abs[i] = SDL_TRUE;
|
||||||
|
@ -1008,24 +1068,6 @@ ConfigJoystick(SDL_Joystick *joystick, int fd)
|
||||||
++joystick->naxes;
|
++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)) {
|
if (test_bit(REL_X, relbit) || test_bit(REL_Y, relbit)) {
|
||||||
++joystick->nballs;
|
++joystick->nballs;
|
||||||
}
|
}
|
||||||
|
@ -1071,14 +1113,19 @@ ConfigJoystick(SDL_Joystick *joystick, int fd)
|
||||||
for (i = 0; i < abs_pam_size; ++i) {
|
for (i = 0; i < abs_pam_size; ++i) {
|
||||||
Uint8 code = joystick->hwdata->abs_pam[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) {
|
if (code >= ABS_HAT0X && code <= ABS_HAT3Y) {
|
||||||
int hat_index = (code - ABS_HAT0X) / 2;
|
int hat_index = (code - ABS_HAT0X) / 2;
|
||||||
if (!joystick->hwdata->has_hat[hat_index]) {
|
if (!joystick->hwdata->has_hat[hat_index]) {
|
||||||
#ifdef DEBUG_INPUT_EVENTS
|
#ifdef DEBUG_INPUT_EVENTS
|
||||||
SDL_Log("Joystick has hat %d\n", hat_index);
|
SDL_Log("Joystick has hat: %d\n", hat_index);
|
||||||
#endif
|
#endif
|
||||||
joystick->hwdata->hats_indices[hat_index] = joystick->nhats++;
|
joystick->hwdata->hats_indices[hat_index] = joystick->nhats++;
|
||||||
joystick->hwdata->has_hat[hat_index] = SDL_TRUE;
|
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 {
|
} else {
|
||||||
#ifdef DEBUG_INPUT_EVENTS
|
#ifdef DEBUG_INPUT_EVENTS
|
||||||
|
@ -1277,26 +1324,47 @@ LINUX_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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 hwdata_hat *the_hat;
|
||||||
|
struct hat_axis_correct *correct;
|
||||||
const Uint8 position_map[3][3] = {
|
const Uint8 position_map[3][3] = {
|
||||||
{SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP},
|
{SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP},
|
||||||
{SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT},
|
{SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT},
|
||||||
{SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN}
|
{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) {
|
if (value < 0) {
|
||||||
value = 0;
|
if (value <= correct->minimum[axis]) {
|
||||||
} else if (value == 0) {
|
correct->minimum[axis] = value;
|
||||||
value = 1;
|
value = 0;
|
||||||
|
} else if (value < correct->minimum[axis] / 2) {
|
||||||
|
value = 0;
|
||||||
|
} else {
|
||||||
|
value = 1;
|
||||||
|
}
|
||||||
} else if (value > 0) {
|
} 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]) {
|
if (value != the_hat->axis[axis]) {
|
||||||
the_hat->axis[axis] = value;
|
the_hat->axis[axis] = value;
|
||||||
SDL_PrivateJoystickHat(stick, hat,
|
SDL_PrivateJoystickHat(stick, hatnum,
|
||||||
position_map[the_hat->axis[1]][the_hat->axis[0]]);
|
position_map[the_hat->axis[1]][the_hat->axis[0]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1351,10 +1419,7 @@ PollAllValues(SDL_Joystick *joystick)
|
||||||
|
|
||||||
/* Poll all axis */
|
/* Poll all axis */
|
||||||
for (i = ABS_X; i < ABS_MAX; i++) {
|
for (i = ABS_X; i < ABS_MAX; i++) {
|
||||||
if (i == ABS_HAT0X) { /* we handle hats in the next loop, skip them for now. */
|
/* We don't need to test for digital hats here, they won't have has_abs[] set */
|
||||||
i = ABS_HAT3Y;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (joystick->hwdata->has_abs[i]) {
|
if (joystick->hwdata->has_abs[i]) {
|
||||||
if (ioctl(joystick->hwdata->fd, EVIOCGABS(i), &absinfo) >= 0) {
|
if (ioctl(joystick->hwdata->fd, EVIOCGABS(i), &absinfo) >= 0) {
|
||||||
absinfo.value = AxisCorrect(joystick, i, absinfo.value);
|
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++) {
|
for (i = ABS_HAT0X; i <= ABS_HAT3Y; i++) {
|
||||||
const int baseaxis = i - ABS_HAT0X;
|
const int baseaxis = i - ABS_HAT0X;
|
||||||
const int hatidx = baseaxis / 2;
|
const int hatidx = baseaxis / 2;
|
||||||
SDL_assert(hatidx < SDL_arraysize(joystick->hwdata->has_hat));
|
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 (joystick->hwdata->has_hat[hatidx]) {
|
||||||
if (ioctl(joystick->hwdata->fd, EVIOCGABS(i), &absinfo) >= 0) {
|
if (ioctl(joystick->hwdata->fd, EVIOCGABS(i), &absinfo) >= 0) {
|
||||||
const int hataxis = baseaxis % 2;
|
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)
|
HandleInputEvents(SDL_Joystick *joystick)
|
||||||
{
|
{
|
||||||
struct input_event events[32];
|
struct input_event events[32];
|
||||||
int i, len, code;
|
int i, len, code, hat_index;
|
||||||
|
|
||||||
if (joystick->hwdata->fresh) {
|
if (joystick->hwdata->fresh) {
|
||||||
PollAllValues(joystick);
|
PollAllValues(joystick);
|
||||||
|
@ -1441,9 +1507,11 @@ HandleInputEvents(SDL_Joystick *joystick)
|
||||||
case ABS_HAT2Y:
|
case ABS_HAT2Y:
|
||||||
case ABS_HAT3X:
|
case ABS_HAT3X:
|
||||||
case ABS_HAT3Y:
|
case ABS_HAT3Y:
|
||||||
code -= ABS_HAT0X;
|
hat_index = (code - ABS_HAT0X) / 2;
|
||||||
HandleHat(joystick, joystick->hwdata->hats_indices[code / 2], code % 2, events[i].value);
|
if (joystick->hwdata->has_hat[hat_index]) {
|
||||||
break;
|
HandleHat(joystick, hat_index, code % 2, events[i].value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
events[i].value = AxisCorrect(joystick, code, events[i].value);
|
events[i].value = AxisCorrect(joystick, code, events[i].value);
|
||||||
SDL_PrivateJoystickAxis(joystick,
|
SDL_PrivateJoystickAxis(joystick,
|
||||||
|
@ -1496,7 +1564,7 @@ static void
|
||||||
HandleClassicEvents(SDL_Joystick *joystick)
|
HandleClassicEvents(SDL_Joystick *joystick)
|
||||||
{
|
{
|
||||||
struct js_event events[32];
|
struct js_event events[32];
|
||||||
int i, len, code;
|
int i, len, code, hat_index;
|
||||||
|
|
||||||
joystick->hwdata->fresh = SDL_FALSE;
|
joystick->hwdata->fresh = SDL_FALSE;
|
||||||
while ((len = read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
|
while ((len = read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
|
||||||
|
@ -1520,9 +1588,11 @@ HandleClassicEvents(SDL_Joystick *joystick)
|
||||||
case ABS_HAT2Y:
|
case ABS_HAT2Y:
|
||||||
case ABS_HAT3X:
|
case ABS_HAT3X:
|
||||||
case ABS_HAT3Y:
|
case ABS_HAT3Y:
|
||||||
code -= ABS_HAT0X;
|
hat_index = (code - ABS_HAT0X) / 2;
|
||||||
HandleHat(joystick, joystick->hwdata->hats_indices[code / 2], code % 2, events[i].value);
|
if (joystick->hwdata->has_hat[hat_index]) {
|
||||||
break;
|
HandleHat(joystick, hat_index, code % 2, events[i].value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
SDL_PrivateJoystickAxis(joystick,
|
SDL_PrivateJoystickAxis(joystick,
|
||||||
joystick->hwdata->abs_map[code],
|
joystick->hwdata->abs_map[code],
|
||||||
|
@ -1628,6 +1698,7 @@ LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
|
||||||
{
|
{
|
||||||
SDL_Joystick *joystick;
|
SDL_Joystick *joystick;
|
||||||
SDL_joylist_item *item = JoystickByDevIndex(device_index);
|
SDL_joylist_item *item = JoystickByDevIndex(device_index);
|
||||||
|
unsigned int mapped;
|
||||||
|
|
||||||
if (item->checked_mapping) {
|
if (item->checked_mapping) {
|
||||||
if (item->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.
|
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]) {
|
if (joystick->hwdata->has_key[BTN_TL]) {
|
||||||
out->leftshoulder.kind = EMappingKind_Button;
|
out->leftshoulder.kind = EMappingKind_Button;
|
||||||
out->leftshoulder.target = joystick->hwdata->key_map[BTN_TL];
|
out->leftshoulder.target = joystick->hwdata->key_map[BTN_TL];
|
||||||
|
mapped |= 0x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (joystick->hwdata->has_key[BTN_TR]) {
|
if (joystick->hwdata->has_key[BTN_TR]) {
|
||||||
out->rightshoulder.kind = EMappingKind_Button;
|
out->rightshoulder.kind = EMappingKind_Button;
|
||||||
out->rightshoulder.target = joystick->hwdata->key_map[BTN_TR];
|
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. */
|
if (mapped != 0x3 && joystick->hwdata->has_hat[1]) {
|
||||||
(!joystick->hwdata->has_key[BTN_TL] || !joystick->hwdata->has_key[BTN_TR])) {
|
|
||||||
int hat = joystick->hwdata->hats_indices[1] << 4;
|
int hat = joystick->hwdata->hats_indices[1] << 4;
|
||||||
out->leftshoulder.kind = EMappingKind_Hat;
|
out->leftshoulder.kind = EMappingKind_Hat;
|
||||||
out->rightshoulder.kind = EMappingKind_Hat;
|
out->rightshoulder.kind = EMappingKind_Hat;
|
||||||
out->leftshoulder.target = hat | 0x4;
|
out->leftshoulder.target = hat | 0x4;
|
||||||
out->rightshoulder.target = hat | 0x2;
|
out->rightshoulder.target = hat | 0x2;
|
||||||
|
mapped |= 0x3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prefer analog triggers, but settle for digital if missing. */
|
if (!(mapped & 0x1) && joystick->hwdata->has_abs[ABS_HAT1Y]) {
|
||||||
if (joystick->hwdata->has_hat[2]) { /* Check if ABS_HAT2{X,Y} is available. */
|
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 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;
|
int hat = joystick->hwdata->hats_indices[2] << 4;
|
||||||
out->lefttrigger.kind = EMappingKind_Hat;
|
out->lefttrigger.kind = EMappingKind_Hat;
|
||||||
out->righttrigger.kind = EMappingKind_Hat;
|
out->righttrigger.kind = EMappingKind_Hat;
|
||||||
out->lefttrigger.target = hat | 0x4;
|
out->lefttrigger.target = hat | 0x4;
|
||||||
out->righttrigger.target = hat | 0x2;
|
out->righttrigger.target = hat | 0x2;
|
||||||
} else {
|
mapped |= 0x3;
|
||||||
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];
|
|
||||||
}
|
|
||||||
|
|
||||||
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];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prefer digital D-Pad, but settle for analog if missing. */
|
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 buttons, but settle for digital or analog hat. */
|
||||||
|
mapped = 0;
|
||||||
|
|
||||||
if (joystick->hwdata->has_key[BTN_DPAD_UP]) {
|
if (joystick->hwdata->has_key[BTN_DPAD_UP]) {
|
||||||
out->dpup.kind = EMappingKind_Button;
|
out->dpup.kind = EMappingKind_Button;
|
||||||
out->dpup.target = joystick->hwdata->key_map[BTN_DPAD_UP];
|
out->dpup.target = joystick->hwdata->key_map[BTN_DPAD_UP];
|
||||||
|
mapped |= 0x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (joystick->hwdata->has_key[BTN_DPAD_DOWN]) {
|
if (joystick->hwdata->has_key[BTN_DPAD_DOWN]) {
|
||||||
out->dpdown.kind = EMappingKind_Button;
|
out->dpdown.kind = EMappingKind_Button;
|
||||||
out->dpdown.target = joystick->hwdata->key_map[BTN_DPAD_DOWN];
|
out->dpdown.target = joystick->hwdata->key_map[BTN_DPAD_DOWN];
|
||||||
|
mapped |= 0x2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (joystick->hwdata->has_key[BTN_DPAD_LEFT]) {
|
if (joystick->hwdata->has_key[BTN_DPAD_LEFT]) {
|
||||||
out->dpleft.kind = EMappingKind_Button;
|
out->dpleft.kind = EMappingKind_Button;
|
||||||
out->dpleft.target = joystick->hwdata->key_map[BTN_DPAD_LEFT];
|
out->dpleft.target = joystick->hwdata->key_map[BTN_DPAD_LEFT];
|
||||||
|
mapped |= 0x4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (joystick->hwdata->has_key[BTN_DPAD_RIGHT]) {
|
if (joystick->hwdata->has_key[BTN_DPAD_RIGHT]) {
|
||||||
out->dpright.kind = EMappingKind_Button;
|
out->dpright.kind = EMappingKind_Button;
|
||||||
out->dpright.target = joystick->hwdata->key_map[BTN_DPAD_RIGHT];
|
out->dpright.target = joystick->hwdata->key_map[BTN_DPAD_RIGHT];
|
||||||
|
mapped |= 0x8;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (joystick->hwdata->has_hat[0] && /* Check if ABS_HAT0{X,Y} is available. */
|
if (mapped != 0xF) {
|
||||||
(!joystick->hwdata->has_key[BTN_DPAD_LEFT] || !joystick->hwdata->has_key[BTN_DPAD_RIGHT] ||
|
if (joystick->hwdata->has_hat[0]) {
|
||||||
!joystick->hwdata->has_key[BTN_DPAD_UP] || !joystick->hwdata->has_key[BTN_DPAD_DOWN])) {
|
int hat = joystick->hwdata->hats_indices[0] << 4;
|
||||||
int hat = joystick->hwdata->hats_indices[0] << 4;
|
out->dpleft.kind = EMappingKind_Hat;
|
||||||
out->dpleft.kind = EMappingKind_Hat;
|
out->dpright.kind = EMappingKind_Hat;
|
||||||
out->dpright.kind = EMappingKind_Hat;
|
out->dpup.kind = EMappingKind_Hat;
|
||||||
out->dpup.kind = EMappingKind_Hat;
|
out->dpdown.kind = EMappingKind_Hat;
|
||||||
out->dpdown.kind = EMappingKind_Hat;
|
out->dpleft.target = hat | 0x8;
|
||||||
out->dpleft.target = hat | 0x8;
|
out->dpright.target = hat | 0x2;
|
||||||
out->dpright.target = hat | 0x2;
|
out->dpup.target = hat | 0x1;
|
||||||
out->dpup.target = hat | 0x1;
|
out->dpdown.target = hat | 0x4;
|
||||||
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]) {
|
if (joystick->hwdata->has_abs[ABS_X] && joystick->hwdata->has_abs[ABS_Y]) {
|
||||||
|
|
|
@ -83,6 +83,11 @@ struct joystick_hwdata
|
||||||
/* 4 = (ABS_HAT3X-ABS_HAT0X)/2 (see input-event-codes.h in kernel) */
|
/* 4 = (ABS_HAT3X-ABS_HAT0X)/2 (see input-event-codes.h in kernel) */
|
||||||
int hats_indices[4];
|
int hats_indices[4];
|
||||||
SDL_bool has_hat[4];
|
SDL_bool has_hat[4];
|
||||||
|
struct hat_axis_correct
|
||||||
|
{
|
||||||
|
int minimum[2];
|
||||||
|
int maximum[2];
|
||||||
|
} hat_correct[4];
|
||||||
|
|
||||||
/* Set when gamepad is pending removal due to ENODEV read error */
|
/* Set when gamepad is pending removal due to ENODEV read error */
|
||||||
SDL_bool gone;
|
SDL_bool gone;
|
||||||
|
|
Loading…
Reference in New Issue