[PATCH] Cochran: Made numerous changes after review

John Van Ostrand john at vanostrand.com
Mon Mar 7 09:52:10 PST 2016


- More localization of variables
- Variable name changes to be more consistent with other backends
- Removed special PTY serial_setup case
- Avoided potential double-free situations
- Consolidated serial queue flushing
- Verified heartbeat bytes
- Used goto-style error handling on _open
- Bounds checking on pointers
- Removed rounding reads to nearest 8k.
- Issue DEVINFO event in foreach
- Separated dive data from device_t
- switched to date-based fingerprint
- Many other small bugs and style fixes.
---
 src/cochran_commander.c        | 553 +++++++++++++++++++----------------------
 src/cochran_commander.h        |  52 ++--
 src/cochran_commander_parser.c |  14 +-
 3 files changed, 283 insertions(+), 336 deletions(-)

diff --git a/src/cochran_commander.c b/src/cochran_commander.c
index c457b3a..127518d 100644
--- a/src/cochran_commander.c
+++ b/src/cochran_commander.c
@@ -49,28 +49,29 @@
 */
 
 // Cochran Commander Nitrox
-cochran_device_info_t cochran_cmdr_device_info = {
+const cochran_device_info_t cochran_cmdr_device_info = {
 	COCHRAN_MODEL_COMMANDER_AIR_NITROX,		// model
-	ADDRESS_24_BIT,							// address_size
+	24,										// address_bits
 	ENDIAN_BE,								// endian
 	115200,									// high_baud
 	0x00000000,								// rb_logbook_begin
 	0x00020000,								// rb_lobook_end
 	0x00020000,								// rb_profile_begin
 	0x00100000,								// rb_profile_end
-	256,									// log_size
-	512,									// max_log
+	256,									// logbook_entry_size
+	512,									// logbook_entry_count
 	2,										// max_gas
 	SAMPLE_CMDR,							// sample_format
 }; 
 
-cochran_conf_offsets_t cochran_cmdr_conf_offsets = {
+const cochran_conf_offsets_t cochran_cmdr_conf_offsets = {
 	0x046,		// dive_count
 	0x06e,		// last_log
 	0x071,		// last_interdive
+	0x0aa,		// serial_number
 };
 
-cochran_log_offsets_t cochran_cmdr_log_offsets = {
+const cochran_log_offsets_t cochran_cmdr_log_offsets = {
 	1, 0, 3, 2, 5, 4,	// sec, min, hour, day, mon, year, 1 byte each
 	6,					// profile_begin_offset, 4 bytes
 	24,					// water_conductivity, 1 byte, 0=low(fresh), 2=high(sea)
@@ -91,7 +92,7 @@ cochran_log_offsets_t cochran_cmdr_log_offsets = {
 };
 
 // inter-dive event lengths
-struct event_size cmdr_event_bytes[15] = {
+const struct event_size cmdr_event_bytes[15] = {
 		{0x00, 17}, {0x01, 21}, {0x02, 18},
 		{0x03, 17}, {0x06, 19}, {0x07, 19},
 		{0x08, 19}, {0x09, 19}, {0x0a, 19},
@@ -100,63 +101,64 @@ struct event_size cmdr_event_bytes[15] = {
 		{  -1,  1} };
 
 // Cochran EMC-14
-cochran_device_info_t cochran_emc14_device_info = {
+const cochran_device_info_t cochran_emc14_device_info = {
 	COCHRAN_MODEL_EMC_14,	// model
-	ADDRESS_32_BIT,			// address_size
+	32,						// address_bits
 	ENDIAN_LE,				// endian
 	806400,					// high_baud
 	0x00000000,				// rb_logbook_begin
 	0x00020000,				// rb_lobook_end
 	0x00022000,				// rb_profile_begin
 	0x00200000,				// rb_profile_end
-	512,					// log_size
-	256,					// max_log
+	512,					// logbook_entry_size
+	256,					// logbook_entry_count
 	2,						// max_gas
 	SAMPLE_EMC,				// sample_format
 };
 
 // Cochran EMC-16
-cochran_device_info_t cochran_emc16_device_info = {
+const cochran_device_info_t cochran_emc16_device_info = {
 	COCHRAN_MODEL_EMC_16,	// model
-	ADDRESS_32_BIT,			// address_size
+	32,						// address_bits
 	ENDIAN_LE,				// endian
 	806400,					// high_baud
 	0x00000000,				// rb_logbook_begin
 	0x00080000,				// rb_lobook_end
 	0x00094000,				// rb_profile_begin
 	0x00800000,				// rb_profile_end
-	512,					// log_size
-	1024,					// max_log
+	512,					// logbook_entry_size
+	1024,					// logbook_entry_count
 	2,						// max_gas
 	SAMPLE_EMC,				// sample_format
 };
 
 
 // Cochran EMC-20
-cochran_device_info_t cochran_emc20_device_info = {
+const cochran_device_info_t cochran_emc20_device_info = {
 	COCHRAN_MODEL_EMC_20,	// model
-	ADDRESS_32_BIT,			// address_size
+	32,						// address_bits
 	ENDIAN_LE,				// endian
 	806400,					// high_baud
 	0x00000000,				// rb_logbook_begin
 	0x00080000,				// rb_lobook_end
 	0x00094000,				// rb_profile_begin
 	0x01000000,				// rb_profile_end
-	512,					// log_size
-	1024,					// max_log
+	512,					// logbook_entry_size
+	1024,					// logbook_entry_count
 	2,						// max_gas
 	SAMPLE_EMC,				// sample_format
 };
 
 // Common EMC offsets
-cochran_conf_offsets_t cochran_emc_conf_offsets = {
+const cochran_conf_offsets_t cochran_emc_conf_offsets = {
 	0x0d2,		// dive_count
 	0x13e,		// last_log
 	0x142,		// last_interdive
+	0x1e6,		// serial_number
 };
 
 
-cochran_log_offsets_t cochran_emc_log_offsets = {
+const cochran_log_offsets_t cochran_emc_log_offsets = {
 	0, 1, 2, 3, 4, 5,	// sec, min, hour, day, mon, year, 1 byte each
 	6,					// profile_begin_offset, 4 bytes
 	24,					// water_conductivity, 1 byte 0=low(fresh), 2=high(sea)
@@ -176,7 +178,7 @@ cochran_log_offsets_t cochran_emc_log_offsets = {
 	407,				// max_temp, 1 byte, /2+20=F
 };
 
-struct event_size emc_event_bytes[15] = {
+const struct event_size emc_event_bytes[15] = {
 		{0x00, 19}, {0x01, 23}, {0x02, 20},
 		{0x03, 19}, {0x06, 21}, {0x07, 21},
 		{0x0a, 21}, {0x0b, 21}, {0x0f, 19},
@@ -196,12 +198,12 @@ static const dc_device_vtable_t cochran_commander_device_vtable = {
 
 
 static dc_status_t
-cochran_read_id(dc_device_t *device);
+cochran_read_id(dc_device_t *device, unsigned char *id, int size);
 static dc_status_t
 cochran_commander_read (dc_device_t *abstract, dc_event_progress_t *progress,
 		unsigned int address, unsigned char data[], unsigned int size);
 static void
-cochran_check_profiles(dc_device_t *abstract);
+cochran_check_profiles(dc_device_t *abstract, cochran_data_t *data);
 
 
 static dc_status_t
@@ -210,17 +212,18 @@ cochran_packet (cochran_device_t *device, dc_event_progress_t *progress,
 		unsigned char answer[], unsigned int asize, int high_speed)
 {
 	dc_device_t *abstract = (dc_device_t *) device;
-	unsigned int bytes_read = 0, n, read_size;
-	unsigned int ptr;
-	int rc;
 
 	if (device_is_cancelled (abstract))
 		return DC_STATUS_CANCELLED;
 
 	// Send the command to the device, one byte at a time
-	for (ptr = 0; ptr < csize; ptr++) {
-		if (ptr) serial_sleep(device->port, 16);	// 16 ms
-		n = serial_write(device->port, command + ptr, 1);
+	// If sent all at once the command is ignored. It's like the DC
+	// has no buffering.
+	for (int i = 0; i < csize; i++) {
+		// Give the DC time to read the character.
+		if (i) serial_sleep(device->port, 16);	// 16 ms
+
+		unsigned int n = serial_write(device->port, command + i, 1);
 		if (n != 1) {
 			ERROR (abstract->context, "Failed to send the command.");
 			return EXITCODE (n);
@@ -228,38 +231,40 @@ cochran_packet (cochran_device_t *device, dc_event_progress_t *progress,
 	}
 
 	if (high_speed) {
+		int rc = 0;
+
+		// Give the DC time to process the command.
+		// This is required.
 		serial_sleep(device->port, 45);
 
 		// Rates are odd, like 806400 for the EMC, 115200 for commander
 		rc = serial_configure(device->port, device->info->high_baud, 8,
 						SERIAL_PARITY_NONE, 2, SERIAL_FLOWCONTROL_NONE);
 		if (rc == -1) {
-			// Assume we are talking to a pty, a simulator
-			rc = serial_configure(device->port, 115200, 8, SERIAL_PARITY_NONE,
-						2, SERIAL_FLOWCONTROL_NONE);
-			if (rc == -1) {
-				ERROR (abstract->context, "Failed to set the high baud rate.");
-				return DC_STATUS_IO;
-			}
+			ERROR (abstract->context, "Failed to set the high baud rate.");
+			return DC_STATUS_IO;
 		}
 	}
 
 	// Receive the answer from the device.
 	// Use 1024 byte "packets" so we can display progress.
-	while (bytes_read < asize) {
-		if (asize - bytes_read > 1024)
-			read_size = 1024;
+	unsigned int nbytes = 0;
+	while (nbytes < asize) {
+		unsigned int len = 0;
+
+		if (asize - nbytes > 1024)
+			len = 1024;
 		else
-			read_size = asize - bytes_read;
+			len = asize - nbytes;
 
-		n = serial_read (device->port, answer + bytes_read, read_size);
-		if (n != read_size) {
+		int n = serial_read (device->port, answer + nbytes, len);
+		if (n != len) {
 			ERROR (abstract->context, "Failed to receive data, expected %u,"
-					"read %u.", read_size, n);
+					"read %u.",len, n);
 			return EXITCODE (n);
 		}
 
-		bytes_read += n;
+		nbytes += n;
 
 		if (progress) {
 			progress->current += n;
@@ -281,51 +286,39 @@ cochran_commander_serial_setup (cochran_device_t *device)
 							2, SERIAL_FLOWCONTROL_NONE);
 	if (rc == -1) {
 		ERROR (device->base.context, "Failed to set the terminal attributes.");
-		serial_close (device->port);
 		return DC_STATUS_IO;
 	}
 
-	serial_set_queue_size(device->port, 4096, 4096);
-
-	// Make sure everything is in a sane state.
-	serial_flush (device->port, SERIAL_QUEUE_OUTPUT);
-	serial_flush (device->port, SERIAL_QUEUE_INPUT);
-
-	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).
 	if (serial_set_timeout (device->port, 5000) == -1) {
 		ERROR (device->base.context, "Failed to set the timeout.");
-		serial_close (device->port);
 		return DC_STATUS_IO;
 	}
 
+	// Wake up DC and trigger heartbeat
+	serial_set_break(device->port, 1);
+	serial_sleep(device->port, 16);
+	serial_set_break(device->port, 0);
+
+	// Clear old heartbeats
+	serial_flush (device->port, SERIAL_QUEUE_BOTH);
+
 	// Wait for heartbeat byte before send
-	char answer[1];
-	int n = serial_read(device->port, answer, 1);
+	unsigned char answer = 0;
+	int n = serial_read(device->port, &answer, 1);
 	if (n != 1) {
+		serial_close (device->port);
 		ERROR (device->base.context, "Failed to receive device heartbeat.");
 		return EXITCODE (n);
 	}
 
-	return DC_STATUS_SUCCESS;
-}
-
-
-dc_status_t
-cochran_commander_serial_open(cochran_device_t *device)
-{
-	// Open the device.
-	int rc = serial_open (&device->port, device->base.context, device->name);
-	if (rc == -1) {
-		ERROR (device->base.context, "Failed to open the serial port.");
-		return DC_STATUS_IO;
+	if (answer != 0xAA) {
+		serial_close (device->port);
+		ERROR (device->base.context, "Received bad hearbeat byte (%02x).", answer);
+		return DC_STATUS_PROTOCOL;
 	}
 
-	return cochran_commander_serial_setup(device);
+	return DC_STATUS_SUCCESS;
 }
 
 
@@ -334,7 +327,7 @@ cochran_commander_device_open (dc_device_t **out, dc_context_t *context,
 		const char *name)
 {
 	cochran_device_t *device = NULL;
-	dc_status_t rc;
+	dc_status_t status;
 
 	if (out == NULL)
 		return DC_STATUS_INVALIDARGS;
@@ -348,29 +341,31 @@ cochran_commander_device_open (dc_device_t **out, dc_context_t *context,
 
 	// Set the default values.
 	device->port = NULL;
-	device->name = name;
-	device->data.logbook = NULL;
-	device->data.sample = NULL;
 	cochran_commander_device_set_fingerprint((dc_device_t *) device,
 		NULL, 0);
 
-	rc = cochran_commander_serial_open(device);
-	if (rc != DC_STATUS_SUCCESS) {
-		dc_device_deallocate((dc_device_t *) device);
-		return rc;
+	// Open the device.
+	int rc = serial_open (&device->port, device->base.context, name);
+	if (rc == -1) {
+		ERROR (device->base.context, "Failed to open the serial port.");
+		status = DC_STATUS_IO;
+		goto error_free;
 	}
 
+	rc = cochran_commander_serial_setup(device);
+	if (rc != DC_STATUS_SUCCESS)
+		return rc;
+
 	// Read ID from the device
-	rc = cochran_read_id((dc_device_t *) device);
+	unsigned char id[67];
+	status = cochran_read_id((dc_device_t *) device, id, sizeof(id));
 
-	if (rc != DC_STATUS_SUCCESS) {
+	if (status != DC_STATUS_SUCCESS) {
 		ERROR (context, "Device not responding.");
-		serial_close (device->port);
-		dc_device_deallocate((dc_device_t *) device);
-		return rc;
+		goto error_close;
 	}
 
-	memcpy(device->model_string, device->data.id + 0x3b, 8);
+	memcpy(device->model_string, id + 0x3b, 8);
 	device->model_string[8] = 0;
 
 	device->base.devinfo.model = cochran_commander_model_id(device->model_string);
@@ -383,9 +378,8 @@ cochran_commander_device_open (dc_device_t **out, dc_context_t *context,
 			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);
-		dc_device_deallocate((dc_device_t *) device);
-		return DC_STATUS_UNSUPPORTED;
+		status = DC_STATUS_UNSUPPORTED;
+		goto error_close;
 	}
 
 	// Get model capability, protocol and data format
@@ -395,24 +389,27 @@ cochran_commander_device_open (dc_device_t **out, dc_context_t *context,
 	*out = (dc_device_t *) device;
 
 	return DC_STATUS_SUCCESS;
+
+error_close:
+	serial_close (device->port);
+error_free:
+	dc_device_deallocate ((dc_device_t *) device);
+	return status;
 }
 
 
 dc_status_t
 cochran_commander_device_close (dc_device_t *abstract)
 {
+	dc_status_t status = DC_STATUS_SUCCESS;
 	cochran_device_t *device = (cochran_device_t*) abstract;
 
 	// Close the device.
 	if (serial_close (device->port) == -1) {
-		return DC_STATUS_IO;
+		dc_status_set_error( &status, DC_STATUS_IO );
 	}
 
-	// Free memory.
-	free (device->data.logbook);
-	free (device->data.sample);
-
-	return DC_STATUS_SUCCESS;
+	return status;
 }
 
 
@@ -421,15 +418,14 @@ cochran_commander_device_set_fingerprint (dc_device_t *abstract,
 		const unsigned char data[], unsigned int size)
 {
 	cochran_device_t *device = (cochran_device_t *) abstract;
-	cochran_data_t *d = &device->data;
 
-	if (size && size != sizeof (d->fingerprint))
+	if (size && size != sizeof (device->fingerprint))
 		return DC_STATUS_INVALIDARGS;
 
 	if (size)
-		memcpy (&d->fingerprint, data, sizeof (d->fingerprint));
+		memcpy (device->fingerprint, data, sizeof (device->fingerprint));
 	else
-		memset (&d->fingerprint, 0xFF, sizeof (d->fingerprint));
+		memset (device->fingerprint, 0xFF, sizeof (device->fingerprint));
 
 	return DC_STATUS_SUCCESS;
 }
@@ -453,9 +449,9 @@ cochran_commander_read (dc_device_t *abstract, dc_event_progress_t *progress,
 	unsigned char command[10];
 	unsigned char command_size;
 
-	switch (device->info->address_size)
+	switch (device->info->address_bits)
 	{
-	case ADDRESS_32_BIT:
+	case 32:
 		// EMC uses 32 bit addressing
 		command[0] = 0x15;
 		command[1] = (address      ) & 0xff;
@@ -469,7 +465,7 @@ cochran_commander_read (dc_device_t *abstract, dc_event_progress_t *progress,
 		command[9] = 0x05;
 		command_size = 10;
 		break;
-	case ADDRESS_24_BIT:
+	case 24:
 		// Commander uses 24 byte addressing
 		command[0] = 0x15;
 		command[1] = (address      ) & 0xff;
@@ -523,7 +519,7 @@ cochran_commander_model_id(const char *model)
 
 // Get device capability, protocol info and data format for a device
 dc_status_t
-cochran_commander_info (const int model, cochran_device_info_t **info, cochran_conf_offsets_t **conf_ptr, cochran_log_offsets_t **log_ptr, struct event_size (**event_bytes)[15])
+cochran_commander_info (const int model, const cochran_device_info_t **info, const cochran_conf_offsets_t **conf_ptr, const cochran_log_offsets_t **log_ptr, const struct event_size (**event_bytes)[15])
 {
 	// Determine model
 	if (model == COCHRAN_MODEL_EMC_20)
@@ -564,99 +560,51 @@ cochran_commander_info (const int model, cochran_device_info_t **info, cochran_c
 
 
 static dc_status_t
-cochran_read_id (dc_device_t *abstract)
+cochran_read_id (dc_device_t *abstract, unsigned char *id, int size)
 {
 	cochran_device_t *device = (cochran_device_t *) abstract;
 	dc_status_t rc;
 	unsigned char command[6] = {0x05, 0x9D, 0xFF, 0x00, 0x43, 0x00};
 
-	rc = cochran_packet(device, NULL, command, 6, device->data.id, 67, 0);
+	rc = cochran_packet(device, NULL, command, sizeof(command), id, size, 0);
 	if (rc != DC_STATUS_SUCCESS)
 		return rc;
 
-	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;
-
+	if (strncmp((const char *) id, "(C)", 3) != 0) {
+		// It's a Commander, read a different location
 		command[1] = 0xBD;
 		command[2] = 0x7F;
 
-		rc = cochran_packet(device, NULL, command, 6, device->data.id, 67, 0);
+		rc = cochran_packet(device, NULL, command, sizeof(command), id, size, 0);
 		if (rc != DC_STATUS_SUCCESS)
 			return rc;
 	}
 
-	return DC_STATUS_SUCCESS;
-}
-
-
-static dc_status_t
-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;
+	// Emit ID block
 	dc_event_vendor_t vendor;
-
-	dc_status_t rc;
-	unsigned char command[2] = { 0x96, 0x00 };
-
-	int 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);
-	}
+	vendor.data = id;
+	vendor.size = size;
+	device_event_emit (abstract, DC_EVENT_VENDOR, &vendor);
 
 	return DC_STATUS_SUCCESS;
 }
 
 
 static dc_status_t
-cochran_read_misc (dc_device_t *abstract, dc_event_progress_t *progress)
+cochran_read_config (dc_device_t *abstract, cochran_data_t *data, 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 };
-
-	switch (device->info->model & 0xFF0000)
-	{
-	case COCHRAN_MODEL_COMMANDER_FAMILY:
-		command[2] = 0xCA;
-		command[3] = 0xFD;
-		break;
-	case COCHRAN_MODEL_EMC_FAMILY:
-		command[2] = 0xE0;
-		command[3] = 0x03;
-		break;
-	default:
-		return DC_STATUS_UNSUPPORTED;
-	}
-
-	// Send first byte then wait for heartbeat before sending the rest
-	serial_write(device->port, command, 1);
-
-	char answer[1];
-	int n = serial_read(device->port, answer, 1);
-	if (n != 1) {
-		ERROR (abstract->context, "Failed to receive device heartbeat.");
-		return EXITCODE (n);
-	}
-
-	rc = cochran_packet(device, progress, command + 1, 6, device->data.misc, 1500, 0);
+	dc_status_t rc;
+	unsigned char command[2] = { 0x96, 0x00 };
 
+	rc = cochran_packet(device, progress, command, sizeof(command), data->config, sizeof(data->config), 0);
 	if (rc != DC_STATUS_SUCCESS)
 		return rc;
 
-	vendor.data = device->data.misc;
-	vendor.size = 1500;
+	vendor.data = data->config;
+	vendor.size = sizeof(data->config);
 	device_event_emit (abstract, DC_EVENT_VENDOR, &vendor);
 
 	return DC_STATUS_SUCCESS;
@@ -664,18 +612,17 @@ cochran_read_misc (dc_device_t *abstract, dc_event_progress_t *progress)
 
 
 static dc_status_t
-cochran_read_logbook (dc_device_t *abstract, dc_event_progress_t *progress)
+cochran_read_logbook (dc_device_t *abstract, cochran_data_t *data, dc_event_progress_t *progress)
 {
 	cochran_device_t *device = (cochran_device_t *) abstract;
-	cochran_data_t *d = &device->data;
 	dc_status_t rc;
 
-	if (d->logbook)
-		free(d->logbook);
+	if (data->logbook)
+		free(data->logbook);
 
 	// Allocate space for log book.
-	d->logbook = (unsigned char *) malloc(d->logbook_size);
-	if (device == NULL) {
+	data->logbook = (unsigned char *) malloc(data->logbook_size);
+	if (data->logbook == NULL) {
 		ERROR (abstract->context, "Failed to allocate memory.");
 		return DC_STATUS_NOMEMORY;
 	}
@@ -683,38 +630,38 @@ cochran_read_logbook (dc_device_t *abstract, dc_event_progress_t *progress)
 	serial_sleep(device->port, 800);
 
 	// set back to 9600 baud
-	cochran_commander_serial_setup(device);
+	rc = cochran_commander_serial_setup(device);
+	if (rc != DC_STATUS_SUCCESS)
+		return rc;
 
 	// Request log book
-	rc = cochran_commander_read(abstract, progress, 0, d->logbook,
-		d->logbook_size);
+	rc = cochran_commander_read(abstract, progress, 0, data->logbook,
+		data->logbook_size);
 
 	return rc;
 }
 
 
 static void
-cochran_find_fingerprint(dc_device_t *abstract)
+cochran_find_fingerprint(dc_device_t *abstract, cochran_data_t *data)
 {
 	cochran_device_t *device = (cochran_device_t *) abstract;
-	cochran_data_t *d = (cochran_data_t *) &device->data;
 
 	// Skip to fingerprint to reduce time
-	d->fp_dive_num = d->dive_count - 1;
+	data->fp_dive_num = data->dive_count;
+	data->fp_dive_num--;
 
-	while (d->fp_dive_num >= 0 && memcmp(&d->fingerprint,
-						 d->logbook + d->fp_dive_num * device->info->log_size
-						+ device->log_ptr->dive_number,
-						 sizeof(d->fingerprint)))
-		d->fp_dive_num--;
+	while (data->fp_dive_num >= 0 && memcmp(device->fingerprint,
+			data->logbook + data->fp_dive_num * device->info->logbook_entry_size,
+			sizeof(device->fingerprint)))
+		data->fp_dive_num--;
 }
 
 
 static void
-cochran_get_sample_parms(dc_device_t *abstract)
+cochran_get_sample_parms(dc_device_t *abstract, cochran_data_t *data)
 {
 	cochran_device_t *device = (cochran_device_t *) abstract;
-	cochran_data_t *d = (cochran_data_t *) &device->data;
 	unsigned int pre_dive_offset = 0, end_dive_offset = 0;
 	unsigned int low_offset, high_offset;
 
@@ -723,12 +670,27 @@ cochran_get_sample_parms(dc_device_t *abstract)
 	high_offset = 0;
 
 	int i;
-	for (i = d->fp_dive_num + 1; i < d->dive_count; i++) {
-		pre_dive_offset = array_uint32_le (&(d->logbook[i * device->info->log_size
-				+ device->log_ptr->profile_pre_offset]));
-		end_dive_offset = array_uint32_le (&(d->logbook[i * device->info->log_size
-				+ device->log_ptr->profile_end_offset]));
+	for (i = data->fp_dive_num + 1; i < data->dive_count; i++) {
+		pre_dive_offset = array_uint32_le (data->logbook + i * device->info->logbook_entry_size
+				+ device->log_ptr->profile_pre_offset);
+		end_dive_offset = array_uint32_le (data->logbook + i * device->info->logbook_entry_size
+				+ device->log_ptr->profile_end_offset);
+
+		// Validate offsets, allow 0xFFFFFFF for end_dive_offset
+		// because we handle that as a special case.
+		if (pre_dive_offset < device->info->rb_profile_begin
+				|| pre_dive_offset > device->info->rb_profile_end) {
+			ERROR(abstract->context, "Invalid pre-dive offset (%08x) on dive %d.", pre_dive_offset, i);
+			continue;
+		}
 
+		if (end_dive_offset < device->info->rb_profile_begin
+				|| (end_dive_offset > device->info->rb_profile_end
+				&& end_dive_offset != 0xFFFFFFFF)) {
+			ERROR(abstract->context, "Invalid end-dive offset (%08x) on dive %d.", end_dive_offset, i);
+			continue;
+		}
+		
 		// Check for ring buffer wrap-around.
 		if (pre_dive_offset > end_dive_offset)
 			break;
@@ -740,39 +702,33 @@ cochran_get_sample_parms(dc_device_t *abstract)
 	}
 
 	if (pre_dive_offset > end_dive_offset) {
-		// Since I can't tell how much memory it has, I'll round.
-		// 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;
+		high_offset = device->info->rb_profile_end;
 		low_offset = device->info->rb_profile_begin;
-		d->sample_data_offset = low_offset;
-		d->sample_size = high_offset - low_offset;
+		data->sample_data_offset = low_offset;
+		data->sample_size = high_offset - low_offset;
 	} else if (low_offset < 0xFFFFFFFF && high_offset > 0) {
-		// Round offset and size to 16K boundary
-		d->sample_data_offset = low_offset & 0xFFFFC000;
-		high_offset = ((high_offset  - 1) & 0xFFFFC000) + 0x4000;
-		d->sample_size = high_offset - d->sample_data_offset;
+		data->sample_data_offset = low_offset;
+		data->sample_size = high_offset - data->sample_data_offset;
 	} else {
-		d->sample_data_offset = 0;
-		d->sample_size = 0;
+		data->sample_data_offset = 0;
+		data->sample_size = 0;
 	}
 }
 
 
 static dc_status_t
-cochran_read_samples(dc_device_t *abstract, dc_event_progress_t *progress)
+cochran_read_samples(dc_device_t *abstract, cochran_data_t *data, dc_event_progress_t *progress)
 {
 	cochran_device_t *device = (cochran_device_t *) abstract;
-	cochran_data_t *d = (cochran_data_t *) &device->data;
 	dc_status_t rc;
 
 
-	if (d->sample_size > 0) {
-		if (d->sample)
-			free(d->sample);
+	if (data->sample_size > 0) {
+		if (data->sample)
+			free(data->sample);
 
-		d->sample = (unsigned char *) malloc(d->sample_size);
-		if (d->sample == NULL) {
+		data->sample = (unsigned char *) malloc(data->sample_size);
+		if (data->sample == NULL) {
 			ERROR (abstract->context, "Failed to allocate memory.");
 			return DC_STATUS_NOMEMORY;
 		}
@@ -780,11 +736,13 @@ cochran_read_samples(dc_device_t *abstract, dc_event_progress_t *progress)
 		serial_sleep(device->port, 800);
 
 		// set back to 9600 baud
-		cochran_commander_serial_setup(device);
+		rc = cochran_commander_serial_setup(device);
+		if (rc != DC_STATUS_SUCCESS)
+			return rc;
 
 		// Read the sample data
-		rc = cochran_commander_read (abstract, progress, d->sample_data_offset,
-				d->sample, d->sample_size);
+		rc = cochran_commander_read (abstract, progress, data->sample_data_offset,
+				data->sample, data->sample_size);
 		if (rc != DC_STATUS_SUCCESS) {
 			ERROR (abstract->context, "Failed to read the sample data.");
 			return rc;
@@ -796,11 +754,10 @@ cochran_read_samples(dc_device_t *abstract, dc_event_progress_t *progress)
 
 
 static dc_status_t
-cochran_commander_device_read_all (dc_device_t *abstract)
+cochran_commander_device_read_all (dc_device_t *abstract, cochran_data_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_progress_t progress = EVENT_PROGRESS_INITIALIZER;
 
 	dc_status_t rc;
 	int max_config, max_logbook, max_sample;
@@ -815,39 +772,42 @@ cochran_commander_device_read_all (dc_device_t *abstract)
 	device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
 
 	// Read config
-	rc = cochran_read_config(abstract, &progress);
+	rc = cochran_read_config(abstract, data, &progress);
 	if (rc != DC_STATUS_SUCCESS)
 		return rc;
 
 	// Determine size of dive list to read. Round up to nearest 16K
 	if (device->info->endian == ENDIAN_LE)
-		d->dive_count = array_uint16_le (d->config[0] + device->conf_ptr->dive_count);
+		data->dive_count = array_uint16_le (data->config + device->conf_ptr->dive_count);
 	else
-		d->dive_count = array_uint16_be (d->config[0] + device->conf_ptr->dive_count);
+		data->dive_count = array_uint16_be (data->config + device->conf_ptr->dive_count);
 
-	d->logbook_size = ((d->dive_count * device->info->log_size) & 0xFFFFC000)
-		 + 0x4000;
+	if (data->dive_count > device->info->logbook_entry_count) {
+		data->logbook_size = device->info->logbook_entry_count * device->info->logbook_entry_size;
+	} else {
+		data->logbook_size = data->dive_count * device->info->logbook_entry_size;
+	}
 
-	progress.maximum -= max_logbook - d->logbook_size;
+	progress.maximum -= max_logbook - data->logbook_size;
 	device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
 
-	rc = cochran_read_logbook(abstract, &progress);
+	rc = cochran_read_logbook(abstract, data, &progress);
 	if (rc != DC_STATUS_SUCCESS)
 		return rc;
 
 	// Determine sample memory to read
-	cochran_find_fingerprint(abstract);
-	cochran_get_sample_parms(abstract);
+	cochran_find_fingerprint(abstract, data);
+	cochran_get_sample_parms(abstract, data);
 
-	progress.maximum -= max_sample - d->sample_size;
+	progress.maximum -= max_sample - data->sample_size;
 	device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
 
-	rc = cochran_read_samples(abstract, &progress);
+	rc = cochran_read_samples(abstract, data, &progress);
 	if (rc != DC_STATUS_SUCCESS)
 		return rc;
 
 	// Determine logs that haven't had profile data overwritten
-	cochran_check_profiles(abstract);
+	cochran_check_profiles(abstract, data);
 
 	return DC_STATUS_SUCCESS;
 }
@@ -859,64 +819,49 @@ cochran_commander_device_read_all (dc_device_t *abstract)
 									(d)[3] = ((i) >> 24) & 0xff)
 
 dc_status_t
-cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *data)
+cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *dump)
 {
 	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_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
 	dc_status_t rc;
-	int size;
+	cochran_data_t data;
+	data.logbook = NULL;
+	data.sample = NULL;
 
 	// Make sure buffer is good.
-	if (!dc_buffer_clear(data)) {
+	if (!dc_buffer_clear(dump)) {
 		ERROR (abstract->context, "Uninitialized buffer.");
 		return DC_STATUS_INVALIDARGS;
 	}
 
-	// Determine size for progress
-	size = 512 + 512 + 1500 + device->info->rb_profile_end;
+	// Reserve space
+	if (!dc_buffer_resize(dump, device->info->rb_profile_end)) {
+		ERROR(abstract->context, "Insufficient buffer space available.");
+		return DC_STATUS_NOMEMORY;
+	}
 
+	// Determine size for progress
 	progress.current = 0;
-	progress.maximum = size;
+	progress.maximum = 512 + device->info->rb_profile_end;
 	device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
 
-	// Emit ID blocks as vendor data
-	if (d->extra_id_flag) {
-		vendor.data = d->id0;
-		vendor.size = 67;
-		device_event_emit (abstract, DC_EVENT_VENDOR, &vendor);
-	}
-
-	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;
-
-	rc = cochran_read_misc (abstract, &progress);
+	rc = cochran_read_config (abstract, &data, &progress);
 	if (rc != DC_STATUS_SUCCESS)
 		return rc;
 
 	// Read logbook and sample memory
 
-	// Reserve space
-	if (!dc_buffer_resize(data, device->info->rb_profile_end)) {
-		ERROR(abstract->context, "Insufficient buffer space available.");
-		return DC_STATUS_NOMEMORY;
-	}
-
 	serial_sleep(device->port, 800);
 
 	// set back to 9600 baud
-	cochran_commander_serial_setup(device);
+	rc = cochran_commander_serial_setup(device);
+	if (rc != DC_STATUS_SUCCESS) {
+		return rc;
+	}
 
 	// Read the sample data, from 0 to sample end will include logbook
 	rc = cochran_commander_read (abstract, &progress, 0,
-			dc_buffer_get_data(data), device->info->rb_profile_end);
+			dc_buffer_get_data(dump), device->info->rb_profile_end);
 	if (rc != DC_STATUS_SUCCESS) {
 		ERROR (abstract->context, "Failed to read the sample data.");
 		return rc;
@@ -935,15 +880,15 @@ cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *data)
 static unsigned int
 cochran_guess_sample_end_address(cochran_device_t *device, cochran_data_t *data, unsigned int log_num)
 {
-	const unsigned char *log_entry = data->logbook + device->info->log_size * log_num;
+	const unsigned char *log_entry = data->logbook + device->info->logbook_entry_size * log_num;
 
 	if (log_num == data->dive_count)
-		// Return next usable address from config0 page
-		return array_uint32_le(data->config[0]
+		// Return next usable address from config page
+		return array_uint32_le(data->config
 			+ device->info->rb_profile_end);
 
 	// Next log's start address
-	return array_uint32_le(log_entry + device->info->log_size + 6);
+	return array_uint32_le(log_entry + device->info->logbook_entry_size + 6);
 }
 
 
@@ -952,7 +897,6 @@ cochran_commander_device_foreach (dc_device_t *abstract,
 		dc_dive_callback_t callback, void *userdata)
 {
 	cochran_device_t *device = (cochran_device_t *) abstract;
-	cochran_data_t *data = &device->data;
 
 	unsigned int sample_start_address, sample_end_address;
 	dc_status_t rc;
@@ -960,28 +904,47 @@ cochran_commander_device_foreach (dc_device_t *abstract,
 	unsigned char *log_entry, *fingerprint, *sample, *dive;
 	int sample_size, dive_size;
 
-	rc = cochran_commander_device_read_all (abstract);
+	cochran_data_t data;
+	data.logbook = NULL;
+	data.sample = NULL;
+	rc = cochran_commander_device_read_all (abstract, &data);
+
+	// Emit a device info event.
+	dc_event_devinfo_t devinfo;
+	devinfo.model = abstract->devinfo.model;
+	devinfo.firmware = 0;	// unknown
+	devinfo.serial = array_uint32_le(data.config + device->conf_ptr->serial_number);
+	device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);
 
 	if (rc != DC_STATUS_SUCCESS)
 		return rc;
 
 	// Loop through each dive
 	int i;
-	for (i = data->dive_count - 1; i > data->fp_dive_num; i--) {
-		log_entry = data->logbook + i * device->info->log_size;
+	for (i = data.dive_count - 1; i > data.fp_dive_num; i--) {
+		log_entry = data.logbook + i * device->info->logbook_entry_size;
 
 		sample_start_address = array_uint32_le (log_entry + 6);
-		sample_end_address = array_uint32_le (log_entry + device->info->log_size / 2);
+		sample_end_address = array_uint32_le (log_entry + device->info->logbook_entry_size / 2);
+
+		// Validate
+		if (sample_start_address < device->info->rb_profile_begin
+				|| sample_start_address > device->info->rb_profile_end
+				|| sample_end_address < device->info->rb_profile_begin
+				|| (sample_end_address > device->info->rb_profile_end
+				&&  sample_end_address != 0xFFFFFFFF)) {
+			continue;
+		}
 
 		if (sample_end_address == 0xFFFFFFFF)
 			// Corrupt dive, guess the end address
-			sample_end_address = cochran_guess_sample_end_address(device, data, i);
+			sample_end_address = cochran_guess_sample_end_address(device, &data, i);
 
-		sample = data->sample + sample_start_address - data->sample_data_offset;
+		sample = data.sample + sample_start_address - data.sample_data_offset;
 
 		// Determine size of sample
 		unsigned int dive_num =array_uint16_le(log_entry + device->log_ptr->dive_number);
-		if (dive_num >= data->profile_tail)
+		if (dive_num >= data.profile_tail)
 			sample_size = sample_end_address - sample_start_address;
 		else
 			sample_size = 0;
@@ -991,28 +954,28 @@ cochran_commander_device_foreach (dc_device_t *abstract,
 			sample_size += device->info->rb_profile_end
 				- device->info->rb_profile_begin;
 
-		fingerprint = log_entry + device->log_ptr->dive_number;
+		fingerprint = log_entry;	// Date bytes
 
 		// Build dive blob
-		dive_size = device->info->log_size + sample_size;
+		dive_size = device->info->logbook_entry_size + sample_size;
 		dive = (unsigned char *) malloc(dive_size);
 		if (dive == NULL)
 			return DC_STATUS_NOMEMORY;
 
-		memcpy(dive, log_entry, device->info->log_size); // log
+		memcpy(dive, log_entry, device->info->logbook_entry_size); // log
 
 		// Copy profile data
 		if (sample_size) {
 			if (sample_start_address <= sample_end_address) {
-				memcpy(dive + device->info->log_size, sample,
+				memcpy(dive + device->info->logbook_entry_size, sample,
 					sample_size);
 			} else {
 				// It wrapped the buffer, copy two sections
 				unsigned int size = device->info->rb_profile_end - sample_start_address;
 
-				memcpy(dive + device->info->log_size, sample, size);
-				memcpy(dive + device->info->log_size + size,
-					data->sample, sample_end_address - device->info->rb_profile_begin);
+				memcpy(dive + device->info->logbook_entry_size, sample, size);
+				memcpy(dive + device->info->logbook_entry_size + size,
+					data.sample, sample_end_address - device->info->rb_profile_begin);
 			}
 		}
 
@@ -1038,16 +1001,16 @@ cochran_commander_device_foreach (dc_device_t *abstract,
 */
 
 static void
-cochran_check_profiles(dc_device_t *abstract) {
+cochran_check_profiles(dc_device_t *abstract, cochran_data_t *data) {
 	cochran_device_t *device = (cochran_device_t *) abstract;
 
 	// Find head log entry
 	// Set handy point to first dive's dive number
-	unsigned char *l = device->data.logbook + device->log_ptr->dive_number;
+	unsigned char *l = data->logbook + device->log_ptr->dive_number;
 	int head;
-	for (head = 0; head < device->info->max_log - 1; head ++) {
+	for (head = 0; head < device->info->logbook_entry_count - 1; head ++) {
 		int this_dive = array_uint16_le(l);
-		l += device->info->log_size;
+		l += device->info->logbook_entry_size;
 		int next_dive = array_uint16_le(l);
 
 		if (next_dive < this_dive || next_dive == 0xFFFF)
@@ -1057,9 +1020,9 @@ cochran_check_profiles(dc_device_t *abstract) {
 	// This is the last piece of data
 	unsigned int head_ptr;
 	if (device->info->endian == ENDIAN_LE)
-		head_ptr = array_uint32_le(device->data.config[0] + device->conf_ptr->last_log);
+		head_ptr = array_uint32_le(data->config + device->conf_ptr->last_log);
 	else
-		head_ptr = array_uint32_be(device->data.config[0] + device->conf_ptr->last_log);
+		head_ptr = array_uint32_be(data->config + device->conf_ptr->last_log);
 
 	// Cochran (commander at least) erases 8k blocks, so round up
 	head_ptr = (head_ptr & 0xfffff000) + 0x2000;
@@ -1071,16 +1034,16 @@ cochran_check_profiles(dc_device_t *abstract) {
 	int profile_wrap = 0;
 	int n = head - 1;
 	if (n < 0)
-		n = MIN(device->info->max_log - 1, head);
+		n = MIN(device->info->logbook_entry_count - 1, head);
 
 	while (n != head) {
-		unsigned int start_dive_ptr = array_uint32_le(device->data.logbook + device->info->log_size * n + device->log_ptr->profile_begin_offset);
-		unsigned int end_dive_ptr = array_uint32_le(device->data.logbook + device->info->log_size * n + device->log_ptr->profile_end_offset);
+		unsigned int start_dive_ptr = array_uint32_le(data->logbook + device->info->logbook_entry_size * n + device->log_ptr->profile_begin_offset);
+		unsigned int end_dive_ptr = array_uint32_le(data->logbook + device->info->logbook_entry_size * n + device->log_ptr->profile_end_offset);
 
 		if (start_dive_ptr == 0xFFFFFFFF || start_dive_ptr == 0) {
 			n--;
 			if (n < 0)
-				n = MIN(device->info->max_log - 1, head);
+				n = MIN(device->info->logbook_entry_count - 1, head);
 			continue;
 		}
 
@@ -1098,11 +1061,11 @@ cochran_check_profiles(dc_device_t *abstract) {
 
 		n--;
 		if (n < 0)
-			n = MIN(device->info->max_log - 1, head);
+			n = MIN(device->info->logbook_entry_count - 1, head);
 	}
 
-	device->data.log_head = head;
-	device->data.profile_head = head;
+	data->log_head = head;
+	data->profile_head = head;
 
-	device->data.profile_tail = tail;
+	data->profile_tail = tail;
 }
diff --git a/src/cochran_commander.h b/src/cochran_commander.h
index 22f17a3..f6e3921 100644
--- a/src/cochran_commander.h
+++ b/src/cochran_commander.h
@@ -24,30 +24,21 @@
 #define COCHRAN_TIMESTAMP_OFFSET	694242000
 
 #define COCHRAN_MODEL_SIZE			8
-#define COCHRAN_FINGERPRINT_SIZE	2
+#define COCHRAN_FINGERPRINT_SIZE	6
 
 #define UNSUPPORTED 0xFFFFFFFF
 
-typedef enum cochran_model_t {
-	COCHRAN_MODEL_UNKNOWN = 0,
-	COCHRAN_MODEL_EMC_FAMILY = 1 << 16,
-	COCHRAN_MODEL_EMC_14,
-	COCHRAN_MODEL_EMC_16,
-	COCHRAN_MODEL_EMC_20,
-	COCHRAN_MODEL_COMMANDER_FAMILY = 2 << 16,
-	COCHRAN_MODEL_COMMANDER_AIR_NITROX,
-} cochran_model_t;
+#define COCHRAN_MODEL_UNKNOWN = -1,
+#define COCHRAN_MODEL_COMMANDER_AIR_NITROX 0
+#define COCHRAN_MODEL_EMC_14 1
+#define COCHRAN_MODEL_EMC_16 2
+#define COCHRAN_MODEL_EMC_20 3
 
 typedef enum cochran_endian_t {
 	ENDIAN_LE,
 	ENDIAN_BE,
 } cochran_endian_t;
 
-typedef enum cochran_addresssize_t {
-	ADDRESS_24_BIT,
-	ADDRESS_32_BIT,
-} cochran_addresssize_t;
-
 typedef enum cochran_sample_format_t {
 	SAMPLE_UNKNOWN,
 	SAMPLE_CMDR,
@@ -58,8 +49,8 @@ typedef enum cochran_sample_format_t {
 // Used in reading the information from the device
 // and (in the case of max_*) used when decoding.
 typedef struct cochran_device_info_t {
-	cochran_model_t model;
-	cochran_addresssize_t address_size;
+	int model;
+	int address_bits;
 	cochran_endian_t endian;
 	int high_baud;
 
@@ -68,8 +59,8 @@ typedef struct cochran_device_info_t {
 	int rb_profile_begin;
 	int rb_profile_end;
 
-	int log_size;
-	int max_log;
+	int logbook_entry_size;
+	int logbook_entry_count;
 	int max_gas;
 
 	cochran_sample_format_t sample_format;
@@ -80,6 +71,7 @@ typedef struct cochran_conf_offsets_t {
 	int dive_count;
 	int last_log;
 	int last_interdive;
+	int serial_number;
 } cochran_conf_offsets_t;
 
 // Offsets into each log block
@@ -104,18 +96,11 @@ typedef struct cochran_log_offsets_t {
 } cochran_log_offsets_t;
 
 typedef struct cochran_data_t {
-	unsigned char id0[67];
-	unsigned char id[67];
-	unsigned char config[2][512];
-	unsigned char misc[1500];
+	unsigned char config[512];
 	unsigned char *logbook;
 	unsigned char *sample;
 
-	unsigned int extra_id_flag;
-	unsigned int config_count;
-
 	unsigned short int dive_count;
-	unsigned char fingerprint[COCHRAN_FINGERPRINT_SIZE];
 	int fp_dive_num;
 	int log_head, log_tail;			// head and tail for log ringbuffer
 	int profile_head, profile_tail;	// Entries that have valid profiles
@@ -133,14 +118,13 @@ struct event_size {
 
 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_device_info_t *info;
-	cochran_conf_offsets_t *conf_ptr;
-	cochran_log_offsets_t *log_ptr;
-	struct event_size (*event_bytes)[15];
-	cochran_data_t data;			// dive data used in parsing
+	unsigned char fingerprint[COCHRAN_FINGERPRINT_SIZE];
+	const cochran_device_info_t *info;
+	const cochran_conf_offsets_t *conf_ptr;
+	const cochran_log_offsets_t *log_ptr;
+	const struct event_size (*event_bytes)[15];
 } cochran_device_t;
 
 
@@ -157,4 +141,4 @@ dc_status_t cochran_commander_device_dump (dc_device_t *abstract,
 		dc_buffer_t *data);
 int cochran_commander_model_id(const char *model);
 dc_status_t cochran_commander_info(const int model,
-		cochran_device_info_t **info, cochran_conf_offsets_t **conf_ptr, cochran_log_offsets_t **log_ptr, struct event_size (**event_bytes)[15]);
+		const cochran_device_info_t **info, const cochran_conf_offsets_t **conf_ptr, const cochran_log_offsets_t **log_ptr, const struct event_size (**event_bytes)[15]);
diff --git a/src/cochran_commander_parser.c b/src/cochran_commander_parser.c
index 45184fe..0100a94 100644
--- a/src/cochran_commander_parser.c
+++ b/src/cochran_commander_parser.c
@@ -81,9 +81,9 @@ typedef struct cochran_commander_parser_t cochran_commander_parser_t;
 struct cochran_commander_parser_t {
 	dc_parser_t base;
 	unsigned int model;
-	cochran_device_info_t *info;
-	cochran_log_offsets_t *log_ptr;
-	struct event_size (*event_bytes)[15];
+	const cochran_device_info_t *info;
+	const cochran_log_offsets_t *log_ptr;
+	const struct event_size (*event_bytes)[15];
 };
 
 static dc_parser_vtable_t cochran_commander_parser_vtable = {
@@ -136,7 +136,7 @@ cochran_commander_parser_get_datetime (dc_parser_t *abstract,
 		dc_datetime_t *datetime)
 {
 	cochran_commander_parser_t *parser = (cochran_commander_parser_t *) abstract;
-	cochran_log_offsets_t *l = parser->log_ptr;
+	const cochran_log_offsets_t *l = parser->log_ptr;
 	const unsigned char *log_entry = abstract->data;
 
 	datetime->second = log_entry[l->sec];
@@ -220,7 +220,7 @@ cochran_commander_handle_event (dc_parser_t *abstract,
 *	Used to find the end of a dive that has an incomplete dive-end
 *	block. It parses backwards past inter-dive events.
 */
-int cochran_backparse(dc_parser_t *abstract, unsigned const char *samples, int size, struct event_size (*event_bytes)[15]) {
+int cochran_backparse(dc_parser_t *abstract, unsigned const char *samples, int size, const struct event_size (*event_bytes)[15]) {
 	int result = size, best_result = size;
 
 	for (int x = 0; (*event_bytes)[x].code != -1; x++) {
@@ -351,9 +351,9 @@ cochran_commander_parser_samples_foreach (dc_parser_t *abstract,
 	const cochran_commander_parser_t *parser = (cochran_commander_parser_t *) abstract;
 	const cochran_log_offsets_t *l = parser->log_ptr;
 	const unsigned char *log_entry = abstract->data;
-	const unsigned char *samples = log_entry + parser->info->log_size;
+	const unsigned char *samples = log_entry + parser->info->logbook_entry_size;
 
-	unsigned int size = abstract->size - parser->info->log_size;
+	unsigned int size = abstract->size - parser->info->logbook_entry_size;
 
 	int sampling_size;
 	switch (parser->info->sample_format) {
-- 
2.4.3



More information about the devel mailing list