Shearwater: restore ID_MODEL as model source, expose FWID for consumer sub-model refinement - #125
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
The new dc_event_devinfo_t.devinfo_hw_id field is not guaranteed to be initialized to 0 for many existing DC_EVENT_DEVINFO emitters, which can expose undefined/garbage values to consumers.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR adjusts Shearwater model identification to treat ID_MODEL as the authoritative coarse model source (aligning with upstream libdc), while exposing the raw Shearwater hardware identifier (FWID / ID_HARDWARE) to consumers for best-effort sub-model refinement (e.g., Petrel 1 vs Petrel 2). It also adds a generic descriptor-lookup helper to let consumers map (family, hw_id) to a more specific dc_descriptor_t when available.
Changes:
- Shearwater Petrel live download now reads
ID_MODELdirectly; FWID is read best-effort and exposed viaDC_EVENT_DEVINFO. dc_event_devinfo_tgains a newdevinfo_hw_idfield (0 when unknown/not available).- Descriptor API gains
dc_descriptor_find_by_hw_id()and a hardware-id mapping table (initially for Shearwater Petrel family).
File summaries
| File | Description |
|---|---|
| src/shearwater_predator.c | Zero-initialize devinfo and explicitly emit devinfo_hw_id = 0 for the dump path. |
| src/shearwater_predator_parser.c | Clarifies that stored logs carry the coarse Product-Version, not FWID, so sub-model refinement isn’t possible on re-parse. |
| src/shearwater_petrel.c | Reads ID_MODEL directly; reads FWID best-effort and emits it via DC_EVENT_DEVINFO; updates timesync model check. |
| src/shearwater_common.h | Documents PETREL2 sharing the same ID_MODEL value as PETREL; removes shearwater_common_get_model declaration. |
| src/shearwater_common.c | Removes shearwater_common_get_model() implementation. |
| src/descriptor.c | Adds g_hw_id_map[] and implements dc_descriptor_find_by_hw_id(). |
| include/libdivecomputer/device.h | Adds devinfo_hw_id to dc_event_devinfo_t with documentation. |
| include/libdivecomputer/descriptor.h | Declares and documents dc_descriptor_find_by_hw_id(). |
Review details
- Files reviewed: 8/8 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| * with the device's hardware type identifier (e.g. Shearwater FWID | ||
| * from RDBI 0x8050). It supplements the coarse model field for | ||
| * consumer-side sub-model differentiation. Consumers that do not use | ||
| * this field are unaffected; the model field remains authoritative. */ | ||
| unsigned int devinfo_hw_id; |
There was a problem hiding this comment.
🟡 Changes recommended
The new public API dc_descriptor_find_by_hw_id is not added to src/libdivecomputer.symbols, so it may not be exported on builds that rely on the export list.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 45/45 changed files
- Comments generated: 1
- Review effort level: Lite
| dc_descriptor_t * | ||
| dc_descriptor_find_by_hw_id (dc_family_t family, unsigned int hw_id); |
There was a problem hiding this comment.
🟢 Approval recommended
The changes are consistent with the stated two-layer design, and the new hw_id field is safely initialized across drivers with a best-effort Shearwater FWID exposure path.
Review details
Suppressed comments (1)
include/libdivecomputer/device.h:61
- The PR description refers to this new field as
devinfo_hw_id, but the public API introduces it asdc_event_devinfo_t::hw_id. To avoid consumer confusion (and mismatched downstream patches), please align the PR description and any related docs/examples to the actual exported name (hw_id) or rename consistently across the API ifdevinfo_hw_idis intended.
/* Generic hardware identifier, 0 = unknown/not available.
* On live download from devices that support it, this is populated
* with the device's hardware type identifier (e.g. Shearwater FWID
* from RDBI 0x8050). It supplements the coarse model field for
* consumer-side sub-model differentiation. Consumers that do not use
* this field are unaffected; the model field remains authoritative. */
unsigned int hw_id;
- Files reviewed: 46/46 changed files
- Comments generated: 0 new
- Review effort level: Lite
There was a problem hiding this comment.
🟡 Changes recommended
Resolve the public field naming mismatch and prevent uninitialized hardware-ID reads.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (1)
include/libdivecomputer/device.h:61
- The public member added here is named
hw_id, but the PR contract specifiesdevinfo_hw_id. Since the companion consumer is supposed to compile against this API, resolve the naming mismatch before merging by keeping the exported member name and consumer contract consistent.
unsigned int hw_id;
- Files reviewed: 11/11 changed files
- Comments generated: 1
- Review effort level: Lite
There was a problem hiding this comment.
🔵 Needs a closer look
Align the public hardware-ID member name with the advertised API and document it in the installed man page.
Review details
Suppressed comments (2)
Previously missed (1) — in code that hasn't changed since the last review.
include/libdivecomputer/device.h:61
- The public DC_EVENT_DEVINFO man page still documents only model, firmware, and serial, so consumers using the installed API documentation will not discover the newly added hw_id field. Update doc/man/dc_device_set_events.3 together with this public-struct change.
include/libdivecomputer/device.h:61
- The PR description specifies the public member as
devinfo_hw_id, but this header exports it ashw_id. A consumer following the advertised contract (for example,devinfo->devinfo_hw_id) will not compile against this API; please either use the documented member name consistently or update the PR contract and all consumers before merging.
unsigned int hw_id;
- Files reviewed: 11/11 changed files
- Comments generated: 0 new
- Review effort level: Lite
0c83517 to
2ce8815
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Align the public field name with the stated contract and document its semantics in the installed API documentation.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (1)
include/libdivecomputer/device.h:61
- The PR description advertises the new public member as
devinfo_hw_id, but this header exposes it ashw_id. A consumer following the stated companion-PR contract will fail to compile against this API; please use one member name consistently or update the contract before merging.
/* Generic hardware identifier, 0 = unknown/not available.
* On live download from devices that support it, this is populated
* with the device's hardware type identifier (e.g. Shearwater FWID
* from RDBI 0x8050). It supplements the coarse model field for
* consumer-side sub-model differentiation. Consumers that do not use
* this field are unaffected; the model field remains authoritative. */
unsigned int hw_id;
- Files reviewed: 11/11 changed files
- Comments generated: 1
- Review effort level: Lite
| /* Generic hardware identifier, 0 = unknown/not available. | ||
| * On live download from devices that support it, this is populated | ||
| * with the device's hardware type identifier (e.g. Shearwater FWID | ||
| * from RDBI 0x8050). It supplements the coarse model field for | ||
| * consumer-side sub-model differentiation. Consumers that do not use | ||
| * this field are unaffected; the model field remains authoritative. */ | ||
| unsigned int hw_id; |
…source
ID_MODEL (RDBI 0x8060, Product-Version byte) is now the sole authoritative
model source on live Shearwater download, aligning with upstream libdc.
The previous shearwater_common_get_model() FWID->model mapping is removed
from the model-resolution path.
The raw FWID (ID_HARDWARE, RDBI 0x8050) is read best-effort in
shearwater_petrel_device_foreach() and exposed to consumers through a new
generic field on dc_event_devinfo_t:
unsigned int devinfo_hw_id;
Value 0 means unknown or not available (all non-Shearwater drivers, Predator
memory-dump path, and any RDBI failure). This lets consumers distinguish
e.g. Petrel 1 vs Petrel 2 hardware on a live download without libdc mapping
the FWID to a synthetic model number.
shearwater_petrel_device_timesync() is also updated to read ID_MODEL
directly rather than calling the now-removed shearwater_common_get_model().
Only the two Shearwater drivers that use devinfo_hw_id (shearwater_petrel.c
and shearwater_predator.c) zero-initialise dc_event_devinfo_t; all other
drivers retain their existing plain declaration since they explicitly assign
all fields before use.
// AI-generated (Claude)
Signed-off-by: Michael Keller <github@ike.ch>
…el lookup
Some device families share a coarse model number across multiple marketed
products. The Shearwater Petrel family is one example: both Petrel 1 and
Petrel 2 report ID_MODEL=3, with the hardware type (FWID) read via RDBI
0x8050 being the only runtime distinguisher.
Add a generic public API to descriptor.c / descriptor.h:
dc_descriptor_t *
dc_descriptor_find_by_hw_id (dc_family_t family, unsigned int hw_id);
The implementation keeps a separate static table g_hw_id_map[] that maps
(family, hw_id) to a (family, model, product) triple, then resolves that
to a direct pointer into g_descriptors[] at call time. This avoids
touching g_descriptors[] and keeps the mapping table small and legible.
The returned pointer is a direct reference into the static table, so
dc_descriptor_free() is safe to call on it (it remains a no-op, consistent
with the iterator path). hw_id==0 returns NULL immediately.
The initial g_hw_id_map[] entries cover the Shearwater Petrel family:
Petrel 1 (model=3): FWIDs 0x0404, 0x0909
Petrel 2 (model=3): FWIDs 0x0505, 0x0808, 0x0838, 0x08A5,
0x0B0B, 0x7828, 0x7B2C, 0x8838
Remove shearwater_fwid_to_product_version() and its suppress-unused stub
from shearwater_common.c. That knowledge now lives in descriptor.c;
shearwater_petrel.c continues to populate devinfo.devinfo_hw_id from the
RDBI 0x8050 read, which is the source for the hw_id passed to the new API.
Consumers that receive DC_EVENT_DEVINFO can call dc_descriptor_find_by_hw_id()
with the reported family and devinfo_hw_id to obtain a refined descriptor
without any device-specific knowledge on their side. A NULL return means
the hw_id is not in the table and the caller should fall back to the coarse
model-based descriptor.
// AI-generated (Claude)
Signed-off-by: Michael Keller <github@ike.ch>
…drivers Rename the new dc_event_devinfo_t field from devinfo_hw_id to hw_id for consistency with the existing model, firmware, and serial fields, which do not carry the struct name as a prefix. Update all references: struct definition, descriptor.h comment, shearwater_petrel.c (assignment), shearwater_predator.c (assignment and comment), shearwater_predator_parser.c (comment), shearwater_common.h (comment), and descriptor.c (comment). Add an explicit devinfo.hw_id = 0 assignment immediately before every DC_EVENT_DEVINFO emit in the 37 non-Shearwater drivers. These drivers declare dc_event_devinfo_t on the stack without an initialiser and only assign model, firmware, and serial, leaving hw_id as indeterminate stack memory. The Subsurface consumer guards the sub-model refinement path on hw_id != 0; indeterminate stack garbage could trigger a spurious dc_descriptor_find_by_hw_id() lookup. The explicit assignment is the minimal targeted fix: it adds one line per emit site and does not alter any existing line, avoiding merge conflicts if upstream adds to those blocks independently. Shearwater Petrel already sets devinfo.hw_id = fwid (RDBI 0x8050 read). Shearwater Predator already sets devinfo.hw_id = 0 explicitly. No behaviour change for any existing user: hw_id was new on this branch. Signed-off-by: AI-generated (Claude) Signed-off-by: Michael Keller <github@ike.ch>
The function was added to the public API (declared in include/libdivecomputer/descriptor.h, implemented in src/descriptor.c) but was omitted from src/libdivecomputer.symbols. On Autotools builds the linker export map is generated from this file, so the symbol was unexported, causing a link failure for any consumer calling it. Add dc_descriptor_find_by_hw_id in the dc_descriptor_* group, immediately after dc_descriptor_filter. Signed-off-by: Michael Keller <github@ike.ch>
Signed-off-by: Michael Keller <github@ike.ch>
Signed-off-by: Michael Keller <github@ike.ch>
2ce8815 to
2f2a609
Compare
There was a problem hiding this comment.
🔵 Needs a closer look
The public API field name must be aligned, and the newly added comment should be rewritten as a complete sentence.
Review details
Suppressed comments (2)
include/libdivecomputer/device.h:61
- The public member is declared as
hw_id, but the PR contract explicitly names this fielddevinfo_hw_idand describes consumers reading that member. A companion consumer built against the advertised name will fail to compile, so align the member name across this API and its consumers (or update the contract before merging).
unsigned int hw_id;
src/shearwater_predator_parser.c:876
- This newly added line is a sentence fragment: it lacks a subject/verb and makes the explanatory comment harder to read. Please make it a complete sentence while retaining the existing continuation on the next line.
// Product-Version byte from the device's final record — authoritative for
- Files reviewed: 11/11 changed files
- Comments generated: 0 new
- Review effort level: Lite
The Shearwater Petrel 1 and Petrel 2 share the same ID_MODEL value (3), making
them indistinguishable by model number alone. The previous approach on this fork
mapped ID_HARDWARE (the FWID) to a synthetic model number, but that has two
problems raised in review: the parser overwrites the model with the
Product-Version byte from the dive log's final block regardless, and a
fork-local number immediately above the upstream range risks colliding with the
next Shearwater model assignment.
This replaces that approach with a two-layer design.
Layer 1 — ID_MODEL is authoritative (fccf5e2)
ID_MODEL (RDBI 0x8060) is now the sole authoritative model source on live
Shearwater download, matching upstream libdc. shearwater_common_get_model() is
removed from the model-resolution path. shearwater_petrel_device_timesync() is
also updated to read ID_MODEL directly.
The raw FWID (ID_HARDWARE, RDBI 0x8050) is still read best-effort and exposed
to consumers through a new generic field on dc_event_devinfo_t:
This is 0 for all non-Shearwater drivers, for the Predator memory-dump path,
and on any RDBI failure. Only the two Shearwater drivers that use the field
zero-initialise dc_event_devinfo_t; all other drivers retain their existing
plain declaration.
Layer 2 — generic descriptor lookup by hardware id (27c0477)
A new function is added to the descriptor API:
The FWID-to-product mapping lives in descriptor.c in a separate g_hw_id_map[]
table alongside the descriptor entries. g_descriptors[] itself is unchanged.
The initial table covers the Shearwater Petrel family, where both Petrel 1 and
Petrel 2 report model=3:
Petrel 1: 0x0404, 0x0909
Petrel 2: 0x0505, 0x0808, 0x0838, 0x08A5, 0x0B0B, 0x7828, 0x7B2C, 0x8838
A consumer can call dc_descriptor_find_by_hw_id() with the family and
devinfo_hw_id from DC_EVENT_DEVINFO to obtain a more specific descriptor without
any device-specific knowledge on its side. NULL means the FWID is unknown; the
caller falls back to the coarse model-based descriptor. This is best-effort: the
FWID is only available on live download and can change across firmware updates.
A companion Subsurface PR calls dc_descriptor_find_by_hw_id() generically in
the DC_EVENT_DEVINFO handler, so a Petrel 2 is correctly identified even if the
user selected "Petrel" in the drop-down, and incorrect information is not
returned when the selected and connected devices differ.
Unchanged
Transport flags, protocol selection (including the Perdix 3 V2 special-case in
shearwater_common_setup), parser sample decoding, Teric time sync, Teric
tank-serial handling, and Predator calibration scaling are all unchanged.