input: more device support on macOS (incl. SpaceNavigator)

This commit is contained in:
rdb 2018-02-04 11:01:06 +01:00
parent 6ada306184
commit c1fd2e46de
1 changed files with 77 additions and 27 deletions

View File

@ -46,8 +46,15 @@ IOKitInputDevice(IOHIDDeviceRef device) :
CFStringRef name = (CFStringRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
if (name) {
buffer[0] = 0;
CFStringGetCString(name, buffer, sizeof(buffer), kCFStringEncodingUTF8);
_name = buffer;
// Strip trailing spaces.
size_t len = strlen(buffer);
while (isspace(buffer[len - 1])) {
--len;
}
_name.assign(buffer, len);
}
CFStringRef mfg = (CFStringRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDManufacturerKey));
@ -89,6 +96,18 @@ IOKitInputDevice(IOHIDDeviceRef device) :
} else if (_vendor_id == 0x044f && _product_id == 0xb108) {
// T.Flight Hotas X
_device_class = DC_flight_stick;
} else if (_vendor_id == 0x046d &&
(_product_id == 0xc623 ||
_product_id == 0xc625 ||
_product_id == 0xc626 ||
_product_id == 0xc627 ||
_product_id == 0xc628 ||
_product_id == 0xc629 ||
_product_id == 0xc62b)) {
// 3Dconnexion SpaceNavigator and friends.
_device_class = DC_3d_mouse;
} else if (_name == "usb gamepad") {
_device_class = DC_gamepad;
}
CFArrayRef elements = IOHIDDeviceCopyMatchingElements(device, NULL, 0);
@ -189,15 +208,25 @@ parse_element(IOHIDElementRef element) {
case kHIDUsage_GD_Z:
if (_device_class == DC_gamepad) {
axis = C_left_trigger;
} else {
} else if (_device_class == DC_flight_stick) {
axis = C_throttle;
} else {
axis = C_z;
}
break;
case kHIDUsage_GD_Rx:
axis = C_right_x;
if (_device_class == DC_gamepad) {
axis = C_right_x;
} else {
axis = C_pitch;
}
break;
case kHIDUsage_GD_Ry:
axis = C_right_y;
if (_device_class == DC_gamepad) {
axis = C_right_y;
} else {
axis = C_roll;
}
break;
case kHIDUsage_GD_Rz:
if (_device_class == DC_gamepad) {
@ -259,7 +288,8 @@ parse_element(IOHIDElementRef element) {
if (_vendor_id == 0x044f && _product_id == 0xb108 && axis == C_throttle) {
// T.Flight Hotas X throttle is reversed and can go backwards.
add_control(axis, max, min, true);
} else if (axis == C_yaw || axis == C_left_y || axis == C_right_y) {
} else if (axis == C_yaw || axis == C_rudder || axis == C_left_y || axis == C_right_y ||
(_device_class == DC_3d_mouse && (axis == C_y || axis == C_z || axis == C_roll))) {
// We'd like to reverse the Y axis to match the XInput behavior.
// We also reverse yaw to obey the right-hand rule.
add_control(axis, max, min);
@ -598,28 +628,48 @@ parse_element(IOHIDElementRef element) {
case kHIDPage_Button:
if (_device_class == DC_gamepad) {
// These seem to be the button mappings exposed by the 360Controller
// driver I don't know if other drivers do the same thing at all.
static const ButtonHandle gamepad_buttons[] = {
ButtonHandle::none(),
GamepadButton::action_a(),
GamepadButton::action_b(),
GamepadButton::action_x(),
GamepadButton::action_y(),
GamepadButton::lshoulder(),
GamepadButton::rshoulder(),
GamepadButton::lstick(),
GamepadButton::rstick(),
GamepadButton::start(),
GamepadButton::back(),
GamepadButton::guide(),
GamepadButton::dpad_up(),
GamepadButton::dpad_down(),
GamepadButton::dpad_left(),
GamepadButton::dpad_right(),
};
if (usage < sizeof(gamepad_buttons) / sizeof(ButtonHandle)) {
handle = gamepad_buttons[usage];
if (_vendor_id == 0x0810 && _product_id == 0xe501) {
// SNES-style USB gamepad
static const ButtonHandle gamepad_buttons[] = {
ButtonHandle::none(),
GamepadButton::action_x(),
GamepadButton::action_a(),
GamepadButton::action_b(),
GamepadButton::action_y(),
GamepadButton::lshoulder(),
GamepadButton::rshoulder(),
ButtonHandle::none(),
ButtonHandle::none(),
GamepadButton::back(),
GamepadButton::start(),
};
if (usage < sizeof(gamepad_buttons) / sizeof(ButtonHandle)) {
handle = gamepad_buttons[usage];
}
} else {
// These seem to be the button mappings exposed by the 360Controller
// driver. I don't know if other drivers do the same thing at all.
static const ButtonHandle gamepad_buttons[] = {
ButtonHandle::none(),
GamepadButton::action_a(),
GamepadButton::action_b(),
GamepadButton::action_x(),
GamepadButton::action_y(),
GamepadButton::lshoulder(),
GamepadButton::rshoulder(),
GamepadButton::lstick(),
GamepadButton::rstick(),
GamepadButton::start(),
GamepadButton::back(),
GamepadButton::guide(),
GamepadButton::dpad_up(),
GamepadButton::dpad_down(),
GamepadButton::dpad_left(),
GamepadButton::dpad_right(),
};
if (usage < sizeof(gamepad_buttons) / sizeof(ButtonHandle)) {
handle = gamepad_buttons[usage];
}
}
} else if (_device_class == DC_flight_stick) {
if (usage > 0) {