Scubapro Galileo 2 (G2)

Jef Driesen jef at libdivecomputer.org
Wed Jun 14 04:14:56 PDT 2017


On 2017-06-09 07:28, Linus Torvalds wrote:
> diff --git a/examples/common.c b/examples/common.c
> index 3c4561b..5ebdd77 100644
> --- a/examples/common.c
> +++ b/examples/common.c
> @@ -54,6 +54,7 @@ static const backend_table_t g_backends[] = {
>  	{"smart",       DC_FAMILY_UWATEC_SMART,        0x10},
> +	{"g2",          DC_FAMILY_UWATEC_SMART,        0x10},
>  	{"meridian",    DC_FAMILY_UWATEC_MERIDIAN,     0x20},

I think you meant DC_FAMILY_SCUBAPRO_G2 here.

> diff --git a/include/libdivecomputer/common.h 
> b/include/libdivecomputer/common.h
> index 67398d1..fdaaa1b 100644
> --- a/include/libdivecomputer/common.h
> +++ b/include/libdivecomputer/common.h
> @@ -59,6 +59,8 @@ typedef enum dc_family_t {
>  	DC_FAMILY_UWATEC_MEMOMOUSE,
>  	DC_FAMILY_UWATEC_SMART,
>  	DC_FAMILY_UWATEC_MERIDIAN,
> +	/* We'll enumerate the Scubapro G2 under Uwatec */
> +	DC_FAMILY_SCUBAPRO_G2,

For consistency with the other uwatec/scubapro backends, replace 
DC_FAMILY_SCUBAPRO_G2 with DC_FAMILY_UWATEC_G2. Same remark for the 
filenames. For end-users the fact that the internal name is uwatec 
instead of scubapro doesn't really matter, because they will only see 
the name "Scubapro G2".

BTW, we now have 3 backends (smart, meridian and g2) using the exact 
same communication protocol, but with a different transport (irda, 
usb-serial and usbhid). I wonder if we can merge this back into a single 
backend some day? Because once the I/O refactoring lands, the difference 
between the transports will disappear and those backends will even look 
more similar.

The main difference is the transfer function. For the smart it's a plain 
IrDA read/write, for the meridian there is some additional framing 
added, and for the G2 there is the USB HID packet stuff.

> diff --git a/src/parser.c b/src/parser.c
> index ebbc6a6..fea1454 100644
> --- a/src/parser.c
> +++ b/src/parser.c
> @@ -96,6 +96,9 @@ dc_parser_new_internal (dc_parser_t **out, 
> dc_context_t *context, dc_family_t fa
>  	case DC_FAMILY_UWATEC_MEMOMOUSE:
>  		rc = uwatec_memomouse_parser_create (&parser, context, devtime, 
> systime);
>  		break;
> +	case DC_FAMILY_SCUBAPRO_G2:
> +		rc = uwatec_smart_parser_create (&parser, context, 0x11, devtime, 
> systime);
> +		break;
>  	case DC_FAMILY_UWATEC_SMART:
>  	case DC_FAMILY_UWATEC_MERIDIAN:
>  		rc = uwatec_smart_parser_create (&parser, context, model, devtime, 
> systime);

Is there a reason why you have hardcoded the model number to 0x11? Does 
the data contain a different model number? Because in that case we 
should update the parser to support the new model number.

> +typedef struct scubapro_g2_device_t {
> +	...
> +	unsigned int address;
> +	...
> +} scubapro_g2_device_t;

The address member is a left-over from the irda code and can be removed.

> +#define PACKET_SIZE 64
> +static int receive_data(scubapro_g2_device_t *g2, unsigned char 
> *buffer, int size)
> +{
> +	while (size) {
> +		unsigned char buf[PACKET_SIZE];
> +		size_t transferred = 0;
> +		dc_status_t rc;
> +		int len;
> +
> +		rc = dc_usbhid_read(g2->usbhid, buf, PACKET_SIZE, &transferred);
> +		if (rc != DC_STATUS_SUCCESS) {
> +			ERROR(g2->base.context, "read interrupt transfer failed");
> +			return -1;
> +		}
> +		if (transferred != PACKET_SIZE) {
> +			ERROR(g2->base.context, "incomplete read interrupt transfer (got 
> %zu, expected %d)", transferred, PACKET_SIZE);
> +			return -1;
> +		}
> +		len = buf[0];
> +		if (len >= PACKET_SIZE) {
> +			ERROR(g2->base.context, "read interrupt transfer returns impossible 
> packet size (%d)", len);
> +			return -1;
> +		}
> +		HEXDUMP (g2->base.context, DC_LOGLEVEL_DEBUG, "rcv", buf+1, len);
> +		if (len > size) {
> +			ERROR(g2->base.context, "receive result buffer too small - 
> truncating");
> +			len = size;
> +		}
> +		memcpy(buffer, buf+1, len);
> +		size -= len;
> +		buffer += len;
> +	}
> +	return 0;
> +}

There are a two issues with this code:

The error code from dc_usbhid_read is dropped and replaced with a 
generic -1, which is translated again to DC_STATUS_IO in the caller. It 
would be much better to pass the actual error code. The difference 
between for example TIMEOUT, IO and PROTOCOL errors is valuable info. 
(Maybe not for the end-user, but certainly for the developer debugging 
the problem.) Those other -1 should be translated into 
DC_STATUS_PROTOCOL.

Truncating the data if the buffer is too small is a bad idea because 
you'll return corrupt data. Just bail out with error DC_STATUS_PROTOCOL. 
If this ever happens, then it's most likely caused by a bug in the code 
or a change in the communication protocol. In both cases the code should 
be fixed.

> +dc_status_t
> +scubapro_g2_device_open(dc_device_t **out, dc_context_t *context)
> +{
> +	dc_status_t status = DC_STATUS_SUCCESS;
> +	scubapro_g2_device_t *device = NULL;
> +
> +	...
> +
> +	// Open the irda socket.
> +	status = dc_usbhid_open(&device->usbhid, context, 0x2e6c, 0x3201);
> +	if (status != DC_STATUS_SUCCESS) {
> +		ERROR (context, "Failed to open USB device");
> +		goto error_free;
> +	}
> +
> +	*out = (dc_device_t*) device;
> +
> +	return DC_STATUS_SUCCESS;
> +
> +error_free:
> +	dc_device_deallocate ((dc_device_t *) device);
> +	return status;
> +}

Is the handshaking no longer necessary for the G2? I've always wondered 
why it's there for the smart and meridian because it doesn't really 
return any useful info. It's certainly possible that it can be omitted, 
but I never really tried that. So I'm just curious why you left it out.

> +static dc_status_t
> +scubapro_g2_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
> +{
> +	scubapro_g2_device_t *device = (scubapro_g2_device_t*) abstract;
> +	dc_status_t rc = DC_STATUS_SUCCESS;
> +
> +	...
> +
> +	if (receive_data(device, data, length)) {
> +		ERROR (abstract->context, "Received an unexpected size.");
> +		return DC_STATUS_IO;
> +	}
> +
> +	...
> +
> +	return DC_STATUS_SUCCESS;
> +}

This will need some improvements to report more fine-grained progress 
events.

The rest looks good to me. Will you send an updated patch, or do I make 
the changes myself?

Jef


More information about the subsurface mailing list