Index: src/hid/OFGameController.h ================================================================== --- src/hid/OFGameController.h +++ src/hid/OFGameController.h @@ -245,10 +245,15 @@ /** * @brief The Mode button on a game controller. */ extern const OFGameControllerButton OFGameControllerModeButton; + +/** + * @brief The Assistant button on a game controller. + */ +extern const OFGameControllerButton OFGameControllerAssistantButton; #ifdef __cplusplus } #endif /** @@ -263,14 +268,16 @@ uint16_t _vendorID, _productID; OFString *_name; OFMutableSet *_buttons, *_pressedButtons; bool _hasLeftAnalogStick, _hasRightAnalogStick; bool _hasLeftTriggerPressure, _hasRightTriggerPressure; + unsigned int _leftTriggerPressureBit, _rightTriggerPressureBit; OFPoint _leftAnalogStickPosition, _rightAnalogStickPosition; float _leftTriggerPressure, _rightTriggerPressure; int32_t _leftAnalogStickMinX, _leftAnalogStickMaxX; int32_t _leftAnalogStickMinY, _leftAnalogStickMaxY; + unsigned int _rightAnalogStickXBit, _rightAnalogStickYBit; int32_t _rightAnalogStickMinX, _rightAnalogStickMaxX; int32_t _rightAnalogStickMinY, _rightAnalogStickMaxY; int32_t _leftTriggerMinPressure, _leftTriggerMaxPressure; int32_t _rightTriggerMinPressure, _rightTriggerMaxPressure; #elif defined(OF_NINTENDO_DS) Index: src/hid/OFGameController.m ================================================================== --- src/hid/OFGameController.m +++ src/hid/OFGameController.m @@ -57,10 +57,11 @@ const OFGameControllerButton OFGameControllerPlusButton = @"+"; const OFGameControllerButton OFGameControllerMinusButton = @"-"; const OFGameControllerButton OFGameControllerSLButton = @"SL"; const OFGameControllerButton OFGameControllerSRButton = @"SR"; const OFGameControllerButton OFGameControllerModeButton = @"Mode"; +const OFGameControllerButton OFGameControllerAssistantButton = @"Assistant"; #if defined(OF_LINUX) && defined(OF_HAVE_FILES) # include "platform/Linux/OFGameController.m" #elif defined(OF_WINDOWS) # include "platform/Windows/OFGameController.m" Index: src/hid/platform/Linux/OFGameController.m ================================================================== --- src/hid/platform/Linux/OFGameController.m +++ src/hid/platform/Linux/OFGameController.m @@ -46,15 +46,17 @@ * Joy-Con (L) [057E:2006] * Joy-Con (R) [057E:2007] * N64 Controller [057E:2019] * Sony Interactive Entertainment DualSense Wireless Controller [054C:0CE6] * 8BitDo Pro 2 Wired Controller [2DC8:3106] + * Stadia2SZY-0d6c [18D1:9400] */ static const uint16_t vendorIDMicrosoft = 0x045E; static const uint16_t vendorIDNintendo = 0x057E; static const uint16_t vendorIDSony = 0x054C; +static const uint16_t vendorIDGoogle = 0x18D1; /* Microsoft controllers */ static const uint16_t productIDXbox360 = 0x028E; /* Nintendo controllers */ @@ -63,18 +65,22 @@ static const uint16_t productIDN64Controller = 0x2019; /* Sony controllers */ static const uint16_t productIDDualSense = 0x0CE6; +/* Google controllers */ +static const uint16_t productIDStadia = 0x9400; + @interface OFGameController () - (instancetype)of_initWithPath: (OFString *)path OF_METHOD_FAMILY(init); @end static const uint16_t buttons[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_SELECT, BTN_START, BTN_MODE, BTN_THUMBL, BTN_THUMBR, - BTN_DPAD_UP, BTN_DPAD_DOWN, BTN_DPAD_LEFT, BTN_DPAD_RIGHT + BTN_DPAD_UP, BTN_DPAD_DOWN, BTN_DPAD_LEFT, BTN_DPAD_RIGHT, + BTN_TRIGGER_HAPPY1, BTN_TRIGGER_HAPPY2 }; static OFGameControllerButton buttonToName(uint16_t button, uint16_t vendorID, uint16_t productID) { @@ -127,10 +133,17 @@ switch (button) { case BTN_NORTH: return OFGameControllerNorthButton; case BTN_WEST: return OFGameControllerWestButton; + } + } else if (vendorID == vendorIDGoogle && productID == productIDStadia) { + switch (button) { + case BTN_TRIGGER_HAPPY1: + return OFGameControllerAssistantButton; + case BTN_TRIGGER_HAPPY2: + return OFGameControllerCaptureButton; } } switch (button) { case BTN_Y: @@ -288,22 +301,44 @@ _name = [[OFString alloc] initWithCString: name encoding: encoding]; _buttons = [[OFMutableSet alloc] init]; for (size_t i = 0; i < sizeof(buttons) / sizeof(*buttons); - i++) - if (OFBitSetIsSet(keyBits, buttons[i])) - [_buttons addObject: buttonToName( - buttons[i], _vendorID, _productID)]; + i++) { + if (OFBitSetIsSet(keyBits, buttons[i])) { + OFGameControllerButton button = buttonToName( + buttons[i], _vendorID, _productID); + + if (button != nil) + [_buttons addObject: button]; + } + } _pressedButtons = [[OFMutableSet alloc] init]; if (OFBitSetIsSet(evBits, EV_ABS)) { if (ioctl(_fd, EVIOCGBIT(EV_ABS, sizeof(absBits)), absBits) == -1) @throw [OFInitializationFailedException exception]; + + if (_vendorID == vendorIDGoogle && + _productID == productIDStadia) { + /* + * It's unclear how this can be screwed up + * *this* bad. + */ + _rightAnalogStickXBit = ABS_Z; + _rightAnalogStickYBit = ABS_RZ; + _leftTriggerPressureBit = ABS_BRAKE; + _rightTriggerPressureBit = ABS_GAS; + } else { + _rightAnalogStickXBit = ABS_RX; + _rightAnalogStickYBit = ABS_RY; + _leftTriggerPressureBit = ABS_Z; + _rightTriggerPressureBit = ABS_RZ; + } if (OFBitSetIsSet(absBits, ABS_X) && OFBitSetIsSet(absBits, ABS_Y)) { struct input_absinfo infoX, infoY; @@ -321,21 +356,23 @@ _leftAnalogStickMaxX = infoX.maximum; _leftAnalogStickMinY = infoY.minimum; _leftAnalogStickMaxY = infoY.maximum; } - if (OFBitSetIsSet(absBits, ABS_RX) && - OFBitSetIsSet(absBits, ABS_RY)) { + if (OFBitSetIsSet(absBits, _rightAnalogStickXBit) && + OFBitSetIsSet(absBits, _rightAnalogStickYBit)) { struct input_absinfo infoX, infoY; _hasRightAnalogStick = true; - if (ioctl(_fd, EVIOCGABS(ABS_RX), &infoX) == -1) + if (ioctl(_fd, EVIOCGABS(_rightAnalogStickXBit), + &infoX) == -1) @throw [OFInitializationFailedException exception]; - if (ioctl(_fd, EVIOCGABS(ABS_RY), &infoY) == -1) + if (ioctl(_fd, EVIOCGABS(_rightAnalogStickYBit), + &infoY) == -1) @throw [OFInitializationFailedException exception]; _rightAnalogStickMinX = infoX.minimum; _rightAnalogStickMaxX = infoX.maximum; @@ -353,16 +390,17 @@ OFGameControllerDPadUpButton]; [_buttons addObject: OFGameControllerDPadDownButton]; } - if (OFBitSetIsSet(absBits, ABS_Z)) { + if (OFBitSetIsSet(absBits, _leftTriggerPressureBit)) { struct input_absinfo info; _hasLeftTriggerPressure = true; - if (ioctl(_fd, EVIOCGABS(ABS_Z), &info) == -1) + if (ioctl(_fd, EVIOCGABS( + _leftTriggerPressureBit), &info) == -1) @throw [OFInitializationFailedException exception]; _leftTriggerMinPressure = info.minimum; _leftTriggerMaxPressure = info.maximum; @@ -369,16 +407,17 @@ [_buttons addObject: OFGameControllerLeftTriggerButton]; } - if (OFBitSetIsSet(absBits, ABS_RZ)) { + if (OFBitSetIsSet(absBits, _rightTriggerPressureBit)) { struct input_absinfo info; _hasRightTriggerPressure = true; - if (ioctl(_fd, EVIOCGABS(ABS_RZ), &info) == -1) + if (ioctl(_fd, EVIOCGABS( + _rightTriggerPressureBit), &info) == -1) @throw [OFInitializationFailedException exception]; _rightTriggerMinPressure = info.minimum; _rightTriggerMaxPressure = info.maximum; @@ -451,30 +490,25 @@ else [_pressedButtons removeObject: button]; } break; case EV_ABS: - switch (event.code) { - case ABS_X: + if (event.code == ABS_X) _leftAnalogStickPosition.x = scale(event.value, _leftAnalogStickMinX, _leftAnalogStickMaxX); - break; - case ABS_Y: + else if (event.code == ABS_Y) _leftAnalogStickPosition.y = scale(event.value, _leftAnalogStickMinY, _leftAnalogStickMaxY); - break; - case ABS_RX: + else if (event.code == _rightAnalogStickXBit) _rightAnalogStickPosition.x = scale(event.value, _rightAnalogStickMinX, _rightAnalogStickMaxX); - break; - case ABS_RY: + else if (event.code == _rightAnalogStickYBit) _rightAnalogStickPosition.y = scale(event.value, _rightAnalogStickMinY, _rightAnalogStickMaxY); - break; - case ABS_HAT0X: + else if (event.code == ABS_HAT0X) { if (event.value < 0) { [_pressedButtons addObject: OFGameControllerDPadLeftButton]; [_pressedButtons removeObject: OFGameControllerDPadRightButton]; @@ -487,12 +521,11 @@ [_pressedButtons removeObject: OFGameControllerDPadLeftButton]; [_pressedButtons removeObject: OFGameControllerDPadRightButton]; } - break; - case ABS_HAT0Y: + } else if (event.code == ABS_HAT0Y) { if (event.value < 0) { [_pressedButtons addObject: OFGameControllerDPadUpButton]; [_pressedButtons removeObject: OFGameControllerDPadDownButton]; @@ -505,12 +538,11 @@ [_pressedButtons removeObject: OFGameControllerDPadUpButton]; [_pressedButtons removeObject: OFGameControllerDPadDownButton]; } - break; - case ABS_Z: + } else if (event.code == _leftTriggerPressureBit) { _leftTriggerPressure = scale(event.value, _leftTriggerMinPressure, _leftTriggerMaxPressure); if (_leftTriggerPressure > 0) @@ -517,12 +549,11 @@ [_pressedButtons addObject: OFGameControllerLeftTriggerButton]; else [_pressedButtons removeObject: OFGameControllerLeftTriggerButton]; - break; - case ABS_RZ: + } else if (event.code == _rightTriggerPressureBit) { _rightTriggerPressure = scale(event.value, _rightTriggerMinPressure, _rightTriggerMaxPressure); if (_rightTriggerPressure > 0) @@ -529,13 +560,11 @@ [_pressedButtons addObject: OFGameControllerRightTriggerButton]; else [_pressedButtons removeObject: OFGameControllerRightTriggerButton]; - break; } - break; } } }