Merge branch 'ix3m'

This commit is contained in:
Jef Driesen 2017-05-24 07:18:19 +02:00
commit e2d623fc65
3 changed files with 66 additions and 13 deletions

View File

@ -290,8 +290,15 @@ static const dc_descriptor_t g_descriptors[] = {
{"DiveSystem", "iDive Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x0B},
{"DiveSystem", "iX3M Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x22},
{"DiveSystem", "iX3M Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x23},
{"DiveSystem", "iX3M Tec", DC_FAMILY_DIVESYSTEM_IDIVE, 0x24},
{"DiveSystem", "iX3M Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x24},
{"DiveSystem", "iX3M Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x25},
{"DiveSystem", "iX3M Pro Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x32},
{"DiveSystem", "iX3M Pro Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x34},
{"DiveSystem", "iX3M Pro Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x35},
{"DiveSystem", "iDive2 Free", DC_FAMILY_DIVESYSTEM_IDIVE, 0x40},
{"DiveSystem", "iDive2 Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x42},
{"DiveSystem", "iDive2 Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x44},
{"DiveSystem", "iDive2 Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x45},
{"Cochran", "Commander", DC_FAMILY_COCHRAN_COMMANDER, 0},
{"Cochran", "EMC-14", DC_FAMILY_COCHRAN_COMMANDER, 1},
{"Cochran", "EMC-16", DC_FAMILY_COCHRAN_COMMANDER, 2},

View File

@ -57,6 +57,7 @@ typedef struct divesystem_idive_commands_t {
divesystem_idive_command_t range;
divesystem_idive_command_t header;
divesystem_idive_command_t sample;
unsigned int nsamples;
} divesystem_idive_commands_t;
typedef struct divesystem_idive_device_t {
@ -86,6 +87,7 @@ static const divesystem_idive_commands_t idive = {
{0x98, 0x04},
{0xA0, 0x32},
{0xA8, 0x2A},
1,
};
static const divesystem_idive_commands_t ix3m = {
@ -93,6 +95,15 @@ static const divesystem_idive_commands_t ix3m = {
{0x78, 0x04},
{0x79, 0x36},
{0x7A, 0x36},
1,
};
static const divesystem_idive_commands_t ix3m_apos4 = {
{0x11, 0x1A},
{0x78, 0x04},
{0x79, 0x36},
{0x7A, 0x40},
3,
};
dc_status_t
@ -356,7 +367,7 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
unsigned char packet[MAXPACKET - 2];
const divesystem_idive_commands_t *commands = &idive;
if (device->model >= IX3M_EASY && device->model <= IX3M_REB) {
if (device->model >= IX3M_EASY) {
commands = &ix3m;
}
@ -372,7 +383,7 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
// Emit a device info event.
dc_event_devinfo_t devinfo;
devinfo.model = array_uint16_le (packet);
devinfo.firmware = 0;
devinfo.firmware = array_uint32_le (packet + 2);
devinfo.serial = array_uint32_le (packet + 6);
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);
@ -382,6 +393,14 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
vendor.size = commands->id.size;
device_event_emit (abstract, DC_EVENT_VENDOR, &vendor);
if (device->model >= IX3M_EASY) {
// Detect the APOS4 firmware.
unsigned int apos4 = (devinfo.firmware / 10000000) >= 4;
if (apos4) {
commands = &ix3m_apos4;
}
}
unsigned char cmd_range[] = {commands->range.cmd, 0x8D};
rc = divesystem_idive_transfer (device, cmd_range, sizeof(cmd_range), packet, commands->range.size);
if (rc != DC_STATUS_SUCCESS)
@ -429,20 +448,28 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
dc_buffer_reserve(buffer, commands->header.size + commands->sample.size * nsamples);
dc_buffer_append(buffer, packet, commands->header.size);
for (unsigned int j = 0; j < nsamples; ++j) {
for (unsigned int j = 0; j < nsamples; j += commands->nsamples) {
unsigned int idx = j + 1;
unsigned char cmd_sample[] = {commands->sample.cmd,
(idx ) & 0xFF,
(idx >> 8) & 0xFF};
rc = divesystem_idive_transfer (device, cmd_sample, sizeof(cmd_sample), packet, commands->sample.size);
rc = divesystem_idive_transfer (device, cmd_sample, sizeof(cmd_sample), packet, commands->sample.size * commands->nsamples);
if (rc != DC_STATUS_SUCCESS)
return rc;
// If the number of samples is not an exact multiple of the
// number of samples per packet, then the last packet
// appears to contain garbage data. Ignore those samples.
unsigned int n = commands->nsamples;
if (j + n > nsamples) {
n = nsamples - j;
}
// Update and emit a progress event.
progress.current = i * NSTEPS + STEP(j + 2, nsamples + 1);
progress.current = i * NSTEPS + STEP(j + n + 1, nsamples + 1);
device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
dc_buffer_append(buffer, packet, commands->sample.size);
dc_buffer_append(buffer, packet, commands->sample.size * n);
}
unsigned char *data = dc_buffer_get_data(buffer);

View File

@ -37,6 +37,7 @@
#define SZ_SAMPLE_IDIVE 0x2A
#define SZ_HEADER_IX3M 0x36
#define SZ_SAMPLE_IX3M 0x36
#define SZ_SAMPLE_IX3M_APOS4 0x40
#define NGASMIXES 8
@ -53,8 +54,8 @@ typedef struct divesystem_idive_parser_t divesystem_idive_parser_t;
struct divesystem_idive_parser_t {
dc_parser_t base;
unsigned int model;
unsigned int headersize;
unsigned int samplesize;
// Cached fields.
unsigned int cached;
unsigned int divemode;
@ -97,12 +98,11 @@ divesystem_idive_parser_create (dc_parser_t **out, dc_context_t *context, unsign
}
// Set the default values.
if (model >= IX3M_EASY && model <= IX3M_REB) {
parser->model = model;
if (model >= IX3M_EASY) {
parser->headersize = SZ_HEADER_IX3M;
parser->samplesize = SZ_SAMPLE_IX3M;
} else {
parser->headersize = SZ_HEADER_IDIVE;
parser->samplesize = SZ_SAMPLE_IDIVE;
}
parser->cached = 0;
parser->divemode = INVALID;
@ -241,8 +241,27 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
unsigned int mode_previous = INVALID;
unsigned int divemode = INVALID;
unsigned int nsamples = array_uint16_le (data + 1);
unsigned int samplesize = SZ_SAMPLE_IDIVE;
if (parser->model >= IX3M_EASY) {
// Detect the APOS4 firmware.
unsigned int firmware = array_uint32_le(data + 0x2A);
unsigned int apos4 = (firmware / 10000000) >= 4;
if (apos4) {
// Dive downloaded and recorded with the APOS4 firmware.
samplesize = SZ_SAMPLE_IX3M_APOS4;
} else if (size == parser->headersize + nsamples * SZ_SAMPLE_IX3M_APOS4) {
// Dive downloaded with the APOS4 firmware, but recorded
// with an older firmware.
samplesize = SZ_SAMPLE_IX3M_APOS4;
} else {
// Dive downloaded and recorded with an older firmware.
samplesize = SZ_SAMPLE_IX3M;
}
}
unsigned int offset = parser->headersize;
while (offset + parser->samplesize <= size) {
while (offset + samplesize <= size) {
dc_sample_value_t sample = {0};
// Time (seconds).
@ -328,7 +347,7 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
sample.cns = cns / 100.0;
if (callback) callback (DC_SAMPLE_CNS, sample, userdata);
offset += parser->samplesize;
offset += samplesize;
}
// Cache the data for later use.