## [2.0.0] - 2026-09-03 #31
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/audit-security-lis2dh12"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
[2.0.0] - 2026-09-03
CI: record the repository owner's explicit decision to accept, for now, the supply-chain risk of the five reusable workflows (
check-on-feature-branch,create-tag-on-dev,create-tag-on-main,publish-on-tag,validate-branch-flow) tracking the mutablefaicel/central_ci/...@mainref — push-triggered jobs passRUNNER_TOKENto whatever@maincontains at run time. The decision and its residual exposure are documented in.forgejo/README.md; the workflows are unchanged and the decision is to revisit pinning them to an immutable commit SHA when practical.Breaking/fix:
set_interrupt_thresholdandset_interrupt_durationnow reject values greater than 127 withLis2dh12Error::InvalidConfigurationinstead of silently truncating them to the 7-bit register width (INTx_THS.THS[6:0],INTx_DURATION.D[6:0]) — a caller passing e.g. 255 previously configured 127 without any error.configure_motion_detectionandconfigure_free_fallvalidate the configured threshold and duration up front, before the first I2C transaction, so an invalid configuration can no longer leave partially-modified hardware behind (previously the error surfaced only after the power-mode/data-rate/range/filter/reference/interrupt writes on the motion path, and after theINT_CFG/THSwrites on the free-fall path). In-range values (0–127) are unaffected.Fix: the self-test could panic on legal bus data and validated responses against wrong limits. Per-axis deltas are now computed in
i32with the absolute value taken before any conversion (the datasheet defines the self-test change as the absolute output difference), so the full legal raw span (baseline 0x8000 vs tested 0x7FFF, a 65535-count difference) no longer overflowsi16— previously a debug-build panic (an abort onno_stdtargets) exactly when diagnosing broken hardware. Deltas are now reported in digits of the configured power mode (raw count difference ÷ 16/64/256 for high resolution/normal/low power, rounded to nearest; the maximum possible value is 4096 digits, so thei16fields are unchanged) andSelfTestLimits::for_configurationconverts the datasheet's physical self-test window (68–1440 mg, derived from the only published limits: 17–360 LSB at ±2g normal) into the configured mode's digit counts with ceil/floor instead of an inverted sensitivity ratio — the old limits were wrong for every configuration except ±2g normal (e.g. ±2g high resolution returned 4–90 instead of 68–1440 digits). Consumers asserting onSelfTestResult.delta_*values or customSelfTestLimitsmust adapt to the configured-mode-digit unit.Breaking/fix: acceleration readings were 16× (high resolution), 64× (normal) or 256× (low power) too large — the conversion applied the per-power-mode mg/LSB sensitivity directly to the left-justified raw 16-bit output without undoing the left-justification (datasheet Table 4).
read_acceleration,try_read_accelerationandread_fifonow convert with the mode-independent g-per-raw16-LSB factor (g = raw16 × 6.25e-5 × range multiplier: 1/2/4/12 for ±2g/±4g/±8g/±16g), identical across the single-sample and FIFO paths. On ±16g extreme codes legitimately report up to ≈24.5 g (the conversion law is not clamped to nominal full scale). Consumers must recalibrate any g-based thresholds calibrated against the old (wrong) values.Performance: data-ready polling is now paced by the output data rate — between status polls the driver sleeps one quarter of the two-sample-period window (1 ms floor) instead of a fixed 1 ms, so a timed-out wait at 100 Hz costs 5 status polls with 4 × 5 ms sleeps instead of 20 polls, and at 1 Hz 5 polls with 4 × 500 ms sleeps instead of ~2000. Data arriving exactly at the timeout boundary is now accepted (the timeout is raised only after a poll at the boundary itself); as the honest cost of that uniform boundary rule, the worst case at ODR ≥ 400 Hz becomes one poll and one 1 ms delay longer than before (6 polls / 5 delays at the 5 ms timeout floor, ~95 µs of extra bus time per timed-out read). Applies to both the acceleration and temperature wait loops.
Performance: the output data rate tables are merged into a single milli-Hz source of truth — the Hz accessor (
sample_rate, timeouts) is now derived from the milli-Hz table instead of a parallel hand-maintained match, with identical outputs for every data rate and power mode (PowerDown → 0.0, 1.620 kHz low power → 1620.0, 5.376 kHz → 5376.0 low power / 1344.0 otherwise); a new unit test pins all data-rate × power-mode combinations exactly.Performance: driver initialization now takes 19 I2C transactions instead of 42 (active-low variant: 20 instead of 44). After the BOOT reboot, the writable registers are zeroed with multi-byte write frames per the datasheet (Table 18 frame: ST, SAD+W, SUB, DATA…) over the contiguous register runs instead of 21 single-register writes, and CTRL_REG1/CTRL_REG4 (plus the CTRL_REG6 polarity bit when configured) are written once with their computed final values instead of a read-modify-write chain over registers the reset just cleared — the end state is unchanged (CTRL_REG1 = 0x57, CTRL_REG4 = 0x88); public setters keep read-modify-write semantics for runtime use. Note: the datasheet explicitly guarantees subaddress auto-increment for multi-byte reads only (§6.1), so the multi-byte write form was verified on real hardware: a board probe writing distinct per-position values over both burst ranges and reading back all 13 positions individually passed with every position matching — the burst-write initialization is confirmed as the final shipped form (no fallback to single-register writes applies).
CI: the local
scripts/check-version-sync.shtolerates a top-level## [Unreleased]CHANGELOG section (reports sync OK without a version comparison) so audit changes can accumulate before the release is cut; the strict version-to-version comparison is unchanged for release flows.Performance:
clear_interrupt_flagsnow reads each latched source register (INT1_SRC, INT2_SRC, CLICK_SRC) once — 3 I2C transactions instead of 9: reading a source register already clears its own flags, so repeat passes only cleared re-triggers the caller cannot rely on;configure_motion_detectiondrops accordingly from 30 to 24 transactions.CI:
scripts/test.shnow runs the full local quality gate suite —cargo fmt --all -- --check,cargo clippy --locked --all-targets -- -D warnings,RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --locked, andcargo test --locked -- --nocapture— so formatting, lint, doc and test gates are enforced locally under the same reproducible--lockedcontract as CI; the README "Tests" section documents the new sequence.Tests: add mock-I2C coverage for the remaining public API paths —
sanity_check(success and invalid device id),device_id,suspend_motion_interrupt/resume_motion_interrupton both interrupt pins,disable_all_axes, andis_data_ready— each asserting the exact bus transaction sequence and returned values.Documentation: correct the
FifoStatus::sample_countfield documentation — the 5-bit counter spans 0-31; a full buffer of 32 unread samples is signaled by theoverrunflag (datasheet FIFO_SRC_REG description).Declare package metadata:
rust-version = "1.73"(the floor actually imposed byu32::div_ceil, previously undeclared),repository, andreadmeinCargo.toml.Breaking change: remove the never-constructed
Lis2dh12Error::DeviceNotRespondingandLis2dh12Error::SelfTestFailedvariants (no library code path could ever produce them; a failed self-test is already reported throughSelfTestResult.passed, and data-ready timeouts surface asDataReadyTimeout). Users pattern-matching on these variants must drop the dead arms.Breaking change: the public API surface is consolidated to one canonical path per item — the
driver,registers,types, anderrormodules are now private, so every public item is reachable only through the crate-root re-exports (lis2dh12::Range,lis2dh12::SlaveAddr,lis2dh12::Lis2dh12Error, …) pluslis2dh12::i2c::Lis2dh12for the driver. The unusedF32x3,Accelerometer,RawAccelerometer,Error, andErrorKindre-exports from theaccelerometercrate are removed (I16x3stays: it appears in theread_fifo_rawsignature).Documentation: all 21 doc examples now compile as
no_rundoctests instead of being fencedignore(several imported a path that did not exist); each example is type-checked against a mock I2C bus built from theembedded-hal-mockdev-dependency and stays hardware-neutral.Performance: acceleration reads (
read_acceleration,try_read_acceleration) no longer re-read CTRL_REG1/CTRL_REG4 on every sample — the driver's cached configuration (range, power mode, data rate, maintained by every setter) is authoritative, halving the per-read I2C traffic from 4 to 2 transactions (STATUS poll + OUT_X..Z burst).Breaking change: rename the
DataRatevariantHz_1600_LPtoHz_1620_LPso the variant name matches the actual low-power output data rate.Fix: the low-power ODR code
0b1000now reports its datasheet value of 1.620 kHz (sample_rate()returns 1620.0 Hz) instead of 1600 Hz; data-ready timeout behavior is unchanged (the 5 ms floor still dominates).Breaking change: remove the unreachable
Accelerometer/RawAccelerometertrait implementations (they existed only on the crate-internal attached driver, so no trait impl was reachable from outside the crate) and their dead conversion helpers; the crate documentation no longer claims to implement theaccelerometercrate traits.Breaking change:
Lis2dh12::sample_ratenow returnsResult<f32, Lis2dh12Error<E>>(the same error type as every other method) instead ofaccelerometer::Error<E>, and reads the device configuration before computing the rate.Add co-located register bit-layout tests (
src/registers/tests/) pinning every register constant (addresses, masks, bit positions, free-fall preset) to its documented datasheet value.Move the unit tests into per-module
tests/directories co-located with their sources (src/driver/tests/,src/types/tests/,src/error/tests/); the centralsrc/tests/directory is gone.Restore the clippy-clean baseline in the shared test helper (use a
vec!literal instead ofVec::new()+ push, remove a no-op0x00 |operation).Fix README.md.
Update .gitignore