Skip to content

Conversation

@lordfolken
Copy link
Member

@lordfolken lordfolken commented Nov 30, 2025

Your PR should:

  • all description should be in the commit messages (no text in the pr)
  • your pr should be rebased on the current HEAD
  • one commit per atomic feature (every commit should build)
  • no fixup commits
  • pass all the compile and CI targets

For coding, style guide, architecture information please see our development guide:
https://xcsoar.readthedocs.io/en/latest/index.html

Summary by CodeRabbit

Release Notes

  • New Features

    • Added support for crew mass and empty mass configuration on compatible devices
    • Enhanced elevation handling for improved altitude calculations
    • Added custom baud rate support (up to 1,000,000) for serial port communication
    • Improved ballast management with new configuration options
  • Documentation

    • Added comprehensive FLARM protocol specification and compliance documentation
    • Added LXNAV device protocol specification reference
    • Added build configuration and screen size usage guides
  • Tests

    • Added POLAR data parsing validation tests
    • Expanded ballast handling test coverage

✏️ Tip: You can customize this high-level summary in your review settings.

- Add SetVolume() function to LXNAVVario namespace
- Update PutVolume() to support both LXNAV Vario and LX16xx devices
- Add VOL setting to LXNAVVarioConfigWidget for reading and writing volume
- Volume can be configured via device config dialog (0-100%)
- Implements PLXV0,VOL protocol command per LXNAV specification 1.05
…io devices

- Add support for reading and writing ALTOFF setting via PLXV0 protocol
- Implement all three ALTOFF parameters: error, QNH, and takeoff offset
- Add three integer fields to LXNAVVarioConfigWidget (-1000 to 1000 meters)
- Use NMEAInputLine utility for parsing comma-separated float values
- Implements PLXV0,ALTOFF protocol command per LXNAV specification 1.05
Add generic elevation setting support to the device interface, allowing
devices to provide and receive elevation values for calibration.

- Add elevation to ExternalSettings for device-provided elevation values
- Add PutElevation() and RequestElevation() to Device interface
- Implement elevation support in LXNAV driver via PLXV0,ELEVATION
- Add elevation control to AltitudeSetupPanel (AutoAltitude InfoBox)
- Display elevation value from device or "N/A" if not available
- Integrate elevation with AutoQNH to sync elevation when QNH is set
- Request elevation from devices when opening AltitudeSetup dialog

The elevation setting is abstracted through ExternalSettings, similar to
QNH, keeping the UI layer independent of driver-specific implementations.
Add firmware version logging when LXNAV devices are detected via PLXVC.
The firmware and hardware version are included in the detection log message,
or logged separately if received later via LXWP1.

- Include firmware/hardware version in device detection log message
- Use "unknown" for missing version information
- Log firmware version separately if received after device detection
- Only log once per device connection
- Parse license string from LXWP1 sentence
- Display license in device setup dialogs (ManageLXNAVVarioDialog,
  ManageNanoDialog, ManageLX16xxDialog) as read-only field
- Remove hardware version from PLXVC detection logging (it contains
  serial number, not hardware version, for privacy reasons)
- Filter out high-frequency LXWP2 sentences from NMEA logging
- Remove firmware version logging from LXWP1 handler (already logged
  in device detection message)

All device information (product, serial, hardware version, firmware,
license) remains available in the configuration dialogs when received
from the device.
Extend baud rate options in device configuration dialog to include
256000, 460800, 500000, 921600, and 1000000 baud rates.

Implement custom baud rate support for Linux using TIOCSSERIAL with
ASYNC_SPD_CUST flag. This method works with USB-to-serial drivers
like FTDI that don't support termios2.

- Add TIOCSSERIAL implementation for baud rates > 230400 on Linux
- Remove termios2 implementation (not widely supported by USB drivers)
- Update GetBaudrate() to read custom baud rates from TIOCSSERIAL
- Add platform-specific comments explaining Windows/macOS/iOS/Android behavior

Windows natively supports arbitrary baud rates via SerialPort.
macOS/iOS don't support TIOCSSERIAL and will show an error for
custom baud rates. Android uses platform-specific implementations.

TIOCSSERIAL has been available since Linux kernel 2.2, ensuring
compatibility with older systems.
Parse the IGC press altitude field from PLXVS sentence and use it
as the barometric altitude in IGC files when available. This ensures
XCSoar's IGC files match the device's own IGC recording values.

- Add igc_pressure_altitude field to NMEAInfo
- Parse IGC press altitude from PLXVS sentence
- Use IGC pressure altitude with highest priority in IGCFix::Apply()
- Priority: IGC pressure altitude > pressure altitude > baro altitude > GPS altitude

This follows the IGC standard requirement that the barometric
altitude should match the device's recording value when available.
Add OnCalculatedUpdate method to send MacCready value to LXNAV device
on startup. This ensures MC is synchronized when XCSoar starts, similar
to how the OpenVario driver handles it.

- Add mc_sent flag to track if MC has been sent
- Implement OnCalculatedUpdate to send MC on first calculation cycle
- Reset mc_sent flag in LinkTimeout for reconnection handling
- Use proper locking to avoid race conditions
Refactor MC, Ballast, and Bugs synchronization to use ExternalSettings
from the blackboard instead of DeviceSettingsMap. This makes the code
consistent with XCSoar's architecture and eliminates data duplication.

Changes:
- Use basic.settings (ExternalSettings) from blackboard for all settings
- Add SyncMacCready(), SyncBallast(), SyncBugs() utility functions
- Add IsMCEcho(), IsBallastEcho(), IsBugsEcho() helper functions
- Track last_sent values for feedback loop detection
- Request MC on vario detection; ballast/bugs come via LXWP2
- If device has non-zero values (and not an echo), use device's values
- Otherwise, send XCSoar's values to the device

This ensures proper synchronization while respecting device settings
and preventing feedback loops.
When converting ballast overload to ballast fraction, handle cases where
the overload is less than 1.0 (glider lighter than reference mass).
The ballast fraction must be clamped to >= 0 since negative water
ballast is not physically possible.

Also removed the >= 0.8 check to allow processing of any overload value,
as overload can theoretically be negative when the actual mass is lighter
than the reference mass.
- Rename ballast member to ballast_litres for clarity
- Remove SetBallast()/GetBallast() fraction-based methods
- Add SetBallastLitres(), SetBallastFraction(), SetBallastOverload()
- Add GetBallastFraction(), GetBallastOverload()
- Add max_ballast as configured member (not calculated)
- Update all call sites to use new litres-based API
- Update ActionInterface, ApplyExternalSettings, BallastDumpManager,
  dlgBasicSettings, GaugeVario, InputEventsSettings, lua/Settings,
  PlaneGlue to use GetBallastLitres() and related methods
@lordfolken lordfolken requested a review from a team as a code owner November 30, 2025 02:26
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 30, 2025

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This pull request introduces significant infrastructure enhancements and a major ballast handling refactoring. It adds new build automation scripts and documentation, extends device driver capabilities (particularly LX LXNAV vario), refactors ballast from fraction-based to absolute litres-based representation throughout the codebase, expands external settings with elevation and POLAR data fields, and adds comprehensive FLARM protocol analysis documentation alongside new specification files.

Changes

