Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(modularisation/docs) New hardware metadata version #2396

Closed
wants to merge 54 commits into from

Conversation

Nick-Munnich
Copy link
Contributor

@Nick-Munnich Nick-Munnich commented Jul 31, 2024

This is an initial rough draft for a version 2 of the ZMK hardware metadata standard. The goal is to define the metadata such that the metadata files can be collected in a separate repository titled zmk-modules. This draft has not updated the metadata schema, but rather the documentation of it, to be easier to read and encourage discussion. Also note that as the schema has been previously changed without updating the documentation, there are some properties to which I was uncertain of their use - I gave it my best guess.

The assumption is that (almost) all boards and shields currently in the ZMK tree will be moved to external module repositories, all interconnect definitions will be moved to zmk-modules, and only the boards and shields used for testing purposes remain in-tree.

ZMK's setup scripts and related docs would need to be adjusted accordingly, either also in this PR or in a separate one. An initial rough draft zmk-modules can be found here, focusing on folder structure.

As this would obviously break compatibility with a lot of people's setups, I would suggest doing it simultaneously with whatever changes are necessary to move to Zephyr 3.7 LTS. When everything is completed, then I believe we can (finally) close #453.

We could also include some optional properties that would allow for some cool tools to make use of zmk-modules. In particular, the data to enable tools comparing keyboards to one another might be very beneficial, as currently the developers of such tools have to input each new keyboard manually themselves.

TODO:

  • Agree on metadata v2
  • Create zmk-modules repository
  • Adjust ZMK's setup scripts to use zmk-modules
  • Document zmk-modules repository
  • Fill zmk-modules with existing modules
  • Move non-essential boards and shields from ZMK tree into modules

EDIT: Thanks to discussion, it seems that we also need:

  • Agree and implement a versioning system for ZMK

@Nick-Munnich Nick-Munnich requested a review from a team as a code owner July 31, 2024 14:11
@Nick-Munnich Nick-Munnich marked this pull request as draft July 31, 2024 14:11
@Nick-Munnich Nick-Munnich added documentation Improvements or additions to documentation enhancement New feature or request board PRs and issues related to boards. user configs shields PRs and issues related to shields refactor labels Aug 2, 2024
petejohanson and others added 3 commits August 2, 2024 16:37
* Other drivers properly disconnect/de-config pins now, so we need
  to be sure the wakeup trigger connects the wake pin as input.
* Clean up composite kscan to allow multiple instances properly.
* Implement PM hook and properly suspend/resume the child devices.

Fixes: zmkfirmware#2388
@ssbb
Copy link

ssbb commented Aug 4, 2024

It would be cool to add some physical layout definitions for keyboards. For example, QMK uses a KLE-like JSON format.

We could add some common presets like ANSI60, ANSI104, ISO60, ISO105, etc. Then, we might allow the xxx+x approach for ergonomic boards (e.g., 23332+2 is a Hummingbird layout). Additionally, we could use a KLE-like JSON for custom layouts.

Usage examples:

  • Projects such as a keymap-drawer could benefit significantly from this (currently, you have to specify it manually).
  • Projects like YellowAfterlife's ergo keyboard list could parse this information to determine the number of columns, rows, and thumbs.
  • Some CLI tools could use it to render the proper layout, etc.

@petejohanson
Copy link
Contributor

It would be cool to add some physical layout definitions for keyboards. For example, QMK uses a KLE-like JSON format.

We could add some common presets like ANSI60, ANSI104, ISO60, ISO105, etc. Then, we might allow the xxx+x approach for ergonomic boards (e.g., 23332+2 is a Hummingbird layout). Additionally, we could use a KLE-like JSON for custom layouts.

Usage examples:

  • Projects such as a keymap-drawer could benefit significantly from this (currently, you have to specify it manually).
  • Projects like YellowAfterlife's ergo keyboard list could parse this information to determine the number of columns, rows, and thumbs.
  • Some CLI tools could use it to render the proper layout, etc.

That information is already now possible to set in the devicetree with the new physics layouts refactor so it's available in firmware for the upcoming ZMK Studio work. It would be a net negative to duplicate that in the metadata, IMHO.

@caksoylar
Copy link
Contributor

I think the broad strokes of this organization makes sense. A separate repo where PRs can go into to add "references" from which tooling can discover things is a sensible approach.

