Add a workaround for the hwOS ppO2 firmware bug

Due to a bug in the hwOS Tech firmware v3.03 to v3.07, and the hwOS
Sport firmware v10.57 to v10.63, the ppO2 divisor is sometimes not
correctly reset to zero when no ppO2 samples are being recorded.

Usually this condition can be detected by the fact that the length of
the extended sample will not have enough space left for the ppO2 sample
(9 bytes). As a workaround, reset the divisor back to zero to manually
disable the ppO2 samples.

In theory this detection method is not 100% reliable. There can still be
other sample types present in the extended sample. If their total size
is larger than 9 bytes, the bug will not be detected at all. Instead,
those bytes will get interpreted as the ppO2 sample, resulting in bogus
ppO2 values. Additionally, one of the other sample types will now run
out of space and cause the parsing to fail with an error. However, in
practice this risk is relative low. Most of the other samples are
relative small (1 or 2 bytes), so you would need many of them. That's
rather unlikely in most configurations. The only exception is the large
deco plan sample (15 bytes).
This commit is contained in:
Jef Driesen 2019-11-19 22:16:09 +01:00
parent a5ba2f4e41
commit b9a3606f37

View File

@ -880,6 +880,17 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
for (unsigned int i = 0; i < nconfig; ++i) {
if (info[i].divisor && (nsamples % info[i].divisor) == 0) {
if (length < info[i].size) {
// Due to a bug in the hwOS Tech firmware v3.03 to v3.07, and
// the hwOS Sport firmware v10.57 to v10.63, the ppO2 divisor
// is sometimes not correctly reset to zero when no ppO2
// samples are being recorded.
if (info[i].type == PPO2 && parser->hwos && parser->model != OSTC4 &&
((firmware >= OSTC3FW(3,3) && firmware <= OSTC3FW(3,7)) ||
(firmware >= OSTC3FW(10,57) && firmware <= OSTC3FW(10,63)))) {
WARNING (abstract->context, "Reset invalid ppO2 divisor to zero.");
info[i].divisor = 0;
continue;
}
ERROR (abstract->context, "Buffer overflow detected!");
return DC_STATUS_DATAFORMAT;
}