Cohort / File(s) Change Summary
Build Infrastructure & Scripts
build_all_configs.sh, build_quick_test.sh, check_screensize_usage.sh, BUILD_ALL_CONFIGS.md, SCREENSIZE_ANALYSIS.md
New build automation scripts with validation, dry-run support, and logging; new documentation for multi-target builds and screen size access analysis
Configuration Files
.bash_aliases, .gitignore, bash_aliases, foo.bash
New shell aliases for UNIX/WAYLAND builds; tags entry added to gitignore; new foo.bash script
FLARM Protocol Documentation
FLARM_*.md, FLARM_PROTOCOL_ANALYSIS.md, FTD-014.txt, LXNAV_105.txt
Comprehensive FLARM analysis documents (inconsistencies, compliance checklists, specification mapping); new device specification documents for LX NAV and FLARM
Build Logs & Configuration
build_logs/*, build/test.mk
Build result logs; expanded TEST_DRIVER_SOURCES and TEST_DRIVER_DEPENDS in test configuration
Submodule Updates
android/UsbSerial, android/ioio
Submodule pointer updates (no functional changes)
Ballast System Refactoring
src/Engine/GlideSolvers/GlidePolar.*, src/Gauge/GaugeVario.cpp, src/Input/InputEventsSettings.cpp, src/lua/Settings.cpp, test/src/TestGlidePolar.cpp, test/src/test_replay_task.cpp
Rework ballast representation from fraction-based to absolute litres; replace SetBallast/GetBallast with SetBallastLitres/SetBallastFraction and corresponding getters; update all usages
ActionInterface & Ballast Handlers
src/ActionInterface.*, src/ApplyExternalSettings.cpp, src/BallastDumpManager.cpp
Rename SetBallast parameter to ballast_litres; add SetCrewMass/SetEmptyMass; refactor ballast handling to use litres-based computations; add elevation pushing
Device Descriptor & Base Drivers
src/Device/Descriptor.*, src/Device/Driver.*, src/Device/MultipleDevices.*
Add PutCrewMass, PutEmptyMass, PutElevation, RequestElevation methods across descriptor, driver interface, and multiple devices forwarding
LX Driver Extensions
src/Device/Driver/LX/Internal.hpp, src/Device/Driver/LX/LXNAVVario.hpp, src/Device/Driver/LX/Mode.cpp, src/Device/Driver/LX/Parser.cpp, src/Device/Driver/LX/Settings.cpp
Add crew/empty mass, elevation, and POLAR data handling; implement synchronization callbacks; enhance NMEA parsing for POLAR coefficients; add LXWP2 logging suppression
External Settings & Data Structures
src/NMEA/ExternalSettings.*, src/NMEA/DeviceInfo.hpp, src/NMEA/Derived.*, src/NMEA/Info.*
Add elevation and POLAR-related fields (coefficients, load, masses) with availability flags; add Provide* methods for validation and updates; update Reset/Clear logic
Plane & Computer Components
src/Plane/Plane.hpp, src/Plane/PlaneFileGlue.cpp, src/Plane/PlaneGlue.cpp, src/Computer/AutoQNH.cpp
Add plane_profile_active flag; implement SetMaxBallast usage; update polar loading logic when device POLAR is available; track elevation in QNH calculation
Device Port & Settings UI
src/Device/Port/TTYPort.cpp, src/Dialogs/Device/DeviceEditWidget.cpp, src/Dialogs/Device/LX/*, src/Dialogs/Settings/dlgBasicSettings.cpp, src/InfoBoxes/Panel/AltitudeSetup.cpp
Add Linux custom baud rate support; extend baud rate options; add VOL/ALTOFF config UI for LXNAV; add License display; implement elevation device polling and UI controls
Test Enhancements
test/src/TestDriver.cpp, test/src/TestGlidePolar.cpp
Add BackendComponents stubs; add TestLXV7POLAR() test for POLAR parsing; update ballast API calls to use new litres/fraction methods

Sequence Diagram

sequenceDiagram
    participant User as User<br/>(Settings UI)
    participant XCSoar as XCSoar<br/>(Core)
    participant Device as LX Device<br/>(LXNAV Vario)
    participant External as External<br/>Settings

    User->>XCSoar: Set Crew Mass
    activate XCSoar
    XCSoar->>XCSoar: ActionInterface::SetCrewMass()
    XCSoar->>External: ProvideCrewMass() check
    XCSoar->>Device: PutCrewMass(crew_mass)
    activate Device
    Device->>Device: Send PLXV0,POLAR,...
    Device-->>XCSoar: Success
    deactivate Device
    XCSoar->>XCSoar: SetTaskPolar (recalculate)
    deactivate XCSoar

    User->>XCSoar: Request Elevation
    activate XCSoar
    XCSoar->>Device: RequestElevation()
    activate Device
    Device->>Device: Send PLXV0,ELEVATION,R
    Device-->>Device: Receive PLXV0,ELEVATION,W,...
    Device-->>XCSoar: elevation data via PLXV0
    deactivate Device
    XCSoar->>External: ProvideElevation()
    XCSoar->>XCSoar: Update DerivedInfo.pressure_elevation
    deactivate XCSoar

    Device->>Device: Periodic update (OnCalculatedUpdate)
    activate Device
    Device->>Device: SyncMacCready/Ballast/Bugs/CrewWeight/EmptyWeight
    Device->>Device: Echo detection (avoid redundant sends)
    Device->>XCSoar: PutBallast/SetMacCready if changed
    deactivate Device
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Key areas requiring extra attention:

  • Ballast refactoring consistency: Verify all ballast-related API changes (SetBallastLitres, SetBallastFraction, GetBallastFraction, GetBallastOverload) are correctly applied across GlidePolar.cpp/hpp, ActionInterface, BallastDumpManager, InputEventsSettings, test files, and lua bindings. Watch for edge cases around max_ballast initialization and fraction-to-litres conversions.

  • LX driver state management: Review LXDevice private state additions (last_sent_*, pending request flags, polar tracking) in Internal.hpp and synchronization logic in Mode.cpp (SyncMacCready, SyncBallast, etc.). Verify echo detection prevents feedback loops and plane_profile_active guards work correctly.

  • External settings POLAR expansion: Validate new Provide* methods in ExternalSettings implement range checks, change detection, and timestamp updates consistently; verify Complement() and EliminateRedundant() handle new fields correctly.

  • Device descriptor forwarding: Confirm MultipleDevices correctly forwards all new Put*/Request* methods to contained devices and that error handling is uniform.

  • Elevation polling logic: Verify the 1000ms polling loop in AltitudeSetup.cpp with device blackboard reads doesn't block UI; check fallback to CommonInterface::Basic() works reliably.

  • TTYPort Linux custom baud: Review custom divisor calculation and TIOCSSERIAL ioctl usage for edge cases and error conditions.

Poem

🐰 The ballast flows in litres now, not fractions of the weight,
Device and driver dance as one, with elevation set just right,
LX learns the crew mass song, the empty mass delight,
External settings bloom so full, with POLAR shine so bright,
Build scripts tumble endlessly, through every config state! 🚀

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.09% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Feature/lxnav105' is vague and does not clearly convey the scope or purpose of the changes, using a generic naming convention without describing what LXNAV105 represents or what functionality is being added. Revise the title to clearly describe the main feature or change (e.g., 'Add LXNAV 105 device support with crew mass, elevation, and polar synchronization' or similar descriptive phrase).
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/ApplyExternalSettings.cpp (1)

45-57: Consider propagating ballast litres changes via SetTaskPolar.

The BallastLitresProcessTimer() function sets ballast litres directly (line 52) but doesn't call SetTaskPolar to propagate changes, unlike the refactored BallastProcessTimer() which calls SetTaskPolar after both SetBallastFraction (line 25) and SetBallastOverload (line 35).

This inconsistency may prevent ballast litres updates from being properly propagated to backend components.

Consider applying this change for consistency:

 BallastLitresProcessTimer()
 {
   bool modified = false;
   static Validity last_ballast_litres_validity;
   const NMEAInfo &basic = CommonInterface::Basic();
   if(basic.settings.ballast_litres_available.Modified(last_ballast_litres_validity)){
     PolarSettings &polar(CommonInterface::SetComputerSettings().polar);
     polar.glide_polar_task.SetBallastLitres(basic.settings.ballast_litres);
+    backend_components->SetTaskPolar(CommonInterface::GetComputerSettings().polar);
     modified = true;
   }
   last_ballast_litres_validity = basic.settings.ballast_litres_available;
   return modified;
 }
src/NMEA/ExternalSettings.hpp (1)

162-171: Typo in comment: "absolure" should be "absolute".

   /**
-   * Compare the absolure ballast in kg (litres) setting with the specified value.
+   * Compare the absolute ballast in kg (litres) setting with the specified value.
    *
🧹 Nitpick comments (24)
check_screensize_usage.sh (1)

1-197: Script provides good automation for pattern analysis.

The script effectively scans directories, aggregates pattern matches, and surfaces inconsistencies. It complements the SCREENSIZE_ANALYSIS.md documentation well. Error handling with set -e and 2>/dev/null redirection is appropriate for a scanning utility.

Minor suggestions:

  • Consider adding an exit code check after grep commands (some fail silently with || true)
  • The logic at lines 64–68 could be simplified using grep's -l flag directly
src/Device/Port/TTYPort.cpp (2)

26-60: Consider using <linux/serial.h> instead of local definitions.

Defining serial_struct locally works but risks divergence from kernel definitions. The kernel's serial struct is part of the stable UAPI, so including <linux/serial.h> would be more maintainable and automatically provide TIOCGSERIAL, TIOCSSERIAL, and ASYNC_SPD_CUST.

If there's a specific reason to avoid the header (e.g., cross-compilation issues), a comment explaining this choice would be helpful.

 #ifdef __linux__
 #include <sys/ioctl.h>
-/* For TIOCSSERIAL method (works on USB-to-serial drivers like FTDI) */
-/* TIOCSSERIAL has been available since kernel 2.2 */
-#ifndef TIOCGSERIAL
-#define TIOCGSERIAL 0x541E
-#endif
-#ifndef TIOCSSERIAL
-#define TIOCSSERIAL 0x541F
-#endif
-/* ASYNC_SPD_CUST may not be defined in very old kernel headers (pre-2.4) */
-#ifndef ASYNC_SPD_CUST
-#define ASYNC_SPD_CUST 0x0030
-#endif
-struct serial_struct {
-  int type;
-  int line;
-  unsigned int port;
-  int irq;
-  int flags;
-  int xmit_fifo_size;
-  int custom_divisor;
-  int baud_base;
-  unsigned short close_delay;
-  char io_type;
-  char reserved_char[1];
-  int hub6;
-  unsigned short closing_wait;
-  unsigned short closing_wait2;
-  unsigned char *iomem_base;
-  unsigned short iomem_reg_shift;
-  unsigned int port_high;
-  unsigned long iomap_base;
-};
+#include <linux/serial.h>
 #endif

163-178: Reduce code duplication in termios attribute setup.

The termios configuration (lines 167-178) is nearly identical to the standard path (lines 200-210). Consider extracting a helper function to set the common attributes.

