Skip to content

GPS refactor & license text updates - #601

Merged
KenVanHoeylandt merged 8 commits into
mainfrom
gps-refactor
Jul 30, 2026
Merged

GPS refactor & license text updates#601
KenVanHoeylandt merged 8 commits into
mainfrom
gps-refactor

Conversation

@KenVanHoeylandt

@KenVanHoeylandt KenVanHoeylandt commented Jul 30, 2026

Copy link
Copy Markdown
Contributor
  • Split up gps-generic-module into:
    • gps-generic-module that contains only interfaces/configs/bindings (Apache license)
    • gps-meshtastic-module that contains an implementation (GPL license)
  • Update LICENSE.md for changes, but also added clarifications
  • Added licenses to directories where they were missing
  • Changed license of some test projects from GPL to Apache.

The code that was left behind was code that I wrote myself, so I'm
relicensing that to Apache
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The change separates generic GPS interfaces from the Meshtastic GPS implementation, adds module headers and build wiring, and starts both modules during boot. It introduces CAS message definitions and Meshtastic-specific logging identifiers. README, device-tree, license metadata, and repository license documentation are also updated.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main GPS module refactor and the broad license documentation updates.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch gps-refactor

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 9


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: be7b9b76-c057-4e2a-bfcc-7dfab93942aa

📥 Commits

Reviewing files that changed from the base of the PR and between c729e83 and dabcb49.

📒 Files selected for processing (31)
  • Drivers/gps-generic-module/CMakeLists.txt
  • Drivers/gps-generic-module/LICENSE-Apache-2.0.md
  • Drivers/gps-generic-module/README.md
  • Drivers/gps-generic-module/bindings/tactility,gps-generic.yaml
  • Drivers/gps-generic-module/include/gps_generic/module.h
  • Drivers/gps-generic-module/source/module.cpp
  • Drivers/gps-meshtastic-module/CMakeLists.txt
  • Drivers/gps-meshtastic-module/LICENSE-GPL-3.0.md
  • Drivers/gps-meshtastic-module/README.md
  • Drivers/gps-meshtastic-module/devicetree.yaml
  • Drivers/gps-meshtastic-module/include/gps_meshtastic/module.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/cas_messages.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/gps_response.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/init.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/probe.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/ublox.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/ublox_messages.h
  • Drivers/gps-meshtastic-module/source/gps_meshtastic.cpp
  • Drivers/gps-meshtastic-module/source/init.cpp
  • Drivers/gps-meshtastic-module/source/module.cpp
  • Drivers/gps-meshtastic-module/source/probe.cpp
  • Drivers/gps-meshtastic-module/source/ublox.cpp
  • LICENSE.md
  • Tactility/CMakeLists.txt
  • Tactility/Source/Tactility.cpp
  • Tests/SdkIntegration/LICENSE-Apache-2.0.md
  • Tests/Tactility/LICENSE-GPL-3.0.md
  • Tests/TactilityFreeRtos/LICENSE-Apache-2.0.md
  • Tests/TactilityKernel/LICENSE-Apache-2.0.md
  • Tests/crypt-module/LICENSE-Apache-2.0.md
  • Translations/LICENSE-Apache-2.0.md
💤 Files with no reviewable changes (1)
  • Drivers/gps-generic-module/CMakeLists.txt

Comment thread Drivers/gps-meshtastic-module/CMakeLists.txt Outdated
Comment thread Drivers/gps-meshtastic-module/README.md Outdated
Comment thread Drivers/gps-meshtastic-module/source/module.cpp
Comment thread LICENSE.md Outdated
Comment thread LICENSE.md Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 9


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: be7b9b76-c057-4e2a-bfcc-7dfab93942aa

📥 Commits

Reviewing files that changed from the base of the PR and between c729e83 and dabcb49.

