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:
Jef Driesen 2015-09-13 11:19:14 +02:00
parent dbba7f3272
commit 84563c6303
39 changed files with 1992 additions and 1703 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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.

View File

@ -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;

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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;

View File

@ -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.");

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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;
}

View File

@ -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.

View File

@ -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;

View File

@ -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;