
For years, Linux users have been asking for better support for modern USB fingerprint readers. You can find these things everywhere. They're small, portable and inexpensive, and for around $10 to $50 you can add fingerprint authentication to just about any Windows PC. Some even support macOS. Linux users haven't been so fortunate.
It's not that Linux doesn't support fingerprint authentication. It does. The problem is that many of the small, inexpensive Windows Hello readers that have flooded the market simply aren't supported. If you wanted a reliably compatible external reader, you often ended up looking at older, bulky desktop scanners that looked like they came straight out of the early 2000s.
It's not for lack of trying, either. The Linux community has been asking manufacturers to support these devices for years, and independent developers have made several attempts to reverse-engineer them. Some figured out how to communicate with the sensors, initialize the hardware and even capture fingerprint images. That's where the progress stopped, because getting an image off the sensor is only half the problem. The other half is reliably matching that image against an enrolled fingerprint, and the algorithms manufacturers use to do that are proprietary.
That was the obstacle nobody had managed to overcome for the FT9201, a Focal-systems reader (USB ID 2808:93a9). I own one, and in April I took my first crack at it. I got Linux talking to the sensor and pulling fingerprint images off it, which put me right where everyone else had stopped. (FocalTech does have a closed-source Linux driver for a related model, but not for this one.)
I banged my head against my desk trying to build the matching myself. The sensor only captures a 96 by 96 pixel image, which is tiny for a fingerprint. There isn't enough detail for libfprint's standard matcher to reliably tell one finger from another. It would accept the wrong finger or reject the right one at random. I had hit the limits of what I knew, so I put the project down.
In July I came back to it with a different idea. FocalTech already had a matcher built for this exact sensor, so why was I trying to build a replacement? What if I just used theirs?
FocalTech's Windows driver includes a file called ftWbioEngineAdapter.dll. It's the matching engine Windows Hello uses with this reader. The problem was getting a Windows DLL to run natively on Linux. And I mean natively: no Wine, no Windows installation, no virtual machine in the background.
The answer, which I built with Claude Code, was a small loader, about 450 lines of C. It maps the DLL into memory, provides the roughly 90 Windows system functions the DLL expects, recreates just enough of Windows' per-thread environment to keep it happy, and then calls straight into FocalTech's matching engine. It never makes memory both writable and executable, so fprintd's security hardening stays on.
That wasn't the only hurdle. The sensor's microcontroller has no firmware of its own, so the driver has to upload it, and uploading alone wasn't enough. It needed a specific sequence of register writes before it would run, which I recovered from FocalTech's own Linux driver.
Then came the discovery that made the biggest difference. The sensor captures 96 by 96 images, but FocalTech's matcher is designed for 64 by 80. Feeding it the whole image gave me the same unreliable results I'd been fighting before: of five fingers tested, none matched its own enrollment. Cropping the image to the size the engine expects fixed it. Five out of five.

My second attempt started on July 9, and by July 10 I had a working fingerprint reader. Not just a proof of concept in a terminal: it's integrated with libfprint and fprintd, so I can enroll a finger and verify it through KDE or GNOME. A reader that was sold for Windows Hello now works on Linux, using the manufacturer's own matching algorithm. I think that's pretty cool.

What matters to anyone else is the method. The barrier everyone kept running into was the proprietary matcher, and this gets past it without recreating it: the manufacturer's own matcher does the matching. So I published the code on GitHub, with a technical writeup and a guide for trying the method on other Windows Hello readers.
When I shared it on r/Linux, it spent a couple of days on the front page, which says something about how many people have wanted this. A few people compared it to ndiswrapper, the old tool that let Linux run Windows Wi-Fi drivers, which is a pretty fitting comparison.
The maintainer of libfprint joined the thread too. He said a version inside libfprint wouldn't be maintainable, because it would mean reimplementing many Windows interfaces, that Wine is the better way to work out a device's protocol, and that libfprint's own matching could be improved. He also pointed to a similar project of his own, synaWudfBioUsb-sandbox. I offered him my reader and the few like it that I own to test with.
The thread also turned into a debate about AI-assisted development, so I want to be clear about that part. I built this with Claude Code. I found the problem, came up with the approach of running FocalTech's own matcher, directed the work, tested it on real hardware and judged the results until it worked. Claude Code and my development setup handled most of the code, testing and writing. When someone asked whether I or Claude had written it, I answered Claude. The commit history shows it.
People have started building on it, which is what I hoped for. A commenter with a different FT9201 model said it didn't work on theirs, and two contributors have opened pull requests, all still open on November 9, 2026. One adds support for a variant that reports a different sensor type and fixes a crash when a scan is canceled. Another checks a finger against every enrolled template, which login and sudo prompts need when more than one finger is enrolled. There's more work to do.
It has limits. It still depends on FocalTech's proprietary matching engine and firmware. A script fetches them when you build it, and the repository doesn't contain them. I've only tested it on one reader, the FT9348W variant of the FT9201, and because the engine is 64-bit x86 code, it only runs on 64-bit x86. The same method should work for other readers sold only for Windows Hello, but I've only proved it on this one.
The USB protocol work started with banianitc's FT9201 driver, and I also relied on mrrbrilliant's FT9201 work for the firmware and the start-up sequence. This builds on both.
This doesn't fix every fingerprint reader on Linux. What it does show is that the barrier people kept running into for years, the proprietary matcher, can be worked around. The method is public, and the next Windows Hello reader doesn't have to stop where the FT9201 did.