Fix UPER encoding of CurvatureCalculationMode; verified on hardware
CurvatureCalculationMode is the one extensible ENUMERATED in CAM:
ENUMERATED {yawRateUsed(0), yawRateNotUsed(1), unavailable(2), ...}
UPER encodes an extensible ENUMERATED as an extension bit followed by the root
index - 1 + 2 = 3 bits. All three of our encoders wrote only the 2-bit index,
shifting yawRate and the entire low-frequency container one bit early for any
standards-compliant receiver.
It went unnoticed because every end of this project shared the mistake: the
Kotlin codec was ported bit-for-bit from cam.c, so phone and ESP32 agreed
perfectly with each other and with nothing else. Confirmed against the ETSI
ASN.1 in the C-ITS-Parser checkout, where rasn marks this type - and only this
type - #[non_exhaustive].
Fixed in all three copies of the encoder (app CamUperCodec.kt,
obu-firmware/main/cam.c, obu-cam-transmistter/main/cam.c) plus the decoder,
which now rejects rather than misreads a set extension bit. Frame size is
unchanged at 43 bytes. Transmitter reflashed and the phone decodes its CAMs.
Also in this change:
- serial_link: skip send_frame entirely when no USB host is attached, and raise
the tx mutex timeout above the worst-case hold. With the phone unplugged every
write blocked its full timeout while holding the lock, so forwarded CAM_RX
traffic starved the 1 Hz heartbeat - observed as "tx mutex timeout, dropping
frame" on the console, and it would have tripped the phone's link watchdog.
Verified gone on hardware.
- Log decoded and failed CAMs in CamUseCaseRepository. "The app shows nothing"
had two indistinguishable causes; a silent `?: return` made this bug much
harder to find than it needed to be.
- Remove the ESP32 send-only/send-and-receive toggle. Reception can't be
disabled in firmware (raw TX only works while promiscuous), so it was an
app-side filter pretending to be a radio control.
- V2X monitor follows the serial link state on the ESP32 path instead of MQTT,
which is permanently disconnected there; CAM intake is gated on the link being
up, and engine state is cleared when it drops.
- About screen: 0.5.0, Phase 03.
- Track obu-cam-transmistter, the bench CAM transmitter. Its cam.c is compiled
(unlike obu-firmware's reference copy) and must stay bit-identical to the other
two - this commit is what that coupling costs when it's broken.
- Document the two-toolchain split: this project builds on IDF 5.5.4, obu-firmware
on the pinned 6.1. Exporting both in one shell fails confusingly.
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
#include <stdint.h>
|
||||
|
||||
// RETIRED - no longer built (removed from main/CMakeLists.txt SRCS), kept only
|
||||
// for history. Confirmed not to work: linked cleanly with -Wl,-zmuldefs but
|
||||
// the QoS-frame rejection persisted identically. Also turned out to be based
|
||||
// on the wrong function signature - the real ieee80211_raw_frame_sanity_check
|
||||
// takes (wifi_interface_t ifx, const void *buffer, int32_t len, bool
|
||||
// en_sys_seq), confirmed from opentrafficmap/its-g5-receiver-firmware_txenabled's
|
||||
// main/tx_custom.c, not the 3x int32_t guessed below. Superseded by
|
||||
// tx_custom.c, which bypasses esp_wifi_80211_tx() (and the function that
|
||||
// calls this check) entirely instead of trying to neutralize the check.
|
||||
// See docs/04-transmit-setup.md.
|
||||
|
||||
// Overrides a function inside the closed-source WiFi library that gates
|
||||
// which raw 802.11 frame types esp_wifi_80211_tx() will accept. By default
|
||||
// it only allows beacon/probe-request/probe-response/action and non-QoS
|
||||
// data frames - it explicitly rejects QoS Data (subtype 8), which is what
|
||||
// real ITS-G5/802.11p hardware actually transmits and expects.
|
||||
//
|
||||
// This is the same technique used by ESP32 WiFi-security tools (deauther/
|
||||
// injection projects) to unlock raw frame injection: define a function with
|
||||
// the exact same name as the library's gate, and link with -Wl,-zmuldefs
|
||||
// (see CMakeLists.txt) so the linker accepts having two definitions of the
|
||||
// same symbol instead of erroring with "multiple definition of
|
||||
// `ieee80211_raw_frame_sanity_check'" - and takes this one instead of the
|
||||
// library's.
|
||||
//
|
||||
// Confirmed present for THIS target/IDF version: `nm` on
|
||||
// components/esp_wifi/lib/esp32c5/libnet80211.a (IDF v5.5.4) shows
|
||||
// `ieee80211_raw_frame_sanity_check` as a normal (non-weak) global text
|
||||
// symbol in ieee80211_node.o. The exact argument count/meaning is
|
||||
// reverse-engineered from community ESP32 (Xtensa) deauther tools, not
|
||||
// confirmed byte-for-byte against esp32c5's actual implementation - if
|
||||
// frames still get rejected, or this crashes, the real signature may take
|
||||
// different arguments than assumed here.
|
||||
//
|
||||
// Real risk, not just an inconvenience: this disables ALL sanity checking
|
||||
// on raw frames going through esp_wifi_80211_tx(), not just the QoS-type
|
||||
// gate. Whatever else that check validates (frame length bounds, etc.) is
|
||||
// now unchecked. Malformed frames from a bug elsewhere in this codebase
|
||||
// could behave worse (silent corruption, crash) than they would have with
|
||||
// the check in place, where they'd have just been rejected cleanly.
|
||||
int ieee80211_raw_frame_sanity_check(int32_t arg1, int32_t arg2, int32_t arg3)
|
||||
{
|
||||
(void)arg1;
|
||||
(void)arg2;
|
||||
(void)arg3;
|
||||
return 0; // 0 = "frame is sane" - always pass
|
||||
}
|
||||
Reference in New Issue
Block a user