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

Switch sysfs GPIO ABI to pigpiod #12

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

DigitalBrains1
Copy link

@DigitalBrains1 DigitalBrains1 commented Jan 3, 2025

The sysfs GPIO ABI has been deprecated in 2015 and Raspberry Pi OS bookworm no longer supports it. This interface is used in some shell scripts in betrusted-scripts.

The proper way to handle GPIO, through a character device in /dev, is not immediately enough for these scripts. Anything written to the sysfs ABI persisted, but as soon as you close the character device, the lines will reset to a "default state", meaning they are no longer driving output.

You need a daemon to keep the character device open. There are at least three options:

  • Use the latest libgpiod from the kernel people; version 2.2 adds a daemon that exposes a DBus interface to deal with it.
  • Use pigpiod
  • Write your own daemon; it can be pretty simple
  • I suppose you could also use /dev/gpiomem; I expect just poking registers is also persistent, but I didn't try.

The libgpiod is too new and not yet in the Debian/RPi repositories. We could compile it ourselves, but I opted for pigpiod. I have to say, I'm not a fan of a whole bunch of design decisions. For instance:

  • The pigs client program will only connect to a fixed port on localhost, and the port is 8888, a port commonly used for HTTP-related stuff. If it connects to a different service than the intended one, it'll likely simply hang indefinitely; or alternatively, it might return bogus output.
  • The daemon will by default only listen on IPv6, but if the host has disabled IPv6 altogether, it will listen on IPv4.
  • The systemd service quite often will not stop because the main daemon process does not exit, necessitating SIGKILL.
  • Quite some more I won't bore you with

If you don't want pigpiod, I could give it another go by adding libgpiod as a git submodule and just build the thing and install it as a Systemd service. But I think pigpiod fills the gap left by the removal of the sysfs ABI even though it's not great.

I tested vbus{,_on,_off}.sh and reset_soc.sh, and I verified jtag_gpio.py can still do JTAG. I didn't truly test the other shell scripts using the sysfs ABI, but I see no reason why they should be any different.

There's one more change you need before you can actually use stuff on the latest stable Raspberry Pi OS (which is bookworm). jtag_gpio.py uses the old python3-crypto interface which was dropped from Debian bullseye but apparently Raspberry Pi OS decided to keep it one more release? I simply did:

--- a/jtag_gpio.py
+++ b/jtag_gpio.py
@@ -12,7 +12,7 @@ import subprocess
 import logging
 import sys
 import binascii
-from Crypto.Cipher import AES
+from Cryptodome.Cipher import AES
 
 from enum import Enum

but I don't know if that actually works because I didn't use the code path that uses that module.

The sysfs GPIO ABI has been deprecated in 2015 and Raspberry Pi OS
bookworm no longer supports it.
@DigitalBrains1
Copy link
Author

Ah! It would seem I lost track of why I was doing the whole "check the socket" dance in the first place :-P. I meant to be able to check with some fidelity whether something else was listening on the daemon port, because the client handles this case so atrociously. I've changed the script to do that now.

@DigitalBrains1
Copy link
Author

I suppose this could also work to check what is listening on 8888:

$ sudo ss -HlpntO 'sport = 8888'|tr -s '' ' '|cut -d' ' -f6|cut -d'"' -f2

It will output the name of the first process listening on that port. But I've never done parsing of ss before, it only just occurred to me.

@bunnie
Copy link
Member

bunnie commented Jan 9, 2025

thanks for the PR! I need to get some old hardware out and test some configurations before merging. My main concern is how to merge this without breaking legacy platforms as well - especially the factory infrastructure which is never going to get an OS update because it's operated in a primarily offline mode.

I'll try to review this in the next couple of weeks!

@DigitalBrains1
Copy link
Author

Oh, I forgot to mention this. I tested it on both bullseye (previous version of Raspberry Pi OS) as well bookworm (current version). Really should have mentioned that! I did not try older versions (since they are well and truly end-of-life).

By chance, writing something based on libgpiod on a Raspberry Pi Zero with bullseye, I found out that even changes made through /dev/gpiochipX actually are persistent; I didn't try yet, but I'm assuming that on bookworm they are truly transient as documented. I suspect they become persistent by enabling the kernel config option for the deprecated sysfs ABI, which bullseye does.

@DigitalBrains1
Copy link
Author

DigitalBrains1 commented Jan 11, 2025

There's one more change you need before you can actually use stuff on the latest stable Raspberry Pi OS (which is bookworm). jtag_gpio.py uses the old python3-crypto interface which was dropped from Debian bullseye but apparently Raspberry Pi OS decided to keep it one more release?

I just now notice there's an alternative option. I noticed that doing pip install precursorupdater in a venv actually populated the Crypto namespace. As it turns out: if you pip install pycryptodome (getting version 3.21.0) in a venv you get the Crypto namespace, but if you apt-get install python3-pycryptodome, you do not (it configures a build flag-like file to put it into Cryptodome).

This is irrespective of bullseye or bookworm; it's just that Raspberry Pi OS bullseye also still carried the old unmaintained library from https://www.pycrypto.org , so you could install that instead of pycryptodome.

So another solution is to make jtag_gpio.py compatible with venvs and run it in a venv:

--- a/jtag_gpio.py
+++ b/jtag_gpio.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
 
 try:
     import RPi.GPIO as GPIO

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants