diff --git a/src/gamepad/linux_gamepad.cpp b/src/gamepad/linux_gamepad.cpp index 59b4bfc..0f0c1e6 100644 --- a/src/gamepad/linux_gamepad.cpp +++ b/src/gamepad/linux_gamepad.cpp @@ -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; @@ -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; } @@ -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]); @@ -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; } @@ -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}; @@ -369,6 +381,7 @@ struct GamepadProvider { SourceData *sourcedata = static_cast(data); GamepadProvider& self = *(sourcedata->first); + int32_t gamepad_id = sourcedata->second; if (condition & (G_IO_HUP | G_IO_ERR)) { self.closeGamepad(gamepad_id); @@ -572,8 +585,9 @@ void GamepadProvider::updateGamepad(GamepadInfo& info, std::vector 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; @@ -584,12 +598,12 @@ void GamepadProvider::updateGamepad(GamepadInfo& info, std::vector { // 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; @@ -599,6 +613,32 @@ void GamepadProvider::updateGamepad(GamepadInfo& info, std::vector 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); @@ -611,8 +651,10 @@ void GamepadProvider::updateGamepad(GamepadInfo& info, std::vector 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; }; @@ -628,6 +670,9 @@ void GamepadProvider::updateGamepad(GamepadInfo& info, std::vector } 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