static void
ConfigureRawMode(struct termios &attr) noexcept
{
  attr.c_iflag &= ~(BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
  attr.c_iflag |= (IGNPAR | IGNBRK);
  attr.c_oflag &= ~OPOST;
  attr.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
  attr.c_cflag &= ~(CSIZE | PARENB | CRTSCTS);
  attr.c_cflag |= (CS8 | CLOCAL);
  attr.c_cc[VMIN] = 0;
  attr.c_cc[VTIME] = 1;
}

Also applies to: 196-211

build_quick_test.sh (1)

59-60: Remove trailing blank lines.

The script has unnecessary blank lines at the end. This is a minor style issue.

Apply this diff:

 echo "Summary: $SUCCESS successful, $FAILED failed"
-
-
-
build_all_configs.sh (4)

31-33: Use explicit no-op command for file truncation.

Shellcheck warns that these redirections lack commands. While > file works in bash, using : > file or true > file is more explicit and portable.

 # Initialize result files
-> "$RESULTS_FILE"
-> "$FAILED_BUILDS"
-> "$SUCCESSFUL_BUILDS"
+: > "$RESULTS_FILE"
+: > "$FAILED_BUILDS"
+: > "$SUCCESSFUL_BUILDS"

128-135: Remove unused TARGET_SPECIFIC_FLAGS variable.

This array is defined but never referenced. If it's intended as documentation, consider converting it to a comment. If it's planned for future use, add a # shellcheck disable=SC2034 annotation or remove it.

-# Flags that are target-specific and should be skipped for certain targets
-TARGET_SPECIFIC_FLAGS=(
-    "ENABLE_SDL"      # Only for UNIX-like targets
-    "USE_FB"          # Only for Linux targets
-    "VFB"             # Only for certain targets
-    "ENABLE_MESA_KMS" # Only for Linux targets
-    "GREYSCALE"       # Only for certain targets
-    "DITHER"          # Only for certain targets
-)
+# Note: Target-specific flags (ENABLE_SDL, USE_FB, VFB, ENABLE_MESA_KMS, 
+# GREYSCALE, DITHER) are filtered in is_valid_combination()

192-197: Separate variable declaration and assignment.

Shellcheck warns that combining local declaration with command substitution can mask return values. While low risk here, it's good practice to separate them.

-    local flag_name=$(echo "$flags" | sed 's/ /_/g' | sed 's/=/-/g')
+    local flag_name
+    flag_name=$(echo "$flags" | sed 's/ /_/g' | sed 's/=/-/g')
     build_name="${target}_${flag_name}"
   fi
   
-  local log_file="${LOG_DIR}/${build_name}.log"
-  local start_time=$(date +%s)
+  local log_file start_time
+  log_file="${LOG_DIR}/${build_name}.log"
+  start_time=$(date +%s)

210-211: Add comment explaining intentional word splitting.

The unquoted $flags is intentional to allow word splitting for multiple make arguments. Adding a brief comment would clarify this for maintainers and silence potential linter warnings.

     # Build with make
+    # Note: $flags intentionally unquoted for word splitting (multiple make args)
     if make TARGET="$target" $flags > "$log_file" 2>&1; then
src/Device/Driver/LX/Internal.hpp (2)

131-152: Consider consolidating overlapping struct fields.

TrackedPolar and DevicePolar share several common fields (a, b, c, empty_mass/empty_weight). While they serve different purposes (tracking XCSoar's view vs. device-reported data), consider whether a common base or shared structure could reduce duplication.

This is optional since the current separation clearly delineates the two different data sources and their distinct usage patterns.


139-139: Minor: Remove extra blank line.

There's a double blank line between tracked_polar and DevicePolar struct definitions.

src/NMEA/Info.cpp (1)

125-127: Reset of IGC pressure altitude looks correct; consider matching expiry semantics

Resetting igc_pressure_altitude_available and igc_pressure_altitude here is good and avoids stale values after a full reset. If igc_pressure_altitude is intended to behave like the other altitude sources, you may also want to expire igc_pressure_altitude_available in NMEAInfo::Expire() with a similar timeout to pressure_altitude_available, to avoid an IGC fix using a very old IGC altitude.

build_logs/successful_builds.txt (1)

1-8: Build log format looks consistent with multi-config workflow

The entries follow a clear, parseable name|status|duration|flags format and align with the described multi-config build logging. If 0s durations are not expected for some configs, it may be worth double-checking the timing logic in the generator script, but the file itself looks fine.

src/Plane/Plane.hpp (1)

39-43: Consider default‑initialising plane_profile_active to avoid indeterminate state

The new plane_profile_active flag is useful for distinguishing default vs. profile-based planes. To guard against default-constructed Plane instances where this flag might not be explicitly set, it would be safer to give it an in-class default:

-  bool plane_profile_active;
+  bool plane_profile_active = false;

This ensures a well-defined default and avoids relying on all construction paths to remember to set it.

BUILD_ALL_CONFIGS.md (2)

79-81: Consider minor wording improvements.

The phrase "Only successful builds" and "Only failed builds" on consecutive lines creates repetition. Consider rewording for better readability:

 The script creates a `build_logs/` directory with:
 - Individual log files for each build (`<target>_<flags>.log`)
 - `build_results.txt` - All results
-- `successful_builds.txt` - Only successful builds
-- `failed_builds.txt` - Only failed builds
+- `successful_builds.txt` - Successful builds only
+- `failed_builds.txt` - Failed builds only

104-104: Simplify "with success/failure counts" phrase.

-- The script provides a summary at the end with success/failure counts
+- The script provides a summary at the end showing success/failure counts
src/Dialogs/Settings/dlgBasicSettings.cpp (1)

134-143: Consider using static_cast instead of C-style cast.

The C-style cast on line 137 is flagged by static analysis. Using C++ style casts is preferred for type safety and clarity.

-    DataFieldFloat &df = *(DataFieldFloat *)control.GetDataField();
+    DataFieldFloat &df = *static_cast<DataFieldFloat *>(control.GetDataField());
FLARM_FTD014_SPECIFICATION_ANALYSIS.md (1)

50-52: Add language specifier to fenced code block.

The code block lacks a language specifier, which is flagged by markdownlint.

-```
+```text
 $PFLAC,A,<name>*<checksum>

</blockquote></details>
<details>
<summary>src/Device/Driver/LX/LXNAVVario.hpp (1)</summary><blockquote>

`106-112`: **Consider using `snprintf` for bounds safety.**

While the buffer size (32 bytes) is sufficient for this format string, using `snprintf` would be safer and more consistent with secure coding practices. This applies to other functions in this file as well.



```diff
   static inline void
   SetVolume(Port &port, OperationEnvironment &env, unsigned volume)
   {
     char buffer[32];
-    sprintf(buffer, "PLXV0,VOL,W,%.1f", (double)volume);
+    snprintf(buffer, sizeof(buffer), "PLXV0,VOL,W,%u", volume);
     PortWriteNMEA(port, buffer, env);
   }

Note: The (double) cast and %.1f format are unnecessary for an integer value; %u would be more direct.

src/InfoBoxes/Panel/AltitudeSetup.cpp (2)

48-49: Replace C-style casts with static_cast for DataField types

In OnModified() and Prepare(), the casts:

  • DataFieldFloat &df = (DataFieldFloat &)_df;
  • DataFieldInteger &df = (DataFieldInteger &)_df;
  • DataFieldFloat &df = *(DataFieldFloat *)qnh_control->GetDataField();

are safe given how the controls are created, but trigger the static-analysis warning and are less explicit than necessary.

Consider switching to static_cast to make the intent clear and keep tools quiet:

-  DataFieldFloat &df = (DataFieldFloat &)_df;
+  auto &df = static_cast<DataFieldFloat &>(_df);

-  DataFieldInteger &df = (DataFieldInteger &)_df;
+  auto &df = static_cast<DataFieldInteger &>(_df);

-  DataFieldFloat &df = *(DataFieldFloat *)qnh_control->GetDataField();
+  auto &df = static_cast<DataFieldFloat &>(*qnh_control->GetDataField());

Also applies to: 61-62, 86-89


94-113: UI thread blocks up to 1 s while polling device_blackboard

The 10×Sleep(100) loop runs on the UI thread during Prepare(), which can freeze the dialog for up to 1 second if the device is slow or absent. If this becomes noticeable, consider reducing the wait or making the elevation request/refresh asynchronous instead of busy-waiting in the dialog.

src/Device/Driver/LX/Settings.cpp (1)

150-211: Clarify unsupported-device semantics and avoid redundant last_sent_* updates

The new methods generally look good, but there are two small consistency points:

  1. Return values for unsupported devices

    • PutCrewMass() / PutEmptyMass() return true when !IsLXNAVVario(), i.e. they no-op but report success.
    • PutElevation() / RequestElevation() return false for non‑LXNAV varios.

    If callers interpret false as “feature not supported” (rather than a hard error), it might be clearer to use the same convention for all three families (either always true/no-op or always false for unsupported devices) and document it. Right now DeviceDescriptor wrappers will see different statuses depending on which setter is called.

  2. last_sent_* tracking in two layers

    • PutBallast(), PutBugs(), and PutMacCready() already set last_sent_ballast_overload, last_sent_bugs, and last_sent_mc under mutex.
    • LXDevice::SyncBallast(), SyncBugs(), and SyncMacCready() in Mode.cpp set the same fields again after calling these methods.

    This duplication is harmless but makes ownership of the “last sent” state a bit fuzzy. You can simplify by relying on the driver methods to own last_sent_* updates and dropping the extra assignments in Sync*, which reduces the chance of the two drifting apart during future refactors.

Also applies to: 213-255, 270-295

src/Device/Driver/LX/Mode.cpp (1)

192-544: Verify ballast overload calculation uses the correct mass units

The new OnCalculatedUpdate() / Sync* logic is comprehensive and the direction-of-truth handling (default plane → read from vario, plane profile active → push to vario) is well structured. One detail worth double‑checking is the ballast overload computation in SyncBallast():

const GlidePolar &polar = calculated.glide_polar_safety;
...
const double ballast_litres = polar.GetBallastLitres();
const double dry_mass = polar.GetDryMass();
const double reference_mass = polar.GetReferenceMass();
...
const double overload = (dry_mass + ballast_litres) / reference_mass;
...
PutBallast(0.0, overload, env);

This assumes that ballast_litres can be added directly to dry_mass (i.e. that 1 litre of ballast is effectively treated as 1 kg and that GetBallastLitres() is already “mass-like”). If GlidePolar ever changes to distinguish litres from kilograms more explicitly (e.g. with a density factor or a separate GetBallastMass()), this formula could drift.

It’s probably fine today, but to future‑proof the code you might want to:

  • either switch to a mass-returning API if one exists (e.g. GetTotalMass() or GetBallastMassKg()), or
  • add a short comment documenting the 1‑litre‑≈‑1‑kg assumption so it’s clear this is intentional.

The rest of the sync logic (MC, bugs, crew/empty mass echo checks, and polar change tracking via tracked_polar and device_polar) looks consistent and avoids unnecessary device traffic.

Also applies to: 578-617

src/Engine/GlideSolvers/GlidePolar.hpp (2)

266-283: Clarify and harden semantics of new ballast setters/getters

The new trio SetBallastLitres / SetBallastFraction / SetBallastOverload plus GetBallastLitres / GetBallastFraction / GetBallastOverload looks like a clean API split, but a couple of edge-case behaviours are worth nailing down in the implementation:

  • For SetBallastFraction(const double fraction) (Lines 273-276), it’s not obvious whether callers may pass values outside [0, 1] (or NaNs) and whether you clamp, assert, or allow them through. Given it’s a config-like API, clamping to [0, 1] (or at least documenting the expectation) would avoid surprising states.
  • Similarly for SetBallastOverload(const double overload) (Lines 279-282), it would be good to define behaviour for values < 1.0 (or <= 0) and for pathological values. If you treat overload as “total_mass / reference_mass”, then overload < 1 probably deserves either clamping or an assertion.
  • For GetBallastFraction() and GetBallastOverload() (Lines 299-304, 305-309), please ensure the implementation handles max_ballast <= 0 and/or reference_mass <= 0 gracefully (e.g. returning 0 rather than risking division by zero or NaNs in degenerate configurations).
  • HasBallast() (Lines 287-289) now uses ballast_litres > 0, which is consistent with the new storage. If in practice you often end up with tiny residuals (e.g. numerical noise after dumps), consider using a small epsilon threshold rather than strict > 0, but that’s more of a style choice.

Tightening these behaviours (and documenting them briefly in the comments) would make the new API safer to use in the various UI, device, and test call sites.

Also applies to: 287-297, 299-310


49-50: Keep max_ballast, ballast_ratio, and reference_mass invariants explicit

The introduction of ballast_litres and max_ballast plus the changes in SetMaxBallast and SetBallastRatio (Lines 545-558, 566-573) nicely encode a relationship:

  • SetMaxBallast() derives ballast_ratio = max_ballast / reference_mass when reference_mass > 0.
  • SetBallastRatio() derives max_ballast = ballast_ratio * reference_mass when reference_mass > 0.

A couple of design points are worth considering to avoid surprising states:

  • SetReferenceMass() (Lines 507-512) currently just updates reference_mass and calls Update(), without re-synchronising max_ballast / ballast_ratio. If the intent is that these three always satisfy the same physical relation, you might want to recompute one from the other in SetReferenceMass() (or document that changing reference_mass does not affect the configured capacity/ratio).
  • Conversely, if you intend max_ballast and ballast_ratio to be independent configuration knobs, automatically deriving one from the other inside SetMaxBallast() / SetBallastRatio() may be surprising. In that case, it may be clearer to drop the implicit recomputation and leave them orthogonal.
  • SetMaxBallast() currently always calls Update() by default, although changing the capacity alone doesn’t change the actual all-up mass unless you also change the current ballast. If Update() is relatively expensive in real use (e.g. called often from settings flows), you might consider making update=false the default here or deferring updates to the point where current ballast or mass really changes.

Clarifying and, if needed, slightly refactoring these interactions would make the invariants around ballast configuration more obvious to future maintainers.

Also applies to: 76-80, 545-558, 566-573

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d8ff20b and b9fe953.

📒 Files selected for processing (65)
  • .bash_aliases (1 hunks)
  • .gitignore (1 hunks)
  • BUILD_ALL_CONFIGS.md (1 hunks)
  • FLARM_ANALYSIS_SUMMARY.md (1 hunks)
  • FLARM_FTD014_COMPLIANCE_CHECKLIST.md (1 hunks)
  • FLARM_FTD014_SPECIFICATION_ANALYSIS.md (1 hunks)
  • FLARM_PROTOCOL_ANALYSIS.md (1 hunks)
  • FTD-014.txt (1 hunks)
  • LXNAV_105.txt (1 hunks)
  • SCREENSIZE_ANALYSIS.md (1 hunks)
  • android/UsbSerial (1 hunks)
  • android/ioio (1 hunks)
  • bash_aliases (1 hunks)
  • build/test.mk (1 hunks)
  • build_all_configs.sh (1 hunks)
  • build_logs/build_results.txt (1 hunks)
  • build_logs/failed_builds.txt (1 hunks)
  • build_logs/successful_builds.txt (1 hunks)
  • build_quick_test.sh (1 hunks)
  • check_screensize_usage.sh (1 hunks)
  • foo.bash (1 hunks)
  • src/ActionInterface.cpp (4 hunks)
  • src/ActionInterface.hpp (2 hunks)
  • src/ApplyExternalSettings.cpp (3 hunks)
  • src/BallastDumpManager.cpp (1 hunks)
  • src/Computer/AutoQNH.cpp (1 hunks)
  • src/Device/Descriptor.cpp (4 hunks)
  • src/Device/Descriptor.hpp (2 hunks)
  • src/Device/Driver.cpp (1 hunks)
  • src/Device/Driver.hpp (3 hunks)
  • src/Device/Driver/LX/Internal.hpp (6 hunks)
  • src/Device/Driver/LX/LXNAVVario.hpp (4 hunks)
  • src/Device/Driver/LX/Mode.cpp (3 hunks)
  • src/Device/Driver/LX/Parser.cpp (9 hunks)
  • src/Device/Driver/LX/Settings.cpp (5 hunks)
  • src/Device/MultipleDevices.cpp (2 hunks)
  • src/Device/MultipleDevices.hpp (2 hunks)
  • src/Device/Port/TTYPort.cpp (4 hunks)
  • src/Dialogs/Device/DeviceEditWidget.cpp (1 hunks)
  • src/Dialogs/Device/LX/LXNAVVarioConfigWidget.cpp (4 hunks)
  • src/Dialogs/Device/LX/LXNAVVarioConfigWidget.hpp (1 hunks)
  • src/Dialogs/Device/LX/ManageLX16xxDialog.cpp (1 hunks)
  • src/Dialogs/Device/LX/ManageLXNAVVarioDialog.cpp (1 hunks)
  • src/Dialogs/Device/LX/ManageNanoDialog.cpp (1 hunks)
  • src/Dialogs/Settings/dlgBasicSettings.cpp (3 hunks)
  • src/Engine/GlideSolvers/GlidePolar.cpp (2 hunks)
  • src/Engine/GlideSolvers/GlidePolar.hpp (5 hunks)
  • src/Gauge/GaugeVario.cpp (1 hunks)
  • src/IGC/IGCFix.cpp (1 hunks)
  • src/InfoBoxes/Panel/AltitudeSetup.cpp (3 hunks)
  • src/Input/InputEventsSettings.cpp (1 hunks)
  • src/NMEA/Derived.cpp (1 hunks)
  • src/NMEA/Derived.hpp (1 hunks)
  • src/NMEA/DeviceInfo.hpp (1 hunks)
  • src/NMEA/ExternalSettings.cpp (6 hunks)
  • src/NMEA/ExternalSettings.hpp (3 hunks)
  • src/NMEA/Info.cpp (1 hunks)
  • src/NMEA/Info.hpp (1 hunks)
  • src/Plane/Plane.hpp (1 hunks)
  • src/Plane/PlaneFileGlue.cpp (1 hunks)
  • src/Plane/PlaneGlue.cpp (4 hunks)
  • src/lua/Settings.cpp (1 hunks)
  • test/src/TestDriver.cpp (4 hunks)
  • test/src/TestGlidePolar.cpp (4 hunks)
  • test/src/test_replay_task.cpp (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-09-04T20:52:26.947Z
Learnt from: lordfolken
Repo: XCSoar/XCSoar PR: 0
File: :0-0
Timestamp: 2025-09-04T20:52:26.947Z
Learning: In XCSoar's ApplyExternalSettings.cpp:178, when processing transponder data from external devices like Air Control Display, both transponder_code.IsDefined() and transponder_mode.IsDefined() must be checked before calling ActionInterface::SetTransponderCode() to prevent assertion failures when the transponder is switched off.

Applied to files:

  • src/ApplyExternalSettings.cpp
  • FLARM_PROTOCOL_ANALYSIS.md
  • FLARM_FTD014_COMPLIANCE_CHECKLIST.md
  • src/InfoBoxes/Panel/AltitudeSetup.cpp
  • src/NMEA/ExternalSettings.cpp
  • src/Device/Driver/LX/Mode.cpp
  • src/Device/Driver/LX/Parser.cpp
  • src/Device/Driver/LX/Internal.hpp
📚 Learning: 2025-08-02T01:25:49.521Z
Learnt from: yorickreum
Repo: XCSoar/XCSoar PR: 1714
File: src/ProgressWindow.cpp:0-0
Timestamp: 2025-08-02T01:25:49.521Z
Learning: In XCSoar's ProgressWindow.cpp, the iOS layout positioning issues that previously required magic number workarounds (3x progress_height multipliers) have been resolved with a proper fix that eliminates the need for hardcoded adjustments.

Applied to files:

  • src/ApplyExternalSettings.cpp
  • src/Dialogs/Device/LX/LXNAVVarioConfigWidget.cpp
  • src/IGC/IGCFix.cpp
📚 Learning: 2025-08-02T01:25:49.521Z
Learnt from: yorickreum
Repo: XCSoar/XCSoar PR: 1714
File: src/ProgressWindow.cpp:0-0
Timestamp: 2025-08-02T01:25:49.521Z
Learning: In XCSoar's ProgressWindow.cpp, iOS layout positioning issues that previously required magic number workarounds (3x progress_height multipliers) and platform-specific conditional code have been resolved with a proper fix, eliminating the need for hardcoded adjustments in the UpdateLayout method.

Applied to files:

  • src/Device/Driver/LX/Mode.cpp
🧬 Code graph analysis (22)
src/Device/Descriptor.hpp (3)
src/Device/Driver.hpp (14)
  • crew_mass (91-91)
  • crew_mass (279-279)
  • env (48-48)
  • env (125-125)
  • env (140-140)
  • env (178-178)
  • env (271-271)
  • env (284-284)
  • env (286-286)
  • env (296-296)
  • empty_mass (99-99)
  • empty_mass (280-280)
  • elevation (117-117)
  • elevation (283-283)
src/Device/Driver/LX/Internal.hpp (5)
  • crew_mass (367-367)
  • env (348-348)
  • env (350-350)
  • empty_mass (368-368)
  • elevation (372-372)
src/Device/MultipleDevices.hpp (7)
  • crew_mass (79-79)
  • env (66-66)
  • env (68-68)
  • env (82-82)
  • env (90-90)
  • empty_mass (80-80)
  • elevation (89-89)
src/ApplyExternalSettings.cpp (6)
src/MainWindow.cpp (2)
  • SetComputerSettings (958-963)
  • SetComputerSettings (959-959)
src/MapWindow/GlueMapWindow.cpp (2)
  • SetComputerSettings (75-86)
  • SetComputerSettings (76-76)
src/BackendComponents.hpp (1)
  • settings (59-59)
src/Menu/ExpandMacros.cpp (2)
  • GetComputerSettings (228-232)
  • GetComputerSettings (229-229)
src/MainWindow.hpp (1)
  • settings_computer (290-290)
src/Device/MultipleDevices.hpp (1)
  • elevation (89-89)
src/Plane/PlaneFileGlue.cpp (1)
src/Plane/PlaneFileGlue.hpp (1)
  • Read (17-17)
src/Device/MultipleDevices.cpp (3)
src/Device/Descriptor.cpp (10)
  • PutCrewMass (886-910)
  • PutCrewMass (887-887)
  • env (53-55)
  • env (53-53)
  • PutEmptyMass (912-936)
  • PutEmptyMass (913-913)
  • PutElevation (1093-1117)
  • PutElevation (1094-1094)
  • RequestElevation (1119-1143)
  • RequestElevation (1120-1120)
src/Device/Driver.cpp (8)
  • PutCrewMass (47-51)
  • PutCrewMass (48-48)
  • PutEmptyMass (53-57)
  • PutEmptyMass (54-54)
  • PutElevation (66-70)
  • PutElevation (67-67)
  • RequestElevation (72-76)
  • RequestElevation (73-73)
src/Device/Driver/LX/Settings.cpp (8)
  • PutCrewMass (213-233)
  • PutCrewMass (214-214)
  • PutEmptyMass (235-255)
  • PutEmptyMass (236-236)
  • PutElevation (270-282)
  • PutElevation (271-271)
  • RequestElevation (284-294)
  • RequestElevation (285-285)
src/ActionInterface.hpp (5)
src/Dialogs/Settings/dlgBasicSettings.cpp (2)
  • ballast_litres (81-86)
  • ballast_litres (81-81)
src/Engine/GlideSolvers/GlidePolar.hpp (5)
  • ballast_litres (287-289)
  • ballast_litres (295-297)
  • crew_mass (541-543)
  • empty_mass (515-517)
  • empty_mass (520-522)
src/Device/Descriptor.hpp (2)
  • crew_mass (547-547)
  • empty_mass (548-548)
src/Device/Driver.hpp (4)
  • crew_mass (91-91)
  • crew_mass (279-279)
  • empty_mass (99-99)
  • empty_mass (280-280)
src/Device/MultipleDevices.hpp (2)
  • crew_mass (79-79)
  • empty_mass (80-80)
src/lua/Settings.cpp (1)
src/MainWindow.hpp (1)
  • settings_computer (290-290)
src/Device/Port/TTYPort.cpp (1)
src/Device/Port/Port.hpp (1)
  • BaudRate (114-114)
src/Device/MultipleDevices.hpp (3)
src/Device/Descriptor.hpp (10)
  • crew_mass (547-547)
  • env (394-394)
  • env (403-403)
  • env (410-410)
  • env (418-418)
  • env (428-428)
  • env (550-550)
  • env (561-561)
  • empty_mass (548-548)
  • elevation (560-560)
src/Device/Driver.hpp (13)
  • crew_mass (91-91)
  • crew_mass (279-279)
  • env (48-48)
  • env (125-125)
  • env (140-140)
  • env (178-178)
  • env (271-271)
  • env (284-284)
  • env (286-286)
  • empty_mass (99-99)
  • empty_mass (280-280)
  • elevation (117-117)
  • elevation (283-283)
src/Device/Driver/LX/Internal.hpp (3)
  • crew_mass (367-367)
  • empty_mass (368-368)
  • elevation (372-372)
src/IGC/IGCFix.cpp (1)
src/IGC/IGCFix.hpp (1)
  • basic (95-95)
src/Device/Driver/LX/Settings.cpp (4)
src/Device/Driver/LX/Mode.cpp (2)
  • EnableNMEA (56-96)
  • EnableNMEA (57-57)
src/Device/Descriptor.cpp (8)
  • PutCrewMass (886-910)
  • PutCrewMass (887-887)
  • env (53-55)
  • env (53-53)
  • EnableNMEA (565-586)
  • EnableNMEA (566-566)
  • PutElevation (1093-1117)
  • PutElevation (1094-1094)
src/Device/MultipleDevices.cpp (4)
  • PutCrewMass (101-106)
  • PutCrewMass (102-102)
  • PutElevation (163-168)
  • PutElevation (164-164)
src/Device/Driver/LX/LXNAVVario.hpp (6)
  • SetPilotWeight (142-152)
  • SetPilotWeight (143-143)
  • SetEmptyWeight (158-168)
  • SetEmptyWeight (159-159)
  • SetElevation (118-124)
  • SetElevation (119-119)
src/Device/Driver.hpp (3)
src/Device/Descriptor.hpp (10)
  • crew_mass (547-547)
  • env (394-394)
  • env (403-403)
  • env (410-410)
  • env (418-418)
  • env (428-428)
  • env (550-550)
  • env (561-561)
  • elevation (560-560)
  • pres (558-559)
src/Device/Driver/LX/Internal.hpp (6)
  • crew_mass (367-367)
  • env (348-348)
  • env (350-350)
  • env (359-359)
  • elevation (372-372)
  • pres (369-370)
src/Device/MultipleDevices.hpp (7)
  • crew_mass (79-79)
  • env (66-66)
  • env (68-68)
  • env (82-82)
  • env (90-90)
  • elevation (89-89)
  • pres (88-88)
src/Dialogs/Settings/dlgBasicSettings.cpp (1)
src/Engine/GlideSolvers/GlidePolar.hpp (5)
  • _crew_mass (533-538)
  • _crew_mass (533-533)
  • ballast_litres (287-289)
  • ballast_litres (295-297)
  • overload (282-282)
src/InfoBoxes/Panel/AltitudeSetup.cpp (3)
src/Device/Descriptor.hpp (8)
  • env (394-394)
  • env (403-403)
  • env (410-410)
  • env (418-418)
  • env (428-428)
  • env (550-550)
  • env (561-561)
  • elevation (560-560)
src/Device/MultipleDevices.hpp (3)
  • elevation (89-89)
  • i (47-49)
  • i (47-47)
src/system/Sleep.h (1)
  • Sleep (14-23)
src/BallastDumpManager.cpp (2)
src/Dialogs/Settings/dlgBasicSettings.cpp (2)
  • ballast_litres (81-86)
  • ballast_litres (81-81)
src/Engine/GlideSolvers/GlidePolar.hpp (3)
  • ballast_litres (287-289)
  • ballast_litres (295-297)
  • max_ballast (546-548)
src/ActionInterface.cpp (5)
src/ActionInterface.hpp (1)
  • SetBallast (23-23)
src/Dialogs/Settings/dlgBasicSettings.cpp (5)
  • SetBallast (129-162)
  • SetBallast (130-130)
  • ballast_litres (81-86)
  • ballast_litres (81-81)
  • backend_components (77-79)
src/Engine/GlideSolvers/GlidePolar.hpp (7)
  • ballast_litres (287-289)
  • ballast_litres (295-297)
  • polar (581-583)
  • overload (282-282)
  • crew_mass (541-543)
  • empty_mass (515-517)
  • empty_mass (520-522)
src/Device/MultipleDevices.hpp (2)
  • crew_mass (79-79)
  • empty_mass (80-80)
src/Menu/ExpandMacros.cpp (2)
  • GetComputerSettings (228-232)
  • GetComputerSettings (229-229)
src/NMEA/ExternalSettings.cpp (1)
src/NMEA/ExternalSettings.hpp (4)
  • add (116-116)
  • other (127-128)
  • time (115-115)
  • a (240-240)
src/Device/Driver/LX/Mode.cpp (3)
src/Device/Descriptor.cpp (6)
  • OnCalculatedUpdate (1335-1347)
  • OnCalculatedUpdate (1336-1337)
  • env (53-55)
  • env (53-53)
  • PutMacCready (789-819)
  • PutMacCready (790-791)
src/Device/Driver/LX/Internal.hpp (12)
  • basic (385-386)
  • basic (442-445)
  • basic (450-453)
  • basic (458-461)
  • basic (462-465)
  • basic (466-469)
  • env (348-348)
  • env (350-350)
  • env (359-359)
  • env (373-373)
  • env (376-376)
  • env (378-378)
src/Device/Driver/LX/LXNAVVario.hpp (2)
  • SetPilotWeight (142-152)
  • SetPilotWeight (143-143)
src/Plane/PlaneGlue.cpp (2)
src/Plane/PlaneFileGlue.cpp (2)
  • ReadFile (134-149)
  • ReadFile (135-135)
src/Plane/PlaneFileGlue.hpp (1)
  • ReadFile (20-20)
src/NMEA/ExternalSettings.hpp (4)
src/Device/Descriptor.hpp (2)
  • elevation (560-560)
  • time (615-622)
src/Device/Driver.hpp (2)
  • elevation (117-117)
  • elevation (283-283)
src/Device/Driver/LX/Internal.hpp (1)
  • elevation (372-372)
src/Device/MultipleDevices.hpp (1)
  • elevation (89-89)
src/Engine/GlideSolvers/GlidePolar.hpp (2)
src/Dialogs/Settings/dlgBasicSettings.cpp (2)
  • ballast_litres (81-86)
  • ballast_litres (81-81)
src/Engine/GlideSolvers/GlidePolar.cpp (2)
  • Update (39-60)
  • Update (40-40)
src/Device/Driver/LX/Parser.cpp (3)
src/NMEA/Info.hpp (16)
  • value (393-397)
  • value (393-393)
  • value (403-411)
  • value (403-403)
  • value (425-429)
  • value (425-425)
  • value (435-443)
  • value (435-435)
  • value (458-461)
  • value (458-458)
  • value (468-471)
  • value (468-468)
  • value (478-481)
  • value (478-478)
  • value (491-495)
  • value (491-491)
src/NMEA/ExternalSettings.hpp (1)
  • a (240-240)
src/Device/Driver/LX/Mode.cpp (2)
  • lock (30-30)
  • lock (35-35)
src/Engine/GlideSolvers/GlidePolar.cpp (2)
src/Engine/GlideSolvers/GlidePolar.hpp (13)
  • litres (270-270)
  • assert (139-142)
  • assert (149-152)
  • assert (161-164)
  • assert (180-184)
  • assert (191-195)
  • assert (202-206)
  • assert (213-217)
  • ballast_litres (287-289)
  • ballast_litres (295-297)
  • fraction (276-276)
  • max_ballast (546-548)
  • overload (282-282)
src/BallastDumpManager.cpp (2)
  • Update (34-86)
  • Update (35-36)
🪛 GitHub Check: Codacy Static Code Analysis
build_quick_test.sh

[warning] 46-46: build_quick_test.sh#L46
Double quote to prevent globbing and word splitting.

check_screensize_usage.sh

[warning] 79-79: check_screensize_usage.sh#L79
total_files appears unused. Verify use (or export if used externally).

src/Device/Port/TTYPort.cpp

[warning] 27-27: src/Device/Port/TTYPort.cpp#L27
Include file: <sys/ioctl.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

build_all_configs.sh

[warning] 128-128: build_all_configs.sh#L128
TARGET_SPECIFIC_FLAGS appears unused. Verify use (or export if used externally).


[warning] 211-211: build_all_configs.sh#L211
Double quote to prevent globbing and word splitting.

src/Dialogs/Settings/dlgBasicSettings.cpp

[warning] 137-137: src/Dialogs/Settings/dlgBasicSettings.cpp#L137
C-style pointer casting

src/InfoBoxes/Panel/AltitudeSetup.cpp

[warning] 86-86: src/InfoBoxes/Panel/AltitudeSetup.cpp#L86
C-style pointer casting

src/Device/Driver/LX/Mode.cpp

[warning] 423-423: src/Device/Driver/LX/Mode.cpp#L423
The scope of the variable 'polar' can be reduced.

src/Device/Driver/LX/Internal.hpp

[warning] 18-18: src/Device/Driver/LX/Internal.hpp#L18
Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.

🪛 LanguageTool
FLARM_FTD014_SPECIFICATION_ANALYSIS.md

[style] ~95-~95: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...erify) - COMPCLASS - Competition class (need to verify) - NEWTASK - Task declaration co...

(REP_NEED_TO_VB)


[style] ~96-~96: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...) - NEWTASK - Task declaration command (need to verify) - ADDWP - Add waypoint command ...

(REP_NEED_TO_VB)


[style] ~97-~97: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...verify) - ADDWP - Add waypoint command (need to verify) ### Version Information **Spe...

(REP_NEED_TO_VB)

FLARM_PROTOCOL_ANALYSIS.md

[style] ~133-~133: Try using a synonym here to strengthen your wording.
Context: ...e.cpp:23-26` Issue: There's a TODO comment about FLARM declaration checks that men...

(COMMENT_REMARK)

BUILD_ALL_CONFIGS.md

[style] ~81-~81: This adverb was used twice in the sentence. Consider removing one of them or replacing them with a synonym.
Context: ...ccessful builds - failed_builds.txt - Only failed builds ## Examples ### Build o...

(ADVERB_REPETITION_PREMIUM)


[style] ~104-~104: ‘with success’ might be wordy. Consider a shorter alternative.
Context: ...he script provides a summary at the end with success/failure counts - Failed builds are logg...

(EN_WORDINESS_PREMIUM_WITH_SUCCESS)

FLARM_FTD014_COMPLIANCE_CHECKLIST.md

[style] ~4-~4: Some style guides suggest that commas should set off the year in a month-day-year date.
Context: ...ation-1.18.pdf Date: December 19, 2024 Version: 1.18 This checklist sho...

(MISSING_COMMA_AFTER_YEAR)

🪛 markdownlint-cli2 (0.18.1)
FLARM_FTD014_SPECIFICATION_ANALYSIS.md

50-50: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🪛 Shellcheck (0.11.0)
check_screensize_usage.sh

[warning] 79-79: total_files appears unused. Verify use (or export if used externally).

(SC2034)

build_all_configs.sh

[warning] 31-31: This redirection doesn't have a command. Move to its command (or use 'true' as no-op).

(SC2188)


[warning] 32-32: This redirection doesn't have a command. Move to its command (or use 'true' as no-op).

(SC2188)


[warning] 33-33: This redirection doesn't have a command. Move to its command (or use 'true' as no-op).

(SC2188)


[warning] 128-128: TARGET_SPECIFIC_FLAGS appears unused. Verify use (or export if used externally).

(SC2034)


[warning] 192-192: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 197-197: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 212-212: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 220-220: Declare and assign separately to avoid masking return values.

(SC2155)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: build (macos-14, MACOS, XCSoar, bin, XCSoar, false)
  • GitHub Check: build (ubuntu-22.04, PC, XCSoar, bin, XCSoar, .exe, true, debian:bookworm-slim)
  • GitHub Check: build (ubuntu-22.04, WIN64, XCSoar, bin, XCSoar, .exe, true, debian:bookworm-slim)
  • GitHub Check: build (ubuntu-22.04, ANDROID_BUNDLE, XCSoar, bin, XCSoar, .apk, false, r26d, debian:bookworm-slim)
  • GitHub Check: build (ubuntu-22.04, ANDROID, XCSoar, bin, XCSoar, .apk, true, r26d, debian:bookworm-slim)
  • GitHub Check: build (ubuntu-22.04, KOBO, KoboRoot, KoboRoot, .tgz, true, debian:bookworm-slim)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: build (macos-14, IOS64, XCSoar, bin, XCSoar, false)
  • GitHub Check: build (macos-14, MACOS, XCSoar, bin, XCSoar, false)
  • GitHub Check: build (ubuntu-22.04, WIN64, XCSoar, bin, XCSoar, .exe, true, debian:bookworm-slim)
  • GitHub Check: build (ubuntu-22.04, PC, XCSoar, bin, XCSoar, .exe, true, debian:bookworm-slim)
  • GitHub Check: build (ubuntu-22.04, KOBO, KoboRoot, KoboRoot, .tgz, true, debian:bookworm-slim)
  • GitHub Check: build (ubuntu-22.04, UNIX, xcsoar_7.44_amd64, xcsoar_, .deb, true, debian:bookworm-slim)
  • GitHub Check: Codacy Static Code Analysis

Comment on lines +1 to +2
alias unix='cd ~/git-xcsoar/XCSoar && make -j16 USE_CCACHE=y TARGET=UNIX && ./output/UNIX/bin/xcsoar $@'
alias wayland='cd ~/git-xcsoar/XCSoar && make -j16 USE_CCACHE=y TARGET=WAYLAND && ./output/WAYLAND/bin/xcsoar $@'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove developer-specific configuration and duplicate file.

This file has two issues:

  1. Hardcoded developer-specific paths: The aliases contain paths (~/git-xcsoar/XCSoar) specific to your environment that won't work for other contributors.

  2. Duplicate file: This file duplicates the content of bash_aliases (without the dot prefix). Only one should exist, and .bash_aliases is the more conventional naming.

Please remove both alias files from the PR and keep them in your local environment. If you want to share these patterns with other developers, consider documenting them in developer documentation instead of committing personal configuration files.

🤖 Prompt for AI Agents
In .bash_aliases (lines 1-2) the file contains developer-specific hardcoded
paths and duplicates the non-dot bash_aliases file; remove both alias files from
the branch/PR (delete the committed .bash_aliases and the duplicate
bash_aliases), keep the aliases only in your local environment, and if you want
to share them add a short snippet in project developer documentation instead of
committing personal dotfiles; also ensure these files are not re-added by
updating the repo ignore rules or excluding them from commits.

Comment on lines +1 to +2
alias unix='cd ~/git-xcsoar/XCSoar && make -j16 USE_CCACHE=y TARGET=UNIX && ./output/UNIX/bin/xcsoar'
alias wayland='cd ~/git-xcsoar/XCSoar && make -j16 USE_CCACHE=y TARGET=WAYLAND && ./output/WAYLAND/bin/xcsoar'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove developer-specific configuration from the repository.

These aliases contain hardcoded paths (~/git-xcsoar/XCSoar) that are specific to your development environment and will not work for other contributors. Developer-specific configuration files should not be committed to the repository.

Consider one of the following approaches:

  • Remove this file entirely and keep it in your local environment
  • Document the alias pattern in developer documentation for others to adapt
  • Use environment variables instead of hardcoded paths (e.g., ${XCSOAR_ROOT:-~/git-xcsoar/XCSoar})

Note: This file also appears to be duplicated as .bash_aliases (with a dot prefix).

🤖 Prompt for AI Agents
In bash_aliases around lines 1-2 the file contains developer-specific hardcoded
paths; remove or replace them: either delete this file from the repo and add it
to .gitignore (keeping a local copy), or replace the hardcoded path with an
environment-variable-based pattern like use ${XCSOAR_ROOT:-~/git-xcsoar/XCSoar}
in the alias so others can override it, and add a short note to developer docs
describing the alias pattern; also remove the duplicate (or consolidate) so only
the canonical .bash_aliases remains in the repo.


# With flags
for flags in "${TEST_FLAGS[@]}"; do
if make TARGET="$target" $flags clean all > /dev/null 2>&1; then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Quote the variable to prevent word splitting.

The $flags variable should be quoted to prevent potential issues with word splitting and globbing, as indicated by the static analysis tool.

Apply this diff:

-        if make TARGET="$target" $flags clean all > /dev/null 2>&1; then
+        if make TARGET="$target" "$flags" clean all > /dev/null 2>&1; then

However, note that in this specific case, $flags is intentionally unquoted because it contains multiple make variables that need to be split (e.g., "DEBUG=n LTO=y"). If you quote it, make will receive a single argument instead of separate variables. The current implementation is actually correct for this use case. You may want to add a shellcheck disable comment to suppress the warning:

     # With flags
     for flags in "${TEST_FLAGS[@]}"; do
+        # shellcheck disable=SC2086 - intentional word splitting for make flags
         if make TARGET="$target" $flags clean all > /dev/null 2>&1; then
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if make TARGET="$target" $flags clean all > /dev/null 2>&1; then
# With flags
for flags in "${TEST_FLAGS[@]}"; do
# shellcheck disable=SC2086 - intentional word splitting for make flags
if make TARGET="$target" $flags clean all > /dev/null 2>&1; then
🧰 Tools
🪛 GitHub Check: Codacy Static Code Analysis

[warning] 46-46: build_quick_test.sh#L46
Double quote to prevent globbing and word splitting.

🤖 Prompt for AI Agents
In build_quick_test.sh around line 46, the static analyzer flagged unquoted
$flags in the make invocation; leave $flags unquoted because it must expand into
multiple make variable assignments (e.g., "DEBUG=n LTO=y"), and to silence the
warning add a ShellCheck disable comment directly above the if line (e.g., a
comment disabling SC2086) with a short rationale that $flags is intentionally
unquoted to allow word-splitting for make variables.

echo "=========================================================="
echo ""

total_files=0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove unused variable declaration.

The variable total_files is initialized but never used in the script. Either remove this line or integrate the variable into the output logic if it was intended for reporting.

-total_files=0
 for pattern in "${PATTERNS[@]}"; do
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
total_files=0
for pattern in "${PATTERNS[@]}"; do
🧰 Tools
🪛 GitHub Check: Codacy Static Code Analysis

[warning] 79-79: check_screensize_usage.sh#L79
total_files appears unused. Verify use (or export if used externally).

🪛 Shellcheck (0.11.0)

[warning] 79-79: total_files appears unused. Verify use (or export if used externally).

(SC2034)

🤖 Prompt for AI Agents
In check_screensize_usage.sh around line 79, the variable `total_files` is
declared but never used; remove this unused declaration to clean up the script,
or if it was intended to report the number of files, initialize and increment
`total_files` where files are discovered and include it in the script's final
output/report so the variable is actually referenced.

Comment on lines +1 to +5
#!/bin/bash

set -e
echo "hello world"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove debug artifact from the PR.

This script appears to be a test/debug artifact with no production purpose. It only echoes "hello world" and is not referenced by any other files in the codebase.

Please remove this file from the PR.

🤖 Prompt for AI Agents
In foo.bash lines 1-5 the file is a debug/test artifact that only echoes "hello
world" and is unused; remove it from the PR by deleting the file from the branch
(e.g., run git rm foo.bash && git commit -m "remove debug artifact: foo.bash"
and push) or, if already committed in a feature branch, remove it from the
commit history (interactive rebase or git reset + recommit) so the file is no
longer present in the PR.

Comment on lines +53 to +55
const double max_ballast = glide_polar.GetBallastRatio() > 0
? glide_polar.GetBallastRatio() * glide_polar.GetReferenceMass()
: 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use GetMaxBallast() instead of manual calculation.

The GlidePolar class provides GetMaxBallast() (see src/Engine/GlideSolvers/GlidePolar.hpp lines 545-547), which returns the max_ballast member directly. The manual calculation here may produce inconsistent results if max_ballast is set independently from ballast_ratio * reference_mass.

-  // Calculate max ballast to determine dump rate
-  const double max_ballast = glide_polar.GetBallastRatio() > 0 
-    ? glide_polar.GetBallastRatio() * glide_polar.GetReferenceMass() 
-    : 0;
+  // Get max ballast to determine dump rate
+  const double max_ballast = glide_polar.GetMaxBallast();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const double max_ballast = glide_polar.GetBallastRatio() > 0
? glide_polar.GetBallastRatio() * glide_polar.GetReferenceMass()
: 0;
// Get max ballast to determine dump rate
const double max_ballast = glide_polar.GetMaxBallast();
🤖 Prompt for AI Agents
In src/BallastDumpManager.cpp around lines 53 to 55, the code computes
max_ballast manually using GetBallastRatio() * GetReferenceMass(), which can be
inconsistent with the GlidePolar internal max_ballast; replace the manual
calculation with a call to glide_polar.GetMaxBallast() and assign that value
(ensuring the variable type remains double) so the code uses the canonical
max_ballast stored in GlidePolar.

Comment on lines +71 to +83
} else {
// No max ballast - dump directly from litres (assume 1L per second as fallback)
ballast_litres -= ToFloatSeconds(dt);

// Check if the plane is dry now
if (ballast_litres < 0) {
Stop();
glide_polar.SetBallastLitres(0);
return false;
}

// Set new ballast
glide_polar.SetBallastLitres(ballast_litres);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Inconsistent handling of dump_time in fallback path.

In the fraction-based path, the dump rate respects dump_time (ballast_fraction -= ToFloatSeconds(dt) / dump_time). However, in the fallback path, dump_time is ignored and a fixed 1 L/second rate is assumed. This inconsistency means the dump time configuration has no effect when max_ballast is zero.

Consider using dump_time consistently:

   } else {
-    // No max ballast - dump directly from litres (assume 1L per second as fallback)
-    ballast_litres -= ToFloatSeconds(dt);
+    // No max ballast - dump directly from litres using dump_time
+    // dump_time represents total seconds to dump full ballast, 
+    // but without max_ballast we need a reference. Using current ballast as reference:
+    if (ballast_litres > 0) {
+      ballast_litres -= ballast_litres * ToFloatSeconds(dt) / dump_time;
+    }

Alternatively, clarify the intended behavior in documentation if the fixed 1 L/s rate is intentional.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} else {
// No max ballast - dump directly from litres (assume 1L per second as fallback)
ballast_litres -= ToFloatSeconds(dt);
// Check if the plane is dry now
if (ballast_litres < 0) {
Stop();
glide_polar.SetBallastLitres(0);
return false;
}
// Set new ballast
glide_polar.SetBallastLitres(ballast_litres);
} else {
// No max ballast - dump directly from litres using dump_time
// dump_time represents total seconds to dump full ballast,
// but without max_ballast we need a reference. Using current ballast as reference:
if (ballast_litres > 0) {
ballast_litres -= ballast_litres * ToFloatSeconds(dt) / dump_time;
}
// Check if the plane is dry now
if (ballast_litres < 0) {
Stop();
glide_polar.SetBallastLitres(0);
return false;
}
// Set new ballast
glide_polar.SetBallastLitres(ballast_litres);
🤖 Prompt for AI Agents
In src/BallastDumpManager.cpp around lines 71-83, the fallback path subtracts a
fixed 1 L/s ignoring dump_time; change it to respect dump_time by computing a
litres-per-second rate from the current ballast and dump_time (e.g.,
litres_per_sec = current_ballast_litres / dump_time) and subtracting
ToFloatSeconds(dt) * litres_per_sec, with a safe fallback to 1 L/s only when
dump_time is zero or invalid; ensure you still stop and clamp to zero as
currently done.

Comment on lines +156 to +191
if (speed == B0 && BaudRate > 230400) {
#ifdef __linux__
struct serial_struct serinfo;
if (ioctl(tty.Get(), TIOCGSERIAL, &serinfo) < 0)
throw MakeErrno("TIOCGSERIAL failed");

/* Set standard termios attributes first */
struct termios attr;
if (!tty.GetAttr(attr))
throw MakeErrno("tcgetattr() failed");

attr.c_iflag &= ~(BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
attr.c_iflag |= (IGNPAR | IGNBRK);
attr.c_oflag &= ~OPOST;
attr.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
attr.c_cflag &= ~(CSIZE | PARENB | CRTSCTS);
attr.c_cflag |= (CS8 | CLOCAL);
attr.c_cc[VMIN] = 0;
attr.c_cc[VTIME] = 1;
cfsetospeed(&attr, B38400); /* Use a standard speed as base */
cfsetispeed(&attr, B38400);
if (!tty.SetAttr(TCSANOW, attr))
throw MakeErrno("tcsetattr() failed");

/* Set custom baud rate using TIOCSSERIAL */
serinfo.flags |= ASYNC_SPD_CUST;
serinfo.custom_divisor = (serinfo.baud_base + (BaudRate / 2)) / BaudRate;
if (serinfo.custom_divisor < 1)
serinfo.custom_divisor = 1;
if (ioctl(tty.Get(), TIOCSSERIAL, &serinfo) < 0)
throw MakeErrno("TIOCSSERIAL failed");
return;
#else
throw std::runtime_error("Custom baud rates above 230400 not supported on this platform");
#endif
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add validation for baud_base before computing divisor.

If serinfo.baud_base is zero or unexpectedly small (e.g., some virtual serial devices), the divisor calculation could produce incorrect results or the actual baud rate would be far from the requested value.

     if (ioctl(tty.Get(), TIOCGSERIAL, &serinfo) < 0)
       throw MakeErrno("TIOCGSERIAL failed");
 
+    if (serinfo.baud_base <= 0)
+      throw std::runtime_error("Serial port does not support custom baud rates (baud_base is 0)");
+
     /* Set standard termios attributes first */
🤖 Prompt for AI Agents
In src/Device/Port/TTYPort.cpp around lines 156-191, validate serinfo.baud_base
before computing custom_divisor: check if serinfo.baud_base is zero or
unreasonably small and handle it instead of using it in the divisor calculation.
If baud_base is 0 (or below a sane threshold) either throw a descriptive error
(MakeErrno or std::runtime_error) indicating custom baud rates are unsupported
for this device, or skip setting ASYNC_SPD_CUST and leave the port at the
standard base speed; do not perform the division when baud_base is zero to avoid
incorrect divisors or divide-by-zero. Ensure the chosen behavior returns/throws
before calling ioctl(TIOCSSERIAL).

Comment on lines +358 to +368
#ifdef __linux__
/* Check if using custom baud rate via TIOCSSERIAL */
struct serial_struct serinfo;
if (ioctl(tty.Get(), TIOCGSERIAL, &serinfo) == 0) {
if (serinfo.flags & ASYNC_SPD_CUST && serinfo.baud_base > 0) {
unsigned custom_baud = serinfo.baud_base / serinfo.custom_divisor;
if (custom_baud > 230400)
return custom_baud;
}
}
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard against division by zero when custom_divisor is zero.

If custom_divisor is zero (e.g., uninitialized or corrupted serial settings), line 363 will cause undefined behavior.

 #ifdef __linux__
   /* Check if using custom baud rate via TIOCSSERIAL */
   struct serial_struct serinfo;
   if (ioctl(tty.Get(), TIOCGSERIAL, &serinfo) == 0) {
-    if (serinfo.flags & ASYNC_SPD_CUST && serinfo.baud_base > 0) {
+    if ((serinfo.flags & ASYNC_SPD_CUST) && serinfo.baud_base > 0 && serinfo.custom_divisor > 0) {
       unsigned custom_baud = serinfo.baud_base / serinfo.custom_divisor;
       if (custom_baud > 230400)
         return custom_baud;
     }
   }
 #endif
🤖 Prompt for AI Agents
In src/Device/Port/TTYPort.cpp around lines 358 to 368, the code divides
serinfo.baud_base by serinfo.custom_divisor without checking for zero; add a
guard that ensures serinfo.custom_divisor != 0 (and typically > 0) before
performing the division and computing custom_baud, and if the divisor is zero
skip the custom baud calculation (or treat it as invalid) so no division by zero
can occur.

Comment on lines +145 to +151
if (SaveValueInteger(ALTOFF_ERROR, altoff_error) ||
SaveValueInteger(ALTOFF_QNH, altoff_qnh) ||
SaveValueInteger(ALTOFF_TAKEOFF, altoff_takeoff)) {
buffer.UnsafeFormat("%d,%d,%d", altoff_error, altoff_qnh, altoff_takeoff);
device.SendLXNAVVarioSetting("ALTOFF", buffer, env);
changed = true;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Potential bug: short-circuit evaluation may skip UI reads for unchanged fields.

The || operator short-circuits, so if SaveValueInteger(ALTOFF_ERROR, altoff_error) returns true, the other two SaveValueInteger calls won't execute. This means altoff_qnh and altoff_takeoff won't be updated from the UI before sending to the device.

Consider reading all values unconditionally:

-  if (SaveValueInteger(ALTOFF_ERROR, altoff_error) ||
-      SaveValueInteger(ALTOFF_QNH, altoff_qnh) ||
-      SaveValueInteger(ALTOFF_TAKEOFF, altoff_takeoff)) {
+  bool altoff_changed = SaveValueInteger(ALTOFF_ERROR, altoff_error);
+  altoff_changed |= SaveValueInteger(ALTOFF_QNH, altoff_qnh);
+  altoff_changed |= SaveValueInteger(ALTOFF_TAKEOFF, altoff_takeoff);
+  if (altoff_changed) {
     buffer.UnsafeFormat("%d,%d,%d", altoff_error, altoff_qnh, altoff_takeoff);
     device.SendLXNAVVarioSetting("ALTOFF", buffer, env);
     changed = true;
   }
🤖 Prompt for AI Agents
In src/Dialogs/Device/LX/LXNAVVarioConfigWidget.cpp around lines 145-151 the use
of the || operator causes short-circuiting so SaveValueInteger may not be called
for all fields; change the logic to call SaveValueInteger(ALTOFF_ERROR,
altoff_error), SaveValueInteger(ALTOFF_QNH, altoff_qnh) and
SaveValueInteger(ALTOFF_TAKEOFF, altoff_takeoff) unconditionally (assign each
result to a bool), then if any of those bools is true, format the buffer with
the now-updated altoff_error/altoff_qnh/altoff_takeoff values and call
device.SendLXNAVVarioSetting("ALTOFF", buffer, env) and set changed = true.

@lordfolken lordfolken marked this pull request as draft November 30, 2025 08:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant