mirror of
https://github.com/meshtastic/firmware.git
synced 2026-05-29 19:24:46 -04:00
* macOS: enable CH341 LoRa-hardware path — fix serial truncation, document setup
Verified on Apple Silicon with a CH341A USB-SPI bridge (VID 0x1A86,
PID 0x5512) wired to an SX1262 (Meshstick variant) that the existing
`pine64/libch341-spi-userspace` lib_dep works on macOS as-is — Apple's
bundled CH34x driver only matches the CH340 *UART* variant
(PID 0x7523), so the CH341A's interface 0 is left unclaimed and
libusb opens / configures / claims it directly via IOUSBHostInterface.
End-to-end test: meshtasticd boots, libusb claim succeeds, SX1262 init
returns 0, TCP API serves the meshtastic CLI's --info / --sendtext flow.
Two changes:
1. **`PortduinoGlue.cpp:497`**: pass `sizeof(serial)` (= 9) instead of
the literal `8` to `Ch341Hal::getSerialString()`. The function in
`USBHal.h:61-68` treats `len` as buffer size and reserves one slot
for the null terminator (`bytesCopied = (len - 1) < 8 ? (len - 1) : 8`),
so passing 8 produced a 7-char serial — which then broke the
`strlen(serial) == 8` check at line 502, skipping the auto-MAC
derivation from serial + product string. On Linux this was masked
by the BlueZ HCI MAC fallback in `getMacAddr()` at lines 139-157,
but on macOS that fallback is `__linux__`-guarded so the serial path
is mandatory and the truncation left `mac_address` empty, causing
the daemon to exit with `*** Blank MAC Address not allowed!`.
2. **`variants/native/portduino/platformio.ini`**: expand the
`[env:native-macos]` comment block with a "Real LoRa hardware on
macOS" section. Documents:
- Why no upstream library change is needed (Apple kext targets
CH340/UART, not CH341A/SPI; libusb's `#ifdef __linux__` skip is
correct for macOS in this case).
- How to point `meshtasticd` at an existing platform-agnostic
`bin/config.d/lora-*.yaml` for CH341 hardware.
- The auto-MAC-derivation contract (now working with this fix).
- `ioreg` and `LIBUSB_DEBUG=4` diagnostic recipes for the failure
mode where a third-party WCH `CH34xVCPDriver` *would* claim
interface 0 (`kmutil unload -b <bundleID>` workaround).
No upstream library forks, no PR chain, no additional lib_deps —
the existing `pine64/libch341-spi-userspace` + libusb-1.0 stack does
the right thing on macOS already.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Apply suggestion from @Copilot
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
209 lines
8.3 KiB
INI
209 lines
8.3 KiB
INI
[native_base]
|
|
extends = portduino_base
|
|
build_flags = ${portduino_base.build_flags} -I variants/native/portduino
|
|
-I /usr/include
|
|
board = cross_platform
|
|
board_level = extra
|
|
lib_deps =
|
|
${portduino_base.lib_deps}
|
|
# renovate: datasource=custom.pio depName=Melopero RV3028 packageName=melopero/library/Melopero RV3028
|
|
melopero/Melopero RV3028@1.2.0
|
|
|
|
build_src_filter = ${portduino_base.build_src_filter}
|
|
|
|
[env:native]
|
|
extends = native_base
|
|
; The pkg-config commands below optionally add link flags.
|
|
; the || : is just a "or run the null command" to avoid returning an error code
|
|
build_flags = ${native_base.build_flags}
|
|
!pkg-config --libs libulfius --silence-errors || :
|
|
!pkg-config --libs openssl --silence-errors || :
|
|
!pkg-config --cflags --libs sdl2 --silence-errors || :
|
|
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
|
|
|
[env:native-tft]
|
|
extends = native_base
|
|
build_type = release
|
|
lib_deps =
|
|
${native_base.lib_deps}
|
|
${device-ui_base.lib_deps}
|
|
build_flags = ${native_base.build_flags} -Os -lX11 -linput -lxkbcommon -ffunction-sections -fdata-sections -Wl,--gc-sections
|
|
-D RAM_SIZE=16384
|
|
-D USE_X11=1
|
|
-D HAS_TFT=1
|
|
-D HAS_SCREEN=1
|
|
-D LV_CACHE_DEF_SIZE=6291456
|
|
-D LV_BUILD_TEST=0
|
|
-D LV_USE_LIBINPUT=1
|
|
-D LV_LVGL_H_INCLUDE_SIMPLE
|
|
-D LV_CONF_INCLUDE_SIMPLE
|
|
-D LV_COMP_CONF_INCLUDE_SIMPLE
|
|
-D USE_LOG_DEBUG
|
|
-D LOG_DEBUG_INC=\"DebugConfiguration.h\"
|
|
-D USE_PACKET_API
|
|
-D VIEW_320x240
|
|
!pkg-config --libs libulfius --silence-errors || :
|
|
!pkg-config --libs openssl --silence-errors || :
|
|
!pkg-config --cflags --libs sdl2 --silence-errors || :
|
|
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
|
build_src_filter =
|
|
${native_base.build_src_filter}
|
|
|
|
[env:native-fb]
|
|
extends = native_base
|
|
build_type = release
|
|
lib_deps =
|
|
${native_base.lib_deps}
|
|
${device-ui_base.lib_deps}
|
|
build_flags = ${native_base.build_flags} -Os -ffunction-sections -fdata-sections -Wl,--gc-sections
|
|
-D RAM_SIZE=8192
|
|
-D USE_FRAMEBUFFER=1
|
|
-D LV_COLOR_DEPTH=32
|
|
-D HAS_TFT=1
|
|
-D HAS_SCREEN=1
|
|
-D LV_BUILD_TEST=0
|
|
-D LV_USE_LOG=0
|
|
-D LV_USE_EVDEV=1
|
|
-D LV_LVGL_H_INCLUDE_SIMPLE
|
|
-D LV_CONF_INCLUDE_SIMPLE
|
|
-D LV_COMP_CONF_INCLUDE_SIMPLE
|
|
-D USE_LOG_DEBUG
|
|
-D LOG_DEBUG_INC=\"DebugConfiguration.h\"
|
|
-D USE_PACKET_API
|
|
-D VIEW_320x240
|
|
-D MAP_FULL_REDRAW
|
|
!pkg-config --libs libulfius --silence-errors || :
|
|
!pkg-config --libs openssl --silence-errors || :
|
|
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
|
build_src_filter =
|
|
${native_base.build_src_filter}
|
|
|
|
[env:native-tft-debug]
|
|
extends = native_base
|
|
build_type = debug
|
|
lib_deps =
|
|
${native_base.lib_deps}
|
|
${device-ui_base.lib_deps}
|
|
build_flags = ${native_base.build_flags} -O0 -fsanitize=address -lX11 -linput -lxkbcommon
|
|
-D DEBUG_HEAP
|
|
-D RAM_SIZE=16384
|
|
-D USE_X11=1
|
|
-D HAS_TFT=1
|
|
-D HAS_SCREEN=0
|
|
-D LV_CACHE_DEF_SIZE=6291456
|
|
-D LV_BUILD_TEST=0
|
|
-D LV_USE_LOG=1
|
|
-D LV_USE_SYSMON=1
|
|
-D LV_USE_PERF_MONITOR=1
|
|
-D LV_USE_MEM_MONITOR=0
|
|
-D LV_USE_PROFILER=0
|
|
-D LV_USE_LIBINPUT=1
|
|
-D LV_LVGL_H_INCLUDE_SIMPLE
|
|
-D LV_CONF_INCLUDE_SIMPLE
|
|
-D LV_COMP_CONF_INCLUDE_SIMPLE
|
|
-D USE_LOG_DEBUG
|
|
-D LOG_DEBUG_INC=\"DebugConfiguration.h\"
|
|
-D USE_PACKET_API
|
|
-D VIEW_320x240
|
|
!pkg-config --libs libulfius --silence-errors || :
|
|
!pkg-config --libs openssl --silence-errors || :
|
|
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
|
build_src_filter = ${env:native-tft.build_src_filter}
|
|
|
|
[env:coverage]
|
|
extends = env:native
|
|
build_flags = -lgcov --coverage -fprofile-abs-path -fsanitize=address ${env:native.build_flags}
|
|
; https://docs.platformio.org/en/latest/projectconf/sections/env/options/test/test_testing_command.html
|
|
test_testing_command =
|
|
${platformio.build_dir}/${this.__env__}/meshtasticd
|
|
-s
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Native build for macOS (Darwin / arm64 + x86_64). Headless meshtasticd that
|
|
; runs in SimRadio mode (`-s`) or against real LoRa hardware via a CH341
|
|
; USB-SPI bridge. No BlueZ, libgpiod, or Linux I2C — those require Linux.
|
|
;
|
|
; Prerequisites (Homebrew):
|
|
; brew install platformio yaml-cpp libuv openssl@3 libusb argp-standalone pkg-config
|
|
;
|
|
; The macOS-side patches now live upstream:
|
|
; * meshtastic/platform-native — `String.h`-shadow shim, `-Wno-enum-constexpr-conversion`,
|
|
; empty-variant-dir guard. Pulled via `portduino_base.platform` zip pin.
|
|
; * meshtastic/framework-portduino — LinuxHardwareI2C macOS stubs, AsyncUDP
|
|
; SOCK_NONBLOCK fallback, Common.h __APPLE__ guard, WiFiServer.cpp extern-C
|
|
; fix, package.json URL refresh. Pulled by platform-native at its pinned commit.
|
|
; This env therefore only carries the firmware-side build flags and src filter.
|
|
;
|
|
; Real LoRa hardware on macOS:
|
|
; The same lib_dep `pine64/libch341-spi-userspace` used on Linux works on
|
|
; macOS as-is — its `libusb_detach_kernel_driver()` call is `__linux__`-
|
|
; guarded, but on macOS the kernel doesn't bind a driver to a CH341A SPI
|
|
; bridge (PID 0x5512; bDeviceClass=0xff vendor-specific) by default, so
|
|
; no detach is needed. Apple's bundled CH34x driver targets the CH340
|
|
; *UART* variant (PID 0x7523) — different product. libusb opens the device
|
|
; and claims interface 0 directly via IOUSBHostInterface.
|
|
;
|
|
; To use, point `meshtasticd` at any of the existing `bin/config.d/lora-*.yaml`
|
|
; files that specify `spidev: ch341` — they're platform-agnostic. Example:
|
|
; pio run -e native-macos
|
|
; mkdir -p ~/.meshtasticd && cp bin/config-dist.yaml ~/.meshtasticd/config.yaml
|
|
; # Edit ~/.meshtasticd/config.yaml: ConfigDirectory: ./config.d/
|
|
; mkdir ~/.meshtasticd/config.d && cp bin/config.d/lora-meshstick-1262.yaml ~/.meshtasticd/config.d/
|
|
; cd ~/.meshtasticd && /path/to/firmware/.pio/build/native-macos/meshtasticd
|
|
;
|
|
; The MAC address auto-derives from the CH341's USB serial + product string
|
|
; (PortduinoGlue.cpp ~497-518); on Linux a BlueZ HCI socket is the fallback
|
|
; when that path isn't taken, but BlueZ is `__linux__`-guarded so the
|
|
; serial-derivation path is mandatory on macOS. Override with
|
|
; `MACAddress: AA:BB:CC:DD:EE:FF` in config.yaml's `General:` section if
|
|
; the device's serial isn't 8 hex chars.
|
|
;
|
|
; Diagnosing CH341 issues on macOS:
|
|
; ioreg -p IOUSB -l -w 0 | grep -B2 -A30 0x5512
|
|
; Children should be `IOUSBHostInterface`. If a vendor driver class
|
|
; (e.g. `com.wch.CH34xVCPDriver` from a third-party WCH installer)
|
|
; claims interface 0, libusb will fail with LIBUSB_ERROR_BUSY.
|
|
; Workaround: `sudo kmutil unload -b <bundleID>`.
|
|
; LIBUSB_DEBUG=4 .pio/build/native-macos/meshtasticd
|
|
; Verbose libusb trace — useful when claim_interface fails.
|
|
; ---------------------------------------------------------------------------
|
|
[env:native-macos]
|
|
extends = native_base
|
|
; Apple's ld doesn't accept GNU ld's `-Wl,-Map,<file>` syntax (inherited from
|
|
; the top-level platformio.ini). Strip it; the linker map isn't useful for
|
|
; the macOS dev loop anyway, and Apple ld's equivalent (`-Wl,-map,<file>`)
|
|
; uses different argument shape.
|
|
build_unflags = -Wl,-Map,"${platformio.build_dir}"/output.map
|
|
build_flags = ${portduino_base.build_flags_common}
|
|
-I variants/native/portduino
|
|
-I/opt/homebrew/include
|
|
-I/opt/homebrew/opt/argp-standalone/include
|
|
-I/opt/homebrew/opt/yaml-cpp/include
|
|
-L/opt/homebrew/lib
|
|
-L/opt/homebrew/opt/argp-standalone/lib
|
|
-L/opt/homebrew/opt/yaml-cpp/lib
|
|
-largp
|
|
-DPORTDUINO_DARWIN
|
|
; Headless build — variants/native/portduino/variant.h would otherwise
|
|
; default HAS_SCREEN to 1 and pull in screen-renderer source that uses
|
|
; VLA-with-initializer (a GNU/GCC extension Apple Clang rejects).
|
|
; MESHTASTIC_EXCLUDE_SCREEN gates the optional `screen->setHeading(...)`-
|
|
; style screen-driver hooks scattered through sensor sources.
|
|
-DHAS_SCREEN=0
|
|
-DMESHTASTIC_EXCLUDE_SCREEN=1
|
|
!pkg-config --libs openssl --silence-errors || :
|
|
; src/input/Linux*.{cpp,h} drive evdev (`<linux/input.h>`) which doesn't exist
|
|
; on macOS. graphics/Panel_sdl.* and graphics/TFTDisplay.cpp pull LovyanGFX
|
|
; (which we lib_ignore on macOS for the <malloc.h> issue). Neither is needed
|
|
; for the headless build.
|
|
build_src_filter = ${native_base.build_src_filter}
|
|
-<input/LinuxInput.cpp>
|
|
-<input/LinuxInputImpl.cpp>
|
|
-<graphics/Panel_sdl.cpp>
|
|
-<graphics/TFTDisplay.cpp>
|
|
; LovyanGFX includes <malloc.h> (Linux-only) and is only needed by TFT
|
|
; variants — not relevant for the headless macOS build.
|
|
lib_ignore =
|
|
${portduino_base.lib_ignore}
|
|
LovyanGFX
|