Skip to content

Commit cf3a14d

Browse files
committed
Heinrichs Weikamp: Separate Models for OSTC 4 and OSTC 5.
Introduce separate models for the OSTC 4 and OSTC 5 dive computers, giving divers information about which model a particular log was downloaded from. Signed-off-by: Michael Keller <[email protected]>
1 parent e761955 commit cf3a14d

File tree

3 files changed

+61
-47
lines changed

3 files changed

+61
-47
lines changed

src/descriptor.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,8 @@ static const dc_descriptor_t g_descriptors[] = {
337337
{"Heinrichs Weikamp", "OSTC 3", DC_FAMILY_HW_OSTC3, 0x0A, DC_TRANSPORT_SERIAL, NULL},
338338
{"Heinrichs Weikamp", "OSTC Plus", DC_FAMILY_HW_OSTC3, 0x13, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH | DC_TRANSPORT_BLE, dc_filter_hw},
339339
{"Heinrichs Weikamp", "OSTC Plus", DC_FAMILY_HW_OSTC3, 0x1A, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH | DC_TRANSPORT_BLE, dc_filter_hw},
340-
{"Heinrichs Weikamp", "OSTC 4/5", DC_FAMILY_HW_OSTC3, 0x3B, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH | DC_TRANSPORT_BLE, dc_filter_hw},
340+
{"Heinrichs Weikamp", "OSTC 4", DC_FAMILY_HW_OSTC3, 0x3B43, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH | DC_TRANSPORT_BLE, dc_filter_hw},
341+
{"Heinrichs Weikamp", "OSTC 5", DC_FAMILY_HW_OSTC3, 0x3B44, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH | DC_TRANSPORT_BLE, dc_filter_hw},
341342
{"Heinrichs Weikamp", "OSTC cR", DC_FAMILY_HW_OSTC3, 0x05, DC_TRANSPORT_SERIAL, NULL},
342343
{"Heinrichs Weikamp", "OSTC cR", DC_FAMILY_HW_OSTC3, 0x07, DC_TRANSPORT_SERIAL, NULL},
343344
{"Heinrichs Weikamp", "OSTC Sport", DC_FAMILY_HW_OSTC3, 0x12, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH | DC_TRANSPORT_BLE, dc_filter_hw},

src/hw_ostc3.c

Lines changed: 59 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,11 @@
8383
#define INVALID 0xFFFFFFFF
8484
#define UNKNOWN 0x00
8585
#define OSTC3 0x0A
86-
#define OSTC4 0x3B
86+
#define OSTC4_5_PREFIX 0x3B
8787
#define SPORT 0x12
8888
#define CR 0x05
89+
#define MODEL_OSTC4 0x43
90+
#define MODEL_OSTC5 0x44
8991

9092
#define NODELAY 0
9193
#define TIMEOUT 400
@@ -103,6 +105,7 @@
103105
#define HDR_FULL_POINTERS 2 // 6 bytes
104106
#define HDR_FULL_FIRMWARE 48 // 2 bytes
105107

108+
106109
typedef enum hw_ostc3_state_t {
107110
OPEN,
108111
DOWNLOAD,
@@ -201,6 +204,12 @@ hw_ostc3_strncpy (unsigned char *data, unsigned int size, const char *text)
201204
return 0;
202205
}
203206

207+
static bool is_ostc4_family(unsigned int hardware)
208+
{
209+
// Check if the hardware is an OSTC 4 or 5.
210+
return (hardware >> 8) == OSTC4_5_PREFIX;
211+
}
212+
204213
static dc_status_t
205214
hw_ostc3_read (hw_ostc3_device_t *device, dc_event_progress_t *progress, unsigned char data[], size_t size)
206215
{
@@ -240,7 +249,7 @@ hw_ostc3_write (hw_ostc3_device_t *device, dc_event_progress_t *progress, const
240249
size_t nbytes = 0;
241250
while (nbytes < size) {
242251
// Set the maximum packet size.
243-
size_t length = (device->hardware == OSTC4) ? 64 : 1024;
252+
size_t length = is_ostc4_family(device->hardware) ? 64 : 1024;
244253

245254
// Limit the packet size to the total size.
246255
if (nbytes + length > size)
@@ -488,17 +497,13 @@ hw_ostc3_device_id (hw_ostc3_device_t *device, unsigned char data[], unsigned in
488497
if (size != SZ_HARDWARE && size != SZ_HARDWARE2)
489498
return DC_STATUS_INVALIDARGS;
490499

491-
// We need to try the HARDWARE command first, as HARDWARE2 results
492-
// in a bluetooth disconnect when the OSTC4 is in bootloader mode.
493500
unsigned char hardware[SZ_HARDWARE2] = {0};
494-
status = hw_ostc3_transfer(device, NULL, HARDWARE, NULL, 0, hardware + 1, SZ_HARDWARE, NULL, NODELAY);
495-
if (size == SZ_HARDWARE2 && array_uint16_be(hardware) != OSTC4) {
496-
// HARDWARE2 returns additional information
497-
unsigned char hardware2[SZ_HARDWARE2] = {0};
498-
status = hw_ostc3_transfer(device, NULL, HARDWARE2, NULL, 0, hardware2, SZ_HARDWARE2, NULL, NODELAY);
499-
if (status == DC_STATUS_SUCCESS) {
500-
memcpy(hardware, hardware2, SZ_HARDWARE2);
501-
}
501+
if (size == SZ_HARDWARE2) {
502+
status = hw_ostc3_transfer(device, NULL, HARDWARE2, NULL, 0, hardware, SZ_HARDWARE2, NULL, NODELAY);
503+
}
504+
505+
if (size == SZ_HARDWARE || status == DC_STATUS_UNSUPPORTED) {
506+
status = hw_ostc3_transfer(device, NULL, HARDWARE, NULL, 0, hardware + 1, SZ_HARDWARE, NULL, NODELAY);
502507
}
503508

504509
if (status != DC_STATUS_SUCCESS)
@@ -605,14 +610,34 @@ hw_ostc3_device_init (hw_ostc3_device_t *device, hw_ostc3_state_t state)
605610
return DC_STATUS_SUCCESS;
606611

607612
// Read the hardware descriptor.
608-
unsigned char hardware[SZ_HARDWARE2] = {0, UNKNOWN};
609-
rc = hw_ostc3_device_id (device, hardware, sizeof(hardware));
610-
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
611-
ERROR (abstract->context, "Failed to read the hardware descriptor.");
612-
return rc;
613+
unsigned int hardware_prefix;
614+
if (device->state == SERVICE) {
615+
// We need to try the HARDWARE command first, as HARDWARE2 results
616+
// in a bluetooth disconnect when the OSTC 4/5 is in bootloader mode.
617+
unsigned char hardware[SZ_HARDWARE] = {UNKNOWN};
618+
rc = hw_ostc3_device_id (device, hardware, sizeof(hardware));
619+
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
620+
ERROR (abstract->context, "Failed to read the hardware descriptor.");
621+
return rc;
622+
}
623+
624+
HEXDUMP (abstract->context, DC_LOGLEVEL_DEBUG, "Hardware", hardware, sizeof(hardware));
625+
626+
hardware_prefix = hardware[0];
613627
}
614628

615-
HEXDUMP (abstract->context, DC_LOGLEVEL_DEBUG, "Hardware", hardware, sizeof(hardware));
629+
unsigned char hardware2[SZ_HARDWARE2] = {0, UNKNOWN, 0, 0, MODEL_OSTC4};
630+
if (device->state != SERVICE || hardware_prefix != OSTC4_5_PREFIX) {
631+
rc = hw_ostc3_device_id (device, hardware2, sizeof(hardware2));
632+
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
633+
ERROR (abstract->context, "Failed to read the hardware2 descriptor.");
634+
return rc;
635+
}
636+
637+
HEXDUMP (abstract->context, DC_LOGLEVEL_DEBUG, "Hardware2", hardware2, sizeof(hardware2));
638+
639+
hardware_prefix = array_uint16_be(hardware2 + 0);
640+
}
616641

617642
// Read the version information.
618643
unsigned char version[SZ_VERSION] = {0};
@@ -625,17 +650,16 @@ hw_ostc3_device_init (hw_ostc3_device_t *device, hw_ostc3_state_t state)
625650
HEXDUMP (abstract->context, DC_LOGLEVEL_DEBUG, "Version", version, sizeof(version));
626651

627652
// Cache the descriptor.
628-
device->hardware = array_uint16_be(hardware + 0);
629-
if (device->hardware != OSTC4) {
630-
device->feature = array_uint16_be(hardware + 2);
631-
device->model = hardware[4];
632-
}
633-
device->serial = array_uint16_le (version + 0);
634-
if (device->hardware == OSTC4) {
635-
device->firmware = array_uint16_le (version + 2);
636-
} else {
653+
if (hardware_prefix != OSTC4_5_PREFIX) {
654+
device->hardware = hardware_prefix;
655+
device->feature = array_uint16_be(hardware2 + 2);
637656
device->firmware = array_uint16_be (version + 2);
657+
} else {
658+
device->hardware = (hardware_prefix << 8) | hardware2[4];
659+
device->firmware = array_uint16_le (version + 2);
638660
}
661+
device->model = hardware2[4];
662+
device->serial = array_uint16_le (version + 0);
639663

640664
return DC_STATUS_SUCCESS;
641665
}
@@ -811,7 +835,7 @@ hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, voi
811835

812836
// Get the internal dive number.
813837
unsigned int current = array_uint16_le (header + offset + logbook->number);
814-
if (current > maximum || device->hardware == OSTC4) {
838+
if (current > maximum || is_ostc4_family(device->hardware)) {
815839
maximum = current;
816840
latest = i;
817841
}
@@ -913,7 +937,7 @@ hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, voi
913937
}
914938

915939
// Detect invalid profile data.
916-
unsigned int delta = device->hardware == OSTC4 ? 3 : 0;
940+
unsigned int delta = is_ostc4_family(device->hardware) ? 3 : 0;
917941
if (length < RB_LOGBOOK_SIZE_FULL + 2 ||
918942
profile[length - 2] != 0xFD || profile[length - 1] != 0xFD) {
919943
// A valid profile should have at least a correct 2 byte
@@ -1031,7 +1055,7 @@ hw_ostc3_device_config_read (dc_device_t *abstract, unsigned int config, unsigne
10311055
if (rc != DC_STATUS_SUCCESS)
10321056
return rc;
10331057

1034-
if (device->hardware == OSTC4 ? size != SZ_CONFIG : size > SZ_CONFIG) {
1058+
if (is_ostc4_family(device->hardware) ? size != SZ_CONFIG : size > SZ_CONFIG) {
10351059
ERROR (abstract->context, "Invalid parameter specified.");
10361060
return DC_STATUS_INVALIDARGS;
10371061
}
@@ -1057,7 +1081,7 @@ hw_ostc3_device_config_write (dc_device_t *abstract, unsigned int config, const
10571081
if (rc != DC_STATUS_SUCCESS)
10581082
return rc;
10591083

1060-
if (device->hardware == OSTC4 ? size != SZ_CONFIG : size > SZ_CONFIG) {
1084+
if (is_ostc4_family(device->hardware) ? size != SZ_CONFIG : size > SZ_CONFIG) {
10611085
ERROR (abstract->context, "Invalid parameter specified.");
10621086
return DC_STATUS_INVALIDARGS;
10631087
}
@@ -1624,7 +1648,7 @@ hw_ostc3_device_fwupdate (dc_device_t *abstract, const char *filename, bool forc
16241648
return status;
16251649
}
16261650

1627-
if (device->hardware == OSTC4) {
1651+
if (is_ostc4_family(device->hardware)) {
16281652
return hw_ostc3_device_fwupdate4 (abstract, filename, forceUpdate);
16291653
} else {
16301654
if (forceUpdate) {
@@ -1653,7 +1677,7 @@ hw_ostc3_device_read (dc_device_t *abstract, unsigned int address, unsigned char
16531677
return status;
16541678
}
16551679

1656-
if (device->hardware == OSTC4) {
1680+
if (is_ostc4_family(device->hardware)) {
16571681
return DC_STATUS_UNSUPPORTED;
16581682
}
16591683

@@ -1690,7 +1714,7 @@ hw_ostc3_device_write (dc_device_t *abstract, unsigned int address, const unsign
16901714
return status;
16911715
}
16921716

1693-
if (device->hardware == OSTC4) {
1717+
if (is_ostc4_family(device->hardware)) {
16941718
return DC_STATUS_UNSUPPORTED;
16951719
}
16961720

@@ -1732,7 +1756,7 @@ hw_ostc3_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
17321756
return rc;
17331757
}
17341758

1735-
if (device->hardware == OSTC4) {
1759+
if (is_ostc4_family(device->hardware)) {
17361760
return DC_STATUS_UNSUPPORTED;
17371761
}
17381762

src/hw_ostc_parser.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,6 @@
9696
#define OSTC4_SCRUBBER_STATE_ERROR_FLAG 0x4000
9797
#define OSTC4_SCRUBBER_STATE_WARNING_FLAG 0x2000
9898

99-
#define OSTC5_STARTING_SERIAL 1500
100-
10199
typedef struct hw_ostc_sample_info_t {
102100
unsigned int type;
103101
unsigned int divisor;
@@ -833,15 +831,6 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned
833831

834832
string->desc = "Remaining scrubber time at end [minutes]";
835833
snprintf(buf, BUFLEN, "%d", parser->last_scrubber_time_minutes);
836-
break;
837-
case 8:
838-
if (parser->model != OSTC4) {
839-
return DC_STATUS_UNSUPPORTED;
840-
}
841-
842-
string->desc = "Model";
843-
snprintf(buf, BUFLEN, "%s", parser->serial < OSTC5_STARTING_SERIAL ? "OSTC4" : "OSTC5");
844-
845834
break;
846835
default:
847836
return DC_STATUS_UNSUPPORTED;

0 commit comments

Comments
 (0)