Implement controller arrival metadata support
This commit is contained in:
@@ -140,17 +140,18 @@ gamepad
|
|||||||
===== ===========
|
===== ===========
|
||||||
Value Description
|
Value Description
|
||||||
===== ===========
|
===== ===========
|
||||||
x360 xbox 360 controller
|
auto Selected based on information from client
|
||||||
ds4 dualshock controller (PS4)
|
x360 Xbox 360 controller
|
||||||
|
ds4 DualShock 4 controller (PS4)
|
||||||
===== ===========
|
===== ===========
|
||||||
|
|
||||||
**Default**
|
**Default**
|
||||||
``x360``
|
``auto``
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
gamepad = x360
|
gamepad = auto
|
||||||
|
|
||||||
back_button_timeout
|
back_button_timeout
|
||||||
^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|||||||
@@ -264,6 +264,21 @@ namespace input {
|
|||||||
<< "--end controller packet--"sv;
|
<< "--end controller packet--"sv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prints a controller arrival packet.
|
||||||
|
* @param packet The controller arrival packet.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
print(PSS_CONTROLLER_ARRIVAL_PACKET packet) {
|
||||||
|
BOOST_LOG(debug)
|
||||||
|
<< "--begin controller arrival packet--"sv << std::endl
|
||||||
|
<< "controllerNumber ["sv << (uint32_t) packet->controllerNumber << ']' << std::endl
|
||||||
|
<< "type ["sv << util::hex(packet->type).to_string_view() << ']' << std::endl
|
||||||
|
<< "capabilities ["sv << util::hex(packet->capabilities).to_string_view() << ']' << std::endl
|
||||||
|
<< "supportedButtonFlags ["sv << util::hex(packet->supportedButtonFlags).to_string_view() << ']' << std::endl
|
||||||
|
<< "--end controller arrival packet--"sv;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
print(void *payload) {
|
print(void *payload) {
|
||||||
auto header = (PNV_INPUT_HEADER) payload;
|
auto header = (PNV_INPUT_HEADER) payload;
|
||||||
@@ -295,6 +310,9 @@ namespace input {
|
|||||||
case MULTI_CONTROLLER_MAGIC_GEN5:
|
case MULTI_CONTROLLER_MAGIC_GEN5:
|
||||||
print((PNV_MULTI_CONTROLLER_PACKET) payload);
|
print((PNV_MULTI_CONTROLLER_PACKET) payload);
|
||||||
break;
|
break;
|
||||||
|
case SS_CONTROLLER_ARRIVAL_MAGIC:
|
||||||
|
print((PSS_CONTROLLER_ARRIVAL_PACKET) payload);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -643,7 +661,7 @@ namespace input {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (platf::alloc_gamepad(platf_input, id, rumble_queue)) {
|
if (platf::alloc_gamepad(platf_input, id, {}, rumble_queue)) {
|
||||||
free_id(gamepadMask, id);
|
free_id(gamepadMask, id);
|
||||||
// allocating a gamepad failed: solution: ignore gamepads
|
// allocating a gamepad failed: solution: ignore gamepads
|
||||||
// The implementations of platf::alloc_gamepad already has logging
|
// The implementations of platf::alloc_gamepad already has logging
|
||||||
@@ -658,6 +676,46 @@ namespace input {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called to pass a controller arrival message to the platform backend.
|
||||||
|
* @param input The input context pointer.
|
||||||
|
* @param packet The controller arrival packet.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
passthrough(std::shared_ptr<input_t> &input, PSS_CONTROLLER_ARRIVAL_PACKET packet) {
|
||||||
|
if (!config::input.controller) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet->controllerNumber >= gamepadMask.size()) {
|
||||||
|
// Invalid controller number
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gamepadMask[packet->controllerNumber]) {
|
||||||
|
// There's already a gamepad in this slot
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
platf::gamepad_arrival_t arrival {
|
||||||
|
packet->controllerNumber,
|
||||||
|
packet->type,
|
||||||
|
util::endian::little(packet->capabilities),
|
||||||
|
util::endian::little(packet->supportedButtonFlags),
|
||||||
|
};
|
||||||
|
|
||||||
|
gamepadMask[packet->controllerNumber] = true;
|
||||||
|
input->active_gamepad_state |= (1 << packet->controllerNumber);
|
||||||
|
|
||||||
|
// Allocate a new gamepad
|
||||||
|
if (platf::alloc_gamepad(platf_input, packet->controllerNumber, arrival, input->rumble_queue)) {
|
||||||
|
free_id(gamepadMask, packet->controllerNumber);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
input->gamepads[packet->controllerNumber].id = packet->controllerNumber;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
passthrough(std::shared_ptr<input_t> &input, PNV_MULTI_CONTROLLER_PACKET packet) {
|
passthrough(std::shared_ptr<input_t> &input, PNV_MULTI_CONTROLLER_PACKET packet) {
|
||||||
if (!config::input.controller) {
|
if (!config::input.controller) {
|
||||||
@@ -1135,6 +1193,9 @@ namespace input {
|
|||||||
case MULTI_CONTROLLER_MAGIC_GEN5:
|
case MULTI_CONTROLLER_MAGIC_GEN5:
|
||||||
passthrough(input, (PNV_MULTI_CONTROLLER_PACKET) payload);
|
passthrough(input, (PNV_MULTI_CONTROLLER_PACKET) payload);
|
||||||
break;
|
break;
|
||||||
|
case SS_CONTROLLER_ARRIVAL_MAGIC:
|
||||||
|
passthrough(input, (PSS_CONTROLLER_ARRIVAL_PACKET) payload);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -170,6 +170,13 @@ namespace platf {
|
|||||||
std::int16_t rsY;
|
std::int16_t rsY;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct gamepad_arrival_t {
|
||||||
|
std::uint8_t gamepadNumber;
|
||||||
|
std::uint8_t type;
|
||||||
|
std::uint16_t capabilities;
|
||||||
|
std::uint32_t supportedButtons;
|
||||||
|
};
|
||||||
|
|
||||||
class deinit_t {
|
class deinit_t {
|
||||||
public:
|
public:
|
||||||
virtual ~deinit_t() = default;
|
virtual ~deinit_t() = default;
|
||||||
@@ -455,8 +462,16 @@ namespace platf {
|
|||||||
void
|
void
|
||||||
unicode(input_t &input, char *utf8, int size);
|
unicode(input_t &input, char *utf8, int size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates a new virtual gamepad.
|
||||||
|
* @param input The input context.
|
||||||
|
* @param nr The assigned controller number.
|
||||||
|
* @param metadata Controller metadata from client (empty if none provided).
|
||||||
|
* @param rumble_queue The queue for posting rumble messages to the client.
|
||||||
|
* @return 0 on success.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue);
|
alloc_gamepad(input_t &input, int nr, const gamepad_arrival_t &metadata, rumble_queue_t rumble_queue);
|
||||||
void
|
void
|
||||||
free_gamepad(input_t &input, int nr);
|
free_gamepad(input_t &input, int nr);
|
||||||
|
|
||||||
|
|||||||
@@ -770,8 +770,15 @@ namespace platf {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates a new virtual gamepad.
|
||||||
|
* @param nr The assigned controller number.
|
||||||
|
* @param metadata Controller metadata from client (empty if none provided).
|
||||||
|
* @param rumble_queue The queue for posting rumble messages to the client.
|
||||||
|
* @return 0 on success.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
alloc_gamepad(int nr, rumble_queue_t &&rumble_queue) {
|
alloc_gamepad(int nr, const gamepad_arrival_t &metadata, rumble_queue_t &&rumble_queue) {
|
||||||
TUPLE_2D_REF(input, gamepad_state, gamepads[nr]);
|
TUPLE_2D_REF(input, gamepad_state, gamepads[nr]);
|
||||||
|
|
||||||
int err = libevdev_uinput_create_from_device(gamepad_dev.get(), LIBEVDEV_UINPUT_OPEN_MANAGED, &input);
|
int err = libevdev_uinput_create_from_device(gamepad_dev.get(), LIBEVDEV_UINPUT_OPEN_MANAGED, &input);
|
||||||
@@ -1480,9 +1487,17 @@ namespace platf {
|
|||||||
keyboard_ev(kb, KEY_LEFTCTRL, 0);
|
keyboard_ev(kb, KEY_LEFTCTRL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates a new virtual gamepad.
|
||||||
|
* @param input The input context.
|
||||||
|
* @param nr The assigned controller number.
|
||||||
|
* @param metadata Controller metadata from client (empty if none provided).
|
||||||
|
* @param rumble_queue The queue for posting rumble messages to the client.
|
||||||
|
* @return 0 on success.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue) {
|
alloc_gamepad(input_t &input, int nr, const gamepad_arrival_t &metadata, rumble_queue_t rumble_queue) {
|
||||||
return ((input_raw_t *) input.get())->alloc_gamepad(nr, std::move(rumble_queue));
|
return ((input_raw_t *) input.get())->alloc_gamepad(nr, metadata, std::move(rumble_queue));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -288,8 +288,16 @@ const KeyCodeMap kKeyCodesMap[] = {
|
|||||||
BOOST_LOG(info) << "unicode: Unicode input not yet implemented for MacOS."sv;
|
BOOST_LOG(info) << "unicode: Unicode input not yet implemented for MacOS."sv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates a new virtual gamepad.
|
||||||
|
* @param input The input context.
|
||||||
|
* @param nr The assigned controller number.
|
||||||
|
* @param metadata Controller metadata from client (empty if none provided).
|
||||||
|
* @param rumble_queue The queue for posting rumble messages to the client.
|
||||||
|
* @return 0 on success.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue) {
|
alloc_gamepad(input_t &input, int nr, const gamepad_arrival_t &metadata, rumble_queue_t rumble_queue) {
|
||||||
BOOST_LOG(info) << "alloc_gamepad: Gamepad not yet implemented for MacOS."sv;
|
BOOST_LOG(info) << "alloc_gamepad: Gamepad not yet implemented for MacOS."sv;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,15 +26,6 @@ namespace platf {
|
|||||||
using client_t = util::safe_ptr<_VIGEM_CLIENT_T, vigem_free>;
|
using client_t = util::safe_ptr<_VIGEM_CLIENT_T, vigem_free>;
|
||||||
using target_t = util::safe_ptr<_VIGEM_TARGET_T, vigem_target_free>;
|
using target_t = util::safe_ptr<_VIGEM_TARGET_T, vigem_target_free>;
|
||||||
|
|
||||||
static VIGEM_TARGET_TYPE
|
|
||||||
map(const std::string_view &gp) {
|
|
||||||
if (gp == "x360"sv) {
|
|
||||||
return Xbox360Wired;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DualShock4Wired;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CALLBACK
|
void CALLBACK
|
||||||
x360_notify(
|
x360_notify(
|
||||||
client_t::pointer client,
|
client_t::pointer client,
|
||||||
@@ -423,15 +414,54 @@ namespace platf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates a new virtual gamepad.
|
||||||
|
* @param input The input context.
|
||||||
|
* @param nr The assigned controller number.
|
||||||
|
* @param metadata Controller metadata from client (empty if none provided).
|
||||||
|
* @param rumble_queue The queue for posting rumble messages to the client.
|
||||||
|
* @return 0 on success.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue) {
|
alloc_gamepad(input_t &input, int nr, const gamepad_arrival_t &metadata, rumble_queue_t rumble_queue) {
|
||||||
auto raw = (input_raw_t *) input.get();
|
auto raw = (input_raw_t *) input.get();
|
||||||
|
|
||||||
if (!raw->vigem) {
|
if (!raw->vigem) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return raw->vigem->alloc_gamepad_interal(nr, rumble_queue, map(config::input.gamepad));
|
VIGEM_TARGET_TYPE selectedGamepadType;
|
||||||
|
|
||||||
|
if (config::input.gamepad == "x360"sv) {
|
||||||
|
BOOST_LOG(info) << "Gamepad " << nr << " will be Xbox 360 controller (manual selection)"sv;
|
||||||
|
selectedGamepadType = Xbox360Wired;
|
||||||
|
}
|
||||||
|
else if (config::input.gamepad == "ps4"sv || config::input.gamepad == "ds4"sv) {
|
||||||
|
BOOST_LOG(info) << "Gamepad " << nr << " will be DualShock 4 controller (manual selection)"sv;
|
||||||
|
selectedGamepadType = DualShock4Wired;
|
||||||
|
}
|
||||||
|
else if (metadata.type == LI_CTYPE_PS) {
|
||||||
|
BOOST_LOG(info) << "Gamepad " << nr << " will be DualShock 4 controller (auto-selected by client-reported type)"sv;
|
||||||
|
selectedGamepadType = DualShock4Wired;
|
||||||
|
}
|
||||||
|
else if (metadata.type == LI_CTYPE_XBOX) {
|
||||||
|
BOOST_LOG(info) << "Gamepad " << nr << " will be Xbox 360 controller (auto-selected by client-reported type)"sv;
|
||||||
|
selectedGamepadType = Xbox360Wired;
|
||||||
|
}
|
||||||
|
else if (metadata.capabilities & (LI_CCAP_ACCEL | LI_CCAP_GYRO)) {
|
||||||
|
BOOST_LOG(info) << "Gamepad " << nr << " will be DualShock 4 controller (auto-selected by motion sensor presence)"sv;
|
||||||
|
selectedGamepadType = DualShock4Wired;
|
||||||
|
}
|
||||||
|
else if (metadata.capabilities & LI_CCAP_TOUCHPAD) {
|
||||||
|
BOOST_LOG(info) << "Gamepad " << nr << " will be DualShock 4 controller (auto-selected by touchpad presence)"sv;
|
||||||
|
selectedGamepadType = DualShock4Wired;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BOOST_LOG(info) << "Gamepad " << nr << " will be Xbox 360 controller (default)"sv;
|
||||||
|
selectedGamepadType = Xbox360Wired;
|
||||||
|
}
|
||||||
|
|
||||||
|
return raw->vigem->alloc_gamepad_interal(nr, rumble_queue, selectedGamepadType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -591,11 +621,15 @@ namespace platf {
|
|||||||
delete input;
|
delete input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the supported gamepads for this platform backend.
|
||||||
|
* @return Vector of gamepad type strings.
|
||||||
|
*/
|
||||||
std::vector<std::string_view> &
|
std::vector<std::string_view> &
|
||||||
supported_gamepads() {
|
supported_gamepads() {
|
||||||
// ds4 == ps4
|
// ds4 == ps4
|
||||||
static std::vector<std::string_view> gps {
|
static std::vector<std::string_view> gps {
|
||||||
"x360"sv, "ds4"sv, "ps4"sv
|
"auto"sv, "x360"sv, "ds4"sv, "ps4"sv
|
||||||
};
|
};
|
||||||
|
|
||||||
return gps;
|
return gps;
|
||||||
|
|||||||
@@ -94,10 +94,11 @@
|
|||||||
<div class="mb-3" v-if="platform === 'windows'">
|
<div class="mb-3" v-if="platform === 'windows'">
|
||||||
<label for="gamepad" class="form-label">Gamepads</label>
|
<label for="gamepad" class="form-label">Gamepads</label>
|
||||||
<select id="gamepad" class="form-select" v-model="config.gamepad">
|
<select id="gamepad" class="form-select" v-model="config.gamepad">
|
||||||
|
<option value="auto">Automatic</option>
|
||||||
<option value="ds4">DS4 (PS4)</option>
|
<option value="ds4">DS4 (PS4)</option>
|
||||||
<option value="x360">X360 (Xbox 360)</option>
|
<option value="x360">X360 (Xbox 360)</option>
|
||||||
</select>
|
</select>
|
||||||
<div class="form-text">Choose which type of gamepad to Emulate on the host</div>
|
<div class="form-text">Choose which type of gamepad to emulate on the host</div>
|
||||||
</div>
|
</div>
|
||||||
<!--Ping Timeout-->
|
<!--Ping Timeout-->
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
@@ -1029,7 +1030,7 @@
|
|||||||
"dwmflush": "enabled",
|
"dwmflush": "enabled",
|
||||||
"encoder": "",
|
"encoder": "",
|
||||||
"fps": "[10,30,60,90,120]",
|
"fps": "[10,30,60,90,120]",
|
||||||
"gamepad": "x360",
|
"gamepad": "auto",
|
||||||
"hevc_mode": 0,
|
"hevc_mode": 0,
|
||||||
"key_rightalt_to_key_win": "disabled",
|
"key_rightalt_to_key_win": "disabled",
|
||||||
"keyboard": "enabled",
|
"keyboard": "enabled",
|
||||||
|
|||||||
Reference in New Issue
Block a user