static dc_status_t hw_ostc_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime) { hw_ostc_parser_t *parser = (hw_ostc_parser_t *) abstract; const unsigned char *data = abstract->data; unsigned int size = abstract->size; // Cache the header data. dc_status_t rc = hw_ostc_parser_cache (parser); if (rc != DC_STATUS_SUCCESS) return rc; unsigned int version = parser->version; const hw_ostc_layout_t *layout = parser->layout; unsigned int divetime = 0; if (version > 0x20) { // Use the dive time stored in the extended header, rounded down towards // the nearest minute, to match the value displayed by the ostc. divetime = (array_uint16_le (data + layout->duration) / 60) * 60; } else { // Use the normal dive time (excluding the shallow parts of the dive). divetime = array_uint16_le (data + layout->divetime) * 60 + data[layout->divetime + 2]; } const unsigned char *p = data + layout->datetime; dc_datetime_t dt; if (version == 0x23) { dt.year = p[0] + 2000; dt.month = p[1]; dt.day = p[2]; } else { dt.year = p[2] + 2000; dt.month = p[0]; dt.day = p[1]; } dt.hour = p[3]; dt.minute = p[4]; dt.second = 0; dc_ticks_t ticks = dc_datetime_mktime (&dt); if (ticks == (dc_ticks_t) -1) return DC_STATUS_DATAFORMAT; ticks -= divetime; if (!dc_datetime_localtime (datetime, ticks)) return DC_STATUS_DATAFORMAT; return DC_STATUS_SUCCESS; }
int libdc_parser_parse_header(parser_handle_t abstract, const void * buffer, uint32_t size, header_callback_fn_t cb, void * userdata) { libdc_parser_t parser = (libdc_parser_t)(abstract); if (parser == NULL) { errno = EINVAL; return -1; } dc_status_t rc = dc_parser_set_data(parser->parser, buffer, size); if (rc != DC_STATUS_SUCCESS) { parser->dev->errcode = DRIVER_ERR_PARSER; parser->dev->errmsg = "Failed to set parser data"; return -1; } // Parse Dive Date/Time dc_datetime_t dt = {0}; rc = dc_parser_get_datetime(parser->parser, & dt); if ((rc != DC_STATUS_SUCCESS) && (rc != DC_STATUS_UNSUPPORTED)) { parser->dev->errcode = DRIVER_ERR_PARSER; parser->dev->errmsg = "Failed to retrieve dive date/time"; return -1; } if ((rc == DC_STATUS_SUCCESS) && (cb != NULL)) { dc_ticks_t ts = dc_datetime_mktime(& dt); cb(userdata, DIVE_HEADER_START_TIME, (time_t)ts, 0, 0); } // Parse Dive Duration unsigned int duration = 0; rc = dc_parser_get_field (parser->parser, DC_FIELD_DIVETIME, 0, & duration); if ((rc != DC_STATUS_SUCCESS) && (rc != DC_STATUS_UNSUPPORTED)) { parser->dev->errcode = DRIVER_ERR_PARSER; parser->dev->errmsg = "Failed to retrieve dive duration"; return -1; } if ((rc == DC_STATUS_SUCCESS) && (cb != NULL)) cb(userdata, DIVE_HEADER_DURATION, duration / 60, 0, 0); // Parse Maximum Depth double maxdepth = 0.0; rc = dc_parser_get_field (parser->parser, DC_FIELD_MAXDEPTH, 0, & maxdepth); if ((rc != DC_STATUS_SUCCESS) && (rc != DC_STATUS_UNSUPPORTED)) { parser->dev->errcode = DRIVER_ERR_PARSER; parser->dev->errmsg = "Failed to retrieve maximum depth"; return -1; } if ((rc == DC_STATUS_SUCCESS) && (cb != NULL)) cb(userdata, DIVE_HEADER_MAX_DEPTH, (uint32_t)round(maxdepth * 100), 0, 0); // Parse Gas Mixes unsigned int ngasses = 0; rc = dc_parser_get_field(parser->parser, DC_FIELD_GASMIX_COUNT, 0, & ngasses); if ((rc != DC_STATUS_SUCCESS) && (rc != DC_STATUS_UNSUPPORTED)) { parser->dev->errcode = DRIVER_ERR_PARSER; parser->dev->errmsg = "Failed to retrieve gas mix count"; return -1; } unsigned int i; for (i = 0; i < ngasses; ++i) { dc_gasmix_t gasmix = {0}; rc = dc_parser_get_field(parser->parser, DC_FIELD_GASMIX, i, & gasmix); if ((rc != DC_STATUS_SUCCESS) && (rc != DC_STATUS_UNSUPPORTED)) { parser->dev->errcode = DRIVER_ERR_PARSER; parser->dev->errmsg = "Failed to retrieve gas mix data"; return -1; } if ((rc == DC_STATUS_SUCCESS) && (cb != NULL)) { uint32_t pmHe = (uint32_t)round(gasmix.helium * 1000.0); uint32_t pmO2 = (uint32_t)round(gasmix.oxygen * 1000.0); cb(userdata, DIVE_HEADER_PMO2, pmO2, i, 0); cb(userdata, DIVE_HEADER_PMHe, pmHe, i, 0); } } return 0; }