📒 Files selected for processing (31)
  • Drivers/gps-generic-module/CMakeLists.txt
  • Drivers/gps-generic-module/LICENSE-Apache-2.0.md
  • Drivers/gps-generic-module/README.md
  • Drivers/gps-generic-module/bindings/tactility,gps-generic.yaml
  • Drivers/gps-generic-module/include/gps_generic/module.h
  • Drivers/gps-generic-module/source/module.cpp
  • Drivers/gps-meshtastic-module/CMakeLists.txt
  • Drivers/gps-meshtastic-module/LICENSE-GPL-3.0.md
  • Drivers/gps-meshtastic-module/README.md
  • Drivers/gps-meshtastic-module/devicetree.yaml
  • Drivers/gps-meshtastic-module/include/gps_meshtastic/module.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/cas_messages.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/gps_response.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/init.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/probe.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/ublox.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/ublox_messages.h
  • Drivers/gps-meshtastic-module/source/gps_meshtastic.cpp
  • Drivers/gps-meshtastic-module/source/init.cpp
  • Drivers/gps-meshtastic-module/source/module.cpp
  • Drivers/gps-meshtastic-module/source/probe.cpp
  • Drivers/gps-meshtastic-module/source/ublox.cpp
  • LICENSE.md
  • Tactility/CMakeLists.txt
  • Tactility/Source/Tactility.cpp
  • Tests/SdkIntegration/LICENSE-Apache-2.0.md
  • Tests/Tactility/LICENSE-GPL-3.0.md
  • Tests/TactilityFreeRtos/LICENSE-Apache-2.0.md
  • Tests/TactilityKernel/LICENSE-Apache-2.0.md
  • Tests/crypt-module/LICENSE-Apache-2.0.md
  • Translations/LICENSE-Apache-2.0.md
💤 Files with no reviewable changes (1)
  • Drivers/gps-generic-module/CMakeLists.txt
🛑 Comments failed to post (4)
Drivers/gps-meshtastic-module/private/gps_generic/private/ublox_messages.h (1)

218-228: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Align the GSA payload with its initialization intent.

Line 223 configures a zero UART1 rate, so this disables GSA, while init_ublox_789 sends it as “enable NMEA GSA”. Enable the UART1 rate or update the initialization behavior/logging to intentionally disable it.

Drivers/gps-meshtastic-module/source/ublox.cpp (3)

119-190: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm the return type/semantics of uart_controller_read_bytes
rg -n "uart_controller_read_bytes" --type=cpp -g '*.h' -B2 -A5

Repository: TactilityProject/Tactility

Length of output: 164


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== tracked files matching ublox / uart_controller_read_bytes =="
git ls-files | rg '(^|/)(ublox\.(cpp|hpp|h)|.*)' || true

echo "== broad search uart_controller_read_bytes =="
rg -n "uart_controller_read_bytes" . || true

echo "== locate ublox.cpp =="
fd -a 'ublox\.cpp$' . || true

echo "== list source files in Drivers/gps-meshtastic-module/source if present =="
fd . Drivers/gps-meshtastic-module/source 2>/dev/null | sed -n '1,120p' || true

Repository: TactilityProject/Tactility

Length of output: 50382


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== ublox.cpp relevant sections =="
sed -n '1,230p' Drivers/gps-meshtastic-module/source/ublox.cpp
sed -n '230,520p' Drivers/gps-meshtastic-module/source/ublox.cpp

echo "== declarations/usages of read_chars/readbytes/read_bytes/read_bytes_return-like names =="
rg -n "uart_controller_.*(read|write|available)|read_bytes|read_chars|size_t|auto .*read" Drivers/gps-meshtastic-module/source Drivers/gps-meshtastic-module/include Drivers -g '*.{h,hpp,cpp,c}' || true

Repository: TactilityProject/Tactility

Length of output: 50382


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== uart_controller declarations =="
fd -a 'uart_controller\.(h|hpp|cpp|c)$' . | sed -n '1,40p'
rg -n "uart_controller_get_available|uart_controller_read_byte|uart_controller_write_bytes|uart_controller_flush_input|typedef.*uart_controller|error_t.*uart_controller" Drivers include . -g '*.{h,hpp,c,cpp}' --glob '!**/.git/**' --glob '!**/build/**' | sed -n '1,220p'

echo "== gps meshtastic uart read/write/call patterns =="
rg -n "uart_controller_(read|write|get_available|flush_input)|get_ack\\(" Drivers/gps-meshtastic-module -g '*.{h,hpp,c,cpp}'

Repository: TactilityProject/Tactility

Length of output: 22309


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== read_bytes implementation =="
sed -n '1,45p' TactilityKernel/source/drivers/uart_controller.cpp

echo "== read_until success return path around bytes_read =="
sed -n '35,55p' TactilityKernel/source/drivers/uart_controller.cpp

echo "== read_until declaration =="
sed -n '175,188p' TactilityKernel/include/tactility/drivers/uart_controller.h

Repository: TactilityProject/Tactility

Length of output: 3579


Assign and check uart_controller_read_bytes’s returned status.

uart_controller_read_bytes() returns an error_t, but the return here is ignored, so read_bytes remains the stale 0U and the success check becomes a no-op. Capture the returned error code and reject the UBX frame path when the read did not complete successfully.


192-249: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

