Skip to content

Commit

Permalink
support xbox triggers
Browse files Browse the repository at this point in the history
  • Loading branch information
emutavchi committed Sep 6, 2020
1 parent 95171a4 commit 12e9725
Showing 1 changed file with 59 additions and 14 deletions.
73 changes: 59 additions & 14 deletions src/gamepad/linux_gamepad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,16 @@ static int32_t mapButtonId(int32_t code)
// buttons[3] Top button in right cluster
// buttons[4] Top left front button
// buttons[5] Top right front button
// buttons[6] Bottom left front button
// buttons[7] Bottom right front button
// buttons[6] Bottom left front button (trigger)
// buttons[7] Bottom right front button (trigger)
// buttons[8] Left button in center cluster
// buttons[9] Right button in center cluster
// buttons[10] Left stick pressed button
// buttons[11] Right stick pressed button
// buttons[12] Top button in left cluster
// buttons[13] Bottom button in left cluster
// buttons[14] Right button in left cluster
// buttons[15] Left button in left cluster
// buttons[14] Right button in left cluster
// buttons[15] Left button in left cluster

struct MapEntry {
const int32_t code;
Expand All @@ -107,18 +107,28 @@ static int32_t mapButtonId(int32_t code)
{ BTN_TR2, 7 },
{ BTN_SELECT, 8 },
{ BTN_START, 9 },
{ BTN_THUMBL, 10 },
{ BTN_THUMBR, 11 },
{ BTN_THUMBL, 10 }, // stick pressed button
{ BTN_THUMBR, 11 }, // stick pressed button
{ ABS_HAT0Y, 12 },
{ ABS_HAT0X, 14 }
{ ABS_HAT0X, 14 },

// TODO: Add configurable re-mapping for any controller
//
// Append: XBOX Wireless Controller
//
{ ABS_BRAKE, 6 }, // trigger
{ ABS_GAS, 7 }, // trigger
{ KEY_BACK, 8 } // Left center "menu/start" button

};

static const size_t mapSize = sizeof(map)/sizeof(map[0]);

for (int i = 0; i < mapSize; ++i)
{
if (code == map[i].code)
return map[i].id;

}
return -1;
}

Expand All @@ -137,7 +147,7 @@ static int mapAxisId(int32_t code)
{ ABS_X, 0 },
{ ABS_Y, 1 },
{ ABS_Z, 2 },
{ ABS_RZ, 3 }
{ ABS_RZ, 3 },
};

static const size_t mapSize = sizeof(map)/sizeof(map[0]);
Expand All @@ -164,8 +174,10 @@ static double mapAxisValue(int32_t val, int32_t min, int32_t max)
double offset = (max + min) / (kMappedMax - kMappedMin) * scale * kMappedMin;
double mappedVal = val * scale + offset;
mappedVal = clamp(mappedVal, kMappedMin, kMappedMax);

if (mappedVal < 0.009 && mappedVal > -0.009)
return 0.0;
mappedVal = 0.0;

return mappedVal;
}

Expand Down Expand Up @@ -304,7 +316,7 @@ struct GamepadProvider
if (fd < 0)
return false;

unsigned long ev_bits[NBITS(EV_CNT)] = {0};
unsigned long ev_bits[NBITS( EV_CNT)] = {0};
unsigned long key_bits[NBITS(KEY_CNT)] = {0};
unsigned long abs_bits[NBITS(ABS_CNT)] = {0};

Expand Down Expand Up @@ -369,6 +381,7 @@ struct GamepadProvider
{
SourceData *sourcedata = static_cast<SourceData*>(data);
GamepadProvider& self = *(sourcedata->first);

int32_t gamepad_id = sourcedata->second;
if (condition & (G_IO_HUP | G_IO_ERR)) {
self.closeGamepad(gamepad_id);
Expand Down Expand Up @@ -572,8 +585,9 @@ void GamepadProvider::updateGamepad(GamepadInfo& info, std::vector<input_event>
const auto updateButtonValue = [&info, &buttonValuesChanged] (int32_t code, int32_t value)
{
const int32_t button_id = mapButtonId(code);

if (button_id < 0 || button_id >= info.buttonValues.size()) {
g_warning("unmapped button code: %d \n", code);
g_warning("unmapped button code: %d 0x%04X\n", code, code);
return;
}
info.buttonValues[button_id] = value == 0 ? 0.0 : 1.0;
Expand All @@ -584,12 +598,12 @@ void GamepadProvider::updateGamepad(GamepadInfo& info, std::vector<input_event>
{
// todo: figure out a better to handle dpad
if (code != ABS_HAT0X && code != ABS_HAT0Y) {
g_warning("not supported code: %d \n", code);
g_warning("not supported code: %d 0x%04X\n", code, code);
return;
}
const int32_t idx_base = mapButtonId(code);
if ((idx_base < 0) || (idx_base + 1 >= info.buttonValues.size())) {
g_warning("unmapped button code: %d \n", code);
g_warning("unmapped button code: %d 0x%04X\n", code, code);
return;
}
info.buttonValues[idx_base] = 0.0;
Expand All @@ -599,6 +613,32 @@ void GamepadProvider::updateGamepad(GamepadInfo& info, std::vector<input_event>
buttonValuesChanged = true;
};

const auto updateTriggerValue = [&info, &buttonValuesChanged] (int32_t code, int32_t value)
{
const int32_t idx_base = mapButtonId(code);
if ((idx_base < 0) || (idx_base + 1 >= info.buttonValues.size())) {
g_warning("unmapped trigger code: %d 0x%04X\n", code, code);
return;
}

auto info_iter = info.axisInfo.find(code);
if (info_iter == info.axisInfo.end()) {
g_warning("no trigger info: %d \n", code);
return;
}

const input_absinfo& axisInfo = info_iter->second;
double mapped = mapAxisValue(value, axisInfo.minimum, axisInfo.maximum);

// Need to Normalize values in [ -1 <-> 1 ] to [ 0 <-> 1 ]
//
// First [ -1 <-> 1 ] / 2 = [ -0.5 <-> 0.5 ]
// Then [ -0.5 <-> 0.5] + 0.5 = [ 0.0 <-> 1.0 ]
//
info.buttonValues[idx_base] = (mapped/2) + 0.5;
buttonValuesChanged = true;
};

const auto updateAxisValue = [&info, &axisValuesChanged] (int32_t code, int32_t value)
{
auto info_iter = info.axisInfo.find(code);
Expand All @@ -611,8 +651,10 @@ void GamepadProvider::updateGamepad(GamepadInfo& info, std::vector<input_event>
g_warning("unmapped axis code: %d \n", code);
return;
}

const input_absinfo& axisInfo = info_iter->second;
double mapped = mapAxisValue(value, axisInfo.minimum, axisInfo.maximum);

info.axisValues[axis_id] = mapped;
axisValuesChanged = true;
};
Expand All @@ -628,6 +670,9 @@ void GamepadProvider::updateGamepad(GamepadInfo& info, std::vector<input_event>
}
case EV_ABS:
{
if (event.code == ABS_GAS || event.code == ABS_BRAKE) // L/R triggers
updateTriggerValue(event.code, event.value);
else
if (event.code == ABS_HAT0X || event.code == ABS_HAT0Y)
updateDpadButtonValue(event.code, event.value);
else
Expand Down

0 comments on commit 12e9725

Please sign in to comment.