From 19ddadf3ff61059a42eb7885e2be6dce434ba875 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Mon, 20 Jul 2026 02:58:58 -0500 Subject: [PATCH] Check for the SPI bufsize, and throw a useful error when set too small (#11072) --- src/platform/portduino/PortduinoGlue.cpp | 43 ++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index c8e27eb8d..750396769 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -120,6 +120,44 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) return 0; } +// A kernel SPI transfer is capped by the spidev module's `bufsiz` parameter (4096 by default). +// LovyanGFX pushes the framebuffer in large chunks, so a display bigger than that budget fails +// deep inside the driver with a bare -EMSGSIZE. Check up front so the user gets told what to fix. +static void checkSpidevBufsiz() +{ + if (portduino_config.display_spi_dev == "" || portduino_config.displayWidth == 0 || portduino_config.displayHeight == 0) { + return; + } + switch (portduino_config.displayPanel) { + case no_screen: + case x11: + case fb: + case hub75: + return; // not driven over spidev + default: + break; + } + + const long required = (long)portduino_config.displayWidth * portduino_config.displayHeight / 2 * 3; + + std::ifstream bufsizFile("/sys/module/spidev/parameters/bufsiz"); + long bufsiz = 0; + if (!bufsizFile.is_open() || !(bufsizFile >> bufsiz)) { + // spidev may be built into the kernel without exposing the parameter; nothing to check. + return; + } + + if (bufsiz < required) { + std::cerr << "SPI display " << portduino_config.displayWidth << "x" << portduino_config.displayHeight + << " needs a spidev buffer of at least " << required << " bytes, but " + << "/sys/module/spidev/parameters/bufsiz is " << bufsiz << "." << std::endl; + std::cerr << "Add 'spidev.bufsiz=" << required << "' to your kernel command line " + << "(/boot/firmware/cmdline.txt on Raspberry Pi OS) and reboot." << std::endl; + std::cerr << "Or echo that value into /etc/modprobe.d/spidev.conf and reload the spidev module" << std::endl; + exit(EXIT_FAILURE); + } +} + void portduinoCustomInit() { static struct argp_option options[] = {{"port", 'p', "PORT", 0, "The TCP port to use."}, @@ -559,6 +597,11 @@ void portduinoSetup() } } + // if we have s SPI display, check /sys/module/spidev/parameters/bufsiz + // It needs to be at least width * height / 2 * 3 + // fail with a more useful error message. + checkSpidevBufsiz(); + // if we're using a usermode driver, we need to initialize it here, to get a serial number back for mac address uint8_t dmac[6] = {0}; if (portduino_config.lora_spi_dev == "ch341") {