Merge branch 'ix3m'
This commit is contained in:
commit
434e765128
@ -42,7 +42,14 @@
|
|||||||
#define START 0x55
|
#define START 0x55
|
||||||
#define ACK 0x06
|
#define ACK 0x06
|
||||||
#define NAK 0x15
|
#define NAK 0x15
|
||||||
#define BUSY 0x60
|
|
||||||
|
#define ERR_INVALID_CMD 0x10
|
||||||
|
#define ERR_INVALID_LENGTH 0x20
|
||||||
|
#define ERR_INVALID_DATA 0x30
|
||||||
|
#define ERR_UNSUPPORTED 0x40
|
||||||
|
#define ERR_UNAVAILABLE 0x58
|
||||||
|
#define ERR_UNREADABLE 0x5F
|
||||||
|
#define ERR_BUSY 0x60
|
||||||
|
|
||||||
#define NSTEPS 1000
|
#define NSTEPS 1000
|
||||||
#define STEP(i,n) (NSTEPS * (i) / (n))
|
#define STEP(i,n) (NSTEPS * (i) / (n))
|
||||||
@ -291,72 +298,98 @@ divesystem_idive_receive (divesystem_idive_device_t *device, unsigned char answe
|
|||||||
|
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
divesystem_idive_transfer (divesystem_idive_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize)
|
divesystem_idive_packet (divesystem_idive_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize, unsigned int *errorcode)
|
||||||
{
|
{
|
||||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
dc_status_t status = DC_STATUS_SUCCESS;
|
||||||
dc_device_t *abstract = (dc_device_t *) device;
|
dc_device_t *abstract = (dc_device_t *) device;
|
||||||
unsigned char packet[MAXPACKET] = {0};
|
unsigned char packet[MAXPACKET] = {0};
|
||||||
unsigned int length = 0;
|
unsigned int length = sizeof(packet);
|
||||||
unsigned int nretries = 0;
|
unsigned int errcode = 0;
|
||||||
|
|
||||||
while (1) {
|
// Send the command.
|
||||||
// Send the command.
|
status = divesystem_idive_send (device, command, csize);
|
||||||
rc = divesystem_idive_send (device, command, csize);
|
if (status != DC_STATUS_SUCCESS) {
|
||||||
if (rc != DC_STATUS_SUCCESS)
|
goto error;
|
||||||
return rc;
|
}
|
||||||
|
|
||||||
// Receive the answer.
|
// Receive the answer.
|
||||||
length = sizeof(packet);
|
status = divesystem_idive_receive (device, packet, &length);
|
||||||
rc = divesystem_idive_receive (device, packet, &length);
|
if (status != DC_STATUS_SUCCESS) {
|
||||||
if (rc != DC_STATUS_SUCCESS)
|
goto error;
|
||||||
return rc;
|
}
|
||||||
|
|
||||||
// Verify the command byte.
|
// Verify the command byte.
|
||||||
if (packet[0] != command[0]) {
|
if (packet[0] != command[0]) {
|
||||||
ERROR (abstract->context, "Unexpected packet header.");
|
ERROR (abstract->context, "Unexpected packet header.");
|
||||||
return DC_STATUS_PROTOCOL;
|
status = DC_STATUS_PROTOCOL;
|
||||||
}
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
// Check the ACK byte.
|
// Verify the ACK/NAK byte.
|
||||||
if (packet[length - 1] == ACK)
|
unsigned int type = packet[length - 1];
|
||||||
break;
|
if (type != ACK && type != NAK) {
|
||||||
|
ERROR (abstract->context, "Unexpected ACK/NAK byte.");
|
||||||
// Verify the NAK byte.
|
status = DC_STATUS_PROTOCOL;
|
||||||
if (packet[length - 1] != NAK) {
|
goto error;
|
||||||
ERROR (abstract->context, "Unexpected ACK/NAK byte.");
|
|
||||||
return DC_STATUS_PROTOCOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify the length of the packet.
|
|
||||||
if (length != 3) {
|
|
||||||
ERROR (abstract->context, "Unexpected packet length.");
|
|
||||||
return DC_STATUS_PROTOCOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify the error code.
|
|
||||||
unsigned int errcode = packet[1];
|
|
||||||
if (errcode != BUSY) {
|
|
||||||
ERROR (abstract->context, "Received NAK packet with error code %02x.", errcode);
|
|
||||||
return DC_STATUS_PROTOCOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Abort if the maximum number of retries is reached.
|
|
||||||
if (nretries++ >= MAXRETRIES)
|
|
||||||
return DC_STATUS_PROTOCOL;
|
|
||||||
|
|
||||||
// Delay the next attempt.
|
|
||||||
dc_serial_sleep(device->port, 100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the length of the packet.
|
// Verify the length of the packet.
|
||||||
if (asize != length - 2) {
|
unsigned int expected = (type == ACK ? asize : 1) + 2;
|
||||||
|
if (length != expected) {
|
||||||
ERROR (abstract->context, "Unexpected packet length.");
|
ERROR (abstract->context, "Unexpected packet length.");
|
||||||
return DC_STATUS_PROTOCOL;
|
status = DC_STATUS_PROTOCOL;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the error code from a NAK packet.
|
||||||
|
if (type == NAK) {
|
||||||
|
errcode = packet[1];
|
||||||
|
ERROR (abstract->context, "Received NAK packet with error code %02x.", errcode);
|
||||||
|
status = DC_STATUS_PROTOCOL;
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(answer, packet + 1, length - 2);
|
memcpy(answer, packet + 1, length - 2);
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
error:
|
||||||
|
if (errorcode) {
|
||||||
|
*errorcode = errcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
divesystem_idive_transfer (divesystem_idive_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize, unsigned int *errorcode)
|
||||||
|
{
|
||||||
|
dc_status_t status = DC_STATUS_SUCCESS;
|
||||||
|
unsigned int errcode = 0;
|
||||||
|
|
||||||
|
unsigned int nretries = 0;
|
||||||
|
while ((status = divesystem_idive_packet (device, command, csize, answer, asize, &errcode)) != DC_STATUS_SUCCESS) {
|
||||||
|
// Automatically discard a corrupted packet,
|
||||||
|
// and request a new one.
|
||||||
|
if (status != DC_STATUS_PROTOCOL && status != DC_STATUS_TIMEOUT)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Abort if the device reports a fatal error.
|
||||||
|
if (errcode && errcode != ERR_BUSY)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Abort if the maximum number of retries is reached.
|
||||||
|
if (nretries++ >= MAXRETRIES)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Delay the next attempt.
|
||||||
|
dc_serial_sleep (device->port, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errorcode) {
|
||||||
|
*errorcode = errcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
@ -365,6 +398,7 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
|
|||||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||||
divesystem_idive_device_t *device = (divesystem_idive_device_t *) abstract;
|
divesystem_idive_device_t *device = (divesystem_idive_device_t *) abstract;
|
||||||
unsigned char packet[MAXPACKET - 2];
|
unsigned char packet[MAXPACKET - 2];
|
||||||
|
unsigned int errcode = 0;
|
||||||
|
|
||||||
const divesystem_idive_commands_t *commands = &idive;
|
const divesystem_idive_commands_t *commands = &idive;
|
||||||
if (device->model >= IX3M_EASY) {
|
if (device->model >= IX3M_EASY) {
|
||||||
@ -376,7 +410,7 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
|
|||||||
device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
|
device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
|
||||||
|
|
||||||
unsigned char cmd_id[] = {commands->id.cmd, 0xED};
|
unsigned char cmd_id[] = {commands->id.cmd, 0xED};
|
||||||
rc = divesystem_idive_transfer (device, cmd_id, sizeof(cmd_id), packet, commands->id.size);
|
rc = divesystem_idive_transfer (device, cmd_id, sizeof(cmd_id), packet, commands->id.size, &errcode);
|
||||||
if (rc != DC_STATUS_SUCCESS)
|
if (rc != DC_STATUS_SUCCESS)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -402,9 +436,14 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned char cmd_range[] = {commands->range.cmd, 0x8D};
|
unsigned char cmd_range[] = {commands->range.cmd, 0x8D};
|
||||||
rc = divesystem_idive_transfer (device, cmd_range, sizeof(cmd_range), packet, commands->range.size);
|
rc = divesystem_idive_transfer (device, cmd_range, sizeof(cmd_range), packet, commands->range.size, &errcode);
|
||||||
if (rc != DC_STATUS_SUCCESS)
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
return rc;
|
if (errcode == ERR_UNAVAILABLE) {
|
||||||
|
return DC_STATUS_SUCCESS; // No dives found.
|
||||||
|
} else {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get the range of the available dive numbers.
|
// Get the range of the available dive numbers.
|
||||||
unsigned int first = array_uint16_le (packet + 0);
|
unsigned int first = array_uint16_le (packet + 0);
|
||||||
@ -431,9 +470,15 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
|
|||||||
unsigned char cmd_header[] = {commands->header.cmd,
|
unsigned char cmd_header[] = {commands->header.cmd,
|
||||||
(number ) & 0xFF,
|
(number ) & 0xFF,
|
||||||
(number >> 8) & 0xFF};
|
(number >> 8) & 0xFF};
|
||||||
rc = divesystem_idive_transfer (device, cmd_header, sizeof(cmd_header), packet, commands->header.size);
|
rc = divesystem_idive_transfer (device, cmd_header, sizeof(cmd_header), packet, commands->header.size, &errcode);
|
||||||
if (rc != DC_STATUS_SUCCESS)
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
return rc;
|
if (errcode == ERR_UNREADABLE) {
|
||||||
|
WARNING(abstract->context, "Skipped unreadable dive!");
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (memcmp(packet + 7, device->fingerprint, sizeof(device->fingerprint)) == 0)
|
if (memcmp(packet + 7, device->fingerprint, sizeof(device->fingerprint)) == 0)
|
||||||
break;
|
break;
|
||||||
@ -453,7 +498,7 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
|
|||||||
unsigned char cmd_sample[] = {commands->sample.cmd,
|
unsigned char cmd_sample[] = {commands->sample.cmd,
|
||||||
(idx ) & 0xFF,
|
(idx ) & 0xFF,
|
||||||
(idx >> 8) & 0xFF};
|
(idx >> 8) & 0xFF};
|
||||||
rc = divesystem_idive_transfer (device, cmd_sample, sizeof(cmd_sample), packet, commands->sample.size * commands->nsamples);
|
rc = divesystem_idive_transfer (device, cmd_sample, sizeof(cmd_sample), packet, commands->sample.size * commands->nsamples, &errcode);
|
||||||
if (rc != DC_STATUS_SUCCESS)
|
if (rc != DC_STATUS_SUCCESS)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user