I removed the conf member from the data struct, that's not being carried around any more. Each function that needs layout information will be call cochran_commander_get_layout to obtain the layout to use in parsing the data. --- src/cochran_commander.c | 320 ++++++++++++++++++++++------------------- src/cochran_commander.h | 54 +++++-- src/cochran_commander_parser.c | 19 +-- 3 files changed, 224 insertions(+), 169 deletions(-)
diff --git a/src/cochran_commander.c b/src/cochran_commander.c index 2287541..036ca6c 100644 --- a/src/cochran_commander.c +++ b/src/cochran_commander.c @@ -38,6 +38,105 @@ rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \ )
+ +/* +* Hardware and data layout information for various Cochran models. +* +* EMC models are identical except for the size of logbook and profile +* memory. +*/ +static cochran_layout_t cochran_layout_cmdr = { + COCHRAN_MODEL_COMMANDER_AIR_NITROX, /* model */ + ENDIAN_BE, /* endian */ + DATE_MSDHYM, /* date_format */ + ADDRESS_24_BIT, /* address_size */ + 115200, /* high_baud_rate */ + + 0x00000000, /* rb_logbook_begin */ + 0x00020000, /* rb_logbook_end */ + 256, /* rb_log_size */ + 0x00020000, /* rb_profile_begin */ + 0x00100000, /* rb_profile_end */ + + 0x006, /* pt_log_profile_begin */ + 0x01e, /* pt_log_profile_pre */ + 0x046, /* pt_log_dive_number */ + 0x080, /* pt_log_profile_end */ + + 0x046, /* pt_conf_dive_count */ + 0x06e, /* pt_conf_last_log */ + 0x0a7, /* pt_conf_last_interdive */ +}; + +static cochran_layout_t cochran_layout_emc20 = { + COCHRAN_MODEL_EMC_20, /* model */ + ENDIAN_LE, /* endian */ + DATE_SMHDMY, /* date_format */ + ADDRESS_32_BIT, /* address_size */ + 825600, /* high_baud_rate */ + + 0x00000000, /* rb_logbook_begin */ + 0x00080000, /* rb_logbook_end */ + 512, /* rb_log_size */ + 0x00094000, /* rb_profile_begin */ + 0x01000000, /* rb_profile_end */ + + 0x006, /* pt_log_profile_begin */ + 0x01e, /* pt_log_profile_pre */ + 0x056, /* pt_log_dive_number */ + 0x100, /* pt_log_profile_end */ + + 0x0d2, /* pt_conf_dive_count */ + 0x142, /* pt_conf_last_log */ + 0x13e, /* pt_conf_last_interdive */ +}; + +static cochran_layout_t cochran_layout_emc16 = { + COCHRAN_MODEL_EMC_16, /* model */ + ENDIAN_LE, /* endian */ + DATE_SMHDMY, /* date_format */ + ADDRESS_32_BIT, /* address_size */ + 825600, /* high_baud_rate */ + + 0x00000000, /* rb_logbook_begin */ + 0x00080000, /* rb_logbook_end */ + 512, /* rb_log_size */ + 0x00094000, /* rb_profile_begin */ + 0x00800000, /* rb_profile_end */ + + 0x006, /* pt_log_profile_begin */ + 0x01e, /* pt_log_profile_pre */ + 0x056, /* pt_log_dive_number */ + 0x100, /* pt_log_profile_end */ + + 0x0d2, /* pt_conf_dive_count */ + 0x142, /* pt_conf_last_log */ + 0x13e, /* pt_conf_last_interdive */ +}; + +static cochran_layout_t cochran_layout_emc14 = { + COCHRAN_MODEL_EMC_14, /* model */ + ENDIAN_LE, /* endian */ + DATE_SMHDMY, /* date_format */ + ADDRESS_32_BIT, /* address_size */ + 825600, /* high_baud_rate */ + + 0x00000000, /* rb_logbook_begin */ + 0x00020000, /* rb_logbook_end */ + 512, /* rb_log_size */ + 0x00022000, /* rb_profile_begin */ + 0x00200000, /* rb_profile_end */ + + 0x006, /* pt_log_profile_begin */ + 0x01e, /* pt_log_profile_pre */ + 0x056, /* pt_log_dive_number */ + 0x100, /* pt_log_profile_end */ + + 0x0d2, /* pt_conf_dive_count */ + 0x142, /* pt_conf_last_log */ + 0x13e, /* pt_conf_last_interdive */ +}; + static const dc_device_vtable_t cochran_commander_device_vtable = { DC_FAMILY_COCHRAN_COMMANDER, cochran_commander_device_set_fingerprint, /* set_fingerprint */ @@ -83,7 +182,8 @@ cochran_packet (cochran_device_t *device, dc_event_progress_t *progress, serial_sleep(device->port, 45);
// Rates are odd, like 825600 for the EMC, 115200 for commander - rc = serial_configure(device->port, device->data.conf.high_baud, 8, + cochran_layout_t *layout = cochran_commander_get_layout(device->model_string); + rc = serial_configure(device->port, layout->high_baud_rate, 8, SERIAL_PARITY_NONE, 2, SERIAL_FLOWCONTROL_NONE); if (rc == -1) { ERROR (abstract->context, "Failed to set the high baud rate."); @@ -142,7 +242,7 @@ cochran_commander_serial_setup (cochran_device_t *device, dc_context_t *context)
serial_set_break(device->port, 1); serial_sleep(device->port, 16); - + serial_set_break(device->port, 0);
// Set the timeout for receiving data (5000 ms). @@ -185,6 +285,7 @@ cochran_commander_device_open (dc_device_t **out, dc_context_t *context, const char *name) { dc_status_t rc; + cochran_layout_t *layout;
if (out == NULL) return DC_STATUS_INVALIDARGS; @@ -222,14 +323,18 @@ cochran_commander_device_open (dc_device_t **out, dc_context_t *context, return rc; }
+ memcpy(device->model_string, device->data.id + 0x3b, 8); + device->model_string[8] = 0; + layout = cochran_commander_get_layout(device->model_string); + // Check ID - if ((device->data.conf.model & 0xFF0000) == COCHRAN_MODEL_UNKNOWN) { + if ((layout->model & 0xFF0000) == COCHRAN_MODEL_UNKNOWN) { ERROR (context, "Unknown Cochran model %02x %02x %02x %02x %02x %02x %02x %02x", - *(device->data.id + 0x3B), *(device->data.id + 0x3B + 1), - *(device->data.id + 0x3B + 2), *(device->data.id + 0x3B + 3), - *(device->data.id + 0x3B + 4), *(device->data.id + 0x3B + 5), - *(device->data.id + 0x3B + 6), *(device->data.id + 0x3B + 7)); + device->model_string[0], device->model_string[1], + device->model_string[2], device->model_string[3], + device->model_string[4], device->model_string[5], + device->model_string[6], device->model_string[7]); serial_close (device->port); free (device); return DC_STATUS_UNSUPPORTED; @@ -293,14 +398,15 @@ cochran_commander_read (dc_device_t *abstract, dc_event_progress_t *progress, unsigned int address, unsigned char data[], unsigned int size) { cochran_device_t *device = (cochran_device_t*) abstract; + cochran_layout_t *layout = cochran_commander_get_layout(device->model_string);
// Build the command unsigned char command[10]; unsigned char command_size;
- switch (device->data.conf.address_length) + switch (layout->address_size) { - case COCHRAN_ADDRESS_LENGTH_32: + case ADDRESS_32_BIT: // EMC uses 32 bit addressing command[0] = 0x15; command[1] = (address ) & 0xff; @@ -314,7 +420,7 @@ cochran_commander_read (dc_device_t *abstract, dc_event_progress_t *progress, command[9] = 0x05; command_size = 10; break; - case COCHRAN_ADDRESS_LENGTH_24: + case ADDRESS_24_BIT: // Commander uses 24 byte addressing command[0] = 0x15; command[1] = (address ) & 0xff; @@ -339,89 +445,28 @@ cochran_commander_read (dc_device_t *abstract, dc_event_progress_t *progress, }
-void -cochran_commander_get_config (const unsigned char *model, - cochran_config_t *conf) +cochran_layout_t * +cochran_commander_get_layout (const unsigned char *model) { // Determine model if (memcmp(model, "AM2315\xA3\x71", 8) == 0) { - conf->model = COCHRAN_MODEL_EMC_20; - conf->log_size = 512; - conf->sample_memory_start_address = 0x94000; - conf->sample_memory_end_address = 0x1000000; // 16MB - conf->dive_num_ptr = 0x56; - conf->dive_count_ptr = 0xD2; - conf->dive_count_endian = COCHRAN_LE_TYPE; - conf->sample_end_ptr = 256; - conf->log_pre_dive_ptr = 30; - conf->log_end_dive_ptr = 256; - conf->last_interdive_ptr = 233; - conf->last_entry_ptr = 194; - conf->date_format = COCHRAN_DATE_FORMAT_SMHDMY; - conf->address_length = COCHRAN_ADDRESS_LENGTH_32; - conf->high_baud = 825600; + return &cochran_layout_emc20; } else if (memcmp(model, "AMA315\xC3\xC5", 8) == 0) { - conf->model = COCHRAN_MODEL_EMC_16; - conf->log_size = 512; - conf->sample_memory_start_address = 0x94000; - conf->sample_memory_end_address = 0x800000; // 8MB, a guess - conf->dive_num_ptr = 0x56; - conf->dive_count_ptr = 0xD2; - conf->dive_count_endian = COCHRAN_LE_TYPE; - conf->sample_end_ptr = 256; - conf->log_pre_dive_ptr = 30; - conf->log_end_dive_ptr = 256; - conf->last_interdive_ptr = 233; - conf->last_entry_ptr = 194; - conf->date_format = COCHRAN_DATE_FORMAT_SMHDMY; - conf->address_length = COCHRAN_ADDRESS_LENGTH_32; - conf->high_baud = 825600; + return &cochran_layout_emc16; } else if (memcmp(model, "AM7303\x8b\x43", 8) == 0) { - conf->model = COCHRAN_MODEL_EMC_14; - conf->log_size = 512; - conf->sample_memory_start_address = 0x22000; - conf->sample_memory_end_address = 0x200000; // 2MB, a guess - conf->dive_num_ptr = 0x56; - conf->dive_count_ptr = 0xD2; - conf->dive_count_endian = COCHRAN_LE_TYPE; - conf->sample_end_ptr = 256; - conf->log_pre_dive_ptr = 30; - conf->log_end_dive_ptr = 256; - conf->last_interdive_ptr = 233; - conf->last_entry_ptr = 194; - conf->date_format = COCHRAN_DATE_FORMAT_SMHDMY; - conf->address_length = COCHRAN_ADDRESS_LENGTH_32; - conf->high_baud = 825600; + return &cochran_layout_emc14; } else if (memcmp(model, "AM\x11""2212\x02", 8) == 0) { - conf->model = COCHRAN_MODEL_COMMANDER_AIR_NITROX; - conf->log_size = 256; - conf->sample_memory_start_address = 0x20000; - conf->sample_memory_end_address = 0x100000; - conf->dive_num_ptr = 0x46; - conf->dive_count_ptr = 0x46; - conf->dive_count_endian = COCHRAN_BE_TYPE; - conf->sample_end_ptr = 256; - conf->log_pre_dive_ptr = 30; - conf->log_end_dive_ptr = 128; - conf->last_interdive_ptr = 167; - conf->last_entry_ptr = -1; - conf->date_format = COCHRAN_DATE_FORMAT_MSDHYM; - conf->address_length = COCHRAN_ADDRESS_LENGTH_24; - conf->high_baud = 115200; - } - else - { - conf->model = 0; + return &cochran_layout_cmdr; }
- return; + return NULL; }
@@ -449,9 +494,6 @@ cochran_read_id (dc_device_t *abstract) return rc; }
- cochran_commander_get_config(device->data.id + 0x3B, &device->data.conf); - - return DC_STATUS_SUCCESS; }
@@ -488,10 +530,11 @@ cochran_read_misc (dc_device_t *abstract, dc_event_progress_t *progress) cochran_device_t *device = (cochran_device_t *) abstract; dc_status_t rc; dc_event_vendor_t vendor; + cochran_layout_t *layout = cochran_commander_get_layout(device->model_string);
unsigned char command[7] = { 0x89, 0x05, 0x00, 0x00, 0x00, 0xDC, 0x05 };
- switch (device->data.conf.model & 0xFF0000) + switch (layout->model & 0xFF0000) { case COCHRAN_MODEL_COMMANDER_FAMILY: command[2] = 0xCA; @@ -563,14 +606,14 @@ cochran_find_fingerprint(dc_device_t *abstract) { cochran_device_t *device = (cochran_device_t *) abstract; cochran_data_t *d = (cochran_data_t *) &device->data; - cochran_config_t *conf = &d->conf; + cochran_layout_t *layout = cochran_commander_get_layout(device->model_string);
// Skip to fingerprint to reduce time d->fp_dive_num = d->dive_count - 1;
while (d->fp_dive_num >= 0 && memcmp(&d->fingerprint, - d->logbook + d->fp_dive_num * conf->log_size - + conf->dive_num_ptr, + d->logbook + d->fp_dive_num * layout->rb_log_size + + layout->pt_log_dive_number, sizeof(d->fingerprint))) d->fp_dive_num--; } @@ -581,9 +624,9 @@ cochran_get_sample_parms(dc_device_t *abstract) { cochran_device_t *device = (cochran_device_t *) abstract; cochran_data_t *d = (cochran_data_t *) &device->data; - cochran_config_t *conf = &d->conf; unsigned int pre_dive_offset = 0, end_dive_offset = 0; unsigned int low_offset, high_offset; + cochran_layout_t *layout = cochran_commander_get_layout(device->model_string);
// Find lowest and highest offsets into sample data low_offset = 0xFFFFFFFF; @@ -591,15 +634,15 @@ cochran_get_sample_parms(dc_device_t *abstract)
int i; for (i = d->fp_dive_num + 1; i < d->dive_count; i++) { - pre_dive_offset = array_uint32_le (&(d->logbook[i * conf->log_size - + conf->log_pre_dive_ptr])); - end_dive_offset = array_uint32_le (&(d->logbook[i * conf->log_size - + conf->log_end_dive_ptr])); + pre_dive_offset = array_uint32_le (&(d->logbook[i * layout->rb_log_size + + layout->pt_log_profile_pre])); + end_dive_offset = array_uint32_le (&(d->logbook[i * layout->rb_log_size + + layout->pt_log_profile_begin]));
// Check for ring buffer wrap-around. if (pre_dive_offset > end_dive_offset) break; - + if (pre_dive_offset < low_offset) low_offset = pre_dive_offset; if (end_dive_offset > high_offset && end_dive_offset != 0xFFFFFFFF ) @@ -611,8 +654,8 @@ cochran_get_sample_parms(dc_device_t *abstract) // I'll round to 128K, dives longer than 12 hrs aren't likely // and memory in sizes not rounded to 128K might be odd. high_offset = ((pre_dive_offset - 1) & 0xE0000) + 0x20000; - conf->sample_memory_end_address = high_offset; - low_offset = conf->sample_memory_start_address; + layout->rb_profile_end = high_offset; + low_offset = layout->rb_profile_begin; d->sample_data_offset = low_offset; d->sample_size = high_offset - low_offset; } else if (low_offset < 0xFFFFFFFF && high_offset > 0) { @@ -668,25 +711,19 @@ cochran_commander_device_read_all (dc_device_t *abstract) { cochran_device_t *device = (cochran_device_t *) abstract; cochran_data_t *d = (cochran_data_t *) &device->data; - cochran_config_t *conf = &d->conf; dc_event_progress_t progress = {0}; + cochran_layout_t *layout = cochran_commander_get_layout(device->model_string);
dc_status_t rc; - int sample_size; - int max_config, max_misc, max_logbook, max_sample; + int max_config, max_logbook, max_sample;
- if ((conf->model & 0xFFFF0000) == COCHRAN_MODEL_COMMANDER_FAMILY) - sample_size = 2; - else - sample_size = 3; - - max_config = 512 * 4; // max config page size - max_misc = 1500; // misc size - max_logbook = 1024 * conf->log_size; // max logbook size - max_sample = 1450 * 3600 * sample_size; // max sample size + // Calculate max data sizes + max_config = 512 * 2; + max_logbook =layout->rb_logbook_end - layout->rb_logbook_begin; + max_sample = layout->rb_profile_end - layout->rb_profile_begin;
progress.current = 0; - progress.maximum = max_config + max_misc + max_logbook + max_sample; + progress.maximum = max_config + max_logbook + max_sample; device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
// Read config @@ -694,21 +731,13 @@ cochran_commander_device_read_all (dc_device_t *abstract) if (rc != DC_STATUS_SUCCESS) return rc;
- // Update max based on what's read - progress.maximum -= max_config - progress.current; - device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); - - rc = cochran_read_misc(abstract, &progress); - if (rc != DC_STATUS_SUCCESS) - return rc; - // Determine size of dive list to read. Round up to nearest 16K - if (conf->dive_count_endian == COCHRAN_LE_TYPE) - d->dive_count = array_uint16_le (d->config[0] + conf->dive_count_ptr); - else - d->dive_count = array_uint16_be (d->config[0] + conf->dive_count_ptr); - - d->logbook_size = ((d->dive_count * conf->log_size) & 0xFFFFC000) + if (layout->endian == ENDIAN_LE) + d->dive_count = array_uint16_le (d->config[0] + layout->pt_conf_dive_count); + else + d->dive_count = array_uint16_be (d->config[0] + layout->pt_conf_dive_count); + + d->logbook_size = ((d->dive_count * layout->rb_log_size) & 0xFFFFC000) + 0x4000;
progress.maximum -= max_logbook - d->logbook_size; @@ -719,7 +748,7 @@ cochran_commander_device_read_all (dc_device_t *abstract) return rc;
// Determine sample memory to read - cochran_find_fingerprint(abstract); + cochran_find_fingerprint(abstract); cochran_get_sample_parms(abstract);
progress.maximum -= max_sample - d->sample_size; @@ -745,6 +774,7 @@ cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *data) cochran_data_t *d = (cochran_data_t *) &device->data; dc_event_progress_t progress = {0}; dc_event_vendor_t vendor; + cochran_layout_t *layout = cochran_commander_get_layout(device->model_string);
dc_status_t rc; int size; @@ -756,7 +786,7 @@ cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *data) }
// Determine size for progress - size = 512 + 512 + 1500 + d->conf.sample_memory_end_address; + size = 512 + 512 + 1500 + layout->rb_profile_end;
progress.current = 0; progress.maximum = size; @@ -776,7 +806,7 @@ cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *data) rc = cochran_read_config (abstract, &progress); if (rc != DC_STATUS_SUCCESS) return rc; - + rc = cochran_read_misc (abstract, &progress); if (rc != DC_STATUS_SUCCESS) return rc; @@ -784,7 +814,7 @@ cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *data) // Read logbook and sample memory
// Reserve space - if (!dc_buffer_resize(data, d->conf.sample_memory_end_address)) { + if (!dc_buffer_resize(data, layout->rb_profile_end)) { ERROR(abstract->context, "Insufficient buffer space available."); return DC_STATUS_NOMEMORY; } @@ -795,8 +825,8 @@ cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *data) cochran_commander_serial_setup(device, abstract->context);
// Read the sample data, from 0 to sample end will include logbook - rc = cochran_commander_read (abstract, &progress, 0, - dc_buffer_get_data(data), d->conf.sample_memory_end_address); + rc = cochran_commander_read (abstract, &progress, 0, + dc_buffer_get_data(data), layout->rb_profile_end); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to read the sample data."); return rc; @@ -813,18 +843,17 @@ cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *data) */
static unsigned int -cochran_guess_sample_end_address(cochran_data_t *data, unsigned int log_num) +cochran_guess_sample_end_address(cochran_layout_t *layout, cochran_data_t *data, unsigned int log_num) { - cochran_config_t *conf = &data->conf; - const unsigned char *log = data->logbook + data->conf.log_size * log_num; + const unsigned char *log = data->logbook + layout->rb_log_size * log_num;
if (log_num == data->dive_count) // Return next usable address from config0 page return array_uint32_le(data->config[0] - + conf->sample_memory_end_address); + + layout->rb_profile_end);
// Next log's start address - return array_uint32_le(log + conf->log_size + 6); + return array_uint32_le(log + layout->rb_log_size + 6); }
@@ -834,7 +863,7 @@ cochran_commander_device_foreach (dc_device_t *abstract, { cochran_device_t *device = (cochran_device_t *) abstract; cochran_data_t *data = &device->data; - cochran_config_t *conf = &data->conf; + cochran_layout_t *layout = cochran_commander_get_layout(device->model_string);
unsigned int sample_start_address, sample_end_address; dc_status_t rc; @@ -850,14 +879,14 @@ cochran_commander_device_foreach (dc_device_t *abstract, // Loop through each dive int i; for (i = data->dive_count - 1; i > data->fp_dive_num; i--) { - log = data->logbook + i * conf->log_size; + log = data->logbook + i * layout->rb_log_size;
sample_start_address = array_uint32_le (log + 6); - sample_end_address = array_uint32_le (log + conf->log_size / 2); + sample_end_address = array_uint32_le (log + layout->rb_log_size / 2);
if (sample_end_address == 0xFFFFFFFF) // Corrupt dive, guess the end address - sample_end_address = cochran_guess_sample_end_address(data, i); + sample_end_address = cochran_guess_sample_end_address(layout, data, i);
sample = data->sample + sample_start_address - data->sample_data_offset;
@@ -865,28 +894,29 @@ cochran_commander_device_foreach (dc_device_t *abstract, sample_size = sample_end_address - sample_start_address; if (sample_size < 0) // Adjust for ring buffer wrap-around - sample_size += conf->sample_memory_end_address - - conf->sample_memory_start_address; + sample_size += layout->rb_profile_end + - layout->rb_profile_begin;
- fingerprint = log + conf->dive_num_ptr; + fingerprint = log + layout->pt_log_dive_number;
// Build dive blob - dive_size = COCHRAN_MODEL_SIZE + conf->log_size + sample_size; + dive_size = COCHRAN_MODEL_SIZE + layout->rb_log_size + sample_size; dive = malloc(dive_size); if (dive == NULL) return DC_STATUS_NOMEMORY;
- memcpy(dive, data->id + 0x3B, 8); // model string - memcpy(dive + COCHRAN_MODEL_SIZE, log, conf->log_size); + memcpy(dive, data->id + 0x3B, 8); // model string + memcpy(dive + COCHRAN_MODEL_SIZE, log, layout->rb_log_size); + if (sample_start_address <= sample_end_address) { - memcpy(dive + COCHRAN_MODEL_SIZE + conf->log_size, sample, + memcpy(dive + COCHRAN_MODEL_SIZE + layout->rb_log_size, sample, sample_size); } else { // It wrapped the buffer, copy two sections - unsigned int size = conf->sample_memory_end_address + unsigned int size = layout->rb_profile_end - sample_start_address; - memcpy(dive + COCHRAN_MODEL_SIZE + conf->log_size, sample, size); - memcpy(dive + COCHRAN_MODEL_SIZE + conf->log_size + size, + memcpy(dive + COCHRAN_MODEL_SIZE + layout->rb_log_size, sample, size); + memcpy(dive + COCHRAN_MODEL_SIZE + layout->rb_log_size + size, data->sample, sample_size - size); }
diff --git a/src/cochran_commander.h b/src/cochran_commander.h index 57962d8..f9d09ec 100644 --- a/src/cochran_commander.h +++ b/src/cochran_commander.h @@ -32,15 +32,6 @@ #define COCHRAN_CMDR_LOG_SIZE 256 #define COCHRAN_CMDR_SAMPLE_SIZE 2
-#define COCHRAN_LE_TYPE 0 -#define COCHRAN_BE_TYPE 1 - -#define COCHRAN_DATE_FORMAT_SMHDMY 0 -#define COCHRAN_DATE_FORMAT_MSDHYM 1 - -#define COCHRAN_ADDRESS_LENGTH_32 0 -#define COCHRAN_ADDRESS_LENGTH_24 1 - typedef enum cochran_model_t { COCHRAN_MODEL_UNKNOWN = 0, COCHRAN_MODEL_EMC_FAMILY = 1 << 16, @@ -51,7 +42,46 @@ typedef enum cochran_model_t { COCHRAN_MODEL_COMMANDER_AIR_NITROX, } cochran_model_t;
+typedef enum cochran_endian_t { + ENDIAN_LE, + ENDIAN_BE, +} cochran_endian_t; + +typedef enum cochran_dateformat_t { + DATE_SMHDMY, + DATE_MSDHYM, +} cochran_dateformat_t; + +typedef enum cochran_addresssize_t { + ADDRESS_24_BIT, + ADDRESS_32_BIT, +} cochran_addresssize_t; + +typedef struct cochran_layout_t { + cochran_model_t model; + cochran_endian_t endian; + cochran_dateformat_t date_format; + cochran_addresssize_t address_size; + unsigned int high_baud_rate; + + unsigned int rb_logbook_begin; + unsigned int rb_logbook_end; + unsigned int rb_log_size; + unsigned int rb_profile_begin; + unsigned int rb_profile_end; + + unsigned int pt_log_profile_begin; + unsigned int pt_log_profile_pre; + unsigned int pt_log_dive_number; + unsigned int pt_log_profile_end; + + unsigned int pt_conf_dive_count; + unsigned int pt_conf_last_log; + unsigned int pt_conf_last_interdive; +} cochran_layout_t; + // Device configuration items +/* typedef struct cochran_config_t { cochran_model_t model; int log_size; @@ -69,6 +99,7 @@ typedef struct cochran_config_t { int address_length; int high_baud; // baud rate to switch to for log/sample download } cochran_config_t; +*/
typedef struct cochran_data_t { unsigned char id0[67]; @@ -89,14 +120,13 @@ typedef struct cochran_data_t {
unsigned int sample_data_offset; unsigned int sample_size; - - cochran_config_t conf; } cochran_data_t;
typedef struct cochran_device_t { dc_device_t base; const char *name; // serial port name serial_t *port; + unsigned char model_string[COCHRAN_MODEL_SIZE + 1]; cochran_data_t data; // dive data used in parsing } cochran_device_t;
@@ -156,4 +186,4 @@ dc_status_t cochran_commander_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata); dc_status_t cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *data); -void cochran_commander_get_config(const unsigned char *model, cochran_config_t *conf); +cochran_layout_t *cochran_commander_get_layout(const unsigned char *model); diff --git a/src/cochran_commander_parser.c b/src/cochran_commander_parser.c index 8db87cf..434d332 100644 --- a/src/cochran_commander_parser.c +++ b/src/cochran_commander_parser.c @@ -109,11 +109,10 @@ cochran_commander_parser_get_datetime (dc_parser_t *abstract, { const unsigned char *data = abstract->data; const unsigned char *log = data + COCHRAN_MODEL_SIZE; - cochran_config_t conf; + // abstract->data is prefixed by the model string + cochran_layout_t *layout = cochran_commander_get_layout(data);
- cochran_commander_get_config(data, &conf); - - if (conf.date_format == COCHRAN_DATE_FORMAT_SMHDMY) { + if (layout->date_format == DATE_SMHDMY) { datetime->second = log[0]; datetime->minute = log[1]; datetime->hour = log[2]; @@ -136,11 +135,9 @@ static dc_status_t cochran_commander_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value) { - cochran_config_t conf; - - cochran_commander_get_config(abstract->data, &conf); + cochran_layout_t *layout = cochran_commander_get_layout(abstract->data);
- switch (conf.model & 0xFF0000) + switch (layout->model & 0xFF0000) { case COCHRAN_MODEL_COMMANDER_FAMILY: return cochran_cmdr_parser_get_field(abstract, type, flags, value); @@ -157,11 +154,9 @@ static dc_status_t cochran_commander_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata) { - cochran_config_t conf; - - cochran_commander_get_config(abstract->data, &conf); + cochran_layout_t *layout = cochran_commander_get_layout(abstract->data);
- switch (conf.model & 0xFF0000) + switch (layout->model & 0xFF0000) { case COCHRAN_MODEL_COMMANDER_FAMILY: return cochran_cmdr_parser_samples_foreach(abstract, callback,