Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions include/libdivecomputer/descriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,26 @@ dc_descriptor_get_transports (const dc_descriptor_t *descriptor);
int
dc_descriptor_filter (const dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);

/**
* Find a descriptor by hardware identifier.
*
* Some device families share a coarse model number across multiple marketed
* products. When a device reports a hardware identifier (via
* DC_EVENT_DEVINFO.hw_id), this function can find a more specific
* descriptor than the model number alone provides. This is best-effort:
* returns NULL if the hardware id is unknown or not in the table.
*
* The returned descriptor is a direct reference to an internal table entry
* and must be released with dc_descriptor_free(), which is safe to call on
* such a reference.
*
* @param[in] family The device family type.
* @param[in] hw_id The hardware identifier from DC_EVENT_DEVINFO.
* @returns A descriptor on success, or NULL if no match.
*/
dc_descriptor_t *
dc_descriptor_find_by_hw_id (dc_family_t family, unsigned int hw_id);
Comment on lines +144 to +145

#ifdef __cplusplus
}
#endif /* __cplusplus */
Expand Down
7 changes: 7 additions & 0 deletions include/libdivecomputer/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ typedef struct dc_event_devinfo_t {
unsigned int model;
unsigned int firmware;
unsigned int serial;
/* 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;
} dc_event_devinfo_t;

typedef struct dc_event_clock_t {
Expand Down
1 change: 1 addition & 0 deletions src/atomics_cobalt.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ atomics_cobalt_device_foreach (dc_device_t *abstract, dc_dive_callback_t callbac
devinfo.serial *= 10;
devinfo.serial += device->version[i] - '0';
}
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

// Allocate a memory buffer.
Expand Down
2 changes: 1 addition & 1 deletion src/cochran_commander.c
Original file line number Diff line number Diff line change
Expand Up @@ -937,7 +937,7 @@ cochran_commander_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
devinfo.serial = array_uint32_word_be(data.config + layout->cf_serial_number);
else
devinfo.serial = array_uint32_le(data.config + layout->cf_serial_number);

devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

unsigned int head_dive = 0, tail_dive = 0, dive_count = 0;
Expand Down
2 changes: 2 additions & 0 deletions src/cressi_edy.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ cressi_edy_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
devinfo.model = device->model;
devinfo.firmware = 0;
devinfo.serial = 0;
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

return device_dump_read (abstract, 0, dc_buffer_get_data (buffer),
Expand All @@ -438,6 +439,7 @@ cressi_edy_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
devinfo.model = device->model;
devinfo.firmware = 0;
devinfo.serial = 0;
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

// Read the logbook data.
Expand Down
1 change: 1 addition & 0 deletions src/cressi_goa.c
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,7 @@ cressi_goa_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
devinfo.model = model;
devinfo.firmware = firmware;
devinfo.serial = serial;
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

// Allocate memory for the logbook data.
Expand Down
1 change: 1 addition & 0 deletions src/cressi_leonardo.c
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ cressi_leonardo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
devinfo.model = data[0];
devinfo.firmware = 0;
devinfo.serial = array_uint24_le (data + 1);
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

return DC_STATUS_SUCCESS;
Expand Down
1 change: 1 addition & 0 deletions src/deepblu_cosmiq.c
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ deepblu_cosmiq_device_foreach (dc_device_t *abstract, dc_dive_callback_t callbac
devinfo.model = 0;
devinfo.firmware = fw[0] & 0x3F;
devinfo.serial = array_uint32_le (mac);
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

unsigned char ndives = 0;
Expand Down
1 change: 1 addition & 0 deletions src/deepsix_excursion.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ deepsix_excursion_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
devinfo.model = 0;
devinfo.firmware = array_uint16_be (rsp_software + 4);
devinfo.serial = array_convert_str2num (rsp_serial + 3, sizeof(rsp_serial) - 3);
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

// Firmware version 6+ uses the new commands.
Expand Down
62 changes: 62 additions & 0 deletions src/descriptor.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,38 @@ static const dc_iterator_vtable_t dc_descriptor_iterator_vtable = {
* actually used to identify individual models, identical values are assigned.
*/

/* Hardware-identifier to descriptor mapping.
*
* Some device families share a coarse model number (DC_EVENT_DEVINFO.model)
* across multiple marketed products; the hardware identifier (hw_id)
* from DC_EVENT_DEVINFO can refine the selection to a specific descriptor.
* This table is best-effort: the FWID is only available on live download and
* may change across firmware updates. Consumers should treat a NULL result
* from dc_descriptor_find_by_hw_id() as "use the coarse model descriptor". */
typedef struct {
dc_family_t family;
unsigned int model;
unsigned int hw_id;
const char *product;
} dc_hw_id_entry_t;

static const dc_hw_id_entry_t g_hw_id_map[] = {
/* Shearwater Petrel family.
* Petrel 1 (model=3): hardware ids 0x0404, 0x0909 */
{DC_FAMILY_SHEARWATER_PETREL, 3, 0x0404, "Petrel"},
{DC_FAMILY_SHEARWATER_PETREL, 3, 0x0909, "Petrel"},
/* Petrel 2 (model=3): hardware ids 0x0505, 0x0808, 0x0838, 0x08A5,
* 0x0B0B, 0x7828, 0x7B2C, 0x8838 */
{DC_FAMILY_SHEARWATER_PETREL, 3, 0x0505, "Petrel 2"},
{DC_FAMILY_SHEARWATER_PETREL, 3, 0x0808, "Petrel 2"},
{DC_FAMILY_SHEARWATER_PETREL, 3, 0x0838, "Petrel 2"},
{DC_FAMILY_SHEARWATER_PETREL, 3, 0x08A5, "Petrel 2"},
{DC_FAMILY_SHEARWATER_PETREL, 3, 0x0B0B, "Petrel 2"},
{DC_FAMILY_SHEARWATER_PETREL, 3, 0x7828, "Petrel 2"},
{DC_FAMILY_SHEARWATER_PETREL, 3, 0x7B2C, "Petrel 2"},
{DC_FAMILY_SHEARWATER_PETREL, 3, 0x8838, "Petrel 2"},
};

static const dc_descriptor_t g_descriptors[] = {
/* Suunto Solution */
{"Suunto", "Solution", DC_FAMILY_SUUNTO_SOLUTION, 0, DC_TRANSPORT_SERIAL, NULL},
Expand Down Expand Up @@ -1053,6 +1085,36 @@ dc_descriptor_free (dc_descriptor_t *descriptor)
return;
}

dc_descriptor_t *
dc_descriptor_find_by_hw_id (dc_family_t family, unsigned int hw_id)
{
if (hw_id == 0)
return NULL;

for (size_t i = 0; i < C_ARRAY_SIZE(g_hw_id_map); i++) {
if (g_hw_id_map[i].family != family || g_hw_id_map[i].hw_id != hw_id)
continue;

/* Matched — find the corresponding entry in g_descriptors[] by
* family, model, and product name. Returning a direct pointer
* into the static table is safe: dc_descriptor_free() is a
* no-op and g_descriptors[] has static storage duration. */
for (size_t j = 0; j < C_ARRAY_SIZE(g_descriptors); j++) {
if (g_descriptors[j].type == family &&
g_descriptors[j].model == g_hw_id_map[i].model &&
strcmp(g_descriptors[j].product, g_hw_id_map[i].product) == 0) {
return (dc_descriptor_t *) &g_descriptors[j];
}
}
/* hw_id matched the map but the descriptor was not found —
* product name mismatch or g_descriptors[] was edited without
* updating g_hw_id_map[]. */
return NULL;
}

return NULL;
}

const char *
dc_descriptor_get_vendor (const dc_descriptor_t *descriptor)
{
Expand Down
1 change: 1 addition & 0 deletions src/diverite_nitekq.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ diverite_nitekq_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
devinfo.model = 0;
devinfo.firmware = 0;
devinfo.serial = array_uint32_be (device->version + 0x0A);
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

// Send the upload request. It's not clear whether this request is
Expand Down
1 change: 1 addition & 0 deletions src/divesoft_freedom.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ divesoft_freedom_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
devinfo.model = rsp_version[0];
devinfo.firmware = array_uint24_be (rsp_version + 3);
devinfo.serial = array_convert_str2num (rsp_version + 10 + 5, 11);
devinfo.hw_id = 0;
device_event_emit(abstract, DC_EVENT_DEVINFO, &devinfo);

// Allocate memory for the dive list.
Expand Down
1 change: 1 addition & 0 deletions src/divesystem_idive.c
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
devinfo.model = array_uint16_le (packet);
devinfo.firmware = array_uint32_le (packet + 2);
devinfo.serial = array_uint32_le (packet + 6);
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

// Emit a vendor event.
Expand Down
1 change: 1 addition & 0 deletions src/garmin.c
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,7 @@ garmin_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void
if (devinfo_p) {
// first time we came through here, let's emit the
// devinfo and vendor events
devinfo_p->hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, devinfo_p);
devinfo_p = NULL;
}
Expand Down
1 change: 1 addition & 0 deletions src/halcyon_symbios.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,7 @@ halcyon_symbios_device_foreach (dc_device_t *abstract, dc_dive_callback_t callba
devinfo.model = info[5];
devinfo.firmware = array_uint24_be (info + 16);
devinfo.serial = array_uint32_le (info);
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

DEBUG (abstract->context, "Device: model=%u, serial=%u, firmware=%u.%u.%u, hw=%u, bt=%u.%u, battery=%u, pressure=%u, errorbits=%u",
Expand Down
1 change: 1 addition & 0 deletions src/hw_ostc.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ hw_ostc_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
devinfo.model = 1; // OSTC Mk2
else
devinfo.model = 0; // OSTC
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

return DC_STATUS_SUCCESS;
Expand Down
2 changes: 2 additions & 0 deletions src/hw_ostc3.c
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,7 @@ hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, voi
else
devinfo.model = OSTC3;
}
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

// Allocate memory.
Expand Down Expand Up @@ -1894,6 +1895,7 @@ hw_ostc3_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
else
devinfo.model = OSTC3;
}
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

// Allocate the required amount of memory.
Expand Down
1 change: 1 addition & 0 deletions src/libdivecomputer.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ dc_descriptor_get_type
dc_descriptor_get_model
dc_descriptor_get_transports
dc_descriptor_filter
dc_descriptor_find_by_hw_id

dc_iostream_get_transport
dc_iostream_set_timeout
Expand Down
2 changes: 2 additions & 0 deletions src/liquivision_lynx.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ liquivision_lynx_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
devinfo.model = array_uint16_le (device->info + 0);
devinfo.firmware = 0;
devinfo.serial = array_uint32_le (device->more + 0);
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

// Allocate the required amount of memory.
Expand Down Expand Up @@ -410,6 +411,7 @@ liquivision_lynx_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
devinfo.model = model;
devinfo.firmware = 0;
devinfo.serial = array_uint32_le (device->more + 0);
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

// Read the config segment.
Expand Down
1 change: 1 addition & 0 deletions src/mares_darwin.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ mares_darwin_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
devinfo.model = device->model;
devinfo.firmware = 0;
devinfo.serial = array_uint16_be (data + 8);
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

return status;
Expand Down
3 changes: 3 additions & 0 deletions src/mares_iconhd.c
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,7 @@ mares_iconhd_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
devinfo.model = device->model;
devinfo.firmware = 0;
devinfo.serial = array_uint32_le (data + 0x0C);
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

return status;
Expand All @@ -848,6 +849,7 @@ mares_iconhd_device_foreach_raw (dc_device_t *abstract, dc_dive_callback_t callb
devinfo.model = device->model;
devinfo.firmware = 0;
devinfo.serial = array_uint32_le (serial);
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

// Enable progress notifications.
Expand Down Expand Up @@ -1101,6 +1103,7 @@ mares_iconhd_device_foreach_object (dc_device_t *abstract, dc_dive_callback_t ca
devinfo.model = device->model;
devinfo.firmware = 0;
devinfo.serial = serial;
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

// Erase the buffer.
Expand Down
1 change: 1 addition & 0 deletions src/mares_nemo.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ mares_nemo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
devinfo.model = data[1];
devinfo.firmware = 0;
devinfo.serial = array_uint16_be (data + 8);
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

return DC_STATUS_SUCCESS;
Expand Down
1 change: 1 addition & 0 deletions src/mares_puck.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ mares_puck_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
devinfo.model = data[1];
devinfo.firmware = 0;
devinfo.serial = array_uint16_be (data + 8);
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

return status;
Expand Down
1 change: 1 addition & 0 deletions src/mclean_extreme.c
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,7 @@ mclean_extreme_device_foreach(dc_device_t *abstract, dc_dive_callback_t callback
devinfo.model = 0;
devinfo.firmware = array_uint32_le (firmware);
devinfo.serial = hashcode (serial, serial_len);
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

// Read the computer configuration.
Expand Down
1 change: 1 addition & 0 deletions src/oceanic_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ oceanic_common_device_devinfo (dc_device_t *abstract, dc_event_progress_t *progr
(id[11] & 0x0F) * 100000 + ((id[11] & 0xF0) >> 4) * 10000 +
(id[12] & 0x0F) * 1000 + ((id[12] & 0xF0) >> 4) * 100 +
(id[13] & 0x0F) * 10 + ((id[13] & 0xF0) >> 4) * 1;
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

return status;
Expand Down
1 change: 1 addition & 0 deletions src/oceans_s1.c
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,7 @@ oceans_s1_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, vo
devinfo.model = 0;
devinfo.firmware = major << 16 | minor;
devinfo.serial = 0;
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

dc_buffer_t *buffer = dc_buffer_new (4096);
Expand Down
1 change: 1 addition & 0 deletions src/pelagic_i330r.c
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,7 @@ pelagic_i330r_device_devinfo (dc_device_t *abstract, dc_event_progress_t *progre
bcd2dec (device->hwcal[12]) +
bcd2dec (device->hwcal[13]) * 100 +
bcd2dec (device->hwcal[14]) * 10000;
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

return DC_STATUS_SUCCESS;
Expand Down
1 change: 1 addition & 0 deletions src/reefnet_sensus.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ reefnet_sensus_handshake (reefnet_sensus_device_t *device)
devinfo.model = handshake[2] - '0';
devinfo.firmware = handshake[3] - '0';
devinfo.serial = array_uint16_le (handshake + 6);
devinfo.hw_id = 0;
device_event_emit (&device->base, DC_EVENT_DEVINFO, &devinfo);

// Emit a vendor event.
Expand Down
1 change: 1 addition & 0 deletions src/reefnet_sensuspro.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ reefnet_sensuspro_handshake (reefnet_sensuspro_device_t *device)
devinfo.model = handshake[0];
devinfo.firmware = handshake[1];
devinfo.serial = array_uint16_le (handshake + 4);
devinfo.hw_id = 0;
device_event_emit (&device->base, DC_EVENT_DEVINFO, &devinfo);

// Emit a vendor event.
Expand Down
1 change: 1 addition & 0 deletions src/reefnet_sensusultra.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ reefnet_sensusultra_handshake (reefnet_sensusultra_device_t *device, unsigned sh
devinfo.model = handshake[1];
devinfo.firmware = handshake[0];
devinfo.serial = array_uint16_le (handshake + 2);
devinfo.hw_id = 0;
device_event_emit (&device->base, DC_EVENT_DEVINFO, &devinfo);

// Emit a vendor event.
Expand Down
2 changes: 2 additions & 0 deletions src/seac_screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,7 @@ seac_screen_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
devinfo.firmware = array_uint32_le (device->info + 0x11C);
}
devinfo.serial = array_uint32_le (device->info + 0x10);
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

// Emit a vendor event.
Expand Down Expand Up @@ -531,6 +532,7 @@ seac_screen_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback,
devinfo.firmware = array_uint32_le (device->info + 0x11C);
}
devinfo.serial = array_uint32_le (device->info + 0x010);
devinfo.hw_id = 0;
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);

// Emit a vendor event.
Expand Down
Loading
Loading