The ESP32 BLE controller glue guards ble_enc_funcs_reset() on
CONFIG_BT_CTRL_BLE_SECURITY_ENABLE, an ESP-IDF sdkconfig symbol that is never
defined in a Zephyr build. The call is therefore compiled out and the
controller's LE Secure Connections encryption table is left uninitialised, so
SC pairing derives a wrong session key and the link is terminated with HCI
reason 0x3D (MIC failure).
This breaks pairing for SC-capable centrals (e.g. Pixel 7 / recent Android);
legacy-pairing centrals use a different path and are unaffected. The existing
CONFIG_ESP32_BT_CTLR_LE_SECURITY_ENABLE=y only sets .enc_en and does not reach
this guard.
Correct the guard to BLE_SECURITY_ENABLE, which esp_bt.h already derives from
CONFIG_ESP32_BT_CTLR_LE_SECURITY_ENABLE (the Zephyr knob) and already uses for
.enc_en. Carried as a managed hal_espressif patch via the existing
zephcore_apply_patches() mechanism (mirrors the loramac-node patch).
Verified on Heltec Wireless Tracker (ESP32-S3): device reaches security
level 4, pairing complete bonded=1; Pixel 7 bonds over SC and the companion app
communicates; older Samsung still pairs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- calibrate_image: revert to datasheet band table. Narrow ±2 MHz
window had truncation bug placing 433/869 MHz operating freq
outside their own calibration windows. DS §9.2.1 confirms cal
is range-validity, not point-precision
- reset_agc: K_FOREVER mutex → K_MSEC(50). Was holding dispatcher
thread up to ~3 s if a long TX/RX held the SPI lock. Now bails
with WARN log; caller retries next maintenance interval.
Add .gitattributes rules so .c/.h/.cpp/.hpp are always stored as LF
(prevents EOL drift from editors with autocrlf-true defaults), and
renormalize the 30 source files that had drifted to CRLF in the index.
Pure mechanical change — `git diff --ignore-cr-at-eol` is empty.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
-Removed broken §15.3 implicit-header workaround (wrong addresses, wrong bit, wrong condition)
-Initialize data->rx_boost_enabled from config->rx_boosted (DTS) instead of hard-coded false
-Re-apply RX gain after the first SetRx in lora_recv_async to match restart_rx / recv_duty_cycle
-Re-issue CalibrateImage(operating_freq) after Calibrate(ALL) to keep image-rejection band correct on EU868 / 433 MHz / 779 MHz
-rx_cb_gen converted from uint32_t to atomic_t — atomic_set/get/inc at all 13 sites; local snapshot is now atomic_val_t
stolen from Zephyr main:
1. Issue StopTimerOnPreamble=1 before SetRxDutyCycle so the chip's
timer is not reset on every preamble detect (per §13.1 of the
datasheet). Without this, duty cycle effectively never sleeps in
noisy RF and current draw spikes.
2. On IRQ_RX_TX_TIMEOUT during duty-cycle RX, re-arm via
sx126x_restart_rx() instead of falling through to set_sleep().
The old path silently killed duty cycle after the first preamble
false-positive.
3. On recv_duty_cycle(NULL) cancel, wake the radio before issuing
SetStandby — BUSY stays asserted during the sleep phase and the
standby command was being dropped.
Also adds a dc_timeout_restarts atomic counter incremented on the Fix 2
path, exposed end-to-end: sx126x_ext.h accessors → LoRaRadioBase vtable
→ SX126xRadio override → CommonCLICallbacks → RepeaterMesh. Query via
`get dc.restarts` on the repeater CLI; cleared by `clear stats`. High
values indicate a noisy environment or a too-loose preamble threshold.
(+increase ESP BT stack because future zephyr pin advance will trip that mine)
Three correctness fixes for the SX127x radio adapter on top of
Rastislav's initial sx1276 + patch commits:
1. _loramac_node flag (LoRaRadioBase + SX127xRadio):
Guard the direction-only fast path in configureTx()/configureRx()
so loramac-node always calls both Radio.SetTxConfig() and
Radio.SetRxConfig(). Skipping either leaves TxTimeout=0 in the
library, causing an immediate TX timeout callback, which prevents
the _tx_signal from ever being raised and blocks the TX wait thread
for TX_TIMEOUT_MS (5 s) — a 5-second RX blackout per transmission.
This was the root cause of "boots but no RX".
2. SX127xRadio::resetAGC() override:
The base-class resetAGC() calls startReceive() after hwResetAGC().
During async RX the loramac-node modem mutex is STATE_BUSY, so
lora_recv_async() returns -EBUSY, which sets _in_recv_mode = 0 and
corrupts the receive state machine. Override skips the call
entirely — the loramac-node driver self-manages AGC.
3. BW 62.5 kHz support in loramac-node/sx1276.c + patch:
Rastislav's 0004-lora-sx127x-62k5-bandwidth.patch adds BW_62_KHZ
support to sx12xx_common.c (Zephyr side) but not to the loramac-
node library itself. Without this fix bandwidth index 3 hits the
"while(1)" fatal guard in SX1276SetRxConfig/SX1276SetTxConfig.
This commit patches sx1276.c directly and adds
patches/modules/loramac-node/0001-sx1276-bw62k5.patch so the fix
survives west update. CMakeLists.txt is extended to apply module
patches via the existing zephcore_apply_patches() mechanism.