1 /*
2 * Copyright (C) 2014-2020 Garrett Brown
3 * Copyright (C) 2014-2020 Team Kodi
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSE.md for more information.
7 */
8
9 #include "JoystickXInput.h"
10 #include "JoystickInterfaceXInput.h"
11 #include "XInputDLL.h"
12 #include "api/JoystickTypes.h"
13
14 #include <Xinput.h>
15
16 using namespace JOYSTICK;
17
18 #define XINPUT_ALIAS "Xbox 360-compatible controller"
19 #define BUTTON_COUNT 15
20 #define HAT_COUNT 0 // hats are treated as buttons
21 #define AXIS_COUNT 6
22 #define MAX_AXIS 32768
23 #define MAX_TRIGGER 255
24 #define MAX_MOTOR 65535
25
CJoystickXInput(unsigned int controllerID)26 CJoystickXInput::CJoystickXInput(unsigned int controllerID)
27 : CJoystick(EJoystickInterface::XINPUT),
28 m_controllerID(controllerID),
29 m_dwPacketNumber(0)
30 {
31 SetName(XINPUT_ALIAS);
32 SetRequestedPort(m_controllerID);
33 SetButtonCount(BUTTON_COUNT);
34 SetHatCount(HAT_COUNT);
35 SetAxisCount(AXIS_COUNT);
36 SetMotorCount(MOTOR_COUNT);
37
38 m_motorSpeeds[MOTOR_LEFT] = 0.0f;
39 m_motorSpeeds[MOTOR_RIGHT] = 0.0f;
40
41 SetSupportsPowerOff(true);
42 }
43
Equals(const CJoystick * rhs) const44 bool CJoystickXInput::Equals(const CJoystick* rhs) const
45 {
46 if (rhs == nullptr)
47 return false;
48
49 const CJoystickXInput* rhsXInput = dynamic_cast<const CJoystickXInput*>(rhs);
50 if (rhsXInput == nullptr)
51 return false;
52
53 return m_controllerID == rhsXInput->m_controllerID;
54 }
55
PowerOff()56 void CJoystickXInput::PowerOff()
57 {
58 if (CXInputDLL::Get().Version() == "1.3")
59 CXInputDLL::Get().PowerOff(m_controllerID);
60 }
61
ScanEvents(void)62 bool CJoystickXInput::ScanEvents(void)
63 {
64 if (CXInputDLL::Get().Version() == "1.3")
65 {
66 XINPUT_STATE_EX controllerState;
67
68 if (!CXInputDLL::Get().GetStateWithGuide(m_controllerID, controllerState))
69 return false;
70
71 m_dwPacketNumber = controllerState.dwPacketNumber;
72
73 SetButtonValue(0, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_A) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
74 SetButtonValue(1, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_B) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
75 SetButtonValue(2, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_X) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
76 SetButtonValue(3, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_Y) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
77 SetButtonValue(4, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
78 SetButtonValue(5, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
79 SetButtonValue(6, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
80 SetButtonValue(7, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_START) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
81 SetButtonValue(8, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
82 SetButtonValue(9, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
83 SetButtonValue(10, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
84 SetButtonValue(11, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
85 SetButtonValue(12, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
86 SetButtonValue(13, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
87 SetButtonValue(14, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_GUIDE) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
88
89 SetAxisValue(0, (long)controllerState.Gamepad.sThumbLX, MAX_AXIS);
90 SetAxisValue(1, (long)controllerState.Gamepad.sThumbLY, MAX_AXIS);
91 SetAxisValue(2, (long)controllerState.Gamepad.sThumbRX, MAX_AXIS);
92 SetAxisValue(3, (long)controllerState.Gamepad.sThumbRY, MAX_AXIS);
93 SetAxisValue(4, (long)controllerState.Gamepad.bLeftTrigger, MAX_TRIGGER);
94 SetAxisValue(5, (long)controllerState.Gamepad.bRightTrigger, MAX_TRIGGER);
95 }
96 else
97 {
98 XINPUT_STATE controllerState;
99
100 if (!CXInputDLL::Get().GetState(m_controllerID, controllerState))
101 return false;
102
103 m_dwPacketNumber = controllerState.dwPacketNumber;
104
105 SetButtonValue(0, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_A) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
106 SetButtonValue(1, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_B) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
107 SetButtonValue(2, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_X) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
108 SetButtonValue(3, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_Y) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
109 SetButtonValue(4, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
110 SetButtonValue(5, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
111 SetButtonValue(6, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
112 SetButtonValue(7, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_START) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
113 SetButtonValue(8, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
114 SetButtonValue(9, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
115 SetButtonValue(10, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
116 SetButtonValue(11, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
117 SetButtonValue(12, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
118 SetButtonValue(13, (controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) ? JOYSTICK_STATE_BUTTON_PRESSED : JOYSTICK_STATE_BUTTON_UNPRESSED);
119
120 SetAxisValue(0, (long)controllerState.Gamepad.sThumbLX, MAX_AXIS);
121 SetAxisValue(1, (long)controllerState.Gamepad.sThumbLY, MAX_AXIS);
122 SetAxisValue(2, (long)controllerState.Gamepad.sThumbRX, MAX_AXIS);
123 SetAxisValue(3, (long)controllerState.Gamepad.sThumbRY, MAX_AXIS);
124 SetAxisValue(4, (long)controllerState.Gamepad.bLeftTrigger, MAX_TRIGGER);
125 SetAxisValue(5, (long)controllerState.Gamepad.bRightTrigger, MAX_TRIGGER);
126 }
127
128 return true;
129 }
130
SetMotor(unsigned int motorIndex,float magnitude)131 bool CJoystickXInput::SetMotor(unsigned int motorIndex, float magnitude)
132 {
133 bool bSuccess = false;
134
135 if (motorIndex < MOTOR_COUNT && 0.0f <= magnitude && magnitude <= 1.0f)
136 {
137 m_motorSpeeds[motorIndex] = magnitude;
138
139 XINPUT_VIBRATION vibrationState;
140
141 vibrationState.wLeftMotorSpeed = static_cast<WORD>(m_motorSpeeds[MOTOR_LEFT] * MAX_MOTOR);
142 vibrationState.wRightMotorSpeed = static_cast<WORD>(m_motorSpeeds[MOTOR_RIGHT] * MAX_MOTOR);
143
144 // TODO: Only dispatch after both left and right events have been received
145 bSuccess = CXInputDLL::Get().SetState(m_controllerID, vibrationState);
146 }
147
148 return bSuccess;
149 }
150