Skip to content

Commit

Permalink
Implement controller arrival metadata support
Browse files Browse the repository at this point in the history
  • Loading branch information
cgutman committed Jun 28, 2023
1 parent 12e6774 commit 210d22e
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 24 deletions.
9 changes: 5 additions & 4 deletions docs/source/about/advanced_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -140,17 +140,18 @@ gamepad
===== ===========
Value Description
===== ===========
x360 xbox 360 controller
ds4 dualshock controller (PS4)
auto Selected based on information from client
x360 Xbox 360 controller
ds4 DualShock 4 controller (PS4)
===== ===========

**Default**
``x360``
``auto``

**Example**
.. code-block:: text
gamepad = x360
gamepad = auto
back_button_timeout
^^^^^^^^^^^^^^^^^^^
Expand Down
54 changes: 53 additions & 1 deletion src/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,17 @@ namespace input {
<< "--end controller packet--"sv;
}

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
print(void *payload) {
auto header = (PNV_INPUT_HEADER) payload;
Expand Down Expand Up @@ -295,6 +306,9 @@ namespace input {
case MULTI_CONTROLLER_MAGIC_GEN5:
print((PNV_MULTI_CONTROLLER_PACKET) payload);
break;
case SS_CONTROLLER_ARRIVAL_MAGIC:
print((PSS_CONTROLLER_ARRIVAL_PACKET) payload);
break;
}
}

Expand Down Expand Up @@ -643,7 +657,7 @@ namespace input {
return -1;
}

if (platf::alloc_gamepad(platf_input, id, rumble_queue)) {
if (platf::alloc_gamepad(platf_input, id, {}, rumble_queue)) {
free_id(gamepadMask, id);
// allocating a gamepad failed: solution: ignore gamepads
// The implementations of platf::alloc_gamepad already has logging
Expand All @@ -658,6 +672,41 @@ namespace input {
return 0;
}

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
passthrough(std::shared_ptr<input_t> &input, PNV_MULTI_CONTROLLER_PACKET packet) {
if (!config::input.controller) {
Expand Down Expand Up @@ -1135,6 +1184,9 @@ namespace input {
case MULTI_CONTROLLER_MAGIC_GEN5:
passthrough(input, (PNV_MULTI_CONTROLLER_PACKET) payload);
break;
case SS_CONTROLLER_ARRIVAL_MAGIC:
passthrough(input, (PSS_CONTROLLER_ARRIVAL_PACKET) payload);
break;
}
}

Expand Down
9 changes: 8 additions & 1 deletion src/platform/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,13 @@ namespace platf {
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 {
public:
virtual ~deinit_t() = default;
Expand Down Expand Up @@ -456,7 +463,7 @@ namespace platf {
unicode(input_t &input, char *utf8, int size);

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
free_gamepad(input_t &input, int nr);

Expand Down
6 changes: 3 additions & 3 deletions src/platform/linux/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -771,7 +771,7 @@ namespace platf {
}

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]);

int err = libevdev_uinput_create_from_device(gamepad_dev.get(), LIBEVDEV_UINPUT_OPEN_MANAGED, &input);
Expand Down Expand Up @@ -1481,8 +1481,8 @@ namespace platf {
}

int
alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue) {
return ((input_raw_t *) input.get())->alloc_gamepad(nr, std::move(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, metadata, std::move(rumble_queue));
}

void
Expand Down
2 changes: 1 addition & 1 deletion src/platform/macos/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ const KeyCodeMap kKeyCodesMap[] = {
}

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;
return -1;
}
Expand Down
46 changes: 34 additions & 12 deletions src/platform/windows/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,6 @@ namespace platf {
using client_t = util::safe_ptr<_VIGEM_CLIENT_T, vigem_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
x360_notify(
client_t::pointer client,
Expand Down Expand Up @@ -424,14 +415,45 @@ namespace platf {
}

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();

if (!raw->vigem) {
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
Expand Down Expand Up @@ -595,7 +617,7 @@ namespace platf {
supported_gamepads() {
// ds4 == ps4
static std::vector<std::string_view> gps {
"x360"sv, "ds4"sv, "ps4"sv
"auto"sv, "x360"sv, "ds4"sv, "ps4"sv
};

return gps;
Expand Down
5 changes: 3 additions & 2 deletions src_assets/common/assets/web/config.html
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,11 @@ <h1 class="my-4">Configuration</h1>
<div class="mb-3" v-if="platform === 'windows'">
<label for="gamepad" class="form-label">Gamepads</label>
<select id="gamepad" class="form-select" v-model="config.gamepad">
<option value="auto">Automatic</option>
<option value="ds4">DS4 (PS4)</option>
<option value="x360">X360 (Xbox 360)</option>
</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>
<!--Ping Timeout-->
<div class="mb-3">
Expand Down Expand Up @@ -1029,7 +1030,7 @@ <h1 class="my-4">Configuration</h1>
"dwmflush": "enabled",
"encoder": "",
"fps": "[10,30,60,90,120]",
"gamepad": "x360",
"gamepad": "auto",
"hevc_mode": 0,
"key_rightalt_to_key_win": "disabled",
"keyboard": "enabled",
Expand Down

0 comments on commit 210d22e

Please sign in to comment.