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
2 changes: 1 addition & 1 deletion astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import react from '@astrojs/react';

// https://astro.build/config
export default defineConfig({
site: "https://blog.yorisoft.dev/",
site: "http://blog.yorisoft.dev/",
vite: {
plugins: [tailwindcss()],
},
Expand Down
14 changes: 13 additions & 1 deletion src/content.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@ const blog = defineCollection({
}),
});

const project = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
date: z.coerce.date(),
description: z.string(),
url: z.string(),
thumbnail: z.string(),
techList: z.string(),
}),
});

export const collections = {
blog,
blog, project
};
36 changes: 36 additions & 0 deletions src/content/project/0.kwin-project-intro/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
title: GSoC 2025 Project Blog Intro - Improving Game Controller Support in KWin
authors:
- yorisoft
date: 2025-05-12
thumbnail: https://community.kde.org/images.community/thumb/a/af/Mascot_konqi-base-plasma.png/250px-Mascot_konqi-base-plasma.png
SPDX-License-Identifier: CC-BY-SA-4.0
SPDX-FileCopyrightText: 2025 Yelsin Sepulveda <yelsin.sepulveda@kdemail.net>
---

# Hello KDE Community!

My name is Yelsin ['yorisoft'](https://invent.kde.org/yorisoft) Sepulveda. I'm an engineer with experience in DevOps, and Cloud Computing. I joined KDE as part of the GSoC application process early last month and have been contributing to a few projects ever since. Miraculously, my GSoC proposal has been selected! ❤️ *Hallelujah!* Which means over this summer **I'll be working on implementing game controller input recognition into KWin.**

## About the Project

Currently, applications directly manage controller input, leading to inconsistencies, the inability of the system to recognize controller input for power management, and unintentionally enabling/disabling "lizard mode" in certain controllers. This project proposes a solution to unify game controller input within KWin by capturing controller events, creating a virtual controller emulation layer, and ensuring proper routing of input to applications. This project aims to address the following issues:
- **System Power Management**: KWin lacks controller input recognition, preventing activity reporting and causing premature system sleep.
- **"Lizard Mode"**: When KWin opens a file descriptor for certain gaming controller devices (like the Steam Controller and Steam Deck Controller), this disables those controllers' lizard mode (keyboard and mouse input emulation), since the controller detects that a program is now handling input?even if KWin isn't actively using it.
- **Decentralized Input Handling**: Individual application input handling results in inconsistent input parsing and limited remapping capabilities.

## Project Goals

The primary goals of this project are to:
- Enable KWin to capture and process game controller input events.
- Implement a virtual controller emulation layer within KWin.
- Route physical controller input 1:1 to emulated devices, including haptics.
- Prevent system sleep during active controller use.
- Manage "lizard mode" for compatible controllers.
- Establish a foundation for future features: global remapping, haptics settings, and advanced Wayland protocols.

## About Me

I often spend my time surfing the internet learning new things, spending quality time with family and friends, or picking up new hobbies and skills-such as music! You could say I'm someone who likes to jump between multiple hobbies and interests. As of late, I'm learning a new [snare solo](https://youtu.be/q887A3B0tZQ?si=WNsSR2d4Me2TTU3o) and how to build an online brand.

I started my career as a DevOps Engineer and SRE where I learned tools like Jenkins, Docker, and Terraform. I then transitioned to a Solutions Architect role where I worked with many different cloud technologies and helped other companies design their cloud architecture. I am relatively new to contributing to open-source projects but have been an avid user of Linux and open-source tools for over 4 years, and am committed to learning and growing in this community. Check me out on [GitHub](https://github.com/Yorisoft).
110 changes: 110 additions & 0 deletions src/content/project/1.kwin-project-week-1-2/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
---
title: "GSoC'25 Kwin Project Blog Post: Week 1-2"
authors:
- yorisoft
date: 2025-06-24
thumbnail: /images/games.svg
SPDX-License-Identifier: CC-BY-SA-4.0
SPDX-FileCopyrightText: 2025 Yelsin Sepulveda <yelsinsepulveda@gmail.com>
---

These past few week’s my focus was on exploring input device detection and event handling mechanisms in Linux, with a particular emphasis on game controllers and their potential integration into KWin.
I also spent time reading through KWin’s input-related source code to understand how it currently manages devices, and began reviewing documentation for various Linux input subsystems—including `evdev`, HID, and `/dev/input/jsX` in order to evaluate which layer would provide the most reliable and straight forward support for integrating controller recognition.
The time was mostly spent learning how to use different libraries, tools and creating virtual controller prototype.


## Tools, Libraries, and Concepts Used

### libevdev

`libevdev` is a library for handling `evdev` devices.
It provides a higher-level interface over `/dev/input/event*` and abstracts much of the complexity of input event parsing.
> `evdev` is the generic input event interface. This is the preferred interface for userspace to consume user input, and all clients are encouraged to use it.
>
> -The kernel development community.

`libevdev` can be used to:
- Detect physical game controllers.
- Read input events (e.g., joystick, buttons).
- Create virtual input device and write/forward events to it from physical game controller.

### Useful functions:
- `libevdev_new()`, `libevdev_set_fd(int fd, struct libevdev **dev)`: for opening physical devices.
- `libevdev_next_event(struct libevdev *dev, unsigned int flags, struct input_event *ev)`: for polling events.
- `libevdev_get_id_*(const struct libevdev *dev)`: to query device meta data.

### uinput (User Input Subsystem)
I used the Linux **uinput** subsystem to create a **virtual input device** that mirrors a physical controller input.
**uinput** is what allows us to make a virtual controller out of any evdev device by:
- Opening a file discriptor for the input device that will be emulate (i.e. have it input event forwarded).
- Forwarding the inputs from a `evdev` interface device to `/dev/uinput` (or `/dev/input/uinput`).
- **uinput** then creates a new node to expose the virtual device as a `evdev` interface device in `/dev/input/event*`

From here the idea is that KWin or any other system component can treat the virtual controller as if it were an ordinary HID device.

> uinput is a kernel module that makes it possible to emulate input devices from userspace.
> By writing to /dev/uinput (or /dev/input/uinput) device, a process can create a virtual input device with specific capabilities.
> Once this virtual device is created, the process can send events through it, that will be delivered to userspace and in-kernel consumers.
>
> -The kernel development community.

### Useful functions:
- `libevdev_uinput_create_from_device(const struct libevdev *dev, int uinput_fd, struct libevdev_uinput **uinput_dev)`:
For creating a uinput device based on the given libevdev device.
- `libevdev_uinput_get_devnode (struct libevdev_uinput *uinput_dev)`:
Return the device node representing this uinput device.
- `libevdev_uinput_write_event (const struct libevdev_uinput *uinput_dev, unsigned int type, unsigned int code, int value)`:
Post an event through the uinput device.


Tools used:
- `libevdev-uinput.h` for management of `uinput` devices via `libevdev`.
- `/dev/uinput` opened with correct permissions.
- Ensuring the current user is in the `input` group.
- Verifying that the `uinput` kernel module is loaded (using `modprobe uinput`). Some distros (Ubuntu/Kubuntu) have it built in, not loaded as module, thus `modprobe uinput` command won't log anything.
- Opening `/dev/uinput` with `O_WRONLY | O_NONBLOCK` flags using `open()`, and ensuring no `EPERM` or `EACCES` errors were returned.
- Optional: Run program as sudo user.

### force feedback detection/support

Using `ioctl(fd, EVIOCGBIT(EV_FF, ...))` and tools like `fftest`, I examined:

- How to query a device’s force feedback (FF) capabilities to figure out which effects are supported (e.g., rumble, sine wave).
- How to upload ff effects to physical game controller and test rumble motors.
- This was key to understanding haptic capability support on physical devices.

> To enable force feedback, you have to:
>
> have your kernel configured with evdev and a driver that supports your device.
>
> make sure evdev module is loaded and /dev/input/event* device files are created.


### Testing & Validation
- Used `evtest` and `fftest`to test evdev devices and understand their capabilities -
`sudo evtest /dev/input/eventX`.
- Used those same tools to test virtual devices creating using uinput -
`sudo fftest dev/input/eventX`. uinput creates a node device in `dev/input/eventX` for the virtual input.
- Prototype logs validate that a virtual device can be created and events can properly be written to a that virtual device using `libevdev`.

---

### **Takeaways**

- Using `libevdev` and `libevdev-uinput` we can access physical controllers, create virtual controller and read/write low-level input events.
- Understanding of the permission requirements to open `/dev/input/*` and `/dev/uinput` (use `udev` rules or run as root).
- Tools to test:
- `evtest` and `fftest` (from `input-utils`)
- `udevadm info --name=/dev/input/eventX --attribute-walk`
- Shows the device hierarchy - how the device is connected to PC and any parent device it connects to.
- Built a minimal proof-of-concept C++ program that routes an evdev devices input 1:1 to a virtual controller (via uinput).
- Not all controllers support all force feedback types; some failed with `EINVAL` during upload.
- `libevdev` does not handle FF upload directly — this remains kernel-level and typically involves `ioctl()`.


### References and Documentation
- **[Linux Input Subsystem Documentation](https://www.kernel.org/doc/html/latest/input/index.html) (kernel-level overview of evdev, HID, uinput, etc.)**
- **[evdev interface documentation](https://www.kernel.org/doc/html/latest/input/event.html) (from the kernel source)**
- **[uinput](https://www.kernel.org/doc/html/latest/input/uinput.html): User-level input device emulation**
- **[Force Feedback programming on Linux](https://www.kernel.org/doc/html/latest/input/ff.html) (FF effect types and ioctl usage)**
- **[libevdev](https://www.freedesktop.org/software/libevdev/doc/latest/) (Userspace abstraction for evdev devices)**
Loading
Loading