Repository navigation
Replace gpiozero with a built-in GPIO character device helper - #169
Open
zigpy-review-bot wants to merge 3 commits into
Open
zigpy-review-bot wants to merge 3 commits into
zigpy-review-bot wants to merge 3 commits into
Conversation
gpiozero pulls in colorzero, which declares setuptools as a runtime dependency. The PiZiGate only needs to drive two output pins, so do that directly through /dev/gpiochipN with the GPIO v2 uAPI and drop the dependency.
- gpio.py needs fcntl (Linux only); import it only when switching PiZiGate modes - point at the kernel version when the GPIO v2 uAPI is missing - the Pi 5 launch kernel names the RP1 header lines PINnn, test the label fallback for it - the fake kernel checks the padding/limits the real one validates
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## dev #169 +/- ##
==========================================
+ Coverage 46.46% 49.71% +3.24%
==========================================
Files 8 9 +1
Lines 1300 1386 +86
==========================================
+ Hits 604 689 +85
- Misses 696 697 +1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #168 (option 2):
gpiozerois replaced with a small GPIO helper that drives the PiZiGate's two pins through the Linux GPIO character device, andgpiozerois dropped fromdependencies. That removesgpiozero→colorzero→setuptoolsfrom every install, so zha no longer needs its Dependabot ignore for it and Home Assistant can drop thezhaentries from hassfest's forbidden-package exceptions once a release with this lands.Changes
zigpy_zigate/gpio.py(standard library only): talks to/dev/gpiochipNwith the GPIO v2 uAPI (ioctl).common.pyimports it only inside the two PiZiGate functions, so importing the radio module no longer loads any GPIO code (andfcntl, which only exists on Unix, is never imported elsewhere).GPIO17/GPIO27, as named by the Raspberry Pi device trees), searching every/dev/gpiochip*in numeric order. If no line carries that name, it falls back to a chip labelledpinctrl-bcm2835,pinctrl-bcm2711orpinctrl-rp1(Pi 1–3, Pi 4, Pi 5), where the line offset is the BCM GPIO number. On the Pi 5 this covers both kernel layouts: Raspberry Pi kernels from 6.6 put the header ongpiochip0withGPIO17-style names, while the 6.1 launch kernel had it ongpiochip4with lines named after the header pins (PIN11for GPIO17), which the label fallback handles. On non-Pi hardware (is_pizigate()also matches/dev/ttyS*), a line is only driven if it is literally namedGPIO17/GPIO27; otherwise it fails, asgpiozerodid there.gpiozerowas used withinitial_value=None, which switched both pins to outputs with whatever value their output latch held.UnclosableOutputDevice: the pins stay driven after the mode switch, and later calls (a reconnect, or the flasher switching back to running mode) reuse the held request instead of requesting the line again.set_pizigate_running_mode()/set_pizigate_flashing_mode()keep the exact pin sequence and 0.5 s delays.GPIOErrorwith the reason: no/dev/gpiochip*, no matching line (listing chips that could not be read, e.g. permission denied, or a kernel without the v2 uAPI), or the line request failing (e.g. the line is busy). Callers are unchanged, so as before the connection attempt fails with that exception./dev/gpiochip*(Linux 5.10 or later).Behaviour differences to be aware of:
/dev/gpiochip*instead of/dev/gpiomem. Home Assistant OS (and Supervised) runs the Home Assistant container privileged, so nothing changes there; a Docker setup that only passed through/dev/gpiomemhas to pass through the GPIO chip devices instead.gpiozero's native backend the pins stayed outputs after the process exited (e.g. afterflasher --gpio); now that depends on the kernel. Raspberry Pi kernels since mid-2024 (6.6 and later) keep a released output driven (persist_gpio_outputs, on by default for both the BCM283x/BCM2711 and the RP1 pin controller). Other kernels may return a released line to an input; GPIO17 is the ZiGate's reset line and may then be pulled low, holding the ZiGate in reset until zigpy-zigate next starts and drives both pins again.gpiozero's native backend only knows the GPIO registers of the Pi 1–4; the character device is the same on every Pi, so this may also make the PiZiGate work on a Pi 5 (untested).Testing
tests/test_gpio.pyrun the helper against a fake character device (mockedos.open/fcntl.ioctl) that also checks the padding and limits the kernel validates: the line lookup by name, by chip label (including the Pi 5 6.1 layout) and in numeric chip order, the request layout, holding and reusing the request, and the error paths. The struct sizes and ioctl numbers are checked against values printed by a small C program compiled againstlinux/gpio.h(the v2 structs are padded to the same layout on 32- and 64-bit).tests/test_uart.pynow asserts the exact pin sequence of both mode switches.autoflake8hook was left out of that run because its repository no longer exists, so pre-commit cannot install it (this also affectsdev).gpio-simmodule needs root). Testers with a PiZiGate on a Pi 4 and on a Pi 5 would be very welcome, ideally checking that the ZiGate starts in running mode and that the flasher's--gpiomode still works.Alternative
#170 takes the approach puddly suggested in #168 instead: a minimal helper that writes the GPIO registers through
/dev/gpiomem, asgpiozero's native backend normally does on Home Assistant today. It keeps the current device access and pin behaviour for Raspberry Pi 1–4 users on Home Assistant and leaves the Pi 5 unsupported. Only one of the two PRs should be merged.