diff --git a/src/input.cpp b/src/input.cpp index 37591514..c7b0be14 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -22,6 +22,8 @@ extern "C" { #include "thread_pool.h" #include "utility.h" +#include + using namespace std::literals; namespace input { @@ -78,6 +80,16 @@ namespace input { return kpid & 0xFF; } + /** + * @brief Converts a little-endian netfloat to a native endianness float. + * @param f Netfloat value. + * @return Float value. + */ + float + from_netfloat(netfloat f) { + return boost::endian::endian_load(f); + } + static task_pool_util::TaskPool::task_id_t key_press_repeat_id {}; static std::unordered_map key_press {}; static std::array mouse_press {}; @@ -279,6 +291,53 @@ namespace input { << "--end controller arrival packet--"sv; } + /** + * @brief Prints a controller touch packet. + * @param packet The controller touch packet. + */ + void + print(PSS_CONTROLLER_TOUCH_PACKET packet) { + BOOST_LOG(debug) + << "--begin controller touch packet--"sv << std::endl + << "controllerNumber ["sv << (uint32_t) packet->controllerNumber << ']' << std::endl + << "eventType ["sv << util::hex(packet->eventType).to_string_view() << ']' << std::endl + << "pointerId ["sv << util::hex(packet->pointerId).to_string_view() << ']' << std::endl + << "x ["sv << from_netfloat(packet->x) << ']' << std::endl + << "y ["sv << from_netfloat(packet->y) << ']' << std::endl + << "pressure ["sv << from_netfloat(packet->pressure) << ']' << std::endl + << "--end controller touch packet--"sv; + } + + /** + * @brief Prints a controller motion packet. + * @param packet The controller motion packet. + */ + void + print(PSS_CONTROLLER_MOTION_PACKET packet) { + BOOST_LOG(verbose) + << "--begin controller motion packet--"sv << std::endl + << "controllerNumber ["sv << util::hex(packet->controllerNumber).to_string_view() << ']' << std::endl + << "motionType ["sv << util::hex(packet->motionType).to_string_view() << ']' << std::endl + << "x ["sv << from_netfloat(packet->x) << ']' << std::endl + << "y ["sv << from_netfloat(packet->y) << ']' << std::endl + << "z ["sv << from_netfloat(packet->z) << ']' << std::endl + << "--end controller motion packet--"sv; + } + + /** + * @brief Prints a controller battery packet. + * @param packet The controller battery packet. + */ + void + print(PSS_CONTROLLER_BATTERY_PACKET packet) { + BOOST_LOG(verbose) + << "--begin controller battery packet--"sv << std::endl + << "controllerNumber ["sv << util::hex(packet->controllerNumber).to_string_view() << ']' << std::endl + << "batteryState ["sv << util::hex(packet->batteryState).to_string_view() << ']' << std::endl + << "batteryPercentage ["sv << util::hex(packet->batteryPercentage).to_string_view() << ']' << std::endl + << "--end controller battery packet--"sv; + } + void print(void *payload) { auto header = (PNV_INPUT_HEADER) payload; @@ -313,6 +372,15 @@ namespace input { case SS_CONTROLLER_ARRIVAL_MAGIC: print((PSS_CONTROLLER_ARRIVAL_PACKET) payload); break; + case SS_CONTROLLER_TOUCH_MAGIC: + print((PSS_CONTROLLER_TOUCH_PACKET) payload); + break; + case SS_CONTROLLER_MOTION_MAGIC: + print((PSS_CONTROLLER_MOTION_PACKET) payload); + break; + case SS_CONTROLLER_BATTERY_MAGIC: + print((PSS_CONTROLLER_BATTERY_PACKET) payload); + break; } } @@ -716,6 +784,116 @@ namespace input { input->gamepads[packet->controllerNumber].id = packet->controllerNumber; } + /** + * @brief Called to pass a controller touch message to the platform backend. + * @param input The input context pointer. + * @param packet The controller touch packet. + */ + void + passthrough(std::shared_ptr &input, PSS_CONTROLLER_TOUCH_PACKET packet) { + if (!config::input.controller) { + return; + } + + if (packet->controllerNumber < 0 || packet->controllerNumber >= input->gamepads.size()) { + BOOST_LOG(warning) << "ControllerNumber out of range ["sv << packet->controllerNumber << ']'; + return; + } + + if (!((input->active_gamepad_state >> packet->controllerNumber) & 1)) { + BOOST_LOG(warning) << "ControllerNumber ["sv << packet->controllerNumber << "] not allocated"sv; + return; + } + + auto &gamepad = input->gamepads[packet->controllerNumber]; + if (gamepad.id < 0) { + return; + } + + platf::gamepad_touch_t touch { + packet->controllerNumber, + packet->eventType, + util::endian::little(packet->pointerId), + from_netfloat(packet->x), + from_netfloat(packet->y), + from_netfloat(packet->pressure), + }; + + platf::gamepad_touch(platf_input, touch); + } + + /** + * @brief Called to pass a controller motion message to the platform backend. + * @param input The input context pointer. + * @param packet The controller motion packet. + */ + void + passthrough(std::shared_ptr &input, PSS_CONTROLLER_MOTION_PACKET packet) { + if (!config::input.controller) { + return; + } + + if (packet->controllerNumber < 0 || packet->controllerNumber >= input->gamepads.size()) { + BOOST_LOG(warning) << "ControllerNumber out of range ["sv << packet->controllerNumber << ']'; + return; + } + + if (!((input->active_gamepad_state >> packet->controllerNumber) & 1)) { + BOOST_LOG(warning) << "ControllerNumber ["sv << packet->controllerNumber << "] not allocated"sv; + return; + } + + auto &gamepad = input->gamepads[packet->controllerNumber]; + if (gamepad.id < 0) { + return; + } + + platf::gamepad_motion_t motion { + packet->controllerNumber, + packet->motionType, + from_netfloat(packet->x), + from_netfloat(packet->y), + from_netfloat(packet->z), + }; + + platf::gamepad_motion(platf_input, motion); + } + + /** + * @brief Called to pass a controller battery message to the platform backend. + * @param input The input context pointer. + * @param packet The controller battery packet. + */ + void + passthrough(std::shared_ptr &input, PSS_CONTROLLER_BATTERY_PACKET packet) { + if (!config::input.controller) { + return; + } + + if (packet->controllerNumber < 0 || packet->controllerNumber >= input->gamepads.size()) { + BOOST_LOG(warning) << "ControllerNumber out of range ["sv << packet->controllerNumber << ']'; + return; + } + + if (!((input->active_gamepad_state >> packet->controllerNumber) & 1)) { + BOOST_LOG(warning) << "ControllerNumber ["sv << packet->controllerNumber << "] not allocated"sv; + return; + } + + auto &gamepad = input->gamepads[packet->controllerNumber]; + if (gamepad.id < 0) { + return; + } + + platf::gamepad_battery_t battery { + packet->controllerNumber, + packet->batteryState, + packet->batteryPercentage + }; + + platf::gamepad_battery(platf_input, battery); + } + void passthrough(std::shared_ptr &input, PNV_MULTI_CONTROLLER_PACKET packet) { if (!config::input.controller) { @@ -1196,6 +1374,15 @@ namespace input { case SS_CONTROLLER_ARRIVAL_MAGIC: passthrough(input, (PSS_CONTROLLER_ARRIVAL_PACKET) payload); break; + case SS_CONTROLLER_TOUCH_MAGIC: + passthrough(input, (PSS_CONTROLLER_TOUCH_PACKET) payload); + break; + case SS_CONTROLLER_MOTION_MAGIC: + passthrough(input, (PSS_CONTROLLER_MOTION_PACKET) payload); + break; + case SS_CONTROLLER_BATTERY_MAGIC: + passthrough(input, (PSS_CONTROLLER_BATTERY_PACKET) payload); + break; } } diff --git a/src/platform/common.h b/src/platform/common.h index 4d2ba921..49e1b1c1 100644 --- a/src/platform/common.h +++ b/src/platform/common.h @@ -185,6 +185,32 @@ namespace platf { std::uint32_t supportedButtons; }; + struct gamepad_touch_t { + std::uint8_t gamepadNumber; + std::uint8_t eventType; + std::uint32_t pointerId; + float x; + float y; + float pressure; + }; + + struct gamepad_motion_t { + std::uint8_t gamepadNumber; + std::uint8_t motionType; + + // Accel: m/s^2 + // Gyro: deg/s + float x; + float y; + float z; + }; + + struct gamepad_battery_t { + std::uint8_t gamepadNumber; + std::uint8_t state; + std::uint8_t percentage; + }; + class deinit_t { public: virtual ~deinit_t() = default; @@ -470,6 +496,30 @@ namespace platf { void unicode(input_t &input, char *utf8, int size); + /** + * @brief Sends a gamepad touch event to the OS. + * @param input The input context. + * @param touch The touch event. + */ + void + gamepad_touch(input_t &input, const gamepad_touch_t &touch); + + /** + * @brief Sends a gamepad motion event to the OS. + * @param input The input context. + * @param motion The motion event. + */ + void + gamepad_motion(input_t &input, const gamepad_motion_t &motion); + + /** + * @brief Sends a gamepad battery event to the OS. + * @param input The input context. + * @param battery The battery event. + */ + void + gamepad_battery(input_t &input, const gamepad_battery_t &battery); + /** * @brief Creates a new virtual gamepad. * @param input The input context. diff --git a/src/platform/linux/input.cpp b/src/platform/linux/input.cpp index 942d69e9..62a2e906 100644 --- a/src/platform/linux/input.cpp +++ b/src/platform/linux/input.cpp @@ -1567,6 +1567,36 @@ namespace platf { libevdev_uinput_write_event(uinput.get(), EV_SYN, SYN_REPORT, 0); } + /** + * @brief Sends a gamepad touch event to the OS. + * @param input The input context. + * @param touch The touch event. + */ + void + gamepad_touch(input_t &input, const gamepad_touch_t &touch) { + // Unimplemented feature - platform_caps::controller_touch + } + + /** + * @brief Sends a gamepad motion event to the OS. + * @param input The input context. + * @param motion The motion event. + */ + void + gamepad_motion(input_t &input, const gamepad_motion_t &motion) { + // Unimplemented + } + + /** + * @brief Sends a gamepad battery event to the OS. + * @param input The input context. + * @param battery The battery event. + */ + void + gamepad_battery(input_t &input, const gamepad_battery_t &battery) { + // Unimplemented + } + /** * @brief Initialize a new keyboard and return it. * diff --git a/src/platform/macos/input.cpp b/src/platform/macos/input.cpp index b9b5b9b4..b9eb073a 100644 --- a/src/platform/macos/input.cpp +++ b/src/platform/macos/input.cpp @@ -448,6 +448,36 @@ const KeyCodeMap kKeyCodesMap[] = { // Unimplemented } + /** + * @brief Sends a gamepad touch event to the OS. + * @param input The input context. + * @param touch The touch event. + */ + void + gamepad_touch(input_t &input, const gamepad_touch_t &touch) { + // Unimplemented feature - platform_caps::controller_touch + } + + /** + * @brief Sends a gamepad motion event to the OS. + * @param input The input context. + * @param motion The motion event. + */ + void + gamepad_motion(input_t &input, const gamepad_motion_t &motion) { + // Unimplemented + } + + /** + * @brief Sends a gamepad battery event to the OS. + * @param input The input context. + * @param battery The battery event. + */ + void + gamepad_battery(input_t &input, const gamepad_battery_t &battery) { + // Unimplemented + } + input_t input() { input_t result { new macos_input_t() }; diff --git a/src/platform/windows/input.cpp b/src/platform/windows/input.cpp index 797c9d7e..76f2cd74 100644 --- a/src/platform/windows/input.cpp +++ b/src/platform/windows/input.cpp @@ -805,6 +805,36 @@ namespace platf { } } + /** + * @brief Sends a gamepad touch event to the OS. + * @param input The input context. + * @param touch The touch event. + */ + void + gamepad_touch(input_t &input, const gamepad_touch_t &touch) { + // Unimplemented feature - platform_caps::controller_touch + } + + /** + * @brief Sends a gamepad motion event to the OS. + * @param input The input context. + * @param motion The motion event. + */ + void + gamepad_motion(input_t &input, const gamepad_motion_t &motion) { + // Unimplemented + } + + /** + * @brief Sends a gamepad battery event to the OS. + * @param input The input context. + * @param battery The battery event. + */ + void + gamepad_battery(input_t &input, const gamepad_battery_t &battery) { + // Unimplemented + } + void freeInput(void *p) { auto input = (input_raw_t *) p; diff --git a/third-party/moonlight-common-c b/third-party/moonlight-common-c index 28d63b11..49fef038 160000 --- a/third-party/moonlight-common-c +++ b/third-party/moonlight-common-c @@ -1 +1 @@ -Subproject commit 28d63b11ddb808662f0a7d90674a1376d99059c4 +Subproject commit 49fef0383020272941c4704d2ecf3e1e71174092