Send the command and read the echo byte by byte.

When trying to send a command, the first attempt always fails. We
receive the echo, but no data packet. A second attempt usually works,
but we always get back the same data packet. That's cleary wrong.

Now, when comparing the data packets with those of the Tusa application,
I noticed something very interesting. When we request the first packet
(page 0x0000), we get:

  W: 520000
  R: 520000
  R: 00880124056202000250002890470824...19202720002000200020002000204145

The Tusa application also request this page, but the response is
completely different:

  W: 520000
  R: 520000
  R: 22182224222322092203220522112210...0000000000f021fc0000000000000045

The response we get is identical to the response that the Tusa
application gets for page 0x0052:

  W: 520052
  R: 520052
  R: 00880124056202000250002890470824...19202720002000200020002000204145

The only difference here is the echo of the command. But the echo should
be ignored, because it's generated by the pc interface, and not send by
the dive computer. This is easily verified by the fact that we always
receive an echo, even without a dive computer connected (e.g. only the
pc interface).

Notice how the command type (first byte) and page number (last byte) are
identical (0x52) for this request! I suspect that somehow the command
type ends up being interpreted as the page number. That would explain
why we're always getting the same response: as far as the device is
concerned we're always requesting page 0x52. This is probably also
related to the fact that the device doesn't respond after the first
request. It's not impossible that if the first command wasn't received
correctly and we resend the command, the device receives something that
contains parts of both attempts.

By sending the command and reading the echo byte by byte instead of all
at once, the above problem disappears.
This commit is contained in:
Jef Driesen 2015-03-19 20:23:47 +01:00
parent edd777dbd3
commit c4233c091d

View File

@ -83,35 +83,45 @@ cressi_edy_packet (cressi_edy_device_t *device, const unsigned char command[], u
{
dc_device_t *abstract = (dc_device_t *) device;
assert (asize >= csize);
if (device_is_cancelled (abstract))
return DC_STATUS_CANCELLED;
// Send the command to the device.
int n = serial_write (device->port, command, csize);
if (n != csize) {
ERROR (abstract->context, "Failed to send the command.");
return EXITCODE (n);
for (unsigned int i = 0; i < csize; ++i) {
// Send the command to the device.
int n = serial_write (device->port, command + i, 1);
if (n != 1) {
ERROR (abstract->context, "Failed to send the command.");
return EXITCODE (n);
}
// Receive the echo.
unsigned char echo = 0;
n = serial_read (device->port, &echo, 1);
if (n != 1) {
ERROR (abstract->context, "Failed to receive the echo.");
return EXITCODE (n);
}
// Verify the echo.
if (command[i] != echo) {
ERROR (abstract->context, "Unexpected echo.");
return DC_STATUS_PROTOCOL;
}
}
// Receive the answer of the device.
n = serial_read (device->port, answer, asize);
if (n != asize) {
ERROR (abstract->context, "Failed to receive the answer.");
return EXITCODE (n);
}
if (asize) {
// Receive the answer of the device.
int n = serial_read (device->port, answer, asize);
if (n != asize) {
ERROR (abstract->context, "Failed to receive the answer.");
return EXITCODE (n);
}
// Verify the echo.
if (memcmp (answer, command, csize) != 0) {
ERROR (abstract->context, "Unexpected echo.");
return DC_STATUS_PROTOCOL;
}
// Verify the trailer of the packet.
if (trailer && answer[asize - 1] != 0x45) {
ERROR (abstract->context, "Unexpected answer trailer byte.");
return DC_STATUS_PROTOCOL;
// Verify the trailer of the packet.
if (trailer && answer[asize - 1] != 0x45) {
ERROR (abstract->context, "Unexpected answer trailer byte.");
return DC_STATUS_PROTOCOL;
}
}
return DC_STATUS_SUCCESS;
@ -142,7 +152,7 @@ static dc_status_t
cressi_edy_init1 (cressi_edy_device_t *device)
{
unsigned char command[3] = {0x41, 0x42, 0x43};
unsigned char answer[6] = {0};
unsigned char answer[3] = {0};
return cressi_edy_transfer (device, command, sizeof (command), answer, sizeof (answer), 0);
}
@ -152,13 +162,13 @@ static dc_status_t
cressi_edy_init2 (cressi_edy_device_t *device)
{
unsigned char command[1] = {0x44};
unsigned char answer[2] = {0};
unsigned char answer[1] = {0};
dc_status_t rc = cressi_edy_transfer (device, command, sizeof (command), answer, sizeof (answer), 0);
if (rc != DC_STATUS_SUCCESS)
return rc;
device->model = answer[1];
device->model = answer[0];
return DC_STATUS_SUCCESS;
}
@ -168,7 +178,7 @@ static dc_status_t
cressi_edy_init3 (cressi_edy_device_t *device)
{
unsigned char command[1] = {0x0C};
unsigned char answer[2] = {0};
unsigned char answer[1] = {0};
return cressi_edy_transfer (device, command, sizeof (command), answer, sizeof (answer), 1);
}
@ -178,9 +188,8 @@ static dc_status_t
cressi_edy_quit (cressi_edy_device_t *device)
{
unsigned char command[1] = {0x46};
unsigned char answer[1] = {0};
return cressi_edy_transfer (device, command, sizeof (command), answer, sizeof (answer), 0);
return cressi_edy_transfer (device, command, sizeof (command), NULL, 0, 0);
}
@ -301,7 +310,7 @@ cressi_edy_device_read (dc_device_t *abstract, unsigned int address, unsigned ch
while (nbytes < size) {
// Read the package.
unsigned int number = address / SZ_PAGE;
unsigned char answer[3 + SZ_PACKET + 1] = {0};
unsigned char answer[SZ_PACKET + 1] = {0};
unsigned char command[3] = {0x52,
(number >> 8) & 0xFF, // high
(number ) & 0xFF}; // low
@ -309,7 +318,7 @@ cressi_edy_device_read (dc_device_t *abstract, unsigned int address, unsigned ch
if (rc != DC_STATUS_SUCCESS)
return rc;
memcpy (data, answer + 3, SZ_PACKET);
memcpy (data, answer, SZ_PACKET);
nbytes += SZ_PACKET;
address += SZ_PACKET;