Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions src/core/report.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,19 +190,21 @@ namespace lvh::reports {

std::byte dualsense_battery_state(GamepadBatteryState state) {
switch (state) {
case GamepadBatteryState::discharging:
using enum GamepadBatteryState;

case discharging:
return std::byte {0x00};
case GamepadBatteryState::charging:
case charging:
return std::byte {0x01};
case GamepadBatteryState::full:
case full:
return std::byte {0x02};
case GamepadBatteryState::voltage_or_temperature_error:
case voltage_or_temperature_error:
return std::byte {0x0A};
case GamepadBatteryState::temperature_error:
case temperature_error:
return std::byte {0x0B};
case GamepadBatteryState::charging_error:
case charging_error:
return std::byte {0x0F};
case GamepadBatteryState::unknown:
case unknown:
break;
}

Expand Down
12 changes: 7 additions & 5 deletions src/core/runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,20 +157,22 @@ namespace lvh {
namespace {

OperationStatus validate_gamepad_options(const CreateGamepadOptions &options) {
using enum ErrorCode;

if (options.profile.device_type != DeviceType::gamepad) {
return OperationStatus::failure(ErrorCode::unsupported_profile, "device profile is not a gamepad");
return OperationStatus::failure(unsupported_profile, "device profile is not a gamepad");
}
if (options.profile.name.empty()) {
return OperationStatus::failure(ErrorCode::invalid_argument, "device profile name must not be empty");
return OperationStatus::failure(invalid_argument, "device profile name must not be empty");
}
if (options.profile.report_descriptor.empty()) {
return OperationStatus::failure(ErrorCode::invalid_argument, "device profile report descriptor must not be empty");
return OperationStatus::failure(invalid_argument, "device profile report descriptor must not be empty");
}
if (options.profile.report_id == 0) {
return OperationStatus::failure(ErrorCode::invalid_argument, "device profile report id must not be zero");
return OperationStatus::failure(invalid_argument, "device profile report id must not be zero");
}
if (options.profile.input_report_size == 0) {
return OperationStatus::failure(ErrorCode::invalid_argument, "device profile input report size must not be zero");
return OperationStatus::failure(invalid_argument, "device profile input report size must not be zero");
}

return OperationStatus::success();
Expand Down
94 changes: 55 additions & 39 deletions src/platform/linux/uhid_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -642,15 +642,17 @@ namespace lvh::detail {

int mouse_button_to_linux(MouseButton button) {
switch (button) {
case MouseButton::left:
using enum MouseButton;

case left:
return BTN_LEFT;
case MouseButton::middle:
case middle:
return BTN_MIDDLE;
case MouseButton::right:
case right:
return BTN_RIGHT;
case MouseButton::side:
case side:
return BTN_SIDE;
case MouseButton::extra:
case extra:
return BTN_EXTRA;
}

Expand Down Expand Up @@ -1090,17 +1092,19 @@ namespace lvh::detail {

OperationStatus configure_evdev_device(libevdev *device, DeviceType device_type) {
switch (device_type) {
case DeviceType::keyboard:
using enum DeviceType;

case keyboard:
return configure_evdev_keyboard(device);
case DeviceType::mouse:
case mouse:
return configure_evdev_mouse(device);
case DeviceType::touchscreen:
case touchscreen:
return configure_evdev_touchscreen(device);
case DeviceType::trackpad:
case trackpad:
return configure_evdev_trackpad(device);
case DeviceType::pen_tablet:
case pen_tablet:
return configure_evdev_pen_tablet(device);
case DeviceType::gamepad:
case gamepad:
return OperationStatus::failure(ErrorCode::unsupported_profile, "gamepads are created through UHID, not uinput");
}

Expand Down Expand Up @@ -1320,15 +1324,17 @@ namespace lvh::detail {
}

switch (event.kind) {
case MouseEventKind::relative_motion:
using enum MouseEventKind;

case relative_motion:
return submit_relative_motion(event);
case MouseEventKind::absolute_motion:
case absolute_motion:
return submit_absolute_motion(event);
case MouseEventKind::button:
case button:
return submit_button(event);
case MouseEventKind::vertical_scroll:
case vertical_scroll:
return submit_vertical_scroll(event.high_resolution_scroll);
case MouseEventKind::horizontal_scroll:
case horizontal_scroll:
return submit_horizontal_scroll(event.high_resolution_scroll);
}

Expand Down Expand Up @@ -1659,19 +1665,21 @@ namespace lvh::detail {

int pen_tool_to_linux(PenToolType tool) {
switch (tool) {
case PenToolType::pen:
using enum PenToolType;

case pen:
return BTN_TOOL_PEN;
case PenToolType::eraser:
case eraser:
return BTN_TOOL_RUBBER;
case PenToolType::brush:
case brush:
return BTN_TOOL_BRUSH;
case PenToolType::pencil:
case pencil:
return BTN_TOOL_PENCIL;
case PenToolType::airbrush:
case airbrush:
return BTN_TOOL_AIRBRUSH;
case PenToolType::touch:
case touch:
return BTN_TOUCH;
case PenToolType::unchanged:
case unchanged:
return -1;
}

Expand All @@ -1680,11 +1688,13 @@ namespace lvh::detail {

int pen_button_to_linux(PenButton button) {
switch (button) {
case PenButton::primary:
using enum PenButton;

case primary:
return BTN_STYLUS;
case PenButton::secondary:
case secondary:
return BTN_STYLUS2;
case PenButton::tertiary:
case tertiary:
#if defined(BTN_STYLUS3)
return BTN_STYLUS3;
#else
Expand Down Expand Up @@ -1910,15 +1920,17 @@ namespace lvh::detail {

int mouse_button_to_xtest(MouseButton button) {
switch (button) {
case MouseButton::left:
using enum MouseButton;

case left:
return 1;
case MouseButton::middle:
case middle:
return 2;
case MouseButton::right:
case right:
return 3;
case MouseButton::side:
case side:
return 8;
case MouseButton::extra:
case extra:
return 9;
}

Expand Down Expand Up @@ -2072,19 +2084,21 @@ namespace lvh::detail {
}

switch (event.kind) {
case MouseEventKind::relative_motion:
using enum MouseEventKind;

case relative_motion:
XTestFakeRelativeMotionEvent(display_, event.x, event.y, CurrentTime);
break;
case MouseEventKind::absolute_motion:
case absolute_motion:
submit_absolute_motion(event);
break;
case MouseEventKind::button:
case button:
XTestFakeButtonEvent(display_, mouse_button_to_xtest(event.button), event.pressed ? True : False, CurrentTime);
break;
case MouseEventKind::vertical_scroll:
case vertical_scroll:
submit_scroll(event.high_resolution_scroll, 4, 5);
break;
case MouseEventKind::horizontal_scroll:
case horizontal_scroll:
submit_scroll(event.high_resolution_scroll, 6, 7);
break;
}
Expand Down Expand Up @@ -2255,17 +2269,19 @@ namespace lvh::detail {

private:
OperationStatus write_event(const uhid_event &event) {
using enum ErrorCode;

std::lock_guard lock {write_mutex_};
if (fd_ < 0) {
return OperationStatus::failure(ErrorCode::device_closed, "UHID file descriptor is closed");
return OperationStatus::failure(device_closed, "UHID file descriptor is closed");
}

const auto result = system_write(fd_, &event, sizeof(event));
if (result < 0) {
return system_error_status(ErrorCode::backend_failure, "failed to write UHID event", errno);
return system_error_status(backend_failure, "failed to write UHID event", errno);
}
if (static_cast<std::size_t>(result) != sizeof(event)) {
return OperationStatus::failure(ErrorCode::backend_failure, "short write while sending UHID event");
return OperationStatus::failure(backend_failure, "short write while sending UHID event");
}

return OperationStatus::success();
Expand Down
30 changes: 16 additions & 14 deletions tests/fixtures/linux_backend_test_hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1081,14 +1081,15 @@ namespace lvh::detail::test {

UinputPenTablet pen_tablet {descriptors[1]};
auto status = OperationStatus::success();
using enum PenToolType;
constexpr std::array tools {
PenToolType::pen,
PenToolType::eraser,
PenToolType::brush,
PenToolType::pencil,
PenToolType::airbrush,
PenToolType::touch,
PenToolType::unchanged,
pen,
eraser,
brush,
pencil,
airbrush,
touch,
unchanged,
};
for (const auto tool : tools) {
if (!status.ok()) {
Expand All @@ -1098,8 +1099,8 @@ namespace lvh::detail::test {
.tool = tool,
.x = 0.25F,
.y = 0.75F,
.pressure = tool == PenToolType::eraser ? -1.0F : 0.25F,
.distance = tool == PenToolType::eraser ? 0.5F : -1.0F,
.pressure = tool == eraser ? -1.0F : 0.25F,
.distance = tool == eraser ? 0.5F : -1.0F,
.tilt_x = 120.0F,
.tilt_y = -120.0F,
});
Expand Down Expand Up @@ -1965,19 +1966,20 @@ namespace lvh::detail::test {
return status;
}

if (const auto status = mouse.submit({.kind = MouseEventKind::relative_motion, .x = 1, .y = -1}); !status.ok()) {
using enum MouseEventKind;
if (const auto status = mouse.submit({.kind = relative_motion, .x = 1, .y = -1}); !status.ok()) {
return status;
}
if (const auto status = mouse.submit({.kind = MouseEventKind::absolute_motion, .x = 1, .y = 1, .width = 2, .height = 2}); !status.ok()) {
if (const auto status = mouse.submit({.kind = absolute_motion, .x = 1, .y = 1, .width = 2, .height = 2}); !status.ok()) {
return status;
}
if (const auto status = mouse.submit({.kind = MouseEventKind::button, .button = MouseButton::extra, .pressed = true}); !status.ok()) {
if (const auto status = mouse.submit({.kind = button, .button = MouseButton::extra, .pressed = true}); !status.ok()) {
return status;
}
if (const auto status = mouse.submit({.kind = MouseEventKind::vertical_scroll, .high_resolution_scroll = 120}); !status.ok()) {
if (const auto status = mouse.submit({.kind = vertical_scroll, .high_resolution_scroll = 120}); !status.ok()) {
return status;
}
return mouse.submit({.kind = MouseEventKind::horizontal_scroll, .high_resolution_scroll = -120});
return mouse.submit({.kind = horizontal_scroll, .high_resolution_scroll = -120});
#else
return OperationStatus::failure(ErrorCode::backend_unavailable, "XTest fallback is not enabled");
#endif
Expand Down
8 changes: 5 additions & 3 deletions tests/unit/test_report.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,18 @@ TEST(ReportTest, NormalizesAxesAndTriggers) {
}

TEST(ReportTest, EncodesHatSwitch) {
using enum lvh::GamepadButton;

lvh::ButtonSet buttons;
EXPECT_EQ(lvh::reports::hat_from_buttons(buttons), 8);

buttons.set(lvh::GamepadButton::dpad_up);
buttons.set(dpad_up);
EXPECT_EQ(lvh::reports::hat_from_buttons(buttons), 0);

buttons.set(lvh::GamepadButton::dpad_right);
buttons.set(dpad_right);
EXPECT_EQ(lvh::reports::hat_from_buttons(buttons), 1);

buttons.set(lvh::GamepadButton::dpad_down);
buttons.set(dpad_down);
EXPECT_EQ(lvh::reports::hat_from_buttons(buttons), 2);
}

Expand Down