Refactor the internal serial and IrDA api.
The low level serial and IrDA functions are modified to: - Use the libdivecomputer namespace prefix. - Return a more detailed status code instead of the zero on success and negative on error return value. This will allow to return more fine-grained error codes. - The read and write functions have an additional output parameter to return the actual number of bytes transferred. Since these functions are not atomic, some data might still be transferred successfully if an error occurs. The dive computer backends are updated to use the new api.
This commit is contained in:
parent
dbba7f3272
commit
84563c6303
@ -33,14 +33,9 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &citizen_aqualand_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
typedef struct citizen_aqualand_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
unsigned char fingerprint[8];
|
||||
} citizen_aqualand_device_t;
|
||||
|
||||
@ -82,38 +77,36 @@ citizen_aqualand_device_open (dc_device_t **out, dc_context_t *context, const ch
|
||||
memset (device->fingerprint, 0, sizeof (device->fingerprint));
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (4800 8N1).
|
||||
rc = serial_configure (device->port, 4800, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 4800, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (1000ms).
|
||||
if (serial_set_timeout (device->port, 1000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 1000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_sleep (device->port, 300);
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_sleep (device->port, 300);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
*out = (dc_device_t *) device;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -125,10 +118,12 @@ citizen_aqualand_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
citizen_aqualand_device_t *device = (citizen_aqualand_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -154,6 +149,7 @@ citizen_aqualand_device_set_fingerprint (dc_device_t *abstract, const unsigned c
|
||||
static dc_status_t
|
||||
citizen_aqualand_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
citizen_aqualand_device_t *device = (citizen_aqualand_device_t *) abstract;
|
||||
|
||||
// Erase the current contents of the buffer and
|
||||
@ -163,49 +159,49 @@ citizen_aqualand_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
serial_set_dtr (device->port, 1);
|
||||
dc_serial_set_dtr (device->port, 1);
|
||||
|
||||
// Send the init byte.
|
||||
const unsigned char init[] = {0x7F};
|
||||
int n = serial_write (device->port, init, sizeof (init));
|
||||
if (n != sizeof (init)) {
|
||||
status = dc_serial_write (device->port, init, sizeof (init), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
serial_sleep(device->port, 1200);
|
||||
dc_serial_sleep(device->port, 1200);
|
||||
|
||||
// Send the command.
|
||||
const unsigned char command[] = {0xFF};
|
||||
n = serial_write (device->port, command, sizeof (command));
|
||||
if (n != sizeof (command)) {
|
||||
status = dc_serial_write (device->port, command, sizeof (command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
// Receive the response packet.
|
||||
unsigned char answer[32] = {0};
|
||||
n = serial_read (device->port, answer, sizeof (answer));
|
||||
if (n != sizeof (answer)) {
|
||||
status = dc_serial_read (device->port, answer, sizeof (answer), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
dc_buffer_append(buffer, answer, sizeof (answer));
|
||||
|
||||
// Send the command.
|
||||
n = serial_write (device->port, command, sizeof (command));
|
||||
if (n != sizeof (command)) {
|
||||
status = dc_serial_write (device->port, command, sizeof (command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (answer[sizeof(answer) - 1] == 0xFF)
|
||||
break;
|
||||
}
|
||||
|
||||
serial_set_dtr (device->port, 0);
|
||||
dc_serial_set_dtr (device->port, 0);
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -32,11 +32,6 @@
|
||||
|
||||
#define C_ARRAY_SIZE(array) (sizeof (array) / sizeof *(array))
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define COCHRAN_MODEL_COMMANDER_AIR_NITROX 0
|
||||
#define COCHRAN_MODEL_EMC_14 1
|
||||
#define COCHRAN_MODEL_EMC_16 2
|
||||
@ -92,7 +87,7 @@ typedef struct cochran_device_layout_t {
|
||||
|
||||
typedef struct cochran_commander_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
const cochran_device_layout_t *layout;
|
||||
unsigned char id[67];
|
||||
unsigned char fingerprint[6];
|
||||
@ -226,33 +221,36 @@ cochran_commander_get_model (cochran_commander_device_t *device)
|
||||
static dc_status_t
|
||||
cochran_commander_serial_setup (cochran_commander_device_t *device)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
|
||||
// Set the serial communication protocol (9600 8N2, no FC).
|
||||
int rc = serial_configure (device->port, 9600, 8, SERIAL_PARITY_NONE, 2, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_TWO, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (device->base.context, "Failed to set the terminal attributes.");
|
||||
return DC_STATUS_IO;
|
||||
return status;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (5000 ms).
|
||||
if (serial_set_timeout (device->port, 5000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 5000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (device->base.context, "Failed to set the timeout.");
|
||||
return DC_STATUS_IO;
|
||||
return status;
|
||||
}
|
||||
|
||||
// Wake up DC and trigger heartbeat
|
||||
serial_set_break(device->port, 1);
|
||||
serial_sleep(device->port, 16);
|
||||
serial_set_break(device->port, 0);
|
||||
dc_serial_set_break(device->port, 1);
|
||||
dc_serial_sleep(device->port, 16);
|
||||
dc_serial_set_break(device->port, 0);
|
||||
|
||||
// Clear old heartbeats
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
// Wait for heartbeat byte before send
|
||||
unsigned char answer = 0;
|
||||
int n = serial_read(device->port, &answer, 1);
|
||||
if (n != 1) {
|
||||
status = dc_serial_read(device->port, &answer, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (device->base.context, "Failed to receive device heartbeat.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (answer != 0xAA) {
|
||||
@ -270,6 +268,7 @@ cochran_commander_packet (cochran_commander_device_t *device, dc_event_progress_
|
||||
unsigned char answer[], unsigned int asize, int high_speed)
|
||||
{
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
|
||||
if (device_is_cancelled (abstract))
|
||||
return DC_STATUS_CANCELLED;
|
||||
@ -279,24 +278,24 @@ cochran_commander_packet (cochran_commander_device_t *device, dc_event_progress_
|
||||
// has no buffering.
|
||||
for (unsigned int i = 0; i < csize; i++) {
|
||||
// Give the DC time to read the character.
|
||||
if (i) serial_sleep(device->port, 16); // 16 ms
|
||||
if (i) dc_serial_sleep(device->port, 16); // 16 ms
|
||||
|
||||
unsigned int n = serial_write(device->port, command + i, 1);
|
||||
if (n != 1) {
|
||||
status = dc_serial_write(device->port, command + i, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (high_speed) {
|
||||
// Give the DC time to process the command.
|
||||
serial_sleep(device->port, 45);
|
||||
dc_serial_sleep(device->port, 45);
|
||||
|
||||
// Rates are odd, like 806400 for the EMC, 115200 for commander
|
||||
int rc = serial_configure(device->port, device->layout->baudrate, 8, SERIAL_PARITY_NONE, 2, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure(device->port, device->layout->baudrate, 8, DC_PARITY_NONE, DC_STOPBITS_TWO, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to set the high baud rate.");
|
||||
return DC_STATUS_IO;
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
@ -308,17 +307,16 @@ cochran_commander_packet (cochran_commander_device_t *device, dc_event_progress_
|
||||
if (len > 1024)
|
||||
len = 1024;
|
||||
|
||||
int n = serial_read (device->port, answer + nbytes, len);
|
||||
if (n != len) {
|
||||
ERROR (abstract->context, "Failed to receive data, expected %u,"
|
||||
"read %u.",len, n);
|
||||
return EXITCODE (n);
|
||||
status = dc_serial_read (device->port, answer + nbytes, len, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive data.");
|
||||
return status;
|
||||
}
|
||||
|
||||
nbytes += n;
|
||||
nbytes += len;
|
||||
|
||||
if (progress) {
|
||||
progress->current += n;
|
||||
progress->current += len;
|
||||
device_event_emit (abstract, DC_EVENT_PROGRESS, progress);
|
||||
}
|
||||
}
|
||||
@ -417,7 +415,7 @@ cochran_commander_read (cochran_commander_device_t *device, dc_event_progress_t
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
serial_sleep(device->port, 800);
|
||||
dc_serial_sleep(device->port, 800);
|
||||
|
||||
// set back to 9600 baud
|
||||
rc = cochran_commander_serial_setup(device);
|
||||
@ -630,10 +628,9 @@ cochran_commander_device_open (dc_device_t **out, dc_context_t *context, const c
|
||||
cochran_commander_device_set_fingerprint((dc_device_t *) device, NULL, 0);
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, device->base.context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, device->base.context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (device->base.context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
@ -674,7 +671,7 @@ cochran_commander_device_open (dc_device_t **out, dc_context_t *context, const c
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -685,10 +682,12 @@ cochran_commander_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
cochran_commander_device_t *device = (cochran_commander_device_t *) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
@ -34,11 +34,6 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &cressi_edy_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define MAXRETRIES 4
|
||||
|
||||
#define SZ_PACKET 0x80
|
||||
@ -60,7 +55,7 @@ typedef struct cressi_edy_layout_t {
|
||||
|
||||
typedef struct cressi_edy_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
const cressi_edy_layout_t *layout;
|
||||
unsigned char fingerprint[SZ_PAGE / 2];
|
||||
unsigned int model;
|
||||
@ -122,6 +117,7 @@ iceil (unsigned int x, unsigned int n)
|
||||
static dc_status_t
|
||||
cressi_edy_packet (cressi_edy_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize, int trailer)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
if (device_is_cancelled (abstract))
|
||||
@ -129,18 +125,18 @@ cressi_edy_packet (cressi_edy_device_t *device, const unsigned char command[], u
|
||||
|
||||
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) {
|
||||
status = dc_serial_write (device->port, command + i, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Receive the echo.
|
||||
unsigned char echo = 0;
|
||||
n = serial_read (device->port, &echo, 1);
|
||||
if (n != 1) {
|
||||
status = dc_serial_read (device->port, &echo, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the echo.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the echo.
|
||||
@ -152,10 +148,10 @@ cressi_edy_packet (cressi_edy_device_t *device, const unsigned char command[], u
|
||||
|
||||
if (asize) {
|
||||
// Receive the answer of the device.
|
||||
int n = serial_read (device->port, answer, asize);
|
||||
if (n != asize) {
|
||||
status = dc_serial_read (device->port, answer, asize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the trailer of the packet.
|
||||
@ -182,8 +178,8 @@ cressi_edy_transfer (cressi_edy_device_t *device, const unsigned char command[],
|
||||
return rc;
|
||||
|
||||
// Delay the next attempt.
|
||||
serial_sleep (device->port, 300);
|
||||
serial_flush (device->port, SERIAL_QUEUE_INPUT);
|
||||
dc_serial_sleep (device->port, 300);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_INPUT);
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
@ -257,39 +253,43 @@ cressi_edy_device_open (dc_device_t **out, dc_context_t *context, const char *na
|
||||
memset (device->fingerprint, 0, sizeof (device->fingerprint));
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (1200 8N1).
|
||||
rc = serial_configure (device->port, 1200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 1200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (1000 ms).
|
||||
if (serial_set_timeout (device->port, 1000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 1000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the DTR and clear the RTS line.
|
||||
if (serial_set_dtr (device->port, 1) == -1 ||
|
||||
serial_set_rts (device->port, 0) == -1) {
|
||||
ERROR (context, "Failed to set the DTR/RTS line.");
|
||||
status = DC_STATUS_IO;
|
||||
// Set the DTR line.
|
||||
status = dc_serial_set_dtr (device->port, 1);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the DTR line.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Clear the RTS line.
|
||||
status = dc_serial_set_rts (device->port, 0);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to clear the RTS line.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_sleep(device->port, 300);
|
||||
serial_flush(device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_sleep(device->port, 300);
|
||||
dc_serial_purge(device->port, DC_DIRECTION_ALL);
|
||||
|
||||
// Send the init commands.
|
||||
cressi_edy_init1 (device);
|
||||
@ -303,23 +303,22 @@ cressi_edy_device_open (dc_device_t **out, dc_context_t *context, const char *na
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (4800 8N1).
|
||||
rc = serial_configure (device->port, 4800, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 4800, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_sleep(device->port, 300);
|
||||
serial_flush(device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_sleep(device->port, 300);
|
||||
dc_serial_purge(device->port, DC_DIRECTION_ALL);
|
||||
|
||||
*out = (dc_device_t*) device;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -331,13 +330,15 @@ cressi_edy_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
cressi_edy_device_t *device = (cressi_edy_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Send the quit command.
|
||||
cressi_edy_quit (device);
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
@ -34,11 +34,6 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &cressi_leonardo_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define SZ_MEMORY 32000
|
||||
|
||||
#define RB_LOGBOOK_BEGIN 0x0100
|
||||
@ -52,7 +47,7 @@
|
||||
|
||||
typedef struct cressi_leonardo_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
unsigned char fingerprint[5];
|
||||
} cressi_leonardo_device_t;
|
||||
|
||||
@ -93,45 +88,49 @@ cressi_leonardo_device_open (dc_device_t **out, dc_context_t *context, const cha
|
||||
memset (device->fingerprint, 0, sizeof (device->fingerprint));
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (115200 8N1).
|
||||
rc = serial_configure (device->port, 115200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (1000 ms).
|
||||
if (serial_set_timeout (device->port, 1000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 1000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Clear the DTR and set the RTS line.
|
||||
if (serial_set_dtr (device->port, 0) == -1 ||
|
||||
serial_set_rts (device->port, 1) == -1) {
|
||||
ERROR (context, "Failed to set the DTR/RTS line.");
|
||||
status = DC_STATUS_IO;
|
||||
// Clear the DTR line.
|
||||
status = dc_serial_set_dtr (device->port, 0);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to clear the DTR line.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
serial_sleep (device->port, 100);
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
// Set the RTS line.
|
||||
status = dc_serial_set_rts (device->port, 1);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the RTS line.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
dc_serial_sleep (device->port, 100);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
*out = (dc_device_t *) device;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -142,10 +141,12 @@ cressi_leonardo_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
cressi_leonardo_device_t *device = (cressi_leonardo_device_t *) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -170,6 +171,7 @@ cressi_leonardo_device_set_fingerprint (dc_device_t *abstract, const unsigned ch
|
||||
static dc_status_t
|
||||
cressi_leonardo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
cressi_leonardo_device_t *device = (cressi_leonardo_device_t *) abstract;
|
||||
|
||||
// Erase the current contents of the buffer and
|
||||
@ -186,18 +188,18 @@ cressi_leonardo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
|
||||
// Send the command header to the dive computer.
|
||||
const unsigned char command[] = {0x7B, 0x31, 0x32, 0x33, 0x44, 0x42, 0x41, 0x7d};
|
||||
int n = serial_write (device->port, command, sizeof (command));
|
||||
if (n != sizeof (command)) {
|
||||
status = dc_serial_write (device->port, command, sizeof (command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Receive the header packet.
|
||||
unsigned char header[7] = {0};
|
||||
n = serial_read (device->port, header, sizeof (header));
|
||||
if (n != sizeof (header)) {
|
||||
status = dc_serial_read (device->port, header, sizeof (header), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the header packet.
|
||||
@ -215,8 +217,9 @@ cressi_leonardo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
unsigned int len = 1024;
|
||||
|
||||
// Increase the packet size if more data is immediately available.
|
||||
int available = serial_get_received (device->port);
|
||||
if (available > len)
|
||||
size_t available = 0;
|
||||
status = dc_serial_get_available (device->port, &available);
|
||||
if (status == DC_STATUS_SUCCESS && available > len)
|
||||
len = available;
|
||||
|
||||
// Limit the packet size to the total size.
|
||||
@ -224,10 +227,10 @@ cressi_leonardo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
len = SZ_MEMORY - nbytes;
|
||||
|
||||
// Read the packet.
|
||||
n = serial_read (device->port, data + nbytes, len);
|
||||
if (n != len) {
|
||||
status = dc_serial_read (device->port, data + nbytes, len, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Update and emit a progress event.
|
||||
@ -239,10 +242,10 @@ cressi_leonardo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
|
||||
// Receive the trailer packet.
|
||||
unsigned char trailer[4] = {0};
|
||||
n = serial_read (device->port, trailer, sizeof (trailer));
|
||||
if (n != sizeof (trailer)) {
|
||||
status = dc_serial_read (device->port, trailer, sizeof (trailer), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Convert to a binary checksum.
|
||||
|
||||
@ -33,11 +33,6 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &diverite_nitekq_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define KEEPALIVE 0x3E // '<'
|
||||
#define BLOCK 0x42 // 'B'
|
||||
#define DISCONNECT 0x44 // 'D'
|
||||
@ -57,7 +52,7 @@
|
||||
|
||||
typedef struct diverite_nitekq_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
unsigned char version[32];
|
||||
unsigned char fingerprint[SZ_LOGBOOK];
|
||||
} diverite_nitekq_device_t;
|
||||
@ -82,6 +77,7 @@ static const dc_device_vtable_t diverite_nitekq_device_vtable = {
|
||||
static dc_status_t
|
||||
diverite_nitekq_send (diverite_nitekq_device_t *device, unsigned char cmd)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
if (device_is_cancelled (abstract))
|
||||
@ -89,10 +85,10 @@ diverite_nitekq_send (diverite_nitekq_device_t *device, unsigned char cmd)
|
||||
|
||||
// Send the command.
|
||||
unsigned char command[] = {cmd};
|
||||
int n = serial_write (device->port, command, sizeof (command));
|
||||
if (n != sizeof (command)) {
|
||||
status = dc_serial_write (device->port, command, sizeof (command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
@ -102,21 +98,22 @@ diverite_nitekq_send (diverite_nitekq_device_t *device, unsigned char cmd)
|
||||
static dc_status_t
|
||||
diverite_nitekq_receive (diverite_nitekq_device_t *device, unsigned char data[], unsigned int size)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
// Read the answer.
|
||||
int n = serial_read (device->port, data, size);
|
||||
if (n != size) {
|
||||
status = dc_serial_read (device->port, data, size, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Read the checksum.
|
||||
unsigned char checksum[2] = {0};
|
||||
n = serial_read (device->port, checksum, sizeof (checksum));
|
||||
if (n != sizeof (checksum)) {
|
||||
status = dc_serial_read (device->port, checksum, sizeof (checksum), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the checksum.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
@ -126,21 +123,22 @@ diverite_nitekq_receive (diverite_nitekq_device_t *device, unsigned char data[],
|
||||
static dc_status_t
|
||||
diverite_nitekq_handshake (diverite_nitekq_device_t *device)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
// Send the command.
|
||||
unsigned char command[] = {HANDSHAKE};
|
||||
int n = serial_write (device->port, command, sizeof (command));
|
||||
if (n != sizeof (command)) {
|
||||
status = dc_serial_write (device->port, command, sizeof (command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Read the answer.
|
||||
n = serial_read (device->port, device->version, sizeof (device->version));
|
||||
if (n != sizeof (device->version)) {
|
||||
status = dc_serial_read (device->port, device->version, sizeof (device->version), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
@ -168,31 +166,29 @@ diverite_nitekq_device_open (dc_device_t **out, dc_context_t *context, const cha
|
||||
memset (device->fingerprint, 0, sizeof (device->fingerprint));
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (9600 8N1).
|
||||
rc = serial_configure (device->port, 9600, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (1000ms).
|
||||
if (serial_set_timeout (device->port, 1000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 1000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_sleep (device->port, 100);
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_sleep (device->port, 100);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
// Perform the handshaking.
|
||||
status = diverite_nitekq_handshake (device);
|
||||
@ -206,7 +202,7 @@ diverite_nitekq_device_open (dc_device_t **out, dc_context_t *context, const cha
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -218,13 +214,15 @@ diverite_nitekq_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
diverite_nitekq_device_t *device = (diverite_nitekq_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Disconnect.
|
||||
diverite_nitekq_send (device, DISCONNECT);
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
@ -32,11 +32,6 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &divesystem_idive_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define IX3M_EASY 0x22
|
||||
#define IX3M_DEEP 0x23
|
||||
#define IX3M_TEC 0x24
|
||||
@ -67,7 +62,7 @@ typedef struct divesystem_idive_commands_t {
|
||||
|
||||
typedef struct divesystem_idive_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
unsigned char fingerprint[4];
|
||||
unsigned int model;
|
||||
} divesystem_idive_device_t;
|
||||
@ -130,38 +125,36 @@ divesystem_idive_device_open2 (dc_device_t **out, dc_context_t *context, const c
|
||||
device->model = model;
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (115200 8N1).
|
||||
rc = serial_configure (device->port, 115200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (1000ms).
|
||||
if (serial_set_timeout (device->port, 1000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 1000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_sleep (device->port, 300);
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_sleep (device->port, 300);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
*out = (dc_device_t *) device;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -173,10 +166,12 @@ divesystem_idive_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
divesystem_idive_device_t *device = (divesystem_idive_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -203,6 +198,7 @@ divesystem_idive_device_set_fingerprint (dc_device_t *abstract, const unsigned c
|
||||
static dc_status_t
|
||||
divesystem_idive_send (divesystem_idive_device_t *device, const unsigned char command[], unsigned int csize)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
unsigned char packet[MAXPACKET + 4];
|
||||
unsigned short crc = 0;
|
||||
@ -222,10 +218,10 @@ divesystem_idive_send (divesystem_idive_device_t *device, const unsigned char co
|
||||
packet[csize + 3] = (crc ) & 0xFF;
|
||||
|
||||
// Send the data packet.
|
||||
int n = serial_write (device->port, packet, csize + 4);
|
||||
if (n != csize + 4) {
|
||||
status = dc_serial_write (device->port, packet, csize + 4, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
@ -235,9 +231,9 @@ divesystem_idive_send (divesystem_idive_device_t *device, const unsigned char co
|
||||
static dc_status_t
|
||||
divesystem_idive_receive (divesystem_idive_device_t *device, unsigned char answer[], unsigned int *asize)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
unsigned char packet[MAXPACKET + 4];
|
||||
int n = 0;
|
||||
|
||||
if (asize == NULL || *asize < MAXPACKET) {
|
||||
ERROR (abstract->context, "Invalid arguments.");
|
||||
@ -246,10 +242,10 @@ divesystem_idive_receive (divesystem_idive_device_t *device, unsigned char answe
|
||||
|
||||
// Read the packet start byte.
|
||||
while (1) {
|
||||
n = serial_read (device->port, packet + 0, 1);
|
||||
if (n != 1) {
|
||||
status = dc_serial_read (device->port, packet + 0, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the packet start byte.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (packet[0] == START)
|
||||
@ -257,10 +253,10 @@ divesystem_idive_receive (divesystem_idive_device_t *device, unsigned char answe
|
||||
}
|
||||
|
||||
// Read the packet length.
|
||||
n = serial_read (device->port, packet + 1, 1);
|
||||
if (n != 1) {
|
||||
status = dc_serial_read (device->port, packet + 1, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the packet length.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
unsigned int len = packet[1];
|
||||
@ -270,10 +266,10 @@ divesystem_idive_receive (divesystem_idive_device_t *device, unsigned char answe
|
||||
}
|
||||
|
||||
// Read the packet payload and checksum.
|
||||
n = serial_read (device->port, packet + 2, len + 2);
|
||||
if (n != len + 2) {
|
||||
status = dc_serial_read (device->port, packet + 2, len + 2, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the packet payload and checksum.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the checksum.
|
||||
@ -346,7 +342,7 @@ divesystem_idive_transfer (divesystem_idive_device_t *device, const unsigned cha
|
||||
return DC_STATUS_PROTOCOL;
|
||||
|
||||
// Delay the next attempt.
|
||||
serial_sleep(device->port, 100);
|
||||
dc_serial_sleep(device->port, 100);
|
||||
}
|
||||
|
||||
// Verify the length of the packet.
|
||||
|
||||
@ -33,11 +33,6 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &hw_frog_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define SZ_DISPLAY 15
|
||||
#define SZ_CUSTOMTEXT 13
|
||||
#define SZ_VERSION (SZ_CUSTOMTEXT + 4)
|
||||
@ -61,7 +56,7 @@
|
||||
|
||||
typedef struct hw_frog_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
unsigned char fingerprint[5];
|
||||
} hw_frog_device_t;
|
||||
|
||||
@ -110,6 +105,7 @@ hw_frog_transfer (hw_frog_device_t *device,
|
||||
unsigned char output[],
|
||||
unsigned int osize)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
if (device_is_cancelled (abstract))
|
||||
@ -117,19 +113,19 @@ hw_frog_transfer (hw_frog_device_t *device,
|
||||
|
||||
// Send the command.
|
||||
unsigned char command[1] = {cmd};
|
||||
int n = serial_write (device->port, command, sizeof (command));
|
||||
if (n != sizeof (command)) {
|
||||
status = dc_serial_write (device->port, command, sizeof (command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (cmd != INIT && cmd != HEADER) {
|
||||
// Read the echo.
|
||||
unsigned char answer[1] = {0};
|
||||
n = serial_read (device->port, answer, sizeof (answer));
|
||||
if (n != sizeof (answer)) {
|
||||
status = dc_serial_read (device->port, answer, sizeof (answer), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the echo.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the echo.
|
||||
@ -141,10 +137,10 @@ hw_frog_transfer (hw_frog_device_t *device,
|
||||
|
||||
if (input) {
|
||||
// Send the input data packet.
|
||||
n = serial_write (device->port, input, isize);
|
||||
if (n != isize) {
|
||||
status = dc_serial_write (device->port, input, isize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the data packet.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,8 +151,9 @@ hw_frog_transfer (hw_frog_device_t *device,
|
||||
unsigned int len = 1024;
|
||||
|
||||
// Increase the packet size if more data is immediately available.
|
||||
int available = serial_get_received (device->port);
|
||||
if (available > len)
|
||||
size_t available = 0;
|
||||
status = dc_serial_get_available (device->port, &available);
|
||||
if (status == DC_STATUS_SUCCESS && available > len)
|
||||
len = available;
|
||||
|
||||
// Limit the packet size to the total size.
|
||||
@ -164,10 +161,10 @@ hw_frog_transfer (hw_frog_device_t *device,
|
||||
len = osize - nbytes;
|
||||
|
||||
// Read the packet.
|
||||
n = serial_read (device->port, output + nbytes, len);
|
||||
if (n != len) {
|
||||
status = dc_serial_read (device->port, output + nbytes, len, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Update and emit a progress event.
|
||||
@ -183,10 +180,10 @@ hw_frog_transfer (hw_frog_device_t *device,
|
||||
if (cmd != EXIT) {
|
||||
// Read the ready byte.
|
||||
unsigned char answer[1] = {0};
|
||||
n = serial_read (device->port, answer, sizeof (answer));
|
||||
if (n != sizeof (answer)) {
|
||||
status = dc_serial_read (device->port, answer, sizeof (answer), NULL);
|
||||
if (status != sizeof (answer)) {
|
||||
ERROR (abstract->context, "Failed to receive the ready byte.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the ready byte.
|
||||
@ -221,31 +218,29 @@ hw_frog_device_open (dc_device_t **out, dc_context_t *context, const char *name)
|
||||
memset (device->fingerprint, 0, sizeof (device->fingerprint));
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (115200 8N1).
|
||||
rc = serial_configure (device->port, 115200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (3000ms).
|
||||
if (serial_set_timeout (device->port, 3000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 3000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_sleep (device->port, 300);
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_sleep (device->port, 300);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
// Send the init command.
|
||||
status = hw_frog_transfer (device, NULL, INIT, NULL, 0, NULL, 0);
|
||||
@ -259,7 +254,7 @@ hw_frog_device_open (dc_device_t **out, dc_context_t *context, const char *name)
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -281,8 +276,9 @@ hw_frog_device_close (dc_device_t *abstract)
|
||||
}
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
143
src/hw_ostc.c
143
src/hw_ostc.c
@ -33,11 +33,6 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &hw_ostc_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define C_ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
|
||||
|
||||
#define MAXRETRIES 9
|
||||
@ -64,7 +59,7 @@
|
||||
|
||||
typedef struct hw_ostc_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
unsigned char fingerprint[5];
|
||||
} hw_ostc_device_t;
|
||||
|
||||
@ -93,23 +88,24 @@ static const dc_device_vtable_t hw_ostc_device_vtable = {
|
||||
static dc_status_t
|
||||
hw_ostc_send (hw_ostc_device_t *device, unsigned char cmd, unsigned int echo)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
// Send the command.
|
||||
unsigned char command[1] = {cmd};
|
||||
int n = serial_write (device->port, command, sizeof (command));
|
||||
if (n != sizeof (command)) {
|
||||
status = dc_serial_write (device->port, command, sizeof (command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (echo) {
|
||||
// Read the echo.
|
||||
unsigned char answer[1] = {0};
|
||||
n = serial_read (device->port, answer, sizeof (answer));
|
||||
if (n != sizeof (answer)) {
|
||||
status = dc_serial_read (device->port, answer, sizeof (answer), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the echo.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the echo.
|
||||
@ -144,38 +140,36 @@ hw_ostc_device_open (dc_device_t **out, dc_context_t *context, const char *name)
|
||||
memset (device->fingerprint, 0, sizeof (device->fingerprint));
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (115200 8N1).
|
||||
rc = serial_configure (device->port, 115200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data.
|
||||
if (serial_set_timeout (device->port, 4000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 4000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_sleep (device->port, 100);
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_sleep (device->port, 100);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
*out = (dc_device_t*) device;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -187,10 +181,12 @@ hw_ostc_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
hw_ostc_device_t *device = (hw_ostc_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -217,6 +213,7 @@ hw_ostc_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[
|
||||
static dc_status_t
|
||||
hw_ostc_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
hw_ostc_device_t *device = (hw_ostc_device_t*) abstract;
|
||||
|
||||
// Erase the current contents of the buffer.
|
||||
@ -232,18 +229,18 @@ hw_ostc_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
|
||||
// Send the command.
|
||||
unsigned char command[1] = {'a'};
|
||||
int rc = serial_write (device->port, command, sizeof (command));
|
||||
if (rc != sizeof (command)) {
|
||||
status = dc_serial_write (device->port, command, sizeof (command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (rc);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Read the header.
|
||||
unsigned char header[SZ_HEADER] = {0};
|
||||
int n = serial_read (device->port, header, sizeof (header));
|
||||
if (n != sizeof (header)) {
|
||||
status = dc_serial_read (device->port, header, sizeof (header), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the header.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the header.
|
||||
@ -285,8 +282,9 @@ hw_ostc_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
unsigned int len = 1024;
|
||||
|
||||
// Increase the packet size if more data is immediately available.
|
||||
int available = serial_get_received (device->port);
|
||||
if (available > len)
|
||||
size_t available = 0;
|
||||
status = dc_serial_get_available (device->port, &available);
|
||||
if (status == DC_STATUS_SUCCESS && available > len)
|
||||
len = available;
|
||||
|
||||
// Limit the packet size to the total size.
|
||||
@ -294,10 +292,10 @@ hw_ostc_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
len = size - nbytes;
|
||||
|
||||
// Read the packet.
|
||||
int n = serial_read (device->port, data + nbytes, len);
|
||||
if (n != len) {
|
||||
status = dc_serial_read (device->port, data + nbytes, len, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Update and emit a progress event.
|
||||
@ -351,6 +349,7 @@ hw_ostc_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void
|
||||
dc_status_t
|
||||
hw_ostc_device_md2hash (dc_device_t *abstract, unsigned char data[], unsigned int size)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
hw_ostc_device_t *device = (hw_ostc_device_t *) abstract;
|
||||
|
||||
if (!ISINSTANCE (abstract))
|
||||
@ -367,10 +366,10 @@ hw_ostc_device_md2hash (dc_device_t *abstract, unsigned char data[], unsigned in
|
||||
return rc;
|
||||
|
||||
// Read the answer.
|
||||
int n = serial_read (device->port, data, SZ_MD2HASH);
|
||||
if (n != SZ_MD2HASH) {
|
||||
status = dc_serial_read (device->port, data, SZ_MD2HASH, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
@ -380,6 +379,7 @@ hw_ostc_device_md2hash (dc_device_t *abstract, unsigned char data[], unsigned in
|
||||
dc_status_t
|
||||
hw_ostc_device_clock (dc_device_t *abstract, const dc_datetime_t *datetime)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
hw_ostc_device_t *device = (hw_ostc_device_t *) abstract;
|
||||
|
||||
if (!ISINSTANCE (abstract))
|
||||
@ -399,10 +399,10 @@ hw_ostc_device_clock (dc_device_t *abstract, const dc_datetime_t *datetime)
|
||||
unsigned char packet[6] = {
|
||||
datetime->hour, datetime->minute, datetime->second,
|
||||
datetime->month, datetime->day, datetime->year - 2000};
|
||||
int n = serial_write (device->port, packet, sizeof (packet));
|
||||
if (n != sizeof (packet)) {
|
||||
status = dc_serial_write (device->port, packet, sizeof (packet), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the data packet.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
@ -412,6 +412,7 @@ hw_ostc_device_clock (dc_device_t *abstract, const dc_datetime_t *datetime)
|
||||
dc_status_t
|
||||
hw_ostc_device_eeprom_read (dc_device_t *abstract, unsigned int bank, unsigned char data[], unsigned int size)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
hw_ostc_device_t *device = (hw_ostc_device_t *) abstract;
|
||||
|
||||
if (!ISINSTANCE (abstract))
|
||||
@ -434,10 +435,10 @@ hw_ostc_device_eeprom_read (dc_device_t *abstract, unsigned int bank, unsigned c
|
||||
return rc;
|
||||
|
||||
// Read the answer.
|
||||
int n = serial_read (device->port, data, SZ_EEPROM);
|
||||
if (n != SZ_EEPROM) {
|
||||
status = dc_serial_read (device->port, data, SZ_EEPROM, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
@ -499,6 +500,7 @@ hw_ostc_device_reset (dc_device_t *abstract)
|
||||
dc_status_t
|
||||
hw_ostc_device_screenshot (dc_device_t *abstract, dc_buffer_t *buffer, hw_ostc_format_t format)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
hw_ostc_device_t *device = (hw_ostc_device_t *) abstract;
|
||||
|
||||
if (!ISINSTANCE (abstract))
|
||||
@ -554,13 +556,13 @@ hw_ostc_device_screenshot (dc_device_t *abstract, dc_buffer_t *buffer, hw_ostc_f
|
||||
unsigned int npixels = 0;
|
||||
while (npixels < WIDTH * HEIGHT) {
|
||||
unsigned char raw[3] = {0};
|
||||
int n = serial_read (device->port, raw, 1);
|
||||
if (n != 1) {
|
||||
status = dc_serial_read (device->port, raw, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the packet.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
unsigned int nbytes = n;
|
||||
unsigned int nbytes = 1;
|
||||
unsigned int count = raw[0];
|
||||
if ((count & 0x80) == 0x00) {
|
||||
// Black pixel.
|
||||
@ -572,13 +574,13 @@ hw_ostc_device_screenshot (dc_device_t *abstract, dc_buffer_t *buffer, hw_ostc_f
|
||||
count &= 0x3F;
|
||||
} else {
|
||||
// Color pixel.
|
||||
n = serial_read (device->port, raw + 1, 2);
|
||||
if (n != 2) {
|
||||
status = dc_serial_read (device->port, raw + 1, 2, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the packet.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
nbytes += n;
|
||||
nbytes += 2;
|
||||
count &= 0x3F;
|
||||
}
|
||||
count++;
|
||||
@ -767,22 +769,23 @@ hw_ostc_firmware_readfile (hw_ostc_firmware_t *firmware, dc_context_t *context,
|
||||
static dc_status_t
|
||||
hw_ostc_firmware_setup_internal (hw_ostc_device_t *device)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
// Send the command.
|
||||
unsigned char command[1] = {0xC1};
|
||||
int n = serial_write (device->port, command, sizeof (command));
|
||||
if (n != sizeof (command)) {
|
||||
status = dc_serial_write (device->port, command, sizeof (command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Read the response.
|
||||
unsigned char answer[2] = {0};
|
||||
n = serial_read (device->port, answer, sizeof (answer));
|
||||
if (n != sizeof (answer)) {
|
||||
status = dc_serial_read (device->port, answer, sizeof (answer), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the response.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the response.
|
||||
@ -818,21 +821,22 @@ hw_ostc_firmware_setup (hw_ostc_device_t *device, unsigned int maxretries)
|
||||
static dc_status_t
|
||||
hw_ostc_firmware_write_internal (hw_ostc_device_t *device, unsigned char *data, unsigned int size)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
// Send the packet.
|
||||
int n = serial_write (device->port, data, size);
|
||||
if (n != size) {
|
||||
status = dc_serial_write (device->port, data, size, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the packet.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Read the response.
|
||||
unsigned char answer[1] = {0};
|
||||
n = serial_read (device->port, answer, sizeof (answer));
|
||||
if (n != sizeof (answer)) {
|
||||
status = dc_serial_read (device->port, answer, sizeof (answer), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the response.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the response.
|
||||
@ -901,16 +905,17 @@ hw_ostc_device_fwupdate (dc_device_t *abstract, const char *filename)
|
||||
// bootloader needs to be send repeatedly, until the response packet is
|
||||
// received. Thus the time between each two attempts is directly controlled
|
||||
// by the timeout value.
|
||||
serial_set_timeout (device->port, 300);
|
||||
dc_serial_set_timeout (device->port, 300);
|
||||
|
||||
// Setup the bootloader.
|
||||
const unsigned int baudrates[] = {19200, 115200};
|
||||
for (unsigned int i = 0; i < C_ARRAY_SIZE(baudrates); ++i) {
|
||||
// Adjust the baudrate.
|
||||
if (serial_configure (device->port, baudrates[i], 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE) == -1) {
|
||||
rc = dc_serial_configure (device->port, baudrates[i], 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to set the terminal attributes.");
|
||||
free (firmware);
|
||||
return DC_STATUS_IO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Try to setup the bootloader.
|
||||
@ -926,7 +931,7 @@ hw_ostc_device_fwupdate (dc_device_t *abstract, const char *filename)
|
||||
}
|
||||
|
||||
// Increase the timeout again.
|
||||
serial_set_timeout (device->port, 1000);
|
||||
dc_serial_set_timeout (device->port, 1000);
|
||||
|
||||
// Enable progress notifications.
|
||||
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
|
||||
|
||||
@ -38,11 +38,6 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &hw_ostc3_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define SZ_DISPLAY 16
|
||||
#define SZ_CUSTOMTEXT 60
|
||||
#define SZ_VERSION (SZ_CUSTOMTEXT + 4)
|
||||
@ -98,7 +93,7 @@ typedef enum hw_ostc3_state_t {
|
||||
|
||||
typedef struct hw_ostc3_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
unsigned int hardware;
|
||||
unsigned char fingerprint[5];
|
||||
hw_ostc3_state_t state;
|
||||
@ -188,6 +183,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
|
||||
unsigned int delay)
|
||||
{
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
|
||||
if (device_is_cancelled (abstract))
|
||||
return DC_STATUS_CANCELLED;
|
||||
@ -197,18 +193,18 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
|
||||
|
||||
// Send the command.
|
||||
unsigned char command[1] = {cmd};
|
||||
int n = serial_write (device->port, command, sizeof (command));
|
||||
if (n != sizeof (command)) {
|
||||
status = dc_serial_write (device->port, command, sizeof (command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Read the echo.
|
||||
unsigned char echo[1] = {0};
|
||||
n = serial_read (device->port, echo, sizeof (echo));
|
||||
if (n != sizeof (echo)) {
|
||||
status = dc_serial_read (device->port, echo, sizeof (echo), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the echo.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the echo.
|
||||
@ -234,10 +230,10 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
|
||||
len = isize - nbytes;
|
||||
|
||||
// Write the packet.
|
||||
n = serial_write (device->port, input + nbytes, len);
|
||||
if (n != len) {
|
||||
status = dc_serial_write (device->port, input + nbytes, len, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the data packet.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Update and emit a progress event.
|
||||
@ -257,8 +253,9 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
|
||||
unsigned int len = 1024;
|
||||
|
||||
// Increase the packet size if more data is immediately available.
|
||||
int available = serial_get_received (device->port);
|
||||
if (available > len)
|
||||
size_t available = 0;
|
||||
status = dc_serial_get_available (device->port, &available);
|
||||
if (status == DC_STATUS_SUCCESS && available > len)
|
||||
len = available;
|
||||
|
||||
// Limit the packet size to the total size.
|
||||
@ -266,10 +263,10 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
|
||||
len = osize - nbytes;
|
||||
|
||||
// Read the packet.
|
||||
n = serial_read (device->port, output + nbytes, len);
|
||||
if (n != len) {
|
||||
status = dc_serial_read (device->port, output + nbytes, len, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Update and emit a progress event.
|
||||
@ -285,20 +282,22 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
|
||||
if (delay) {
|
||||
unsigned int count = delay / 100;
|
||||
for (unsigned int i = 0; i < count; ++i) {
|
||||
if (serial_get_received (device->port) > 0)
|
||||
size_t available = 0;
|
||||
status = dc_serial_get_available (device->port, &available);
|
||||
if (status == DC_STATUS_SUCCESS && available > 0)
|
||||
break;
|
||||
|
||||
serial_sleep (device->port, 100);
|
||||
dc_serial_sleep (device->port, 100);
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd != EXIT) {
|
||||
// Read the ready byte.
|
||||
unsigned char answer[1] = {0};
|
||||
n = serial_read (device->port, answer, sizeof (answer));
|
||||
if (n != sizeof (answer)) {
|
||||
status = dc_serial_read (device->port, answer, sizeof (answer), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the ready byte.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the ready byte.
|
||||
@ -334,31 +333,29 @@ hw_ostc3_device_open (dc_device_t **out, dc_context_t *context, const char *name
|
||||
memset (device->fingerprint, 0, sizeof (device->fingerprint));
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (115200 8N1).
|
||||
rc = serial_configure (device->port, 115200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (3000ms).
|
||||
if (serial_set_timeout (device->port, 3000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 3000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_sleep (device->port, 300);
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_sleep (device->port, 300);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
device->state = OPEN;
|
||||
|
||||
@ -367,7 +364,7 @@ hw_ostc3_device_open (dc_device_t **out, dc_context_t *context, const char *name
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -396,28 +393,28 @@ hw_ostc3_device_init_download (hw_ostc3_device_t *device)
|
||||
static dc_status_t
|
||||
hw_ostc3_device_init_service (hw_ostc3_device_t *device)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
dc_context_t *context = (abstract ? abstract->context : NULL);
|
||||
|
||||
unsigned char command[] = {0xAA, 0xAB, 0xCD, 0xEF};
|
||||
unsigned char output[5];
|
||||
int n = 0;
|
||||
|
||||
// We cant use hw_ostc3_transfer here, due to the different echos
|
||||
n = serial_write (device->port, command, sizeof (command));
|
||||
if (n != sizeof (command)) {
|
||||
status = dc_serial_write (device->port, command, sizeof (command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Give the device some time to enter service mode
|
||||
serial_sleep (device->port, 100);
|
||||
dc_serial_sleep (device->port, 100);
|
||||
|
||||
// Read the response
|
||||
n = serial_read (device->port, output, sizeof (output));
|
||||
if (n != sizeof (output)) {
|
||||
status = dc_serial_read (device->port, output, sizeof (output), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to receive the echo.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the response to service mode
|
||||
@ -500,8 +497,9 @@ hw_ostc3_device_close (dc_device_t *abstract)
|
||||
}
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
164
src/irda.c
164
src/irda.c
@ -39,16 +39,19 @@
|
||||
#endif
|
||||
|
||||
#include "irda.h"
|
||||
#include "common-private.h"
|
||||
#include "context-private.h"
|
||||
#include "array.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef int s_ssize_t;
|
||||
#define S_ERRNO WSAGetLastError ()
|
||||
#define S_EAGAIN WSAEWOULDBLOCK
|
||||
#define S_INVALID INVALID_SOCKET
|
||||
#define S_IOCTL ioctlsocket
|
||||
#define S_CLOSE closesocket
|
||||
#else
|
||||
typedef ssize_t s_ssize_t;
|
||||
#define S_ERRNO errno
|
||||
#define S_EAGAIN EAGAIN
|
||||
#define S_INVALID -1
|
||||
@ -60,32 +63,34 @@
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
struct irda_t {
|
||||
struct dc_irda_t {
|
||||
dc_context_t *context;
|
||||
#ifdef _WIN32
|
||||
SOCKET fd;
|
||||
#else
|
||||
int fd;
|
||||
#endif
|
||||
long timeout;
|
||||
int timeout;
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
irda_socket_open (irda_t **out, dc_context_t *context)
|
||||
dc_status_t
|
||||
dc_irda_open (dc_irda_t **out, dc_context_t *context)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_irda_t *device = NULL;
|
||||
|
||||
if (out == NULL)
|
||||
return -1; // EINVAL (Invalid argument)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
irda_t *device = (irda_t *) malloc (sizeof (irda_t));
|
||||
device = (dc_irda_t *) malloc (sizeof (dc_irda_t));
|
||||
if (device == NULL) {
|
||||
#ifdef _WIN32
|
||||
SYSERROR (context, ERROR_OUTOFMEMORY);
|
||||
#else
|
||||
SYSERROR (context, ENOMEM);
|
||||
#endif
|
||||
return -1; // ENOMEM (Not enough space)
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
// Library context.
|
||||
@ -101,6 +106,7 @@ irda_socket_open (irda_t **out, dc_context_t *context)
|
||||
int rc = WSAStartup (wVersionRequested, &wsaData);
|
||||
if (rc != 0) {
|
||||
SYSERROR (context, rc);
|
||||
status = DC_STATUS_UNSUPPORTED;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
@ -110,6 +116,7 @@ irda_socket_open (irda_t **out, dc_context_t *context)
|
||||
if (LOBYTE (wsaData.wVersion) != 2 ||
|
||||
HIBYTE (wsaData.wVersion) != 2) {
|
||||
ERROR (context, "Incorrect winsock version.");
|
||||
status = DC_STATUS_UNSUPPORTED;
|
||||
goto error_wsacleanup;
|
||||
}
|
||||
#endif
|
||||
@ -118,12 +125,13 @@ irda_socket_open (irda_t **out, dc_context_t *context)
|
||||
device->fd = socket (AF_IRDA, SOCK_STREAM, 0);
|
||||
if (device->fd == S_INVALID) {
|
||||
SYSERROR (context, S_ERRNO);
|
||||
status = DC_STATUS_IO;
|
||||
goto error_wsacleanup;
|
||||
}
|
||||
|
||||
*out = device;
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_wsacleanup:
|
||||
#ifdef _WIN32
|
||||
@ -131,17 +139,16 @@ error_wsacleanup:
|
||||
error_free:
|
||||
#endif
|
||||
free (device);
|
||||
return -1;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
irda_socket_close (irda_t *device)
|
||||
dc_status_t
|
||||
dc_irda_close (dc_irda_t *device)
|
||||
{
|
||||
int errcode = 0;
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
|
||||
if (device == NULL)
|
||||
return -1;
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
// Terminate all send and receive operations.
|
||||
shutdown (device->fd, 0);
|
||||
@ -149,35 +156,34 @@ irda_socket_close (irda_t *device)
|
||||
// Close the socket.
|
||||
if (S_CLOSE (device->fd) != 0) {
|
||||
SYSERROR (device->context, S_ERRNO);
|
||||
errcode = -1;
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// Terminate the winsock dll.
|
||||
if (WSACleanup () != 0) {
|
||||
SYSERROR (device->context, S_ERRNO);
|
||||
errcode = -1;
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Free memory.
|
||||
free (device);
|
||||
|
||||
return errcode;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
irda_socket_set_timeout (irda_t *device, long timeout)
|
||||
dc_status_t
|
||||
dc_irda_set_timeout (dc_irda_t *device, int timeout)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // EINVAL (Invalid argument)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
INFO (device->context, "Timeout: value=%li", timeout);
|
||||
INFO (device->context, "Timeout: value=%i", timeout);
|
||||
|
||||
device->timeout = timeout;
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@ -192,11 +198,11 @@ irda_socket_set_timeout (irda_t *device, long timeout)
|
||||
sizeof (struct irda_device_info) * (DISCOVER_MAX_DEVICES - 1)
|
||||
#endif
|
||||
|
||||
int
|
||||
irda_socket_discover (irda_t *device, irda_callback_t callback, void *userdata)
|
||||
dc_status_t
|
||||
dc_irda_discover (dc_irda_t *device, dc_irda_callback_t callback, void *userdata)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1;
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
unsigned char data[DISCOVER_BUFSIZE] = {0};
|
||||
#ifdef _WIN32
|
||||
@ -223,13 +229,13 @@ irda_socket_discover (irda_t *device, irda_callback_t callback, void *userdata)
|
||||
if (rc != 0) {
|
||||
if (S_ERRNO != S_EAGAIN) {
|
||||
SYSERROR (device->context, S_ERRNO);
|
||||
return -1; // Error during getsockopt call.
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
}
|
||||
|
||||
// Abort if the maximum number of retries is reached.
|
||||
if (nretries++ >= DISCOVER_MAX_RETRIES)
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
// Restore the size parameter in case it was
|
||||
// modified by the previous getsockopt call.
|
||||
@ -266,15 +272,14 @@ irda_socket_discover (irda_t *device, irda_callback_t callback, void *userdata)
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
irda_socket_connect_name (irda_t *device, unsigned int address, const char *name)
|
||||
dc_status_t
|
||||
dc_irda_connect_name (dc_irda_t *device, unsigned int address, const char *name)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1;
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
INFO (device->context, "Connect: address=%08x, name=%s", address, name ? name : "");
|
||||
|
||||
@ -301,17 +306,17 @@ irda_socket_connect_name (irda_t *device, unsigned int address, const char *name
|
||||
|
||||
if (connect (device->fd, (struct sockaddr *) &peer, sizeof (peer)) != 0) {
|
||||
SYSERROR (device->context, S_ERRNO);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
irda_socket_connect_lsap (irda_t *device, unsigned int address, unsigned int lsap)
|
||||
dc_status_t
|
||||
dc_irda_connect_lsap (dc_irda_t *device, unsigned int address, unsigned int lsap)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1;
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
INFO (device->context, "Connect: address=%08x, lsap=%u", address, lsap);
|
||||
|
||||
@ -333,18 +338,17 @@ irda_socket_connect_lsap (irda_t *device, unsigned int address, unsigned int lsa
|
||||
|
||||
if (connect (device->fd, (struct sockaddr *) &peer, sizeof (peer)) != 0) {
|
||||
SYSERROR (device->context, S_ERRNO);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
irda_socket_available (irda_t *device)
|
||||
dc_status_t
|
||||
dc_irda_get_available (dc_irda_t *device, size_t *value)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // EINVAL (Invalid argument)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
#ifdef _WIN32
|
||||
unsigned long bytes = 0;
|
||||
@ -354,18 +358,25 @@ irda_socket_available (irda_t *device)
|
||||
|
||||
if (S_IOCTL (device->fd, FIONREAD, &bytes) != 0) {
|
||||
SYSERROR (device->context, S_ERRNO);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
if (value)
|
||||
*value = bytes;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
irda_socket_read (irda_t *device, void *data, unsigned int size)
|
||||
dc_status_t
|
||||
dc_irda_read (dc_irda_t *device, void *data, size_t size, size_t *actual)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // EINVAL (Invalid argument)
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
size_t nbytes = 0;
|
||||
|
||||
if (device == NULL) {
|
||||
status = DC_STATUS_INVALIDARGS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
struct timeval tv;
|
||||
if (device->timeout >= 0) {
|
||||
@ -377,20 +388,21 @@ irda_socket_read (irda_t *device, void *data, unsigned int size)
|
||||
FD_ZERO (&fds);
|
||||
FD_SET (device->fd, &fds);
|
||||
|
||||
unsigned int nbytes = 0;
|
||||
while (nbytes < size) {
|
||||
int rc = select (device->fd + 1, &fds, NULL, NULL, (device->timeout >= 0 ? &tv : NULL));
|
||||
if (rc < 0) {
|
||||
SYSERROR (device->context, S_ERRNO);
|
||||
return -1; // Error during select call.
|
||||
status = DC_STATUS_IO;
|
||||
goto out;
|
||||
} else if (rc == 0) {
|
||||
break; // Timeout.
|
||||
}
|
||||
|
||||
int n = recv (device->fd, (char*) data + nbytes, size - nbytes, 0);
|
||||
s_ssize_t n = recv (device->fd, (char*) data + nbytes, size - nbytes, 0);
|
||||
if (n < 0) {
|
||||
SYSERROR (device->context, S_ERRNO);
|
||||
return -1; // Error during recv call.
|
||||
status = DC_STATUS_IO;
|
||||
goto out;
|
||||
} else if (n == 0) {
|
||||
break; // EOF reached.
|
||||
}
|
||||
@ -398,30 +410,50 @@ irda_socket_read (irda_t *device, void *data, unsigned int size)
|
||||
nbytes += n;
|
||||
}
|
||||
|
||||
if (nbytes != size) {
|
||||
status = DC_STATUS_TIMEOUT;
|
||||
}
|
||||
|
||||
out:
|
||||
HEXDUMP (device->context, DC_LOGLEVEL_INFO, "Read", (unsigned char *) data, nbytes);
|
||||
|
||||
return nbytes;
|
||||
if (actual)
|
||||
*actual = nbytes;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
irda_socket_write (irda_t *device, const void *data, unsigned int size)
|
||||
dc_status_t
|
||||
dc_irda_write (dc_irda_t *device, const void *data, size_t size, size_t *actual)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // EINVAL (Invalid argument)
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
size_t nbytes = 0;
|
||||
|
||||
if (device == NULL) {
|
||||
status = DC_STATUS_INVALIDARGS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
unsigned int nbytes = 0;
|
||||
while (nbytes < size) {
|
||||
int n = send (device->fd, (char*) data + nbytes, size - nbytes, 0);
|
||||
s_ssize_t n = send (device->fd, (char*) data + nbytes, size - nbytes, 0);
|
||||
if (n < 0) {
|
||||
SYSERROR (device->context, S_ERRNO);
|
||||
return -1; // Error during send call.
|
||||
status = DC_STATUS_IO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
nbytes += n;
|
||||
}
|
||||
|
||||
if (nbytes != size) {
|
||||
status = DC_STATUS_TIMEOUT;
|
||||
}
|
||||
|
||||
out:
|
||||
HEXDUMP (device->context, DC_LOGLEVEL_INFO, "Write", (unsigned char *) data, nbytes);
|
||||
|
||||
return nbytes;
|
||||
if (actual)
|
||||
*actual = nbytes;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
152
src/irda.h
152
src/irda.h
@ -19,37 +19,161 @@
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef IRDA_H
|
||||
#define IRDA_H
|
||||
#ifndef DC_IRDA_H
|
||||
#define DC_IRDA_H
|
||||
|
||||
#include <libdivecomputer/common.h>
|
||||
#include <libdivecomputer/context.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct irda_t irda_t;
|
||||
/**
|
||||
* Opaque object representing an IrDA connection.
|
||||
*/
|
||||
typedef struct dc_irda_t dc_irda_t;
|
||||
|
||||
typedef void (*irda_callback_t) (unsigned int address, const char *name, unsigned int charset, unsigned int hints, void *userdata);
|
||||
/**
|
||||
* IrDA enumeration callback.
|
||||
*
|
||||
* @param[in] address The IrDA device address.
|
||||
* @param[in] name The IrDA device name.
|
||||
* @param[in] charset The IrDA device character set.
|
||||
* @param[in] hints The IrDA device hints.
|
||||
* @param[in] userdata The user data pointer.
|
||||
*/
|
||||
typedef void (*dc_irda_callback_t) (unsigned int address, const char *name, unsigned int charset, unsigned int hints, void *userdata);
|
||||
|
||||
int irda_socket_open (irda_t **device, dc_context_t *context);
|
||||
/**
|
||||
* Open an IrDA connection.
|
||||
*
|
||||
* @param[out] irda A location to store the IrDA connection.
|
||||
* @param[in] context A valid context object.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_irda_open (dc_irda_t **irda, dc_context_t *context);
|
||||
|
||||
int irda_socket_close (irda_t *device);
|
||||
/**
|
||||
* Close the IrDA connection and free all resources.
|
||||
*
|
||||
* @param[in] irda A valid IrDA connection.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_irda_close (dc_irda_t *irda);
|
||||
|
||||
int irda_socket_set_timeout (irda_t *device, long timeout);
|
||||
/**
|
||||
* Set the read timeout.
|
||||
*
|
||||
* There are three distinct modes available:
|
||||
*
|
||||
* 1. Blocking (timeout < 0):
|
||||
*
|
||||
* The read operation is blocked until all the requested bytes have
|
||||
* been received. If the requested number of bytes does not arrive,
|
||||
* the operation will block forever.
|
||||
*
|
||||
* 2. Non-blocking (timeout == 0):
|
||||
*
|
||||
* The read operation returns immediately with the bytes that have
|
||||
* already been received, even if no bytes have been received.
|
||||
*
|
||||
* 3. Timeout (timeout > 0):
|
||||
*
|
||||
* The read operation is blocked until all the requested bytes have
|
||||
* been received. If the requested number of bytes does not arrive
|
||||
* within the specified amount of time, the operation will return
|
||||
* with the bytes that have already been received.
|
||||
*
|
||||
* @param[in] irda A valid IrDA connection.
|
||||
* @param[in] timeout The timeout in milliseconds.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_irda_set_timeout (dc_irda_t *irda, int timeout);
|
||||
|
||||
int irda_socket_discover (irda_t *device, irda_callback_t callback, void *userdata);
|
||||
/**
|
||||
* Enumerate the IrDA devices.
|
||||
*
|
||||
* @param[in] irda A valid IrDA connection.
|
||||
* @param[in] callback The callback function to call.
|
||||
* @param[in] userdata User data to pass to the callback function.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_irda_discover (dc_irda_t *irda, dc_irda_callback_t callback, void *userdata);
|
||||
|
||||
int irda_socket_connect_name (irda_t *device, unsigned int address, const char *name);
|
||||
int irda_socket_connect_lsap (irda_t *device, unsigned int address, unsigned int lsap);
|
||||
/**
|
||||
* Connect to an IrDA device.
|
||||
*
|
||||
* @param[in] irda A valid IrDA connection.
|
||||
* @param[in] address The IrDA device address.
|
||||
* @param[in] name The IrDA service name.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_irda_connect_name (dc_irda_t *irda, unsigned int address, const char *name);
|
||||
|
||||
int irda_socket_available (irda_t *device);
|
||||
/**
|
||||
* Connect to an IrDA device.
|
||||
*
|
||||
* @param[in] irda A valid IrDA connection.
|
||||
* @param[in] address The IrDA device address.
|
||||
* @param[in] lsap The IrDA LSAP number.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_irda_connect_lsap (dc_irda_t *irda, unsigned int address, unsigned int lsap);
|
||||
|
||||
int irda_socket_read (irda_t *device, void *data, unsigned int size);
|
||||
/**
|
||||
* Query the number of available bytes in the input buffer.
|
||||
*
|
||||
* @param[in] irda A valid IrDA connection.
|
||||
* @param[out] value A location to store the number of bytes in the
|
||||
* input buffer.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_irda_get_available (dc_irda_t *irda, size_t *value);
|
||||
|
||||
int irda_socket_write (irda_t *device, const void *data, unsigned int size);
|
||||
/**
|
||||
* Read data from the IrDA connection.
|
||||
*
|
||||
* @param[in] irda A valid IrDA connection.
|
||||
* @param[out] data The memory buffer to read the data into.
|
||||
* @param[in] size The number of bytes to read.
|
||||
* @param[out] actual An (optional) location to store the actual
|
||||
* number of bytes transferred.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_irda_read (dc_irda_t *irda, void *data, size_t size, size_t *actual);
|
||||
|
||||
/**
|
||||
* Write data to the IrDA connection.
|
||||
*
|
||||
* @param[in] irda A valid IrDA connection.
|
||||
* @param[in] data The memory buffer to write the data from.
|
||||
* @param[in] size The number of bytes to write.
|
||||
* @param[out] actual An (optional) location to store the actual
|
||||
* number of bytes transferred.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_irda_write (dc_irda_t *irda, const void *data, size_t size, size_t *actual);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* IRDA_H */
|
||||
#endif /* DC_IRDA_H */
|
||||
|
||||
@ -23,65 +23,56 @@
|
||||
|
||||
#include "irda.h"
|
||||
|
||||
|
||||
int
|
||||
irda_socket_open (irda_t **out, dc_context_t *context)
|
||||
dc_status_t
|
||||
dc_irda_open (dc_irda_t **out, dc_context_t *context)
|
||||
{
|
||||
return -1;
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
irda_socket_close (irda_t *device)
|
||||
dc_status_t
|
||||
dc_irda_close (dc_irda_t *device)
|
||||
{
|
||||
return -1;
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
irda_socket_set_timeout (irda_t *device, long timeout)
|
||||
dc_status_t
|
||||
dc_irda_set_timeout (dc_irda_t *device, int timeout)
|
||||
{
|
||||
return -1;
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
irda_socket_discover (irda_t *device, irda_callback_t callback, void *userdata)
|
||||
dc_status_t
|
||||
dc_irda_discover (dc_irda_t *device, dc_irda_callback_t callback, void *userdata)
|
||||
{
|
||||
return -1;
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
irda_socket_connect_name (irda_t *device, unsigned int address, const char *name)
|
||||
dc_status_t
|
||||
dc_irda_connect_name (dc_irda_t *device, unsigned int address, const char *name)
|
||||
{
|
||||
return -1;
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
irda_socket_connect_lsap (irda_t *device, unsigned int address, unsigned int lsap)
|
||||
dc_status_t
|
||||
dc_irda_connect_lsap (dc_irda_t *device, unsigned int address, unsigned int lsap)
|
||||
{
|
||||
return -1;
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
irda_socket_available (irda_t *device)
|
||||
dc_status_t
|
||||
dc_irda_get_available (dc_irda_t *device, size_t *value)
|
||||
{
|
||||
return -1;
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
irda_socket_read (irda_t *device, void *data, unsigned int size)
|
||||
dc_status_t
|
||||
dc_irda_read (dc_irda_t *device, void *data, size_t size, size_t *actual)
|
||||
{
|
||||
return -1;
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
irda_socket_write (irda_t *device, const void *data, unsigned int size)
|
||||
dc_status_t
|
||||
dc_irda_write (dc_irda_t *device, const void *data, size_t size, size_t *actual)
|
||||
{
|
||||
return -1;
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
@ -28,11 +28,6 @@
|
||||
#include "checksum.h"
|
||||
#include "array.h"
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define MAXRETRIES 4
|
||||
|
||||
#define FP_OFFSET 8
|
||||
@ -86,29 +81,30 @@ mares_common_make_ascii (const unsigned char raw[], unsigned int rsize, unsigned
|
||||
static dc_status_t
|
||||
mares_common_packet (mares_common_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
if (device_is_cancelled (abstract))
|
||||
return DC_STATUS_CANCELLED;
|
||||
|
||||
if (device->delay) {
|
||||
serial_sleep (device->port, device->delay);
|
||||
dc_serial_sleep (device->port, device->delay);
|
||||
}
|
||||
|
||||
// Send the command to the device.
|
||||
int n = serial_write (device->port, command, csize);
|
||||
if (n != csize) {
|
||||
status = dc_serial_write (device->port, command, csize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (device->echo) {
|
||||
// Receive the echo of the command.
|
||||
unsigned char echo[PACKETSIZE] = {0};
|
||||
n = serial_read (device->port, echo, csize);
|
||||
if (n != csize) {
|
||||
status = dc_serial_read (device->port, echo, csize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the echo.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the echo.
|
||||
@ -118,10 +114,10 @@ mares_common_packet (mares_common_device_t *device, const unsigned char command[
|
||||
}
|
||||
|
||||
// Receive the answer of the device.
|
||||
n = serial_read (device->port, answer, asize);
|
||||
if (n != asize) {
|
||||
status = dc_serial_read (device->port, answer, asize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the header and trailer of the packet.
|
||||
@ -159,8 +155,8 @@ mares_common_transfer (mares_common_device_t *device, const unsigned char comman
|
||||
return rc;
|
||||
|
||||
// Discard any garbage bytes.
|
||||
serial_sleep (device->port, 100);
|
||||
serial_flush (device->port, SERIAL_QUEUE_INPUT);
|
||||
dc_serial_sleep (device->port, 100);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_INPUT);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
@ -41,7 +41,7 @@ typedef struct mares_common_layout_t {
|
||||
|
||||
typedef struct mares_common_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
unsigned int echo;
|
||||
unsigned int delay;
|
||||
} mares_common_device_t;
|
||||
|
||||
@ -122,39 +122,43 @@ mares_darwin_device_open (dc_device_t **out, dc_context_t *context, const char *
|
||||
device->layout = &mares_darwin_layout;
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->base.port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->base.port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (9600 8N1).
|
||||
rc = serial_configure (device->base.port, 9600, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->base.port, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (1000 ms).
|
||||
if (serial_set_timeout (device->base.port, 1000) == -1) {
|
||||
status = dc_serial_set_timeout (device->base.port, 1000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the DTR/RTS lines.
|
||||
if (serial_set_dtr (device->base.port, 1) == -1 ||
|
||||
serial_set_rts (device->base.port, 1) == -1) {
|
||||
ERROR (context, "Failed to set the DTR/RTS line.");
|
||||
status = DC_STATUS_IO;
|
||||
// Set the DTR line.
|
||||
status = dc_serial_set_dtr (device->base.port, 1);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the DTR line.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the RTS line.
|
||||
status = dc_serial_set_rts (device->base.port, 1);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the RTS line.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_sleep (device->base.port, 100);
|
||||
serial_flush (device->base.port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_sleep (device->base.port, 100);
|
||||
dc_serial_purge (device->base.port, DC_DIRECTION_ALL);
|
||||
|
||||
// Override the base class values.
|
||||
device->base.echo = 1;
|
||||
@ -165,7 +169,7 @@ mares_darwin_device_open (dc_device_t **out, dc_context_t *context, const char *
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->base.port);
|
||||
dc_serial_close (device->base.port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -176,10 +180,12 @@ mares_darwin_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
mares_darwin_device_t *device = (mares_darwin_device_t *) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->base.port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->base.port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
@ -34,11 +34,6 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &mares_iconhd_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define MATRIX 0x0F
|
||||
#define SMART 0x000010
|
||||
#define SMARTAPNEA 0x010010
|
||||
@ -69,7 +64,7 @@ typedef struct mares_iconhd_model_t {
|
||||
|
||||
typedef struct mares_iconhd_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
const mares_iconhd_layout_t *layout;
|
||||
unsigned char fingerprint[10];
|
||||
unsigned char version[140];
|
||||
@ -150,6 +145,7 @@ mares_iconhd_transfer (mares_iconhd_device_t *device,
|
||||
const unsigned char command[], unsigned int csize,
|
||||
unsigned char answer[], unsigned int asize)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
assert (csize >= 2);
|
||||
@ -158,18 +154,18 @@ mares_iconhd_transfer (mares_iconhd_device_t *device,
|
||||
return DC_STATUS_CANCELLED;
|
||||
|
||||
// Send the command header to the dive computer.
|
||||
int n = serial_write (device->port, command, 2);
|
||||
if (n != 2) {
|
||||
status = dc_serial_write (device->port, command, 2, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Receive the header byte.
|
||||
unsigned char header[1] = {0};
|
||||
n = serial_read (device->port, header, sizeof (header));
|
||||
if (n != sizeof (header)) {
|
||||
status = dc_serial_read (device->port, header, sizeof (header), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the header byte.
|
||||
@ -180,26 +176,26 @@ mares_iconhd_transfer (mares_iconhd_device_t *device,
|
||||
|
||||
// Send the command payload to the dive computer.
|
||||
if (csize > 2) {
|
||||
n = serial_write (device->port, command + 2, csize - 2);
|
||||
if (n != csize - 2) {
|
||||
status = dc_serial_write (device->port, command + 2, csize - 2, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the packet.
|
||||
n = serial_read (device->port, answer, asize);
|
||||
if (n != asize) {
|
||||
status = dc_serial_read (device->port, answer, asize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Receive the trailer byte.
|
||||
unsigned char trailer[1] = {0};
|
||||
n = serial_read (device->port, trailer, sizeof (trailer));
|
||||
if (n != sizeof (trailer)) {
|
||||
status = dc_serial_read (device->port, trailer, sizeof (trailer), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the trailer byte.
|
||||
@ -237,39 +233,42 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, const char *
|
||||
device->packetsize = 0;
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (115200 8E1).
|
||||
rc = serial_configure (device->port, 115200, 8, SERIAL_PARITY_EVEN, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 115200, 8, DC_PARITY_EVEN, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (1000 ms).
|
||||
if (serial_set_timeout (device->port, 1000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 1000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the DTR/RTS lines.
|
||||
if (serial_set_dtr (device->port, 0) == -1 ||
|
||||
serial_set_rts (device->port, 0) == -1)
|
||||
{
|
||||
ERROR (context, "Failed to set the DTR/RTS line.");
|
||||
status = DC_STATUS_IO;
|
||||
// Clear the DTR line.
|
||||
status = dc_serial_set_dtr (device->port, 0);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to clear the DTR line.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Clear the RTS line.
|
||||
status = dc_serial_set_rts (device->port, 0);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to clear the RTS line.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
// Send the version command.
|
||||
unsigned char command[] = {0xC2, 0x67};
|
||||
@ -312,7 +311,7 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, const char *
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -324,10 +323,12 @@ mares_iconhd_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
mares_iconhd_device_t *device = (mares_iconhd_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
@ -33,11 +33,6 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &mares_nemo_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#ifdef PACKETSIZE
|
||||
#undef PACKETSIZE /* Override the common value. */
|
||||
#endif
|
||||
@ -51,7 +46,7 @@
|
||||
|
||||
typedef struct mares_nemo_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
unsigned char fingerprint[5];
|
||||
} mares_nemo_device_t;
|
||||
|
||||
@ -109,45 +104,49 @@ mares_nemo_device_open (dc_device_t **out, dc_context_t *context, const char *na
|
||||
memset (device->fingerprint, 0, sizeof (device->fingerprint));
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (9600 8N1).
|
||||
rc = serial_configure (device->port, 9600, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (1000 ms).
|
||||
if (serial_set_timeout (device->port, 1000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 1000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the DTR/RTS lines.
|
||||
if (serial_set_dtr (device->port, 1) == -1 ||
|
||||
serial_set_rts (device->port, 1) == -1) {
|
||||
ERROR (context, "Failed to set the DTR/RTS line.");
|
||||
status = DC_STATUS_IO;
|
||||
// Set the DTR line.
|
||||
status = dc_serial_set_dtr (device->port, 1);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the DTR line.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the RTS line.
|
||||
status = dc_serial_set_rts (device->port, 1);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the RTS line.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
*out = (dc_device_t*) device;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -159,10 +158,12 @@ mares_nemo_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
mares_nemo_device_t *device = (mares_nemo_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -189,6 +190,7 @@ mares_nemo_device_set_fingerprint (dc_device_t *abstract, const unsigned char da
|
||||
static dc_status_t
|
||||
mares_nemo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
mares_nemo_device_t *device = (mares_nemo_device_t *) abstract;
|
||||
|
||||
// Erase the current contents of the buffer and
|
||||
@ -204,21 +206,22 @@ mares_nemo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
|
||||
|
||||
// Wait until some data arrives.
|
||||
while (serial_get_received (device->port) == 0) {
|
||||
size_t available = 0;
|
||||
while (dc_serial_get_available (device->port, &available) == DC_STATUS_SUCCESS && available == 0) {
|
||||
if (device_is_cancelled (abstract))
|
||||
return DC_STATUS_CANCELLED;
|
||||
|
||||
device_event_emit (abstract, DC_EVENT_WAITING, NULL);
|
||||
serial_sleep (device->port, 100);
|
||||
dc_serial_sleep (device->port, 100);
|
||||
}
|
||||
|
||||
// Receive the header of the package.
|
||||
unsigned char header = 0x00;
|
||||
for (unsigned int i = 0; i < 20;) {
|
||||
int n = serial_read (device->port, &header, 1);
|
||||
if (n != 1) {
|
||||
status = dc_serial_read (device->port, &header, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the header.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
if (header == 0xEE) {
|
||||
i++; // Continue.
|
||||
@ -235,10 +238,10 @@ mares_nemo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
while (nbytes < MEMORYSIZE) {
|
||||
// Read the packet.
|
||||
unsigned char packet[(PACKETSIZE + 1) * 2] = {0};
|
||||
int n = serial_read (device->port, packet, sizeof (packet));
|
||||
if (n != sizeof (packet)) {
|
||||
status = dc_serial_read (device->port, packet, sizeof (packet), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the checksums of the packet.
|
||||
|
||||
@ -110,38 +110,42 @@ mares_puck_device_open (dc_device_t **out, dc_context_t *context, const char *na
|
||||
memset (device->fingerprint, 0, sizeof (device->fingerprint));
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->base.port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->base.port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (38400 8N1).
|
||||
rc = serial_configure (device->base.port, 38400, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->base.port, 38400, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (1000 ms).
|
||||
if (serial_set_timeout (device->base.port, 1000) == -1) {
|
||||
status = dc_serial_set_timeout (device->base.port, 1000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Clear the DTR/RTS lines.
|
||||
if (serial_set_dtr (device->base.port, 0) == -1 ||
|
||||
serial_set_rts (device->base.port, 0) == -1) {
|
||||
ERROR (context, "Failed to set the DTR/RTS line.");
|
||||
status = DC_STATUS_IO;
|
||||
// Clear the DTR line.
|
||||
status = dc_serial_set_dtr (device->base.port, 0);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to clear the DTR line.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Clear the RTS line.
|
||||
status = dc_serial_set_rts (device->base.port, 0);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to clear the RTS line.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_flush (device->base.port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_purge (device->base.port, DC_DIRECTION_ALL);
|
||||
|
||||
// Identify the model number.
|
||||
unsigned char header[PACKETSIZE] = {0};
|
||||
@ -172,7 +176,7 @@ mares_puck_device_open (dc_device_t **out, dc_context_t *context, const char *na
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->base.port);
|
||||
dc_serial_close (device->base.port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -184,10 +188,12 @@ mares_puck_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
mares_puck_device_t *device = (mares_puck_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->base.port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->base.port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
@ -40,11 +40,6 @@
|
||||
#define MAXDELAY 16
|
||||
#define INVALID 0xFFFFFFFF
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define CMD_INIT 0xA8
|
||||
#define CMD_VERSION 0x84
|
||||
#define CMD_READ1 0xB1
|
||||
@ -59,7 +54,7 @@
|
||||
|
||||
typedef struct oceanic_atom2_device_t {
|
||||
oceanic_common_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
unsigned int delay;
|
||||
unsigned int bigpage;
|
||||
unsigned char cache[256];
|
||||
@ -422,20 +417,21 @@ static const oceanic_common_layout_t aqualung_i450t_layout = {
|
||||
static dc_status_t
|
||||
oceanic_atom2_packet (oceanic_atom2_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize, unsigned int crc_size)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
if (device_is_cancelled (abstract))
|
||||
return DC_STATUS_CANCELLED;
|
||||
|
||||
if (device->delay) {
|
||||
serial_sleep (device->port, device->delay);
|
||||
dc_serial_sleep (device->port, device->delay);
|
||||
}
|
||||
|
||||
// Send the command to the dive computer.
|
||||
int n = serial_write (device->port, command, csize);
|
||||
if (n != csize) {
|
||||
status = dc_serial_write (device->port, command, csize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Get the correct ACK byte.
|
||||
@ -446,10 +442,10 @@ oceanic_atom2_packet (oceanic_atom2_device_t *device, const unsigned char comman
|
||||
|
||||
// Receive the response (ACK/NAK) of the dive computer.
|
||||
unsigned char response = 0;
|
||||
n = serial_read (device->port, &response, 1);
|
||||
if (n != 1) {
|
||||
status = dc_serial_read (device->port, &response, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the response of the dive computer.
|
||||
@ -460,10 +456,10 @@ oceanic_atom2_packet (oceanic_atom2_device_t *device, const unsigned char comman
|
||||
|
||||
if (asize) {
|
||||
// Receive the answer of the dive computer.
|
||||
int n = serial_read (device->port, answer, asize);
|
||||
if (n != asize) {
|
||||
status = dc_serial_read (device->port, answer, asize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the checksum of the answer.
|
||||
@ -509,8 +505,8 @@ oceanic_atom2_transfer (oceanic_atom2_device_t *device, const unsigned char comm
|
||||
device->delay++;
|
||||
|
||||
// Delay the next attempt.
|
||||
serial_sleep (device->port, 100);
|
||||
serial_flush (device->port, SERIAL_QUEUE_INPUT);
|
||||
dc_serial_sleep (device->port, 100);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_INPUT);
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
@ -564,10 +560,9 @@ oceanic_atom2_device_open2 (dc_device_t **out, dc_context_t *context, const char
|
||||
memset(device->cache, 0, sizeof(device->cache));
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
@ -578,29 +573,28 @@ oceanic_atom2_device_open2 (dc_device_t **out, dc_context_t *context, const char
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (38400 8N1).
|
||||
rc = serial_configure (device->port, baudrate, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, baudrate, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (1000 ms).
|
||||
if (serial_set_timeout (device->port, 1000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 1000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Give the interface 100 ms to settle and draw power up.
|
||||
serial_sleep (device->port, 100);
|
||||
dc_serial_sleep (device->port, 100);
|
||||
|
||||
// Set the DTR/RTS lines.
|
||||
serial_set_dtr(device->port, 1);
|
||||
serial_set_rts(device->port, 1);
|
||||
dc_serial_set_dtr(device->port, 1);
|
||||
dc_serial_set_rts(device->port, 1);
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
// Switch the device from surface mode into download mode. Before sending
|
||||
// this command, the device needs to be in PC mode (automatically activated
|
||||
@ -662,7 +656,7 @@ oceanic_atom2_device_open2 (dc_device_t **out, dc_context_t *context, const char
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -674,13 +668,15 @@ oceanic_atom2_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
oceanic_atom2_device_t *device = (oceanic_atom2_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Send the quit command.
|
||||
oceanic_atom2_quit (device);
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
@ -36,17 +36,12 @@
|
||||
#define MAXRETRIES 2
|
||||
#define MULTIPAGE 4
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define ACK 0x5A
|
||||
#define NAK 0xA5
|
||||
|
||||
typedef struct oceanic_veo250_device_t {
|
||||
oceanic_common_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
unsigned int last;
|
||||
} oceanic_veo250_device_t;
|
||||
|
||||
@ -91,27 +86,28 @@ static const oceanic_common_layout_t oceanic_veo250_layout = {
|
||||
static dc_status_t
|
||||
oceanic_veo250_send (oceanic_veo250_device_t *device, const unsigned char command[], unsigned int csize)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
if (device_is_cancelled (abstract))
|
||||
return DC_STATUS_CANCELLED;
|
||||
|
||||
// Discard garbage bytes.
|
||||
serial_flush (device->port, SERIAL_QUEUE_INPUT);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_INPUT);
|
||||
|
||||
// Send the command to the dive computer.
|
||||
int n = serial_write (device->port, command, csize);
|
||||
if (n != csize) {
|
||||
status = dc_serial_write (device->port, command, csize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Receive the response (ACK/NAK) of the dive computer.
|
||||
unsigned char response = NAK;
|
||||
n = serial_read (device->port, &response, 1);
|
||||
if (n != 1) {
|
||||
status = dc_serial_read (device->port, &response, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the response of the dive computer.
|
||||
@ -127,6 +123,7 @@ oceanic_veo250_send (oceanic_veo250_device_t *device, const unsigned char comman
|
||||
static dc_status_t
|
||||
oceanic_veo250_transfer (oceanic_veo250_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
// Send the command to the device. If the device responds with an
|
||||
@ -146,14 +143,14 @@ oceanic_veo250_transfer (oceanic_veo250_device_t *device, const unsigned char co
|
||||
return rc;
|
||||
|
||||
// Delay the next attempt.
|
||||
serial_sleep (device->port, 100);
|
||||
dc_serial_sleep (device->port, 100);
|
||||
}
|
||||
|
||||
// Receive the answer of the dive computer.
|
||||
int n = serial_read (device->port, answer, asize);
|
||||
if (n != asize) {
|
||||
status = dc_serial_read (device->port, answer, asize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the last byte of the answer.
|
||||
@ -169,24 +166,26 @@ oceanic_veo250_transfer (oceanic_veo250_device_t *device, const unsigned char co
|
||||
static dc_status_t
|
||||
oceanic_veo250_init (oceanic_veo250_device_t *device)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
// Send the command to the dive computer.
|
||||
unsigned char command[2] = {0x55, 0x00};
|
||||
int n = serial_write (device->port, command, sizeof (command));
|
||||
if (n != sizeof (command)) {
|
||||
status = dc_serial_write (device->port, command, sizeof (command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Receive the answer of the dive computer.
|
||||
size_t n = 0;
|
||||
unsigned char answer[13] = {0};
|
||||
n = serial_read (device->port, answer, sizeof (answer));
|
||||
if (n != sizeof (answer)) {
|
||||
status = dc_serial_read (device->port, answer, sizeof (answer), &n);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
if (n == 0)
|
||||
return DC_STATUS_SUCCESS;
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the answer.
|
||||
@ -205,14 +204,15 @@ oceanic_veo250_init (oceanic_veo250_device_t *device)
|
||||
static dc_status_t
|
||||
oceanic_veo250_quit (oceanic_veo250_device_t *device)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
// Send the command to the dive computer.
|
||||
unsigned char command[2] = {0x98, 0x00};
|
||||
int n = serial_write (device->port, command, sizeof (command));
|
||||
if (n != sizeof (command)) {
|
||||
status = dc_serial_write (device->port, command, sizeof (command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
@ -247,41 +247,45 @@ oceanic_veo250_device_open (dc_device_t **out, dc_context_t *context, const char
|
||||
device->last = 0;
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (9600 8N1).
|
||||
rc = serial_configure (device->port, 9600, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (3000 ms).
|
||||
if (serial_set_timeout (device->port, 3000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 3000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the DTR and RTS lines.
|
||||
if (serial_set_dtr (device->port, 1) == -1 ||
|
||||
serial_set_rts (device->port, 1) == -1) {
|
||||
ERROR (context, "Failed to set the DTR/RTS line.");
|
||||
status = DC_STATUS_IO;
|
||||
// Set the DTR line.
|
||||
status = dc_serial_set_dtr (device->port, 1);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the DTR line.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the RTS line.
|
||||
status = dc_serial_set_rts (device->port, 1);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the RTS line.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Give the interface 100 ms to settle and draw power up.
|
||||
serial_sleep (device->port, 100);
|
||||
dc_serial_sleep (device->port, 100);
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
// Initialize the data cable (PPS mode).
|
||||
status = oceanic_veo250_init (device);
|
||||
@ -290,7 +294,7 @@ oceanic_veo250_device_open (dc_device_t **out, dc_context_t *context, const char
|
||||
}
|
||||
|
||||
// Delay the sending of the version command.
|
||||
serial_sleep (device->port, 100);
|
||||
dc_serial_sleep (device->port, 100);
|
||||
|
||||
// Switch the device from surface mode into download mode. Before sending
|
||||
// this command, the device needs to be in PC mode (manually activated by
|
||||
@ -305,7 +309,7 @@ oceanic_veo250_device_open (dc_device_t **out, dc_context_t *context, const char
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -317,13 +321,15 @@ oceanic_veo250_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
oceanic_veo250_device_t *device = (oceanic_veo250_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Switch the device back to surface mode.
|
||||
oceanic_veo250_quit (device);
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
@ -36,18 +36,13 @@
|
||||
#define MAXRETRIES 2
|
||||
#define MULTIPAGE 4
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define ACK 0x5A
|
||||
#define NAK 0xA5
|
||||
#define END 0x51
|
||||
|
||||
typedef struct oceanic_vtpro_device_t {
|
||||
oceanic_common_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
} oceanic_vtpro_device_t;
|
||||
|
||||
static dc_status_t oceanic_vtpro_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size);
|
||||
@ -107,24 +102,25 @@ static const oceanic_common_layout_t oceanic_wisdom_layout = {
|
||||
static dc_status_t
|
||||
oceanic_vtpro_send (oceanic_vtpro_device_t *device, const unsigned char command[], unsigned int csize)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
if (device_is_cancelled (abstract))
|
||||
return DC_STATUS_CANCELLED;
|
||||
|
||||
// Send the command to the dive computer.
|
||||
int n = serial_write (device->port, command, csize);
|
||||
if (n != csize) {
|
||||
status = dc_serial_write (device->port, command, csize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Receive the response (ACK/NAK) of the dive computer.
|
||||
unsigned char response = NAK;
|
||||
n = serial_read (device->port, &response, 1);
|
||||
if (n != 1) {
|
||||
status = dc_serial_read (device->port, &response, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the response of the dive computer.
|
||||
@ -140,6 +136,7 @@ oceanic_vtpro_send (oceanic_vtpro_device_t *device, const unsigned char command[
|
||||
static dc_status_t
|
||||
oceanic_vtpro_transfer (oceanic_vtpro_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
// Send the command to the device. If the device responds with an
|
||||
@ -160,10 +157,10 @@ oceanic_vtpro_transfer (oceanic_vtpro_device_t *device, const unsigned char comm
|
||||
}
|
||||
|
||||
// Receive the answer of the dive computer.
|
||||
int n = serial_read (device->port, answer, asize);
|
||||
if (n != asize) {
|
||||
status = dc_serial_read (device->port, answer, asize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
@ -173,22 +170,23 @@ oceanic_vtpro_transfer (oceanic_vtpro_device_t *device, const unsigned char comm
|
||||
static dc_status_t
|
||||
oceanic_vtpro_init (oceanic_vtpro_device_t *device)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
// Send the command to the dive computer.
|
||||
unsigned char command[2] = {0xAA, 0x00};
|
||||
int n = serial_write (device->port, command, sizeof (command));
|
||||
if (n != sizeof (command)) {
|
||||
status = dc_serial_write (device->port, command, sizeof (command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Receive the answer of the dive computer.
|
||||
unsigned char answer[13] = {0};
|
||||
n = serial_read (device->port, answer, sizeof (answer));
|
||||
if (n != sizeof (answer)) {
|
||||
status = dc_serial_read (device->port, answer, sizeof (answer), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the answer.
|
||||
@ -236,9 +234,9 @@ oceanic_vtpro_calibrate (oceanic_vtpro_device_t *device)
|
||||
// device needs approximately 6 seconds to respond.
|
||||
unsigned char answer[2] = {0};
|
||||
unsigned char command[2] = {0x18, 0x00};
|
||||
serial_set_timeout (device->port, 9000);
|
||||
dc_serial_set_timeout (device->port, 9000);
|
||||
dc_status_t rc = oceanic_vtpro_transfer (device, command, sizeof (command), answer, sizeof (answer));
|
||||
serial_set_timeout (device->port, 3000);
|
||||
dc_serial_set_timeout (device->port, 3000);
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
@ -278,41 +276,45 @@ oceanic_vtpro_device_open (dc_device_t **out, dc_context_t *context, const char
|
||||
device->port = NULL;
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (9600 8N1).
|
||||
rc = serial_configure (device->port, 9600, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (3000 ms).
|
||||
if (serial_set_timeout (device->port, 3000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 3000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the DTR and RTS lines.
|
||||
if (serial_set_dtr (device->port, 1) == -1 ||
|
||||
serial_set_rts (device->port, 1) == -1) {
|
||||
ERROR (context, "Failed to set the DTR/RTS line.");
|
||||
status = DC_STATUS_IO;
|
||||
// Set the DTR line.
|
||||
status = dc_serial_set_dtr (device->port, 1);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the DTR line.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the RTS line.
|
||||
status = dc_serial_set_rts (device->port, 1);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the RTS line.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Give the interface 100 ms to settle and draw power up.
|
||||
serial_sleep (device->port, 100);
|
||||
dc_serial_sleep (device->port, 100);
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
// Initialize the data cable (MOD mode).
|
||||
status = oceanic_vtpro_init (device);
|
||||
@ -348,7 +350,7 @@ oceanic_vtpro_device_open (dc_device_t **out, dc_context_t *context, const char
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -360,13 +362,15 @@ oceanic_vtpro_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
oceanic_vtpro_device_t *device = (oceanic_vtpro_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Switch the device back to surface mode.
|
||||
oceanic_vtpro_quit (device);
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
@ -32,17 +32,12 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &reefnet_sensus_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define SZ_MEMORY 32768
|
||||
#define SZ_HANDSHAKE 10
|
||||
|
||||
typedef struct reefnet_sensus_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
unsigned char handshake[SZ_HANDSHAKE];
|
||||
unsigned int waiting;
|
||||
unsigned int timestamp;
|
||||
@ -70,14 +65,15 @@ static const dc_device_vtable_t reefnet_sensus_device_vtable = {
|
||||
static dc_status_t
|
||||
reefnet_sensus_cancel (reefnet_sensus_device_t *device)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
// Send the command to the device.
|
||||
unsigned char command = 0x00;
|
||||
int n = serial_write (device->port, &command, 1);
|
||||
if (n != 1) {
|
||||
status = dc_serial_write (device->port, &command, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// The device leaves the waiting state.
|
||||
@ -112,37 +108,35 @@ reefnet_sensus_device_open (dc_device_t **out, dc_context_t *context, const char
|
||||
memset (device->handshake, 0, sizeof (device->handshake));
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (19200 8N1).
|
||||
rc = serial_configure (device->port, 19200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 19200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (3000 ms).
|
||||
if (serial_set_timeout (device->port, 3000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 3000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
*out = (dc_device_t*) device;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -154,15 +148,18 @@ reefnet_sensus_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
reefnet_sensus_device_t *device = (reefnet_sensus_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Safely close the connection if the last handshake was
|
||||
// successful, but no data transfer was ever initiated.
|
||||
if (device->waiting)
|
||||
reefnet_sensus_cancel (device);
|
||||
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -208,22 +205,23 @@ reefnet_sensus_device_set_fingerprint (dc_device_t *abstract, const unsigned cha
|
||||
static dc_status_t
|
||||
reefnet_sensus_handshake (reefnet_sensus_device_t *device)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
// Send the command to the device.
|
||||
unsigned char command = 0x0A;
|
||||
int n = serial_write (device->port, &command, 1);
|
||||
if (n != 1) {
|
||||
status = dc_serial_write (device->port, &command, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Receive the answer from the device.
|
||||
unsigned char handshake[SZ_HANDSHAKE + 2] = {0};
|
||||
n = serial_read (device->port, handshake, sizeof (handshake));
|
||||
if (n != sizeof (handshake)) {
|
||||
status = dc_serial_read (device->port, handshake, sizeof (handshake), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the handshake.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the header of the packet.
|
||||
@ -264,7 +262,7 @@ reefnet_sensus_handshake (reefnet_sensus_device_t *device)
|
||||
// Wait at least 10 ms to ensures the data line is
|
||||
// clear before transmission from the host begins.
|
||||
|
||||
serial_sleep (device->port, 10);
|
||||
dc_serial_sleep (device->port, 10);
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
@ -273,6 +271,7 @@ reefnet_sensus_handshake (reefnet_sensus_device_t *device)
|
||||
static dc_status_t
|
||||
reefnet_sensus_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
reefnet_sensus_device_t *device = (reefnet_sensus_device_t*) abstract;
|
||||
|
||||
// Erase the current contents of the buffer and
|
||||
@ -294,10 +293,10 @@ reefnet_sensus_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
|
||||
// Send the command to the device.
|
||||
unsigned char command = 0x40;
|
||||
int n = serial_write (device->port, &command, 1);
|
||||
if (n != 1) {
|
||||
status = dc_serial_write (device->port, &command, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// The device leaves the waiting state.
|
||||
@ -311,10 +310,10 @@ reefnet_sensus_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
if (len > 128)
|
||||
len = 128;
|
||||
|
||||
n = serial_read (device->port, answer + nbytes, len);
|
||||
if (n != len) {
|
||||
status = dc_serial_read (device->port, answer + nbytes, len, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Update and emit a progress event.
|
||||
|
||||
@ -32,17 +32,12 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &reefnet_sensuspro_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define SZ_MEMORY 56320
|
||||
#define SZ_HANDSHAKE 10
|
||||
|
||||
typedef struct reefnet_sensuspro_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
unsigned char handshake[SZ_HANDSHAKE];
|
||||
unsigned int timestamp;
|
||||
unsigned int devtime;
|
||||
@ -90,37 +85,35 @@ reefnet_sensuspro_device_open (dc_device_t **out, dc_context_t *context, const c
|
||||
memset (device->handshake, 0, sizeof (device->handshake));
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (19200 8N1).
|
||||
rc = serial_configure (device->port, 19200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 19200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (3000ms).
|
||||
if (serial_set_timeout (device->port, 3000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 3000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
*out = (dc_device_t*) device;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -132,10 +125,12 @@ reefnet_sensuspro_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
reefnet_sensuspro_device_t *device = (reefnet_sensuspro_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -181,21 +176,22 @@ reefnet_sensuspro_device_set_fingerprint (dc_device_t *abstract, const unsigned
|
||||
static dc_status_t
|
||||
reefnet_sensuspro_handshake (reefnet_sensuspro_device_t *device)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
// Assert a break condition.
|
||||
serial_set_break (device->port, 1);
|
||||
dc_serial_set_break (device->port, 1);
|
||||
|
||||
// Receive the handshake from the dive computer.
|
||||
unsigned char handshake[SZ_HANDSHAKE + 2] = {0};
|
||||
int rc = serial_read (device->port, handshake, sizeof (handshake));
|
||||
if (rc != sizeof (handshake)) {
|
||||
status = dc_serial_read (device->port, handshake, sizeof (handshake), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the handshake.");
|
||||
return EXITCODE (rc);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Clear the break condition again.
|
||||
serial_set_break (device->port, 0);
|
||||
dc_serial_set_break (device->port, 0);
|
||||
|
||||
// Verify the checksum of the handshake packet.
|
||||
unsigned short crc = array_uint16_le (handshake + SZ_HANDSHAKE);
|
||||
@ -231,7 +227,7 @@ reefnet_sensuspro_handshake (reefnet_sensuspro_device_t *device)
|
||||
vendor.size = sizeof (device->handshake);
|
||||
device_event_emit (abstract, DC_EVENT_VENDOR, &vendor);
|
||||
|
||||
serial_sleep (device->port, 10);
|
||||
dc_serial_sleep (device->port, 10);
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
@ -240,6 +236,7 @@ reefnet_sensuspro_handshake (reefnet_sensuspro_device_t *device)
|
||||
static dc_status_t
|
||||
reefnet_sensuspro_send (reefnet_sensuspro_device_t *device, unsigned char command)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
// Wake-up the device.
|
||||
@ -248,10 +245,10 @@ reefnet_sensuspro_send (reefnet_sensuspro_device_t *device, unsigned char comman
|
||||
return rc;
|
||||
|
||||
// Send the instruction code to the device.
|
||||
int n = serial_write (device->port, &command, 1);
|
||||
if (n != 1) {
|
||||
status = dc_serial_write (device->port, &command, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
@ -261,6 +258,7 @@ reefnet_sensuspro_send (reefnet_sensuspro_device_t *device, unsigned char comman
|
||||
static dc_status_t
|
||||
reefnet_sensuspro_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
reefnet_sensuspro_device_t *device = (reefnet_sensuspro_device_t*) abstract;
|
||||
|
||||
// Erase the current contents of the buffer and
|
||||
@ -287,10 +285,10 @@ reefnet_sensuspro_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
if (len > 256)
|
||||
len = 256;
|
||||
|
||||
int n = serial_read (device->port, answer + nbytes, len);
|
||||
if (n != len) {
|
||||
status = dc_serial_read (device->port, answer + nbytes, len, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Update and emit a progress event.
|
||||
@ -338,6 +336,7 @@ reefnet_sensuspro_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
|
||||
dc_status_t
|
||||
reefnet_sensuspro_device_write_interval (dc_device_t *abstract, unsigned char interval)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
reefnet_sensuspro_device_t *device = (reefnet_sensuspro_device_t*) abstract;
|
||||
|
||||
if (!ISINSTANCE (abstract))
|
||||
@ -351,12 +350,12 @@ reefnet_sensuspro_device_write_interval (dc_device_t *abstract, unsigned char in
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
serial_sleep (device->port, 10);
|
||||
dc_serial_sleep (device->port, 10);
|
||||
|
||||
int n = serial_write (device->port, &interval, 1);
|
||||
if (n != 1) {
|
||||
status = dc_serial_write (device->port, &interval, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the data packet.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
@ -33,11 +33,6 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &reefnet_sensusultra_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define SZ_PACKET 512
|
||||
#define SZ_MEMORY 2080768
|
||||
#define SZ_USER 16384
|
||||
@ -51,7 +46,7 @@
|
||||
|
||||
typedef struct reefnet_sensusultra_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
unsigned char handshake[SZ_HANDSHAKE];
|
||||
unsigned int timestamp;
|
||||
unsigned int devtime;
|
||||
@ -99,37 +94,35 @@ reefnet_sensusultra_device_open (dc_device_t **out, dc_context_t *context, const
|
||||
memset (device->handshake, 0, sizeof (device->handshake));
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (115200 8N1).
|
||||
rc = serial_configure (device->port, 115200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (3000ms).
|
||||
if (serial_set_timeout (device->port, 3000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 3000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
*out = (dc_device_t*) device;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -141,10 +134,12 @@ reefnet_sensusultra_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
reefnet_sensusultra_device_t *device = (reefnet_sensusultra_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -190,14 +185,15 @@ reefnet_sensusultra_device_set_fingerprint (dc_device_t *abstract, const unsigne
|
||||
static dc_status_t
|
||||
reefnet_sensusultra_send_uchar (reefnet_sensusultra_device_t *device, unsigned char value)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
// Wait for the prompt byte.
|
||||
unsigned char prompt = 0;
|
||||
int rc = serial_read (device->port, &prompt, 1);
|
||||
if (rc != 1) {
|
||||
status = dc_serial_read (device->port, &prompt, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the prompt byte");
|
||||
return EXITCODE (rc);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the prompt byte.
|
||||
@ -207,10 +203,10 @@ reefnet_sensusultra_send_uchar (reefnet_sensusultra_device_t *device, unsigned c
|
||||
}
|
||||
|
||||
// Send the value to the device.
|
||||
rc = serial_write (device->port, &value, 1);
|
||||
if (rc != 1) {
|
||||
status = dc_serial_write (device->port, &value, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the value.");
|
||||
return EXITCODE (rc);
|
||||
return status;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
@ -239,18 +235,19 @@ reefnet_sensusultra_send_ushort (reefnet_sensusultra_device_t *device, unsigned
|
||||
static dc_status_t
|
||||
reefnet_sensusultra_packet (reefnet_sensusultra_device_t *device, unsigned char *data, unsigned int size, unsigned int header)
|
||||
{
|
||||
assert (size >= header + 2);
|
||||
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
assert (size >= header + 2);
|
||||
|
||||
if (device_is_cancelled (abstract))
|
||||
return DC_STATUS_CANCELLED;
|
||||
|
||||
// Receive the data packet.
|
||||
int rc = serial_read (device->port, data, size);
|
||||
if (rc != size) {
|
||||
status = dc_serial_read (device->port, data, size, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the packet.");
|
||||
return EXITCODE (rc);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the checksum of the packet.
|
||||
@ -349,7 +346,7 @@ static dc_status_t
|
||||
reefnet_sensusultra_send (reefnet_sensusultra_device_t *device, unsigned short command)
|
||||
{
|
||||
// Flush the input and output buffers.
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
// Wake-up the device and send the instruction code.
|
||||
unsigned int nretries = 0;
|
||||
@ -369,8 +366,8 @@ reefnet_sensusultra_send (reefnet_sensusultra_device_t *device, unsigned short c
|
||||
// not accidentally buffered by the host and (mis)interpreted as part
|
||||
// of the next packet.
|
||||
|
||||
serial_sleep (device->port, 250);
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_sleep (device->port, 250);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
334
src/serial.h
334
src/serial.h
@ -19,101 +19,303 @@
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SERIAL_H
|
||||
#define SERIAL_H
|
||||
#ifndef DC_SERIAL_H
|
||||
#define DC_SERIAL_H
|
||||
|
||||
#include <libdivecomputer/common.h>
|
||||
#include <libdivecomputer/context.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct serial_t serial_t;
|
||||
/**
|
||||
* Opaque object representing a serial connection.
|
||||
*/
|
||||
typedef struct dc_serial_t dc_serial_t;
|
||||
|
||||
typedef enum serial_parity_t {
|
||||
SERIAL_PARITY_NONE,
|
||||
SERIAL_PARITY_EVEN,
|
||||
SERIAL_PARITY_ODD
|
||||
} serial_parity_t;
|
||||
/**
|
||||
* The parity checking scheme.
|
||||
*/
|
||||
typedef enum dc_parity_t {
|
||||
DC_PARITY_NONE, /**< No parity */
|
||||
DC_PARITY_ODD, /**< Odd parity */
|
||||
DC_PARITY_EVEN, /**< Even parity */
|
||||
DC_PARITY_MARK, /**< Mark parity (always 1) */
|
||||
DC_PARITY_SPACE /**< Space parity (alwasy 0) */
|
||||
} dc_parity_t;
|
||||
|
||||
typedef enum serial_flowcontrol_t {
|
||||
SERIAL_FLOWCONTROL_NONE,
|
||||
SERIAL_FLOWCONTROL_HARDWARE,
|
||||
SERIAL_FLOWCONTROL_SOFTWARE
|
||||
} serial_flowcontrol_t;
|
||||
/**
|
||||
* The number of stop bits.
|
||||
*/
|
||||
typedef enum dc_stopbits_t {
|
||||
DC_STOPBITS_ONE, /**< 1 stop bit */
|
||||
DC_STOPBITS_ONEPOINTFIVE, /**< 1.5 stop bits*/
|
||||
DC_STOPBITS_TWO /**< 2 stop bits */
|
||||
} dc_stopbits_t;
|
||||
|
||||
typedef enum serial_queue_t {
|
||||
SERIAL_QUEUE_INPUT = 0x01,
|
||||
SERIAL_QUEUE_OUTPUT = 0x02,
|
||||
SERIAL_QUEUE_BOTH = SERIAL_QUEUE_INPUT | SERIAL_QUEUE_OUTPUT
|
||||
} serial_queue_t;
|
||||
/**
|
||||
* The flow control.
|
||||
*/
|
||||
typedef enum dc_flowcontrol_t {
|
||||
DC_FLOWCONTROL_NONE, /**< No flow control */
|
||||
DC_FLOWCONTROL_HARDWARE, /**< Hardware (RTS/CTS) flow control */
|
||||
DC_FLOWCONTROL_SOFTWARE /**< Software (XON/XOFF) flow control */
|
||||
} dc_flowcontrol_t;
|
||||
|
||||
typedef enum serial_line_t {
|
||||
SERIAL_LINE_DCD, // Data carrier detect
|
||||
SERIAL_LINE_CTS, // Clear to send
|
||||
SERIAL_LINE_DSR, // Data set ready
|
||||
SERIAL_LINE_RNG, // Ring indicator
|
||||
} serial_line_t;
|
||||
/**
|
||||
* The direction of the data transmission.
|
||||
*/
|
||||
typedef enum dc_direction_t {
|
||||
DC_DIRECTION_INPUT = 0x01, /**< Input direction */
|
||||
DC_DIRECTION_OUTPUT = 0x02, /**< Output direction */
|
||||
DC_DIRECTION_ALL = DC_DIRECTION_INPUT | DC_DIRECTION_OUTPUT /**< All directions */
|
||||
} dc_direction_t;
|
||||
|
||||
typedef void (*serial_callback_t) (const char *name, void *userdata);
|
||||
/**
|
||||
* The serial line signals.
|
||||
*/
|
||||
typedef enum dc_line_t {
|
||||
DC_LINE_DCD = 0x01, /**< Data carrier detect */
|
||||
DC_LINE_CTS = 0x02, /**< Clear to send */
|
||||
DC_LINE_DSR = 0x04, /**< Data set ready */
|
||||
DC_LINE_RNG = 0x08, /**< Ring indicator */
|
||||
} dc_line_t;
|
||||
|
||||
int serial_enumerate (serial_callback_t callback, void *userdata);
|
||||
/**
|
||||
* Serial enumeration callback.
|
||||
*
|
||||
* @param[in] name The name of the device node.
|
||||
* @param[in] userdata The user data pointer.
|
||||
*/
|
||||
typedef void (*dc_serial_callback_t) (const char *name, void *userdata);
|
||||
|
||||
int serial_open (serial_t **device, dc_context_t *context, const char* name);
|
||||
/**
|
||||
* Enumerate the serial ports.
|
||||
*
|
||||
* @param[in] callback The callback function to call.
|
||||
* @param[in] userdata User data to pass to the callback function.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_serial_enumerate (dc_serial_callback_t callback, void *userdata);
|
||||
|
||||
int serial_close (serial_t *device);
|
||||
/**
|
||||
* Open a serial connection.
|
||||
*
|
||||
* @param[out] serial A location to store the serial connection.
|
||||
* @param[in] context A valid context object.
|
||||
* @param[in] name The name of the device node.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_serial_open (dc_serial_t **serial, dc_context_t *context, const char *name);
|
||||
|
||||
int serial_configure (serial_t *device, int baudrate, int databits, int parity, int stopbits, int flowcontrol);
|
||||
/**
|
||||
* Close the serial connection and free all resources.
|
||||
*
|
||||
* @param[in] serial A valid serial connection.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_serial_close (dc_serial_t *serial);
|
||||
|
||||
//
|
||||
// Available read modes:
|
||||
//
|
||||
// * Blocking (timeout < 0):
|
||||
//
|
||||
// The read function is blocked until all the requested bytes have
|
||||
// been received. If the requested number of bytes does not arrive,
|
||||
// the function will block forever.
|
||||
//
|
||||
// * Non-blocking (timeout == 0):
|
||||
//
|
||||
// The read function returns immediately with the bytes that have already
|
||||
// been received, even if no bytes have been received.
|
||||
//
|
||||
// * Timeout (timeout > 0):
|
||||
//
|
||||
// The read function is blocked until all the requested bytes have
|
||||
// been received. If the requested number of bytes does not arrive
|
||||
// within the specified amount of time, the function will return
|
||||
// with the bytes that have already been received.
|
||||
//
|
||||
/**
|
||||
* Configure the serial line settings of the connection.
|
||||
*
|
||||
* @param[in] serial A valid serial connection.
|
||||
* @param[in] baudrate The baud rate setting.
|
||||
* @param[in] databits The number of data bits.
|
||||
* @param[in] parity The parity setting.
|
||||
* @param[in] stopbits The number of stop bits.
|
||||
* @param[in] flowcontrol The flow control setting.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_serial_configure (dc_serial_t *serial, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
|
||||
|
||||
int serial_set_timeout (serial_t *device, long timeout /* milliseconds */);
|
||||
/**
|
||||
* Set the read timeout.
|
||||
*
|
||||
* There are three distinct modes available:
|
||||
*
|
||||
* 1. Blocking (timeout < 0):
|
||||
*
|
||||
* The read operation is blocked until all the requested bytes have
|
||||
* been received. If the requested number of bytes does not arrive,
|
||||
* the operation will block forever.
|
||||
*
|
||||
* 2. Non-blocking (timeout == 0):
|
||||
*
|
||||
* The read operation returns immediately with the bytes that have
|
||||
* already been received, even if no bytes have been received.
|
||||
*
|
||||
* 3. Timeout (timeout > 0):
|
||||
*
|
||||
* The read operation is blocked until all the requested bytes have
|
||||
* been received. If the requested number of bytes does not arrive
|
||||
* within the specified amount of time, the operation will return
|
||||
* with the bytes that have already been received.
|
||||
*
|
||||
* @param[in] serial A valid serial connection.
|
||||
* @param[in] timeout The timeout in milliseconds.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_serial_set_timeout (dc_serial_t *serial, int timeout);
|
||||
|
||||
int serial_set_queue_size (serial_t *device, unsigned int input, unsigned int output);
|
||||
/**
|
||||
* Set the state of the half duplex emulation.
|
||||
*
|
||||
* @param[in] serial A valid serial connection.
|
||||
* @param[in] value The half duplex state.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_serial_set_halfduplex (dc_serial_t *serial, unsigned int value);
|
||||
|
||||
int serial_set_halfduplex (serial_t *device, int value);
|
||||
/**
|
||||
* Set the receive latency.
|
||||
*
|
||||
* The effect of this setting is highly platform and driver specific. On
|
||||
* Windows it does nothing at all, on Linux it controls the low latency
|
||||
* flag (e.g. only zero vs non-zero latency), and on Mac OS X it sets
|
||||
* the receive latency as requested.
|
||||
*
|
||||
* @param[in] serial A valid serial connection.
|
||||
* @param[in] value The latency in milliseconds.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_serial_set_latency (dc_serial_t *serial, unsigned int value);
|
||||
|
||||
int serial_set_latency (serial_t *device, unsigned int milliseconds);
|
||||
/**
|
||||
* Read data from the serial connection.
|
||||
*
|
||||
* @param[in] serial A valid serial connection.
|
||||
* @param[out] data The memory buffer to read the data into.
|
||||
* @param[in] size The number of bytes to read.
|
||||
* @param[out] actual An (optional) location to store the actual
|
||||
* number of bytes transferred.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_serial_read (dc_serial_t *serial, void *data, size_t size, size_t *actual);
|
||||
|
||||
int serial_read (serial_t *device, void* data, unsigned int size);
|
||||
int serial_write (serial_t *device, const void* data, unsigned int size);
|
||||
/**
|
||||
* Write data to the serial connection.
|
||||
*
|
||||
* @param[in] serial A valid serial connection.
|
||||
* @param[in] data The memory buffer to write the data from.
|
||||
* @param[in] size The number of bytes to write.
|
||||
* @param[out] actual An (optional) location to store the actual
|
||||
* number of bytes transferred.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_serial_write (dc_serial_t *serial, const void *data, size_t size, size_t *actual);
|
||||
|
||||
int serial_flush (serial_t *device, int queue);
|
||||
/**
|
||||
* Flush the internal output buffer and wait until the data has been
|
||||
* transmitted.
|
||||
*
|
||||
* @param[in] serial A valid serial connection.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_serial_flush (dc_serial_t *serial);
|
||||
|
||||
int serial_send_break (serial_t *device);
|
||||
/**
|
||||
* Discards all data from the internal buffers.
|
||||
*
|
||||
* @param[in] serial A valid serial connection.
|
||||
* @param[in] direction The direction of the buffer(s).
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_serial_purge (dc_serial_t *serial, dc_direction_t direction);
|
||||
|
||||
int serial_set_break (serial_t *device, int level);
|
||||
int serial_set_dtr (serial_t *device, int level);
|
||||
int serial_set_rts (serial_t *device, int level);
|
||||
/**
|
||||
* Set the state of the break condition.
|
||||
*
|
||||
* @param[in] serial A valid serial connection.
|
||||
* @param[in] value The break condition state.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_serial_set_break (dc_serial_t *serial, unsigned int value);
|
||||
|
||||
int serial_get_received (serial_t *device);
|
||||
int serial_get_transmitted (serial_t *device);
|
||||
/**
|
||||
* Set the state of the DTR line.
|
||||
*
|
||||
* @param[in] serial A valid serial connection.
|
||||
* @param[in] value The DTR line state.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_serial_set_dtr (dc_serial_t *serial, unsigned int value);
|
||||
|
||||
int serial_get_line (serial_t *device, int line);
|
||||
/**
|
||||
* Set the state of the RTS line.
|
||||
*
|
||||
* @param[in] serial A valid serial connection.
|
||||
* @param[in] value The RTS line state.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_serial_set_rts (dc_serial_t *serial, unsigned int value);
|
||||
|
||||
int serial_sleep (serial_t *device, unsigned long timeout /* milliseconds */);
|
||||
/**
|
||||
* Query the number of available bytes in the input buffer.
|
||||
*
|
||||
* @param[in] serial A valid serial connection.
|
||||
* @param[out] value A location to store the number of bytes in the
|
||||
* input buffer.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_serial_get_available (dc_serial_t *serial, size_t *value);
|
||||
|
||||
/**
|
||||
* Query the state of the line signals.
|
||||
*
|
||||
* @param[in] serial A valid serial connection.
|
||||
* @param[out] value A location to store the bitmap with the state of
|
||||
* the line signals.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_serial_get_lines (dc_serial_t *serial, unsigned int *value);
|
||||
|
||||
/**
|
||||
* Suspend execution of the current thread for the specified amount of
|
||||
* time.
|
||||
*
|
||||
* @param[in] serial A valid serial connection.
|
||||
* @param[in] milliseconds The number of milliseconds to sleep.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_serial_sleep (dc_serial_t *serial, unsigned int milliseconds);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* SERIAL_H */
|
||||
#endif /* DC_SERIAL_H */
|
||||
|
||||
@ -54,16 +54,17 @@
|
||||
#endif
|
||||
|
||||
#include "serial.h"
|
||||
#include "common-private.h"
|
||||
#include "context-private.h"
|
||||
|
||||
struct serial_t {
|
||||
struct dc_serial_t {
|
||||
/* Library context. */
|
||||
dc_context_t *context;
|
||||
/*
|
||||
* The file descriptor corresponding to the serial port.
|
||||
*/
|
||||
int fd;
|
||||
long timeout;
|
||||
int timeout;
|
||||
/*
|
||||
* Serial port settings are saved into this variable immediately
|
||||
* after the port is opened. These settings are restored when the
|
||||
@ -77,8 +78,8 @@ struct serial_t {
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
serial_enumerate (serial_callback_t callback, void *userdata)
|
||||
dc_status_t
|
||||
dc_serial_enumerate (dc_serial_callback_t callback, void *userdata)
|
||||
{
|
||||
DIR *dp = NULL;
|
||||
struct dirent *ep = NULL;
|
||||
@ -97,7 +98,7 @@ serial_enumerate (serial_callback_t callback, void *userdata)
|
||||
|
||||
dp = opendir (dirname);
|
||||
if (dp == NULL) {
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
while ((ep = readdir (dp)) != NULL) {
|
||||
@ -107,7 +108,7 @@ serial_enumerate (serial_callback_t callback, void *userdata)
|
||||
int n = snprintf (filename, sizeof (filename), "%s/%s", dirname, ep->d_name);
|
||||
if (n >= sizeof (filename)) {
|
||||
closedir (dp);
|
||||
return -1;
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
callback (filename, userdata);
|
||||
@ -118,27 +119,24 @@ serial_enumerate (serial_callback_t callback, void *userdata)
|
||||
|
||||
closedir (dp);
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Open the serial port.
|
||||
//
|
||||
|
||||
int
|
||||
serial_open (serial_t **out, dc_context_t *context, const char* name)
|
||||
dc_status_t
|
||||
dc_serial_open (dc_serial_t **out, dc_context_t *context, const char *name)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
|
||||
if (out == NULL)
|
||||
return -1; // EINVAL (Invalid argument)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
INFO (context, "Open: name=%s", name ? name : "");
|
||||
|
||||
// Allocate memory.
|
||||
serial_t *device = (serial_t *) malloc (sizeof (serial_t));
|
||||
dc_serial_t *device = (dc_serial_t *) malloc (sizeof (dc_serial_t));
|
||||
if (device == NULL) {
|
||||
SYSERROR (context, ENOMEM);
|
||||
return -1; // ENOMEM (Not enough space)
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
// Library context.
|
||||
@ -157,6 +155,7 @@ serial_open (serial_t **out, dc_context_t *context, const char* name)
|
||||
device->fd = open (name, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||
if (device->fd == -1) {
|
||||
SYSERROR (context, errno);
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
@ -164,6 +163,7 @@ serial_open (serial_t **out, dc_context_t *context, const char* name)
|
||||
// Enable exclusive access mode.
|
||||
if (ioctl (device->fd, TIOCEXCL, NULL) != 0) {
|
||||
SYSERROR (context, errno);
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
#endif
|
||||
@ -174,36 +174,33 @@ serial_open (serial_t **out, dc_context_t *context, const char* name)
|
||||
// file descriptor represents a terminal device.
|
||||
if (tcgetattr (device->fd, &device->tty) != 0) {
|
||||
SYSERROR (context, errno);
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
*out = device;
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
close (device->fd);
|
||||
error_free:
|
||||
free (device);
|
||||
return -1;
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Close the serial port.
|
||||
//
|
||||
|
||||
int
|
||||
serial_close (serial_t *device)
|
||||
dc_status_t
|
||||
dc_serial_close (dc_serial_t *device)
|
||||
{
|
||||
int errcode = 0;
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
|
||||
if (device == NULL)
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
// Restore the initial terminal attributes.
|
||||
if (tcsetattr (device->fd, TCSANOW, &device->tty) != 0) {
|
||||
SYSERROR (device->context, errno);
|
||||
errcode = -1;
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
}
|
||||
|
||||
#ifndef ENABLE_PTY
|
||||
@ -214,24 +211,20 @@ serial_close (serial_t *device)
|
||||
// Close the device.
|
||||
if (close (device->fd) != 0) {
|
||||
SYSERROR (device->context, errno);
|
||||
errcode = -1;
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
}
|
||||
|
||||
// Free memory.
|
||||
free (device);
|
||||
|
||||
return errcode;
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Configure the serial port (baudrate, databits, parity, stopbits and flowcontrol).
|
||||
//
|
||||
|
||||
int
|
||||
serial_configure (serial_t *device, int baudrate, int databits, int parity, int stopbits, int flowcontrol)
|
||||
dc_status_t
|
||||
dc_serial_configure (dc_serial_t *device, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // EINVAL (Invalid argument)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
INFO (device->context, "Configure: baudrate=%i, databits=%i, parity=%i, stopbits=%i, flowcontrol=%i",
|
||||
baudrate, databits, parity, stopbits, flowcontrol);
|
||||
@ -241,7 +234,7 @@ serial_configure (serial_t *device, int baudrate, int databits, int parity, int
|
||||
memset (&tty, 0, sizeof (tty));
|
||||
if (tcgetattr (device->fd, &tty) != 0) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
// Setup raw input/output mode without echo.
|
||||
@ -337,7 +330,7 @@ serial_configure (serial_t *device, int baudrate, int databits, int parity, int
|
||||
if (cfsetispeed (&tty, baud) != 0 ||
|
||||
cfsetospeed (&tty, baud) != 0) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
// Set the character size.
|
||||
@ -356,70 +349,70 @@ serial_configure (serial_t *device, int baudrate, int databits, int parity, int
|
||||
tty.c_cflag |= CS8;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
}
|
||||
|
||||
// Set the parity type.
|
||||
tty.c_cflag &= ~(PARENB | PARODD);
|
||||
tty.c_iflag &= ~(IGNPAR | PARMRK | INPCK);
|
||||
switch (parity) {
|
||||
case SERIAL_PARITY_NONE: // No parity
|
||||
case DC_PARITY_NONE:
|
||||
tty.c_iflag |= IGNPAR;
|
||||
break;
|
||||
case SERIAL_PARITY_EVEN: // Even parity
|
||||
case DC_PARITY_EVEN:
|
||||
tty.c_cflag |= PARENB;
|
||||
tty.c_iflag |= INPCK;
|
||||
break;
|
||||
case SERIAL_PARITY_ODD: // Odd parity
|
||||
case DC_PARITY_ODD:
|
||||
tty.c_cflag |= (PARENB | PARODD);
|
||||
tty.c_iflag |= INPCK;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
}
|
||||
|
||||
// Set the number of stop bits.
|
||||
switch (stopbits) {
|
||||
case 1: // One stopbit
|
||||
case DC_STOPBITS_ONE:
|
||||
tty.c_cflag &= ~CSTOPB;
|
||||
break;
|
||||
case 2: // Two stopbits
|
||||
case DC_STOPBITS_TWO:
|
||||
tty.c_cflag |= CSTOPB;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
}
|
||||
|
||||
// Set the flow control.
|
||||
switch (flowcontrol) {
|
||||
case SERIAL_FLOWCONTROL_NONE: // No flow control.
|
||||
case DC_FLOWCONTROL_NONE:
|
||||
#ifdef CRTSCTS
|
||||
tty.c_cflag &= ~CRTSCTS;
|
||||
#endif
|
||||
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
|
||||
break;
|
||||
case SERIAL_FLOWCONTROL_HARDWARE: // Hardware (RTS/CTS) flow control.
|
||||
case DC_FLOWCONTROL_HARDWARE:
|
||||
#ifdef CRTSCTS
|
||||
tty.c_cflag |= CRTSCTS;
|
||||
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
|
||||
break;
|
||||
#else
|
||||
return -1; // Hardware flow control is unsupported.
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
case SERIAL_FLOWCONTROL_SOFTWARE: // Software (XON/XOFF) flow control.
|
||||
case DC_FLOWCONTROL_SOFTWARE:
|
||||
#ifdef CRTSCTS
|
||||
tty.c_cflag &= ~CRTSCTS;
|
||||
#endif
|
||||
tty.c_iflag |= (IXON | IXOFF);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
}
|
||||
|
||||
// Apply the new settings.
|
||||
if (tcsetattr (device->fd, TCSANOW, &tty) != 0 && NOPTY) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
// Configure a custom baudrate if necessary.
|
||||
@ -429,7 +422,7 @@ serial_configure (serial_t *device, int baudrate, int databits, int parity, int
|
||||
struct serial_struct ss;
|
||||
if (ioctl (device->fd, TIOCGSERIAL, &ss) != 0 && NOPTY) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
// Set the custom divisor.
|
||||
@ -440,81 +433,62 @@ serial_configure (serial_t *device, int baudrate, int databits, int parity, int
|
||||
// Apply the new settings.
|
||||
if (ioctl (device->fd, TIOCSSERIAL, &ss) != 0 && NOPTY) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
#elif defined(IOSSIOSPEED)
|
||||
speed_t speed = baudrate;
|
||||
if (ioctl (device->fd, IOSSIOSPEED, &speed) != 0 && NOPTY) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
#else
|
||||
// Custom baudrates are not supported.
|
||||
return -1;
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
device->baudrate = baudrate;
|
||||
device->nbits = 1 + databits + stopbits + (parity ? 1 : 0);
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Configure the serial port (timeouts).
|
||||
//
|
||||
|
||||
int
|
||||
serial_set_timeout (serial_t *device, long timeout)
|
||||
dc_status_t
|
||||
dc_serial_set_timeout (dc_serial_t *device, int timeout)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // EINVAL (Invalid argument)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
INFO (device->context, "Timeout: value=%li", timeout);
|
||||
INFO (device->context, "Timeout: value=%i", timeout);
|
||||
|
||||
device->timeout = timeout;
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Configure the serial port (recommended size of the input/output buffers).
|
||||
//
|
||||
|
||||
int
|
||||
serial_set_queue_size (serial_t *device, unsigned int input, unsigned int output)
|
||||
dc_status_t
|
||||
dc_serial_set_halfduplex (dc_serial_t *device, unsigned int value)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // ERROR_INVALID_PARAMETER (The parameter is incorrect)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_set_halfduplex (serial_t *device, int value)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // EINVAL (Invalid argument)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
device->halfduplex = value;
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
serial_set_latency (serial_t *device, unsigned int milliseconds)
|
||||
dc_status_t
|
||||
dc_serial_set_latency (dc_serial_t *device, unsigned int milliseconds)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // EINVAL (Invalid argument)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
#if defined(TIOCGSERIAL) && defined(TIOCSSERIAL) && !defined(__ANDROID__)
|
||||
// Get the current settings.
|
||||
struct serial_struct ss;
|
||||
if (ioctl (device->fd, TIOCGSERIAL, &ss) != 0 && NOPTY) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
// Set or clear the low latency flag.
|
||||
@ -527,7 +501,7 @@ serial_set_latency (serial_t *device, unsigned int milliseconds)
|
||||
// Apply the new settings.
|
||||
if (ioctl (device->fd, TIOCSSERIAL, &ss) != 0 && NOPTY) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
#elif defined(IOSSDATALAT)
|
||||
// Set the receive latency in microseconds. Serial drivers use this
|
||||
@ -536,27 +510,31 @@ serial_set_latency (serial_t *device, unsigned int milliseconds)
|
||||
unsigned long usec = (milliseconds == 0 ? 1 : milliseconds * 1000);
|
||||
if (ioctl (device->fd, IOSSDATALAT, &usec) != 0 && NOPTY) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
serial_read (serial_t *device, void *data, unsigned int size)
|
||||
dc_status_t
|
||||
dc_serial_read (dc_serial_t *device, void *data, size_t size, size_t *actual)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // EINVAL (Invalid argument)
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
size_t nbytes = 0;
|
||||
|
||||
if (device == NULL) {
|
||||
status = DC_STATUS_INVALIDARGS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// The total timeout.
|
||||
long timeout = device->timeout;
|
||||
int timeout = device->timeout;
|
||||
|
||||
// The absolute target time.
|
||||
struct timeval tve;
|
||||
|
||||
int init = 1;
|
||||
unsigned int nbytes = 0;
|
||||
while (nbytes < size) {
|
||||
fd_set fds;
|
||||
FD_ZERO (&fds);
|
||||
@ -567,7 +545,8 @@ serial_read (serial_t *device, void *data, unsigned int size)
|
||||
struct timeval now;
|
||||
if (gettimeofday (&now, NULL) != 0) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
status = DC_STATUS_IO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (init) {
|
||||
@ -593,17 +572,19 @@ serial_read (serial_t *device, void *data, unsigned int size)
|
||||
if (errno == EINTR)
|
||||
continue; // Retry.
|
||||
SYSERROR (device->context, errno);
|
||||
return -1; // Error during select call.
|
||||
status = DC_STATUS_IO;
|
||||
goto out;
|
||||
} else if (rc == 0) {
|
||||
break; // Timeout.
|
||||
}
|
||||
|
||||
int n = read (device->fd, (char *) data + nbytes, size - nbytes);
|
||||
ssize_t n = read (device->fd, (char *) data + nbytes, size - nbytes);
|
||||
if (n < 0) {
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
continue; // Retry.
|
||||
SYSERROR (device->context, errno);
|
||||
return -1; // Error during read call.
|
||||
status = DC_STATUS_IO;
|
||||
goto out;
|
||||
} else if (n == 0) {
|
||||
break; // EOF.
|
||||
}
|
||||
@ -611,28 +592,40 @@ serial_read (serial_t *device, void *data, unsigned int size)
|
||||
nbytes += n;
|
||||
}
|
||||
|
||||
if (nbytes != size) {
|
||||
status = DC_STATUS_TIMEOUT;
|
||||
}
|
||||
|
||||
out:
|
||||
HEXDUMP (device->context, DC_LOGLEVEL_INFO, "Read", (unsigned char *) data, nbytes);
|
||||
|
||||
return nbytes;
|
||||
if (actual)
|
||||
*actual = nbytes;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_write (serial_t *device, const void *data, unsigned int size)
|
||||
dc_status_t
|
||||
dc_serial_write (dc_serial_t *device, const void *data, size_t size, size_t *actual)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // EINVAL (Invalid argument)
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
size_t nbytes = 0;
|
||||
|
||||
if (device == NULL) {
|
||||
status = DC_STATUS_INVALIDARGS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
struct timeval tve, tvb;
|
||||
if (device->halfduplex) {
|
||||
// Get the current time.
|
||||
if (gettimeofday (&tvb, NULL) != 0) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
status = DC_STATUS_IO;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int nbytes = 0;
|
||||
while (nbytes < size) {
|
||||
fd_set fds;
|
||||
FD_ZERO (&fds);
|
||||
@ -643,17 +636,19 @@ serial_write (serial_t *device, const void *data, unsigned int size)
|
||||
if (errno == EINTR)
|
||||
continue; // Retry.
|
||||
SYSERROR (device->context, errno);
|
||||
return -1; // Error during select call.
|
||||
status = DC_STATUS_IO;
|
||||
goto out;
|
||||
} else if (rc == 0) {
|
||||
break; // Timeout.
|
||||
}
|
||||
|
||||
int n = write (device->fd, (char *) data + nbytes, size - nbytes);
|
||||
ssize_t n = write (device->fd, (const char *) data + nbytes, size - nbytes);
|
||||
if (n < 0) {
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
continue; // Retry.
|
||||
SYSERROR (device->context, errno);
|
||||
return -1; // Error during write call.
|
||||
status = DC_STATUS_IO;
|
||||
goto out;
|
||||
} else if (n == 0) {
|
||||
break; // EOF.
|
||||
}
|
||||
@ -670,7 +665,8 @@ serial_write (serial_t *device, const void *data, unsigned int size)
|
||||
#endif
|
||||
if (errno != EINTR ) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
status = DC_STATUS_IO;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@ -678,7 +674,8 @@ serial_write (serial_t *device, const void *data, unsigned int size)
|
||||
// Get the current time.
|
||||
if (gettimeofday (&tve, NULL) != 0) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
status = DC_STATUS_IO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Calculate the elapsed time (microseconds).
|
||||
@ -697,69 +694,67 @@ serial_write (serial_t *device, const void *data, unsigned int size)
|
||||
// The remaining time is rounded up to the nearest millisecond to
|
||||
// match the Windows implementation. The higher resolution is
|
||||
// pointless anyway, since we already added a fudge factor above.
|
||||
serial_sleep (device, (remaining + 999) / 1000);
|
||||
dc_serial_sleep (device, (remaining + 999) / 1000);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
HEXDUMP (device->context, DC_LOGLEVEL_INFO, "Write", (unsigned char *) data, nbytes);
|
||||
|
||||
return nbytes;
|
||||
if (actual)
|
||||
*actual = nbytes;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_flush (serial_t *device, int queue)
|
||||
dc_status_t
|
||||
dc_serial_purge (dc_serial_t *device, dc_direction_t direction)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // EINVAL (Invalid argument)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
INFO (device->context, "Flush: queue=%u, input=%i, output=%i", queue,
|
||||
serial_get_received (device),
|
||||
serial_get_transmitted (device));
|
||||
INFO (device->context, "Purge: direction=%u", direction);
|
||||
|
||||
int flags = 0;
|
||||
|
||||
switch (queue) {
|
||||
case SERIAL_QUEUE_INPUT:
|
||||
switch (direction) {
|
||||
case DC_DIRECTION_INPUT:
|
||||
flags = TCIFLUSH;
|
||||
break;
|
||||
case SERIAL_QUEUE_OUTPUT:
|
||||
case DC_DIRECTION_OUTPUT:
|
||||
flags = TCOFLUSH;
|
||||
break;
|
||||
default:
|
||||
case DC_DIRECTION_ALL:
|
||||
flags = TCIOFLUSH;
|
||||
break;
|
||||
default:
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
}
|
||||
|
||||
if (tcflush (device->fd, flags) != 0) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_send_break (serial_t *device)
|
||||
dc_status_t
|
||||
dc_serial_flush (dc_serial_t *device)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // EINVAL (Invalid argument)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
if (tcsendbreak (device->fd, 0) != 0) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
INFO (device->context, "Flush: none");
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_set_break (serial_t *device, int level)
|
||||
dc_status_t
|
||||
dc_serial_set_break (dc_serial_t *device, unsigned int level)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // EINVAL (Invalid argument)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
INFO (device->context, "Break: value=%i", level);
|
||||
|
||||
@ -767,18 +762,17 @@ serial_set_break (serial_t *device, int level)
|
||||
|
||||
if (ioctl (device->fd, action, NULL) != 0 && NOPTY) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_set_dtr (serial_t *device, int level)
|
||||
dc_status_t
|
||||
dc_serial_set_dtr (dc_serial_t *device, unsigned int level)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // EINVAL (Invalid argument)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
INFO (device->context, "DTR: value=%i", level);
|
||||
|
||||
@ -787,18 +781,17 @@ serial_set_dtr (serial_t *device, int level)
|
||||
int value = TIOCM_DTR;
|
||||
if (ioctl (device->fd, action, &value) != 0 && NOPTY) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_set_rts (serial_t *device, int level)
|
||||
dc_status_t
|
||||
dc_serial_set_rts (dc_serial_t *device, unsigned int level)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // EINVAL (Invalid argument)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
INFO (device->context, "RTS: value=%i", level);
|
||||
|
||||
@ -807,81 +800,66 @@ serial_set_rts (serial_t *device, int level)
|
||||
int value = TIOCM_RTS;
|
||||
if (ioctl (device->fd, action, &value) != 0 && NOPTY) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_get_received (serial_t *device)
|
||||
dc_status_t
|
||||
dc_serial_get_available (dc_serial_t *device, size_t *value)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // EINVAL (Invalid argument)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
int bytes = 0;
|
||||
if (ioctl (device->fd, TIOCINQ, &bytes) != 0) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
if (value)
|
||||
*value = bytes;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_get_transmitted (serial_t *device)
|
||||
dc_status_t
|
||||
dc_serial_get_lines (dc_serial_t *device, unsigned int *value)
|
||||
{
|
||||
unsigned int lines = 0;
|
||||
|
||||
if (device == NULL)
|
||||
return -1; // EINVAL (Invalid argument)
|
||||
|
||||
int bytes = 0;
|
||||
if (ioctl (device->fd, TIOCOUTQ, &bytes) != 0) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_get_line (serial_t *device, int line)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // EINVAL (Invalid argument)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
int status = 0;
|
||||
if (ioctl (device->fd, TIOCMGET, &status) != 0) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
switch (line) {
|
||||
case SERIAL_LINE_DCD:
|
||||
return (status & TIOCM_CAR) == TIOCM_CAR;
|
||||
case SERIAL_LINE_CTS:
|
||||
return (status & TIOCM_CTS) == TIOCM_CTS;
|
||||
case SERIAL_LINE_DSR:
|
||||
return (status & TIOCM_DSR) == TIOCM_DSR;
|
||||
case SERIAL_LINE_RNG:
|
||||
return (status & TIOCM_RNG) == TIOCM_RNG;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
if (status & TIOCM_CAR)
|
||||
lines |= DC_LINE_DCD;
|
||||
if (status & TIOCM_CTS)
|
||||
lines |= DC_LINE_CTS;
|
||||
if (status & TIOCM_DSR)
|
||||
lines |= DC_LINE_DSR;
|
||||
if (status & TIOCM_RNG)
|
||||
lines |= DC_LINE_RNG;
|
||||
|
||||
return 0;
|
||||
if (value)
|
||||
*value = lines;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_sleep (serial_t *device, unsigned long timeout)
|
||||
dc_status_t
|
||||
dc_serial_sleep (dc_serial_t *device, unsigned int timeout)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1;
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
INFO (device->context, "Sleep: value=%lu", timeout);
|
||||
INFO (device->context, "Sleep: value=%u", timeout);
|
||||
|
||||
struct timespec ts;
|
||||
ts.tv_sec = (timeout / 1000);
|
||||
@ -890,9 +868,9 @@ serial_sleep (serial_t *device, unsigned long timeout)
|
||||
while (nanosleep (&ts, &ts) != 0) {
|
||||
if (errno != EINTR ) {
|
||||
SYSERROR (device->context, errno);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -25,9 +25,10 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include "serial.h"
|
||||
#include "common-private.h"
|
||||
#include "context-private.h"
|
||||
|
||||
struct serial_t {
|
||||
struct dc_serial_t {
|
||||
/* Library context. */
|
||||
dc_context_t *context;
|
||||
/*
|
||||
@ -47,17 +48,17 @@ struct serial_t {
|
||||
unsigned int nbits;
|
||||
};
|
||||
|
||||
int
|
||||
serial_enumerate (serial_callback_t callback, void *userdata)
|
||||
dc_status_t
|
||||
dc_serial_enumerate (dc_serial_callback_t callback, void *userdata)
|
||||
{
|
||||
// Open the registry key.
|
||||
HKEY hKey;
|
||||
LONG rc = RegOpenKeyExA (HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &hKey);
|
||||
if (rc != ERROR_SUCCESS) {
|
||||
if (rc == ERROR_FILE_NOT_FOUND)
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
else
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
// Get the number of values.
|
||||
@ -65,7 +66,7 @@ serial_enumerate (serial_callback_t callback, void *userdata)
|
||||
rc = RegQueryInfoKey (hKey, NULL, NULL, NULL, NULL, NULL, NULL, &count, NULL, NULL, NULL, NULL);
|
||||
if (rc != ERROR_SUCCESS) {
|
||||
RegCloseKey(hKey);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
for (DWORD i = 0; i < count; ++i) {
|
||||
@ -77,7 +78,7 @@ serial_enumerate (serial_callback_t callback, void *userdata)
|
||||
rc = RegEnumValueA (hKey, i, name, &name_len, NULL, &type, (LPBYTE) data, &data_len);
|
||||
if (rc != ERROR_SUCCESS) {
|
||||
RegCloseKey(hKey);
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
// Ignore non-string values.
|
||||
@ -87,7 +88,7 @@ serial_enumerate (serial_callback_t callback, void *userdata)
|
||||
// Prevent a possible buffer overflow.
|
||||
if (data_len >= sizeof (data)) {
|
||||
RegCloseKey(hKey);
|
||||
return -1;
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
// Null terminate the string.
|
||||
@ -98,18 +99,16 @@ serial_enumerate (serial_callback_t callback, void *userdata)
|
||||
|
||||
RegCloseKey(hKey);
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Open the serial port.
|
||||
//
|
||||
|
||||
int
|
||||
serial_open (serial_t **out, dc_context_t *context, const char* name)
|
||||
dc_status_t
|
||||
dc_serial_open (dc_serial_t **out, dc_context_t *context, const char *name)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
|
||||
if (out == NULL)
|
||||
return -1; // ERROR_INVALID_PARAMETER (The parameter is incorrect)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
INFO (context, "Open: name=%s", name ? name : "");
|
||||
|
||||
@ -119,7 +118,7 @@ serial_open (serial_t **out, dc_context_t *context, const char* name)
|
||||
if (name && strncmp (name, buffer, 4) != 0) {
|
||||
size_t length = strlen (name) + 1;
|
||||
if (length + 4 > sizeof (buffer))
|
||||
return -1;
|
||||
return DC_STATUS_NOMEMORY;
|
||||
memcpy (buffer + 4, name, length);
|
||||
devname = buffer;
|
||||
} else {
|
||||
@ -127,10 +126,10 @@ serial_open (serial_t **out, dc_context_t *context, const char* name)
|
||||
}
|
||||
|
||||
// Allocate memory.
|
||||
serial_t *device = (serial_t *) malloc (sizeof (serial_t));
|
||||
dc_serial_t *device = (dc_serial_t *) malloc (sizeof (dc_serial_t));
|
||||
if (device == NULL) {
|
||||
SYSERROR (context, ERROR_OUTOFMEMORY);
|
||||
return -1; // ERROR_OUTOFMEMORY (Not enough storage is available to complete this operation)
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
// Library context.
|
||||
@ -150,6 +149,7 @@ serial_open (serial_t **out, dc_context_t *context, const char* name)
|
||||
NULL);
|
||||
if (device->hFile == INVALID_HANDLE_VALUE) {
|
||||
SYSERROR (context, GetLastError ());
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
@ -160,60 +160,53 @@ serial_open (serial_t **out, dc_context_t *context, const char* name)
|
||||
if (!GetCommState (device->hFile, &device->dcb) ||
|
||||
!GetCommTimeouts (device->hFile, &device->timeouts)) {
|
||||
SYSERROR (context, GetLastError ());
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
*out = device;
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
CloseHandle (device->hFile);
|
||||
error_free:
|
||||
free (device);
|
||||
return -1;
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Close the serial port.
|
||||
//
|
||||
|
||||
int
|
||||
serial_close (serial_t *device)
|
||||
dc_status_t
|
||||
dc_serial_close (dc_serial_t *device)
|
||||
{
|
||||
int errcode = 0;
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
|
||||
if (device == NULL)
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
// Restore the initial communication settings and timeouts.
|
||||
if (!SetCommState (device->hFile, &device->dcb) ||
|
||||
!SetCommTimeouts (device->hFile, &device->timeouts)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
errcode = -1;
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
}
|
||||
|
||||
// Close the device.
|
||||
if (!CloseHandle (device->hFile)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
errcode = -1;
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
}
|
||||
|
||||
// Free memory.
|
||||
free (device);
|
||||
|
||||
return errcode;
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Configure the serial port (baudrate, databits, parity, stopbits and flowcontrol).
|
||||
//
|
||||
|
||||
int
|
||||
serial_configure (serial_t *device, int baudrate, int databits, int parity, int stopbits, int flowcontrol)
|
||||
dc_status_t
|
||||
dc_serial_configure (dc_serial_t *device, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // ERROR_INVALID_PARAMETER (The parameter is incorrect)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
INFO (device->context, "Configure: baudrate=%i, databits=%i, parity=%i, stopbits=%i, flowcontrol=%i",
|
||||
baudrate, databits, parity, stopbits, flowcontrol);
|
||||
@ -222,7 +215,7 @@ serial_configure (serial_t *device, int baudrate, int databits, int parity, int
|
||||
DCB dcb;
|
||||
if (!GetCommState (device->hFile, &dcb)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
dcb.fBinary = TRUE; // Enable Binary Transmission
|
||||
@ -235,40 +228,41 @@ serial_configure (serial_t *device, int baudrate, int databits, int parity, int
|
||||
if (databits >= 5 && databits <= 8)
|
||||
dcb.ByteSize = databits;
|
||||
else
|
||||
return -1;
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Parity checking.
|
||||
switch (parity) {
|
||||
case SERIAL_PARITY_NONE: // No parity
|
||||
case DC_PARITY_NONE:
|
||||
dcb.Parity = NOPARITY;
|
||||
dcb.fParity = FALSE;
|
||||
break;
|
||||
case SERIAL_PARITY_EVEN: // Even parity
|
||||
case DC_PARITY_EVEN:
|
||||
dcb.Parity = EVENPARITY;
|
||||
dcb.fParity = TRUE;
|
||||
break;
|
||||
case SERIAL_PARITY_ODD: // Odd parity
|
||||
case DC_PARITY_ODD:
|
||||
dcb.Parity = ODDPARITY;
|
||||
dcb.fParity = TRUE;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
}
|
||||
|
||||
// Stopbits.
|
||||
switch (stopbits) {
|
||||
case 1: // One stopbit
|
||||
case DC_STOPBITS_ONE:
|
||||
dcb.StopBits = ONESTOPBIT;
|
||||
break;
|
||||
case 2: // Two stopbits
|
||||
case DC_STOPBITS_TWO:
|
||||
dcb.StopBits = TWOSTOPBITS;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
}
|
||||
|
||||
// Flow control.
|
||||
switch (flowcontrol) {
|
||||
case SERIAL_FLOWCONTROL_NONE: // No flow control.
|
||||
case DC_FLOWCONTROL_NONE:
|
||||
dcb.fInX = FALSE;
|
||||
dcb.fOutX = FALSE;
|
||||
dcb.fOutxCtsFlow = FALSE;
|
||||
@ -276,7 +270,7 @@ serial_configure (serial_t *device, int baudrate, int databits, int parity, int
|
||||
dcb.fDtrControl = DTR_CONTROL_ENABLE;
|
||||
dcb.fRtsControl = RTS_CONTROL_ENABLE;
|
||||
break;
|
||||
case SERIAL_FLOWCONTROL_HARDWARE: // Hardware (RTS/CTS) flow control.
|
||||
case DC_FLOWCONTROL_HARDWARE:
|
||||
dcb.fInX = FALSE;
|
||||
dcb.fOutX = FALSE;
|
||||
dcb.fOutxCtsFlow = TRUE;
|
||||
@ -284,7 +278,7 @@ serial_configure (serial_t *device, int baudrate, int databits, int parity, int
|
||||
dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
|
||||
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
|
||||
break;
|
||||
case SERIAL_FLOWCONTROL_SOFTWARE: // Software (XON/XOFF) flow control.
|
||||
case DC_FLOWCONTROL_SOFTWARE:
|
||||
dcb.fInX = TRUE;
|
||||
dcb.fOutX = TRUE;
|
||||
dcb.fOutxCtsFlow = FALSE;
|
||||
@ -293,38 +287,34 @@ serial_configure (serial_t *device, int baudrate, int databits, int parity, int
|
||||
dcb.fRtsControl = RTS_CONTROL_ENABLE;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
}
|
||||
|
||||
// Apply the new settings.
|
||||
if (!SetCommState (device->hFile, &dcb)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
device->baudrate = baudrate;
|
||||
device->nbits = 1 + databits + stopbits + (parity ? 1 : 0);
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Configure the serial port (timeouts).
|
||||
//
|
||||
|
||||
int
|
||||
serial_set_timeout (serial_t *device, long timeout)
|
||||
dc_status_t
|
||||
dc_serial_set_timeout (dc_serial_t *device, int timeout)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // ERROR_INVALID_PARAMETER (The parameter is incorrect)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
INFO (device->context, "Timeout: value=%li", timeout);
|
||||
INFO (device->context, "Timeout: value=%i", timeout);
|
||||
|
||||
// Retrieve the current timeouts.
|
||||
COMMTIMEOUTS timeouts;
|
||||
if (!GetCommTimeouts (device->hFile, &timeouts)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
// Update the settings.
|
||||
@ -354,75 +344,72 @@ serial_set_timeout (serial_t *device, long timeout)
|
||||
// Activate the new timeouts.
|
||||
if (!SetCommTimeouts (device->hFile, &timeouts)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Configure the serial port (recommended size of the input/output buffers).
|
||||
//
|
||||
|
||||
int
|
||||
serial_set_queue_size (serial_t *device, unsigned int input, unsigned int output)
|
||||
dc_status_t
|
||||
dc_serial_set_halfduplex (dc_serial_t *device, unsigned int value)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // ERROR_INVALID_PARAMETER (The parameter is incorrect)
|
||||
|
||||
if (!SetupComm (device->hFile, input, output)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_set_halfduplex (serial_t *device, int value)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // ERROR_INVALID_PARAMETER (The parameter is incorrect)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
device->halfduplex = value;
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_set_latency (serial_t *device, unsigned int milliseconds)
|
||||
dc_status_t
|
||||
dc_serial_set_latency (dc_serial_t *device, unsigned int value)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // ERROR_INVALID_PARAMETER (The parameter is incorrect)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
serial_read (serial_t *device, void* data, unsigned int size)
|
||||
dc_status_t
|
||||
dc_serial_read (dc_serial_t *device, void *data, size_t size, size_t *actual)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // ERROR_INVALID_PARAMETER (The parameter is incorrect)
|
||||
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
DWORD dwRead = 0;
|
||||
if (!ReadFile (device->hFile, data, size, &dwRead, NULL)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
return -1;
|
||||
|
||||
if (device == NULL) {
|
||||
status = DC_STATUS_INVALIDARGS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!ReadFile (device->hFile, data, size, &dwRead, NULL)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
status = DC_STATUS_IO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (dwRead != size) {
|
||||
status = DC_STATUS_TIMEOUT;
|
||||
}
|
||||
|
||||
out:
|
||||
HEXDUMP (device->context, DC_LOGLEVEL_INFO, "Read", (unsigned char *) data, dwRead);
|
||||
|
||||
return dwRead;
|
||||
if (actual)
|
||||
*actual = dwRead;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_write (serial_t *device, const void* data, unsigned int size)
|
||||
dc_status_t
|
||||
dc_serial_write (dc_serial_t *device, const void *data, size_t size, size_t *actual)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // ERROR_INVALID_PARAMETER (The parameter is incorrect)
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
DWORD dwWritten = 0;
|
||||
|
||||
if (device == NULL) {
|
||||
status = DC_STATUS_INVALIDARGS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
LARGE_INTEGER begin, end, freq;
|
||||
if (device->halfduplex) {
|
||||
@ -430,21 +417,23 @@ serial_write (serial_t *device, const void* data, unsigned int size)
|
||||
if (!QueryPerformanceFrequency(&freq) ||
|
||||
!QueryPerformanceCounter(&begin)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
return -1;
|
||||
status = DC_STATUS_IO;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD dwWritten = 0;
|
||||
if (!WriteFile (device->hFile, data, size, &dwWritten, NULL)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
return -1;
|
||||
status = DC_STATUS_IO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (device->halfduplex) {
|
||||
// Get the current time.
|
||||
if (!QueryPerformanceCounter(&end)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
return -1;
|
||||
status = DC_STATUS_IO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Calculate the elapsed time (microseconds).
|
||||
@ -461,99 +450,99 @@ serial_write (serial_t *device, const void* data, unsigned int size)
|
||||
// The remaining time is rounded up to the nearest millisecond
|
||||
// because the Windows Sleep() function doesn't have a higher
|
||||
// resolution.
|
||||
serial_sleep (device, (remaining + 999) / 1000);
|
||||
dc_serial_sleep (device, (remaining + 999) / 1000);
|
||||
}
|
||||
}
|
||||
|
||||
if (dwWritten != size) {
|
||||
status = DC_STATUS_TIMEOUT;
|
||||
}
|
||||
|
||||
out:
|
||||
HEXDUMP (device->context, DC_LOGLEVEL_INFO, "Write", (unsigned char *) data, dwWritten);
|
||||
|
||||
return dwWritten;
|
||||
if (actual)
|
||||
*actual = dwWritten;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_flush (serial_t *device, int queue)
|
||||
dc_status_t
|
||||
dc_serial_purge (dc_serial_t *device, dc_direction_t direction)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // ERROR_INVALID_PARAMETER (The parameter is incorrect)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
INFO (device->context, "Flush: queue=%u, input=%i, output=%i", queue,
|
||||
serial_get_received (device),
|
||||
serial_get_transmitted (device));
|
||||
INFO (device->context, "Purge: direction=%u", direction);
|
||||
|
||||
DWORD flags = 0;
|
||||
|
||||
switch (queue) {
|
||||
case SERIAL_QUEUE_INPUT:
|
||||
switch (direction) {
|
||||
case DC_DIRECTION_INPUT:
|
||||
flags = PURGE_RXABORT | PURGE_RXCLEAR;
|
||||
break;
|
||||
case SERIAL_QUEUE_OUTPUT:
|
||||
case DC_DIRECTION_OUTPUT:
|
||||
flags = PURGE_TXABORT | PURGE_TXCLEAR;
|
||||
break;
|
||||
default:
|
||||
case DC_DIRECTION_ALL:
|
||||
flags = PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR;
|
||||
break;
|
||||
default:
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
}
|
||||
|
||||
if (!PurgeComm (device->hFile, flags)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_send_break (serial_t *device)
|
||||
dc_status_t
|
||||
dc_serial_flush (dc_serial_t *device)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // ERROR_INVALID_PARAMETER (The parameter is incorrect)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
if (!SetCommBreak (device->hFile)) {
|
||||
INFO (device->context, "Flush: none");
|
||||
|
||||
if (!FlushFileBuffers (device->hFile)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
Sleep (250);
|
||||
|
||||
if (!ClearCommBreak (device->hFile)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_set_break (serial_t *device, int level)
|
||||
dc_status_t
|
||||
dc_serial_set_break (dc_serial_t *device, unsigned int level)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // ERROR_INVALID_PARAMETER (The parameter is incorrect)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
INFO (device->context, "Break: value=%i", level);
|
||||
|
||||
if (level) {
|
||||
if (!SetCommBreak (device->hFile)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
} else {
|
||||
if (!ClearCommBreak (device->hFile)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
serial_set_dtr (serial_t *device, int level)
|
||||
dc_status_t
|
||||
dc_serial_set_dtr (dc_serial_t *device, unsigned int level)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // ERROR_INVALID_PARAMETER (The parameter is incorrect)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
INFO (device->context, "DTR: value=%i", level);
|
||||
|
||||
@ -561,18 +550,17 @@ serial_set_dtr (serial_t *device, int level)
|
||||
|
||||
if (!EscapeCommFunction (device->hFile, status)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_set_rts (serial_t *device, int level)
|
||||
dc_status_t
|
||||
dc_serial_set_rts (dc_serial_t *device, unsigned int level)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // ERROR_INVALID_PARAMETER (The parameter is incorrect)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
INFO (device->context, "RTS: value=%i", level);
|
||||
|
||||
@ -580,85 +568,69 @@ serial_set_rts (serial_t *device, int level)
|
||||
|
||||
if (!EscapeCommFunction (device->hFile, status)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_get_received (serial_t *device)
|
||||
dc_status_t
|
||||
dc_serial_get_available (dc_serial_t *device, size_t *value)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // ERROR_INVALID_PARAMETER (The parameter is incorrect)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
COMSTAT stats;
|
||||
|
||||
if (!ClearCommError (device->hFile, NULL, &stats)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
return stats.cbInQue;
|
||||
if (value)
|
||||
*value = stats.cbInQue;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_get_transmitted (serial_t *device)
|
||||
dc_status_t
|
||||
dc_serial_get_lines (dc_serial_t *device, unsigned int *value)
|
||||
{
|
||||
unsigned int lines = 0;
|
||||
|
||||
if (device == NULL)
|
||||
return -1; // ERROR_INVALID_PARAMETER (The parameter is incorrect)
|
||||
|
||||
COMSTAT stats;
|
||||
|
||||
if (!ClearCommError (device->hFile, NULL, &stats)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return stats.cbOutQue;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_get_line (serial_t *device, int line)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1; // ERROR_INVALID_PARAMETER (The parameter is incorrect)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
DWORD stats = 0;
|
||||
if (!GetCommModemStatus (device->hFile, &stats)) {
|
||||
SYSERROR (device->context, GetLastError ());
|
||||
return -1;
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
switch (line) {
|
||||
case SERIAL_LINE_DCD:
|
||||
return (stats & MS_RLSD_ON) == MS_RLSD_ON;
|
||||
case SERIAL_LINE_CTS:
|
||||
return (stats & MS_CTS_ON) == MS_CTS_ON;
|
||||
case SERIAL_LINE_DSR:
|
||||
return (stats & MS_DSR_ON) == MS_DSR_ON;
|
||||
case SERIAL_LINE_RNG:
|
||||
return (stats & MS_RING_ON) == MS_RING_ON;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
if (stats & MS_RLSD_ON)
|
||||
lines |= DC_LINE_DCD;
|
||||
if (stats & MS_CTS_ON)
|
||||
lines |= DC_LINE_CTS;
|
||||
if (stats & MS_DSR_ON)
|
||||
lines |= DC_LINE_DSR;
|
||||
if (stats & MS_RING_ON)
|
||||
lines |= DC_LINE_RNG;
|
||||
|
||||
return 0;
|
||||
if (value)
|
||||
*value = lines;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
serial_sleep (serial_t *device, unsigned long timeout)
|
||||
dc_status_t
|
||||
dc_serial_sleep (dc_serial_t *device, unsigned int timeout)
|
||||
{
|
||||
if (device == NULL)
|
||||
return -1;
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
INFO (device->context, "Sleep: value=%lu", timeout);
|
||||
INFO (device->context, "Sleep: value=%u", timeout);
|
||||
|
||||
Sleep (timeout);
|
||||
|
||||
return 0;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -35,43 +35,40 @@
|
||||
#define ESC_END 0xDC
|
||||
#define ESC_ESC 0xDD
|
||||
|
||||
#define EXITCODE(n) ((n) < 0 ? DC_STATUS_IO : DC_STATUS_TIMEOUT)
|
||||
|
||||
dc_status_t
|
||||
shearwater_common_open (shearwater_common_device_t *device, dc_context_t *context, const char *name)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
return DC_STATUS_IO;
|
||||
return status;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (115200 8N1).
|
||||
rc = serial_configure (device->port, 115200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (3000ms).
|
||||
if (serial_set_timeout (device->port, 3000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 3000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_sleep (device->port, 300);
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_sleep (device->port, 300);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -80,11 +77,7 @@ dc_status_t
|
||||
shearwater_common_close (shearwater_common_device_t *device)
|
||||
{
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
return dc_serial_close (device->port);
|
||||
}
|
||||
|
||||
|
||||
@ -150,7 +143,7 @@ shearwater_common_decompress_xor (unsigned char *data, unsigned int size)
|
||||
static dc_status_t
|
||||
shearwater_common_slip_write (shearwater_common_device_t *device, const unsigned char data[], unsigned int size)
|
||||
{
|
||||
int n = 0;
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
const unsigned char end[] = {END};
|
||||
const unsigned char esc_end[] = {ESC, ESC_END};
|
||||
const unsigned char esc_esc[] = {ESC, ESC_ESC};
|
||||
@ -160,9 +153,9 @@ shearwater_common_slip_write (shearwater_common_device_t *device, const unsigned
|
||||
#if 0
|
||||
// Send an initial END character to flush out any data that may have
|
||||
// accumulated in the receiver due to line noise.
|
||||
n = serial_write (device->port, end, sizeof (end));
|
||||
if (n != sizeof (end)) {
|
||||
return EXITCODE(n);
|
||||
status = dc_serial_write (device->port, end, sizeof (end), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -189,9 +182,9 @@ shearwater_common_slip_write (shearwater_common_device_t *device, const unsigned
|
||||
|
||||
// Flush the buffer if necessary.
|
||||
if (nbytes + len + sizeof(end) > sizeof(buffer)) {
|
||||
n = serial_write (device->port, buffer, nbytes);
|
||||
if (n != nbytes) {
|
||||
return EXITCODE(n);
|
||||
status = dc_serial_write (device->port, buffer, nbytes, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
nbytes = 0;
|
||||
@ -207,9 +200,9 @@ shearwater_common_slip_write (shearwater_common_device_t *device, const unsigned
|
||||
nbytes += sizeof(end);
|
||||
|
||||
// Flush the buffer.
|
||||
n = serial_write (device->port, buffer, nbytes);
|
||||
if (n != nbytes) {
|
||||
return EXITCODE(n);
|
||||
status = dc_serial_write (device->port, buffer, nbytes, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
@ -219,6 +212,7 @@ shearwater_common_slip_write (shearwater_common_device_t *device, const unsigned
|
||||
static dc_status_t
|
||||
shearwater_common_slip_read (shearwater_common_device_t *device, unsigned char data[], unsigned int size, unsigned int *actual)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
unsigned int received = 0;
|
||||
|
||||
// Read bytes until a complete packet has been received. If the
|
||||
@ -227,12 +221,11 @@ shearwater_common_slip_read (shearwater_common_device_t *device, unsigned char d
|
||||
// than the supplied buffer size.
|
||||
while (1) {
|
||||
unsigned char c = 0;
|
||||
int n = 0;
|
||||
|
||||
// Get a single character to process.
|
||||
n = serial_read (device->port, &c, 1);
|
||||
if (n != 1) {
|
||||
return EXITCODE(n);
|
||||
status = dc_serial_read (device->port, &c, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
@ -249,9 +242,9 @@ shearwater_common_slip_read (shearwater_common_device_t *device, unsigned char d
|
||||
case ESC:
|
||||
// If it's an ESC character, get another character and then
|
||||
// figure out what to store in the packet based on that.
|
||||
n = serial_read (device->port, &c, 1);
|
||||
if (n != 1) {
|
||||
return EXITCODE(n);
|
||||
status = dc_serial_read (device->port, &c, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
// If it's not one of the two escaped characters, then we
|
||||
|
||||
@ -34,7 +34,7 @@ extern "C" {
|
||||
|
||||
typedef struct shearwater_common_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
} shearwater_common_device_t;
|
||||
|
||||
dc_status_t
|
||||
|
||||
@ -33,11 +33,6 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), (const dc_device_vtable_t *) &suunto_d9_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define C_ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
|
||||
|
||||
#define D4i 0x19
|
||||
@ -49,7 +44,7 @@
|
||||
|
||||
typedef struct suunto_d9_device_t {
|
||||
suunto_common2_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
} suunto_d9_device_t;
|
||||
|
||||
static dc_status_t suunto_d9_device_packet (dc_device_t *abstract, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize, unsigned int size);
|
||||
@ -114,10 +109,10 @@ suunto_d9_device_autodetect (suunto_d9_device_t *device, unsigned int model)
|
||||
unsigned int idx = (hint + i) % C_ARRAY_SIZE(baudrates);
|
||||
|
||||
// Adjust the baudrate.
|
||||
int rc = serial_configure (device->port, baudrates[idx], 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, baudrates[idx], 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to set the terminal attributes.");
|
||||
return DC_STATUS_IO;
|
||||
return status;
|
||||
}
|
||||
|
||||
// Try reading the version info.
|
||||
@ -153,40 +148,38 @@ suunto_d9_device_open (dc_device_t **out, dc_context_t *context, const char *nam
|
||||
device->port = NULL;
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (9600 8N1).
|
||||
rc = serial_configure (device->port, 9600, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (3000 ms).
|
||||
if (serial_set_timeout (device->port, 3000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 3000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the DTR line (power supply for the interface).
|
||||
if (serial_set_dtr (device->port, 1) == -1) {
|
||||
status = dc_serial_set_dtr (device->port, 1);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the DTR line.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Give the interface 100 ms to settle and draw power up.
|
||||
serial_sleep (device->port, 100);
|
||||
dc_serial_sleep (device->port, 100);
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
// Try to autodetect the protocol variant.
|
||||
status = suunto_d9_device_autodetect (device, model);
|
||||
@ -210,7 +203,7 @@ suunto_d9_device_open (dc_device_t **out, dc_context_t *context, const char *nam
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -222,10 +215,12 @@ suunto_d9_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
suunto_d9_device_t *device = (suunto_d9_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -235,28 +230,29 @@ suunto_d9_device_close (dc_device_t *abstract)
|
||||
static dc_status_t
|
||||
suunto_d9_device_packet (dc_device_t *abstract, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize, unsigned int size)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
suunto_d9_device_t *device = (suunto_d9_device_t *) abstract;
|
||||
|
||||
if (device_is_cancelled (abstract))
|
||||
return DC_STATUS_CANCELLED;
|
||||
|
||||
// Clear RTS to send the command.
|
||||
serial_set_rts (device->port, 0);
|
||||
dc_serial_set_rts (device->port, 0);
|
||||
|
||||
// Send the command to the dive computer.
|
||||
int n = serial_write (device->port, command, csize);
|
||||
if (n != csize) {
|
||||
status = dc_serial_write (device->port, command, csize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Receive the echo.
|
||||
unsigned char echo[128] = {0};
|
||||
assert (sizeof (echo) >= csize);
|
||||
n = serial_read (device->port, echo, csize);
|
||||
if (n != csize) {
|
||||
status = dc_serial_read (device->port, echo, csize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the echo.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the echo.
|
||||
@ -266,13 +262,13 @@ suunto_d9_device_packet (dc_device_t *abstract, const unsigned char command[], u
|
||||
}
|
||||
|
||||
// Set RTS to receive the reply.
|
||||
serial_set_rts (device->port, 1);
|
||||
dc_serial_set_rts (device->port, 1);
|
||||
|
||||
// Receive the answer of the dive computer.
|
||||
n = serial_read (device->port, answer, asize);
|
||||
if (n != asize) {
|
||||
status = dc_serial_read (device->port, answer, asize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the header of the package.
|
||||
|
||||
@ -33,16 +33,11 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &suunto_eon_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define SZ_MEMORY 0x900
|
||||
|
||||
typedef struct suunto_eon_device_t {
|
||||
suunto_common_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
} suunto_eon_device_t;
|
||||
|
||||
static dc_status_t suunto_eon_device_dump (dc_device_t *abstract, dc_buffer_t *buffer);
|
||||
@ -92,32 +87,30 @@ suunto_eon_device_open (dc_device_t **out, dc_context_t *context, const char *na
|
||||
device->port = NULL;
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (1200 8N2).
|
||||
rc = serial_configure (device->port, 1200, 8, SERIAL_PARITY_NONE, 2, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 1200, 8, DC_PARITY_NONE, DC_STOPBITS_TWO, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (1000ms).
|
||||
if (serial_set_timeout (device->port, 1000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 1000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Clear the RTS line.
|
||||
if (serial_set_rts (device->port, 0)) {
|
||||
status = dc_serial_set_rts (device->port, 0);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the DTR/RTS line.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
@ -126,7 +119,7 @@ suunto_eon_device_open (dc_device_t **out, dc_context_t *context, const char *na
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -138,10 +131,12 @@ suunto_eon_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
suunto_eon_device_t *device = (suunto_eon_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -151,6 +146,7 @@ suunto_eon_device_close (dc_device_t *abstract)
|
||||
static dc_status_t
|
||||
suunto_eon_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
suunto_eon_device_t *device = (suunto_eon_device_t*) abstract;
|
||||
|
||||
// Erase the current contents of the buffer and
|
||||
@ -167,10 +163,10 @@ suunto_eon_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
|
||||
// Send the command.
|
||||
unsigned char command[1] = {'P'};
|
||||
int rc = serial_write (device->port, command, sizeof (command));
|
||||
if (rc != sizeof (command)) {
|
||||
status = dc_serial_write (device->port, command, sizeof (command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (rc);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Receive the answer.
|
||||
@ -181,8 +177,9 @@ suunto_eon_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
unsigned int len = 64;
|
||||
|
||||
// Increase the packet size if more data is immediately available.
|
||||
int available = serial_get_received (device->port);
|
||||
if (available > len)
|
||||
size_t available = 0;
|
||||
status = dc_serial_get_available (device->port, &available);
|
||||
if (status == DC_STATUS_SUCCESS && available > len)
|
||||
len = available;
|
||||
|
||||
// Limit the packet size to the total size.
|
||||
@ -190,10 +187,10 @@ suunto_eon_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
len = sizeof(answer) - nbytes;
|
||||
|
||||
// Read the packet.
|
||||
int n = serial_read (device->port, answer + nbytes, len);
|
||||
if (n != len) {
|
||||
status = dc_serial_read (device->port, answer + nbytes, len, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Update and emit a progress event.
|
||||
@ -254,6 +251,7 @@ suunto_eon_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
|
||||
dc_status_t
|
||||
suunto_eon_device_write_name (dc_device_t *abstract, unsigned char data[], unsigned int size)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
suunto_eon_device_t *device = (suunto_eon_device_t*) abstract;
|
||||
|
||||
if (!ISINSTANCE (abstract))
|
||||
@ -265,10 +263,10 @@ suunto_eon_device_write_name (dc_device_t *abstract, unsigned char data[], unsig
|
||||
// Send the command.
|
||||
unsigned char command[21] = {'N'};
|
||||
memcpy (command + 1, data, size);
|
||||
int rc = serial_write (device->port, command, sizeof (command));
|
||||
if (rc != sizeof (command)) {
|
||||
status = dc_serial_write (device->port, command, sizeof (command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (rc);
|
||||
return status;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
@ -278,6 +276,7 @@ suunto_eon_device_write_name (dc_device_t *abstract, unsigned char data[], unsig
|
||||
dc_status_t
|
||||
suunto_eon_device_write_interval (dc_device_t *abstract, unsigned char interval)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
suunto_eon_device_t *device = (suunto_eon_device_t*) abstract;
|
||||
|
||||
if (!ISINSTANCE (abstract))
|
||||
@ -285,10 +284,10 @@ suunto_eon_device_write_interval (dc_device_t *abstract, unsigned char interval)
|
||||
|
||||
// Send the command.
|
||||
unsigned char command[2] = {'T', interval};
|
||||
int rc = serial_write (device->port, command, sizeof (command));
|
||||
if (rc != sizeof (command)) {
|
||||
status = dc_serial_write (device->port, command, sizeof (command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (rc);
|
||||
return status;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
@ -32,11 +32,6 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &suunto_solution_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define SZ_MEMORY 256
|
||||
|
||||
#define RB_PROFILE_BEGIN 0x020
|
||||
@ -44,7 +39,7 @@
|
||||
|
||||
typedef struct suunto_solution_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
} suunto_solution_device_t;
|
||||
|
||||
static dc_status_t suunto_solution_device_dump (dc_device_t *abstract, dc_buffer_t *buffer);
|
||||
@ -83,32 +78,30 @@ suunto_solution_device_open (dc_device_t **out, dc_context_t *context, const cha
|
||||
device->port = NULL;
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (1200 8N2).
|
||||
rc = serial_configure (device->port, 1200, 8, SERIAL_PARITY_NONE, 2, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 1200, 8, DC_PARITY_NONE, DC_STOPBITS_TWO, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (1000ms).
|
||||
if (serial_set_timeout (device->port, 1000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 1000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Clear the RTS line.
|
||||
if (serial_set_rts (device->port, 0)) {
|
||||
status = dc_serial_set_rts (device->port, 0);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the DTR/RTS line.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
@ -117,7 +110,7 @@ suunto_solution_device_open (dc_device_t **out, dc_context_t *context, const cha
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -129,10 +122,12 @@ suunto_solution_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
suunto_solution_device_t *device = (suunto_solution_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -142,6 +137,7 @@ suunto_solution_device_close (dc_device_t *abstract)
|
||||
static dc_status_t
|
||||
suunto_solution_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
suunto_solution_device_t *device = (suunto_solution_device_t*) abstract;
|
||||
|
||||
// Erase the current contents of the buffer and
|
||||
@ -158,20 +154,20 @@ suunto_solution_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
progress.maximum = SZ_MEMORY - 1 + 2;
|
||||
device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
|
||||
|
||||
int n = 0;
|
||||
unsigned char command[3] = {0};
|
||||
unsigned char answer[3] = {0};
|
||||
|
||||
// Assert DTR
|
||||
serial_set_dtr (device->port, 1);
|
||||
dc_serial_set_dtr (device->port, 1);
|
||||
|
||||
// Send: 0xFF
|
||||
command[0] = 0xFF;
|
||||
serial_write (device->port, command, 1);
|
||||
dc_serial_write (device->port, command, 1, NULL);
|
||||
|
||||
// Receive: 0x3F
|
||||
n = serial_read (device->port, answer, 1);
|
||||
if (n != 1) return EXITCODE (n);
|
||||
status = dc_serial_read (device->port, answer, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS)
|
||||
return status;
|
||||
if (answer[0] != 0x3F)
|
||||
WARNING (abstract->context, "Unexpected answer byte.");
|
||||
|
||||
@ -179,7 +175,7 @@ suunto_solution_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
command[0] = 0x4D;
|
||||
command[1] = 0x01;
|
||||
command[2] = 0x01;
|
||||
serial_write (device->port, command, 3);
|
||||
dc_serial_write (device->port, command, 3, NULL);
|
||||
|
||||
// Update and emit a progress event.
|
||||
progress.current += 1;
|
||||
@ -188,24 +184,26 @@ suunto_solution_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
data[0] = 0x00;
|
||||
for (unsigned int i = 1; i < SZ_MEMORY; ++i) {
|
||||
// Receive: 0x01, i, data[i]
|
||||
n = serial_read (device->port, answer, 3);
|
||||
if (n != 3) return EXITCODE (n);
|
||||
status = dc_serial_read (device->port, answer, 3, NULL);
|
||||
if (status != DC_STATUS_SUCCESS)
|
||||
return status;
|
||||
if (answer[0] != 0x01 || answer[1] != i)
|
||||
WARNING (abstract->context, "Unexpected answer byte.");
|
||||
|
||||
// Send: i
|
||||
command[0] = i;
|
||||
serial_write (device->port, command, 1);
|
||||
dc_serial_write (device->port, command, 1, NULL);
|
||||
|
||||
// Receive: data[i]
|
||||
n = serial_read (device->port, data + i, 1);
|
||||
if (n != 1) return EXITCODE (n);
|
||||
status = dc_serial_read (device->port, data + i, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS)
|
||||
return status;
|
||||
if (data[i] != answer[2])
|
||||
WARNING (abstract->context, "Unexpected answer byte.");
|
||||
|
||||
// Send: 0x0D
|
||||
command[0] = 0x0D;
|
||||
serial_write (device->port, command, 1);
|
||||
dc_serial_write (device->port, command, 1, NULL);
|
||||
|
||||
// Update and emit a progress event.
|
||||
progress.current += 1;
|
||||
@ -213,28 +211,31 @@ suunto_solution_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
}
|
||||
|
||||
// Receive: 0x02, 0x00, 0x80
|
||||
n = serial_read (device->port, answer, 3);
|
||||
if (n != 3) return EXITCODE (n);
|
||||
status = dc_serial_read (device->port, answer, 3, NULL);
|
||||
if (status != DC_STATUS_SUCCESS)
|
||||
return status;
|
||||
if (answer[0] != 0x02 || answer[1] != 0x00 || answer[2] != 0x80)
|
||||
WARNING (abstract->context, "Unexpected answer byte.");
|
||||
|
||||
// Send: 0x80
|
||||
command[0] = 0x80;
|
||||
serial_write (device->port, command, 1);
|
||||
dc_serial_write (device->port, command, 1, NULL);
|
||||
|
||||
// Receive: 0x80
|
||||
n = serial_read (device->port, answer, 1);
|
||||
if (n != 1) return EXITCODE (n);
|
||||
status = dc_serial_read (device->port, answer, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS)
|
||||
return status;
|
||||
if (answer[0] != 0x80)
|
||||
WARNING (abstract->context, "Unexpected answer byte.");
|
||||
|
||||
// Send: 0x20
|
||||
command[0] = 0x20;
|
||||
serial_write (device->port, command, 1);
|
||||
dc_serial_write (device->port, command, 1, NULL);
|
||||
|
||||
// Receive: 0x3F
|
||||
n = serial_read (device->port, answer, 1);
|
||||
if (n != 1) return EXITCODE (n);
|
||||
status = dc_serial_read (device->port, answer, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS)
|
||||
return status;
|
||||
if (answer[0] != 0x3F)
|
||||
WARNING (abstract->context, "Unexpected answer byte.");
|
||||
|
||||
|
||||
@ -34,11 +34,6 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &suunto_vyper_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
@ -52,7 +47,7 @@
|
||||
|
||||
typedef struct suunto_vyper_device_t {
|
||||
suunto_common_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
} suunto_vyper_device_t;
|
||||
|
||||
static dc_status_t suunto_vyper_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size);
|
||||
@ -112,47 +107,45 @@ suunto_vyper_device_open (dc_device_t **out, dc_context_t *context, const char *
|
||||
device->port = NULL;
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status= DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (2400 8O1).
|
||||
rc = serial_configure (device->port, 2400, 8, SERIAL_PARITY_ODD, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 2400, 8, DC_PARITY_ODD, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (1000 ms).
|
||||
if (serial_set_timeout (device->port, 1000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 1000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the DTR line (power supply for the interface).
|
||||
if (serial_set_dtr (device->port, 1) == -1) {
|
||||
status = dc_serial_set_dtr (device->port, 1);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the DTR line.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Give the interface 100 ms to settle and draw power up.
|
||||
serial_sleep (device->port, 100);
|
||||
dc_serial_sleep (device->port, 100);
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
*out = (dc_device_t*) device;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -164,10 +157,12 @@ suunto_vyper_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
suunto_vyper_device_t *device = (suunto_vyper_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -177,18 +172,19 @@ suunto_vyper_device_close (dc_device_t *abstract)
|
||||
static dc_status_t
|
||||
suunto_vyper_send (suunto_vyper_device_t *device, const unsigned char command[], unsigned int csize)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
serial_sleep (device->port, 500);
|
||||
dc_serial_sleep (device->port, 500);
|
||||
|
||||
// Set RTS to send the command.
|
||||
serial_set_rts (device->port, 1);
|
||||
dc_serial_set_rts (device->port, 1);
|
||||
|
||||
// Send the command to the dive computer.
|
||||
int n = serial_write (device->port, command, csize);
|
||||
if (n != csize) {
|
||||
status = dc_serial_write (device->port, command, csize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// If the interface sends an echo back (which is the case for many clone
|
||||
@ -202,11 +198,11 @@ suunto_vyper_send (suunto_vyper_device_t *device, const unsigned char command[],
|
||||
// receive the reply before RTS is cleared. We have to wait some time
|
||||
// before clearing RTS (around 30ms). But if we wait too long (> 500ms),
|
||||
// the reply disappears again.
|
||||
serial_sleep (device->port, 200);
|
||||
serial_flush (device->port, SERIAL_QUEUE_INPUT);
|
||||
dc_serial_sleep (device->port, 200);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_INPUT);
|
||||
|
||||
// Clear RTS to receive the reply.
|
||||
serial_set_rts (device->port, 0);
|
||||
dc_serial_set_rts (device->port, 0);
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
@ -215,10 +211,11 @@ suunto_vyper_send (suunto_vyper_device_t *device, const unsigned char command[],
|
||||
static dc_status_t
|
||||
suunto_vyper_transfer (suunto_vyper_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize, unsigned int size)
|
||||
{
|
||||
assert (asize >= size + 2);
|
||||
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
assert (asize >= size + 2);
|
||||
|
||||
if (device_is_cancelled (abstract))
|
||||
return DC_STATUS_CANCELLED;
|
||||
|
||||
@ -230,10 +227,10 @@ suunto_vyper_transfer (suunto_vyper_device_t *device, const unsigned char comman
|
||||
}
|
||||
|
||||
// Receive the answer of the dive computer.
|
||||
int n = serial_read (device->port, answer, asize);
|
||||
if (n != asize) {
|
||||
status = dc_serial_read (device->port, answer, asize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the header of the package.
|
||||
@ -329,6 +326,7 @@ suunto_vyper_device_write (dc_device_t *abstract, unsigned int address, const un
|
||||
static dc_status_t
|
||||
suunto_vyper_read_dive (dc_device_t *abstract, dc_buffer_t *buffer, int init, dc_event_progress_t *progress)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
suunto_vyper_device_t *device = (suunto_vyper_device_t*) abstract;
|
||||
|
||||
if (device_is_cancelled (abstract))
|
||||
@ -352,9 +350,10 @@ suunto_vyper_read_dive (dc_device_t *abstract, dc_buffer_t *buffer, int init, dc
|
||||
unsigned int nbytes = 0;
|
||||
for (unsigned int npackages = 0;; ++npackages) {
|
||||
// Receive the header of the package.
|
||||
size_t n = 0;
|
||||
unsigned char answer[SZ_PACKET + 3] = {0};
|
||||
int n = serial_read (device->port, answer, 2);
|
||||
if (n != 2) {
|
||||
status = dc_serial_read (device->port, answer, 2, &n);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
// If no data is received because a timeout occured, we assume
|
||||
// the last package was already received and the transmission
|
||||
// can be finished. Unfortunately this is not 100% reliable,
|
||||
@ -366,7 +365,7 @@ suunto_vyper_read_dive (dc_device_t *abstract, dc_buffer_t *buffer, int init, dc
|
||||
if (n == 0 && npackages != 0)
|
||||
break;
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the header of the package.
|
||||
@ -378,10 +377,10 @@ suunto_vyper_read_dive (dc_device_t *abstract, dc_buffer_t *buffer, int init, dc
|
||||
|
||||
// Receive the remaining part of the package.
|
||||
unsigned char len = answer[1];
|
||||
n = serial_read (device->port, answer + 2, len + 1);
|
||||
if (n != len + 1) {
|
||||
status = dc_serial_read (device->port, answer + 2, len + 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the checksum of the package.
|
||||
|
||||
@ -32,16 +32,11 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), (const dc_device_vtable_t *) &suunto_vyper2_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define HELO2 0x15
|
||||
|
||||
typedef struct suunto_vyper2_device_t {
|
||||
suunto_common2_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
} suunto_vyper2_device_t;
|
||||
|
||||
static dc_status_t suunto_vyper2_device_packet (dc_device_t *abstract, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize, unsigned int size);
|
||||
@ -101,43 +96,41 @@ suunto_vyper2_device_open (dc_device_t **out, dc_context_t *context, const char
|
||||
device->port = NULL;
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (9600 8N1).
|
||||
rc = serial_configure (device->port, 9600, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (3000 ms).
|
||||
if (serial_set_timeout (device->port, 3000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 3000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the DTR line (power supply for the interface).
|
||||
if (serial_set_dtr (device->port, 1) == -1) {
|
||||
status = dc_serial_set_dtr (device->port, 1);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the DTR line.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Give the interface 100 ms to settle and draw power up.
|
||||
serial_sleep (device->port, 100);
|
||||
dc_serial_sleep (device->port, 100);
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
// Enable half-duplex emulation.
|
||||
serial_set_halfduplex (device->port, 1);
|
||||
dc_serial_set_halfduplex (device->port, 1);
|
||||
|
||||
// Read the version info.
|
||||
status = suunto_common2_device_version ((dc_device_t *) device, device->base.version, sizeof (device->base.version));
|
||||
@ -158,7 +151,7 @@ suunto_vyper2_device_open (dc_device_t **out, dc_context_t *context, const char
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -170,10 +163,12 @@ suunto_vyper2_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
suunto_vyper2_device_t *device = (suunto_vyper2_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -183,31 +178,32 @@ suunto_vyper2_device_close (dc_device_t *abstract)
|
||||
static dc_status_t
|
||||
suunto_vyper2_device_packet (dc_device_t *abstract, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize, unsigned int size)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
suunto_vyper2_device_t *device = (suunto_vyper2_device_t *) abstract;
|
||||
|
||||
if (device_is_cancelled (abstract))
|
||||
return DC_STATUS_CANCELLED;
|
||||
|
||||
serial_sleep (device->port, 600);
|
||||
dc_serial_sleep (device->port, 600);
|
||||
|
||||
// Set RTS to send the command.
|
||||
serial_set_rts (device->port, 1);
|
||||
dc_serial_set_rts (device->port, 1);
|
||||
|
||||
// Send the command to the dive computer.
|
||||
int n = serial_write (device->port, command, csize);
|
||||
if (n != csize) {
|
||||
status = dc_serial_write (device->port, command, csize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Clear RTS to receive the reply.
|
||||
serial_set_rts (device->port, 0);
|
||||
dc_serial_set_rts (device->port, 0);
|
||||
|
||||
// Receive the answer of the dive computer.
|
||||
n = serial_read (device->port, answer, asize);
|
||||
if (n != asize) {
|
||||
status = dc_serial_read (device->port, answer, asize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the header of the package.
|
||||
|
||||
@ -33,11 +33,6 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &uwatec_aladin_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define SZ_MEMORY 2048
|
||||
|
||||
#define RB_PROFILE_BEGIN 0x000
|
||||
@ -49,7 +44,7 @@
|
||||
|
||||
typedef struct uwatec_aladin_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
unsigned int timestamp;
|
||||
unsigned int devtime;
|
||||
dc_ticks_t systime;
|
||||
@ -95,33 +90,37 @@ uwatec_aladin_device_open (dc_device_t **out, dc_context_t *context, const char
|
||||
device->devtime = 0;
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (19200 8N1).
|
||||
rc = serial_configure (device->port, 19200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 19200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (INFINITE).
|
||||
if (serial_set_timeout (device->port, -1) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, -1);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Clear the RTS line and set the DTR line.
|
||||
if (serial_set_dtr (device->port, 1) == -1 ||
|
||||
serial_set_rts (device->port, 0) == -1) {
|
||||
ERROR (context, "Failed to set the DTR/RTS line.");
|
||||
status = DC_STATUS_IO;
|
||||
// Set the DTR line.
|
||||
status = dc_serial_set_dtr (device->port, 1);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the DTR line.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Clear the RTS line.
|
||||
status = dc_serial_set_rts (device->port, 0);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to clear the RTS line.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
@ -130,7 +129,7 @@ uwatec_aladin_device_open (dc_device_t **out, dc_context_t *context, const char
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -142,10 +141,12 @@ uwatec_aladin_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
uwatec_aladin_device_t *device = (uwatec_aladin_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -172,6 +173,7 @@ uwatec_aladin_device_set_fingerprint (dc_device_t *abstract, const unsigned char
|
||||
static dc_status_t
|
||||
uwatec_aladin_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
uwatec_aladin_device_t *device = (uwatec_aladin_device_t*) abstract;
|
||||
|
||||
// Erase the current contents of the buffer and
|
||||
@ -193,10 +195,10 @@ uwatec_aladin_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
if (device_is_cancelled (abstract))
|
||||
return DC_STATUS_CANCELLED;
|
||||
|
||||
int rc = serial_read (device->port, answer + i, 1);
|
||||
if (rc != 1) {
|
||||
status = dc_serial_read (device->port, answer + i, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (rc);
|
||||
return status;
|
||||
}
|
||||
if (answer[i] == (i < 3 ? 0x55 : 0x00)) {
|
||||
i++; // Continue.
|
||||
@ -214,10 +216,10 @@ uwatec_aladin_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
|
||||
|
||||
// Receive the remaining part of the package.
|
||||
int rc = serial_read (device->port, answer + 4, sizeof (answer) - 4);
|
||||
if (rc != sizeof (answer) - 4) {
|
||||
status = dc_serial_read (device->port, answer + 4, sizeof (answer) - 4, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Unexpected EOF in answer.");
|
||||
return EXITCODE (rc);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Update and emit a progress event.
|
||||
|
||||
@ -33,11 +33,6 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &uwatec_memomouse_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define PACKETSIZE 126
|
||||
|
||||
#define ACK 0x60
|
||||
@ -45,7 +40,7 @@
|
||||
|
||||
typedef struct uwatec_memomouse_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
unsigned int timestamp;
|
||||
unsigned int devtime;
|
||||
dc_ticks_t systime;
|
||||
@ -91,45 +86,49 @@ uwatec_memomouse_device_open (dc_device_t **out, dc_context_t *context, const ch
|
||||
device->devtime = 0;
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (9600 8N1).
|
||||
rc = serial_configure (device->port, 9600, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (1000 ms).
|
||||
if (serial_set_timeout (device->port, 1000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 1000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Clear the RTS and DTR lines.
|
||||
if (serial_set_rts (device->port, 0) == -1 ||
|
||||
serial_set_dtr (device->port, 0) == -1) {
|
||||
ERROR (context, "Failed to set the DTR/RTS line.");
|
||||
status = DC_STATUS_IO;
|
||||
// Clear the DTR line.
|
||||
status = dc_serial_set_dtr (device->port, 0);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to clear the DTR line.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Clear the RTS line.
|
||||
status = dc_serial_set_rts (device->port, 0);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to clear the RTS line.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
*out = (dc_device_t*) device;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -141,10 +140,12 @@ uwatec_memomouse_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
uwatec_memomouse_device_t *device = (uwatec_memomouse_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -171,15 +172,16 @@ uwatec_memomouse_device_set_fingerprint (dc_device_t *abstract, const unsigned c
|
||||
static dc_status_t
|
||||
uwatec_memomouse_read_packet (uwatec_memomouse_device_t *device, unsigned char data[], unsigned int size, unsigned int *result)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
assert (result != NULL);
|
||||
|
||||
// Receive the header of the package.
|
||||
int rc = serial_read (device->port, data, 1);
|
||||
if (rc != 1) {
|
||||
status = dc_serial_read (device->port, data, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (rc);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Reverse the bits.
|
||||
@ -193,10 +195,10 @@ uwatec_memomouse_read_packet (uwatec_memomouse_device_t *device, unsigned char d
|
||||
}
|
||||
|
||||
// Receive the remaining part of the package.
|
||||
rc = serial_read (device->port, data + 1, len + 1);
|
||||
if (rc != len + 1) {
|
||||
status = dc_serial_read (device->port, data + 1, len + 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (rc);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Reverse the bits.
|
||||
@ -219,6 +221,7 @@ uwatec_memomouse_read_packet (uwatec_memomouse_device_t *device, unsigned char d
|
||||
static dc_status_t
|
||||
uwatec_memomouse_read_packet_outer (uwatec_memomouse_device_t *device, unsigned char data[], unsigned int size, unsigned int *result)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
@ -229,14 +232,14 @@ uwatec_memomouse_read_packet_outer (uwatec_memomouse_device_t *device, unsigned
|
||||
return rc;
|
||||
|
||||
// Flush the input buffer.
|
||||
serial_flush (device->port, SERIAL_QUEUE_INPUT);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_INPUT);
|
||||
|
||||
// Reject the packet.
|
||||
unsigned char value = NAK;
|
||||
int n = serial_write (device->port, &value, 1);
|
||||
if (n != 1) {
|
||||
status = dc_serial_write (device->port, &value, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to reject the packet.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
@ -247,6 +250,7 @@ uwatec_memomouse_read_packet_outer (uwatec_memomouse_device_t *device, unsigned
|
||||
static dc_status_t
|
||||
uwatec_memomouse_read_packet_inner (uwatec_memomouse_device_t *device, dc_buffer_t *buffer, dc_event_progress_t *progress)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
// Erase the current contents of the buffer.
|
||||
@ -271,10 +275,10 @@ uwatec_memomouse_read_packet_inner (uwatec_memomouse_device_t *device, dc_buffer
|
||||
|
||||
// Accept the packet.
|
||||
unsigned char value = ACK;
|
||||
int n = serial_write (device->port, &value, 1);
|
||||
if (n != 1) {
|
||||
status = dc_serial_write (device->port, &value, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to accept the packet.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (nbytes == 0) {
|
||||
@ -329,29 +333,31 @@ uwatec_memomouse_read_packet_inner (uwatec_memomouse_device_t *device, dc_buffer
|
||||
static dc_status_t
|
||||
uwatec_memomouse_dump_internal (uwatec_memomouse_device_t *device, dc_buffer_t *buffer)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
size_t available = 0;
|
||||
|
||||
// Enable progress notifications.
|
||||
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
|
||||
device_event_emit (&device->base, DC_EVENT_PROGRESS, &progress);
|
||||
|
||||
// Waiting for greeting message.
|
||||
while (serial_get_received (device->port) == 0) {
|
||||
while (dc_serial_get_available (device->port, &available) == DC_STATUS_SUCCESS && available == 0) {
|
||||
if (device_is_cancelled (abstract))
|
||||
return DC_STATUS_CANCELLED;
|
||||
|
||||
// Flush the input buffer.
|
||||
serial_flush (device->port, SERIAL_QUEUE_INPUT);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_INPUT);
|
||||
|
||||
// Reject the packet.
|
||||
unsigned char value = NAK;
|
||||
int n = serial_write (device->port, &value, 1);
|
||||
if (n != 1) {
|
||||
status = dc_serial_write (device->port, &value, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to reject the packet.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
serial_sleep (device->port, 300);
|
||||
dc_serial_sleep (device->port, 300);
|
||||
}
|
||||
|
||||
// Read the ID string.
|
||||
@ -374,27 +380,27 @@ uwatec_memomouse_dump_internal (uwatec_memomouse_device_t *device, dc_buffer_t *
|
||||
|
||||
// Wait a small amount of time before sending the command.
|
||||
// Without this delay, the transfer will fail most of the time.
|
||||
serial_sleep (device->port, 50);
|
||||
dc_serial_sleep (device->port, 50);
|
||||
|
||||
// Keep send the command to the device,
|
||||
// until the ACK answer is received.
|
||||
unsigned char answer = NAK;
|
||||
while (answer == NAK) {
|
||||
// Flush the input buffer.
|
||||
serial_flush (device->port, SERIAL_QUEUE_INPUT);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_INPUT);
|
||||
|
||||
// Send the command to the device.
|
||||
int n = serial_write (device->port, command, sizeof (command));
|
||||
if (n != sizeof (command)) {
|
||||
status = dc_serial_write (device->port, command, sizeof (command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Wait for the answer (ACK).
|
||||
n = serial_read (device->port, &answer, 1);
|
||||
if (n != 1) {
|
||||
status = dc_serial_read (device->port, &answer, 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
@ -405,12 +411,12 @@ uwatec_memomouse_dump_internal (uwatec_memomouse_device_t *device, dc_buffer_t *
|
||||
}
|
||||
|
||||
// Wait for the data packet.
|
||||
while (serial_get_received (device->port) == 0) {
|
||||
while (dc_serial_get_available (device->port, &available) == DC_STATUS_SUCCESS && available == 0) {
|
||||
if (device_is_cancelled (abstract))
|
||||
return DC_STATUS_CANCELLED;
|
||||
|
||||
device_event_emit (&device->base, DC_EVENT_WAITING, NULL);
|
||||
serial_sleep (device->port, 100);
|
||||
dc_serial_sleep (device->port, 100);
|
||||
}
|
||||
|
||||
// Fetch the current system time.
|
||||
@ -438,7 +444,9 @@ uwatec_memomouse_dump_internal (uwatec_memomouse_device_t *device, dc_buffer_t *
|
||||
static dc_status_t
|
||||
uwatec_memomouse_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
uwatec_memomouse_device_t *device = (uwatec_memomouse_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Erase the current contents of the buffer.
|
||||
if (!dc_buffer_clear (buffer)) {
|
||||
@ -448,24 +456,26 @@ uwatec_memomouse_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
|
||||
// Give the interface some time to notice the DTR
|
||||
// line change from a previous transfer (if any).
|
||||
serial_sleep (device->port, 500);
|
||||
dc_serial_sleep (device->port, 500);
|
||||
|
||||
// Set the DTR line.
|
||||
if (serial_set_dtr (device->port, 1) == -1) {
|
||||
rc = dc_serial_set_dtr (device->port, 1);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to set the RTS line.");
|
||||
return DC_STATUS_IO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Start the transfer.
|
||||
dc_status_t rc = uwatec_memomouse_dump_internal (device, buffer);
|
||||
status = uwatec_memomouse_dump_internal (device, buffer);
|
||||
|
||||
// Clear the DTR line again.
|
||||
if (serial_set_dtr (device->port, 0) == -1) {
|
||||
rc = dc_serial_set_dtr (device->port, 0);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to set the RTS line.");
|
||||
return DC_STATUS_IO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -33,17 +33,12 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &uwatec_meridian_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define ACK 0x11
|
||||
#define NAK 0x66
|
||||
|
||||
typedef struct uwatec_meridian_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
unsigned int timestamp;
|
||||
unsigned int devtime;
|
||||
dc_ticks_t systime;
|
||||
@ -69,6 +64,7 @@ static const dc_device_vtable_t uwatec_meridian_device_vtable = {
|
||||
static dc_status_t
|
||||
uwatec_meridian_transfer (uwatec_meridian_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
assert (csize > 0 && csize <= 255);
|
||||
@ -85,18 +81,18 @@ uwatec_meridian_transfer (uwatec_meridian_device_t *device, const unsigned char
|
||||
packet[11 + csize] = checksum_xor_uint8 (packet + 7, csize + 4, 0x00);
|
||||
|
||||
// Send the packet.
|
||||
int n = serial_write (device->port, packet, csize + 12);
|
||||
if (n != csize + 12) {
|
||||
status = dc_serial_write (device->port, packet, csize + 12, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Read the echo.
|
||||
unsigned char echo[sizeof(packet)];
|
||||
n = serial_read (device->port, echo, csize + 12);
|
||||
if (n != csize + 12) {
|
||||
status = dc_serial_read (device->port, echo, csize + 12, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the echo.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the echo.
|
||||
@ -107,10 +103,10 @@ uwatec_meridian_transfer (uwatec_meridian_device_t *device, const unsigned char
|
||||
|
||||
// Read the header.
|
||||
unsigned char header[6];
|
||||
n = serial_read (device->port, header, sizeof (header));
|
||||
if (n != sizeof (header)) {
|
||||
status = dc_serial_read (device->port, header, sizeof (header), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the header.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the header.
|
||||
@ -120,18 +116,18 @@ uwatec_meridian_transfer (uwatec_meridian_device_t *device, const unsigned char
|
||||
}
|
||||
|
||||
// Read the packet.
|
||||
n = serial_read (device->port, answer, asize);
|
||||
if (n != asize) {
|
||||
status = dc_serial_read (device->port, answer, asize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the packet.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Read the checksum.
|
||||
unsigned char csum = 0x00;
|
||||
n = serial_read (device->port, &csum, sizeof (csum));
|
||||
if (n != sizeof (csum)) {
|
||||
status = dc_serial_read (device->port, &csum, sizeof (csum), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the checksum.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the checksum.
|
||||
@ -207,30 +203,28 @@ uwatec_meridian_device_open (dc_device_t **out, dc_context_t *context, const cha
|
||||
device->devtime = 0;
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (57600 8N1).
|
||||
rc = serial_configure (device->port, 57600, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 57600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (3000ms).
|
||||
if (serial_set_timeout (device->port, 3000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 3000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
// Perform the handshaking.
|
||||
uwatec_meridian_handshake (device);
|
||||
@ -240,7 +234,7 @@ uwatec_meridian_device_open (dc_device_t **out, dc_context_t *context, const cha
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -252,10 +246,12 @@ uwatec_meridian_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
uwatec_meridian_device_t *device = (uwatec_meridian_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -282,6 +278,7 @@ uwatec_meridian_device_set_fingerprint (dc_device_t *abstract, const unsigned ch
|
||||
static dc_status_t
|
||||
uwatec_meridian_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
uwatec_meridian_device_t *device = (uwatec_meridian_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
@ -395,10 +392,10 @@ uwatec_meridian_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
|
||||
// Read the header.
|
||||
unsigned char header[5];
|
||||
int n = serial_read (device->port, header, sizeof (header));
|
||||
if (n != sizeof (header)) {
|
||||
status = dc_serial_read (device->port, header, sizeof (header), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the header.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Get the packet size.
|
||||
@ -409,18 +406,18 @@ uwatec_meridian_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
}
|
||||
|
||||
// Read the packet data.
|
||||
n = serial_read (device->port, data + nbytes, packetsize - 1);
|
||||
if (n != packetsize - 1) {
|
||||
status = dc_serial_read (device->port, data + nbytes, packetsize - 1, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the packet.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Read the checksum.
|
||||
unsigned char csum = 0x00;
|
||||
n = serial_read (device->port, &csum, sizeof (csum));
|
||||
if (n != sizeof (csum)) {
|
||||
status = dc_serial_read (device->port, &csum, sizeof (csum), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the checksum.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the checksum.
|
||||
|
||||
@ -31,14 +31,9 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &uwatec_smart_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
typedef struct uwatec_smart_device_t {
|
||||
dc_device_t base;
|
||||
irda_t *socket;
|
||||
dc_irda_t *socket;
|
||||
unsigned int address;
|
||||
unsigned int timestamp;
|
||||
unsigned int devtime;
|
||||
@ -88,18 +83,19 @@ uwatec_smart_discovery (unsigned int address, const char *name, unsigned int cha
|
||||
static dc_status_t
|
||||
uwatec_smart_transfer (uwatec_smart_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
int n = irda_socket_write (device->socket, command, csize);
|
||||
if (n != csize) {
|
||||
status = dc_irda_write (device->socket, command, csize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
n = irda_socket_read (device->socket, answer, asize);
|
||||
if (n != asize) {
|
||||
status = dc_irda_read (device->socket, answer, asize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
@ -167,18 +163,16 @@ uwatec_smart_device_open (dc_device_t **out, dc_context_t *context)
|
||||
device->devtime = 0;
|
||||
|
||||
// Open the irda socket.
|
||||
int rc = irda_socket_open (&device->socket, context);
|
||||
if (rc == -1) {
|
||||
status = dc_irda_open (&device->socket, context);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the irda socket.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Discover the device.
|
||||
rc = irda_socket_discover (device->socket, uwatec_smart_discovery, device);
|
||||
if (rc == -1) {
|
||||
status = dc_irda_discover (device->socket, uwatec_smart_discovery, device);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to discover the device.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
@ -189,10 +183,9 @@ uwatec_smart_device_open (dc_device_t **out, dc_context_t *context)
|
||||
}
|
||||
|
||||
// Connect the device.
|
||||
rc = irda_socket_connect_lsap (device->socket, device->address, 1);
|
||||
if (rc == -1) {
|
||||
status = dc_irda_connect_lsap (device->socket, device->address, 1);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to connect the device.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
@ -204,7 +197,7 @@ uwatec_smart_device_open (dc_device_t **out, dc_context_t *context)
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
irda_socket_close (device->socket);
|
||||
dc_irda_close (device->socket);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -216,10 +209,12 @@ uwatec_smart_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
uwatec_smart_device_t *device = (uwatec_smart_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (irda_socket_close (device->socket) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_irda_close (device->socket);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -360,25 +355,26 @@ uwatec_smart_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
unsigned int len = 32;
|
||||
|
||||
// Increase the packet size if more data is immediately available.
|
||||
int available = irda_socket_available (device->socket);
|
||||
if (available > len)
|
||||
size_t available = 0;
|
||||
rc = dc_irda_get_available (device->socket, &available);
|
||||
if (rc == DC_STATUS_SUCCESS && available > len)
|
||||
len = available;
|
||||
|
||||
// Limit the packet size to the total size.
|
||||
if (nbytes + len > length)
|
||||
len = length - nbytes;
|
||||
|
||||
int n = irda_socket_read (device->socket, data + nbytes, len);
|
||||
if (n != len) {
|
||||
rc = dc_irda_read (device->socket, data + nbytes, len, NULL);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Update and emit a progress event.
|
||||
progress.current += n;
|
||||
progress.current += len;
|
||||
device_event_emit (&device->base, DC_EVENT_PROGRESS, &progress);
|
||||
|
||||
nbytes += n;
|
||||
nbytes += len;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
@ -34,11 +34,6 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &zeagle_n2ition3_device_vtable)
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
|
||||
)
|
||||
|
||||
#define SZ_MEMORY 0x8000
|
||||
#define SZ_PACKET 64
|
||||
|
||||
@ -51,7 +46,7 @@
|
||||
|
||||
typedef struct zeagle_n2ition3_device_t {
|
||||
dc_device_t base;
|
||||
serial_t *port;
|
||||
dc_serial_t *port;
|
||||
unsigned char fingerprint[16];
|
||||
} zeagle_n2ition3_device_t;
|
||||
|
||||
@ -76,6 +71,7 @@ static const dc_device_vtable_t zeagle_n2ition3_device_vtable = {
|
||||
static dc_status_t
|
||||
zeagle_n2ition3_packet (zeagle_n2ition3_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
assert (asize >= csize + 5);
|
||||
@ -84,17 +80,17 @@ zeagle_n2ition3_packet (zeagle_n2ition3_device_t *device, const unsigned char co
|
||||
return DC_STATUS_CANCELLED;
|
||||
|
||||
// Send the command to the device.
|
||||
int n = serial_write (device->port, command, csize);
|
||||
if (n != csize) {
|
||||
status = dc_serial_write (device->port, command, csize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Receive the answer of the device.
|
||||
n = serial_read (device->port, answer, asize);
|
||||
if (n != asize) {
|
||||
status = dc_serial_read (device->port, answer, asize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return EXITCODE (n);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the echo.
|
||||
@ -156,30 +152,28 @@ zeagle_n2ition3_device_open (dc_device_t **out, dc_context_t *context, const cha
|
||||
memset (device->fingerprint, 0, sizeof (device->fingerprint));
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_open (&device->port, context, name);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the serial port.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (4800 8N1).
|
||||
rc = serial_configure (device->port, 4800, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
|
||||
if (rc == -1) {
|
||||
status = dc_serial_configure (device->port, 4800, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (1000 ms).
|
||||
if (serial_set_timeout (device->port, 1000) == -1) {
|
||||
status = dc_serial_set_timeout (device->port, 1000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_ALL);
|
||||
|
||||
// Send the init commands.
|
||||
zeagle_n2ition3_init (device);
|
||||
@ -189,7 +183,7 @@ zeagle_n2ition3_device_open (dc_device_t **out, dc_context_t *context, const cha
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
serial_close (device->port);
|
||||
dc_serial_close (device->port);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -201,10 +195,12 @@ zeagle_n2ition3_device_close (dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
zeagle_n2ition3_device_t *device = (zeagle_n2ition3_device_t*) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Close the device.
|
||||
if (serial_close (device->port) == -1) {
|
||||
dc_status_set_error(&status, DC_STATUS_IO);
|
||||
rc = dc_serial_close (device->port);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user