mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-29 16:20:11 -04:00
device: support for Steam Controller on Linux
Adds lgrip and rgrip button handles, which are present on Steam Controller but also on the Oculus Touch
This commit is contained in:
parent
4699dfcd5b
commit
f3ba1d317c
@ -57,6 +57,9 @@ enum QuirkBits {
|
|||||||
|
|
||||||
// ABS_THROTTLE maps to rudder
|
// ABS_THROTTLE maps to rudder
|
||||||
QB_rudder_from_throttle = 16,
|
QB_rudder_from_throttle = 16,
|
||||||
|
|
||||||
|
// Special handling for Steam Controller, which has many peculiarities.
|
||||||
|
QB_steam_controller = 32,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct DeviceMapping {
|
static const struct DeviceMapping {
|
||||||
@ -71,6 +74,10 @@ static const struct DeviceMapping {
|
|||||||
{0x044f, 0xb108, InputDevice::DeviceClass::flight_stick, QB_centered_throttle | QB_reversed_throttle | QB_rudder_from_throttle},
|
{0x044f, 0xb108, InputDevice::DeviceClass::flight_stick, QB_centered_throttle | QB_reversed_throttle | QB_rudder_from_throttle},
|
||||||
// Xbox 360 Wireless Controller
|
// Xbox 360 Wireless Controller
|
||||||
{0x045e, 0x0719, InputDevice::DeviceClass::gamepad, QB_connect_if_nonzero},
|
{0x045e, 0x0719, InputDevice::DeviceClass::gamepad, QB_connect_if_nonzero},
|
||||||
|
// Steam Controller (wired)
|
||||||
|
{0x28de, 0x1102, InputDevice::DeviceClass::unknown, QB_steam_controller},
|
||||||
|
// Steam Controller (wireless)
|
||||||
|
{0x28de, 0x1142, InputDevice::DeviceClass::unknown, QB_steam_controller},
|
||||||
// Jess Tech Colour Rumble Pad
|
// Jess Tech Colour Rumble Pad
|
||||||
{0x0f30, 0x0111, InputDevice::DeviceClass::gamepad, 0},
|
{0x0f30, 0x0111, InputDevice::DeviceClass::gamepad, 0},
|
||||||
// Trust GXT 24
|
// Trust GXT 24
|
||||||
@ -299,6 +306,13 @@ init_device() {
|
|||||||
++mapping;
|
++mapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The Steam Controller reports as multiple devices, one of which a gamepad.
|
||||||
|
if (quirks & QB_steam_controller) {
|
||||||
|
if (test_bit(BTN_GAMEPAD, keys)) {
|
||||||
|
_device_class = DeviceClass::gamepad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Try to detect which type of device we have here
|
// Try to detect which type of device we have here
|
||||||
if (_device_class == DeviceClass::unknown) {
|
if (_device_class == DeviceClass::unknown) {
|
||||||
int device_scores[(size_t)DeviceClass::spatial_mouse] = {0};
|
int device_scores[(size_t)DeviceClass::spatial_mouse] = {0};
|
||||||
@ -378,7 +392,7 @@ init_device() {
|
|||||||
for (int i = 0; i <= KEY_MAX; ++i) {
|
for (int i = 0; i <= KEY_MAX; ++i) {
|
||||||
if (test_bit(i, keys)) {
|
if (test_bit(i, keys)) {
|
||||||
ButtonState button;
|
ButtonState button;
|
||||||
button.handle = map_button(i, _device_class);
|
button.handle = map_button(i, _device_class, quirks);
|
||||||
|
|
||||||
int button_index = (int)_buttons.size();
|
int button_index = (int)_buttons.size();
|
||||||
if (button.handle == ButtonHandle::none()) {
|
if (button.handle == ButtonHandle::none()) {
|
||||||
@ -527,6 +541,18 @@ init_device() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ABS_HAT2X:
|
||||||
|
if (quirks & QB_steam_controller) {
|
||||||
|
axis = InputDevice::Axis::right_trigger;
|
||||||
|
have_analog_triggers = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ABS_HAT2Y:
|
||||||
|
if (quirks & QB_steam_controller) {
|
||||||
|
axis = InputDevice::Axis::left_trigger;
|
||||||
|
have_analog_triggers = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the initial value and ranges.
|
// Check the initial value and ranges.
|
||||||
@ -740,7 +766,7 @@ process_events() {
|
|||||||
* Static function to map an evdev code to a ButtonHandle.
|
* Static function to map an evdev code to a ButtonHandle.
|
||||||
*/
|
*/
|
||||||
ButtonHandle EvdevInputDevice::
|
ButtonHandle EvdevInputDevice::
|
||||||
map_button(int code, DeviceClass device_class) {
|
map_button(int code, DeviceClass device_class, int quirks) {
|
||||||
if (code >= 0 && code < 0x80) {
|
if (code >= 0 && code < 0x80) {
|
||||||
// See linux/input.h for the source of this mapping.
|
// See linux/input.h for the source of this mapping.
|
||||||
static const ButtonHandle keyboard_map[] = {
|
static const ButtonHandle keyboard_map[] = {
|
||||||
@ -897,7 +923,11 @@ map_button(int code, DeviceClass device_class) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else if ((code & 0xfff0) == BTN_JOYSTICK) {
|
} else if ((code & 0xfff0) == BTN_JOYSTICK) {
|
||||||
if (device_class == DeviceClass::gamepad) {
|
if (quirks & QB_steam_controller) {
|
||||||
|
// BTN_THUMB and BTN_THUMB2 detect touching the touchpads.
|
||||||
|
return ButtonHandle::none();
|
||||||
|
|
||||||
|
} else if (device_class == DeviceClass::gamepad) {
|
||||||
// Based on "Jess Tech Colour Rumble Pad"
|
// Based on "Jess Tech Colour Rumble Pad"
|
||||||
static const ButtonHandle mapping[] = {
|
static const ButtonHandle mapping[] = {
|
||||||
GamepadButton::face_x(),
|
GamepadButton::face_x(),
|
||||||
@ -991,6 +1021,13 @@ map_button(int code, DeviceClass device_class) {
|
|||||||
case BTN_TRIGGER_HAPPY4:
|
case BTN_TRIGGER_HAPPY4:
|
||||||
return GamepadButton::dpad_down();
|
return GamepadButton::dpad_down();
|
||||||
|
|
||||||
|
// The next two are for the Steam Controller's grip buttons.
|
||||||
|
case BTN_GEAR_DOWN:
|
||||||
|
return GamepadButton::lgrip();
|
||||||
|
|
||||||
|
case BTN_GEAR_UP:
|
||||||
|
return GamepadButton::rgrip();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return ButtonHandle::none();
|
return ButtonHandle::none();
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,9 @@ private:
|
|||||||
int _rtrigger_code;
|
int _rtrigger_code;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static ButtonHandle map_button(int code, DeviceClass device_class = DeviceClass::unknown);
|
static ButtonHandle map_button(int code,
|
||||||
|
DeviceClass device_class = DeviceClass::unknown,
|
||||||
|
int quirks = 0);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static TypeHandle get_class_type() {
|
static TypeHandle get_class_type() {
|
||||||
|
@ -113,6 +113,7 @@ open_device() {
|
|||||||
ioctl(_fd, JSIOCGNAME(sizeof(name)), name);
|
ioctl(_fd, JSIOCGNAME(sizeof(name)), name);
|
||||||
_name = name;
|
_name = name;
|
||||||
|
|
||||||
|
bool emulate_dpad = true;
|
||||||
bool have_analog_triggers = false;
|
bool have_analog_triggers = false;
|
||||||
|
|
||||||
// Get the number of axes.
|
// Get the number of axes.
|
||||||
@ -138,6 +139,8 @@ open_device() {
|
|||||||
_device_class = DeviceClass::gamepad;
|
_device_class = DeviceClass::gamepad;
|
||||||
} else if (handle == GamepadButton::trigger()) {
|
} else if (handle == GamepadButton::trigger()) {
|
||||||
_device_class = DeviceClass::flight_stick;
|
_device_class = DeviceClass::flight_stick;
|
||||||
|
} else if (handle == GamepadButton::dpad_left()) {
|
||||||
|
emulate_dpad = false;
|
||||||
} else if (handle == GamepadButton::ltrigger()) {
|
} else if (handle == GamepadButton::ltrigger()) {
|
||||||
_ltrigger_button = i;
|
_ltrigger_button = i;
|
||||||
} else if (handle == GamepadButton::rtrigger()) {
|
} else if (handle == GamepadButton::rtrigger()) {
|
||||||
@ -220,7 +223,7 @@ open_device() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ABS_HAT0X:
|
case ABS_HAT0X:
|
||||||
if (_dpad_left_button == -1) {
|
if (emulate_dpad) {
|
||||||
// Emulate D-Pad or hat switch.
|
// Emulate D-Pad or hat switch.
|
||||||
_dpad_x_axis = i;
|
_dpad_x_axis = i;
|
||||||
_dpad_left_button = (int)_buttons.size();
|
_dpad_left_button = (int)_buttons.size();
|
||||||
@ -236,7 +239,7 @@ open_device() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ABS_HAT0Y:
|
case ABS_HAT0Y:
|
||||||
if (_dpad_up_button == -1) {
|
if (emulate_dpad) {
|
||||||
// Emulate D-Pad.
|
// Emulate D-Pad.
|
||||||
_dpad_y_axis = i;
|
_dpad_y_axis = i;
|
||||||
_dpad_up_button = (int)_buttons.size();
|
_dpad_up_button = (int)_buttons.size();
|
||||||
@ -251,6 +254,18 @@ open_device() {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ABS_HAT2X:
|
||||||
|
if (_device_class == DeviceClass::gamepad) {
|
||||||
|
axis = InputDevice::Axis::right_trigger;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ABS_HAT2Y:
|
||||||
|
if (_device_class == DeviceClass::gamepad) {
|
||||||
|
axis = InputDevice::Axis::left_trigger;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (device_cat.is_debug()) {
|
if (device_cat.is_debug()) {
|
||||||
device_cat.debug() << "Unmapped /dev/input/js" << _index
|
device_cat.debug() << "Unmapped /dev/input/js" << _index
|
||||||
@ -278,7 +293,7 @@ open_device() {
|
|||||||
|
|
||||||
if (_ltrigger_button >= 0 && _rtrigger_button >= 0 && !have_analog_triggers) {
|
if (_ltrigger_button >= 0 && _rtrigger_button >= 0 && !have_analog_triggers) {
|
||||||
// Emulate analog triggers.
|
// Emulate analog triggers.
|
||||||
_ltrigger_control = (int)_axes.size();
|
_ltrigger_axis = (int)_axes.size();
|
||||||
add_axis(Axis::left_trigger, 0, 1, false);
|
add_axis(Axis::left_trigger, 0, 1, false);
|
||||||
add_axis(Axis::right_trigger, 0, 1, false);
|
add_axis(Axis::right_trigger, 0, 1, false);
|
||||||
} else {
|
} else {
|
||||||
@ -398,9 +413,9 @@ process_events() {
|
|||||||
|
|
||||||
if (events[i].type & JS_EVENT_BUTTON) {
|
if (events[i].type & JS_EVENT_BUTTON) {
|
||||||
if (index == _ltrigger_button) {
|
if (index == _ltrigger_button) {
|
||||||
axis_changed(_ltrigger_control, events[i].value);
|
axis_changed(_ltrigger_axis, events[i].value);
|
||||||
} else if (index == _rtrigger_button) {
|
} else if (index == _rtrigger_button) {
|
||||||
axis_changed(_ltrigger_control + 1, events[i].value);
|
axis_changed(_ltrigger_axis + 1, events[i].value);
|
||||||
}
|
}
|
||||||
button_changed(index, (events[i].value != 0));
|
button_changed(index, (events[i].value != 0));
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ private:
|
|||||||
int _dpad_up_button;
|
int _dpad_up_button;
|
||||||
|
|
||||||
// This is used for axis emulation.
|
// This is used for axis emulation.
|
||||||
int _ltrigger_control;
|
int _ltrigger_axis;
|
||||||
int _ltrigger_button;
|
int _ltrigger_button;
|
||||||
int _rtrigger_button;
|
int _rtrigger_button;
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@ DEFINE_GAMEPAD_BUTTON_HANDLE(lshoulder)
|
|||||||
DEFINE_GAMEPAD_BUTTON_HANDLE(rshoulder)
|
DEFINE_GAMEPAD_BUTTON_HANDLE(rshoulder)
|
||||||
DEFINE_GAMEPAD_BUTTON_HANDLE(ltrigger)
|
DEFINE_GAMEPAD_BUTTON_HANDLE(ltrigger)
|
||||||
DEFINE_GAMEPAD_BUTTON_HANDLE(rtrigger)
|
DEFINE_GAMEPAD_BUTTON_HANDLE(rtrigger)
|
||||||
|
DEFINE_GAMEPAD_BUTTON_HANDLE(lgrip)
|
||||||
|
DEFINE_GAMEPAD_BUTTON_HANDLE(rgrip)
|
||||||
|
|
||||||
DEFINE_GAMEPAD_BUTTON_HANDLE(dpad_left)
|
DEFINE_GAMEPAD_BUTTON_HANDLE(dpad_left)
|
||||||
DEFINE_GAMEPAD_BUTTON_HANDLE(dpad_right)
|
DEFINE_GAMEPAD_BUTTON_HANDLE(dpad_right)
|
||||||
@ -87,6 +89,8 @@ init_gamepad_buttons() {
|
|||||||
ButtonRegistry::ptr()->register_button(_rshoulder, "rshoulder");
|
ButtonRegistry::ptr()->register_button(_rshoulder, "rshoulder");
|
||||||
ButtonRegistry::ptr()->register_button(_ltrigger, "ltrigger");
|
ButtonRegistry::ptr()->register_button(_ltrigger, "ltrigger");
|
||||||
ButtonRegistry::ptr()->register_button(_rtrigger, "rtrigger");
|
ButtonRegistry::ptr()->register_button(_rtrigger, "rtrigger");
|
||||||
|
ButtonRegistry::ptr()->register_button(_lgrip, "lgrip");
|
||||||
|
ButtonRegistry::ptr()->register_button(_rgrip, "rgrip");
|
||||||
|
|
||||||
ButtonRegistry::ptr()->register_button(_dpad_left, "dpad_left");
|
ButtonRegistry::ptr()->register_button(_dpad_left, "dpad_left");
|
||||||
ButtonRegistry::ptr()->register_button(_dpad_right, "dpad_right");
|
ButtonRegistry::ptr()->register_button(_dpad_right, "dpad_right");
|
||||||
|
@ -30,6 +30,8 @@ PUBLISHED:
|
|||||||
static ButtonHandle rshoulder();
|
static ButtonHandle rshoulder();
|
||||||
static ButtonHandle ltrigger();
|
static ButtonHandle ltrigger();
|
||||||
static ButtonHandle rtrigger();
|
static ButtonHandle rtrigger();
|
||||||
|
static ButtonHandle lgrip();
|
||||||
|
static ButtonHandle rgrip();
|
||||||
|
|
||||||
static ButtonHandle dpad_left();
|
static ButtonHandle dpad_left();
|
||||||
static ButtonHandle dpad_right();
|
static ButtonHandle dpad_right();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user