#!/usr/bin/env python3 """Raise spidev bufsiz so full WS2812 SPI frames fit (405 LEDs ≈ 10 KiB).""" from __future__ import annotations import argparse import subprocess import sys from pathlib import Path from leds.backends.spi import _DEFAULT_BUFSIZ, spidev_bufsize MODPROBE_D = Path("/etc/modprobe.d/spidev-bufsiz.conf") MARKER = "# portal spidev bufsiz" def main() -> int: parser = argparse.ArgumentParser( description="Configure spidev bufsiz for long WS2812 SPI strips" ) parser.add_argument( "--bufsiz", type=int, default=_DEFAULT_BUFSIZ, help=f"Kernel SPI buffer size (default {_DEFAULT_BUFSIZ})", ) parser.add_argument( "--install", action="store_true", help="Write /etc/modprobe.d/spidev-bufsiz.conf and reload spidev (sudo)", ) args = parser.parse_args() current = spidev_bufsize() print(f"spidev bufsiz: {current}") print(f"405 LEDs need ~9762 bytes per frame.\n") line = f"options spidev bufsiz={args.bufsiz}" print("Add to /etc/modprobe.d/spidev-bufsiz.conf:\n") print(f"{MARKER}") print(line) print("\nThen reload:\n sudo modprobe -r spidev && sudo modprobe spidev") if not args.install: return 0 try: existing = MODPROBE_D.read_text() if MODPROBE_D.exists() else "" if MARKER in existing: print(f"\n{MODPROBE_D} already configured.") else: MODPROBE_D.write_text(f"{MARKER}\n{line}\n") print(f"\nWrote {MODPROBE_D}.") subprocess.run(["modprobe", "-r", "spidev"], check=False) subprocess.run(["modprobe", "spidev", f"bufsiz={args.bufsiz}"], check=True) print(f"Reloaded spidev (bufsiz={spidev_bufsize()}).") except OSError as exc: print(f"Error: {exc}", file=sys.stderr) print("Re-run with sudo.", file=sys.stderr) return 1 except subprocess.CalledProcessError as exc: print(f"modprobe failed: {exc}", file=sys.stderr) return 1 return 0 if __name__ == "__main__": raise SystemExit(main())