Skip to content

Support hardware model v2#43

Merged
joelspadin merged 3 commits intozmkfirmware:mainfrom
joelspadin:hw-model-v2
Jan 4, 2026
Merged

Support hardware model v2#43
joelspadin merged 3 commits intozmkfirmware:mainfrom
joelspadin:hw-model-v2

Conversation

@joelspadin
Copy link
Collaborator

@joelspadin joelspadin commented Nov 23, 2025

This updates ZMK CLI to understand Zephyr's hardware model v2 board revisions. zmk keyboard new now also generates board files correctly for hardware model v2.

Board qualifiers are not yet handled, since those need to go after the board revision, but I want to see what we decide on zmkfirmware/zmk#3145 before figuring out if/how ZMK CLI needs to handle those.

@joelspadin joelspadin added the enhancement New feature or request label Nov 23, 2025
@joelspadin joelspadin marked this pull request as ready for review December 10, 2025 02:55
Updated the west project filter to exclude lvgl and zmk-studio-messages,
since they aren't needed for discovering keyboards.

West commands now check the project filter and update it as necessary.
This required reworking West to be run in a subprocess, because the
command to read the value of a config property terminates the current
script if the property isn't set.
Copy link
Contributor

@caksoylar caksoylar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, a few comments.

Maybe it'd make sense to rename Keyboard class to KeyboardComponent, given it also encapsulates boards that are not keyboards by itself?

@joelspadin
Copy link
Collaborator Author

LGTM, a few comments.

Maybe it'd make sense to rename Keyboard class to KeyboardComponent, given it also encapsulates boards that are not keyboards by itself?

I don't think I designed this very well, and I think I want to fix it in a separate PR rather than trying to do it here.

Currently, both boards and shields can be a "keyboard" if they have the keys feature. MaybeKeyboard would be a more appropriate name for this class. My current solution for modeling the hardware is to have both Board and Shield derive from a class that has the interface for everything we want to know about a keyboard, then to use an is_keyboard() function to check if something is actually a keyboard.

The problem with this is that the component that has keys is usually not a complete keyboard on its own. I'm thinking of restructuring it something more like this, where Keyboard describes the combination of components that result in a complete keyboard. This would also give a more convenient place to store the board revision (and maybe any board qualifiers) that are chosen for the build, and it would make it easier to implement a UI where zmk keyboard add offers to add other shields to the build (displays, etc.).

classDiagram
    Hardware <|-- Interconnect
    Hardware <|-- KeyboardComponent
    KeyboardComponent <|-- Board
    KeyboardComponent <|-- Shield

    Keyboard *-- Board
    Keyboard *-- Shield

    class Hardware {
        +str type
        +str id
        +str name
        +str file_format
        +str url
        +str description
        +str manufacturer
        +str version
        $from_dict(data)
    }

    class KeyboardComponent {
        +list[str] siblings
        +list[str] exposes
        +list[Feature] features
        +list[Variant] variants
    }

    class Board {
        +str arch
        +list[Output] outputs
        +list[str] revisions
        +str default_revision
    }

    class Shield {
        +list[str] requires
    }

    class Interconnect {
        +dict[str, str] node_labels
        +str design_guideline
    }



    note for Keyboard "get_build_items() returns
    one item per combination 
    of board/shield siblings,
    with revision+qualifiers, e.g. 
    - board=foo
    - shield=bar,baz
    - board_revision=2
    - board_qualifiers=a,b
    with bar having siblings
    returns:
    - 'foo@2/a/b', 'bar_left baz'
    - 'foo@2/a/b', 'bar_right baz'"

    note for Keyboard "is_complete is true when 
    board is set and at least 
    one item in boards/shields 
    has the 'keys' feature."

    class Keyboard {
        +Board board
        +list[Shield] shields
        +str board_revision
        +list[str] board_qualifiers
        +bool is_complete 
        +bool has_revision(revision)

        +list[BuildItem] get_build_items()
    }

    class BuildItem {
        +str board
        +str shield
        +str snippet
        +str cmake_args
        +str artifact_name
    }

    Keyboard -- BuildItem
Loading

"zmk keyboard add" nows understand board revisions.

If you attempt to add a board which has multiple revisions (and you
don't provide a revision with a parameter like "-c nice_nano@2"), it
will now prompt you to select a revision.

When copying .keymap and .conf files to your config repo, if the
keyboard is a board with a revision, it will now check for versioned
files before checking for a common file with no revision.

"zmk keyboard list" now supports a --revisions flag which prints each
board revision as a separate item.
Updated the board templates for "zmk keyboard new" to support Zephyr's
hardware model v2. Also updated links to Zephyr's documentation to point
to Zephyr 4.1 to match the ZMK update that brings in hardware model v2.
@caksoylar
Copy link
Contributor

I see, your plan+diagram makes sense to me (and certainly, not for this PR). I like the is_complete flag too, and supporting multiple shields would be pretty nice.

@joelspadin joelspadin merged commit 1dc0273 into zmkfirmware:main Jan 4, 2026
1 check passed
@joelspadin joelspadin deleted the hw-model-v2 branch January 4, 2026 21:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants