Merge branch 'goa-freedive'
This commit is contained in:
commit
5b133233f7
@ -51,6 +51,9 @@ dc_buffer_append (dc_buffer_t *buffer, const unsigned char data[], size_t size);
|
||||
int
|
||||
dc_buffer_prepend (dc_buffer_t *buffer, const unsigned char data[], size_t size);
|
||||
|
||||
int
|
||||
dc_buffer_insert (dc_buffer_t *buffer, size_t offset, const unsigned char data[], size_t size);
|
||||
|
||||
int
|
||||
dc_buffer_slice (dc_buffer_t *buffer, size_t offset, size_t size);
|
||||
|
||||
|
||||
66
src/buffer.c
66
src/buffer.c
@ -231,6 +231,72 @@ dc_buffer_prepend (dc_buffer_t *buffer, const unsigned char data[], size_t size)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
dc_buffer_insert (dc_buffer_t *buffer, size_t offset, const unsigned char data[], size_t size)
|
||||
{
|
||||
if (buffer == NULL)
|
||||
return 0;
|
||||
|
||||
if (offset > buffer->size)
|
||||
return 0;
|
||||
|
||||
size_t head = buffer->offset;
|
||||
size_t tail = buffer->capacity - (buffer->offset + buffer->size);
|
||||
|
||||
unsigned char *ptr = buffer->data + buffer->offset;
|
||||
|
||||
if (size <= head) {
|
||||
if (buffer->size)
|
||||
memmove (ptr - size, ptr, offset);
|
||||
buffer->offset -= size;
|
||||
} else if (size <= tail) {
|
||||
if (buffer->size)
|
||||
memmove (ptr + offset + size, ptr + offset, buffer->size - offset);
|
||||
} else if (size <= tail + head) {
|
||||
size_t n = buffer->size + size;
|
||||
size_t available = buffer->capacity - n;
|
||||
|
||||
size_t tmp_offset = head > tail ? available : 0;
|
||||
|
||||
unsigned char *tmp = buffer->data;
|
||||
|
||||
if (buffer->size) {
|
||||
memmove (tmp + tmp_offset, ptr, offset);
|
||||
memmove (tmp + tmp_offset + offset + size, ptr + offset, buffer->size - offset);
|
||||
}
|
||||
|
||||
buffer->offset = tmp_offset;
|
||||
} else {
|
||||
size_t n = buffer->size + size;
|
||||
size_t capacity = dc_buffer_expand_calc (buffer, n);
|
||||
size_t available = capacity - n;
|
||||
|
||||
size_t tmp_offset = head > tail ? available : 0;
|
||||
|
||||
unsigned char *tmp = (unsigned char *) malloc (capacity);
|
||||
if (tmp == NULL)
|
||||
return 0;
|
||||
|
||||
if (buffer->size) {
|
||||
memcpy (tmp + tmp_offset, ptr, offset);
|
||||
memcpy (tmp + tmp_offset + offset + size, ptr + offset, buffer->size - offset);
|
||||
}
|
||||
|
||||
free (buffer->data);
|
||||
buffer->data = tmp;
|
||||
buffer->capacity = capacity;
|
||||
buffer->offset = tmp_offset;
|
||||
}
|
||||
|
||||
if (size)
|
||||
memcpy (buffer->data + buffer->offset + offset, data, size);
|
||||
|
||||
buffer->size += size;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
dc_buffer_slice (dc_buffer_t *buffer, size_t offset, size_t size)
|
||||
{
|
||||
|
||||
@ -485,7 +485,19 @@ cressi_goa_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
|
||||
goto error_free_dive;
|
||||
}
|
||||
|
||||
if (callback && !callback(dive_data, dive_size, dive_data + FP_OFFSET - 5, sizeof(device->fingerprint), userdata))
|
||||
// Those 5 extra bytes contain the dive mode, which is required for
|
||||
// parsing the dive data. Therefore, insert all 5 bytes again. The
|
||||
// remaining 4 bytes appear to be some 32 bit address.
|
||||
if (!dc_buffer_insert (dive, 2, logbook_data + offset + 2, 5)) {
|
||||
ERROR (abstract->context, "Out of memory.");
|
||||
status = DC_STATUS_NOMEMORY;
|
||||
goto error_free_dive;
|
||||
}
|
||||
|
||||
dive_data = dc_buffer_get_data (dive);
|
||||
dive_size = dc_buffer_get_size (dive);
|
||||
|
||||
if (callback && !callback(dive_data, dive_size, dive_data + FP_OFFSET, sizeof(device->fingerprint), userdata))
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -28,11 +28,23 @@
|
||||
|
||||
#define ISINSTANCE(parser) dc_device_isinstance((parser), &cressi_goa_parser_vtable)
|
||||
|
||||
#define SZ_HEADER 0x5C
|
||||
#define C_ARRAY_SIZE(array) (sizeof (array) / sizeof *(array))
|
||||
|
||||
#define SZ_HEADER 23
|
||||
#define SZ_HEADER_SCUBA 0x61
|
||||
#define SZ_HEADER_FREEDIVE 0x2B
|
||||
#define SZ_HEADER_GAUGE 0x2D
|
||||
|
||||
#define DEPTH 0
|
||||
#define DEPTH2 1
|
||||
#define TIME 2
|
||||
#define TEMPERATURE 3
|
||||
|
||||
#define SCUBA 0
|
||||
#define NITROX 1
|
||||
#define FREEDIVE 2
|
||||
#define GAUGE 3
|
||||
|
||||
typedef struct cressi_goa_parser_t cressi_goa_parser_t;
|
||||
|
||||
struct cressi_goa_parser_t {
|
||||
@ -58,6 +70,13 @@ static const dc_parser_vtable_t cressi_goa_parser_vtable = {
|
||||
NULL /* destroy */
|
||||
};
|
||||
|
||||
static const unsigned int headersizes[] = {
|
||||
SZ_HEADER_SCUBA,
|
||||
SZ_HEADER_SCUBA,
|
||||
SZ_HEADER_FREEDIVE,
|
||||
SZ_HEADER_GAUGE,
|
||||
};
|
||||
|
||||
dc_status_t
|
||||
cressi_goa_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||
{
|
||||
@ -97,17 +116,29 @@ cressi_goa_parser_set_data (dc_parser_t *abstract, const unsigned char *data, un
|
||||
static dc_status_t
|
||||
cressi_goa_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
if (abstract->size < SZ_HEADER)
|
||||
const unsigned char *data = abstract->data;
|
||||
unsigned int size = abstract->size;
|
||||
|
||||
if (size < SZ_HEADER)
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
|
||||
const unsigned char *p = abstract->data;
|
||||
unsigned int divemode = data[2];
|
||||
if (divemode >= C_ARRAY_SIZE(headersizes)) {
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
|
||||
unsigned int headersize = headersizes[divemode];
|
||||
if (size < headersize)
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
|
||||
const unsigned char *p = abstract->data + 0x11;
|
||||
|
||||
if (datetime) {
|
||||
datetime->year = array_uint16_le(p + 0x0C);
|
||||
datetime->month = p[0x0E];
|
||||
datetime->day = p[0x0F];
|
||||
datetime->hour = p[0x10];
|
||||
datetime->minute = p[0x11];
|
||||
datetime->year = array_uint16_le(p);
|
||||
datetime->month = p[2];
|
||||
datetime->day = p[3];
|
||||
datetime->hour = p[4];
|
||||
datetime->minute = p[5];
|
||||
datetime->second = 0;
|
||||
datetime->timezone = DC_TIMEZONE_NONE;
|
||||
}
|
||||
@ -119,10 +150,20 @@ static dc_status_t
|
||||
cressi_goa_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value)
|
||||
{
|
||||
cressi_goa_parser_t *parser = (cressi_goa_parser_t *) abstract;
|
||||
if (abstract->size < SZ_HEADER)
|
||||
const unsigned char *data = abstract->data;
|
||||
unsigned int size = abstract->size;
|
||||
|
||||
if (size < SZ_HEADER)
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
|
||||
const unsigned char *data = abstract->data;
|
||||
unsigned int divemode = data[2];
|
||||
if (divemode >= C_ARRAY_SIZE(headersizes)) {
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
|
||||
unsigned int headersize = headersizes[divemode];
|
||||
if (size < headersize)
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
|
||||
if (!parser->cached) {
|
||||
sample_statistics_t statistics = SAMPLE_STATISTICS_INITIALIZER;
|
||||
@ -140,19 +181,35 @@ cressi_goa_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign
|
||||
if (value) {
|
||||
switch (type) {
|
||||
case DC_FIELD_DIVETIME:
|
||||
*((unsigned int *) value) = array_uint16_le (data + 0x14);
|
||||
*((unsigned int *) value) = array_uint16_le (data + 0x19);
|
||||
break;
|
||||
case DC_FIELD_MAXDEPTH:
|
||||
*((double *) value) = parser->maxdepth;
|
||||
break;
|
||||
case DC_FIELD_GASMIX_COUNT:
|
||||
*((unsigned int *) value) = 2;
|
||||
*((unsigned int *) value) = divemode == SCUBA || divemode == NITROX ? 2 : 0;
|
||||
break;
|
||||
case DC_FIELD_GASMIX:
|
||||
gasmix->helium = 0.0;
|
||||
gasmix->oxygen = data[0x1B + 2 * flags] / 100.0;
|
||||
gasmix->oxygen = data[0x20 + 2 * flags] / 100.0;
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
break;
|
||||
case DC_FIELD_DIVEMODE:
|
||||
switch (divemode) {
|
||||
case SCUBA:
|
||||
case NITROX:
|
||||
*((dc_divemode_t *) value) = DC_DIVEMODE_OC;
|
||||
break;
|
||||
case GAUGE:
|
||||
*((dc_divemode_t *) value) = DC_DIVEMODE_GAUGE;
|
||||
break;
|
||||
case FREEDIVE:
|
||||
*((dc_divemode_t *) value) = DC_DIVEMODE_FREEDIVE;
|
||||
break;
|
||||
default:
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
}
|
||||
@ -167,12 +224,28 @@ cressi_goa_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
||||
const unsigned char *data = abstract->data;
|
||||
unsigned int size = abstract->size;
|
||||
|
||||
unsigned int time = 0;
|
||||
unsigned int interval = 5;
|
||||
unsigned int complete = 1;
|
||||
unsigned int gasmix_previous = 0xFFFFFFFF;
|
||||
if (size < SZ_HEADER)
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
|
||||
unsigned int offset = SZ_HEADER;
|
||||
unsigned int divemode = data[2];
|
||||
if (divemode >= C_ARRAY_SIZE(headersizes)) {
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
|
||||
unsigned int headersize = headersizes[divemode];
|
||||
if (size < headersize)
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
|
||||
unsigned int interval = divemode == FREEDIVE ? 2 : 5;
|
||||
|
||||
unsigned int time = 0;
|
||||
unsigned int depth = 0;
|
||||
unsigned int gasmix = 0, gasmix_previous = 0xFFFFFFFF;
|
||||
unsigned int temperature = 0;
|
||||
unsigned int have_temperature = 0;
|
||||
unsigned int complete = 0;
|
||||
|
||||
unsigned int offset = headersize;
|
||||
while (offset + 2 <= size) {
|
||||
dc_sample_value_t sample = {0};
|
||||
|
||||
@ -181,35 +254,44 @@ cressi_goa_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
||||
unsigned int type = (raw & 0x0003);
|
||||
unsigned int value = (raw & 0xFFFC) >> 2;
|
||||
|
||||
if (complete) {
|
||||
// Time (seconds).
|
||||
if (type == DEPTH || type == DEPTH2) {
|
||||
depth = (value & 0x07FF);
|
||||
gasmix = (value & 0x0800) >> 11;
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
complete = 0;
|
||||
complete = 1;
|
||||
} else if (type == TEMPERATURE) {
|
||||
temperature = value;
|
||||
have_temperature = 1;
|
||||
} else if (type == TIME) {
|
||||
time += value;
|
||||
}
|
||||
|
||||
if (type == DEPTH) {
|
||||
if (complete) {
|
||||
// Time (seconds).
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
|
||||
// Temperature (1/10 °C).
|
||||
if (have_temperature) {
|
||||
sample.temperature = temperature / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
have_temperature = 0;
|
||||
}
|
||||
|
||||
// Depth (1/10 m).
|
||||
unsigned int depth = value & 0x07FF;
|
||||
sample.depth = depth / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
|
||||
// Gas change.
|
||||
unsigned int gasmix = (value & 0x0800) >> 11;
|
||||
if (gasmix != gasmix_previous) {
|
||||
sample.gasmix = gasmix;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||
gasmix_previous = gasmix;
|
||||
// Gas change
|
||||
if (divemode == SCUBA || divemode == NITROX) {
|
||||
if (gasmix != gasmix_previous) {
|
||||
sample.gasmix = gasmix;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||
gasmix_previous = gasmix;
|
||||
}
|
||||
}
|
||||
|
||||
complete = 1;
|
||||
} else if (type == TEMPERATURE) {
|
||||
// Temperature (1/10 °C).
|
||||
sample.temperature = value / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
} else {
|
||||
WARNING(abstract->context, "Unknown sample type %u.", type);
|
||||
complete = 0;
|
||||
}
|
||||
|
||||
offset += 2;
|
||||
|
||||
@ -8,6 +8,7 @@ dc_buffer_reserve
|
||||
dc_buffer_resize
|
||||
dc_buffer_append
|
||||
dc_buffer_prepend
|
||||
dc_buffer_insert
|
||||
dc_buffer_slice
|
||||
dc_buffer_get_size
|
||||
dc_buffer_get_data
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user