diff --git a/panda/src/device/ioKitInputDevice.cxx b/panda/src/device/ioKitInputDevice.cxx index 3b18b3546c..85269d49e6 100644 --- a/panda/src/device/ioKitInputDevice.cxx +++ b/panda/src/device/ioKitInputDevice.cxx @@ -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) {