One small suggestion I'd have for now would be to have module dict field instead of murl, where url, commit, outdated (also maybe project name, to be used in west.yml) can go as sub-entries.

I think there are a few things that warrant further discussion. I am not listing these because I necessarily have an opinion on them but discussion around them would be good to have.

  1. Pinning modules to commits: The proposal mandates it, but there might be advantages to be able to point to a branch/tag.
  2. How to handle compatibility with ZMK versions (or even between modules): The proposal has an outdated field which might be useful, but also is not a well-defined concept1. This is a hard question to answer in general, and having ZMK use some sort of specific versioning scheme might be a prerequisite to a proper solution.
  3. Maybe it is better to omit a pull-request field to limit "support" (since these will be used by official tooling) to the main branch/release.

Footnotes

  1. Do ZMK committers update these as things break? An automated tool can check for building but can't check for changed/broken functionality

@Nick-Munnich
Copy link
Contributor Author

One small suggestion I'd have for now would be to have module dict field instead of murl, where url, commit, outdated (also maybe project name, to be used in west.yml) can go as sub-entries.

Great idea, I'll make this change.

1. Pinning modules to commits: The proposal mandates it, but there might be advantages to be able to point to a branch/tag.

The reason for this is specifically a security/malicious actor concern. By specifying a commit, we can prevent harmful images/code/etc from being present in the version of the module that we recommend (unless it is missed on review). I think SHA-1 should suffice here, though cybersecurity/cryptography isn't my specialty.

