Updating OpenHardware Firmware

EDIT: Don’t implement this. See the follow-up post.

One of the use-cases I’ve got for fwupd is for updating firmware on small OpenHardware projects. It doesn’t make sense for each of the projects to write a GUI firmware flash program when most of them are using a simple HID or DFU bootloader to do basically the same thing. We can abstract out the details, and just require the upstream project to provide metadata about what is fixed in each update that we can all share.

The devil, as they say, is in the details. When enumerating devices, fwupd needs to know the device GUID (usually, just a hardcoded mapping table from USB VID/PID). This certainly could be in a udev rule that can be dropped into the right place when developing a new device, as I don’t want people to have to build a fwupd from git just to update the new shiny device that’s just arrived.

There are two other things fwupd needs to know. The most important is the current firmware version for a device. There is no specification for this as far as I can tell. ColorHug has a HID command GET_VERSION which returns 3 uint16M numbers for the major, minor and micro versions and other device firmwares have other similarly obvious but different ways of doing it.

The other is how to switch the device in firmware mode back into bootloader mode so that it can flash a new version. For ColorHug there’s a RESET command, but on other hardware it’s either a custom command sequence, or doing something physical like pressing a secret button with a paperclip or shorting two pins on a PCB.

I think it would be useful to notify the user that there in an update available, even if we can’t actually do the upgrade without doing some manual step. For this we need to get the current firmware version, ideally without open()ing the device as this will prevent other software from using it straight away. What we can get from the device for free is the device descriptors.

What I’m going to do for ColorHug is to change the unused device serial string descriptor to “FW:1.2.3”. I’ll also support in fwupd devices changing the product string from “Widget” to “Widget FW:1.2.3” i.e. we look in the various strings for a token with a “FW:” prefix and use that.

If that isn’t specified then we can fall back to opening the device and doing a custom command, but when you can ask friendly upstream firmware vendors to make a super small change, it makes things much easier for everyone. Comments welcome.

Published by

hughsie

Richard has over 10 years of experience developing open source software. He is the maintainer of GNOME Software, PackageKit, GNOME Packagekit, GNOME Power Manager, GNOME Color Manager, colord, and UPower and also contributes to many other projects and opensource standards. Richard has three main areas of interest on the free desktop, color management, package management, and power management. Richard graduated a few years ago from the University of Surrey with a Masters in Electronics Engineering. He now works for Red Hat in the desktop group, and also manages a company selling open source calibration equipment. Richard's outside interests include taking photos and eating good food.

8 thoughts on “Updating OpenHardware Firmware”

  1. I think abusing the serial string is a *** idea. If this becomes a common pattern, you may need to “reinstall” your hardware every time the firmware is updated.

    E.g. USB printers are identified in the CUPS URI by its serial.

    If you want to do it properly, nonblocking, use a device request to the control endpoint.
    You can add an interface descriptor with an vendor interfaceClass/Subclass. To this, you can add an arbitrary descriptor.

    1. Sure, valid point about the CUPS serial issue. I did think about just adding a different interface for getting the firmware version, but that doesn’t work so well when there’s a kernel driver. For devices like ColorHugALS we’re already at 96% program space used, so there’s not a huge amount of space left. That said, if we could agree on a new interface spec or extend DFU in some way I’d be really keen on working together on this.

      1. By “the unused device serial string descriptor” did you mean the serial string from the standard device descriptor? Windows use it to identify the device (e.g. as part of the device path or in the corresponding key in the registry) if this string is available . At work we set the serial number for our devices so that user space can reliable detect them (e.g. if multiple devices are attached, always talk to the same device even if it is plugged in another port). Other vendors might rely on this Windows behaviour too which might prevent adaptation of your idea.

        Personally I would prefer extending DFU but I have no experience with USB working groups. So I don’t know what it would take to extend the DFU class. So maybe the most pragmatic way is to create a new class (aka device meta data interface??).

        Anyways I like your idea of fwupd – at work one of the big item in our backlog is the FW upgrade including all the user space tools. It would have been nice, if there was a way to do it by generic means supported by all major operation systems …

        1. If Windows is using it for device enumeration changing the serial number between firmware versions is probably not a good idea :/

      2. Hm, adding it as a vendor class interface descriptor is bytes. 9 Byte for the Interface descriptor itself, on byte bLength.

        I don’t think there is an issue with the HID kernel driver, the second interface should be ignored.

        Extending the DFU with a “current version” descriptor would be nicer, indeed.

Comments are closed.