[PATCH 5/6] Cochran: Dump of Commander TM devices is now supported

Jef Driesen jef at libdivecomputer.org
Thu Aug 10 08:00:14 PDT 2017


On 2017-07-15 22:39, John Van Ostrand wrote:
>  static dc_status_t
> -cochran_commander_read_config (cochran_commander_device_t *device,
> dc_event_progress_t *progress, unsigned char data[], unsigned int
> size)
> +cochran_commander_read_config (cochran_commander_device_t *device,
> dc_event_progress_t *progress, unsigned char data[])

Removing the size parameter is a bad idea. Any function that takes some 
buffer as argument should also have a corresponding size parameter. Even 
if it's only used to verify whether the caller passed the right amount:

if (size % 512 != 0)
    return some_error;

If you simply trust the caller to always pass a buffer of the right 
size, you'll run into trouble someday!

>  	dc_device_t *abstract = (dc_device_t *) device;
>  	dc_status_t rc = DC_STATUS_SUCCESS;
> 
> +	unsigned int pages = 2;
> +
> +	if (device->layout->model == COCHRAN_MODEL_COMMANDER_TM)
> +		pages = 1;
> +
>  	// Read two 512 byte blocks into one 1024 byte buffer
> -	for (unsigned int i = 0; i < 2; i++) {
> -		const unsigned int len = size / 2;
> +	for (unsigned int i = 0; i < pages; i++) {
> 
>  		unsigned char command[2] = {0x96, i};
> -		rc = cochran_commander_packet(device, progress, command,
> sizeof(command), data + i * len, len, 0);
> +		unsigned int command_size = 2;
> +		if (device->layout->model == COCHRAN_MODEL_COMMANDER_TM)
> +			command_size = 1;
> +
> +		rc = cochran_commander_packet(device, progress, command,
> command_size, data + i * 512, 512, 0);
>  		if (rc != DC_STATUS_SUCCESS)
>  			return rc;

How about using the size argument to calculate the number of pages? That 
way the function becomes even more generic. Only the caller needs to 
know how many pages there are. The function just needs to handle the 
difference between the 1 or 2 byte command variant (and even that can be 
based on the number of pages).

> +		if (device->layout->baudrate == 9600) {
> +			// Older commander, use low-speed read command
> +			command[0] = 0x05;
> +			command[1] = (address      ) & 0xff;
> +			command[2] = (address >>  8) & 0xff;
> +			command[3] = (address >> 16) & 0xff;
> +			command[4] = (size         ) & 0xff;
> +			command[5] = (size >> 8    ) & 0xff;
> +			command_size = 6;
> +		} else {
> +			// Newer commander with high-speed read command
> +			command[0] = 0x15;
> +			command[1] = (address      ) & 0xff;
> +			command[2] = (address >>  8) & 0xff;
> +			command[3] = (address >> 16) & 0xff;
> +			command[4] = (size         ) & 0xff;
> +			command[5] = (size >>  8   ) & 0xff;
> +			command[6] = (size >> 16   ) & 0xff;
> +			command[7] = 0x04;
> +			command_size = 8;
> +		}

So this means that the byte sequences:

05 9D FF 00 43 00
05 BD 7F 00 43 00

that are send in the cochran_commander_read_id() function are actually 
read operations at the addresses 0xFF9D and 0x7FBD (and a size of 0x0043 
bytes). Interesting. I didn't realize that before.

> -	// Read the sample data, from 0 to sample end will include logbook
> -	rc = cochran_commander_read (device, &progress,
> device->layout->rb_logbook_begin, dc_buffer_get_data(buffer),
> device->layout->rb_profile_end);
> +	// Read the sample data, logbook and sample data are contiguous
> +	rc = cochran_commander_read (device, &progress,
> device->layout->rb_logbook_begin, dc_buffer_get_data(buffer), size);
>  	if (rc != DC_STATUS_SUCCESS) {
>  		ERROR (abstract->context, "Failed to read the sample data.");
>  		return rc;

This can't work. The size variable is calculated as:

layout->rb_profile_end - layout->rb_logbook_begin

For the Commander TM that is 0x010000 bytes (0x020000 - 0x010000). But 
the size field in the command is only 16 bits wide. So you'll try to 
read 0 bytes. Oops. I think the only solution here is to split the large 
read operation into multiple smaller blocks.

Jef


More information about the devel mailing list