2. How to handle compatibility with ZMK versions (or even between modules): The proposal has an `outdated` field which might be useful, but also is not a well-defined concept[1](#user-content-fn-1-14bdca0f8be552f5c0b9ba62bc8be843). This is a hard question to answer in general, and having ZMK use some sort of specific versioning scheme might be a prerequisite to a proper solution.

I think I'll change it so that the outdated field points to the most recently working zmk commit and is omitted when up-to-date - then builds with outdated modules could still be attempted, while raising big warnings. A proper versioning scheme would be very nice, but I don't think it's necessarily necessary.

3. Maybe it is better to omit a `pull-request` field to limit "support" (since these will be used by official tooling) to the main branch/release.

I was quite torn on whether to include or remove it. I'll remove it.

Footnotes

1. Do ZMK committers update these as things break? An automated tool can check for building but can't check for changed/broken functionality [↩](#user-content-fnref-1-14bdca0f8be552f5c0b9ba62bc8be843)

My thinking was that we could write a tool that goes through all of the modules in a type category, marks them as outdated, and opens issues on all the remote repos found. The owners/maintainers of the module could comment on the issue to discard it if it doesn't apply to them, causing the tool to automatically remove the outdated flag, or they can apply changes and then open a PR to update the pinned commit prompting manual review. It would be ZMK committers' responsibility to write the issue description if their commit breaks something, and ZMK maintainers' responsibility to run the tool on a breaking merge.

Ideally we could have it auto-accept particular changes (ex. adding wakeup-source), but that seems like a significantly more complex task and could be investigated far into the future. A proper versioning scheme as you mentioned would also help it feel smoother.

@caksoylar
Copy link
Contributor

I think I'll change it so that the outdated field points to the most recently working zmk commit and is omitted when up-to-date - then builds with outdated modules could still be attempted, while raising big warnings. A proper versioning scheme would be very nice, but I don't think it's necessarily necessary.

I like that a bit better, and you may be right on the versioning.

My thinking was that we could write a tool that goes through all of the modules in a type category, marks them as outdated, and opens issues on all the remote repos found. The owners/maintainers of the module could comment on the issue to discard it if it doesn't apply to them, causing the tool to automatically remove the outdated flag, or they can apply changes and then open a PR to update the pinned commit prompting manual review. It would be ZMK committers' responsibility to write the issue description if their commit breaks something, and ZMK maintainers' responsibility to run the tool on a breaking merge.

That makes sense to me.

@urob
Copy link
Contributor

urob commented Aug 6, 2024

I have been thinking a bit about maintenance costs. Zephyr has a policy in place which only allows changes to modules as mergeable PRs and strictly forbids force-pushes to the main branch. Something similar could help reduce the review burden for the ZMK team.

On the flipside, to reduce maintenance costs for module maintainers, I'd second that some form of ZMK version system (with infrequent api-breaking changes) would be desirable. Even if not strictly necessary, forcing maintainers to check compatibility for every ZMK commit is a huge burden.

Moreover, if modules aren't synchronized, which seems inevitable in a large ecosystem without proper upstream versioning, then the burden ultimately gets passed on to end-users: To update their firmware, they will need to:

  1. Find the latest ZMK commit that's supported by all modules they are using
  2. For each of their modules, find the corresponding commit that supports this latest-commonly-supported commit

@Nick-Munnich
Copy link
Contributor Author

Something similar would be an excellent policy to have in zmk-modules.

You raise a good point and argument for versioning as well. If we introduced a versioning system, then the commit and outdated child properties of module could be cleanly replaced by a version property:

module:
  url: https://github.com/module-owner/module-repo-name
  version:
    - 2-1-3: 093dj09sdapasdlkd09285c585e08pjonkjn7y8798
    - 1-0-12: c43a0365183c58f74c285c585e0cbc1ea99f8a12

That would allow tools like zmk-cli to completely remove the burden you described.

caksoylar and others added 8 commits August 15, 2024 10:38
* UART and BLE/GATT transports for a protobuf encoded RPC
  request/response protocol.
* Custom framing protocol is used to frame a give message.
* Requests/responses are divided into major "subsystems" which
  handle requests and create response messages.
* Notification support, including mapping local events to RPC
  notifications by a given subsystem.
* Meta responses for "no response" and "unlock needed".
* Initial basic lock state support in a new core section, and allow specifying
  if a given RPC callback requires unlocked state or not.
* Add behavior subsystem with full metadata support and examples of
  using callback to serialize a repeated field without extra stack space needed.

Co-authored-by: Cem Aksoylar <[email protected]>
 * Add an easy snippet for enabling USB UART added
   to the `zephyr_udc0` standard node.
* New behavior allows unlocking the keyboard to allow ZMK Studio to
  make changes.

Co-authored-by: Cem Aksoylar <[email protected]>
* Cover stm32, RP2040, and nRF52 builds.
* Reduce RAM usage, no need for heap any more in ZMK.
* Don't attempt to enable FPU that's not present.
@Nick-Munnich Nick-Munnich removed the enhancement New feature or request label Aug 16, 2024
@joelspadin
Copy link
Collaborator

If I'm understanding this correctly, with this proposal, in order to add or update a module, you would need to manually copy all the .zmk.yml files from the module into the central repository, then update each one to include the module repo's URL and the specific commit from which the data was pulled. Failing to do this correctly could lead to the data in the central repo not matching that of the module repo.

It seems to me like it would be a lot easier to maintain if the central repo contained only module URLs and commit hashes. Then to update a module, you would only need to update the commit hash in one file. This would mean you could not search the central repo directly for specific keyboards/behaviors/etc., but it would be possible to set up a website which is generated by collecting data from every module into a searchable database.

@Nick-Munnich Nick-Munnich changed the title feat(modularisation/docs) New hardware metadata version for zmk-modules repository feat(modularisation/docs) New hardware metadata version Aug 18, 2024
@YellowAfterlife
Copy link

On keyboard geometry, that's such a topic - e.g. with Xx+Y notation, how do you describe something like Hillside? Even my current "key count, columns, rows, and extra keys" format doesn't quite work because an extra index finger column and an extra pinky column serve different purposes.

@Nick-Munnich
Copy link
Contributor Author

On keyboard geometry, that's such a topic - e.g. with Xx+Y notation, how do you describe something like Hillside? Even my current "key count, columns, rows, and extra keys" format doesn't quite work because an extra index finger column and an extra pinky column serve different purposes.

The docs from #2268 found here describe the physical layout system nicely. The current plan is to add tags to each key such as "PINKY_HOME" at some point in the future.

@Nick-Munnich
Copy link
Contributor Author

Closing this for the time being. While I do still feel like an update to the metadata would be nice, I no longer feel that it is necessary for the module ecosystem to mature. It would be better to revisit this topic at a much later stage and see what would be useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
board PRs and issues related to boards. documentation Improvements or additions to documentation shields PRs and issues related to shields
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Towards a modular ZMK
9 participants