Ignore excess bytes in the BLE version packet
For the Oceanic Pro Plus X and the Aqualung i770R, downloading over BLE
often fails because the version packet contains one or more unexpected
bytes.
For a successful download, the correct structure for the version packet
is as follows:
5A 4F4345414E4F43582031432030303032 C6
That's the start byte, the payload "OCEANOCX 1C 0002" and the checksum.
For all the failed packets, there are one or more bytes extra present
between the payload and the checksum:
5A 4F4345414E4F43582031432030303032 9F02 67
5A 4F4345414E4F43582031432030303032 3603 FF
5A 4F4345414E4F43582031432030303032 64 2A
5A 4F4345414E4F43582031432030303032 9202 5A
5A 4F4345414E4F43582031432030303032 08 CE
5A 4F4345414E4F43582031432030303032 2C01 F3
The amount of extra bytes, and their content appears to be pretty
random. The strangest part is that the checksum of the packet is
actually correct and includes those extra bytes!
As workaround, accept extra bytes in the BLE packet, verify the checksum
as usual, and finally strip the excess bytes and only pass the actual
content to the next layer. To avoid false positives, the workaround is
limited to packets with a payload and checksum, and only enabled for the
two affected models.
This commit is contained in:
parent
8a1d32d319
commit
ffa9e0aa3c
@ -65,6 +65,7 @@ typedef struct oceanic_atom2_device_t {
|
||||
dc_iostream_t *iostream;
|
||||
unsigned int sequence;
|
||||
unsigned int delay;
|
||||
unsigned int extra;
|
||||
unsigned int bigpage;
|
||||
unsigned char cache[256];
|
||||
unsigned int cached_page;
|
||||
@ -590,7 +591,7 @@ oceanic_atom2_ble_write (oceanic_atom2_device_t *device, const unsigned char dat
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
oceanic_atom2_ble_read (oceanic_atom2_device_t *device, unsigned char data[], unsigned int size)
|
||||
oceanic_atom2_ble_read (oceanic_atom2_device_t *device, unsigned char data[], unsigned int size, unsigned int *actual)
|
||||
{
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
@ -656,11 +657,15 @@ oceanic_atom2_ble_read (oceanic_atom2_device_t *device, unsigned char data[], un
|
||||
}
|
||||
|
||||
// Verify the expected number of bytes.
|
||||
if (nbytes != size) {
|
||||
if (nbytes > size) {
|
||||
ERROR (abstract->context, "Unexpected number of bytes received (%u %u).", nbytes, size);
|
||||
return DC_STATUS_PROTOCOL;
|
||||
}
|
||||
|
||||
if (actual) {
|
||||
*actual = nbytes;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -699,8 +704,13 @@ oceanic_atom2_packet (oceanic_atom2_device_t *device, const unsigned char comman
|
||||
|
||||
// Receive the answer of the dive computer.
|
||||
unsigned char packet[1 + MAXPACKET + 2];
|
||||
unsigned int nbytes = 1 + asize + crc_size;
|
||||
if (transport == DC_TRANSPORT_BLE) {
|
||||
status = oceanic_atom2_ble_read (device, packet, 1 + asize + crc_size);
|
||||
// Accept excess bytes for some models.
|
||||
if (asize && device->extra) {
|
||||
nbytes = 1 + MAXPACKET + crc_size;
|
||||
}
|
||||
status = oceanic_atom2_ble_read (device, packet, nbytes, &nbytes);
|
||||
} else {
|
||||
status = dc_iostream_read (device->iostream, packet, 1 + asize + crc_size, NULL);
|
||||
}
|
||||
@ -709,6 +719,14 @@ oceanic_atom2_packet (oceanic_atom2_device_t *device, const unsigned char comman
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the number of bytes.
|
||||
if (nbytes < 1 + asize + crc_size) {
|
||||
ERROR (abstract->context, "Unexpected number of bytes received (%u %u).", nbytes, 1 + asize + crc_size);
|
||||
return DC_STATUS_PROTOCOL;
|
||||
}
|
||||
|
||||
nbytes -= 1 + crc_size;
|
||||
|
||||
// Verify the ACK byte of the answer.
|
||||
if (packet[0] != ack) {
|
||||
ERROR (abstract->context, "Unexpected answer start byte(s).");
|
||||
@ -719,11 +737,11 @@ oceanic_atom2_packet (oceanic_atom2_device_t *device, const unsigned char comman
|
||||
// Verify the checksum of the answer.
|
||||
unsigned short crc, ccrc;
|
||||
if (crc_size == 2) {
|
||||
crc = array_uint16_le (packet + 1 + asize);
|
||||
ccrc = checksum_add_uint16 (packet + 1, asize, 0x0000);
|
||||
crc = array_uint16_le (packet + 1 + nbytes);
|
||||
ccrc = checksum_add_uint16 (packet + 1, nbytes, 0x0000);
|
||||
} else {
|
||||
crc = packet[1 + asize];
|
||||
ccrc = checksum_add_uint8 (packet + 1, asize, 0x00);
|
||||
crc = packet[1 + nbytes];
|
||||
ccrc = checksum_add_uint8 (packet + 1, nbytes, 0x00);
|
||||
}
|
||||
if (crc != ccrc) {
|
||||
ERROR (abstract->context, "Unexpected answer checksum.");
|
||||
@ -733,6 +751,10 @@ oceanic_atom2_packet (oceanic_atom2_device_t *device, const unsigned char comman
|
||||
memcpy (answer, packet + 1, asize);
|
||||
}
|
||||
|
||||
if (nbytes > asize) {
|
||||
WARNING (abstract->context, "Ignored %u excess byte(s).", nbytes - asize);
|
||||
}
|
||||
|
||||
device->sequence++;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
@ -852,6 +874,7 @@ oceanic_atom2_device_open (dc_device_t **out, dc_context_t *context, dc_iostream
|
||||
// Set the default values.
|
||||
device->iostream = iostream;
|
||||
device->delay = 0;
|
||||
device->extra = model == PROPLUSX || model == I770R;
|
||||
device->sequence = 0;
|
||||
device->bigpage = 1; // no big pages
|
||||
device->cached_page = INVALID;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user