[HN Gopher] Writing a basic Linux device driver when you know no...
       ___________________________________________________________________
        
       Writing a basic Linux device driver when you know nothing about
       Linux drivers
        
       Author : sbt567
       Score  : 412 points
       Date   : 2025-06-22 10:29 UTC (4 days ago)
        
 (HTM) web link (crescentro.se)
 (TXT) w3m dump (crescentro.se)
        
       | ianlevesque wrote:
       | It's a userspace USB HID driver in rust, which is honestly more
       | interesting/applicable to me than a kernel driver, which is what
       | I thought it meant from the title.
        
       | ahartmetz wrote:
       | > I also thought I'd message the vendor and ask them if they
       | could share any specifications or docs regarding their protocol.
       | To my surprise, Nanoleaf tech support responded to me within 4
       | hours, with a full description of the protocol that's used both
       | by the Desk Dock as well as their RGB strips.
       | 
       | How cool is that? Too many vendors still think that they have
       | valuable intellectual property in such relative trivialities. And
       | that handing out the specs freely helps their competitors more
       | than themselves.
        
         | starkrights wrote:
         | I had the same reaction. Nano leaf is extremely cool for that.
        
           | baby_souffle wrote:
           | This has to put them in the top 0.01% of companies that make
           | consumer electronics.
           | 
           | I can think of only a few companies that bother to publish
           | any details... And most of them are focused on industrial
           | customers where it isn't unreasonable to need certain
           | protocol details for integration or even just compliance with
           | certain regulatory systems.
           | 
           | Maybe things are changing?
           | 
           | I have noticed that some of the LED light controllers you see
           | on AliExpress are leaning in to open firmware standards. 5
           | years ago, you bought the controller and had to flash your
           | own firmware. Now, there's an option at checkout to select an
           | open source firmware. Some even have a USB port built in for
           | flashing!
        
             | pipe01 wrote:
             | It really makes me wonder why it's not more common. They
             | literally don't have to write any firmware, just use one of
             | the thousands already available provided that the license
             | allows for it
        
         | Teknoman117 wrote:
         | I almost had that experience with one of the popular PC liquid
         | cooling hardware vendors around 10 years ago.
         | 
         | I emailed them saying I'd be interested in developing drivers
         | for their hardware for Linux as I was a happy customer and was
         | immediately put in touch with one of the managers and their
         | engineering team.
         | 
         | Made quite a bit of progress before the whole thing was shut
         | down because one of their component vendors threatened them
         | saying it'd be a breach of their contract with them.
         | 
         | Apparently that vendor sold a "datacenter" (non consumer)
         | version of that hardware for which they charged a hefty license
         | fee for the management software (which was Linux compatible).
         | 
         | Jokes on them, someone reverse engineered the whole thing with
         | a USB analyzer years later and published it XD. (not me)
        
         | agentkilo wrote:
         | Yeah that part of the article put a big smile on my face.
         | 
         | I did the same thing back in college, when I was in a lab. We
         | wanted to do some research on Wi-Fi signals, and I happened to
         | own a bunch of Wi-Fi adaptors produced by SomeSmallTech Co.
         | Ltd., which featured relatively new Atheros chips and didn't
         | have Linux drivers at the time.
         | 
         | So I sent an email to the company's public email address,
         | asking for some datasheets, "for science". To my
         | disappointment, presumably a PR person replied that they "don't
         | have a company policy to collaborate with academic research".
         | (But they did send a quick reply, kudos to that.)
         | 
         | Funnily enough, years later I ended up working for said
         | company. Naturally, when I first logged into the company
         | network, I searched for the datasheets I asked for. There were
         | "classified" watermarks all over the PDFs :)
        
           | wiz21c wrote:
           | > don't have a company policy to collaborate with academic
           | research"
           | 
           | Strangely they all have a tacit policy to build their
           | products at least partly on the results of academic research.
        
         | 2Gkashmiri wrote:
         | I have a solar inveter from a company, aparticular German
         | brand. I wanted to use home assistant with it so I needed rs232
         | data.. tried the support and they asked me to sign an NDA.
         | 
         | Okay, cool. I did with a fake name, address and everything and
         | they sent a file..
         | 
         | Turns out the file is available online.
         | 
         | Facepalm pro Max.
         | 
         | So my question is, what kind of "IP" is in a data sheet that
         | needs protection ? And this isnt even some secret product but a
         | generic solar product sold by millions.
         | 
         | Rs-232 protocol ? Really ?
        
           | wiz21c wrote:
           | They have asked to the legal team who basically don't know
           | shit about what us do and who will always take the most
           | conservative approach possible. So you'll get either: no
           | answer, a "NO" answer or an "NDA" answer.
        
             | tialaramex wrote:
             | Yup. The default from lawyers will be "No" because why
             | help? The correct way to use lawyers, either in-house
             | counsel or a paid lawyer if you have a specific project is
             | to tell them what you _want_ to happen and then they figure
             | out what the best legal course of action is to closest
             | achieve that. Mundanely this might mean e.g  "Fill out form
             | X1234 and then send letters to this politician suggesting
             | they support your X1234 application" but at the extreme it
             | could mean closer to the situation in the UK where a ferry
             | company illegally fired crews with zero notice, and their
             | legal advice had clearly been "Worst case they put one of
             | your executives in prison, probably not even that, but
             | either way you replace union workers with people on slave
             | wages and that means $$$".
        
           | Mad_ad wrote:
           | Was it Alpha-ESS? they make it so stupidly hard to get your
           | information outside of their smartphone app.
        
           | ainiriand wrote:
           | Germans germaning!
        
             | ahartmetz wrote:
             | Even though there are much fewer lawyers in Germany and
             | they are less involved in running companies (like in any
             | country, compared to the US).
        
         | sysmax wrote:
         | It's not the IP, it's sadly how people react. Some folks will
         | be appreciative of help, credit to them. Others will
         | immediately get back how they tried it, it didn't work and now
         | they need you to rewrite everything, or do their project for
         | them, or redesign your product to match what they want it to
         | be. And if you politely refuse, it quickly escalates to threats
         | of trashing your business through every channel, and other
         | things.
         | 
         | So, the safest thing to do is not give details at all, or
         | "leak" them like another reply in this thread mentions.
        
         | amelius wrote:
         | I wish more vendors would put "Linux support" on the package.
         | Or maybe "Unofficially supported in Linux" or "Linux community
         | support" if they don't want to get their fingers burned.
         | 
         | Maybe this kind of thing should be enforced in the GPL (as many
         | devices use Linux under the hood).
        
           | ahartmetz wrote:
           | IME, Linux support is often mentioned on the package these
           | days. But you still need to look it up anyway because it's
           | often a vendor source dump for a particular kernel version.
           | Such drivers are often not that good. Notable exception: my
           | Brother printer-scanner-copier has been working fine with its
           | vendor-provided user space driver for ~10 years now. I think
           | it has not been updated for most of that time. It contains 32
           | bit binaries!
        
         | BobbyTables2 wrote:
         | Or worse, they just reply "Linux is not supported" ...
        
       | jonnypotty wrote:
       | Thanks for this. Good read and also kinda inspiring.
        
       | dabedee wrote:
       | I really enjoyed the way this post was written, i.e. it includes
       | the code, how it was run, the false paths, etc. You almost get to
       | live through the author's journey and how he figured out just
       | enough to get something working.
        
       | kblissett wrote:
       | I enjoyed this post, but I'm eager to hear what the next step
       | would be for a real "production" userspace driver. Are these
       | typically just daemons that are configured to run at start up?
       | And then some configuration GUI communicates with it over a
       | socket or something?
        
         | ItsHarper wrote:
         | You could certainly do that, and it would make a ton of sense
         | if there's both no standard software API for communicating with
         | that type of device, _and_ it 's important that multiple pieces
         | of software that communicate with the device are able to run at
         | the same time (or you want to avoid repeating work when
         | starting software multiple times). ADB (Android Debug Bridge)
         | takes this approach.
         | 
         | If there _is_ an applicable standard software API (either
         | multiplatform like a filesystem, or a special one exposed by
         | the OS kernel [1] ), the driver probably belongs in the Linux
         | kernel (or in the form of a Windows driver on that platform).
         | My understanding is that GPU APIs are an exception on Linux,
         | and are implemented in userspace by a piece of software called
         | MESA. You could also use the daemon approach in this case if
         | you don 't want to bother with getting a driver added to the
         | kernel.
         | 
         | For a more niche device where exclusive access is acceptable
         | and every piece of software would need to add special support
         | for this specific type of device anyway, it's a lot simpler to
         | distribute the driver as a library that software authors can
         | include in their program. If there are several devices that
         | work similarly but communicate differently, you could have one
         | library that either includes multiple drivers, or exposes a
         | common interface that other libraries can implement.
         | 
         | A downside of any approach for USB devices on Linux that isn't
         | a kernel driver is that one or more udev rules will need to be
         | added (as the article described). This also applies when using
         | a device that uses a supported USB protocol, but has different
         | IDs than the ones listed in the kernel driver.
         | 
         | [1] More devices fall into this category than you might expect.
         | For example, Linux has an API for communicating with CAN
         | devices called SocketCAN, so if you're writing a driver for a
         | CAN device that connects via USB and exposes the full CAN bus
         | over USB (maybe something that goes in or connects to a car),
         | you should write a kernel driver that converts data between
         | SocketCAN and whatever USB protocol is being used (assuming one
         | doesn't already exist, a lot of USB CAN devices use protocols
         | that already have drivers in the kernel). SocketCAN only
         | exposes the raw data extracted from the CAN frames, so if you
         | want to expose an easy way to control a particular CAN device,
         | that belongs in a userspace library that uses the SocketCAN API
         | under the hood.
        
       | shreddit wrote:
       | > Let's run it again to make sure it was not a fluke!
       | 
       | I understood that reference
        
       | 0xbadcafebee wrote:
       | I want to run FreeBSD on my laptop, but they don't have a
       | [complete] driver for my wifi card. I've thought about diving
       | into AI coding-assistant agents just to see if I could use one to
       | finish throwing together a working driver... but figuring out the
       | AI agents is frictiony enough that I'm leaving it be. (I'm not a
       | VSCode user)
        
         | buildbot wrote:
         | Claude code, being a CLI interface, might be more your style?
         | Expensive though
        
         | fithisux wrote:
         | AI can also be used to help reverse engineer blobs.
        
         | MobiusHorizons wrote:
         | My understanding is that FreeBSD lacks the support for modern
         | WiFi standards in any of its drivers, so it would be a
         | significant effort of understanding the WiFi protocol in
         | addition to understanding your specific device. That said,
         | FreeBSD would be much easier to use on laptops if someone were
         | to put in this effort
        
       | LorenDB wrote:
       | The author should probably have implemented support in OpenRGB
       | instead to better benefit others, but this is cool nonetheless.
        
         | jeroenhd wrote:
         | I think they wrote the code more for the challenge of it than
         | anything else. The final code doesn't seem to do more than the
         | bare basics (which is probably enough for the author).
         | 
         | Plus, to port this to OpenRGB, you'd need to rewrite the code
         | into C++ (ugly, old C-inspired C++, at that: https://github.com
         | /CalcProgrammer1/OpenRGB/blob/master/CONTR...) which would take
         | most of the joy out of it for me at least.
        
           | surajrmal wrote:
           | I don't think the style described in that doc is at all ugly.
           | It's practical and simple. I say this as someone who spends a
           | lot of time writing modern c++ and heavily using templates.
           | 
           | I thoroughly enjoy rust, but I doubt not being able to use it
           | should be grounds for avoiding contributing to a project.
           | Unless you are going to write async heavy code, libusb is
           | pretty easy to use in C.
        
       | fracus wrote:
       | I wish this was done in C so I didn't have to learn Rust. But
       | maybe it is time to learn Rust.
        
         | dralley wrote:
         | Rust isn't that difficult really. Easier in many ways than C if
         | you're building normal software and not, like, a library of
         | fancy data structures.
        
         | jeroenhd wrote:
         | This is using rusb, a Rust wrapper around libusb. libusb is
         | still written in plain old C: https://libusb.info/
         | 
         | If you don't want to learn a different programming language,
         | you can take the exact same approach in any language you prefer
         | and play along. You may need to turn the more object oriented
         | calls into libusb_* calls, but if you're used to programming in
         | C you probably won't have a problem getting that to work.
        
       | VTimofeenko wrote:
       | Excellent post! I have a Nanoleaf 3d thing that I was hoping to
       | use as an ambilight-like thing for the TV, but the experience
       | was... meh. I know about the Hyperion project and hope to set it
       | up one day, but meanwhile I think I could try to repurpose this
       | code to control the strip from a Linux box.
        
       | rkagerer wrote:
       | This is awesome!
       | 
       | But it also makes me a little bit sad. The original parallel port
       | and even ISA interface seemed so simple by comparison, with less
       | layers of abstraction. Just run a wire, and write to a port.
       | 
       | I remember when I was a kid, I found a breakout board in an
       | electronics store's random clearance parts bin, with an ISA
       | header on an edge. On a whim I took it home and wire-wrapped a
       | 7-segment LED onto it. Power and ground were easy. Each segment
       | was hooked to a data line, through a simple buffer IC. I cheated
       | and used only a minimal number of address lines to feed the
       | enable port (guessing through a simple AND gate or something). I
       | was amazed when I wrote to that address and it worked the first
       | time!
       | 
       | I look at a protocol like USB, with hundreds of pages, and
       | instead of that curious excitement and enablement I felt back
       | then, I feel a bit overwhelmed.
        
         | colechristensen wrote:
         | I sometimes think about this, starting from scratch with a
         | computer hardware and software stack that disallowed all of the
         | layers of abstraction that have built up over the decades.
         | 
         | Yeah many of the abstractions help with performance but maybe
         | there's value giving up much of that performance in exchange
         | for simplicity.
        
           | rkagerer wrote:
           | It would be neat to design a whole new contemporary stack
           | from scratch.
        
             | bzzzt wrote:
             | It would also be an enormous undertaking, requiring man-
             | centuries of work and has the risk of falling into the
             | 'second systems effect' trap...
        
           | dspillett wrote:
           | For toy tinkering, to replicate something like the old
           | ability to just write a byte to an IO memory location and
           | have it appear on the pins of a parallel port, you could
           | design a simple USB peripheral that did similar. Give it a
           | set of DIP switches to pick a number (4 for 0-f, more would
           | probably be overkill but feel free) and have the driver
           | present something like /proc/simpleio/device<num>/in and
           | /proc/simpleio/device<num>/out/pin<num> for reading &
           | writing1. If you use the same set of pins for in and out,
           | /proc/simpleio/device<num>/config to state which direction
           | each is expected to work, and perhaps set voltage options
           | (probably per device, per pin sounds overkill for this).
           | Release the full design and let people make their own, sell
           | pre-made boards and cases and/or let others do that (or just
           | the boards and have people 3D-print their own cases). Devices
           | could have as many pins as the maker likes.
           | 
           | That would only cover the real basics: reading/writing the
           | hi/low status of pins. Other things people might want is
           | analogue voltage control/read (for many sensors) or pulse
           | control (for controlling servos and such). Things like that
           | could be mapped into the
           | /proc/simpleio/device<num>/{in|out}/pin<num> files. Perhaps
           | for setting/reading multiple pins at a time perhaps have
           | something like /proc/simpleio/device<num>/{in|out}/allpins.
           | You could expand the feature in many ways, though TBH beyond
           | the simple hi/low thing people are probably better off
           | getting an rPi or microcontroller and using all the available
           | devices and plans there are out there already for their IO
           | pins and using something newer.
           | 
           | --------
           | 
           | [1] Not sure what you'd do for Windows, I'd be inclined to
           | release a Linux driver and let the Windows community worry
           | about one for their platform.
        
             | colechristensen wrote:
             | USB parallel ports, data acquisition peripherals, or modern
             | boards that run linux and have GPIO pins are already a
             | thing and don't need to be created.
             | 
             | What I'm talking about is a whole computer system + systems
             | programming language + OS which is as simple to understand
             | and program as computers were in the 80s. With modern
             | speedups, without modern layers of abstraction.
        
             | rkagerer wrote:
             | Thanks for the info!
             | 
             | I actually bought a real parallel port card years ago that
             | plugs into a PCI port on my motherboard. Incidentally it
             | also provides 4 serial ports.
             | 
             | Only tried it on Windows, but it works great. If I recall
             | there was some kind of library I have to use in modern
             | Windows versions due to a permissions or kernel isolation
             | thing.
        
         | znpy wrote:
         | > The original parallel port and even ISA interface seemed so
         | simple by comparison, with less layers of abstraction. Just run
         | a wire, and write to a port.
         | 
         | All those layers of abstraction is likely what allows us to
         | hook up a single wire to our laptops and get multiple very fast
         | ports from the docking station along with power and display
         | output.
         | 
         | You get some, you lose some.
        
         | vbezhenar wrote:
         | USB is designed to solve a complex, but necessary problem.
         | 
         | 1. Hot-plug.
         | 
         | 2. High speeds with long cables of dubious quality.
         | 
         | 3. Multiplexing multiple devices on a single wire with hubs.
         | 
         | 4. Reliable transmission on lower layer, so higher level
         | protocols don't need to worry about it.
         | 
         | 5. Multiple speeds with negotiation.
         | 
         | 6. Newer USB standards support multiple power voltages with
         | negotiation.
         | 
         | All that said, old USB protocols like USB 1.1 is not that hard.
         | You don't need those hundreds of pages, only a subset of them.
         | There are some tutorials in the Internets which will help you
         | to understand everything, from wire signalling to application
         | interface. Don't use USB reference as a learning source. These
         | days ChatGPT probably will guide you over every layer. Just
         | stick with old standards, they are simpler and plenty of
         | devices use them.
         | 
         | With enough persistence and some fast enough MCU you should be
         | able to bit-bang USB 1.1 LS (1.5 Mbps) and write some simple
         | USB device. That will require to implement all layers of USB
         | and I'm pretty sure it's not impossible task.
        
         | jeroenhd wrote:
         | Serial ports still exist today. Even in desktop computers
         | (though usually in weird underpowered ones designed for
         | industrial applications and such). Even the most GAMING of
         | motherboards have headers ready for one or even more serial
         | ports to mess with. All you need is a cable and a card to slot
         | into a PCIe bracket!
         | 
         | USB itself, at least the 1.1 protocol that's still used for
         | some devices today, isn't all that complicated in itself:
         | https://youtu.be/wdgULBpRoXk
         | 
         | Many if the complicated parts here, like device identifiers,
         | are the things you'd need to manually configure if you were to
         | use a serial port. Those hundreds of pages are similar to the
         | hundreds of device types, vendors, and models that Windows
         | would list when you clicked "add new hardware" back in Windows
         | 98. When push comes to shove, you're just sending energy pulses
         | down wires, there's just a chip in there that helps collect
         | pulses so you don't need to manage the timing manually.
        
       | dmonitor wrote:
       | This is exactly the kind of simple tutorial I was looking for a
       | few years ago. I forget what the project was that I wanted this
       | for, though, haha. Thank you for the writeup!
        
       | bhasi wrote:
       | The title was misleading because the author wrote a userspace
       | Rust driver and not a Linux kernel driver in C.
        
         | amelius wrote:
         | Upon reading the title I thought this was going to be about how
         | easy it is to write or modify a Linux driver when using a LLM
         | even if you know nothing about the subject.
        
           | Neywiny wrote:
           | No LLM needed. Kernel driver code for simple things is
           | usually copy-paste-modify. Find something that works with an
           | HID interrupt based device, and modify that. If you want a
           | /sys led, copy from that. It's only if you try to push to
           | mainline you need to worry about understanding it, but they'd
           | probably smell LLM trash from miles away.
        
       | fithisux wrote:
       | There are many innovative OSes that are killed by the lack of
       | Device Drivers.
       | 
       | As a community we must find a way for tackling this issue.
       | 
       | Micro-Kernels are a solution where one can run different OSes but
       | they will reuse the same device driver servers.
       | 
       | But it requires co-ordination and determination.
       | 
       | Rust can be a solution for sure.
        
         | jeroenhd wrote:
         | Any programming language can be a solution, the programming
         | language itself isn't the problem. Convincing device driver
         | programmers around the world to come up with a universal API
         | that includes all the possible features and works on every OS
         | is.
         | 
         | In this case, the cross-platform libusb should make this code
         | work on either Linux or Windows (if you install the signed
         | Windows drivers). If other operating systems port libusb, they
         | get this code for free.
         | 
         | Most "real" drivers still run in kernel mode, though, and not
         | even Linux can keep their ABI stable (Windows has to, between
         | releases, with the aid of compatibility wrappers that only work
         | for a certain amount of releases).
         | 
         | It would probably be worth it more forbBespoke operating
         | systems to implement either the Windows API (like ReactOS does)
         | or the Linux API (pick an LTS version) to get existing drivers
         | to work. Unless you pay them, most driver programmers aren't
         | going to bother with anything than Windows, maybe Linux,
         | _possibly_ macOS.
        
           | sumtechguy wrote:
           | On a previous project I spent a lot of time trying to figure
           | out a 'generic device driver'. That is actually a decently
           | hard space to crack. As each device has randomly different
           | ways of talking. Some are serial/local bus. Some are memory
           | space. Some have a combination. Some systems broadcast data,
           | some you have to query it, some you have to query then wait
           | for the next broadcast. Some systems mildly follow the spec,
           | some strictly follow it, some strictly follow their own
           | flavor of the spec or an outdated one, some have their
           | totally made up spec that they may or may not give you. Even
           | from the same company you can have two models that on the
           | outside if you use their stuff looks the same but under the
           | hood is sorta different enough that your driver is garbage. I
           | basically ended up here https://xkcd.com/927/
        
         | yjftsjthsd-h wrote:
         | Neither microkernels nor rust will help if you can't get
         | everybody to agree on an ABI, which is the hard part in the
         | first place.
         | 
         | That said, if you're willing to deal with other people's APIs,
         | NetBSD's rump kernels are good for providing reusable drivers,
         | and some projects have even had luck pulling drivers out of
         | Linux to reuse, though obviously that's a little bit touchier.
        
       | amelius wrote:
       | Does this provide protection against opening then device from two
       | processes at the same time?
        
         | yrro wrote:
         | Does O_EXCL work with linux USB devices?
        
       | blahgeek wrote:
       | Given the title, I'm surprised (in a good way) that it's not
       | about AI coding.
        
         | Culonavirus wrote:
         | I was kinda hopeful... I mean, letting an LLM write a driver,
         | what could possibly go wrong :)
        
       | rajiv256 wrote:
       | Love it! I wrote an RTL8139 Ethernet driver in Rust as my
       | undergrad thesis!
       | 
       | With questionable grammar:
       | [https://rajiv256.github.io//projects/ouros/](link)
        
       | westurner wrote:
       | Recommendations for a tutorial on how to write a formally
       | verified kernel module in C? Rust?
       | 
       | Are VFIO or eBPF sufficient; Does this code need to run in the
       | kernel?
        
       ___________________________________________________________________
       (page generated 2025-06-26 23:01 UTC)