--- src/libdivecomputer.symbols | 3 --- 1 file changed, 3 deletions(-)
diff --git a/src/libdivecomputer.symbols b/src/libdivecomputer.symbols index fd8f44a..a870a22 100644 --- a/src/libdivecomputer.symbols +++ b/src/libdivecomputer.symbols @@ -170,8 +170,5 @@ shearwater_predator_extract_dives shearwater_petrel_device_open diverite_nitekq_device_open diverite_nitekq_extract_dives -<<<<<<< HEAD cochran_commander_device_open -======= citizen_aqualand_device_open ->>>>>>> 134da18190b5ea1581d789564979e3e4c73cd243
The emc14 sample memory start address had been set to 0x94000 and should be 0x20000. --- src/cochran_commander.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/cochran_commander.c b/src/cochran_commander.c index 895c859..a1be22f 100644 --- a/src/cochran_commander.c +++ b/src/cochran_commander.c @@ -382,7 +382,7 @@ cochran_commander_get_config (const unsigned char *model, { conf->model = COCHRAN_MODEL_EMC_14; conf->log_size = 512; - conf->sample_memory_start_address = 0x94000; + conf->sample_memory_start_address = 0x20000; conf->dive_num_ptr = 0x56; conf->dive_count_ptr = 0xD2; conf->dive_count_endian = COCHRAN_LE_TYPE;
Memory end address is now defined. It may not be accurate for model which have a memory capacity disabled. Fixed sample start address for EMC-14.
Signed-off-by: John Van Ostrand john@vanostrand.com --- src/cochran_commander.c | 148 +++++++++++++++++------------------------------- 1 file changed, 52 insertions(+), 96 deletions(-)
diff --git a/src/cochran_commander.c b/src/cochran_commander.c index a1be22f..c9d7386 100644 --- a/src/cochran_commander.c +++ b/src/cochran_commander.c @@ -349,6 +349,7 @@ cochran_commander_get_config (const unsigned char *model, 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; @@ -366,6 +367,7 @@ cochran_commander_get_config (const unsigned char *model, 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; @@ -382,7 +384,8 @@ cochran_commander_get_config (const unsigned char *model, { conf->model = COCHRAN_MODEL_EMC_14; conf->log_size = 512; - conf->sample_memory_start_address = 0x20000; + 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; @@ -400,6 +403,7 @@ cochran_commander_get_config (const unsigned char *model, 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; @@ -435,6 +439,7 @@ cochran_read_id (dc_device_t *abstract) if (strncmp((const char *)device->data.id, "(C)", 3) != 0) { // It's a Commander, read again memcpy(device->data.id0, device->data.id, 67); + device->data.extra_id_flag = 1;
command[1] = 0xBD; command[2] = 0x7F; @@ -727,120 +732,71 @@ cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *data) { cochran_device_t *device = (cochran_device_t *) abstract; cochran_data_t *d = (cochran_data_t *) &device->data; - int ptr = 0; + dc_event_progress_t progress = {0};
dc_status_t rc; - unsigned char *b; - int size; + int size, offset;
- rc = cochran_commander_device_read_all (abstract); - - if (rc != DC_STATUS_SUCCESS) - return rc; + // Determine size for progress + if (d->extra_id_flag) { + // two ID blocks, 4 config block, misc block + size = 67 + 67 + 512 + 512 + 512 + 512 + 1500 + d->conf.sample_memory_end_address; + } else { + // one ID blocks, 2 config block, misc block + size = 67 + 512 + 512 + 1500 + d->conf.sample_memory_end_address; + }
- // Reserve space for block pointers - // Structure is: - // int ptr; - // char data_valid_flag; - dc_buffer_resize(data, 10 * 5); - - // Set pointer to first block - size = dc_buffer_get_size(data); - pack_uint32_array_le(dc_buffer_get_data(data) + ptr, size); + progress.current = 0; + progress.maximum = size; + device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
+ // Append id blocks if (d->extra_id_flag) { - dc_buffer_append(data, d->id0, 67); - *(dc_buffer_get_data(data) + ptr + 4) = 1; + dc_buffer_append (data, d->id0, 67); + dc_buffer_append (data, d->id, 67); + progress.current += 134; } else { - dc_buffer_resize(data, size + 67); - b = dc_buffer_get_data(data); - - memset(b + size, 0, 67); + dc_buffer_append (data, d->id, 67); + progress.current += 67; } - - // Set pointer to next block - ptr += 5; - size = dc_buffer_get_size(data); - pack_uint32_array_le(dc_buffer_get_data(data) + ptr, size);
- dc_buffer_append (data, d->id, 67); - *(dc_buffer_get_data(data) + ptr + 4) = 1; - - // Add config blocks - int n; - for (n = 0; n < d->config_count; n++) { - // Set pointer to next block - ptr += 5; - size = dc_buffer_get_size(data); - pack_uint32_array_le(dc_buffer_get_data(data) + ptr, size); + device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
+ rc = cochran_read_config (abstract, &progress); + if (rc != DC_STATUS_SUCCESS) + return rc; + + for (int n = 0; n < d->config_count; n++) { dc_buffer_append (data, d->config[n], 512); - - *(dc_buffer_get_data(data) + ptr + 4) = 1; }
- // Add blank config blocks - for (n = d->config_count; n < 4; n++) { - // Set pointer to next block - ptr += 5; - size = dc_buffer_get_size(data); - pack_uint32_array_le(dc_buffer_get_data(data) + ptr, size); + rc = cochran_read_misc (abstract, &progress); + if (rc != DC_STATUS_SUCCESS) + return rc;
- dc_buffer_resize(data, size + 512); + dc_buffer_append(data, d->misc, 1500);
- b = dc_buffer_get_data(data); - memset(b + size, 0, 512); - } - - // Set pointer to next block - ptr += 5; - size = dc_buffer_get_size(data); - pack_uint32_array_le(dc_buffer_get_data(data) + ptr, size); - - if (d->misc) { - dc_buffer_append (data, d->misc, 1500); - *(dc_buffer_get_data(data) + ptr + 4) = 1; - } else { - dc_buffer_resize(data, size + 1500); + // Read logbook and sample memory
- b = dc_buffer_get_data(data); - memset(b + size, 0, 1500); - } - - // Set pointer to next block - ptr += 5; - size = dc_buffer_get_size(data); - pack_uint32_array_le(dc_buffer_get_data(data) + ptr, size); - - if (d->logbook) { - dc_buffer_append (data, d->logbook, d->logbook_size); - *(dc_buffer_get_data(data) + ptr + 4) = 1; - } else { - dc_buffer_resize(data, size + d->logbook_size); + // Reserve space + offset = dc_buffer_get_size(data); + int rcm; + rcm = dc_buffer_resize(data, offset + d->conf.sample_memory_end_address); + if (!rcm) + return DC_STATUS_NOMEMORY;
- b = dc_buffer_get_data(data); - memset(b + size, 0, d->logbook_size); - } - - // Set pointer to next block - ptr += 5; - size = dc_buffer_get_size(data); - pack_uint32_array_le(dc_buffer_get_data(data) + ptr, size); - - if (d->sample) { - dc_buffer_append (data, d->sample, d->sample_size); - *(dc_buffer_get_data(data) + ptr + 4) = 1; - } else { - dc_buffer_resize(data, dc_buffer_get_size(data) + d->sample_size); + serial_sleep(device->port, 800);
- b = dc_buffer_get_data(data); - memset(b + size, 0, d->logbook_size); - } + // set back to 9600 baud + cochran_commander_serial_setup(device, abstract->context);
- // Set pointer to end - ptr += 5; - size = dc_buffer_get_size(data); - pack_uint32_array_le(dc_buffer_get_data(data) + ptr, size); + // Read the sample data, from 0 to sample end will include logbook + rc = cochran_commander_read (abstract, &progress, 0, + dc_buffer_get_data(data) + offset, d->conf.sample_memory_end_address); + if (rc != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to read the sample data."); + return rc; + }
return DC_STATUS_SUCCESS; }
It's no longer reading the two extra config blocks for Commanders. These only ever seem to hold FFs. It cleans up some other logic.
ID, config and misc blocks are now sent to the user via vendor events. The dump file now contains only logbook and sample memory. --- src/cochran_commander.c | 72 ++++++++++++++++++++++++++----------------------- src/cochran_commander.h | 2 +- 2 files changed, 39 insertions(+), 35 deletions(-)
diff --git a/src/cochran_commander.c b/src/cochran_commander.c index c9d7386..2287541 100644 --- a/src/cochran_commander.c +++ b/src/cochran_commander.c @@ -461,21 +461,21 @@ cochran_read_config (dc_device_t *abstract, dc_event_progress_t *progress) { cochran_device_t *device = (cochran_device_t *) abstract; cochran_data_t *data = &device->data; + dc_event_vendor_t vendor;
dc_status_t rc; unsigned char command[2] = { 0x96, 0x00 };
- if ((data->conf.model & 0xFF0000) == COCHRAN_MODEL_EMC_FAMILY) - data->config_count = 2; - else - data->config_count = 4; - int n; - for (n = 0; n < data->config_count; n++) { + for (n = 0; n < 2; n++) { command[1] = n; rc = cochran_packet(device, progress, command, 2, data->config[n], 512, 0); if (rc != DC_STATUS_SUCCESS) return rc; + + vendor.data = data->config[n]; + vendor.size = 512; + device_event_emit (abstract, DC_EVENT_VENDOR, &vendor); }
return DC_STATUS_SUCCESS; @@ -486,6 +486,8 @@ static dc_status_t 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;
unsigned char command[7] = { 0x89, 0x05, 0x00, 0x00, 0x00, 0xDC, 0x05 };
@@ -513,7 +515,16 @@ cochran_read_misc (dc_device_t *abstract, dc_event_progress_t *progress) return EXITCODE (n); }
- return cochran_packet(device, progress, command + 1, 6, device->data.misc, 1500, 0); + rc = cochran_packet(device, progress, command + 1, 6, device->data.misc, 1500, 0); + + if (rc != DC_STATUS_SUCCESS) + return rc; + + vendor.data = device->data.misc; + vendor.size = 1500; + device_event_emit (abstract, DC_EVENT_VENDOR, &vendor); + + return DC_STATUS_SUCCESS; }
@@ -733,57 +744,50 @@ cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *data) cochran_device_t *device = (cochran_device_t *) abstract; cochran_data_t *d = (cochran_data_t *) &device->data; dc_event_progress_t progress = {0}; + dc_event_vendor_t vendor;
dc_status_t rc; - int size, offset; + int size;
- // Determine size for progress - if (d->extra_id_flag) { - // two ID blocks, 4 config block, misc block - size = 67 + 67 + 512 + 512 + 512 + 512 + 1500 + d->conf.sample_memory_end_address; - } else { - // one ID blocks, 2 config block, misc block - size = 67 + 512 + 512 + 1500 + d->conf.sample_memory_end_address; + // Make sure buffer is good. + if (!dc_buffer_clear(data)) { + ERROR (abstract->context, "Uninitialized buffer."); + return DC_STATUS_INVALIDARGS; }
+ // Determine size for progress + size = 512 + 512 + 1500 + d->conf.sample_memory_end_address; + progress.current = 0; progress.maximum = size; device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
- // Append id blocks + // Emit ID blocks as vendor data if (d->extra_id_flag) { - dc_buffer_append (data, d->id0, 67); - dc_buffer_append (data, d->id, 67); - progress.current += 134; - } else { - dc_buffer_append (data, d->id, 67); - progress.current += 67; + vendor.data = d->id0; + vendor.size = 67; + device_event_emit (abstract, DC_EVENT_VENDOR, &vendor); }
- device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + vendor.data = d->id; + vendor.size = 67; + device_event_emit (abstract, DC_EVENT_VENDOR, &vendor);
rc = cochran_read_config (abstract, &progress); if (rc != DC_STATUS_SUCCESS) return rc; - for (int n = 0; n < d->config_count; n++) { - dc_buffer_append (data, d->config[n], 512); - } - rc = cochran_read_misc (abstract, &progress); if (rc != DC_STATUS_SUCCESS) return rc;
- dc_buffer_append(data, d->misc, 1500); - // Read logbook and sample memory
// Reserve space - offset = dc_buffer_get_size(data); - int rcm; - rcm = dc_buffer_resize(data, offset + d->conf.sample_memory_end_address); - if (!rcm) + if (!dc_buffer_resize(data, d->conf.sample_memory_end_address)) { + ERROR(abstract->context, "Insufficient buffer space available."); return DC_STATUS_NOMEMORY; + }
serial_sleep(device->port, 800);
@@ -792,7 +796,7 @@ cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *data)
// Read the sample data, from 0 to sample end will include logbook rc = cochran_commander_read (abstract, &progress, 0, - dc_buffer_get_data(data) + offset, d->conf.sample_memory_end_address); + dc_buffer_get_data(data), d->conf.sample_memory_end_address); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to read the sample data."); return rc; diff --git a/src/cochran_commander.h b/src/cochran_commander.h index 05b49ed..57962d8 100644 --- a/src/cochran_commander.h +++ b/src/cochran_commander.h @@ -73,7 +73,7 @@ typedef struct cochran_config_t { typedef struct cochran_data_t { unsigned char id0[67]; unsigned char id[67]; - unsigned char config[4][512]; + unsigned char config[2][512]; unsigned char misc[1500]; unsigned char *logbook; unsigned char *sample;
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,
--- examples/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/examples/Makefile.am b/examples/Makefile.am index 0495e7c..aaa7e4f 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -3,7 +3,7 @@ LDADD = $(top_builddir)/src/libdivecomputer.la AM_LDFLAGS = -lm
bin_PROGRAMS = \ - dctool + dctool \ cochran_download
dctool_SOURCES = \
--- examples/dctool_download.c | 2 +- src/cochran_commander.c | 23 ++++++++------------- src/cochran_commander_parser.c | 47 +++++++++++++++++++++--------------------- 3 files changed, 33 insertions(+), 39 deletions(-)
diff --git a/examples/dctool_download.c b/examples/dctool_download.c index 02f2be6..ffcdc41 100644 --- a/examples/dctool_download.c +++ b/examples/dctool_download.c @@ -126,7 +126,7 @@ sample_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata) fprintf (sampledata->ostream, " <gasmix>%u</gasmix>\n", value.gasmix); break; case DC_SAMPLE_ASCENT_RATE: - fprintf (sampledata->fp, " <ascent_rate>%.2f</ascent_rate>\n", + fprintf (sampledata->ostream, " <ascent_rate>%.2f</ascent_rate>\n", value.ascent_rate); break; default: diff --git a/src/cochran_commander.c b/src/cochran_commander.c index 036ca6c..3ba3786 100644 --- a/src/cochran_commander.c +++ b/src/cochran_commander.c @@ -138,6 +138,7 @@ static cochran_layout_t cochran_layout_emc14 = { };
static const dc_device_vtable_t cochran_commander_device_vtable = { + sizeof(cochran_device_t), DC_FAMILY_COCHRAN_COMMANDER, cochran_commander_device_set_fingerprint, /* set_fingerprint */ cochran_commander_device_read, /* read */ @@ -187,7 +188,6 @@ cochran_packet (cochran_device_t *device, dc_event_progress_t *progress, SERIAL_PARITY_NONE, 2, SERIAL_FLOWCONTROL_NONE); if (rc == -1) { ERROR (abstract->context, "Failed to set the high baud rate."); - free (device); return DC_STATUS_IO; } } @@ -230,7 +230,6 @@ cochran_commander_serial_setup (cochran_device_t *device, dc_context_t *context) if (rc == -1) { ERROR (context, "Failed to set the terminal attributes."); serial_close (device->port); - free (device); return DC_STATUS_IO; }
@@ -249,7 +248,6 @@ cochran_commander_serial_setup (cochran_device_t *device, dc_context_t *context) if (serial_set_timeout (device->port, 5000) == -1) { ERROR (context, "Failed to set the timeout."); serial_close (device->port); - free (device); return DC_STATUS_IO; }
@@ -272,7 +270,6 @@ cochran_commander_serial_open(cochran_device_t *device, dc_context_t *context) int rc = serial_open (&device->port, context, device->name); if (rc == -1) { ERROR (context, "Failed to open the serial port."); - free (device); return DC_STATUS_IO; }
@@ -284,6 +281,7 @@ dc_status_t cochran_commander_device_open (dc_device_t **out, dc_context_t *context, const char *name) { + cochran_device_t *device = NULL; dc_status_t rc; cochran_layout_t *layout;
@@ -291,16 +289,13 @@ cochran_commander_device_open (dc_device_t **out, dc_context_t *context, return DC_STATUS_INVALIDARGS;
// Allocate memory. - cochran_device_t *device = (cochran_device_t *) malloc ( - sizeof (cochran_device_t)); + device = (cochran_device_t *) + dc_device_allocate(context, &cochran_commander_device_vtable); if (device == NULL) { ERROR (context, "Failed to allocate memory."); return DC_STATUS_NOMEMORY; }
- // Initialize the base class. - device_init (&device->base, context, &cochran_commander_device_vtable); - // Set the default values. device->port = NULL; device->name = name; @@ -310,8 +305,10 @@ cochran_commander_device_open (dc_device_t **out, dc_context_t *context, NULL, 0);
rc = cochran_commander_serial_open(device, context); - if (rc != DC_STATUS_SUCCESS) + if (rc != DC_STATUS_SUCCESS) { + dc_device_deallocate((dc_device_t *) device); return rc; + }
// Read ID from the device rc = cochran_read_id((dc_device_t *) device); @@ -319,7 +316,7 @@ cochran_commander_device_open (dc_device_t **out, dc_context_t *context, if (rc != DC_STATUS_SUCCESS) { ERROR (context, "Device not responding."); serial_close (device->port); - free (device); + dc_device_deallocate((dc_device_t *) device); return rc; }
@@ -336,7 +333,7 @@ cochran_commander_device_open (dc_device_t **out, dc_context_t *context, device->model_string[4], device->model_string[5], device->model_string[6], device->model_string[7]); serial_close (device->port); - free (device); + dc_device_deallocate((dc_device_t *) device); return DC_STATUS_UNSUPPORTED; }
@@ -353,14 +350,12 @@ cochran_commander_device_close (dc_device_t *abstract)
// Close the device. if (serial_close (device->port) == -1) { - free (device); return DC_STATUS_IO; }
// Free memory. free (device->data.logbook); free (device->data.sample); - free (device);
return DC_STATUS_SUCCESS; } diff --git a/src/cochran_commander_parser.c b/src/cochran_commander_parser.c index 434d332..bce3cad 100644 --- a/src/cochran_commander_parser.c +++ b/src/cochran_commander_parser.c @@ -40,7 +40,6 @@ dc_status_t cochran_commander_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime); static dc_status_t cochran_commander_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value); -dc_status_t cochran_commander_parser_destroy (dc_parser_t *abstract); static dc_status_t cochran_commander_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata); @@ -48,14 +47,21 @@ int cochran_commander_handle_event (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata, unsigned char code, unsigned int offset, unsigned int time);
+typedef struct cochran_commander_parser_t cochran_commander_parser_t; + +struct cochran_commander_parser_t { + dc_parser_t base; + cochran_layout_t *layout; +};
static dc_parser_vtable_t cochran_commander_parser_vtable = { + sizeof(cochran_commander_parser_t), DC_FAMILY_COCHRAN_COMMANDER, cochran_commander_parser_set_data, /* set_data */ cochran_commander_parser_get_datetime, /* datetime */ cochran_commander_parser_get_field, /* fields */ cochran_commander_parser_samples_foreach, /* samples_foreach */ - cochran_commander_parser_destroy /* destroy */ + NULL /* destroy */ };
@@ -63,29 +69,18 @@ static dc_parser_vtable_t cochran_commander_parser_vtable = { dc_status_t cochran_commander_parser_create (dc_parser_t **out, dc_context_t *context) { + cochran_commander_parser_t *parser = NULL; if (out == NULL) return DC_STATUS_INVALIDARGS;
// Allocate memory. - dc_parser_t *parser = (dc_parser_t *) malloc (sizeof (dc_parser_t)); + parser = (cochran_commander_parser_t *) dc_parser_allocate(context, &cochran_commander_parser_vtable); if (parser == NULL) { ERROR (context, "Failed to allocate memory."); return DC_STATUS_NOMEMORY; }
- parser_init (parser, context, &cochran_commander_parser_vtable); - - *out = parser; - - return DC_STATUS_SUCCESS; -} - - -dc_status_t -cochran_commander_parser_destroy (dc_parser_t *abstract) -{ - // Free memory. - free (abstract); + *out = (dc_parser_t *) parser;
return DC_STATUS_SUCCESS; } @@ -95,11 +90,16 @@ dc_status_t cochran_commander_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size) { + cochran_commander_parser_t *parser = (cochran_commander_parser_t *) abstract; abstract->data = data; abstract->size = size;
+ // Determine cochran data format + // abstract->data is prefixed by the model string + parser->layout = cochran_commander_get_layout(data); + return DC_STATUS_SUCCESS; -} +}
// There are two date formats used by Cochran @@ -107,12 +107,11 @@ dc_status_t cochran_commander_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime) { + cochran_commander_parser_t *parser = (cochran_commander_parser_t *) abstract; const unsigned char *data = abstract->data; const unsigned char *log = data + COCHRAN_MODEL_SIZE; - // abstract->data is prefixed by the model string - cochran_layout_t *layout = cochran_commander_get_layout(data);
- if (layout->date_format == DATE_SMHDMY) { + if (parser->layout->date_format == DATE_SMHDMY) { datetime->second = log[0]; datetime->minute = log[1]; datetime->hour = log[2]; @@ -135,9 +134,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_layout_t *layout = cochran_commander_get_layout(abstract->data); + cochran_commander_parser_t *parser = (cochran_commander_parser_t *) abstract;
- switch (layout->model & 0xFF0000) + switch (parser->layout->model & 0xFF0000) { case COCHRAN_MODEL_COMMANDER_FAMILY: return cochran_cmdr_parser_get_field(abstract, type, flags, value); @@ -154,9 +153,9 @@ static dc_status_t cochran_commander_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata) { - cochran_layout_t *layout = cochran_commander_get_layout(abstract->data); + cochran_commander_parser_t *parser = (cochran_commander_parser_t *) abstract;
- switch (layout->model & 0xFF0000) + switch (parser->layout->model & 0xFF0000) { case COCHRAN_MODEL_COMMANDER_FAMILY: return cochran_cmdr_parser_samples_foreach(abstract, callback,