Moving My Main PC to Linux: Fedora Plasma 44
I have threatened to move my main PC to Linux for years. Servers, the homelab and most of the things I build for a living have been on Linux for a long time. The desktop I sit in front of every day was the one exception, and it stayed that way mostly out of habit and a vague worry about games. Today I finally did it. My main dev and gaming PC now runs Fedora KDE Plasma 44, and I am not planning on going back.
There was no single reason. It was more of a slow build-up. Windows 11 has spent the last couple of years turning into an advert with an operating system attached, with Copilot in places nobody asked for, updates that reboot on their own schedule and a start menu that wants to sell me things. At the same time, Proton has got good enough that “can I still play my games” went from a real worry to an occasional one. And since most of my development work already ends up running in a Linux container somewhere, developing on Windows had started to feel like working through an extra translation layer for no benefit.
So I wiped the drive and started again.
Why Fedora, and why Plasma
I have been an Ubuntu person for as long as I have been using Linux. Every server I have built and most of the VMs I have spun up were Ubuntu. For a desktop, though, I wanted something that moves quicker. Fedora ships current kernels (this machine is on 7.2), current Mesa and current KDE, without the feeling of running a rolling release that might fall over on a Tuesday.
Plasma was an easier decision. I wanted a desktop I could shape to fit how I work, rather than learning someone else’s opinion about how I should work. Plasma 6 is polished, fast, and doesn’t fight me when I want to change something. Coming from Windows, it also feels familiar enough that my first few hours weren’t spent hunting for basic settings.
The sim rig stays on Windows
One machine is not moving, and that is the sim rig.
I race on iRacing, and iRacing’s anti-cheat does not work with Linux or Proton. It isn’t a case of fiddling with launch options until it works. It simply won’t run. The sim rig is a separate PC dedicated to racing, so the answer was easy: it stays on Windows, it does one job, and it does it well.
I actually quite like the split. Windows gets to be an appliance for one game, and the machine I spend my day on runs the operating system I would rather be using. I don’t see that as giving in. It’s just picking the right tool for each job.
The honest caveats
It hasn’t all been smooth. There are three things worth calling out.
- Some games are still a no-go. iRacing is one, and War Dogs is the other. Both come down to anti-cheat. Everything else I have tried today has run fine through Steam and Proton. The anti-cheat problem is a business decision by the publishers, not a technical limit, and until that changes there isn’t much anyone on Linux can do about it.
- Missing drivers. To be fair to Linux, only one device has been a problem on day one. Unfortunately that device is my webcam, and it gets most of this article.
- Knowledge. Years of Ubuntu habits don’t carry over as neatly as I expected.
aptbecomesdnf, PPAs become RPM Fusion and COPR, and SELinux is actually on and actually has opinions. Kernel modules get built through akmods and DKMS against a kernel that updates far more often than I’m used to. None of it is hard, but I spent a good part of today typing the Ubuntu way of doing things before learning the Fedora way instead of assuming it would be the same.
The webcam problem
My “webcam” isn’t really a webcam. It is a Canon EOS M50 outputting clean HDMI into an Elgato Cam Link Pro, a PCIe capture card with four HDMI inputs that can take up to 4K. On Windows it was plug in, install Elgato’s software, done.
On Linux, Elgato has no driver, and the card doesn’t appear as a standard capture device. There is an older community driver for the chipset family inside it, but on this card it loaded and then produced nothing. No picture, just a device that insisted it was working.
Then there is the camera itself. The M50 is designed to be connected to a computer running Canon’s EOS Utility, and without that connection it powers itself down after a few minutes regardless of what you set in the menus. EOS Utility doesn’t exist for Linux.
So on day one, my webcam turned into two problems.
Building a Cam Link Pro driver with Claude
The first problem was the capture card. I sat down with Claude and we wrote a new driver from scratch. It is a Linux kernel module written in C, called camlinkpro, and it exposes the card as a normal V4L2 video device that OBS, ffmpeg and everything else already know how to use. It is on GitHub as elgato-camlink-pro-linux-driver.
I should be honest about my part in this. I know what all the terms mean. DMA, FPGA, I2C, registers, ring buffers, none of that is foreign to me. But knowing what the words mean and knowing where to start writing a kernel driver are very different things, and doing it in C is another step again. I touched a minimal amount of C at university and haven’t written any since. I could have spent weeks fighting the language and the kernel APIs, but there was no point. This is exactly what I was getting at in my post on being language agnostic. Claude handled the syntax and the kernel boilerplate, and I brought the understanding of what the hardware should be doing and whether what we were seeing made sense.
Inside, the card turned out to be a YUAN “SC0710” design: a Xilinx FPGA handling the PCIe side and DMA, a Lattice ECP5 FPGA handling the HDMI front end, and a small ARM microcontroller on I2C that reports what signal is coming in on each input. The ECP5 doesn’t hold its own configuration. The host has to upload it every time, and that bitstream only exists inside Elgato’s Windows installer.
Getting it out was the first puzzle. The firmware file in the installer isn’t stored as-is. It is two halves in swapped order, each XOR’d with a different byte (0xA5 and 0x5A). Once you undo that, the decoded file starts with the words “Lattice Semiconductor Corporation Bitstream”, which was a very satisfying thing to see scroll past in a hex dump. The bitstream is Elgato’s, so it isn’t in the repo. You extract it yourself from their installer.
The second puzzle explained why the old driver showed nothing. The card sends video one line at a time, each line wrapped in a small header. The older code expected a fixed pair of bytes at a certain position in that header, and on this card those bytes hold the source width instead. It never found a single line it recognised, so it never built a frame.
The third puzzle was my favourite. Once we had pictures, every 1080p frame arrived at 960 pixels wide. Every earlier attempt at this card had seen the same data rate, and it turned out one bit in a pipeline control register tells the FPGA to halve the width. Flip it, and full 1920×1080 frames come through.
A few hours after the first image (a slightly squashed Canon menu screen), the driver was doing a steady 1080p at 50 fps with zero dropped frames and zero resyncs. It installs through DKMS so it gets rebuilt with each Fedora kernel update, loads at boot, and shows up in OBS as a normal “Video Capture Device (V4L2)” source.
One oddity from testing: the ECP5 stays configured after a normal shutdown. Standby power in the PCIe slot keeps it alive, so only switching off at the PSU actually clears it. The driver has an fpga_reload option to force a fresh upload when you need to be sure what is running.
What works right now is video on HDMI-1, up to 1080p. Inputs 2 to 4, audio and 4K aren’t done yet. The audio DMA channel has been found but not wired up, and the other inputs need the same treatment HDMI-1 got. For my setup, one camera on one input, it already does everything I need.
What struck me most was how it went, more than the fact that it worked. Claude kept a hardware notes file as we went, and every fact about the card was tagged either as confirmed on this card or as taken from reference material and not yet checked. There was also a dated log of every experiment. Reverse engineering is mostly careful bookkeeping about what you actually know versus what you are assuming, and having that discipline built in from the first hour is a big reason this went from nothing to a working, installable driver on the same day I installed Fedora.
Keeping the camera awake without EOS Utility
With a picture coming through, the next problem was keeping it there. With no computer connected, the M50 was going to sleep after about five minutes. I don’t want to reach over and poke a camera in the middle of a call.
EOS Utility keeps the camera awake by holding a remote session open with it. The camera doesn’t care what software is on the other end. It only cares that something is talking to it properly. So the second tool, canon-eos-wifi-keepalive, does exactly that over Wi-Fi.
It is a single Python script using only the standard library. It speaks PTP/IP, the network protocol cameras use for remote control, and does the minimum needed to look like EOS Utility:
- Discovery: it finds the camera on the network through SSDP, the same way Canon’s software does.
- Pairing: it connects with a GUID that it generates once and saves, so after pressing OK on the camera the first time, it is recognised automatically from then on.
- Keeping awake: it opens a session, puts the camera into Canon’s remote mode, then polls for events every second and sends Canon’s “keep device on” command every minute.
- Recovery: if the camera drops off, it reconnects on its own. After a power cycle, it is back about 25 seconds after the camera is.
It runs as a systemd user service, so it starts when I log in and I never think about it:
[Unit]
Description=Keep a Canon EOS camera awake over Wi-Fi (PTP/IP remote session)
After=network-online.target
[Service]
ExecStart=%h/.local/bin/eos_wifi_keepalive.py
Restart=always
RestartSec=5
[Install]
WantedBy=default.target
Installing is ./install.sh, and if you want to watch it work, journalctl --user -u eos-wifi-keepalive -f shows it chatting to the camera. There is also a fake Canon camera in the test suite that runs on localhost, which is a lot more convenient than pressing buttons on the real one after every change.
The honest caveat is that I haven’t yet pushed it past the 30-minute mark. The M50 has a harder shutoff at around 30 minutes that I’m hoping the keep-alive covers, and that is the next thing to confirm. So far, the five-minute sleep is gone.
Where that leaves me
The main PC is on Linux, and it is staying there. The sim rig is on Windows for as long as iRacing needs it to be. A couple of games are off the table for now, and I am still unlearning some Ubuntu habits.
The part I didn’t expect was the webcam. A few years ago, “Elgato doesn’t support Linux” would have been the end of it. I would have bought a different capture card or kept a Windows install around just for calls. This time the answer was to spend the rest of install day building the missing pieces, and they are both on GitHub now in case anyone else has the same combination of hardware and stubbornness.
Turns out the missing driver was just one I hadn’t written yet.