ublox_info.extensionNo is never reset at the start of probe() — risk of out-of-bounds write on repeated calls.

ublox_info is static, so its state persists across invocations of probe(). extensionNo is only ever incremented (lines 246-248) and bounded via if (ublox_info.extensionNo > 9) break;, but never reset to 0 at the top of probe(). If probe() runs a second time within the same power cycle (driver restart/retry) after a prior call left extensionNo at 10, the next accumulation loop iteration will write to ublox_info.extension[10][...], one past the bound of char extension[10][30], corrupting the adjacent protocol_version field (or beyond).

🔧 Suggested fix
 GpsModel probe(Device* uart) {
     LOG_I(TAG, "Probing for U-blox");
+    ublox_info.extensionNo = 0;
📝 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.

static struct UbloxGnssModelInfo {
    char swVersion[30];
    char hwVersion[10];
    uint8_t extensionNo;
    char extension[10][30];
    uint8_t protocol_version;
} ublox_info;

GpsModel probe(Device* uart) {
    LOG_I(TAG, "Probing for U-blox");
    ublox_info.extensionNo = 0;

    uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00};
    checksum(cfg_rate, sizeof(cfg_rate));
    uart_controller_flush_input(uart);
    uart_controller_write_bytes(uart, cfg_rate, sizeof(cfg_rate), 500 / portTICK_PERIOD_MS);
    // Check that the returned response class and message ID are correct
    GpsResponse response = get_ack(uart, 0x06, 0x08, 750);
    if (response == GpsResponse::None) {
        LOG_W(TAG, "No GNSS Module");
        return GpsModel::GPS_MODEL_UNKNOWN;
    } else if (response == GpsResponse::FrameErrors) {
        LOG_W(TAG, "UBlox Frame Errors");
    }

    uint8_t buffer[256];
    memset(buffer, 0, sizeof(buffer));
    uint8_t message_monver[8] = {
        0xB5, 0x62, // Sync message for UBX protocol
        0x0A, 0x04, // Message class and ID (UBX-MON-VER)
        0x00, 0x00, // Length of payload (we're asking for an answer, so no payload)
        0x00, 0x00 // Checksum
    };
    //  Get Ublox gnss module hardware and software info
    checksum(message_monver, sizeof(message_monver));
    uart_controller_flush_input(uart);
    uart_controller_write_bytes(uart, message_monver, sizeof(message_monver), 500);

    uint16_t ack_response_len = get_ack(uart, buffer, sizeof(buffer), 0x0A, 0x04, 1200);
    if (ack_response_len) {
        uint16_t position = 0;
        for (char& i: ublox_info.swVersion) {
            i = buffer[position];
            position++;
        }
        for (char& i: ublox_info.hwVersion) {
            i = buffer[position];
            position++;
        }

        while (ack_response_len >= position + 30) {
            for (int i = 0; i < 30; i++) {
                ublox_info.extension[ublox_info.extensionNo][i] = buffer[position];
                position++;
            }
            ublox_info.extensionNo++;
            if (ublox_info.extensionNo > 9)
                break;
        }

226-227: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm expected units (ticks vs ms) for uart_controller_write_bytes's timeout parameter
rg -n "uart_controller_write_bytes" --type=cpp -g '*.h' -B2 -A5

Repository: TactilityProject/Tactility

Length of output: 164


🏁 Script executed:

#!/bin/bash
set -u

echo "== locate ublox.cpp and related files =="
git ls-files | rg '(^|/)ublox\.cpp$|((uart_controller|Uart|UART).*\.(h|c|cxx|cpp)|\bdrivers?|Drivers)' | sed -n '1,200p'

echo
echo "== search for uart_controller_write_bytes across repo =="
rg -n "uart_controller_write_bytes|UART_CONTROLLER|uart_controller" . -g '!build' -g '!node_modules' -g '!dist' | sed -n '1,240p'

echo
echo "== outline ublox if present =="
file="$(git ls-files | rg '(^|/)ublox\.cpp$' | head -n1)"
if [ -n "${file:-}" ]; then
  echo "FILE=$file"
  wc -l "$file"
  ast-grep outline "$file" --view compact | sed -n '1,200p'
fi

Repository: TactilityProject/Tactility

Length of output: 28818


🏁 Script executed:

#!/bin/bash
set -u

echo "== ublox.cpp relevant sections =="
sed -n '1,80p;190,235p;300,340p;350,370p;455,472p' Drivers/gps-meshtastic-module/source/ublox.cpp

echo
echo "== uart_controller signature/implementation and type constants =="
sed -n '1,220p' TactilityKernel/include/tactility/drivers/uart_controller.h
sed -n '1,320p' TactilityKernel/source/drivers/uart_controller.cpp
rg -n "portTICK_PERIOD_MS|typedef.*TickType|struct TickType|TickType_t" --glob '*.{h,c,cpp}' --glob '!Drivers/gps-meshtastic-module/source/*' -B1 -A1 | sed -n '1,160p'

echo
echo "== all direct millis values passed to uart_controller write calls in the gps module =="
python3 - <<'PY'
from pathlib import Path
p = Path("Drivers/gps-meshtastic-module/source/ublox.cpp")
for i,line in enumerate(p.read_text().split("\n"),1):
    if "uart_controller_write_bytes" in line:
        print(f"{i}: {line.strip()}")
PY

Repository: TactilityProject/Tactility

Length of output: 19839


🏁 Script executed:

#!/bin/bash
set -u

echo "== esp32 uart write implementation around write_bytes =="
sed -n '180,340p' Platforms/platform-esp32/source/drivers/esp32_uart.cpp

echo
echo "== portTICK_PERIOD_MS definition references =="
rg -n "portTICK_PERIOD_MS|pdMS_TO_TICKS|pdTICKS_TO_MS|CONFIG_FREERTOS_HZ" . -g '!node_modules' -g '!build' -g '!dist' | sed -n '1,200p'

Repository: TactilityProject/Tactility

Length of output: 28692


🏁 Script executed:

#!/bin/bash
set -u

echo "== esp32 uart write_bytes definition =="
rg -n "write_bytes|uart_write_bytes|write_byte|xQueueSend|pdMS_TO_TICKS|TickType_t timeout" Platforms/platform-esp32/source/drivers/esp32_uart.cpp -B3 -A3

echo
echo "== targeted lines 1-180 esp32_uart.cpp =="
sed -n '1,180p' Platforms/platform-esp32/source/drivers/esp32_uart.cpp

Repository: TactilityProject/Tactility

Length of output: 8070


Pass tick values to uart_controller_write_bytes.

uart_controller_* timeout parameters are TickType_t, and the ESP32 driver forwards them to uart_wait_tx_done. Keep these raw millisecond values consistent with the other calls in this file, but pass 500 / portTICK_PERIOD_MS here and 2000 / portTICK_PERIOD_MS for the SAVE call so the timeout duration is preserved.

Also applies to: 466-467

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
Drivers/gps-meshtastic-module/source/module.cpp (1)

14-16: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Define the Meshtastic module symbol here.

Changing .name does not change the exported symbol: this file still defines gps_generic_module, while the Meshtastic header, driver owner, and startup path use gps_meshtastic_module. This can duplicate the generic module and leave the Meshtastic module undefined or unregistered.

Proposed fix
-Module gps_generic_module = {
+Module gps_meshtastic_module = {

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 16f70c30-da64-4c54-a437-9208ee5ba519

📥 Commits

Reviewing files that changed from the base of the PR and between 1039440 and df46fd9.

📒 Files selected for processing (14)
  • Drivers/gps-meshtastic-module/README.md
  • Drivers/gps-meshtastic-module/include/gps_meshtastic/module.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/cas_messages.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/gps_response.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/init.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/probe.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/ublox.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/ublox_messages.h
  • Drivers/gps-meshtastic-module/source/gps_meshtastic.cpp
  • Drivers/gps-meshtastic-module/source/init.cpp
  • Drivers/gps-meshtastic-module/source/module.cpp
  • Drivers/gps-meshtastic-module/source/probe.cpp
  • Drivers/gps-meshtastic-module/source/ublox.cpp
  • LICENSE.md
🚧 Files skipped from review as they are similar to previous changes (10)
  • Drivers/gps-meshtastic-module/private/gps_generic/private/ublox_messages.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/ublox.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/gps_response.h
  • Drivers/gps-meshtastic-module/source/ublox.cpp
  • Drivers/gps-meshtastic-module/source/init.cpp
  • Drivers/gps-meshtastic-module/source/gps_meshtastic.cpp
  • Drivers/gps-meshtastic-module/private/gps_generic/private/init.h
  • Drivers/gps-meshtastic-module/private/gps_generic/private/cas_messages.h
  • Drivers/gps-meshtastic-module/source/probe.cpp
  • Drivers/gps-meshtastic-module/private/gps_generic/private/probe.h

@KenVanHoeylandt
KenVanHoeylandt merged commit 1cb6614 into main Jul 30, 2026
61 checks passed
@KenVanHoeylandt
KenVanHoeylandt deleted the gps-refactor branch July 30, 2026 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant